diff -u --recursive --new-file v2.3.15/linux/CREDITS linux/CREDITS
--- v2.3.15/linux/CREDITS	Thu Aug 26 13:05:34 1999
+++ linux/CREDITS	Tue Aug 31 11:27:38 1999
@@ -810,7 +810,7 @@
 D: Selection mechanism
 
 N: Andre Hedrick
-E: hedrick@astro.dyer.vanderbilt.edu
+E: andre@suse.com
 D: Random SMP kernel hacker...
 D: Uniform Multi-Platform E-IDE driver
 D: Aladdin 1533/1543(C) chipset
@@ -1031,6 +1031,16 @@
 S: 80-283 Gdansk
 S: Poland
 
+N: Dave Jones
+E: dave@powertweak.com
+W: http://linux.powertweak.com
+D: Centaur/IDT Winchip/Winchip 2 tweaks
+D: Misc clean ups and other random hacking.
+S: 40, Heol Edward Lewis,
+S: Gelligaer, Hengoed,
+S: Mid Glamorgan, CF82 8EJ,
+S: Wales, United Kingdom
+
 N: Bernhard Kaindl
 E: bkaindl@netway.at
 E: edv@bartelt.via.at
@@ -2362,6 +2372,7 @@
 E: lnz@dandelion.com
 W: http://www.dandelion.com/Linux/
 D: BusLogic SCSI driver
+D: Mylex DAC960 PCI RAID driver
 D: Miscellaneous kernel fixes
 S: 3078 Sulphur Spring Court
 S: San Jose, California 95148
diff -u --recursive --new-file v2.3.15/linux/Documentation/Changes linux/Documentation/Changes
--- v2.3.15/linux/Documentation/Changes	Thu Aug 26 13:05:34 1999
+++ linux/Documentation/Changes	Tue Aug 31 11:02:26 1999
@@ -243,7 +243,7 @@
 modules) are currently distributed separately: see
 	http://antarctica.penguincomputing.com/~netfilter/
 	http://www.samba.org/netfilter/
-	http://netfilter.kernenotes.org
+	http://netfilter.kernelnotes.org
 
    DHCP clients for 2.0 do not work with the new networking code in the
 2.2 kernel.  You will need to upgrade your dhcpcd / dhcpclient.
@@ -419,9 +419,16 @@
 =========
 
    Linux PCI utils are available; these include lspci, which displays
-the detailed information about your system's PCI devices which used to
-be in /proc/pci, and setpci, which allws you to read and write
-configuration registers on your PCI devices.
+detailed information about your system's PCI devices (much more than
+the basic things in /proc/pci), and setpci, which allows you to read
+and write PCI configuration registers of your devices.
+
+Powertweak
+==========
+
+   The PCI Bridge Optimization has been removed from the kernel. If you
+think your BIOS does a poor job when setting up your chipset, there
+is a utility called PowerTweak whose job is to tune chipset parameters.
 
 Xosview
 =======
@@ -734,9 +741,16 @@
 PCI utils
 =========
 
-The 1.09 release:
-ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci/pciutils-1.09.tar.gz
-ftp://metalab.unc.edu/pub/Linux/hardware/pciutils-1.09.tar.gz
+The 2.0 release:
+ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci/pciutils-2.0.tar.gz
+ftp://metalab.unc.edu/pub/Linux/hardware/pciutils-2.0.tar.gz
+
+Powertweak
+==========
+
+The 0.1.2 release:
+http://linux.powertweak.com/files/powertweak-0.1.2.tgz
+ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci/powertweak/powertweak-0.1.2.tgz
 
 Tunelp
 ======
diff -u --recursive --new-file v2.3.15/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.15/linux/Documentation/Configure.help	Thu Aug 26 13:05:34 1999
+++ linux/Documentation/Configure.help	Mon Aug 30 18:05:57 1999
@@ -168,6 +168,11 @@
   on the Alpha. The only time you would ever not say Y is to say M in
   order to debug the code. Say Y unless you know what you are doing.
 
+Big memory support
+CONFIG_BIGMEM
+  This option is required if you want to utilize physical memory which
+  is not covered by the kernel virtual address space (> 1GB).
+
 Normal PC floppy disk support
 CONFIG_BLK_DEV_FD
   If you want to use the floppy disk drive(s) of your PC under Linux,
@@ -931,6 +936,17 @@
 
   It's pretty unlikely that you have one of these: say N.
 
+Mylex DAC960/DAC1100 PCI RAID Controller support
+CONFIG_BLK_DEV_DAC960
+  This driver adds support for the Mylex DAC960, AcceleRAID, and
+  eXtremeRAID PCI RAID controllers.  See README.DAC960 for further
+  information about this driver.
+
+  If you want to compile the driver as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt.  The module will be
+  called DAC960.o. 
+
 Parallel port IDE device support
 CONFIG_PARIDE
   There are many external CD-ROM and disk devices that connect through
@@ -4047,6 +4063,15 @@
   kernel. The default value has been reduced to 5 seconds. If this
   doesn't work with your hardware, try increasing this value.
 
+IBM ServeRAID Support
+CONFIG_SCSI_IPS
+  This is support for the IBM ServeRAID hardware RAID controllers.
+  Consult the SCSI-HOWTO, available via anonymous FTP from
+  ftp://metalab.unc.edu/pub/Linux/docs/HOWTO, and the file
+  README.ips in drivers/scsi for more information.  If this driver
+  does not work correctly without modification please contact the
+  author by email at ipslinux@us.ibm.com.
+
 BusLogic SCSI support
 CONFIG_SCSI_BUSLOGIC
   This is support for BusLogic MultiMaster and FlashPoint SCSI Host
@@ -9081,6 +9106,35 @@
   module ( = code which can be inserted in and removed from the
   running kernel whenever you want), say M here and read
   Documentation/modules.txt. The module will be called dtlk.o.
+
+Siemens R3964 serial protocol support
+CONFIG_R3964
+  This driver allows syncronous communication with devices using the
+  Siemens R3964 packet protocol. Unless you are dealing with special
+  hardware like PLCs, you are unlikely to need this.
+
+  To compile this driver as a module ( = code which can be inserted in
+  and removed from the running kernel whenever you want), say M here
+  and read Documentation/modules.txt. The module will be called 
+  n_r3964.o.
+
+  If unsure, say N.
+
+Applicom intelligent fieldbus card support
+CONFIG_APPLICOM
+  This driver provides the kernel-side support for the intelligent 
+  fieldbus cards made by Applicom International. More information
+  about these cards can be found on the WWW at the address
+  http://www.applicom-int.com/ (to browse the WWW, you need to have
+  access to a machine on the Internet that has a program like lynx
+  or netscape), or by email from David Woodhouse <dwmw2@mvhi.com>.
+
+  To compile this driver as a module ( = code which can be inserted in
+  and removed from the running kernel whenever you want), say M here
+  and read Documentation/modules.txt. The module will be called
+  applicom.o.
+
+  If unsure, say N.
 
 Advanced Power Management
 CONFIG_APM
diff -u --recursive --new-file v2.3.15/linux/Documentation/README.DAC960 linux/Documentation/README.DAC960
--- v2.3.15/linux/Documentation/README.DAC960	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/README.DAC960	Mon Aug 30 10:24:14 1999
@@ -0,0 +1,717 @@
+	   Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux
+
+			Version 2.2.4 for Linux 2.2.11
+			Version 2.0.4 for Linux 2.0.37
+
+			      PRODUCTION RELEASE
+
+				23 August 1999
+
+			       Leonard N. Zubkoff
+			       Dandelion Digital
+			       lnz@dandelion.com
+
+	 Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+
+
+				 INTRODUCTION
+
+Mylex, Inc. designs and manufactures a variety of high performance PCI RAID
+controllers.  Mylex Corporation is located at 34551 Ardenwood Blvd., Fremont,
+California 94555, USA and can be reached at 510/796-6100 or on the World Wide
+Web at http://www.mylex.com.  Mylex RAID Technical Support can be reached by
+electronic mail at support@mylex.com (for eXtremeRAID 1100 and older DAC960
+models) or techsup@mylex.com (for AcceleRAID models), by voice at 510/608-2400,
+or by FAX at 510/745-7715.  Contact information for offices in Europe and Japan
+is available on the Web site.
+
+The latest information on Linux support for DAC960 PCI RAID Controllers, as
+well as the most recent release of this driver, will always be available from
+my Linux Home Page at URL "http://www.dandelion.com/Linux/".  The Linux DAC960
+driver supports all current DAC960 PCI family controllers including the
+AcceleRAID models, as well as the eXtremeRAID 1100; see below for a complete
+list.  For simplicity, in most places this documentation refers to DAC960
+generically rather than explicitly listing all the models.
+
+Bug reports should be sent via electronic mail to "lnz@dandelion.com".  Please
+include with the bug report the complete configuration messages reported by the
+driver at startup, along with any subsequent system messages relevant to the
+controller's operation, and a detailed description of your system's hardware
+configuration.
+
+Please consult the DAC960 RAID controller documentation for detailed
+information regarding installation and configuration of the controllers.  This
+document primarily provides information specific to the Linux DAC960 support.
+
+
+				DRIVER FEATURES
+
+The DAC960 RAID controllers are supported solely as high performance RAID
+controllers, not as interfaces to arbitrary SCSI devices.  The Linux DAC960
+driver operates at the block device level, the same level as the SCSI and IDE
+drivers.  Unlike other RAID controllers currently supported on Linux, the
+DAC960 driver is not dependent on the SCSI subsystem, and hence avoids all the
+complexity and unnecessary code that would be associated with an implementation
+as a SCSI driver.  The DAC960 driver is designed for as high a performance as
+possible with no compromises or extra code for compatibility with lower
+performance devices.  The DAC960 driver includes extensive error logging and
+online configuration management capabilities.  Except for initial configuration
+of the controller and adding new disk drives, most everything can be handled
+from Linux while the system is operational.
+
+The DAC960 driver is architected to support up to 8 controllers per system.
+Each DAC960 controller can support up to 15 disk drives per channel, for a
+maximum of 45 drives on a three channel controller.  The drives installed on a
+controller are divided into one or more "Drive Groups", and then each Drive
+Group is subdivided further into 1 to 32 "Logical Drives".  Each Logical Drive
+has a specific RAID Level and caching policy associated with it, and it appears
+to Linux as a single block device.  Logical Drives are further subdivided into
+up to 7 partitions through the normal Linux and PC disk partitioning schemes.
+Logical Drives are also known as "System Drives", and Drive Groups are also
+called "Packs".  Both terms are in use in the Mylex documentation; I have
+chosen to standardize on the more generic "Logical Drive" and "Drive Group".
+
+DAC960 RAID disk devices are named in the style of the Device File System
+(DEVFS).  The device corresponding to Logical Drive D on Controller C is
+referred to as /dev/rd/cCdD, and the partitions are called /dev/rd/cCdDp1
+through /dev/rd/cCdDp7.  For example, partition 3 of Logical Drive 5 on
+Controller 2 is referred to as /dev/rd/c2d5p3.  Note that unlike with SCSI
+disks the device names will not change in the event of a disk drive failure.
+The DAC960 driver is assigned major numbers 48 - 55 with one major number per
+controller.  The 8 bits of minor number are divided into 5 bits for the Logical
+Drive and 3 bits for the partition.
+
+
+		 SUPPORTED DAC960/DAC1100 PCI RAID CONTROLLERS
+
+The following list comprises the supported DAC960 and DAC1100 PCI RAID
+Controllers as of the date of this document.  It is recommended that anyone
+purchasing a Mylex PCI RAID Controller not in the following table contact the
+author beforehand to verify that it is or will be supported.
+
+eXtremeRAID 1100 (DAC1164P)
+	    3 Wide Ultra-2/LVD SCSI channels
+	    233MHz StrongARM SA 110 Processor
+	    64 Bit PCI (backward compatible with 32 Bit PCI slots)
+	    16MB/32MB/64MB Parity SDRAM Memory with Battery Backup
+
+AcceleRAID 250 (DAC960PTL1)
+	    Uses onboard Symbios SCSI chips on certain motherboards
+	    Also includes one onboard Wide Ultra-2/LVD SCSI Channel
+	    66MHz Intel i960RD RISC Processor
+	    4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
+
+AcceleRAID 200 (DAC960PTL0)
+	    Uses onboard Symbios SCSI chips on certain motherboards
+	    Includes no onboard SCSI Channels
+	    66MHz Intel i960RD RISC Processor
+	    4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
+
+AcceleRAID 150 (DAC960PRL)
+	    Uses onboard Symbios SCSI chips on certain motherboards
+	    Also includes one onboard Wide Ultra-2/LVD SCSI Channel
+	    33MHz Intel i960RP RISC Processor
+	    4MB Parity EDO Memory
+
+DAC960PJ    1/2/3 Wide Ultra SCSI-3 Channels
+	    66MHz Intel i960RD RISC Processor
+	    4MB/8MB/16MB/32MB/64MB/128MB ECC EDO Memory
+
+DAC960PG    1/2/3 Wide Ultra SCSI-3 Channels
+	    33MHz Intel i960RP RISC Processor
+	    4MB/8MB ECC EDO Memory
+
+DAC960PU    1/2/3 Wide Ultra SCSI-3 Channels
+	    Intel i960CF RISC Processor
+	    4MB/8MB EDRAM or 2MB/4MB/8MB/16MB/32MB DRAM Memory
+
+DAC960PD    1/2/3 Wide Fast SCSI-2 Channels
+	    Intel i960CF RISC Processor
+	    4MB/8MB EDRAM or 2MB/4MB/8MB/16MB/32MB DRAM Memory
+
+DAC960PL    1/2/3 Wide Fast SCSI-2 Channels
+	    Intel i960 RISC Processor
+	    2MB/4MB/8MB/16MB/32MB DRAM Memory
+
+For the eXtremeRAID 1100, firmware version 5.06-0-52 or above is required.
+
+For the AcceleRAID 250, 200, and 150, firmware version 4.06-0-57 or above is
+required.
+
+For the DAC960PJ and DAC960PG, firmware version 4.06-0-00 or above is required.
+
+For the DAC960PU, DAC960PD, and DAC960PL, firmware version 3.51-0-04 or above
+is required.
+
+Note that earlier revisions of the DAC960PU, DAC960PD, and DAC960PL controllers
+were delivered with version 2.xx firmware.  Version 2.xx firmware is not
+supported by this driver and no support is envisioned.  Contact Mylex RAID
+Technical Support to inquire about upgrading controllers with version 2.xx
+firmware to version 3.51-0-04.  Upgrading to version 3.xx firmware requires
+installation of higher capacity Flash ROM chips, and not all DAC960PD and
+DAC960PL controllers can be upgraded.
+
+Please note that not all SCSI disk drives are suitable for use with DAC960
+controllers, and only particular firmware versions of any given model may
+actually function correctly.  Similarly, not all motherboards have a BIOS that
+properly initializes the AcceleRAID 250, AcceleRAID 200, AcceleRAID 150,
+DAC960PJ, and DAC960PG because the Intel i960RD/RP is a multi-function device.
+If in doubt, contact Mylex RAID Technical Support (support@mylex.com) to verify
+compatibility.  Mylex makes available a hard disk compatibility list by FTP at
+ftp://ftp.mylex.com/pub/dac960/diskcomp.html.
+
+
+			      DRIVER INSTALLATION
+
+This distribution was prepared for Linux kernel version 2.2.11 or 2.0.37.
+
+To install the DAC960 RAID driver, you may use the following commands,
+replacing "/usr/src" with wherever you keep your Linux kernel source tree:
+
+  cd /usr/src
+  tar -xvzf DAC960-2.2.4.tar.gz (or DAC960-2.0.4.tar.gz)
+  mv README.DAC960 linux/Documentation
+  mv DAC960.[ch] linux/drivers/block
+  patch -p0 < DAC960.patch
+  cd linux
+  make config
+  make depend
+  make bzImage (or zImage)
+
+Then install "arch/i386/boot/bzImage" or "arch/i386/boot/zImage" as your
+standard kernel, run lilo if appropriate, and reboot.
+
+To create the necessary devices in /dev, the "make_rd" script included in
+"DAC960-Utilities.tar.gz" from http://www.dandelion.com/Linux/ may be used.
+LILO 21 and FDISK v2.9 include DAC960 support; also included in this archive
+are patches to LILO 20 and FDISK v2.8 that add DAC960 support, along with
+statically linked executables of LILO and FDISK.  This modified version of LILO
+will allow booting from a DAC960 controller and/or mounting the root file
+system from a DAC960.
+
+Red Hat Linux 6.0 and SuSE Linux 6.1 include support for Mylex PCI RAID
+controllers.  Installing directly onto a DAC960 may be problematic from other
+Linux distributions until their installation utilities are updated.
+
+
+			      INSTALLATION NOTES
+
+Before installing Linux or adding DAC960 logical drives to an existing Linux
+system, the controller must first be configured to provide one or more logical
+drives using the BIOS Configuration Utility or DACCF.  Please note that since
+there are only at most 6 usable partitions on each logical drive, systems
+requiring more partitions should subdivide a drive group into multiple logical
+drives, each of which can have up to 6 partitions.  Also, note that with large
+disk arrays it is advisable to enable the 8GB BIOS Geometry (255/63) rather
+than accepting the default 2GB BIOS Geometry (128/32); failing to so do will
+cause the logical drive geometry to have more than 65535 cylinders which will
+make it impossible for FDISK to be used properly.  The 8GB BIOS Geometry can be
+enabled by configuring the DAC960 BIOS, which is accessible via Alt-M during
+the BIOS initialization sequence.
+
+For maximum performance and the most efficient E2FSCK performance, it is
+recommended that EXT2 file systems be built with a 4KB block size and 16 block
+stride to match the DAC960 controller's 64KB default stripe size.  The command
+"mke2fs -b 4096 -R stride=16 <device>" is appropriate.  Unless there will be a
+large number of small files on the file systems, it is also beneficial to add
+the "-i 16384" option to increase the bytes per inode parameter thereby
+reducing the file system metadata.  Finally, on systems that will only be run
+with Linux 2.2 or later kernels it is beneficial to enable sparse superblocks
+with the "-s 1" option.
+
+
+		      DAC960 ANNOUNCEMENTS MAILING LIST
+
+The DAC960 Announcements Mailing List provides a forum for informing Linux
+users of new driver releases and other announcements regarding Linux support
+for DAC960 PCI RAID Controllers.  To join the mailing list, send a message to
+"dac960-announce-request@dandelion.com" with the line "subscribe" in the
+message body.
+
+
+		CONTROLLER CONFIGURATION AND STATUS MONITORING
+
+The DAC960 RAID controllers running firmware 4.06 or above include a Background
+Initialization facility so that system downtime is minimized both for initial
+installation and subsequent configuration of additional storage.  The BIOS
+Configuration Utility (accessible via Alt-R during the BIOS initialization
+sequence) is used to quickly configure the controller, and then the logical
+drives that have been created are available for immediate use even while they
+are still being initialized by the controller.  The primary need for online
+configuration and status monitoring is then to avoid system downtime when disk
+drives fail and must be replaced.  Mylex's online monitoring and configuration
+utilities are being ported to Linux and will become available at some point in
+the future.  Note that with a SAF-TE (SCSI Accessed Fault-Tolerant Enclosure)
+enclosure, the controller is able to rebuild failed drives automatically as
+soon as a drive replacement is made available.
+
+The primary interfaces for controller configuration and status monitoring are
+special files created in the /proc/rd/... hierarchy along with the normal
+system console logging mechanism.  Whenever the system is operating, the DAC960
+driver queries each controller for status information every 10 seconds, and
+checks for additional conditions every 60 seconds.  The initial status of each
+controller is always available for controller N in /proc/rd/cN/initial_status,
+and the current status as of the last status monitoring query is available in
+/proc/rd/cN/current_status.  In addition, status changes are also logged by the
+driver to the system console and will appear in the log files maintained by
+syslog.  The progress of asynchronous rebuild or consistency check operations
+is also available in /proc/rd/cN/current_status, and progress messages are
+logged to the system console at most every 60 seconds.
+
+Starting with the 2.2.3/2.0.3 versions of the driver, the status information
+available in /proc/rd/cN/initial_status and /proc/rd/cN/current_status has been
+augmented to include the vendor, model, revision, and serial number (if
+available) for each physical device found connected to the controller:
+
+***** DAC960 RAID Driver Version 2.2.3 of 19 August 1999 *****
+Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+Configuring Mylex DAC960PRL PCI RAID Controller
+  Firmware Version: 4.07-0-07, Channels: 1, Memory Size: 16MB
+  PCI Bus: 1, Device: 4, Function: 1, I/O Address: Unassigned
+  PCI Address: 0xFE300000 mapped at 0xA0800000, IRQ Channel: 21
+  Controller Queue Depth: 128, Maximum Blocks per Command: 128
+  Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
+  Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
+  SAF-TE Enclosure Management Enabled
+  Physical Devices:
+    0:0  Vendor: IBM       Model: DRVS09D           Revision: 0270
+         Serial Number:       68016775HA
+         Disk Status: Online, 17928192 blocks
+    0:1  Vendor: IBM       Model: DRVS09D           Revision: 0270
+         Serial Number:       68004E53HA
+         Disk Status: Online, 17928192 blocks
+    0:2  Vendor: IBM       Model: DRVS09D           Revision: 0270
+         Serial Number:       13013935HA
+         Disk Status: Online, 17928192 blocks
+    0:3  Vendor: IBM       Model: DRVS09D           Revision: 0270
+         Serial Number:       13016897HA
+         Disk Status: Online, 17928192 blocks
+    0:4  Vendor: IBM       Model: DRVS09D           Revision: 0270
+         Serial Number:       68019905HA
+         Disk Status: Online, 17928192 blocks
+    0:5  Vendor: IBM       Model: DRVS09D           Revision: 0270
+         Serial Number:       68012753HA
+         Disk Status: Online, 17928192 blocks
+    0:6  Vendor: ESG-SHV   Model: SCA HSBP M6       Revision: 0.61
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Online, 89640960 blocks, Write Thru
+  No Rebuild or Consistency Check in Progress
+
+To simplify the monitoring process for custom software, the special file
+/proc/rd/status returns "OK" when all DAC960 controllers in the system are
+operating normally and no failures have occurred, or "ALERT" if any logical
+drives are offline or critical or any non-standby physical drives are dead.
+
+Configuration commands for controller N are available via the special file
+/proc/rd/cN/user_command.  A human readable command can be written to this
+special file to initiate a configuration operation, and the results of the
+operation can then be read back from the special file in addition to being
+logged to the system console.  The shell command sequence
+
+  echo "<configuration-command>" > /proc/rd/c0/user_command
+  cat /proc/rd/c0/user_command
+
+is typically used to execute configuration commands.  The configuration
+commands are:
+
+  flush-cache
+
+    The "flush-cache" command flushes the controller's cache.  The system
+    automatically flushes the cache at shutdown or if the driver module is
+    unloaded, so this command is only needed to be certain a write back cache
+    is flushed to disk before the system is powered off by a command to a UPS.
+    Note that the flush-cache command also stops an asynchronous rebuild or
+    consistency check, so it should not be used except when the system is being
+    halted.
+
+  kill <channel>:<target-id>
+
+    The "kill" command marks the physical drive <channel>:<target-id> as DEAD.
+    This command is provided primarily for testing, and should not be used
+    during normal system operation.
+
+  make-online <channel>:<target-id>
+
+    The "make-online" command changes the physical drive <channel>:<target-id>
+    from status DEAD to status ONLINE.  In cases where multiple physical drives
+    have been killed simultaneously, this command may be used to bring them
+    back online, after which a consistency check is advisable.
+
+    Warning: make-online should only be used on a dead physical drive that is
+    an active part of a drive group, never on a standby drive.
+
+  make-standby <channel>:<target-id>
+
+    The "make-standby" command changes physical drive <channel>:<target-id>
+    from status DEAD to status STANDBY.  It should only be used in cases where
+    a dead drive was replaced after an automatic rebuild was performed onto a
+    standby drive.  It cannot be used to add a standby drive to the controller
+    configuration if one was not created initially; the BIOS Configuration
+    Utility must be used for that currently.
+
+  rebuild <channel>:<target-id>
+
+    The "rebuild" command initiates an asynchronous rebuild onto physical drive
+    <channel>:<target-id>.  It should only be used when a dead drive has been
+    replaced.
+
+  check-consistency <logical-drive-number>
+
+    The "check-consistency" command initiates an asynchronous consistency check
+    of <logical-drive-number> with automatic restoration.  It can be used
+    whenever it is desired to verify the consistency of the redundancy
+    information.
+
+  cancel-rebuild
+  cancel-consistency-check
+
+    The "cancel-rebuild" and "cancel-consistency-check" commands cancel any
+    rebuild or consistency check operations previously initiated.
+
+
+	       EXAMPLE I - DRIVE FAILURE WITHOUT A STANDBY DRIVE
+
+The following annotated logs demonstrate the controller configuration and and
+online status monitoring capabilities of the Linux DAC960 Driver.  The test
+configuration comprises 6 1GB Quantum Atlas I disk drives on two channels of a
+DAC960PJ controller.  The physical drives are configured into a single drive
+group without a standby drive, and the drive group has been configured into two
+logical drives, one RAID-5 and one RAID-6.  Note that these logs are from an
+earlier version of the driver and the messages have changed somewhat with newer
+releases, but the functionality remains similar.  First, here is the current
+status of the RAID configuration:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
+Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+Configuring Mylex DAC960PJ PCI RAID Controller
+  Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
+  PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
+  PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
+  Controller Queue Depth: 128, Maximum Blocks per Command: 128
+  Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
+  Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Online, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Online, 5498880 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Online, 3305472 blocks, Write Thru
+  No Rebuild or Consistency Check in Progress
+
+gwynedd:/u/lnz# cat /proc/rd/status
+OK
+
+The above messages indicate that everything is healthy, and /proc/rd/status
+returns "OK" indicating that there are no problems with any DAC960 controller
+in the system.  For demonstration purposes, while I/O is active Physical Drive
+1:1 is now disconnected, simulating a drive failure.  The failure is noted by
+the driver within 10 seconds of the controller's having detected it, and the
+driver logs the following console status messages indicating that Logical
+Drives 0 and 1 are now CRITICAL as a result of Physical Drive 1:1 being DEAD:
+
+DAC960#0: Physical Drive 1:2 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
+DAC960#0: Physical Drive 1:3 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
+DAC960#0: Physical Drive 1:1 killed because of timeout on SCSI command
+DAC960#0: Physical Drive 1:1 is now DEAD
+DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now CRITICAL
+DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now CRITICAL
+
+The Sense Keys logged here are just Check Condition / Unit Attention conditions
+arising from a SCSI bus reset that is forced by the controller during its error
+recovery procedures.  Concurrently with the above, the driver status available
+from /proc/rd also reflects the drive failure.  The status message in
+/proc/rd/status has changed from "OK" to "ALERT":
+
+gwynedd:/u/lnz# cat /proc/rd/status
+ALERT
+
+and /proc/rd/c0/current_status has been updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Dead, 2201600 blocks
+    1:2 - Disk: Online, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
+  No Rebuild or Consistency Check in Progress
+
+Since there are no standby drives configured, the system can continue to access
+the logical drives in a performance degraded mode until the failed drive is
+replaced and a rebuild operation completed to restore the redundancy of the
+logical drives.  Once Physical Drive 1:1 is replaced with a properly
+functioning drive, or if the physical drive was killed without having failed
+(e.g., due to electrical problems on the SCSI bus), the user can instruct the
+controller to initiate a rebuild operation onto the newly replaced drive:
+
+gwynedd:/u/lnz# echo "rebuild 1:1" > /proc/rd/c0/user_command
+gwynedd:/u/lnz# cat /proc/rd/c0/user_command
+Rebuild of Physical Drive 1:1 Initiated
+
+The echo command instructs the controller to initiate an asynchronous rebuild
+operation onto Physical Drive 1:1, and the status message that results from the
+operation is then available for reading from /proc/rd/c0/user_command, as well
+as being logged to the console by the driver.
+
+Within 10 seconds of this command the driver logs the initiation of the
+asynchronous rebuild operation:
+
+DAC960#0: Rebuild of Physical Drive 1:1 Initiated
+DAC960#0: Physical Drive 1:1 Error Log: Sense Key = 6, ASC = 29, ASCQ = 01
+DAC960#0: Physical Drive 1:1 is now WRITE-ONLY
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 1% completed
+
+and /proc/rd/c0/current_status is updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Write-Only, 2201600 blocks
+    1:2 - Disk: Online, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
+  Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 6% completed
+
+As the rebuild progresses, the current status in /proc/rd/c0/current_status is
+updated every 10 seconds:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Write-Only, 2201600 blocks
+    1:2 - Disk: Online, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Critical, 5498880 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Critical, 3305472 blocks, Write Thru
+  Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 15% completed
+
+and every minute a progress message is logged to the console by the driver:
+
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 32% completed
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 63% completed
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 94% completed
+DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 94% completed
+
+Finally, the rebuild completes successfully.  The driver logs the status of the 
+logical and physical drives and the rebuild completion:
+
+DAC960#0: Rebuild Completed Successfully
+DAC960#0: Physical Drive 1:1 is now ONLINE
+DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now ONLINE
+DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now ONLINE
+
+/proc/rd/c0/current_status is updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Online, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Online, 5498880 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Online, 3305472 blocks, Write Thru
+  Rebuild Completed Successfully
+
+and /proc/rd/status indicates that everything is healthy once again:
+
+gwynedd:/u/lnz# cat /proc/rd/status
+OK
+
+
+		EXAMPLE II - DRIVE FAILURE WITH A STANDBY DRIVE
+
+The following annotated logs demonstrate the controller configuration and and
+online status monitoring capabilities of the Linux DAC960 Driver.  The test
+configuration comprises 6 1GB Quantum Atlas I disk drives on two channels of a
+DAC960PJ controller.  The physical drives are configured into a single drive
+group with a standby drive, and the drive group has been configured into two
+logical drives, one RAID-5 and one RAID-6.  Note that these logs are from an
+earlier version of the driver and the messages have changed somewhat with newer
+releases, but the functionality remains similar.  First, here is the current
+status of the RAID configuration:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
+Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+Configuring Mylex DAC960PJ PCI RAID Controller
+  Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
+  PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
+  PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
+  Controller Queue Depth: 128, Maximum Blocks per Command: 128
+  Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
+  Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Online, 2201600 blocks
+    1:3 - Disk: Standby, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
+  No Rebuild or Consistency Check in Progress
+
+gwynedd:/u/lnz# cat /proc/rd/status
+OK
+
+The above messages indicate that everything is healthy, and /proc/rd/status
+returns "OK" indicating that there are no problems with any DAC960 controller
+in the system.  For demonstration purposes, while I/O is active Physical Drive
+1:2 is now disconnected, simulating a drive failure.  The failure is noted by
+the driver within 10 seconds of the controller's having detected it, and the
+driver logs the following console status messages:
+
+DAC960#0: Physical Drive 1:1 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
+DAC960#0: Physical Drive 1:3 Error Log: Sense Key = 6, ASC = 29, ASCQ = 02
+DAC960#0: Physical Drive 1:2 killed because of timeout on SCSI command
+DAC960#0: Physical Drive 1:2 is now DEAD
+DAC960#0: Physical Drive 1:2 killed because it was removed
+DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now CRITICAL
+DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now CRITICAL
+
+Since a standby drive is configured, the controller automatically begins
+rebuilding onto the standby drive:
+
+DAC960#0: Physical Drive 1:3 is now WRITE-ONLY
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 4% completed
+
+Concurrently with the above, the driver status available from /proc/rd also
+reflects the drive failure and automatic rebuild.  The status message in
+/proc/rd/status has changed from "OK" to "ALERT":
+
+gwynedd:/u/lnz# cat /proc/rd/status
+ALERT
+
+and /proc/rd/c0/current_status has been updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Dead, 2201600 blocks
+    1:3 - Disk: Write-Only, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Critical, 4399104 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Critical, 2754560 blocks, Write Thru
+  Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 4% completed
+
+As the rebuild progresses, the current status in /proc/rd/c0/current_status is
+updated every 10 seconds:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Dead, 2201600 blocks
+    1:3 - Disk: Write-Only, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Critical, 4399104 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Critical, 2754560 blocks, Write Thru
+  Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 40% completed
+
+and every minute a progress message is logged on the console by the driver:
+
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 40% completed
+DAC960#0: Rebuild in Progress: Logical Drive 0 (/dev/rd/c0d0) 76% completed
+DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 66% completed
+DAC960#0: Rebuild in Progress: Logical Drive 1 (/dev/rd/c0d1) 84% completed
+
+Finally, the rebuild completes successfully.  The driver logs the status of the 
+logical and physical drives and the rebuild completion:
+
+DAC960#0: Rebuild Completed Successfully
+DAC960#0: Physical Drive 1:3 is now ONLINE
+DAC960#0: Logical Drive 0 (/dev/rd/c0d0) is now ONLINE
+DAC960#0: Logical Drive 1 (/dev/rd/c0d1) is now ONLINE
+
+/proc/rd/c0/current_status is updated:
+
+***** DAC960 RAID Driver Version 2.0.0 of 23 March 1999 *****
+Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+Configuring Mylex DAC960PJ PCI RAID Controller
+  Firmware Version: 4.06-0-08, Channels: 3, Memory Size: 8MB
+  PCI Bus: 0, Device: 19, Function: 1, I/O Address: Unassigned
+  PCI Address: 0xFD4FC000 mapped at 0x8807000, IRQ Channel: 9
+  Controller Queue Depth: 128, Maximum Blocks per Command: 128
+  Driver Queue Depth: 127, Maximum Scatter/Gather Segments: 33
+  Stripe Size: 64KB, Segment Size: 8KB, BIOS Geometry: 255/63
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Dead, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
+  Rebuild Completed Successfully
+
+and /proc/rd/status indicates that everything is healthy once again:
+
+gwynedd:/u/lnz# cat /proc/rd/status
+OK
+
+Note that the absence of a viable standby drive does not create an "ALERT"
+status.  Once dead Physical Drive 1:2 has been replaced, the controller must be
+told that this has occurred and that the newly replaced drive should become the
+new standby drive:
+
+gwynedd:/u/lnz# echo "make-standby 1:2" > /proc/rd/c0/user_command
+gwynedd:/u/lnz# cat /proc/rd/c0/user_command
+Make Standby of Physical Drive 1:2 Succeeded
+
+The echo command instructs the controller to make Physical Drive 1:2 into a
+standby drive, and the status message that results from the operation is then
+available for reading from /proc/rd/c0/user_command, as well as being logged to
+the console by the driver.  Within 60 seconds of this command the driver logs:
+
+DAC960#0: Physical Drive 1:2 Error Log: Sense Key = 6, ASC = 29, ASCQ = 01
+DAC960#0: Physical Drive 1:2 is now STANDBY
+DAC960#0: Make Standby of Physical Drive 1:2 Succeeded
+
+and /proc/rd/c0/current_status is updated:
+
+gwynedd:/u/lnz# cat /proc/rd/c0/current_status
+  ...
+  Physical Devices:
+    0:1 - Disk: Online, 2201600 blocks
+    0:2 - Disk: Online, 2201600 blocks
+    0:3 - Disk: Online, 2201600 blocks
+    1:1 - Disk: Online, 2201600 blocks
+    1:2 - Disk: Standby, 2201600 blocks
+    1:3 - Disk: Online, 2201600 blocks
+  Logical Drives:
+    /dev/rd/c0d0: RAID-5, Online, 4399104 blocks, Write Thru
+    /dev/rd/c0d1: RAID-6, Online, 2754560 blocks, Write Thru
+  Rebuild Completed Successfully
diff -u --recursive --new-file v2.3.15/linux/Documentation/i386/zero-page.txt linux/Documentation/i386/zero-page.txt
--- v2.3.15/linux/Documentation/i386/zero-page.txt	Mon Oct  5 12:59:25 1998
+++ linux/Documentation/i386/zero-page.txt	Mon Aug 30 10:47:02 1999
@@ -30,6 +30,7 @@
  0xb0 - 0x1df		Free. Add more parameters here if you really need them.
 
 0x1e0	unsigned long	ALT_MEM_K, alternative mem check, in Kb
+0x1e8	char		number of entries in E820MAP (below)
 0x1f1	char		size of setup.S, number of sectors
 0x1f2	unsigned short	MOUNT_ROOT_RDONLY (if !=0)
 0x1f4	unsigned short	size of compressed kernel-part in the
@@ -64,7 +65,7 @@
 0x21c	unsigned long	INITRD_SIZE, size in bytes of ramdisk image
 0x220	4 bytes		(setup.S)
 0x224	unsigned short	setup.S heap end pointer
-0x226 - 0x7ff		setup.S code.
+0x2d0 - 0x600		E820MAP
 
 0x800	string, 2K max	COMMAND_LINE, the kernel commandline as
 			copied using CL_OFFSET.
diff -u --recursive --new-file v2.3.15/linux/Documentation/ioctl-number.txt linux/Documentation/ioctl-number.txt
--- v2.3.15/linux/Documentation/ioctl-number.txt	Thu Aug 26 13:05:34 1999
+++ linux/Documentation/ioctl-number.txt	Fri Aug 27 11:46:35 1999
@@ -79,6 +79,7 @@
 'S'	82-FF	scsi/scsi.h
 'T'	all	linux/soundcard.h	conflict!
 'T'	all	asm-i386/ioctls.h	conflict!
+'U'     all     linux/drivers/usb/usb.h
 'V'	all	linux/vt.h
 'W'	00-1F	linux/router.h		conflict [Please reallocate]
 'W'	00-1F	linux/watchdog.h
diff -u --recursive --new-file v2.3.15/linux/Documentation/networking/soundmodem.txt linux/Documentation/networking/soundmodem.txt
--- v2.3.15/linux/Documentation/networking/soundmodem.txt	Wed May 20 18:54:34 1998
+++ linux/Documentation/networking/soundmodem.txt	Mon Aug 30 10:18:40 1999
@@ -42,8 +42,8 @@
 /etc/conf.modules).
 
 Examples:
-  insmod soundmodem hw=0 mode=0 iobase=0x220 irq=5 dma=1
-  sethdlc -i sm0 -p hw sbc type afsk1200 io 0x220 irq 5 dma 1
+  insmod soundmodem mode="sbc:afsk1200" iobase=0x220 irq=5 dma=1
+  sethdlc -i sm0 -p mode "sbc:afsk1200" io 0x220 irq 5 dma 1
 
 Both lines configure the first port to drive a soundblaster card
 in 1200 baud AFSK mode.
diff -u --recursive --new-file v2.3.15/linux/Documentation/watchdog.txt linux/Documentation/watchdog.txt
--- v2.3.15/linux/Documentation/watchdog.txt	Wed Jun 24 14:30:07 1998
+++ linux/Documentation/watchdog.txt	Mon Aug 30 10:18:40 1999
@@ -77,17 +77,17 @@
 Contact Information
 
 People keep asking about the WDT watchdog timer hardware: The phone contacts
-for Industrial Computer Source are:
+for ICS Advent are:
  
 US: 619 677 0877 (sales)  0895 (fax)
 UK: 01243 533900
 France (1) 69.18.74.30
 
-Industrial Computer Source 
+ICS Advent 
 9950 Barnes Canyon Road 
 San Diego, CA     
 
-http://www.industry.net/indcompsrc
+http://www.icsadvent.com
 
 and please mention Linux when enquiring.
 
diff -u --recursive --new-file v2.3.15/linux/MAINTAINERS linux/MAINTAINERS
--- v2.3.15/linux/MAINTAINERS	Thu Aug 26 13:05:34 1999
+++ linux/MAINTAINERS	Tue Aug 31 16:03:17 1999
@@ -401,16 +401,24 @@
 W:	http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
 S:	Maintained
 
+IBM ServeRAID RAID DRIVER
+P:      Keith Mitchell
+M:      ipslinux@us.ibm.com
+W:      http://www.developer.ibm.com/welcome/netfinity/serveraid_beta.html
+S:      Supported 
+
 IDE DRIVER [GENERAL]
 P:	Andre Hedrick
-M:	hedrick@astro.dyer.vanderbilt.edu
+M:	andre@suse.com
 L:	linux-kernel@vger.rutgers.edu
-S:	Maintained
+W:	http://linux.kernel.org/pub/linux/kernel/people/hedrick/
+S:	Supported
 
 IDE/ATAPI CDROM DRIVER 
 P:	Jens Axboe
 M:	axboe@image.dk
 L:	linux-kernel@vger.rutgers.edu
+W:	http://www.kernel.dk
 S:	Maintained
 
 IDE/ATAPI TAPE/FLOPPY DRIVERS
@@ -716,6 +724,13 @@
 L:	linux-kernel@vger.rutgers.edu
 S:	Maintained
 
+SCSI CDROM DRIVER 
+P:	Jens Axboe
+M:	axboe@image.dk
+L:	linux-kernel@vger.rutgers.edu
+W:	http://www.kernel.dk
+S:	Maintained
+
 SCSI SG DRIVER
 P:	Doug Gilbert
 M:	dgilbert@interlog.com
@@ -843,6 +858,7 @@
 P:	Jens Axboe
 M:	axboe@image.dk
 L:	linux-kernel@vger.rutgers.edu
+W:	http://www.kernel.dk
 S:	Maintained
 
 USB HUB AND UHCI DRIVERS
diff -u --recursive --new-file v2.3.15/linux/Makefile linux/Makefile
--- v2.3.15/linux/Makefile	Thu Aug 26 13:05:34 1999
+++ linux/Makefile	Thu Aug 26 13:05:56 1999
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 15
+SUBLEVEL = 16
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
diff -u --recursive --new-file v2.3.15/linux/Rules.make linux/Rules.make
--- v2.3.15/linux/Rules.make	Mon Aug  2 17:09:47 1999
+++ linux/Rules.make	Thu Aug 26 09:41:36 1999
@@ -73,11 +73,11 @@
 ALL_O = $(OX_OBJS) $(O_OBJS)
 $(O_TARGET): $(ALL_O)
 	rm -f $@
-ifneq "$(strip $(ALL_O))" ""
-	$(LD) $(EXTRA_LDFLAGS) -r -o $@ $(ALL_O)
-else
-	$(AR) rcs $@
-endif
+    ifneq "$(strip $(ALL_O))" ""
+	$(LD) $(EXTRA_LDFLAGS) -r -o $@ $(filter $(ALL_O), $^)
+    else
+	$(AR) rcs $@ $(filter $(ALL_O), $^)
+    endif
 	@ ( \
 	    echo 'ifeq ($(strip $(subst $(comma),:,$(EXTRA_LDFLAGS) $(ALL_O))),$$(strip $$(subst $$(comma),:,$$(EXTRA_LDFLAGS) $$(ALL_O))))' ; \
 	    echo 'FILES_FLAGS_UP_TO_DATE += $@' ; \
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/Makefile linux/arch/alpha/Makefile
--- v2.3.15/linux/arch/alpha/Makefile	Sun Jan 24 21:29:52 1999
+++ linux/arch/alpha/Makefile	Tue Aug 31 10:50:39 1999
@@ -59,10 +59,10 @@
 endif
 
 # For TSUNAMI, we must have the assembler not emulate our instructions.
-# The same is true for POLARIS.
+# The same is true for POLARIS, and now PYXIS.
 # BWX is most important, but we don't really want any emulation ever.
 ifeq ($(old_gas),y)
- ifneq ($(CONFIG_ALPHA_GENERIC)$(CONFIG_ALPHA_TSUNAMI)$(CONFIG_ALPHA_POLARIS),)
+ ifneq ($(CONFIG_ALPHA_GENERIC)$(CONFIG_ALPHA_TSUNAMI)$(CONFIG_ALPHA_POLARIS)$(CONFIG_ALPHA_PYXIS),)
    # How do we do #error in make?
    CFLAGS := --error-please-upgrade-your-assembler
  endif
@@ -71,7 +71,7 @@
    CFLAGS := $(CFLAGS) -Wa,-mev6
  endif
  ifeq ($(CONFIG_ALPHA_PYXIS),y)
-   CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWIO_ENABLED
+   CFLAGS := $(CFLAGS) -Wa,-m21164a
  endif
  ifeq ($(CONFIG_ALPHA_POLARIS),y)
    CFLAGS := $(CFLAGS) -Wa,-m21164pc
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.3.15/linux/arch/alpha/config.in	Thu Aug 26 13:05:34 1999
+++ linux/arch/alpha/config.in	Tue Aug 31 10:50:39 1999
@@ -150,11 +150,6 @@
 	-o "$CONFIG_ALPHA_DP264" = "y" -o "$CONFIG_ALPHA_RAWHIDE" = "y" ]
 then
   bool 'Use SRM as bootloader' CONFIG_ALPHA_SRM
-  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-    if [ "$CONFIG_ALPHA_SRM" = "y" ]; then
-      bool '  Use SRM PCI setup' CONFIG_ALPHA_SRM_SETUP
-    fi
-  fi
 fi
 if [ "$CONFIG_ALPHA_ALCOR" = "y" -o "$CONFIG_ALPHA_MIKASA" = "y" \
 	-o "$CONFIG_ALPHA_SABLE" = "y" -o "$CONFIG_ALPHA_NORITAKE" = "y" \
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.3.15/linux/arch/alpha/defconfig	Thu Feb 25 10:46:46 1999
+++ linux/arch/alpha/defconfig	Tue Aug 31 10:50:39 1999
@@ -17,7 +17,6 @@
 #
 # General setup
 #
-CONFIG_NATIVE=y
 CONFIG_ALPHA_GENERIC=y
 # CONFIG_ALPHA_ALCOR is not set
 # CONFIG_ALPHA_XL is not set
@@ -39,14 +38,12 @@
 # CONFIG_ALPHA_P2K is not set
 # CONFIG_ALPHA_RAWHIDE is not set
 # CONFIG_ALPHA_RUFFIAN is not set
+# CONFIG_ALPHA_RX164 is not set
 # CONFIG_ALPHA_SX164 is not set
 # CONFIG_ALPHA_SABLE is not set
 # CONFIG_ALPHA_TAKARA is not set
-# CONFIG_SMP is not set
 CONFIG_PCI=y
-CONFIG_ALPHA_NEED_ROUNDING_EMULATION=y
-# CONFIG_PCI_QUIRKS is not set
-CONFIG_PCI_OLD_PROC=y
+# CONFIG_SMP is not set
 CONFIG_NET=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
@@ -58,9 +55,10 @@
 # CONFIG_PARPORT is not set
 
 #
-# Plug and Play support
+# Plug and Play configuration
 #
 # CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
 
 #
 # Block devices
@@ -72,6 +70,7 @@
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
 # CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_CPQ_DA is not set
 
 #
 # Additional Block Devices
@@ -83,6 +82,7 @@
 # CONFIG_BLK_DEV_XD is not set
 CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -90,7 +90,7 @@
 #
 # CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
-# CONFIG_FIREWALL is not set
+# CONFIG_NETFILTER is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -106,8 +106,6 @@
 #
 # (it is safe to leave these untouched)
 #
-# CONFIG_INET_RARP is not set
-CONFIG_IP_NOSR=y
 CONFIG_SKB_LARGE=y
 
 #
@@ -141,6 +139,7 @@
 # SCSI low-level drivers
 #
 # CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA152X is not set
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
@@ -148,23 +147,29 @@
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_DMA is not set
 # CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_NCR53C8XX is not set
+# CONFIG_SCSI_SYM53C8XX 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=y
+# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_SEAGATE is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
@@ -175,9 +180,18 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
 # CONFIG_ARCNET is not set
 CONFIG_DUMMY=m
 # CONFIG_EQUALIZER is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
 CONFIG_NET_ETHERNET=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -194,14 +208,26 @@
 # CONFIG_EEXPRESS_PRO100 is not set
 # CONFIG_NE2K_PCI is not set
 # CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE 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_SLIP is not set
 # CONFIG_NET_RADIO is not set
+
+#
+# Token ring devices
+#
 # CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+
+#
+# Wan interfaces
+#
 # CONFIG_HOSTESS_SV11 is not set
+# CONFIG_COSA is not set
+# CONFIG_SEALEVEL_4021 is not set
+# CONFIG_DLCI is not set
 # CONFIG_WAN_DRIVERS is not set
 # CONFIG_LAPBETHER is not set
 # CONFIG_X25_ASY is not set
@@ -217,7 +243,7 @@
 # CONFIG_ISDN is not set
 
 #
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+# Old CD-ROM drivers (not SCSI, not IDE)
 #
 # CONFIG_CD_NO_IDESCSI is not set
 
@@ -232,20 +258,30 @@
 # CONFIG_SERIAL_NONSTANDARD is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_MOUSE=y
-# CONFIG_ATIXL_BUSMOUSE is not set
+
+#
+# Mice
+#
 # CONFIG_BUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
-# CONFIG_UMISC is not set
 # CONFIG_QIC02_TAPE is not set
 # CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
+
+#
+# Video For Linux
+#
 # CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
+
+#
+# Joystick support
+#
 # CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
 
 #
 # Ftape, the floppy tape device driver
@@ -256,31 +292,43 @@
 # Filesystems
 #
 # CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_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_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
+CONFIG_DEVPTS_FS=y
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
-# CONFIG_NFSD is not set
 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_DEVPTS_FS=y
-# CONFIG_MAC_PARTITION is not set
+# CONFIG_NCP_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_OSF_PARTITION=y
+# CONFIG_SMD_DISKLABEL is not set
+# CONFIG_SGI_DISKLABEL is not set
 # CONFIG_NLS is not set
 
 #
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile
--- v2.3.15/linux/arch/alpha/kernel/Makefile	Thu Aug 26 13:05:34 1999
+++ linux/arch/alpha/kernel/Makefile	Tue Aug 31 10:50:39 1999
@@ -16,7 +16,7 @@
 
 O_TARGET := kernel.o
 O_OBJS   := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
-	    bios32.o ptrace.o time.o fpreg.o semaphore.o
+	    ptrace.o time.o fpreg.o semaphore.o pci_syscall.o
 OX_OBJS  := alpha_ksyms.o
 
 
@@ -28,9 +28,14 @@
 	    sys_jensen.o sys_miata.o sys_mikasa.o sys_noritake.o \
 	    sys_rawhide.o sys_ruffian.o sys_sable.o sys_sio.o \
 	    sys_sx164.o sys_takara.o sys_rx164.o \
-	    es1888.o smc37c669.o smc37c93x.o
+	    es1888.o smc37c669.o smc37c93x.o ns87312.o \
+	    pci.o pci_setup.o
 else
 
+ifdef CONFIG_PCI
+O_OBJS   += pci.o pci_setup.o
+endif
+
 # Core logic support
 ifdef CONFIG_ALPHA_APECS
 O_OBJS   += core_apecs.o
@@ -62,10 +67,10 @@
 O_OBJS   += sys_alcor.o
 endif
 ifneq ($(CONFIG_ALPHA_CABRIOLET)$(CONFIG_ALPHA_EB164)$(CONFIG_ALPHA_EB66P)$(CONFIG_ALPHA_LX164)$(CONFIG_ALPHA_PC164),)
-O_OBJS   += sys_cabriolet.o
+O_OBJS   += sys_cabriolet.o ns87312.o
 endif
 ifdef CONFIG_ALPHA_DP264
-O_OBJS   += sys_dp264.o
+O_OBJS   += sys_dp264.o es1888.o smc37c669.o
 endif
 ifneq ($(CONFIG_ALPHA_EB64P)$(CONFIG_ALPHA_EB66),)
 O_OBJS   += sys_eb64p.o
@@ -74,7 +79,7 @@
 O_OBJS   += sys_jensen.o
 endif
 ifdef CONFIG_ALPHA_MIATA
-O_OBJS   += sys_miata.o
+O_OBJS   += sys_miata.o es1888.o smc37c669.o
 endif
 ifdef CONFIG_ALPHA_MIKASA
 O_OBJS   += sys_mikasa.o
@@ -95,22 +100,16 @@
 O_OBJS   += sys_sable.o
 endif
 ifneq ($(CONFIG_ALPHA_BOOK1)$(CONFIG_ALPHA_AVANTI)$(CONFIG_ALPHA_NONAME)$(CONFIG_ALPHA_P2K)$(CONFIG_ALPHA_XL),)
-O_OBJS   += sys_sio.o
+O_OBJS   += sys_sio.o ns87312.o
 endif
 ifdef CONFIG_ALPHA_SX164
-O_OBJS   += sys_sx164.o
+O_OBJS   += sys_sx164.o smc37c669.o
 endif
 ifdef CONFIG_ALPHA_TAKARA
-O_OBJS   += sys_takara.o
+O_OBJS   += sys_takara.o ns87312.o
 endif
 
 # Device support
-ifneq ($(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),)
-O_OBJS   += es1888.o
-endif
-ifneq ($(CONFIG_ALPHA_SX164)$(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),)
-O_OBJS   += smc37c669.o
-endif
 ifneq ($(CONFIG_ALPHA_PC164)$(CONFIG_ALPHA_LX164),)
 O_OBJS   += smc37c93x.o
 endif
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.3.15/linux/arch/alpha/kernel/alpha_ksyms.c	Wed Aug  4 15:48:00 1999
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Tue Aug 31 10:50:39 1999
@@ -36,6 +36,7 @@
 extern struct hwrpb_struct *hwrpb;
 extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
+extern void ___delay(void);
 
 /* these are C runtime functions with special calling conventions: */
 extern void __divl (void);
@@ -146,6 +147,11 @@
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
+
+/*
+ * This is called specially from __delay.
+ */
+EXPORT_SYMBOL_NOVERS(___delay);
 
 /* 
  * SMP-specific symbols.
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
--- v2.3.15/linux/arch/alpha/kernel/bios32.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/bios32.c	Wed Dec 31 16:00:00 1969
@@ -1,1374 +0,0 @@
-/*
- * bios32.c - PCI BIOS functions for Alpha systems not using BIOS
- *	      emulation code.
- *
- * Written by Dave Rusling (david.rusling@reo.mts.dec.com)
- *
- * Adapted to 64-bit kernel and then rewritten by David Mosberger
- * (davidm@cs.arizona.edu)
- *
- * For more information, please consult
- *
- * PCI BIOS Specification Revision
- * PCI Local Bus Specification
- * PCI System Design Guide
- *
- * PCI Special Interest Group
- * M/S HF3-15A
- * 5200 N.E. Elam Young Parkway
- * Hillsboro, Oregon 97124-6497
- * +1 (503) 696-2000
- * +1 (800) 433-5177
- *
- * Manuals are $25 each or $50 for all three, plus $7 shipping
- * within the United States, $35 abroad.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <asm/pci.h>
-#include <asm/dma.h>
-
-#include "proto.h"
-#include "bios32.h"
-
-#define DEBUG_DEVS 0
-#define DEBUG_HOSE 0
-
-#if DEBUG_DEVS
-# define DBG_DEVS(args)		printk args
-#else
-# define DBG_DEVS(args)
-#endif
-
-#if DEBUG_HOSE
-# define DBG_HOSE(args)		printk args
-#else
-# define DBG_HOSE(args)
-#endif
-
-#ifndef CONFIG_PCI
-
-asmlinkage int sys_pciconfig_read() { return -ENOSYS; }
-asmlinkage int sys_pciconfig_write() { return -ENOSYS; }
-void reset_for_srm(void) { }
-
-#else /* CONFIG_PCI */
-
-#include <linux/malloc.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-
-/*
- * PCI public interfaces.
- */
-
-#define MAJOR_REV	0
-#define MINOR_REV	4	/* minor revision 4, add multi-PCI handling */
-
-struct linux_hose_info *bus2hose[256];
-struct linux_hose_info *hose_head, **hose_tail = &hose_head;
-int hose_count;
-int pci_probe_enabled;
-
-static void layout_hoses(void);
-
-int
-pcibios_present(void)
-{
-	return alpha_mv.hose_read_config_byte != NULL;
-}
-
-void __init
-pcibios_init(void)
-{
-	if (!pcibios_present())
-		return;
-
-	printk("Alpha PCI BIOS32 revision %d.%02d\n", MAJOR_REV, MINOR_REV);
-	if (alpha_use_srm_setup)
-		printk("   NOT modifying existing (SRM) PCI configuration\n");
-}
-
-char * __init
-pcibios_setup(char *str)
-{
-	return str;
-}
-
-void __init
-pcibios_fixup(void)
-{
-	alpha_mv.pci_fixup();
-}
-
-void __init
-pcibios_fixup_bus(struct pci_bus *bus)
-{
-}
-
-int
-pcibios_read_config_byte (u8 bus, u8 dev, u8 where, u8 *value)
-{
-	int r = PCIBIOS_FUNC_NOT_SUPPORTED;
-	*value = 0xff;
-	if (alpha_mv.hose_read_config_byte) {
-		r = (alpha_mv.hose_read_config_byte
-		     (bus, dev, where, value, bus2hose[bus]));
-	}
-	return r;
-}
-
-int
-pcibios_read_config_word (u8 bus, u8 dev, u8 where, u16 *value)
-{
-	int r = PCIBIOS_FUNC_NOT_SUPPORTED;
-	*value = 0xffff;
-	if (alpha_mv.hose_read_config_word) {
-		r = PCIBIOS_BAD_REGISTER_NUMBER;
-		if (!(where & 1))
-			r = (alpha_mv.hose_read_config_word
-			     (bus, dev, where, value, bus2hose[bus]));
-	}
-	return r;
-}
-
-int
-pcibios_read_config_dword (u8 bus, u8 dev, u8 where, u32 *value)
-{
-	int r = PCIBIOS_FUNC_NOT_SUPPORTED;
-	*value = 0xffffffff;
-	if (alpha_mv.hose_read_config_dword) {
-		r = PCIBIOS_BAD_REGISTER_NUMBER;
-		if (!(where & 3))
-			r = (alpha_mv.hose_read_config_dword
-			     (bus, dev, where, value, bus2hose[bus]));
-	}
-	return r;
-}
-
-int
-pcibios_write_config_byte (u8 bus, u8 dev, u8 where, u8 value)
-{
-	int r = PCIBIOS_FUNC_NOT_SUPPORTED;
-	if (alpha_mv.hose_write_config_byte) {
-		r = (alpha_mv.hose_write_config_byte
-		     (bus, dev, where, value, bus2hose[bus]));
-	}
-	return r;
-}
-
-int
-pcibios_write_config_word (u8 bus, u8 dev, u8 where, u16 value)
-{
-	int r = PCIBIOS_FUNC_NOT_SUPPORTED;
-	if (alpha_mv.hose_write_config_word) {
-		r = PCIBIOS_BAD_REGISTER_NUMBER;
-		if (!(where & 1))
-			r = (alpha_mv.hose_write_config_word
-			     (bus, dev, where, value, bus2hose[bus]));
-	}
-	return r;
-}
-
-int
-pcibios_write_config_dword (u8 bus, u8 dev, u8 where, u32 value)
-{
-	int r = PCIBIOS_FUNC_NOT_SUPPORTED;
-	if (alpha_mv.hose_write_config_dword) {
-		r = PCIBIOS_BAD_REGISTER_NUMBER;
-		if (!(where & 3))
-			r = (alpha_mv.hose_write_config_dword
-			     (bus, dev, where, value, bus2hose[bus]));
-	}
-	return r;
-}
-
-asmlinkage int
-sys_pciconfig_read(unsigned long bus, unsigned long dfn,
-		   unsigned long off, unsigned long len,
-		   unsigned char *buf)
-{
-	unsigned char ubyte;
-	unsigned short ushort;
-	unsigned int uint;
-	long err = 0;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	if (!pcibios_present())
-		return -ENOSYS;
-	
-	switch (len) {
-	case 1:
-		err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
-		put_user(ubyte, buf);
-		break;
-	case 2:
-		err = pcibios_read_config_word(bus, dfn, off, &ushort);
-		put_user(ushort, (unsigned short *)buf);
-		break;
-	case 4:
-		err = pcibios_read_config_dword(bus, dfn, off, &uint);
-		put_user(uint, (unsigned int *)buf);
-		break;
-	default:
-		err = -EINVAL;
-		break;
-	}
-	return err;
-}
-
-asmlinkage int
-sys_pciconfig_write(unsigned long bus, unsigned long dfn,
-		    unsigned long off, unsigned long len,
-		    unsigned char *buf)
-{
-	unsigned char ubyte;
-	unsigned short ushort;
-	unsigned int uint;
-	long err = 0;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	if (!pcibios_present())
-		return -ENOSYS;
-
-	switch (len) {
-	case 1:
-		err = get_user(ubyte, buf);
-		if (err)
-			break;
-		err = pcibios_write_config_byte(bus, dfn, off, ubyte);
-		if (err != PCIBIOS_SUCCESSFUL) {
-			err = -EFAULT;
-		}
-		break;
-	case 2:
-		err = get_user(ushort, (unsigned short *)buf);
-		if (err)
-			break;
-		err = pcibios_write_config_word(bus, dfn, off, ushort);
-		if (err != PCIBIOS_SUCCESSFUL) {
-			err = -EFAULT;
-		}
-		break;
-	case 4:
-		err = get_user(uint, (unsigned int *)buf);
-		if (err)
-			break;
-		err = pcibios_write_config_dword(bus, dfn, off, uint);
-		if (err != PCIBIOS_SUCCESSFUL) {
-			err = -EFAULT;
-		}
-		break;
-	default:
-		err = -EINVAL;
-		break;
-	}
-	return err;
-}
-
-
-/*
- * Gory details start here...
- */
-
-/*
- * Align VAL to ALIGN, which must be a power of two.
- */
-#define ALIGN(val,align)	(((val) + ((align) - 1)) & ~((align) - 1))
-
-
-/* 
- * The following structure records initial configuration of devices
- * so that we can reset them on shutdown and so enable clean reboots
- * on SRM.  It is more trouble than it iw worth to conditionalize this.
- */
-
-struct srm_irq_reset {
-	struct srm_irq_reset *next;
-	struct pci_dev *dev;
-	u8 irq;
-} *srm_irq_resets;
-
-struct srm_io_reset {
-	struct srm_io_reset *next;
-	struct pci_dev *dev;
-	u32 io;
-	u8 reg;
-} *srm_io_resets;
-
-/* Apply the collected reset modifications.  */
-
-void
-reset_for_srm(void)
-{
-	struct srm_irq_reset *qreset;
-	struct srm_io_reset *ireset;
-
-	/* Reset any IRQs that we changed.  */
-	for (qreset = srm_irq_resets; qreset ; qreset = qreset->next) {
-		pcibios_write_config_byte(qreset->dev->bus->number,
-					  qreset->dev->devfn,
-					  PCI_INTERRUPT_LINE,
-					  qreset->irq);
-#if 1
-		printk("reset_for_srm: bus %d slot 0x%x "
-		       "SRM IRQ 0x%x changed back from 0x%x\n",
-		       qreset->dev->bus->number,
-		       PCI_SLOT(qreset->dev->devfn),
-		       qreset->irq, qreset->dev->irq);
-#endif
-	}
-
-	/* Reset any IO addresses that we changed.  */
-	for (ireset = srm_io_resets; ireset ; ireset = ireset->next) {
-		pcibios_write_config_dword(ireset->dev->bus->number,
-					   ireset->dev->devfn,
-					   ireset->reg, ireset->io);
-#if 1
-		printk("reset_for_srm: bus %d slot 0x%x "
-		       "SRM MEM/IO restored to 0x%x\n",
-		       ireset->dev->bus->number,
-		       PCI_SLOT(ireset->dev->devfn),
-		       ireset->io);
-#endif
-	}
-}
-
-static void
-new_irq_reset(struct pci_dev *dev, u8 irq)
-{
-	struct srm_irq_reset *n;
-	n = kmalloc(sizeof(*n), GFP_KERNEL);
-
-	n->next = srm_irq_resets;
-	n->dev = dev;
-	n->irq = irq;
-	srm_irq_resets = n;
-}
-
-static void
-new_io_reset(struct pci_dev *dev, u8 reg, u32 io)
-{
-	struct srm_io_reset *n;
-	n = kmalloc(sizeof(*n), GFP_KERNEL);
-
-	n->next = srm_io_resets;
-	n->dev = dev;
-	n->reg = reg;
-	n->io = io;
-	srm_io_resets = n;
-}
-
-
-/*
- * Disable PCI device DEV so that it does not respond to I/O or memory
- * accesses.
- */
-static void __init
-disable_dev(struct pci_dev *dev)
-{
-	struct pci_bus *bus;
-	unsigned short cmd;
-
-	/*
-	 * HACK: the PCI-to-EISA bridge does not seem to identify
-	 *       itself as a bridge... :-(
-	 */
-	if (dev->vendor == PCI_VENDOR_ID_INTEL &&
-	    dev->device == PCI_DEVICE_ID_INTEL_82375) {
-		dev->class = PCI_CLASS_BRIDGE_EISA;
-		DBG_DEVS(("disable_dev: ignoring PCEB...\n"));
-		return;
-	}
-
-	if (dev->vendor == PCI_VENDOR_ID_INTEL &&
-	    dev->device == PCI_DEVICE_ID_INTEL_82378) {
-		dev->class = PCI_CLASS_BRIDGE_ISA;
-		DBG_DEVS(("disable_dev: ignoring SIO...\n"));
-		return;
-	}
-
-	/*
-	 * We don't have code that will init the CYPRESS bridge correctly
-	 * so we do the next best thing, and depend on the previous
-	 * console code to do the right thing, and ignore it here... :-\
-	 */
-	if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
-	    dev->device == PCI_DEVICE_ID_CONTAQ_82C693) {
-		DBG_DEVS(("disable_dev: ignoring CYPRESS bridge...\n"));
-		return;
-	}
-
-#if DEBUG_DEVS && 0
-	/* Worse HACK: Don't disable the video card, so I can see where
-	   it is *really* falling over.  */
-	if (dev->class >> 16 == PCI_BASE_CLASS_DISPLAY) {
-		DBG_DEVS(("disable_dev: ignoring video card %04x:%04x\n",
-			  dev->vendor, dev->device));
-		return;
-	}
-#endif
-
-	DBG_DEVS(("disable_dev: disabling %04x:%04x\n",
-		  dev->vendor, dev->device));
-
-	bus = dev->bus;
-	pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
-
-	/* hack, turn it off first... */
-	cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
-	pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND, cmd);
-}
-
-
-/*
- * Layout memory and I/O for a device:
- */
-#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))
-
-static unsigned int io_base;
-static unsigned int mem_base; 
-
-static void __init
-layout_dev(struct pci_dev *dev)
-{
-	struct pci_bus *bus;
-	unsigned short cmd;
-	unsigned int base, mask, size, off, idx;
-	unsigned int orig_base;
-	unsigned int alignto;
-	unsigned long handle;
-
-	/*
-	 * HACK: the PCI-to-EISA bridge does not seem to identify
-	 *       itself as a bridge... :-(
-	 */
-	if (dev->vendor == PCI_VENDOR_ID_INTEL
-	    && dev->device == PCI_DEVICE_ID_INTEL_82375) {
-		dev->class = PCI_CLASS_BRIDGE_EISA;
-		DBG_DEVS(("layout_dev: ignoring PCEB...\n"));
-		return;
-	}
-
-	if (dev->vendor == PCI_VENDOR_ID_INTEL
-	    && dev->device == PCI_DEVICE_ID_INTEL_82378) {
-		dev->class = PCI_CLASS_BRIDGE_ISA;
-		DBG_DEVS(("layout_dev: ignoring SIO...\n"));
-		return;
-	}
-
-	if (dev->vendor == PCI_VENDOR_ID_CONTAQ
-	    && dev->device == PCI_DEVICE_ID_CONTAQ_82C693
-	    && dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) {
-		DBG_DEVS(("layout_dev: ignoring CYPRESS bridge...\n"));
-		return;
-	}
-
-	bus = dev->bus;
-	pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
-
-	for (idx = 0; idx <= 5; idx++) {
-		off = PCI_BASE_ADDRESS_0 + 4*idx;
-		/*
-		 * Figure out how much space and of what type this
-		 * device wants.
-		 */
-		pcibios_read_config_dword(bus->number, dev->devfn, off,
-					  &orig_base);
-		pcibios_write_config_dword(bus->number, dev->devfn, off,
-					   0xffffffff);
-		pcibios_read_config_dword(bus->number, dev->devfn, off, &base);
-		if (!base) {
-			/* This base-address register is unused.  */
-			dev->resource[idx].start = 0;
-			dev->resource[idx].end = 0;
-			dev->resource[idx].flags = 0;
-			continue;
-		}
-
-		DBG_DEVS(("layout_dev: slot %d fn %d off 0x%x base 0x%x\n",
-			  PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
-			  off, base));
-
-		/*
-		 * We've read the base address register back after
-		 * writing all ones and so now we must decode it.
-		 */
-		if (base & PCI_BASE_ADDRESS_SPACE_IO) {
-			/*
-			 * I/O space base address register.
-			 */
-			cmd |= PCI_COMMAND_IO;
-
-			base &= PCI_BASE_ADDRESS_IO_MASK;
-			mask = (~base << 1) | 0x1;
-			size = (mask & base) & 0xffffffff;
-
-			/* We don't want to disturb normal IDE functions, so
-			   we don't touch the first two I/O ports on the
-			   Cypress.  */
-			if (dev->vendor == PCI_VENDOR_ID_CONTAQ
-			    && dev->device == PCI_DEVICE_ID_CONTAQ_82C693
-			    && idx < 2) {
-				continue;
-			}
-
-			/*
-			 * Aligning to 0x800 rather than the minimum base of
-			 * 0x400 is an attempt to avoid having devices in 
-			 * any 0x?C?? range, which is where the de4x5 driver
-			 * probes for EISA cards.
-			 *
-			 * Adaptecs, especially, resent such intrusions.
-			 */
-			alignto = MAX(0x800, size);
-			base = ALIGN(io_base, alignto);
-			io_base = base + size;
-
-			pcibios_write_config_dword(bus->number, dev->devfn, 
-						   off, base | 0x1);
-			new_io_reset(dev, off, orig_base);
-
-			handle = PCI_HANDLE(bus->number) | base | 1;
-			dev->resource[idx].start
-			  = handle & PCI_BASE_ADDRESS_IO_MASK;
-			dev->resource[idx].end
-			  = dev->resource[idx].start + size - 1;
-			dev->resource[idx].flags
-			  = handle & ~PCI_BASE_ADDRESS_IO_MASK;
-
-			DBG_DEVS(("layout_dev: dev 0x%x IO @ 0x%lx (0x%x)\n",
-				  dev->device, handle, size));
-		} else {
-			unsigned int type;
-			/*
-			 * Memory space base address register.
-			 */
-			cmd |= PCI_COMMAND_MEMORY;
-			type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
-			base &= PCI_BASE_ADDRESS_MEM_MASK;
-			mask = (~base << 1) | 0x1;
-			size = (mask & base) & 0xffffffff;
-			switch (type) {
-			case PCI_BASE_ADDRESS_MEM_TYPE_32:
-			case PCI_BASE_ADDRESS_MEM_TYPE_64:
-				break;
-
-			case PCI_BASE_ADDRESS_MEM_TYPE_1M:
-				/*
-				 * Allocating memory below 1MB is *very*
-				 * tricky, as there may be all kinds of
-				 * ISA devices lurking that we don't know
-				 * about.  For now, we just cross fingers
-				 * and hope nobody tries to do this on an
-				 * Alpha (or that the console has set it
-				 * up properly).
-				 */
-				printk("bios32 WARNING: slot %d, function %d"
-				       " requests memory below 1MB---don't"
-				       " know how to do that.\n",
-				       PCI_SLOT(dev->devfn),
-				       PCI_FUNC(dev->devfn));
-				continue;
-			}
-			/*
-			 * The following holds at least for the Low Cost
-			 * Alpha implementation of the PCI interface:
-			 *
-			 * In sparse memory address space, the first
-			 * octant (16MB) of every 128MB segment is
-			 * aliased to the very first 16 MB of the
-			 * address space (i.e., it aliases the ISA
-			 * memory address space).  Thus, we try to
-			 * avoid allocating PCI devices in that range.
-			 * Can be allocated in 2nd-7th octant only.
-			 * Devices that need more than 112MB of
-			 * address space must be accessed through
-			 * dense memory space only!
-			 */
-			/* align to multiple of size of minimum base */
-			alignto = MAX(0x1000, size);
-			base = ALIGN(mem_base, alignto);
-			if (size > 7 * 16*MB) {
-				printk("bios32 WARNING: slot %d, function %d"
-				       " requests 0x%x bytes of contiguous"
-				       " address space---don't use sparse"
-				       " memory accesses on this device!!\n",
-				       PCI_SLOT(dev->devfn),
-				       PCI_FUNC(dev->devfn), size);
-			} else {
-				if (((base / (16*MB)) & 0x7) == 0) {
-					base &= ~(128*MB - 1);
-					base += 16*MB;
-					base  = ALIGN(base, alignto);
-				}
-				if (base/(128*MB) != (base + size)/(128*MB)) {
-					base &= ~(128*MB - 1);
-					base += (128 + 16)*MB;
-					base  = ALIGN(base, alignto);
-				}
-			}
-			mem_base = base + size;
-
-			pcibios_write_config_dword(bus->number, dev->devfn,
-						   off, base);
-			new_io_reset(dev, off, orig_base);
-
-			handle = PCI_HANDLE(bus->number) | base;
-			dev->resource[idx].start
-			  = handle & PCI_BASE_ADDRESS_MEM_MASK;
-			dev->resource[idx].end
-			  = dev->resource[idx].start + size - 1;
-			dev->resource[idx].flags
-			  = handle & ~PCI_BASE_ADDRESS_MEM_MASK;
-
-			/*
-			 * Currently for 64-bit cards, we simply do the usual
-			 * for setup of the first register (low) of the pair,
-			 * and then clear out the second (high) register, as
-			 * we are not yet able to do 64-bit addresses, and
-			 * setting the high register to 0 allows 32-bit SAC
-			 * addresses to be used.
-			 */
-			if (type == PCI_BASE_ADDRESS_MEM_TYPE_64) {
-				unsigned int orig_base2;
-				pcibios_read_config_dword(bus->number,
-							  dev->devfn,
-							  off+4, &orig_base2);
-				if (0 != orig_base2) {
-					pcibios_write_config_dword(bus->number,
-								   dev->devfn,
-								   off+4, 0);
-					new_io_reset (dev, off+4, orig_base2);
-				}
-				/* Bypass hi reg in the loop.  */
-				dev->resource[++idx].start = 0;
-				dev->resource[idx].end = 0;
-				dev->resource[idx].flags = 0;
-
-				printk("bios32 WARNING: "
-				       "handling 64-bit device in "
-				       "slot %d, function %d: \n",
-				       PCI_SLOT(dev->devfn),
-				       PCI_FUNC(dev->devfn));
-			}
-
-			DBG_DEVS(("layout_dev: dev 0x%x MEM @ 0x%lx (0x%x)\n",
-				  dev->device, handle, size));
-		}
-	}
-
-	/* Enable device: */
-	if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED ||
-	    dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
-	    dev->class >> 8 == PCI_CLASS_STORAGE_IDE ||
-	    dev->class >> 16 == PCI_BASE_CLASS_DISPLAY) {
-		/*
-		 * All of these (may) have I/O scattered all around
-		 * and may not use i/o-base address registers at all.
-		 * So we just have to always enable I/O to these
-		 * devices.
-		 */
-		cmd |= PCI_COMMAND_IO;
-	}
-
-	pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND,
-				  cmd | PCI_COMMAND_MASTER);
-
-	DBG_DEVS(("layout_dev: bus %d slot %d VID 0x%x DID 0x%x"
-		  " class 0x%x cmd 0 x%x\n",
-		  bus->number, PCI_SLOT(dev->devfn), dev->vendor,
-		  dev->device, dev->class, cmd|PCI_COMMAND_MASTER));
-}
-
-static int __init
-layout_bus(struct pci_bus *bus)
-{
-	unsigned int l, tio, bio, tmem, bmem;
-	struct pci_bus *child;
-	struct pci_dev *dev;
-	int found_vga = 0;
-
-	DBG_DEVS(("layout_bus: starting bus %d\n", bus->number));
-
-	if (!bus->devices && !bus->children)
-		return 0;
-
-	/*
-	 * Align the current bases on appropriate boundaries (4K for
-	 * IO and 1MB for memory).
-	 */
-	bio = io_base = ALIGN(io_base, 4*KB);
-	bmem = mem_base = ALIGN(mem_base, 1*MB);
-
-	/*
-	 * There are times when the PCI devices have already been
-	 * setup (e.g., by MILO or SRM).  In these cases there is a
-	 * window during which two devices may have an overlapping
-	 * address range.  To avoid this causing trouble, we first
-	 * turn off the I/O and memory address decoders for all PCI
-	 * devices.  They'll be re-enabled only once all address
-	 * decoders are programmed consistently.
-	 */
-	DBG_DEVS(("layout_bus: disable_dev for bus %d\n", bus->number));
-
-	for (dev = bus->devices; dev; dev = dev->sibling) {
-		if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
-		    (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA)) {
-			disable_dev(dev);
-		}
-	}
-
-	/*
-	 * Allocate space to each device:
-	 */
-	DBG_DEVS(("layout_bus: starting bus %d devices\n", bus->number));
-
-	for (dev = bus->devices; dev; dev = dev->sibling) {
-		if ((dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) ||
-		    (dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA)) {
-			layout_dev(dev);
-		}
-		if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
-			found_vga = 1;
-	}
-	/*
-	 * Recursively allocate space for all of the sub-buses:
-	 */
-	DBG_DEVS(("layout_bus: starting bus %d children\n", bus->number));
-
-    	for (child = bus->children; child; child = child->next) {
-		found_vga += layout_bus(child);
-	}
-	/*
-	 * Align the current bases on 4K and 1MB boundaries:
-	 */
-	tio = io_base = ALIGN(io_base, 4*KB);
-	tmem = mem_base = ALIGN(mem_base, 1*MB);
-
-	if (bus->self) {
-		struct pci_dev *bridge = bus->self;
-
-		DBG_DEVS(("layout_bus: config bus %d bridge\n", bus->number));
-
-		/*
-		 * Set up the top and bottom of the PCI I/O segment
-		 * for this bus.
-		 */
-		pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
-					  PCI_IO_BASE, &l);
-		l &= 0xffff0000;
-		l |= ((bio >> 8) & 0x00f0) | ((tio - 1) & 0xf000);
-		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
-					   PCI_IO_BASE, l);
-
-		/*
-		 * Clear out the upper 16 bits of IO base/limit.
-		 * Clear out the upper 32 bits of PREF base/limit.
-		 */
-		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
-					   PCI_IO_BASE_UPPER16, 0);
-		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
-					   PCI_PREF_BASE_UPPER32, 0);
-		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
-					   PCI_PREF_LIMIT_UPPER32, 0);
-
-		/*
-		 * Set up the top and bottom of the PCI Memory segment
-		 * for this bus.
-		 */
-		l = ((bmem & 0xfff00000) >> 16) | ((tmem - 1) & 0xfff00000);
-		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
-					   PCI_MEMORY_BASE, l);
-
-		/*
-		 * Turn off downstream PF memory address range, unless
-		 * there is a VGA behind this bridge, in which case, we
-		 * enable the PREFETCH range to include BIOS ROM at C0000.
-		 *
-		 * NOTE: this is a bit of a hack, done with PREFETCH for
-		 * simplicity, rather than having to add it into the above
-		 * non-PREFETCH range, which could then be bigger than we want.
-		 * We might assume that we could relocate the BIOS ROM, but
-		 * that would depend on having it found by those who need it
-		 * (the DEC BIOS emulator would find it, but I do not know
-		 * about the Xservers). So, we do it this way for now... ;-}
-		 */
-		l = (found_vga) ? 0 : 0x0000ffff;
-		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
-					   PCI_PREF_MEMORY_BASE, l);
-
-		/*
-		 * Tell bridge that there is an ISA bus in the system,
-		 * and (possibly) a VGA as well.
-		 */
-		l = (found_vga) ? 0x0c : 0x04;
-		pcibios_write_config_byte(bridge->bus->number, bridge->devfn,
-					   PCI_BRIDGE_CONTROL, l);
-
-		/*
-		 * Clear status bits,
-		 * turn on I/O    enable (for downstream I/O),
-		 * turn on memory enable (for downstream memory),
-		 * turn on master enable (for upstream memory and I/O).
-		 */
-		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
-					   PCI_COMMAND, 0xffff0007);
-	}
-	DBG_DEVS(("layout_bus: bus %d finished\n", bus->number));
-	return found_vga;
-}
-
-void __init
-layout_all_busses(unsigned long default_io_base,
-		  unsigned long default_mem_base)
-{
-	struct pci_bus *cur;
-
-	layout_hoses();
-
-	/*
-	 * Scan the tree, allocating PCI memory and I/O space.
-	 */
-	/*
-	 * Sigh; check_region() will need changing to accept a PCI_HANDLE,
-	 * if we allocate I/O space addresses on a per-bus basis.
-	 * For now, make the I/O bases unique across all busses, so
-	 * that check_region() will not get confused... ;-}
-	 */
-	io_base = default_io_base;
-	for (cur = &pci_root; cur; cur = cur->next) {
-		mem_base = default_mem_base;
-		DBG_DEVS(("layout_all_busses: calling layout_bus()\n"));
-		layout_bus(cur);
-	}
-	DBG_DEVS(("layout_all_busses: done.\n"));
-}
-
-
-/*
- * The SRM console *disables* the IDE interface, this code ensures it's
- * enabled.
- *
- * This code bangs on a control register of the 87312 Super I/O chip
- * that implements parallel port/serial ports/IDE/FDI.  Depending on
- * the motherboard, the Super I/O chip can be configured through a
- * pair of registers that are located either at I/O ports 0x26e/0x26f
- * or 0x398/0x399.  Unfortunately, autodetecting which base address is
- * in use works only once (right after a reset).  The Super I/O chip
- * has the additional quirk that configuration register data must be
- * written twice (I believe this is a safety feature to prevent
- * accidental modification---fun, isn't it?).
- */
-
-void __init
-enable_ide(long ide_base)
-{
-	int data;
-	unsigned long flags;
-
-	__save_and_cli(flags);
-	outb(0, ide_base);		/* set the index register for reg #0 */
-	data = inb(ide_base+1);		/* read the current contents */
-	outb(0, ide_base);		/* set the index register for reg #0 */
-	outb(data | 0x40, ide_base+1);	/* turn on IDE */
-	outb(data | 0x40, ide_base+1);	/* turn on IDE, really! */
-	__restore_flags(flags);
-}
-
-/* Look for mis-configured devices' I/O space addresses behind bridges.  */
-static void
-check_behind_io(struct pci_dev *dev)
-{
-	struct pci_bus *bus = dev->bus;
-	unsigned int reg, orig_base, new_base, found_one = 0;
-
-	for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
-		/* Read the current setting, check for I/O space and >= 64K */
-		pcibios_read_config_dword(bus->number, dev->devfn,
-					  reg, &orig_base);
-
-		if (!orig_base || !(orig_base & PCI_BASE_ADDRESS_SPACE_IO))
-			continue; /* unused or non-IO */
-
-		if (orig_base < 64*1024) {
-#if 1
-printk("check_behind_io: ALREADY OK! bus %d slot %d base 0x%x\n",
-       bus->number, PCI_SLOT(dev->devfn), orig_base);
-#endif
-			if (orig_base & ~1)
-				continue; /* OK! */
-			orig_base = 0x12001; /* HACK! FIXME!! */
-		}
-
-		/* HACK ALERT! for now, just subtract 32K from the
-		   original address, which should give us addresses
-		   in the range 0x8000 and up */
-		new_base = orig_base - 0x8000;
-#if 1
-printk("check_behind_io: ALERT! bus %d slot %d old 0x%x new 0x%x\n",
-       bus->number, PCI_SLOT(dev->devfn), orig_base, new_base);
-#endif
-		pcibios_write_config_dword(bus->number, dev->devfn,
-					   reg, new_base);
-
-		new_io_reset(dev, reg, orig_base);
-		found_one++;
-	}
-
-	/* If any were modified, gotta hack the bridge IO limits too. */
-	if (found_one) {
-		if (bus->self) {
-			struct pci_dev *bridge = bus->self;
-			unsigned int l;
-			/*
-			 * Set up the top and bottom of the PCI I/O segment
-			 * for this bus.
-			 */
-			pcibios_read_config_dword(bridge->bus->number,
-						  bridge->devfn, 0x1c, &l);
-#if 1
-printk("check_behind_io: ALERT! bus %d slot %d oldLIM 0x%x\n",
-       bus->number, PCI_SLOT(bridge->devfn), l);
-#endif
-			l = (l & 0xffff0000U) | 0xf080U; /* give it ALL */
-			pcibios_write_config_dword(bridge->bus->number,
-						   bridge->devfn, 0x1c, l);
-			pcibios_write_config_dword(bridge->bus->number,
-						   bridge->devfn,
-						   0x3c, 0x00040000);
-			pcibios_write_config_dword(bridge->bus->number,
-						   bridge->devfn,
-						   0x4, 0xffff0007);
-		} else
-			printk("check_behind_io: WARNING! bus->self NULL\n");
-	}
-}
-
-
-/*
- * Most boards share most of the fixup code, which is isolated here.
- */
-
-void __init
-common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin),
-		 int (*swizzle)(struct pci_dev *dev, int *pin))
-{
-	struct pci_dev *dev;
-	u8 pin, slot, irq_orig;
-	int irq;
-
-	/*
-	 * Go through all devices, fixing up irqs as we see fit.
-	 */
-	for (dev = pci_devices; dev; dev = dev->next) {
-		if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
-		    (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
-			continue;
-
-		/*
-		 * We don't have code that will init the CYPRESS bridge
-		 * correctly so we do the next best thing, and depend on
-		 * the previous console code to do the right thing, and
-		 * ignore it here... :-\
-		 */
-		if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
-		    dev->device == PCI_DEVICE_ID_CONTAQ_82C693) {
-			DBG_DEVS(("common_pci_fixup: ignoring CYPRESS bridge...\n"));
-			continue;
-		}
-
-		/*
-		 * This device is not on the primary bus, we need
-		 * to figure out which interrupt pin it will come
-		 * in on.   We know which slot it will come in on
-		 * 'cos that slot is where the bridge is.   Each
-		 * time the interrupt line passes through a PCI-PCI
-		 * bridge we must apply the swizzle function (see
-		 * the inline static routine above).
-		 */
-		dev->irq = 0;
-
-		pcibios_read_config_byte(dev->bus->number, dev->devfn,
-					 PCI_INTERRUPT_PIN, &pin);
-		/* Cope with 0 and illegal. */
-		if (pin == 0 || pin > 4)
-			pin = 1;
-
-		if (!DEV_IS_ON_PRIMARY(dev)) {
-			/* Follow the chain of bridges, swizzling as we go.  */
-
-			int spill = pin;
-			slot = (*swizzle)(dev, &spill);
-			pin = spill;
-
-			/* Must make sure that SRM didn't screw up
-			   and allocate an address > 64K for I/O
-			   space behind a PCI-PCI bridge. */
-			if (alpha_use_srm_setup)
-				check_behind_io(dev);
-		} else {
-			/* Just a device on a primary bus.  */
-			slot = PCI_SLOT(dev->devfn);
-		}
-
-		irq = (*map_irq)(dev, slot, pin);
-
-		DBG_DEVS(("common_pci_fixup: bus %d slot %d "
-			  "pin %d irq %d\n",
-			  dev->bus->number, slot, pin, irq));
-
-		if (irq != -1)
-			dev->irq = irq;
-
-		if (alpha_using_srm) {
-			/* Read the original SRM-set IRQ and tell. */
-			pcibios_read_config_byte(dev->bus->number,
-						 dev->devfn,
-						 PCI_INTERRUPT_LINE,
-						 &irq_orig);
-
-			if (irq_orig != dev->irq) {
-				DBG_DEVS(("common_pci_fixup: bus %d "
-					  "slot 0x%x SRM IRQ 0x%x "
-					  "changed to 0x%x\n",
-					  dev->bus->number,
-					  PCI_SLOT(dev->devfn),
-					  irq_orig, dev->irq));
-
-				new_irq_reset(dev, irq_orig);
-			}
-		}
-
-		/* Always tell the device, so the driver knows what is
-		   the real IRQ to use; the device does not use it. */
-		pcibios_write_config_byte(dev->bus->number, dev->devfn,
-					  PCI_INTERRUPT_LINE, dev->irq);
-
-		DBG_DEVS(("common_pci_fixup: bus %d slot 0x%x"
-			  " VID 0x%x DID 0x%x\n"
-			  "              int_slot 0x%x pin 0x%x"
-			  " pirq 0x%x\n",
-			  dev->bus->number, PCI_SLOT(dev->devfn),
-			  dev->vendor, dev->device,
-			  slot, pin, dev->irq));
-
-		/*
-		 * If it's a VGA, enable its BIOS ROM at C0000.
-		 */
-		if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
-			/* But if its a Cirrus 543x/544x DISABLE it,
-			   since enabling ROM disables the memory... */
-			if ((dev->vendor == PCI_VENDOR_ID_CIRRUS) &&
-			    (dev->device >= 0x00a0) &&
-			    (dev->device <= 0x00ac)) {
-				pcibios_write_config_dword(
-					dev->bus->number,
-					dev->devfn,
-					PCI_ROM_ADDRESS,
-					0x00000000);
-			} else {
-				pcibios_write_config_dword(
-					dev->bus->number,
-					dev->devfn,
-					PCI_ROM_ADDRESS,
-					0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
-			}
-		}
-		/*
-		 * If it's a SCSI, disable its BIOS ROM.
-		 */
-		if ((dev->class >> 8) == PCI_CLASS_STORAGE_SCSI) {
-			pcibios_write_config_dword(dev->bus->number,
-						   dev->devfn,
-						   PCI_ROM_ADDRESS,
-						   0x0000000);
-		}
-	}
-}
-
-/* Most Alphas have straight-forward swizzling needs.  */
-
-int __init
-common_swizzle(struct pci_dev *dev, int *pinp)
-{
-	int pin = *pinp;
-	do {
-		pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
-		/* Move up the chain of bridges. */
-		dev = dev->bus->self;
-	} while (dev->bus->self);
-	*pinp = pin;
-
-	/* The slot is the slot of the last bridge. */
-	return PCI_SLOT(dev->devfn);
-}
-
-/*
- * On multiple bus machines, in order to cope with a somewhat deficient
- * API, we must map the 8-bit bus identifier so that it is unique across
- * multiple interfaces (hoses).  At the same time we do this, chain the
- * other hoses off of pci_root so that they will be found during normal
- * PCI probing and layout.
- */
-
-#define PRIMARY(b)	((b)&0xff)
-#define SECONDARY(b)	(((b)>>8)&0xff)
-#define SUBORDINATE(b)	(((b)>>16)&0xff)
-
-static int __init
-hose_scan_bridges(struct linux_hose_info *hose, unsigned char bus)
-{
-	unsigned int devfn, l, class;
-	unsigned char hdr_type = 0;
-	unsigned int found = 0;
-
-	for (devfn = 0; devfn < 0xff; ++devfn) {
-		if (PCI_FUNC(devfn) == 0) {
-			alpha_mv.hose_read_config_byte(bus, devfn,
-						       PCI_HEADER_TYPE,
-						       &hdr_type, hose);
-		} else if (!(hdr_type & 0x80)) {
-			/* not a multi-function device */
-			continue;
-		}
-
-		/* Check if there is anything here. */
-		alpha_mv.hose_read_config_dword(bus, devfn, PCI_VENDOR_ID,
-						&l, hose);
-		if (l == 0xffffffff || l == 0x00000000) {
-			hdr_type = 0;
-			continue;
-		}
-
-		/* See if this is a bridge device. */
-		alpha_mv.hose_read_config_dword(bus, devfn, PCI_CLASS_REVISION,
-						&class, hose);
-
-		if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
-			unsigned int busses;
-
-			found++;
-
-			alpha_mv.hose_read_config_dword(bus, devfn,
-							PCI_PRIMARY_BUS,
-							&busses, hose);
-
-			DBG_HOSE(("hose_scan_bridges: hose %d bus %d "
-				  "slot %d busses 0x%x\n",
-				  hose->pci_hose_index, bus, PCI_SLOT(devfn),
-				  busses));
-
-			/*
-			 * Do something with first_busno and last_busno
-			 */
-			if (hose->pci_first_busno > PRIMARY(busses)) {
-				hose->pci_first_busno = PRIMARY(busses);
-				DBG_HOSE(("hose_scan_bridges: hose %d bus %d "
-					  "slot %d change first to %d\n",
-					  hose->pci_hose_index, bus,
-					 PCI_SLOT(devfn), PRIMARY(busses)));
-			}
-			if (hose->pci_last_busno < SUBORDINATE(busses)) {
-				hose->pci_last_busno = SUBORDINATE(busses);
-				DBG_HOSE(("hose_scan_bridges: hose %d bus %d "
-					  "slot %d change last to %d\n",
-					  hose->pci_hose_index, bus,
-					  PCI_SLOT(devfn),
-					  SUBORDINATE(busses)));
-			}
-			/*
-			 * Now scan everything underneath the bridge.
-			 */
-			hose_scan_bridges(hose, SECONDARY(busses));
-		}
-	}
-	return found;
-}
-
-static void __init
-hose_reconfigure_bridges(struct linux_hose_info *hose, unsigned char bus)
-{
-	unsigned int devfn, l, class;
-	unsigned char hdr_type = 0;
-
-	for (devfn = 0; devfn < 0xff; ++devfn) {
-		if (PCI_FUNC(devfn) == 0) {
-			alpha_mv.hose_read_config_byte(bus, devfn,
-						       PCI_HEADER_TYPE,
-						       &hdr_type, hose);
-		} else if (!(hdr_type & 0x80)) {
-			/* not a multi-function device */
-			continue;
-		}
-
-		/* Check if there is anything here. */
-		alpha_mv.hose_read_config_dword(bus, devfn, PCI_VENDOR_ID,
-						&l, hose);
-		if (l == 0xffffffff || l == 0x00000000) {
-			hdr_type = 0;
-			continue;
-		}
-
-		/* See if this is a bridge device. */
-		alpha_mv.hose_read_config_dword(bus, devfn, PCI_CLASS_REVISION,
-						&class, hose);
-
-		if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
-			unsigned int busses;
-
-			alpha_mv.hose_read_config_dword(bus, devfn,
-							PCI_PRIMARY_BUS,
-							&busses, hose);
-
-			/*
-			 * First reconfigure everything underneath the bridge.
-			 */
-			hose_reconfigure_bridges(hose, (busses >> 8) & 0xff);
-
-			/*
-			 * Unconfigure this bridges bus numbers,
-			 * pci_scan_bus() will fix this up properly.
-			 */
-			busses &= 0xff000000;
-			alpha_mv.hose_write_config_dword(bus, devfn,
-							 PCI_PRIMARY_BUS,
-							 busses, hose);
-		}
-	}
-}
-
-static void __init
-hose_fixup_busno(struct linux_hose_info *hose, unsigned char bus)
-{
-	int nbus;
-
-	/*
-	 * First, scan for all bridge devices underneath this hose,
-	 * to determine the first and last busnos.
-	 */
-	DBG_HOSE(("hose_fixup_busno: before hose_scan_bridges()\n"));
-
-	if (!hose_scan_bridges(hose, 0)) {
-		/* none found, exit */
-		hose->pci_first_busno = bus;
-		hose->pci_last_busno = bus;
-	} else {
-		/*
-		 * Reconfigure all bridge devices underneath this hose.
-		 */
-		DBG_HOSE(("hose_fixup_busno: before hose_reconfigure_bridges\n"));
-		hose_reconfigure_bridges(hose, hose->pci_first_busno);
-	}
-
-	/*
-	 * Now reconfigure the hose to it's new bus number and set up
-	 * our bus2hose mapping for this hose.
-	 */
-	nbus = hose->pci_last_busno - hose->pci_first_busno;
-
-	hose->pci_first_busno = bus;
-
-	DBG_HOSE(("hose_fixup_busno: hose %d startbus %d nbus %d\n",
-		  hose->pci_hose_index, bus, nbus));
-
-	do {
-		bus2hose[bus++] = hose;
-	} while (nbus-- > 0);
-	DBG_HOSE(("hose_fixup_busno: returning...\n"));
-}
-
-static void __init
-layout_one_hose(struct linux_hose_info *hose)
-{
-	static struct pci_bus *pchain = NULL;
-	struct pci_bus *pbus = &hose->pci_bus;
-	static unsigned char busno = 0;
-
-	DBG_HOSE(("layout_one_hose: entry\n"));
-
-	/*
-	 * Hoses include child PCI bridges in bus-range property,
-	 * but we don't scan each of those ourselves, Linux generic PCI
-	 * probing code will find child bridges and link them into this
-	 * hose's root PCI device hierarchy.
-	 */
-
-	pbus->number = pbus->secondary = busno;
-	pbus->sysdata = hose;
-
-	DBG_HOSE(("layout_one_hose: before hose_fixup_busno()\n"));
-
-	hose_fixup_busno(hose, busno);
-
-	DBG_HOSE(("layout_one_hose: before pci_scan_bus()\n"));
-
-	pbus->subordinate = pci_scan_bus(pbus); /* the original! */
-
-	/*
-	 * Set the maximum subordinate bus of this hose.
-	 */
-	hose->pci_last_busno = pbus->subordinate;
-#if 0
-	alpha_mv.hose_write_config_byte(busno, 0, 0x41, hose->pci_last_busno,
-					hose);
-#endif
-	busno = pbus->subordinate + 1;
-
-	/*
-	 * Fixup the chain of primary PCI busses.
-	 */
-	if (pchain) {
-		pchain->next = &hose->pci_bus;
-		pchain = pchain->next;
-	} else {
-		pchain = &pci_root;
-		memcpy(pchain, &hose->pci_bus, sizeof(pci_root));
-	}
-	DBG_HOSE(("layout_one_hose: returning...\n"));
-}
-
-static void __init
-layout_hoses(void)
-{
-	struct linux_hose_info * hose;
-	int i;
-
-	/* On multiple bus machines, we play games with pci_root in order
-	   that all of the busses are probed as part of the normal PCI
-	   setup.  The existance of the busses was determined in init_arch.  */
-
-	if (hose_head) {
-		/* Multi-bus machines did not yet wish to allow bus
-		   accesses.  We now do our own thing after the normal
-		   pci_scan_bus is over.  This mechanism is relatively
-		   broken but will be fixed later.  */
-		pci_probe_enabled = 1;
-
-		for (hose = hose_head; hose; hose = hose->next)
-			layout_one_hose(hose);
-	} else {
-		/* For the benefit of single-bus machines, emulate a
-		   multi-bus machine to the (limited) extent necessary. 
-		   Init all bus2hose entries to point to a dummy.  */
-		hose = kmalloc(sizeof(*hose), GFP_KERNEL);
-		memset(hose, 0, sizeof(*hose));
-		for (i = 0; i < 256; ++i)
-			bus2hose[i] = hose;
-	}
-}
-
-#endif /* CONFIG_PCI */
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/bios32.h linux/arch/alpha/kernel/bios32.h
--- v2.3.15/linux/arch/alpha/kernel/bios32.h	Sun Jan 10 09:59:54 1999
+++ linux/arch/alpha/kernel/bios32.h	Wed Dec 31 16:00:00 1969
@@ -1,166 +0,0 @@
-/*
- *	linux/arch/alpha/kernel/bios32.h
- *
- * This file contains declarations and inline functions for interfacing
- * with the PCI initialization routines in bios32.c.
- */
-
-
-#define KB		1024
-#define MB		(1024*KB)
-#define GB		(1024*MB)
-
-/*
- * We can't just blindly use 64K for machines with EISA busses; they
- * may also have PCI-PCI bridges present, and then we'd configure the
- * bridge incorrectly.
- *
- * Also, we start at 0x8000 or 0x9000, in hopes to get all devices'
- * IO space areas allocated *before* 0xC000; this is because certain
- * BIOSes (Millennium for one) use PCI Config space "mechanism #2"
- * accesses to probe the bus. If a device's registers appear at 0xC000,
- * it may see an INx/OUTx at that address during BIOS emulation of the
- * VGA BIOS, and some cards, notably Adaptec 2940UW, take mortal offense.
- *
- * Note that we may need this stuff for SRM_SETUP also, since certain
- * SRM consoles screw up and allocate I/O space addresses > 64K behind
- * PCI-to_PCI bridges, which can't pass I/O addresses larger than 64K,
- * AFAIK.
- */
-
-#define EISA_DEFAULT_IO_BASE 0x9000	/* start above 8th slot */
-#define DEFAULT_IO_BASE 0x8000		/* start at 8th slot */
-
-/*
- * We try to make the DEFAULT_MEM_BASE addresses *always* have more than
- * a single bit set. This is so that devices like the broken Myrinet card
- * will always have a PCI memory address that will never match a IDSEL
- * address in PCI Config space, which can cause problems with early rev cards.
- */
-
-/*
- * An XL is AVANTI (APECS) family, *but* it has only 27 bits of ISA address
- * that get passed through the PCI<->ISA bridge chip. Although this causes
- * us to set the PCI->Mem window bases lower than normal, we still allocate
- * PCI bus devices' memory addresses *below* the low DMA mapping window,
- * and hope they fit below 64Mb (to avoid conflicts), and so that they can
- * be accessed via SPARSE space.
- *
- * We accept the risk that a broken Myrinet card will be put into a true XL
- * and thus can more easily run into the problem described below.
- */
-#define XL_DEFAULT_MEM_BASE (16*MB + 2*MB) /* 16M to 64M-1 is avail */
-
-/*
- * APECS and LCA have only 34 bits for physical addresses, thus limiting PCI
- * bus memory addresses for SPARSE access to be less than 128Mb.
- */
-#define APECS_AND_LCA_DEFAULT_MEM_BASE (64*MB + 2*MB)
-
-/*
- * Because the MCPCIA core logic supports more bits for physical addresses,
- * it should allow an expanded range of SPARSE memory addresses.
- * However, we do not use them all, in order to avoid the HAE manipulation
- * that would be needed.
- */
-#define RAWHIDE_DEFAULT_MEM_BASE (64*MB + 2*MB)
-
-/*
- * Because CIA and PYXIS and T2 have more bits for physical addresses,
- * they support an expanded range of SPARSE memory addresses.
- */
-#define DEFAULT_MEM_BASE (128*MB + 16*MB)
-
-
-/*
- * PCI_MODIFY
- *
- * If this 0, then do not write to any of the PCI registers, merely
- * read them (i.e., use configuration as determined by SRM).  The SRM
- * seem do be doing a less than perfect job in configuring PCI
- * devices, so for now we do it ourselves.  Reconfiguring PCI devices
- * breaks console (RPB) callbacks, but those don't work properly with
- * 64 bit addresses anyways.
- *
- * The accepted convention seems to be that the console (POST
- * software) should fully configure boot devices and configure the
- * interrupt routing of *all* devices.  In particular, the base
- * addresses of non-boot devices need not be initialized.  For
- * example, on the AXPpci33 board, the base address a #9 GXE PCI
- * graphics card reads as zero (this may, however, be due to a bug in
- * the graphics card---there have been some rumor that the #9 BIOS
- * incorrectly resets that address to 0...).
- */
-
-#define PCI_MODIFY	(!alpha_use_srm_setup)
-     
-
-/* 
- * A small note about bridges and interrupts.  The DECchip 21050 (and
- * later) adheres to the PCI-PCI bridge specification.  This says that
- * the interrupts on the other side of a bridge are swizzled in the
- * following manner:
- *
- * Dev    Interrupt   Interrupt 
- *        Pin on      Pin on 
- *        Device      Connector
- *
- *   4    A           A
- *        B           B
- *        C           C
- *        D           D
- * 
- *   5    A           B
- *        B           C
- *        C           D
- *        D           A
- *
- *   6    A           C
- *        B           D
- *        C           A
- *        D           B
- *
- *   7    A           D
- *        B           A
- *        C           B
- *        D           C
- *
- *   Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
- *   Thus, each swizzle is ((pin-1) + (device#-4)) % 4
- *
- *   The following code swizzles for exactly one bridge.  The routine
- *   common_swizzle below handles multiple bridges.  But there are a
- *   couple boards that do strange things, so we define this here.
- */
-
-static inline unsigned char
-bridge_swizzle(unsigned char pin, unsigned int slot) 
-{
-	return (((pin-1) + slot) % 4) + 1;
-}
-
-extern void layout_all_busses(unsigned long io_base, unsigned long mem_base);
-extern void enable_ide(long ide_base);
-
-struct pci_dev;
-
-extern void
-common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin),
-		 int (*swizzle)(struct pci_dev *dev, int *pin));
-
-extern int common_swizzle(struct pci_dev *dev, int *pinp);
-
-/* The following macro is used to implement the table-based irq mapping
-   function for all single-bus Alphas.  */
-
-#define COMMON_TABLE_LOOKUP						\
-({ long _ctl_ = -1; 							\
-   if (slot >= min_idsel && slot <= max_idsel && pin < irqs_per_slot)	\
-     _ctl_ = irq_tab[slot - min_idsel][pin];				\
-   _ctl_; })
-
-
-/* The hose list.  */
-extern struct linux_hose_info *hose_head, **hose_tail;
-extern int hose_count;
-extern int pci_probe_enabled;
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/core_apecs.c linux/arch/alpha/kernel/core_apecs.c
--- v2.3.15/linux/arch/alpha/kernel/core_apecs.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/core_apecs.c	Tue Aug 31 10:50:39 1999
@@ -1,14 +1,15 @@
 /*
  *	linux/arch/alpha/kernel/core_apecs.c
  *
- * Code common to all APECS core logic chips.
- *
  * Rewritten for Apecs from the lca.c from:
  *
  * Written by David Mosberger (davidm@cs.arizona.edu) with some code
  * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
  * bios code.
+ *
+ * Code common to all APECS core logic chips.
  */
+
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
@@ -18,6 +19,7 @@
 #include <asm/system.h>
 #include <asm/ptrace.h>
 #include <asm/smp.h>
+#include <asm/pci.h>
 
 #define __EXTERN_INLINE inline
 #include <asm/io.h>
@@ -25,6 +27,7 @@
 #undef __EXTERN_INLINE
 
 #include "proto.h"
+#include "pci_impl.h"
 
 /*
  * NOTE: Herein lie back-to-back mb instructions.  They are magic. 
@@ -89,10 +92,12 @@
  */
 
 static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
 	     unsigned char *type1)
 {
 	unsigned long addr;
+	u8 bus = dev->bus->number;
+	u8 device_fn = dev->devfn;
 
 	DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
 	      " pci_addr=0x%p, type1=0x%p)\n",
@@ -212,7 +217,6 @@
 
 	__save_and_cli(flags);	/* avoid getting hit by machine check */
 
-
 	/* Reset status register to avoid losing errors.  */
 	stat0 = *(vuip)APECS_IOC_DCSR;
 	*(vuip)APECS_IOC_DCSR = stat0;
@@ -270,162 +274,106 @@
 	__restore_flags(flags);
 }
 
-int
-apecs_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
-			     struct linux_hose_info *hose)
+static int
+apecs_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
-	unsigned long addr = APECS_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x00;
-
+	addr = (pci_addr << 5) + 0x00 + APECS_CONF;
 	*value = conf_read(addr, type1) >> ((where & 3) * 8);
-
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-apecs_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
-			     struct linux_hose_info *hose)
+static int 
+apecs_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-	unsigned long addr = APECS_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x08;
-
+	addr = (pci_addr << 5) + 0x08 + APECS_CONF;
 	*value = conf_read(addr, type1) >> ((where & 3) * 8);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-apecs_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
-			      struct linux_hose_info *hose)
+static int
+apecs_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
-	unsigned long addr = APECS_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x18;
+	addr = (pci_addr << 5) + 0x18 + APECS_CONF;
 	*value = conf_read(addr, type1);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-apecs_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
-			      struct linux_hose_info *hose)
+static int
+apecs_write_config(struct pci_dev *dev, int where, u32 value, long mask)
 {
-	unsigned long addr = APECS_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x00;
+	addr = (pci_addr << 5) + mask + APECS_CONF;
 	conf_write(addr, value << ((where & 3) * 8), type1);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-apecs_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
-			      struct linux_hose_info *hose)
+static int
+apecs_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-	unsigned long addr = APECS_CONF;
-	unsigned long pci_addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	addr |= (pci_addr << 5) + 0x08;
-	conf_write(addr, value << ((where & 3) * 8), type1);
-	return PCIBIOS_SUCCESSFUL;
+	return apecs_write_config(dev, where, value, 0x00);
 }
 
-int 
-apecs_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
-			       struct linux_hose_info *hose)
+static int
+apecs_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-	unsigned long addr = APECS_CONF;
-	unsigned long pci_addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	return apecs_write_config(dev, where, value, 0x08);
+}
 
-	addr |= (pci_addr << 5) + 0x18;
-	conf_write(addr, value << ((where & 3) * 8), type1);
-	return PCIBIOS_SUCCESSFUL;
+static int
+apecs_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+	return apecs_write_config(dev, where, value, 0x18);
 }
 
+struct pci_ops apecs_pci_ops = 
+{
+	read_byte:	apecs_read_config_byte,
+	read_word:	apecs_read_config_word,
+	read_dword:	apecs_read_config_dword,
+	write_byte:	apecs_write_config_byte,
+	write_word:	apecs_write_config_word,
+	write_dword:	apecs_write_config_dword
+};
+
 void __init
 apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end)
 {
-	switch (alpha_use_srm_setup)
-	{
-	default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-		/* Check window 1 for enabled and mapped to 0. */
-		if ((*(vuip)APECS_IOC_PB1R & (1U<<19))
-		    && (*(vuip)APECS_IOC_TB1R == 0)) {
-			APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB1R & 0xfff00000U;
-			APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM1R & 0xfff00000U;
-			APECS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-			printk("apecs_init: using Window 1 settings\n");
-			printk("apecs_init: PB1R 0x%x PM1R 0x%x TB1R 0x%x\n",
-			       *(vuip)APECS_IOC_PB1R,
-			       *(vuip)APECS_IOC_PM1R,
-			       *(vuip)APECS_IOC_TB1R);
-#endif
-			break;
-		}
+	struct pci_controler *hose;
 
-		/* Check window 2 for enabled and mapped to 0.  */
-		if ((*(vuip)APECS_IOC_PB2R & (1U<<19))
-		    && (*(vuip)APECS_IOC_TB2R == 0)) {
-			APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB2R & 0xfff00000U;
-			APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM2R & 0xfff00000U;
-			APECS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-			printk("apecs_init: using Window 2 settings\n");
-			printk("apecs_init: PB2R 0x%x PM2R 0x%x TB2R 0x%x\n",
-			       *(vuip)APECS_IOC_PB2R,
-			       *(vuip)APECS_IOC_PM2R,
-			       *(vuip)APECS_IOC_TB2R);
-#endif
-			break;
-		}
-		
-		/* Otherwise, we must use our defaults.  */
-		APECS_DMA_WIN_BASE = APECS_DMA_WIN_BASE_DEFAULT;
-		APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT;
-#endif
-	case 0:
-		/*
-		 * Set up the PCI->physical memory translation windows.
-		 * For now, window 2 is disabled.  In the future, we may
-		 * want to use it to do scatter/gather DMA.  Window 1
-		 * goes at 1 GB and is 1 GB large.
-		 */
-		*(vuip)APECS_IOC_PB2R  = 0U; /* disable window 2 */
-
-		*(vuip)APECS_IOC_PB1R  = 1U<<19 | (APECS_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
-		*(vuip)APECS_IOC_PM1R  = (APECS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
-		*(vuip)APECS_IOC_TB1R  = 0;
-		break;
-	}
+	/*
+	 * Set up the PCI->physical memory translation windows.
+	 * For now, window 2 is disabled.  In the future, we may
+	 * want to use it to do scatter/gather DMA.  Window 1
+	 * goes at 1 GB and is 1 GB large.
+	 */
+	*(vuip)APECS_IOC_PB1R = 1UL << 19 | (APECS_DMA_WIN_BASE & 0xfff00000U);
+	*(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE - 1) & 0xfff00000U;
+	*(vuip)APECS_IOC_TB1R = 0;
+
+	*(vuip)APECS_IOC_PB2R = 0U;	/* disable window 2 */
 
 	/*
 	 * Finally, clear the HAXR2 register, which gets used
@@ -433,7 +381,18 @@
 	 * we want to use it, and we do not want to depend on
 	 * what ARC or SRM might have left behind...
 	 */
-	*(vuip)APECS_IOC_HAXR2 = 0; mb();
+	*(vuip)APECS_IOC_HAXR2 = 0;
+	mb();
+
+	/*
+	 * Create our single hose.
+	 */
+
+	hose = alloc_pci_controler(mem_start);
+	hose->io_space = &ioport_resource;
+	hose->mem_space = &iomem_resource;
+	hose->config_space = APECS_CONF;
+	hose->index = 0;
 }
 
 void
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/core_cia.c linux/arch/alpha/kernel/core_cia.c
--- v2.3.15/linux/arch/alpha/kernel/core_cia.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/core_cia.c	Tue Aug 31 10:50:39 1999
@@ -1,12 +1,16 @@
 /*
  *	linux/arch/alpha/kernel/core_cia.c
  *
- * Code common to all CIA core logic chips.
- *
  * Written by David A Rusling (david.rusling@reo.mts.dec.com).
  * December 1995.
  *
+ *	Copyright (C) 1995  David A Rusling
+ *	Copyright (C) 1997, 1998  Jay Estabrook
+ *	Copyright (C) 1998, 1999  Richard Henderson
+ *
+ * Code common to all CIA core logic chips.
  */
+
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
@@ -16,6 +20,7 @@
 
 #include <asm/system.h>
 #include <asm/ptrace.h>
+#include <asm/pci.h>
 
 #define __EXTERN_INLINE inline
 #include <asm/io.h>
@@ -23,6 +28,8 @@
 #undef __EXTERN_INLINE
 
 #include "proto.h"
+#include "pci_impl.h"
+
 
 /*
  * NOTE: Herein lie back-to-back mb instructions.  They are magic. 
@@ -88,10 +95,12 @@
  */
 
 static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
 	     unsigned char *type1)
 {
 	unsigned long addr;
+	u8 bus = dev->bus->number;
+	u8 device_fn = dev->devfn;
 
 	DBGC(("mk_conf_addr(bus=%d, device_fn=0x%x, where=0x%x, "
 	      "pci_addr=0x%p, type1=0x%p)\n",
@@ -166,30 +175,6 @@
 	mcheck_expected(0) = 0;
 	mb();
 
-#if 0
-	/* This code might be necessary if machine checks aren't taken,
-	   but I can't get it to work on CIA-2, so its disabled. */
-	draina();
-
-	/* Now look for any errors.  */
-	stat0 = *(vuip)CIA_IOC_CIA_ERR;
-	DBGC(("conf_read: CIA ERR after read 0x%x\n", stat0));
-
-	/* Is any error bit set? */
-	if (stat0 & 0x8FEF0FFFU) {
-		/* If not MAS_ABT, print status. */
-		if (!(stat0 & 0x0080)) {
-			printk("CIA.c:conf_read: got stat0=%x\n", stat0);
-		}
-
-		/* reset error status: */
-		*(vuip)CIA_IOC_CIA_ERR = stat0;
-		mb();
-		wrmces(0x7);			/* reset machine check */
-		value = 0xffffffff;
-	}
-#endif
-
 	/* If Type1 access, must reset IOC CFG so normal IO space ops work.  */
 	if (type1) {
 		*(vuip)CIA_IOC_CFG = cia_cfg & ~1;
@@ -237,30 +222,6 @@
 	mcheck_expected(0) = 0;
 	mb();
 
-#if 0
-	/* This code might be necessary if machine checks aren't taken,
-	   but I can't get it to work on CIA-2, so its disabled. */
-	draina();
-
-	/* Now look for any errors */
-	stat0 = *(vuip)CIA_IOC_CIA_ERR;
-	DBGC(("conf_write: CIA ERR after write 0x%x\n", stat0));
-
-	/* Is any error bit set? */
-	if (stat0 & 0x8FEF0FFFU) {
-		/* If not MAS_ABT, print status */
-		if (!(stat0 & 0x0080)) {
-			printk("CIA.c:conf_read: got stat0=%x\n", stat0);
-		}
-
-		/* Reset error status.  */
-		*(vuip)CIA_IOC_CIA_ERR = stat0;
-		mb();
-		wrmces(0x7);			/* reset machine check */
-		value = 0xffffffff;
-	}
-#endif
-
 	/* If Type1 access, must reset IOC CFG so normal IO space ops work.  */
 	if (type1) {
 		*(vuip)CIA_IOC_CFG = cia_cfg & ~1;
@@ -271,267 +232,179 @@
 	__restore_flags(flags);
 }
 
-int
-cia_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
-			   struct linux_hose_info *hose)
+static int
+cia_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
-	unsigned long addr = CIA_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x00;
+	addr = (pci_addr << 5) + 0x00 + CIA_CONF;
 	*value = conf_read(addr, type1) >> ((where & 3) * 8);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-cia_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
-			   struct linux_hose_info *hose)
+static int 
+cia_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-	unsigned long addr = CIA_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x08;
+	addr = (pci_addr << 5) + 0x08 + CIA_CONF;
 	*value = conf_read(addr, type1) >> ((where & 3) * 8);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-cia_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
-			    struct linux_hose_info *hose)
+static int 
+cia_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
-	unsigned long addr = CIA_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x18;
+	addr = (pci_addr << 5) + 0x18 + CIA_CONF;
 	*value = conf_read(addr, type1);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-cia_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
-			    struct linux_hose_info *hose)
+static int 
+cia_write_config(struct pci_dev *dev, int where, u32 value, long mask)
 {
-	unsigned long addr = CIA_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x00;
+	addr = (pci_addr << 5) + mask + CIA_CONF;
 	conf_write(addr, value << ((where & 3) * 8), type1);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-cia_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
-			    struct linux_hose_info *hose)
+static int
+cia_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-	unsigned long addr = CIA_CONF;
-	unsigned long pci_addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	addr |= (pci_addr << 5) + 0x08;
-	conf_write(addr, value << ((where & 3) * 8), type1);
-	return PCIBIOS_SUCCESSFUL;
+	return cia_write_config(dev, where, value, 0x00);
 }
 
-int 
-cia_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
-			     struct linux_hose_info *hose)
+static int 
+cia_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-	unsigned long addr = CIA_CONF;
-	unsigned long pci_addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	return cia_write_config(dev, where, value, 0x08);
+}
 
-	addr |= (pci_addr << 5) + 0x18;
-	conf_write(addr, value << ((where & 3) * 8), type1);
-	return PCIBIOS_SUCCESSFUL;
+static int 
+cia_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+	return cia_write_config(dev, where, value, 0x18);
 }
 
+struct pci_ops cia_pci_ops = 
+{
+	read_byte:	cia_read_config_byte,
+	read_word:	cia_read_config_word,
+	read_dword:	cia_read_config_dword,
+	write_byte:	cia_write_config_byte,
+	write_word:	cia_write_config_word,
+	write_dword:	cia_write_config_dword
+};
+
 void __init
 cia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
 {
-        unsigned int cia_tmp;
+	struct pci_controler *hose;
+	struct resource *hae_mem;
+        unsigned int temp;
 
 #if DEBUG_DUMP_REGS
-	{
-		unsigned int temp;
-		temp = *(vuip)CIA_IOC_CIA_REV; mb();
-		printk("cia_init: CIA_REV was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_PCI_LAT; mb();
-		printk("cia_init: CIA_PCI_LAT was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
-		printk("cia_init: CIA_CTRL was 0x%x\n", temp);
-		temp = *(vuip)0xfffffc8740000140UL; mb();
-		printk("cia_init: CIA_CTRL1 was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_HAE_MEM; mb();
-		printk("cia_init: CIA_HAE_MEM was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_HAE_IO; mb();
-		printk("cia_init: CIA_HAE_IO was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_CFG; mb();
-		printk("cia_init: CIA_CFG was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_CACK_EN; mb();
-		printk("cia_init: CIA_CACK_EN was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_CFG; mb();
-		printk("cia_init: CIA_CFG was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_CIA_DIAG; mb();
-		printk("cia_init: CIA_DIAG was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_DIAG_CHECK; mb();
-		printk("cia_init: CIA_DIAG_CHECK was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_PERF_MONITOR; mb();
-		printk("cia_init: CIA_PERF_MONITOR was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_PERF_CONTROL; mb();
-		printk("cia_init: CIA_PERF_CONTROL was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_CIA_ERR; mb();
-		printk("cia_init: CIA_ERR was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_CIA_STAT; mb();
-		printk("cia_init: CIA_STAT was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_MCR; mb();
-		printk("cia_init: CIA_MCR was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
-		printk("cia_init: CIA_CTRL was 0x%x\n", temp);
-		temp = *(vuip)CIA_IOC_ERR_MASK; mb();
-		printk("cia_init: CIA_ERR_MASK was 0x%x\n", temp);
-		temp = *((vuip)CIA_IOC_PCI_W0_BASE); mb();
-		printk("cia_init: W0_BASE was 0x%x\n", temp);
-		temp = *((vuip)CIA_IOC_PCI_W1_BASE); mb();
-		printk("cia_init: W1_BASE was 0x%x\n", temp);
-		temp = *((vuip)CIA_IOC_PCI_W2_BASE); mb();
-		printk("cia_init: W2_BASE was 0x%x\n", temp);
-		temp = *((vuip)CIA_IOC_PCI_W3_BASE); mb();
-		printk("cia_init: W3_BASE was 0x%x\n", temp);
-	}
+	temp = *(vuip)CIA_IOC_CIA_REV; mb();
+	printk("cia_init: CIA_REV was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_PCI_LAT; mb();
+	printk("cia_init: CIA_PCI_LAT was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
+	printk("cia_init: CIA_CTRL was 0x%x\n", temp);
+	temp = *(vuip)0xfffffc8740000140UL; mb();
+	printk("cia_init: CIA_CTRL1 was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_HAE_MEM; mb();
+	printk("cia_init: CIA_HAE_MEM was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_HAE_IO; mb();
+	printk("cia_init: CIA_HAE_IO was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_CFG; mb();
+	printk("cia_init: CIA_CFG was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_CACK_EN; mb();
+	printk("cia_init: CIA_CACK_EN was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_CFG; mb();
+	printk("cia_init: CIA_CFG was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_CIA_DIAG; mb();
+	printk("cia_init: CIA_DIAG was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_DIAG_CHECK; mb();
+	printk("cia_init: CIA_DIAG_CHECK was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_PERF_MONITOR; mb();
+	printk("cia_init: CIA_PERF_MONITOR was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_PERF_CONTROL; mb();
+	printk("cia_init: CIA_PERF_CONTROL was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_CIA_ERR; mb();
+	printk("cia_init: CIA_ERR was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_CIA_STAT; mb();
+	printk("cia_init: CIA_STAT was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_MCR; mb();
+	printk("cia_init: CIA_MCR was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
+	printk("cia_init: CIA_CTRL was 0x%x\n", temp);
+	temp = *(vuip)CIA_IOC_ERR_MASK; mb();
+	printk("cia_init: CIA_ERR_MASK was 0x%x\n", temp);
+	temp = *((vuip)CIA_IOC_PCI_W0_BASE); mb();
+	printk("cia_init: W0_BASE was 0x%x\n", temp);
+	temp = *((vuip)CIA_IOC_PCI_W1_BASE); mb();
+	printk("cia_init: W1_BASE was 0x%x\n", temp);
+	temp = *((vuip)CIA_IOC_PCI_W2_BASE); mb();
+	printk("cia_init: W2_BASE was 0x%x\n", temp);
+	temp = *((vuip)CIA_IOC_PCI_W3_BASE); mb();
+	printk("cia_init: W3_BASE was 0x%x\n", temp);
 #endif /* DEBUG_DUMP_REGS */
 
         /* 
 	 * Set up error reporting.
 	 */
-	cia_tmp = *(vuip)CIA_IOC_CIA_ERR;
-	cia_tmp |= 0x180;   /* master, target abort */
-	*(vuip)CIA_IOC_CIA_ERR = cia_tmp;
-	mb();
-
-	cia_tmp = *(vuip)CIA_IOC_CIA_CTRL;
-	cia_tmp |= 0x400;	/* turn on FILL_ERR to get mchecks */
-	*(vuip)CIA_IOC_CIA_CTRL = cia_tmp;
-	mb();
-
-	switch (alpha_use_srm_setup)
-	{
-	default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-		/* Check window 0 for enabled and mapped to 0 */
-		if (((*(vuip)CIA_IOC_PCI_W0_BASE & 3) == 1)
-		    && (*(vuip)CIA_IOC_PCI_T0_BASE == 0)) {
-			CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W0_BASE & 0xfff00000U;
-			CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W0_MASK & 0xfff00000U;
-			CIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-			printk("cia_init: using Window 0 settings\n");
-			printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
-			       *(vuip)CIA_IOC_PCI_W0_BASE,
-			       *(vuip)CIA_IOC_PCI_W0_MASK,
-			       *(vuip)CIA_IOC_PCI_T0_BASE);
-#endif
-			break;
-		}
-
-		/* Check window 1 for enabled and mapped to 0.  */
-		if (((*(vuip)CIA_IOC_PCI_W1_BASE & 3) == 1)
-		    && (*(vuip)CIA_IOC_PCI_T1_BASE == 0)) {
-			CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W1_BASE & 0xfff00000U;
-			CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W1_MASK & 0xfff00000U;
-			CIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-			printk("cia_init: using Window 1 settings\n");
-			printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
-			       *(vuip)CIA_IOC_PCI_W1_BASE,
-			       *(vuip)CIA_IOC_PCI_W1_MASK,
-			       *(vuip)CIA_IOC_PCI_T1_BASE);
-#endif
-			break;
-		}
+	temp = *(vuip)CIA_IOC_CIA_ERR;
+	temp |= 0x180;   /* master, target abort */
+	*(vuip)CIA_IOC_CIA_ERR = temp;
+	mb();
 
-		/* Check window 2 for enabled and mapped to 0.  */
-		if (((*(vuip)CIA_IOC_PCI_W2_BASE & 3) == 1)
-		    && (*(vuip)CIA_IOC_PCI_T2_BASE == 0)) {
-			CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W2_BASE & 0xfff00000U;
-			CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W2_MASK & 0xfff00000U;
-			CIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-			printk("cia_init: using Window 2 settings\n");
-			printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
-			       *(vuip)CIA_IOC_PCI_W2_BASE,
-			       *(vuip)CIA_IOC_PCI_W2_MASK,
-			       *(vuip)CIA_IOC_PCI_T2_BASE);
-#endif
-			break;
-		}
+	temp = *(vuip)CIA_IOC_CIA_CTRL;
+	temp |= 0x400;	/* turn on FILL_ERR to get mchecks */
+	*(vuip)CIA_IOC_CIA_CTRL = temp;
+	mb();
 
-		/* Check window 3 for enabled and mapped to 0.  */
-		if (((*(vuip)CIA_IOC_PCI_W3_BASE & 3) == 1)
-		    && (*(vuip)CIA_IOC_PCI_T3_BASE == 0)) {
-			CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W3_BASE & 0xfff00000U;
-			CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W3_MASK & 0xfff00000U;
-			CIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-			printk("cia_init: using Window 3 settings\n");
-			printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
-			       *(vuip)CIA_IOC_PCI_W3_BASE,
-			       *(vuip)CIA_IOC_PCI_W3_MASK,
-			       *(vuip)CIA_IOC_PCI_T3_BASE);
-#endif
-			break;
-		}
+	/*
+	 * Set up the PCI->physical memory translation windows.
+	 * For now, windows 2 and 3 are disabled.  In the future,
+	 * we may want to use them to do scatter/gather DMA. 
+	 *
+	 * Window 0 goes at 1 GB and is 1 GB large.
+	 * Window 1 goes at 2 GB and is 1 GB large.
+	 */
 
-		/* Otherwise, we must use our defaults.  */
-		CIA_DMA_WIN_BASE = CIA_DMA_WIN_BASE_DEFAULT;
-		CIA_DMA_WIN_SIZE = CIA_DMA_WIN_SIZE_DEFAULT;
-#endif
-	case 0:
-		/*
-		 * Set up the PCI->physical memory translation windows.
-		 * For now, windows 2 and 3 are disabled.  In the future,
-		 * we may want to use them to do scatter/gather DMA. 
-		 *
-		 * Window 0 goes at 1 GB and is 1 GB large.
-		 * Window 1 goes at 2 GB and is 1 GB large.
-		 */
-
-		*(vuip)CIA_IOC_PCI_W0_BASE = CIA_DMA_WIN0_BASE_DEFAULT | 1U;
-		*(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN0_SIZE_DEFAULT - 1) &
-					     0xfff00000U;
-		*(vuip)CIA_IOC_PCI_T0_BASE = CIA_DMA_WIN0_TRAN_DEFAULT >> 2;
+	*(vuip)CIA_IOC_PCI_W0_BASE = CIA_DMA_WIN0_BASE_DEFAULT | 1U;
+	*(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN0_SIZE_DEFAULT - 1) &
+				     0xfff00000U;
+	*(vuip)CIA_IOC_PCI_T0_BASE = CIA_DMA_WIN0_TRAN_DEFAULT >> 2;
 		
-		*(vuip)CIA_IOC_PCI_W1_BASE = CIA_DMA_WIN1_BASE_DEFAULT | 1U;
-		*(vuip)CIA_IOC_PCI_W1_MASK = (CIA_DMA_WIN1_SIZE_DEFAULT - 1) &
-					     0xfff00000U;
-		*(vuip)CIA_IOC_PCI_T1_BASE = CIA_DMA_WIN1_TRAN_DEFAULT >> 2;
+	*(vuip)CIA_IOC_PCI_W1_BASE = CIA_DMA_WIN1_BASE_DEFAULT | 1U;
+	*(vuip)CIA_IOC_PCI_W1_MASK = (CIA_DMA_WIN1_SIZE_DEFAULT - 1) &
+				     0xfff00000U;
+	*(vuip)CIA_IOC_PCI_T1_BASE = CIA_DMA_WIN1_TRAN_DEFAULT >> 2;
 
-		*(vuip)CIA_IOC_PCI_W2_BASE = 0x0;
-		*(vuip)CIA_IOC_PCI_W3_BASE = 0x0;
-		mb();
-		break;
-	}
+	*(vuip)CIA_IOC_PCI_W2_BASE = 0x0;
+	*(vuip)CIA_IOC_PCI_W3_BASE = 0x0;
+	mb();
 
         /*
          * Next, clear the CIA_CFG register, which gets used
@@ -541,40 +414,31 @@
          */
 	*((vuip)CIA_IOC_CFG) = 0; mb();
  
+	/*
+	 * Zero the HAEs. 
+	 */
+	*((vuip)CIA_IOC_HAE_MEM) = 0; mb();
+	*((vuip)CIA_IOC_HAE_MEM); /* read it back. */
+	*((vuip)CIA_IOC_HAE_IO) = 0; mb();
+	*((vuip)CIA_IOC_HAE_IO);  /* read it back. */
 
 	/*
-	 * Sigh... For the SRM setup, unless we know apriori what the HAE
-	 * contents will be, we need to setup the arbitrary region bases
-	 * so we can test against the range of addresses and tailor the
-	 * region chosen for the SPARSE memory access.
-	 *
-	 * See include/asm-alpha/cia.h for the SPARSE mem read/write.
+	 * Create our single hose.
 	 */
-	if (alpha_use_srm_setup) {
-		unsigned int cia_hae_mem = *((vuip)CIA_IOC_HAE_MEM);
 
-		alpha_mv.sm_base_r1 = (cia_hae_mem      ) & 0xe0000000UL;
-		alpha_mv.sm_base_r2 = (cia_hae_mem << 16) & 0xf8000000UL;
-		alpha_mv.sm_base_r3 = (cia_hae_mem << 24) & 0xfc000000UL;
-
-		/*
-		 * Set the HAE cache, so that setup_arch() code
-		 * will use the SRM setting always. Our readb/writeb
-		 * code in cia.h expects never to have to change
-		 * the contents of the HAE.
-		 */
-		alpha_mv.hae_cache = cia_hae_mem;
-
-		alpha_mv.mv_readb = cia_srm_readb;
-		alpha_mv.mv_readw = cia_srm_readw;
-		alpha_mv.mv_writeb = cia_srm_writeb;
-		alpha_mv.mv_writew = cia_srm_writew;
-	} else {
-		*((vuip)CIA_IOC_HAE_MEM) = 0; mb();
-		*((vuip)CIA_IOC_HAE_MEM); /* read it back. */
-		*((vuip)CIA_IOC_HAE_IO) = 0; mb();
-		*((vuip)CIA_IOC_HAE_IO);  /* read it back. */
-        }
+	hose = alloc_pci_controler(mem_start);
+	hae_mem = alloc_resource(mem_start);
+
+	hose->io_space = &ioport_resource;
+	hose->mem_space = hae_mem;
+	hose->config_space = CIA_CONF;
+	hose->index = 0;
+
+	hae_mem->start = 0;
+	hae_mem->end = CIA_MEM_R1_MASK;
+	hae_mem->name = pci_hae0_name;
+
+	request_resource(&iomem_resource, hae_mem);
 }
 
 static inline void
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/core_lca.c linux/arch/alpha/kernel/core_lca.c
--- v2.3.15/linux/arch/alpha/kernel/core_lca.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/core_lca.c	Tue Aug 31 10:50:39 1999
@@ -1,12 +1,13 @@
 /*
  *	linux/arch/alpha/kernel/core_lca.c
  *
- * Code common to all LCA core logic chips.
- *
  * Written by David Mosberger (davidm@cs.arizona.edu) with some code
  * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
  * bios code.
+ *
+ * Code common to all LCA core logic chips.
  */
+
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/types.h>
@@ -17,6 +18,7 @@
 #include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/smp.h>
+#include <asm/pci.h>
 
 #define __EXTERN_INLINE inline
 #include <asm/io.h>
@@ -24,6 +26,8 @@
 #undef __EXTERN_INLINE
 
 #include "proto.h"
+#include "pci_impl.h"
+
 
 /*
  * BIOS32-style PCI interface:
@@ -97,9 +101,11 @@
  */
 
 static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr)
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr)
 {
 	unsigned long addr;
+	u8 bus = dev->bus->number;
+	u8 device_fn = dev->devfn;
 
 	if (bus == 0) {
 		int device = device_fn >> 3;
@@ -194,154 +200,103 @@
 	__restore_flags(flags);
 }
 
-int
-lca_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
-			   struct linux_hose_info *hose)
+static int
+lca_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
-	unsigned long addr = LCA_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+	if (mk_conf_addr(dev, where, &pci_addr))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x00;
+	addr = (pci_addr << 5) + 0x00 + LCA_CONF;
 	*value = conf_read(addr) >> ((where & 3) * 8);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-lca_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
-			   struct linux_hose_info *hose)
+static int 
+lca_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-	unsigned long addr = LCA_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+	if (mk_conf_addr(dev, where, &pci_addr))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x08;
+	addr = (pci_addr << 5) + 0x08 + LCA_CONF;
 	*value = conf_read(addr) >> ((where & 3) * 8);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-lca_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
-			    struct linux_hose_info *hose)
+static int
+lca_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
-	unsigned long addr = LCA_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+	if (mk_conf_addr(dev, where, &pci_addr))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x18;
+	addr = (pci_addr << 5) + 0x18 + LCA_CONF;
 	*value = conf_read(addr);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-lca_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
-			    struct linux_hose_info *hose)
+static int 
+lca_write_config(struct pci_dev *dev, int where, u32 value, long mask)
 {
-	unsigned long addr = LCA_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+	if (mk_conf_addr(dev, where, &pci_addr))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x00;
+	addr = (pci_addr << 5) + mask + LCA_CONF;
 	conf_write(addr, value << ((where & 3) * 8));
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-lca_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
-			    struct linux_hose_info *hose)
+static int
+lca_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-	unsigned long addr = LCA_CONF;
-	unsigned long pci_addr;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	addr |= (pci_addr << 5) + 0x08;
-	conf_write(addr, value << ((where & 3) * 8));
-	return PCIBIOS_SUCCESSFUL;
+	return lca_write_config(dev, where, value, 0x00);
 }
 
-int 
-lca_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
-			     struct linux_hose_info *hose)
+static int
+lca_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-	unsigned long addr = LCA_CONF;
-	unsigned long pci_addr;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	return lca_write_config(dev, where, value, 0x08);
+}
 
-	addr |= (pci_addr << 5) + 0x18;
-	conf_write(addr, value << ((where & 3) * 8));
-	return PCIBIOS_SUCCESSFUL;
+static int
+lca_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+	return lca_write_config(dev, where, value, 0x18);
 }
 
+struct pci_ops lca_pci_ops = 
+{
+	read_byte:	lca_read_config_byte,
+	read_word:	lca_read_config_word,
+	read_dword:	lca_read_config_dword,
+	write_byte:	lca_write_config_byte,
+	write_word:	lca_write_config_word,
+	write_dword:	lca_write_config_dword
+};
+
 void __init
 lca_init_arch(unsigned long *mem_start, unsigned long *mem_end)
 {
-	switch (alpha_use_srm_setup)
-	{
-	default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-		/* Check window 0 for enabled and mapped to 0.  */
-		if ((*(vulp)LCA_IOC_W_BASE0 & (1UL<<33))
-		    && (*(vulp)LCA_IOC_T_BASE0 == 0)) {
-			LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE0 & 0xffffffffUL;
-			LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK0 & 0xffffffffUL;
-			LCA_DMA_WIN_SIZE += 1;
-#if 0
-			printk("lca_init: using Window 0 settings\n");
-			printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
-			       *(vulp)LCA_IOC_W_BASE0,
-			       *(vulp)LCA_IOC_W_MASK0,
-			       *(vulp)LCA_IOC_T_BASE0);
-#endif
-			break;
-		}
+	struct pci_controler *hose;
 
-		/* Check window 2 for enabled and mapped to 0.  */
-		if ((*(vulp)LCA_IOC_W_BASE1 & (1UL<<33))
-		    && (*(vulp)LCA_IOC_T_BASE1 == 0)) {
-			LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE1 & 0xffffffffUL;
-			LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK1 & 0xffffffffUL;
-			LCA_DMA_WIN_SIZE += 1;
-#if 1
-			printk("lca_init: using Window 1 settings\n");
-			printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
-			       *(vulp)LCA_IOC_W_BASE1,
-			       *(vulp)LCA_IOC_W_MASK1,
-			       *(vulp)LCA_IOC_T_BASE1);
-#endif
-			break;
-		}
+	/*
+	 * Set up the PCI->physical memory translation windows.
+	 * For now, window 1 is disabled.  In the future, we may
+	 * want to use it to do scatter/gather DMA. 
+	 *
+	 * Window 0 goes at 1 GB and is 1 GB large.
+	 */
+	*(vulp)LCA_IOC_W_BASE0 = 1UL << 33 | LCA_DMA_WIN_BASE;
+	*(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE - 1;
+	*(vulp)LCA_IOC_T_BASE0 = 0;
 
-		/* Otherwise, we must use our defaults.  */
-		LCA_DMA_WIN_BASE = LCA_DMA_WIN_BASE_DEFAULT;
-		LCA_DMA_WIN_SIZE = LCA_DMA_WIN_SIZE_DEFAULT;
-#endif
-	case 0:
-		/*
-		 * Set up the PCI->physical memory translation windows.
-		 * For now, window 1 is disabled.  In the future, we may
-		 * want to use it to do scatter/gather DMA. 
-		 *
-		 * Window 0 goes at 1 GB and is 1 GB large.
-		 */
-		*(vulp)LCA_IOC_W_BASE1 = 0UL<<33;
-
-		*(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE_DEFAULT;
-		*(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE_DEFAULT - 1;
-		*(vulp)LCA_IOC_T_BASE0 = 0;
-		break;
-	}
+	*(vulp)LCA_IOC_W_BASE1 = 0UL;
 
 	/*
 	 * Disable PCI parity for now.  The NCR53c810 chip has
@@ -349,6 +304,16 @@
 	 * data parity errors.
 	 */
 	*(vulp)LCA_IOC_PAR_DIS = 1UL<<5;
+
+	/*
+	 * Create our single hose.
+	 */
+
+	hose = alloc_pci_controler(mem_start);
+	hose->io_space = &ioport_resource;
+	hose->mem_space = &iomem_resource;
+	hose->config_space = LCA_CONF;
+	hose->index = 0;
 }
 
 /*
@@ -376,7 +341,7 @@
 #define IOC_P_NBR	((__u32) ~((1<<13) - 1))
 
 static void
-mem_error (unsigned long esr, unsigned long ear)
+mem_error(unsigned long esr, unsigned long ear)
 {
 	printk("    %s %s error to %s occurred at address %x\n",
 	       ((esr & ESR_CEE) ? "Correctable" :
@@ -399,7 +364,7 @@
 }
 
 static void
-ioc_error (__u32 stat0, __u32 stat1)
+ioc_error(__u32 stat0, __u32 stat1)
 {
 	static const char * const pci_cmd[] = {
 		"Interrupt Acknowledge", "Special", "I/O Read", "I/O Write",
@@ -430,8 +395,8 @@
 }
 
 void
-lca_machine_check (unsigned long vector, unsigned long la_ptr,
-		   struct pt_regs *regs)
+lca_machine_check(unsigned long vector, unsigned long la_ptr,
+		  struct pt_regs *regs)
 {
 	const char * reason;
 	union el_lca el;
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/core_mcpcia.c linux/arch/alpha/kernel/core_mcpcia.c
--- v2.3.15/linux/arch/alpha/kernel/core_mcpcia.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/core_mcpcia.c	Tue Aug 31 10:50:39 1999
@@ -1,11 +1,11 @@
 /*
  *	linux/arch/alpha/kernel/core_mcpcia.c
  *
- * Code common to all MCbus-PCI Adaptor core logic chipsets
- *
  * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
  *
+ * Code common to all MCbus-PCI Adaptor core logic chipsets
  */
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -25,7 +25,7 @@
 #undef __EXTERN_INLINE
 
 #include "proto.h"
-#include "bios32.h"
+#include "pci_impl.h"
 
 /*
  * NOTE: Herein lie back-to-back mb instructions.  They are magic. 
@@ -47,6 +47,11 @@
 
 #define MCPCIA_MAX_HOSES 2
 
+/* Dodge has PCI0 and PCI1 at MID 4 and 5 respectively.  Durango adds
+   PCI2 and PCI3 at MID 6 and 7 respectively.  */
+
+#define hose2mid(h)	((h) + 4)
+
 
 /*
  * Given a bus, device, and function number, compute resulting
@@ -92,10 +97,10 @@
 
 static unsigned int
 conf_read(unsigned long addr, unsigned char type1,
-	  struct linux_hose_info *hose)
+	  struct pci_controler *hose)
 {
 	unsigned long flags;
-	unsigned long hoseno = hose->pci_hose_index;
+	unsigned long mid = hose2mid(hose->index);
 	unsigned int stat0, value, temp, cpu;
 
 	cpu = smp_processor_id();
@@ -103,19 +108,20 @@
 	__save_and_cli(flags);
 
 	DBG_CFG(("conf_read(addr=0x%lx, type1=%d, hose=%d)\n",
-		 addr, type1, hoseno));
+		 addr, type1, mid));
 
 	/* Reset status register to avoid losing errors.  */
-	stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno);
-	*(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb();
-	temp = *(vuip)MCPCIA_CAP_ERR(hoseno);
-	DBG_CFG(("conf_read: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
+	stat0 = *(vuip)MCPCIA_CAP_ERR(mid);
+	*(vuip)MCPCIA_CAP_ERR(mid) = stat0;
+	mb();
+	temp = *(vuip)MCPCIA_CAP_ERR(mid);
+	DBG_CFG(("conf_read: MCPCIA_CAP_ERR(%d) was 0x%x\n", mid, stat0));
 
 	mb();
 	draina();
 	mcheck_expected(cpu) = 1;
 	mcheck_taken(cpu) = 0;
-	mcheck_hose(cpu) = hoseno;
+	mcheck_extra(cpu) = mid;
 	mb();
 
 	/* Access configuration space.  */
@@ -139,10 +145,10 @@
 
 static void
 conf_write(unsigned long addr, unsigned int value, unsigned char type1,
-	   struct linux_hose_info *hose)
+	   struct pci_controler *hose)
 {
 	unsigned long flags;
-	unsigned long hoseno = hose->pci_hose_index;
+	unsigned long mid = hose2mid(hose->index);
 	unsigned int stat0, temp, cpu;
 
 	cpu = smp_processor_id();
@@ -150,21 +156,21 @@
 	__save_and_cli(flags);	/* avoid getting hit by machine check */
 
 	/* Reset status register to avoid losing errors.  */
-	stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno);
-	*(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb();
-	temp = *(vuip)MCPCIA_CAP_ERR(hoseno);
-	DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
+	stat0 = *(vuip)MCPCIA_CAP_ERR(mid);
+	*(vuip)MCPCIA_CAP_ERR(mid) = stat0; mb();
+	temp = *(vuip)MCPCIA_CAP_ERR(mid);
+	DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", mid, stat0));
 
 	draina();
 	mcheck_expected(cpu) = 1;
-	mcheck_hose(cpu) = hoseno;
+	mcheck_extra(cpu) = mid;
 	mb();
 
 	/* Access configuration space.  */
 	*((vuip)addr) = value;
 	mb();
 	mb();  /* magic */
-	temp = *(vuip)MCPCIA_CAP_ERR(hoseno); /* read to force the write */
+	temp = *(vuip)MCPCIA_CAP_ERR(mid); /* read to force the write */
 	mcheck_expected(cpu) = 0;
 	mb();
 
@@ -173,71 +179,71 @@
 }
 
 static int
-mk_conf_addr(struct linux_hose_info *hose,
-	     u8 bus, u8 device_fn, u8 where,
+mk_conf_addr(struct pci_dev *dev, int where, struct pci_controler *hose,
 	     unsigned long *pci_addr, unsigned char *type1)
 {
+	u8 bus = dev->bus->number;
+	u8 devfn = dev->devfn;
 	unsigned long addr;
 
-	if (!pci_probe_enabled)
-		return -1;
-
-	DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
+	DBG_CFG(("mk_conf_addr(bus=%d,devfn=0x%x,hose=%d,where=0x%x,"
 		 " pci_addr=0x%p, type1=0x%p)\n",
-		 bus, device_fn, where, pci_addr, type1));
+		 bus, devfn, hose->index, where, pci_addr, type1));
 
 	/* Type 1 configuration cycle for *ALL* busses.  */
 	*type1 = 1;
 
-	if (hose->pci_first_busno == bus)
+	if (dev->bus->number == hose->first_busno)
 		bus = 0;
-	addr = (bus << 16) | (device_fn << 8) | (where);
+	addr = (bus << 16) | (devfn << 8) | (where);
 	addr <<= 5; /* swizzle for SPARSE */
-	addr |= hose->pci_config_space;
+	addr |= hose->config_space;
 
 	*pci_addr = addr;
 	DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
 	return 0;
 }
 
-int
-mcpcia_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
-			      struct linux_hose_info *hose)
+static int
+mcpcia_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
-	unsigned long addr;
+	struct pci_controler *hose = dev->sysdata ? : probing_hose;
+	unsigned long addr, w;
 	unsigned char type1;
 
-	if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+	if (mk_conf_addr(dev, where, hose, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	addr |= 0x00;
-	*value = conf_read(addr, type1, hose) >> ((where & 3) * 8);
+	w = conf_read(addr, type1, hose);
+	*value = __kernel_extbl(w, where & 3);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-mcpcia_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
-			      struct linux_hose_info *hose)
+static int
+mcpcia_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-	unsigned long addr;
+	struct pci_controler *hose = dev->sysdata ? : probing_hose;
+	unsigned long addr, w;
 	unsigned char type1;
 
-	if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+	if (mk_conf_addr(dev, where, hose, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	addr |= 0x08;
-	*value = conf_read(addr, type1, hose) >> ((where & 3) * 8);
+	w = conf_read(addr, type1, hose);
+	*value = __kernel_extwl(w, where & 3);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-mcpcia_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
-			       struct linux_hose_info *hose)
+static int
+mcpcia_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
+	struct pci_controler *hose = dev->sysdata ? : probing_hose;
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+	if (mk_conf_addr(dev, where, hose, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	addr |= 0x18;
@@ -245,311 +251,213 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-mcpcia_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
-			       struct linux_hose_info *hose)
+static int
+mcpcia_write_config(struct pci_dev *dev, int where, u32 value, long mask)
 {
+	struct pci_controler *hose = dev->sysdata ? : probing_hose;
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+	if (mk_conf_addr(dev, where, hose, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= 0x00;
-	conf_write(addr, value << ((where & 3) * 8), type1, hose);
+	addr |= mask;
+	value = __kernel_insql(value, where & 3);
+	conf_write(addr, value, type1, hose);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-mcpcia_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
-			       struct linux_hose_info *hose)
+static int
+mcpcia_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	addr |= 0x08;
-	conf_write(addr, value << ((where & 3) * 8), type1, hose);
-	return PCIBIOS_SUCCESSFUL;
+	return mcpcia_write_config(dev, where, value, 0x00);
 }
 
-int
-mcpcia_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
-				struct linux_hose_info *hose)
+static int
+mcpcia_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-	unsigned long addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	return mcpcia_write_config(dev, where, value, 0x08);
+}
 
-	addr |= 0x18;
-	conf_write(addr, value << ((where & 3) * 8), type1, hose);
-	return PCIBIOS_SUCCESSFUL;
+static int
+mcpcia_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+	return mcpcia_write_config(dev, where, value, 0x18);
 }
 
-void __init
-mcpcia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+struct pci_ops mcpcia_pci_ops = 
 {
-	extern asmlinkage void entInt(void);
-	struct linux_hose_info *hose;
-	unsigned int mcpcia_err;
+	read_byte:	mcpcia_read_config_byte,
+	read_word:	mcpcia_read_config_word,
+	read_dword:	mcpcia_read_config_dword,
+	write_byte:	mcpcia_write_config_byte,
+	write_word:	mcpcia_write_config_word,
+	write_dword:	mcpcia_write_config_dword
+};
+
+static int __init
+mcpcia_probe_hose(int h)
+{
+	int cpu = smp_processor_id();
+	int mid = hose2mid(h);
 	unsigned int pci_rev;
-	int h, cpu;
 
-	/* Ho hum.. init_arch is called before init_IRQ, but we need to be
-	   able to handle machine checks.  So install the handler now.  */
-	wrent(entInt, 0);
-
-	/* Align memory to cache line; we'll be allocating from it.  */
-	*mem_start = (*mem_start | 31) + 1;
+	/* Gotta be REAL careful.  If hose is absent, we get an mcheck.  */
 
-	cpu = smp_processor_id();
-
-	/* First, find how many hoses we have.  */
-	for (h = 0; h < MCPCIA_MAX_HOSES; h++) {
+	mb();
+	mb();
+	draina();
+	mcheck_expected(cpu) = 1;
+	mcheck_taken(cpu) = 0;
+	mcheck_extra(cpu) = mid;
+	mb();
 
-		/* Gotta be REAL careful.  If hose is absent, we get a
-		   machine check.  */
+	/* Access the bus revision word. */
+	pci_rev = *(vuip)MCPCIA_REV(mid);
 
-		mb();
-		mb();
-		draina();
-		mcheck_expected(cpu) = 1;
+	mb();
+	mb();  /* magic */
+	if (mcheck_taken(cpu)) {
 		mcheck_taken(cpu) = 0;
+		pci_rev = 0xffffffff;
 		mb();
+	}
+	mcheck_expected(cpu) = 0;
+	mb();
 
-		/* Access the bus revision word. */
-		pci_rev = *(vuip)MCPCIA_REV(h);
+	return (pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST;
+}
 
-		mb();
-		mb();  /* magic */
-		if (mcheck_taken(cpu)) {
-			mcheck_taken(cpu) = 0;
-			pci_rev = 0xffffffff;
-			mb();
-		}
-		mcheck_expected(cpu) = 0;
-		mb();
+static void __init
+mcpcia_new_hose(unsigned long *mem_start, int h)
+{
+	struct pci_controler *hose;
+	struct resource *io, *mem, *hae_mem;
+	int mid = hose2mid(h);
 
-#if 0
-		printk("mcpcia_init_arch: got 0x%x for PCI_REV for hose %d\n",
-		       pci_rev, h);
-#endif
-		if ((pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST) {
-			hose_count++;
+	hose = alloc_pci_controler(mem_start);
+	io = alloc_resource(mem_start);
+	mem = alloc_resource(mem_start);
+	hae_mem = alloc_resource(mem_start);
+			
+	hose->io_space = io;
+	hose->mem_space = hae_mem;
+	hose->config_space = MCPCIA_CONF(mid);
+	hose->index = h;
 
-			hose = (struct linux_hose_info *)*mem_start;
-			*mem_start = (unsigned long)(hose + 1);
+	io->start = MCPCIA_IO(mid) - MCPCIA_IO_BIAS;
+	io->end = io->start + 0xffff;
+	io->name = pci_io_names[h];
 
-			memset(hose, 0, sizeof(*hose));
+	mem->start = MCPCIA_DENSE(mid) - MCPCIA_MEM_BIAS;
+	mem->end = mem->start + 0xffffffff;
+	mem->name = pci_mem_names[h];
 
-			*hose_tail = hose;
-			hose_tail = &hose->next;
+	hae_mem->start = mem->start;
+	hae_mem->end = mem->start + MCPCIA_MEM_MASK;
+	hae_mem->name = pci_hae0_name;
 
-			hose->pci_io_space = MCPCIA_IO(h);
-			hose->pci_mem_space = MCPCIA_DENSE(h);
-			hose->pci_config_space = MCPCIA_CONF(h);
-			hose->pci_sparse_space = MCPCIA_SPARSE(h);
-			hose->pci_hose_index = h;
-			hose->pci_first_busno = 255;
-			hose->pci_last_busno = 0;
-		}
-	}
+	request_resource(&ioport_resource, io);
+	request_resource(&iomem_resource, mem);
+	request_resource(mem, hae_mem);
+}
 
-#if 1
-	printk("mcpcia_init_arch: found %d hoses\n", hose_count);
-#endif
+static void __init
+mcpcia_startup_hose(struct pci_controler *hose)
+{
+	int mid = hose2mid(hose->index);
+	unsigned int tmp;
 
-	/* Now do init for each hose.  */
-	for (hose = hose_head; hose; hose = hose->next) {
-		h = hose->pci_hose_index;
+	/* 
+	 * Set up error reporting. Make sure CPU_PE is OFF in the mask.
+	 */
 #if 0
-		printk("mcpcia_init_arch: -------- hose %d --------\n",h);
-		printk("MCPCIA_REV 0x%x\n", *(vuip)MCPCIA_REV(h));
-		printk("MCPCIA_WHOAMI 0x%x\n", *(vuip)MCPCIA_WHOAMI(h));
-		printk("MCPCIA_HAE_MEM 0x%x\n", *(vuip)MCPCIA_HAE_MEM(h));
-		printk("MCPCIA_HAE_IO 0x%x\n", *(vuip)MCPCIA_HAE_IO(h));
-		printk("MCPCIA_HAE_DENSE 0x%x\n", *(vuip)MCPCIA_HAE_DENSE(h));
-		printk("MCPCIA_INT_CTL 0x%x\n", *(vuip)MCPCIA_INT_CTL(h));
-		printk("MCPCIA_INT_REQ 0x%x\n", *(vuip)MCPCIA_INT_REQ(h));
-		printk("MCPCIA_INT_TARG 0x%x\n", *(vuip)MCPCIA_INT_TARG(h));
-		printk("MCPCIA_INT_ADR 0x%x\n", *(vuip)MCPCIA_INT_ADR(h));
-		printk("MCPCIA_INT_ADR_EXT 0x%x\n", *(vuip)MCPCIA_INT_ADR_EXT(h));
-		printk("MCPCIA_INT_MASK0 0x%x\n", *(vuip)MCPCIA_INT_MASK0(h));
-		printk("MCPCIA_INT_MASK1 0x%x\n", *(vuip)MCPCIA_INT_MASK1(h));
-		printk("MCPCIA_HBASE 0x%x\n", *(vuip)MCPCIA_HBASE(h));
+	tmp = *(vuip)MCPCIA_ERR_MASK(mid);
+	tmp &= ~4;
+	*(vuip)MCPCIA_ERR_MASK(mid) = tmp;
+	mb();
+	tmp = *(vuip)MCPCIA_ERR_MASK(mid);
 #endif
 
-		/* 
-		 * Set up error reporting. Make sure CPU_PE is OFF in the mask.
-		 */
-#if 0
-		mcpcia_err = *(vuip)MCPCIA_ERR_MASK(h);
-		mcpcia_err &= ~4;   
-		*(vuip)MCPCIA_ERR_MASK(h) = mcpcia_err;
-		mb();
-		mcpcia_err = *(vuip)MCPCIA_ERR_MASK;
-#endif
+	tmp = *(vuip)MCPCIA_CAP_ERR(mid);
+	tmp |= 0x0006;   /* master/target abort */
+	*(vuip)MCPCIA_CAP_ERR(mid) = tmp;
+	mb();
+	tmp = *(vuip)MCPCIA_CAP_ERR(mid);
 
-		mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
-		mcpcia_err |= 0x0006;   /* master/target abort */
-		*(vuip)MCPCIA_CAP_ERR(h) = mcpcia_err;
-		mb() ;
-		mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
-
-		switch (alpha_use_srm_setup)
-		{
-		default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-			/* Check window 0 for enabled and mapped to 0. */
-			if (((*(vuip)MCPCIA_W0_BASE(h) & 3) == 1)
-			    && (*(vuip)MCPCIA_T0_BASE(h) == 0)
-			    && ((*(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
-				MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W0_BASE(h) & 0xfff00000U;
-				MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U;
-				MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-				printk("mcpcia_init_arch: using Window 0 settings\n");
-				printk("mcpcia_init_arch: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
-				       *(vuip)MCPCIA_W0_BASE(h),
-				       *(vuip)MCPCIA_W0_MASK(h),
-				       *(vuip)MCPCIA_T0_BASE(h));
-#endif
-				break;
-			}
+	/*
+	 * Set up the PCI->physical memory translation windows.
+	 * For now, windows 1,2 and 3 are disabled.  In the
+	 * future, we may want to use them to do scatter/
+	 * gather DMA.
+	 *
+	 * Window 0 goes at 2 GB and is 2 GB large.
+	 */
+
+	*(vuip)MCPCIA_W0_BASE(mid) = 1U | (MCPCIA_DMA_WIN_BASE & 0xfff00000U);
+	*(vuip)MCPCIA_W0_MASK(mid) = (MCPCIA_DMA_WIN_SIZE - 1) & 0xfff00000U;
+	*(vuip)MCPCIA_T0_BASE(mid) = 0;
+
+	*(vuip)MCPCIA_W1_BASE(mid) = 0x0;
+	*(vuip)MCPCIA_W2_BASE(mid) = 0x0;
+	*(vuip)MCPCIA_W3_BASE(mid) = 0x0;
 
-			/* Check window 1 for enabled and mapped to 0.  */
-			if (((*(vuip)MCPCIA_W1_BASE(h) & 3) == 1)
-			    && (*(vuip)MCPCIA_T1_BASE(h) == 0)
-			    && ((*(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
-				MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W1_BASE(h) & 0xfff00000U;
-				MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U;
-				MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-				printk("mcpcia_init_arch: using Window 1 settings\n");
-				printk("mcpcia_init_arch: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
-				       *(vuip)MCPCIA_W1_BASE(h),
-				       *(vuip)MCPCIA_W1_MASK(h),
-				       *(vuip)MCPCIA_T1_BASE(h));
-#endif
-				break;
-			}
+	*(vuip)MCPCIA_HBASE(mid) = 0x0;
+	mb();
 
-			/* Check window 2 for enabled and mapped to 0.  */
-			if (((*(vuip)MCPCIA_W2_BASE(h) & 3) == 1)
-			    && (*(vuip)MCPCIA_T2_BASE(h) == 0)
-			    && ((*(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
-				MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W2_BASE(h) & 0xfff00000U;
-				MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U;
-				MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-				printk("mcpcia_init_arch: using Window 2 settings\n");
-				printk("mcpcia_init_arch: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
-				       *(vuip)MCPCIA_W2_BASE(h),
-				       *(vuip)MCPCIA_W2_MASK(h),
-				       *(vuip)MCPCIA_T2_BASE(h));
+#if 0
+	tmp = *(vuip)MCPCIA_INT_CTL(mid);
+	printk("mcpcia_init_arch: INT_CTL was 0x%x\n", tmp);
+	*(vuip)MCPCIA_INT_CTL(mid) = 1U;
+	mb();
+	tmp = *(vuip)MCPCIA_INT_CTL(mid);
 #endif
-				break;
-			}
 
-			/* Check window 3 for enabled and mapped to 0.  */
-			if (((*(vuip)MCPCIA_W3_BASE(h) & 3) == 1)
-			    && (*(vuip)MCPCIA_T3_BASE(h) == 0)
-			    && ((*(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
-				MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W3_BASE(h) & 0xfff00000U;
-				MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U;
-				MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-				printk("mcpcia_init_arch: using Window 3 settings\n");
-				printk("mcpcia_init_arch: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
-				       *(vuip)MCPCIA_W3_BASE(h),
-				       *(vuip)MCPCIA_W3_MASK(h),
-				       *(vuip)MCPCIA_T3_BASE(h));
-#endif
-				break;
-			}
+	*(vuip)MCPCIA_HAE_MEM(mid) = 0U;
+	mb();
+	*(vuip)MCPCIA_HAE_MEM(mid); /* read it back. */
+	*(vuip)MCPCIA_HAE_IO(mid) = 0;
+	mb();
+	*(vuip)MCPCIA_HAE_IO(mid);  /* read it back. */
+}
 
-			/* Otherwise, we must use our defaults.  */
-			MCPCIA_DMA_WIN_BASE = MCPCIA_DMA_WIN_BASE_DEFAULT;
-			MCPCIA_DMA_WIN_SIZE = MCPCIA_DMA_WIN_SIZE_DEFAULT;
-#endif
-		case 0:
-			/*
-			 * Set up the PCI->physical memory translation windows.
-			 * For now, windows 1,2 and 3 are disabled.  In the
-			 * future, we may want to use them to do scatter/
-			 * gather DMA.
-			 *
-			 * Window 0 goes at 2 GB and is 2 GB large.
-			 */
-
-			*(vuip)MCPCIA_W0_BASE(h) = 1U | (MCPCIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
-			*(vuip)MCPCIA_W0_MASK(h) = (MCPCIA_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
-			*(vuip)MCPCIA_T0_BASE(h) = 0;
-
-			*(vuip)MCPCIA_W1_BASE(h) = 0x0 ;
-			*(vuip)MCPCIA_W2_BASE(h) = 0x0 ;
-			*(vuip)MCPCIA_W3_BASE(h) = 0x0 ;
+void __init
+mcpcia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+	extern asmlinkage void entInt(void);
+	struct pci_controler *hose;
+	int h, hose_count = 0;
 
-			*(vuip)MCPCIA_HBASE(h) = 0x0 ;
-			mb();
-			break;
-		}
-#if 0
-		{
-			unsigned int mcpcia_int_ctl = *((vuip)MCPCIA_INT_CTL(h));
-			printk("mcpcia_init_arch: INT_CTL was 0x%x\n", mcpcia_int_ctl);
-			*(vuip)MCPCIA_INT_CTL(h) = 1U; mb();
-			mcpcia_int_ctl = *(vuip)MCPCIA_INT_CTL(h);
-		}
-#endif
+	/* Ho hum.. init_arch is called before init_IRQ, but we need to be
+	   able to handle machine checks.  So install the handler now.  */
+	wrent(entInt, 0);
+
+	/* With multiple PCI busses, we play with I/O as physical addrs.  */
+	ioport_resource.end = ~0UL;
+	iomem_resource.end = ~0UL;
 
-		/*
-		 * Sigh... For the SRM setup, unless we know apriori what the HAE
-		 * contents will be, we need to setup the arbitrary region bases
-		 * so we can test against the range of addresses and tailor the
-		 * region chosen for the SPARSE memory access.
-		 *
-		 * See include/asm-alpha/mcpcia.h for the SPARSE mem read/write.
-		 */
-		if (alpha_use_srm_setup) {
-			unsigned int mcpcia_hae_mem = *(vuip)MCPCIA_HAE_MEM(h);
-
-			alpha_mv.sm_base_r1 = (mcpcia_hae_mem      ) & 0xe0000000UL;
-			alpha_mv.sm_base_r2 = (mcpcia_hae_mem << 16) & 0xf8000000UL;
-			alpha_mv.sm_base_r3 = (mcpcia_hae_mem << 24) & 0xfc000000UL;
-
-			/*
-			 * Set the HAE cache, so that setup_arch() code
-			 * will use the SRM setting always. Our readb/writeb
-			 * code in mcpcia.h expects never to have to change
-			 * the contents of the HAE.
-			 */
-			alpha_mv.hae_cache = mcpcia_hae_mem;
-
-			alpha_mv.mv_readb = mcpcia_srm_readb;
-			alpha_mv.mv_readw = mcpcia_srm_readw;
-			alpha_mv.mv_writeb = mcpcia_srm_writeb;
-			alpha_mv.mv_writew = mcpcia_srm_writew;
-		} else {
-			*(vuip)MCPCIA_HAE_MEM(h) = 0U; mb();
-			*(vuip)MCPCIA_HAE_MEM(h); /* read it back. */
-			*(vuip)MCPCIA_HAE_IO(h) = 0; mb();
-			*(vuip)MCPCIA_HAE_IO(h);  /* read it back. */
+	/* First, find how many hoses we have.  */
+	for (h = 0; h < MCPCIA_MAX_HOSES; ++h) {
+		if (mcpcia_probe_hose(h)) {
+			mcpcia_new_hose(mem_start, h);
+			hose_count++;
 		}
 	}
+
+	printk("mcpcia_init_arch: found %d hoses\n", hose_count);
+
+	/* Now do init for each hose.  */
+	for (hose = hose_head; hose; hose = hose->next)
+		mcpcia_startup_hose(hose);
 }
 
 static void
-mcpcia_pci_clr_err(int hose)
+mcpcia_pci_clr_err(int mid)
 {
-	*(vuip)MCPCIA_CAP_ERR(hose);
-	*(vuip)MCPCIA_CAP_ERR(hose) = 0xffffffff;   /* Clear them all.  */
+	*(vuip)MCPCIA_CAP_ERR(mid);
+	*(vuip)MCPCIA_CAP_ERR(mid) = 0xffffffff;   /* Clear them all.  */
 	mb();
-	*(vuip)MCPCIA_CAP_ERR(hose);  /* Re-read for force write.  */
+	*(vuip)MCPCIA_CAP_ERR(mid);  /* Re-read for force write.  */
 }
 
 static void
@@ -639,19 +547,21 @@
 	mb();  /* magic */
 	draina();
 	if (mcheck_expected(cpu)) {
-		mcpcia_pci_clr_err(mcheck_hose(cpu));
+		mcpcia_pci_clr_err(mcheck_extra(cpu));
 	} else {
 		/* FIXME: how do we figure out which hose the error was on?  */	
-		mcpcia_pci_clr_err(0);
-		mcpcia_pci_clr_err(1);
+		struct pci_controler *hose;
+		for (hose = hose_head; hose; hose = hose->next)
+			mcpcia_pci_clr_err(hose2mid(hose->index));
 	}
 	wrmces(0x7);
 	mb();
 
-	process_mcheck_info(vector, la_ptr, regs, "MCPCIA",
-		            mcheck_expected(cpu));
-
-	if (vector != 0x620 && vector != 0x630) {
-		mcpcia_print_uncorrectable(mchk_logout);
+	if (mcheck_expected(cpu)) {
+		process_mcheck_info(vector, la_ptr, regs, "MCPCIA", 1);
+	} else {
+		process_mcheck_info(vector, la_ptr, regs, "MCPCIA", 0);
+		if (vector != 0x620 && vector != 0x630)
+			mcpcia_print_uncorrectable(mchk_logout);
 	}
 }
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/core_polaris.c linux/arch/alpha/kernel/core_polaris.c
--- v2.3.15/linux/arch/alpha/kernel/core_polaris.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/core_polaris.c	Tue Aug 31 10:50:39 1999
@@ -2,8 +2,8 @@
  *      linux/arch/alpha/kernel/core_polaris.c
  *
  * POLARIS chip-specific code
- *
  */
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -20,7 +20,7 @@
 #undef __EXTERN_INLINE
 
 #include "proto.h"
-#include "bios32.h"
+#include "pci_impl.h"
 
 /*
  * BIOS32-style PCI interface:
@@ -66,8 +66,11 @@
  */
 
 static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, u8 *type1)
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, u8 *type1)
 {
+	u8 bus = dev->bus->number;
+	u8 device_fn = dev->devfn;
+
 	*type1 = (bus == 0) ? 0 : 1;
 	*pci_addr = (bus << 16) | (device_fn << 8) | (where) |
 		    POLARIS_DENSE_CONFIG_BASE;
@@ -79,59 +82,52 @@
 	return 0;
 }
 
-int
-polaris_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
-                             struct linux_hose_info *hose)
+static int
+polaris_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
 	unsigned long pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
                 return PCIBIOS_DEVICE_NOT_FOUND;
 
 	*value = __kernel_ldbu(*(vucp)pci_addr);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-
-int
-polaris_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
-                             struct linux_hose_info *hose)
+static int
+polaris_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
 	unsigned long pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
                 return PCIBIOS_DEVICE_NOT_FOUND;
 
 	*value = __kernel_ldwu(*(vusp)pci_addr);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-
-int
-polaris_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
-                              struct linux_hose_info *hose)
+static int
+polaris_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
 	unsigned long pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
                 return PCIBIOS_DEVICE_NOT_FOUND;
 
 	*value = *(vuip)pci_addr;
 	return PCIBIOS_SUCCESSFUL;
 }
 
-
-int 
-polaris_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
-                              struct linux_hose_info *hose)
+static int 
+polaris_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
 	unsigned long pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
                 return PCIBIOS_DEVICE_NOT_FOUND;
 
         __kernel_stb(value, *(vucp)pci_addr);
@@ -140,15 +136,13 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-
-int 
-polaris_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
-                              struct linux_hose_info *hose)
+static int 
+polaris_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
 	unsigned long pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
                 return PCIBIOS_DEVICE_NOT_FOUND;
 
         __kernel_stw(value, *(vusp)pci_addr);
@@ -157,15 +151,13 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-
-int 
-polaris_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
-                               struct linux_hose_info *hose)
+static int 
+polaris_write_config_dword(struct pci_dev *dev, int where, u32 value)
 {
 	unsigned long pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
                 return PCIBIOS_DEVICE_NOT_FOUND;
 
 	*(vuip)pci_addr = value;
@@ -174,9 +166,21 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
+struct pci_ops polaris_pci_ops = 
+{
+	read_byte:	polaris_read_config_byte,
+	read_word:	polaris_read_config_word,
+	read_dword:	polaris_read_config_dword,
+	write_byte:	polaris_write_config_byte,
+	write_word:	polaris_write_config_word,
+	write_dword:	polaris_write_config_dword
+};
+
 void __init
 polaris_init_arch(unsigned long *mem_start, unsigned long *mem_end)
 {
+	struct pci_controler *hose;
+
 	/* May need to initialize error reporting (see PCICTL0/1), but
 	 * for now assume that the firmware has done the right thing
 	 * already.
@@ -184,6 +188,16 @@
 #if 0
 	printk("polaris_init_arch(): trusting firmware for setup\n");
 #endif
+
+	/*
+	 * Create our single hose.
+	 */
+
+	hose = alloc_pci_controler(mem_start);
+	hose->io_space = &ioport_resource;
+	hose->mem_space = &iomem_resource;
+	hose->config_space = POLARIS_DENSE_CONFIG_BASE;
+	hose->index = 0;
 }
 
 static inline void
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/core_pyxis.c linux/arch/alpha/kernel/core_pyxis.c
--- v2.3.15/linux/arch/alpha/kernel/core_pyxis.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/core_pyxis.c	Tue Aug 31 10:50:39 1999
@@ -1,11 +1,11 @@
 /*
  *	linux/arch/alpha/kernel/core_pyxis.c
  *
- * Code common to all PYXIS core logic chips.
- *
  * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
  *
+ * Code common to all PYXIS core logic chips.
  */
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -15,6 +15,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
+#include <asm/pci.h>
 
 #define __EXTERN_INLINE inline
 #include <asm/io.h>
@@ -22,6 +23,8 @@
 #undef __EXTERN_INLINE
 
 #include "proto.h"
+#include "pci_impl.h"
+
 
 /* NOTE: Herein are back-to-back mb instructions.  They are magic.
    One plausible explanation is that the I/O controller does not properly
@@ -83,9 +86,12 @@
  */
 
 static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
 	     unsigned char *type1)
 {
+	u8 bus = dev->bus->number;
+	u8 device_fn = dev->devfn;
+
 	*type1 = (bus == 0) ? 0 : 1;
 	*pci_addr = (bus << 16) | (device_fn << 8) | (where);
 
@@ -196,106 +202,95 @@
 		 addr, value, type1));
 }
 
-int
-pyxis_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
-			     struct linux_hose_info *hose)
+static int
+pyxis_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
-	unsigned long addr = PYXIS_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x00;
+	addr = (pci_addr << 5) + 0x00 + PYXIS_CONF;
 	*value = conf_read(addr, type1) >> ((where & 3) * 8);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-pyxis_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
-			     struct linux_hose_info *hose)
+static int
+pyxis_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-	unsigned long addr = PYXIS_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x08;
+	addr = (pci_addr << 5) + 0x08 + PYXIS_CONF;
 	*value = conf_read(addr, type1) >> ((where & 3) * 8);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-pyxis_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
-			      struct linux_hose_info *hose)
+static int
+pyxis_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
-	unsigned long addr = PYXIS_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x18;
+	addr = (pci_addr << 5) + 0x18 + PYXIS_CONF;
 	*value = conf_read(addr, type1);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-pyxis_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
-			      struct linux_hose_info *hose)
+static int
+pyxis_write_config(struct pci_dev *dev, int where, u32 value, long mask)
 {
-	unsigned long addr = PYXIS_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x00;
+	addr = (pci_addr << 5) + mask + PYXIS_CONF;
 	conf_write(addr, value << ((where & 3) * 8), type1);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-pyxis_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
-			      struct linux_hose_info *hose)
+static int 
+pyxis_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-	unsigned long addr = PYXIS_CONF;
-	unsigned long pci_addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	addr |= (pci_addr << 5) + 0x08;
-	conf_write(addr, value << ((where & 3) * 8), type1);
-	return PCIBIOS_SUCCESSFUL;
+	return pyxis_write_config(dev, where, value, 0x00);
 }
 
-int 
-pyxis_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
-			       struct linux_hose_info *hose)
+static int 
+pyxis_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-	unsigned long addr = PYXIS_CONF;
-	unsigned long pci_addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	return pyxis_write_config(dev, where, value, 0x08);
+}
 
-	addr |= (pci_addr << 5) + 0x18;
-	conf_write(addr, value << ((where & 3) * 8), type1);
-	return PCIBIOS_SUCCESSFUL;
+static int 
+pyxis_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+	return pyxis_write_config(dev, where, value, 0x18);
 }
 
+struct pci_ops pyxis_pci_ops = 
+{
+	read_byte:	pyxis_read_config_byte,
+	read_word:	pyxis_read_config_word,
+	read_dword:	pyxis_read_config_dword,
+	write_byte:	pyxis_write_config_byte,
+	write_word:	pyxis_write_config_word,
+	write_dword:	pyxis_write_config_dword
+};
+
 void __init
-pyxis_enable_errors (void)
+pyxis_init_arch(unsigned long *mem_start, unsigned long *mem_end)
 {
-	unsigned int pyxis_err;
+	struct pci_controler *hose;
+	unsigned int temp;
 
 #if 0
 	printk("pyxis_init: PYXIS_ERR_MASK 0x%x\n", *(vuip)PYXIS_ERR_MASK);
@@ -311,105 +306,16 @@
 	/* 
 	 * Set up error reporting. Make sure CPU_PE is OFF in the mask.
 	 */
-	pyxis_err = *(vuip)PYXIS_ERR_MASK;
-	pyxis_err &= ~4;   
-	*(vuip)PYXIS_ERR_MASK = pyxis_err; mb();
-	pyxis_err = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */
-
-	pyxis_err = *(vuip)PYXIS_ERR ;
-	pyxis_err |= 0x180;   /* master/target abort */
-	*(vuip)PYXIS_ERR = pyxis_err; mb();
-	pyxis_err = *(vuip)PYXIS_ERR; /* re-read to force write */
-}
-
-int __init
-pyxis_srm_window_setup (void)
-{
-	switch (alpha_use_srm_setup)
-	{
-	default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-		/* Check window 0 for enabled and mapped to 0.  */
-		if (((*(vuip)PYXIS_W0_BASE & 3) == 1)
-		    && (*(vuip)PYXIS_T0_BASE == 0)
-		    && ((*(vuip)PYXIS_W0_MASK & 0xfff00000U) > 0x0ff00000U)) {
-			PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W0_BASE & 0xfff00000U;
-			PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W0_MASK & 0xfff00000U;
-			PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-			printk("pyxis_init: using Window 0 settings\n");
-			printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
-			       *(vuip)PYXIS_W0_BASE,
-			       *(vuip)PYXIS_W0_MASK,
-			       *(vuip)PYXIS_T0_BASE);
-#endif
-			break;
-		}
+	temp = *(vuip)PYXIS_ERR_MASK;
+	temp &= ~4;   
+	*(vuip)PYXIS_ERR_MASK = temp; mb();
+	temp = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */
+
+	temp = *(vuip)PYXIS_ERR ;
+	temp |= 0x180;   /* master/target abort */
+	*(vuip)PYXIS_ERR = temp; mb();
+	temp = *(vuip)PYXIS_ERR; /* re-read to force write */
 
-		/* Check window 1 for enabled and mapped to 0.  */
-		if (((*(vuip)PYXIS_W1_BASE & 3) == 1)
-		    && (*(vuip)PYXIS_T1_BASE == 0)
-		    && ((*(vuip)PYXIS_W1_MASK & 0xfff00000U) > 0x0ff00000U)) {
-			PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W1_BASE & 0xfff00000U;
-			PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W1_MASK & 0xfff00000U;
-			PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-			printk("pyxis_init: using Window 1 settings\n");
-			printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
-			       *(vuip)PYXIS_W1_BASE,
-			       *(vuip)PYXIS_W1_MASK,
-			       *(vuip)PYXIS_T1_BASE);
-#endif
-			break;
-		}
-
-		/* Check window 2 for enabled and mapped to 0.  */
-		if (((*(vuip)PYXIS_W2_BASE & 3) == 1)
-		    && (*(vuip)PYXIS_T2_BASE == 0)
-		    && ((*(vuip)PYXIS_W2_MASK & 0xfff00000U) > 0x0ff00000U)) {
-			PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W2_BASE & 0xfff00000U;
-			PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W2_MASK & 0xfff00000U;
-			PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-			printk("pyxis_init: using Window 2 settings\n");
-			printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
-			       *(vuip)PYXIS_W2_BASE,
-			       *(vuip)PYXIS_W2_MASK,
-			       *(vuip)PYXIS_T2_BASE);
-#endif
-			break;
-		}
-
-		/* Check window 3 for enabled and mapped to 0.  */
-		if (((*(vuip)PYXIS_W3_BASE & 3) == 1)
-		    && (*(vuip)PYXIS_T3_BASE == 0)
-		    && ((*(vuip)PYXIS_W3_MASK & 0xfff00000U) > 0x0ff00000U)) {
-			PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W3_BASE & 0xfff00000U;
-			PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W3_MASK & 0xfff00000U;
-			PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
-			printk("pyxis_init: using Window 3 settings\n");
-			printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
-			       *(vuip)PYXIS_W3_BASE,
-			       *(vuip)PYXIS_W3_MASK,
-			       *(vuip)PYXIS_T3_BASE);
-#endif
-			break;
-		}
-
-		/* Otherwise, we must use our defaults.  */
-		PYXIS_DMA_WIN_BASE = PYXIS_DMA_WIN_BASE_DEFAULT;
-		PYXIS_DMA_WIN_SIZE = PYXIS_DMA_WIN_SIZE_DEFAULT;
-#endif
-	case 0:
-		return 0;
-	}
-	return 1;
-}
-
-void __init
-pyxis_native_window_setup(void)
-{
 	/*
 	 * Set up the PCI->physical memory translation windows.
 	 * For now, windows 2 and 3 are disabled.  In the future, we may
@@ -430,11 +336,7 @@
 	*(vuip)PYXIS_W2_BASE = 0x0;
 	*(vuip)PYXIS_W3_BASE = 0x0;
 	mb();
-}
 
-void __init
-pyxis_finish_init_arch(void)
-{
 	/*
          * Next, clear the PYXIS_CFG register, which gets used
 	 *  for PCI Config Space accesses. That is the way
@@ -453,42 +355,11 @@
 		}
 	}
  
-	/*
-	 * Sigh... For the SRM setup, unless we know apriori what the HAE
-	 * contents will be, we need to setup the arbitrary region bases
-	 * so we can test against the range of addresses and tailor the
-	 * region chosen for the SPARSE memory access.
-	 *
-	 * See include/asm-alpha/pyxis.h for the SPARSE mem read/write.
-	 */
-	if (alpha_use_srm_setup) {
-		unsigned int pyxis_hae_mem = *(vuip)PYXIS_HAE_MEM;
-
-		alpha_mv.sm_base_r1 = (pyxis_hae_mem      ) & 0xe0000000UL;
-		alpha_mv.sm_base_r2 = (pyxis_hae_mem << 16) & 0xf8000000UL;
-		alpha_mv.sm_base_r3 = (pyxis_hae_mem << 24) & 0xfc000000UL;
-
-		/*
-		 * Set the HAE cache, so that setup_arch() code
-		 * will use the SRM setting always. Our readb/writeb
-		 * code in pyxis.h expects never to have to change
-		 * the contents of the HAE.
-		 */
-		alpha_mv.hae_cache = pyxis_hae_mem;
-
-#ifndef CONFIG_ALPHA_GENERIC
-		/* In a generic kernel, we can always use BWIO.  */
-		alpha_mv.mv_readb = pyxis_srm_readb;
-		alpha_mv.mv_readw = pyxis_srm_readw;
-		alpha_mv.mv_writeb = pyxis_srm_writeb;
-		alpha_mv.mv_writew = pyxis_srm_writew;
-#endif
-	} else {
-		*(vuip)PYXIS_HAE_MEM = 0U; mb();
-		*(vuip)PYXIS_HAE_MEM; /* re-read to force write */
-		*(vuip)PYXIS_HAE_IO = 0; mb();
-		*(vuip)PYXIS_HAE_IO;  /* re-read to force write */
-        }
+	/* Zero the HAE.  */
+	*(vuip)PYXIS_HAE_MEM = 0U; mb();
+	*(vuip)PYXIS_HAE_MEM; /* re-read to force write */
+	*(vuip)PYXIS_HAE_IO = 0; mb();
+	*(vuip)PYXIS_HAE_IO;  /* re-read to force write */
 
 	/*
 	 * Finally, check that the PYXIS_CTRL1 has IOA_BEN set for
@@ -505,15 +376,16 @@
 			ctrl1 = *(vuip)PYXIS_CTRL1;  /* re-read */
 		}
 	}
-}
 
-void __init
-pyxis_init_arch(unsigned long *mem_start, unsigned long *mem_end)
-{
-	pyxis_enable_errors();
-	if (!pyxis_srm_window_setup())
-		pyxis_native_window_setup();
-	pyxis_finish_init_arch();
+	/*
+	 * Create our single hose.
+	 */
+
+	hose = alloc_pci_controler(mem_start);
+	hose->io_space = &ioport_resource;
+	hose->mem_space = &iomem_resource;
+	hose->config_space = PYXIS_CONF;
+	hose->index = 0;
 }
 
 static inline void
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/core_t2.c linux/arch/alpha/kernel/core_t2.c
--- v2.3.15/linux/arch/alpha/kernel/core_t2.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/core_t2.c	Tue Aug 31 10:50:39 1999
@@ -1,14 +1,14 @@
 /*
  *	linux/arch/alpha/kernel/core_t2.c
  *
- * Code common to all T2 core logic chips.
- *
  * Written by Jay A Estabrook (jestabro@amt.tay1.dec.com).
  * December 1996.
  *
  * based on CIA code by David A Rusling (david.rusling@reo.mts.dec.com)
  *
+ * Code common to all T2 core logic chips.
  */
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -18,6 +18,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
+#include <asm/pci.h>
 
 #define __EXTERN_INLINE
 #include <asm/io.h>
@@ -25,6 +26,8 @@
 #undef __EXTERN_INLINE
 
 #include "proto.h"
+#include "pci_impl.h"
+
 
 /*
  * NOTE: Herein lie back-to-back mb instructions.  They are magic. 
@@ -88,10 +91,12 @@
  */
 
 static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
 	     unsigned char *type1)
 {
 	unsigned long addr;
+	u8 bus = dev->bus->number;
+	u8 device_fn = dev->devfn;
 
 	DBG(("mk_conf_addr(bus=%d, dfn=0x%x, where=0x%x,"
 	     " addr=0x%lx, type1=0x%x)\n",
@@ -234,105 +239,94 @@
 	__restore_flags(flags);
 }
 
-int
-t2_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
-			  struct linux_hose_info *hose)
+static int
+t2_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
-	unsigned long addr = T2_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x00;
+	addr = (pci_addr << 5) + 0x00 + T2_CONF;
 	*value = conf_read(addr, type1) >> ((where & 3) * 8);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-t2_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
-			  struct linux_hose_info *hose)
+static int 
+t2_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-	unsigned long addr = T2_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x08;
+	addr = (pci_addr << 5) + 0x08 + T2_CONF;
 	*value = conf_read(addr, type1) >> ((where & 3) * 8);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-t2_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
-			   struct linux_hose_info *hose)
+static int 
+t2_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
-	unsigned long addr = T2_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x18;
+	addr = (pci_addr << 5) + 0x18 + T2_CONF;
 	*value = conf_read(addr, type1);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-t2_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
-			   struct linux_hose_info *hose)
+static int 
+t2_write_config(struct pci_dev *dev, int where, u32 value, long mask)
 {
-	unsigned long addr = T2_CONF;
-	unsigned long pci_addr;
+	unsigned long addr, pci_addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+	if (mk_conf_addr(dev, where, &pci_addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	addr |= (pci_addr << 5) + 0x00;
+	addr = (pci_addr << 5) + mask + T2_CONF;
 	conf_write(addr, value << ((where & 3) * 8), type1);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-t2_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
-			   struct linux_hose_info *hose)
+static int 
+t2_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-	unsigned long addr = T2_CONF;
-	unsigned long pci_addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	addr |= (pci_addr << 5) + 0x08;
-	conf_write(addr, value << ((where & 3) * 8), type1);
-	return PCIBIOS_SUCCESSFUL;
+	return t2_write_config(dev, where, value, 0x00);
 }
 
-int 
-t2_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
-			    struct linux_hose_info *hose)
+static int 
+t2_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-	unsigned long addr = T2_CONF;
-	unsigned long pci_addr;
-	unsigned char type1;
-
-	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
-		return PCIBIOS_DEVICE_NOT_FOUND;
+	return t2_write_config(dev, where, value, 0x08);
+}
 
-	addr |= (pci_addr << 5) + 0x18;
-	conf_write(addr, value << ((where & 3) * 8), type1);
-	return PCIBIOS_SUCCESSFUL;
+static int 
+t2_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+	return t2_write_config(dev, where, value, 0x18);
 }
 
+struct pci_ops t2_pci_ops = 
+{
+	read_byte:	t2_read_config_byte,
+	read_word:	t2_read_config_word,
+	read_dword:	t2_read_config_dword,
+	write_byte:	t2_write_config_byte,
+	write_word:	t2_write_config_word,
+	write_dword:	t2_write_config_dword
+};
+
 void __init
 t2_init_arch(unsigned long *mem_start, unsigned long *mem_end)
 {
+	struct pci_controler *hose;
 	unsigned int i;
 
 	for (i = 0; i < NR_CPUS; i++) {
@@ -364,100 +358,39 @@
 	       *(vulp)T2_TBASE2);
 #endif
 
-	switch (alpha_use_srm_setup) 
-	{
-	default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-		/* Check window 1 for enabled and mapped to 0.  */
-		if (((*(vulp)T2_WBASE1 & (3UL<<18)) == (2UL<<18))
-		    && (*(vulp)T2_TBASE1 == 0)) {
-			T2_DMA_WIN_BASE = *(vulp)T2_WBASE1 & 0xfff00000UL;
-			T2_DMA_WIN_SIZE = *(vulp)T2_WMASK1 & 0xfff00000UL;
-			T2_DMA_WIN_SIZE += 0x00100000UL;
-			/* DISABLE window 2!! ?? */
-#if 1
-			printk("t2_init: using Window 1 settings\n");
-			printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
-			       *(vulp)T2_WBASE1,
-			       *(vulp)T2_WMASK1,
-			       *(vulp)T2_TBASE1);
-#endif
-			break;
-		}
-
-		/* Check window 2 for enabled and mapped to 0.  */
-		if (((*(vulp)T2_WBASE2 & (3UL<<18)) == (2UL<<18))
-		    && (*(vulp)T2_TBASE2 == 0)) {
-			T2_DMA_WIN_BASE = *(vulp)T2_WBASE2 & 0xfff00000UL;
-			T2_DMA_WIN_SIZE = *(vulp)T2_WMASK2 & 0xfff00000UL;
-			T2_DMA_WIN_SIZE += 0x00100000UL;
-			/* DISABLE window 1!! ?? */
-#if 1
-			printk("t2_init: using Window 2 settings\n");
-			printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
-			       *(vulp)T2_WBASE2,
-			       *(vulp)T2_WMASK2,
-			       *(vulp)T2_TBASE2);
-#endif
-			break;
-		}
-
-		/* Otherwise, we must use our defaults.  */
-		T2_DMA_WIN_BASE = T2_DMA_WIN_BASE_DEFAULT;
-		T2_DMA_WIN_SIZE = T2_DMA_WIN_SIZE_DEFAULT;
-#endif
-	case 0:
-		/*
-		 * Set up the PCI->physical memory translation windows.
-		 * For now, window 2 is  disabled.  In the future, we may
-		 * want to use it to do scatter/gather DMA. 
-		 *
-		 * Window 1 goes at 1 GB and is 1 GB large.
-		 */
-
-		/* WARNING!! must correspond to the DMA_WIN params!!! */
-		*(vulp)T2_WBASE1 = 0x400807ffU;
-		*(vulp)T2_WMASK1 = 0x3ff00000U;
-		*(vulp)T2_TBASE1 = 0;
-
-		*(vulp)T2_WBASE2 = 0x0;
-		*(vulp)T2_HBASE = 0x0;
-		break;
-	}
-
 	/*
-	 * Sigh... For the SRM setup, unless we know apriori what the HAE
-	 * contents will be, we need to setup the arbitrary region bases
-	 * so we can test against the range of addresses and tailor the
-	 * region chosen for the SPARSE memory access.
+	 * Set up the PCI->physical memory translation windows.
+	 * For now, window 2 is  disabled.  In the future, we may
+	 * want to use it to do scatter/gather DMA. 
 	 *
-	 * See include/asm-alpha/t2.h for the SPARSE mem read/write.
+	 * Window 1 goes at 1 GB and is 1 GB large.
 	 */
-	if (alpha_use_srm_setup) {
-		unsigned long t2_hae_1 = *(vulp)T2_HAE_1;
-
-		alpha_mv.sm_base_r1 = (t2_hae_1 << 27) & 0xf8000000UL;
 
-		/*
-		 * Set the HAE cache, so that setup_arch() code
-		 * will use the SRM setting always. Our readb/writeb
-		 * code in .h expects never to have to change
-		 * the contents of the HAE.
-		 */
-		alpha_mv.hae_cache = t2_hae_1;
-
-		alpha_mv.mv_readb = t2_srm_readb;
-		alpha_mv.mv_readw = t2_srm_readw;
-		alpha_mv.mv_writeb = t2_srm_writeb;
-		alpha_mv.mv_writew = t2_srm_writew;
-	} else {
-		*(vulp)T2_HAE_1 = 0; mb();
-		*(vulp)T2_HAE_2 = 0; mb();
-		*(vulp)T2_HAE_3 = 0; mb();
+	/* WARNING!! must correspond to the DMA_WIN params!!! */
+	*(vulp)T2_WBASE1 = 0x400807ffU;
+	*(vulp)T2_WMASK1 = 0x3ff00000U;
+	*(vulp)T2_TBASE1 = 0;
+
+	*(vulp)T2_WBASE2 = 0x0;
+	*(vulp)T2_HBASE = 0x0;
+
+	/* Zero HAE.  */
+	*(vulp)T2_HAE_1 = 0; mb();
+	*(vulp)T2_HAE_2 = 0; mb();
+	*(vulp)T2_HAE_3 = 0; mb();
 #if 0
-		*(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */
+	*(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */
 #endif
-	}
+
+	/*
+	 * Create our single hose.
+	 */
+
+	hose = alloc_pci_controler(mem_start);
+	hose->io_space = &ioport_resource;
+	hose->mem_space = &iomem_resource;
+	hose->config_space = T2_CONF;
+	hose->index = 0;
 }
 
 #define SIC_SEIC (1UL << 33)    /* System Event Clear */
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/core_tsunami.c linux/arch/alpha/kernel/core_tsunami.c
--- v2.3.15/linux/arch/alpha/kernel/core_tsunami.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/core_tsunami.c	Tue Aug 31 10:50:39 1999
@@ -1,10 +1,9 @@
 /*
  *	linux/arch/alpha/kernel/core_tsunami.c
  *
- * Code common to all TSUNAMI core logic chips.
- *
  * Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com).
  *
+ * Code common to all TSUNAMI core logic chips.
  */
 
 #include <linux/config.h>
@@ -25,7 +24,7 @@
 #undef __EXTERN_INLINE
 
 #include "proto.h"
-#include "bios32.h"
+#include "pci_impl.h"
 
 int TSUNAMI_bootcpu;
 
@@ -84,115 +83,118 @@
  */
 
 static int
-mk_conf_addr(u8 bus, u8 device_fn, u8 where, struct linux_hose_info *hose,
-	     unsigned long *pci_addr, unsigned char *type1)
+mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
+	     unsigned char *type1)
 {
+	struct pci_controler *hose = dev->sysdata ? : probing_hose;
 	unsigned long addr;
-
-	if (!pci_probe_enabled)
-		return -1;
+	u8 bus = dev->bus->number;
+	u8 device_fn = dev->devfn;
 
 	DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
 		 "pci_addr=0x%p, type1=0x%p)\n",
 		 bus, device_fn, where, pci_addr, type1));
 
-        *type1 = (bus != 0);
-
-        if (hose->pci_first_busno == bus)
+        if (hose->first_busno == dev->bus->number)
 		bus = 0;
+        *type1 = (bus != 0);
 
         addr = (bus << 16) | (device_fn << 8) | where;
-	addr |= hose->pci_config_space;
+	addr |= hose->config_space;
 		
 	*pci_addr = addr;
 	DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
 	return 0;
 }
 
-int 
-tsunami_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
-			       struct linux_hose_info *hose)
+static int 
+tsunami_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1))
+	if (mk_conf_addr(dev, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	*value = __kernel_ldbu(*(vucp)addr);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-tsunami_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
-			       struct linux_hose_info *hose)
+static int
+tsunami_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1))
+	if (mk_conf_addr(dev, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	*value = __kernel_ldwu(*(vusp)addr);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-tsunami_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
-				struct linux_hose_info *hose)
+static int
+tsunami_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1))
+	if (mk_conf_addr(dev, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	*value = *(vuip)addr;
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-tsunami_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
-				struct linux_hose_info *hose)
+static int 
+tsunami_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1))
+	if (mk_conf_addr(dev, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	__kernel_stb(value, *(vucp)addr);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int 
-tsunami_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
-				struct linux_hose_info *hose)
+static int 
+tsunami_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1))
+	if (mk_conf_addr(dev, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	__kernel_stw(value, *(vusp)addr);
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int
-tsunami_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
-				 struct linux_hose_info *hose)
+static int
+tsunami_write_config_dword(struct pci_dev *dev, int where, u32 value)
 {
 	unsigned long addr;
 	unsigned char type1;
 
-	if (mk_conf_addr(bus, device_fn, where, hose, &addr, &type1))
+	if (mk_conf_addr(dev, where, &addr, &type1))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	*(vuip)addr = value;
 	return PCIBIOS_SUCCESSFUL;
 }
 
+struct pci_ops tsunami_pci_ops = 
+{
+	read_byte:	tsunami_read_config_byte,
+	read_word:	tsunami_read_config_word,
+	read_dword:	tsunami_read_config_dword,
+	write_byte:	tsunami_write_config_byte,
+	write_word:	tsunami_write_config_word,
+	write_dword:	tsunami_write_config_dword
+};
+
 #ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI
 static long
 tsunami_probe_read(volatile unsigned long *vaddr)
@@ -246,75 +248,51 @@
 tsunami_init_one_pchip(tsunami_pchip *pchip, int index,
 		       unsigned long *mem_start)
 {
-	struct linux_hose_info *hose;
-	int i;
+	struct pci_controler *hose;
 
 	if (tsunami_probe_read(&pchip->pctl.csr) == 0)
 		return;
 
-	hose = (struct linux_hose_info *)*mem_start;
-	*mem_start = (unsigned long)(hose + 1);
-	memset(hose, 0, sizeof(*hose));
-
-	*hose_tail = hose;
-	hose_tail = &hose->next;
-
-	hose->pci_io_space = TSUNAMI_IO(index);
-	hose->pci_mem_space = TSUNAMI_MEM(index);
-	hose->pci_config_space = TSUNAMI_CONF(index);
-	hose->pci_sparse_space = 0;
-	hose->pci_hose_index = index;
-
-	switch (alpha_use_srm_setup)
-	{
-	default:
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-		for (i = 0; i < 4; ++i) {
-			if ((pchip->wsba[i].csr & 3) == 1
-			    && pchip->tba[i].csr == 0
-			    && (pchip->wsm[i].csr & 0xfff00000) > 0x0ff00000) {
-				TSUNAMI_DMA_WIN_BASE = pchip->wsba[i].csr & 0xfff00000;
-				TSUNAMI_DMA_WIN_SIZE = pchip->wsm[i].csr & 0xfff00000;
-				TSUNAMI_DMA_WIN_SIZE += 0x00100000;
-#if 1
-				printk("%s: using Window %d settings\n", FN, i);
-				printk("%s: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
-				       FN, pchip->wsba[i].csr, pchip->wsm[i].csr,
-				       pchip->tba[i].csr);
-#endif
-				goto found;
-			}
-		}
-
-		/* Otherwise, we must use our defaults.  */
-		TSUNAMI_DMA_WIN_BASE = TSUNAMI_DMA_WIN_BASE_DEFAULT;
-		TSUNAMI_DMA_WIN_SIZE = TSUNAMI_DMA_WIN_SIZE_DEFAULT;
-#endif
-	case 0:
-		/*
-		 * Set up the PCI->physical memory translation windows.
-		 * For now, windows 1,2 and 3 are disabled.  In the future,
-		 * we may want to use them to do scatter/gather DMA. 
-		 *
-		 * Window 0 goes at 1 GB and is 1 GB large, mapping to 0.
-		 * Window 1 goes at 2 GB and is 1 GB large, mapping to 1GB.
-		 */
-
-		pchip->wsba[0].csr = TSUNAMI_DMA_WIN0_BASE_DEFAULT | 1UL;
-		pchip->wsm[0].csr  = (TSUNAMI_DMA_WIN0_SIZE_DEFAULT - 1) &
-				     0xfff00000UL;
-		pchip->tba[0].csr  = TSUNAMI_DMA_WIN0_TRAN_DEFAULT;
-		
-		pchip->wsba[1].csr = TSUNAMI_DMA_WIN1_BASE_DEFAULT | 1UL;
-		pchip->wsm[1].csr  = (TSUNAMI_DMA_WIN1_SIZE_DEFAULT - 1) &
-				     0xfff00000UL;
-		pchip->tba[1].csr  = TSUNAMI_DMA_WIN1_TRAN_DEFAULT;
-
-		pchip->wsba[2].csr = 0;
-		pchip->wsba[3].csr = 0;
-		mb();
-	}
-found:;
+	hose = alloc_pci_controler(mem_start);
+	hose->io_space = alloc_resource(mem_start);
+	hose->mem_space = alloc_resource(mem_start);
+
+	hose->config_space = TSUNAMI_CONF(index);
+	hose->index = index;
+
+	hose->io_space->start = TSUNAMI_IO(index) - TSUNAMI_IO_BIAS;
+	hose->io_space->end = hose->io_space->start + 0xffff;
+	hose->io_space->name = pci_io_names[index];
+
+	hose->mem_space->start = TSUNAMI_MEM(index) - TSUNAMI_MEM_BIAS;
+	hose->mem_space->end = hose->mem_space->start + 0xffffffff;
+	hose->mem_space->name = pci_mem_names[index];
+
+	request_resource(&ioport_resource, hose->io_space);
+	request_resource(&iomem_resource, hose->mem_space);
+
+	/*
+	 * Set up the PCI->physical memory translation windows.
+	 * For now, windows 1,2 and 3 are disabled.  In the future,
+	 * we may want to use them to do scatter/gather DMA. 
+	 *
+	 * Window 0 goes at 1 GB and is 1 GB large, mapping to 0.
+	 * Window 1 goes at 2 GB and is 1 GB large, mapping to 1GB.
+	 */
+
+	pchip->wsba[0].csr = TSUNAMI_DMA_WIN0_BASE_DEFAULT | 1UL;
+	pchip->wsm[0].csr  = (TSUNAMI_DMA_WIN0_SIZE_DEFAULT - 1) &
+			     0xfff00000UL;
+	pchip->tba[0].csr  = TSUNAMI_DMA_WIN0_TRAN_DEFAULT;
+
+	pchip->wsba[1].csr = TSUNAMI_DMA_WIN1_BASE_DEFAULT | 1UL;
+	pchip->wsm[1].csr  = (TSUNAMI_DMA_WIN1_SIZE_DEFAULT - 1) &
+			     0xfff00000UL;
+	pchip->tba[1].csr  = TSUNAMI_DMA_WIN1_TRAN_DEFAULT;
+
+	pchip->wsba[2].csr = 0;
+	pchip->wsba[3].csr = 0;
+	mb();
 }
 
 void __init
@@ -353,17 +331,18 @@
 	printk("%s: CSR_STR 0x%lx\n", FN, TSUNAMI_dchip->str.csr);
 	printk("%s: CSR_DREV 0x%lx\n", FN, TSUNAMI_dchip->drev.csr);
 #endif
-
-	/* Align memory to cache line; we'll be allocating from it.  */
-	*mem_start = (*mem_start | 31) + 1;
-
 	TSUNAMI_bootcpu = __hard_smp_processor_id();
 
+	/* With multiple PCI busses, we play with I/O as physical addrs.  */
+	ioport_resource.end = ~0UL;
+	iomem_resource.end = ~0UL;
+
 	/* Find how many hoses we have, and initialize them.  TSUNAMI
 	   and TYPHOON can have 2, but might only have 1 (DS10).  */
+
 	tsunami_init_one_pchip(TSUNAMI_pchip0, 0, mem_start);
 	if (TSUNAMI_cchip->csc.csr & 1L<<14)
-	    tsunami_init_one_pchip(TSUNAMI_pchip1, 1, mem_start);
+		tsunami_init_one_pchip(TSUNAMI_pchip1, 1, mem_start);
 }
 
 static inline void
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.3.15/linux/arch/alpha/kernel/entry.S	Wed Aug  4 15:48:00 1999
+++ linux/arch/alpha/kernel/entry.S	Tue Aug 31 10:50:44 1999
@@ -8,7 +8,7 @@
 
 #define SIGCHLD 20
 
-#define NR_SYSCALLS 371
+#define NR_SYSCALLS 373
 
 /*
  * These offsets must match with alpha_mv in <asm/machvec.h>.
@@ -1147,3 +1147,5 @@
 	.quad sys_capget
 	.quad sys_capset
 	.quad sys_sendfile			/* 370 */
+	.quad sys_setresgid
+	.quad sys_getresgid
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/head.S linux/arch/alpha/kernel/head.S
--- v2.3.15/linux/arch/alpha/kernel/head.S	Tue Jun 22 10:46:52 1999
+++ linux/arch/alpha/kernel/head.S	Tue Aug 31 10:50:44 1999
@@ -95,3 +95,21 @@
 	.prologue 0
 	call_pal PAL_halt
 	.end	halt
+
+	#
+	# Having the delay loop out of line guarantees that we wont
+	# run into weird alignment conditions (on new processors)
+	# that vary the speed of the loop.
+	#
+	.align 5
+	.globl	___delay
+	.ent	___delay
+___delay:
+	.set noat
+	.frame $30,0,$28,0
+	.prologue 0
+1:	subq	$0,1,$0
+	bge	$0,1b
+	ret	$31,($28),0
+	.set at
+	.end	___delay
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.3.15/linux/arch/alpha/kernel/irq.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/irq.c	Tue Aug 31 10:50:44 1999
@@ -30,7 +30,7 @@
 #include <asm/machvec.h>
 
 #include "proto.h"
-#include "irq.h"
+#include "irq_impl.h"
 
 #define vulp	volatile unsigned long *
 #define vuip	volatile unsigned int *
@@ -67,7 +67,7 @@
  */
 
 void
-generic_ack_irq(unsigned long irq)
+common_ack_irq(unsigned long irq)
 {
 	if (irq < 16) {
 		/* Ack the interrupt making it the lowest priority */
@@ -987,7 +987,9 @@
 
 	printk(KERN_CRIT "machine check type: %s%s\n",
 	       reason, mchk_header->retry ? " (retryable)" : "");
-	
+
+	dik_show_regs(regs, NULL);
+
 #if DEBUG_MCHECK > 1
 	{
 		/* Dump the logout area to give all info.  */
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/irq.h linux/arch/alpha/kernel/irq.h
--- v2.3.15/linux/arch/alpha/kernel/irq.h	Mon Jul 12 07:49:36 1999
+++ linux/arch/alpha/kernel/irq.h	Wed Dec 31 16:00:00 1969
@@ -1,49 +0,0 @@
-/*
- *	linux/arch/alpha/kernel/irq.h
- *
- *	Copyright (C) 1995 Linus Torvalds
- *	Copyright (C) 1998 Richard Henderson
- *
- * This file contains declarations and inline functions for interfacing
- * with the IRQ handling routines in irq.c.
- */
-
-#include <linux/config.h>
-
-#define STANDARD_INIT_IRQ_PROLOG	\
-	outb(0, DMA1_RESET_REG);	\
-	outb(0, DMA2_RESET_REG);	\
-	outb(0, DMA1_CLR_MASK_REG);	\
-	outb(0, DMA2_CLR_MASK_REG)
-
-extern unsigned long alpha_irq_mask;
-
-extern void generic_ack_irq(unsigned long irq);
-extern void isa_device_interrupt(unsigned long vector, struct pt_regs * regs);
-extern void srm_device_interrupt(unsigned long vector, struct pt_regs * regs);
-
-extern void handle_irq(int irq, int ack, struct pt_regs * regs);
-
-#define RTC_IRQ    8
-#ifdef CONFIG_RTC
-#define TIMER_IRQ  0			 /* timer is the pit */
-#else
-#define TIMER_IRQ  RTC_IRQ		 /* timer is the rtc */
-#endif
-
-extern char _stext;
-static inline void alpha_do_profile (unsigned long pc)
-{
-	if (prof_buffer && current->pid) {
-		pc -= (unsigned long) &_stext;
-		pc >>= prof_shift;
-		/*
-		 * Don't ignore out-of-bounds PC values silently,
-		 * put them into the last histogram slot, so if
-		 * present, they will show up as a sharp peak.
-		 */
-		if (pc > prof_len - 1)
-			pc = prof_len - 1;
-		atomic_inc((atomic_t *)&prof_buffer[pc]);
-	}
-}
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/irq_impl.h linux/arch/alpha/kernel/irq_impl.h
--- v2.3.15/linux/arch/alpha/kernel/irq_impl.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/kernel/irq_impl.h	Tue Aug 31 10:50:44 1999
@@ -0,0 +1,49 @@
+/*
+ *	linux/arch/alpha/kernel/irq.h
+ *
+ *	Copyright (C) 1995 Linus Torvalds
+ *	Copyright (C) 1998 Richard Henderson
+ *
+ * This file contains declarations and inline functions for interfacing
+ * with the IRQ handling routines in irq.c.
+ */
+
+#include <linux/config.h>
+
+#define STANDARD_INIT_IRQ_PROLOG	\
+	outb(0, DMA1_RESET_REG);	\
+	outb(0, DMA2_RESET_REG);	\
+	outb(0, DMA1_CLR_MASK_REG);	\
+	outb(0, DMA2_CLR_MASK_REG)
+
+extern unsigned long alpha_irq_mask;
+
+extern void common_ack_irq(unsigned long irq);
+extern void isa_device_interrupt(unsigned long vector, struct pt_regs * regs);
+extern void srm_device_interrupt(unsigned long vector, struct pt_regs * regs);
+
+extern void handle_irq(int irq, int ack, struct pt_regs * regs);
+
+#define RTC_IRQ    8
+#ifdef CONFIG_RTC
+#define TIMER_IRQ  0			 /* timer is the pit */
+#else
+#define TIMER_IRQ  RTC_IRQ		 /* timer is the rtc */
+#endif
+
+extern char _stext;
+static inline void alpha_do_profile (unsigned long pc)
+{
+	if (prof_buffer && current->pid) {
+		pc -= (unsigned long) &_stext;
+		pc >>= prof_shift;
+		/*
+		 * Don't ignore out-of-bounds PC values silently,
+		 * put them into the last histogram slot, so if
+		 * present, they will show up as a sharp peak.
+		 */
+		if (pc > prof_len - 1)
+			pc = prof_len - 1;
+		atomic_inc((atomic_t *)&prof_buffer[pc]);
+	}
+}
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/machvec.h linux/arch/alpha/kernel/machvec.h
--- v2.3.15/linux/arch/alpha/kernel/machvec.h	Mon Aug 16 10:33:58 1999
+++ linux/arch/alpha/kernel/machvec.h	Wed Dec 31 16:00:00 1969
@@ -1,140 +0,0 @@
-/*
- *	linux/arch/alpha/kernel/machvec.h
- *
- *	Copyright (C) 1997, 1998  Richard Henderson
- *
- * This file has goodies to help simplify instantiation of machine vectors.
- */
-
-#include <linux/config.h>
-
-/* Whee.  Both TSUNAMI and POLARIS don't have an HAE.  Fix things up for
-   the GENERIC kernel by defining the HAE address to be that of the cache.
-   Now we can read and write it as we like.  ;-)  */
-#define TSUNAMI_HAE_ADDRESS	(&alpha_mv.hae_cache)
-#define POLARIS_HAE_ADDRESS	(&alpha_mv.hae_cache)
-
-/* Only a few systems don't define IACK_SC, handling all interrupts through
-   the SRM console.  But splitting out that one case from IO() below
-   seems like such a pain.  Define this to get things to compile.  */
-#define JENSEN_IACK_SC		1
-#define T2_IACK_SC		1
-
-
-/*
- * Some helpful macros for filling in the blanks.
- */
-
-#define CAT1(x,y)  x##y
-#define CAT(x,y)   CAT1(x,y)
-
-#define DO_DEFAULT_RTC rtc_port: 0x70
-
-#define DO_EV4_MMU							\
-	max_asn:			EV4_MAX_ASN,			\
-	mv_switch_mm:			ev4_switch_mm,			\
-	mv_activate_mm:			ev4_activate_mm,		\
-	mv_flush_tlb_current:		ev4_flush_tlb_current,		\
-	mv_flush_tlb_other:		ev4_flush_tlb_other,		\
-	mv_flush_tlb_current_page:	ev4_flush_tlb_current_page
-
-#define DO_EV5_MMU							\
-	max_asn:			EV5_MAX_ASN,			\
-	mv_switch_mm:			ev5_switch_mm,			\
-	mv_activate_mm:			ev5_activate_mm,		\
-	mv_flush_tlb_current:		ev5_flush_tlb_current,		\
-	mv_flush_tlb_other:		ev5_flush_tlb_other,		\
-	mv_flush_tlb_current_page:	ev5_flush_tlb_current_page
-
-#define DO_EV6_MMU							\
-	max_asn:			EV6_MAX_ASN,			\
-	mv_switch_mm:			ev5_switch_mm,			\
-	mv_activate_mm:			ev5_activate_mm,		\
-	mv_flush_tlb_current:		ev5_flush_tlb_current,		\
-	mv_flush_tlb_other:		ev5_flush_tlb_other,		\
-	mv_flush_tlb_current_page:	ev5_flush_tlb_current_page
-
-#define IO_LITE(UP,low1,low2)						\
-	hae_register:		(unsigned long *) CAT(UP,_HAE_ADDRESS),	\
-	iack_sc:		CAT(UP,_IACK_SC),			\
-	mv_inb:			CAT(low1,_inb),				\
-	mv_inw:			CAT(low1,_inw),				\
-	mv_inl:			CAT(low1,_inl),				\
-	mv_outb:		CAT(low1,_outb),			\
-	mv_outw:		CAT(low1,_outw),			\
-	mv_outl:		CAT(low1,_outl),			\
-	mv_readb:		CAT(low1,_readb),			\
-	mv_readw:		CAT(low1,_readw),			\
-	mv_readl:		CAT(low1,_readl),			\
-	mv_readq:		CAT(low1,_readq),			\
-	mv_writeb:		CAT(low1,_writeb),			\
-	mv_writew:		CAT(low1,_writew),			\
-	mv_writel:		CAT(low1,_writel),			\
-	mv_writeq:		CAT(low1,_writeq),			\
-	mv_ioremap:		CAT(low2,_ioremap),			\
-	mv_is_ioaddr:		CAT(low2,_is_ioaddr)
-
-#define IO(UP,low1,low2)						\
-	IO_LITE(UP,low1,low2),						\
-	hose_read_config_byte:	CAT(low2,_hose_read_config_byte),	\
-	hose_read_config_word:	CAT(low2,_hose_read_config_word),	\
-	hose_read_config_dword:	CAT(low2,_hose_read_config_dword),	\
-	hose_write_config_byte:	CAT(low2,_hose_write_config_byte),	\
-	hose_write_config_word:	CAT(low2,_hose_write_config_word),	\
-	hose_write_config_dword: CAT(low2,_hose_write_config_dword),	\
-	dma_win_base:		CAT(UP,_DMA_WIN_BASE_DEFAULT),		\
-        dma_win_size:		CAT(UP,_DMA_WIN_SIZE_DEFAULT)
-
-/* Any assembler that can generate a GENERIC kernel can generate BWX
-   instructions.  So always use them for PYXIS I/O.  */
-
-#define DO_APECS_IO	IO(APECS,apecs,apecs)
-#define DO_CIA_IO	IO(CIA,cia,cia)
-#define DO_LCA_IO	IO(LCA,lca,lca)
-#define DO_MCPCIA_IO	IO(MCPCIA,mcpcia,mcpcia)
-#define DO_PYXIS_IO	IO(PYXIS,pyxis_bw,pyxis)
-#define DO_POLARIS_IO	IO(POLARIS,polaris,polaris)
-#define DO_T2_IO	IO(T2,t2,t2)
-#define DO_TSUNAMI_IO	IO(TSUNAMI,tsunami,tsunami)
-
-#define BUS(which)					\
-	mv_virt_to_bus:	CAT(which,_virt_to_bus),	\
-	mv_bus_to_virt:	CAT(which,_bus_to_virt)
-
-#define DO_APECS_BUS	BUS(apecs)
-#define DO_CIA_BUS	BUS(cia)
-#define DO_LCA_BUS	BUS(lca)
-#define DO_MCPCIA_BUS	BUS(mcpcia)
-#define DO_PYXIS_BUS	BUS(pyxis)
-#define DO_POLARIS_BUS	BUS(polaris)
-#define DO_T2_BUS	BUS(t2)
-#define DO_TSUNAMI_BUS	BUS(tsunami)
-
-
-/*
- * In a GENERIC kernel, we have lots of these vectors floating about,
- * all but one of which we want to go away.  In a non-GENERIC kernel,
- * we want only one, ever.
- *
- * Accomplish this in the GENERIC kernel by puting all of the vectors
- * in the .init.data section where they'll go away.  We'll copy the
- * one we want to the real alpha_mv vector in setup_arch.
- *
- * Accomplish this in a non-GENERIC kernel by ifdef'ing out all but
- * one of the vectors, which will not reside in .init.data.  We then
- * alias this one vector to alpha_mv, so no copy is needed.
- *
- * Upshot: set __initdata to nothing for non-GENERIC kernels.
- */
-
-#ifdef CONFIG_ALPHA_GENERIC
-#define __initmv __initdata
-#define ALIAS_MV(x)
-#else
-#define __initmv
-
-/* GCC actually has a syntax for defining aliases, but is under some
-   delusion that you shouldn't be able to declare it extern somewhere
-   else beforehand.  Fine.  We'll do it ourselves.  */
-#define ALIAS_MV(system) asm(".global alpha_mv\nalpha_mv = " #system "_mv");
-#endif
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/machvec_impl.h linux/arch/alpha/kernel/machvec_impl.h
--- v2.3.15/linux/arch/alpha/kernel/machvec_impl.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/kernel/machvec_impl.h	Tue Aug 31 10:50:44 1999
@@ -0,0 +1,146 @@
+/*
+ *	linux/arch/alpha/kernel/machvec.h
+ *
+ *	Copyright (C) 1997, 1998  Richard Henderson
+ *
+ * This file has goodies to help simplify instantiation of machine vectors.
+ */
+
+#include <linux/config.h>
+
+/* Whee.  Both TSUNAMI and POLARIS don't have an HAE.  Fix things up for
+   the GENERIC kernel by defining the HAE address to be that of the cache.
+   Now we can read and write it as we like.  ;-)  */
+#define TSUNAMI_HAE_ADDRESS	(&alpha_mv.hae_cache)
+#define POLARIS_HAE_ADDRESS	(&alpha_mv.hae_cache)
+
+#if CIA_ONE_HAE_WINDOW
+#define CIA_HAE_ADDRESS		(&alpha_mv.hae_cache)
+#endif
+#if MCPCIA_ONE_HAE_WINDOW
+#define MCPCIA_HAE_ADDRESS	(&alpha_mv.hae_cache)
+#endif
+
+/* Only a few systems don't define IACK_SC, handling all interrupts through
+   the SRM console.  But splitting out that one case from IO() below
+   seems like such a pain.  Define this to get things to compile.  */
+#define JENSEN_IACK_SC		1
+#define T2_IACK_SC		1
+
+
+/*
+ * Some helpful macros for filling in the blanks.
+ */
+
+#define CAT1(x,y)  x##y
+#define CAT(x,y)   CAT1(x,y)
+
+#define DO_DEFAULT_RTC rtc_port: 0x70
+
+#define DO_EV4_MMU							\
+	max_asn:			EV4_MAX_ASN,			\
+	mv_switch_mm:			ev4_switch_mm,			\
+	mv_activate_mm:			ev4_activate_mm,		\
+	mv_flush_tlb_current:		ev4_flush_tlb_current,		\
+	mv_flush_tlb_other:		ev4_flush_tlb_other,		\
+	mv_flush_tlb_current_page:	ev4_flush_tlb_current_page
+
+#define DO_EV5_MMU							\
+	max_asn:			EV5_MAX_ASN,			\
+	mv_switch_mm:			ev5_switch_mm,			\
+	mv_activate_mm:			ev5_activate_mm,		\
+	mv_flush_tlb_current:		ev5_flush_tlb_current,		\
+	mv_flush_tlb_other:		ev5_flush_tlb_other,		\
+	mv_flush_tlb_current_page:	ev5_flush_tlb_current_page
+
+#define DO_EV6_MMU							\
+	max_asn:			EV6_MAX_ASN,			\
+	mv_switch_mm:			ev5_switch_mm,			\
+	mv_activate_mm:			ev5_activate_mm,		\
+	mv_flush_tlb_current:		ev5_flush_tlb_current,		\
+	mv_flush_tlb_other:		ev5_flush_tlb_other,		\
+	mv_flush_tlb_current_page:	ev5_flush_tlb_current_page
+
+#define IO_LITE(UP,low)							\
+	hae_register:		(unsigned long *) CAT(UP,_HAE_ADDRESS),	\
+	iack_sc:		CAT(UP,_IACK_SC),			\
+	mv_inb:			CAT(low,_inb),				\
+	mv_inw:			CAT(low,_inw),				\
+	mv_inl:			CAT(low,_inl),				\
+	mv_outb:		CAT(low,_outb),				\
+	mv_outw:		CAT(low,_outw),				\
+	mv_outl:		CAT(low,_outl),				\
+	mv_readb:		CAT(low,_readb),			\
+	mv_readw:		CAT(low,_readw),			\
+	mv_readl:		CAT(low,_readl),			\
+	mv_readq:		CAT(low,_readq),			\
+	mv_writeb:		CAT(low,_writeb),			\
+	mv_writew:		CAT(low,_writew),			\
+	mv_writel:		CAT(low,_writel),			\
+	mv_writeq:		CAT(low,_writeq),			\
+	mv_ioremap:		CAT(low,_ioremap),			\
+	mv_is_ioaddr:		CAT(low,_is_ioaddr)
+
+#define IO(UP,low)							\
+	IO_LITE(UP,low),						\
+	pci_ops:		&CAT(low,_pci_ops)
+
+/* Any assembler that can generate a GENERIC kernel can generate BWX
+   instructions.  So always use them for PYXIS I/O.  */
+
+#define DO_APECS_IO	IO(APECS,apecs)
+#define DO_CIA_IO	IO(CIA,cia)
+#define DO_LCA_IO	IO(LCA,lca)
+#define DO_MCPCIA_IO	IO(MCPCIA,mcpcia)
+#define DO_PYXIS_IO	IO(PYXIS,pyxis)
+#define DO_POLARIS_IO	IO(POLARIS,polaris)
+#define DO_T2_IO	IO(T2,t2)
+#define DO_TSUNAMI_IO	IO(TSUNAMI,tsunami)
+
+#define BUS(which)					\
+	mv_virt_to_bus:	CAT(which,_virt_to_bus),	\
+	mv_bus_to_virt:	CAT(which,_bus_to_virt)
+
+#define DO_APECS_BUS	BUS(apecs)
+#define DO_CIA_BUS	BUS(cia)
+#define DO_LCA_BUS	BUS(lca)
+#define DO_MCPCIA_BUS	BUS(mcpcia)
+#define DO_PYXIS_BUS	BUS(pyxis)
+#define DO_POLARIS_BUS	BUS(polaris)
+#define DO_T2_BUS	BUS(t2)
+#define DO_TSUNAMI_BUS	BUS(tsunami)
+
+
+/*
+ * In a GENERIC kernel, we have lots of these vectors floating about,
+ * all but one of which we want to go away.  In a non-GENERIC kernel,
+ * we want only one, ever.
+ *
+ * Accomplish this in the GENERIC kernel by puting all of the vectors
+ * in the .init.data section where they'll go away.  We'll copy the
+ * one we want to the real alpha_mv vector in setup_arch.
+ *
+ * Accomplish this in a non-GENERIC kernel by ifdef'ing out all but
+ * one of the vectors, which will not reside in .init.data.  We then
+ * alias this one vector to alpha_mv, so no copy is needed.
+ *
+ * Upshot: set __initdata to nothing for non-GENERIC kernels.
+ */
+
+#ifdef CONFIG_ALPHA_GENERIC
+#define __initmv __initdata
+#define ALIAS_MV(x)
+#else
+#define __initmv
+
+/* GCC actually has a syntax for defining aliases, but is under some
+   delusion that you shouldn't be able to declare it extern somewhere
+   else beforehand.  Fine.  We'll do it ourselves.  */
+#if 0
+#define ALIAS_MV(system) \
+  struct alpha_machine_vector alpha_mv __attribute__((alias(#system "_mv")));
+#else
+#define ALIAS_MV(system) \
+  asm(".global alpha_mv\nalpha_mv = " #system "_mv");
+#endif
+#endif /* GENERIC */
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/ns87312.c linux/arch/alpha/kernel/ns87312.c
--- v2.3.15/linux/arch/alpha/kernel/ns87312.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/kernel/ns87312.c	Tue Aug 31 10:50:44 1999
@@ -0,0 +1,38 @@
+/*
+ *	linux/arch/alpha/kernel/ns87312.c
+ */
+
+#include <linux/init.h>
+#include <asm/io.h>
+#include "proto.h"
+
+
+/*
+ * The SRM console *disables* the IDE interface, this code ensures it's
+ * enabled.
+ *
+ * This code bangs on a control register of the 87312 Super I/O chip
+ * that implements parallel port/serial ports/IDE/FDI.  Depending on
+ * the motherboard, the Super I/O chip can be configured through a
+ * pair of registers that are located either at I/O ports 0x26e/0x26f
+ * or 0x398/0x399.  Unfortunately, autodetecting which base address is
+ * in use works only once (right after a reset).  The Super I/O chip
+ * has the additional quirk that configuration register data must be
+ * written twice (I believe this is a safety feature to prevent
+ * accidental modification---fun, isn't it?).
+ */
+
+void __init
+ns87312_enable_ide(long ide_base)
+{
+	int data;
+	unsigned long flags;
+
+	__save_and_cli(flags);
+	outb(0, ide_base);		/* set the index register for reg #0 */
+	data = inb(ide_base+1);		/* read the current contents */
+	outb(0, ide_base);		/* set the index register for reg #0 */
+	outb(data | 0x40, ide_base+1);	/* turn on IDE */
+	outb(data | 0x40, ide_base+1);	/* turn on IDE, really! */
+	__restore_flags(flags);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/pci.c linux/arch/alpha/kernel/pci.c
--- v2.3.15/linux/arch/alpha/kernel/pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/kernel/pci.c	Tue Aug 31 10:50:44 1999
@@ -0,0 +1,230 @@
+/*
+ *	linux/arch/alpha/kernel/pci.c
+ *
+ * Extruded from code written by
+ *	Dave Rusling (david.rusling@reo.mts.dec.com)
+ *	David Mosberger (davidm@cs.arizona.edu)
+ */
+
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <asm/pci.h>
+#include <asm/machvec.h>
+
+#include "proto.h"
+#include "pci_impl.h"
+
+
+/*
+ * Some string constants used by the various core logics. 
+ */
+
+const char *const pci_io_names[] = {
+	"PCI IO bus 0", "PCI IO bus 1", "PCI IO bus 2", "PCI IO bus 3"
+};
+
+const char *const pci_mem_names[] = {
+	"PCI mem bus 0", "PCI mem bus 1", "PCI mem bus 2", "PCI mem bus 3"
+};
+
+const char pci_hae0_name[] = "HAE0";
+
+
+/*
+ * The PCI controler list.
+ */
+
+struct pci_controler *hose_head, **hose_tail = &hose_head;
+struct pci_controler *probing_hose;
+
+/*
+ * Quirks.
+ */
+
+static void __init
+quirk_eisa_bridge(struct pci_dev *dev)
+{
+	dev->class = PCI_CLASS_BRIDGE_EISA;
+}
+
+static void __init
+quirk_isa_bridge(struct pci_dev *dev)
+{
+	dev->class = PCI_CLASS_BRIDGE_ISA;
+}
+
+struct pci_fixup pcibios_fixups[] __initdata = {
+	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375,
+	  quirk_eisa_bridge },
+	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378,
+	  quirk_isa_bridge },
+	{ 0 }
+};
+
+
+/* 
+ * Pre-layout host-independant device initialization.
+ */
+
+static void __init
+pci_assign_special(void)
+{
+	struct pci_dev *dev;
+
+	/* The first three resources of the Cypress IDE controler need
+	   to remain unchanged.  So allocate them as-is.  */
+	dev = NULL;
+	while ((dev = pci_find_device(PCI_VENDOR_ID_CONTAQ,
+				       PCI_DEVICE_ID_CONTAQ_82C693, dev))) {
+		if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
+			pci_record_assignment(dev, 0);
+			pci_record_assignment(dev, 1);
+			pci_record_assignment(dev, 2);
+		}
+	}
+}
+
+
+void __init
+pcibios_init(void)
+{
+	if (!alpha_mv.init_pci)
+		return;
+	alpha_mv.init_pci();
+}
+
+char * __init
+pcibios_setup(char *str)
+{
+	return str;
+}
+
+void __init
+pcibios_fixup_bus(struct pci_bus *bus)
+{
+	/* Propogate hose info into the subordinate devices.  */
+
+	struct pci_dev *dev;
+	void *sysdata;
+
+	sysdata = (bus->parent ? bus->parent->sysdata : bus->sysdata);
+	for (dev = bus->devices; dev; dev = dev->sibling)
+		dev->sysdata = sysdata;
+}
+
+void __init
+pcibios_base_address_update(struct pci_dev *dev, int resource)
+{
+	struct pci_controler *hose = dev->sysdata;
+        struct resource *res = &dev->resource[resource];
+        unsigned long base, where, size;
+        u32 reg;
+
+        if (res->flags & IORESOURCE_IO)
+                base = hose->io_space->start;
+        else
+                base = hose->mem_space->start;
+
+        where = PCI_BASE_ADDRESS_0 + (resource * 4);
+        size = res->end - res->start;
+        pci_read_config_dword(dev, where, &reg);
+        reg = (reg & size) | (((u32)(res->start - base)) & ~size);
+        pci_write_config_dword(dev, where, reg);
+
+	/* ??? FIXME -- record old value for shutdown.  */
+}
+
+void __init
+pcibios_irq_update(struct pci_dev *dev, u8 irq)
+{
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+
+	/* ??? FIXME -- record old value for shutdown.  */
+}
+
+/* Most Alphas have straight-forward swizzling needs.  */
+
+u8 __init
+common_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+	struct pci_controler *hose = dev->sysdata;
+
+	if (dev->bus->number != hose->first_busno) {
+		u8 pin = *pinp;
+		do {
+			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+			/* Move up the chain of bridges. */
+			dev = dev->bus->self;
+		} while (dev->bus->self);
+		*pinp = pin;
+
+		/* The slot is the slot of the last bridge. */
+	}
+
+	return PCI_SLOT(dev->devfn);
+}
+
+void __init
+common_init_pci(void)
+{
+	struct pci_controler *hose;
+	struct pci_bus *bus;
+	int next_busno;
+
+	/* Scan all of the recorded PCI controlers.  */
+	for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
+		hose->first_busno = next_busno;
+		hose->last_busno = 0xff;
+		probing_hose = hose;
+		bus = pci_scan_bus(next_busno, alpha_mv.pci_ops, hose);
+		hose->bus = bus;
+		next_busno = hose->last_busno = bus->subordinate;
+		next_busno += 1;
+	}
+	probing_hose = NULL;
+
+	pci_assign_special();
+	pci_assign_unassigned(alpha_mv.min_io_address,
+			      alpha_mv.min_mem_address);
+	pci_fixup_irq(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
+	pci_set_bus_ranges();
+}
+
+
+struct pci_controler * __init
+alloc_pci_controler(unsigned long *mem_start)
+{
+	unsigned long start = *mem_start;
+	struct pci_controler *hose;
+	if (start & 31)
+		start = (start | 31) + 1;
+	hose = (void *) start;
+	start = (unsigned long) (hose + 1);
+	*mem_start = start;
+
+	memset(hose, 0, sizeof(*hose));
+
+	*hose_tail = hose;
+	hose_tail = &hose->next;
+
+	return hose;
+}
+
+struct resource * __init
+alloc_resource(unsigned long *mem_start)
+{
+	unsigned long start = *mem_start;
+	struct resource *res;
+	if (start & 31)
+		start = (start | 31) + 1;
+	res = (void *) start;
+	start = (unsigned long) (res + 1);
+	*mem_start = start;
+
+	memset(res, 0, sizeof(*res));
+
+	return res;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/pci_impl.h linux/arch/alpha/kernel/pci_impl.h
--- v2.3.15/linux/arch/alpha/kernel/pci_impl.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/kernel/pci_impl.h	Tue Aug 31 10:50:44 1999
@@ -0,0 +1,146 @@
+/*
+ *	linux/arch/alpha/kernel/pci_impl.h
+ *
+ * This file contains declarations and inline functions for interfacing
+ * with the PCI initialization routines.
+ */
+
+struct pci_dev;
+struct pci_controler;
+
+
+/*
+ * We can't just blindly use 64K for machines with EISA busses; they
+ * may also have PCI-PCI bridges present, and then we'd configure the
+ * bridge incorrectly.
+ *
+ * Also, we start at 0x8000 or 0x9000, in hopes to get all devices'
+ * IO space areas allocated *before* 0xC000; this is because certain
+ * BIOSes (Millennium for one) use PCI Config space "mechanism #2"
+ * accesses to probe the bus. If a device's registers appear at 0xC000,
+ * it may see an INx/OUTx at that address during BIOS emulation of the
+ * VGA BIOS, and some cards, notably Adaptec 2940UW, take mortal offense.
+ */
+
+#define EISA_DEFAULT_IO_BASE	0x9000	/* start above 8th slot */
+#define DEFAULT_IO_BASE		0x8000	/* start at 8th slot */
+
+/*
+ * We try to make the DEFAULT_MEM_BASE addresses *always* have more than
+ * a single bit set. This is so that devices like the broken Myrinet card
+ * will always have a PCI memory address that will never match a IDSEL
+ * address in PCI Config space, which can cause problems with early rev cards.
+ */
+
+/*
+ * An XL is AVANTI (APECS) family, *but* it has only 27 bits of ISA address
+ * that get passed through the PCI<->ISA bridge chip. Although this causes
+ * us to set the PCI->Mem window bases lower than normal, we still allocate
+ * PCI bus devices' memory addresses *below* the low DMA mapping window,
+ * and hope they fit below 64Mb (to avoid conflicts), and so that they can
+ * be accessed via SPARSE space.
+ *
+ * We accept the risk that a broken Myrinet card will be put into a true XL
+ * and thus can more easily run into the problem described below.
+ */
+#define XL_DEFAULT_MEM_BASE ((16+2)*1024*1024) /* 16M to 64M-1 is avail */
+
+/*
+ * APECS and LCA have only 34 bits for physical addresses, thus limiting PCI
+ * bus memory addresses for SPARSE access to be less than 128Mb.
+ */
+#define APECS_AND_LCA_DEFAULT_MEM_BASE ((32+2)*1024*1024)
+
+/*
+ * Because the MCPCIA core logic supports more bits for physical addresses,
+ * it should allow an expanded range of SPARSE memory addresses.
+ * However, we do not use them all, in order to avoid the HAE manipulation
+ * that would be needed.
+ */
+#define MCPCIA_DEFAULT_MEM_BASE ((32+2)*1024*1024)
+
+/*
+ * Because CIA and PYXIS and T2 have more bits for physical addresses,
+ * they support an expanded range of SPARSE memory addresses.
+ */
+#define DEFAULT_MEM_BASE ((128+16)*1024*1024)
+
+/* ??? Experimenting with no HAE for CIA.  */
+#define CIA_DEFAULT_MEM_BASE ((32+2)*1024*1024)
+
+
+/* 
+ * A small note about bridges and interrupts.  The DECchip 21050 (and
+ * later) adheres to the PCI-PCI bridge specification.  This says that
+ * the interrupts on the other side of a bridge are swizzled in the
+ * following manner:
+ *
+ * Dev    Interrupt   Interrupt 
+ *        Pin on      Pin on 
+ *        Device      Connector
+ *
+ *   4    A           A
+ *        B           B
+ *        C           C
+ *        D           D
+ * 
+ *   5    A           B
+ *        B           C
+ *        C           D
+ *        D           A
+ *
+ *   6    A           C
+ *        B           D
+ *        C           A
+ *        D           B
+ *
+ *   7    A           D
+ *        B           A
+ *        C           B
+ *        D           C
+ *
+ *   Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
+ *   Thus, each swizzle is ((pin-1) + (device#-4)) % 4
+ *
+ *   The following code swizzles for exactly one bridge.  The routine
+ *   common_swizzle below handles multiple bridges.  But there are a
+ *   couple boards that do strange things, so we define this here.
+ */
+
+static inline u8 bridge_swizzle(u8 pin, u8 slot) 
+{
+	return (((pin-1) + slot) % 4) + 1;
+}
+
+
+/* The following macro is used to implement the table-based irq mapping
+   function for all single-bus Alphas.  */
+
+#define COMMON_TABLE_LOOKUP						\
+({ long _ctl_ = -1; 							\
+   if (slot >= min_idsel && slot <= max_idsel && pin < irqs_per_slot)	\
+     _ctl_ = irq_tab[slot - min_idsel][pin];				\
+   _ctl_; })
+
+
+/* The hose list.  */
+extern struct pci_controler *hose_head, **hose_tail;
+extern struct pci_controler *probing_hose;
+
+/* pci_common.c */
+extern void common_init_pci(void);
+extern u8 common_swizzle(struct pci_dev *, u8 *);
+extern struct pci_controler *alloc_pci_controler(unsigned long *);
+extern struct resource *alloc_resource(unsigned long *);
+
+extern const char *const pci_io_names[];
+extern const char *const pci_mem_names[];
+extern const char pci_hae0_name[];
+
+/* pci_setup.c */
+void pci_record_assignment(struct pci_dev *dev, int resource);
+void pci_assign_unassigned(int, int);
+void pci_fixup_irq(u8 (*swizzle)(struct pci_dev *, u8 *),
+		   int (*map_irq)(struct pci_dev *, u8, u8));
+void pci_set_bus_ranges(void);
+
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/pci_setup.c linux/arch/alpha/kernel/pci_setup.c
--- v2.3.15/linux/arch/alpha/kernel/pci_setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/kernel/pci_setup.c	Tue Aug 31 10:50:44 1999
@@ -0,0 +1,328 @@
+/*
+ *	linux/arch/alpha/kernel/pci_setup.c
+ *
+ * Extruded from code written by
+ *      Dave Rusling (david.rusling@reo.mts.dec.com)
+ *      David Mosberger (davidm@cs.arizona.edu)
+ *	David Miller (davem@redhat.com)
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <asm/pci.h>
+
+
+#define DEBUG_CONFIG 0
+#if DEBUG_CONFIG
+# define DBGC(args)     printk args
+#else
+# define DBGC(args)
+#endif
+
+
+void __init
+pci_record_assignment(struct pci_dev *dev, int resource)
+{
+	struct pci_controler *hose = dev->sysdata;
+        struct resource *res = &dev->resource[resource];
+	struct resource *base;
+	int ok;
+
+	if (res->flags == 0)
+		return;
+	if (res->flags & IORESOURCE_IO)
+		base = hose->io_space;
+	else
+		base = hose->mem_space;
+
+	res->start += base->start;
+	res->end += base->start;
+
+	ok = request_resource(base, res);
+
+	DBGC(("PCI record assignment: (%s) resource %d %s\n",
+	      dev->name, resource, (ok < 0 ? "failed" : "ok")));
+}
+
+static void inline
+pdev_assign_unassigned(struct pci_dev *dev, int min_io, int min_mem)
+{
+	u32 reg;
+	u16 cmd;
+	int i;
+
+	DBGC(("PCI assign resources : (%s)\n", dev->name));
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		struct pci_controler *hose;
+		struct resource *root, *res;
+		unsigned long size, min, max;
+
+		res = &dev->resource[i];
+
+		if (res->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		else if (res->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+
+		/* If it is already assigned or the resource does
+		   not exist, there is nothing to do.  */
+		if (res->parent != NULL || res->flags == 0UL)
+			continue;
+
+		hose = dev->sysdata;
+
+		/* Determine the root we allocate from.  */
+		if (res->flags & IORESOURCE_IO) {
+			root = hose->io_space;
+			min = root->start + min_io;
+			max = root->end;
+		} else {
+			root = hose->mem_space;
+			min = root->start + min_mem;
+			max = root->end;
+		}
+
+		size = res->end - res->start + 1;
+
+		DBGC(("  for root[%016lx:%016lx]\n"
+		      "       res[%016lx:%016lx]\n"
+		      "      span[%016lx:%016lx] size[%lx]\n",
+		      root->start, root->end, res->start, res->end,
+		      min, max, size));
+
+		if (allocate_resource(root, res, size, min, max, size) < 0) {
+			printk(KERN_ERR
+			       "PCI: Failed to allocate resource %d for %s\n",
+			       i, dev->name);
+		}
+
+		DBGC(("  got res[%016lx:%016lx] for resource %d\n",
+		      res->start, res->end, i));
+
+		/* Update PCI config space.  */
+		pcibios_base_address_update(dev, i);
+	}
+
+	/* Special case, disable the ROM.  Several devices act funny
+	   (ie. do not respond to memory space writes) when it is left
+	   enabled.  A good example are QlogicISP adapters.  */
+
+	pci_read_config_dword(dev, PCI_ROM_ADDRESS, &reg);
+	reg &= ~PCI_ROM_ADDRESS_ENABLE;
+	pci_write_config_dword(dev, PCI_ROM_ADDRESS, reg);
+
+	/* All of these (may) have I/O scattered all around and may not
+	   use IO-base address registers at all.  So we just have to
+	   always enable IO to these devices.  */
+	if ((dev->class >> 8) == PCI_CLASS_NOT_DEFINED
+	    || (dev->class >> 8) == PCI_CLASS_NOT_DEFINED_VGA
+	    || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE
+	    || (dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+		cmd |= PCI_COMMAND_IO;
+	}
+
+	/* ??? Always turn on bus mastering.  */
+	cmd |= PCI_COMMAND_MASTER;
+
+	/* Enable the appropriate bits in the PCI command register.  */
+	pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+	DBGC(("  cmd reg 0x%x\n", cmd));
+
+	/* If this is a PCI bridge, set the cache line correctly.  */
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+		/* ??? EV4/EV5 cache line is 32 bytes.  */
+		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+				      (64 / sizeof(u32)));
+	}
+}
+
+void __init
+pci_assign_unassigned(int min_io, int min_mem)
+{
+	struct pci_dev *dev;
+
+	for (dev = pci_devices; dev; dev = dev->next)
+		pdev_assign_unassigned(dev, min_io, min_mem);
+}
+
+struct pbus_set_ranges_data
+{
+	int found_vga;
+	unsigned int io_start, io_end;
+	unsigned int mem_start, mem_end;
+};
+
+static void __init
+pbus_set_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
+{
+	struct pbus_set_ranges_data inner;
+	struct pci_bus *child;
+	struct pci_dev *dev;
+
+	inner.found_vga = 0;
+	inner.mem_start = inner.io_start = ~0;
+	inner.mem_end = inner.io_end = 0;
+
+	/* Collect information about how our direct children are layed out. */
+	for (dev = bus->devices; dev; dev = dev->sibling) {
+		int i;
+		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+			struct resource *res = &dev->resource[i];
+			if (res->flags & IORESOURCE_IO) {
+				if (res->start < inner.io_start)
+					inner.io_start = res->start;
+				if (res->end > inner.io_end)
+					inner.io_end = res->end;
+			} else if (res->flags & IORESOURCE_MEM) {
+				if (res->start < inner.mem_start)
+					inner.mem_start = res->start;
+				if (res->end > inner.mem_end)
+					inner.mem_end = res->end;
+			}
+		}
+                if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
+                        inner.found_vga = 1;
+	}
+
+	/* And for all of the sub-busses.  */
+	for (child = bus->children; child; child = child->next)
+		pbus_set_ranges(child, &inner);
+
+	/* Align the values.  */
+	inner.io_start &= ~(4*1024 - 1);
+	inner.mem_start &= ~(1*1024*1024 - 1);
+	if (inner.io_end & (4*1024-1))
+		inner.io_end = (inner.io_end | (4*1024 - 1)) + 1;
+	if (inner.mem_end & (1*1024*1024-1))
+		inner.mem_end = (inner.mem_end | (1*1024*1024 - 1)) + 1;
+
+	/* Configure the bridge, if possible.  */
+	if (bus->self) {
+		struct pci_dev *bridge = bus->self;
+		u32 l;
+
+                /* Set up the top and bottom of the PCI I/O segment
+                   for this bus.  */
+                pci_read_config_dword(bridge, PCI_IO_BASE, &l);
+                l &= 0xffff0000;
+                l |= (inner.io_start >> 8) & 0x00f0;
+		l |= (inner.io_end - 1) & 0xf000;
+                pci_write_config_dword(bridge, PCI_IO_BASE, l);
+
+                /*
+                 * Clear out the upper 16 bits of IO base/limit.
+                 * Clear out the upper 32 bits of PREF base/limit.
+                 */
+                pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0);
+                pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
+                pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
+
+                /* Set up the top and bottom of the PCI Memory segment
+                   for this bus.  */
+                l = (inner.mem_start & 0xfff00000) >> 16;
+		l |= (inner.mem_end - 1) & 0xfff00000;
+                pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
+
+                /*
+                 * Turn off downstream PF memory address range, unless
+                 * there is a VGA behind this bridge, in which case, we
+                 * enable the PREFETCH range to include BIOS ROM at C0000.
+                 *
+                 * NOTE: this is a bit of a hack, done with PREFETCH for
+                 * simplicity, rather than having to add it into the above
+                 * non-PREFETCH range, which could then be bigger than we want.
+                 * We might assume that we could relocate the BIOS ROM, but
+                 * that would depend on having it found by those who need it
+                 * (the DEC BIOS emulator would find it, but I do not know
+                 * about the Xservers). So, we do it this way for now... ;-)
+                 */
+                l = (inner.found_vga) ? 0 : 0x0000ffff;
+                pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
+
+                /*
+                 * Tell bridge that there is an ISA bus in the system,
+                 * and (possibly) a VGA as well.
+                 */
+                l = (inner.found_vga) ? 0x0c : 0x04;
+                pci_write_config_byte(bridge, PCI_BRIDGE_CONTROL, l);
+
+                /*
+                 * Clear status bits,
+                 * turn on I/O    enable (for downstream I/O),
+                 * turn on memory enable (for downstream memory),
+                 * turn on master enable (for upstream memory and I/O).
+                 */
+                pci_write_config_dword(bridge, PCI_COMMAND, 0xffff0007);
+	}
+
+	if (outer) {
+		outer->found_vga |= inner.found_vga;
+		if (inner.io_start < outer->io_start)
+			outer->io_start = inner.io_start;
+		if (inner.io_end > outer->io_end)
+			outer->io_end = inner.io_end;
+		if (inner.mem_start < outer->mem_start)
+			outer->mem_start = inner.mem_start;
+		if (inner.mem_end > outer->mem_end)
+			outer->mem_end = inner.mem_end;
+	}
+}
+
+void __init
+pci_set_bus_ranges(void)
+{
+	struct pci_bus *bus;
+
+	for (bus = pci_root; bus; bus = bus->next)
+		pbus_set_ranges(bus, NULL);
+}
+
+static void inline
+pdev_fixup_irq(struct pci_dev *dev,
+	       u8 (*swizzle)(struct pci_dev *, u8 *),
+	       int (*map_irq)(struct pci_dev *, u8, u8))
+{
+	u8 pin, slot;
+	int irq;
+
+	/* If this device is not on the primary bus, we need to figure out
+	   which interrupt pin it will come in on.   We know which slot it
+	   will come in on 'cos that slot is where the bridge is.   Each
+	   time the interrupt line passes through a PCI-PCI bridge we must
+	   apply the swizzle function.  */
+
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	/* Cope with 0 and illegal. */
+	if (pin == 0 || pin > 4)
+		pin = 1;
+
+	/* Follow the chain of bridges, swizzling as we go.  */
+	slot = (*swizzle)(dev, &pin);
+
+	irq = (*map_irq)(dev, slot, pin);
+	if (irq == -1)
+		irq = 0;
+	dev->irq = irq;
+
+	DBGC(("PCI fixup irq : (%s) got %d\n", dev->name, dev->irq));
+
+	/* Always tell the device, so the driver knows what is
+	   the real IRQ to use; the device does not use it. */
+	pcibios_irq_update(dev, irq);
+}
+
+void __init
+pci_fixup_irq(u8 (*swizzle)(struct pci_dev *, u8 *),
+	      int (*map_irq)(struct pci_dev *, u8, u8))
+{
+	struct pci_dev *dev;
+
+	for (dev = pci_devices; dev; dev = dev->next)
+		pdev_fixup_irq(dev, swizzle, map_irq);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/pci_syscall.c linux/arch/alpha/kernel/pci_syscall.c
--- v2.3.15/linux/arch/alpha/kernel/pci_syscall.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/kernel/pci_syscall.c	Tue Aug 31 10:50:44 1999
@@ -0,0 +1,148 @@
+/*
+ *	pci_syscall.c
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+
+
+#ifndef CONFIG_PCI
+
+asmlinkage int sys_pciconfig_read() { return -ENOSYS; }
+asmlinkage int sys_pciconfig_write() { return -ENOSYS; }
+
+#else
+
+asmlinkage long
+sys_pciconfig_read(unsigned long bus, unsigned long dfn,
+		   unsigned long off, unsigned long len, void *buf)
+{
+	struct pci_dev *dev;
+	u8 byte;
+	u16 word;
+	u32 dword;
+	long err, cfg_ret;
+
+	err = -EPERM;
+	if (!capable(CAP_SYS_ADMIN))
+		goto error;
+
+	err = -ENODEV;
+	dev = pci_find_slot(bus, dfn);
+	if (!dev)
+		goto error;
+
+	lock_kernel();
+	switch (len) {
+	case 1:
+		cfg_ret = pci_read_config_byte(dev, off, &byte);
+		break;
+	case 2:
+		cfg_ret = pci_read_config_word(dev, off, &word);
+		break;
+	case 4:
+		cfg_ret = pci_read_config_dword(dev, off, &dword);
+		break;
+	default:
+		err = -EINVAL;
+		unlock_kernel();
+		goto error;
+	};
+	unlock_kernel();
+
+	err = -EIO;
+	if (cfg_ret != PCIBIOS_SUCCESSFUL)
+		goto error;
+
+	switch (len) {
+	case 1:
+		err = put_user(byte, (unsigned char *)buf);
+		break;
+	case 2:
+		err = put_user(word, (unsigned short *)buf);
+		break;
+	case 4:
+		err = put_user(dword, (unsigned int *)buf);
+		break;
+	};
+	return err;
+
+error:
+	/* ??? XFree86 doesn't even check the return value.  They
+	   just look for 0xffffffff in the output, since that's what
+	   they get instead of a machine check on x86.  */
+	switch (len) {
+	case 1:
+		put_user(-1, (unsigned char *)buf);
+		break;
+	case 2:
+		put_user(-1, (unsigned short *)buf);
+		break;
+	case 4:
+		put_user(-1, (unsigned int *)buf);
+		break;
+	};
+	return err;
+}
+
+asmlinkage long
+sys_pciconfig_write(unsigned long bus, unsigned long dfn,
+		    unsigned long off, unsigned long len, void *buf)
+{
+	struct pci_dev *dev;
+	u8 byte;
+	u16 word;
+	u32 dword;
+	int err = 0;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (!pcibios_present())
+		return -ENOSYS;
+
+	dev = pci_find_slot(bus, dfn);
+	if (!dev)
+		return -ENODEV;
+
+	lock_kernel();
+	switch(len) {
+	case 1:
+		err = get_user(byte, (u8 *)buf);
+		if (err)
+			break;
+		err = pci_write_config_byte(dev, off, byte);
+		if (err != PCIBIOS_SUCCESSFUL)
+			err = -EIO;
+		break;
+
+	case 2:
+		err = get_user(word, (u16 *)buf);
+		if (err)
+			break;
+		err = pci_write_config_byte(dev, off, word);
+		if (err != PCIBIOS_SUCCESSFUL)
+			err = -EIO;
+		break;
+
+	case 4:
+		err = get_user(dword, (u32 *)buf);
+		if (err)
+			break;
+		pci_write_config_byte(dev, off, dword);
+		if (err != PCIBIOS_SUCCESSFUL)
+			err = -EIO;
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+	};
+	unlock_kernel();
+
+	return err;
+}
+
+#endif /* CONFIG_PCI */
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.3.15/linux/arch/alpha/kernel/process.c	Tue Aug  3 08:20:45 1999
+++ linux/arch/alpha/kernel/process.c	Tue Aug 31 10:50:44 1999
@@ -43,7 +43,7 @@
 #include <asm/fpu.h>
 
 #include "proto.h"
-#include "bios32.h"
+#include "pci_impl.h"
 
 /*
  * Initial task structure. Make this a per-architecture thing,
@@ -95,7 +95,7 @@
 }
 
 void
-generic_kill_arch (int mode, char *restart_cmd)
+common_kill_arch (int mode, char *restart_cmd)
 {
 	/* The following currently only has any effect on SRM.  We should
 	   fix MILO to understand it.  Should be pretty easy.  Also we can
@@ -130,7 +130,7 @@
 		cpup->flags = flags;					       
 		mb();						
 
-		reset_for_srm();
+		/* reset_for_srm(); */
 		set_hae(srm_hae);
 
 #ifdef CONFIG_DUMMY_CONSOLE
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h
--- v2.3.15/linux/arch/alpha/kernel/proto.h	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/proto.h	Tue Aug 31 10:50:44 1999
@@ -6,141 +6,48 @@
 #define vuip	volatile unsigned int   *
 #define vulp	volatile unsigned long  *
 
-struct linux_hose_info;
+struct pt_regs;
+struct task_struct;
+struct pci_dev;
 
 /* core_apecs.c */
-extern int apecs_hose_read_config_byte (u8, u8, u8, u8 *value,
-					struct linux_hose_info *hose);
-extern int apecs_hose_read_config_word (u8, u8, u8, u16 *value,
-					struct linux_hose_info *hose);
-extern int apecs_hose_read_config_dword (u8, u8, u8, u32 *value,
-					 struct linux_hose_info *hose);
-extern int apecs_hose_write_config_byte (u8, u8, u8, u8 value,
-					 struct linux_hose_info *hose);
-extern int apecs_hose_write_config_word (u8, u8, u8, u16 value,
-					 struct linux_hose_info *hose);
-extern int apecs_hose_write_config_dword (u8, u8, u8, u32 value,
-					  struct linux_hose_info *hose);
+extern struct pci_ops apecs_pci_ops;
 extern void apecs_init_arch(unsigned long *, unsigned long *);
-
-extern volatile unsigned int apecs_mcheck_expected;
-extern volatile unsigned int apecs_mcheck_taken;
 extern void apecs_pci_clr_err(void);
 extern void apecs_machine_check(u64, u64, struct pt_regs *);
 
 /* core_cia.c */
-extern int cia_hose_read_config_byte (u8, u8, u8, u8 *value,
-				      struct linux_hose_info *hose);
-extern int cia_hose_read_config_word (u8, u8, u8, u16 *value,
-				      struct linux_hose_info *hose);
-extern int cia_hose_read_config_dword (u8, u8, u8, u32 *value,
-				       struct linux_hose_info *hose);
-extern int cia_hose_write_config_byte (u8, u8, u8, u8 value,
-				       struct linux_hose_info *hose);
-extern int cia_hose_write_config_word (u8, u8, u8, u16 value,
-				       struct linux_hose_info *hose);
-extern int cia_hose_write_config_dword (u8, u8, u8, u32 value,
-					struct linux_hose_info *hose);
+extern struct pci_ops cia_pci_ops;
 extern void cia_init_arch(unsigned long *, unsigned long *);
 extern void cia_machine_check(u64, u64, struct pt_regs *);
 
 /* core_lca.c */
-extern int lca_hose_read_config_byte (u8, u8, u8, u8 *value,
-				      struct linux_hose_info *hose);
-extern int lca_hose_read_config_word (u8, u8, u8, u16 *value,
-				      struct linux_hose_info *hose);
-extern int lca_hose_read_config_dword (u8, u8, u8, u32 *value,
-				       struct linux_hose_info *hose);
-extern int lca_hose_write_config_byte (u8, u8, u8, u8 value,
-				       struct linux_hose_info *hose);
-extern int lca_hose_write_config_word (u8, u8, u8, u16 value,
-				       struct linux_hose_info *hose);
-extern int lca_hose_write_config_dword (u8, u8, u8, u32 value,
-					struct linux_hose_info *hose);
+extern struct pci_ops lca_pci_ops;
 extern void lca_init_arch(unsigned long *, unsigned long *);
 extern void lca_machine_check(u64, u64, struct pt_regs *);
 
 /* core_mcpcia.c */
-extern int mcpcia_hose_read_config_byte (u8, u8, u8, u8 *value,
-					 struct linux_hose_info *hose);
-extern int mcpcia_hose_read_config_word (u8, u8, u8, u16 *value,
-					 struct linux_hose_info *hose);
-extern int mcpcia_hose_read_config_dword (u8, u8, u8, u32 *value,
-					  struct linux_hose_info *hose);
-extern int mcpcia_hose_write_config_byte (u8, u8, u8, u8 value,
-					  struct linux_hose_info *hose);
-extern int mcpcia_hose_write_config_word (u8, u8, u8, u16 value,
-					  struct linux_hose_info *hose);
-extern int mcpcia_hose_write_config_dword (u8, u8, u8, u32 value,
-					   struct linux_hose_info *hose);
+extern struct pci_ops mcpcia_pci_ops;
 extern void mcpcia_init_arch(unsigned long *, unsigned long *);
 extern void mcpcia_machine_check(u64, u64, struct pt_regs *);
 
 /* core_polaris.c */
-extern int polaris_hose_read_config_byte (u8, u8, u8, u8 *value,
-					struct linux_hose_info *hose);
-extern int polaris_hose_read_config_word (u8, u8, u8, u16 *value,
-					struct linux_hose_info *hose);
-extern int polaris_hose_read_config_dword (u8, u8, u8, u32 *value,
-					 struct linux_hose_info *hose);
-extern int polaris_hose_write_config_byte (u8, u8, u8, u8 value,
-					 struct linux_hose_info *hose);
-extern int polaris_hose_write_config_word (u8, u8, u8, u16 value,
-					 struct linux_hose_info *hose);
-extern int polaris_hose_write_config_dword (u8, u8, u8, u32 value,
-					  struct linux_hose_info *hose);
+extern struct pci_ops polaris_pci_ops;
 extern void polaris_init_arch(unsigned long *, unsigned long *);
 extern void polaris_machine_check(u64, u64, struct pt_regs *);
 
 /* core_pyxis.c */
-extern int pyxis_hose_read_config_byte (u8, u8, u8, u8 *value,
-					struct linux_hose_info *hose);
-extern int pyxis_hose_read_config_word (u8, u8, u8, u16 *value,
-					struct linux_hose_info *hose);
-extern int pyxis_hose_read_config_dword (u8, u8, u8, u32 *value,
-					 struct linux_hose_info *hose);
-extern int pyxis_hose_write_config_byte (u8, u8, u8, u8 value,
-					 struct linux_hose_info *hose);
-extern int pyxis_hose_write_config_word (u8, u8, u8, u16 value,
-					 struct linux_hose_info *hose);
-extern int pyxis_hose_write_config_dword (u8, u8, u8, u32 value,
-					  struct linux_hose_info *hose);
-extern void pyxis_enable_errors (void);
-extern int pyxis_srm_window_setup (void);
-extern void pyxis_native_window_setup(void);
-extern void pyxis_finish_init_arch(void);
+extern struct pci_ops pyxis_pci_ops;
 extern void pyxis_init_arch(unsigned long *, unsigned long *);
 extern void pyxis_machine_check(u64, u64, struct pt_regs *);
 
 /* core_t2.c */
-extern int t2_hose_read_config_byte (u8, u8, u8, u8 *value,
-				     struct linux_hose_info *hose);
-extern int t2_hose_read_config_word (u8, u8, u8, u16 *value,
-				     struct linux_hose_info *hose);
-extern int t2_hose_read_config_dword (u8, u8, u8, u32 *value,
-				      struct linux_hose_info *hose);
-extern int t2_hose_write_config_byte (u8, u8, u8, u8 value,
-				      struct linux_hose_info *hose);
-extern int t2_hose_write_config_word (u8, u8, u8, u16 value,
-				      struct linux_hose_info *hose);
-extern int t2_hose_write_config_dword (u8, u8, u8, u32 value,
-				       struct linux_hose_info *hose);
+extern struct pci_ops t2_pci_ops;
 extern void t2_init_arch(unsigned long *, unsigned long *);
 extern void t2_machine_check(u64, u64, struct pt_regs *);
 
 /* core_tsunami.c */
-extern int tsunami_hose_read_config_byte (u8, u8, u8, u8 *value,
-					  struct linux_hose_info *hose);
-extern int tsunami_hose_read_config_word (u8, u8, u8, u16 *value,
-					  struct linux_hose_info *hose);
-extern int tsunami_hose_read_config_dword (u8, u8, u8, u32 *value,
-					   struct linux_hose_info *hose);
-extern int tsunami_hose_write_config_byte (u8, u8, u8, u8 value,
-					   struct linux_hose_info *hose);
-extern int tsunami_hose_write_config_word (u8, u8, u8, u16 value,
-					   struct linux_hose_info *hose);
-extern int tsunami_hose_write_config_dword (u8, u8, u8, u32 value,
-					    struct linux_hose_info *hose);
+extern struct pci_ops tsunami_pci_ops;
 extern void tsunami_init_arch(unsigned long *, unsigned long *);
 extern void tsunami_machine_check(u64, u64, struct pt_regs *);
 
@@ -155,14 +62,13 @@
 extern int smp_boot_cpuid;
 
 /* bios32.c */
-extern void reset_for_srm(void);
+/* extern void reset_for_srm(void); */
 
 /* time.c */
 extern void timer_interrupt(int irq, void *dev, struct pt_regs * regs);
 extern void rtc_init_pit(void);
-extern void generic_init_pit(void);
+extern void common_init_pit(void);
 extern unsigned long est_cycle_freq;
-extern struct resource timer_resource;
 
 /* smc37c93x.c */
 extern void SMC93x_Init(void);
@@ -173,6 +79,9 @@
 /* es1888.c */
 extern void es1888_init(void);
 
+/* ns87312.c */
+extern void ns87312_enable_ide(long ide_base);
+
 /* fpregs.c */
 extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
 extern unsigned long alpha_read_fp_reg (unsigned long reg);
@@ -193,13 +102,17 @@
 extern void entDbg(void);
 
 /* process.c */
-extern void generic_kill_arch (int mode, char *reboot_cmd);
+extern void common_kill_arch (int mode, char *reboot_cmd);
 extern void cpu_idle(void) __attribute__((noreturn));
 
 /* ptrace.c */
 extern int ptrace_set_bpt (struct task_struct *child);
 extern int ptrace_cancel_bpt (struct task_struct *child);
 
+/* traps.c */
+extern void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15);
+extern void die_if_kernel(char *, struct pt_regs *, long, unsigned long *);
+
 /* ../mm/init.c */
 void srm_paging_stop(void);
 
@@ -208,18 +121,18 @@
 #ifdef __SMP__
 #define mcheck_expected(cpu)	(cpu_data[cpu].mcheck_expected)
 #define mcheck_taken(cpu)	(cpu_data[cpu].mcheck_taken)
-#define mcheck_hose(cpu)	(cpu_data[cpu].mcheck_hose)
+#define mcheck_extra(cpu)	(cpu_data[cpu].mcheck_extra)
 #else
 extern struct mcheck_info
 {
 	unsigned char expected __attribute__((aligned(8)));
 	unsigned char taken;
-	unsigned char hose;
+	unsigned char extra;
 } __mcheck_info;
 
 #define mcheck_expected(cpu)	(__mcheck_info.expected)
 #define mcheck_taken(cpu)	(__mcheck_info.taken)
-#define mcheck_hose(cpu)	(__mcheck_info.hose)
+#define mcheck_extra(cpu)	(__mcheck_info.extra)
 #endif
 
 #define DEBUG_MCHECK 0          /* 0 = minimal, 1 = debug, 2 = debug+dump.  */
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v2.3.15/linux/arch/alpha/kernel/setup.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/setup.c	Tue Aug 31 10:50:44 1999
@@ -25,6 +25,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/string.h>
+#include <linux/ioport.h>
 
 #ifdef CONFIG_RTC
 #include <linux/timex.h>
@@ -39,16 +40,18 @@
 #include <asm/hwrpb.h>
 #include <asm/dma.h>
 #include <asm/io.h>
-
+#include <asm/pci.h>
 
 #include "proto.h"
+#include "pci_impl.h"
+
 
 struct hwrpb_struct *hwrpb;
 unsigned long srm_hae;
 
 #ifdef CONFIG_ALPHA_GENERIC
 struct alpha_machine_vector alpha_mv;
-int alpha_using_srm, alpha_use_srm_setup;
+int alpha_using_srm;
 #endif
 
 unsigned char aux_device_present = 0xaa;
@@ -90,6 +93,7 @@
 	orig_video_points: 16
 };
 
+
 /*
  * Declare all of the machine vectors.
  */
@@ -136,6 +140,47 @@
 
 #undef WEAK
 
+/*
+ * I/O resources inherited from PeeCees.  Except for perhaps the
+ * turbochannel alphas, everyone has these on some sort of SuperIO chip.
+ *
+ * ??? If this becomes less standard, move the struct out into the
+ * machine vector.
+ */
+
+static void __init
+reserve_std_resources(void)
+{
+	static struct resource standard_io_resources[] = {
+		{ "rtc", -1, -1 },
+        	{ "dma1", 0x00, 0x1f },
+        	{ "pic1", 0x20, 0x3f },
+        	{ "timer", 0x40, 0x5f },
+        	{ "keyboard", 0x60, 0x6f },
+        	{ "dma page reg", 0x80, 0x8f },
+        	{ "pic2", 0xa0, 0xbf },
+        	{ "dma2", 0xc0, 0xdf },
+	};
+
+	struct resource *io = &ioport_resource;
+	long i;
+
+	if (hose_head) {
+		struct pci_controler *hose;
+		for (hose = hose_head; hose; hose = hose->next)
+			if (hose->index == 0) {
+				io = hose->io_space;
+				break;
+			}
+	}
+
+	/* Fix up for the Jensen's queer RTC placement.  */
+	standard_io_resources[0].start = RTC_PORT(0);
+	standard_io_resources[0].end = RTC_PORT(0) + 0x10;
+
+	for (i = 0; i < N(standard_io_resources); ++i)
+		request_resource(io, standard_io_resources+i);
+}
 
 void __init
 setup_arch(char **cmdline_p, unsigned long * memory_start_p,
@@ -171,20 +216,10 @@
 	 */
 
 	for (p = strtok(command_line, " \t"); p ; p = strtok(NULL, " \t")) {
-#ifndef alpha_use_srm_setup
-		/* Allow a command-line option to respect the
-		   SRM's configuration.  */
-		if (strncmp(p, "srm_setup=", 10) == 0) {
-			alpha_use_srm_setup = (p[10] != '0');
-			continue;
-		}
-#endif
-
 		if (strncmp(p, "alpha_mv=", 9) == 0) {
 			vec = get_sysvec_byname(p+9);
 			continue;
 		}
-
 		if (strncmp(p, "cycle=", 6) == 0) {
 			est_cycle_freq = simple_strtol(p+6, NULL, 0);
 			continue;
@@ -270,6 +305,9 @@
 	   DMA windows and the like.  */
 	if (alpha_mv.init_arch)
 		alpha_mv.init_arch(memory_start_p, memory_end_p);
+
+	/* Reserve standard resources.  */
+	reserve_std_resources();
 
 	/* Initialize the timers.  */
 	/* ??? There is some circumstantial evidence that this needs
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- v2.3.15/linux/arch/alpha/kernel/smp.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/smp.c	Tue Aug 31 10:50:44 1999
@@ -30,7 +30,7 @@
 #include <asm/unistd.h>
 
 #include "proto.h"
-#include "irq.h"
+#include "irq_impl.h"
 
 
 #define DEBUG_SMP 0
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_alcor.c linux/arch/alpha/kernel/sys_alcor.c
--- v2.3.15/linux/arch/alpha/kernel/sys_alcor.c	Sun Sep  6 10:34:33 1998
+++ linux/arch/alpha/kernel/sys_alcor.c	Tue Aug 31 10:50:44 1999
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the ALCOR and XLT (XL-300/366/433).
  */
@@ -27,9 +27,9 @@
 #include <asm/core_cia.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 
 static void 
@@ -158,7 +158,7 @@
  */
 
 static int __init
-alcor_map_irq(struct pci_dev *dev, int slot, int pin)
+alcor_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[7][5] __initlocaldata = {
 		/*INT    INTA   INTB   INTC   INTD */
@@ -175,16 +175,8 @@
 	return COMMON_TABLE_LOOKUP;
 }
 
-static void __init
-alcor_pci_fixup(void)
-{
-	layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(alcor_map_irq, common_swizzle);
-}
-
-
 static void
-alcor_kill_arch (int mode, char *reboot_cmd)
+alcor_kill_arch(int mode, char *reboot_cmd)
 {
 	/* Who said DEC engineer's have no sense of humor? ;-)  */
 	if (alpha_using_srm) {
@@ -192,7 +184,7 @@
 		mb();
 	}
 
-	generic_kill_arch(mode, reboot_cmd);
+	common_kill_arch(mode, reboot_cmd);
 }
 
 
@@ -209,6 +201,8 @@
 	DO_CIA_BUS,
 	machine_check:		cia_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		EISA_DEFAULT_IO_BASE,
+	min_mem_address:	CIA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		48,
 	irq_probe_mask:		ALCOR_PROBE_MASK,
@@ -218,9 +212,11 @@
 
 	init_arch:		cia_init_arch,
 	init_irq:		alcor_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		alcor_pci_fixup,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
 	kill_arch:		alcor_kill_arch,
+	pci_map_irq:		alcor_map_irq,
+	pci_swizzle:		common_swizzle,
 
 	sys: { cia: {
 	    gru_int_req_bits:	ALCOR_GRU_INT_REQ_BITS
@@ -238,6 +234,8 @@
 	DO_CIA_BUS,
 	machine_check:		cia_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		EISA_DEFAULT_IO_BASE,
+	min_mem_address:	CIA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		48,
 	irq_probe_mask:		ALCOR_PROBE_MASK,
@@ -247,9 +245,11 @@
 
 	init_arch:		cia_init_arch,
 	init_irq:		alcor_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		alcor_pci_fixup,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
 	kill_arch:		alcor_kill_arch,
+	pci_map_irq:		alcor_map_irq,
+	pci_swizzle:		common_swizzle,
 
 	sys: { cia: {
 	    gru_int_req_bits:	XLT_GRU_INT_REQ_BITS
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_cabriolet.c linux/arch/alpha/kernel/sys_cabriolet.c
--- v2.3.15/linux/arch/alpha/kernel/sys_cabriolet.c	Sun Sep  6 10:34:33 1998
+++ linux/arch/alpha/kernel/sys_cabriolet.c	Tue Aug 31 10:50:44 1999
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the Cabriolet (AlphaPC64), EB66+, and EB164,
  * PC164 and LX164.
@@ -31,9 +31,9 @@
 #include <asm/core_pyxis.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 
 static void
@@ -124,7 +124,7 @@
  */
 
 static inline int __init
-eb66p_map_irq(struct pci_dev *dev, int slot, int pin)
+eb66p_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[5][5] __initlocaldata = {
 		/*INT  INTA  INTB  INTC   INTD */
@@ -138,14 +138,6 @@
 	return COMMON_TABLE_LOOKUP;
 }
 
-static inline void __init
-eb66p_pci_fixup(void)
-{
-	layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
-	common_pci_fixup(eb66p_map_irq, common_swizzle);
-	enable_ide(0x398);
-}
-
 
 /*
  * The AlphaPC64 is very similar to the EB66+ except that its slots
@@ -162,7 +154,7 @@
  */
 
 static inline int __init
-cabriolet_map_irq(struct pci_dev *dev, int slot, int pin)
+cabriolet_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[5][5] __initlocaldata = {
 		/*INT   INTA  INTB  INTC   INTD */
@@ -177,19 +169,10 @@
 }
 
 static inline void __init
-cabriolet_pci_fixup(void)
-{
-	layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
-	common_pci_fixup(cabriolet_map_irq, common_swizzle);
-	enable_ide(0x398);
-}
-
-static inline void __init
-eb164_pci_fixup(void)
+cabriolet_init_pci(void)
 {
-	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(cabriolet_map_irq, common_swizzle);
-	enable_ide(0x398);
+	common_init_pci();
+	ns87312_enable_ide(0x398);
 }
 
 
@@ -236,7 +219,7 @@
  */
 
 static inline int __init
-alphapc164_map_irq(struct pci_dev *dev, int slot, int pin)
+alphapc164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[7][5] __initlocaldata = {
 		/*INT   INTA  INTB   INTC   INTD */
@@ -253,13 +236,13 @@
 }
 
 static inline void __init
-alphapc164_pci_fixup(void)
+alphapc164_init_pci(void)
 {
-	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(alphapc164_map_irq, common_swizzle);
+	common_init_pci();
 	SMC93x_Init();
 }
 
+
 /*
  * The System Vector
  */
@@ -273,18 +256,22 @@
 	DO_APECS_BUS,
 	machine_check:		apecs_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	APECS_AND_LCA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		35,
 	irq_probe_mask:		_PROBE_MASK(35),
 	update_irq_hw:		cabriolet_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	cabriolet_device_interrupt,
 
 	init_arch:		apecs_init_arch,
 	init_irq:		cabriolet_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		cabriolet_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		cabriolet_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		cabriolet_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(cabriolet)
 #endif
@@ -298,18 +285,22 @@
 	DO_CIA_BUS,
 	machine_check:		cia_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	CIA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		35,
 	irq_probe_mask:		_PROBE_MASK(35),
 	update_irq_hw:		cabriolet_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	cabriolet_device_interrupt,
 
 	init_arch:		cia_init_arch,
 	init_irq:		cabriolet_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		eb164_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		cabriolet_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		cabriolet_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(eb164)
 #endif
@@ -323,18 +314,22 @@
 	DO_LCA_BUS,
 	machine_check:		lca_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	APECS_AND_LCA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		35,
 	irq_probe_mask:		_PROBE_MASK(35),
 	update_irq_hw:		cabriolet_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	cabriolet_device_interrupt,
 
 	init_arch:		lca_init_arch,
 	init_irq:		cabriolet_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		eb66p_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		cabriolet_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		eb66p_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(eb66p)
 #endif
@@ -348,18 +343,22 @@
 	DO_PYXIS_BUS,
 	machine_check:		pyxis_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	DEFAULT_MEM_BASE,
 
 	nr_irqs:		35,
 	irq_probe_mask:		_PROBE_MASK(35),
 	update_irq_hw:		cabriolet_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	cabriolet_device_interrupt,
 
 	init_arch:		pyxis_init_arch,
 	init_irq:		cabriolet_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		alphapc164_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		alphapc164_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		alphapc164_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(lx164)
 #endif
@@ -373,19 +372,22 @@
 	DO_CIA_BUS,
 	machine_check:		cia_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	CIA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		35,
 	irq_probe_mask:		_PROBE_MASK(35),
 	update_irq_hw:		cabriolet_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	cabriolet_device_interrupt,
 
 	init_arch:		cia_init_arch,
 	init_irq:		cabriolet_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		alphapc164_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		alphapc164_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		alphapc164_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(pc164)
 #endif
-
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_dp264.c linux/arch/alpha/kernel/sys_dp264.c
--- v2.3.15/linux/arch/alpha/kernel/sys_dp264.c	Mon Jul 12 07:49:36 1999
+++ linux/arch/alpha/kernel/sys_dp264.c	Tue Aug 31 10:50:44 1999
@@ -28,11 +28,10 @@
 #include <asm/hwrpb.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
-#define dev2hose(d) (bus2hose[(d)->bus->number]->pci_hose_index)
 
 /*
  * HACK ALERT! only the boot cpu is used for interrupts.
@@ -260,7 +259,7 @@
  */
 
 static int __init
-dp264_map_irq(struct pci_dev *dev, int slot, int pin)
+dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[6][5] __initlocaldata = {
 		/*INT    INTA   INTB   INTC   INTD */
@@ -272,16 +271,18 @@
 		{ 16+ 3, 16+ 3, 16+ 2, 16+ 1, 16+ 0}  /* IdSel 10 slot 3 */
 	};
 	const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5;
+
+	struct pci_controler *hose = dev->sysdata;
 	int irq = COMMON_TABLE_LOOKUP;
 
 	if (irq > 0)
-		irq += 16 * dev2hose(dev);
+		irq += 16 * hose->index;
 
 	return irq;
 }
 
 static int __init
-monet_map_irq(struct pci_dev *dev, int slot, int pin)
+monet_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[13][5] __initlocaldata = {
 		/*INT    INTA   INTB   INTC   INTD */
@@ -308,19 +309,23 @@
 	return COMMON_TABLE_LOOKUP;
 }
 
-static int __init
-monet_swizzle(struct pci_dev *dev, int *pinp)
+static u8 __init
+monet_swizzle(struct pci_dev *dev, u8 *pinp)
 {
+	struct pci_controler *hose = dev->sysdata;
 	int slot, pin = *pinp;
 
-	/* Check first for the built-in bridge on hose 1. */
-	if (dev2hose(dev) == 1 && PCI_SLOT(dev->bus->self->devfn) == 8) {
+	if (hose->first_busno == dev->bus->number) {
+		slot = PCI_SLOT(dev->devfn);
+	}
+	/* Check for the built-in bridge on hose 1. */
+	else if (hose->index == 1 && PCI_SLOT(dev->bus->self->devfn) == 8) {
 		slot = PCI_SLOT(dev->devfn);
 	} else {
 		/* Must be a card-based bridge.  */
 		do {
 			/* Check for built-in bridge on hose 1. */
-			if (dev2hose(dev) == 1 &&
+			if (hose->index == 1 &&
 			    PCI_SLOT(dev->bus->self->devfn) == 8) {
 				slot = PCI_SLOT(dev->devfn);
 				break;
@@ -338,7 +343,7 @@
 }
 
 static int __init
-webbrick_map_irq(struct pci_dev *dev, int slot, int pin)
+webbrick_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[13][5] __initlocaldata = {
 		/*INT    INTA   INTB   INTC   INTD */
@@ -359,7 +364,7 @@
 }
 
 static int __init
-clipper_map_irq(struct pci_dev *dev, int slot, int pin)
+clipper_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[7][5] __initlocaldata = {
 		/*INT    INTA   INTB   INTC   INTD */
@@ -372,46 +377,31 @@
 		{    -1,    -1,    -1,    -1,    -1}  /* IdSel 7 ISA Bridge */
 	};
 	const long min_idsel = 1, max_idsel = 7, irqs_per_slot = 5;
+
+	struct pci_controler *hose = dev->sysdata;
 	int irq = COMMON_TABLE_LOOKUP;
 
 	if (irq > 0)
-		irq += 16 * dev2hose(dev);
+		irq += 16 * hose->index;
 
 	return irq;
 }
 
 static void __init
-dp264_pci_fixup(void)
+dp264_init_pci(void)
 {
-	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(dp264_map_irq, common_swizzle);
+	common_init_pci();
 	SMC669_Init(0);
 }
 
 static void __init
-monet_pci_fixup(void)
+monet_init_pci(void)
 {
-	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(monet_map_irq, monet_swizzle);
+	common_init_pci();
 	SMC669_Init(1);
 	es1888_init();
 }
 
-static void __init
-webbrick_pci_fixup(void)
-{
-	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(webbrick_map_irq, common_swizzle);
-	SMC669_Init(0);
-}
-
-static void __init
-clipper_pci_fixup(void)
-{
-	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(clipper_map_irq, common_swizzle);
-}
-
 
 /*
  * The System Vectors
@@ -425,18 +415,22 @@
 	DO_TSUNAMI_BUS,
 	machine_check:		tsunami_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	DEFAULT_MEM_BASE,
 
 	nr_irqs:		64,
 	irq_probe_mask:		_PROBE_MASK(64),
 	update_irq_hw:		dp264_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	dp264_device_interrupt,
 
 	init_arch:		tsunami_init_arch,
 	init_irq:		dp264_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		dp264_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		dp264_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		dp264_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(dp264)
 
@@ -448,18 +442,22 @@
 	DO_TSUNAMI_BUS,
 	machine_check:		tsunami_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	DEFAULT_MEM_BASE,
 
 	nr_irqs:		64,
 	irq_probe_mask:		_PROBE_MASK(64),
 	update_irq_hw:		dp264_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	dp264_device_interrupt,
 
 	init_arch:		tsunami_init_arch,
 	init_irq:		dp264_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		monet_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		monet_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		monet_map_irq,
+	pci_swizzle:		monet_swizzle,
 };
 
 struct alpha_machine_vector webbrick_mv __initmv = {
@@ -470,18 +468,22 @@
 	DO_TSUNAMI_BUS,
 	machine_check:		tsunami_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	DEFAULT_MEM_BASE,
 
 	nr_irqs:		64,
 	irq_probe_mask:		_PROBE_MASK(64),
 	update_irq_hw:		dp264_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	dp264_device_interrupt,
 
 	init_arch:		tsunami_init_arch,
 	init_irq:		dp264_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		webbrick_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		dp264_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		webbrick_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 
 struct alpha_machine_vector clipper_mv __initmv = {
@@ -492,18 +494,22 @@
 	DO_TSUNAMI_BUS,
 	machine_check:		tsunami_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	DEFAULT_MEM_BASE,
 
 	nr_irqs:		64,
 	irq_probe_mask:		_PROBE_MASK(64),
 	update_irq_hw:		clipper_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	dp264_device_interrupt,
 
 	init_arch:		tsunami_init_arch,
 	init_irq:		clipper_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		clipper_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		clipper_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 
 /* No alpha_mv alias for webbrick/monet/clipper, since we compile them
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_eb64p.c linux/arch/alpha/kernel/sys_eb64p.c
--- v2.3.15/linux/arch/alpha/kernel/sys_eb64p.c	Sun Sep  6 10:34:33 1998
+++ linux/arch/alpha/kernel/sys_eb64p.c	Tue Aug 31 10:50:44 1999
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the EB64+ and EB66.
  */
@@ -28,9 +28,9 @@
 #include <asm/core_lca.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 
 static void
@@ -142,7 +142,7 @@
  */
 
 static int __init
-eb64p_map_irq(struct pci_dev *dev, int slot, int pin)
+eb64p_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[5][5] __initlocaldata = {
 		/*INT  INTA  INTB  INTC   INTD */
@@ -156,13 +156,6 @@
 	return COMMON_TABLE_LOOKUP;
 }
 
-static void __init
-eb64p_pci_fixup(void)
-{
-	layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
-	common_pci_fixup(eb64p_map_irq, common_swizzle);
-}
-
 
 /*
  * The System Vector
@@ -177,18 +170,22 @@
 	DO_APECS_BUS,
 	machine_check:		apecs_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	APECS_AND_LCA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		32,
 	irq_probe_mask:		_PROBE_MASK(32),
 	update_irq_hw:		eb64p_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	eb64p_device_interrupt,
 
 	init_arch:		apecs_init_arch,
 	init_irq:		eb64p_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		eb64p_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		eb64p_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(eb64p)
 #endif
@@ -202,18 +199,22 @@
 	DO_LCA_BUS,
 	machine_check:		lca_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	APECS_AND_LCA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		32,
 	irq_probe_mask:		_PROBE_MASK(32),
 	update_irq_hw:		eb64p_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	eb64p_device_interrupt,
 
 	init_arch:		lca_init_arch,
 	init_irq:		eb64p_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		eb64p_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		eb64p_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(eb66)
 #endif
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_jensen.c linux/arch/alpha/kernel/sys_jensen.c
--- v2.3.15/linux/arch/alpha/kernel/sys_jensen.c	Mon Oct 12 11:40:12 1998
+++ linux/arch/alpha/kernel/sys_jensen.c	Tue Aug 31 10:50:44 1999
@@ -2,7 +2,7 @@
  *	linux/arch/alpha/kernel/sys_jensen.c
  *
  *	Copyright (C) 1995 Linus Torvalds
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the Jensen.
  */
@@ -28,8 +28,8 @@
 #include <asm/pgtable.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "machvec_impl.h"
 
 
 static void
@@ -124,7 +124,7 @@
 struct alpha_machine_vector jensen_mv __initmv = {
 	vector_name:		"Jensen",
 	DO_EV4_MMU,
-	IO_LITE(JENSEN,jensen,jensen),
+	IO_LITE(JENSEN,jensen),
 	BUS(jensen),
 	machine_check:		jensen_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
@@ -133,12 +133,13 @@
 	nr_irqs:		16,
 	irq_probe_mask:		_PROBE_MASK(16),
 	update_irq_hw:		jensen_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	jensen_device_interrupt,
 
 	init_arch:		NULL,
 	init_irq:		jensen_init_irq,
-	init_pit:		generic_init_pit,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		NULL,
+	kill_arch:		common_kill_arch,
 };
 ALIAS_MV(jensen)
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_miata.c linux/arch/alpha/kernel/sys_miata.c
--- v2.3.15/linux/arch/alpha/kernel/sys_miata.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/sys_miata.c	Tue Aug 31 10:50:44 1999
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the MIATA (EV56+PYXIS).
  */
@@ -25,9 +25,9 @@
 #include <asm/core_pyxis.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 
 static void 
@@ -202,7 +202,7 @@
  */
 
 static int __init
-miata_map_irq(struct pci_dev *dev, int slot, int pin)
+miata_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
         static char irq_tab[18][5] __initlocaldata = {
 		/*INT    INTA   INTB   INTC   INTD */
@@ -224,21 +224,24 @@
 		{16+20, 16+20, 16+21, 16+22, 16+23},  /* IdSel 28,  slot 1  */
 		{16+24, 16+24, 16+25, 16+26, 16+27},  /* IdSel 29,  slot 2  */
 		{16+28, 16+28, 16+29, 16+30, 16+31},  /* IdSel 30,  slot 3  */
-		/* this bridge is on the main bus of the later original MIATA */
+		/* This bridge is on the main bus of the later orig MIATA */
 		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 31,  PCI-PCI */
         };
 	const long min_idsel = 3, max_idsel = 20, irqs_per_slot = 5;
 	return COMMON_TABLE_LOOKUP;
 }
 
-static int __init
-miata_swizzle(struct pci_dev *dev, int *pinp)
+static u8 __init
+miata_swizzle(struct pci_dev *dev, u8 *pinp)
 {
 	int slot, pin = *pinp;
 
-	/* Check first for the built-in bridge.  */
-	if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
-	    (PCI_SLOT(dev->bus->self->devfn) == 20)) {
+	if (dev->bus->number == 0) {
+		slot = PCI_SLOT(dev->devfn);
+	}		
+	/* Check for the built-in bridge.  */
+	else if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
+		 (PCI_SLOT(dev->bus->self->devfn) == 20)) {
 		slot = PCI_SLOT(dev->devfn) + 9;
 	}
 	else 
@@ -263,10 +266,9 @@
 }
 
 static void __init
-miata_pci_fixup(void)
+miata_init_pci(void)
 {
-	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(miata_map_irq, miata_swizzle);
+	common_init_pci();
 	SMC669_Init(0); /* it might be a GL (fails harmlessly if not) */
 	es1888_init();
 }
@@ -279,7 +281,7 @@
 		*(vuip) PYXIS_RESET = 0x0000dead;
 		mb();
 	}
-	generic_kill_arch(mode, reboot_cmd);
+	common_kill_arch(mode, reboot_cmd);
 }
 
 
@@ -295,17 +297,21 @@
 	DO_PYXIS_BUS,
 	machine_check:		pyxis_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	DEFAULT_MEM_BASE,
 
 	nr_irqs:		48,
 	irq_probe_mask:		_PROBE_MASK(48),
 	update_irq_hw:		miata_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	miata_device_interrupt,
 
 	init_arch:		pyxis_init_arch,
 	init_irq:		miata_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		miata_pci_fixup,
+	init_pit:		common_init_pit,
+	init_pci:		miata_init_pci,
 	kill_arch:		miata_kill_arch,
+	pci_map_irq:		miata_map_irq,
+	pci_swizzle:		miata_swizzle,
 };
 ALIAS_MV(miata)
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_mikasa.c linux/arch/alpha/kernel/sys_mikasa.c
--- v2.3.15/linux/arch/alpha/kernel/sys_mikasa.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/sys_mikasa.c	Tue Aug 31 10:50:44 1999
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the MIKASA (AlphaServer 1000).
  */
@@ -28,9 +28,9 @@
 #include <asm/core_cia.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 static void
 mikasa_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
@@ -120,7 +120,7 @@
  */
 
 static int __init
-mikasa_map_irq(struct pci_dev *dev, int slot, int pin)
+mikasa_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[8][5] __initlocaldata = {
 		/*INT    INTA   INTB   INTC   INTD */
@@ -137,19 +137,6 @@
 	return COMMON_TABLE_LOOKUP;
 }
 
-static void __init
-mikasa_pci_fixup(void)
-{
-	layout_all_busses(EISA_DEFAULT_IO_BASE,APECS_AND_LCA_DEFAULT_MEM_BASE);
-	common_pci_fixup(mikasa_map_irq, common_swizzle);
-}
-
-static void __init
-mikasa_primo_pci_fixup(void)
-{
-	layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(mikasa_map_irq, common_swizzle);
-}
 
 #if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
 static void
@@ -180,6 +167,7 @@
 }
 #endif
 
+
 /*
  * The System Vector
  */
@@ -193,18 +181,22 @@
 	DO_APECS_BUS,
 	machine_check:		mikasa_apecs_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	APECS_AND_LCA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		32,
 	irq_probe_mask:		_PROBE_MASK(32),
 	update_irq_hw:		mikasa_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	mikasa_device_interrupt,
 
 	init_arch:		apecs_init_arch,
 	init_irq:		mikasa_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		mikasa_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		mikasa_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(mikasa)
 #endif
@@ -218,18 +210,22 @@
 	DO_CIA_BUS,
 	machine_check:		cia_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	CIA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		32,
 	irq_probe_mask:		_PROBE_MASK(32),
 	update_irq_hw:		mikasa_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	mikasa_device_interrupt,
 
 	init_arch:		cia_init_arch,
 	init_irq:		mikasa_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		mikasa_primo_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		mikasa_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(mikasa_primo)
 #endif
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_noritake.c linux/arch/alpha/kernel/sys_noritake.c
--- v2.3.15/linux/arch/alpha/kernel/sys_noritake.c	Sun Sep  6 10:34:33 1998
+++ linux/arch/alpha/kernel/sys_noritake.c	Tue Aug 31 10:50:44 1999
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the NORITAKE (AlphaServer 1000A), 
  * CORELLE (AlphaServer 800), and ALCOR Primo (AlphaStation 600A).
@@ -29,9 +29,9 @@
 #include <asm/core_cia.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 
 static void 
@@ -168,7 +168,7 @@
  */
 
 static int __init
-noritake_map_irq(struct pci_dev *dev, int slot, int pin)
+noritake_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[15][5] __initlocaldata = {
 		/*INT    INTA   INTB   INTC   INTD */
@@ -195,13 +195,16 @@
 	return COMMON_TABLE_LOOKUP;
 }
 
-static int __init
-noritake_swizzle(struct pci_dev *dev, int *pinp)
+static u8 __init
+noritake_swizzle(struct pci_dev *dev, u8 *pinp)
 {
 	int slot, pin = *pinp;
 
-	/* Check first for the built-in bridge */
-	if (PCI_SLOT(dev->bus->self->devfn) == 8) {
+	if (dev->bus->number == 0) {
+		slot = PCI_SLOT(dev->devfn);
+	}
+	/* Check for the built-in bridge */
+	else if (PCI_SLOT(dev->bus->self->devfn) == 8) {
 		slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */
 	}
 	else
@@ -224,20 +227,6 @@
 	return slot;
 }
 
-static void __init
-noritake_pci_fixup(void)
-{
-	layout_all_busses(EISA_DEFAULT_IO_BASE,APECS_AND_LCA_DEFAULT_MEM_BASE);
-	common_pci_fixup(noritake_map_irq, noritake_swizzle);
-}
-
-static void __init
-noritake_primo_pci_fixup(void)
-{
-	layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(noritake_map_irq, noritake_swizzle);
-}
-
 
 /*
  * The System Vectors
@@ -252,18 +241,22 @@
 	DO_APECS_BUS,
 	machine_check:		apecs_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		EISA_DEFAULT_IO_BASE,
+	min_mem_address:	APECS_AND_LCA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		48,
 	irq_probe_mask:		_PROBE_MASK(48),
 	update_irq_hw:		noritake_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	noritake_device_interrupt,
 
 	init_arch:		apecs_init_arch,
 	init_irq:		noritake_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		noritake_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		noritake_map_irq,
+	pci_swizzle:		noritake_swizzle,
 };
 ALIAS_MV(noritake)
 #endif
@@ -277,18 +270,22 @@
 	DO_CIA_BUS,
 	machine_check:		cia_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		EISA_DEFAULT_IO_BASE,
+	min_mem_address:	CIA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		48,
 	irq_probe_mask:		_PROBE_MASK(48),
 	update_irq_hw:		noritake_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	noritake_device_interrupt,
 
 	init_arch:		cia_init_arch,
 	init_irq:		noritake_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		noritake_primo_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		noritake_map_irq,
+	pci_swizzle:		noritake_swizzle,
 };
 ALIAS_MV(noritake_primo)
 #endif
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_rawhide.c linux/arch/alpha/kernel/sys_rawhide.c
--- v2.3.15/linux/arch/alpha/kernel/sys_rawhide.c	Sun Jan 10 09:59:59 1999
+++ linux/arch/alpha/kernel/sys_rawhide.c	Tue Aug 31 10:50:44 1999
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the RAWHIDE.
  */
@@ -24,11 +24,12 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/core_mcpcia.h>
+#include <asm/pci.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 
 static void
@@ -36,19 +37,19 @@
 {
 	if (irq >= 40) {
 		/* PCI bus 1 with builtin NCR810 SCSI */
-		*(vuip)MCPCIA_INT_MASK0(1) =
+		*(vuip)MCPCIA_INT_MASK0(5) =
 			(~((mask) >> 40) & 0x00ffffffU) | 0x00fe0000U;
 		mb();
 		/* ... and read it back to make sure it got written.  */
-	  	*(vuip)MCPCIA_INT_MASK0(1);
+	  	*(vuip)MCPCIA_INT_MASK0(5);
 	}
 	else if (irq >= 16) {
 		/* PCI bus 0 with EISA bridge */
-		*(vuip)MCPCIA_INT_MASK0(0) =
+		*(vuip)MCPCIA_INT_MASK0(4) =
 			(~((mask) >> 16) & 0x00ffffffU) | 0x00ff0000U;
 		mb();
 		/* ... and read it back to make sure it got written.  */
-	  	*(vuip)MCPCIA_INT_MASK0(0);
+	  	*(vuip)MCPCIA_INT_MASK0(4);
 	}
 	else if (irq >= 8)
 		outb(mask >> 8, 0xA1);	/* ISA PIC2 */
@@ -63,6 +64,10 @@
 
 	ack = irq = (vector - 0x800) >> 4;
 
+	/* ??? A 4 bus RAWHIDE has 67 interrupts.  Oops.  We need
+	   something wider than one word for our own internal
+	   manipulations.  */
+
         /*
          * The RAWHIDE SRM console reports PCI interrupts with a vector
 	 * 0x80 *higher* than one might expect, as PCI IRQ 0 (ie bit 0)
@@ -90,17 +95,17 @@
 	STANDARD_INIT_IRQ_PROLOG;
 
 	/* HACK ALERT! only PCI busses 0 and 1 are used currently,
-	   and routing is only to CPU #1*/
+	   (MIDs 4 and 5 respectively) and routing is only to CPU #1*/
 
-	*(vuip)MCPCIA_INT_MASK0(0) =
+	*(vuip)MCPCIA_INT_MASK0(4) =
 		(~((alpha_irq_mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb();
 	/* ... and read it back to make sure it got written.  */
-	*(vuip)MCPCIA_INT_MASK0(0);
+	*(vuip)MCPCIA_INT_MASK0(4);
 
-	*(vuip)MCPCIA_INT_MASK0(1) =
+	*(vuip)MCPCIA_INT_MASK0(5) =
 		(~((alpha_irq_mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb();
 	/* ... and read it back to make sure it got written.  */
-	*(vuip)MCPCIA_INT_MASK0(1);
+	*(vuip)MCPCIA_INT_MASK0(5);
 
 	enable_irq(2);
 }
@@ -139,7 +144,7 @@
  */
 
 static int __init
-rawhide_map_irq(struct pci_dev *dev, int slot, int pin)
+rawhide_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[5][5] __initlocaldata = {
 		/*INT    INTA   INTB   INTC   INTD */
@@ -150,19 +155,14 @@
 		{ 16+12, 16+12, 16+13, 16+14, 16+15}  /* IdSel 5 slot 5 */
 	};
 	const long min_idsel = 1, max_idsel = 5, irqs_per_slot = 5;
+
+	struct pci_controler *hose = dev->sysdata;
 	int irq = COMMON_TABLE_LOOKUP;
 	if (irq >= 0)
-		irq += 24 * bus2hose[dev->bus->number]->pci_hose_index;
+		irq += 24 * hose->index;
 	return irq;
 }
 
-static void __init
-rawhide_pci_fixup(void)
-{
-	layout_all_busses(DEFAULT_IO_BASE, RAWHIDE_DEFAULT_MEM_BASE);
-	common_pci_fixup(rawhide_map_irq, common_swizzle);
-}
-
 
 /*
  * The System Vector
@@ -176,17 +176,21 @@
 	DO_MCPCIA_BUS,
 	machine_check:		mcpcia_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	MCPCIA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		64,
 	irq_probe_mask:		_PROBE_MASK(64),
 	update_irq_hw:		rawhide_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	rawhide_srm_device_interrupt,
 
 	init_arch:		mcpcia_init_arch,
 	init_irq:		rawhide_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		rawhide_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		rawhide_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(rawhide)
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_ruffian.c linux/arch/alpha/kernel/sys_ruffian.c
--- v2.3.15/linux/arch/alpha/kernel/sys_ruffian.c	Tue Aug  3 08:20:45 1999
+++ linux/arch/alpha/kernel/sys_ruffian.c	Tue Aug 31 10:50:44 1999
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the RUFFIAN.
  */
@@ -26,9 +26,9 @@
 #include <asm/core_pyxis.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 static void
 ruffian_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
@@ -164,18 +164,6 @@
 }
 
 
-/*
- * For RUFFIAN, we do not want to make any modifications to the PCI
- * setup.  But we may need to do some kind of init.
- */
-
-static void __init
-ruffian_pci_fixup(void)
-{
-	/* layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); */
-}
-
-
 #ifdef BUILDING_FOR_MILO
 /*
  * The DeskStation Ruffian motherboard firmware does not place
@@ -215,31 +203,9 @@
 }
 #endif /* BUILDING_FOR_MILO */
 
-static void __init
-ruffian_init_arch(unsigned long *mem_start, unsigned long *mem_end)
-{
-	/* FIXME: What do we do with ruffian_get_bank_size above?  */
-
-#if 1
-	pyxis_init_arch(mem_start, mem_end);
-#else
-	pyxis_enable_errors();
-	if (!pyxis_srm_window_setup()) {
-		printk("ruffian_init_arch: Skipping window register rewrites."
-		       "\n... Trust DeskStation firmware!\n");
-	}
-	pyxis_finish_init_arch();
-#endif
-}
-
 static void
 ruffian_init_pit (void)
 {
-	/* Ruffian depends on the system timer established in MILO! */
-        timer_resource.start = 0x70;
-        timer_resource.end = 0x70 + 0x10;
-        request_resource(&ioport_resource, &timer_resource);
-
 	outb(0xb6, 0x43);       /* pit counter 2: speaker */
 	outb(0x31, 0x42);
 	outb(0x13, 0x42);
@@ -254,7 +220,15 @@
 	*(vuip) PYXIS_RESET = 0x0000dead;
 	mb();
 #endif
-	generic_kill_arch(mode, reboot_cmd);
+	common_kill_arch(mode, reboot_cmd);
+}
+
+static int __init
+ruffian_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	/* We don't know anything about the PCI routing, so leave
+	   the IRQ unchanged.  */
+	return dev->irq;
 }
 
 
@@ -266,11 +240,12 @@
 	vector_name:		"Ruffian",
 	DO_EV5_MMU,
 	DO_DEFAULT_RTC,
-	/* For the moment, do not use BWIO on RUFFIAN.  */
-	IO(PYXIS,pyxis,pyxis),
+	DO_PYXIS_IO,
 	DO_PYXIS_BUS,
 	machine_check:		pyxis_machine_check,
 	max_dma_address:	ALPHA_RUFFIAN_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	DEFAULT_MEM_BASE,
 
 	nr_irqs:		48,
 	irq_probe_mask:		RUFFIAN_PROBE_MASK,
@@ -278,10 +253,12 @@
 	ack_irq:		ruffian_ack_irq,
 	device_interrupt:	ruffian_device_interrupt,
 
-	init_arch:		ruffian_init_arch,
+	init_arch:		pyxis_init_arch,
 	init_irq:		ruffian_init_irq,
 	init_pit:		ruffian_init_pit,
-	pci_fixup:		ruffian_pci_fixup,
+	init_pci:		common_init_pci,
 	kill_arch:		ruffian_kill_arch,
+	pci_map_irq:		ruffian_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(ruffian)
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_rx164.c linux/arch/alpha/kernel/sys_rx164.c
--- v2.3.15/linux/arch/alpha/kernel/sys_rx164.c	Fri Aug 13 11:53:50 1999
+++ linux/arch/alpha/kernel/sys_rx164.c	Tue Aug 31 10:50:44 1999
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the RX164 (PCA56+POLARIS).
  */
@@ -26,9 +26,9 @@
 #include <asm/core_polaris.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 
 static void
@@ -138,6 +138,8 @@
         enable_irq(16 + 20);    /* enable ISA interrupts */
 	enable_irq(2);		/* enable cascade */
 }
+
+
 /* The RX164 changed its interrupt routing between pass1 and pass2...
  *
  * PASS1:
@@ -171,7 +173,7 @@
  */
 
 static int __init
-rx164_map_irq(struct pci_dev *dev, int slot, int pin)
+rx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 #if 0
         char irq_tab_pass1[6][5] = {
@@ -183,7 +185,7 @@
           { 16+2, 16+2, 16+7, 16+12, 16+17},      /* IdSel 9,  slot 3 */
           { 16+1, 16+1, 16+6, 16+11, 16+16},      /* IdSel 10, slot 4 */
         };
-#endif
+#else
         char irq_tab[6][5] = {
           /*INT   INTA  INTB  INTC   INTD */
           { 16+0, 16+0, 16+6, 16+11, 16+16},      /* IdSel 5,  slot 0 */
@@ -193,20 +195,14 @@
           { 16+3, 16+3, 16+9, 16+14, 16+19},      /* IdSel 9,  slot 3 */
           { 16+4, 16+4, 16+10, 16+15, 16+5},      /* IdSel 10, PCI-PCI */
         };
+#endif
 	const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5;
+
         /* JRP - Need to figure out how to distinguish pass1 from pass2,
-         * and use the correct table...
-         */
+	   and use the correct table.  */
 	return COMMON_TABLE_LOOKUP;
 }
 
-void __init
-rx164_pci_fixup(void)
-{
-	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(rx164_map_irq, common_swizzle);
-}
-
 
 /*
  * The System Vector
@@ -220,17 +216,21 @@
 	DO_POLARIS_BUS,
 	machine_check:		polaris_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	DEFAULT_MEM_BASE,
 
 	nr_irqs:		40,
 	irq_probe_mask:		_PROBE_MASK(40),
 	update_irq_hw:		rx164_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	rx164_device_interrupt,
 
 	init_arch:		polaris_init_arch,
 	init_irq:		rx164_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		rx164_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		rx164_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(rx164)
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_sable.c linux/arch/alpha/kernel/sys_sable.c
--- v2.3.15/linux/arch/alpha/kernel/sys_sable.c	Sun Sep  6 10:34:33 1998
+++ linux/arch/alpha/kernel/sys_sable.c	Tue Aug 31 10:50:44 1999
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the Sable and Sable-Gamma systems.
  */
@@ -26,9 +26,9 @@
 #include <asm/core_t2.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 
 /*
@@ -198,7 +198,7 @@
  */
 
 static int __init
-sable_map_irq(struct pci_dev *dev, int slot, int pin)
+sable_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
         static char irq_tab[9][5] __initlocaldata = {
 		/*INT    INTA   INTB   INTC   INTD */
@@ -216,13 +216,6 @@
 	return COMMON_TABLE_LOOKUP;
 }
 
-void __init
-sable_pci_fixup(void)
-{
-	layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-        common_pci_fixup(sable_map_irq, common_swizzle);
-}
-
 
 /*
  * The System Vectors
@@ -242,6 +235,8 @@
 	DO_T2_BUS,
 	machine_check:		t2_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		EISA_DEFAULT_IO_BASE,
+	min_mem_address:	DEFAULT_MEM_BASE,
 
 	nr_irqs:		40,
 	irq_probe_mask:		_PROBE_MASK(40),
@@ -251,9 +246,11 @@
 
 	init_arch:		t2_init_arch,
 	init_irq:		sable_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		sable_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		sable_map_irq,
+	pci_swizzle:		common_swizzle,
 
 	sys: { t2: {
 	    gamma_bias:		0
@@ -273,6 +270,8 @@
 	DO_T2_BUS,
 	machine_check:		t2_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		EISA_DEFAULT_IO_BASE,
+	min_mem_address:	DEFAULT_MEM_BASE,
 
 	nr_irqs:		40,
 	irq_probe_mask:		_PROBE_MASK(40),
@@ -282,9 +281,11 @@
 
 	init_arch:		t2_init_arch,
 	init_irq:		sable_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		sable_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		common_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		sable_map_irq,
+	pci_swizzle:		common_swizzle,
 
 	sys: { t2: {
 	    gamma_bias:		_GAMMA_BIAS
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_sio.c linux/arch/alpha/kernel/sys_sio.c
--- v2.3.15/linux/arch/alpha/kernel/sys_sio.c	Thu Jan 21 11:26:30 1999
+++ linux/arch/alpha/kernel/sys_sio.c	Tue Aug 31 10:50:44 1999
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code for all boards that route the PCI interrupts through the SIO
  * PCI/ISA bridge.  This includes Noname (AXPpci33), Multia (UDB),
@@ -28,11 +28,12 @@
 #include <asm/pgtable.h>
 #include <asm/core_apecs.h>
 #include <asm/core_lca.h>
+#include <asm/pci.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 static void
 sio_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
@@ -57,6 +58,8 @@
 static inline void __init
 xl_init_arch(unsigned long *mem_start, unsigned long *mem_end)
 {
+	struct pci_controler *hose;
+
 	/*
 	 * Set up the PCI->physical memory translation windows.  For
 	 * the XL we *must* use both windows, in order to maximize the
@@ -86,6 +89,16 @@
 	 */
 
 	*(vuip)APECS_IOC_HAXR2 = 0; mb();
+
+	/*
+	 * Create our single hose.
+	 */
+
+	hose = alloc_pci_controler(mem_start);
+	hose->io_space = &ioport_resource;
+	hose->mem_space = &iomem_resource;
+	hose->config_space = LCA_CONF;
+	hose->index = 0;
 }
 
 static inline void __init
@@ -114,26 +127,12 @@
  * This is NOT how we should do it. PIRQ0-X should have
  * their own IRQ's, the way intel uses the IO-APIC irq's.
  */
-static unsigned long sio_route_tab __initdata = 0;
 
 static void __init
-sio_pci_fixup(int (*map_irq)(struct pci_dev *dev, int sel, int pin),
-	      unsigned long new_route_tab)
+sio_pci_route(void)
 {
-	unsigned int route_tab;
-
-	/* Examine or update the PCI routing table.  */
-        pcibios_read_config_dword(0, PCI_DEVFN(7, 0), 0x60, &route_tab);
-
-	sio_route_tab = route_tab; 
-	if (PCI_MODIFY) {
-		sio_route_tab = new_route_tab;
-		pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60,
-					   new_route_tab);
-	}
-
-	/* Update all the IRQs.  */
-	common_pci_fixup(map_irq, common_swizzle);
+	pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60,
+				   alpha_mv.sys.sio.route_tab);
 }
 
 static unsigned int __init
@@ -180,7 +179,7 @@
 }
 
 static inline int __init
-noname_map_irq(struct pci_dev *dev, int slot, int pin)
+noname_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	/*
 	 * The Noname board has 5 PCI slots with each of the 4
@@ -214,49 +213,12 @@
 	};
 	const long min_idsel = 6, max_idsel = 14, irqs_per_slot = 5;
 	int irq = COMMON_TABLE_LOOKUP, tmp;
-	tmp = __kernel_extbl(sio_route_tab, irq);
+	tmp = __kernel_extbl(alpha_mv.sys.sio.route_tab, irq);
 	return irq >= 0 ? tmp : -1;
 }
 
-static inline void __init
-noname_pci_fixup(void)
-{
-	/*
-	 * For UDB, the only available PCI slot must not map to IRQ 9,
-	 * since that's the builtin MSS sound chip. That PCI slot
-	 * will map to PIRQ1 (for INTA at least), so we give it IRQ 15
-	 * instead.
-	 *
-	 * Unfortunately we have to do this for NONAME as well, since
-	 * they are co-indicated when the platform type "Noname" is
-	 * selected... :-(
-	 */
-	layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
-	sio_pci_fixup(noname_map_irq, 0x0b0a0f0d);
-	sio_fixup_irq_levels(sio_collect_irq_levels());
-        enable_ide(0x26e);
-}
-
-static inline void __init
-avanti_pci_fixup(void)
-{
-	layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
-	sio_pci_fixup(noname_map_irq, 0x0b0a0e0f);
-	sio_fixup_irq_levels(sio_collect_irq_levels());
-        enable_ide(0x26e);
-}
-
-static inline void __init
-xl_pci_fixup(void)
-{
-	layout_all_busses(DEFAULT_IO_BASE, XL_DEFAULT_MEM_BASE);
-	sio_pci_fixup(noname_map_irq, 0x0b0a090f);
-	sio_fixup_irq_levels(sio_collect_irq_levels());
-        enable_ide(0x26e);
-}
-
 static inline int __init
-p2k_map_irq(struct pci_dev *dev, int slot, int pin)
+p2k_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[][5] __initlocaldata = {
 		/*INT A   B   C   D */
@@ -270,29 +232,27 @@
 	};
 	const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5;
 	int irq = COMMON_TABLE_LOOKUP, tmp;
-	tmp = __kernel_extbl(sio_route_tab, irq);
+	tmp = __kernel_extbl(alpha_mv.sys.sio.route_tab, irq);
 	return irq >= 0 ? tmp : -1;
 }
 
 static inline void __init
-p2k_pci_fixup(void)
+noname_init_pci(void)
 {
-	layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
-	sio_pci_fixup(p2k_map_irq, 0x0b0a090f);
+	sio_pci_route();
+	common_init_pci();
 	sio_fixup_irq_levels(sio_collect_irq_levels());
-        enable_ide(0x26e);
+	ns87312_enable_ide(0x26e);
 }
 
 static inline void __init
-alphabook1_pci_fixup(void)
+alphabook1_init_pci(void)
 {
 	struct pci_dev *dev;
 	unsigned char orig, config;
 
-	layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
-
-        /* For the AlphaBook1, NCR810 SCSI is 14, PCMCIA controller is 15. */
-	sio_pci_fixup(noname_map_irq, 0x0e0f0a0a);
+	sio_pci_route();
+	common_init_pci();
 
 	/*
 	 * On the AlphaBook1, the PCMCIA chip (Cirrus 6729)
@@ -304,20 +264,17 @@
 	 * moment (2.0.29), ncr53c8xx.c does NOT do this, but
 	 * 53c7,8xx.c DOES.
 	 */
-	for (dev = pci_devices; dev; dev = dev->next) {
-                if (dev->vendor == PCI_VENDOR_ID_NCR &&
-                    (dev->device == PCI_DEVICE_ID_NCR_53C810 ||
-                     dev->device == PCI_DEVICE_ID_NCR_53C815 ||
-                     dev->device == PCI_DEVICE_ID_NCR_53C820 ||
-                     dev->device == PCI_DEVICE_ID_NCR_53C825)) {
-			unsigned int io_port;
+
+	dev = NULL;
+	while ((dev = pci_find_device(PCI_VENDOR_ID_NCR, PCI_ANY_ID, dev))) {
+                if (dev->device == PCI_DEVICE_ID_NCR_53C810
+		    || dev->device == PCI_DEVICE_ID_NCR_53C815
+		    || dev->device == PCI_DEVICE_ID_NCR_53C820
+		    || dev->device == PCI_DEVICE_ID_NCR_53C825) {
+			unsigned long io_port;
 			unsigned char ctest4;
 
-			pcibios_read_config_dword(dev->bus->number,
-						  dev->devfn,
-						  PCI_BASE_ADDRESS_0,
-						  &io_port);
-			io_port &= PCI_BASE_ADDRESS_IO_MASK;
+			io_port = dev->resource[0].start;
 			ctest4 = inb(io_port+0x21);
 			if (!(ctest4 & 0x80)) {
 				printk("AlphaBook1 NCR init: setting"
@@ -356,18 +313,27 @@
 	DO_LCA_BUS,
 	machine_check:		lca_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	APECS_AND_LCA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		16,
 	irq_probe_mask:		_PROBE_MASK(16),
 	update_irq_hw:		sio_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	isa_device_interrupt,
 
 	init_arch:		alphabook1_init_arch,
 	init_irq:		sio_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		alphabook1_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		alphabook1_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		noname_map_irq,
+	pci_swizzle:		common_swizzle,
+
+	sys: { sio: {
+		/* NCR810 SCSI is 14, PCMCIA controller is 15.  */
+		route_tab:	0x0e0f0a0a,
+	}}
 };
 ALIAS_MV(alphabook1)
 #endif
@@ -381,18 +347,26 @@
 	DO_APECS_BUS,
 	machine_check:		apecs_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	APECS_AND_LCA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		16,
 	irq_probe_mask:		_PROBE_MASK(16),
 	update_irq_hw:		sio_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	isa_device_interrupt,
 
 	init_arch:		apecs_init_arch,
 	init_irq:		sio_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		avanti_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		noname_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		noname_map_irq,
+	pci_swizzle:		common_swizzle,
+
+	sys: { sio: {
+		route_tab:	0x0b0a0e0f,
+	}}
 };
 ALIAS_MV(avanti)
 #endif
@@ -406,18 +380,35 @@
 	DO_LCA_BUS,
 	machine_check:		lca_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	APECS_AND_LCA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		16,
 	irq_probe_mask:		_PROBE_MASK(16),
 	update_irq_hw:		sio_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	srm_device_interrupt,
 
 	init_arch:		lca_init_arch,
 	init_irq:		sio_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		noname_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		noname_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		noname_map_irq,
+	pci_swizzle:		common_swizzle,
+
+	sys: { sio: {
+		/* For UDB, the only available PCI slot must not map to IRQ 9,
+		   since that's the builtin MSS sound chip. That PCI slot
+		   will map to PIRQ1 (for INTA at least), so we give it IRQ 15
+		   instead.
+
+		   Unfortunately we have to do this for NONAME as well, since
+		   they are co-indicated when the platform type "Noname" is
+		   selected... :-(  */
+
+		route_tab:	0x0b0a0f0d,
+	}}
 };
 ALIAS_MV(noname)
 #endif
@@ -431,18 +422,26 @@
 	DO_LCA_BUS,
 	machine_check:		lca_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	APECS_AND_LCA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		16,
 	irq_probe_mask:		P2K_PROBE_MASK,
 	update_irq_hw:		sio_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	srm_device_interrupt,
 
 	init_arch:		lca_init_arch,
 	init_irq:		sio_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		p2k_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		noname_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		p2k_map_irq,
+	pci_swizzle:		common_swizzle,
+
+	sys: { sio: {
+		route_tab:	0x0b0a090f,
+	}}
 };
 ALIAS_MV(p2k)
 #endif
@@ -456,18 +455,26 @@
 	BUS(apecs_xl),
 	machine_check:		apecs_machine_check,
 	max_dma_address:	ALPHA_XL_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	XL_DEFAULT_MEM_BASE,
 
 	nr_irqs:		16,
 	irq_probe_mask:		_PROBE_MASK(16),
 	update_irq_hw:		sio_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	isa_device_interrupt,
 
 	init_arch:		xl_init_arch,
 	init_irq:		sio_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		xl_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		noname_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		noname_map_irq,
+	pci_swizzle:		common_swizzle,
+
+	sys: { sio: {
+		route_tab:	0x0b0a090f,
+	}}
 };
 ALIAS_MV(xl)
 #endif
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_sx164.c linux/arch/alpha/kernel/sys_sx164.c
--- v2.3.15/linux/arch/alpha/kernel/sys_sx164.c	Sun Feb 21 19:06:36 1999
+++ linux/arch/alpha/kernel/sys_sx164.c	Tue Aug 31 10:50:44 1999
@@ -3,7 +3,7 @@
  *
  *	Copyright (C) 1995 David A Rusling
  *	Copyright (C) 1996 Jay A Estabrook
- *	Copyright (C) 1998 Richard Henderson
+ *	Copyright (C) 1998, 1999 Richard Henderson
  *
  * Code supporting the SX164 (PCA56+PYXIS).
  */
@@ -26,9 +26,9 @@
 #include <asm/core_pyxis.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 
 static void
@@ -164,7 +164,7 @@
  */
 
 static int __init
-sx164_map_irq(struct pci_dev *dev, int slot, int pin)
+sx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[5][5] __initlocaldata = {
 		/*INT    INTA   INTB   INTC   INTD */
@@ -179,10 +179,9 @@
 }
 
 void __init
-sx164_pci_fixup(void)
+sx164_init_pci(void)
 {
-	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(sx164_map_irq, common_swizzle);
+	common_init_pci();
 	SMC669_Init(0);
 }
 
@@ -199,17 +198,21 @@
 	DO_PYXIS_BUS,
 	machine_check:		pyxis_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	DEFAULT_MEM_BASE,
 
 	nr_irqs:		40,
 	irq_probe_mask:		_PROBE_MASK(40),
 	update_irq_hw:		sx164_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	sx164_device_interrupt,
 
 	init_arch:		pyxis_init_arch,
 	init_irq:		sx164_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		sx164_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		sx164_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		sx164_map_irq,
+	pci_swizzle:		common_swizzle,
 };
 ALIAS_MV(sx164)
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/sys_takara.c linux/arch/alpha/kernel/sys_takara.c
--- v2.3.15/linux/arch/alpha/kernel/sys_takara.c	Tue Jun 22 10:46:52 1999
+++ linux/arch/alpha/kernel/sys_takara.c	Tue Aug 31 10:50:44 1999
@@ -25,9 +25,9 @@
 #include <asm/core_cia.h>
 
 #include "proto.h"
-#include "irq.h"
-#include "bios32.h"
-#include "machvec.h"
+#include "irq_impl.h"
+#include "pci_impl.h"
+#include "machvec_impl.h"
 
 
 static void 
@@ -127,7 +127,7 @@
  */
 
 static int __init
-takara_map_irq(struct pci_dev *dev, int slot, int pin)
+takara_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	static char irq_tab[15][5] __initlocaldata = {
 		{ 16+3, 16+3, 16+3, 16+3, 16+3},   /* slot  6 == device 3 */
@@ -150,16 +150,18 @@
 	return COMMON_TABLE_LOOKUP;
 }
 
-static int __init
-takara_swizzle(struct pci_dev *dev, int *pinp)
+static u8 __init
+takara_swizzle(struct pci_dev *dev, u8 *pinp)
 {
 	int slot = PCI_SLOT(dev->devfn);
 	int pin = *pinp;
 	unsigned int ctlreg = inl(0x500);
 	unsigned int busslot = PCI_SLOT(dev->bus->self->devfn);
 
-	/* Check first for built-in bridges.  */
-	if (busslot > 16 && ((1<<(36-busslot)) & ctlreg)) {
+	/* Check for built-in bridges.  */
+	if (dev->bus->number != 0
+	    && busslot > 16
+	    && ((1<<(36-busslot)) & ctlreg)) {
 		if (pin == 1)
 			pin += (20 - busslot);
 		else {
@@ -174,11 +176,10 @@
 }
 
 static void __init
-takara_pci_fixup(void)
+takara_init_pci(void)
 {
-	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
-	common_pci_fixup(takara_map_irq, takara_swizzle);
-	/* enable_ide(0x26e); */
+	common_init_pci();
+	/* ns87312_enable_ide(0x26e); */
 }
 
 
@@ -194,17 +195,21 @@
 	DO_CIA_BUS,
 	machine_check:		cia_machine_check,
 	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,
+	min_io_address:		DEFAULT_IO_BASE,
+	min_mem_address:	CIA_DEFAULT_MEM_BASE,
 
 	nr_irqs:		20,
 	irq_probe_mask:		_PROBE_MASK(20),
 	update_irq_hw:		takara_update_irq_hw,
-	ack_irq:		generic_ack_irq,
+	ack_irq:		common_ack_irq,
 	device_interrupt:	takara_device_interrupt,
 
 	init_arch:		cia_init_arch,
 	init_irq:		takara_init_irq,
-	init_pit:		generic_init_pit,
-	pci_fixup:		takara_pci_fixup,
-	kill_arch:		generic_kill_arch,
+	init_pit:		common_init_pit,
+	init_pci:		takara_init_pci,
+	kill_arch:		common_kill_arch,
+	pci_map_irq:		takara_map_irq,
+	pci_swizzle:		takara_swizzle,
 };
 ALIAS_MV(takara)
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c
--- v2.3.15/linux/arch/alpha/kernel/time.c	Thu Jul 29 13:37:22 1999
+++ linux/arch/alpha/kernel/time.c	Tue Aug 31 10:50:44 1999
@@ -40,19 +40,13 @@
 #include <linux/timex.h>
 
 #include "proto.h"
-#include "irq.h"
+#include "irq_impl.h"
 
 extern rwlock_t xtime_lock;
 extern volatile unsigned long lost_ticks;	/* kernel/sched.c */
 
 static int set_rtc_mmss(unsigned long);
 
-#ifdef CONFIG_RTC
-struct resource timer_resource = { "pit", 0x40, 0x40+0x20 };
-#else
-struct resource timer_resource = { "rtc", 0, 0 };
-#endif
-
 
 /*
  * Shift amount by which scaled_ticks_per_cycle is scaled.  Shifting
@@ -190,8 +184,6 @@
 	CMOS_WRITE(control, RTC_CONTROL);
 	(void) CMOS_READ(RTC_INTR_FLAGS);
 
-	request_resource(&ioport_resource, &timer_resource);
-
 	/* Setup interval timer.  */
 	outb(0x34, 0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
 	outb(LATCH & 0xff, 0x40);	/* LSB */
@@ -204,7 +196,7 @@
 #endif
 
 void
-generic_init_pit (void)
+common_init_pit (void)
 {
 	unsigned char x;
 
@@ -225,10 +217,6 @@
 	}
 	(void) CMOS_READ(RTC_INTR_FLAGS);
 
-	timer_resource.start = RTC_PORT(0);
-	timer_resource.end = RTC_PORT(0) + 0x10;
-	request_resource(&ioport_resource, &timer_resource);
-
 	outb(0x36, 0x43);	/* pit counter 0: system timer */
 	outb(0x00, 0x40);
 	outb(0x00, 0x40);
@@ -331,7 +319,7 @@
 
 	/* setup timer */ 
 	irq_handler = timer_interrupt;
-	if (request_irq(TIMER_IRQ, irq_handler, 0, timer_resource.name, NULL))
+	if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL))
 		panic("Could not allocate timer IRQ!");
 }
 
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v2.3.15/linux/arch/alpha/kernel/traps.c	Thu Jul 29 13:37:22 1999
+++ linux/arch/alpha/kernel/traps.c	Tue Aug 31 10:50:44 1999
@@ -22,7 +22,7 @@
 
 #include "proto.h"
 
-static void
+void
 dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
 {
 	printk("pc = [<%016lx>]  ra = [<%016lx>]  ps = %04lx\n",
diff -u --recursive --new-file v2.3.15/linux/arch/alpha/vmlinux.lds linux/arch/alpha/vmlinux.lds
--- v2.3.15/linux/arch/alpha/vmlinux.lds	Wed Aug  4 15:48:00 1999
+++ linux/arch/alpha/vmlinux.lds	Tue Aug 31 10:50:44 1999
@@ -59,4 +59,27 @@
   .mdebug 0 : { *(.mdebug) }
   .note 0 : { *(.note) }
   .comment 0 : { *(.comment) }
+
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
 }
diff -u --recursive --new-file v2.3.15/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- v2.3.15/linux/arch/arm/Makefile	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/Makefile	Mon Aug 30 18:14:55 1999
@@ -12,21 +12,52 @@
 #
 # Copyright (C) 1995-1999 by Russell King
 
-CFLAGS_PROC		:=
-ASFLAGS_PROC		:=
-
 # GCC 2.7 uses different options to later compilers; sort out which we have
 CONFIG_GCC_NEW		:= $(shell if $(CC) --version 2>&1 | grep '^2\.7' > /dev/null; then echo n; else echo y; fi)
 
-# Hack to get around RiscPC with StrongARM optimistaion
-# problem - force ARM710 optimisation for now.
+# See if this is ld "2.9.4" or later
+NEW_LINKER		:= $(shell if $(LD) --gc-sections --version >/dev/null 2>&1; then echo y; else echo n; fi)
+
+# CFLAGS_PROC - processor dependent CFLAGS
+# PROCESSOR   - processor type
+# TEXTADDR    - Uncompressed kernel link text address
+# ZTEXTADDR   - Compressed kernel link text address
+# ZRELADDR    - Compressed kernel relocating address
+#	        (point at which uncompressed kernel is loaded).
+
+#
+# select flags depending on the compiler
+#
 ifeq ($(CONFIG_GCC_NEW),y)
-  ifeq ($(CONFIG_ARCH_RPC),y)
-    ifeq ($(CONFIG_CPU_SA110),y)
-      CONFIG_CPU_SA110	:= n
-      CONFIG_CPU_ARM7	:= y
-    endif
-  endif
+  CFLAGS_PROC		:= -mshort-load-bytes -msoft-float
+  CFLAGS_PROC_CPU_26	:= -mcpu=arm3 -Os
+  CFLAGS_PROC_CPU_32v3	:= -march=armv3
+  CFLAGS_PROC_CPU_32v4	:= -march=armv4
+  CFLAGS_ARM6		:= -mtune=arm6
+  CFLAGS_ARM7		:= -mtune=arm7
+  CFLAGS_SA110		:= -mtune=strongarm110
+else
+  CFLAGS_PROC		:=
+  CFLAGS_PROC_CPU_26	:= -m3
+  CFLAGS_PROC_CPU_32v3	:=
+  CFLAGS_PROC_CPU_32v4	:=
+  CFLAGS_ARM6		:= -m6
+  CFLAGS_ARM7		:= -m6
+  CFLAGS_SA110		:= -m6
+endif
+
+ifeq ($(NEW_LINKER),y)
+  ASFLAGS_PROC		:= -mno-fpu
+  ASFLAGS_PROC_CPU_26	:= -mapcs-26
+  ASFLAGS_PROC_CPU_32v3	:= -mapcs-32 -marmv3m
+  ASFLAGS_PROC_CPU_32v4	:= -mapcs-32 -marmv4t
+  LINKFLAGS		:= -p
+else
+  ASFLAGS_PROC		:=
+  ASFLAGS_PROC_CPU_26	:= -m3
+  ASFLAGS_PROC_CPU_32v3	:= -m6
+  ASFLAGS_PROC_CPU_32v4	:= -m6
+  LINKFLAGS		:=
 endif
 
 ifeq ($(CONFIG_CPU_26),y)
@@ -34,56 +65,36 @@
   TEXTADDR		 = 0x02080000
   ZTEXTADDR		 = 0x01800000
   ZRELADDR		 = 0x02080000
-  ifeq ($(CONFIG_GCC_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
+  CFLAGS_PROC		+= $(CFLAGS_PROC_CPU_26)
+  ASFLAGS_PROC		+= $(ASFLAGS_PROC_CPU_26)
 endif
 
 ifeq ($(CONFIG_CPU_32),y)
   PROCESSOR		 = armv
   TEXTADDR		 = 0xC0008000
-  ifeq ($(CONFIG_GCC_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
+  ifeq ($(CONFIG_CPU_32v4),y)
+    CFLAGS_PROC		+= $(CFLAGS_PROC_CPU_32v4)
+    ASFLAGS_PROC	+= $(ASFLAGS_PROC_CPU_32v4)
+  else
+    CFLAGS_PROC		+= $(CFLAGS_PROC_CPU_32v3)
+    ASFLAGS_PROC	+= $(ASFLAGS_PROC_CPU_32v3)
+  endif
+  #
+  # Exactly one of the following must be selected
+  #
+  ifeq ($(CONFIG_CPU_ARM6),y)
+    CFLAGS_PROC		+= $(CFLAGS_ARM6)
+  else
+  ifeq ($(CONFIG_CPU_ARM7),y)
+    CFLAGS_PROC		+= $(CFLAGS_ARM7)
   else
-    CFLAGS_PROC		+= -m6
+  ifeq ($(CONFIG_CPU_SA110),y)
+    CFLAGS_PROC		+= $(CFLAGS_SA110)
+  endif
+  endif
   endif
-  ASFLAGS_PROC		+= -m6
 endif
 
-# Processor Architecture
-# CFLAGS_PROC - processor dependent CFLAGS
-# PROCESSOR   - processor type
-# TEXTADDR    - Uncompressed kernel link text address
-# ZTEXTADDR   - Compressed kernel link text address
-# ZRELADDR    - Compressed kernel relocating address
-#	        (point at which uncompressed kernel is loaded).
-#
 
 COMPRESSED_HEAD	 = head.o
 
@@ -131,6 +142,8 @@
 COMPRESSED_HEAD	 = head-nexuspci.o
 endif
 
+
+
 PERL		 = perl
 LD		 = $(CROSS_COMPILE)ld
 OBJCOPY		 = $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
@@ -144,7 +157,7 @@
 endif
 CFLAGS		:= $(CFLAGS_PROC) $(CFLAGS) -pipe
 ASFLAGS		:= $(ASFLAGS_PROC) $(ASFLAGS)
-LINKFLAGS	 = -T $(TOPDIR)/arch/arm/vmlinux-$(PROCESSOR).lds -e stext -Ttext $(TEXTADDR)
+LINKFLAGS	+= -X -T $(TOPDIR)/arch/arm/vmlinux-$(PROCESSOR).lds -e stext
 ZLINKFLAGS	 = -Ttext $(ZTEXTADDR)
 
 # If we're intending to debug the kernel, make sure it has line number
@@ -175,12 +188,31 @@
 DRIVERS		+= arch/arm/nwfpe/math-emu.a
 endif
 
-MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+MAKEBOOT	 = $(MAKE) -C arch/$(ARCH)/boot
+
+# The following is a hack to get 'constants.h' up
+# to date before starting compilation
+CONSTANTS	:= constants
+
+constants: dummy
+	@$(MAKE) -C arch/arm/lib constants.h
 
-symlinks::
+symlinks: archsymlinks
+
+archsymlinks:
 	$(RM) include/asm-arm/arch include/asm-arm/proc
 	(cd include/asm-arm; ln -sf arch-$(ARCHDIR) arch; ln -sf proc-$(PROCESSOR) proc)
 
+# We need to rebuild the linker script
+# each time, in case the architecture has
+# changed.
+.PHONY: arch/arm/vmlinux-$(PROCESSOR).lds
+
+vmlinux: arch/arm/vmlinux-$(PROCESSOR).lds
+
+arch/arm/vmlinux-$(PROCESSOR).lds: $(TOPDIR)/arch/arm/vmlinux-$(PROCESSOR).lds.in
+	@sed 's/TEXTADDR/$(TEXTADDR)/' <$< >$@
+
 arch/arm/kernel: dummy
 	$(MAKE) linuxsubdirs SUBDIRS=arch/arm/kernel
 
@@ -197,6 +229,7 @@
 archmrproper:
 	rm -f include/asm-arm/arch include/asm-arm/proc
 	@$(MAKE) -C arch/$(ARCH)/special mrproper
+	rm -f $(TOPDIR)/arch/arm/vmlinux-*.lds
 
 archclean:
 	@$(MAKEBOOT) clean
diff -u --recursive --new-file v2.3.15/linux/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile
--- v2.3.15/linux/arch/arm/boot/compressed/Makefile	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/boot/compressed/Makefile	Mon Aug 30 18:14:55 1999
@@ -17,6 +17,13 @@
 OBJS	+= ll_char_wr.o font.o
 endif
 
+ifeq ($(NEW_LINKER),y)
+BINFMT	:= elf32-littlearm
+else
+BINFMT	:= elf32-arm
+endif
+
+
 all:		vmlinux
 
 vmlinux:	$(OBJS) piggy.o
@@ -31,7 +38,7 @@
 		$(OBJCOPY) $(SYSTEM) $$tmppiggy; \
 		gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \
 		echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \
-		$(LD) -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-arm -T $$tmppiggy.lnk; \
+		$(LD) -r -o piggy.o -b binary $$tmppiggy.gz -b $(BINFMT) -T $$tmppiggy.lnk; \
 		rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk;
 
 font.o:		$(FONTC)
diff -u --recursive --new-file v2.3.15/linux/arch/arm/config.in linux/arch/arm/config.in
--- v2.3.15/linux/arch/arm/config.in	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/config.in	Mon Aug 30 18:14:55 1999
@@ -17,7 +17,7 @@
 	 FootBridge-based	CONFIG_FOOTBRIDGE" RiscPC
 
 if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
-  bool 'FootBridge in HOST mode'	CONFIG_HOST_FOOTBRIDGE
+  bool 'FootBridge in HOST mode' CONFIG_HOST_FOOTBRIDGE
   if [ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then
     define_bool CONFIG_ADDIN_FOOTBRIDGE n
   else
@@ -37,8 +37,10 @@
   define_bool CONFIG_ARCH_CO285 y
 fi
 
+#
 # Select various configuration options depending on the machine type
 #  Easy check for Acorn-style architectures
+#
 if [ "$CONFIG_ARCH_ARC" = "y" -o \
      "$CONFIG_ARCH_A5K" = "y" -o \
      "$CONFIG_ARCH_RPC" = "y" ]; then
@@ -47,17 +49,53 @@
   define_bool CONFIG_ARCH_ACORN n
 fi
 
-#if [ "$CONFIG_ARCH_TBOX" = "y" ]; then
-#  define_bool CONFIG_BUS_I2C y
-#fi
+#
+# 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_ARC" = "y" -o \
+     "$CONFIG_ARCH_A5K" = "y" ]; then
+  define_bool CONFIG_CPU_32 n
+  define_bool CONFIG_CPU_26 y
 
+  #
+  # Select memory size
+  #
+  bool '2MB physical memory' CONFIG_PAGESIZE_16
+else
+  define_bool CONFIG_CPU_32 y
+  define_bool CONFIG_CPU_26 n
+
+  #
+  # Select CPU and optimisation dependent on architecture
+  #
+  if [ "$CONFIG_ARCH_EBSA110" = "y" -o \
+       "$CONFIG_FOOTBRIDGE" = "y" -o \
+       "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then
+    define_bool CONFIG_CPU_32v4 y
+    define_bool CONFIG_CPU_SA110 y
+  else
+  if [ "$CONFIG_ARCH_RPC" = "y" ]; then
+    define_bool CONFIG_CPU_32v3 y
+    bool 'Support ARM610' CONFIG_CPU_ARM6
+    bool 'Support ARM710' CONFIG_CPU_ARM7
+    bool 'Support StrongARM110' CONFIG_CPU_SA110
+  fi
+  fi
+fi
+
+#
 #  These machines always have PCI
+#
 if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o \
      "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then
   define_bool CONFIG_PCI y
 fi
 
+#
 # These machines have ISA-DMA
+#
 if [ "$CONFIG_CATS" = "y" -o \
      "$CONFIG_ARCH_NETWINDER" = "y" ]; then
   define_bool CONFIG_ISA_DMA y
@@ -65,34 +103,6 @@
   define_bool CONFIG_ISA_DMA n
 fi
 
-# 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_ARC" = "y" -o \
-     "$CONFIG_ARCH_A5K" = "y" ]; then
-  define_bool CONFIG_CPU_32 n
-  define_bool CONFIG_CPU_26 y
-else
-  define_bool CONFIG_CPU_32 y
-  define_bool CONFIG_CPU_26 n
-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" 4MB+
-fi
 endmenu
 
 mainmenu_option next_comment
@@ -101,7 +111,7 @@
 if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then
   bool 'Enable kernel-mode alignment trap handler (EXPERIMENTAL)' CONFIG_ALIGNMENT_TRAP
 fi
-bool 'Split text into discardable sections' CONFIG_TEXT_SECTIONS
+#bool 'Split text into discardable sections' CONFIG_TEXT_SECTIONS
 endmenu
 
 mainmenu_option next_comment
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile
--- v2.3.15/linux/arch/arm/kernel/Makefile	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/kernel/Makefile	Mon Aug 30 18:14:55 1999
@@ -9,8 +9,8 @@
 ENTRY_OBJ = entry-$(PROCESSOR).o
 
 O_TARGET := kernel.o
-O_OBJS   := $(ENTRY_OBJ) irq.o process.o ptrace.o setup.o \
-	    signal.o sys_arm.o time.o traps.o
+O_OBJS   := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o \
+	    semaphore.o setup.o signal.o sys_arm.o time.o traps.o
 
 ifeq ($(CONFIG_ISA_DMA),y)
   ISA_DMA_OBJS += dma-isa.o
@@ -30,7 +30,7 @@
 OX_OBJS_footbridge= dma.o hw-footbridge.o
 OX_OBJS_nexuspci  =
 
-all: lib kernel.o $(HEAD_OBJ) init_task.o
+all: kernel.o $(HEAD_OBJ) init_task.o
 
 O_OBJS += $(O_OBJS_$(MACHINE))
 
@@ -48,7 +48,7 @@
   endif
 else
   ifdef CONFIG_PCI
-    O_OBJS += dec21285.o
+    O_OBJS += bios32.o dec21285.o
   endif
 endif
 
@@ -79,11 +79,6 @@
 include $(TOPDIR)/Rules.make
 
 $(ENTRY_OBJ): ../lib/constants.h
-
-.PHONY: lib
-
-lib:
-	$(MAKE) -C ../lib constants.h
 
 # Spell out some dependencies that `make dep' doesn't spot
 entry-armv.o: calls.S
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c
--- v2.3.15/linux/arch/arm/kernel/armksyms.c	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/kernel/armksyms.c	Mon Aug 30 18:14:55 1999
@@ -12,6 +12,7 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/pgtable.h>
+#include <asm/proc-fns.h>
 #include <asm/semaphore.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -25,9 +26,6 @@
 extern unsigned int local_bh_count[NR_CPUS];
 extern unsigned int local_irq_count[NR_CPUS];
 
-extern void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
-extern void iounmap(void *addr);
-
 extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
 
 /*
@@ -36,7 +34,6 @@
 extern int sys_write(int, const char *, int);
 extern int sys_read(int, char *, int);
 extern int sys_lseek(int, off_t, int);
-extern int sys_open(const char *, int, int);
 extern int sys_exit(int);
 extern int sys_wait4(int, int *, int, struct rusage *);
 
@@ -93,7 +90,7 @@
 EXPORT_SYMBOL(local_irq_count);
 #ifdef CONFIG_CPU_32
 EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(__iounmap);
 #endif
 EXPORT_SYMBOL(kernel_thread);
 
@@ -101,11 +98,28 @@
 EXPORT_SYMBOL(disable_irq);
 
 	/* processor dependencies */
+#ifdef MULTI_CPU
 EXPORT_SYMBOL(processor);
+#else
+EXPORT_SYMBOL(cpu_flush_cache_all);
+EXPORT_SYMBOL(cpu_flush_cache_area);
+EXPORT_SYMBOL(cpu_flush_cache_entry);
+EXPORT_SYMBOL(cpu_clean_cache_area);
+EXPORT_SYMBOL(cpu_flush_ram_page);
+EXPORT_SYMBOL(cpu_flush_tlb_all);
+EXPORT_SYMBOL(cpu_flush_tlb_area);
+EXPORT_SYMBOL(cpu_switch_mm);
+EXPORT_SYMBOL(cpu_set_pmd);
+EXPORT_SYMBOL(cpu_set_pte);
+EXPORT_SYMBOL(cpu_flush_icache_area);
+EXPORT_SYMBOL(cpu_cache_wback_area);
+EXPORT_SYMBOL(cpu_cache_purge_area);
+#endif
 EXPORT_SYMBOL(__machine_arch_type);
 
 	/* networking */
 EXPORT_SYMBOL(csum_partial_copy);
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
 EXPORT_SYMBOL(__csum_ipv6_magic);
 
 	/* io */
@@ -150,6 +164,7 @@
 EXPORT_SYMBOL_NOVERS(strpbrk);
 EXPORT_SYMBOL_NOVERS(strtok);
 EXPORT_SYMBOL_NOVERS(strrchr);
+EXPORT_SYMBOL_NOVERS(strstr);
 EXPORT_SYMBOL_NOVERS(memset);
 EXPORT_SYMBOL_NOVERS(memcpy);
 EXPORT_SYMBOL_NOVERS(memmove);
@@ -198,9 +213,8 @@
 EXPORT_SYMBOL(find_next_zero_bit);
 
 	/* elf */
-EXPORT_SYMBOL(armidlist);
-EXPORT_SYMBOL(armidindex);
 EXPORT_SYMBOL(elf_platform);
+EXPORT_SYMBOL(elf_hwcap);
 
 	/* syscalls */
 EXPORT_SYMBOL(sys_write);
@@ -213,5 +227,5 @@
 	/* semaphores */
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_interruptible_failed);
+EXPORT_SYMBOL_NOVERS(__down_trylock_failed);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
-
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c
--- v2.3.15/linux/arch/arm/kernel/bios32.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/kernel/bios32.c	Mon Aug 30 18:14:55 1999
@@ -0,0 +1,352 @@
+/*
+ * arch/arm/kernel/bios32.c
+ *
+ * PCI bios-type initialisation for PCI machines
+ *
+ * Bits taken from various places.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/system.h>
+
+int have_isa_bridge;
+
+int (*pci_irq_fixup)(struct pci_dev *dev);
+
+extern struct pci_ops *dc21285_init(int pass);
+extern void pcibios_fixup_ebsa285(struct pci_dev *dev);
+extern void hw_init(void);
+
+void
+pcibios_report_device_errors(void)
+{
+	struct pci_dev *dev;
+
+	for (dev = pci_devices; dev; dev = dev->next) {
+		u16 status;
+
+		pci_read_config_word(dev, PCI_STATUS, &status);
+
+		if (status & 0xf900) {
+			pci_write_config_word(dev, PCI_STATUS, status & 0xf900);
+			printk(KERN_DEBUG "PCI: %02x:%02x status = %X\n",
+				dev->bus->number, dev->devfn, status);
+		}
+	}
+}
+
+/*
+ * We don't use this to fix the device, but more our initialisation.
+ * It's not the correct use for this, but it works.  The actions we
+ * take are:
+ * - enable only IO
+ * - set memory region to start at zero
+ * - (0x48) enable all memory requests from ISA to be channeled to PCI
+ * - (0x42) disable ping-pong (as per errata)
+ * - (0x40) enable PCI packet retry
+ * - (0x83) don't use CPU park enable, park on last master, disable GAT bit
+ * - (0x80) default rotating priorities
+ * - (0x81) rotate bank 4
+ */
+static void __init pci_fixup_83c553(struct pci_dev *dev)
+{
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_SPACE_MEMORY);
+	pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO);
+
+	dev->resource[0].end -= dev->resource[0].start;
+	dev->resource[0].start = 0;
+
+	pci_write_config_byte(dev, 0x48, 0xff);
+	pci_write_config_byte(dev, 0x42, 0x00);
+	pci_write_config_byte(dev, 0x40, 0x22);
+	pci_write_config_byte(dev, 0x83, 0x02);
+	pci_write_config_byte(dev, 0x80, 0xe0);
+	pci_write_config_byte(dev, 0x81, 0x01);
+}
+
+struct pci_fixup pcibios_fixups[] = {
+	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, pci_fixup_83c553 },
+	{ 0 }
+};
+
+/*
+ * Assign an address to an I/O range.
+ */
+static void __init pcibios_fixup_io_addr(struct pci_dev *dev, struct resource *r, int idx)
+{
+	unsigned int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
+	unsigned int size = r->end - r->start + 1;
+	u32 try;
+
+	/*
+	 * We need to avoid collisions with `mirrored' VGA ports and other strange
+	 * ISA hardware, so we always want the addresses kilobyte aligned.
+	 */
+	if (!size || size > 256) {
+		printk(KERN_ERR "PCI: Cannot assign I/O space to %s, "
+		       "%d bytes are too much.\n", dev->name, size);
+		return;
+	}
+
+	if (allocate_resource(&ioport_resource, r, size, 0x9000, ~0, 1024)) {
+		printk(KERN_ERR "PCI: Unable to find free %d bytes of I/O "
+			"space for %s.\n", size, dev->name);
+		return;
+	}
+
+	printk("PCI: Assigning I/O space %04lx-%04lx to %s\n",
+		r->start, r->end, dev->name);
+
+	pci_write_config_dword(dev, reg, r->start | PCI_BASE_ADDRESS_SPACE_IO);
+	pci_read_config_dword(dev, reg, &try);
+
+	if ((try & PCI_BASE_ADDRESS_IO_MASK) != r->start) {
+		r->start = 0;
+		pci_write_config_dword(dev, reg, 0);
+		printk(KERN_ERR "PCI: I/O address setup failed, got %04x\n", try);
+	}
+}
+
+/*
+ * Assign an address to an memory range.
+ */
+static void __init pcibios_fixup_mem_addr(struct pci_dev *dev, struct resource *r, int idx)
+{
+	unsigned int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
+	unsigned int size = r->end - r->start + 1;
+	u32 try;
+
+	if (!size) {
+		printk(KERN_ERR "PCI: Cannot assign memory space to %s, "
+		       "%d bytes are too much.\n", dev->name, size);
+		return;
+	}
+
+	if (allocate_resource(&iomem_resource, r, size,
+			      0x00100000, 0x0fffffff, 1024)) {
+		printk(KERN_ERR "PCI: Unable to find free %d bytes of memory "
+			"space for %s.\n", size, dev->name);
+		return;
+	}
+
+	printk("PCI: Assigning memory space %08lx-%08lx to %s\n",
+		r->start, r->end, dev->name);
+
+	pci_write_config_dword(dev, reg, r->start);
+	pci_read_config_dword(dev, reg, &try);
+
+	if (try != r->start) {
+		r->start = 0;
+		pci_write_config_dword(dev, reg, 0);
+		printk(KERN_ERR "PCI: memory address setup failed, "
+		       "got %08x\n", try);
+	}
+}
+
+#define _PCI_REGION_IO	1
+#define _PCI_REGION_MEM	2
+
+/*
+ * Fix up one PCI devices regions, enables and interrupt lines
+ */
+static void __init pcibios_fixup_device(struct pci_dev *dev, u16 *cmd)
+{
+	int i, has_regions = 0;
+
+	/*
+	 * Fix up the regions.  Any regions which aren't allocated
+	 * are given a free region.
+	 */
+	for (i = 0; i < 6; i++) {
+		struct resource *r = dev->resource + i;
+
+		if (r->flags & IORESOURCE_IO) {
+			has_regions |= _PCI_REGION_IO;
+
+			if (!r->start || r->end == 0xffffffff)
+				pcibios_fixup_io_addr(dev, r, i);
+		} else if (r->end) {
+			has_regions |= _PCI_REGION_MEM;
+
+			if (!r->start)
+				pcibios_fixup_mem_addr(dev, r, i);
+		}
+	}
+
+	switch (dev->class >> 8) {
+	case PCI_CLASS_BRIDGE_ISA:
+	case PCI_CLASS_BRIDGE_EISA:
+		/*
+		 * If this device is an ISA bridge, set the have_isa_bridge
+		 * flag.  We will then go looking for things like keyboard,
+		 * etc
+		 */
+		have_isa_bridge = !0;
+		/* FALL THROUGH */
+
+	default:
+		/*
+		 * Don't enable VGA-compatible cards since they have
+		 * fixed I/O and memory space.
+		 *
+		 * Don't enabled disabled IDE interfaces either because
+		 * some BIOSes may reallocate the same address when they
+		 * find that no devices are attached. 
+		 */
+		if (has_regions & _PCI_REGION_IO &&
+		    !((*cmd) & PCI_COMMAND_IO)) {
+			printk("PCI: Enabling I/O for %s\n", dev->name);
+			*cmd |= PCI_COMMAND_IO;
+		}
+
+		if (has_regions & _PCI_REGION_MEM &&
+		    !((*cmd) & PCI_COMMAND_MEMORY)) {
+			printk("PCI: Enabling memory for %s\n", dev->name);
+			*cmd |= PCI_COMMAND_MEMORY;
+		}
+	}
+}
+
+/*
+ * Fix base addresses, I/O and memory enables and IRQ's
+ */
+static void __init pcibios_fixup_devices(void)
+{
+	struct pci_dev *dev;
+
+	for (dev = pci_devices; dev; dev = dev->next) {
+		u16 cmd;
+
+		/*
+		 * architecture specific hacks.
+		 * I don't really want this here,
+		 * but I don't see any other place
+		 * for it to live.
+		 */
+		if (machine_is_netwinder() &&
+		    dev->vendor == PCI_VENDOR_ID_DEC &&
+		    dev->device == PCI_DEVICE_ID_DEC_21142)
+			/* Put the chip to sleep in case the driver isn't loaded */
+			pci_write_config_dword(dev, 0x40, 0x80000000);
+
+		/*
+		 * Set latency timer to 32, and a cache line size to 32 bytes.
+		 * Also, set system error enable, parity error enable, and
+		 * fast back to back transaction enable.  Disable ROM.
+		 */
+		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32);
+		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8);
+		pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+
+		cmd |= PCI_COMMAND_FAST_BACK | PCI_COMMAND_SERR |
+		       PCI_COMMAND_PARITY;
+
+		pcibios_fixup_device(dev, &cmd);
+
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+
+		/*
+		 * now fixup the IRQs, if required
+		 */
+		if (pci_irq_fixup)
+			dev->irq = pci_irq_fixup(dev);
+
+		/*
+		 * If any remaining IRQs are weird, fix it now.
+		 */
+		if (dev->irq >= NR_IRQS)
+			dev->irq = 0;
+
+		/*
+		 * catch any drivers still reading this from the
+		 * device itself.  This can be removed once
+		 * all drivers are fixed. (are there any?)
+		 */
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	}
+}
+
+/*
+ * Allocate resources for all PCI devices that have been enabled.
+ * We need to do that before we try to fix up anything.
+ */
+static void __init pcibios_claim_resources(void)
+{
+	struct pci_dev *dev;
+	int idx;
+
+	for (dev = pci_devices; dev; dev = dev->next)
+		for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+			struct resource *a, *r = &dev->resource[idx];
+
+			/*
+			 * Ignore regions that start at 0 or
+			 * end at 0xffffffff
+			 */
+			if (!r->start || r->end == 0xffffffff)
+				continue;
+
+			if (r->flags & IORESOURCE_IO)
+				a = &ioport_resource;
+			else
+				a = &iomem_resource;
+
+			if (request_resource(a, r) < 0)
+				printk(KERN_ERR "PCI: Address space collision "
+					"on region %d of %s\n",
+					idx, dev->name);
+				/* We probably should disable the region,
+				 * shouldn't we?
+				 */
+		}
+}
+
+/*
+ * Called after each bus is probed, but before its children
+ * are examined.
+ *
+ * No fixup of bus required
+ */
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+}
+
+void __init pcibios_init(void)
+{
+	struct pci_ops *ops;
+
+	/*
+	 * Pre-initialisation.  Set up the host bridge.
+	 */
+	ops = dc21285_init(0);
+
+	printk("PCI: Probing PCI hardware\n");
+
+	pci_scan_bus(0, ops, NULL);
+	pcibios_claim_resources();
+	pcibios_fixup_devices();
+
+	/*
+	 * Now clear down any PCI error IRQs and
+	 * register the error handler
+	 */
+	dc21285_init(1);
+
+	/*
+	 * Initialise any other hardware after we've
+	 * got the PCI bus initialised.  We may need
+	 * the PCI bus to talk to this other hardware.
+	 */
+	hw_init();
+}
+
+char * __init pcibios_setup(char *str)
+{
+	return str;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S
--- v2.3.15/linux/arch/arm/kernel/calls.S	Wed Jul 28 10:30:10 1999
+++ linux/arch/arm/kernel/calls.S	Mon Aug 30 18:14:55 1999
@@ -119,9 +119,9 @@
 		.long	SYMBOL_NAME(sys_newlstat)
 		.long	SYMBOL_NAME(sys_newfstat)
 		.long	SYMBOL_NAME(sys_uname)
-/* 110 */	.long	SYMBOL_NAME(sys_ni_syscall)
+/* 110 */	.long	SYMBOL_NAME(sys_iopl)
 		.long	SYMBOL_NAME(sys_vhangup)
-		.long	SYMBOL_NAME(sys_idle)
+		.long	SYMBOL_NAME(sys_ni_syscall)
 		.long	SYMBOL_NAME(sys_syscall)		/* call a syscall */
 		.long	SYMBOL_NAME(sys_wait4)
 /* 115 */	.long	SYMBOL_NAME(sys_swapoff)
@@ -129,7 +129,7 @@
 		.long	SYMBOL_NAME(sys_ipc)
 		.long	SYMBOL_NAME(sys_fsync)
 		.long	SYMBOL_NAME(sys_sigreturn_wrapper)
-		.long	SYMBOL_NAME(sys_clone_wapper)
+/* 120 */	.long	SYMBOL_NAME(sys_clone_wapper)
 		.long	SYMBOL_NAME(sys_setdomainname)
 		.long	SYMBOL_NAME(sys_newuname)
 		.long	SYMBOL_NAME(sys_ni_syscall)		/* .long	SYMBOL_NAME(sys_modify_ldt) */
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/dec21285.c linux/arch/arm/kernel/dec21285.c
--- v2.3.15/linux/arch/arm/kernel/dec21285.c	Wed Jun 30 11:24:54 1999
+++ linux/arch/arm/kernel/dec21285.c	Mon Aug 30 18:14:55 1999
@@ -1,7 +1,7 @@
 /*
- * arch/arm/kernel/dec21285.c: PCI functions for DEC 21285
+ * arch/arm/kernel/dec21285.c: PCI functions for DC21285
  *
- * Copyright (C) 1998 Russell King, Phil Blundell
+ * Copyright (C) 1998-1999 Russell King, Phil Blundell
  */
 #include <linux/config.h>
 #include <linux/sched.h>
@@ -11,6 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/ioport.h>
 
 #include <asm/irq.h>
 #include <asm/system.h>
@@ -129,7 +130,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-__initfunc(void pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set))
+void __init pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set)
 {
 	unsigned short cmd;
 
@@ -138,7 +139,7 @@
 	pci_write_config_word(dev, PCI_COMMAND, cmd);
 }
 
-__initfunc(void pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr))
+void __init pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr)
 {
 	int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
 
@@ -148,7 +149,7 @@
 	dev->base_address[idx] = addr;
 }
 
-__initfunc(void pcibios_fixup(void))
+void __init pcibios_fixup(void)
 {
 	struct pci_dev *dev;
 
@@ -167,7 +168,7 @@
 	hw_init();
 }
 
-__initfunc(void pcibios_init(void))
+void __init pcibios_init(void)
 {
 	unsigned int mem_size = (unsigned int)high_memory - PAGE_OFFSET;
 	unsigned long cntl;
@@ -242,11 +243,11 @@
 	printk(KERN_DEBUG"PCI: DEC21285 revision %02lX\n", *CSR_CLASSREV & 0xff);
 }
 
-__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
 }
 
-__initfunc(char *pcibios_setup(char *str))
+char * __init pcibios_setup(char *str)
 {
 	return str;
 }
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/dma-a5k.c linux/arch/arm/kernel/dma-a5k.c
--- v2.3.15/linux/arch/arm/kernel/dma-a5k.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/kernel/dma-a5k.c	Thu Aug 26 12:42:30 1999
@@ -91,7 +91,7 @@
 	return 0;
 }
 
-__initfunc(void arch_dma_init(dma_t *dma))
+void __init arch_dma_init(dma_t *dma)
 {
 	dma[DMA_VIRTUAL_FLOPPY].dma_irq = 64;
 }
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/dma-arc.c linux/arch/arm/kernel/dma-arc.c
--- v2.3.15/linux/arch/arm/kernel/dma-arc.c	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/kernel/dma-arc.c	Mon Aug 30 18:15:02 1999
@@ -15,8 +15,11 @@
 
 #include "dma.h"
 
+#define DEBUG
+
 int arch_request_dma(dmach_t channel, dma_t *dma, const char * dev_id)
 {
+  printk("arch_request_dma channel=%d F0=%d F1=%d\n",channel,DMA_VIRTUAL_FLOPPY0,DMA_VIRTUAL_FLOPPY1);
 	if (channel == DMA_VIRTUAL_FLOPPY0 ||
 	    channel == DMA_VIRTUAL_FLOPPY1)
 		return 0;
@@ -30,8 +33,9 @@
 
 void arch_enable_dma(dmach_t channel, dma_t *dma)
 {
+  printk("arch_enable_dma channel=%d F0=%d F1=%d\n",channel,DMA_VIRTUAL_FLOPPY0,DMA_VIRTUAL_FLOPPY1);
 	switch (channel) {
-#ifdef CONFIG_BLK_DEV_FD
+#ifdef CONFIG_BLK_DEV_FD1772
 	case DMA_VIRTUAL_FLOPPY0: { /* Data DMA */
 		switch (dma->dma_mode) {
 		case DMA_MODE_READ: /* read */
@@ -139,7 +143,7 @@
 	return 0;
 }
 
-__initfunc(void arch_dma_init(dma_t *dma))
+void __init arch_dma_init(dma_t *dma)
 {
 	dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
 	dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65;
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/dma-dummy.c linux/arch/arm/kernel/dma-dummy.c
--- v2.3.15/linux/arch/arm/kernel/dma-dummy.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/kernel/dma-dummy.c	Thu Aug 26 12:42:31 1999
@@ -27,6 +27,6 @@
 	return 0;
 }
 
-__initfunc(void init_dma(void))
+void __init init_dma(void)
 {
 }
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/dma-footbridge.c linux/arch/arm/kernel/dma-footbridge.c
--- v2.3.15/linux/arch/arm/kernel/dma-footbridge.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/kernel/dma-footbridge.c	Thu Aug 26 12:42:31 1999
@@ -104,7 +104,7 @@
 	return 0;
 }
 
-__initfunc(void arch_dma_init(dma_t *dma))
+void __init arch_dma_init(dma_t *dma)
 {
 #ifdef CONFIG_ISA_DMA
 	has_isa_dma = isa_init_dma();
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/dma-isa.c linux/arch/arm/kernel/dma-isa.c
--- v2.3.15/linux/arch/arm/kernel/dma-isa.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/kernel/dma-isa.c	Mon Aug 30 18:15:07 1999
@@ -11,6 +11,7 @@
  *  Copyright (C) 1998 Phil Blundell
  */
 #include <linux/sched.h>
+#include <linux/ioport.h>
 #include <linux/init.h>
 
 #include <asm/dma.h>
@@ -125,7 +126,7 @@
 	outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]);
 }
 
-__initfunc(int isa_init_dma(void))
+int __init isa_init_dma(void)
 {
 	int dmac_found;
 
@@ -138,7 +139,7 @@
 	dmac_found = inb(0x00) == 0x55 && inb(0x00) == 0xaa;
 
 	if (dmac_found) {
-		int channel;
+		int channel, i;
 
 		for (channel = 0; channel < 8; channel++)
 			isa_disable_dma(channel, NULL);
@@ -173,6 +174,9 @@
 		outb(0x33, 0x4d6);
 
 		request_dma(DMA_ISA_CASCADE, "cascade");
+
+		for (i = 0; i < sizeof(dma_resources) / sizeof(dma_resources[0]); i++)
+			request_resource(&ioport_resource, dma_resources + i);
 	}
 
 	return dmac_found;
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/dma-rpc.c linux/arch/arm/kernel/dma-rpc.c
--- v2.3.15/linux/arch/arm/kernel/dma-rpc.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/kernel/dma-rpc.c	Thu Aug 26 12:42:31 1999
@@ -359,7 +359,7 @@
 	outb(tcr, IOMD_DMATCR);
 }
 
-__initfunc(void arch_dma_init(dma_t *dma))
+void __init arch_dma_init(dma_t *dma)
 {
 	outb(0, IOMD_IO0CR);
 	outb(0, IOMD_IO1CR);
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/dma.c linux/arch/arm/kernel/dma.c
--- v2.3.15/linux/arch/arm/kernel/dma.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/kernel/dma.c	Thu Aug 26 12:42:31 1999
@@ -221,7 +221,7 @@
 EXPORT_SYMBOL(set_dma_sg);
 EXPORT_SYMBOL(set_dma_speed);
 
-__initfunc(void init_dma(void))
+void __init init_dma(void)
 {
 	arch_dma_init(dma_chan);
 }
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c
--- v2.3.15/linux/arch/arm/kernel/ecard.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/kernel/ecard.c	Mon Aug 30 18:15:11 1999
@@ -44,6 +44,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
+#include <asm/mmu_context.h>
 
 #ifdef CONFIG_ARCH_ARC
 #include <asm/arch/oldlatches.h>
@@ -231,8 +232,42 @@
 static wait_queue_head_t ecard_done;
 static struct ecard_request *ecard_req;
 
+/* to be removed when exec_mmap becomes extern */
+static int exec_mmap(void)
+{
+	struct mm_struct * mm, * old_mm;
+
+	old_mm = current->mm;
+	if (old_mm && atomic_read(&old_mm->mm_users) == 1) {
+		flush_cache_mm(old_mm);
+		mm_release();
+		exit_mmap(old_mm);
+		flush_tlb_mm(old_mm);
+		return 0;
+	}
+
+	mm = mm_alloc();
+	if (mm) {
+		struct mm_struct *active_mm = current->active_mm;
+
+		current->mm = mm;
+		current->active_mm = mm;
+		activate_mm(active_mm, mm);
+		mm_release();
+		if (old_mm) {
+			if (active_mm != old_mm) BUG();
+			mmput(old_mm);
+			return 0;
+		}
+		mmdrop(active_mm);
+		return 0;
+	}
+	return -ENOMEM;
+}
+
 /*
- * Set up the expansion card daemon's environment.
+ * Set up the expansion card
+ * daemon's environment.
  */
 static void
 ecard_init_task(void)
@@ -251,6 +286,8 @@
 	pgd_t *src_pgd, *dst_pgd;
 	unsigned int dst_addr = IO_START;
 
+	exec_mmap();
+
 	src_pgd = pgd_offset(current->mm, IO_BASE);
 	dst_pgd = pgd_offset(current->mm, dst_addr);
 
@@ -333,7 +370,7 @@
 	 * call the loader.  We can't schedule, or
 	 * sleep for this call.
 	 */
-	if ((current == task[0] || in_interrupt()) &&
+	if ((current == &init_task || in_interrupt()) &&
 	    req->req == req_reset && req->ec == NULL) {
 		ecard_init_task();
 		ecard_task_reset(req);
@@ -721,8 +758,8 @@
 		printk(KERN_WARNING "Wild interrupt from backplane (masks)\n");
 }
 
-__initfunc(static void
-ecard_probeirqhw(void))
+static void __init
+ecard_probeirqhw(void)
 {
 	ecard_t *ec;
 	int found;
@@ -798,8 +835,6 @@
 	return address;
 }
 
-static const char *unknown = "*unknown*";
-
 static int ecard_prints(char *buffer, ecard_t *ec)
 {
 	char *start = buffer;
@@ -818,7 +853,7 @@
 			ec->card_desc = kmalloc(strlen(incd.d.string)+1, GFP_KERNEL);
 
 			if (ec->card_desc)
-				strcpy(ec->card_desc, incd.d.string);
+				strcpy((char *)ec->card_desc, incd.d.string);
 		}
 
 		buffer += sprintf(buffer, "%s\n", ec->card_desc ? ec->card_desc : "*unknown*");
@@ -872,8 +907,8 @@
  * If bit 1 of the first byte of the card is set, then the
  * card does not exist.
  */
-__initfunc(static int
-ecard_probe(int slot, card_type_t type))
+static int __init
+ecard_probe(int slot, card_type_t type)
 {
 	ecard_t **ecp;
 	ecard_t *ec;
@@ -1009,7 +1044,7 @@
 	return finding_pos;
 }
 
-__initfunc(static void ecard_free_all(void))
+static void __init ecard_free_all(void)
 {
 	ecard_t *ec, *ecn;
 
@@ -1029,7 +1064,7 @@
  * Locate all hardware - interrupt management and
  * actual cards.
  */
-__initfunc(void ecard_init(void))
+void __init ecard_init(void)
 {
 	int slot;
 
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/entry-armo.S linux/arch/arm/kernel/entry-armo.S
--- v2.3.15/linux/arch/arm/kernel/entry-armo.S	Mon Aug  2 10:19:52 1999
+++ linux/arch/arm/kernel/entry-armo.S	Mon Aug 30 18:15:11 1999
@@ -653,10 +653,10 @@
  * Register switch for older 26-bit only ARMs
  */
 ENTRY(__switch_to)
-		stmfd	sp!, {r4 - r9, fp, lr}		@ Store most regs on stack
+		stmfd	sp!, {r4 - sl, fp, lr}		@ Store most regs on stack
 		str	sp, [r0, #TSS_SAVE]		@ Save sp_SVC
 		ldr	sp, [r1, #TSS_SAVE]		@ Get saved sp_SVC
-		ldmfd	sp!, {r4 - r9, fp, pc}^		@ Load all regs saved previously
+		ldmfd	sp!, {r4 - sl, fp, pc}^		@ Load all regs saved previously
 
 /*
  *=============================================================================
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S
--- v2.3.15/linux/arch/arm/kernel/entry-armv.S	Mon Aug  2 10:19:52 1999
+++ linux/arch/arm/kernel/entry-armv.S	Mon Aug 30 18:15:11 1999
@@ -16,6 +16,7 @@
 #include <asm/errno.h>
 #include <asm/hardware.h>
 #include <asm/arch/irqs.h>
+#include <asm/proc-fns.h>
 
 #include "../lib/constants.h"
 
@@ -453,9 +454,13 @@
 		biceq	r0, r0, #I_BIT			@ previously
 		msreq	cpsr, r0
 		mov	r0, r2
+#ifdef MULTI_CPU
 		ldr	r2, .LCprocfns
 		mov	lr, pc
-		ldr	pc, [r2, #4]			@ call processor specific code
+		ldr	pc, [r2]			@ call processor specific code
+#else
+		bl	cpu_data_abort
+#endif
 		mov	r3, sp
 		bl	SYMBOL_NAME(do_DataAbort)
 		ldr	r0, [sp, #S_PSR]
@@ -507,7 +512,9 @@
 .LCirq:		.word	__temp_irq
 .LCund:		.word	__temp_und
 .LCabt:		.word	__temp_abt
+#ifdef MULTI_CPU
 .LCprocfns:	.word	SYMBOL_NAME(processor)
+#endif
 .LCfp:		.word	SYMBOL_NAME(fp_enter)
 #ifdef CONFIG_ALIGNMENT_TRAP
 .LCswi:		.word	SYMBOL_NAME(cr_alignment)
@@ -540,9 +547,13 @@
 		mrs	r2, cpsr			@ Enable interrupts if they were
 		bic	r2, r2, #I_BIT			@ previously
 		msr	cpsr, r2
+#ifdef MULTI_CPU
 		ldr	r2, .LCprocfns
 		mov	lr, pc
-		ldr	pc, [r2, #4]			@ call processor specific code
+		ldr	pc, [r2]			@ call processor specific code
+#else
+		bl	cpu_data_abort
+#endif
 		mov	r3, sp
 		adrsvc	al, lr, ret_from_sys_call
 		b	SYMBOL_NAME(do_DataAbort)
@@ -661,7 +672,7 @@
  * previous and next are guaranteed not to be the same.
  */
 ENTRY(__switch_to)
-		stmfd	sp!, {r4 - r9, fp, lr}		@ Store most regs on stack
+		stmfd	sp!, {r4 - sl, fp, lr}		@ Store most regs on stack
 		mrs	ip, cpsr
 		stmfd	sp!, {ip}			@ Save cpsr_SVC
 		ldr	r2, [r1, #TSS_DOMAIN]
@@ -670,7 +681,7 @@
 		mcr	p15, 0, r2, c3, c0		@ Set domain register
 		ldmfd	sp!, {ip}
 		msr	spsr, ip			@ Save tasks CPSR into SPSR for this return
-		ldmfd	sp!, {r4 - r9, fp, pc}^		@ Load all regs saved previously
+		ldmfd	sp!, {r4 - sl, fp, pc}^		@ Load all regs saved previously
 
 		.section ".text.init",#alloc,#execinstr
 /*
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S
--- v2.3.15/linux/arch/arm/kernel/entry-common.S	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/kernel/entry-common.S	Mon Aug 30 18:15:11 1999
@@ -2,6 +2,16 @@
 /*============================================================================
  * All exits to user mode from the kernel go through this code.
  */
+
+/*
+ * Define to favour ARM8, ARM9 and StrongARM cpus.  This says that it is
+ * cheaper to use two LDR instructions than a two-register LDM, if the
+ * latter would entail calculating an address specially.
+ */
+#if defined(CONFIG_CPU_SA110)
+#define HARVARD_CACHE
+#endif
+
 		.globl	ret_from_sys_call
 
 		.align	5
@@ -10,18 +20,23 @@
 slow_syscall_return:
 		add	sp, sp, #4
 ret_from_sys_call:
+#ifdef HARVARD_CACHE
+		ldr	r0, bh_data
+		ldr	r4, bh_data+4
+#else
 		adr	r0, bh_data
 		ldmia	r0, {r0, r4}
+#endif
 		ldr	r0, [r0]
 		ldr	r1, [r4]
 		tst	r0, r1
 		blne	SYMBOL_NAME(do_bottom_half)
 ret_with_reschedule:
-		get_current_task r1		@ check for scheduling
-		ldr	r0, [r1, #TSK_NEED_RESCHED]
+		get_current_task r5
+		ldr	r0, [r5, #TSK_NEED_RESCHED]
+		ldr	r1, [r5, #TSK_SIGPENDING]
 		teq	r0, #0
 		bne	ret_reschedule
-		ldr	r1, [r1, #TSK_SIGPENDING]
 		teq	r1, #0			@ check for signals
 		bne	ret_signal
 
@@ -37,8 +52,13 @@
 
 		.globl	ret_from_exception
 ret_from_exception:
+#ifdef HARVARD_CACHE
+		ldr	r0, bh_data
+		ldr	r1, bh_data + 4
+#else
 		adr	r0, bh_data
 		ldmia	r0, {r0, r1}
+#endif
 		ldr	r0, [r0]
 		ldr	r1, [r1]
 		mov	r4, #0
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/fiq.c linux/arch/arm/kernel/fiq.c
--- v2.3.15/linux/arch/arm/kernel/fiq.c	Mon Aug  2 10:19:52 1999
+++ linux/arch/arm/kernel/fiq.c	Thu Aug 26 12:42:31 1999
@@ -213,7 +213,7 @@
 	while (current_fiq->fiq_op(current_fiq->dev_id, 0));
 }
 
-__initfunc(void init_FIQ(void))
+void __init init_FIQ(void)
 {
 	no_fiq_insn = *(unsigned long *)FIQ_VECTOR;
 	set_fs(get_fs());
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/head-armv.S linux/arch/arm/kernel/head-armv.S
--- v2.3.15/linux/arch/arm/kernel/head-armv.S	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/kernel/head-armv.S	Mon Aug 30 18:15:12 1999
@@ -164,9 +164,16 @@
 		addne	r0, r4, #0x3600				@ d8000000
 		strne	r3, [r0]
 #endif
-@
-@ The following should work on both v3 and v4 implementations
-@
+		b	aligned_call
+/*
+ * The following should work on both v3 and v4 implementations
+ * Note: it seems that if the mov pc,lr is on the next cache
+ * line, it doesn't get fetched before the MMU starts
+ * translating, which prevents the kernel from booting.
+ * Ensure that this never happens.
+ */
+		.align 5
+aligned_call:
 		mov	lr, pc
 		mov	pc, r10					@ Call processor flush (returns ctrl reg)
 		adr	r5, __entry
@@ -180,7 +187,7 @@
 #ifdef CONFIG_ARCH_RPC
 /* Turn the screen red on a error - RiscPC only.
  */
-1:		mov	r0, #0x02000000
+		mov	r0, #0x02000000
 		mov	r3, #0x11
 		orr	r3, r3, r3, lsl #8
 		orr	r3, r3, r3, lsl #16
@@ -189,6 +196,7 @@
 		str	r3, [r0], #4
 		str	r3, [r0], #4
 #endif
+1:		mov	r0, r0
 		b	1b
 
 .Lbranch:	.long	.Lalready_done_mmap			@ Real address of routine
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/hw-footbridge.c linux/arch/arm/kernel/hw-footbridge.c
--- v2.3.15/linux/arch/arm/kernel/hw-footbridge.c	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/kernel/hw-footbridge.c	Mon Aug 30 18:15:12 1999
@@ -44,7 +44,7 @@
 
 static int irqmap_ebsa[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 };
 
-__initfunc(static int ebsa_irqval(struct pci_dev *dev))
+static int __init ebsa_irqval(struct pci_dev *dev)
 {
 	unsigned char pin;
 	
@@ -59,7 +59,7 @@
 #ifdef CONFIG_CATS
 static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
 
-__initfunc(static int cats_irqval(struct pci_dev *dev))
+static int __init cats_irqval(struct pci_dev *dev)
 {
 	if (dev->irq >= 128)
 		return 16 + (dev->irq & 0x1f);
@@ -80,7 +80,7 @@
 }
 #endif
 
-__initfunc(void pcibios_fixup_ebsa285(struct pci_dev *dev))
+void __init pcibios_fixup_ebsa285(struct pci_dev *dev)
 {
 	/* Latency timer of 32 */
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32);
@@ -284,7 +284,7 @@
 	irq_pci_err, SA_INTERRUPT, 0, "PCI error", NULL, NULL
 };
 
-__initfunc(void pcibios_init_ebsa285(void))
+void __init pcibios_init_ebsa285(void)
 {
 	setup_arm_irq(IRQ_PCI_ERR, &irq_pci_error);
 }
@@ -592,7 +592,7 @@
 /*
  * Initialise the Winbond W83977F chip.
  */
-__initfunc(static void wb977_init(void))
+static void __init wb977_init(void)
 {
 	request_region(0x370, 2, "W83977AF configuration");
 
@@ -642,7 +642,7 @@
 	gpio_modify_op(GPIO_IOLOAD, 0);
 }
 
-__initfunc(static void cpld_init(void))
+static void __init cpld_init(void)
 {
 	unsigned long flags;
 
@@ -662,7 +662,7 @@
 #define dprintk printk
 #endif
 
-#define WRITE_RWA(r,v) do { outb((r), 0x279); outb((v), 0xa79); } while (0)
+#define WRITE_RWA(r,v) do { outb((r), 0x279); udelay(10); outb((v), 0xa79); } while (0)
 
 static inline void rwa010_unlock(void)
 {
@@ -671,8 +671,10 @@
 	WRITE_RWA(2, 2);
 	mdelay(10);
 
-	for (i = 0; i < sizeof(rwa_unlock); i++)
+	for (i = 0; i < sizeof(rwa_unlock); i++) {
 		outb(rwa_unlock[i], 0x279);
+		udelay(10);
+	}
 }
 
 static inline void rwa010_read_ident(void)
@@ -685,22 +687,22 @@
 
 	outb(1, 0x279);
 
-	mdelay(10);
+	mdelay(1);
 
 	dprintk("Identifier: ");
 	for (i = 0; i < 9; i++) {
 		si[i] = 0;
 		for (j = 0; j < 8; j++) {
 			int bit;
-			mdelay(1);
+			udelay(250);
 			inb(0x203);
-			mdelay(1);
+			udelay(250);
 			bit = inb(0x203);
 			dprintk("%02X ", bit);
+			bit = (bit == 0xaa) ? 1 : 0;
 			si[i] |= bit << j;
 		}
-		mdelay(10);
-		dprintk("%02X ", si[i]);
+		dprintk("(%02X) ", si[i]);
 	}
 	dprintk("\n");
 }
@@ -842,7 +844,7 @@
 	outb(1, 0x38b);
 }
 
-__initfunc(static void rwa010_init(void))
+static void __init rwa010_init(void)
 {
 	rwa010_unlock();
 	rwa010_read_ident();
@@ -918,7 +920,7 @@
 
 #endif
 
-__initfunc(void hw_init(void))
+void __init hw_init(void)
 {
 	extern void register_isa_ports(unsigned int, unsigned int, 
 				       unsigned int);
@@ -943,9 +945,10 @@
 		spin_unlock_irqrestore(&gpio_lock, flags);
 	}
 #endif
-
+#ifdef CONFIG_CATS
 	if (machine_is_cats())
 		cats_hw_init();
+#endif
 
 	leds_event(led_start);
 }
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/ioport.c linux/arch/arm/kernel/ioport.c
--- v2.3.15/linux/arch/arm/kernel/ioport.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/kernel/ioport.c	Mon Aug 30 18:15:12 1999
@@ -0,0 +1,27 @@
+/*
+ * linux/arch/arm/kernel/ioport.c
+ *
+ * IO permission support for ARM.
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+
+asmlinkage int sys_iopl(unsigned long turn_on)
+{
+	if (turn_on && !capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	/*
+	 * We only support an on_off approach
+	 */
+	modify_domain(DOMAIN_IO, turn_on ? DOMAIN_MANAGER : DOMAIN_CLIENT);
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/irq.c linux/arch/arm/kernel/irq.c
--- v2.3.15/linux/arch/arm/kernel/irq.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/kernel/irq.c	Thu Aug 26 12:42:31 1999
@@ -479,7 +479,7 @@
 	return irq_found;
 }
 
-__initfunc(void init_IRQ(void))
+void __init init_IRQ(void)
 {
 	extern void init_dma(void);
 	int irq;
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/isa.c linux/arch/arm/kernel/isa.c
--- v2.3.15/linux/arch/arm/kernel/isa.c	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/kernel/isa.c	Mon Aug 30 18:15:15 1999
@@ -37,8 +37,8 @@
 static ctl_table ctl_bus[2] = {{CTL_BUS, "bus", NULL, 0, 0555, ctl_isa},
 			       {0}};
 
-__initfunc(void
-register_isa_ports(unsigned int membase, unsigned int portbase, unsigned int portshift))
+void __init
+register_isa_ports(unsigned int membase, unsigned int portbase, unsigned int portshift)
 {
 	isa_membase = membase;
 	isa_portbase = portbase;
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/leds-footbridge.c linux/arch/arm/kernel/leds-footbridge.c
--- v2.3.15/linux/arch/arm/kernel/leds-footbridge.c	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/kernel/leds-footbridge.c	Mon Aug 30 18:15:15 1999
@@ -223,8 +223,8 @@
 {
 }
 
-__initfunc(void
-init_leds_event(led_event_t evt))
+void __init
+init_leds_event(led_event_t evt)
 {
 	switch (machine_arch_type) {
 #ifdef CONFIG_FOOTBRIDGE
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c
--- v2.3.15/linux/arch/arm/kernel/process.c	Mon Aug  2 10:19:52 1999
+++ linux/arch/arm/kernel/process.c	Mon Aug 30 18:15:15 1999
@@ -9,7 +9,6 @@
  * This file handles the architecture-dependent parts of process handling..
  */
 
-#define __KERNEL_SYSCALLS__
 #include <stdarg.h>
 
 #include <linux/errno.h>
@@ -54,16 +53,15 @@
 /*
  * The idle loop on an ARM...
  */
-asmlinkage int sys_idle(void)
+void cpu_idle(void)
 {
-	if (current->pid != 0)
-		return -EPERM;
-
 	/* endless idle loop with no priority at all */
+	init_idle();
+	current->priority = 0;
+	current->counter = -100;
 	while (1) {
 		if (!current->need_resched && !hlt_counter)
 			proc_idle();
-		current->policy = SCHED_YIELD;
 		schedule();
 #ifndef CONFIG_NO_PGT_CACHE
 		check_pgt_cache();
@@ -73,7 +71,7 @@
 
 static char reboot_mode = 'h';
 
-__initfunc(void reboot_setup(char *str, int *ints))
+void __init reboot_setup(char *str, int *ints)
 {
 	reboot_mode = str[0];
 }
@@ -283,7 +281,6 @@
  */
 pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 {
-	extern int sys_exit(int) __attribute__((noreturn));
 	pid_t __ret;
 
 	__asm__ __volatile__(
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/ptrace.c linux/arch/arm/kernel/ptrace.c
--- v2.3.15/linux/arch/arm/kernel/ptrace.c	Mon Aug  2 10:19:52 1999
+++ linux/arch/arm/kernel/ptrace.c	Mon Aug 30 18:15:15 1999
@@ -130,7 +130,7 @@
 		val = (((signed long)val) >> shift);
 		break;
 	case 3:
-		__asm__ __volatile__("mov %0, %0, ror %1" : "=r" (val) : "0" (val), "r" (shift));
+ 		val = (val >> shift) | (val << (32 - shift));
 		break;
 	}
 printk ("=%08lX ", val);
@@ -158,7 +158,7 @@
 		val = (((signed long)val) >> shift);
 		break;
 	case 3:
-		__asm__ __volatile__("mov %0, %0, ror %1" : "=r" (val) : "0" (val), "r" (shift));
+ 		val = (val >> shift) | (val << (32 - shift));
 		break;
 	}
 printk ("=%08lX ", val);
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/semaphore.c linux/arch/arm/kernel/semaphore.c
--- v2.3.15/linux/arch/arm/kernel/semaphore.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/kernel/semaphore.c	Mon Aug 30 18:15:15 1999
@@ -0,0 +1,202 @@
+/*
+ * ARM semaphore implementation, taken from
+ *
+ * i386 semaphore implementation.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * Modified for ARM by Russell King
+ */
+#include <linux/sched.h>
+
+#include <asm/semaphore.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to aquire the semaphore, while the "sleeping"
+ * variable is a count of such aquires.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * "sleeping" and the contention routine ordering is
+ * protected by the semaphore spinlock.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+
+/*
+ * Logic:
+ *  - only on a boundary condition do we need to care. When we go
+ *    from a negative count to a non-negative, we wake people up.
+ *  - when we go from a non-negative count to a negative do we
+ *    (a) synchronize with the "sleeper" count and (b) make sure
+ *    that we're on the wakeup list before we synchronize so that
+ *    we cannot lose wakeup events.
+ */
+
+void __up(struct semaphore *sem)
+{
+	wake_up(&sem->wait);
+}
+
+static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
+
+void __down(struct semaphore * sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+	tsk->state = TASK_UNINTERRUPTIBLE;
+	add_wait_queue(&sem->wait, &wait);
+
+	spin_lock_irq(&semaphore_lock);
+	sem->sleepers++;
+	for (;;) {
+		int sleepers = sem->sleepers;
+
+		/*
+		 * Add "everybody else" into it. They aren't
+		 * playing, because we own the spinlock.
+		 */
+		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+			sem->sleepers = 0;
+			wake_up(&sem->wait);
+			break;
+		}
+		sem->sleepers = 1;	/* us - see -1 above */
+		spin_unlock_irq(&semaphore_lock);
+
+		schedule();
+		tsk->state = TASK_UNINTERRUPTIBLE;
+		spin_lock_irq(&semaphore_lock);
+	}
+	spin_unlock_irq(&semaphore_lock);
+	remove_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_RUNNING;
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+	int retval;
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+	tsk->state = TASK_INTERRUPTIBLE;
+	add_wait_queue(&sem->wait, &wait);
+
+	spin_lock_irq(&semaphore_lock);
+	sem->sleepers ++;
+	for (;;) {
+		int sleepers = sem->sleepers;
+
+		/*
+		 * With signals pending, this turns into
+		 * the trylock failure case - we won't be
+		 * sleeping, and we* can't get the lock as
+		 * it has contention. Just correct the count
+		 * and exit.
+		 */
+		retval = -EINTR;
+		if (signal_pending(current)) {
+			sem->sleepers = 0;
+			if (atomic_add_negative(sleepers, &sem->count))
+				break;
+			wake_up(&sem->wait);
+			break;
+		}
+
+		/*
+		 * Add "everybody else" into it. They aren't
+		 * playing, because we own the spinlock. The
+		 * "-1" is because we're still hoping to get
+		 * the lock.
+		 */
+		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+			wake_up(&sem->wait);
+			retval = 0;
+			sem->sleepers = 0;
+			break;
+		}
+		sem->sleepers = 1;	/* us - see -1 above */
+		spin_unlock_irq(&semaphore_lock);
+
+		schedule();
+		tsk->state = TASK_INTERRUPTIBLE;
+		spin_lock_irq(&semaphore_lock);
+	}
+	spin_unlock_irq(&semaphore_lock);
+	tsk->state = TASK_RUNNING;
+	remove_wait_queue(&sem->wait, &wait);
+	return retval;
+}
+
+/*
+ * Trylock failed - make sure we correct for
+ * having decremented the count.
+ *
+ * We could have done the trylock with a
+ * single "cmpxchg" without failure cases,
+ * but then it wouldn't work on a 386.
+ */
+int __down_trylock(struct semaphore * sem)
+{
+	int sleepers;
+
+	spin_lock_irq(&semaphore_lock);
+	sleepers = sem->sleepers + 1;
+	sem->sleepers = 0;
+
+	/*
+	 * Add "everybody else" and us into it. They aren't
+	 * playing, because we own the spinlock.
+	 */
+	if (!atomic_add_negative(sleepers, &sem->count))
+		wake_up(&sem->wait);
+
+	spin_unlock_irq(&semaphore_lock);
+	return 1;
+}
+
+/*
+ * The semaphore operations have a special calling sequence that
+ * allow us to do a simpler in-line version of them. These routines
+ * need to convert that sequence back into the C sequence when
+ * there is contention on the semaphore.
+ *
+ * r0 contains the semaphore pointer on entry. Save the C-clobbered
+ * registers (r0 to r3, ip and lr) except r0 in the cases where it
+ * is used as a return value..
+ */
+asm(".align	5
+	.globl	__down_failed
+__down_failed:
+	stmfd	sp!, {r0 - r3, ip, lr}
+	bl	__down
+	ldmfd	sp!, {r0 - r3, ip, pc}");
+
+asm(".align	5
+	.globl	__down_interruptible_failed
+__down_interruptible_failed:
+	stmfd	sp!, {r1 - r3, ip, lr}
+	bl	__down_interruptible
+	ldmfd	sp!, {r1 - r3, ip, pc}");
+
+asm(".align	5
+	.globl	__down_trylock_failed
+__down_trylock_failed:
+	stmfd	sp!, {r1 - r3, ip, lr}
+	bl	__down_trylock
+	ldmfd	sp!, {r1 - r3, ip, pc}");
+
+asm(".align	5
+	.globl	__up_wakeup
+__up_wakeup:
+	stmfd	sp!, {r0 - r3, ip, lr}
+	bl	__up
+	ldmfd	sp!, {r0 - r3, ip, pc}");
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c
--- v2.3.15/linux/arch/arm/kernel/setup.c	Fri Jul 23 12:20:23 1999
+++ linux/arch/arm/kernel/setup.c	Mon Aug 30 18:15:15 1999
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/kernel/setup.c
  *
- *  Copyright (C) 1995-1998 Russell King
+ *  Copyright (C) 1995-1999 Russell King
  */
 
 /*
@@ -38,24 +38,6 @@
 #include <asm/setup.h>
 #include <asm/system.h>
 
-/* Work out which CPUs to support */
-#ifdef CONFIG_ARCH_ACORN
-#define SUPPORT_CPU_ARM6
-#define SUPPORT_CPU_ARM7
-#define SUPPORT_CPU_SA110
-#else
-#define SUPPORT_CPU_SA110
-#endif
-#ifdef CONFIG_CPU_ARM6
-#define SUPPORT_CPU_ARM6
-#endif
-#ifdef CONFIG_CPU_ARM7
-#define SUPPORT_CPU_ARM7
-#endif
-#ifdef CONFIG_CPU_SA110
-#define SUPPORT_CPU_SA110
-#endif
-
 #define MEM_SIZE	(16*1024*1024)
 #define COMMAND_LINE_SIZE 256
 
@@ -63,6 +45,10 @@
 #define CONFIG_CMDLINE ""
 #endif
 
+#ifndef PARAMS_BASE
+#define PARAMS_BASE NULL
+#endif
+
 extern void reboot_setup(char *str, int *ints);
 extern void fpe_init(void);
 extern void disable_hlt(void);
@@ -76,71 +62,32 @@
  orig_video_isVGA:	1,
  orig_video_points:	8
 };
-struct processor processor;
+
+extern int root_mountflags;
+extern int _etext, _edata, _end;
+
 unsigned char aux_device_present;
 
-extern const struct processor arm2_processor_functions;
-extern const struct processor arm250_processor_functions;
-extern const struct processor arm3_processor_functions;
-extern const struct processor arm6_processor_functions;
-extern const struct processor arm7_processor_functions;
-extern const struct processor sa110_processor_functions;
-
-char elf_platform[ELF_PLATFORM_SIZE];
-
-const struct armversions armidlist[] = {
-  /*-- Match -- --- Mask -- -- Manu --  Processor  uname -m   --- ELF STUFF ---
-	--- processor asm funcs --- */
-#if defined(CONFIG_CPU_26)
-  /* ARM2 fake ident */
-  { 0x41560200, 0xfffffff0, "ARM/VLSI",	"arm2"	 , "armv1"  , "v1", 0,
-	&arm2_processor_functions   },
-  /* ARM250 fake ident */
-  { 0x41560250, 0xfffffff0, "ARM/VLSI",	"arm250" , "armv2"  , "v2", HWCAP_SWP,
-	&arm250_processor_functions },
-  /* ARM3 processors */
-  { 0x41560300, 0xfffffff0, "ARM/VLSI",	"arm3"	 , "armv2"  , "v2", HWCAP_SWP,
-	&arm3_processor_functions   },
-#elif defined(CONFIG_CPU_32)
-#ifdef SUPPORT_CPU_ARM6
-  /* ARM6 */
-  { 0x41560600, 0xfffffff0, "ARM/VLSI",	"arm6"	 , "armv3"  , "v3", HWCAP_SWP,
-	&arm6_processor_functions   },
-  /* ARM610 */
-  { 0x41560610, 0xfffffff0, "ARM/VLSI",	"arm610" , "armv3"  , "v3", HWCAP_SWP,
-	&arm6_processor_functions   },
-#endif
-#ifdef SUPPORT_CPU_ARM7
-  /* ARM7's have a strange numbering */
-  { 0x41007000, 0xffffff00, "ARM/VLSI",	"arm7"	 , "armv3"  , "v3", HWCAP_SWP,
-	&arm7_processor_functions   },
-  /* ARM710 IDs are non-standard */
-  { 0x41007100, 0xfff8ff00, "ARM/VLSI",	"arm710" , "armv3"  , "v3", HWCAP_SWP,
-	&arm7_processor_functions   },
-#endif
-#ifdef SUPPORT_CPU_SA110
-#ifdef CONFIG_ARCH_RPC
-  /* Acorn RiscPC's can't handle ARMv4 half-word instructions */
-  { 0x4401a100, 0xfffffff0, "Intel",	"sa110"	 , "armv4"  , "v4", HWCAP_SWP,
-	&sa110_processor_functions  },
-#else
-  { 0x4401a100, 0xfffffff0, "Intel",	"sa110"	 , "armv4"  , "v4", HWCAP_SWP|HWCAP_HALF,
-	&sa110_processor_functions  },
-#endif
-#endif
-#endif
-  { 0x00000000, 0x00000000, "***", "unknown", "unknown", "**", 0, NULL }
-};
+         char elf_platform[ELF_PLATFORM_SIZE];
+unsigned int  elf_hwcap;
 
 /*
  * From head-armv.S
  */
 unsigned int processor_id;
 unsigned int __machine_arch_type;
-int armidindex;
+#ifdef MULTI_CPU
+struct processor processor;
+#endif
+#ifdef CONFIG_ARCH_ACORN
+int memc_ctrl_reg;
+int number_mfm_drives;
+unsigned int vram_size;
+#endif
 
-extern int root_mountflags;
-extern int _etext, _edata, _end;
+static struct proc_info_item proc_info;
+static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
+#define ENDIANNESS ((char)endian_test.l)
 
 /*-------------------------------------------------------------------------
  * Early initialisation routines for various configurable items in the
@@ -152,8 +99,8 @@
  * initial ram disk
  */
 #ifdef CONFIG_BLK_DEV_INITRD
-__initfunc(static void
-check_initrd(unsigned long mem_start, unsigned long mem_end))
+static void __init
+check_initrd(unsigned long mem_start, unsigned long mem_end)
 {
 	if (initrd_end > mem_end) {
 		printk ("initrd extends beyond end of memory "
@@ -167,8 +114,8 @@
 #define check_initrd(ms,me)
 #endif
 
-__initfunc(void
-setup_processor(void))
+void __init
+setup_processor(void)
 {
 	armidindex = 0;
 
@@ -187,8 +134,8 @@
 static char command_line[COMMAND_LINE_SIZE] = { 0, };
        char saved_command_line[COMMAND_LINE_SIZE];
 
-__initfunc(static void
-setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_sz))
+static void __init
+setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_sz)
 {
 	char c = ' ', *to = command_line;
 	int len = 0;
@@ -233,8 +180,8 @@
 		*to = '\0';
 }
 
-__initfunc(static void
-setup_ram(int doload, int prompt, int image_start))
+static void __init
+setup_ram(int doload, int prompt, int image_start)
 {
 #ifdef CONFIG_BLK_DEV_RAM
 	extern int rd_doload;
@@ -250,8 +197,8 @@
 /*
  * initial ram disk
  */
-__initfunc(static void
-setup_initrd(unsigned int start, unsigned int size))
+static void __init
+setup_initrd(unsigned int start, unsigned int size)
 {
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (start) {
@@ -277,8 +224,8 @@
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
 #define ENDIANNESS ((char)endian_test.l)
 
-__initfunc(void
-setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p))
+void __init
+setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
 	struct param_struct *params = (struct param_struct *)PARAMS_BASE;
 	static unsigned char smptrap;
@@ -298,9 +245,9 @@
 	setup_processor();
 
 	init_mm.start_code = TASK_SIZE;
-	init_mm.end_code	 = TASK_SIZE + (unsigned long) &_etext;
-	init_mm.end_data	 = TASK_SIZE + (unsigned long) &_edata;
-	init_mm.brk	 = TASK_SIZE + (unsigned long) &_end;
+	init_mm.end_code   = TASK_SIZE + (unsigned long) &_etext;
+	init_mm.end_data   = TASK_SIZE + (unsigned long) &_edata;
+	init_mm.brk	   = TASK_SIZE + (unsigned long) &_end;
 
 	/*
 	 * Add your machine dependencies here
@@ -313,6 +260,11 @@
 			params = NULL;
 		break;
 
+	case MACH_TYPE_RISCPC:
+		/* RiscPC can't handle half-word loads and stores */
+		elf_hwcap &= ~HWCAP_HALF;
+		break;
+
 	case MACH_TYPE_EBSA285:
 		if (params) {
 			ORIG_X		 = params->u1.s.video_x;
@@ -416,7 +368,7 @@
 
 		from = params->commandline;
 	} else {
-		ROOT_DEV	  = 0x00ff;
+		ROOT_DEV	  = to_kdev_t(0x00ff);
 
 		setup_ram(1, 1, 0);
 		setup_initrd(0, 0);
@@ -442,9 +394,6 @@
 
 	check_initrd(*memory_start_p, memory_end);
 
-	sprintf(system_utsname.machine, "%s%c", armidlist[armidindex].arch_vsn, ENDIANNESS);
-	sprintf(elf_platform, "%s%c", armidlist[armidindex].elf_vsn, ENDIANNESS);
-
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
 	conswitchp = &vga_con;
@@ -463,7 +412,7 @@
 	"unknown",
 	"Nexus-FTV/PCI",
 	"EBSA285",
-	"Corel-NetWinder",
+	"Rebel-NetWinder",
 	"Chalice-CATS",
 	"unknown-TBOX",
 	"co-EBSA285",
@@ -477,12 +426,13 @@
 	int len;
 
 	len = sprintf(buffer,
-		"Processor\t: %s %s rev %d\n"
+		"Processor\t: %s %s rev %d (%s)\n"
 		"BogoMips\t: %lu.%02lu\n"
 		"Hardware\t: %s\n",
-		armidlist[armidindex].manu,
-		armidlist[armidindex].name,
+		proc_info.manufacturer,
+		proc_info.cpu_name,
 		(int)processor_id & 15,
+		elf_platform,
 		(loops_per_sec+2500) / 500000,
 		((loops_per_sec+2500) / 5000) % 100,
 		machine_desc[machine_arch_type]);
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c
--- v2.3.15/linux/arch/arm/kernel/time.c	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/kernel/time.c	Thu Aug 26 12:42:31 1999
@@ -149,7 +149,7 @@
 	sti();
 }
 
-__initfunc(void time_init(void))
+void __init time_init(void)
 {
 	xtime.tv_usec = 0;
 
diff -u --recursive --new-file v2.3.15/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- v2.3.15/linux/arch/arm/kernel/traps.c	Mon Aug  2 10:19:52 1999
+++ linux/arch/arm/kernel/traps.c	Mon Aug 30 18:15:16 1999
@@ -292,9 +292,7 @@
 	case 2:	/* sys_cacheflush */
 #ifdef CONFIG_CPU_32
 		/* r0 = start, r1 = length, r2 = flags */
-		processor.u.armv3v4._flush_cache_area(regs->ARM_r0,
-						      regs->ARM_r1,
-						      1);
+		cpu_flush_cache_area(regs->ARM_r0, regs->ARM_r1, 1);
 #endif
 		break;
 
diff -u --recursive --new-file v2.3.15/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile
--- v2.3.15/linux/arch/arm/lib/Makefile	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/lib/Makefile	Mon Aug 30 18:15:16 1999
@@ -6,7 +6,7 @@
 
 L_TARGET := lib.a
 L_OBJS   := backtrace.o bitops.o checksum.o delay.o memcpy.o \
-	    semaphore.o string.o system.o uaccess.o
+	    string.o system.o uaccess.o
 
 ifeq ($(PROCESSOR),armo)
   L_OBJS += uaccess-armo.o
diff -u --recursive --new-file v2.3.15/linux/arch/arm/lib/semaphore.S linux/arch/arm/lib/semaphore.S
--- v2.3.15/linux/arch/arm/lib/semaphore.S	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/lib/semaphore.S	Wed Dec 31 16:00:00 1969
@@ -1,34 +0,0 @@
-/*
- *  linux/arch/arm/lib/semaphore.S
- *
- *  Idea from i386 code, Copyright Linus Torvalds.
- *  Converted for ARM by Russell King
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-
-/*
- * The semaphore operations have a special calling sequence
- * that allows us to keep the distruption of the main code
- * path to a minimum.  These routines save and restore the
- * registers that will be touched by __down etc.
- */
-ENTRY(__down_failed)
-	stmfd	sp!, {r0 - r3, ip, lr}
-	bl	SYMBOL_NAME(__down)
-	LOADREGS(fd, sp!, {r0 - r3, ip, pc})
-
-ENTRY(__down_interruptible_failed)
-	stmfd	sp!, {r1 - r3, ip, lr}
-	bl	SYMBOL_NAME(__down_interruptible)
-	LOADREGS(fd, sp!, {r1 - r3, ip, pc})
-
-ENTRY(__down_trylock_failed)
-	stmfd	sp!, {r1 - r3, ip, lr}
-	bl	SYMBOL_NAME(__down_trylock)
-	LOADREGS(fd, sp!, {r1 - r3, ip, pc})
-
-ENTRY(__up_wakeup)
-	stmfd	sp!, {r0 - r3, ip, lr}
-	bl	SYMBOL_NAME(__up)
-	LOADREGS(fd, sp!, {r0 - r3, ip, pc})
diff -u --recursive --new-file v2.3.15/linux/arch/arm/mm/Makefile linux/arch/arm/mm/Makefile
--- v2.3.15/linux/arch/arm/mm/Makefile	Sat May  8 11:06:56 1999
+++ linux/arch/arm/mm/Makefile	Mon Aug 30 18:15:16 1999
@@ -7,26 +7,30 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
-all:	lib first_rule
+O_TARGET	:= mm.o
+O_OBJS		:= init.o extable.o fault-$(PROCESSOR).o small_page.o
 
-O_TARGET := mm.o
-O_OBJS   := init.o extable.o fault-$(PROCESSOR).o small_page.o
-
-ifeq ($(PROCESSOR),armo)
- O_OBJS += proc-arm2,3.o
+ifeq ($(CONFIG_CPU_26),y)
+  O_OBJS	+= proc-arm2,3.o
 endif
 
-ifeq ($(PROCESSOR),armv)
- O_OBJS += mm-$(MACHINE).o proc-arm6,7.o proc-sa110.o ioremap.o
+ifeq ($(CONFIG_CPU_32),y)
+  ifeq ($(CONFIG_CPU_ARM6),y)
+    P_OBJS	+= proc-arm6,7.o
+  endif
+  ifeq ($(CONFIG_CPU_ARM7),y)
+    P_OBJS	+= proc-arm6,7.o
+  endif
+  ifeq ($(CONFIG_CPU_SA110),y)
+    P_OBJS	+= proc-sa110.o
+  endif
+  O_OBJS	+= mm-$(MACHINE).o ioremap.o $(sort $(P_OBJS))
 endif
 
 include $(TOPDIR)/Rules.make
 
 %.o: %.S
 	$(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $<
-
-.PHONY:	lib
-lib:;	@$(MAKE) -C ../lib constants.h
 
 # Special dependencies
 fault-armv.o: fault-common.c
diff -u --recursive --new-file v2.3.15/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c
--- v2.3.15/linux/arch/arm/mm/fault-armv.c	Mon Aug  2 10:19:52 1999
+++ linux/arch/arm/mm/fault-armv.c	Mon Aug 30 18:15:16 1999
@@ -205,6 +205,7 @@
 	return len;
 }
 
+#ifdef CONFIG_SYSCTL
 /*
  * This needs to be done after sysctl_init, otherwise sys/
  * will be overwritten.
@@ -219,6 +220,9 @@
 		e->read_proc = proc_alignment_read;
 }
 
+__initcall(alignment_init);
+#endif
+
 static int
 do_alignment_exception(struct pt_regs *regs)
 {
@@ -405,8 +409,25 @@
 asmlinkage void
 do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
 {
-	if (user_mode(regs))
+	if (user_mode(regs)) {
+		if (addr == regs->ARM_pc) {
+			static int first = 1;
+			if (first) {
+				/*
+				 * I want statistical information on this problem!
+				 */
+				printk(KERN_ERR "Buggy processor (%08X), "
+					"trying to continue.\n"
+					"Please send contents of /proc/cpuinfo "
+					"and this message to linux@arm.linux.org.uk",
+					fsr);
+				first = 0;
+			}
+			return;
+		}
+
 		error_code |= FAULT_CODE_USER;
+	}
 
 #define DIE(signr,nam)\
 		force_sig(signr, current);\
diff -u --recursive --new-file v2.3.15/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c
--- v2.3.15/linux/arch/arm/mm/init.c	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/mm/init.c	Thu Aug 26 12:42:31 1999
@@ -123,7 +123,7 @@
 /*
  * paging_init() sets up the page tables...
  */
-__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem)
 {
 	extern unsigned long free_area_init(unsigned long, unsigned long);
 
@@ -156,7 +156,7 @@
  * memory is free.  This is done after various parts of the system have
  * claimed their memory after the kernel image.
  */
-__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
+void __init mem_init(unsigned long start_mem, unsigned long end_mem)
 {
 	extern void sound_init(void);
 	int codepages = 0;
diff -u --recursive --new-file v2.3.15/linux/arch/arm/mm/ioremap.c linux/arch/arm/mm/ioremap.c
--- v2.3.15/linux/arch/arm/mm/ioremap.c	Sun Jul 25 13:45:25 1999
+++ linux/arch/arm/mm/ioremap.c	Mon Aug 30 18:15:18 1999
@@ -143,7 +143,7 @@
 	return (void *) (offset + (char *)addr);
 }
 
-void iounmap(void *addr)
+void __iounmap(void *addr)
 {
 	return vfree((void *) (PAGE_MASK & (unsigned long) addr));
 }
diff -u --recursive --new-file v2.3.15/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c
--- v2.3.15/linux/arch/arm/mm/mm-armv.c	Sat May  8 11:06:57 1999
+++ linux/arch/arm/mm/mm-armv.c	Thu Aug 26 12:42:31 1999
@@ -25,7 +25,7 @@
 
 #define SIZEOFMAP (sizeof(mapping) / sizeof(mapping[0]))
 
-__initfunc(unsigned long setup_io_pagetables(unsigned long start_mem))
+unsigned long __init setup_io_pagetables(unsigned long start_mem)
 {
 	const struct mapping *mp;
 	int i;
diff -u --recursive --new-file v2.3.15/linux/arch/arm/mm/mm-rpc.c linux/arch/arm/mm/mm-rpc.c
--- v2.3.15/linux/arch/arm/mm/mm-rpc.c	Mon Aug  2 10:19:52 1999
+++ linux/arch/arm/mm/mm-rpc.c	Mon Aug 30 18:15:19 1999
@@ -68,8 +68,8 @@
 	return phys + rambank[bank].phys_offset;
 }
 
-__initfunc(void
-init_dram_banks(struct param_struct *params))
+void __init
+init_dram_banks(struct param_struct *params)
 {
 	unsigned int bank;
 	unsigned int bytes = 0;
diff -u --recursive --new-file v2.3.15/linux/arch/arm/mm/proc-arm2,3.S linux/arch/arm/mm/proc-arm2,3.S
--- v2.3.15/linux/arch/arm/mm/proc-arm2,3.S	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/mm/proc-arm2,3.S	Mon Aug 30 18:15:19 1999
@@ -1,14 +1,14 @@
 /*
- * linux/arch/arm/mm/arm2,3.S: MMU functions for ARM2,3
+ * linux/arch/arm/mm/proc-arm2,3.S: MMU functions for ARM2,3
  *
- * (C) 1997 Russell King
+ * (C) 1997-1999 Russell King
  *
  * These are the low level assembler for performing cache
  * and memory functions on ARM2, ARM250 and ARM3 processors.
  */
 #include <linux/linkage.h>
-
 #include <asm/assembler.h>
+#include <asm/procinfo.h>
 #include "../lib/constants.h"
 
 /*
@@ -424,17 +424,18 @@
 		movs	pc, lr
 
 
+armvlsi_name:	.asciz	"ARM/VLSI"
+_arm2_name:	.asciz	"arm2"
+_arm250_name:	.asciz	"arm250"
+_arm3_name:	.asciz	"arm3"
+
+		.section ".text.init", #alloc, #execinstr
 /*
  * Purpose : Function pointers used to access above functions - all calls
  *	     come through these
  */
-_arm2_name:
-		.ascii	"arm2\0"
-		.align
-
 		.globl	SYMBOL_NAME(arm2_processor_functions)
 SYMBOL_NAME(arm2_processor_functions):
-		.word	_arm2_name			@  0
 		.word	_arm2_switch_to			@  4
 		.word	_arm2_3_data_abort		@  8
 		.word	_arm2_3_check_bugs		@ 12
@@ -448,13 +449,8 @@
 		.word	SYMBOL_NAME(abort)		@ 40
 		.word	_arm2_xchg_4			@ 44
 
-_arm250_name:
-		.ascii	"arm250\0"
-		.align
-
 		.globl	SYMBOL_NAME(arm250_processor_functions)
 SYMBOL_NAME(arm250_processor_functions):
-		.word	_arm250_name			@  0
 		.word	_arm2_switch_to			@  4
 		.word	_arm2_3_data_abort		@  8
 		.word	_arm2_3_check_bugs		@ 12
@@ -468,13 +464,8 @@
 		.word	SYMBOL_NAME(abort)		@ 40
 		.word	_arm3_xchg_4			@ 44
 
-_arm3_name:
-		.ascii	"arm3\0"
-		.align
-
 		.globl	SYMBOL_NAME(arm3_processor_functions)
 SYMBOL_NAME(arm3_processor_functions):
-		.word	_arm3_name			@  0
 		.word	_arm3_switch_to			@  4
 		.word	_arm2_3_data_abort		@  8
 		.word	_arm2_3_check_bugs		@ 12
@@ -487,4 +478,48 @@
 		.word	_arm3_xchg_1			@ 36
 		.word	SYMBOL_NAME(abort)		@ 40
 		.word	_arm3_xchg_4			@ 44
+
+cpu_arm2_info:
+		.long	armvlsi_name
+		.long	_arm2_name
+
+cpu_arm250_info:
+		.long	armvlsi_name
+		.long	_arm250_name
+
+cpu_arm3_info:
+		.long	armvlsi_name
+		.long	_arm3_name
+
+arm2_arch_name:	.asciz	"armv1"
+arm3_arch_name:	.asciz	"armv2"
+arm2_elf_name:	.asciz	"v1"
+arm3_elf_name:	.asciz	"v2"
+		.align
+
+		.section ".proc.info", #alloc
+
+		.long	0x41560200
+		.long	0xfffffff0
+		.long	arm2_arch_name
+		.long	arm2_elf_name
+		.long	0
+		.long	cpu_arm2_info
+		.long	SYMBOL_NAME(arm2_processor_functions)
+
+		.long	0x41560250
+		.long	0xfffffff0
+		.long	arm3_arch_name
+		.long	arm3_elf_name
+		.long	0
+		.long	cpu_arm250_info
+		.long	SYMBOL_NAME(arm250_processor_functions)
+
+		.long	0x41560300
+		.long	0xfffffff0
+		.long	arm3_arch_name
+		.long	arm3_elf_name
+		.long	0
+		.long	cpu_arm3_info
+		.long	SYMBOL_NAME(arm3_processor_functions)
 
diff -u --recursive --new-file v2.3.15/linux/arch/arm/mm/proc-arm6,7.S linux/arch/arm/mm/proc-arm6,7.S
--- v2.3.15/linux/arch/arm/mm/proc-arm6,7.S	Mon Aug  2 10:19:52 1999
+++ linux/arch/arm/mm/proc-arm6,7.S	Mon Aug 30 18:15:19 1999
@@ -1,13 +1,14 @@
 /*
- * linux/arch/arm/mm/arm6.S: MMU functions for ARM6
+ * linux/arch/arm/mm/proc-arm6,7.S: MMU functions for ARM6
  *
- * (C) 1997 Russell King
+ * (C) 1997-1999 Russell King
  *
  * These are the low level assembler for performing cache and TLB
  * functions on the ARM6 & ARM7.
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/procinfo.h>
 #include "../lib/constants.h"
 
 /*
@@ -20,10 +21,24 @@
  *
  * Purpose : Flush all cache lines
  */
-_arm6_7_flush_cache:
+ENTRY(cpu_arm6_flush_cache_all)
+ENTRY(cpu_arm7_flush_cache_all)
+ENTRY(cpu_arm6_flush_cache_area)
+ENTRY(cpu_arm7_flush_cache_area)
+ENTRY(cpu_arm6_flush_cache_entry)
+ENTRY(cpu_arm7_flush_cache_entry)
+ENTRY(cpu_arm6_flush_icache_area)
+ENTRY(cpu_arm7_flush_icache_area)
+ENTRY(cpu_arm6_cache_wback_area)
+ENTRY(cpu_arm7_cache_wback_area)
+ENTRY(cpu_arm6_cache_purge_area)
+ENTRY(cpu_arm7_cache_purge_area)
 		mov	r0, #0
 		mcr	p15, 0, r0, c7, c0, 0		@ flush cache
-_arm6_7_null:
+ENTRY(cpu_arm6_clean_cache_area)
+ENTRY(cpu_arm7_clean_cache_area)
+ENTRY(cpu_arm6_flush_ram_page)
+ENTRY(cpu_arm7_flush_ram_page)
 		mov	pc, lr
 
 /*
@@ -31,7 +46,8 @@
  *
  * Purpose : flush all TLB entries in all caches
  */
-_arm6_7_flush_tlb_all:
+ENTRY(cpu_arm6_flush_tlb_all)
+ENTRY(cpu_arm7_flush_tlb_all)
 		mov	r0, #0
 		mcr	p15, 0, r0, c5, c0, 0		@ flush TLB
 		mov	pc, lr
@@ -45,7 +61,8 @@
  *
  * Purpose : flush a TLB entry
  */
-_arm6_7_flush_tlb_area:
+ENTRY(cpu_arm6_flush_tlb_area)
+ENTRY(cpu_arm7_flush_tlb_area)
 1:		mcr	p15, 0, r0, c6, c0, 0		@ flush TLB
 		add	r0, r0, #4096
 		cmp	r0, r1
@@ -71,7 +88,7 @@
 msg:		.ascii	"DA*%p=%p\n\0"
 		.align
 
-_arm6_data_abort:
+ENTRY(cpu_arm6_data_abort)
 		ldr	r4, [r0]			@ read instruction causing problem
 		mov	r2, r4, lsr #19			@ r2 b1 = L
 		and	r1, r4, #15 << 24
@@ -102,7 +119,7 @@
 		bl	SYMBOL_NAME(panic)
 Lstop:		b	Lstop
 
-_arm7_data_abort:
+ENTRY(cpu_arm7_data_abort)
 		ldr	r4, [r0]			@ read instruction causing problem
 		mov	r2, r4, lsr #19			@ r2 b1 = L
 		and	r1, r4, #15 << 24
@@ -297,12 +314,15 @@
  *
  * Notes   : This processor does not require these
  */
-_arm6_7_check_bugs:
+ENTRY(cpu_arm6_check_bugs)
+ENTRY(cpu_arm7_check_bugs)
 		mrs	ip, cpsr
 		bic	ip, ip, #F_BIT
 		msr	cpsr, ip
-_arm6_7_proc_init:
-_arm6_7_proc_fin:
+ENTRY(cpu_arm6_proc_init)
+ENTRY(cpu_arm7_proc_init)
+ENTRY(cpu_arm6_proc_fin)
+ENTRY(cpu_arm7_proc_fin)
 		mov	pc, lr
 
 /*
@@ -311,7 +331,8 @@
  * Purpose : Perform a task switch, saving the old processes state, and restoring
  *	     the new.
  */
-_arm6_7_set_pgd:
+ENTRY(cpu_arm6_set_pgd)
+ENTRY(cpu_arm7_set_pgd)
 		mov	r1, #0
 		mcr	p15, 0, r1, c7, c0, 0		@ flush cache
 		mcr	p15, 0, r0, c2, c0, 0		@ update page table ptr
@@ -326,7 +347,8 @@
  *
  * Purpose : Set a PMD and flush it out of any WB cache
  */
-_arm6_set_pmd:	and	r2, r1, #11
+ENTRY(cpu_arm6_set_pmd)
+		and	r2, r1, #11
 		teq	r2, #1
 		teqne	r2, #9
 		teqne	r2, #10
@@ -342,7 +364,8 @@
  *
  * Purpose : Set a PMD and flush it out of any WB cache
  */
-_arm7_set_pmd:	tst	r1, #3
+ENTRY(cpu_arm7_set_pmd)
+		tst	r1, #3
 		orrne	r1, r1, #16			@ Updatable bit is always set on ARM7
 		str	r1, [r0]
 		mov	pc, lr
@@ -354,7 +377,8 @@
  * Purpose : Set a PTE and flush it out of any WB cache
  */
 		.align	5
-_arm6_7_set_pte:
+ENTRY(cpu_arm6_set_pte)
+ENTRY(cpu_arm7_set_pte)
 		str	r1, [r0], #-1024		@ linux version
 
 		bic	r2, r1, #0xff0
@@ -381,7 +405,9 @@
  *
  * Notes   : This sets up everything for a reset
  */
-_arm6_7_reset:	mrs	r1, cpsr
+ENTRY(cpu_arm6_reset)
+ENTRY(cpu_arm7_reset)
+		mrs	r1, cpsr
 		orr	r1, r1, #F_BIT|I_BIT
 		msr	cpsr, r1
 		mov	r0, #0
@@ -390,62 +416,145 @@
 		mov	r1, #F_BIT | I_BIT | 3
 		mov	pc, lr
 
+cpu_armvlsi_name:
+		.asciz	"ARM/VLSI"
+cpu_arm6_name:	.asciz	"arm6"
+cpu_arm610_name:
+		.asciz	"arm610"
+cpu_arm7_name:	.asciz	"arm7"
+cpu_arm710_name:
+		.asciz	"arm710"
+		.align
+
+		.section ".text.init", #alloc, #execinstr
+
 /*
  * Purpose : Function pointers used to access above functions - all calls
  *	     come through these
  */
-_arm6_name:	.ascii	"arm6\0"
-		.align
-
+		.type	arm6_processor_functions, #object
 ENTRY(arm6_processor_functions)
-		.word	_arm6_name			@  0
-		.word	_arm6_data_abort		@  4
-		.word	_arm6_7_check_bugs		@  8
-		.word	_arm6_7_proc_init		@ 12
-		.word	_arm6_7_proc_fin		@ 16
-
-		.word	_arm6_7_flush_cache		@ 20
-		.word	_arm6_7_flush_cache		@ 24
-		.word	_arm6_7_flush_cache		@ 28
-		.word	_arm6_7_null			@ 32
-		.word	_arm6_7_flush_cache		@ 36
-		.word	_arm6_7_flush_tlb_all		@ 40
-		.word	_arm6_7_flush_tlb_area		@ 44
-		.word	_arm6_7_set_pgd			@ 48
-		.word	_arm6_set_pmd			@ 52
-		.word	_arm6_7_set_pte			@ 56
-		.word	_arm6_7_reset			@ 60
-		.word	_arm6_7_flush_cache		@ 64
-
-		.word	_arm6_7_flush_cache		@ 68
-		.word	_arm6_7_flush_cache		@ 72
+		.word	cpu_arm6_data_abort
+		.word	cpu_arm6_check_bugs
+		.word	cpu_arm6_proc_init
+		.word	cpu_arm6_proc_fin
+		.word	cpu_arm6_flush_cache_all
+		.word	cpu_arm6_flush_cache_area
+		.word	cpu_arm6_flush_cache_entry
+		.word	cpu_arm6_clean_cache_area
+		.word	cpu_arm6_flush_ram_page
+		.word	cpu_arm6_flush_tlb_all
+		.word	cpu_arm6_flush_tlb_area
+		.word	cpu_arm6_set_pgd
+		.word	cpu_arm6_set_pmd
+		.word	cpu_arm6_set_pte
+		.word	cpu_arm6_reset
+		.word	cpu_arm6_flush_icache_area
+		.word	cpu_arm6_cache_wback_area
+		.word	cpu_arm6_cache_purge_area
+		.size	arm6_processor_functions, . - arm6_processor_functions
 
 /*
  * Purpose : Function pointers used to access above functions - all calls
  *	     come through these
  */
-_arm7_name:	.ascii	"arm7\0"
+		.type	arm7_processor_functions, #object
+ENTRY(arm7_processor_functions)
+		.word	cpu_arm7_data_abort
+		.word	cpu_arm7_check_bugs
+		.word	cpu_arm7_proc_init
+		.word	cpu_arm7_proc_fin
+		.word	cpu_arm7_flush_cache_all
+		.word	cpu_arm7_flush_cache_area
+		.word	cpu_arm7_flush_cache_entry
+		.word	cpu_arm7_clean_cache_area
+		.word	cpu_arm7_flush_ram_page
+		.word	cpu_arm7_flush_tlb_all
+		.word	cpu_arm7_flush_tlb_area
+		.word	cpu_arm7_set_pgd
+		.word	cpu_arm7_set_pmd
+		.word	cpu_arm7_set_pte
+		.word	cpu_arm7_reset
+		.word	cpu_arm7_flush_icache_area
+		.word	cpu_arm7_cache_wback_area
+		.word	cpu_arm7_cache_purge_area
+		.size	arm7_processor_functions, . - arm7_processor_functions
+
+		.type	cpu_arm6_info, #object
+cpu_arm6_info:
+		.long	cpu_armvlsi_name
+		.long	cpu_arm6_name
+		.size	cpu_arm6_info, . - cpu_arm6_info
+
+		.type	cpu_arm610_info, #object
+cpu_arm610_info:
+		.long	cpu_armvlsi_name
+		.long	cpu_arm610_name
+		.size	cpu_arm610_info, . - cpu_Arm610_info
+
+		.type	cpu_arm7_info, #object
+cpu_arm7_info:
+		.long	cpu_armvlsi_name
+		.long	cpu_arm7_name
+		.size	cpu_arm7_info, . - cpu_arm7_info
+
+		.type	cpu_arm710_info, #object
+cpu_arm710_info:
+		.long	cpu_armvlsi_name
+		.long	cpu_arm710_name
+		.size	cpu_arm710_info, . - cpu_arm710_info
+
+		.type	cpu_arch_name, #object
+cpu_arch_name:	.asciz	"armv3"
+		.size	cpu_arch_name, . - cpu_arch_name
+
+		.type	cpu_elf_name, #object
+cpu_elf_name:	.asciz	"v3"
+		.size	cpu_elf_name, . - cpu_elf_name
 		.align
 
-ENTRY(arm7_processor_functions)
-		.word	_arm7_name			@  0
-		.word	_arm7_data_abort		@  4
-		.word	_arm6_7_check_bugs		@  8
-		.word	_arm6_7_proc_init		@ 12
-		.word	_arm6_7_proc_fin		@ 16
-
-		.word	_arm6_7_flush_cache		@ 20
-		.word	_arm6_7_flush_cache		@ 24
-		.word	_arm6_7_flush_cache		@ 28
-		.word	_arm6_7_null			@ 32
-		.word	_arm6_7_flush_cache		@ 36
-		.word	_arm6_7_flush_tlb_all		@ 40
-		.word	_arm6_7_flush_tlb_area		@ 44
-		.word	_arm6_7_set_pgd			@ 48
-		.word	_arm7_set_pmd			@ 52
-		.word	_arm6_7_set_pte			@ 56
-		.word	_arm6_7_reset			@ 60
-		.word	_arm6_7_flush_cache		@ 64
+		.section ".proc.info", #alloc
 
-		.word	_arm6_7_flush_cache		@ 68
-		.word	_arm6_7_flush_cache		@ 72
+		.type	__arm6_proc_info, #object
+__arm6_proc_info:
+		.long	0x41560600
+		.long	0xfffffff0
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP
+		.long	cpu_arm6_info
+		.long	arm6_processor_functions
+		.size	__arm6_proc_info, . - __arm6_proc_info
+
+		.type	__arm610_proc_info, #object
+__arm610_proc_info:
+		.long	0x41560610
+		.long	0xfffffff0
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP
+		.long	cpu_arm610_info
+		.long	arm6_processor_functions
+		.size	__arm610_proc_info, . - __arm610_proc_info
+
+		.type	__arm7_proc_info, #object
+__arm7_proc_info:
+		.long	0x41007000
+		.long	0xffffff00
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP
+		.long	cpu_arm7_info
+		.long	arm7_processor_functions
+		.size	__arm7_proc_info, . - __arm7_proc_info
+
+		.type	__arm710_proc_info, #object
+__arm710_proc_info:
+		.long	0x41007100
+		.long	0xfff8ff00
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP
+		.long	cpu_arm710_info
+		.long	arm7_processor_functions
+		.size	__arm710_proc_info, . - __arm710_proc_info
diff -u --recursive --new-file v2.3.15/linux/arch/arm/mm/proc-sa110.S linux/arch/arm/mm/proc-sa110.S
--- v2.3.15/linux/arch/arm/mm/proc-sa110.S	Mon Aug  2 10:19:52 1999
+++ linux/arch/arm/mm/proc-sa110.S	Mon Aug 30 18:15:19 1999
@@ -1,13 +1,15 @@
 /*
- * linux/arch/arm/mm/sa110.S: MMU functions for SA110
+ * linux/arch/arm/mm/proc-sa110.S: MMU functions for SA110
  *
- * (C) 1997 Russell King
+ * (C) 1997-1999 Russell King
  *
  * These are the low level assembler for performing cache and TLB
  * functions on the sa110.
  */
+#include <linux/config.h>
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/procinfo.h>
 #include <asm/hardware.h>
 #include "../lib/constants.h"
 
@@ -25,9 +27,9 @@
  * Purpose : Flush all cache lines
  */
 		.align	5
-_sa110_flush_cache_all:					@ preserves r0
+ENTRY(cpu_sa110_flush_cache_all)			@ preserves r0
 		mov	r2, #1
-_sa110_flush_cache_all_r2:
+cpu_sa110_flush_cache_all_r2:
 		ldr	r3, =Lclean_switch
 		ldr	ip, =FLUSH_BASE
 		ldr	r1, [r3]
@@ -53,10 +55,10 @@
  * Purpose : clean & flush all cache lines associated with this area of memory
  */
 		.align	5
-_sa110_flush_cache_area:
+ENTRY(cpu_sa110_flush_cache_area)
 		sub	r3, r1, r0
 		cmp	r3, #MAX_AREA_SIZE
-		bgt	_sa110_flush_cache_all_r2
+		bgt	cpu_sa110_flush_cache_all_r2
 1:		mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 		mcr	p15, 0, r0, c7, c6, 1		@ flush D entry
 		add	r0, r0, #32
@@ -78,11 +80,11 @@
  *	     written out to memory (for DMA)
  */
 		.align	5
-_sa110_cache_wback_area:
+ENTRY(cpu_sa110_cache_wback_area)
 		sub	r3, r1, r0
 		cmp	r3, #MAX_AREA_SIZE
 		mov	r2, #0
-		bgt	_sa110_flush_cache_all_r2
+		bgt	cpu_sa110_flush_cache_all_r2
 		bic	r0, r0, #31
 1:		mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 		add	r0, r0, #32
@@ -103,7 +105,7 @@
  *	     start and/or end address are not cache aligned.
  */
 		.align	5
-_sa110_cache_purge_area:
+ENTRY(cpu_sa110_cache_purge_area)
 		tst	r0, #31
 		bic	r0, r0, #31
 		mcrne	p15, 0, r0, c7, c10, 1		@ clean D entry
@@ -121,7 +123,7 @@
  * Purpose : clean & flush an entry
  */
 		.align	5
-_sa110_flush_cache_entry:
+ENTRY(cpu_sa110_flush_cache_entry)
 		mov	r1, #0
 		mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 		mcr	p15, 0, r1, c7, c10, 4		@ drain WB
@@ -134,7 +136,7 @@
  * Purpose : Ensure that physical memory reflects cache at this location
  *	     for page table purposes.
  */
-_sa110_clean_cache_area:
+ENTRY(cpu_sa110_clean_cache_area)
 1:		mcr	p15, 0, r0, c7, c10, 1		@ clean D entry	 (drain is done by TLB fns)
 		add	r0, r0, #32
 		subs	r1, r1, #32
@@ -143,25 +145,24 @@
 
 /*
  * Function: sa110_flush_ram_page (unsigned long page)
- * Params  : address	Area start address
- *	   : size	size of area
- *	   : flags	b0 = I cache as well
- * Purpose : clean & flush all cache lines associated with this area of memory
+ * Params  : page	Area start address
+ * Purpose : clean all cache lines associated with this area of memory
  */
 		.align	5
-_sa110_flush_ram_page:
+ENTRY(cpu_sa110_flush_ram_page)
 		mov	r1, #4096
 1:		mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-		mcr	p15, 0, r0, c7, c6, 1		@ flush D entry
 		add	r0, r0, #32
 		mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
-		mcr	p15, 0, r0, c7, c6, 1		@ flush D entry
 		add	r0, r0, #32
-		subs	r1, r1, #64
+		mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+		add	r0, r0, #32
+		mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
+		add	r0, r0, #32
+		subs	r1, r1, #128
 		bne	1b
 		mov	r0, #0
 		mcr	p15, 0, r0, c7, c10, 4		@ drain WB
-		mcr	p15, 0, r0, c7, c5, 0		@ flush I cache
 		mov	pc, lr
 
 /*
@@ -169,7 +170,7 @@
  * Purpose : flush all TLB entries in all caches
  */
 		.align	5
-_sa110_flush_tlb_all:
+ENTRY(cpu_sa110_flush_tlb_all)
 		mov	r0, #0
 		mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 		mcr	p15, 0, r0, c8, c7, 0		@ flush I & D tlbs
@@ -179,11 +180,11 @@
  * Function: sa110_flush_tlb_area (unsigned long address, unsigned long end, int flags)
  * Params  : address	Area start address
  *	   : end	Area end address
- *	   : flags	b0 = I cache as well
+ *	   : flags	b0 = I-TLB as well
  * Purpose : flush a TLB entry
  */
 		.align	5
-_sa110_flush_tlb_area:
+ENTRY(cpu_sa110_flush_tlb_area)
 		mov	r3, #0
 		mcr	p15, 0, r3, c7, c10, 4		@ drain WB
 1:		cmp	r0, r1
@@ -198,7 +199,7 @@
 		mov	pc, lr
 
 		.align	5
-_sa110_flush_icache_area:
+ENTRY(cpu_sa110_flush_icache_area)
 1:		mcr	p15, 0, r0, c7, c10, 1		@ Clean D entry
 		add	r0, r0, #32
 		subs	r1, r1, #32
@@ -217,7 +218,7 @@
  *	   : r2 != 0 if writing
  */
 		.align	5
-_sa110_data_abort:
+ENTRY(cpu_sa110_data_abort)
 		ldr	r2, [r0]			@ read instruction causing problem
 		mrc	p15, 0, r0, c6, c0, 0		@ get FAR
 		mov	r2, r2, lsr #19			@ b1 = L
@@ -235,7 +236,7 @@
  *	     the new.
  */
 		.align	5
-_sa110_set_pgd:
+ENTRY(cpu_sa110_set_pgd)
 		ldr	r3, =Lclean_switch
 		ldr	r2, [r3]
 		ands	r2, r2, #1
@@ -261,7 +262,8 @@
  * Purpose : Set a PMD and flush it out
  */
 		.align	5
-_sa110_set_pmd:	str	r1, [r0]
+ENTRY(cpu_sa110_set_pmd)
+		str	r1, [r0]
 		mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 		mcr	p15, 0, r0, c7, c10, 4		@ drain WB (TLB bypasses WB)
 		mov	pc, lr
@@ -273,7 +275,8 @@
  * Purpose : Set a PTE and flush it out
  */
 		.align	5
-_sa110_set_pte:	str	r1, [r0], #-1024		@ linux version
+ENTRY(cpu_sa110_set_pte)
+		str	r1, [r0], #-1024		@ linux version
 
 		eor	r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
 
@@ -302,26 +305,27 @@
  *	   : sa110_proc_fin (void)
  * Notes   : This processor does not require these
  */
-_sa110_check_bugs:
+ENTRY(cpu_sa110_check_bugs)
 		mrs	ip, cpsr
 		bic	ip, ip, #F_BIT
 		msr	cpsr, ip
 
-_sa110_proc_init:
-_sa110_proc_fin:
+ENTRY(cpu_sa110_proc_init)
+ENTRY(cpu_sa110_proc_fin)
 		mov	pc, lr
 
 /*
  * Function: sa110_reset
  * Notes   : This sets up everything for a reset
  */
-_sa110_reset:	mrs	r1, cpsr
+ENTRY(cpu_sa110_reset)
+		mrs	r1, cpsr
 		orr	r1, r1, #F_BIT | I_BIT
 		msr	cpsr, r1
 		stmfd	sp!, {r1, lr}
 		mov	r2, #1
-		bl	_sa110_flush_cache_all
-		bl	_sa110_flush_tlb_all
+		bl	cpu_sa110_flush_cache_all
+		bl	cpu_sa110_flush_tlb_all
 		mcr	p15, 0, ip, c7, c7, 0		@ flush I,D caches
 		mrc	p15, 0, r0, c1, c0, 0		@ ctrl register
 		bic	r0, r0, #0x1800
@@ -331,29 +335,60 @@
  * Purpose : Function pointers used to access above functions - all calls
  *	     come through these
  */
-_sa110_name:	.ascii	"sa110\0"
+
+cpu_manu_name:	.asciz	"Intel"
+ENTRY(cpu_sa110_name)
+		.asciz	"sa110"
 		.align
 
+		.section ".text.init", #alloc, #execinstr
+
+		.type	sa110_processor_functions, #object
 ENTRY(sa110_processor_functions)
-		.word	_sa110_name			@  0
-		.word	_sa110_data_abort		@  4
-		.word	_sa110_check_bugs		@  8
-		.word	_sa110_proc_init		@ 12
-		.word	_sa110_proc_fin			@ 16
-
-		.word	_sa110_flush_cache_all		@ 20
-		.word	_sa110_flush_cache_area		@ 24
-		.word	_sa110_flush_cache_entry	@ 28
-		.word	_sa110_clean_cache_area		@ 32
-		.word	_sa110_flush_ram_page		@ 36
-		.word	_sa110_flush_tlb_all		@ 40
-		.word	_sa110_flush_tlb_area		@ 44
-
-		.word	_sa110_set_pgd			@ 48
-		.word	_sa110_set_pmd			@ 52
-		.word	_sa110_set_pte			@ 56
-		.word	_sa110_reset			@ 60
-		.word	_sa110_flush_icache_area	@ 64
+		.word	cpu_sa110_data_abort
+		.word	cpu_sa110_check_bugs
+		.word	cpu_sa110_proc_init
+		.word	cpu_sa110_proc_fin
+		.word	cpu_sa110_flush_cache_all
+		.word	cpu_sa110_flush_cache_area
+		.word	cpu_sa110_flush_cache_entry
+		.word	cpu_sa110_clean_cache_area
+		.word	cpu_sa110_flush_ram_page
+		.word	cpu_sa110_flush_tlb_all
+		.word	cpu_sa110_flush_tlb_area
+		.word	cpu_sa110_set_pgd
+		.word	cpu_sa110_set_pmd
+		.word	cpu_sa110_set_pte
+		.word	cpu_sa110_reset
+		.word	cpu_sa110_flush_icache_area
+		.word	cpu_sa110_cache_wback_area
+		.word	cpu_sa110_cache_purge_area
+
+		.size	sa110_processor_functions, . - sa110_processor_functions
+
+		.type	cpu_sa110_info, #object
+cpu_sa110_info:
+		.long	cpu_manu_name
+		.long	cpu_sa110_name
+		.size	cpu_sa110_info, . - cpu_sa110_info
+
+		.type	cpu_arch_name, #object
+cpu_arch_name:	.asciz	"armv4"
+		.size	cpu_arch_name, . - cpu_arch_name
+
+		.type	cpu_elf_name, #object
+cpu_elf_name:	.asciz	"v4"
+		.size	cpu_elf_name, . - cpu_elf_name
+		.align
 
-		.word	_sa110_cache_wback_area		@ 68
-		.word	_sa110_cache_purge_area		@ 72
+		.section ".proc.info", #alloc, #execinstr
+		.type	__sa110_proc_info,#object
+__sa110_proc_info:
+		.long	0x4401a100
+		.long	0xfffffff0
+		.long	cpu_arch_name
+		.long	cpu_elf_name
+		.long	HWCAP_SWP | HWCAP_HALF
+		.long	cpu_sa110_info
+		.long	sa110_processor_functions
+		.size	__sa110_proc_info, . - __sa110_proc_info
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/config.h linux/arch/arm/nwfpe/config.h
--- v2.3.15/linux/arch/arm/nwfpe/config.h	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/config.h	Mon Aug 30 18:15:19 1999
@@ -1,8 +1,8 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/double_cpdo.c linux/arch/arm/nwfpe/double_cpdo.c
--- v2.3.15/linux/arch/arm/nwfpe/double_cpdo.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/double_cpdo.c	Mon Aug 30 18:15:19 1999
@@ -1,8 +1,8 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/extended_cpdo.c linux/arch/arm/nwfpe/extended_cpdo.c
--- v2.3.15/linux/arch/arm/nwfpe/extended_cpdo.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/extended_cpdo.c	Mon Aug 30 18:15:19 1999
@@ -1,8 +1,8 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/fpa11.c linux/arch/arm/nwfpe/fpa11.c
--- v2.3.15/linux/arch/arm/nwfpe/fpa11.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/fpa11.c	Mon Aug 30 18:15:19 1999
@@ -1,8 +1,8 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/fpa11.h linux/arch/arm/nwfpe/fpa11.h
--- v2.3.15/linux/arch/arm/nwfpe/fpa11.h	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/fpa11.h	Mon Aug 30 18:15:19 1999
@@ -1,8 +1,8 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
     
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/fpa11_cpdo.c linux/arch/arm/nwfpe/fpa11_cpdo.c
--- v2.3.15/linux/arch/arm/nwfpe/fpa11_cpdo.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/fpa11_cpdo.c	Mon Aug 30 18:15:19 1999
@@ -1,8 +1,8 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/fpa11_cpdt.c linux/arch/arm/nwfpe/fpa11_cpdt.c
--- v2.3.15/linux/arch/arm/nwfpe/fpa11_cpdt.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/fpa11_cpdt.c	Mon Aug 30 18:15:19 1999
@@ -1,9 +1,9 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
     (c) Philip Blundell, 1998
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/fpa11_cprt.c linux/arch/arm/nwfpe/fpa11_cprt.c
--- v2.3.15/linux/arch/arm/nwfpe/fpa11_cprt.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/fpa11_cprt.c	Mon Aug 30 18:15:19 1999
@@ -1,9 +1,9 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
     (c) Philip Blundell, 1999
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/fpmodule.c linux/arch/arm/nwfpe/fpmodule.c
--- v2.3.15/linux/arch/arm/nwfpe/fpmodule.c	Mon Jul  5 20:35:17 1999
+++ linux/arch/arm/nwfpe/fpmodule.c	Mon Aug 30 18:15:19 1999
@@ -1,9 +1,9 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
     (c) Philip Blundell, 1998-1999
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -62,7 +62,7 @@
 int fp_printk(const char *,...);
 void fp_send_sig(unsigned long sig, PTASK p, int priv);
 #if LINUX_VERSION_CODE > 0x20115
-MODULE_AUTHOR("Scott Bambrough <scottb@corelcomputer.com>");
+MODULE_AUTHOR("Scott Bambrough <scottb@netwinder.org>");
 MODULE_DESCRIPTION("NWFPE floating point emulator");
 #endif
 
@@ -91,7 +91,7 @@
 {
   static const char szTitle[] = "<4>NetWinder Floating Point Emulator ";
   static const char szVersion[] = "V0.94.1 ";
-  static const char szCopyright[] = "(c) 1998 Corel Computer Corp.\n";
+  static const char szCopyright[] = "(c) 1998-1999 Rebel.com\n";
   C_SYMBOL_NAME(fp_printk)(szTitle);
   C_SYMBOL_NAME(fp_printk)(szVersion);
   C_SYMBOL_NAME(fp_printk)(szCopyright);
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/fpmodule.h linux/arch/arm/nwfpe/fpmodule.h
--- v2.3.15/linux/arch/arm/nwfpe/fpmodule.h	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/fpmodule.h	Mon Aug 30 18:15:19 1999
@@ -1,8 +1,8 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/fpopcode.c linux/arch/arm/nwfpe/fpopcode.c
--- v2.3.15/linux/arch/arm/nwfpe/fpopcode.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/fpopcode.c	Mon Aug 30 18:15:19 1999
@@ -1,8 +1,8 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/fpopcode.h linux/arch/arm/nwfpe/fpopcode.h
--- v2.3.15/linux/arch/arm/nwfpe/fpopcode.h	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/fpopcode.h	Mon Aug 30 18:15:19 1999
@@ -1,8 +1,8 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/fpsr.h linux/arch/arm/nwfpe/fpsr.h
--- v2.3.15/linux/arch/arm/nwfpe/fpsr.h	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/fpsr.h	Mon Aug 30 18:15:19 1999
@@ -1,8 +1,8 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/nwfpe/single_cpdo.c linux/arch/arm/nwfpe/single_cpdo.c
--- v2.3.15/linux/arch/arm/nwfpe/single_cpdo.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/nwfpe/single_cpdo.c	Mon Aug 30 18:15:19 1999
@@ -1,8 +1,8 @@
 /*
     NetWinder Floating Point Emulator
-    (c) Corel Computer Corporation, 1998
+    (c) Rebel.com, 1998-1999
 
-    Direct questions, comments to Scott Bambrough <scottb@corelcomputer.com>
+    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
diff -u --recursive --new-file v2.3.15/linux/arch/arm/vmlinux-armo.lds linux/arch/arm/vmlinux-armo.lds
--- v2.3.15/linux/arch/arm/vmlinux-armo.lds	Sun Sep  6 10:44:47 1998
+++ linux/arch/arm/vmlinux-armo.lds	Wed Dec 31 16:00:00 1969
@@ -1,61 +0,0 @@
-/* ld script to make ARM Linux kernel
- * taken from the i386 version by Russell King
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
- */
-OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")
-OUTPUT_ARCH(arm)
-ENTRY(_start)
-SECTIONS
-{
-  _text = .;			/* Text and read-only data */
-  .text : {
-	*(.text)
-	*(.fixup)
-	*(.gnu.warning)
-	} = 0x9090
-  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
-  .rodata : { *(.rodata) }
-  .kstrtab : { *(.kstrtab) }
-
-  . = ALIGN(16);		/* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
-  __start___ksymtab = .;	/* Kernel symbol table */
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
-
-  _etext = .;			/* End of text section */
-
-  . = ALIGN(8192);
-  .data : {			/* Data */
-	*(.init.task)
-	*(.data)
-	CONSTRUCTORS
-	}
-
-  _edata = .;			/* End of data section */
-
-  . = ALIGN(32768);		/* Init code and data */
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(32768);
-  __init_end = .;
-
-  __bss_start = .;		/* BSS */
-  .bss : {
-	*(.bss)
-	}
-  _end = . ;
-
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
-}
diff -u --recursive --new-file v2.3.15/linux/arch/arm/vmlinux-armo.lds.in linux/arch/arm/vmlinux-armo.lds.in
--- v2.3.15/linux/arch/arm/vmlinux-armo.lds.in	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/vmlinux-armo.lds.in	Mon Aug 30 18:15:19 1999
@@ -0,0 +1,64 @@
+/* ld script to make ARM Linux kernel
+ * taken from the i386 version by Russell King
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+  . = TEXTADDR;
+  _text = .;			/* Text and read-only data */
+  .text : {
+	*(.text)
+	*(.fixup)
+	*(.gnu.warning)
+	} = 0x9090
+  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
+  .rodata : { *(.rodata) }
+  .kstrtab : { *(.kstrtab) }
+
+  . = ALIGN(16);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  __start___ksymtab = .;	/* Kernel symbol table */
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+
+  _etext = .;			/* End of text section */
+
+  . = ALIGN(8192);
+  .data : {			/* Data */
+	*(.init.task)
+	*(.data)
+	CONSTRUCTORS
+	}
+
+  _edata = .;			/* End of data section */
+
+  . = ALIGN(32768);		/* Init code and data */
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  __proc_info_begin = .;
+  .proc.info : { *(.proc.info) }
+  __proc_info_end = .;
+  .data.init : { *(.data.init) }
+  . = ALIGN(32768);
+  __init_end = .;
+
+  __bss_start = .;		/* BSS */
+  .bss : {
+	*(.bss)
+	}
+  _end = . ;
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
diff -u --recursive --new-file v2.3.15/linux/arch/arm/vmlinux-armv.lds linux/arch/arm/vmlinux-armv.lds
--- v2.3.15/linux/arch/arm/vmlinux-armv.lds	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/vmlinux-armv.lds	Wed Dec 31 16:00:00 1969
@@ -1,75 +0,0 @@
-/* ld script to make ARM Linux kernel
- * taken from the i386 version by Russell King
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
- */
-OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")
-OUTPUT_ARCH(arm)
-ENTRY(_start)
-SECTIONS
-{
-  _text = .;			/* Text and read-only data	*/
-  .text : { }			/* Set text start address	*/
-
-  __init_begin = .;		/* Init code and data		*/
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(4096);
-  __init_end = .;
-
-  __ebsa285_begin = .;
-  .text.ebsa285 : { *(.text.ebsa285) }
-  .data.ebsa285 : { *(.data.ebsa285) }
-  . = ALIGN(4096);
-  __ebsa285_end = .;
-
-  __netwinder_begin = .;
-  .text.netwinder : { *(.text.netwinder) }
-  .data.netwinder : { *(.data.netwinder) }
-  . = ALIGN(4096);
-  __netwinder_end = .;
-
-  .text.real : {		/* Real text segment		*/
-	*(.text)
-	*(.fixup)
-	*(.gnu.warning)
-	}
-
-  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
-  .rodata : { *(.rodata) }
-  .kstrtab : { *(.kstrtab) }
-
-  . = ALIGN(16);		/* Exception table		*/
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
-  __start___ksymtab = .;	/* Kernel symbol table		*/
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
-
-  _etext = .;			/* End of text section		*/
-
-  . = ALIGN(8192);
-  .data : {			/* Data				*/
-	*(.init.task)
-	*(.data)
-	CONSTRUCTORS
-	}
-
-  _edata = .;			/* End of data section		*/
-
-  __bss_start = .;		/* BSS				*/
-  .bss : {
-	*(.bss)
-	}
-  _end = . ;
-
-				/* Stabs debugging sections.	*/
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
-}
diff -u --recursive --new-file v2.3.15/linux/arch/arm/vmlinux-armv.lds.in linux/arch/arm/vmlinux-armv.lds.in
--- v2.3.15/linux/arch/arm/vmlinux-armv.lds.in	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/vmlinux-armv.lds.in	Mon Aug 30 18:15:19 1999
@@ -0,0 +1,85 @@
+/* ld script to make ARM Linux kernel
+ * taken from the i386 version by Russell King
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+  . = TEXTADDR;
+  _text = .;			/* Text and read-only data	*/
+  .text : { }			/* Set text start address	*/
+
+  __init_begin = .;		/* Init code and data		*/
+  .text.init : { *(.text.init) }
+  __proc_info_begin = .;
+  .proc.info : { *(.proc.info) }
+  __proc_info_end = .;
+  .data.init : { *(.data.init) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
+  . = ALIGN(4096);
+  __init_end = .;
+
+  __ebsa285_begin = .;
+  .text.ebsa285 : { *(.text.ebsa285) }
+  .data.ebsa285 : { *(.data.ebsa285) }
+  . = ALIGN(4096);
+  __ebsa285_end = .;
+
+  __netwinder_begin = .;
+  .text.netwinder : { *(.text.netwinder) }
+  .data.netwinder : { *(.data.netwinder) }
+  . = ALIGN(4096);
+  __netwinder_end = .;
+
+  .text.real : {		/* Real text segment		*/
+	*(.text)
+	*(.fixup)
+	*(.gnu.warning)
+	}
+
+  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
+  .rodata : { *(.rodata) }
+  .kstrtab : { *(.kstrtab) }
+
+  . = ALIGN(16);		/* Exception table		*/
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  __start___ksymtab = .;	/* Kernel symbol table		*/
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+
+  _etext = .;			/* End of text section		*/
+
+  . = ALIGN(8192);
+  .data : {			/* Data				*/
+	*(.init.task)
+	*(.data)
+	CONSTRUCTORS
+	}
+
+  _edata = .;			/* End of data section		*/
+
+  __bss_start = .;		/* BSS				*/
+  .bss : {
+	*(.bss)
+	}
+  _end = . ;
+
+				/* Stabs debugging sections.	*/
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
diff -u --recursive --new-file v2.3.15/linux/arch/i386/boot/Makefile linux/arch/i386/boot/Makefile
--- v2.3.15/linux/arch/i386/boot/Makefile	Sat Jan  2 10:27:52 1999
+++ linux/arch/i386/boot/Makefile	Mon Aug 30 10:18:40 1999
@@ -51,7 +51,7 @@
 setup.o: setup.s
 	$(AS86) -o $@ $<
 
-setup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h
+setup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h $(TOPDIR)/include/linux/compile.h
 	$(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
 
 bsetup: bsetup.o
@@ -60,7 +60,7 @@
 bsetup.o: bsetup.s
 	$(AS86) -o $@ $<
 
-bsetup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h
+bsetup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h $(TOPDIR)/include/linux/compile.h
 	$(CPP) -D__BIG_KERNEL__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
 
 bootsect: bootsect.o
diff -u --recursive --new-file v2.3.15/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S
--- v2.3.15/linux/arch/i386/boot/setup.S	Thu Aug 26 13:05:34 1999
+++ linux/arch/i386/boot/setup.S	Mon Aug 30 10:47:02 1999
@@ -37,6 +37,7 @@
 #include <linux/version.h>
 #include <linux/compile.h>
 #include <asm/boot.h>
+#include <asm/e820.h>
 
 ! Signature words to ensure LILO loaded us right
 #define SIG1	0xAA55
@@ -59,7 +60,7 @@
 
 entry start
 start:
-	jmp	start_of_setup
+	jmp	trampoline
 ! ------------------------ start of header --------------------------------
 !
 ! SETUP-header, must start at CS:2 (old 0x9020:2)
@@ -119,6 +120,8 @@
 heap_end_ptr:	.word	modelist+1024	! space from here (exclusive) down to
 				! end of setup code can be used by setup
 				! for local heap purposes.
+trampoline:	call	start_of_setup
+		.space	1024
 ! ------------------------ end of header ----------------------------------
 
 start_of_setup:
@@ -245,37 +248,91 @@
 loader_ok:
 ! Get memory size (extended mem, kB)
 
+	xor	eax, eax
+	mov	dword ptr [0x1e0], eax
 #ifndef STANDARD_MEMORY_BIOS_CALL
-	push	ebx
 
-        xor     ebx,ebx		! preload new memory slot with 0k
-        mov	[0x1e0], ebx
+	mov	byte ptr [E820NR], al
 
-        mov     ax,#0xe801
-	int     0x15
-	jc      oldstylemem
+! Try three different memory detection schemes.  First, try
+! e820h, which lets us assemble a memory map, then try e801h,
+! which returns a 32-bit memory size, and finally 88h, which
+! returns 0-64m
+
+! method E820H:
+! the memory map from hell.  e820h returns memory classified into
+! a whole bunch of different types, and allows memory holes and
+! everything.  We scan through this memory map and build a list
+! of the first 32 memory areas, which we return at [E820MAP].
+! 
+
+meme820:
+	mov	edx, #0x534d4150		! ascii `SMAP'
+	xor	ebx, ebx			! continuation counter
+
+	mov	di, #E820MAP			! point into the whitelist
+						! so we can have the bios
+						! directly write into it.
+
+jmpe820:
+	mov	eax, #0x0000e820		! e820, upper word zeroed
+	mov	ecx, #20			! size of the e820rec
+
+	push	ds				! data record.
+	pop	es
+	int	0x15				! make the call
+	jc	bail820				! fall to e801 if it fails
+
+	cmp	eax, #0x534d4150		! check the return is `SMAP'
+	jne	bail820				! fall to e801 if it fails
 
-! Memory size is in 1 k chunksizes, to avoid confusing loadlin.
-! We store the 0xe801 memory size in a completely different place,
+!	cmp	dword ptr [16+di], #1		! is this usable memory?
+!	jne	again820
+	
+	! If this is usable memory, we save it by simply advancing di by
+	! sizeof(e820rec).
+	!
+good820:
+	mov	al, byte ptr [E820NR]	! up to 32 good entries, that is
+	cmp	al, #E820MAX
+	jnl	bail820
+	inc	byte ptr [E820NR]
+	mov	ax, di
+	add	ax, #20
+	mov	di, ax
+
+again820:
+	cmp	ebx, #0			! check to see if ebx is
+	jne	jmpe820			! set to EOF
+
+bail820:
+
+
+! method E801H:
+! memory size is in 1k chunksizes, to avoid confusing loadlin.
+! we store the 0xe801 memory size in a completely different place,
 ! because it will most likely be longer than 16 bits.
 ! (use 1e0 because that's what Larry Augustine uses in his
 ! alternative new memory detection scheme, and it's sensible
 ! to write everything into the same place.)
 
-	and     ebx, #0xffff    ! clear sign extend
-	shl     ebx, 6          ! and go from 64k to 1k chunks
-	mov     [0x1e0],ebx     ! store extended memory size
-
-	and     eax, #0xffff    ! clear sign extend
- 	add     [0x1e0],eax     ! and add lower memory into total size.
-  
-	! and fall into the old memory detection code to populate the
-	! compatibility slot.
+meme801:
+
+        mov     ax,#0xe801
+	int     0x15
+	jc	mem88
+
+	and     edx, #0xffff    ! clear sign extend
+	shl     edx, 6          ! and go from 64k to 1k chunks
+	mov     [0x1e0],edx     ! store extended memory size
+
+	and     ecx, #0xffff    ! clear sign extend
+	add     [0x1e0],ecx     ! and add lower memory into total size.
+
+! Ye Olde Traditional Methode.  Returns the memory size (up to 16mb or
+! 64mb, depending on the bios) in ax.
+mem88:
 
-oldstylemem:
-	pop	ebx
-#else
-	mov     dword ptr [0x1e0], #0
 #endif
 	mov	ah,#0x88
 	int	0x15
diff -u --recursive --new-file v2.3.15/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.3.15/linux/arch/i386/config.in	Thu Aug 26 13:05:34 1999
+++ linux/arch/i386/config.in	Thu Aug 26 13:44:03 1999
@@ -4,6 +4,8 @@
 #
 mainmenu_name "Linux Kernel Configuration"
 
+define_bool CONFIG_X86 y
+
 mainmenu_option next_comment
 comment 'Code maturity level options'
 bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
@@ -54,6 +56,7 @@
 mainmenu_option next_comment
 comment 'General setup'
 
+bool 'BIGMEM support' CONFIG_BIGMEM
 bool 'Networking support' CONFIG_NET
 bool 'PCI support' CONFIG_PCI
 if [ "$CONFIG_PCI" = "y" ]; then
diff -u --recursive --new-file v2.3.15/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.3.15/linux/arch/i386/defconfig	Thu Aug 26 13:05:34 1999
+++ linux/arch/i386/defconfig	Tue Aug 31 11:16:45 1999
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
 #
+CONFIG_X86=y
 
 #
 # Code maturity level options
@@ -37,6 +38,7 @@
 #
 # General setup
 #
+# CONFIG_BIGMEM is not set
 CONFIG_NET=y
 CONFIG_PCI=y
 # CONFIG_PCI_GOBIOS is not set
@@ -176,6 +178,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -276,7 +279,7 @@
 # CONFIG_HAMRADIO is not set
 
 #
-# IrDA subsystem support
+# IrDA (infrared) support
 #
 # CONFIG_IRDA is not set
 
@@ -325,6 +328,8 @@
 #
 # CONFIG_JOYSTICK is not set
 # CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
 
 #
 # Ftape, the floppy tape device driver
@@ -378,8 +383,11 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMD_DISKLABEL is not set
-# CONFIG_SGI_DISKLABEL is not set
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 
 #
diff -u --recursive --new-file v2.3.15/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.3.15/linux/arch/i386/kernel/apm.c	Thu Aug 12 11:53:22 1999
+++ linux/arch/i386/kernel/apm.c	Tue Aug 31 11:30:47 1999
@@ -1077,7 +1077,7 @@
 			return -EAGAIN;
 		add_wait_queue(&apm_waitqueue, &wait);
 repeat:
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (queue_empty(as) && !signal_pending(current)) {
 			schedule();
 			goto repeat;
diff -u --recursive --new-file v2.3.15/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- v2.3.15/linux/arch/i386/kernel/bios32.c	Thu Aug 26 13:05:34 1999
+++ linux/arch/i386/kernel/bios32.c	Tue Aug 31 11:02:26 1999
@@ -760,6 +760,36 @@
 #endif
 
 /*
+ * Assign new address to PCI resource.  We hope our resource information
+ * is complete.  On the PC, we don't re-assign resources unless we are
+ * forced to do so.
+ *
+ * Expects start=0, end=size-1, flags=resource type.
+ */
+
+int __init pcibios_assign_resource(struct pci_dev *dev, int i)
+{
+	struct resource *r = &dev->resource[i];
+	struct resource *pr = pci_find_parent_resource(dev, r);
+	unsigned long size = r->end + 1;
+
+	if (!pr)
+		return -EINVAL;
+	if (r->flags & IORESOURCE_IO) {
+		if (size > 0x100)
+			return -EFBIG;
+		if (allocate_resource(pr, r, size, 0x1000, ~0, 1024))
+			return -EBUSY;
+	} else {
+		if (allocate_resource(pr, r, size, 0x10000000, ~0, size))
+			return -EBUSY;
+	}
+	if (i < 6)
+		pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4*i, r->start);
+	return 0;
+}
+
+/*
  * Several BIOS'es forget to assign addresses to I/O ranges. Try to fix it.
  */
 
@@ -792,12 +822,13 @@
 	} else {
 		u32 try;
 
-		if (allocate_resource(&ioport_resource, r, size, 0x1000, ~0, 1024)) {
+		r->start = 0;
+		r->end = size - 1;
+		if (pcibios_assign_resource(dev, idx)) {
 			printk(KERN_ERR "PCI: Unable to find free %d bytes of I/O space for device %s.\n", size, dev->name);
 			return;
 		}
-		printk("PCI: Assigning I/O space %04lx-%04lx to device %s\n", r->start, r->end, dev->name);
-		pci_write_config_dword(dev, reg, r->start | PCI_BASE_ADDRESS_SPACE_IO);
+		printk("PCI: Assigned I/O space %04lx-%04lx to device %s\n", r->start, r->end, dev->name);
 		pci_read_config_dword(dev, reg, &try);
 		if ((try & PCI_BASE_ADDRESS_IO_MASK) != r->start) {
 			r->start = 0;
@@ -819,12 +850,12 @@
 	struct resource *r = &dev->resource[PCI_ROM_RESOURCE];
 	unsigned long rom_size = r->end - r->start + 1;
 
-	if (allocate_resource(&iomem_resource, r, rom_size, 0xf0000000, ~0, rom_size) < 0) {
+	r->start = 0;
+	r->end = rom_size - 1;
+	if (pcibios_assign_resource(dev, PCI_ROM_RESOURCE))
 		printk(KERN_ERR "PCI: Unable to find free space for expansion ROM of device %s (0x%lx bytes)\n",
 		       dev->name, rom_size);
-		r->start = 0;
-		r->end = rom_size - 1;
-	} else {
+	else {
 		DBG("PCI: Assigned address %08lx to expansion ROM of %s (0x%lx bytes)\n", r->start, dev->name, rom_size);
 		pci_write_config_dword(dev, reg, r->start | PCI_ROM_ADDRESS_ENABLE);
 		r->flags |= PCI_ROM_ADDRESS_ENABLE;
@@ -947,7 +978,8 @@
 		if (found) {
 			printk("PCI: Discovered primary peer bus %02x\n", n);
 			b = pci_scan_bus(n, ops, NULL);
-			n = b->subordinate;
+			if (b)
+				n = b->subordinate;
 		}
 		n++;
 	}
@@ -979,33 +1011,6 @@
 	pci_probe |= PCI_NO_PEER_FIXUP;
 }
 
-static void __init pci_fixup_i440bx(struct pci_dev *d)
-{
-#if 0							    /* Temporarily disabled   FIXME */
-	/*
-	 * i440BX/ZX -- Occupy the AGP bridge windows.
-	 */
-	u16 a, b;
-	u8 u, v;
-	pci_read_config_byte(d, 0x1c, &u);
-	pci_read_config_byte(d, 0x1d, &v);
-	if (v >= u) {
-		a = u<<8;
-		b = ((v-u)<<8) + 0x100;
-		occupy_region(a, a+b, b, 1, &d->dev);
-	}
-	for (u = 0; u < 2; u++) {
-		pci_read_config_word(d, 0x20+(u*4), &a);
-		pci_read_config_word(d, 0x22+(u*4), &b);
-		if (b >= a) {
-			u32 m = a<<16;
-			u32 n = ((b-a)<<16) + 0x100000;
-			occupy_mem_region(m, m+n, n, 1, &d->dev);
-		}
-	}
-#endif
-}
-
 static void __init pci_fixup_umc_ide(struct pci_dev *d)
 {
 	/*
@@ -1021,7 +1026,6 @@
 
 struct pci_fixup pcibios_fixups[] = {
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82451NX,	pci_fixup_i450nx },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443BX_1,	pci_fixup_i440bx },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_UMC,	PCI_DEVICE_ID_UMC_UM8886BF,	pci_fixup_umc_ide },
 	{ 0 }
 };
@@ -1031,20 +1035,28 @@
  * we try to fix up anything.
  */
 
-static void __init pcibios_claim_resources(void)
+static void __init pcibios_claim_resources(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 	int idx;
 
-	for (dev=pci_devices; dev; dev=dev->next)
-		for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
-			struct resource *r = &dev->resource[idx];
-			if (!r->start)
-				continue;
-			if (request_resource((r->flags & PCI_BASE_ADDRESS_SPACE_IO) ? &ioport_resource : &iomem_resource, r) < 0)
-				printk(KERN_ERR "PCI: Address space collision on region %d of device %s\n", idx, dev->name);
-				/* We probably should disable the region, shouldn't we? */
+	while (bus) {
+		for (dev=bus->devices; dev; dev=dev->sibling)
+			for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+				struct resource *r = &dev->resource[idx];
+				struct resource *pr;
+				if (!r->start)
+					continue;
+				pr = pci_find_parent_resource(dev, r);
+				if (!pr || request_resource(pr, r) < 0) {
+					printk(KERN_ERR "PCI: Address space collision on region %d of device %s\n", idx, dev->name);
+					/* We probably should disable the region, shouldn't we? */
+				}
 		}
+		if (bus->children)
+			pcibios_claim_resources(bus->children);
+		bus = bus->next;
+	}
 }
 
 /*
@@ -1190,7 +1202,7 @@
 
 	if (!(pci_probe & PCI_NO_PEER_FIXUP))
 		pcibios_fixup_peer_bridges();
-	pcibios_claim_resources();
+	pcibios_claim_resources(pci_root);
 	pcibios_fixup_devices();
 
 #ifdef CONFIG_PCI_BIOS
diff -u --recursive --new-file v2.3.15/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.3.15/linux/arch/i386/kernel/i386_ksyms.c	Thu Aug 26 13:05:34 1999
+++ linux/arch/i386/kernel/i386_ksyms.c	Thu Aug 26 12:47:12 1999
@@ -88,6 +88,7 @@
 EXPORT_SYMBOL(global_bh_count);
 EXPORT_SYMBOL(global_bh_lock);
 EXPORT_SYMBOL(global_irq_holder);
+EXPORT_SYMBOL(i386_bh_lock);
 EXPORT_SYMBOL(__global_cli);
 EXPORT_SYMBOL(__global_sti);
 EXPORT_SYMBOL(__global_save_flags);
diff -u --recursive --new-file v2.3.15/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.3.15/linux/arch/i386/kernel/io_apic.c	Wed Aug 18 11:11:15 1999
+++ linux/arch/i386/kernel/io_apic.c	Tue Aug 31 11:23:03 1999
@@ -319,7 +319,7 @@
 
 /*
  * Find a specific PCI IRQ entry.
- * Not an initfunc, possibly needed by modules
+ * Not an __init, possibly needed by modules
  */
 static int __init pin_2_irq(int idx, int apic, int pin);
 int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin)
@@ -836,7 +836,7 @@
 }
 
 /*
- * Not an initfunc, needed by the reboot code
+ * Not an __init, needed by the reboot code
  */
 void init_pic_mode(void)
 {
diff -u --recursive --new-file v2.3.15/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.3.15/linux/arch/i386/kernel/irq.c	Thu Aug 26 13:05:34 1999
+++ linux/arch/i386/kernel/irq.c	Mon Aug 30 21:44:16 1999
@@ -71,11 +71,11 @@
  * system. We never hold this lock when we call the actual
  * IRQ handler.
  */
-spinlock_t irq_controller_lock ={0};
+spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
 /*
  * Controller mappings for all interrupt sources:
  */
-irq_desc_t irq_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }};
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }};
 
 /*
  * Special irq handlers.
@@ -125,10 +125,13 @@
 	return p - buf;
 }
 
+
 /*
  * Global interrupt locks for SMP. Allow interrupts to come in on any
  * CPU, yet make cli/sti act globally to protect critical regions..
  */
+spinlock_t i386_bh_lock = SPIN_LOCK_UNLOCKED;
+
 #ifdef __SMP__
 unsigned char global_irq_holder = NO_PROC_ID;
 unsigned volatile int global_irq_lock;
@@ -637,16 +640,22 @@
 
 			/* Found it - now remove it from the list of entries */
 			*pp = action->next;
-			if (irq_desc[irq].action)
-				break;
-			irq_desc[irq].status |= IRQ_DISABLED;
-			irq_desc[irq].handler->shutdown(irq);
-			break;
+			if (!irq_desc[irq].action) {
+				irq_desc[irq].status |= IRQ_DISABLED;
+				irq_desc[irq].handler->shutdown(irq);
+			}
+			spin_unlock_irqrestore(&irq_controller_lock,flags);
+
+			/* Wait to make sure it's not being used on another CPU */
+			while (irq_desc[irq].status & IRQ_INPROGRESS)
+				barrier();
+			kfree(action);
+			return;
 		}
 		printk("Trying to free free IRQ%d\n",irq);
-		break;
+		spin_unlock_irqrestore(&irq_controller_lock,flags);
+		return;
 	}
-	spin_unlock_irqrestore(&irq_controller_lock,flags);
 }
 
 /*
diff -u --recursive --new-file v2.3.15/linux/arch/i386/kernel/semaphore.c linux/arch/i386/kernel/semaphore.c
--- v2.3.15/linux/arch/i386/kernel/semaphore.c	Thu Aug 26 13:05:34 1999
+++ linux/arch/i386/kernel/semaphore.c	Mon Aug 30 09:56:12 1999
@@ -49,8 +49,8 @@
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
-	tsk->state = TASK_UNINTERRUPTIBLE;
-	add_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE;
+	add_wait_queue_exclusive(&sem->wait, &wait);
 
 	spin_lock_irq(&semaphore_lock);
 	sem->sleepers++;
@@ -63,28 +63,28 @@
 		 */
 		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
 			sem->sleepers = 0;
-			wake_up(&sem->wait);
 			break;
 		}
 		sem->sleepers = 1;	/* us - see -1 above */
 		spin_unlock_irq(&semaphore_lock);
 
 		schedule();
-		tsk->state = TASK_UNINTERRUPTIBLE;
+		tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE;
 		spin_lock_irq(&semaphore_lock);
 	}
 	spin_unlock_irq(&semaphore_lock);
 	remove_wait_queue(&sem->wait, &wait);
 	tsk->state = TASK_RUNNING;
+	wake_up(&sem->wait);
 }
 
 int __down_interruptible(struct semaphore * sem)
 {
-	int retval;
+	int retval = 0;
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
-	tsk->state = TASK_INTERRUPTIBLE;
-	add_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE;
+	add_wait_queue_exclusive(&sem->wait, &wait);
 
 	spin_lock_irq(&semaphore_lock);
 	sem->sleepers ++;
@@ -98,12 +98,10 @@
 		 * it has contention. Just correct the count
 		 * and exit.
 		 */
-		retval = -EINTR;
 		if (signal_pending(current)) {
+			retval = -EINTR;
 			sem->sleepers = 0;
-			if (atomic_add_negative(sleepers, &sem->count))
-				break;
-			wake_up(&sem->wait);
+			atomic_add(sleepers, &sem->count);
 			break;
 		}
 
@@ -114,8 +112,6 @@
 		 * the lock.
 		 */
 		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
-			wake_up(&sem->wait);
-			retval = 0;
 			sem->sleepers = 0;
 			break;
 		}
@@ -123,12 +119,13 @@
 		spin_unlock_irq(&semaphore_lock);
 
 		schedule();
-		tsk->state = TASK_INTERRUPTIBLE;
+		tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE;
 		spin_lock_irq(&semaphore_lock);
 	}
 	spin_unlock_irq(&semaphore_lock);
 	tsk->state = TASK_RUNNING;
 	remove_wait_queue(&sem->wait, &wait);
+	wake_up(&sem->wait);
 	return retval;
 }
 
@@ -142,7 +139,7 @@
  */
 int __down_trylock(struct semaphore * sem)
 {
-	int retval, sleepers;
+	int sleepers;
 
 	spin_lock_irq(&semaphore_lock);
 	sleepers = sem->sleepers + 1;
diff -u --recursive --new-file v2.3.15/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.3.15/linux/arch/i386/kernel/setup.c	Thu Aug 26 13:05:34 1999
+++ linux/arch/i386/kernel/setup.c	Mon Aug 30 10:54:05 1999
@@ -17,6 +17,14 @@
  *
  *  IDT Winchip tweaks, misc clean ups.
  *	Dave Jones <dave@powertweak.com>, August 1999
+ *
+ *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ *
+ *  Better detection of Centaur/IDT WinChip models.
+ *      Bart Hartgers <bart@etpmod.phys.tue.nl>, August 1999.
+ *
+ *  Memory region support
+ *	David Parsons <orc@pell.chi.il.us>, July-August 1999
  */
 
 /*
@@ -42,6 +50,7 @@
 #ifdef CONFIG_BLK_DEV_RAM
 #include <linux/blk.h>
 #endif
+#include <linux/bigmem.h>
 #include <asm/processor.h>
 #include <linux/console.h>
 #include <asm/uaccess.h>
@@ -51,6 +60,7 @@
 #include <asm/cobalt.h>
 #include <asm/msr.h>
 #include <asm/desc.h>
+#include <asm/e820.h>
 
 /*
  * Machine setup..
@@ -84,6 +94,8 @@
 	unsigned char table[0];
 };
 
+struct e820map e820 = { 0 };
+
 unsigned char aux_device_present;
 
 #ifdef CONFIG_BLK_DEV_RAM
@@ -103,6 +115,8 @@
 #define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
 #define EXT_MEM_K (*(unsigned short *) (PARAM+2))
 #define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0))
+#define E820_MAP_NR (*(char*) (PARAM+E820NR))
+#define E820_MAP    ((unsigned long *) (PARAM+E820MAP))
 #define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40))
 #define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
 #define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0))
@@ -345,12 +359,80 @@
 	}
 }
 
+unsigned long __init memparse(char *ptr, char **retptr)
+{
+	unsigned long ret;
+
+	ret = simple_strtoul(ptr, retptr, 0);
+
+	if (**retptr == 'K' || **retptr == 'k') {
+		ret <<= 10;
+		(*retptr)++;
+	}
+	else if (**retptr == 'M' || **retptr == 'm') {
+		ret <<= 20;
+		(*retptr)++;
+	}
+	return ret;
+} /* memparse */
+
+
+void __init add_memory_region(unsigned long start,
+                                  unsigned long size, int type)
+{
+	int x = e820.nr_map;
+
+	if (x == E820MAX) {
+	    printk("Ooops! Too many entries in the memory map!\n");
+	    return;
+	}
+
+	e820.map[x].addr = start;
+	e820.map[x].size = size;
+	e820.map[x].type = type;
+	e820.nr_map++;
+} /* add_memory_region */
+
+
+#define LOWMEMSIZE()	((*(unsigned short *)__va(0x413)) * 1024)
+
+
+void __init setup_memory_region(void)
+{
+	/*
+	 * If we're lucky and live on a modern system, the setup code
+	 * will have given us a memory map that we can use to properly
+	 * set up memory.  If we aren't, we'll fake a memory map.
+	 */
+	if (E820_MAP_NR) {
+		/* got a memory map; copy it into a safe place.
+		 */
+		e820.nr_map = E820_MAP_NR;
+		if (e820.nr_map > E820MAX)
+			e820.nr_map = E820MAX;
+		memcpy(e820.map, E820_MAP, e820.nr_map * sizeof e820.map[0]);
+	}
+	else {
+		/* otherwise fake a memory map; one section from 0k->640k,
+		 * the next section from 1mb->appropriate_mem_k
+		 */
+		unsigned long mem_size;
+
+		mem_size = (ALT_MEM_K < EXT_MEM_K) ? EXT_MEM_K : ALT_MEM_K;
+
+		add_memory_region(0, LOWMEMSIZE(), 1);
+		add_memory_region(HIGH_MEMORY, mem_size << 10, 1);
+  	}
+} /* setup_memory_region */
+
+
 void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
 	unsigned long memory_start, memory_end;
 	char c = ' ', *to = command_line, *from = COMMAND_LINE;
 	int len = 0;
 	int i;
+	int usermem=0;
 
 #ifdef CONFIG_VISWS
 	visws_get_board_type_and_rev();
@@ -367,24 +449,14 @@
 		BIOS_revision = SYS_DESC_TABLE.table[2];
 	}
 	aux_device_present = AUX_DEVICE_INFO;
-	memory_end = (1<<20) + (EXT_MEM_K<<10);
-#ifndef STANDARD_MEMORY_BIOS_CALL
-	{
-		unsigned long memory_alt_end = (1<<20) + (ALT_MEM_K<<10);
-		/* printk(KERN_DEBUG "Memory sizing: %08x %08x\n", memory_end, memory_alt_end); */
-		if (memory_alt_end > memory_end)
-			memory_end = memory_alt_end;
-	}
-#endif
-
-	ram_resources[1].end = memory_end-1;
 
-	memory_end &= PAGE_MASK;
 #ifdef CONFIG_BLK_DEV_RAM
 	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
 	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
 	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 #endif
+	setup_memory_region();
+
 	if (!MOUNT_ROOT_RDONLY)
 		root_mountflags &= ~MS_RDONLY;
 	memory_start = (unsigned long) &_end;
@@ -405,8 +477,10 @@
 	for (;;) {
 		/*
 		 * "mem=nopentium" disables the 4MB page tables.
-		 * "mem=XXX[kKmM]" overrides the BIOS-reported
-		 * memory size
+		 * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
+		 * to <mem>, overriding the bios size.
+		 * "mem=XXX[KkmM]@XXX[KkmM]" defines a memory region from
+		 * <start> to <start>+<mem>, overriding the bios size.
 		 */
 		if (c == ' ' && *(const unsigned long *)from == *(const unsigned long *)"mem=") {
 			if (to != command_line) to--;
@@ -414,16 +488,29 @@
 				from += 9+4;
 				boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE;
 			} else {
-				memory_end = simple_strtoul(from+4, &from, 0);
-				if ( *from == 'K' || *from == 'k' ) {
-					memory_end = memory_end << 10;
-					from++;
-				} else if ( *from == 'M' || *from == 'm' ) {
-					memory_end = memory_end << 20;
-					from++;
+				/* If the user specifies memory size, we
+				 * blow away any automatically generated
+				 * size
+				 */
+				unsigned long start_at, mem_size;
+ 
+				if (usermem == 0) {
+					/* first time in: zap the whitelist
+					 * and reinitialize it with the
+					 * standard low-memory region.
+					 */
+					e820.nr_map = 0;
+					usermem = 1;
+					add_memory_region(0, LOWMEMSIZE(), 1);
 				}
-				if (memory_end > ram_resources[1].end)
-					ram_resources[1].end = memory_end-1;
+				mem_size = memparse(from+4, &from);
+				if (*from == '@')
+					start_at = memparse(from+1,&from);
+				else {
+					start_at = HIGH_MEMORY;
+					mem_size -= HIGH_MEMORY;
+				}
+				add_memory_region(start_at, mem_size, 1);
 			}
 		}
 		c = *(from++);
@@ -436,23 +523,47 @@
 	*to = '\0';
 	*cmdline_p = command_line;
 
-	/* Request the standard RAM and ROM resources - they eat up PCI memory space */
-	request_resource(&iomem_resource, ram_resources+0);
-	request_resource(&iomem_resource, ram_resources+1);
-	request_resource(&iomem_resource, ram_resources+2);
-	request_resource(ram_resources+1, &code_resource);
-	request_resource(ram_resources+1, &data_resource);
-	probe_roms();
-
 #define VMALLOC_RESERVE	(128 << 20)	/* 128MB for vmalloc and initrd */
 #define MAXMEM	((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
 
+	memory_end = 0;
+	for (i=0; i < e820.nr_map; i++) {
+		/* RAM? */
+		if (e820.map[i].type == 1) {
+			unsigned long end = e820.map[i].addr + e820.map[i].size;
+
+			if (end > memory_end)
+				memory_end = end;
+		}
+	}
+	memory_end &= PAGE_MASK;
+	ram_resources[1].end = memory_end-1;
+
+#ifdef CONFIG_BIGMEM
+	bigmem_start = bigmem_end = memory_end;
+#endif
 	if (memory_end > MAXMEM)
 	{
+#ifdef CONFIG_BIGMEM
+#define MAXBIGMEM ((unsigned long)(~(VMALLOC_RESERVE-1)))
+		bigmem_start = MAXMEM;
+		bigmem_end = (memory_end < MAXBIGMEM) ? memory_end : MAXBIGMEM;
+#endif
 		memory_end = MAXMEM;
+#ifdef CONFIG_BIGMEM
+		printk(KERN_NOTICE "%ldMB BIGMEM available.\n",
+			(bigmem_end-bigmem_start)>>20);
+#else
 		printk(KERN_WARNING "Warning only %ldMB will be used.\n",
 			MAXMEM>>20);
+#endif
 	}
+#if defined(CONFIG_BIGMEM) && defined(BIGMEM_DEBUG)
+	else {
+		memory_end -= memory_end/4;
+		bigmem_start = memory_end;
+	}
+#endif
 
 	memory_end += PAGE_OFFSET;
 	*memory_start_p = memory_start;
@@ -478,6 +589,17 @@
 	}
 #endif
 
+	/*
+	 * Request the standard RAM and ROM resources -
+	 * they eat up PCI memory space
+	 */
+	request_resource(&iomem_resource, ram_resources+0);
+	request_resource(&iomem_resource, ram_resources+1);
+	request_resource(&iomem_resource, ram_resources+2);
+	request_resource(ram_resources+1, &code_resource);
+	request_resource(ram_resources+1, &data_resource);
+	probe_roms();
+
 	/* request I/O space for devices used on all i[345]86 PCs */
 	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
 		request_resource(&ioport_resource, standard_io_resources+i);
@@ -769,6 +891,98 @@
 	return;
 }
 
+static void __init centaur_model(struct cpuinfo_x86 *c)
+{
+	enum {
+		ECX8=1<<1,
+		EIERRINT=1<<2,
+		DPM=1<<3,
+		DMCE=1<<4,
+		DSTPCLK=1<<5,
+		ELINEAR=1<<6,
+		DSMC=1<<7,
+		DTLOCK=1<<8,
+		EDCTLB=1<<8,
+		EMMX=1<<9,
+		DPDC=1<<11,
+		EBRPRED=1<<12,
+		DIC=1<<13,
+		DDC=1<<14,
+		DNA=1<<15,
+		ERETSTK=1<<16,
+		E2MMX=1<<19,
+		EAMD3D=1<<20,
+	};
+
+	char *name;
+	u32  fcr_set=0;
+	u32  fcr_clr=0;
+	u32  lo,hi,newlo;
+	u32  aa,bb,cc,dd;
+
+	switch(c->x86_model) {
+	case 4:
+		name="C6";
+		fcr_set=ECX8|DSMC|EDCTLB|EMMX|ERETSTK;
+		fcr_clr=DPDC;
+		break;
+	case 8:
+		switch(c->x86_mask) {
+		default:
+			name="2";
+			break;
+		case 7 ... 9:
+			name="2A";
+			break;
+		case 10 ... 15:
+			name="2B";
+			break;
+		}
+		fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;
+		fcr_clr=DPDC;
+		break;
+	case 9:
+		name="3";
+		fcr_set=ECX8|DSMC|DTLOCK|EMMX|EBRPRED|ERETSTK|E2MMX|EAMD3D;
+		fcr_clr=DPDC;
+		break;
+	case 10:
+		name="4";
+		/* no info on the WC4 yet */
+		break;
+	default:
+		name="??";
+	}
+
+	/* get FCR  */
+	rdmsr(0x107, lo, hi);
+
+	newlo=(lo|fcr_set) & (~fcr_clr);
+
+	if (newlo!=lo) {
+		printk("Centaur FCR was 0x%X now 0x%X\n", lo, newlo );
+		wrmsr(0x107, newlo, hi );
+	} else {
+		printk("Centaur FCR is 0x%X\n",lo);
+	}
+
+	/* Emulate MTRRs using Centaur's MCR. */
+	c->x86_capability |= X86_FEATURE_MTRR;
+	/* Report CX8 */
+	c->x86_capability |= X86_FEATURE_CX8;
+	/* Set 3DNow! on Winchip 2 and above. */
+	if (c->x86_model >=8)
+		c->x86_capability |= X86_FEATURE_AMD3D;
+	/* See if we can find out some more. */
+	cpuid(0x80000000,&aa,&bb,&cc,&dd);
+	if (aa>=0x80000005) { /* Yes, we can. */
+		cpuid(0x80000005,&aa,&bb,&cc,&dd);
+		/* Add L1 data and code cache sizes. */
+		c->x86_cache_size = (cc>>24)+(dd>>24);
+	}
+	sprintf( c->x86_model_id, "WinChip %s", name );
+}
+
 void __init get_cpu_vendor(struct cpuinfo_x86 *c)
 {
 	char *v = c->x86_vendor_id;
@@ -826,9 +1040,6 @@
 	{ X86_VENDOR_UMC,	4,
 	  { NULL, "U5D", "U5S", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	    NULL, NULL, NULL, NULL, NULL, NULL }},
-	{ X86_VENDOR_CENTAUR,	5,
-	  { NULL, NULL, NULL, NULL, "C6", NULL, NULL, NULL, "C6-2", NULL, NULL,
-	    NULL, NULL, NULL, NULL, NULL }},
 	{ X86_VENDOR_NEXGEN,	5,
 	  { "Nx586", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	    NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
@@ -855,6 +1066,11 @@
 
 	if (c->x86_vendor == X86_VENDOR_AMD && amd_model(c))
 		return;
+
+	if (c->x86_vendor == X86_VENDOR_CENTAUR) {
+		centaur_model(c);
+		return;
+	}
 		
 	if (c->cpuid_level > 0 && c->x86_vendor == X86_VENDOR_INTEL)
 	{
@@ -981,24 +1197,6 @@
 
 	if (c->x86_mask || c->cpuid_level>=0) 
 		printk(" stepping %02x\n", c->x86_mask);
-
-	if(c->x86_vendor == X86_VENDOR_CENTAUR) {
-		u32 hv,lv;
-		rdmsr(0x107, lv, hv);
-		printk("Centaur FSR was 0x%X ",lv);
-		lv|=(1<<1 | 1<<2 | 1<<7);
-		/* lv|=(1<<6);	- may help too if the board can cope */
-		printk("now 0x%X\n", lv);
-		wrmsr(0x107, lv, hv);
-		/* Emulate MTRRs using Centaur's MCR. */
-		c->x86_capability |= X86_FEATURE_MTRR;
-
-		/* Set 3DNow! on Winchip 2 and above. */
-		if (c->x86_model >=8)
-		    c->x86_capability |= X86_FEATURE_AMD3D;
-
-		c->x86_capability |=X86_FEATURE_CX8;
-	}
 }
 
 /*
diff -u --recursive --new-file v2.3.15/linux/arch/i386/kernel/visws_apic.c linux/arch/i386/kernel/visws_apic.c
--- v2.3.15/linux/arch/i386/kernel/visws_apic.c	Sun Jul 11 15:09:29 1999
+++ linux/arch/i386/kernel/visws_apic.c	Tue Aug 31 11:23:03 1999
@@ -102,7 +102,7 @@
 
 
 /*
- * Not an initfunc, needed by the reboot code
+ * Not an __init, needed by the reboot code
  */
 void init_pic_mode(void)
 {
diff -u --recursive --new-file v2.3.15/linux/arch/i386/math-emu/div_Xsig.S linux/arch/i386/math-emu/div_Xsig.S
--- v2.3.15/linux/arch/i386/math-emu/div_Xsig.S	Thu Oct  5 06:30:43 1995
+++ linux/arch/i386/math-emu/div_Xsig.S	Fri Aug 27 10:18:17 1999
@@ -55,7 +55,7 @@
 	Local storage in a static area:
 	Accumulator:	FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0
  */
-	.align 2,0
+	.align 4,0
 FPU_accum_3:
 	.long	0
 FPU_accum_2:
diff -u --recursive --new-file v2.3.15/linux/arch/i386/math-emu/reg_round.S linux/arch/i386/math-emu/reg_round.S
--- v2.3.15/linux/arch/i386/math-emu/reg_round.S	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/reg_round.S	Fri Aug 27 10:18:17 1999
@@ -95,7 +95,7 @@
 /*	Not re-entrant, so we can gain speed by putting
 	local storage in a static area: */
 .data
-	.align 2,0
+	.align 4,0
 FPU_bits_lost:
 	.byte	0
 FPU_denormal:
diff -u --recursive --new-file v2.3.15/linux/arch/i386/math-emu/reg_u_div.S linux/arch/i386/math-emu/reg_u_div.S
--- v2.3.15/linux/arch/i386/math-emu/reg_u_div.S	Tue Dec  9 17:57:09 1997
+++ linux/arch/i386/math-emu/reg_u_div.S	Fri Aug 27 10:18:17 1999
@@ -52,7 +52,7 @@
 	Result:		FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0
 	Overflow flag:	ovfl_flag
  */
-	.align 2,0
+	.align 4,0
 FPU_accum_3:
 	.long	0
 FPU_accum_2:
diff -u --recursive --new-file v2.3.15/linux/arch/i386/mm/Makefile linux/arch/i386/mm/Makefile
--- v2.3.15/linux/arch/i386/mm/Makefile	Fri Nov  1 01:56:43 1996
+++ linux/arch/i386/mm/Makefile	Thu Aug 26 12:34:55 1999
@@ -10,4 +10,8 @@
 O_TARGET := mm.o
 O_OBJS	 := init.o fault.o ioremap.o extable.o
 
+ifeq ($(CONFIG_BIGMEM),y)
+O_OBJS += bigmem.o
+endif
+
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.15/linux/arch/i386/mm/bigmem.c linux/arch/i386/mm/bigmem.c
--- v2.3.15/linux/arch/i386/mm/bigmem.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/i386/mm/bigmem.c	Thu Aug 26 12:34:55 1999
@@ -0,0 +1,33 @@
+/*
+ * BIGMEM IA32 code and variables.
+ *
+ * (C) 1999 Andrea Arcangeli, SuSE GmbH, andrea@suse.de
+ *          Gerhard Wichert, Siemens AG, Gerhard.Wichert@pdb.siemens.de
+ */
+
+#include <linux/mm.h>
+#include <linux/bigmem.h>
+
+unsigned long bigmem_start, bigmem_end;
+
+/* NOTE: fixmap_init alloc all the fixmap pagetables contigous on the
+   physical space so we can cache the place of the first one and move
+   around without checking the pgd every time. */
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
+
+#define kmap_get_fixmap_pte(vaddr)					\
+	pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
+
+void __init kmap_init(void)
+{
+	unsigned long kmap_vstart;
+
+	/* cache the first kmap pte */
+	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+
+	kmap_prot = PAGE_KERNEL;
+	if (boot_cpu_data.x86_capability & X86_FEATURE_PGE)
+		pgprot_val(kmap_prot) |= _PAGE_GLOBAL;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.3.15/linux/arch/i386/mm/init.c	Thu Aug 26 13:05:34 1999
+++ linux/arch/i386/mm/init.c	Mon Aug 30 10:47:02 1999
@@ -2,6 +2,8 @@
  *  linux/arch/i386/mm/init.c
  *
  *  Copyright (C) 1995  Linus Torvalds
+ *
+ *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
  */
 
 #include <linux/config.h>
@@ -20,6 +22,7 @@
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/blk.h>
 #endif
+#include <linux/bigmem.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -27,8 +30,10 @@
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 #include <asm/fixmap.h>
+#include <asm/e820.h>
 
 static unsigned long totalram = 0;
+static unsigned long totalbig = 0;
 
 extern void show_net_buffers(void);
 extern unsigned long init_smp_mappings(unsigned long);
@@ -150,6 +155,7 @@
 {
 	int i,free = 0,total = 0,reserved = 0;
 	int shared = 0, cached = 0;
+	int bigmem = 0;
 
 	printk("Mem-info:\n");
 	show_free_areas();
@@ -157,6 +163,8 @@
 	i = max_mapnr;
 	while (i-- > 0) {
 		total++;
+		if (PageBIGMEM(mem_map+i))
+			bigmem++;
 		if (PageReserved(mem_map+i))
 			reserved++;
 		else if (PageSwapCache(mem_map+i))
@@ -167,6 +175,7 @@
 			shared += page_count(mem_map+i) - 1;
 	}
 	printk("%d pages of RAM\n",total);
+	printk("%d pages of BIGMEM\n",bigmem);
 	printk("%d reserved pages\n",reserved);
 	printk("%d pages shared\n",shared);
 	printk("%d pages swap cached\n",cached);
@@ -238,7 +247,7 @@
  * This routines also unmaps the page at virtual kernel address 0, so
  * that we can trap those pesky NULL-reference errors in the kernel.
  */
-__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem)
 {
 	pgd_t * pg_dir;
 	pte_t * pg_table;
@@ -315,7 +324,12 @@
 #endif
 	local_flush_tlb();
 
+#ifndef CONFIG_BIGMEM
 	return free_area_init(start_mem, end_mem);
+#else
+	kmap_init(); /* run after fixmap_init */
+	return free_area_init(start_mem, bigmem_end + PAGE_OFFSET);
+#endif
 }
 
 /*
@@ -324,7 +338,7 @@
  * before and after the test are here to work-around some nasty CPU bugs.
  */
 
-__initfunc(void test_wp_bit(void))
+void __init test_wp_bit(void)
 {
 	unsigned char tmp_reg;
 	unsigned long old = pg0[0];
@@ -353,7 +367,7 @@
 		printk(".\n");
 }
 
-__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
+void __init mem_init(unsigned long start_mem, unsigned long end_mem)
 {
 	unsigned long start_low_mem = PAGE_SIZE;
 	int codepages = 0;
@@ -361,11 +375,22 @@
 	int datapages = 0;
 	int initpages = 0;
 	unsigned long tmp;
-	unsigned long endbase;
+	unsigned long addr;
+	int i, avail;
 
 	end_mem &= PAGE_MASK;
+#ifdef CONFIG_BIGMEM
+	bigmem_start = PAGE_ALIGN(bigmem_start);
+	bigmem_end &= PAGE_MASK;
+#endif
 	high_memory = (void *) end_mem;
+#ifndef CONFIG_BIGMEM
 	max_mapnr = num_physpages = MAP_NR(end_mem);
+#else
+	max_mapnr = num_physpages = PHYSMAP_NR(bigmem_end);
+	/* cache the bigmem_mapnr */
+	bigmem_mapnr = PHYSMAP_NR(bigmem_start);
+#endif
 
 	/* clear the zero-page */
 	memset(empty_zero_page, 0, PAGE_SIZE);
@@ -385,23 +410,43 @@
 #endif
 	start_mem = PAGE_ALIGN(start_mem);
 
-	/*
-	 * IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000.
-	 * They seem to have done something stupid with the floppy
-	 * controller as well..
-	 * The amount of available base memory is in WORD 40:13. Except
-	 * when it isn't.
+	/* walk the whitelist, unreserving good memory
 	 */
-	endbase = PAGE_OFFSET + 0x9f000;
-	while (start_low_mem < endbase) {
-		clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags);
-		start_low_mem += PAGE_SIZE;
-	}
+	for (avail = i = 0; i < e820.nr_map; i++) {
+		if (e820.map[i].type != 1)	/* not usable memory */
+			continue;
+		printk("memory region: %luk @ %08lx\n",
+				    ((long)(e820.map[i].size)) / 1024,
+				    (long)(e820.map[i].addr) );
+		for (addr=PAGE_ALIGN(((long)(e820.map[i].addr)))+PAGE_OFFSET,
+								     tmp = 0;
+				     tmp < (unsigned long)(e820.map[i].size);
+							    tmp += PAGE_SIZE,
+							   addr += PAGE_SIZE) {
+
+			/* this little bit of grossness is for dealing
+			 * with memory borrowing for system bookkeeping
+			 * (smp stacks, zero page, kernel code, etc)
+			 * without having to go back and edit the e820
+			 * map to compensate.
+			 *
+			 * if we're in low memory (<1024k), we need to
+			 * avoid the smp stack and zero page.
+			 * if we're in high memory, we need to avoid
+			 * the kernel code.
+			 * in any case, we don't want to hack mem_map
+			 * entries above end_mem.
+			 */
+			if ( (addr < start_low_mem)
+			  || (addr >= HIGH_MEMORY && addr <= start_mem)
+			  || (addr > end_mem) )
+				continue;
 
-	while (start_mem < end_mem) {
-		clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
-		start_mem += PAGE_SIZE;
+			avail++;
+			clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags);
+		}
 	}
+
 	for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) {
 		if (tmp >= MAX_DMA_ADDRESS)
 			clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
@@ -424,21 +469,33 @@
 		set_page_count(mem_map+MAP_NR(tmp), 1);
 		totalram += PAGE_SIZE;
 #ifdef CONFIG_BLK_DEV_INITRD
-		if (!initrd_start || (tmp < initrd_start || tmp >=
-		    initrd_end))
+		if (!initrd_start || (tmp < initrd_start || tmp >= initrd_end))
 #endif
 			free_page(tmp);
 	}
-	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+#ifdef CONFIG_BIGMEM
+	for (tmp = bigmem_start; tmp < bigmem_end;  tmp += PAGE_SIZE) {
+		clear_bit(PG_reserved, &mem_map[PHYSMAP_NR(tmp)].flags);
+		set_bit(PG_BIGMEM, &mem_map[PHYSMAP_NR(tmp)].flags);
+		atomic_set(&mem_map[PHYSMAP_NR(tmp)].count, 1);
+		free_page(tmp + PAGE_OFFSET);
+		totalbig += PAGE_SIZE;
+	}
+	totalram += totalbig;
+#endif
+	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %dk bigmem)\n",
 		(unsigned long) nr_free_pages << (PAGE_SHIFT-10),
 		max_mapnr << (PAGE_SHIFT-10),
 		codepages << (PAGE_SHIFT-10),
 		reservedpages << (PAGE_SHIFT-10),
 		datapages << (PAGE_SHIFT-10),
-		initpages << (PAGE_SHIFT-10));
+		initpages << (PAGE_SHIFT-10),
+	        (int) (totalbig >> 10)
+	       );
 
 	if (boot_cpu_data.wp_works_ok < 0)
 		test_wp_bit();
+
 }
 
 void free_initmem(void)
@@ -461,5 +518,7 @@
 	val->sharedram = 0;
 	val->freeram = nr_free_pages << PAGE_SHIFT;
 	val->bufferram = atomic_read(&buffermem);
+	val->totalbig = totalbig;
+	val->freebig = nr_free_bigpages << PAGE_SHIFT;
 	return;
 }
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/amiga/amisound.c linux/arch/m68k/amiga/amisound.c
--- v2.3.15/linux/arch/m68k/amiga/amisound.c	Mon Jun 16 16:35:53 1997
+++ linux/arch/m68k/amiga/amisound.c	Thu Aug 26 12:42:31 1999
@@ -40,7 +40,7 @@
 
 static u_long clock_constant;
 
-__initfunc(void amiga_init_sound(void))
+void __init amiga_init_sound(void)
 {
 	snd_data = amiga_chip_alloc(sizeof(sine_data));
 	if (!snd_data) {
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/amiga/chipram.c linux/arch/m68k/amiga/chipram.c
--- v2.3.15/linux/arch/m68k/amiga/chipram.c	Thu Aug 26 13:05:34 1999
+++ linux/arch/m68k/amiga/chipram.c	Thu Aug 26 12:42:31 1999
@@ -32,7 +32,7 @@
 }
 
 
-__initfunc(void amiga_chip_init (void))
+void __init amiga_chip_init (void)
 {
   struct chip_desc *dp;
 
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/atari/ataints.c linux/arch/m68k/atari/ataints.c
--- v2.3.15/linux/arch/m68k/atari/ataints.c	Mon Oct  5 13:54:39 1998
+++ linux/arch/m68k/atari/ataints.c	Thu Aug 26 12:42:31 1999
@@ -327,7 +327,7 @@
  * the atari IRQ handling routines.
  */
 
-__initfunc(void atari_init_IRQ(void))
+void __init atari_init_IRQ(void)
 {
 	int i;
 
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/atari/atakeyb.c linux/arch/m68k/atari/atakeyb.c
--- v2.3.15/linux/arch/m68k/atari/atakeyb.c	Mon Apr 26 13:35:34 1999
+++ linux/arch/m68k/atari/atakeyb.c	Thu Aug 26 12:42:31 1999
@@ -762,7 +762,7 @@
  * Martin Rogge, 20 Aug 1995
  */
  
-__initfunc(int atari_keyb_init(void))
+int __init atari_keyb_init(void)
 {
     /* setup key map */
     memcpy(key_maps[0], ataplain_map, sizeof(plain_map));
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/atari/config.c linux/arch/m68k/atari/config.c
--- v2.3.15/linux/arch/m68k/atari/config.c	Tue Jan 19 10:58:26 1999
+++ linux/arch/m68k/atari/config.c	Thu Aug 26 12:42:31 1999
@@ -111,8 +111,8 @@
  */
   
 #if 0
-__initfunc(static int
-hwreg_present_bywrite(volatile void *regp, unsigned char val))
+static int __init
+hwreg_present_bywrite(volatile void *regp, unsigned char val)
 {
     int		ret;
     long	save_sp, save_vbr;
@@ -150,7 +150,7 @@
  * should be readable without trouble (from channel A!).
  */
 
-__initfunc(static int scc_test( volatile char *ctla ))
+static int __init scc_test( volatile char *ctla )
 {
 	if (!hwreg_present( ctla ))
 		return( 0 );
@@ -177,7 +177,7 @@
      *  Parse an Atari-specific record in the bootinfo
      */
 
-__initfunc(int atari_parse_bootinfo(const struct bi_record *record))
+int __init atari_parse_bootinfo(const struct bi_record *record)
 {
     int unknown = 0;
     const u_long *data = record->data;
@@ -197,7 +197,7 @@
 
 
 /* Parse the Atari-specific switches= option. */
-__initfunc(void atari_switches_setup( const char *str, unsigned len ))
+void __init atari_switches_setup( const char *str, unsigned len )
 {
     char switches[len+1];
     char *p;
@@ -238,7 +238,7 @@
      *  Setup the Atari configuration info
      */
 
-__initfunc(void config_atari(void))
+void __init config_atari(void)
 {
     unsigned short tos_version;
 
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/atari/debug.c linux/arch/m68k/atari/debug.c
--- v2.3.15/linux/arch/m68k/atari/debug.c	Thu Feb 12 16:30:12 1998
+++ linux/arch/m68k/atari/debug.c	Thu Aug 26 12:42:31 1999
@@ -168,7 +168,7 @@
  * SCC serial ports. They're used by the debugging interface, kgdb, and the
  * serial console code. */
 #ifndef CONFIG_SERIAL_CONSOLE
-__initfunc(static void atari_init_mfp_port( int cflag ))
+static void __init atari_init_mfp_port( int cflag )
 #else
 void atari_init_mfp_port( int cflag )
 #endif
@@ -214,7 +214,7 @@
     } while(0)
     
 #ifndef CONFIG_SERIAL_CONSOLE
-__initfunc(static void atari_init_scc_port( int cflag ))
+static void __init atari_init_scc_port( int cflag )
 #else
 void atari_init_scc_port( int cflag )
 #endif
@@ -281,7 +281,7 @@
 }
 
 #ifndef CONFIG_SERIAL_CONSOLE 
-__initfunc(static void atari_init_midi_port( int cflag ))
+static void __init atari_init_midi_port( int cflag )
 #else
 void atari_init_midi_port( int cflag )
 #endif
@@ -309,7 +309,7 @@
 		     ACIA_RHTID : ACIA_RLTID);
 }
 
-__initfunc(void atari_debug_init(void))
+void __init atari_debug_init(void)
 {
 #ifdef CONFIG_KGDB
     /* the m68k_debug_device is used by the GDB stub, do nothing here */
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/atari/joystick.c linux/arch/m68k/atari/joystick.c
--- v2.3.15/linux/arch/m68k/atari/joystick.c	Mon Aug  9 12:27:30 1999
+++ linux/arch/m68k/atari/joystick.c	Thu Aug 26 12:42:31 1999
@@ -130,7 +130,7 @@
 	release_joystick
 };
 
-__initfunc(int atari_joystick_init(void))
+int __init atari_joystick_init(void)
 {
     joystick[0].active = joystick[1].active = 0;
     joystick[0].ready = joystick[1].ready = 0;
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/atari/stdma.c linux/arch/m68k/atari/stdma.c
--- v2.3.15/linux/arch/m68k/atari/stdma.c	Sat May 15 15:05:35 1999
+++ linux/arch/m68k/atari/stdma.c	Thu Aug 26 12:42:31 1999
@@ -171,7 +171,7 @@
  *
  */
 
-__initfunc(void stdma_init(void))
+void __init stdma_init(void)
 {
 	stdma_isr = NULL;
 	request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW,
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/atari/time.c linux/arch/m68k/atari/time.c
--- v2.3.15/linux/arch/m68k/atari/time.c	Thu Nov  5 09:58:29 1998
+++ linux/arch/m68k/atari/time.c	Thu Aug 26 12:42:31 1999
@@ -17,8 +17,8 @@
 #include <linux/init.h>
 
 
-__initfunc(void
-atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)))
+void __init
+atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
 {
     /* set Timer C data Register */
     mfp.tim_dt_c = INT_TICKS;
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/bvme6000/config.c linux/arch/m68k/bvme6000/config.c
--- v2.3.15/linux/arch/m68k/bvme6000/config.c	Mon Aug  9 12:27:30 1999
+++ linux/arch/m68k/bvme6000/config.c	Thu Aug 26 12:42:31 1999
@@ -103,7 +103,7 @@
 }
 
 
-__initfunc(void config_bvme6000(void))
+void __init config_bvme6000(void)
 {
     volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
 
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/bvme6000/rtc.c linux/arch/m68k/bvme6000/rtc.c
--- v2.3.15/linux/arch/m68k/bvme6000/rtc.c	Mon Aug 24 13:14:10 1998
+++ linux/arch/m68k/bvme6000/rtc.c	Thu Aug 26 12:42:31 1999
@@ -164,7 +164,7 @@
 	&rtc_fops
 };
 
-__initfunc(int rtc_DP8570A_init(void))
+int __init rtc_DP8570A_init(void)
 {
 	if (!MACH_IS_BVME6000)
 		return -ENODEV;
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/hp300/config.c linux/arch/m68k/hp300/config.c
--- v2.3.15/linux/arch/m68k/hp300/config.c	Tue Jan 19 10:58:26 1999
+++ linux/arch/m68k/hp300/config.c	Thu Aug 26 12:42:31 1999
@@ -31,7 +31,7 @@
 extern int hp300_keyb_init(void);
 #else
 /* Dummy function for when there is no keyboard. */
-__initfunc(int hp300_keyb_init(void))
+int __init hp300_keyb_init(void)
 {
 }
 #endif
@@ -60,7 +60,7 @@
   strcpy(model, "HP9000/300");
 }
 
-__initfunc(void config_hp300(void))
+void __init config_hp300(void)
 {
   mach_sched_init      = hp300_sched_init;
   mach_keyb_init       = hp300_keyb_init;
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/hp300/hil.c linux/arch/m68k/hp300/hil.c
--- v2.3.15/linux/arch/m68k/hp300/hil.c	Mon Apr 26 13:37:14 1999
+++ linux/arch/m68k/hp300/hil.c	Thu Aug 26 12:42:31 1999
@@ -304,7 +304,7 @@
  * Initialise HIL. 
  */
 
-__initfunc(int hp300_keyb_init(void))
+int __init hp300_keyb_init(void)
 {
   unsigned char s, c, kbid;
   unsigned int n = 0;
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/hp300/ints.c linux/arch/m68k/hp300/ints.c
--- v2.3.15/linux/arch/m68k/hp300/ints.c	Wed Sep  2 09:39:18 1998
+++ linux/arch/m68k/hp300/ints.c	Thu Aug 26 12:42:31 1999
@@ -153,7 +153,7 @@
 	return 0;
 }
 
-__initfunc(void hp300_init_IRQ(void))
+void __init hp300_init_IRQ(void)
 {
 	spin_lock_init(&irqlist_lock);
 }
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/hp300/time.c linux/arch/m68k/hp300/time.c
--- v2.3.15/linux/arch/m68k/hp300/time.c	Wed Sep  2 09:39:18 1998
+++ linux/arch/m68k/hp300/time.c	Thu Aug 26 12:42:31 1999
@@ -61,7 +61,7 @@
   return (USECS_PER_JIFFY * ticks) / INTVAL;
 }
 
-__initfunc(void hp300_sched_init(void (*vector)(int, void *, struct pt_regs *)))
+void __init hp300_sched_init(void (*vector)(int, void *, struct pt_regs *))
 {
   writeb(0x1, CLOCKBASE + CLKCR2);		/* select CR1 */
   writeb(0x1, CLOCKBASE + CLKCR1);		/* reset */
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/kernel/bios32.c linux/arch/m68k/kernel/bios32.c
--- v2.3.15/linux/arch/m68k/kernel/bios32.c	Sat Jul 18 14:02:10 1998
+++ linux/arch/m68k/kernel/bios32.c	Thu Aug 26 12:42:31 1999
@@ -240,7 +240,7 @@
  * accesses.
  */
 
-__initfunc(static void disable_dev(struct pci_dev *dev))
+static void __init disable_dev(struct pci_dev *dev)
 {
 	struct pci_bus *bus;
 	unsigned short cmd;
@@ -263,8 +263,8 @@
 
 #define MAX(val1, val2) ( ((val1) > (val2)) ? val1 : val2)
 
-__initfunc(static void layout_dev(struct pci_dev *dev, unsigned long pci_mem_base,
-								  unsigned long pci_io_base))
+static void __init layout_dev(struct pci_dev *dev, unsigned long pci_mem_base,
+								  unsigned long pci_io_base)
 {
 	struct pci_bus *bus;
 	unsigned short cmd;
@@ -400,8 +400,8 @@
 		  bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class));
 }
 
-__initfunc(static void layout_bus(struct pci_bus *bus, unsigned long pci_mem_base,
-								  unsigned long pci_io_base))
+static void __init layout_bus(struct pci_bus *bus, unsigned long pci_mem_base,
+								  unsigned long pci_io_base)
 {
 	struct pci_dev *dev;
 
@@ -512,7 +512,7 @@
 		return 0;
 }
 
-__initfunc(void pcibios_init(void))
+void __init pcibios_init(void)
 {
 	printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
 
@@ -531,7 +531,7 @@
  * of the PCI cards.
  */
 
-__initfunc(static inline void hades_fixup(void))
+static inline void __init hades_fixup(void)
 {
 	char irq_tab[4] = {
 			    IRQ_TT_MFP_IO0,	/* Slot 0. */
@@ -560,7 +560,7 @@
 	}
 }
 
-__initfunc(void pcibios_fixup(void))
+void __init pcibios_fixup(void)
 {
 #if PCI_MODIFY
 	unsigned long orig_mem_base, orig_io_base;
@@ -587,11 +587,11 @@
 	hades_fixup();
 }
 
-__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
 }
 
-__initfunc(char *pcibios_setup(char *str))
+char * __init pcibios_setup(char *str)
 {
 	return str;
 }
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/kernel/setup.c linux/arch/m68k/kernel/setup.c
--- v2.3.15/linux/arch/m68k/kernel/setup.c	Fri Jul 23 12:20:23 1999
+++ linux/arch/m68k/kernel/setup.c	Thu Aug 26 12:42:31 1999
@@ -130,7 +130,7 @@
 #define MASK_256K 0xfffc0000
 
 
-__initfunc(static void m68k_parse_bootinfo(const struct bi_record *record))
+static void __init m68k_parse_bootinfo(const struct bi_record *record)
 {
     while (record->tag != BI_LAST) {
 	int unknown = 0;
@@ -190,8 +190,8 @@
 #endif
 }
 
-__initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
-			   unsigned long * memory_end_p))
+void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p,
+			   unsigned long * memory_end_p)
 {
 	extern int _etext, _edata, _end;
 	int i;
@@ -467,7 +467,7 @@
 #endif
 
 #if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) || defined(CONFIG_BLK_DEV_FD)
-__initfunc(void floppy_setup(char *str, int *ints))
+void __init floppy_setup(char *str, int *ints)
 {
 	if (mach_floppy_setup)
 		mach_floppy_setup (str, ints);
@@ -481,7 +481,7 @@
 #endif
 
 /* for "kbd-reset" cmdline param */
-__initfunc(void kbd_reset_setup(char *str, int *ints))
+void __init kbd_reset_setup(char *str, int *ints)
 {
 }
 
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/mac/adb-bus.c linux/arch/m68k/mac/adb-bus.c
--- v2.3.15/linux/arch/m68k/mac/adb-bus.c	Mon Aug  9 12:27:30 1999
+++ linux/arch/m68k/mac/adb-bus.c	Tue Aug 31 11:30:47 1999
@@ -2334,8 +2334,8 @@
 	int ret = 0;
 	DECLARE_WAITQUEUE(wait,current);
 
+	__set_current_state(TASK_INTERRUPTIBLE);
 	add_wait_queue(&adb_wait, &wait);
-	current->state = TASK_INTERRUPTIBLE;
 
 	while (!state->req.got_reply) {
 		if (file->f_flags & O_NONBLOCK) {
@@ -2349,7 +2349,7 @@
 		schedule();
 	}
 
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&adb_wait, &wait);
 
 	return ret;
@@ -2562,8 +2562,8 @@
 	printk("ADB request: wait_reply (blocking ... \n");
 #endif
 
+	__set_current_state(TASK_INTERRUPTIBLE);
 	add_wait_queue(&adb_wait, &wait);
-	current->state = TASK_INTERRUPTIBLE;
 
 	while (!state->req.got_reply) {
 		if (file->f_flags & O_NONBLOCK) {
@@ -2577,7 +2577,7 @@
 		schedule();
 	}
 
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&adb_wait, &wait);
 
 	return ret;
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/mac/config.c linux/arch/m68k/mac/config.c
--- v2.3.15/linux/arch/m68k/mac/config.c	Tue Jan 19 10:58:34 1999
+++ linux/arch/m68k/mac/config.c	Thu Aug 26 12:42:31 1999
@@ -227,7 +227,7 @@
      *  Parse a Macintosh-specific record in the bootinfo
      */
 
-__initfunc(int mac_parse_bootinfo(const struct bi_record *record))
+int __init mac_parse_bootinfo(const struct bi_record *record)
 {
     int unknown = 0;
     const u_long *data = record->data;
@@ -288,7 +288,7 @@
 	restore_flags(flags);
 }
 
-__initfunc(void config_mac(void))
+void __init config_mac(void)
 {
 
     if (!MACH_IS_MAC) {
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/mac/debug.c linux/arch/m68k/mac/debug.c
--- v2.3.15/linux/arch/m68k/mac/debug.c	Tue Jan 19 10:58:34 1999
+++ linux/arch/m68k/mac/debug.c	Thu Aug 26 12:42:31 1999
@@ -305,7 +305,7 @@
     } while(0)
     
 #ifndef CONFIG_SERIAL_CONSOLE
-__initfunc(static void mac_init_scc_port( int cflag, int port ))
+static void __init mac_init_scc_port( int cflag, int port )
 #else
 void mac_init_scc_port( int cflag, int port )
 #endif
@@ -385,7 +385,7 @@
 }
 #endif /* DEBUG_SERIAL */
 
-__initfunc(void mac_debug_init(void))
+void __init mac_debug_init(void)
 {
 #ifdef CONFIG_KGDB
     /* the m68k_debug_device is used by the GDB stub, do nothing here */
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/mac/mackeyb.c linux/arch/m68k/mac/mackeyb.c
--- v2.3.15/linux/arch/m68k/mac/mackeyb.c	Mon Apr 26 13:38:03 1999
+++ linux/arch/m68k/mac/mackeyb.c	Thu Aug 26 12:42:31 1999
@@ -613,7 +613,7 @@
 	return 0;
 }
 
-__initfunc(int mac_keyb_init(void))
+int __init mac_keyb_init(void)
 {
 	static struct adb_request autopoll_req, confcod_req, mouse_req, readkey_req;
 	volatile int ct;
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c
--- v2.3.15/linux/arch/m68k/mm/init.c	Mon Aug  9 12:27:30 1999
+++ linux/arch/m68k/mm/init.c	Thu Aug 26 12:42:31 1999
@@ -120,7 +120,7 @@
 unsigned long mm_cachebits = 0;
 #endif
 
-__initfunc(static pte_t * kernel_page_table(unsigned long *memavailp))
+static pte_t * __init kernel_page_table(unsigned long *memavailp)
 {
 	pte_t *ptablep;
 
@@ -138,7 +138,7 @@
 static pmd_t *last_pgtable __initdata = NULL;
 static pmd_t *zero_pgtable __initdata = NULL;
 
-__initfunc(static pmd_t * kernel_ptr_table(unsigned long *memavailp))
+static pmd_t * __init kernel_ptr_table(unsigned long *memavailp)
 {
 	if (!last_pgtable) {
 		unsigned long pmd, last;
@@ -177,8 +177,8 @@
 	return last_pgtable;
 }
 
-__initfunc(static unsigned long
-map_chunk (unsigned long addr, long size, unsigned long *memavailp))
+static unsigned long __init
+map_chunk (unsigned long addr, long size, unsigned long *memavailp)
 {
 #define PTRTREESIZE (256*1024)
 #define ROOTTREESIZE (32*1024*1024)
@@ -285,8 +285,8 @@
  * paging_init() continues the virtual memory environment setup which
  * was begun by the code in arch/head.S.
  */
-__initfunc(unsigned long paging_init(unsigned long start_mem,
-				     unsigned long end_mem))
+unsigned long __init paging_init(unsigned long start_mem,
+				     unsigned long end_mem)
 {
 	int chunk;
 	unsigned long mem_avail = 0;
@@ -363,7 +363,7 @@
 	return PAGE_ALIGN(free_area_init(start_mem, end_mem));
 }
 
-__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
+void __init mem_init(unsigned long start_mem, unsigned long end_mem)
 {
 	int codepages = 0;
 	int datapages = 0;
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c
--- v2.3.15/linux/arch/m68k/mm/memory.c	Mon Aug  9 12:27:30 1999
+++ linux/arch/m68k/mm/memory.c	Thu Aug 26 12:42:31 1999
@@ -98,7 +98,7 @@
 
 #define PTABLE_SIZE (PTRS_PER_PMD * sizeof(pmd_t))
 
-__initfunc(void init_pointer_table(unsigned long ptable))
+void __init init_pointer_table(unsigned long ptable)
 {
 	ptable_desc *dp;
 	unsigned long page = ptable & PAGE_MASK;
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/mvme147/config.c linux/arch/m68k/mvme147/config.c
--- v2.3.15/linux/arch/m68k/mvme147/config.c	Mon Aug  9 12:27:30 1999
+++ linux/arch/m68k/mvme147/config.c	Thu Aug 26 12:42:31 1999
@@ -90,7 +90,7 @@
 }
 
 
-__initfunc(void config_mvme147(void))
+void __init config_mvme147(void)
 {
 	mach_sched_init		= mvme147_sched_init;
 	mach_keyb_init		= mvme147_keyb_init;
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/mvme16x/config.c linux/arch/m68k/mvme16x/config.c
--- v2.3.15/linux/arch/m68k/mvme16x/config.c	Mon Aug  9 12:27:30 1999
+++ linux/arch/m68k/mvme16x/config.c	Thu Aug 26 12:42:31 1999
@@ -131,7 +131,7 @@
 #define PccSCCTICR	0x1e
 #define PccSCCRICR	0x1f
 
-__initfunc(void config_mvme16x(void))
+void __init config_mvme16x(void)
 {
     p_bdid p = (p_bdid)mvme_bdid_ptr;
     char id[40];
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/mvme16x/rtc.c linux/arch/m68k/mvme16x/rtc.c
--- v2.3.15/linux/arch/m68k/mvme16x/rtc.c	Mon Aug 24 13:14:10 1998
+++ linux/arch/m68k/mvme16x/rtc.c	Thu Aug 26 12:42:31 1999
@@ -155,7 +155,7 @@
 	&rtc_fops
 };
 
-__initfunc(int rtc_MK48T08_init(void))
+int __init rtc_MK48T08_init(void)
 {
 	if (!MACH_IS_MVME16x)
 		return -ENODEV;
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/q40/config.c linux/arch/m68k/q40/config.c
--- v2.3.15/linux/arch/m68k/q40/config.c	Sun Aug 15 11:47:29 1999
+++ linux/arch/m68k/q40/config.c	Thu Aug 26 12:42:31 1999
@@ -157,7 +157,7 @@
 }
 
 
-__initfunc(void config_q40(void))
+void __init config_q40(void)
 {
     mach_sched_init      = q40_sched_init;           /* ok */
     /*mach_kbdrate         = q40_kbdrate;*/          /* unneeded ?*/
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/sun3x/config.c linux/arch/m68k/sun3x/config.c
--- v2.3.15/linux/arch/m68k/sun3x/config.c	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/sun3x/config.c	Thu Aug 26 12:42:31 1999
@@ -39,7 +39,7 @@
     asm ("reset");
 }
 
-__initfunc(int sun3x_keyb_init(void))
+int __init sun3x_keyb_init(void)
 {
     return 0;
 }
@@ -75,7 +75,7 @@
     *sun3x_intreg &= ~(1 << irq);
 }
 
-__initfunc(void sun3x_init_IRQ(void))
+void __init sun3x_init_IRQ(void)
 {
     /* disable all interrupts initially */
     *sun3x_intreg = 1;  /* master enable only */
@@ -89,7 +89,7 @@
 /*
  *  Setup the sun3x configuration info
  */
-__initfunc(void config_sun3x(void))
+void __init config_sun3x(void)
 {
     mach_get_irq_list	 = sun3x_get_irq_list;
     mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/sun3x/sbus.c linux/arch/m68k/sun3x/sbus.c
--- v2.3.15/linux/arch/m68k/sun3x/sbus.c	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/sun3x/sbus.c	Thu Aug 26 12:42:31 1999
@@ -12,7 +12,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 
-__initfunc(void sbus_init(void))
+void __init sbus_init(void)
 {
 
 }
diff -u --recursive --new-file v2.3.15/linux/arch/m68k/sun3x/time.c linux/arch/m68k/sun3x/time.c
--- v2.3.15/linux/arch/m68k/sun3x/time.c	Wed May 12 08:50:00 1999
+++ linux/arch/m68k/sun3x/time.c	Thu Aug 26 12:42:31 1999
@@ -72,7 +72,7 @@
     vector(irq, NULL, regs);
 }
 
-__initfunc(void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *)))
+void __init sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *))
 {
     sys_request_irq(5, sun3x_timer_tick, IRQ_FLG_STD, "timer tick", vector);
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/arc/cmdline.c linux/arch/mips/arc/cmdline.c
--- v2.3.15/linux/arch/mips/arc/cmdline.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/arc/cmdline.c	Thu Aug 26 12:42:31 1999
@@ -16,7 +16,7 @@
 
 char arcs_cmdline[CL_SIZE];
 
-__initfunc(char *prom_getcmdline(void))
+char * __init prom_getcmdline(void)
 {
 	return &(arcs_cmdline[0]);
 }
@@ -31,7 +31,7 @@
 };
 #define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0])))))
 
-__initfunc(void prom_init_cmdline(void))
+void __init prom_init_cmdline(void)
 {
 	char *cp;
 	int actr, i;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/arc/console.c linux/arch/mips/arc/console.c
--- v2.3.15/linux/arch/mips/arc/console.c	Wed Jun 30 11:24:54 1999
+++ linux/arch/mips/arc/console.c	Thu Aug 26 12:42:31 1999
@@ -23,7 +23,7 @@
 #ifdef CONFIG_SGI_PROM_CONSOLE
 void prom_putchar(char c)
 #else
-__initfunc(void prom_putchar(char c))
+void __init prom_putchar(char c)
 #endif
 {
 	long cnt;
@@ -37,7 +37,7 @@
 #ifdef CONFIG_SGI_PROM_CONSOLE
 char prom_getchar(void)
 #else
-__initfunc(char prom_getchar(void))
+char __init prom_getchar(void)
 #endif
 {
 	long cnt;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/arc/env.c linux/arch/mips/arc/env.c
--- v2.3.15/linux/arch/mips/arc/env.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/arc/env.c	Thu Aug 26 12:42:31 1999
@@ -11,12 +11,12 @@
 
 #include <asm/sgialib.h>
 
-__initfunc(char *prom_getenv(char *name))
+char * __init prom_getenv(char *name)
 {
 	return romvec->get_evar(name);
 }
 
-__initfunc(long prom_setenv(char *name, char *value))
+long __init prom_setenv(char *name, char *value)
 {
 	return romvec->set_evar(name, value);
 }
diff -u --recursive --new-file v2.3.15/linux/arch/mips/arc/file.c linux/arch/mips/arc/file.c
--- v2.3.15/linux/arch/mips/arc/file.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/arc/file.c	Thu Aug 26 12:42:31 1999
@@ -8,52 +8,52 @@
 #include <linux/init.h>
 #include <asm/sgialib.h>
 
-__initfunc(long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt))
+long __init prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt)
 {
 	return romvec->get_vdirent(fd, ent, num, cnt);
 }
 
-__initfunc(long prom_open(char *name, enum linux_omode md, unsigned long *fd))
+long __init prom_open(char *name, enum linux_omode md, unsigned long *fd)
 {
 	return romvec->open(name, md, fd);
 }
 
-__initfunc(long prom_close(unsigned long fd))
+long __init prom_close(unsigned long fd)
 {
 	return romvec->close(fd);
 }
 
-__initfunc(long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt))
+long __init prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)
 {
 	return romvec->read(fd, buf, num, cnt);
 }
 
-__initfunc(long prom_getrstatus(unsigned long fd))
+long __init prom_getrstatus(unsigned long fd)
 {
 	return romvec->get_rstatus(fd);
 }
 
-__initfunc(long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt))
+long __init prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)
 {
 	return romvec->write(fd, buf, num, cnt);
 }
 
-__initfunc(long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm))
+long __init prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm)
 {
 	return romvec->seek(fd, off, sm);
 }
 
-__initfunc(long prom_mount(char *name, enum linux_mountops op))
+long __init prom_mount(char *name, enum linux_mountops op)
 {
 	return romvec->mount(name, op);
 }
 
-__initfunc(long prom_getfinfo(unsigned long fd, struct linux_finfo *buf))
+long __init prom_getfinfo(unsigned long fd, struct linux_finfo *buf)
 {
 	return romvec->get_finfo(fd, buf);
 }
 
-__initfunc(long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk))
+long __init prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk)
 {
 	return romvec->set_finfo(fd, flags, msk);
 }
diff -u --recursive --new-file v2.3.15/linux/arch/mips/arc/init.c linux/arch/mips/arc/init.c
--- v2.3.15/linux/arch/mips/arc/init.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/arc/init.c	Thu Aug 26 12:42:31 1999
@@ -22,7 +22,7 @@
 
 extern void prom_testtree(void);
 
-__initfunc(int prom_init(int argc, char **argv, char **envp))
+int __init prom_init(int argc, char **argv, char **envp)
 {
 	struct linux_promblock *pb;
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/arc/memory.c linux/arch/mips/arc/memory.c
--- v2.3.15/linux/arch/mips/arc/memory.c	Wed Jun 30 11:24:54 1999
+++ linux/arch/mips/arc/memory.c	Thu Aug 26 12:42:31 1999
@@ -20,7 +20,7 @@
 
 /* #define DEBUG */
 
-__initfunc(struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr))
+struct linux_mdesc * __init prom_getmdesc(struct linux_mdesc *curr)
 {
 	return romvec->get_mdesc(curr);
 }
@@ -52,7 +52,7 @@
 
 static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS];
 
-__initfunc(struct prom_pmemblock *prom_getpblock_array(void))
+struct prom_pmemblock * __init prom_getpblock_array(void)
 {
 	return &prom_pblocks[0];
 }
@@ -89,7 +89,7 @@
     }
 }
 
-__initfunc(static void prom_setup_memupper(void))
+static void __init prom_setup_memupper(void)
 {
 	struct prom_pmemblock *p, *highest;
 
@@ -106,7 +106,7 @@
 #endif
 }
 
-__initfunc(void prom_meminit(void))
+void __init prom_meminit(void)
 {
 	struct linux_mdesc *p;
 	int totram;
@@ -162,7 +162,7 @@
 }
 
 /* Called from mem_init() to fixup the mem_map page settings. */
-__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end))
+void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
 {
 	struct prom_pmemblock *p;
 	int i, nents;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/arc/misc.c linux/arch/mips/arc/misc.c
--- v2.3.15/linux/arch/mips/arc/misc.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/arc/misc.c	Thu Aug 26 12:42:31 1999
@@ -78,7 +78,7 @@
 	return romvec->get_sysid();
 }
 
-__initfunc(void prom_cacheflush(void))
+void __init prom_cacheflush(void)
 {
 	romvec->cache_flush();
 }
diff -u --recursive --new-file v2.3.15/linux/arch/mips/arc/printf.c linux/arch/mips/arc/printf.c
--- v2.3.15/linux/arch/mips/arc/printf.c	Wed Jun 30 11:24:54 1999
+++ linux/arch/mips/arc/printf.c	Thu Aug 26 12:42:31 1999
@@ -17,7 +17,7 @@
 #ifdef CONFIG_SGI_PROM_CONSOLE
 void prom_printf(char *fmt, ...)
 #else
-__initfunc(void prom_printf(char *fmt, ...))
+void __init prom_printf(char *fmt, ...)
 #endif
 {
 	va_list args;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/arc/salone.c linux/arch/mips/arc/salone.c
--- v2.3.15/linux/arch/mips/arc/salone.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/arc/salone.c	Thu Aug 26 12:42:31 1999
@@ -9,17 +9,17 @@
 #include <linux/init.h>
 #include <asm/sgialib.h>
 
-__initfunc(long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr))
+long __init prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr)
 {
 	return romvec->load(name, end, pc, eaddr);
 }
 
-__initfunc(long prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp))
+long __init prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp)
 {
 	return romvec->invoke(pc, sp, argc, argv, envp);
 }
 
-__initfunc(long prom_exec(char *name, long argc, char **argv, char **envp))
+long __init prom_exec(char *name, long argc, char **argv, char **envp)
 {
 	return romvec->exec(name, argc, argv, envp);
 }
diff -u --recursive --new-file v2.3.15/linux/arch/mips/arc/time.c linux/arch/mips/arc/time.c
--- v2.3.15/linux/arch/mips/arc/time.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/arc/time.c	Thu Aug 26 12:42:31 1999
@@ -8,12 +8,12 @@
 #include <linux/init.h>
 #include <asm/sgialib.h>
 
-__initfunc(struct linux_tinfo *prom_gettinfo(void))
+struct linux_tinfo * __init prom_gettinfo(void)
 {
 	return romvec->get_tinfo();
 }
 
-__initfunc(unsigned long prom_getrtime(void))
+unsigned long __init prom_getrtime(void)
 {
 	return romvec->get_rtime();
 }
diff -u --recursive --new-file v2.3.15/linux/arch/mips/arc/tree.c linux/arch/mips/arc/tree.c
--- v2.3.15/linux/arch/mips/arc/tree.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/arc/tree.c	Thu Aug 26 12:42:31 1999
@@ -10,41 +10,41 @@
 
 #define DEBUG_PROM_TREE
 
-__initfunc(pcomponent *prom_getsibling(pcomponent *this))
+pcomponent * __init prom_getsibling(pcomponent *this)
 {
 	if(this == PROM_NULL_COMPONENT)
 		return PROM_NULL_COMPONENT;
 	return romvec->next_component(this);
 }
 
-__initfunc(pcomponent *prom_getchild(pcomponent *this))
+pcomponent * __init prom_getchild(pcomponent *this)
 {
 	return romvec->child_component(this);
 }
 
-__initfunc(pcomponent *prom_getparent(pcomponent *child))
+pcomponent * __init prom_getparent(pcomponent *child)
 {
 	if(child == PROM_NULL_COMPONENT)
 		return PROM_NULL_COMPONENT;
 	return romvec->parent_component(child);
 }
 
-__initfunc(long prom_getcdata(void *buffer, pcomponent *this))
+long __init prom_getcdata(void *buffer, pcomponent *this)
 {
 	return romvec->component_data(buffer, this);
 }
 
-__initfunc(pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data))
+pcomponent * __init prom_childadd(pcomponent *this, pcomponent *tmp, void *data)
 {
 	return romvec->child_add(this, tmp, data);
 }
 
-__initfunc(long prom_delcomponent(pcomponent *this))
+long __init prom_delcomponent(pcomponent *this)
 {
 	return romvec->comp_del(this);
 }
 
-__initfunc(pcomponent *prom_componentbypath(char *path))
+pcomponent * __init prom_componentbypath(char *path)
 {
 	return romvec->component_by_path(path);
 }
@@ -74,7 +74,7 @@
 	"input", "output"
 };
 
-__initfunc(static void dump_component(pcomponent *p))
+static void __init dump_component(pcomponent *p)
 {
 	prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>",
 		    p, classes[p->class], types[p->type],
@@ -83,7 +83,7 @@
 		    p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname);
 }
 
-__initfunc(static void traverse(pcomponent *p, int op))
+static void __init traverse(pcomponent *p, int op)
 {
 	dump_component(p);
 	if(prom_getchild(p))
@@ -92,7 +92,7 @@
 		traverse(prom_getsibling(p), 1);
 }
 
-__initfunc(void prom_testtree(void))
+void __init prom_testtree(void)
 {
 	pcomponent *p;
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/baget/irq.c linux/arch/mips/baget/irq.c
--- v2.3.15/linux/arch/mips/baget/irq.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/baget/irq.c	Thu Aug 26 12:42:31 1999
@@ -422,7 +422,7 @@
 	*(volatile char*) BAGET_WRERR_ACK = 0;
 }
 
-__initfunc(void init_IRQ(void))
+void __init init_IRQ(void)
 {
 	irq_setup();
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/baget/print.c linux/arch/mips/baget/print.c
--- v2.3.15/linux/arch/mips/baget/print.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/baget/print.c	Thu Aug 26 12:42:31 1999
@@ -76,7 +76,7 @@
         outs( s );
 }
 
-__initfunc(void balo_printf( char *f, ... )) 
+void __init balo_printf( char *f, ... )
 {
         int *arg = (int*)&f + 1;
         char c; 
@@ -111,7 +111,7 @@
         }
 }
 
-__initfunc(void balo_hungup(void))
+void __init balo_hungup(void)
 { 
         outs("Hunging up.\n");
         while(1); 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/baget/prom/init.c linux/arch/mips/baget/prom/init.c
--- v2.3.15/linux/arch/mips/baget/prom/init.c	Wed Jun 30 11:24:54 1999
+++ linux/arch/mips/baget/prom/init.c	Thu Aug 26 12:42:31 1999
@@ -10,7 +10,7 @@
 
 char arcs_cmdline[CL_SIZE];
 
-__initfunc(int prom_init(unsigned int mem_upper))
+int __init prom_init(unsigned int mem_upper)
 {
 	mips_memory_upper = mem_upper;
 	mips_machgroup  = MACH_GROUP_UNKNOWN;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/baget/setup.c linux/arch/mips/baget/setup.c
--- v2.3.15/linux/arch/mips/baget/setup.c	Wed Jun 30 11:24:54 1999
+++ linux/arch/mips/baget/setup.c	Thu Aug 26 12:42:31 1999
@@ -21,7 +21,7 @@
 #define CACHEABLE_STR(val) ((val) ? "not cached" : "cached")
 #define MIN(a,b)           (((a)<(b)) ? (a):(b)) 
 		
-__initfunc(static void vac_show(void))
+static void __init vac_show(void)
 { 
 	int i;
 	unsigned short val, decode = vac_inw(VAC_DECODE_CTRL);
@@ -172,7 +172,7 @@
 	       (VAC_CTRL_DELAY_IOSELI_VAL(val)&1) ? ".5" : "");
 }
 
-__initfunc(static void vac_init(void))
+static void __init vac_init(void)
 {
 	unsigned short mem_limit = ((mips_memory_upper-KSEG0) >> 16);
 
@@ -283,7 +283,7 @@
         vac_show();
 }
 
-__initfunc(static void vac_start(void))
+static void __init vac_start(void)
 {
 	vac_outw(0, VAC_ID);
 	vac_outw(VAC_INT_CTRL_TIMER_DISABLE|
@@ -305,7 +305,7 @@
 	vac_outw((500000/(384*16))<<8,VAC_CPU_CLK_DIV); 
 }
 
-__initfunc(static void vic_show(void))
+static void __init vic_show(void)
 {
 	unsigned char val;
 	char *timeout[]  = { "4", "16", "32", "64", "128", "256", "disabled" };
@@ -364,7 +364,7 @@
 	
 }
 
-__initfunc(static void vic_init(void))
+static void __init vic_init(void)
 {
 	 unsigned char id = vic_inb(VIC_ID);
 	 if ((id & 0xf0) != 0xf0)
@@ -463,7 +463,7 @@
 		 VIC_INT_ENABLE, VIC_LINT7);
 }
 
-__initfunc(void baget_irq_setup(void))
+void __init baget_irq_setup(void)
 {
 	extern void bagetIRQ(void);
 
@@ -475,7 +475,7 @@
 extern void baget_machine_halt(void);
 extern void baget_machine_power_off(void);
  
-__initfunc(void baget_setup(void))
+void __init baget_setup(void)
 {
 	printk("BT23/63-201n found.\n");
 	*BAGET_WRERR_ACK = 0;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/baget/time.c linux/arch/mips/baget/time.c
--- v2.3.15/linux/arch/mips/baget/time.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/baget/time.c	Thu Aug 26 12:42:31 1999
@@ -52,7 +52,7 @@
 	}
 }
 
-__initfunc(static void timer_enable(void))
+static void __init timer_enable(void)
 {
 	unsigned char ss0cr0 = vic_inb(VIC_SS0CR0);
 	ss0cr0 &= ~VIC_SS0CR0_TIMER_FREQ_MASK;
@@ -63,7 +63,7 @@
 		 VIC_INT_LOW|VIC_INT_ENABLE, VIC_LINT2); 
 }
 
-__initfunc(void time_init(void))
+void __init time_init(void)
 {
 	if (request_irq(BAGET_VIC_TIMER_IRQ, timer_interrupt, 
 			SA_INTERRUPT|SA_STATIC_ALLOC, "timer", NULL) < 0) 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/baget/vacserial.c linux/arch/mips/baget/vacserial.c
--- v2.3.15/linux/arch/mips/baget/vacserial.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/baget/vacserial.c	Tue Aug 31 11:30:47 1999
@@ -1778,7 +1778,6 @@
 		baget_printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
 #endif
 		current->state = TASK_INTERRUPTIBLE;
-		current->counter = 0;	/* make us low-priority */
 		schedule_timeout(char_time);
 		if (signal_pending(current))
 			break;
@@ -1903,7 +1902,7 @@
 	restore_flags(flags); 
 	info->blocked_open++;
 	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ASYNC_INITIALIZED)) {
 #ifdef SERIAL_DO_RESTART
@@ -2302,7 +2301,7 @@
 /*
  * The serial driver boot-time initialization code!
  */
-__initfunc(int rs_init(void))
+int __init rs_init(void)
 {
 	int i;
 	struct serial_state * state;
@@ -2666,7 +2665,7 @@
  *	- initialize the serial port
  *	Return non-zero if we didn't find a serial port.
  */
-__initfunc(static int serial_console_setup(struct console *co, char *options))
+static int __init serial_console_setup(struct console *co, char *options)
 {
 	struct serial_state *ser;
 	unsigned cval;
@@ -2821,7 +2820,7 @@
 /*
  *	Register console.
  */
-__initfunc (long serial_console_init(long kmem_start, long kmem_end))
+long __init serial_console_init(long kmem_start, long kmem_end)
 {
 	register_console(&sercons);
 	return kmem_start;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/baget/wbflush.c linux/arch/mips/baget/wbflush.c
--- v2.3.15/linux/arch/mips/baget/wbflush.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/baget/wbflush.c	Thu Aug 26 12:42:31 1999
@@ -11,7 +11,7 @@
 
 static void wbflush_baget(void);
 
-__initfunc(void wbflush_setup(void))
+void __init wbflush_setup(void)
 {
 	__wbflush = wbflush_baget;
 }
diff -u --recursive --new-file v2.3.15/linux/arch/mips/dec/irq.c linux/arch/mips/dec/irq.c
--- v2.3.15/linux/arch/mips/dec/irq.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/dec/irq.c	Thu Aug 26 12:42:31 1999
@@ -263,7 +263,7 @@
     return 0;
 }
 
-__initfunc(void init_IRQ(void))
+void __init init_IRQ(void)
 {
     irq_setup();
 }
diff -u --recursive --new-file v2.3.15/linux/arch/mips/dec/prom/cmdline.c linux/arch/mips/dec/prom/cmdline.c
--- v2.3.15/linux/arch/mips/dec/prom/cmdline.c	Wed Jun 30 11:24:54 1999
+++ linux/arch/mips/dec/prom/cmdline.c	Thu Aug 26 12:42:31 1999
@@ -21,7 +21,7 @@
 
 char arcs_cmdline[CL_SIZE];
 
-__initfunc(void prom_init_cmdline(int argc, char **argv, unsigned long magic))
+void __init prom_init_cmdline(int argc, char **argv, unsigned long magic)
 {
 	int start_arg, i;
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/dec/prom/identify.c linux/arch/mips/dec/prom/identify.c
--- v2.3.15/linux/arch/mips/dec/prom/identify.c	Wed Jun 30 11:24:54 1999
+++ linux/arch/mips/dec/prom/identify.c	Thu Aug 26 12:42:31 1999
@@ -21,7 +21,7 @@
 extern unsigned long mips_machgroup;
 extern unsigned long mips_machtype;
 
-__initfunc(void prom_identify_arch (unsigned int magic))
+void __init prom_identify_arch (unsigned int magic)
 {
 	unsigned char dec_cpunum, dec_firmrev, dec_etc;
 	int dec_systype;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/dec/prom/init.c linux/arch/mips/dec/prom/init.c
--- v2.3.15/linux/arch/mips/dec/prom/init.c	Wed Jun 30 11:24:54 1999
+++ linux/arch/mips/dec/prom/init.c	Thu Aug 26 12:42:31 1999
@@ -41,7 +41,7 @@
  * Detect which PROM's the DECSTATION has, and set the callback vectors
  * appropriately.
  */
-__initfunc(void which_prom(unsigned long magic, int *prom_vec))
+void __init which_prom(unsigned long magic, int *prom_vec)
 {
 	/*
 	 * No sign of the REX PROM's magic number means we assume a non-REX
@@ -78,8 +78,8 @@
 	}
 } 
 
-__initfunc(int prom_init(int argc, char **argv,
-	       unsigned long magic, int *prom_vec))
+int __init prom_init(int argc, char **argv,
+	       unsigned long magic, int *prom_vec)
 {
 	/* Determine which PROM's we have (and therefore which machine we're on!) */
 	which_prom(magic, prom_vec);
diff -u --recursive --new-file v2.3.15/linux/arch/mips/dec/prom/memory.c linux/arch/mips/dec/prom/memory.c
--- v2.3.15/linux/arch/mips/dec/prom/memory.c	Wed Jun 30 11:24:54 1999
+++ linux/arch/mips/dec/prom/memory.c	Thu Aug 26 12:42:31 1999
@@ -34,7 +34,7 @@
 
 #define CHUNK_SIZE 0x400000
 
-__initfunc(unsigned long pmax_get_memory_size(void))
+unsigned long __init pmax_get_memory_size(void)
 {
 	volatile unsigned char *memory_page, dummy;
 	char	old_handler[0x80];
@@ -62,7 +62,7 @@
  * Use the REX prom calls to get hold of the memory bitmap, and thence
  * determine memory size.
  */
-__initfunc(unsigned long rex_get_memory_size(void))
+unsigned long __init rex_get_memory_size(void)
 {
 	int i, bitmap_size;
 	unsigned long mem_size = 0;
@@ -81,7 +81,7 @@
 	return (mem_size);
 }
 
-__initfunc(void prom_meminit(unsigned int magic))
+void __init prom_meminit(unsigned int magic)
 {
 	if (magic != REX_PROM_MAGIC)
 		mips_memory_upper = KSEG0 + pmax_get_memory_size();
@@ -94,7 +94,7 @@
 }
 
 /* Called from mem_init() to fixup the mem_map page settings. */
-__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end))
+void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
 {
 }
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/dec/promcon.c linux/arch/mips/dec/promcon.c
--- v2.3.15/linux/arch/mips/dec/promcon.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/dec/promcon.c	Thu Aug 26 12:42:31 1999
@@ -35,7 +35,7 @@
     return prom_getchar();
 }
 
-__initfunc(static int prom_console_setup(struct console *co, char *options))
+static int __init prom_console_setup(struct console *co, char *options)
 {
     return 0;
 }
@@ -64,7 +64,7 @@
  *    Register console.
  */
 
-__initfunc(long prom_console_init(long kmem_start, long kmem_end))
+long __init prom_console_init(long kmem_start, long kmem_end)
 {
     register_console(&sercons);
     return kmem_start;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/dec/serial.c linux/arch/mips/dec/serial.c
--- v2.3.15/linux/arch/mips/dec/serial.c	Wed Aug  4 16:36:41 1999
+++ linux/arch/mips/dec/serial.c	Thu Aug 26 12:42:31 1999
@@ -45,7 +45,7 @@
 
 #ifdef CONFIG_SERIAL
 
-__initfunc(int rs_init(void))
+int __init rs_init(void)
 {
 
 #if defined(CONFIG_ZS) && defined(CONFIG_DZ)
@@ -73,7 +73,7 @@
 /* serial_console_init handles the special case of starting
  *   up the console on the serial port
  */
-__initfunc(long serial_console_init(long kmem_start, long kmem_end))
+long __init serial_console_init(long kmem_start, long kmem_end)
 {
 #if defined(CONFIG_ZS) && defined(CONFIG_DZ)
     if (IOASIC)
diff -u --recursive --new-file v2.3.15/linux/arch/mips/dec/setup.c linux/arch/mips/dec/setup.c
--- v2.3.15/linux/arch/mips/dec/setup.c	Wed Aug  4 16:36:41 1999
+++ linux/arch/mips/dec/setup.c	Thu Aug 26 12:42:31 1999
@@ -60,7 +60,7 @@
 
 void (*board_time_init) (struct irqaction * irq);
 
-__initfunc(static void dec_irq_setup(void))
+static void __init dec_irq_setup(void)
 {
     switch (mips_machtype) {
     case MACH_DS23100:
@@ -97,7 +97,7 @@
 /*
  * enable the periodic interrupts
  */
-__initfunc(static void dec_time_init(struct irqaction *irq))
+static void __init dec_time_init(struct irqaction *irq)
 {
     /*
      * Here we go, enable periodic rtc interrupts.
@@ -112,7 +112,7 @@
     setup_dec_irq(CLOCK, irq);
 }
 
-__initfunc(void decstation_setup(void))
+void __init decstation_setup(void)
 {
     irq_setup = dec_irq_setup;
     board_time_init = dec_time_init;
@@ -130,7 +130,7 @@
  * Machine-specific initialisation for kn01, aka Pmax, aka DS2100, DS3100,
  * and possibly also the DS5100.
  */
-__initfunc(void dec_init_kn01(void))
+void __init dec_init_kn01(void)
 {
     /*
      * Setup some memory addresses.
@@ -176,7 +176,7 @@
  *
  * There are a lot of experiments to do, this is definitely incomplete.
  */
-__initfunc(void dec_init_kn230(void))
+void __init dec_init_kn230(void)
 {
     /*
      * Setup some memory addresses.
@@ -200,7 +200,7 @@
 /*
  * Machine-specific initialisation for kn02, aka 3max, aka DS5000/2xx.
  */
-__initfunc(void dec_init_kn02(void))
+void __init dec_init_kn02(void)
 {
     /*
      * Setup some memory addresses. FIXME: probably incomplete!
@@ -270,7 +270,7 @@
 /*
  * Machine-specific initialisation for kn02ba, aka 3min, aka DS5000/1xx.
  */
-__initfunc(void dec_init_kn02ba(void))
+void __init dec_init_kn02ba(void)
 {
     /*
      * Setup some memory addresses.
@@ -350,7 +350,7 @@
 /*
  * Machine-specific initialisation for kn02ca, aka maxine, aka DS5000/2x.
  */
-__initfunc(void dec_init_kn02ca(void))
+void __init dec_init_kn02ca(void)
 {
     /*
      * Setup some memory addresses. FIXME: probably incomplete!
@@ -425,7 +425,7 @@
 /*
  * Machine-specific initialisation for kn03, aka 3max+, aka DS5000/240.
  */
-__initfunc(void dec_init_kn03(void))
+void __init dec_init_kn03(void)
 {
     /*
      * Setup some memory addresses. FIXME: probably incomplete!
diff -u --recursive --new-file v2.3.15/linux/arch/mips/dec/time.c linux/arch/mips/dec/time.c
--- v2.3.15/linux/arch/mips/dec/time.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/dec/time.c	Thu Aug 26 12:42:31 1999
@@ -385,7 +385,7 @@
 
 void (*board_time_init) (struct irqaction * irq);
 
-__initfunc(void time_init(void))
+void __init time_init(void)
 {
     unsigned int year, mon, day, hour, min, sec;
     int i;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/dec/wbflush.c linux/arch/mips/dec/wbflush.c
--- v2.3.15/linux/arch/mips/dec/wbflush.c	Wed Aug  4 16:36:41 1999
+++ linux/arch/mips/dec/wbflush.c	Thu Aug 26 12:42:31 1999
@@ -23,7 +23,7 @@
 
 void (*__wbflush) (void);
 
-__initfunc(void wbflush_setup(void))
+void __init wbflush_setup(void)
 {
 	switch (mips_machtype) {
 	case MACH_DS23100:
diff -u --recursive --new-file v2.3.15/linux/arch/mips/jazz/setup.c linux/arch/mips/jazz/setup.c
--- v2.3.15/linux/arch/mips/jazz/setup.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/jazz/setup.c	Thu Aug 26 12:42:31 1999
@@ -52,14 +52,14 @@
 
 void (*board_time_init)(struct irqaction *irq);
 
-__initfunc(static void jazz_time_init(struct irqaction *irq))
+static void __init jazz_time_init(struct irqaction *irq)
 {
         /* set the clock to 100 Hz */
         r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
         i8259_setup_irq(JAZZ_TIMER_IRQ, irq);
 }
 
-__initfunc(static void jazz_irq_setup(void))
+static void __init jazz_irq_setup(void)
 {
         set_except_vector(0, jazz_handle_int);
 	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
@@ -79,7 +79,7 @@
 	i8259_setup_irq(2, &irq2);
 }
 
-__initfunc(void jazz_setup(void))
+void __init jazz_setup(void)
 {
 	add_wired_entry (0x02000017, 0x03c00017, 0xe0000000, PM_64K);
 	add_wired_entry (0x02400017, 0x02440017, 0xe2000000, PM_16M);
diff -u --recursive --new-file v2.3.15/linux/arch/mips/kernel/irixinv.c linux/arch/mips/kernel/irixinv.c
--- v2.3.15/linux/arch/mips/kernel/irixinv.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/kernel/irixinv.c	Thu Aug 26 12:42:31 1999
@@ -53,7 +53,7 @@
 	return inventory_items * sizeof (inventory_t);
 }
 
-__initfunc(void init_inventory (void))
+void __init 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.3.15/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c
--- v2.3.15/linux/arch/mips/kernel/irq.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/kernel/irq.c	Thu Aug 26 12:42:31 1999
@@ -356,7 +356,7 @@
 	return ((irq == 2) ? 9 : irq);
 }
 
-__initfunc(static void i8259_init(void))
+static void __init i8259_init(void)
 {
 	/* Init master interrupt controller */
 	outb(0x11, 0x20); /* Start init sequence */
@@ -376,7 +376,7 @@
 	outb(cached_21, 0x21);
 }
 
-__initfunc(void init_IRQ(void))
+void __init init_IRQ(void)
 {
 	irq_cannonicalize = i8259_irq_cannonicalize;
 	/* i8259_init(); */
diff -u --recursive --new-file v2.3.15/linux/arch/mips/kernel/pci.c linux/arch/mips/kernel/pci.c
--- v2.3.15/linux/arch/mips/kernel/pci.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/kernel/pci.c	Thu Aug 26 12:42:31 1999
@@ -22,7 +22,7 @@
 /*
  * BIOS32 replacement.
  */
-__initfunc(void pcibios_init(void))
+void __init pcibios_init(void)
 {
 }
 
@@ -81,12 +81,12 @@
 	return pci_ops->pcibios_write_config_dword(bus, dev_fn, where, val);
 }
 
-__initfunc(char *pcibios_setup(char *str))
+char * __init pcibios_setup(char *str)
 {
 	return str;
 }
 
-__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
 }
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c
--- v2.3.15/linux/arch/mips/kernel/setup.c	Mon Jul  5 20:35:17 1999
+++ linux/arch/mips/kernel/setup.c	Thu Aug 26 12:42:31 1999
@@ -135,13 +135,13 @@
  */
 unsigned long isa_slot_offset;
 
-__initfunc(static void default_irq_setup(void))
+static void __init default_irq_setup(void)
 {
 	panic("Unknown machtype in init_IRQ");
 }
 
-__initfunc(void setup_arch(char **cmdline_p,
-           unsigned long * memory_start_p, unsigned long * memory_end_p))
+void __init setup_arch(char **cmdline_p,
+           unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
 	unsigned long memory_end;
 #ifdef CONFIG_BLK_DEV_INITRD
diff -u --recursive --new-file v2.3.15/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c
--- v2.3.15/linux/arch/mips/kernel/time.c	Wed Jun 30 11:24:54 1999
+++ linux/arch/mips/kernel/time.c	Thu Aug 26 12:42:31 1999
@@ -479,7 +479,7 @@
 
 void (*board_time_init)(struct irqaction *irq);
 
-__initfunc(void time_init(void))
+void __init time_init(void)
 {
 	unsigned int epoch, year, mon, day, hour, min, sec;
 	int i;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c
--- v2.3.15/linux/arch/mips/kernel/traps.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/kernel/traps.c	Thu Aug 26 12:42:32 1999
@@ -467,7 +467,7 @@
 extern asmlinkage void *r4xx0_resume(void *last, void *next);
 extern asmlinkage void *r2300_resume(void *last, void *next);
 
-__initfunc(void trap_init(void))
+void __init trap_init(void)
 {
 	extern char except_vec0_nevada, except_vec0_r4000;
 	extern char except_vec0_r4600, except_vec0_r2300;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/mm/andes.c linux/arch/mips/mm/andes.c
--- v2.3.15/linux/arch/mips/mm/andes.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/mm/andes.c	Thu Aug 26 12:42:32 1999
@@ -91,7 +91,7 @@
 	return (regs->cp0_status & ST0_KSU) == KSU_USER;
 }
 
-__initfunc(void ld_mmu_andes(void))
+void __init ld_mmu_andes(void)
 {
 	flush_cache_all = andes_flush_cache_all;
 	flush_cache_mm = andes_flush_cache_mm;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c
--- v2.3.15/linux/arch/mips/mm/init.c	Tue Jun 29 09:22:08 1999
+++ linux/arch/mips/mm/init.c	Thu Aug 26 12:42:32 1999
@@ -272,7 +272,7 @@
 
 extern unsigned long free_area_init(unsigned long, unsigned long);
 
-__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem)
 {
 	/* Initialize the entire pgd.  */
 	pgd_init((unsigned long)swapper_pg_dir);
@@ -280,7 +280,7 @@
 	return free_area_init(start_mem, end_mem);
 }
 
-__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
+void __init mem_init(unsigned long start_mem, unsigned long end_mem)
 {
 	int codepages = 0;
 	int datapages = 0;
@@ -383,8 +383,8 @@
 }
 
 /* Fixup an immediate instruction  */
-__initfunc(static void __i_insn_fixup(unsigned int **start, unsigned int **stop,
-                         unsigned int i_const))
+static void __init __i_insn_fixup(unsigned int **start, unsigned int **stop,
+                         unsigned int i_const)
 {
 	unsigned int **p, *ip;
 
@@ -402,9 +402,9 @@
 } while(0)
 
 /* Caller is assumed to flush the caches before the first context switch.  */
-__initfunc(void __asid_setup(unsigned int inc, unsigned int mask,
+void __init __asid_setup(unsigned int inc, unsigned int mask,
                              unsigned int version_mask,
-                             unsigned int first_version))
+                             unsigned int first_version)
 {
 	i_insn_fixup(__asid_inc, inc);
 	i_insn_fixup(__asid_mask, mask);
diff -u --recursive --new-file v2.3.15/linux/arch/mips/mm/loadmmu.c linux/arch/mips/mm/loadmmu.c
--- v2.3.15/linux/arch/mips/mm/loadmmu.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/mm/loadmmu.c	Thu Aug 26 12:42:32 1999
@@ -62,7 +62,7 @@
 extern void ld_mmu_tfp(void);
 extern void ld_mmu_andes(void);
 
-__initfunc(void loadmmu(void))
+void __init loadmmu(void)
 {
 	switch(mips_cputype) {
 	case CPU_R2000:
diff -u --recursive --new-file v2.3.15/linux/arch/mips/mm/r2300.c linux/arch/mips/mm/r2300.c
--- v2.3.15/linux/arch/mips/mm/r2300.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/mm/r2300.c	Thu Aug 26 12:42:32 1999
@@ -127,7 +127,7 @@
 		 "I" (PAGE_SIZE));
 }
 
-__initfunc(static unsigned long size_cache(unsigned long ca_flags))
+static unsigned long __init size_cache(unsigned long ca_flags)
 {
 	unsigned long flags, status, dummy, size;
 	volatile unsigned long *p;
@@ -161,13 +161,13 @@
 	return size * sizeof(*p);
 }
 
-__initfunc(static void probe_dcache(void))
+static void __init probe_dcache(void)
 {
 	dcache.size = size_cache(dcache.ca_flags = ST0_DE);
 	printk("Data cache %dkb\n", dcache.size >> 10);
 }
 
-__initfunc(static void probe_icache(void))
+static void __init probe_icache(void)
 {
 	icache.size = size_cache(icache.ca_flags = ST0_DE|ST0_CE);
 	printk("Instruction cache %dkb\n", icache.size >> 10);
@@ -683,7 +683,7 @@
 	return !(regs->cp0_status & ST0_KUP);
 }
 
-__initfunc(void ld_mmu_r2300(void))
+void __init ld_mmu_r2300(void)
 {
 	printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID));
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/mm/r4xx0.c linux/arch/mips/mm/r4xx0.c
--- v2.3.15/linux/arch/mips/mm/r4xx0.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/mm/r4xx0.c	Thu Aug 26 12:42:32 1999
@@ -2516,7 +2516,7 @@
 }
 
 /* Detect and size the various r4k caches. */
-__initfunc(static void probe_icache(unsigned long config))
+static void __init probe_icache(unsigned long config)
 {
 	icache_size = 1 << (12 + ((config >> 9) & 7));
 	ic_lsize = 16 << ((config >> 5) & 1);
@@ -2525,7 +2525,7 @@
 	       icache_size >> 10, ic_lsize);
 }
 
-__initfunc(static void probe_dcache(unsigned long config))
+static void __init probe_dcache(unsigned long config)
 {
 	dcache_size = 1 << (12 + ((config >> 6) & 7));
 	dc_lsize = 16 << ((config >> 4) & 1);
@@ -2540,7 +2540,7 @@
  * the cache sizing loop that executes in KSEG1 space or else
  * you will crash and burn badly.  You have been warned.
  */
-__initfunc(static int probe_scache(unsigned long config))
+static int __init probe_scache(unsigned long config)
 {
 	extern unsigned long stext;
 	unsigned long flags, addr, begin, end, pow2;
@@ -2624,7 +2624,7 @@
 	return 1;
 }
 
-__initfunc(static void setup_noscache_funcs(void))
+static void __init setup_noscache_funcs(void)
 {
 	unsigned int prid;
 
@@ -2662,7 +2662,7 @@
 	dma_cache_inv = r4k_dma_cache_inv_pc;
 }
 
-__initfunc(static void setup_scache_funcs(void))
+static void __init setup_scache_funcs(void)
 {
 	switch(sc_lsize) {
 	case 16:
@@ -2748,7 +2748,7 @@
 
 typedef int (*probe_func_t)(unsigned long);
 
-__initfunc(static inline void setup_scache(unsigned int config))
+static inline void __init setup_scache(unsigned int config)
 {
 	probe_func_t probe_scache_kseg1;
 	int sc_present = 0;
@@ -2770,7 +2770,7 @@
 	return (regs->cp0_status & ST0_KSU) == KSU_USER;
 }
 
-__initfunc(void ld_mmu_r4xx0(void))
+void __init ld_mmu_r4xx0(void)
 {
 	unsigned long config = read_32bit_cp0_register(CP0_CONFIG);
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/mm/r6000.c linux/arch/mips/mm/r6000.c
--- v2.3.15/linux/arch/mips/mm/r6000.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/mm/r6000.c	Thu Aug 26 12:42:32 1999
@@ -169,7 +169,7 @@
 	return !(regs->cp0_status & 0x4);
 }
 
-__initfunc(void ld_mmu_r6000(void))
+void __init ld_mmu_r6000(void)
 {
 	flush_cache_all = r6000_flush_cache_all;
 	flush_cache_mm = r6000_flush_cache_mm;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/mm/tfp.c linux/arch/mips/mm/tfp.c
--- v2.3.15/linux/arch/mips/mm/tfp.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/mm/tfp.c	Thu Aug 26 12:42:32 1999
@@ -93,7 +93,7 @@
 	return (regs->cp0_status & ST0_KSU) == KSU_USER;
 }
 
-__initfunc(void ld_mmu_tfp(void))
+void __init ld_mmu_tfp(void)
 {
 	flush_cache_all = tfp_flush_cache_all;
 	flush_cache_mm = tfp_flush_cache_mm;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/sgi/kernel/indy_hpc.c linux/arch/mips/sgi/kernel/indy_hpc.c
--- v2.3.15/linux/arch/mips/sgi/kernel/indy_hpc.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/sgi/kernel/indy_hpc.c	Thu Aug 26 12:42:32 1999
@@ -25,7 +25,7 @@
 int sgi_guiness = 0;
 int sgi_boardid;
 
-__initfunc(void sgihpc_init(void))
+void __init sgihpc_init(void)
 {
 	unsigned long sid, crev, brev;
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/sgi/kernel/indy_int.c linux/arch/mips/sgi/kernel/indy_int.c
--- v2.3.15/linux/arch/mips/sgi/kernel/indy_int.c	Wed Jun 30 11:24:54 1999
+++ linux/arch/mips/sgi/kernel/indy_int.c	Thu Aug 26 12:42:32 1999
@@ -422,7 +422,7 @@
 	return irq;	/* Sane hardware, sane code ... */
 }
 
-__initfunc(void init_IRQ(void))
+void __init init_IRQ(void)
 {
 	irq_cannonicalize = indy_irq_cannonicalize;
 	irq_setup();
@@ -527,7 +527,7 @@
 	return 0;
 }
 
-__initfunc(void sgint_init(void))
+void __init sgint_init(void)
 {
 	int i;
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/sgi/kernel/indy_mc.c linux/arch/mips/sgi/kernel/indy_mc.c
--- v2.3.15/linux/arch/mips/sgi/kernel/indy_mc.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/sgi/kernel/indy_mc.c	Thu Aug 26 12:42:32 1999
@@ -47,7 +47,7 @@
 	};
 }
 
-__initfunc(void sgimc_init(void))
+void __init sgimc_init(void)
 {
 	unsigned long tmpreg;
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/sgi/kernel/indy_sc.c linux/arch/mips/sgi/kernel/indy_sc.c
--- v2.3.15/linux/arch/mips/sgi/kernel/indy_sc.c	Thu Jul  1 10:45:57 1999
+++ linux/arch/mips/sgi/kernel/indy_sc.c	Thu Aug 26 12:42:32 1999
@@ -150,7 +150,7 @@
         " : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
 }
 
-__initfunc(static inline int indy_sc_probe(void))
+static inline int __init indy_sc_probe(void)
 {
 	volatile unsigned int *cpu_control;
 	unsigned short cmd = 0xc220;
@@ -219,7 +219,7 @@
 	indy_sc_wback_invalidate
 };
 
-__initfunc(void indy_sc_init(void))
+void __init indy_sc_init(void)
 {
 	if (indy_sc_probe()) {
 		indy_sc_enable();
diff -u --recursive --new-file v2.3.15/linux/arch/mips/sgi/kernel/indy_timer.c linux/arch/mips/sgi/kernel/indy_timer.c
--- v2.3.15/linux/arch/mips/sgi/kernel/indy_timer.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/sgi/kernel/indy_timer.c	Thu Aug 26 12:42:32 1999
@@ -176,7 +176,7 @@
 	  )*60 + sec; /* finally seconds */
 }
 
-__initfunc(static unsigned long get_indy_time(void))
+static unsigned long __init get_indy_time(void)
 {
 	struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS;
 	unsigned int year, mon, day, hour, min, sec;
@@ -221,7 +221,7 @@
 
 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
 
-__initfunc(void indy_timer_init(void))
+void __init indy_timer_init(void)
 {
 	struct sgi_ioc_timers *p;
 	volatile unsigned char *tcwp, *tc2p;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/sgi/kernel/promcon.c linux/arch/mips/sgi/kernel/promcon.c
--- v2.3.15/linux/arch/mips/sgi/kernel/promcon.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/sgi/kernel/promcon.c	Thu Aug 26 12:42:32 1999
@@ -37,7 +37,7 @@
     return prom_getchar();
 }
 
-__initfunc(static int prom_console_setup(struct console *co, char *options))
+static int __init prom_console_setup(struct console *co, char *options)
 {
     return 0;
 }
@@ -66,7 +66,7 @@
  *    Register console.
  */
 
-__initfunc(long sgi_prom_console_init(long kmem_start, long kmem_end))
+long __init sgi_prom_console_init(long kmem_start, long kmem_end)
 {
     register_console(&sercons);
     return kmem_start;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c
--- v2.3.15/linux/arch/mips/sgi/kernel/setup.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/sgi/kernel/setup.c	Thu Aug 26 12:42:32 1999
@@ -118,7 +118,7 @@
 	sgi_read_status
 };
 
-__initfunc(static void sgi_irq_setup(void))
+static void __init sgi_irq_setup(void)
 {
 	sgint_init();
 
@@ -129,7 +129,7 @@
 #endif
 }
 
-__initfunc(void sgi_setup(void))
+void __init sgi_setup(void)
 {
 #ifdef CONFIG_SERIAL_CONSOLE
 	char *ctype;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/sgi/kernel/system.c linux/arch/mips/sgi/kernel/system.c
--- v2.3.15/linux/arch/mips/sgi/kernel/system.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/sgi/kernel/system.c	Thu Aug 26 12:42:32 1999
@@ -35,7 +35,7 @@
 
 #define NUM_CPUS 9 /* for now */
 
-__initfunc(static int string_to_cpu(char *s))
+static int __init string_to_cpu(char *s)
 {
 	int i;
 
@@ -54,7 +54,7 @@
  * We' call this early before loadmmu().  If we do the other way around
  * the firmware will crash and burn.
  */
-__initfunc(void sgi_sysinit(void))
+void __init sgi_sysinit(void)
 {
 	pcomponent *p, *toplev, *cpup = 0;
 	int cputype = -1;
diff -u --recursive --new-file v2.3.15/linux/arch/mips/sgi/kernel/time.c linux/arch/mips/sgi/kernel/time.c
--- v2.3.15/linux/arch/mips/sgi/kernel/time.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/sgi/kernel/time.c	Thu Aug 26 12:42:32 1999
@@ -8,7 +8,7 @@
 
 extern void indy_timer_init(void);
 
-__initfunc(void time_init(void))
+void __init time_init(void)
 {
 	/* XXX assume INDY for now XXX */
 	indy_timer_init();
diff -u --recursive --new-file v2.3.15/linux/arch/mips/sni/pcimt_scache.c linux/arch/mips/sni/pcimt_scache.c
--- v2.3.15/linux/arch/mips/sni/pcimt_scache.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/sni/pcimt_scache.c	Thu Aug 26 12:42:32 1999
@@ -16,7 +16,7 @@
 #define cacheconf (*(volatile unsigned int *)PCIMT_CACHECONF)
 #define invspace (*(volatile unsigned int *)PCIMT_INVSPACE)
 
-__initfunc(void sni_pcimt_sc_init(void))
+void __init sni_pcimt_sc_init(void)
 {
 	unsigned int scsiz, sc_size;
 
diff -u --recursive --new-file v2.3.15/linux/arch/mips/sni/setup.c linux/arch/mips/sni/setup.c
--- v2.3.15/linux/arch/mips/sni/setup.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/sni/setup.c	Thu Aug 26 12:42:32 1999
@@ -53,7 +53,7 @@
 extern struct rtc_ops std_rtc_ops;
 extern struct kbd_ops std_kbd_ops;
 
-__initfunc(static void sni_irq_setup(void))
+static void __init sni_irq_setup(void)
 {
 	set_except_vector(0, sni_rm200_pci_handle_int);
 	request_region(0x20,0x20, "pic1");
@@ -69,7 +69,7 @@
 
 void (*board_time_init)(struct irqaction *irq);
 
-__initfunc(static void sni_rm200_pci_time_init(struct irqaction *irq))
+static void __init sni_rm200_pci_time_init(struct irqaction *irq)
 {
 	/* set the clock to 100 Hz */
 	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
@@ -104,7 +104,7 @@
 	printk("%s.\n", boardtype);
 }
 
-__initfunc(void sni_rm200_pci_setup(void))
+void __init sni_rm200_pci_setup(void)
 {
 	tag *atag;
 
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/8xx_io/fec.c linux/arch/ppc/8xx_io/fec.c
--- v2.3.15/linux/arch/ppc/8xx_io/fec.c	Wed Aug 18 11:39:01 1999
+++ linux/arch/ppc/8xx_io/fec.c	Thu Aug 26 12:42:32 1999
@@ -790,7 +790,7 @@
 
 /* Initialize the FECC Ethernet on 860T.
  */
-__initfunc(int m8xx_enet_init(void))
+int __init m8xx_enet_init(void)
 {
 	struct net_device *dev;
 	struct fec_enet_private *fep;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c
--- v2.3.15/linux/arch/ppc/8xx_io/uart.c	Sat May 15 15:05:35 1999
+++ linux/arch/ppc/8xx_io/uart.c	Tue Aug 31 11:30:47 1999
@@ -1826,7 +1826,7 @@
 				   serial_inp(info, UART_MCR) |
 				   (UART_MCR_DTR | UART_MCR_RTS));
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ASYNC_INITIALIZED)) {
 #ifdef SERIAL_DO_RESTART
@@ -2243,7 +2243,7 @@
 /*
  *	Register console.
  */
-__initfunc (long console_8xx_init(long kmem_start, long kmem_end))
+long __init console_8xx_init(long kmem_start, long kmem_end)
 {
 	register_console(&sercons);
 	return kmem_start;
@@ -2254,7 +2254,7 @@
 /*
  * The serial driver boot-time initialization code!
  */
-__initfunc(int rs_8xx_init(void))
+int __init rs_8xx_init(void)
 {
 	struct serial_state * state;
 	ser_info_t	*info;
@@ -2596,7 +2596,7 @@
 /* This must always be called before the rs_8xx_init() function, otherwise
  * it blows away the port control information.
 */
-__initfunc(static int serial_console_setup(struct console *co, char *options))
+static int __init serial_console_setup(struct console *co, char *options)
 {
 	struct		serial_state *ser;
 	uint		mem_addr, dp_addr;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/Makefile linux/arch/ppc/Makefile
--- v2.3.15/linux/arch/ppc/Makefile	Mon Jul 12 15:12:55 1999
+++ linux/arch/ppc/Makefile	Tue Aug 31 11:36:43 1999
@@ -21,8 +21,8 @@
 ASFLAGS		=
 LINKFLAGS	= -T arch/ppc/vmlinux.lds -Ttext $(KERNELLOAD) -Bstatic
 CFLAGSINC	= -D__KERNEL__ -I$(TOPDIR)/include -D__powerpc__
-CFLAGS		:= $(CFLAGS) -D__powerpc__ -fsigned-char -msoft-float -pipe \
-		-fno-builtin -ffixed-r2 -Wno-uninitialized -mmultiple \
+CFLAGS		:= $(CFLAGS) -I$(HPATH) -D__powerpc__ -fsigned-char -msoft-float \
+		-pipe -fno-builtin -ffixed-r2 -Wno-uninitialized -mmultiple \
 		-mstring
 CPP		= $(CC) -E $(CFLAGS)
 
@@ -34,12 +34,22 @@
 CFLAGS := $(CFLAGS) -Wa,-mppc64bridge #-mpowerpc64
 endif
 
+ifndef CONFIG_8xx
 HEAD := arch/ppc/kernel/head.o
+else
+HEAD := arch/ppc/kernel/head_8xx.o
+endif
 
 ARCH_SUBDIRS = arch/ppc/kernel arch/ppc/mm arch/ppc/lib
 SUBDIRS := $(SUBDIRS) $(ARCH_SUBDIRS)
 ARCHIVES := arch/ppc/kernel/kernel.o arch/ppc/mm/mm.o arch/ppc/lib/lib.o $(ARCHIVES)
 CORE_FILES := arch/ppc/kernel/kernel.o arch/ppc/mm/mm.o arch/ppc/lib/lib.o $(CORE_FILES)
+
+ifdef CONFIG_8xx
+SUBDIRS += arch/ppc/math-emu
+ARCHIVES += arch/ppc/math-emu/math-emu.o
+CORE_FILES += arch/ppc/math-emu/math-emu.o
+endif
 
 ifdef CONFIG_XMON
 SUBDIRS += arch/ppc/xmon
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/amiga/amiints.c linux/arch/ppc/amiga/amiints.c
--- v2.3.15/linux/arch/ppc/amiga/amiints.c	Mon Jul 12 15:12:55 1999
+++ linux/arch/ppc/amiga/amiints.c	Tue Aug 31 11:36:43 1999
@@ -79,7 +79,7 @@
  * the amiga IRQ handling routines.
  */
 
-__initfunc(void amiga_init_IRQ(void))
+void __init amiga_init_IRQ(void)
 {
 	int i;
 
@@ -108,7 +108,7 @@
 	custom.intreq = 0x7fff;
 
 #ifdef CONFIG_APUS
-	/* Clear any inter-CPU interupt requests. Circumvents bug in
+	/* Clear any inter-CPU interrupt requests. Circumvents bug in
            Blizzard IPL emulation HW (or so it appears). */
 	APUS_WRITE(APUS_INT_LVL, INTLVL_SETRESET | INTLVL_MASK);
 
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/amiga/bootinfo.c linux/arch/ppc/amiga/bootinfo.c
--- v2.3.15/linux/arch/ppc/amiga/bootinfo.c	Mon Dec 21 08:37:20 1998
+++ linux/arch/ppc/amiga/bootinfo.c	Thu Aug 26 12:42:32 1999
@@ -24,7 +24,7 @@
 extern int atari_parse_bootinfo(const struct bi_record *);
 extern int mac_parse_bootinfo(const struct bi_record *);
 
-__initfunc(void parse_bootinfo(const struct bi_record *record))
+void __init parse_bootinfo(const struct bi_record *record)
 {
     while (record->tag != BI_LAST) {
 	int unknown = 0;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/amiga/config.c linux/arch/ppc/amiga/config.c
--- v2.3.15/linux/arch/ppc/amiga/config.c	Tue Jul 13 02:29:35 1999
+++ linux/arch/ppc/amiga/config.c	Thu Aug 26 12:42:32 1999
@@ -183,7 +183,7 @@
      *  Identify builtin hardware
      */
 
-__initfunc(static void amiga_identify(void))
+static void __init amiga_identify(void)
 {
   /* Fill in some default values, if necessary */
   if (amiga_eclock == 0)
@@ -344,7 +344,7 @@
      *  Setup the Amiga configuration info
      */
 
-__initfunc(void config_amiga(void))
+void __init config_amiga(void)
 {
   amiga_debug_init();
   amiga_identify();
@@ -437,8 +437,8 @@
 
 static unsigned short jiffy_ticks;
 
-__initfunc(static void amiga_sched_init(void (*timer_routine)(int, void *,
-					struct pt_regs *)))
+static void __init amiga_sched_init(void (*timer_routine)(int, void *,
+					struct pt_regs *))
 {
 	jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
 
@@ -819,7 +819,7 @@
 }
 #endif
 
-__initfunc(static void amiga_debug_init(void))
+static void __init amiga_debug_init(void)
 {
 	if (!strcmp( m68k_debug_device, "ser" )) {
 		/* no initialization required (?) */
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/amiga/ints.c linux/arch/ppc/amiga/ints.c
--- v2.3.15/linux/arch/ppc/amiga/ints.c	Tue Aug  4 16:06:36 1998
+++ linux/arch/ppc/amiga/ints.c	Thu Aug 26 12:42:32 1999
@@ -42,7 +42,7 @@
  * the IRQ handling routines.
  */
 
-__initfunc(void apus_init_IRQ(void))
+void __init apus_init_IRQ(void)
 {
 	int i;
 
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v2.3.15/linux/arch/ppc/boot/Makefile	Sat May 22 13:03:00 1999
+++ linux/arch/ppc/boot/Makefile	Tue Aug 31 11:36:43 1999
@@ -47,9 +47,9 @@
 OBJCOPY_ARGS = -O elf32-powerpc
 
 OBJECTS += vreset.o kbd.o of1275.o
- ifeq ($(CONFIG_SERIAL_CONSOLE),y)
-  OBJECTS += ns16550.o
- endif
+ifeq ($(CONFIG_SERIAL_CONSOLE),y)
+OBJECTS += ns16550.o
+endif
 
 all:	zImage
 
@@ -71,9 +71,12 @@
 		zvmlinux.initrd.tmp $@
 	rm zvmlinux.initrd.tmp
 
-zImage: zvmlinux mkprep
+zImage: zvmlinux mkprep sImage
 	./mkprep -pbp zvmlinux zImage
 
+sImage: ../../../vmlinux
+	$(OBJCOPY) -I elf32-powerpc -O binary ../../../vmlinux sImage
+
 zImage.initrd: zvmlinux.initrd mkprep
 	./mkprep -pbp zvmlinux.initrd zImage.initrd
 
@@ -105,6 +108,7 @@
 
 znetboot : zImage
 	cp zImage $(TFTPIMAGE)
+	cp sImage /tftpboot/
 
 znetboot.initrd : zImage.initrd
 	cp zImage.initrd $(TFTPIMAGE)
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/boot/head.S linux/arch/ppc/boot/head.S
--- v2.3.15/linux/arch/ppc/boot/head.S	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/boot/head.S	Tue Aug 31 11:36:43 1999
@@ -6,7 +6,7 @@
 	.text
 
 /*
- * $Id: head.S,v 1.31 1999/04/22 06:32:00 davem Exp $
+ * $Id: head.S,v 1.32 1999/08/12 19:51:12 cort Exp $
  *	
  * Boot loader philosophy:
  *      ROM loads us to some arbitrary location
@@ -126,9 +126,7 @@
 	 * entry.  see boot/head.S -- Cort 
 	 */
 	li	r9,0x0
-	lwz	r9,0(r9)
 	mtlr	r9
-	li	r9,0
 	lis	r10,0xdeadc0de@h
 	ori	r10,r10,0xdeadc0de@l
 	stw	r10,0(r9)
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c
--- v2.3.15/linux/arch/ppc/boot/misc.c	Sat May 22 13:03:00 1999
+++ linux/arch/ppc/boot/misc.c	Tue Aug 31 11:36:43 1999
@@ -1,7 +1,7 @@
 /*
  * misc.c
  *
- * $Id: misc.c,v 1.65 1999/05/17 19:11:13 cort Exp $
+ * $Id: misc.c,v 1.67 1999/08/10 22:53:57 cort Exp $
  * 
  * Adapted for PowerPC by Gary Thomas
  *
@@ -309,8 +309,6 @@
 	inflateEnd(&s);
 }
 
-unsigned char sanity[0x2000];
-
 unsigned long
 decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
 		  RESIDUAL *residual, void *OFW_interface)
@@ -333,7 +331,6 @@
 	cols = 80;
 	orig_x = 0;
 	orig_y = 24;
-
 	
 	/*
 	 * IBM's have the MMU on, so we have to disable it or
@@ -525,7 +522,6 @@
 		puts("initrd_start located > 16M\n");
        
 	puts("Uncompressing Linux...");
-
 	gunzip(0, 0x400000, zimage_start, &zimage_size);
 	puts("done.\n");
 	puts("Now booting the kernel\n");
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/chrpboot/Makefile linux/arch/ppc/chrpboot/Makefile
--- v2.3.15/linux/arch/ppc/chrpboot/Makefile	Mon Jun 28 13:40:39 1999
+++ linux/arch/ppc/chrpboot/Makefile	Tue Aug 31 11:36:43 1999
@@ -57,7 +57,10 @@
 	mcopy zImage a:zImage
 
 piggyback: piggyback.c
-	$(HOSTCC) -DKERNELBASE=$(KERNELBASE) -o piggyback piggyback.c
+	$(HOSTCC) $(HOSTCFLAGS) -DKERNELBASE=$(KERNELBASE) -o piggyback piggyback.c
+
+mknote: mknote.c
+	$(HOSTCC) $(HOSTCFLAGS) -o mknote mknote.c
 
 image.o: piggyback ../coffboot/vmlinux.gz
 	./piggyback image < ../coffboot/vmlinux.gz | $(AS) -o image.o
@@ -69,9 +72,6 @@
 	$(LD) $(LD_ARGS) -o $@ $(OBJS) no_initrd.o $(LIBS)
 	./mknote > note
 	$(OBJCOPY) $@ $@ --add-section=.note=note -R .comment
-
-mknote: mknote.c
-	$(HOSTCC) $(HOSTCFLAGS) -o $@ mknote.c
 
 zImage.initrd: $(OBJS) initrd.o
 	$(LD) $(LD_ARGS) -o $@ $(OBJS) initrd.o $(LIBS)
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/chrpboot/main.c linux/arch/ppc/chrpboot/main.c
--- v2.3.15/linux/arch/ppc/chrpboot/main.c	Mon Jul 12 15:12:55 1999
+++ linux/arch/ppc/chrpboot/main.c	Tue Aug 31 11:36:43 1999
@@ -68,7 +68,7 @@
 
     flush_cache(dst, len);
     
-    sa = *(unsigned long *)PROG_START+PROG_START;
+    sa = (unsigned long)PROG_START;
     printf("start address = 0x%x\n\r", sa);
 
     (*(void (*)())sa)(0, 0, prom, a1, a2);
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/coffboot/main.c linux/arch/ppc/coffboot/main.c
--- v2.3.15/linux/arch/ppc/coffboot/main.c	Tue Aug  4 16:06:36 1998
+++ linux/arch/ppc/coffboot/main.c	Tue Aug 31 11:36:43 1999
@@ -100,7 +100,7 @@
 
     flush_cache(dst, len);
 
-    sa = *(unsigned *)dst + PROG_START;
+    sa = (unsigned long)dst;
     printf("start address = 0x%x\n", sa);
 
 #if 0
@@ -165,7 +165,7 @@
 	printf("gunzip: ran out of data in header\n");
 	exit();
     }
-
+printf("done 1\n");
     s.zalloc = zalloc;
     s.zfree = zfree;
     r = inflateInit2(&s, -MAX_WBITS);
@@ -177,11 +177,14 @@
     s.avail_in = *lenp - i;
     s.next_out = dst;
     s.avail_out = dstlen;
+printf("doing inflate\n");
     r = inflate(&s, Z_FINISH);
+printf("done inflate\n");
     if (r != Z_OK && r != Z_STREAM_END) {
 	printf("inflate returned %d\n", r);
 	exit();
     }
     *lenp = s.next_out - (unsigned char *) dst;
+printf("doing end\n");
     inflateEnd(&s);
 }
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/common_defconfig linux/arch/ppc/common_defconfig
--- v2.3.15/linux/arch/ppc/common_defconfig	Mon Jun 28 13:40:39 1999
+++ linux/arch/ppc/common_defconfig	Tue Aug 31 11:36:43 1999
@@ -35,7 +35,6 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
 # CONFIG_BINFMT_MISC is not set
-# CONFIG_BINFMT_JAVA is not set
 # CONFIG_PARPORT is not set
 CONFIG_VGA_CONSOLE=y
 CONFIG_FB=y
@@ -44,8 +43,6 @@
 CONFIG_MAC_KEYBOARD=y
 CONFIG_MAC_FLOPPY=y
 CONFIG_MAC_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-CONFIG_ADBMOUSE=y
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_TOTALMP is not set
 CONFIG_BOOTX_TEXT=y
@@ -53,11 +50,6 @@
 # CONFIG_CMDLINE_BOOL is not set
 
 #
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
 # Block devices
 #
 CONFIG_BLK_DEV_FD=y
@@ -80,9 +72,11 @@
 CONFIG_BLK_DEV_SL82C105=y
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_BLK_DEV_IDEDMA=y
 CONFIG_IDEDMA_PMAC_AUTO=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_IDEDMA_AUTO=y
 # CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_CPQ_DA is not set
 
 #
 # Additional Block Devices
@@ -230,10 +224,18 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
 # CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
 CONFIG_NET_ETHERNET=y
 CONFIG_MACE=y
 CONFIG_BMAC=y
@@ -243,10 +245,10 @@
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_RTL8139 is not set
 # CONFIG_YELLOWFIN is not set
-# CONFIG_ACENIC is not set
 # CONFIG_NET_ISA is not set
 CONFIG_NET_EISA=y
 CONFIG_PCNET32=y
+# CONFIG_ACENIC is not set
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
@@ -265,7 +267,10 @@
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-# CONFIG_DLCI is not set
+
+#
+# Appletalk devices
+#
 # CONFIG_LTPC is not set
 # CONFIG_COPS is not set
 # CONFIG_IPDDP is not set
@@ -276,11 +281,21 @@
 #
 # CONFIG_SLIP is not set
 # CONFIG_NET_RADIO is not set
+
+#
+# Token ring devices
+#
 # CONFIG_TR is not set
+# CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
 # CONFIG_HOSTESS_SV11 is not set
 # CONFIG_COSA is not set
-# CONFIG_RCPCI is not set
+# CONFIG_SEALEVEL_4021 is not set
+# CONFIG_DLCI is not set
 
 #
 # Amateur Radio support
@@ -342,14 +357,16 @@
 # CONFIG_SERIAL_NONSTANDARD is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_MOUSE=y
 
 #
 # Mice
 #
+CONFIG_BUSMOUSE=y
 # CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_BUSMOUSE is not set
+# CONFIG_LOGIBUSMOUSE is not set
 # CONFIG_MS_BUSMOUSE is not set
+CONFIG_ADBMOUSE=y
+CONFIG_MOUSE=y
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
@@ -383,17 +400,19 @@
 # CONFIG_FT_ALT_FDC is not set
 
 #
+# USB drivers - not for the faint of heart
+#
+# CONFIG_USB is not set
+
+#
 # Filesystems
 #
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=y
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-# CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=y
+# CONFIG_HFS_FS is not set
+# CONFIG_FAT_FS is not set
 # CONFIG_EFS_FS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -429,38 +448,7 @@
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_SGI_DISKLABEL is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
-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_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS is not set
 
 #
 # Sound
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.3.15/linux/arch/ppc/config.in	Thu Aug 26 13:05:34 1999
+++ linux/arch/ppc/config.in	Tue Aug 31 11:36:43 1999
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.95 1999/07/03 08:57:06 davem Exp $
+# $Id: config.in,v 1.102 1999/08/30 10:06:53 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -25,8 +25,12 @@
   define_bool CONFIG_MACH_SPECIFIC y
 fi
 
-if [ "$CONFIG_PPC64" != "y" ];then
-  define_bool CONFIG_6xx y
+if [ "$CONFIG_8xx" = "y" ]; then
+  bool 'Math emulation' CONFIG_MATH_EMULATION
+else
+  if [ "$CONFIG_PPC64" != "y" ];then
+    define_bool CONFIG_6xx y
+  fi
 fi
 endmenu
 
@@ -71,11 +75,10 @@
 bool 'Power management support for PowerBook 3400/2400' CONFIG_PMAC_PBOOK
 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
+tristate 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL
 if [ "$CONFIG_MAC_SERIAL" = "y" ]; then
    bool '   Support for console on serial port' CONFIG_SERIAL_CONSOLE
 fi
-bool 'Support for PowerMac ADB mouse' CONFIG_ADBMOUSE
 bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
 bool 'Support for TotalImpact TotalMP' CONFIG_TOTALMP
 bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT
@@ -166,6 +169,7 @@
 endmenu
 
 source drivers/char/Config.in
+source drivers/usb/Config.in
 source fs/Config.in
 
 mainmenu_option next_comment
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.3.15/linux/arch/ppc/defconfig	Mon Jun 28 13:40:39 1999
+++ linux/arch/ppc/defconfig	Tue Aug 31 11:36:43 1999
@@ -43,8 +43,6 @@
 CONFIG_MAC_KEYBOARD=y
 CONFIG_MAC_FLOPPY=y
 CONFIG_MAC_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-CONFIG_ADBMOUSE=y
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_TOTALMP is not set
 CONFIG_BOOTX_TEXT=y
@@ -52,11 +50,6 @@
 # CONFIG_CMDLINE_BOOL is not set
 
 #
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
 # Block devices
 #
 CONFIG_BLK_DEV_FD=y
@@ -79,9 +72,11 @@
 CONFIG_BLK_DEV_SL82C105=y
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_BLK_DEV_IDEDMA=y
 CONFIG_IDEDMA_PMAC_AUTO=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_IDEDMA_AUTO=y
 # CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_CPQ_DA is not set
 
 #
 # Additional Block Devices
@@ -229,10 +224,18 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
 # CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
 CONFIG_NET_ETHERNET=y
 CONFIG_MACE=y
 CONFIG_BMAC=y
@@ -242,10 +245,10 @@
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_RTL8139 is not set
 # CONFIG_YELLOWFIN is not set
-# CONFIG_ACENIC is not set
 # CONFIG_NET_ISA is not set
 CONFIG_NET_EISA=y
 CONFIG_PCNET32=y
+# CONFIG_ACENIC is not set
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
@@ -264,7 +267,10 @@
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-# CONFIG_DLCI is not set
+
+#
+# Appletalk devices
+#
 # CONFIG_LTPC is not set
 # CONFIG_COPS is not set
 # CONFIG_IPDDP is not set
@@ -275,11 +281,21 @@
 #
 # CONFIG_SLIP is not set
 # CONFIG_NET_RADIO is not set
+
+#
+# Token ring devices
+#
 # CONFIG_TR is not set
+# CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
 # CONFIG_HOSTESS_SV11 is not set
 # CONFIG_COSA is not set
-# CONFIG_RCPCI is not set
+# CONFIG_SEALEVEL_4021 is not set
+# CONFIG_DLCI is not set
 
 #
 # Amateur Radio support
@@ -341,14 +357,16 @@
 # CONFIG_SERIAL_NONSTANDARD is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_MOUSE=y
 
 #
 # Mice
 #
+CONFIG_BUSMOUSE=y
 # CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_BUSMOUSE is not set
+# CONFIG_LOGIBUSMOUSE is not set
 # CONFIG_MS_BUSMOUSE is not set
+CONFIG_ADBMOUSE=y
+CONFIG_MOUSE=y
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
@@ -382,17 +400,19 @@
 # CONFIG_FT_ALT_FDC is not set
 
 #
+# USB drivers - not for the faint of heart
+#
+# CONFIG_USB is not set
+
+#
 # Filesystems
 #
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=y
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-# CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=y
+# CONFIG_HFS_FS is not set
+# CONFIG_FAT_FS is not set
 # CONFIG_EFS_FS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -428,38 +448,7 @@
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_SGI_DISKLABEL is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
-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_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS is not set
 
 #
 # Sound
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- v2.3.15/linux/arch/ppc/kernel/Makefile	Mon Jun 28 13:40:39 1999
+++ linux/arch/ppc/kernel/Makefile	Tue Aug 31 11:36:43 1999
@@ -14,8 +14,11 @@
 OX_OBJS := ppc_ksyms.o setup.o
 
 
-O_OBJS := traps.o irq.o idle.o time.o process.o signal.o syscalls.o misc.o \
-	  bitops.o ptrace.o align.o ppc_htab.o
+O_OBJS := entry.o traps.o irq.o idle.o time.o process.o signal.o syscalls.o \
+	  misc.o bitops.o ptrace.o align.o ppc_htab.o semaphore.o
+ifndef CONFIG_8xx
+O_OBJS += hashtable.o
+endif
 ifdef CONFIG_PCI
 O_OBJS += pci.o
 endif
@@ -27,17 +30,18 @@
 endif
 
 ifeq ($(CONFIG_MBX),y)
-O_OBJS += mbx_setup.o mbx_pci.o softemu8xx.o i8259.o ppc8xx_pic.o
+O_OBJS += mbx_setup.o mbx_pci.o i8259.o ppc8xx_pic.o
 else
 ifeq ($(CONFIG_APUS),y)
-O_OBJS += apus_setup.o prom.o openpic.o
+O_OBJS += apus_setup.o prom.o open_pic.o
 else
 ifneq ($(CONFIG_MBX),y)
 O_OBJS += prep_time.o pmac_time.o chrp_time.o \
 	  pmac_setup.o pmac_support.o \
 	  prep_pci.o pmac_pci.o chrp_pci.o \
-	  residual.o prom.o openpic.o feature.o \
-	  prep_nvram.o open_pic.o i8259.o pmac_pic.o indirect_pci.o
+	  residual.o prom.o open_pic.o feature.o \
+	  prep_nvram.o i8259.o pmac_pic.o indirect_pci.o \
+	  gemini_pci.o gemini_prom.o gemini_setup.o
 OX_OBJS += chrp_setup.o prep_setup.o
 endif
 endif
@@ -49,7 +53,7 @@
 
 all: head.o kernel.o
 
-head.o: head.S $(TOPDIR)/include/linux/tasks.h ppc_defs.h
+head.o: head.S ppc_defs.h
 
 ppc_defs.h: mk_defs.c ppc_defs.head \
 		$(TOPDIR)/include/asm/mmu.h \
@@ -65,7 +69,7 @@
 	$(HOSTCC) $(HOSTCFLAGS) -o find_name find_name.c
 
 checks: checks.c
-	$(HOSTCC) $(HOSTCFLAGS) -D__KERNEL__ -o checks checks.c
+	$(HOSTCC) -I$(HPATH) $(HOSTCFLAGS) -D__KERNEL__ -o checks checks.c
 	./checks
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/align.c linux/arch/ppc/kernel/align.c
--- v2.3.15/linux/arch/ppc/kernel/align.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/align.c	Tue Aug 31 11:36:43 1999
@@ -243,10 +243,10 @@
 		}
 		break;
 	case LD+F:
-		current->tss.fpr[reg] = data.d;
+		current->thread.fpr[reg] = data.d;
 		break;
 	case ST+F:
-		data.d = current->tss.fpr[reg];
+		data.d = current->thread.fpr[reg];
 		break;
 	/* these require some floating point conversions... */
 	/* we'd like to use the assignment, but we have to compile
@@ -254,13 +254,13 @@
 	 * fp regs for copying 8-byte objects. */
 	case LD+F+S:
 		enable_kernel_fp();
-		cvt_fd(&data.f, &current->tss.fpr[reg], &current->tss.fpscr);
-		/* current->tss.fpr[reg] = data.f; */
+		cvt_fd(&data.f, &current->thread.fpr[reg], &current->thread.fpscr);
+		/* current->thread.fpr[reg] = data.f; */
 		break;
 	case ST+F+S:
 		enable_kernel_fp();
-		cvt_df(&current->tss.fpr[reg], &data.f, &current->tss.fpscr);
-		/* data.f = current->tss.fpr[reg]; */
+		cvt_df(&current->thread.fpr[reg], &data.f, &current->thread.fpscr);
+		/* data.f = current->thread.fpr[reg]; */
 		break;
 	default:
 		printk("align: can't handle flags=%x\n", flags);
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- v2.3.15/linux/arch/ppc/kernel/apus_setup.c	Mon Aug  9 12:32:28 1999
+++ linux/arch/ppc/kernel/apus_setup.c	Thu Aug 26 12:42:32 1999
@@ -103,8 +103,8 @@
 
 /*********************************************************** SETUP */
 /* From arch/m68k/kernel/setup.c. */
-__initfunc(void apus_setup_arch(unsigned long * memory_start_p,
-				unsigned long * memory_end_p))
+void __init apus_setup_arch(unsigned long * memory_start_p,
+				unsigned long * memory_end_p)
 {
 	extern char cmd_line[];
 	int i;
@@ -245,7 +245,7 @@
 
 /*********************************************************** FLOPPY */
 #if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
-__initfunc(void floppy_setup(char *str, int *ints))
+void __init floppy_setup(char *str, int *ints)
 {
 	if (mach_floppy_setup)
 		mach_floppy_setup (str, ints);
@@ -560,24 +560,24 @@
         m68k_ide_fix_driveid(id);
 }
 
-__initfunc(void
-apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq))
+void __init
+apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
         m68k_ide_init_hwif_ports(hw, data_port, ctrl_port, irq);
 }
 #endif
 
-__initfunc(void
-apus_local_init_IRQ(void))
+void __init
+apus_local_init_IRQ(void)
 {
 	ppc_md.mask_irq = amiga_disable_irq;
 	ppc_md.unmask_irq = amiga_enable_irq;
 	apus_init_IRQ();
 }
 
-__initfunc(void
+void __init
 apus_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	  unsigned long r6, unsigned long r7))
+	  unsigned long r6, unsigned long r7)
 {
 	/* Parse bootinfo. The bootinfo is located right after
            the kernel bss */
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- v2.3.15/linux/arch/ppc/kernel/chrp_pci.c	Mon Jul 12 15:12:55 1999
+++ linux/arch/ppc/kernel/chrp_pci.c	Tue Aug 31 11:36:43 1999
@@ -279,8 +279,7 @@
 	if ( !strncmp("IBM", get_property(find_path_device("/"),
 					 "name", NULL),3) )
 	{
-		pci_scan_peer_bridge(1);
-		pci_scan_peer_bridge(2);
+		
 	}
 	
 	/* PCI interrupts are controlled by the OpenPIC */
@@ -290,22 +289,22 @@
 			dev->irq = openpic_to_irq( dev->irq );
 		/* adjust the io_port for the NCR cards for busses other than 0 -- Cort */
 		if ( (dev->bus->number > 0) && (dev->vendor == PCI_VENDOR_ID_NCR) )
-			dev->base_address[0] += (dev->bus->number*0x08000000);
+			dev->resource[0].start += (dev->bus->number*0x08000000);
 		/* these need to be absolute addrs for OF and Matrox FB -- Cort */
 		if ( dev->vendor == PCI_VENDOR_ID_MATROX )
 		{
-			if ( dev->base_address[0] < isa_mem_base )
-				dev->base_address[0] += isa_mem_base;
-			if ( dev->base_address[1] < isa_mem_base )
-				dev->base_address[1] += isa_mem_base;
+			if ( dev->resource[0].start < isa_mem_base )
+				dev->resource[0].start += isa_mem_base;
+			if ( dev->resource[1].start < isa_mem_base )
+				dev->resource[1].start += isa_mem_base;
 		}
 		/* the F50 identifies the amd as a trident */
 		if ( (dev->vendor == PCI_VENDOR_ID_TRIDENT) &&
-		      (dev->class == PCI_CLASS_NETWORK_ETHERNET) )
+		      (dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET) )
 		{
 			dev->vendor = PCI_VENDOR_ID_AMD;
-			pcibios_write_config_word(dev->bus->number, dev->devfn,
-						   PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
+			pcibios_write_config_word(dev->bus->number,
+			  dev->devfn, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
 		}
 	}
 }
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.3.15/linux/arch/ppc/kernel/chrp_setup.c	Mon Jul 12 15:12:55 1999
+++ linux/arch/ppc/kernel/chrp_setup.c	Tue Aug 31 11:36:43 1999
@@ -191,20 +191,20 @@
      *  for keyboard and mouse
      */
 
-__initfunc(static inline void sio_write(u8 val, u8 index))
+static inline void __init sio_write(u8 val, u8 index)
 {
 	outb(index, 0x15c);
 	outb(val, 0x15d);
 }
 
-__initfunc(static inline u8 sio_read(u8 index))
+static inline u8 __init sio_read(u8 index)
 {
 	outb(index, 0x15c);
 	return inb(0x15d);
 }
 
-__initfunc(static void sio_fixup_irq(const char *name, u8 device, u8 level,
-				     u8 type))
+static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
+				     u8 type)
 {
 	u8 level0, type0, active;
 
@@ -226,7 +226,7 @@
 
 }
 
-__initfunc(static void sio_init(void))
+static void __init sio_init(void)
 {
 	/* logical device 0 (KBC/Keyboard) */
 	sio_fixup_irq("keyboard", 0, 1, 2);
@@ -235,8 +235,8 @@
 }
 
 
-__initfunc(void
-	   chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
+void __init
+	   chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
 	extern char cmd_line[];
 	struct device_node *device;
@@ -315,7 +315,10 @@
 chrp_event_scan(void)
 {
 	unsigned char log[1024];
-	call_rtas( "event-scan", 4, 1, NULL, 0x0, 1, __pa(log), 1024 );
+	unsigned long ret = 0;
+	/* XXX: we should loop until the hardware says no more error logs -- Cort */
+	call_rtas( "event-scan", 4, 1, &ret, 0xffffffff, 0,
+		   __pa(log), 1024 );
 	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
 }
 	
@@ -331,12 +334,8 @@
 chrp_power_off(void)
 {
 	/* allow power on only with power button press */
-#define	PWR_FIELD(x) (0x8000000000000000ULL >> ((x)-96))
 	printk("RTAS power-off returned %d\n",
-	       call_rtas("power-off", 2, 1, NULL,
-			 ((PWR_FIELD(96)|PWR_FIELD(97))>>32)&0xffffffff,
-			 (PWR_FIELD(96)|PWR_FIELD(97))&0xffffffff));
-#undef PWR_FIELD	
+	       call_rtas("power-off", 2, 1, NULL,0xffffffff,0xffffffff));
 	for (;;);
 }
 
@@ -434,8 +433,8 @@
                 openpic_eoi(0);
 }
 
-__initfunc(void
-	   chrp_init_IRQ(void))
+void __init
+	   chrp_init_IRQ(void)
 {
 	struct device_node *np;
 	int i;
@@ -448,12 +447,9 @@
 			(*(unsigned long *)get_property(np,
 							"8259-interrupt-acknowledge", NULL));
 	}
+	open_pic.irq_offset = 16;
 	for ( i = 16 ; i < NR_IRQS ; i++ )
 		irq_desc[i].ctl = &open_pic;
-	/* openpic knows that it's at irq 16 offset
-	 * so we don't need to set it in the pic structure
-	 * -- Cort
-	 */
 	openpic_init(1);
 	for ( i = 0 ; i < 16  ; i++ )
 		irq_desc[i].ctl = &i8259_pic;
@@ -468,8 +464,8 @@
 #endif	/* __SMP__ */
 }
 
-__initfunc(void
-	   chrp_init2(void))
+void __init
+	   chrp_init2(void)
 {
 	adb_init();
 
@@ -493,12 +489,9 @@
         chrp_ide_ports_known = 1;
 
         if(pdev) {
-                chrp_ide_regbase[0]=pdev->base_address[0] &
-                        PCI_BASE_ADDRESS_IO_MASK;
-                chrp_ide_regbase[1]=pdev->base_address[2] &
-                        PCI_BASE_ADDRESS_IO_MASK;
-                chrp_idedma_regbase=pdev->base_address[4] &
-                        PCI_BASE_ADDRESS_IO_MASK;
+                chrp_ide_regbase[0]=pdev->resource[0].start;
+                chrp_ide_regbase[1]=pdev->resource[2].start;
+                chrp_idedma_regbase=pdev->resource[4].start;
                 chrp_ide_irq=pdev->irq;
         }
 }
@@ -584,9 +577,9 @@
 
 #endif
 
-__initfunc(void
+void __init
 	   chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
-		     unsigned long r6, unsigned long r7))
+		     unsigned long r6, unsigned long r7)
 {
 	chrp_setup_pci_ptrs();
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -688,14 +681,18 @@
 void chrp_progress(char *s, unsigned short hex)
 {
 	extern unsigned int rtas_data;
-	unsigned long width;
+	int max_width, width;
 	struct device_node *root;
 	char *os = s;
-	
-	if ( (root = find_path_device("/rtas")) )
-		width = *(unsigned long *)get_property(root, "ibm,display-line-length", NULL);
+	unsigned long *p;
+
+	if ( (root = find_path_device("/rtas")) &&
+	     (p = (unsigned long *)get_property(root,
+						"ibm,display-line-length",
+						NULL)) )
+		max_width = *p;
 	else
-		width = 0x10;
+		max_width = 0x10;
 
 	if ( (_machine != _MACH_chrp) || !rtas_data )
 		return;
@@ -704,11 +701,22 @@
 		/* assume no display-character RTAS method - use hex display */
 		return;
 	}
+
+	width = max_width;
 	while ( *os )
+	{
+		if ( (*os == '\n') || (*os == '\r') )
+			width = max_width;
+		else
+			width--;
 		call_rtas( "display-character", 1, 1, NULL, *os++ );
-	/* scan back for the last newline or carriage return */
-	for ( os-- ; (*os != '\n') && (*os != '\r') && (os > s) ; os--, width-- )
-		/* nothing */ ;
-	/*while ( width-- )*/
+		/* if we overwrite the screen length */
+		if ( width == 0 )
+			while ( (*os != 0) && (*os != '\n') && (*os != '\r') )
+				os++;
+	}
+
+	/*while ( width-- > 0 )*/
 	call_rtas( "display-character", 1, 1, NULL, ' ' );
 }
+
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/chrp_time.c linux/arch/ppc/kernel/chrp_time.c
--- v2.3.15/linux/arch/ppc/kernel/chrp_time.c	Fri Mar 19 10:50:03 1999
+++ linux/arch/ppc/kernel/chrp_time.c	Thu Aug 26 12:42:32 1999
@@ -31,7 +31,7 @@
 static int nvram_as0 = NVRAM_AS0;
 static int nvram_data = NVRAM_DATA;
 
-__initfunc(void chrp_time_init(void))
+void __init chrp_time_init(void)
 {
 	struct device_node *rtcs;
 	int base;
@@ -151,7 +151,7 @@
 }
 
 
-__initfunc(void chrp_calibrate_decr(void))
+void __init chrp_calibrate_decr(void)
 {
 	struct device_node *cpu;
 	int *fp, divisor;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- v2.3.15/linux/arch/ppc/kernel/entry.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/entry.S	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,436 @@
+/*
+ *  arch/ppc/kernel/entry.S
+ *
+ *  $Id: entry.S,v 1.2 1999/08/23 02:53:16 paulus Exp $
+ *
+ *  PowerPC version 
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
+ *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
+ *  Adapted for Power Macintosh by Paul Mackerras.
+ *  Low-level exception handlers and MMU support
+ *  rewritten by Paul Mackerras.
+ *    Copyright (C) 1996 Paul Mackerras.
+ *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
+ *
+ *  This file contains the system call entry code, context switch
+ *  code, and exception/interrupt return code for PowerPC.
+ *
+ *  This program is free software; you can redistribute 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 "ppc_asm.h"
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <linux/errno.h>
+#include <linux/sys.h>
+#include <linux/config.h>
+
+#define SHOW_SYSCALLS
+#define SHOW_SYSCALLS_TASK
+
+#ifdef SHOW_SYSCALLS_TASK
+	.data
+show_syscalls_task:
+	.long	-1
+#endif
+
+/*
+ * Handle a system call.
+ */
+	.text
+_GLOBAL(DoSyscall)
+	stw	r0,THREAD+LAST_SYSCALL(r2)
+	lwz	r11,_CCR(r1)	/* Clear SO bit in CR */
+	lis	r10,0x1000
+	andc	r11,r11,r10
+	stw	r11,_CCR(r1)
+#ifdef SHOW_SYSCALLS
+#ifdef SHOW_SYSCALLS_TASK
+	lis	r31,show_syscalls_task@ha
+	lwz	r31,show_syscalls_task@l(r31)
+	cmp	0,r2,r31
+	bne	1f
+#endif
+	lis	r3,7f@ha
+	addi	r3,r3,7f@l
+	lwz	r4,GPR0(r1)
+	lwz	r5,GPR3(r1)
+	lwz	r6,GPR4(r1)
+	lwz	r7,GPR5(r1)
+	lwz	r8,GPR6(r1)
+	lwz	r9,GPR7(r1)
+	bl	printk
+	lis	r3,77f@ha
+	addi	r3,r3,77f@l
+	lwz	r4,GPR8(r1)
+	lwz	r5,GPR9(r1)
+	mr	r6,r2
+	bl	printk
+	lwz	r0,GPR0(r1)
+	lwz	r3,GPR3(r1)
+	lwz	r4,GPR4(r1)
+	lwz	r5,GPR5(r1)
+	lwz	r6,GPR6(r1)
+	lwz	r7,GPR7(r1)
+	lwz	r8,GPR8(r1)
+1:
+#endif /* SHOW_SYSCALLS */
+	cmpi	0,r0,0x7777	/* Special case for 'sys_sigreturn' */
+	beq-	10f
+	lwz	r10,TASK_FLAGS(r2)
+	andi.	r10,r10,PF_TRACESYS
+	bne-	50f
+	cmpli	0,r0,NR_syscalls
+	bge-	66f
+	lis	r10,sys_call_table@h
+	ori	r10,r10,sys_call_table@l
+	slwi	r0,r0,2
+	lwzx	r10,r10,r0	/* Fetch system call handler [ptr] */
+	cmpi	0,r10,0
+	beq-	66f
+	mtlr	r10
+	addi	r9,r1,STACK_FRAME_OVERHEAD
+	blrl			/* Call handler */
+	.globl	ret_from_syscall_1
+ret_from_syscall_1:
+20:	stw	r3,RESULT(r1)	/* Save result */
+#ifdef SHOW_SYSCALLS
+#ifdef SHOW_SYSCALLS_TASK
+	cmp	0,r2,r31
+	bne	91f
+#endif
+	mr	r4,r3
+	lis	r3,79f@ha
+	addi	r3,r3,79f@l
+	bl	printk
+	lwz	r3,RESULT(r1)
+91:
+#endif
+	li	r10,-_LAST_ERRNO
+	cmpl	0,r3,r10
+	blt	30f
+	neg	r3,r3
+	cmpi	0,r3,ERESTARTNOHAND
+	bne	22f
+	li	r3,EINTR
+22:	lwz	r10,_CCR(r1)	/* Set SO bit in CR */
+	oris	r10,r10,0x1000
+	stw	r10,_CCR(r1)
+30:	stw	r3,GPR3(r1)	/* Update return value */
+	b	ret_from_except
+66:	li	r3,ENOSYS
+	b	22b
+/* sys_sigreturn */
+10:	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	sys_sigreturn
+	cmpi	0,r3,0		/* Check for restarted system call */
+	bge	ret_from_except
+	b	20b
+/* Traced system call support */
+50:	bl	syscall_trace
+	lwz	r0,GPR0(r1)	/* Restore original registers */
+	lwz	r3,GPR3(r1)
+	lwz	r4,GPR4(r1)
+	lwz	r5,GPR5(r1)
+	lwz	r6,GPR6(r1)
+	lwz	r7,GPR7(r1)
+	lwz	r8,GPR8(r1)
+	lwz	r9,GPR9(r1)
+	cmpli	0,r0,NR_syscalls
+	bge-	66f
+	lis	r10,sys_call_table@h
+	ori	r10,r10,sys_call_table@l
+	slwi	r0,r0,2
+	lwzx	r10,r10,r0	/* Fetch system call handler [ptr] */
+	cmpi	0,r10,0
+	beq-	66f
+	mtlr	r10
+	addi	r9,r1,STACK_FRAME_OVERHEAD
+	blrl			/* Call handler */
+	.globl	ret_from_syscall_2
+ret_from_syscall_2:
+	stw	r3,RESULT(r1)	/* Save result */	
+	stw	r3,GPR0(r1)	/* temporary gross hack to make strace work */
+	li	r10,-_LAST_ERRNO
+	cmpl	0,r3,r10
+	blt	60f
+	neg	r3,r3
+	cmpi	0,r3,ERESTARTNOHAND
+	bne	52f
+	li	r3,EINTR
+52:	lwz	r10,_CCR(r1)	/* Set SO bit in CR */
+	oris	r10,r10,0x1000
+	stw	r10,_CCR(r1)
+60:	stw	r3,GPR3(r1)	/* Update return value */
+	bl	syscall_trace
+	b	ret_from_except
+66:	li	r3,ENOSYS
+	b	52b
+#ifdef SHOW_SYSCALLS
+7:	.string	"syscall %d(%x, %x, %x, %x, %x, "
+77:	.string	"%x, %x), current=%p\n"
+79:	.string	" -> %x\n"
+	.align	2
+#endif
+
+/*
+ * This routine switches between two different tasks.  The process
+ * state of one is saved on its kernel stack.  Then the state
+ * of the other is restored from its kernel stack.  The memory
+ * management hardware is updated to the second process's state.
+ * Finally, we can return to the second process, via ret_from_except.
+ * On entry, r3 points to the THREAD for the current task, r4
+ * points to the THREAD for the new task.
+ *
+ * Note: there are two ways to get to the "going out" portion
+ * of this code; either by coming in via the entry (_switch)
+ * or via "fork" which must set up an environment equivalent
+ * to the "_switch" path.  If you change this (or in particular, the
+ * SAVE_REGS macro), you'll have to change the fork code also.
+ *
+ * The code which creates the new task context is in 'copy_thread'
+ * in arch/ppc/kernel/process.c
+ */	
+_GLOBAL(_switch)
+	stwu	r1,-INT_FRAME_SIZE(r1)
+	stw	r0,GPR0(r1)
+	lwz	r0,0(r1)
+	stw	r0,GPR1(r1)
+	/* r3-r13 are caller saved -- Cort */
+	SAVE_GPR(2, r1)
+	SAVE_8GPRS(14, r1)
+	SAVE_10GPRS(22, r1)
+	mflr	r20		/* Return to switch caller */
+	mfmsr	r22
+	li	r0,MSR_FP	/* Disable floating-point */
+	andc	r22,r22,r0
+	stw	r20,_NIP(r1)
+	stw	r22,_MSR(r1)
+	stw	r20,_LINK(r1)
+	mfcr	r20
+	mfctr	r22
+	mfspr	r23,XER
+	stw	r20,_CCR(r1)
+	stw	r22,_CTR(r1)
+	stw	r23,_XER(r1)
+	li	r0,0x0ff0
+	stw	r0,TRAP(r1)
+	stw	r1,KSP(r3)	/* Set old stack pointer */
+	sync
+	tophys(r0,r4)
+	mtspr	SPRG3,r0	/* Update current THREAD phys addr */
+#ifdef CONFIG_8xx
+	/* XXX it would be nice to find a SPRGx for this on 6xx,7xx too */
+	lwz	r9,PGDIR(r4)	/* cache the page table root */
+        tophys(r9,r9)		/* convert to phys addr */
+        mtspr   M_TWB,r9	/* Update MMU base address */
+#endif /* CONFIG_8xx */
+	lwz	r1,KSP(r4)	/* Load new stack pointer */
+	/* save the old current 'last' for return value */
+	mr	r3,r2
+	addi	r2,r4,-THREAD	/* Update current */
+	lwz	r9,_MSR(r1)	/* Returning to user mode? */
+	andi.	r9,r9,MSR_PR
+	beq+	10f		/* if not, don't adjust kernel stack */
+8:	addi	r4,r1,INT_FRAME_SIZE	/* size of frame */
+	stw	r4,THREAD+KSP(r2)	/* save kernel stack pointer */
+	tophys(r9,r1)
+	mtspr	SPRG2,r9	/* phys exception stack pointer */
+10:	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	/* r3-r13 are destroyed -- Cort */
+	REST_GPR(14, r1)
+	REST_8GPRS(15, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+/*
+ * ret_from_int():
+ *
+ * Return from an interrupt (external interrupt and
+ * decrementer).  This checks the first argument so
+ * we know if rtl_intercept wants us to check for
+ * a bottom half, signals and so on (normal return) or
+ * we're returning from a real-time interrupt or have
+ * interrupts soft disabled so we cannot enter Linux.
+ *   -- Cort
+ */
+	.globl	ret_from_int
+ret_from_int:
+	cmpi	0,r3,0
+	beq	10f
+	/* we're allowed to do signal/bh checks */
+	b	ret_from_syscall
+#ifdef __SMP__	
+	.globl	ret_from_smpfork
+ret_from_smpfork:
+	bl	schedule_tail
+#endif
+	.globl	ret_from_syscall
+ret_from_syscall:
+	.globl	ret_from_except
+ret_from_except:
+0:	mfmsr	r30		/* Disable interrupts */
+	li	r3,0
+	ori	r3,r3,MSR_EE
+	andc	r30,r30,r3
+	SYNC			/* Some chip revs need this... */
+	mtmsr	r30
+	SYNC
+	lwz	r5,_MSR(r1)
+	and.	r5,r5,r4
+	beq	2f
+3:	lis	r4,ppc_n_lost_interrupts@ha
+	lwz	r4,ppc_n_lost_interrupts@l(r4)
+	cmpi	0,r4,0
+	beq+	1f
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	do_IRQ
+	.globl	lost_irq_ret
+lost_irq_ret:
+	b	3b
+1:	lis	r4,bh_mask@ha
+	lwz	r4,bh_mask@l(r4)
+	lis	r5,bh_active@ha
+	lwz	r5,bh_active@l(r5)
+	and.	r4,r4,r5
+	beq+	2f
+	bl	do_bottom_half
+	.globl	do_bottom_half_ret
+do_bottom_half_ret:
+2:	SYNC
+	mtmsr	r30		/* disable interrupts again */
+	SYNC
+	lwz	r3,_MSR(r1)	/* Returning to user mode? */
+	andi.	r3,r3,MSR_PR
+	beq+	10f		/* if so, check need_resched and signals */
+	lwz	r3,NEED_RESCHED(r2)
+	cmpi	0,r3,0		/* check need_resched flag */
+	beq+	7f
+	bl	schedule
+	b	0b
+7:	lwz	r5,SIGPENDING(r2) /* Check for pending unblocked signals */
+	cmpwi	0,r5,0
+	beq+	8f
+	li	r3,0
+	addi	r4,r1,STACK_FRAME_OVERHEAD
+	bl	do_signal
+	.globl	do_signal_ret
+do_signal_ret:
+	b	0b
+8:	addi	r4,r1,INT_FRAME_SIZE	/* size of frame */
+	stw	r4,THREAD+KSP(r2)	/* save kernel stack pointer */
+	tophys(r3,r1)
+	mtspr	SPRG2,r3	/* phys exception stack pointer */
+10:	lwz	r2,_CTR(r1)
+	lwz	r0,_LINK(r1)
+	mtctr	r2
+	mtlr	r0
+	lwz	r2,_XER(r1)
+	lwz	r0,_CCR(r1)
+	mtspr	XER,r2
+	mtcrf	0xFF,r0
+	REST_10GPRS(3, r1)
+	REST_10GPRS(13, r1)
+	REST_8GPRS(23, r1)
+	REST_GPR(31, r1)
+	lwz	r2,_NIP(r1)	/* Restore environment */
+	lwz	r0,_MSR(r1)
+	mtspr	SRR0,r2
+	mtspr	SRR1,r0
+	lwz	r0,GPR0(r1)
+	lwz	r2,GPR2(r1)
+	lwz	r1,GPR1(r1)
+	SYNC
+	rfi
+
+/*
+ * Fake an interrupt from kernel mode.
+ * This is used when enable_irq loses an interrupt.
+ * We only fill in the stack frame minimally.
+ */
+_GLOBAL(fake_interrupt)
+	mflr	r0
+	stw	r0,4(r1)
+	stwu	r1,-INT_FRAME_SIZE(r1)
+	stw	r0,_NIP(r1)
+	stw	r0,_LINK(r1)
+	mfmsr	r3
+	stw	r3,_MSR(r1)
+	li	r0,0x0fac
+	stw	r0,TRAP(r1)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	li	r4,1
+	bl	do_IRQ
+	addi	r1,r1,INT_FRAME_SIZE
+	lwz	r0,4(r1)
+	mtlr	r0
+	blr
+
+#ifndef CONFIG_8xx
+/*
+ * PROM code for specific machines follows.  Put it 
+ * here so it's easy to add arch-specific sections later.
+ * -- Cort
+ */
+	
+/*
+ * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
+ * called with the MMU off.
+ */
+	.globl	enter_rtas
+enter_rtas:
+	mflr	r0
+	stw	r0,20(r1)
+	lis	r4,rtas_data@ha
+	lwz	r4,rtas_data@l(r4)
+	addis	r4,r4,-KERNELBASE@h
+	lis	r6,1f@ha	/* physical return address for rtas */
+	addi	r6,r6,1f@l
+	addis	r6,r6,-KERNELBASE@h
+	subi	r7,r1,INT_FRAME_SIZE
+	addis	r7,r7,-KERNELBASE@h
+	lis	r8,rtas_entry@ha
+	lwz	r8,rtas_entry@l(r8)
+	addis	r5,r8,-KERNELBASE@h
+	mfmsr	r9
+	stw	r9,8(r1)
+	ori	r0,r0,MSR_EE|MSR_SE|MSR_BE
+	andc	r0,r9,r0
+	andi.	r9,r9,MSR_ME|MSR_RI
+	sync			/* disable interrupts so SRR0/1 */
+	mtmsr	r0		/* don't get trashed */
+	mtlr	r6
+	mtspr	SPRG2,r7
+	mtspr	SRR0,r8
+	mtspr	SRR1,r9
+	rfi
+1:	addis	r9,r1,-KERNELBASE@h
+	lwz	r8,20(r9)	/* get return address */
+	lwz	r9,8(r9)	/* original msr value */
+	li	r0,0
+	mtspr	SPRG2,r0
+	mtspr	SRR0,r8
+	mtspr	SRR1,r9
+	rfi			/* return to caller */
+#endif /* CONFIG_8xx */
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/gemini_pci.c linux/arch/ppc/kernel/gemini_pci.c
--- v2.3.15/linux/arch/ppc/kernel/gemini_pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/gemini_pci.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,268 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/malloc.h>
+
+#include <asm/machdep.h>
+#include <asm/gemini.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include "pci.h"
+
+#define pci_config_addr(bus,dev,offset) \
+        (0x80000000 | (bus<<16) | (dev<<8) | offset)
+
+
+int
+gemini_pcibios_read_config_byte(unsigned char bus, unsigned char dev,
+                                unsigned char offset, unsigned char *val)
+{
+	unsigned long reg;
+	reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
+	*val = ((reg >> ((offset & 0x3) << 3)) & 0xff);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_read_config_word(unsigned char bus, unsigned char dev,
+                                unsigned char offset, unsigned short *val)
+{
+	unsigned long reg;
+	reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
+	*val = ((reg >> ((offset & 0x3) << 3)) & 0xffff);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_read_config_dword(unsigned char bus, unsigned char dev,
+                                 unsigned char offset, unsigned int *val)
+{
+	*val = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_byte(unsigned char bus, unsigned char dev,
+                                 unsigned char offset, unsigned char val)
+{
+	unsigned long reg;
+	int shifts = offset & 0x3;
+
+	reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
+	reg = (reg & ~(0xff << (shifts << 3))) | (val << (shifts << 3));
+	grackle_write( pci_config_addr( bus, dev, (offset & ~(0x3))), reg );
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_word(unsigned char bus, unsigned char dev,
+                                 unsigned char offset, unsigned short val)
+{
+	unsigned long reg;
+	int shifts = offset & 0x3;
+
+	reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
+	reg = (reg & ~(0xffff << (shifts << 3))) | (val << (shifts << 3));
+	grackle_write( pci_config_addr( bus, dev, (offset & ~(0x3))), reg );
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_dword(unsigned char bus, unsigned char dev,
+                                  unsigned char offset, unsigned int val)
+{
+	grackle_write( pci_config_addr( bus, dev, (offset & ~(0x3))), val );
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct gemini_device {
+	unsigned short vendor, device;
+	unsigned char irq;
+	unsigned short cmd;
+	unsigned char cache_line, latency;
+	void (*init)(struct pci_dev *dev);
+};
+
+static struct gemini_device gemini_map[] = {
+	{ PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C885, 11, 0x15, 32, 248, NULL },
+	{ PCI_VENDOR_ID_NCR, 0x701, 10, 0, 0, 0, NULL },
+	{ PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C042, 3, 0, 0, 0, NULL },
+	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_MPIC, 0xff, 0, 0, 0, NULL },
+	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_670, 0xff, 0, 0, 0, NULL },
+	{ PCI_VENDOR_ID_MOTOROLA, PCI_DEVICE_ID_MOTOROLA_MPC106, 0xff, 0, 0, 0, NULL },
+};
+
+static int gemini_map_count = (sizeof( gemini_map ) /
+                               sizeof( gemini_map[0] ));
+
+ 
+
+/*  This just sets up the known devices on the board. */
+static void __init mapin_device( struct pci_dev *dev )
+{
+	struct gemini_device *p;
+	unsigned short cmd;
+	int i;
+  
+
+	for( i=0; i < gemini_map_count; i++ ) {
+		p = &(gemini_map[i]);
+    
+		if ( p->vendor == dev->vendor && 
+		     p->device == dev->device ) {
+     
+			if (p->irq != 0xff) {
+				pci_write_config_byte( dev, PCI_INTERRUPT_LINE, p->irq );
+				dev->irq = p->irq;
+			}
+
+			if (p->cmd) {
+				pci_read_config_word( dev, PCI_COMMAND, &cmd );
+				pci_write_config_word( dev, PCI_COMMAND, (p->cmd|cmd));
+			}
+
+			if (p->cache_line)
+				pci_write_config_byte( dev, PCI_CACHE_LINE_SIZE, p->cache_line );
+ 
+			if (p->latency)
+				pci_write_config_byte( dev, PCI_LATENCY_TIMER, p->latency );
+		}
+	}
+}
+
+#define KB 1024
+#define MB (KB*KB)
+
+#define ALIGN(val,align) (((val) + ((align) -1))&(~((align) -1)))
+#define MAX(a,b)   (((a) > (b)) ? (a) : (b))
+
+#define FIRST_IO_ADDR 0x10000
+#define FIRST_MEM_ADDR 0x02000000
+
+#define GEMINI_PCI_MEM_BASE (0xf0000000)
+#define GEMINI_PCI_IO_BASE  (0xfe800000)
+
+static unsigned long pci_mem_base = GEMINI_PCI_MEM_BASE;
+static unsigned long pci_io_base = GEMINI_PCI_IO_BASE;
+
+static unsigned int io_base = FIRST_IO_ADDR;
+static unsigned int mem_base = FIRST_MEM_ADDR;
+
+
+
+static __init void layout_dev( struct pci_dev *dev )
+{
+	int i;
+	struct pci_bus *bus;
+	unsigned short cmd;
+	unsigned int reg, base, mask, size, alignto, type;
+
+	bus = dev->bus;
+
+	/* make any known settings happen */
+	mapin_device( dev );
+
+	gemini_pcibios_read_config_word( bus->number, dev->devfn, PCI_COMMAND, &cmd );
+
+	for( reg = PCI_BASE_ADDRESS_0, i=0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++ ) {
+    
+		/* MPIC already done */
+		if (dev->vendor == PCI_VENDOR_ID_IBM &&
+		    dev->device == PCI_DEVICE_ID_IBM_MPIC)
+			return;
+
+		gemini_pcibios_write_config_dword( bus->number, dev->devfn, reg, 0xffffffff );
+		gemini_pcibios_read_config_dword( bus->number, dev->devfn, reg, &base );
+		if (!base) {
+			dev->resource[i].start = 0;
+			continue;
+		}
+
+		if (base & PCI_BASE_ADDRESS_SPACE_IO) {
+			cmd |= PCI_COMMAND_IO;
+			base &= PCI_BASE_ADDRESS_IO_MASK;
+			mask = (~base << 1) | 0x1;
+			size = (mask & base) & 0xffffffff;
+			alignto = MAX(0x400, size);
+			base = ALIGN(io_base, alignto);
+			io_base = base + size;
+			gemini_pcibios_write_config_dword( bus->number, dev->devfn, reg, 
+							   ((pci_io_base + base) & 0x00ffffff) | 0x1);
+			dev->resource[i].start = (pci_io_base + base) | 0x1;
+		}
+
+		else {
+			cmd |= PCI_COMMAND_MEMORY;
+			type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+			mask = (~base << 1) | 0x1;
+			size = (mask & base) & 0xffffffff;
+			switch( type ) {
+
+			case PCI_BASE_ADDRESS_MEM_TYPE_32:
+				break;
+			case PCI_BASE_ADDRESS_MEM_TYPE_64:
+				printk("Warning: Ignoring 64-bit device; slot %d, function %d.\n",
+				       PCI_SLOT( dev->devfn ), PCI_FUNC( dev->devfn ));
+				reg += 4;
+				continue;
+			}
+
+			alignto = MAX(0x1000, size);
+			base = ALIGN(mem_base, alignto);
+			mem_base = base + size;
+			gemini_pcibios_write_config_dword( bus->number, dev->devfn,
+							   reg, (pci_mem_base + base));
+			dev->resource[i].start = pci_mem_base + base;
+		}
+	}
+
+	if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
+		cmd |= PCI_COMMAND_IO;
+
+	gemini_pcibios_write_config_word( bus->number, dev->devfn, PCI_COMMAND,
+					  (cmd|PCI_COMMAND_MASTER));
+}
+
+static __init void layout_bus( struct pci_bus *bus )
+{
+	struct pci_dev *dev;
+
+	if (!bus->devices && !bus->children)
+		return;
+
+	io_base = ALIGN(io_base, 4*KB);
+	mem_base = ALIGN(mem_base, 4*KB);
+
+	for( dev = bus->devices; dev; dev = dev->sibling ) {
+		if (((dev->class >> 16) != PCI_BASE_CLASS_BRIDGE) ||
+		    ((dev->class >> 8) == PCI_CLASS_BRIDGE_OTHER))
+			layout_dev( dev );
+	}
+}
+
+void __init gemini_pcibios_fixup(void)
+{
+	struct pci_bus *bus;
+	unsigned long orig_mem_base, orig_io_base;
+
+	orig_mem_base = pci_mem_base;
+	orig_io_base = pci_io_base;
+
+	for( bus = &pci_root; bus; bus = bus->children )
+		layout_bus( bus );
+
+	pci_mem_base = orig_mem_base;
+	pci_io_base = orig_io_base;
+}
+
+decl_config_access_method(gemini);
+
+/* The "bootloader" for Synergy boards does none of this for us, so we need to
+   lay it all out ourselves... --Dan */
+void __init gemini_setup_pci_ptrs(void)
+{
+	set_config_access_method(gemini);
+	ppc_md.pcibios_fixup = gemini_pcibios_fixup;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/gemini_prom.S linux/arch/ppc/kernel/gemini_prom.S
--- v2.3.15/linux/arch/ppc/kernel/gemini_prom.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/gemini_prom.S	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,95 @@
+/*
+ *  arch/ppc/kernel/gemini_prom.S
+ *
+ *  Not really prom support code (yet), but sort of anti-prom code.  The current
+ *  bootloader does a number of things it shouldn't and doesn't do things that it
+ *  should.  The stuff in here is mainly a hodge-podge collection of setup code
+ *  to get the board up and running.
+ *    ---Dan
+ */
+
+#include "ppc_asm.tmpl"
+#include "ppc_defs.h"
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/gemini.h>
+
+#define HID0_ABE (1<<3)
+
+/*
+ *  On 750's the MMU is on when Linux is booted, so we need to clear out the
+ *  bootloader's BAT settings, make sure we're in supervisor state (gotcha!),
+ *  and turn off the MMU.
+ *
+ */
+
+_GLOBAL(gemini_prom_init)
+#ifdef __SMP__
+	/* Since the MMU's on, get stuff in rom space that we'll need */
+	lis	r4,GEMINI_CPUSTAT@h
+	ori	r4,r4,GEMINI_CPUSTAT@l
+	lbz	r5,0(r4)
+	andi.	r5,r5,3
+	mr	r24,r5		/* cpu # used later on */
+#endif
+	mfmsr	r4
+	li	r3,MSR_PR	/* ensure supervisor! */
+	ori	r3,r3,MSR_IR|MSR_DR
+	andc	r4,r4,r3
+	mtmsr	r4
+#if 0
+	/* zero out the bats now that the MMU is off */
+prom_no_mmu:	
+	li	r3,0
+        mtspr   IBAT0U,r3
+        mtspr   IBAT0L,r3
+        mtspr   IBAT1U,r3
+        mtspr   IBAT1L,r3
+        mtspr   IBAT2U,r3
+        mtspr   IBAT2L,r3
+        mtspr   IBAT3U,r3
+        mtspr   IBAT3L,r3
+
+        mtspr   DBAT0U,r3
+        mtspr   DBAT0L,r3
+        mtspr   DBAT1U,r3
+        mtspr   DBAT1L,r3
+        mtspr   DBAT2U,r3
+	mtspr   DBAT2L,r3
+        mtspr   DBAT3U,r3
+        mtspr   DBAT3L,r3
+#endif
+
+	/* the bootloader (as far as I'm currently aware) doesn't mess with page
+	   tables, but since we're already here, might as well zap these, too */
+	li	r4,0
+	mtspr	SDR1,r4
+
+	li	r4,16
+	mtctr	r4
+	li	r3,0
+	li	r4,0
+3:	mtsrin	r3,r4
+	addi	r3,r3,1
+	bdnz	3b
+
+#ifdef __SMP__
+	/* The 750 book (and Mot/IBM support) says that this will "assist" snooping
+	   when in SMP.  Not sure yet whether this should stay or leave... */
+	mfspr	r4,HID0
+	ori	r4,r4,HID0_ABE
+	mtspr	HID0,r4
+	sync
+#endif /* __SMP__ */
+	blr
+
+/*  apparently, SMon doesn't pay attention to HID0[SRST].  Disable the MMU and
+    branch to 0xfff00100 */
+_GLOBAL(_gemini_reboot)
+	lis	r5,GEMINI_BOOT_INIT@h
+	ori	r5,r5,GEMINI_BOOT_INIT@l
+	li	r6,MSR_IP
+	mtspr	SRR0,r5
+	mtspr	SRR1,r6
+	rfi
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/gemini_setup.c linux/arch/ppc/kernel/gemini_setup.c
--- v2.3.15/linux/arch/ppc/kernel/gemini_setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/gemini_setup.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,525 @@
+/*
+ *  linux/arch/ppc/kernel/setup.c
+ *
+ *  Copyright (C) 1995 Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ *  Synergy Microsystems board support by Dan Cox (dan@synergymicro.com)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h> 
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/stddef.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blk.h>
+#include <linux/console.h>
+#include <linux/openpic.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/m48t35.h>
+#include <asm/gemini.h>
+
+#include "time.h"
+#include "local_irq.h"
+#include "open_pic.h"
+
+void gemini_setup_pci_ptrs(void);
+
+static int l2_printed = 0;
+static unsigned char gemini_switch_map = 0;
+static char *gemini_board_families[] = {
+	"VGM", "VSS", "KGM", "VGR", "KSS"
+};
+
+static char *gemini_memtypes[] = {
+	"EDO DRAM, 60nS", "SDRAM, 15nS, CL=2", "SDRAM, 15nS, CL=2 with ECC"
+};
+
+static unsigned int cpu_7xx[16] = {
+	0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+static unsigned int cpu_6xx[16] = {
+	0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
+};
+
+
+static inline unsigned long _get_HID1(void)
+{
+	unsigned long val;
+
+	__asm__ __volatile__("mfspr %0,1009" : "=r" (val));
+	return val;
+}
+
+int
+gemini_get_cpuinfo(char *buffer)
+{
+	int i, len;
+	unsigned char reg, rev;
+	char *family;
+	unsigned int type;
+
+	reg = readb(GEMINI_FEAT);
+	family = gemini_board_families[((reg>>4) & 0xf)];
+	if (((reg>>4) & 0xf) > 2)
+		printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
+
+	reg = readb(GEMINI_BREV);
+	type = (reg>>4) & 0xf;
+	rev = reg & 0xf;
+
+	reg = readb(GEMINI_BECO);
+
+	len = sprintf( buffer, "machine\t\t: Gemini %s%d, rev %c, eco %d\n", 
+		       family, type, (rev + 'A'), (reg & 0xf));
+
+	len += sprintf( buffer+len, "vendor\t\t: %s\n", 
+			(_get_PVR() & (1<<15)) ? "IBM" : "Motorola");
+
+	reg = readb(GEMINI_MEMCFG);
+	len += sprintf( buffer+len, "memory type\t: %s\n", 
+			gemini_memtypes[(reg & 0xc0)>>6]);
+	len += sprintf( buffer+len, "switches on\t: ");
+	for( i=0; i < 8; i++ ) {
+		if ( gemini_switch_map & (1<<i))
+			len += sprintf(buffer+len, "%d ", i);
+	}
+	len += sprintf(buffer+len, "\n");
+
+	return len;
+}
+
+static u_char gemini_openpic_initsenses[] = {
+	1,
+	1,
+	1,
+	1,
+	0,
+	0,
+	1, /* remainder are level-triggered */
+};
+
+#define GEMINI_MPIC_ADDR (0xfcfc0000)
+#define GEMINI_MPIC_PCI_CFG (0x80005800)
+
+void __init gemini_openpic_init(void)
+{
+	grackle_write(GEMINI_MPIC_PCI_CFG + PCI_BASE_ADDRESS_0, 
+		      GEMINI_MPIC_ADDR);
+	grackle_write(GEMINI_MPIC_PCI_CFG + PCI_COMMAND, PCI_COMMAND_MEMORY);
+
+	OpenPIC = (volatile struct OpenPIC *) GEMINI_MPIC_ADDR;
+	OpenPIC_InitSenses = gemini_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
+
+	ioremap( GEMINI_MPIC_ADDR, sizeof( struct OpenPIC ));
+}
+
+
+extern unsigned long loops_per_sec;
+extern int root_mountflags;
+extern char cmd_line[];
+
+
+void __init gemini_setup_arch(unsigned long *memstart, unsigned long *memend)
+{
+	unsigned int cpu;
+	extern char cmd_line[];
+
+
+	loops_per_sec = 50000000;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* bootable off CDROM */
+	if (initrd_start)
+		ROOT_DEV = MKDEV(SCSI_CDROM_MAJOR, 0);
+	else
+#endif
+		ROOT_DEV = to_kdev_t(0x0801);
+
+	/* nothing but serial consoles... */  
+	sprintf(cmd_line, "%s console=ttyS0", cmd_line);
+
+
+	/* The user switches on the front panel can be used as follows:
+
+	   Switch 0 - adds "debug" to the command line for verbose boot info,
+	   Switch 7 - boots in single-user mode 
+
+	*/
+
+	gemini_switch_map = readb( GEMINI_USWITCH );
+  
+	if ( gemini_switch_map & (1<<GEMINI_SWITCH_VERBOSE))
+		sprintf(cmd_line, "%s debug", cmd_line);
+
+	if ( gemini_switch_map & (1<<GEMINI_SWITCH_SINGLE_USER))
+		sprintf(cmd_line, "%s single", cmd_line);
+
+	printk("Boot arguments: %s\n", cmd_line);
+
+	/* mutter some kind words about who made the CPU */
+	cpu = _get_PVR();
+	printk("CPU manufacturer: %s [rev=%04x]\n", (cpu & (1<<15)) ? "IBM" :
+	       "Motorola", (cpu & 0xffff));
+
+	/* take special pains to map the MPIC, since it isn't mapped yet */
+	gemini_openpic_init();
+
+	/* start the L2 */
+	gemini_init_l2();
+
+}
+
+
+int
+gemini_get_clock_speed(void)
+{
+	unsigned long hid1;
+	int clock;
+	unsigned char reg;
+  
+	hid1 = _get_HID1();
+	if ((_get_PVR()>>16) == 8)
+		hid1 = cpu_7xx[hid1];
+	else
+		hid1 = cpu_6xx[hid1];
+
+	reg = readb(GEMINI_BSTAT) & 0xc0;
+
+	switch( reg >> 2 ) {
+
+	case 0:
+	default:
+		clock = (hid1*100)/3;
+		break;
+  
+	case 1:
+		clock = (hid1*125)/3;
+		break;
+  
+	case 2:
+		clock = (hid1*50)/3;
+		break;
+	}
+
+	return clock;
+}
+
+
+#define L2CR_PIPE_LATEWR   (0x01800000)   /* late-write SRAM */
+#define L2CR_L2CTL         (0x00100000)   /* RAM control */
+#define L2CR_INST_DISABLE  (0x00400000)   /* disable for insn's */
+#define L2CR_L2I           (0x00200000)   /* global invalidate */
+#define L2CR_L2E           (0x80000000)   /* enable */
+#define L2CR_L2WT          (0x00080000)   /* write-through */
+
+void __init gemini_init_l2(void)
+{
+	unsigned char reg;
+	unsigned long cache;
+	int speed;
+
+	reg = readb(GEMINI_L2CFG);
+
+	/* 750's L2 initializes differently from a 604's.  Also note that a Grackle
+	   bug will hang a dual-604 board, so make sure that doesn't happen by not
+	   turning on the L2 */
+	if ( _get_PVR() >> 16 != 8 ) {
+     
+		/* check for dual cpus and cry sadly about the loss of an L2... */
+		if ((( readb(GEMINI_CPUSTAT) & 0x0c ) >> 2) != 1) 
+			printk("Sorry. Your dual-604 does not allow the L2 to be enabled due "
+			       "to a Grackle bug.\n");
+		else if ( reg & GEMINI_L2_SIZE_MASK ) {
+			printk("Enabling 604 L2 cache: %dKb\n", 
+			       (128<<((reg & GEMINI_L2_SIZE_MASK)>>6)));
+			writeb( 1, GEMINI_L2CFG );
+		}
+	}
+
+	/* do a 750 */
+	else {
+		/* Synergy's first round of 750 boards had the L2 size stuff into the
+		   board register above.  If it's there, it's used; if not, the
+		   standard default is 1Mb.  The L2 type, I'm told, is "most likely
+		   probably always going to be late-write".  --Dan */
+
+		if (reg & 0xc0) {
+			if (!l2_printed) {
+				printk("Enabling 750 L2 cache: %dKb\n", 
+				       (128 << ((reg & 0xc0)>>6)));
+				l2_printed=1;
+			}
+    
+			/* take the size given */
+			cache = (((reg>>6) & 0x3)<<28);
+		}
+		else
+			/* default of 1Mb */
+			cache = 0x3<<28;
+ 
+		reg &= 0x3;
+
+		/* a cache ratio of 1:1 and CPU clock speeds in excess of 300Mhz are bad
+		   things.  If found, tune it down to 1:1.5.  -- Dan */
+		if (!reg) {
+
+			speed = gemini_get_clock_speed();
+   
+			if (speed >= 300) {
+				printk("Warning:  L2 ratio is 1:1 on a %dMhz processor.  Dropping to 1:1.5.\n",
+				       speed );
+				printk("Contact Synergy Microsystems for an ECO to fix this problem\n");
+				reg = 0x1;
+			}
+		}
+
+		/* standard stuff */
+		cache |= ((1<<reg)<<25);
+#ifdef __SMP__
+		/* A couple errata for the 750's (both IBM and Motorola silicon)
+		   note that you can get missed cache lines on MP implementations.
+		   The workaround - if you call it that - is to make the L2
+		   write-through.  This is fixed in IBM's 3.1 rev (I'm told), but
+		   for now, always make 2.x versions use L2 write-through. --Dan */
+		if (((_get_PVR()>>8) & 0xf) <= 2)
+			cache |= L2CR_L2WT;
+#endif
+		cache |= L2CR_PIPE_LATEWR|L2CR_L2CTL|L2CR_INST_DISABLE;
+		_set_L2CR(0);
+		_set_L2CR(cache|L2CR_L2I|L2CR_L2E);
+	}
+}
+
+void
+gemini_restart(char *cmd)
+{
+	__cli();
+	/* make a clean restart, not via the MPIC */
+	_gemini_reboot();
+	for(;;);
+}
+
+void
+gemini_power_off(void)
+{
+	for(;;);
+}
+
+void
+gemini_halt(void)
+{
+	gemini_restart(NULL);
+}
+
+void __init gemini_init_IRQ(void)
+{
+	int i;
+
+	/* gemini has no 8259 */
+	open_pic.irq_offset = 0;
+	for( i=0; i < 16; i++ ) 
+		irq_desc[i].ctl = &open_pic;
+	openpic_init(1);
+}
+
+#define gemini_rtc_read(x)       (readb(GEMINI_RTC+(x)))
+#define gemini_rtc_write(val,x)  (writeb((val),(GEMINI_RTC+(x))))
+
+/* ensure that the RTC is up and running */
+void __init gemini_time_init(void)
+{
+	unsigned char reg;
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+
+	if ( reg & M48T35_RTC_STOPPED ) {
+		printk(KERN_INFO "M48T35 real-time-clock was stopped. Now starting...\n");
+		gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL);
+		gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL);
+	}
+}
+
+#undef DEBUG_RTC
+
+unsigned long
+gemini_get_rtc_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	unsigned char reg;
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+	gemini_rtc_write((reg|M48T35_RTC_READ), M48T35_RTC_CONTROL);
+#ifdef DEBUG_RTC
+	printk("get rtc: reg = %x\n", reg);
+#endif
+  
+	do {
+		sec = gemini_rtc_read(M48T35_RTC_SECONDS);
+		min = gemini_rtc_read(M48T35_RTC_MINUTES);
+		hour = gemini_rtc_read(M48T35_RTC_HOURS);
+		day = gemini_rtc_read(M48T35_RTC_DOM);
+		mon = gemini_rtc_read(M48T35_RTC_MONTH);
+		year = gemini_rtc_read(M48T35_RTC_YEAR);
+	} while( sec != gemini_rtc_read(M48T35_RTC_SECONDS));
+#ifdef DEBUG_RTC
+	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
+	       sec, min, hour, day, mon, year);
+#endif
+
+	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+	BCD_TO_BIN(sec);
+	BCD_TO_BIN(min);
+	BCD_TO_BIN(hour);
+	BCD_TO_BIN(day);
+	BCD_TO_BIN(mon);
+	BCD_TO_BIN(year);
+
+	if ((year += 1900) < 1970)
+		year += 100;
+#ifdef DEBUG_RTC
+	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
+	       sec, min, hour, day, mon, year);
+#endif
+
+	return mktime( year, mon, day, hour, min, sec );
+}
+
+
+int
+gemini_set_rtc_time( unsigned long now )
+{
+	unsigned char reg;
+	struct rtc_time tm;
+
+	to_tm( now, &tm );
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+#if DEBUG_RTC
+	printk("set rtc: reg = %x\n", reg);
+#endif
+  
+	gemini_rtc_write((reg|M48T35_RTC_SET), M48T35_RTC_CONTROL);
+#if DEBUG_RTC
+	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+  
+	tm.tm_year -= 1900;
+	BIN_TO_BCD(tm.tm_sec);
+	BIN_TO_BCD(tm.tm_min);
+	BIN_TO_BCD(tm.tm_hour);
+	BIN_TO_BCD(tm.tm_mon);
+	BIN_TO_BCD(tm.tm_mday);
+	BIN_TO_BCD(tm.tm_year);
+#ifdef DEBUG_RTC
+	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+
+	gemini_rtc_write(tm.tm_sec, M48T35_RTC_SECONDS);
+	gemini_rtc_write(tm.tm_min, M48T35_RTC_MINUTES);
+	gemini_rtc_write(tm.tm_hour, M48T35_RTC_HOURS);
+	gemini_rtc_write(tm.tm_mday, M48T35_RTC_DOM);
+	gemini_rtc_write(tm.tm_mon, M48T35_RTC_MONTH);
+	gemini_rtc_write(tm.tm_year, M48T35_RTC_YEAR);
+
+	/* done writing */
+	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+	if ((time_state == TIME_ERROR) || (time_state == TIME_BAD))
+		time_state = TIME_OK;
+  
+	return 0;
+}
+
+/*  use the RTC to determine the decrementer count */
+void __init gemini_calibrate_decr(void)
+{
+	int freq, divisor;
+	unsigned char reg;
+
+	/* determine processor bus speed */
+	reg = readb(GEMINI_BSTAT);
+
+	switch(((reg & 0x0c)>>2)&0x3) {
+	case 0:
+	default:
+		freq = 66;
+		break;
+	case 1:
+		freq = 83;
+		break;
+	case 2:
+		freq = 100;
+		break;
+	}
+
+	freq *= 1000000;
+	divisor = 4;
+	decrementer_count = freq / HZ / divisor;
+	count_period_num = divisor;
+	count_period_den = freq / 1000000;
+}
+
+
+void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5,
+			unsigned long r6, unsigned long r7)
+{
+	void chrp_do_IRQ(struct pt_regs *, int, int);
+	gemini_setup_pci_ptrs();
+
+	ISA_DMA_THRESHOLD = 0;
+	DMA_MODE_READ = 0;
+	DMA_MODE_WRITE = 0;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if ( r4 )
+	{
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif
+
+	ppc_md.setup_arch = gemini_setup_arch;
+	ppc_md.setup_residual = NULL;
+	ppc_md.get_cpuinfo = gemini_get_cpuinfo;
+	ppc_md.irq_cannonicalize = NULL;
+	ppc_md.init_IRQ = gemini_init_IRQ;
+	ppc_md.do_IRQ = chrp_do_IRQ;
+	ppc_md.init = NULL;
+
+	ppc_md.restart = gemini_restart;
+	ppc_md.power_off = gemini_power_off;
+	ppc_md.halt = gemini_halt;
+
+	ppc_md.time_init = gemini_time_init;
+	ppc_md.set_rtc_time = gemini_set_rtc_time;
+	ppc_md.get_rtc_time = gemini_get_rtc_time;
+	ppc_md.calibrate_decr = gemini_calibrate_decr;
+
+	/* no keyboard/mouse/video stuff yet.. */
+	ppc_md.kbd_setkeycode = NULL;
+	ppc_md.kbd_getkeycode = NULL;
+	ppc_md.kbd_translate = NULL;
+	ppc_md.kbd_unexpected_up = NULL;
+	ppc_md.kbd_leds = NULL;
+	ppc_md.kbd_init_hw = NULL;
+#ifdef CONFIG_MAGIC_SYSRQ
+	ppc_md.ppc_kbd_sysrq_xlate = NULL;
+#endif
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/hashtable.S linux/arch/ppc/kernel/hashtable.S
--- v2.3.15/linux/arch/ppc/kernel/hashtable.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/hashtable.S	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,476 @@
+/*
+ *  arch/ppc/kernel/hashtable.S
+ *
+ *  $Id: hashtable.S,v 1.2 1999/08/23 02:53:17 paulus Exp $
+ *
+ *  PowerPC version 
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
+ *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
+ *  Adapted for Power Macintosh by Paul Mackerras.
+ *  Low-level exception handlers and MMU support
+ *  rewritten by Paul Mackerras.
+ *    Copyright (C) 1996 Paul Mackerras.
+ *
+ *  This file contains low-level assembler routines for managing
+ *  the PowerPC MMU hash table.  (PPC 8xx processors don't use a
+ *  hash table, so this file is not used on them.)
+ *
+ *  This program is free software; you can redistribute 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 "ppc_asm.h"
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <linux/config.h>
+
+/*
+ * Load a PTE into the hash table, if possible.
+ * The address is in r3, and r4 contains access flags:
+ * _PAGE_USER (4) if a user-mode access, ored with
+ * _PAGE_RW (2) if a write.  r20 contains DSISR or SRR1,
+ * so bit 1 (0x40000000) is set if the exception was due
+ * to no matching PTE being found in the hash table.
+ * r5 contains the physical address of the current task's thread.
+ *
+ * Returns to the caller if the access is illegal or there is no
+ * mapping for the address.  Otherwise it places an appropriate PTE
+ * in the hash table and returns from the exception.
+ * Uses r0, r2 - r6, ctr, lr.
+ *
+ * For speed, 4 of the instructions get patched once the size and
+ * physical address of the hash table are known.  These definitions
+ * of Hash_base and Hash_bits below are just an example.
+ */
+Hash_base = 0x180000
+Hash_bits = 12				/* e.g. 256kB hash table */
+Hash_msk = (((1 << Hash_bits) - 1) * 64)
+	
+	.globl	hash_page
+hash_page:
+#ifdef __SMP__
+	eieio
+	lis	r2,hash_table_lock@h
+	ori	r2,r2,hash_table_lock@l
+ 	tophys(r2,r2)
+	lis	r6,100000000@h
+	mtctr	r6
+	lwz	r0,PROCESSOR-THREAD(r5)
+	or	r0,r0,r6
+10:	lwarx	r6,0,r2
+	cmpi	0,r6,0
+	bne-	12f
+	stwcx.	r0,0,r2
+	beq+	11f
+12:	cmpw	r6,r0
+	bdnzf	2,10b
+	tw	31,31,31
+11:	eieio
+#endif
+	/* Get PTE (linux-style) and check access */
+	mfspr	r2,SPRG3		/* current task's THREAD (phys) */
+	lwz	r5,PGDIR(r2)		/* virt page-table root */
+	tophys(r5,r5)			/* convert to phys addr */
+	rlwimi	r5,r3,12,20,29		/* insert top 10 bits of address */
+	lwz	r5,0(r5)		/* get pmd entry */
+	rlwinm.	r5,r5,0,0,19		/* extract address of pte page */
+#ifdef __SMP__
+	beq-	hash_page_out		/* return if no mapping */
+#else
+	/* XXX it seems like the 601 will give a machine fault on the
+	   rfi if its alignment is wrong (bottom 4 bits of address are
+	   8 or 0xc) and we have had a not-taken conditional branch
+	   to the address following the rfi. */
+	beqlr-
+#endif
+	tophys(r2,r5)
+	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
+	lwz	r6,0(r2)		/* get linux-style pte */
+	ori	r4,r4,1			/* set _PAGE_PRESENT bit in access */
+	andc.	r0,r4,r6		/* check access & ~permission */
+#ifdef __SMP__
+	bne-	hash_page_out		/* return if access not permitted */
+#else
+	bnelr-
+#endif
+
+	ori	r6,r6,0x100		/* set _PAGE_ACCESSED in pte */
+	rlwinm	r5,r4,5,24,24		/* _PAGE_RW access -> _PAGE_DIRTY */
+	rlwimi	r5,r4,7,22,22		/* _PAGE_RW -> _PAGE_HWWRITE */
+	or	r6,r6,r5
+	stw	r6,0(r2)		/* update PTE (accessed/dirty bits) */
+
+	/* Convert linux-style PTE to low word of PPC-style PTE */
+#ifdef CONFIG_PPC64
+	/* clear the high 32 bits just in case */
+	clrldi	r6,r6,32
+	clrldi	r4,r4,32
+#endif /* CONFIG_PPC64 */
+	rlwinm	r4,r6,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
+	rlwimi	r6,r6,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
+	ori	r4,r4,0xe04		/* clear out reserved bits */
+	andc	r6,r6,r4		/* PP=2 or 0, when _PAGE_HWWRITE */
+
+	/* Construct the high word of the PPC-style PTE */
+	mfsrin	r5,r3			/* get segment reg for segment */
+#ifdef CONFIG_PPC64
+	sldi	r5,r5,12
+#else /* CONFIG_PPC64 */
+	rlwinm	r5,r5,7,1,24		/* put VSID in 0x7fffff80 bits */
+#endif /* CONFIG_PPC64 */
+	
+#ifndef __SMP__				/* do this later for SMP */
+#ifdef CONFIG_PPC64
+	ori	r5,r5,1			/* set V (valid) bit */
+#else /* CONFIG_PPC64 */
+	oris	r5,r5,0x8000		/* set V (valid) bit */
+#endif /* CONFIG_PPC64 */
+#endif
+	
+#ifdef CONFIG_PPC64
+/* XXX:	 does this insert the api correctly? -- Cort */
+	rlwimi	r5,r3,17,21,25		/* put in API (abbrev page index) */
+#else /* CONFIG_PPC64 */
+	rlwimi	r5,r3,10,26,31		/* put in API (abbrev page index) */
+#endif /* CONFIG_PPC64 */
+	/* Get the address of the primary PTE group in the hash table */
+	.globl	hash_page_patch_A
+hash_page_patch_A:
+	lis	r4,Hash_base@h		/* base address of hash table */
+#ifdef CONFIG_PPC64
+	/* just in case */
+	clrldi	r4,r4,32
+#endif	
+	rlwimi	r4,r5,32-1,26-Hash_bits,25	/* (VSID & hash_mask) << 6 */
+	rlwinm	r0,r3,32-6,26-Hash_bits,25	/* (PI & hash_mask) << 6 */
+	xor	r4,r4,r0		/* make primary hash */
+
+	/* See whether it was a PTE not found exception or a
+	   protection violation. */
+	andis.	r0,r20,0x4000
+	li	r2,8			/* PTEs/group */
+	bne	10f			/* no PTE: go look for an empty slot */
+	tlbie	r3			/* invalidate TLB entry */
+
+	/* Search the primary PTEG for a PTE whose 1st word matches r5 */
+	mtctr	r2
+	addi	r3,r4,-8
+1:	lwzu	r0,8(r3)		/* get next PTE */
+	cmp	0,r0,r5
+	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
+	beq+	found_slot
+
+	/* Search the secondary PTEG for a matching PTE */
+	ori	r5,r5,0x40		/* set H (secondary hash) bit */
+	.globl	hash_page_patch_B
+hash_page_patch_B:
+	xoris	r3,r4,Hash_msk>>16	/* compute secondary hash */
+	xori	r3,r3,0xffc0
+	addi	r3,r3,-8
+	mtctr	r2
+2:	lwzu	r0,8(r3)
+	cmp	0,r0,r5
+	bdnzf	2,2b
+	beq+	found_slot
+	xori	r5,r5,0x40		/* clear H bit again */
+
+	/* Search the primary PTEG for an empty slot */
+10:	mtctr	r2
+	addi	r3,r4,-8		/* search primary PTEG */
+1:	lwzu	r0,8(r3)		/* get next PTE */
+	srwi.	r0,r0,31		/* only want to check valid bit */
+	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
+	beq+	found_empty
+
+	/* Search the secondary PTEG for an empty slot */
+	ori	r5,r5,0x40		/* set H (secondary hash) bit */
+	.globl	hash_page_patch_C
+hash_page_patch_C:
+	xoris	r3,r4,Hash_msk>>16	/* compute secondary hash */
+	xori	r3,r3,0xffc0
+	addi	r3,r3,-8
+	mtctr	r2
+2:	lwzu	r0,8(r3)
+	srwi.	r0,r0,31		/* only want to check valid bit */
+	bdnzf	2,2b
+	beq+	found_empty
+
+	/*
+	 * Choose an arbitrary slot in the primary PTEG to overwrite.
+	 * Since both the primary and secondary PTEGs are full, and we
+	 * have no information that the PTEs in the primary PTEG are
+	 * more important or useful than those in the secondary PTEG,
+	 * and we know there is a definite (although small) speed
+	 * advantage to putting the PTE in the primary PTEG, we always
+	 * put the PTE in the primary PTEG.
+	 */
+	xori	r5,r5,0x40		/* clear H bit again */
+	lwz	r2,next_slot@l(0)
+	addi	r2,r2,8
+	andi.	r2,r2,0x38
+	stw	r2,next_slot@l(0)
+	add	r3,r4,r2
+11:		
+	/* update counter of evicted pages */
+	lis	r2,htab_evicts@h
+	ori	r2,r2,htab_evicts@l
+	tophys(r2,r2)
+	lwz	r4,0(r2)
+	addi	r4,r4,1
+	stw	r4,0(r2)
+
+#ifndef __SMP__
+	/* Store PTE in PTEG */
+found_empty:
+	stw	r5,0(r3)
+found_slot:
+	stw	r6,4(r3)
+	sync
+
+#else /* __SMP__ */
+/*
+ * Between the tlbie above and updating the hash table entry below,
+ * another CPU could read the hash table entry and put it in its TLB.
+ * There are 3 cases:
+ * 1. using an empty slot
+ * 2. updating an earlier entry to change permissions (i.e. enable write)
+ * 3. taking over the PTE for an unrelated address
+ *
+ * In each case it doesn't really matter if the other CPUs have the old
+ * PTE in their TLB.  So we don't need to bother with another tlbie here,
+ * which is convenient as we've overwritten the register that had the
+ * address. :-)  The tlbie above is mainly to make sure that this CPU comes
+ * and gets the new PTE from the hash table.
+ *
+ * We do however have to make sure that the PTE is never in an invalid
+ * state with the V bit set.
+ */
+found_empty:
+found_slot:
+	stw	r5,0(r3)	/* clear V (valid) bit in PTE */
+	sync
+	tlbsync
+	sync
+	stw	r6,4(r3)	/* put in correct RPN, WIMG, PP bits */
+	sync
+	oris	r5,r5,0x8000
+	stw	r5,0(r3)	/* finally set V bit in PTE */
+#endif /* __SMP__ */
+
+/*
+ * Update the hash table miss count.  We only want misses here
+ * that _are_ valid addresses and have a pte otherwise we don't
+ * count it as a reload.  do_page_fault() takes care of bad addrs
+ * and entries that need linux-style pte's created.
+ *
+ * safe to use r2 here since we're not using it as current yet 
+ * update the htab misses count
+ *   -- Cort
+ */
+	lis	r2,htab_reloads@h
+	ori	r2,r2,htab_reloads@l
+	tophys(r2,r2)
+	lwz	r3,0(r2)
+	addi	r3,r3,1
+	stw	r3,0(r2)
+
+#ifdef __SMP__
+	lis	r2,hash_table_lock@ha
+	tophys(r2,r2)
+	li	r0,0
+	stw	r0,hash_table_lock@l(r2)
+	eieio
+#endif
+
+	/* Return from the exception */
+	lwz	r3,_CCR(r21)
+	lwz	r4,_LINK(r21)
+	lwz	r5,_CTR(r21)
+	mtcrf	0xff,r3
+	mtlr	r4
+	mtctr	r5
+	lwz	r0,GPR0(r21)
+	lwz	r1,GPR1(r21)
+	lwz	r2,GPR2(r21)
+	lwz	r3,GPR3(r21)
+	lwz	r4,GPR4(r21)
+	lwz	r5,GPR5(r21)
+	lwz	r6,GPR6(r21)
+	/* we haven't used xer */
+	mtspr	SRR1,r23
+	mtspr	SRR0,r22
+	lwz	r20,GPR20(r21)
+	lwz	r22,GPR22(r21)
+	lwz	r23,GPR23(r21)
+	lwz	r21,GPR21(r21)
+	rfi
+	
+#ifdef __SMP__
+hash_page_out:
+	lis	r2,hash_table_lock@ha
+	tophys(r2,r2)
+	li	r0,0
+	stw	r0,hash_table_lock@l(r2)
+	eieio
+	blr
+
+	.globl	hash_table_lock
+hash_table_lock:
+	.long	0
+#endif
+
+next_slot:
+	.long	0
+
+/*
+ * Flush entries from the hash table with VSIDs in the range
+ * given.
+ */
+_GLOBAL(flush_hash_segments)
+	lis	r5,Hash@ha
+	lwz	r5,Hash@l(r5)		/* base of hash table */
+	cmpwi	0,r5,0
+	bne+	99f
+	tlbia
+	sync
+#ifdef __SMP__
+	tlbsync
+	sync
+#endif
+	blr
+99:
+#ifdef __SMP__
+	/* Note - we had better not do anything which could generate
+	   a hash table miss while we have the hash table locked,
+	   or we'll get a deadlock.  -paulus */
+	mfmsr	r10
+	sync
+	rlwinm	r0,r10,0,17,15	/* clear bit 16 (MSR_EE) */
+	mtmsr	r0
+	SYNC
+	lis	r9,hash_table_lock@h
+	ori	r9,r9,hash_table_lock@l
+	lwz	r8,PROCESSOR(r2)
+	oris	r8,r8,8
+10:	lwarx	r6,0,r9
+	cmpi	0,r6,0
+	bne-	10b
+	stwcx.	r8,0,r9
+	bne-	10b
+	eieio
+#endif
+	rlwinm	r3,r3,7,1,24		/* put VSID lower limit in position */
+	oris	r3,r3,0x8000		/* set V bit */
+	rlwinm	r4,r4,7,1,24		/* put VSID upper limit in position */
+	oris	r4,r4,0x8000
+	ori	r4,r4,0x7f
+	lis	r6,Hash_size@ha
+	lwz	r6,Hash_size@l(r6)	/* size in bytes */
+	srwi	r6,r6,3			/* # PTEs */
+	mtctr	r6
+	addi	r5,r5,-8
+	li	r0,0
+1:	lwzu	r6,8(r5)		/* get next tag word */
+	cmplw	0,r6,r3
+	cmplw	1,r6,r4
+	cror	0,0,5			/* set cr0.lt if out of range */
+	blt	2f			/* branch if out of range */
+	stw	r0,0(r5)		/* invalidate entry */
+2:	bdnz	1b			/* continue with loop */
+	sync
+	tlbia
+	sync
+#ifdef __SMP__
+	tlbsync
+	sync
+	lis	r3,hash_table_lock@ha
+	stw	r0,hash_table_lock@l(r3)
+	mtmsr	r10
+	SYNC
+#endif
+	blr
+
+/*
+ * Flush the entry for a particular page from the hash table.
+ *
+ * flush_hash_page(unsigned context, unsigned long va)
+ */
+_GLOBAL(flush_hash_page)
+	lis	r6,Hash@ha
+	lwz	r6,Hash@l(r6)		/* hash table base */
+	cmpwi	0,r6,0			/* hash table in use? */
+	bne+	99f
+	tlbie	r4			/* in hw tlb too */
+	sync
+#ifdef __SMP__
+	tlbsync
+	sync
+#endif
+	blr
+99:
+#ifdef __SMP__
+	/* Note - we had better not do anything which could generate
+	   a hash table miss while we have the hash table locked,
+	   or we'll get a deadlock.  -paulus */
+	mfmsr	r10
+	sync
+	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */
+	mtmsr	r0
+	SYNC
+	lis	r9,hash_table_lock@h
+	ori	r9,r9,hash_table_lock@l
+	lwz	r8,PROCESSOR(r2)
+	oris	r8,r8,9
+10:	lwarx	r7,0,r9
+	cmpi	0,r7,0
+	bne-	10b
+	stwcx.	r8,0,r9
+	bne-	10b
+	eieio
+#endif
+	rlwinm	r3,r3,11,1,20		/* put context into vsid */
+	rlwimi	r3,r4,11,21,24		/* put top 4 bits of va into vsid */
+	oris	r3,r3,0x8000		/* set V (valid) bit */
+	rlwimi	r3,r4,10,26,31		/* put in API (abbrev page index) */
+	rlwinm	r7,r4,32-6,10,25	/* get page index << 6 */
+	rlwinm	r5,r3,32-1,7,25		/* vsid << 6 */
+	xor	r7,r7,r5		/* primary hash << 6 */
+	lis	r5,Hash_mask@ha
+	lwz	r5,Hash_mask@l(r5)	/* hash mask */
+	slwi	r5,r5,6			/*  << 6 */
+	and	r7,r7,r5
+	add	r6,r6,r7		/* address of primary PTEG */
+	li	r8,8
+	mtctr	r8
+	addi	r7,r6,-8
+1:	lwzu	r0,8(r7)		/* get next PTE */
+	cmpw	0,r0,r3			/* see if tag matches */
+	bdnzf	2,1b			/* while --ctr != 0 && !cr0.eq */
+	beq	3f			/* if we found it */
+	ori	r3,r3,0x40		/* set H (alt. hash) bit */
+	xor	r6,r6,r5		/* address of secondary PTEG */
+	mtctr	r8
+	addi	r7,r6,-8
+2:	lwzu	r0,8(r7)		/* get next PTE */
+	cmpw	0,r0,r3			/* see if tag matches */
+	bdnzf	2,2b			/* while --ctr != 0 && !cr0.eq */
+	bne	4f			/* if we didn't find it */
+3:	li	r0,0
+	stw	r0,0(r7)		/* invalidate entry */
+4:	sync
+	tlbie	r4			/* in hw tlb too */
+	sync
+#ifdef __SMP__
+	tlbsync
+	sync
+	lis	r3,hash_table_lock@h
+	li	r0,0
+	stw	r0,hash_table_lock@l(r3)
+	mtmsr	r10
+	SYNC
+#endif
+	blr
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.3.15/linux/arch/ppc/kernel/head.S	Mon Jul 12 15:12:55 1999
+++ linux/arch/ppc/kernel/head.S	Tue Aug 31 11:36:43 1999
@@ -1,12 +1,13 @@
 /*
  *  arch/ppc/kernel/head.S
  *
- *  $Id: head.S,v 1.134 1999/06/30 05:05:52 paulus Exp $
+ *  $Id: head.S,v 1.142 1999/08/23 02:53:18 paulus Exp $
  *
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  *
  *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
+ *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
  *  Adapted for Power Macintosh by Paul Mackerras.
  *  Low-level exception handlers and MMU support
  *  rewritten by Paul Mackerras.
@@ -16,7 +17,7 @@
  *
  *  This file contains the low-level support and setup for the
  *  PowerPC platform, including trap and interrupt dispatch.
- *  Also included here is low-level thread/task switch support.
+ *  (The PPC 8xx embedded CPUs use head_8xx.S instead.)
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
@@ -25,118 +26,42 @@
  *	
  */
 
-#include "ppc_asm.tmpl"
-#include "ppc_defs.h"
+#include "ppc_asm.h"
 #include <asm/processor.h>
 #include <asm/page.h>
-#include <asm/ptrace.h>
-#include <linux/sys.h>
-#include <linux/errno.h>
 #include <linux/config.h>
 #include <asm/mmu.h>
-#include <asm/pgtable.h>
-#include <asm/cache.h>
 
 #ifdef CONFIG_APUS
 #include <asm/amigappc.h>
 #endif
 
-/* optimization for 603 to load the tlb directly from the linux table */
-#define NO_RELOAD_HTAB 1
-	
-#ifndef CONFIG_8xx
-CACHE_LINE_SIZE = 32
-LG_CACHE_LINE_SIZE = 5
-#else
-CACHE_LINE_SIZE = 16
-LG_CACHE_LINE_SIZE = 4
-#endif
-
-#define TOPHYS(x)	(x - KERNELBASE)
-
-/*
- * Macros for storing registers into and loading registers from
- * exception frames.
- */
-#define SAVE_GPR(n, base)	stw	n,GPR0+4*(n)(base)
-#define SAVE_2GPRS(n, base)	SAVE_GPR(n, base); SAVE_GPR(n+1, base)
-#define SAVE_4GPRS(n, base)	SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
-#define SAVE_8GPRS(n, base)	SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
-#define SAVE_10GPRS(n, base)	SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
-#define REST_GPR(n, base)	lwz	n,GPR0+4*(n)(base)
-#define REST_2GPRS(n, base)	REST_GPR(n, base); REST_GPR(n+1, base)
-#define REST_4GPRS(n, base)	REST_2GPRS(n, base); REST_2GPRS(n+2, base)
-#define REST_8GPRS(n, base)	REST_4GPRS(n, base); REST_4GPRS(n+4, base)
-#define REST_10GPRS(n, base)	REST_8GPRS(n, base); REST_2GPRS(n+8, base)
-
-#define SAVE_FPR(n, base)	stfd	n,TSS_FPR0+8*(n)(base)
-#define SAVE_2FPRS(n, base)	SAVE_FPR(n, base); SAVE_FPR(n+1, base)
-#define SAVE_4FPRS(n, base)	SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
-#define SAVE_8FPRS(n, base)	SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
-#define SAVE_16FPRS(n, base)	SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
-#define SAVE_32FPRS(n, base)	SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
-#define REST_FPR(n, base)	lfd	n,TSS_FPR0+8*(n)(base)
-#define REST_2FPRS(n, base)	REST_FPR(n, base); REST_FPR(n+1, base)
-#define REST_4FPRS(n, base)	REST_2FPRS(n, base); REST_2FPRS(n+2, base)
-#define REST_8FPRS(n, base)	REST_4FPRS(n, base); REST_4FPRS(n+4, base)
-#define REST_16FPRS(n, base)	REST_8FPRS(n, base); REST_8FPRS(n+8, base)
-#define REST_32FPRS(n, base)	REST_16FPRS(n, base); REST_16FPRS(n+16, base)
-
-#define SYNC \
-	sync; \
-	isync
-
-#ifndef CONFIG_8xx
-/* This instruction is not implemented on the PPC 603 or 601 */
-#define tlbia \
-	li	r4,128; \
-	mtctr	r4; \
-	lis	r4,KERNELBASE@h; \
-0:	tlbie	r4; \
-	addi	r4,r4,0x1000; \
-	bdnz	0b
-#endif
-
 #ifdef CONFIG_PPC64
-#define LOAD_BAT(n, offset, reg, RA, RB) \
-	ld	RA,offset+0(reg);	\
-	ld	RB,offset+8(reg);	\
+#define LOAD_BAT(n, reg, RA, RB)	\
+	ld	RA,(n*32)+0(reg);	\
+	ld	RB,(n*32)+8(reg);	\
 	mtspr	IBAT##n##U,RA;		\
 	mtspr	IBAT##n##L,RB;		\
-	ld	RA,offset+16(reg);	\
-	ld	RB,offset+24(reg);	\
+	ld	RA,(n*32)+16(reg);	\
+	ld	RB,(n*32)+24(reg);	\
 	mtspr	DBAT##n##U,RA;		\
 	mtspr	DBAT##n##L,RB;		\
 	
 #else /* CONFIG_PPC64 */
 	
-/* 601 only have IBAT cr0.eq is set on 601 when using this macro */ 
-#define LOAD_BAT(n, offset, reg, RA, RB) \
-	lwz	RA,offset+0(reg);	\
-	lwz	RB,offset+4(reg);	\
+/* 601 only have IBAT; cr0.eq is set on 601 when using this macro */
+#define LOAD_BAT(n, reg, RA, RB)	\
+	lwz	RA,(n*16)+0(reg);	\
+	lwz	RB,(n*16)+4(reg);	\
 	mtspr	IBAT##n##U,RA;		\
 	mtspr	IBAT##n##L,RB;		\
 	beq	1f;			\
-	lwz	RA,offset+8(reg);	\
-	lwz	RB,offset+12(reg);	\
+	lwz	RA,(n*16)+8(reg);	\
+	lwz	RB,(n*16)+12(reg);	\
 	mtspr	DBAT##n##U,RA;		\
 	mtspr	DBAT##n##L,RB;		\
 1:	
 #endif /* CONFIG_PPC64 */	 
-
-#ifndef CONFIG_APUS
-#define tophys(rd,rs,rt)	addis	rd,rs,-KERNELBASE@h
-#define tovirt(rd,rs,rt)	addis	rd,rs,KERNELBASE@h
-#else
-#define tophys(rd,rs,rt)	 \
-	lis	rt,CYBERBASEp@h; \
-	lwz	rt,0(rt);	 \
-	add	rd,rs,rt
-#define tovirt(rd,rs,rt)	 \
-	lis	rt,CYBERBASEp@h; \
-	lwz	rt,0(rt);	 \
-	sub	rd,rs,rt
-#endif
 	
 	.text
 	.globl	_stext
@@ -149,7 +74,15 @@
 	.text
 	.globl	_start
 _start:
-	.long	TOPHYS(__start),0,0
+	/* 
+	 * These are here for legacy reasons, the kernel used to
+	 * need to look like a coff function entry for the pmac
+	 * but we're always started by some kind of bootloader now.
+	 *  -- Cort
+	 */
+	nop
+	nop
+	nop
 
 /* PMAC
  * Enter here with the kernel text, data and bss loaded starting at
@@ -168,6 +101,7 @@
  *
  * APUS
  *   r3: 'APUS'
+ *   r4: physical address of memory base
  *   Linux/m68k style BootInfo structure at &_end.
  *
  * PREP
@@ -183,39 +117,6 @@
  * This just gets a minimal mmu environment setup so we can call
  * start_here() to do the real work.
  * -- Cort
- *
- * MPC8xx
- * This port was done on an MBX board with an 860.  Right now I only
- * support an ELF compressed (zImage) boot from EPPC-Bug because the
- * code there loads up some registers before calling us:
- *   r3: ptr to board info data
- *   r4: initrd_start or if no initrd then 0
- *   r5: initrd_end - unused if r4 is 0
- *   r6: Start of command line string
- *   r7: End of command line string
- *
- * I decided to use conditional compilation instead of checking PVR and
- * adding more processor specific branches around code I don't need.
- * Since this is an embedded processor, I also appreciate any memory
- * savings I can get.
- *
- * The MPC8xx does not have any BATs, but it supports large page sizes.
- * We first initialize the MMU to support 8M byte pages, then load one
- * entry into each of the instruction and data TLBs to map the first
- * 8M 1:1.  I also mapped an additional I/O space 1:1 so we can get to
- * the "internal" processor registers before MMU_init is called.
- *
- * The TLB code currently contains a major hack.  Since I use the condition
- * code register, I have to save and restore it.  I am out of registers, so
- * I just store it in memory location 0 (the TLB handlers are not reentrant).
- * To avoid making any decisions, I need to use the "segment" valid bit
- * in the first level table, but that would require many changes to the
- * Linux page directory/table functions that I don't want to do right now.
- *
- * I used to use SPRG2 for a temporary register in the TLB handler, but it
- * has since been put to other uses.  I now use a hack to save a register
- * and the CCR at memory location 0.....Someday I'll fix this.....
- *	-- Dan
  */
 	
 	.globl	__start
@@ -241,8 +142,14 @@
 	mr	r28,r6
 	mr	r27,r7
 	li	r24,0			/* cpu # */
-#ifndef CONFIG_8xx
 	bl	prom_init
+#ifdef CONFIG_APUS
+/* On APUS the __va/__pa constants need to be set to the correct 
+ * values before continuing. 
+ */
+	mr	r4,r30
+	bl	fix_mem_constants
+#endif
 	.globl	__secondary_start
 __secondary_start:
 /*
@@ -267,16 +174,9 @@
 	b	5f
 #endif /* CONFIG_PPC64 */
 4:
-#ifdef CONFIG_APUS
-	ori	r11,r11,BL_8M<<2|0x2	/* set up an 8MB mapping */
-	ori	r11,r11,0xfe		/* set up an 8MB mapping */
-	lis	r8,CYBERBASEp@h
-	lwz	r8,0(r8)
-	addis	r8,r8,KERNELBASE@h
-	addi	r8,r8,2
-#else	
+	tophys(r8,r11)
+	ori	r8,r8,2			/* R/W access */
 	ori	r11,r11,BL_256M<<2|0x2	/* set up BAT registers for 604 */
-	li	r8,2			/* R/W access */
 #ifdef CONFIG_PPC64
 	/* clear out the high 32 bits in the BAT */
 	clrldi	r11,r11,32
@@ -295,15 +195,16 @@
 	mtspr	DBAT1U,r21		/* bit in upper BAT register */
 	mtspr	IBAT1L,r18
 	mtspr	IBAT1U,r21
-	
+
+#if 0	/* for now, otherwise we overflow the 0x100 bytes we have here */
 	oris	r18,r8,0x20000000@h
 	oris	r21,r11,(KERNELBASE+0x20000000)@h
 	mtspr	DBAT2L,r18		/* N.B. 6xx (not 601) have valid */
 	mtspr	DBAT2U,r21		/* bit in upper BAT register */
 	mtspr	IBAT2L,r18
 	mtspr	IBAT2U,r21
+#endif /* 0 */
 #endif /* CONFIG_PPC64 */
-#endif
 	mtspr	DBAT0L,r8		/* N.B. 6xx (not 601) have valid */
 	mtspr	DBAT0U,r11		/* bit in upper BAT register */
 	mtspr	IBAT0L,r8
@@ -325,7 +226,7 @@
 	
 	/* Copy exception code to exception vector base. */
 	lis	r3,KERNELBASE@h
-	tophys(r4,r3,r5)
+	tophys(r4,r3)
 	lis	r3,0xfff0		/* Copy to 0xfff00000 on APUS */
 	li	r5,0x4000		/* # bytes of memory to copy */
 	li	r6,0
@@ -359,80 +260,6 @@
  * this shouldn't bother the pmac since it just gets turned on again
  * as we jump to our code at KERNELBASE. -- Cort
  */
-	
-#else /* CONFIG_8xx */
-	tlbia			/* Invalidate all TLB entries */
-	li	r8, 0
-	mtspr	MI_CTR, r8	/* Set instruction control to zero */
-	lis	r8, MD_RESETVAL@h
-	mtspr	MD_CTR, r8	/* Set data TLB control */
-
-	/* Now map the lower 8 Meg into the TLBs.  For this quick hack,
-	 * we can load the instruction and data TLB registers with the
-	 * same values.
-	 */
-	lis	r8, KERNELBASE@h	/* Create vaddr for TLB */
-	ori	r8, r8, MI_EVALID	/* Mark it valid */
-	mtspr	MI_EPN, r8
-	mtspr	MD_EPN, r8
-	li	r8, MI_PS8MEG		/* Set 8M byte page */
-	ori	r8, r8, MI_SVALID	/* Make it valid */
-	mtspr	MI_TWC, r8
-	mtspr	MD_TWC, r8
-	li	r8, MI_BOOTINIT		/* Create RPN for address 0 */
-	mtspr	MI_RPN, r8		/* Store TLB entry */
-	mtspr	MD_RPN, r8
-	lis	r8, MI_Kp@h		/* Set the protection mode */
-	mtspr	MI_AP, r8
-	mtspr	MD_AP, r8
-
-/* We will get these from a configuration file as soon as I verify
- * the extraneous bits don't cause problems in the TLB.
- */
-#if defined(CONFIG_MBX) || defined(CONFIG_RPXLITE)
-#define BOOT_IMMR      0xfa000000
-#endif
-#ifdef CONFIG_BSEIP
-#define BOOT_IMMR      0xff000000
-#endif
-	/* Map another 8 MByte at 0xfa000000 to get the processor
-	 * internal registers (among other things).
-	 */
-	lis     r8, BOOT_IMMR@h         /* Create vaddr for TLB */
-	ori	r8, r8, MD_EVALID	/* Mark it valid */
-	mtspr	MD_EPN, r8
-	li	r8, MD_PS8MEG		/* Set 8M byte page */
-	ori	r8, r8, MD_SVALID	/* Make it valid */
-	mtspr	MD_TWC, r8
-	lis     r8, BOOT_IMMR@h         /* Create paddr for TLB */
-	ori	r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
-	mtspr	MD_RPN, r8
-
-	/* Since the cache is enabled according to the information we
-	 * just loaded into the TLB, invalidate and enable the caches here.
-	 * We should probably check/set other modes....later.
-	 */
-	lis	r8, IDC_INVALL@h
-	mtspr	IC_CST, r8
-	mtspr	DC_CST, r8
-	lis	r8, IDC_ENABLE@h
-	mtspr	IC_CST, r8
-#if 0
-	mtspr	DC_CST, r8
-#else
-	/* For a debug option, I left this here to easily enable
-	 * the write through cache mode
-	 */
-	lis	r8, DC_SFWT@h
-	mtspr	DC_CST, r8
-	lis	r8, IDC_ENABLE@h
-	mtspr	DC_CST, r8
-#endif
-
-/* We now have the lower 8 Meg mapped into TLB entries, and the caches
- * ready to work.
- */
-#endif /* CONFIG_8xx */
 
 turn_on_mmu:
 	mfmsr	r0
@@ -445,14 +272,6 @@
 	rfi				/* enables MMU */
 
 /*
- * GCC sometimes accesses words at negative offsets from the stack
- * pointer, although the SysV ABI says it shouldn't.  To cope with
- * this, we leave this much untouched space on the stack on exception
- * entry.
- */
-#define STACK_UNDERHEAD	0
-	
-/*
  * Exception entry code.  This code runs with address translation
  * turned off, i.e. using physical addresses.
  * We assume sprg3 has the physical address of the current
@@ -465,8 +284,8 @@
 	mfspr	r21,SPRG2;		/* exception stack to use from */ \
 	cmpwi	0,r21,0;		/* user mode or RTAS */ \
 	bne	1f;		\
-	tophys(r21,r1,r21);		/* use tophys(kernel sp) otherwise */ \
-	subi	r21,r21,INT_FRAME_SIZE+STACK_UNDERHEAD;	/* alloc exc. frame */\
+	tophys(r21,r1);			/* use tophys(kernel sp) otherwise */ \
+	subi	r21,r21,INT_FRAME_SIZE;	/* alloc exc. frame */\
 1:	stw	r20,_CCR(r21);		/* save registers */ \
 	stw	r22,GPR22(r21);	\
 	stw	r23,GPR23(r21);	\
@@ -486,7 +305,7 @@
 	stw	r1,GPR1(r21);	\
 	stw	r2,GPR2(r21);	\
 	stw	r1,0(r21);	\
-	tovirt(r1,r21,r1);		/* set new kernel sp */	\
+	tovirt(r1,r21);			/* set new kernel sp */	\
 	SAVE_4GPRS(3, r21);
 /*
  * Note: code which follows this uses cr0.eq (set if from kernel),
@@ -504,7 +323,7 @@
 	li	r20,MSR_KERNEL;			\
 	bl	transfer_to_handler; 		\
 	.long	hdlr;				\
-	.long	int_return
+	.long	ret_from_except
 
 /* System reset */
 #ifdef CONFIG_SMP /* MVME/MTX start the secondary here */
@@ -516,23 +335,18 @@
 /* Machine check */
 	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
 
-/* Data access exception.
- * This is "never generated" by the MPC8xx.  We jump to it for other
- * translation errors.
- */
+/* Data access exception. */
 	. = 0x300
 DataAccess:
 	EXCEPTION_PROLOG
 	mfspr	r20,DSISR
-#ifndef CONFIG_8xx
 	andis.	r0,r20,0xa470		/* weird error? */
 	bne	1f			/* if not, try to put a PTE */
 	mfspr	r3,DAR			/* into the hash table */
 	rlwinm	r4,r23,32-13,30,30	/* MSR_PR -> _PAGE_USER */
 	rlwimi	r4,r20,32-23,29,29	/* DSISR_STORE -> _PAGE_RW */
-	mfspr	r5,SPRG3		/* phys addr of TSS */
+	mfspr	r5,SPRG3		/* phys addr of THREAD */
 	bl	hash_page
-#endif
 1:	stw	r20,_DSISR(r21)
 	mr	r5,r20
 	mfspr	r4,DAR
@@ -542,24 +356,19 @@
 	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
 	bl	transfer_to_handler
 	.long	do_page_fault
-	.long	int_return
+	.long	ret_from_except
 
-/* Instruction access exception.
- * This is "never generated" by the MPC8xx.  We jump to it for other
- * translation errors.
- */
+/* Instruction access exception. */
 	. = 0x400
 InstructionAccess:
 	EXCEPTION_PROLOG
-#ifndef CONFIG_8xx
 	andis.	r0,r23,0x4000		/* no pte found? */
 	beq	1f			/* if so, try to put a PTE */
 	mr	r3,r22			/* into the hash table */
 	rlwinm	r4,r23,32-13,30,30	/* MSR_PR -> _PAGE_USER */
 	mr	r20,r23			/* SRR1 has reason bits */
-	mfspr	r5,SPRG3		/* phys addr of TSS */
+	mfspr	r5,SPRG3		/* phys addr of THREAD */
 	bl	hash_page
-#endif
 1:	addi	r3,r1,STACK_FRAME_OVERHEAD
 	mr	r4,r22
 	mr	r5,r23
@@ -567,7 +376,7 @@
 	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
 	bl	transfer_to_handler
 	.long	do_page_fault
-	.long	int_return
+	.long	ret_from_except
 
 /* External interrupt */
 	. = 0x500;
@@ -606,7 +415,7 @@
 	li	r4,0
 	bl	transfer_to_handler
 	.long	do_IRQ;
-	.long	int_return
+	.long	ret_from_except
 	
 
 /* Alignment exception */
@@ -622,7 +431,7 @@
 	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
 	bl	transfer_to_handler
 	.long	AlignmentException
-	.long	int_return
+	.long	ret_from_except
 
 /* Program check exception */
 	. = 0x700
@@ -633,9 +442,8 @@
 	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
 	bl	transfer_to_handler
 	.long	ProgramCheckException
-	.long	int_return
+	.long	ret_from_except
 
-#ifndef CONFIG_8xx
 /* Floating-point unavailable */
 	. = 0x800
 FPUnavailable:
@@ -644,12 +452,7 @@
 	li	r20,MSR_KERNEL
 	bl	transfer_to_handler	/* if from kernel, take a trap */
 	.long	KernelFP
-	.long	int_return
-#else
-/* No FPU on MPC8xx.  This exception is not supposed to happen.
-*/
-	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
-#endif
+	.long	ret_from_except
 
 	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
 	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
@@ -664,7 +467,7 @@
 	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
 	bl	transfer_to_handler
 	.long	DoSyscall
-	.long	int_return
+	.long	ret_from_except
 
 /* Single step - not used on 601 */
 	STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
@@ -672,14 +475,12 @@
 	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
 	STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
 
-#ifndef CONFIG_8xx
 /*
  * Handle TLB miss for instruction on 603/603e.
  * Note: we get an alternate set of r0 - r3 to use automatically.
  */
 	. = 0x1000
 InstructionTLBMiss:
-#ifdef NO_RELOAD_HTAB
 /*
  * r0:	stored ctr
  * r1:	linux style pte ( later becomes ppc hardware pte )
@@ -689,14 +490,14 @@
 	mfctr	r0
 	/* Get PTE (linux-style) and check access */
 	mfspr	r2,SPRG3
-	lwz	r2,PG_TABLES(r2)
-	tophys(r2,r2,r3)
+	lwz	r2,PGDIR(r2)
+	tophys(r2,r2)
 	mfspr	r3,IMISS
 	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
 	lwz	r2,0(r2)		/* get pmd entry */
 	rlwinm.	r2,r2,0,0,19		/* extract address of pte page */
 	beq-	InstructionAddressInvalid	/* return if no mapping */
-	tophys(r2,r2,r1)
+	tophys(r2,r2)
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
 	lwz	r1,0(r2)		/* get linux-style pte */
 	/* setup access flags in r3 */
@@ -719,40 +520,11 @@
 	mfspr	r3,SRR1		/* Need to restore CR0 */
 	mtcrf	0x80,r3
 	rfi	
-#else
-	mfctr	r0		/* Need to save this - CTR can't be touched! */
-	mfspr	r2,HASH1	/* Get PTE pointer */
-	mfspr	r3,ICMP		/* Partial item compare value */
-00:	li	r1,8		/* 8 items / bucket */
-	mtctr	r1
-	subi	r2,r2,8		/* Preset pointer */
-10:	lwzu	r1,8(r2)	/* Get next PTE */
-	cmp	0,r1,r3		/* Found entry yet? */
-	bdnzf	2,10b		/* Jump back if not, until CTR==0 */
-	bne	30f		/* Try secondary hash if CTR==0 */
-	lwz	r1,4(r2)	/* Get second word of entry */
-20:	mtctr	r0		/* Restore CTR */
-	mfspr	r3,SRR1		/* Need to restore CR0 */
-	mtcrf	0x80,r3
-	mfspr	r0,IMISS	/* Set to update TLB */
-	mtspr	RPA,r1
-	tlbli	r0
-	rfi			/* All done */
-/* Secondary hash */
-30:	andi.	r1,r3,0x40	/* Already doing secondary hash? */
-	bne	InstructionAddressInvalid /* Yes - item not in hash table */
-	mfspr	r2,HASH2	/* Get hash table pointer */
-	ori	r3,r3,0x40	/* Set secondary hash */
-	b	00b		/* Try lookup again */
-#endif /* NO_RELOAD_HTAB */
 InstructionAddressInvalid:
 	mfspr	r3,SRR1
 	rlwinm	r1,r3,9,6,6	/* Get load/store bit */
-#ifdef NO_RELOAD_HTAB
+
 	addis	r1,r1,0x2000
-#else
-	addis	r1,r1,0x4000	/* Set bit 1 -> PTE not found (in HTAB) */
-#endif /* NO_RELOAD_HTAB */
 	mtspr	DSISR,r1	/* (shouldn't be needed) */
 	mtctr	r0		/* Restore CTR */
 	andi.	r2,r3,0xFFFF	/* Clear upper bits of SRR1 */
@@ -769,20 +541,12 @@
 	sync			/* Some chip revs have problems here... */
 	mtmsr	r0
 	b	InstructionAccess
-#else
-/* On the MPC8xx, this is a software emulation interrupt.  It occurs
- * for all unimplemented and illegal instructions.
- */
-	STD_EXCEPTION(0x1000, SoftEmu, SoftwareEmulation)
-#endif
 
 /*
  * Handle TLB miss for DATA Load operation on 603/603e
  */
 	. = 0x1100
-#ifndef CONFIG_8xx
 DataLoadTLBMiss:
-#ifdef NO_RELOAD_HTAB
 /*
  * r0:	stored ctr
  * r1:	linux style pte ( later becomes ppc hardware pte )
@@ -792,14 +556,14 @@
 	mfctr	r0
 	/* Get PTE (linux-style) and check access */
 	mfspr	r2,SPRG3
-	lwz	r2,PG_TABLES(r2)		
-	tophys(r2,r2,r3)
+	lwz	r2,PGDIR(r2)
+	tophys(r2,r2)
 	mfspr	r3,DMISS
 	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
 	lwz	r2,0(r2)		/* get pmd entry */
 	rlwinm.	r2,r2,0,0,19		/* extract address of pte page */
 	beq-	DataAddressInvalid	/* return if no mapping */
-	tophys(r2,r2,r1)
+	tophys(r2,r2)
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
 	lwz	r1,0(r2)		/* get linux-style pte */
 	/* setup access flags in r3 */
@@ -823,40 +587,10 @@
 	mfspr	r3,SRR1		/* Need to restore CR0 */
 	mtcrf	0x80,r3
 	rfi	
-#else
-	mfctr	r0		/* Need to save this - CTR can't be touched! */
-	mfspr	r2,HASH1	/* Get PTE pointer */
-	mfspr	r3,DCMP		/* Partial item compare value */
-00:	li	r1,8		/* 8 items / bucket */
-	mtctr	r1
-	subi	r2,r2,8		/* Preset pointer */
-10:	lwzu	r1,8(r2)	/* Get next PTE */
-	cmp	0,r1,r3		/* Found entry yet? */
-	bdnzf	2,10b		/* Jump back if not, until CTR==0 */
-	bne	30f		/* Try secondary hash if CTR==0 */
-	lwz	r1,4(r2)	/* Get second word of entry */
-20:	mtctr	r0		/* Restore CTR */
-	mfspr	r3,SRR1		/* Need to restore CR0 */
-	mtcrf	0x80,r3
-	mfspr	r0,DMISS	/* Set to update TLB */
-	mtspr	RPA,r1
-	tlbld	r0
-	rfi			/* All done */
-/* Secondary hash */
-30:	andi.	r1,r3,0x40	/* Already doing secondary hash? */
-	bne	DataAddressInvalid /* Yes - item not in hash table */
-	mfspr	r2,HASH2	/* Get hash table pointer */
-	ori	r3,r3,0x40	/* Set secondary hash */
-	b	00b		/* Try lookup again */
-#endif /* NO_RELOAD_HTAB */
 DataAddressInvalid:
 	mfspr	r3,SRR1
 	rlwinm	r1,r3,9,6,6	/* Get load/store bit */
-#ifdef NO_RELOAD_HTAB
 	addis	r1,r1,0x2000
-#else
-	addis	r1,r1,0x4000	/* Set bit 1 -> PTE not found */
-#endif /* NO_RELOAD_HTAB */
 	mtspr	DSISR,r1
 	mtctr	r0		/* Restore CTR */
 	andi.	r2,r3,0xFFFF	/* Clear upper bits of SRR1 */
@@ -872,79 +606,12 @@
 	sync			/* Some chip revs have problems here... */
 	mtmsr	r0
 	b	DataAccess
-#else
-/*
- * For the MPC8xx, this is a software tablewalk to load the instruction
- * TLB.  It is modelled after the example in the Motorola manual.  The task
- * switch loads the M_TWB register with the pointer to the first level table.
- * If we discover there is no second level table (the value is zero), the
- * plan was to load that into the TLB, which causes another fault into the
- * TLB Error interrupt where we can handle such problems.  However, that did
- * not work, so if we discover there is no second level table, we restore
- * registers and branch to the error exception.  We have to use the MD_xxx
- * registers for the tablewalk because the equivalent MI_xxx registers
- * only perform the attribute functions.
- */
-InstructionTLBMiss:
-	mtspr	M_TW, r20	/* Save a couple of working registers */
-	mfcr	r20
-	stw	r20, 0(r0)
-	stw	r21, 4(r0)
-	mfspr	r20, SRR0	/* Get effective address of fault */
-	mtspr	MD_EPN, r20	/* Have to use MD_EPN for walk, MI_EPN can't */
-	mfspr	r20, M_TWB	/* Get level 1 table entry address */
-	lwz	r21, 0(r20)	/* Get the level 1 entry */
-	rlwinm.	r20, r21,0,0,20	/* Extract page descriptor page address */
-	beq	2f		/* If zero, don't try to find a pte */
-
-	/* We have a pte table, so load the MI_TWC with the attributes
-	 * for this page, which has only bit 31 set.
-	 */
-	tophys(r21,r21,0)
-	ori	r21,r21,1		/* Set valid bit */
-	mtspr	MI_TWC, r21	/* Set page attributes */
-	mtspr	MD_TWC, r21	/* Load pte table base address */
-	mfspr	r21, MD_TWC	/* ....and get the pte address */
-	lwz	r21, 0(r21)	/* Get the pte */
-
-	/* Set four subpage valid bits (24, 25, 26, and 27).
-	 * Since we currently run MI_CTR.PPCS = 0, the manual says,
-	 *	"If the page size is larger than 4k byte, then all the
-	 *	 4 bits should have the same value."
-	 * I don't really know what to do if the page size is 4k Bytes,
-	 * but I know setting them all to 0 does not work, and setting them
-	 * all to 1 does, so that is the way it is right now.
-	 * BTW, these four bits map to the software only bits in the
-	 * linux page table.  I used to turn them all of, but now just
-	 * set them all for the hardware.
-	li	r20, 0x00f0
-	andc	r20, r21, r20
-	ori	r20, r20, 0x0080
-	 */
-	ori	r20, r21, 0x00f0
-
-	mtspr	MI_RPN, r20	/* Update TLB entry */
-
-	mfspr	r20, M_TW	/* Restore registers */
-	lwz	r21, 0(r0)
-	mtcr	r21
-	lwz	r21, 4(r0)
-	rfi
-
-2:	mfspr	r20, M_TW	/* Restore registers */
-	lwz	r21, 0(r0)
-	mtcr	r21
-	lwz	r21, 4(r0)
-	b	InstructionAccess
-#endif /* CONFIG_8xx */
 	
 /*
  * Handle TLB miss for DATA Store on 603/603e
  */
 	. = 0x1200
 DataStoreTLBMiss:
-#ifndef CONFIG_8xx
-#ifdef NO_RELOAD_HTAB
 /*
  * r0:	stored ctr
  * r1:	linux style pte ( later becomes ppc hardware pte )
@@ -954,14 +621,14 @@
 	mfctr	r0
 	/* Get PTE (linux-style) and check access */
 	mfspr	r2,SPRG3
-	lwz	r2,PG_TABLES(r2)		
-	tophys(r2,r2,r3)
+	lwz	r2,PGDIR(r2)
+	tophys(r2,r2)
 	mfspr	r3,DMISS
 	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
 	lwz	r2,0(r2)		/* get pmd entry */
 	rlwinm.	r2,r2,0,0,19		/* extract address of pte page */
 	beq-	DataAddressInvalid	/* return if no mapping */
-	tophys(r2,r2,r1)
+	tophys(r2,r2)
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
 	lwz	r1,0(r2)		/* get linux-style pte */
 	/* setup access flags in r3 */
@@ -985,171 +652,12 @@
 	mfspr	r3,SRR1		/* Need to restore CR0 */
 	mtcrf	0x80,r3
 	rfi	
-#else	
-	mfctr	r0		/* Need to save this - CTR can't be touched! */
-	mfspr	r2,HASH1	/* Get PTE pointer */
-	mfspr	r3,DCMP		/* Partial item compare value */
-00:	li	r1,8		/* 8 items / bucket */
-	mtctr	r1
-	subi	r2,r2,8		/* Preset pointer */
-10:	lwzu	r1,8(r2)	/* Get next PTE */
-	cmp	0,r1,r3		/* Found entry yet? */
-	bdnzf	2,10b		/* Jump back if not, until CTR==0 */
-	bne	30f		/* Try secondary hash if CTR==0 */
-	lwz	r1,4(r2)	/* Get second word of entry */
-20:	mtctr	r0		/* Restore CTR */
-	mfspr	r3,SRR1		/* Need to restore CR0 */
-	mtcrf	0x80,r3
-	mfspr	r0,DMISS	/* Set to update TLB */
-	mtspr	RPA,r1
-	tlbld	r0
-	rfi			/* All done */	
-/* Secondary hash */
-30:	andi.	r1,r3,0x40	/* Already doing secondary hash? */
-	bne	DataAddressInvalid /* Yes - item not in hash table */
-	mfspr	r2,HASH2	/* Get hash table pointer */
-	ori	r3,r3,0x40	/* Set secondary hash */
-	b	00b			/* Try lookup again */
-#endif /* NO_RELOAD_HTAB */
-#else /* CONFIG_8xx */	
-	mtspr	M_TW, r20	/* Save a couple of working registers */
-	mfcr	r20
-	stw	r20, 0(r0)
-	stw	r21, 4(r0)
-	mfspr	r20, M_TWB	/* Get level 1 table entry address */
-	lwz	r21, 0(r20)	/* Get the level 1 entry */
-	rlwinm.	r20, r21,0,0,20	/* Extract page descriptor page address */
-	beq	2f		/* If zero, don't try to find a pte */
-
-	/* We have a pte table, so load fetch the pte from the table.
-	 */
-	tophys(r21, r21, 0)
-	ori	r21, r21, 1	/* Set valid bit in physical L2 page */
-	mtspr	MD_TWC, r21	/* Load pte table base address */
-	mfspr	r21, MD_TWC	/* ....and get the pte address */
-	lwz	r21, 0(r21)	/* Get the pte */
-
-	/* Set four subpage valid bits (24, 25, 26, and 27).
-	 * Since we currently run MD_CTR.PPCS = 0, the manual says,
-	 *	"If the page size is larger than 4k byte, then all the
-	 *	 4 bits should have the same value."
-	 * I don't really know what to do if the page size is 4k Bytes,
-	 * but I know setting them all to 0 does not work, and setting them
-	 * all to 1 does, so that is the way it is right now.
-	 * BTW, these four bits map to the software only bits in the
-	 * linux page table.  I used to turn them all of, but now just
-	 * set them all for the hardware.
-	li	r20, 0x00f0
-	andc	r20, r21, r20
-	ori	r20, r20, 0x0080
-	 */
-	ori	r20, r21, 0x00f0
-
-	mtspr	MD_RPN, r20	/* Update TLB entry */
-
-	mfspr	r20, M_TW	/* Restore registers */
-	lwz	r21, 0(r0)
-	mtcr	r21
-	lwz	r21, 4(r0)
-	rfi
-
-2:	mfspr	r20, M_TW	/* Restore registers */
-	lwz	r21, 0(r0)
-	mtcr	r21
-	lwz	r21, 4(r0)
-	b	DataAccess
-#endif /* CONFIG_8xx */
 
-#ifndef CONFIG_8xx
 /* Instruction address breakpoint exception (on 603/604) */
 	STD_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint)
-#else
-
-/* This is an instruction TLB error on the MPC8xx.  This could be due
- * to many reasons, such as executing guarded memory or illegal instruction
- * addresses.  There is nothing to do but handle a big time error fault.
- */
-	. = 0x1300
-InstructionTLBError:
-	b	InstructionAccess
-#endif
 
 /* System management exception (603?) */
-#ifndef CONFIG_8xx
 	STD_EXCEPTION(0x1400, Trap_14, UnknownException)
-#else
-
-/* This is the data TLB error on the MPC8xx.  This could be due to
- * many reasons, including a dirty update to a pte.  We can catch that
- * one here, but anything else is an error.  First, we track down the
- * Linux pte.  If it is valid, write access is allowed, but the
- * page dirty bit is not set, we will set it and reload the TLB.  For
- * any other case, we bail out to a higher level function that can
- * handle it.
- */
-	. = 0x1400
-DataTLBError:
-	mtspr	M_TW, r20	/* Save a couple of working registers */
-	mfcr	r20
-	stw	r20, 0(r0)
-	stw	r21, 4(r0)
-
-	/* First, make sure this was a store operation.
-	*/
-	mfspr	r20, DSISR
-	andis.	r21, r20, 0x0200	/* If set, indicates store op */
-	beq	2f
-
-	mfspr	r20, M_TWB	/* Get level 1 table entry address */
-	lwz	r21, 0(r20)	/* Get the level 1 entry */
-	rlwinm.	r20, r21,0,0,20	/* Extract page descriptor page address */
-	beq	2f		/* If zero, bail */
-
-	/* We have a pte table, so fetch the pte from the table.
-	 */
-	tophys(r21, r21, 0)
-	ori	r21, r21, 1		/* Set valid bit in physical L2 page */
-	mtspr	MD_TWC, r21		/* Load pte table base address */
-	mfspr	r21, MD_TWC		/* ....and get the pte address */
-	lwz	r21, 0(r21)		/* Get the pte */
-
-	andi.	r20, r21, _PAGE_RW	/* Is it writeable? */
-	beq	2f			/* Bail out if not */
-
-	ori	r21, r21, _PAGE_DIRTY	/* Update changed bit */
-	mfspr	r20, MD_TWC		/* Get pte address again */
-	stw	r21, 0(r20)		/* and update pte in table */
-
-	/* Set four subpage valid bits (24, 25, 26, and 27).
-	 * Since we currently run MD_CTR.PPCS = 0, the manual says,
-	 *	"If the page size is larger than 4k byte, then all the
-	 *	 4 bits should have the same value."
-	 * I don't really know what to do if the page size is 4k Bytes,
-	 * but I know setting them all to 0 does not work, and setting them
-	 * all to 1 does, so that is the way it is right now.
-	 * BTW, these four bits map to the software only bits in the
-	 * linux page table.  I used to turn them all of, but now just
-	 * set them all for the hardware.
-	li	r20, 0x00f0
-	andc	r20, r21, r20
-	ori	r20, r20, 0x0080
-	 */
-	ori	r20, r21, 0x00f0
-
-	mtspr	MD_RPN, r20	/* Update TLB entry */
-
-	mfspr	r20, M_TW	/* Restore registers */
-	lwz	r21, 0(r0)
-	mtcr	r21
-	lwz	r21, 4(r0)
-	rfi
-2:
-	mfspr	r20, M_TW	/* Restore registers */
-	lwz	r21, 0(r0)
-	mtcr	r21
-	lwz	r21, 4(r0)
-	b	DataAccess
-#endif /* CONFIG_8xx */
 
 	STD_EXCEPTION(0x1500, Trap_15, UnknownException)
 	STD_EXCEPTION(0x1600, Trap_16, UnknownException)
@@ -1158,16 +666,11 @@
 	STD_EXCEPTION(0x1900, Trap_19, UnknownException)
 	STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
 	STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
-/* On the MPC8xx, these next four traps are used for development
- * support of breakpoints and such.  Someday I will get around to
- * using them.
- */
 	STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
 	STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
 	STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
 	STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
 
-#ifndef CONFIG_8xx
 	/* Run mode exception */
 	STD_EXCEPTION(0x2000, RunMode, RunModeException)
 
@@ -1188,9 +691,6 @@
 	STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
 
 	. = 0x3000
-#else
-	. = 0x2000
-#endif
 
 /*
  * This code finishes saving the registers to the exception frame
@@ -1208,12 +708,12 @@
 	SAVE_8GPRS(12, r21)
 	SAVE_8GPRS(24, r21)
 	andi.	r23,r23,MSR_PR
-	mfspr	r23,SPRG3		/* if from user, fix up tss.regs */
+	mfspr	r23,SPRG3		/* if from user, fix up THREAD.regs */
 	beq	2f
 	addi	r24,r1,STACK_FRAME_OVERHEAD
 	stw	r24,PT_REGS(r23)
-2:	addi	r2,r23,-TSS		/* set r2 to current */
-	tovirt(r2,r2,r23)
+2:	addi	r2,r23,-THREAD		/* set r2 to current */
+	tovirt(r2,r2)
 	mflr	r23
 	andi.	r24,r23,0x3f00		/* get vector offset */
 	stw	r24,TRAP(r21)
@@ -1252,300 +752,6 @@
 	SYNC
 	rfi
 
-#ifndef CONFIG_8xx
-/*
- * Load a PTE into the hash table, if possible.
- * The address is in r3, and r4 contains access flags:
- * _PAGE_USER (4) if a user-mode access, ored with
- * _PAGE_RW (2) if a write.  r20 contains DSISR or SRR1,
- * so bit 1 (0x40000000) is set if the exception was due
- * to no matching PTE being found in the hash table.
- * r5 contains the physical address of the current task's tss.
- *
- * Returns to the caller if the access is illegal or there is no
- * mapping for the address.  Otherwise it places an appropriate PTE
- * in the hash table and returns from the exception.
- * Uses r0, r2 - r6, ctr, lr.
- *
- * For speed, 4 of the instructions get patched once the size and
- * physical address of the hash table are known.  These definitions
- * of Hash_base and Hash_bits below are just an example.
- */
-Hash_base = 0x180000
-Hash_bits = 12				/* e.g. 256kB hash table */
-Hash_msk = (((1 << Hash_bits) - 1) * 64)
-	
-	.globl	hash_page
-hash_page:
-#ifdef __SMP__
-	eieio
-	lis	r2,hash_table_lock@h
-	ori	r2,r2,hash_table_lock@l
- 	tophys(r2,r2,r6)
-	lis	r6,100000000@h
-	mtctr	r6
-	lwz	r0,PROCESSOR-TSS(r5)
-	or	r0,r0,r6
-10:	lwarx	r6,0,r2
-	cmpi	0,r6,0
-	bne-	12f
-	stwcx.	r0,0,r2
-	beq+	11f
-12:	cmpw	r6,r0
-	bdnzf	2,10b
-	tw	31,31,31
-11:	eieio
-#endif
-	/* Get PTE (linux-style) and check access */
-	lwz	r5,PG_TABLES(r5)		
-	tophys(r5,r5,r2)		/* convert to phys addr */
-	rlwimi	r5,r3,12,20,29		/* insert top 10 bits of address */
-	lwz	r5,0(r5)		/* get pmd entry */
-	rlwinm.	r5,r5,0,0,19		/* extract address of pte page */
-#ifdef __SMP__
-	beq-	hash_page_out		/* return if no mapping */
-#else
-	/* XXX it seems like the 601 will give a machine fault on the
-	   rfi if its alignment is wrong (bottom 4 bits of address are
-	   8 or 0xc) and we have had a not-taken conditional branch
-	   to the address following the rfi. */
-	beqlr-
-#endif
-	tophys(r2,r5,r2)
-	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	lwz	r6,0(r2)		/* get linux-style pte */
-	ori	r4,r4,1			/* set _PAGE_PRESENT bit in access */
-	andc.	r0,r4,r6		/* check access & ~permission */
-#ifdef __SMP__
-	bne-	hash_page_out		/* return if access not permitted */
-#else
-	bnelr-
-#endif
-
-	ori	r6,r6,0x100		/* set _PAGE_ACCESSED in pte */
-	rlwinm	r5,r4,5,24,24		/* _PAGE_RW access -> _PAGE_DIRTY */
-	rlwimi	r5,r4,7,22,22		/* _PAGE_RW -> _PAGE_HWWRITE */
-	or	r6,r6,r5
-	stw	r6,0(r2)		/* update PTE (accessed/dirty bits) */
-
-	/* Convert linux-style PTE to low word of PPC-style PTE */
-#ifdef CONFIG_PPC64
-	/* clear the high 32 bits just in case */
-	clrldi	r6,r6,32
-	clrldi	r4,r4,32
-#endif /* CONFIG_PPC64 */
-	rlwinm	r4,r6,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
-	rlwimi	r6,r6,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
-	ori	r4,r4,0xe04		/* clear out reserved bits */
-	andc	r6,r6,r4		/* PP=2 or 0, when _PAGE_HWWRITE */
-
-	/* Construct the high word of the PPC-style PTE */
-	mfsrin	r5,r3			/* get segment reg for segment */
-#ifdef CONFIG_PPC64
-	sldi	r5,r5,12
-#else /* CONFIG_PPC64 */
-	rlwinm	r5,r5,7,1,24		/* put VSID in 0x7fffff80 bits */
-#endif /* CONFIG_PPC64 */
-	
-#ifndef __SMP__				/* do this later for SMP */
-#ifdef CONFIG_PPC64
-	ori	r5,r5,1			/* set V (valid) bit */
-#else /* CONFIG_PPC64 */
-	oris	r5,r5,0x8000		/* set V (valid) bit */
-#endif /* CONFIG_PPC64 */
-#endif
-	
-#ifdef CONFIG_PPC64
-/* XXX:	 does this insert the api correctly? -- Cort */
-	rlwimi	r5,r3,17,21,25		/* put in API (abbrev page index) */
-#else /* CONFIG_PPC64 */
-	rlwimi	r5,r3,10,26,31		/* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64 */
-	/* Get the address of the primary PTE group in the hash table */
-	.globl	hash_page_patch_A
-hash_page_patch_A:
-	lis	r4,Hash_base@h		/* base address of hash table */
-#ifdef CONFIG_PPC64
-	/* just in case */
-	clrldi	r4,r4,32
-#endif	
-	rlwimi	r4,r5,32-1,26-Hash_bits,25	/* (VSID & hash_mask) << 6 */
-	rlwinm	r0,r3,32-6,26-Hash_bits,25	/* (PI & hash_mask) << 6 */
-	xor	r4,r4,r0		/* make primary hash */
-
-	/* See whether it was a PTE not found exception or a
-	   protection violation. */
-	andis.	r0,r20,0x4000
-	li	r2,8			/* PTEs/group */
-	bne	10f			/* no PTE: go look for an empty slot */
-	tlbie	r3			/* invalidate TLB entry */
-
-	/* Search the primary PTEG for a PTE whose 1st word matches r5 */
-	mtctr	r2
-	addi	r3,r4,-8
-1:	lwzu	r0,8(r3)		/* get next PTE */
-	cmp	0,r0,r5
-	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
-	beq+	found_slot
-
-	/* Search the secondary PTEG for a matching PTE */
-	ori	r5,r5,0x40		/* set H (secondary hash) bit */
-	.globl	hash_page_patch_B
-hash_page_patch_B:
-	xoris	r3,r4,Hash_msk>>16	/* compute secondary hash */
-	xori	r3,r3,0xffc0
-	addi	r3,r3,-8
-	mtctr	r2
-2:	lwzu	r0,8(r3)
-	cmp	0,r0,r5
-	bdnzf	2,2b
-	beq+	found_slot
-	xori	r5,r5,0x40		/* clear H bit again */
-
-	/* Search the primary PTEG for an empty slot */
-10:	mtctr	r2
-	addi	r3,r4,-8		/* search primary PTEG */
-1:	lwzu	r0,8(r3)		/* get next PTE */
-	srwi.	r0,r0,31		/* only want to check valid bit */
-	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
-	beq+	found_empty
-
-	/* Search the secondary PTEG for an empty slot */
-	ori	r5,r5,0x40		/* set H (secondary hash) bit */
-	.globl	hash_page_patch_C
-hash_page_patch_C:
-	xoris	r3,r4,Hash_msk>>16	/* compute secondary hash */
-	xori	r3,r3,0xffc0
-	addi	r3,r3,-8
-	mtctr	r2
-2:	lwzu	r0,8(r3)
-	srwi.	r0,r0,31		/* only want to check valid bit */
-	bdnzf	2,2b
-	beq+	found_empty
-
-	/*
-	 * Choose an arbitrary slot in the primary PTEG to overwrite.
-	 * Since both the primary and secondary PTEGs are full, and we
-	 * have no information that the PTEs in the primary PTEG are
-	 * more important or useful than those in the secondary PTEG,
-	 * and we know there is a definite (although small) speed
-	 * advantage to putting the PTE in the primary PTEG, we always
-	 * put the PTE in the primary PTEG.
-	 */
-	xori	r5,r5,0x40		/* clear H bit again */
-	lwz	r2,next_slot@l(0)
-	addi	r2,r2,8
-	andi.	r2,r2,0x38
-	stw	r2,next_slot@l(0)
-	add	r3,r4,r2
-11:		
-	/* update counter of evicted pages */
-	lis	r2,htab_evicts@h
-	ori	r2,r2,htab_evicts@l
-	tophys(r2,r2,r4)
-	lwz	r4,0(r2)
-	addi	r4,r4,1
-	stw	r4,0(r2)
-
-#ifndef __SMP__
-	/* Store PTE in PTEG */
-found_empty:
-	stw	r5,0(r3)
-found_slot:
-	stw	r6,4(r3)
-	sync
-
-#else /* __SMP__ */
-/*
- * Between the tlbie above and updating the hash table entry below,
- * another CPU could read the hash table entry and put it in its TLB.
- * There are 3 cases:
- * 1. using an empty slot
- * 2. updating an earlier entry to change permissions (i.e. enable write)
- * 3. taking over the PTE for an unrelated address
- *
- * In each case it doesn't really matter if the other CPUs have the old
- * PTE in their TLB.  So we don't need to bother with another tlbie here,
- * which is convenient as we've overwritten the register that had the
- * address. :-)  The tlbie above is mainly to make sure that this CPU comes
- * and gets the new PTE from the hash table.
- *
- * We do however have to make sure that the PTE is never in an invalid
- * state with the V bit set.
- */
-found_empty:
-found_slot:
-	stw	r5,0(r3)	/* clear V (valid) bit in PTE */
-	sync
-	tlbsync
-	sync
-	stw	r6,4(r3)	/* put in correct RPN, WIMG, PP bits */
-	sync
-	oris	r5,r5,0x8000
-	stw	r5,0(r3)	/* finally set V bit in PTE */
-#endif /* __SMP__ */
-
-/*
- * Update the hash table miss count.  We only want misses here
- * that _are_ valid addresses and have a pte otherwise we don't
- * count it as a reload.  do_page_fault() takes care of bad addrs
- * and entries that need linux-style pte's created.
- *
- * safe to use r2 here since we're not using it as current yet 
- * update the htab misses count
- *   -- Cort
- */
-	lis	r2,htab_reloads@h
-	ori	r2,r2,htab_reloads@l
-	tophys(r2,r2,r3)
-	lwz	r3,0(r2)
-	addi	r3,r3,1
-	stw	r3,0(r2)
-
-#ifdef __SMP__
-	lis	r2,hash_table_lock@ha
-	tophys(r2,r2,r6)
-	li	r0,0
-	stw	r0,hash_table_lock@l(r2)
-	eieio
-#endif
-
-	/* Return from the exception */
-	lwz	r3,_CCR(r21)
-	lwz	r4,_LINK(r21)
-	lwz	r5,_CTR(r21)
-	mtcrf	0xff,r3
-	mtlr	r4
-	mtctr	r5
-	REST_GPR(0, r21)
-	REST_2GPRS(1, r21)
-	REST_4GPRS(3, r21)
-	/* we haven't used xer */
-	mtspr	SRR1,r23
-	mtspr	SRR0,r22
-	REST_GPR(20, r21)
-	REST_2GPRS(22, r21)
-	lwz	r21,GPR21(r21)
-	rfi
-	
-#ifdef __SMP__
-hash_page_out:
-	lis	r2,hash_table_lock@ha
-	tophys(r2,r2,r6)
-	li	r0,0
-	stw	r0,hash_table_lock@l(r2)
-	eieio
-	blr
-
-	.globl	hash_table_lock
-hash_table_lock:
-	.long	0
-#endif
-
-next_slot:
-	.long	0
-
-load_up_fpu:
 /*
  * Disable FP for the task which had the FPU previously,
  * and save its floating-point registers in its thread_struct.
@@ -1553,6 +759,7 @@
  * On SMP we know the fpu is free, since we give it up every
  * switch.  -- Cort
  */
+load_up_fpu:
 	mfmsr	r5
 	ori	r5,r5,MSR_FP
 	SYNC
@@ -1564,21 +771,17 @@
  * to another.  Instead we call giveup_fpu in switch_to.
  */
 #ifndef __SMP__
-#ifndef CONFIG_APUS
-	lis	r6,-KERNELBASE@h
-#else
-	lis	r6,CYBERBASEp@h
-	lwz	r6,0(r6)
-#endif
+	lis	r6,0                    /* get __pa constant */
+	tophys(r6,r6)
 	addis	r3,r6,last_task_used_math@ha
 	lwz	r4,last_task_used_math@l(r3)
 	cmpi	0,r4,0
 	beq	1f
 	add	r4,r4,r6
-	addi	r4,r4,TSS	        /* want TSS of last_task_used_math */
+	addi	r4,r4,THREAD	        /* want THREAD of last_task_used_math */
 	SAVE_32FPRS(0, r4)
 	mffs	fr0
-	stfd	fr0,TSS_FPSCR-4(r4)
+	stfd	fr0,THREAD_FPSCR-4(r4)
 	lwz	r5,PT_REGS(r4)
 	add	r5,r5,r6
 	lwz	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
@@ -1589,12 +792,12 @@
 #endif /* __SMP__ */
 	/* enable use of FP after return */
 	ori	r23,r23,MSR_FP|MSR_FE0|MSR_FE1
-	mfspr	r5,SPRG3		/* current task's TSS (phys) */
-	lfd	fr0,TSS_FPSCR-4(r5)
+	mfspr	r5,SPRG3		/* current task's THREAD (phys) */
+	lfd	fr0,THREAD_FPSCR-4(r5)
 	mtfsf	0xff,fr0
 	REST_32FPRS(0, r5)
 #ifndef __SMP__
-	subi	r4,r5,TSS
+	subi	r4,r5,THREAD
 	sub	r4,r4,r6
 	stw	r4,last_task_used_math@l(r3)
 #endif /* __SMP__ */
@@ -1627,7 +830,7 @@
 	mr	r4,r2			/* current */
 	lwz	r5,_NIP(r1)
 	bl	printk
-	b	int_return
+	b	ret_from_except
 86:	.string	"floating point used in kernel (task=%p, pc=%x)\n"
 	.align	4
 
@@ -1646,12 +849,12 @@
 	SYNC
 	cmpi	0,r3,0
 	beqlr-				/* if no previous owner, done */
-	addi	r3,r3,TSS	        /* want TSS of task */
+	addi	r3,r3,THREAD	        /* want THREAD of task */
 	lwz	r5,PT_REGS(r3)
 	cmpi	0,r5,0
 	SAVE_32FPRS(0, r3)
 	mffs	fr0
-	stfd	fr0,TSS_FPSCR-4(r3)
+	stfd	fr0,THREAD_FPSCR-4(r3)
 	beq	1f
 	lwz	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
 	li	r3,MSR_FP|MSR_FE0|MSR_FE1
@@ -1665,12 +868,6 @@
 #endif /* __SMP__ */
 	blr
 
-#else  /* CONFIG_8xx */
-	.globl	giveup_fpu
-giveup_fpu:
-	blr
-#endif /* CONFIG_8xx */
-
 /*
  * This code is jumped to from the startup code to copy
  * the kernel image to physical address 0.
@@ -1721,11 +918,66 @@
 	blr
 
 #ifdef CONFIG_APUS
-	/* On APUS the first 0x4000 bytes of the kernel	will be mapped
-	 * at a different physical address than the rest. For this
-	 * reason, the exception code cannot use relative branches to
-	 * access the code below.
-	 */
+/*
+ * On APUS the physical base address of the kernel is not known at compile
+ * time, which means the __pa/__va constants used are incorect. In the
+ * __init section is recorded the virtual addresses of instructions using
+ * these constants, so all that has to be done is fix these before
+ * continuing the kernel boot.
+ *
+ * r4 = The physical address of the kernel base.
+ */
+fix_mem_constants:
+	mr	r10,r4
+	addis	r10,r10,-KERNELBASE@h    /* virt_to_phys constant */
+	neg	r11,r10	                 /* phys_to_virt constant */
+
+	lis	r12,__vtop_table_begin@h
+	ori	r12,r12,__vtop_table_begin@l
+	add	r12,r12,r10	         /* table begin phys address */
+	lis	r13,__vtop_table_end@h
+	ori	r13,r13,__vtop_table_end@l
+	add	r13,r13,r10	         /* table end phys address */
+	subi	r12,r12,4
+	subi	r13,r13,4
+1:	lwzu	r14,4(r12)               /* virt address of instruction */
+	add     r14,r14,r10              /* phys address of instruction */
+	lwz     r15,0(r14)               /* instruction, now insert top */
+	rlwimi  r15,r10,16,16,31         /* half of vp const in low half */
+	stw	r15,0(r14)               /* of instruction and restore. */
+	dcbst	r0,r14			 /* write it to memory */
+	sync
+	icbi	r0,r14			 /* flush the icache line */
+	cmpw	r12,r13
+	bne     1b
+
+	lis	r12,__ptov_table_begin@h
+	ori	r12,r12,__ptov_table_begin@l
+	add	r12,r12,r10	         /* table begin phys address */
+	lis	r13,__ptov_table_end@h
+	ori	r13,r13,__ptov_table_end@l
+	add	r13,r13,r10	         /* table end phys address */
+	subi	r12,r12,4
+	subi	r13,r13,4
+1:	lwzu	r14,4(r12)               /* virt address of instruction */
+	add     r14,r14,r10              /* phys address of instruction */
+	lwz     r15,0(r14)               /* instruction, now insert top */
+	rlwimi  r15,r11,16,16,31         /* half of pv const in low half*/
+	stw	r15,0(r14)               /* of instruction and restore. */
+	dcbst	r0,r14			 /* write it to memory */
+	sync
+	icbi	r0,r14			 /* flush the icache line */
+	cmpw	r12,r13
+	bne     1b
+
+	isync				/* No speculative loading until now */
+	blr
+
+       /* On APUS the first 0x4000 bytes of the kernel will be mapped
+        * at a different physical address than the rest. For this
+        * reason, the exception code cannot use relative branches to
+        * access the code below.
+        */
 	. = 0x4000
 #endif
 
@@ -1752,7 +1004,7 @@
 	/* our cpu # was at addr 0 - go */
 	lis	r5,__secondary_start@h
 	ori	r5,r5,__secondary_start@l
-	tophys(r5,r5,r4)
+	tophys(r5,r5)
 	mtlr	r5
 	mr	r24,r3			/* cpu # */
 	blr
@@ -1762,7 +1014,6 @@
  * This is where the main kernel code starts.
  */
 start_here:
-#ifndef CONFIG_8xx
 	/*
 	 * Enable caches and 604-specific features if necessary.
 	 */
@@ -1794,7 +1045,6 @@
 	ori	r11,r11,HID0_BTCD
 5:	mtspr	HID0,r11		/* superscalar exec & br history tbl */
 4:
-#endif /* CONFIG_8xx */
 #ifdef __SMP__
 	/* if we're the second cpu stack and r2 are different
 	* and we want to not clear the bss -- Cort */
@@ -1848,33 +1098,21 @@
 	mr	r7,r27
 	bl	identify_machine
 	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
 #ifdef CONFIG_PPC64	
 	ld	r6,_SDR1@l(r6)
 #else
 	lwz	r6,_SDR1@l(r6)
 #endif		
-#else
-	/* The right way to do this would be to track it down through
-	 * init's TSS like the context switch code does, but this is
-	 * easier......until someone changes init's static structures.
-	 */
-	lis	r6, swapper_pg_dir@h
-	tophys(r6,r6,0)
-	ori	r6, r6, swapper_pg_dir@l
-	mtspr	M_TWB, r6
-#endif
 	lis	r4,2f@h
 	ori	r4,r4,2f@l
-	tophys(r4,r4,r3)
+	tophys(r4,r4)
 	li	r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
 	mtspr	SRR0,r4
 	mtspr	SRR1,r3
@@ -1888,7 +1126,6 @@
 	tlbsync			/* ... on all CPUs */
 	sync
 #endif
-#ifndef CONFIG_8xx
 	mtspr	SDR1,r6
 #ifdef CONFIG_PPC64
 	/* clear the v bit in the ASR so we can
@@ -1913,23 +1150,23 @@
 	cmpwi	r3,1
 	lis	r3,BATS@ha
 	addi	r3,r3,BATS@l
-	tophys(r3,r3,r4)
+	tophys(r3,r3)
 #ifdef CONFIG_PPC64
-	LOAD_BAT(0,0,r3,r4,r5)
-	LOAD_BAT(1,32,r3,r4,r5)
-	LOAD_BAT(2,64,r3,r4,r5)
-	LOAD_BAT(3,96,r3,r4,r5)
+	LOAD_BAT(0,r3,r4,r5)
+	LOAD_BAT(1,r3,r4,r5)
+	LOAD_BAT(2,r3,r4,r5)
+	LOAD_BAT(3,r3,r4,r5)
 #else /* CONFIG_PPC64 */
-	LOAD_BAT(0,0,r3,r4,r5)
-	LOAD_BAT(1,16,r3,r4,r5)
-	LOAD_BAT(2,32,r3,r4,r5)
-	LOAD_BAT(3,48,r3,r4,r5)
+	LOAD_BAT(0,r3,r4,r5)
+	LOAD_BAT(1,r3,r4,r5)
+	LOAD_BAT(2,r3,r4,r5)
+	LOAD_BAT(3,r3,r4,r5)
 #endif /* CONFIG_PPC64 */
-#endif /* CONFIG_8xx */
+
 /* Set up for using our exception vectors */
-	/* ptr to phys current tss */
-	tophys(r4,r2,r4)
-	addi	r4,r4,TSS	/* init task's TSS */
+	/* ptr to phys current thread */
+	tophys(r4,r2)
+	addi	r4,r4,THREAD	/* init task's THREAD */
 	mtspr	SPRG3,r4
 	li	r3,0
 	mtspr	SPRG2,r3	/* 0 => r1 has kernel sp */
@@ -1943,7 +1180,7 @@
 	 */
 	lis	r5,first_cpu_booted@h
 	ori	r5,r5,first_cpu_booted@l
-	tophys(r5,r5,r3)
+	tophys(r5,r5)
 	lwz	r5,0(r5)
 	cmpi	0,r5,0
 	beq	10f
@@ -1956,371 +1193,6 @@
 	rfi			/* enable MMU and jump to start_kernel */
 
 /*
- * Handle a system call.
- */
-DoSyscall:
-	stw	r0,TSS+LAST_SYSCALL(r2)
-	lwz	r11,_CCR(r1)	/* Clear SO bit in CR */
-	lis	r10,0x1000
-	andc	r11,r11,r10
-	stw	r11,_CCR(r1)
-#ifdef SHOW_SYSCALLS
-#ifdef SHOW_SYSCALLS_TASK
-	lis	r31,show_syscalls_task@ha
-	lwz	r31,show_syscalls_task@l(r31)
-	cmp	0,r2,r31
-	bne	1f
-#endif
-	lis	r3,7f@ha
-	addi	r3,r3,7f@l
-	lwz	r4,GPR0(r1)
-	lwz	r5,GPR3(r1)
-	lwz	r6,GPR4(r1)
-	lwz	r7,GPR5(r1)
-	lwz	r8,GPR6(r1)
-	lwz	r9,GPR7(r1)
-	bl	printk
-	lis	r3,77f@ha
-	addi	r3,r3,77f@l
-	lwz	r4,GPR8(r1)
-	lwz	r5,GPR9(r1)
-	mr	r6,r2
-	bl	printk
-	lwz	r0,GPR0(r1)
-	lwz	r3,GPR3(r1)
-	lwz	r4,GPR4(r1)
-	lwz	r5,GPR5(r1)
-	lwz	r6,GPR6(r1)
-	lwz	r7,GPR7(r1)
-	lwz	r8,GPR8(r1)
-1:
-#endif /* SHOW_SYSCALLS */
-	cmpi	0,r0,0x7777	/* Special case for 'sys_sigreturn' */
-	beq-	10f
-	lwz	r10,TASK_FLAGS(r2)
-	andi.	r10,r10,PF_TRACESYS
-	bne-	50f
-	cmpli	0,r0,NR_syscalls
-	bge-	66f
-	lis	r10,sys_call_table@h
-	ori	r10,r10,sys_call_table@l
-	slwi	r0,r0,2
-	lwzx	r10,r10,r0	/* Fetch system call handler [ptr] */
-	cmpi	0,r10,0
-	beq-	66f
-	mtlr	r10
-	addi	r9,r1,STACK_FRAME_OVERHEAD
-	blrl			/* Call handler */
-	.globl	syscall_ret_1
-syscall_ret_1:
-20:	stw	r3,RESULT(r1)	/* Save result */
-#ifdef SHOW_SYSCALLS
-#ifdef SHOW_SYSCALLS_TASK
-	cmp	0,r2,r31
-	bne	91f
-#endif
-	mr	r4,r3
-	lis	r3,79f@ha
-	addi	r3,r3,79f@l
-	bl	printk
-	lwz	r3,RESULT(r1)
-91:
-#endif
-	li	r10,-_LAST_ERRNO
-	cmpl	0,r3,r10
-	blt	30f
-	neg	r3,r3
-	cmpi	0,r3,ERESTARTNOHAND
-	bne	22f
-	li	r3,EINTR
-22:	lwz	r10,_CCR(r1)	/* Set SO bit in CR */
-	oris	r10,r10,0x1000
-	stw	r10,_CCR(r1)
-30:	stw	r3,GPR3(r1)	/* Update return value */
-	b	int_return
-66:	li	r3,ENOSYS
-	b	22b
-/* sys_sigreturn */
-10:	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	sys_sigreturn
-	cmpi	0,r3,0		/* Check for restarted system call */
-	bge	int_return
-	b	20b
-/* Traced system call support */
-50:	bl	syscall_trace
-	lwz	r0,GPR0(r1)	/* Restore original registers */
-	lwz	r3,GPR3(r1)
-	lwz	r4,GPR4(r1)
-	lwz	r5,GPR5(r1)
-	lwz	r6,GPR6(r1)
-	lwz	r7,GPR7(r1)
-	lwz	r8,GPR8(r1)
-	lwz	r9,GPR9(r1)
-	cmpli	0,r0,NR_syscalls
-	bge-	66f
-	lis	r10,sys_call_table@h
-	ori	r10,r10,sys_call_table@l
-	slwi	r0,r0,2
-	lwzx	r10,r10,r0	/* Fetch system call handler [ptr] */
-	cmpi	0,r10,0
-	beq-	66f
-	mtlr	r10
-	addi	r9,r1,STACK_FRAME_OVERHEAD
-	blrl			/* Call handler */
-	.globl	syscall_ret_2
-syscall_ret_2:
-	stw	r3,RESULT(r1)	/* Save result */	
-	stw	r3,GPR0(r1)	/* temporary gross hack to make strace work */
-	li	r10,-_LAST_ERRNO
-	cmpl	0,r3,r10
-	blt	60f
-	neg	r3,r3
-	cmpi	0,r3,ERESTARTNOHAND
-	bne	52f
-	li	r3,EINTR
-52:	lwz	r10,_CCR(r1)	/* Set SO bit in CR */
-	oris	r10,r10,0x1000
-	stw	r10,_CCR(r1)
-60:	stw	r3,GPR3(r1)	/* Update return value */
-	bl	syscall_trace
-	b	int_return
-66:	li	r3,ENOSYS
-	b	52b
-#ifdef SHOW_SYSCALLS
-7:	.string	"syscall %d(%x, %x, %x, %x, %x, "
-77:	.string	"%x, %x), current=%p\n"
-79:	.string	" -> %x\n"
-	.align	2
-#endif
-
-/*
- * This routine switches between two different tasks.  The process
- * state of one is saved on its kernel stack.  Then the state
- * of the other is restored from its kernel stack.  The memory
- * management hardware is updated to the second process's state.
- * Finally, we can return to the second process, via int_return.
- * On entry, r3 points to the TSS for the current task, r4
- * points to the TSS for the new task, and r5 contains the
- * MMU context number for the new task.
- *
- * Note: there are two ways to get to the "going out" portion
- * of this code; either by coming in via the entry (_switch)
- * or via "fork" which must set up an environment equivalent
- * to the "_switch" path.  If you change this (or in particular, the
- * SAVE_REGS macro), you'll have to change the fork code also.
- *
- * The code which creates the new task context is in 'copy_thread'
- * in arch/ppc/kernel/process.c
- *
- * The MPC8xx has something that currently happens "automagically."
- * Unshared user space address translations are subject to ASID (context)
- * match.  During each task switch, the ASID is incremented.  We can
- * guarantee (I hope :-) that no entries currently match this ASID
- * because every task will cause at least a TLB entry to be loaded for
- * the first instruction and data access, plus the kernel running will
- * have displaced several more TLBs.  The MMU contains 32 entries for
- * each TLB, and there are 16 contexts, so we just need to make sure
- * two pages get replaced for every context switch, which currently
- * happens.  There are other TLB management techniques that I will
- * eventually implement, but this is the easiest for now.  -- Dan
- */	
-_GLOBAL(_switch)
-	stwu	r1,-INT_FRAME_SIZE-STACK_UNDERHEAD(r1)
-	stw	r0,GPR0(r1)
-	lwz	r0,0(r1)
-	stw	r0,GPR1(r1)
-	/* r3-r13 are caller saved -- Cort */
-	SAVE_GPR(2, r1)
-	SAVE_8GPRS(14, r1)
-	SAVE_10GPRS(22, r1)
-	mflr	r20		/* Return to switch caller */
-	mfmsr	r22
-	li	r0,MSR_FP	/* Disable floating-point */
-	andc	r22,r22,r0
-	stw	r20,_NIP(r1)
-	stw	r22,_MSR(r1)
-	stw	r20,_LINK(r1)
-	mfcr	r20
-	mfctr	r22
-	mfspr	r23,XER
-	stw	r20,_CCR(r1)
-	stw	r22,_CTR(r1)
-	stw	r23,_XER(r1)
-	li	r0,0x0ff0
-	stw	r0,TRAP(r1)
-	stw	r1,KSP(r3)	/* Set old stack pointer */
-	sync
-	tophys(r0,r4,r3)
-	mtspr	SPRG3,r0	/* Update current TSS phys addr */
-	SYNC
-	lwz	r1,KSP(r4)	/* Load new stack pointer */
-	/* save the old current 'last' for return value */
-	mr	r3,r2
-	addi	r2,r4,-TSS	/* Update current */
-#ifndef CONFIG_8xx
-	/* Set up segment registers for new task */
-	rlwinm	r5,r5,4,8,27	/* VSID = context << 4 */
-	addis	r5,r5,0x6000	/* Set Ks, Ku bits */
-	li	r0,12		/* TASK_SIZE / SEGMENT_SIZE */
-	mtctr	r0
-	li	r9,0
-3:	mtsrin	r5,r9
-	addi	r5,r5,1		/* next VSID */
-	addis	r9,r9,0x1000	/* address of next segment */
-	bdnz	3b
-#else
-/* On the MPC8xx, we place the physical address of the new task
- * page directory loaded into the MMU base register, and set the
- * ASID compare register with the new "context".
- */
-        lwz     r9,MM-TSS(r4)           /* Get virtual address of mm */
-        lwz     r9,PGD(r9)              /* get new->mm->pgd */
-        addis   r9,r9,-KERNELBASE@h     /* convert to phys addr */
-        mtspr   M_TWB, r9               /* Update MMU base address */
-        mtspr   M_CASID, r5             /* Update context */
-        tlbia
-#endif
-	SYNC
-2:	lwz	r9,_MSR(r1)	/* Returning to user mode? */
-	andi.	r9,r9,MSR_PR
-	beq+	10f		/* if not, don't adjust kernel stack */
-8:	addi	r4,r1,INT_FRAME_SIZE+STACK_UNDERHEAD	/* size of frame */
-	stw	r4,TSS+KSP(r2)	/* save kernel stack pointer */
-	tophys(r9,r1,r9)
-	mtspr	SPRG2,r9	/* phys exception stack pointer */
-10:	lwz	r2,_CTR(r1)
-	lwz	r0,_LINK(r1)
-	mtctr	r2
-	mtlr	r0
-	lwz	r2,_XER(r1)
-	lwz	r0,_CCR(r1)
-	mtspr	XER,r2
-	mtcrf	0xFF,r0
-	/* r3-r13 are destroyed -- Cort */
-	REST_GPR(14, r1)
-	REST_8GPRS(15, r1)
-	REST_8GPRS(23, r1)
-	REST_GPR(31, r1)
-	lwz	r2,_NIP(r1)	/* Restore environment */
-	lwz	r0,_MSR(r1)
-	mtspr	SRR0,r2
-	mtspr	SRR1,r0
-	lwz	r0,GPR0(r1)
-	lwz	r2,GPR2(r1)
-	lwz	r1,GPR1(r1)
-	SYNC
-	rfi
-
-/*
- * Trap exit.
- */
-#ifdef __SMP__	
-	.globl	ret_from_smpfork
-ret_from_smpfork:
-	bl	schedule_tail
-#endif	
-	.globl	ret_from_syscall
-ret_from_syscall:	
-	.globl	int_return
-int_return:
-0:	mfmsr	r30		/* Disable interrupts */
-	li	r4,0
-	ori	r4,r4,MSR_EE
-	andc	r30,r30,r4
-	SYNC			/* Some chip revs need this... */
-	mtmsr	r30
-	SYNC
-	lwz	r5,_MSR(r1)
-	and.	r5,r5,r4
-	beq	2f
-3:	lis	r4,ppc_n_lost_interrupts@ha
-	lwz	r4,ppc_n_lost_interrupts@l(r4)
-	cmpi	0,r4,0
-	beq+	1f
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	do_IRQ
-	.globl	lost_irq_ret
-lost_irq_ret:
-	b	3b
-1:	lis	r4,bh_mask@ha
-	lwz	r4,bh_mask@l(r4)
-	lis	r5,bh_active@ha
-	lwz	r5,bh_active@l(r5)
-	and.	r4,r4,r5
-	beq+	2f
-	bl	do_bottom_half
-	.globl	do_bottom_half_ret
-do_bottom_half_ret:
-	SYNC
-	mtmsr	r30		/* disable interrupts again */
-	SYNC
-2:	lwz	r3,_MSR(r1)	/* Returning to user mode? */
-	andi.	r3,r3,MSR_PR
-	beq+	10f		/* if so, check need_resched and signals */
-	lwz	r3,NEED_RESCHED(r2)
-	cmpi	0,r3,0		/* check need_resched flag */
-	beq+	7f
-	bl	schedule
-	b	0b
-7:	lwz	r5,SIGPENDING(r2) /* Check for pending unblocked signals */
-	cmpwi	0,r5,0
-	beq+	8f
-	li	r3,0
-	addi	r4,r1,STACK_FRAME_OVERHEAD
-	bl	do_signal
-	.globl	do_signal_ret
-do_signal_ret:
-	b	0b
-8:	addi	r4,r1,INT_FRAME_SIZE+STACK_UNDERHEAD	/* size of frame */
-	stw	r4,TSS+KSP(r2)	/* save kernel stack pointer */
-	tophys(r3,r1,r3)
-	mtspr	SPRG2,r3	/* phys exception stack pointer */
-10:	lwz	r2,_CTR(r1)
-	lwz	r0,_LINK(r1)
-	mtctr	r2
-	mtlr	r0
-	lwz	r2,_XER(r1)
-	lwz	r0,_CCR(r1)
-	mtspr	XER,r2
-	mtcrf	0xFF,r0
-	REST_10GPRS(3, r1)
-	REST_10GPRS(13, r1)
-	REST_8GPRS(23, r1)
-	REST_GPR(31, r1)
-	lwz	r2,_NIP(r1)	/* Restore environment */
-	lwz	r0,_MSR(r1)
-	mtspr	SRR0,r2
-	mtspr	SRR1,r0
-	lwz	r0,GPR0(r1)
-	lwz	r2,GPR2(r1)
-	lwz	r1,GPR1(r1)
-	SYNC
-	rfi
-
-/*
- * Fake an interrupt from kernel mode.
- * This is used when enable_irq loses an interrupt.
- * We only fill in the stack frame minimally.
- */
-_GLOBAL(fake_interrupt)
-	mflr	r0
-	stw	r0,4(r1)
-	stwu	r1,-INT_FRAME_SIZE-STACK_UNDERHEAD(r1)
-	stw	r0,_NIP(r1)
-	stw	r0,_LINK(r1)
-	mfmsr	r3
-	stw	r3,_MSR(r1)
-	li	r0,0x0fac
-	stw	r0,TRAP(r1)
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	li	r4,1
-	bl	do_IRQ
-	addi	r1,r1,INT_FRAME_SIZE+STACK_UNDERHEAD
-	lwz	r0,4(r1)
-	mtlr	r0
-	blr
-
-/*
  * Set up the segment registers for a new context.
  */
 _GLOBAL(set_context)
@@ -2336,349 +1208,6 @@
 	SYNC
 	blr
 
-/*
- * Flush instruction cache.
- * This is a no-op on the 601.
- */
-_GLOBAL(flush_instruction_cache)
-	mfspr	r3,PVR
-	rlwinm	r3,r3,16,16,31
-	cmpi	0,r3,1
-	beqlr			/* for 601, do nothing */
-	/* 603/604 processor - use invalidate-all bit in HID0 */
-	mfspr	r3,HID0
-	ori	r3,r3,HID0_ICFI
-	mtspr	HID0,r3
-	SYNC
-	blr
-
-/*
- * Write any modified data cache blocks out to memory
- * and invalidate the corresponding instruction cache blocks.
- * This is a no-op on the 601.
- *
- * flush_icache_range(unsigned long start, unsigned long stop)
- */
-_GLOBAL(flush_icache_range)
-	mfspr	r5,PVR
-	rlwinm	r5,r5,16,16,31
-	cmpi	0,r5,1
-	beqlr				/* for 601, do nothing */
-	li	r5,CACHE_LINE_SIZE-1
-	andc	r3,r3,r5
-	subf	r4,r3,r4
-	add	r4,r4,r5
-	srwi.	r4,r4,LG_CACHE_LINE_SIZE
-	beqlr
-	mtctr	r4
-	mr	r6,r3
-1:	dcbst	0,r3
-	addi	r3,r3,CACHE_LINE_SIZE
-	bdnz	1b
-	sync				/* wait for dcbst's to get to ram */
-	mtctr	r4
-2:	icbi	0,r6
-	addi	r6,r6,CACHE_LINE_SIZE
-	bdnz	2b
-	sync
-	isync
-	blr
-
-/*
- * Like above, but only do the D-cache.  This is used by the 8xx
- * to push the cache so the CPM doesn't get stale data.
- *
- * flush_dcache_range(unsigned long start, unsigned long stop)
- */
-_GLOBAL(flush_dcache_range)
-       li      r5,CACHE_LINE_SIZE-1
-       andc    r3,r3,r5
-       subf    r4,r3,r4
-       add     r4,r4,r5
-       srwi.   r4,r4,LG_CACHE_LINE_SIZE
-       beqlr
-       mtctr   r4
-
-1:     dcbst   0,r3
-       addi    r3,r3,CACHE_LINE_SIZE
-       bdnz    1b
-       sync                            /* wait for dcbst's to get to ram */
-       blr
-
-/*
- * Flush a particular page from the DATA cache
- * Note: this is necessary because the instruction cache does *not*
- * snoop from the data cache.
- * This is a no-op on the 601 which has a unified cache.
- *
- *	void flush_page_to_ram(void *page)
- */
-_GLOBAL(flush_page_to_ram)
-	mfspr	r5,PVR
-	rlwinm	r5,r5,16,16,31
-	cmpi	0,r5,1
-	beqlr				/* for 601, do nothing */
-	li	r4,0x0FFF
-	andc	r3,r3,r4		/* Get page base address */
-	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */
-	mtctr	r4
-	mr	r6,r3
-0:	dcbst	0,r3			/* Write line to ram */
-	addi	r3,r3,CACHE_LINE_SIZE
-	bdnz	0b
-	sync
-	mtctr	r4
-1:	icbi	0,r6
-	addi	r6,r6,CACHE_LINE_SIZE
-	bdnz	1b
-	sync
-	isync
-	blr
-
-/*
- * Clear a page using the dcbz instruction, which doesn't cause any
- * memory traffic (except to write out any cache lines which get
- * displaced).  This only works on cacheable memory.
- */
-_GLOBAL(clear_page)
-	li	r0,4096/CACHE_LINE_SIZE
-	mtctr	r0
-1:	dcbz	0,r3
-	addi	r3,r3,CACHE_LINE_SIZE
-	bdnz	1b
-	blr
-
-/*
- * Flush entries from the hash table with VSIDs in the range
- * given.
- */
-#ifndef CONFIG_8xx	
-_GLOBAL(flush_hash_segments)
-	lis	r5,Hash@ha
-	lwz	r5,Hash@l(r5)		/* base of hash table */
-#ifdef NO_RELOAD_HTAB
-	cmpwi	0,r5,0
-	bne+	99f
-	tlbia
-	sync
-#ifdef __SMP__
-	tlbsync
-	sync
-#endif
-	blr
-99:
-#endif /* NO_RELOAD_HTAB */
-#ifdef __SMP__
-	/* Note - we had better not do anything which could generate
-	   a hash table miss while we have the hash table locked,
-	   or we'll get a deadlock.  -paulus */
-	mfmsr	r10
-	sync
-	rlwinm	r0,r10,0,17,15	/* clear bit 16 (MSR_EE) */
-	mtmsr	r0
-	SYNC
-	lis	r9,hash_table_lock@h
-	ori	r9,r9,hash_table_lock@l
-	lwz	r8,PROCESSOR(r2)
-	oris	r8,r8,8
-10:	lwarx	r6,0,r9
-	cmpi	0,r6,0
-	bne-	10b
-	stwcx.	r8,0,r9
-	bne-	10b
-	eieio
-#endif
-	rlwinm	r3,r3,7,1,24		/* put VSID lower limit in position */
-	oris	r3,r3,0x8000		/* set V bit */
-	rlwinm	r4,r4,7,1,24		/* put VSID upper limit in position */
-	oris	r4,r4,0x8000
-	ori	r4,r4,0x7f
-	lis	r6,Hash_size@ha
-	lwz	r6,Hash_size@l(r6)	/* size in bytes */
-	srwi	r6,r6,3			/* # PTEs */
-	mtctr	r6
-	addi	r5,r5,-8
-	li	r0,0
-1:	lwzu	r6,8(r5)		/* get next tag word */
-	cmplw	0,r6,r3
-	cmplw	1,r6,r4
-	cror	0,0,5			/* set cr0.lt if out of range */
-	blt	2f			/* branch if out of range */
-	stw	r0,0(r5)		/* invalidate entry */
-2:	bdnz	1b			/* continue with loop */
-	sync
-	tlbia
-	sync
-#ifdef __SMP__
-	tlbsync
-	sync
-	lis	r3,hash_table_lock@ha
-	stw	r0,hash_table_lock@l(r3)
-	mtmsr	r10
-	SYNC
-#endif
-	blr
-
-/*
- * Flush the entry for a particular page from the hash table.
- *
- * flush_hash_page(unsigned context, unsigned long va)
- */
-_GLOBAL(flush_hash_page)
-	lis	r6,Hash@ha
-	lwz	r6,Hash@l(r6)		/* hash table base */
-#ifdef NO_RELOAD_HTAB
-	cmpwi	0,r6,0			/* hash table in use? */
-	bne+	99f
-	tlbie	r4			/* in hw tlb too */
-	sync
-#ifdef __SMP__
-	tlbsync
-	sync
-#endif
-	blr
-99:
-#endif /* NO_RELOAD_HTAB */		
-#ifdef __SMP__
-	/* Note - we had better not do anything which could generate
-	   a hash table miss while we have the hash table locked,
-	   or we'll get a deadlock.  -paulus */
-	mfmsr	r10
-	sync
-	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */
-	mtmsr	r0
-	SYNC
-	lis	r9,hash_table_lock@h
-	ori	r9,r9,hash_table_lock@l
-	lwz	r8,PROCESSOR(r2)
-	oris	r8,r8,9
-10:	lwarx	r7,0,r9
-	cmpi	0,r7,0
-	bne-	10b
-	stwcx.	r8,0,r9
-	bne-	10b
-	eieio
-#endif
-	rlwinm	r3,r3,11,1,20		/* put context into vsid */
-	rlwimi	r3,r4,11,21,24		/* put top 4 bits of va into vsid */
-	oris	r3,r3,0x8000		/* set V (valid) bit */
-	rlwimi	r3,r4,10,26,31		/* put in API (abbrev page index) */
-	rlwinm	r7,r4,32-6,10,25	/* get page index << 6 */
-	rlwinm	r5,r3,32-1,7,25		/* vsid << 6 */
-	xor	r7,r7,r5		/* primary hash << 6 */
-	lis	r5,Hash_mask@ha
-	lwz	r5,Hash_mask@l(r5)	/* hash mask */
-	slwi	r5,r5,6			/*  << 6 */
-	and	r7,r7,r5
-	add	r6,r6,r7		/* address of primary PTEG */
-	li	r8,8
-	mtctr	r8
-	addi	r7,r6,-8
-1:	lwzu	r0,8(r7)		/* get next PTE */
-	cmpw	0,r0,r3			/* see if tag matches */
-	bdnzf	2,1b			/* while --ctr != 0 && !cr0.eq */
-	beq	3f			/* if we found it */
-	ori	r3,r3,0x40		/* set H (alt. hash) bit */
-	xor	r6,r6,r5		/* address of secondary PTEG */
-	mtctr	r8
-	addi	r7,r6,-8
-2:	lwzu	r0,8(r7)		/* get next PTE */
-	cmpw	0,r0,r3			/* see if tag matches */
-	bdnzf	2,2b			/* while --ctr != 0 && !cr0.eq */
-	bne	4f			/* if we didn't find it */
-3:	li	r0,0
-	stw	r0,0(r7)		/* invalidate entry */
-4:	sync
-	tlbie	r4			/* in hw tlb too */
-	sync
-#ifdef __SMP__
-	tlbsync
-	sync
-	lis	r3,hash_table_lock@h
-	li	r0,0
-	stw	r0,hash_table_lock@l(r3)
-	mtmsr	r10
-	SYNC
-#endif
-	blr
-#endif /* CONFIG_8xx */
-
-/*
- * This routine is just here to keep GCC happy - sigh...
- */	
-_GLOBAL(__main)
-	blr
-
-/*
- * PROM code for specific machines follows.  Put it 
- * here so it's easy to add arch-specific sections later.
- * -- Cort
- */
-	
-#ifndef CONFIG_8xx		
-/*
- * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
- * called with the MMU off.
- */
-	.globl	enter_rtas
-enter_rtas:
-	mflr	r0
-	stw	r0,20(r1)
-	lis	r4,rtas_data@ha
-	lwz	r4,rtas_data@l(r4)
-	addis	r4,r4,-KERNELBASE@h
-	lis	r6,1f@ha	/* physical return address for rtas */
-	addi	r6,r6,1f@l
-	addis	r6,r6,-KERNELBASE@h
-	subi	r7,r1,INT_FRAME_SIZE+STACK_UNDERHEAD
-	addis	r7,r7,-KERNELBASE@h
-	lis	r8,rtas_entry@ha
-	lwz	r8,rtas_entry@l(r8)
-	addis	r5,r8,-KERNELBASE@h
-	mfmsr	r9
-	stw	r9,8(r1)
-	ori	r0,r0,MSR_EE|MSR_SE|MSR_BE
-	andc	r0,r9,r0
-	andi.	r9,r9,MSR_ME|MSR_RI
-	sync			/* disable interrupts so SRR0/1 */
-	mtmsr	r0		/* don't get trashed */
-	mtlr	r6
-	mtspr	SPRG2,r7
-	mtspr	SRR0,r8
-	mtspr	SRR1,r9
-	rfi
-1:	addis	r9,r1,-KERNELBASE@h
-	lwz	r8,20(r9)	/* get return address */
-	lwz	r9,8(r9)	/* original msr value */
-	li	r0,0
-	mtspr	SPRG2,r0
-	mtspr	SRR0,r8
-	mtspr	SRR1,r9
-	rfi			/* return to caller */
-#endif /* CONFIG_8xx */
-
-#ifdef CONFIG_8xx
-/* Jump into the system reset for the rom.
- * We first disable the MMU, and then jump to the ROM reset address.
- *
- * r3 is the board info structure, r4 is the location for starting.
- * I use this for building a small kernel that can load other kernels,
- * rather than trying to write or rely on a rom monitor that can tftp load.
- */
-       .globl  m8xx_gorom
-m8xx_gorom:
-       li      r5,MSR_KERNEL & ~(MSR_IR|MSR_DR)
-       lis     r6,2f@h
-       addis   r6,r6,-KERNELBASE@h
-       ori     r6,r6,2f@l
-       mtspr   SRR0,r6
-       mtspr   SRR1,r5
-       rfi
-2:
-       mtlr    r4
-       blr
-#endif /* CONFIG_8xx */
-	
 /*
  * We put a few things here that have to be page-aligned.
  * This stuff goes at the beginning of the data segment,
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/head_8xx.S linux/arch/ppc/kernel/head_8xx.S
--- v2.3.15/linux/arch/ppc/kernel/head_8xx.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/head_8xx.S	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,903 @@
+/*
+ *  arch/ppc/kernel/except_8xx.S
+ *
+ *  $Id: head_8xx.S,v 1.2 1999/08/23 02:53:19 paulus Exp $
+ *
+ *  PowerPC version 
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
+ *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
+ *  Low-level exception handlers and MMU support
+ *  rewritten by Paul Mackerras.
+ *    Copyright (C) 1996 Paul Mackerras.
+ *  MPC8xx modifications by Dan Malek
+ *    Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
+ *
+ *  This file contains low-level support and setup for PowerPC 8xx
+ *  embedded processors, including trap and interrupt dispatch.
+ *
+ *  This program is free software; you can redistribute 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 "ppc_asm.h"
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <linux/config.h>
+#include <asm/mmu.h>
+	
+	.text
+	.globl	_stext
+_stext:
+
+/*
+ * _start is defined this way because the XCOFF loader in the OpenFirmware
+ * on the powermac expects the entry point to be a procedure descriptor.
+ */
+	.text
+	.globl	_start
+_start:
+
+/* MPC8xx
+ * This port was done on an MBX board with an 860.  Right now I only
+ * support an ELF compressed (zImage) boot from EPPC-Bug because the
+ * code there loads up some registers before calling us:
+ *   r3: ptr to board info data
+ *   r4: initrd_start or if no initrd then 0
+ *   r5: initrd_end - unused if r4 is 0
+ *   r6: Start of command line string
+ *   r7: End of command line string
+ *
+ * I decided to use conditional compilation instead of checking PVR and
+ * adding more processor specific branches around code I don't need.
+ * Since this is an embedded processor, I also appreciate any memory
+ * savings I can get.
+ *
+ * The MPC8xx does not have any BATs, but it supports large page sizes.
+ * We first initialize the MMU to support 8M byte pages, then load one
+ * entry into each of the instruction and data TLBs to map the first
+ * 8M 1:1.  I also mapped an additional I/O space 1:1 so we can get to
+ * the "internal" processor registers before MMU_init is called.
+ *
+ * The TLB code currently contains a major hack.  Since I use the condition
+ * code register, I have to save and restore it.  I am out of registers, so
+ * I just store it in memory location 0 (the TLB handlers are not reentrant).
+ * To avoid making any decisions, I need to use the "segment" valid bit
+ * in the first level table, but that would require many changes to the
+ * Linux page directory/table functions that I don't want to do right now.
+ *
+ * I used to use SPRG2 for a temporary register in the TLB handler, but it
+ * has since been put to other uses.  I now use a hack to save a register
+ * and the CCR at memory location 0.....Someday I'll fix this.....
+ *	-- Dan
+ */
+	
+	.globl	__start
+__start:
+	mr	r31,r3			/* save parameters */
+	mr	r30,r4
+	mr	r29,r5
+	mr	r28,r6
+	mr	r27,r7
+	li	r24,0			/* cpu # */
+
+	tlbia			/* Invalidate all TLB entries */
+	li	r8, 0
+	mtspr	MI_CTR, r8	/* Set instruction control to zero */
+	lis	r8, MD_RESETVAL@h
+	mtspr	MD_CTR, r8	/* Set data TLB control */
+
+	/* Now map the lower 8 Meg into the TLBs.  For this quick hack,
+	 * we can load the instruction and data TLB registers with the
+	 * same values.
+	 */
+	lis	r8, KERNELBASE@h	/* Create vaddr for TLB */
+	ori	r8, r8, MI_EVALID	/* Mark it valid */
+	mtspr	MI_EPN, r8
+	mtspr	MD_EPN, r8
+	li	r8, MI_PS8MEG		/* Set 8M byte page */
+	ori	r8, r8, MI_SVALID	/* Make it valid */
+	mtspr	MI_TWC, r8
+	mtspr	MD_TWC, r8
+	li	r8, MI_BOOTINIT		/* Create RPN for address 0 */
+	mtspr	MI_RPN, r8		/* Store TLB entry */
+	mtspr	MD_RPN, r8
+	lis	r8, MI_Kp@h		/* Set the protection mode */
+	mtspr	MI_AP, r8
+	mtspr	MD_AP, r8
+
+/* We will get these from a configuration file as soon as I verify
+ * the extraneous bits don't cause problems in the TLB.
+ */
+#if defined(CONFIG_MBX) || defined(CONFIG_RPXLITE)
+#define BOOT_IMMR      0xfa000000
+#endif
+#ifdef CONFIG_BSEIP
+#define BOOT_IMMR      0xff000000
+#endif
+	/* Map another 8 MByte at 0xfa000000 to get the processor
+	 * internal registers (among other things).
+	 */
+	lis     r8, BOOT_IMMR@h         /* Create vaddr for TLB */
+	ori	r8, r8, MD_EVALID	/* Mark it valid */
+	mtspr	MD_EPN, r8
+	li	r8, MD_PS8MEG		/* Set 8M byte page */
+	ori	r8, r8, MD_SVALID	/* Make it valid */
+	mtspr	MD_TWC, r8
+	lis     r8, BOOT_IMMR@h         /* Create paddr for TLB */
+	ori	r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
+	mtspr	MD_RPN, r8
+
+	/* Since the cache is enabled according to the information we
+	 * just loaded into the TLB, invalidate and enable the caches here.
+	 * We should probably check/set other modes....later.
+	 */
+	lis	r8, IDC_INVALL@h
+	mtspr	IC_CST, r8
+	mtspr	DC_CST, r8
+	lis	r8, IDC_ENABLE@h
+	mtspr	IC_CST, r8
+#if 0
+	mtspr	DC_CST, r8
+#else
+	/* For a debug option, I left this here to easily enable
+	 * the write through cache mode
+	 */
+	lis	r8, DC_SFWT@h
+	mtspr	DC_CST, r8
+	lis	r8, IDC_ENABLE@h
+	mtspr	DC_CST, r8
+#endif
+
+/* We now have the lower 8 Meg mapped into TLB entries, and the caches
+ * ready to work.
+ */
+
+turn_on_mmu:
+	mfmsr	r0
+	ori	r0,r0,MSR_DR|MSR_IR
+	mtspr	SRR1,r0
+	lis	r0,start_here@h
+	ori	r0,r0,start_here@l
+	mtspr	SRR0,r0
+	SYNC
+	rfi				/* enables MMU */
+
+/*
+ * Exception entry code.  This code runs with address translation
+ * turned off, i.e. using physical addresses.
+ * We assume sprg3 has the physical address of the current
+ * task's thread_struct.
+ */
+#define EXCEPTION_PROLOG	\
+	mtspr	SPRG0,r20;	\
+	mtspr	SPRG1,r21;	\
+	mfcr	r20;		\
+	mfspr	r21,SPRG2;		/* exception stack to use from */ \
+	cmpwi	0,r21,0;		/* user mode or RTAS */ \
+	bne	1f;		\
+	tophys(r21,r1);			/* use tophys(kernel sp) otherwise */ \
+	subi	r21,r21,INT_FRAME_SIZE;	/* alloc exc. frame */\
+1:	stw	r20,_CCR(r21);		/* save registers */ \
+	stw	r22,GPR22(r21);	\
+	stw	r23,GPR23(r21);	\
+	mfspr	r20,SPRG0;	\
+	stw	r20,GPR20(r21);	\
+	mfspr	r22,SPRG1;	\
+	stw	r22,GPR21(r21);	\
+	mflr	r20;		\
+	stw	r20,_LINK(r21);	\
+	mfctr	r22;		\
+	stw	r22,_CTR(r21);	\
+	mfspr	r20,XER;	\
+	stw	r20,_XER(r21);	\
+	mfspr	r22,SRR0;	\
+	mfspr	r23,SRR1;	\
+	stw	r0,GPR0(r21);	\
+	stw	r1,GPR1(r21);	\
+	stw	r2,GPR2(r21);	\
+	stw	r1,0(r21);	\
+	tovirt(r1,r21);			/* set new kernel sp */	\
+	SAVE_4GPRS(3, r21);
+/*
+ * Note: code which follows this uses cr0.eq (set if from kernel),
+ * r21, r22 (SRR0), and r23 (SRR1).
+ */
+
+/*
+ * Exception vectors.
+ */
+#define STD_EXCEPTION(n, label, hdlr)		\
+	. = n;					\
+label:						\
+	EXCEPTION_PROLOG;			\
+	addi	r3,r1,STACK_FRAME_OVERHEAD;	\
+	li	r20,MSR_KERNEL;			\
+	bl	transfer_to_handler; 		\
+	.long	hdlr;				\
+	.long	ret_from_except
+
+/* System reset */
+#ifdef CONFIG_SMP /* MVME/MTX start the secondary here */
+	STD_EXCEPTION(0x100, Reset, __secondary_start_psurge)
+#else
+	STD_EXCEPTION(0x100, Reset, UnknownException)
+#endif	
+
+/* Machine check */
+	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data access exception.
+ * This is "never generated" by the MPC8xx.  We jump to it for other
+ * translation errors.
+ */
+	. = 0x300
+DataAccess:
+	EXCEPTION_PROLOG
+	mfspr	r20,DSISR
+	stw	r20,_DSISR(r21)
+	mr	r5,r20
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	li	r20,MSR_KERNEL
+	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
+	bl	transfer_to_handler
+	.long	do_page_fault
+	.long	ret_from_except
+
+/* Instruction access exception.
+ * This is "never generated" by the MPC8xx.  We jump to it for other
+ * translation errors.
+ */
+	. = 0x400
+InstructionAccess:
+	EXCEPTION_PROLOG
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	mr	r4,r22
+	mr	r5,r23
+	li	r20,MSR_KERNEL
+	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
+	bl	transfer_to_handler
+	.long	do_page_fault
+	.long	ret_from_except
+
+/* External interrupt */
+	. = 0x500;
+HardwareInterrupt:
+	EXCEPTION_PROLOG;
+#ifdef CONFIG_APUS
+	/* This is horrible, but there's no way around it. Enable the
+	data cache so the IRQ hardware register can be accessed
+	without cache intervention. Then disable interrupts and get
+	the current emulated m68k IPL value. */
+	
+	mfmsr	20
+	xori	r20,r20,MSR_DR
+	sync
+	mtmsr	r20
+	sync
+
+	lis	r3,APUS_IPL_EMU@h
+
+	li	r20,(IPLEMU_SETRESET|IPLEMU_DISABLEINT)
+	stb	r20,APUS_IPL_EMU@l(r3)
+	eieio
+
+	lbz	r3,APUS_IPL_EMU@l(r3)
+
+	mfmsr	r20
+	xori	r20,r20,MSR_DR
+	sync
+	mtmsr	r20
+	sync
+
+	stw	r3,(_CCR+4)(r21);
+#endif
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	li	r20,MSR_KERNEL
+	li	r4,0
+	bl	transfer_to_handler
+	.long	do_IRQ;
+	.long	ret_from_except
+	
+
+/* Alignment exception */
+	. = 0x600
+Alignment:
+	EXCEPTION_PROLOG
+	mfspr	r4,DAR
+	stw	r4,_DAR(r21)
+	mfspr	r5,DSISR
+	stw	r5,_DSISR(r21)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	li	r20,MSR_KERNEL
+	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
+	bl	transfer_to_handler
+	.long	AlignmentException
+	.long	ret_from_except
+
+/* Program check exception */
+	. = 0x700
+ProgramCheck:
+	EXCEPTION_PROLOG
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	li	r20,MSR_KERNEL
+	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
+	bl	transfer_to_handler
+	.long	ProgramCheckException
+	.long	ret_from_except
+
+/* No FPU on MPC8xx.  This exception is not supposed to happen.
+*/
+	STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+	STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+
+/* System call */
+	. = 0xc00
+SystemCall:
+	EXCEPTION_PROLOG
+	stw	r3,ORIG_GPR3(r21)
+	li	r20,MSR_KERNEL
+	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
+	bl	transfer_to_handler
+	.long	DoSyscall
+	.long	ret_from_except
+
+/* Single step - not used on 601 */
+	STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
+
+	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+	STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+/* On the MPC8xx, this is a software emulation interrupt.  It occurs
+ * for all unimplemented and illegal instructions.
+ */
+	STD_EXCEPTION(0x1000, SoftEmu, SoftwareEmulation)
+
+	. = 0x1100
+/*
+ * For the MPC8xx, this is a software tablewalk to load the instruction
+ * TLB.  It is modelled after the example in the Motorola manual.  The task
+ * switch loads the M_TWB register with the pointer to the first level table.
+ * If we discover there is no second level table (the value is zero), the
+ * plan was to load that into the TLB, which causes another fault into the
+ * TLB Error interrupt where we can handle such problems.  However, that did
+ * not work, so if we discover there is no second level table, we restore
+ * registers and branch to the error exception.  We have to use the MD_xxx
+ * registers for the tablewalk because the equivalent MI_xxx registers
+ * only perform the attribute functions.
+ */
+InstructionTLBMiss:
+	mtspr	M_TW, r20	/* Save a couple of working registers */
+	mfcr	r20
+	stw	r20, 0(r0)
+	stw	r21, 4(r0)
+	mfspr	r20, SRR0	/* Get effective address of fault */
+	mtspr	MD_EPN, r20	/* Have to use MD_EPN for walk, MI_EPN can't */
+	mfspr	r20, M_TWB	/* Get level 1 table entry address */
+	lwz	r21, 0(r20)	/* Get the level 1 entry */
+	rlwinm.	r20, r21,0,0,20	/* Extract page descriptor page address */
+	beq	2f		/* If zero, don't try to find a pte */
+
+	/* We have a pte table, so load the MI_TWC with the attributes
+	 * for this page, which has only bit 31 set.
+	 */
+	tophys(r21,r21)
+	ori	r21,r21,1		/* Set valid bit */
+	mtspr	MI_TWC, r21	/* Set page attributes */
+	mtspr	MD_TWC, r21	/* Load pte table base address */
+	mfspr	r21, MD_TWC	/* ....and get the pte address */
+	lwz	r21, 0(r21)	/* Get the pte */
+
+	/* Set four subpage valid bits (24, 25, 26, and 27).
+	 * Since we currently run MI_CTR.PPCS = 0, the manual says,
+	 *	"If the page size is larger than 4k byte, then all the
+	 *	 4 bits should have the same value."
+	 * I don't really know what to do if the page size is 4k Bytes,
+	 * but I know setting them all to 0 does not work, and setting them
+	 * all to 1 does, so that is the way it is right now.
+	 * BTW, these four bits map to the software only bits in the
+	 * linux page table.  I used to turn them all of, but now just
+	 * set them all for the hardware.
+	li	r20, 0x00f0
+	andc	r20, r21, r20
+	ori	r20, r20, 0x0080
+	 */
+	ori	r20, r21, 0x00f0
+
+	mtspr	MI_RPN, r20	/* Update TLB entry */
+
+	mfspr	r20, M_TW	/* Restore registers */
+	lwz	r21, 0(r0)
+	mtcr	r21
+	lwz	r21, 4(r0)
+	rfi
+
+2:	mfspr	r20, M_TW	/* Restore registers */
+	lwz	r21, 0(r0)
+	mtcr	r21
+	lwz	r21, 4(r0)
+	b	InstructionAccess
+
+	. = 0x1200
+DataStoreTLBMiss:
+	mtspr	M_TW, r20	/* Save a couple of working registers */
+	mfcr	r20
+	stw	r20, 0(r0)
+	stw	r21, 4(r0)
+	mfspr	r20, M_TWB	/* Get level 1 table entry address */
+	lwz	r21, 0(r20)	/* Get the level 1 entry */
+	rlwinm.	r20, r21,0,0,20	/* Extract page descriptor page address */
+	beq	2f		/* If zero, don't try to find a pte */
+
+	/* We have a pte table, so load fetch the pte from the table.
+	 */
+	tophys(r21, r21)
+	ori	r21, r21, 1	/* Set valid bit in physical L2 page */
+	mtspr	MD_TWC, r21	/* Load pte table base address */
+	mfspr	r21, MD_TWC	/* ....and get the pte address */
+	lwz	r21, 0(r21)	/* Get the pte */
+
+	/* Set four subpage valid bits (24, 25, 26, and 27).
+	 * Since we currently run MD_CTR.PPCS = 0, the manual says,
+	 *	"If the page size is larger than 4k byte, then all the
+	 *	 4 bits should have the same value."
+	 * I don't really know what to do if the page size is 4k Bytes,
+	 * but I know setting them all to 0 does not work, and setting them
+	 * all to 1 does, so that is the way it is right now.
+	 * BTW, these four bits map to the software only bits in the
+	 * linux page table.  I used to turn them all of, but now just
+	 * set them all for the hardware.
+	li	r20, 0x00f0
+	andc	r20, r21, r20
+	ori	r20, r20, 0x0080
+	 */
+	ori	r20, r21, 0x00f0
+
+	mtspr	MD_RPN, r20	/* Update TLB entry */
+
+	mfspr	r20, M_TW	/* Restore registers */
+	lwz	r21, 0(r0)
+	mtcr	r21
+	lwz	r21, 4(r0)
+	rfi
+
+2:	mfspr	r20, M_TW	/* Restore registers */
+	lwz	r21, 0(r0)
+	mtcr	r21
+	lwz	r21, 4(r0)
+	b	DataAccess
+
+/* This is an instruction TLB error on the MPC8xx.  This could be due
+ * to many reasons, such as executing guarded memory or illegal instruction
+ * addresses.  There is nothing to do but handle a big time error fault.
+ */
+	. = 0x1300
+InstructionTLBError:
+	b	InstructionAccess
+
+/* This is the data TLB error on the MPC8xx.  This could be due to
+ * many reasons, including a dirty update to a pte.  We can catch that
+ * one here, but anything else is an error.  First, we track down the
+ * Linux pte.  If it is valid, write access is allowed, but the
+ * page dirty bit is not set, we will set it and reload the TLB.  For
+ * any other case, we bail out to a higher level function that can
+ * handle it.
+ */
+	. = 0x1400
+DataTLBError:
+	mtspr	M_TW, r20	/* Save a couple of working registers */
+	mfcr	r20
+	stw	r20, 0(r0)
+	stw	r21, 4(r0)
+
+	/* First, make sure this was a store operation.
+	*/
+	mfspr	r20, DSISR
+	andis.	r21, r20, 0x0200	/* If set, indicates store op */
+	beq	2f
+
+	mfspr	r20, M_TWB	/* Get level 1 table entry address */
+	lwz	r21, 0(r20)	/* Get the level 1 entry */
+	rlwinm.	r20, r21,0,0,20	/* Extract page descriptor page address */
+	beq	2f		/* If zero, bail */
+
+	/* We have a pte table, so fetch the pte from the table.
+	 */
+	tophys(r21, r21)
+	ori	r21, r21, 1		/* Set valid bit in physical L2 page */
+	mtspr	MD_TWC, r21		/* Load pte table base address */
+	mfspr	r21, MD_TWC		/* ....and get the pte address */
+	lwz	r21, 0(r21)		/* Get the pte */
+
+	andi.	r20, r21, _PAGE_RW	/* Is it writeable? */
+	beq	2f			/* Bail out if not */
+
+	ori	r21, r21, _PAGE_DIRTY	/* Update changed bit */
+	mfspr	r20, MD_TWC		/* Get pte address again */
+	stw	r21, 0(r20)		/* and update pte in table */
+
+	/* Set four subpage valid bits (24, 25, 26, and 27).
+	 * Since we currently run MD_CTR.PPCS = 0, the manual says,
+	 *	"If the page size is larger than 4k byte, then all the
+	 *	 4 bits should have the same value."
+	 * I don't really know what to do if the page size is 4k Bytes,
+	 * but I know setting them all to 0 does not work, and setting them
+	 * all to 1 does, so that is the way it is right now.
+	 * BTW, these four bits map to the software only bits in the
+	 * linux page table.  I used to turn them all of, but now just
+	 * set them all for the hardware.
+	li	r20, 0x00f0
+	andc	r20, r21, r20
+	ori	r20, r20, 0x0080
+	 */
+	ori	r20, r21, 0x00f0
+
+	mtspr	MD_RPN, r20	/* Update TLB entry */
+
+	mfspr	r20, M_TW	/* Restore registers */
+	lwz	r21, 0(r0)
+	mtcr	r21
+	lwz	r21, 4(r0)
+	rfi
+2:
+	mfspr	r20, M_TW	/* Restore registers */
+	lwz	r21, 0(r0)
+	mtcr	r21
+	lwz	r21, 4(r0)
+	b	DataAccess
+#endif /* CONFIG_8xx */
+
+	STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+	STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+	STD_EXCEPTION(0x1700, Trap_17, TAUException)
+	STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+	STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+	STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+	STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+/* On the MPC8xx, these next four traps are used for development
+ * support of breakpoints and such.  Someday I will get around to
+ * using them.
+ */
+	STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+	STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+	STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+	STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+
+	. = 0x2000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception, turning
+ * on address translation.
+ */
+	.globl	transfer_to_handler
+transfer_to_handler:
+	stw	r22,_NIP(r21)
+	lis	r22,MSR_POW@h
+	andc	r23,r23,r22
+	stw	r23,_MSR(r21)
+	SAVE_GPR(7, r21)
+	SAVE_4GPRS(8, r21)
+	SAVE_8GPRS(12, r21)
+	SAVE_8GPRS(24, r21)
+	andi.	r23,r23,MSR_PR
+	mfspr	r23,SPRG3		/* if from user, fix up THREAD.regs */
+	beq	2f
+	addi	r24,r1,STACK_FRAME_OVERHEAD
+	stw	r24,PT_REGS(r23)
+2:	addi	r2,r23,-THREAD		/* set r2 to current */
+	tovirt(r2,r2)
+	mflr	r23
+	andi.	r24,r23,0x3f00		/* get vector offset */
+	stw	r24,TRAP(r21)
+	li	r22,RESULT
+	stwcx.	r22,r22,r21		/* to clear the reservation */
+	li	r22,0
+	stw	r22,RESULT(r21)
+	mtspr	SPRG2,r22		/* r1 is now kernel sp */
+	addi	r24,r2,TASK_STRUCT_SIZE	/* check for kernel stack overflow */
+	cmplw	0,r1,r2
+	cmplw	1,r1,r24
+	crand	1,1,4
+	bgt-	stack_ovf		/* if r2 < r1 < r2+TASK_STRUCT_SIZE */
+	lwz	r24,0(r23)		/* virtual address of handler */
+	lwz	r23,4(r23)		/* where to go when done */
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	mtlr	r23
+	SYNC
+	rfi				/* jump to handler, enable MMU */
+
+/*
+ * On kernel stack overflow, load up an initial stack pointer
+ * and call StackOverflow(regs), which should not return.
+ */
+stack_ovf:
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	lis	r1,init_task_union@ha
+	addi	r1,r1,init_task_union@l
+	addi	r1,r1,TASK_UNION_SIZE-STACK_FRAME_OVERHEAD
+	lis	r24,StackOverflow@ha
+	addi	r24,r24,StackOverflow@l
+	li	r20,MSR_KERNEL
+	mtspr	SRR0,r24
+	mtspr	SRR1,r20
+	SYNC
+	rfi
+
+	.globl	giveup_fpu
+giveup_fpu:
+	blr
+
+/*
+ * This code is jumped to from the startup code to copy
+ * the kernel image to physical address 0.
+ */
+relocate_kernel:
+	lis	r9,0x426f		/* if booted from BootX, don't */
+	addi	r9,r9,0x6f58		/* translate source addr */
+	cmpw	r31,r9			/* (we have to on chrp) */
+	beq	7f
+	rlwinm	r4,r4,0,8,31		/* translate source address */
+	add	r4,r4,r3		/* to region mapped with BATs */
+7:	addis	r9,r26,klimit@ha	/* fetch klimit */
+	lwz	r25,klimit@l(r9)
+	addis	r25,r25,-KERNELBASE@h
+	li	r6,0			/* Destination offset */
+	li	r5,0x4000		/* # bytes of memory to copy */
+	bl	copy_and_flush		/* copy the first 0x4000 bytes */
+	addi	r0,r3,4f@l		/* jump to the address of 4f */
+	mtctr	r0			/* in copy and do the rest. */
+	bctr				/* jump to the copy */
+4:	mr	r5,r25
+	bl	copy_and_flush		/* copy the rest */
+	b	turn_on_mmu
+
+/*
+ * Copy routine used to copy the kernel to start at physical address 0
+ * and flush and invalidate the caches as needed.
+ * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
+ * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
+ */
+copy_and_flush:
+	addi	r5,r5,-4
+	addi	r6,r6,-4
+4:	li	r0,8
+	mtctr	r0
+3:	addi	r6,r6,4			/* copy a cache line */
+	lwzx	r0,r6,r4
+	stwx	r0,r6,r3
+	bdnz	3b
+	dcbst	r6,r3			/* write it to memory */
+	sync
+	icbi	r6,r3			/* flush the icache line */
+	cmplw	0,r6,r5
+	blt	4b
+	isync
+	addi	r5,r5,4
+	addi	r6,r6,4
+	blr
+
+#ifdef CONFIG_SMP
+	.globl	__secondary_start_psurge
+__secondary_start_psurge:
+	li	r24,1			/* cpu # */
+	b	__secondary_start
+
+	.globl	__secondary_hold
+__secondary_hold:
+	/* tell the master we're here */
+	lis	r5,0x4@h
+	ori	r5,r5,0x4@l
+	stw	r3,0(r5)
+	dcbf	0,r5
+100:
+	lis	r5,0
+	dcbi	0,r5
+	lwz	r4,0(r5)
+	/* wait until we're told to start */
+	cmp	0,r4,r3
+	bne	100b
+	/* our cpu # was at addr 0 - go */
+	lis	r5,__secondary_start@h
+	ori	r5,r5,__secondary_start@l
+	tophys(r5,r5)
+	mtlr	r5
+	mr	r24,r3			/* cpu # */
+	blr
+#endif /* CONFIG_SMP */
+	
+/*
+ * This is where the main kernel code starts.
+ */
+start_here:
+#ifdef __SMP__
+	/* if we're the second cpu stack and r2 are different
+	* and we want to not clear the bss -- Cort */
+	lis	r5,first_cpu_booted@h
+	ori	r5,r5,first_cpu_booted@l
+	lwz	r5,0(r5)
+	cmpi	0,r5,0
+	beq	99f
+
+	/* get current */
+	lis	r2,current_set@h
+	ori	r2,r2,current_set@l
+	slwi	r24,r24,2			/* cpu # to current_set[cpu#] */
+	add	r2,r2,r24
+	lwz	r2,0(r2)
+	b	10f
+99:	
+#endif /* __SMP__ */
+	/* ptr to current */
+	lis	r2,init_task_union@h
+	ori	r2,r2,init_task_union@l
+	/* Clear out the BSS */
+	lis	r11,_end@ha
+	addi	r11,r11,_end@l
+	lis	r8,__bss_start@ha
+	addi	r8,r8,__bss_start@l
+	subf	r11,r8,r11
+	addi	r11,r11,3
+	rlwinm.	r11,r11,30,2,31
+	beq	2f
+	addi	r8,r8,-4
+	mtctr	r11
+	li	r0,0
+3:	stwu	r0,4(r8)
+	bdnz	3b
+2:
+#ifdef __SMP__	
+10:
+#endif /* __SMP__ */
+	/* stack */
+	addi	r1,r2,TASK_UNION_SIZE
+	li	r0,0
+	stwu	r0,-STACK_FRAME_OVERHEAD(r1)
+/*
+ * Decide what sort of machine this is and initialize the MMU.
+ */
+	mr	r3,r31
+	mr	r4,r30
+	mr	r5,r29
+	mr	r6,r28
+	mr	r7,r27
+	bl	identify_machine
+	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.
+ */
+	/* The right way to do this would be to track it down through
+	 * init's THREAD like the context switch code does, but this is
+	 * easier......until someone changes init's static structures.
+	 */
+	lis	r6, swapper_pg_dir@h
+	tophys(r6,r6)
+	ori	r6, r6, swapper_pg_dir@l
+	mtspr	M_TWB, r6
+	lis	r4,2f@h
+	ori	r4,r4,2f@l
+	tophys(r4,r4)
+	li	r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
+	mtspr	SRR0,r4
+	mtspr	SRR1,r3
+	rfi
+/* Load up the kernel context */
+2:
+	SYNC			/* Force all PTE updates to finish */
+	tlbia			/* Clear all TLB entries */
+	sync			/* wait for tlbia/tlbie to finish */
+#ifdef __SMP__
+	tlbsync			/* ... on all CPUs */
+	sync
+#endif
+/* Set up for using our exception vectors */
+	/* ptr to phys current thread */
+	tophys(r4,r2)
+	addi	r4,r4,THREAD	/* init task's THREAD */
+	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
+	ori	r3,r3,start_kernel@l
+#ifdef __SMP__
+	/* the second time through here we go to
+	 * start_secondary(). -- Cort
+	 */
+	lis	r5,first_cpu_booted@h
+	ori	r5,r5,first_cpu_booted@l
+	tophys(r5,r5)
+	lwz	r5,0(r5)
+	cmpi	0,r5,0
+	beq	10f
+	lis	r3,start_secondary@h
+	ori	r3,r3,start_secondary@l
+10:	
+#endif /* __SMP__ */
+	mtspr	SRR0,r3
+	mtspr	SRR1,r4
+	rfi			/* enable MMU and jump to start_kernel */
+
+/*
+ * Set up to use a given MMU context.
+ *
+ * The MPC8xx has something that currently happens "automagically."
+ * Unshared user space address translations are subject to ASID (context)
+ * match.  During each task switch, the ASID is incremented.  We can
+ * guarantee (I hope :-) that no entries currently match this ASID
+ * because every task will cause at least a TLB entry to be loaded for
+ * the first instruction and data access, plus the kernel running will
+ * have displaced several more TLBs.  The MMU contains 32 entries for
+ * each TLB, and there are 16 contexts, so we just need to make sure
+ * two pages get replaced for every context switch, which currently
+ * happens.  There are other TLB management techniques that I will
+ * eventually implement, but this is the easiest for now.  -- Dan
+ *
+ * On the MPC8xx, we place the physical address of the new task
+ * page directory loaded into the MMU base register, and set the
+ * ASID compare register with the new "context".
+ */
+_GLOBAL(set_context)
+        mtspr   M_CASID,r3		/* Update context */
+        tlbia
+	SYNC
+	blr
+
+/* Jump into the system reset for the rom.
+ * We first disable the MMU, and then jump to the ROM reset address.
+ *
+ * r3 is the board info structure, r4 is the location for starting.
+ * I use this for building a small kernel that can load other kernels,
+ * rather than trying to write or rely on a rom monitor that can tftp load.
+ */
+       .globl  m8xx_gorom
+m8xx_gorom:
+       li      r5,MSR_KERNEL & ~(MSR_IR|MSR_DR)
+       lis     r6,2f@h
+       addis   r6,r6,-KERNELBASE@h
+       ori     r6,r6,2f@l
+       mtspr   SRR0,r6
+       mtspr   SRR1,r5
+       rfi
+2:
+       mtlr    r4
+       blr
+	
+/*
+ * We put a few things here that have to be page-aligned.
+ * This stuff goes at the beginning of the data segment,
+ * which is page-aligned.
+ */
+	.data
+	.globl	sdata
+sdata:
+	.globl	empty_zero_page
+empty_zero_page:
+	.space	4096
+
+	.globl	swapper_pg_dir
+swapper_pg_dir:
+	.space	4096	
+
+/*
+ * This space gets a copy of optional info passed to us by the bootstrap
+ * Used to pass parameters into the kernel like root=/dev/sda1, etc.
+ */	
+	.globl	cmd_line
+cmd_line:
+	.space	512
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- v2.3.15/linux/arch/ppc/kernel/idle.c	Fri Jul 23 12:20:23 1999
+++ linux/arch/ppc/kernel/idle.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: idle.c,v 1.63 1999/06/10 22:55:35 geert Exp $
+ * $Id: idle.c,v 1.65 1999/08/03 19:16:19 cort Exp $
  *
  * Idle daemon for PowerPC.  Idle daemon will handle any action
  * that needs to be taken when the system becomes idle.
@@ -69,7 +69,6 @@
 	return 0;
 }
 
-#ifdef __SMP__
 /*
  * SMP entry into the idle task - calls the same thing as the
  * non-smp versions. -- Cort
@@ -78,19 +77,6 @@
 {
 	idled(unused);
 	return 0; 
-}
-#endif /* __SMP__ */
-
-/*
- * Syscall entry into the idle task. -- Cort
- */
-asmlinkage int sys_idle(void)
-{
-	if(current->pid != 0)
-		return -EPERM;
-
-	idled(NULL);
-	return 0; /* should never execute this but it makes gcc happy -- Cort */
 }
 
 /*
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.3.15/linux/arch/ppc/kernel/irq.c	Tue Jul 13 02:29:35 1999
+++ linux/arch/ppc/kernel/irq.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: irq.c,v 1.107 1999/06/17 05:39:12 paulus Exp $
+ * $Id: irq.c,v 1.108 1999/07/23 01:55:44 davem Exp $
  *
  *  arch/ppc/kernel/irq.c
  *
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/local_irq.h linux/arch/ppc/kernel/local_irq.h
--- v2.3.15/linux/arch/ppc/kernel/local_irq.h	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/local_irq.h	Tue Aug 31 11:36:43 1999
@@ -19,10 +19,6 @@
 	int irq_offset;
 };
 
-#define mask_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->disable) irq_desc[irq].ctl->disable(irq);})
-#define unmask_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->enable) irq_desc[irq].ctl->enable(irq);})
-#define mask_and_ack_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->mask_and_ack) irq_desc[irq].ctl->mask_and_ack(irq);})
-
 struct irqdesc {
 	struct irqaction *action;
 	struct hw_interrupt_type *ctl;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/mbx_pci.c linux/arch/ppc/kernel/mbx_pci.c
--- v2.3.15/linux/arch/ppc/kernel/mbx_pci.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/mbx_pci.c	Thu Aug 26 12:42:32 1999
@@ -253,16 +253,14 @@
     return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
-__initfunc(
-void
-mbx_pcibios_fixup(void))
+void __init
+mbx_pcibios_fixup(void)
 {
    /* Nothing to do here? */
 }
 
-__initfunc(
-void
-mbx_setup_pci_ptrs(void))
+void __init
+mbx_setup_pci_ptrs(void)
 {
 	set_config_access_method(mbx);
 
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/mbx_setup.c linux/arch/ppc/kernel/mbx_setup.c
--- v2.3.15/linux/arch/ppc/kernel/mbx_setup.c	Mon Jun 28 13:40:39 1999
+++ linux/arch/ppc/kernel/mbx_setup.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: mbx_setup.c,v 1.11 1999/06/28 17:59:43 cort Exp $
+ * $Id: mbx_setup.c,v 1.12 1999/08/31 06:53:56 davem Exp $
  *
  *  linux/arch/ppc/kernel/setup.c
  *
@@ -75,8 +75,8 @@
 {
 }
 
-__initfunc(void
-mbx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
+void __init
+mbx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
 	int	cpm_page;
 	extern char cmd_line[];
@@ -141,7 +141,7 @@
  * sixteen, or external oscillator divided by four.  Currently, we only
  * support the MBX, which is system clock divided by sixteen.
  */
-__initfunc(void mbx_calibrate_decr(void))
+void __init mbx_calibrate_decr(void)
 {
 	bd_t	*binfo = (bd_t *)&res;
 	int freq, fp, divisor;
@@ -182,8 +182,7 @@
 	return(0);
 }
 
-initfunc(unsigned long
-mbx_get_rtc_time(void)
+unsigned long __init mbx_get_rtc_time(void)
 {
 	/* First, unlock all of the registers we are going to modify.
 	 * To protect them from corruption during power down, registers
@@ -310,8 +309,8 @@
  * interrupts can be either edge or level triggered, but there is no
  * reason for us to change the EPPC-bug values (it would not work if we did).
  */
-__initfunc(void
-mbx_init_IRQ(void))
+void __init
+mbx_init_IRQ(void)
 {
 	int i;
 
@@ -413,9 +412,9 @@
 }
 #endif
 
-__initfunc(void
+void __init
 mbx_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	 unsigned long r6, unsigned long r7))
+	 unsigned long r6, unsigned long r7)
 {
 
 	if ( r3 )
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.3.15/linux/arch/ppc/kernel/misc.S	Wed Jul 28 10:30:10 1999
+++ linux/arch/ppc/kernel/misc.S	Tue Aug 31 11:36:43 1999
@@ -17,19 +17,17 @@
 #include <asm/unistd.h>
 #include <asm/errno.h>
 #include <asm/processor.h>
-#include "ppc_asm.tmpl"
-#include "ppc_defs.h"
+#include <asm/page.h>
+#include "ppc_asm.h"
 
 #ifndef CONFIG_8xx
-/* This instruction is not implemented on the PPC 601 or 603 */
-#define tlbia \
-	li	r4,128; \
-	mtspr	CTR,r4; \
-	li	r4,0; \
-0:	tlbie	r4; \
-	addi	r4,r4,0x1000; \
-	bdnz	0b
-#endif	
+CACHE_LINE_SIZE = 32
+LG_CACHE_LINE_SIZE = 5
+#else
+CACHE_LINE_SIZE = 16
+LG_CACHE_LINE_SIZE = 4
+#endif /* CONFIG_8xx */
+
 	.text
 
 /*
@@ -146,6 +144,117 @@
 	blr
 
 /*
+ * Flush instruction cache.
+ * This is a no-op on the 601.
+ */
+_GLOBAL(flush_instruction_cache)
+	mfspr	r3,PVR
+	rlwinm	r3,r3,16,16,31
+	cmpi	0,r3,1
+	beqlr			/* for 601, do nothing */
+	/* 603/604 processor - use invalidate-all bit in HID0 */
+	mfspr	r3,HID0
+	ori	r3,r3,HID0_ICFI
+	mtspr	HID0,r3
+	SYNC
+	blr
+
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ * This is a no-op on the 601.
+ *
+ * flush_icache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_icache_range)
+	mfspr	r5,PVR
+	rlwinm	r5,r5,16,16,31
+	cmpi	0,r5,1
+	beqlr				/* for 601, do nothing */
+	li	r5,CACHE_LINE_SIZE-1
+	andc	r3,r3,r5
+	subf	r4,r3,r4
+	add	r4,r4,r5
+	srwi.	r4,r4,LG_CACHE_LINE_SIZE
+	beqlr
+	mtctr	r4
+	mr	r6,r3
+1:	dcbst	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	sync				/* wait for dcbst's to get to ram */
+	mtctr	r4
+2:	icbi	0,r6
+	addi	r6,r6,CACHE_LINE_SIZE
+	bdnz	2b
+	sync
+	isync
+	blr
+
+/*
+ * Like above, but only do the D-cache.
+ *
+ * flush_dcache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(flush_dcache_range)
+       li      r5,CACHE_LINE_SIZE-1
+       andc    r3,r3,r5
+       subf    r4,r3,r4
+       add     r4,r4,r5
+       srwi.   r4,r4,LG_CACHE_LINE_SIZE
+       beqlr
+       mtctr   r4
+
+1:     dcbst   0,r3
+       addi    r3,r3,CACHE_LINE_SIZE
+       bdnz    1b
+       sync                            /* wait for dcbst's to get to ram */
+       blr
+
+/*
+ * Flush a particular page from the DATA cache
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ * This is a no-op on the 601 which has a unified cache.
+ *
+ *	void flush_page_to_ram(void *page)
+ */
+_GLOBAL(flush_page_to_ram)
+	mfspr	r5,PVR
+	rlwinm	r5,r5,16,16,31
+	cmpi	0,r5,1
+	beqlr				/* for 601, do nothing */
+	li	r4,0x0FFF
+	andc	r3,r3,r4		/* Get page base address */
+	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */
+	mtctr	r4
+	mr	r6,r3
+0:	dcbst	0,r3			/* Write line to ram */
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	0b
+	sync
+	mtctr	r4
+1:	icbi	0,r6
+	addi	r6,r6,CACHE_LINE_SIZE
+	bdnz	1b
+	sync
+	isync
+	blr
+
+/*
+ * Clear a page using the dcbz instruction, which doesn't cause any
+ * memory traffic (except to write out any cache lines which get
+ * displaced).  This only works on cacheable memory.
+ */
+_GLOBAL(clear_page)
+	li	r0,4096/CACHE_LINE_SIZE
+	mtctr	r0
+1:	dcbz	0,r3
+	addi	r3,r3,CACHE_LINE_SIZE
+	bdnz	1b
+	blr
+
+/*
  * Atomic [test&set] exchange
  *
  *	unsigned long xchg_u32(void *ptr, unsigned long val)
@@ -659,8 +768,8 @@
 	sc
 	cmpi	0,r3,0		/* parent or child? */
 	bnelr			/* return if parent */
-	li	r0,0		/* clear out p->tss.regs */
-	stw	r0,TSS+PT_REGS(r2)	/* since we don't have user ctx */
+	li	r0,0		/* clear out p->thread.regs */
+	stw	r0,THREAD+PT_REGS(r2)	/* since we don't have user ctx */
 	mtlr	r6              /* fn addr in lr */
 	mr	r3,r4	        /* load arg and call fn */
 	blrl
@@ -668,6 +777,12 @@
         li	r3,0
 	sc
 
+/*
+ * This routine is just here to keep GCC happy - sigh...
+ */	
+_GLOBAL(__main)
+	blr
+
 #define SYSCALL(name) \
 _GLOBAL(name) \
 	li	r0,__NR_##name; \
@@ -680,7 +795,6 @@
 
 #define __NR__exit __NR_exit
 
-SYSCALL(idle)
 SYSCALL(sync)
 SYSCALL(setsid)
 SYSCALL(write)
@@ -812,7 +926,7 @@
 	.long sys_uname
 	.long sys_iopl		/* 110 */
 	.long sys_vhangup
-	.long sys_idle
+	.long sys_ni_syscall	/* old 'idle' syscall */
 	.long sys_vm86
 	.long sys_wait4
 	.long sys_swapoff	/* 115 */
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c
--- v2.3.15/linux/arch/ppc/kernel/mk_defs.c	Mon Jun 28 13:40:39 1999
+++ linux/arch/ppc/kernel/mk_defs.c	Tue Aug 31 11:36:43 1999
@@ -35,19 +35,19 @@
 	DEFINE(COUNTER, offsetof(struct task_struct, counter));
 	DEFINE(PROCESSOR, offsetof(struct task_struct, processor));
 	DEFINE(SIGPENDING, offsetof(struct task_struct, sigpending));
-	DEFINE(TSS, offsetof(struct task_struct, tss));
+	DEFINE(THREAD, offsetof(struct task_struct, thread));
 	DEFINE(MM, offsetof(struct task_struct, mm));
+	DEFINE(ACTIVE_MM, offsetof(struct task_struct, active_mm));
 	DEFINE(TASK_STRUCT_SIZE, sizeof(struct task_struct));
 	DEFINE(KSP, offsetof(struct thread_struct, ksp));
-	DEFINE(PG_TABLES, offsetof(struct thread_struct, pg_tables));
-	DEFINE(PGD, offsetof(struct mm_struct, pgd));
+	DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
 	DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall));
 	DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
 	DEFINE(PF_TRACESYS, PF_TRACESYS);
 	DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
 	DEFINE(NEED_RESCHED, offsetof(struct task_struct, need_resched));
-	DEFINE(TSS_FPR0, offsetof(struct thread_struct, fpr[0]));
-	DEFINE(TSS_FPSCR, offsetof(struct thread_struct, fpscr));
+	DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
+	DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr));
 	/* Interrupt register frame */
 	DEFINE(TASK_UNION_SIZE, sizeof(union task_union));
 	DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
--- v2.3.15/linux/arch/ppc/kernel/open_pic.c	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/kernel/open_pic.c	Tue Aug 31 11:36:43 1999
@@ -1,11 +1,87 @@
-#include <linux/stddef.h>
-#include <linux/init.h>
+/*
+ *  arch/ppc/kernel/openpic.c -- OpenPIC Interrupt Handling
+ *
+ *  Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/signal.h>
+#include <linux/init.h>
 #include <linux/openpic.h>
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/io.h>
 #include <asm/irq.h>
-#include "open_pic.h"
-#include "i8259.h"
+#include "local_irq.h"
+
+volatile struct OpenPIC *OpenPIC = NULL;
+u_int OpenPIC_NumInitSenses __initdata = 0;
+u_char *OpenPIC_InitSenses __initdata = NULL;
+
+void chrp_mask_irq(unsigned int);
+void chrp_unmask_irq(unsigned int);
+
+static u_int NumProcessors;
+static u_int NumSources;
+
+struct hw_interrupt_type open_pic = {
+	" OpenPIC  ",
+	NULL,
+	NULL,
+	NULL,
+	openpic_enable_irq,
+	openpic_disable_irq,
+	0,
+	0
+};
+
+/*
+ *  Accesses to the current processor's registers
+ */
+#ifndef __powerpc__
+#define THIS_CPU		Private
+#define CHECK_THIS_CPU		do {} while (0)
+#else
+#define THIS_CPU		Processor[cpu]
+#define CHECK_THIS_CPU		check_arg_cpu(cpu)
+#endif
+
+#if 1
+#define check_arg_ipi(ipi) \
+    if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
+	printk("openpic.c:%d: illegal ipi %d\n", __LINE__, ipi);
+#define check_arg_timer(timer) \
+    if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
+	printk("openpic.c:%d: illegal timer %d\n", __LINE__, timer);
+#define check_arg_vec(vec) \
+    if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
+	printk("openpic.c:%d: illegal vector %d\n", __LINE__, vec);
+#define check_arg_pri(pri) \
+    if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
+	printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri);
+#define check_arg_irq(irq) \
+    if (irq < 0 || irq >= (NumSources+open_pic.irq_offset)) \
+	printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);
+#define check_arg_cpu(cpu) \
+    if (cpu < 0 || cpu >= NumProcessors) \
+	printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu);
+#else
+#define check_arg_ipi(ipi)	do {} while (0)
+#define check_arg_timer(timer)	do {} while (0)
+#define check_arg_vec(vec)	do {} while (0)
+#define check_arg_pri(pri)	do {} while (0)
+#define check_arg_irq(irq)	do {} while (0)
+#define check_arg_cpu(cpu)	do {} while (0)
+#endif
+
+static void no_action(int ir1, void *dev, struct pt_regs *regs)
+{
+}
 
 #ifdef __SMP__
 void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
@@ -14,35 +90,349 @@
 }
 #endif /* __SMP__ */
 
-void chrp_mask_and_ack_irq(unsigned int irq_nr)
+#ifdef __i386__
+static inline u_int ld_le32(volatile u_int *addr)
 {
-	if (is_8259_irq(irq_nr))
-	    i8259_pic.mask_and_ack(irq_nr);
+	return *addr;
 }
 
-static void chrp_mask_irq(unsigned int irq_nr)
+static inline void out_le32(volatile u_int *addr, u_int val)
 {
-	if (is_8259_irq(irq_nr))
-		i8259_pic.disable(irq_nr);
-	else
-		openpic_disable_irq(irq_to_openpic(irq_nr));
+	*addr = val;
+}
+#endif
+
+u_int openpic_read(volatile u_int *addr)
+{
+	u_int val;
+
+	val = ld_le32(addr);
+	return val;
+}
+
+static inline void openpic_write(volatile u_int *addr, u_int val)
+{
+	out_le32(addr, val);
+}
+
+static inline u_int openpic_readfield(volatile u_int *addr, u_int mask)
+{
+	u_int val = openpic_read(addr);
+	return val & mask;
+}
+
+inline void openpic_writefield(volatile u_int *addr, u_int mask,
+			       u_int field)
+{
+	u_int val = openpic_read(addr);
+	openpic_write(addr, (val & ~mask) | (field & mask));
+}
+
+static inline void openpic_clearfield(volatile u_int *addr, u_int mask)
+{
+	openpic_writefield(addr, mask, 0);
+}
+
+static inline void openpic_setfield(volatile u_int *addr, u_int mask)
+{
+	openpic_writefield(addr, mask, mask);
+}
+
+static void openpic_safe_writefield(volatile u_int *addr, u_int mask,
+				    u_int field)
+{
+	openpic_setfield(addr, OPENPIC_MASK);
+	/* wait until it's not in use */
+	while (openpic_read(addr) & OPENPIC_ACTIVITY);
+	openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
 }
 
-static void chrp_unmask_irq(unsigned int irq_nr)
+void __init openpic_init(int main_pic)
 {
-	if (is_8259_irq(irq_nr))
-		i8259_pic.enable(irq_nr);
+	u_int t, i;
+	u_int timerfreq;
+	const char *version;
+
+	if (!OpenPIC)
+		panic("No OpenPIC found");
+
+	if ( ppc_md.progress ) ppc_md.progress("openpic enter",0x122);
+
+	t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
+	switch (t & OPENPIC_FEATURE_VERSION_MASK) {
+	case 1:
+		version = "1.0";
+		break;
+	case 2:
+		version = "1.2";
+		break;
+	case 3:
+		version = "1.3";
+		break;
+	default:
+		version = "?";
+		break;
+	}
+	NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
+			 OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
+	NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
+		      OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
+
+	printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n", version,
+	       NumProcessors, NumSources, OpenPIC);
+	timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
+	printk("OpenPIC timer frequency is ");
+	if (timerfreq)
+		printk("%d Hz\n", timerfreq);
 	else
-		openpic_enable_irq(irq_to_openpic(irq_nr));
+		printk("not set\n");
+
+	if ( main_pic )
+	{
+		/* Initialize timer interrupts */
+		if ( ppc_md.progress ) ppc_md.progress("openpic timer",0x3ba);
+		for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
+			/* Disabled, Priority 0 */
+			openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
+			/* No processor */
+			openpic_maptimer(i, 0);
+		}
+	    
+		/* Initialize IPI interrupts */
+		if ( ppc_md.progress ) ppc_md.progress("openpic ipi",0x3bb);
+		for (i = 0; i < OPENPIC_NUM_IPI; i++) {
+			/* Disabled, Priority 0 */
+			openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
+		}
+	    
+		/* Initialize external interrupts */
+		if ( ppc_md.progress ) ppc_md.progress("openpic ext",0x3bc);
+		/* SIOint (8259 cascade) is special */
+		openpic_initirq(0, 8, open_pic.irq_offset, 1, 1);
+		openpic_mapirq(0, 1<<0);
+		for (i = 1; i < NumSources; i++) {
+			/* Enabled, Priority 8 */
+			openpic_initirq(i, 8, open_pic.irq_offset+i, 0,
+					i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
+			/* Processor 0 */
+			openpic_mapirq(i, 1<<0);
+		}
+	    
+		/* Initialize the spurious interrupt */
+		if ( ppc_md.progress ) ppc_md.progress("openpic spurious",0x3bd);
+		openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
+		if ( _machine != _MACH_gemini )
+		{
+			if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
+					"82c59 cascade", NULL))
+				printk("Unable to get OpenPIC IRQ 0 for cascade\n");
+		}
+		openpic_set_priority(0, 0);
+		openpic_disable_8259_pass_through();
+	}
+	if ( ppc_md.progress ) ppc_md.progress("openpic exit",0x222);
 }
 
-struct hw_interrupt_type open_pic = {
-	" OpenPIC  ",
-	NULL,
-	NULL,
-	NULL,
-	chrp_unmask_irq,
-	chrp_mask_irq,
-	chrp_mask_and_ack_irq,
-	0
-};
+void openpic_reset(void)
+{
+	openpic_setfield(&OpenPIC->Global.Global_Configuration0,
+			 OPENPIC_CONFIG_RESET);
+}
+
+void openpic_enable_8259_pass_through(void)
+{
+	openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
+			   OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
+}
+
+void openpic_disable_8259_pass_through(void)
+{
+	openpic_setfield(&OpenPIC->Global.Global_Configuration0,
+			 OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
+}
+
+#ifndef __i386__
+/*
+ *  Find out the current interrupt
+ */
+u_int openpic_irq(u_int cpu)
+{
+	u_int vec;
+
+	check_arg_cpu(cpu);
+	vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
+				OPENPIC_VECTOR_MASK);
+	return vec;
+}
+#endif
+
+#ifndef __powerpc__
+void openpic_eoi(void)
+#else
+void openpic_eoi(u_int cpu)
+#endif
+{
+	check_arg_cpu(cpu);
+	openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
+}
+
+
+#ifndef __powerpc__
+u_int openpic_get_priority(void)
+#else
+u_int openpic_get_priority(u_int cpu)
+#endif
+{
+	CHECK_THIS_CPU;
+	return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
+				 OPENPIC_CURRENT_TASK_PRIORITY_MASK);
+}
+
+#ifndef __powerpc__
+void openpic_set_priority(u_int pri)
+#else
+void openpic_set_priority(u_int cpu, u_int pri)
+#endif
+{
+	CHECK_THIS_CPU;
+	check_arg_pri(pri);
+	openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
+			   OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
+}
+
+/*
+ *  Get/set the spurious vector
+ */
+u_int openpic_get_spurious(void)
+{
+	return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
+				 OPENPIC_VECTOR_MASK);
+}
+
+void openpic_set_spurious(u_int vec)
+{
+	check_arg_vec(vec);
+	openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
+			   vec);
+}
+
+void openpic_init_processor(u_int cpumask)
+{
+	openpic_write(&OpenPIC->Global.Processor_Initialization, cpumask);
+}
+
+/*
+ *  Initialize an interprocessor interrupt (and disable it)
+ *
+ *  ipi: OpenPIC interprocessor interrupt number
+ *  pri: interrupt source priority
+ *  vec: the vector it will produce
+ */
+void openpic_initipi(u_int ipi, u_int pri, u_int vec)
+{
+	check_arg_timer(ipi);
+	check_arg_pri(pri);
+	check_arg_vec(vec);
+	openpic_safe_writefield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
+				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
+				(pri << OPENPIC_PRIORITY_SHIFT) | vec);
+}
+
+/*
+ *  Send an IPI to one or more CPUs
+ */
+#ifndef __powerpc__
+void openpic_cause_IPI(u_int ipi, u_int cpumask)
+#else
+void openpic_cause_IPI(u_int cpu, u_int ipi, u_int cpumask)
+#endif
+{
+	CHECK_THIS_CPU;
+	check_arg_ipi(ipi);
+	openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpumask);
+}
+
+/*
+ *  Initialize a timer interrupt (and disable it)
+ *
+ *  timer: OpenPIC timer number
+ *  pri: interrupt source priority
+ *  vec: the vector it will produce
+ */
+void openpic_inittimer(u_int timer, u_int pri, u_int vec)
+{
+	check_arg_timer(timer);
+	check_arg_pri(pri);
+	check_arg_vec(vec);
+	openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority,
+				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
+				(pri << OPENPIC_PRIORITY_SHIFT) | vec);
+}
+
+/*
+ *  Map a timer interrupt to one or more CPUs
+ */
+void openpic_maptimer(u_int timer, u_int cpumask)
+{
+	check_arg_timer(timer);
+	openpic_write(&OpenPIC->Global.Timer[timer].Destination, cpumask);
+}
+
+/*
+ *  Enable/disable an interrupt source
+ */
+void openpic_enable_irq(u_int irq)
+{
+	check_arg_irq(irq);
+	openpic_clearfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
+}
+
+void openpic_disable_irq(u_int irq)
+{
+	check_arg_irq(irq);
+	openpic_setfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
+}
+
+/*
+ *  Initialize an interrupt source (and disable it!)
+ *
+ *  irq: OpenPIC interrupt number
+ *  pri: interrupt source priority
+ *  vec: the vector it will produce
+ *  pol: polarity (1 for positive, 0 for negative)
+ *  sense: 1 for level, 0 for edge
+ */
+void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
+{
+	check_arg_irq(irq);
+	check_arg_pri(pri);
+	check_arg_vec(vec);
+	openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
+				OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
+				OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL,
+				(pri << OPENPIC_PRIORITY_SHIFT) | vec |
+				(pol ? OPENPIC_SENSE_POLARITY : 0) |
+				(sense ? OPENPIC_SENSE_LEVEL : 0));
+}
+
+/*
+ *  Map an interrupt source to one or more CPUs
+ */
+void openpic_mapirq(u_int irq, u_int cpumask)
+{
+	check_arg_irq(irq);
+	openpic_write(&OpenPIC->Source[irq].Destination, cpumask);
+}
+
+/*
+ *  Set the sense for an interrupt source (and disable it!)
+ *
+ *  sense: 1 for level, 0 for edge
+ */
+void openpic_set_sense(u_int irq, int sense)
+{
+	check_arg_irq(irq);
+	openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
+				OPENPIC_SENSE_LEVEL,
+				(sense ? OPENPIC_SENSE_LEVEL : 0));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/open_pic.h linux/arch/ppc/kernel/open_pic.h
--- v2.3.15/linux/arch/ppc/kernel/open_pic.h	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/open_pic.h	Tue Aug 31 11:36:43 1999
@@ -1,8 +1,5 @@
-
 #ifndef _PPC_KERNEL_OPEN_PIC_H
 #define _PPC_KERNEL_OPEN_PIC_H
-
-#include "local_irq.h"
 
 extern struct hw_interrupt_type open_pic;
 
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/openpic.c linux/arch/ppc/kernel/openpic.c
--- v2.3.15/linux/arch/ppc/kernel/openpic.c	Mon Jul 12 15:12:55 1999
+++ linux/arch/ppc/kernel/openpic.c	Wed Dec 31 16:00:00 1969
@@ -1,520 +0,0 @@
-/*
- *  arch/ppc/kernel/openpic.c -- OpenPIC Interrupt Handling
- *
- *  Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-
-/*
- *  Note: Interprocessor Interrupt (IPI) and Timer support is incomplete
- */
-
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/openpic.h>
-#include <asm/ptrace.h>
-#include <asm/signal.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-
-#define REGISTER_DEBUG
-#undef REGISTER_DEBUG
-
-
-volatile struct OpenPIC *OpenPIC = NULL;
-u_int OpenPIC_NumInitSenses __initdata = 0;
-u_char *OpenPIC_InitSenses __initdata = NULL;
-
-static u_int NumProcessors;
-static u_int NumSources;
-
-
-    /*
-     *  Accesses to the current processor's registers
-     */
-
-#ifndef __powerpc__
-#define THIS_CPU		Private
-#define CHECK_THIS_CPU		do {} while (0)
-#else
-#define THIS_CPU		Processor[cpu]
-#define CHECK_THIS_CPU		check_arg_cpu(cpu)
-#endif
-
-
-    /*
-     *  Sanity checks
-     */
-
-#if 1
-#define check_arg_ipi(ipi) \
-    if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
-	printk("openpic.c:%d: illegal ipi %d\n", __LINE__, ipi);
-#define check_arg_timer(timer) \
-    if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
-	printk("openpic.c:%d: illegal timer %d\n", __LINE__, timer);
-#define check_arg_vec(vec) \
-    if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
-	printk("openpic.c:%d: illegal vector %d\n", __LINE__, vec);
-#define check_arg_pri(pri) \
-    if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
-	printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri);
-#define check_arg_irq(irq) \
-    if (irq < 0 || irq >= NumSources) \
-	printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);
-#define check_arg_cpu(cpu) \
-    if (cpu < 0 || cpu >= NumProcessors) \
-	printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu);
-#else
-#define check_arg_ipi(ipi)	do {} while (0)
-#define check_arg_timer(timer)	do {} while (0)
-#define check_arg_vec(vec)	do {} while (0)
-#define check_arg_pri(pri)	do {} while (0)
-#define check_arg_irq(irq)	do {} while (0)
-#define check_arg_cpu(cpu)	do {} while (0)
-#endif
-
-
-    /*
-     *  Dummy interrupt handler
-     */
-
-static void no_action(int ir1, void *dev, struct pt_regs *regs)
-{}
-
-
-    /*
-     *  I/O functions
-     */
-
-#ifdef __i386__
-static inline u_int ld_le32(volatile u_int *addr)
-{
-    return *addr;
-}
-
-static inline void out_le32(volatile u_int *addr, u_int val)
-{
-    *addr = val;
-}
-#endif
-
-u_int openpic_read(volatile u_int *addr)
-{
-    u_int val;
-
-    val = ld_le32(addr);
-#ifdef REGISTER_DEBUG
-    printk("openpic_read(0x%08x) = 0x%08x\n", (u_int)addr, val);
-#endif
-    return val;
-}
-
-static inline void openpic_write(volatile u_int *addr, u_int val)
-{
-#ifdef REGISTER_DEBUG
-    printk("openpic_write(0x%08x, 0x%08x)\n", (u_int)addr, val);
-#endif
-    out_le32(addr, val);
-}
-
-
-static inline u_int openpic_readfield(volatile u_int *addr, u_int mask)
-{
-    u_int val = openpic_read(addr);
-    return val & mask;
-}
-
-inline void openpic_writefield(volatile u_int *addr, u_int mask,
-				      u_int field)
-{
-    u_int val = openpic_read(addr);
-    openpic_write(addr, (val & ~mask) | (field & mask));
-}
-
-static inline void openpic_clearfield(volatile u_int *addr, u_int mask)
-{
-    openpic_writefield(addr, mask, 0);
-}
-
-static inline void openpic_setfield(volatile u_int *addr, u_int mask)
-{
-    openpic_writefield(addr, mask, mask);
-}
-
-
-    /*
-     *  Update a Vector/Priority register in a safe manner. The interrupt will
-     *  be disabled.
-     */
-
-static void openpic_safe_writefield(volatile u_int *addr, u_int mask,
-				    u_int field)
-{
-    openpic_setfield(addr, OPENPIC_MASK);
-    /* wait until it's not in use */
-    while (openpic_read(addr) & OPENPIC_ACTIVITY);
-    openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
-}
-
-
-/* -------- Global Operations ---------------------------------------------- */
-
-
-    /*
-     *  Initialize the OpenPIC
-     */
-
-__initfunc(void openpic_init(int main_pic))
-{
-    u_int t, i;
-    u_int timerfreq;
-    const char *version;
-
-    if (!OpenPIC)
-	panic("No OpenPIC found");
-
-    if ( ppc_md.progress ) ppc_md.progress("openpic enter",0x122);
-
-    t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
-    switch (t & OPENPIC_FEATURE_VERSION_MASK) {
-	case 1:
-	    version = "1.0";
-	    break;
-	case 2:
-	    version = "1.2";
-	    break;
-	case 3:
-	    version = "1.3";
-	    break;
-	default:
-	    version = "?";
-	    break;
-    }
-    NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
-		     OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
-    NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
-		  OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
-
-    printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at %p\n", version,
-	   NumProcessors, NumSources, OpenPIC);
-    timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
-    printk("OpenPIC timer frequency is ");
-    if (timerfreq)
-	printk("%d Hz\n", timerfreq);
-    else
-	printk("not set\n");
-
-    if ( main_pic )
-    {
-	    if ( ppc_md.progress ) ppc_md.progress("openpic main",0x3ff);
-      
-	    /* Initialize timer interrupts */
-	    for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
-		    /* Disabled, Priority 0 */
-		    openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
-		    /* No processor */
-		    openpic_maptimer(i, 0);
-	    }
-	    
-	    /* Initialize IPI interrupts */
-	    for (i = 0; i < OPENPIC_NUM_IPI; i++) {
-		    /* Disabled, Priority 0 */
-		    openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
-	    }
-	    
-	    if ( ppc_md.progress ) ppc_md.progress("openpic initirq",0x3bb);
-	    /* Initialize external interrupts */
-	    /* SIOint (8259 cascade) is special */
-	    openpic_initirq(0, 8, OPENPIC_VEC_SOURCE, 1, 1);
-	    
-	    if ( ppc_md.progress ) ppc_md.progress("openpic map",0x3cc);
-	    /* Processor 0 */
-	    openpic_mapirq(0, 1<<0);
-	    for (i = 1; i < NumSources; i++) {
-		    /* Enabled, Priority 8 */
-		    openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, 0,
-				    i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
-		    /* Processor 0 */
-		    openpic_mapirq(i, 1<<0);
-	    }
-	    
-	    /* Initialize the spurious interrupt */
-	    openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
-	    
-	    if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
-			    "82c59 cascade", NULL))
-		    printk("Unable to get OpenPIC IRQ 0 for cascade\n");
-	    openpic_set_priority(0, 0);
-	    openpic_disable_8259_pass_through();
-    }
-    if ( ppc_md.progress ) ppc_md.progress("openpic exit",0x222);
-}
-
-
-    /*
-     *  Reset the OpenPIC
-     */
-
-void openpic_reset(void)
-{
-    openpic_setfield(&OpenPIC->Global.Global_Configuration0,
-    		       OPENPIC_CONFIG_RESET);
-}
-
-
-    /*
-     *  Enable/disable 8259 Pass Through Mode
-     */
-
-void openpic_enable_8259_pass_through(void)
-{
-    openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
-    		       OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
-}
-
-void openpic_disable_8259_pass_through(void)
-{
-    openpic_setfield(&OpenPIC->Global.Global_Configuration0,
-    		     OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
-}
-
-
-#ifndef __i386__
-    /*
-     *  Find out the current interrupt
-     */
-
-u_int openpic_irq(u_int cpu)
-{
-    u_int vec;
-
-    check_arg_cpu(cpu);
-    vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
-			    OPENPIC_VECTOR_MASK);
-#if 0
-if (vec != 22 /* SCSI */)
-printk("++openpic_irq: %d\n", vec);
-#endif
-    return vec;
-}
-#endif
-
-
-    /*
-     *  Signal end of interrupt (EOI) processing
-     */
-
-#ifndef __powerpc__
-void openpic_eoi(void)
-#else
-void openpic_eoi(u_int cpu)
-#endif
-{
-    check_arg_cpu(cpu);
-    openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
-}
-
-
-    /*
-     *  Get/set the current task priority
-     */
-
-#ifndef __powerpc__
-u_int openpic_get_priority(void)
-#else
-u_int openpic_get_priority(u_int cpu)
-#endif
-{
-    CHECK_THIS_CPU;
-    return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
-			     OPENPIC_CURRENT_TASK_PRIORITY_MASK);
-}
-
-#ifndef __powerpc__
-void openpic_set_priority(u_int pri)
-#else
-void openpic_set_priority(u_int cpu, u_int pri)
-#endif
-{
-    CHECK_THIS_CPU;
-    check_arg_pri(pri);
-    openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
-    		       OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
-}
-
-    /*
-     *  Get/set the spurious vector
-     */
-
-u_int openpic_get_spurious(void)
-{
-    return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
-    			     OPENPIC_VECTOR_MASK);
-}
-
-void openpic_set_spurious(u_int vec)
-{
-    check_arg_vec(vec);
-    openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
-    		       vec);
-}
-
-
-    /*
-     *  Initialize one or more CPUs
-     */
-
-void openpic_init_processor(u_int cpumask)
-{
-    openpic_write(&OpenPIC->Global.Processor_Initialization, cpumask);
-}
-
-
-/* -------- Interprocessor Interrupts -------------------------------------- */
-
-
-    /*
-     *  Initialize an interprocessor interrupt (and disable it)
-     *
-     *  ipi: OpenPIC interprocessor interrupt number
-     *  pri: interrupt source priority
-     *  vec: the vector it will produce
-     */
-
-void openpic_initipi(u_int ipi, u_int pri, u_int vec)
-{
-    check_arg_timer(ipi);
-    check_arg_pri(pri);
-    check_arg_vec(vec);
-    openpic_safe_writefield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
-    			    OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
-    			    (pri << OPENPIC_PRIORITY_SHIFT) | vec);
-}
-
-
-    /*
-     *  Send an IPI to one or more CPUs
-     */
-
-#ifndef __powerpc__
-void openpic_cause_IPI(u_int ipi, u_int cpumask)
-#else
-void openpic_cause_IPI(u_int cpu, u_int ipi, u_int cpumask)
-#endif
-{
-    CHECK_THIS_CPU;
-    check_arg_ipi(ipi);
-    openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpumask);
-}
-
-
-/* -------- Timer Interrupts ----------------------------------------------- */
-
-
-    /*
-     *  Initialize a timer interrupt (and disable it)
-     *
-     *  timer: OpenPIC timer number
-     *  pri: interrupt source priority
-     *  vec: the vector it will produce
-     */
-
-void openpic_inittimer(u_int timer, u_int pri, u_int vec)
-{
-    check_arg_timer(timer);
-    check_arg_pri(pri);
-    check_arg_vec(vec);
-    openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority,
-    			    OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
-    			    (pri << OPENPIC_PRIORITY_SHIFT) | vec);
-}
-
-
-    /*
-     *  Map a timer interrupt to one or more CPUs
-     */
-
-void openpic_maptimer(u_int timer, u_int cpumask)
-{
-    check_arg_timer(timer);
-    openpic_write(&OpenPIC->Global.Timer[timer].Destination, cpumask);
-}
-
-
-/* -------- Interrupt Sources ---------------------------------------------- */
-
-
-    /*
-     *  Enable/disable an interrupt source
-     */
-
-void openpic_enable_irq(u_int irq)
-{
-    check_arg_irq(irq);
-    openpic_clearfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
-}
-
-void openpic_disable_irq(u_int irq)
-{
-    check_arg_irq(irq);
-    openpic_setfield(&OpenPIC->Source[irq].Vector_Priority, OPENPIC_MASK);
-}
-
-
-    /*
-     *  Initialize an interrupt source (and disable it!)
-     *
-     *  irq: OpenPIC interrupt number
-     *  pri: interrupt source priority
-     *  vec: the vector it will produce
-     *  pol: polarity (1 for positive, 0 for negative)
-     *  sense: 1 for level, 0 for edge
-     */
-
-void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
-{
-    check_arg_irq(irq);
-    check_arg_pri(pri);
-    check_arg_vec(vec);
-    openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
-    			    OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
-    			    OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL,
-    			    (pri << OPENPIC_PRIORITY_SHIFT) | vec |
-			    (pol ? OPENPIC_SENSE_POLARITY : 0) |
-			    (sense ? OPENPIC_SENSE_LEVEL : 0));
-}
-
-
-    /*
-     *  Map an interrupt source to one or more CPUs
-     */
-
-void openpic_mapirq(u_int irq, u_int cpumask)
-{
-    check_arg_irq(irq);
-    openpic_write(&OpenPIC->Source[irq].Destination, cpumask);
-}
-
-
-    /*
-     *  Set the sense for an interrupt source (and disable it!)
-     *
-     *  sense: 1 for level, 0 for edge
-     */
-
-void openpic_set_sense(u_int irq, int sense)
-{
-    check_arg_irq(irq);
-    openpic_safe_writefield(&OpenPIC->Source[irq].Vector_Priority,
-    			    OPENPIC_SENSE_LEVEL,
-			    (sense ? OPENPIC_SENSE_LEVEL : 0));
-}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v2.3.15/linux/arch/ppc/kernel/pci.c	Tue Jul 13 02:29:35 1999
+++ linux/arch/ppc/kernel/pci.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: pci.c,v 1.54 1999/03/18 04:16:04 cort Exp $
+ * $Id: pci.c,v 1.56 1999/08/31 15:42:37 cort Exp $
  * Common pmac/prep/chrp pci routines. -- Cort
  */
 
@@ -26,46 +26,51 @@
 unsigned long isa_mem_base    = 0;
 unsigned long pci_dram_offset = 0;
 
-int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
-			     unsigned char offset, unsigned char *val)
+struct pci_fixup pcibios_fixups[] = {
+	{ 0 }
+};
+
+int generic_pcibios_read_byte(struct pci_dev *dev, int where, u8 *val)
 {
-	return ppc_md.pcibios_read_config_byte(bus,dev_fn,offset,val);
+	return ppc_md.pcibios_read_config_byte(dev->bus->number,dev->devfn,where,val);
 }
-int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
-			     unsigned char offset, unsigned short *val)
+int generic_pcibios_read_word(struct pci_dev *dev, int where, u16 *val)
 {
-	return ppc_md.pcibios_read_config_word(bus,dev_fn,offset,val);
+	return ppc_md.pcibios_read_config_word(dev->bus->number,dev->devfn,where,val);
 }
-int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
-			      unsigned char offset, unsigned int *val)
+int generic_pcibios_read_dword(struct pci_dev *dev, int where, u32 *val)
 {
-	return ppc_md.pcibios_read_config_dword(bus,dev_fn,offset,val);
+	return ppc_md.pcibios_read_config_dword(dev->bus->number,dev->devfn,where,val);
 }
-int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
-			      unsigned char offset, unsigned char val)
+int generic_pcibios_write_byte(struct pci_dev *dev, int where, u8 val)
 {
-	return ppc_md.pcibios_write_config_byte(bus,dev_fn,offset,val);
+	return ppc_md.pcibios_write_config_byte(dev->bus->number,dev->devfn,where,val);
 }
-int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
-			      unsigned char offset, unsigned short val)
+int generic_pcibios_write_word(struct pci_dev *dev, int where, u16 val)
 {
-	return ppc_md.pcibios_write_config_word(bus,dev_fn,offset,val);
+	return ppc_md.pcibios_write_config_word(dev->bus->number,dev->devfn,where,val);
 }
-int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
-			       unsigned char offset, unsigned int val)
+int generic_pcibios_write_dword(struct pci_dev *dev, int where, u32 val)
 {
-	return ppc_md.pcibios_write_config_dword(bus,dev_fn,offset,val);
+	return ppc_md.pcibios_write_config_dword(dev->bus->number,dev->devfn,where,val);
 }
 
-int pcibios_present(void)
+struct pci_ops generic_pci_ops = 
 {
-	return 1;
-}
+	generic_pcibios_read_byte,
+	generic_pcibios_read_word,
+	generic_pcibios_read_dword,
+	generic_pcibios_write_byte,
+	generic_pcibios_write_word,
+	generic_pcibios_write_dword
+};
 
 void __init pcibios_init(void)
 {
+	printk("PCI: Probing PCI hardware\n");
+	pci_scan_bus(0, &generic_pci_ops, NULL);
+	
 }
-
 
 void __init pcibios_fixup(void)
 {
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/pci.h linux/arch/ppc/kernel/pci.h
--- v2.3.15/linux/arch/ppc/kernel/pci.h	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/pci.h	Tue Aug 31 11:36:43 1999
@@ -11,6 +11,18 @@
 
 void fix_intr(struct device_node *node, struct pci_dev *dev);
 
+#if 0
+#define decl_config_access_method(name) 	\
+struct pci_ops name##_pci_ops = { 		\
+	name##_pcibios_read_config_byte,	\
+	name##_pcibios_read_config_word,	\
+	name##_pcibios_read_config_dword,	\
+	name##_pcibios_write_config_byte,	\
+	name##_pcibios_write_config_word,	\
+	name##_pcibios_write_config_dword	\
+}
+#endif
+
 #define decl_config_access_method(name) \
 extern int name##_pcibios_read_config_byte(unsigned char bus, \
 	unsigned char dev_fn, unsigned char offset, unsigned char *val); \
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
--- v2.3.15/linux/arch/ppc/kernel/pmac_pci.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/pmac_pci.c	Tue Aug 31 11:36:43 1999
@@ -17,6 +17,8 @@
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/init.h>
+
+#include <asm/init.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/prom.h>
@@ -315,7 +317,7 @@
  * N.B. we can't use pcibios_*_config_* here because bridges[]
  * is not initialized yet.
  */
-__initfunc(static void init_bandit(struct bridge_data *bp))
+static void __init init_bandit(struct bridge_data *bp)
 {
 	unsigned int vendev, magic;
 	int rev;
@@ -360,7 +362,7 @@
 	       bp->io_base);
 }
 
-__initfunc(unsigned long pmac_find_bridges(unsigned long mem_start, unsigned long mem_end))
+unsigned long __init pmac_find_bridges(unsigned long mem_start, unsigned long mem_end)
 {
 	int bus;
 	struct bridge_data *bridge;
@@ -385,7 +387,7 @@
  * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
  * if we have one or more bandit or chaos bridges, we don't have a MPC106.
  */
-__initfunc(static void add_bridges(struct device_node *dev, unsigned long *mem_ptr))
+static void __init add_bridges(struct device_node *dev, unsigned long *mem_ptr)
 {
 	int *bus_range;
 	int len;
@@ -442,9 +444,8 @@
 	}
 }
 
-__initfunc(
-void
-pmac_pcibios_fixup(void))
+void __init
+pmac_pcibios_fixup(void)
 {
 	struct pci_dev *dev;
 	
@@ -472,9 +473,8 @@
 	}
 }
 
-__initfunc(
-void
-pmac_setup_pci_ptrs(void))
+void __init
+pmac_setup_pci_ptrs(void)
 {
 	if (find_devices("pci") != 0) {
 		/* looks like a G3 powermac */
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
--- v2.3.15/linux/arch/ppc/kernel/pmac_pic.c	Wed May 12 08:50:00 1999
+++ linux/arch/ppc/kernel/pmac_pic.c	Tue Aug 31 11:36:43 1999
@@ -3,6 +3,8 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
+
+#include <asm/init.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/prom.h>
@@ -290,8 +292,8 @@
 	}
 }
 
-__initfunc(void
-pmac_pic_init(void))
+void __init
+pmac_pic_init(void)
 {
         int i;
         struct device_node *irqctrler;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.3.15/linux/arch/ppc/kernel/pmac_setup.c	Mon Jul 12 15:12:55 1999
+++ linux/arch/ppc/kernel/pmac_setup.c	Tue Aug 31 11:36:43 1999
@@ -43,6 +43,8 @@
 #include <linux/console.h>
 #include <linux/ide.h>
 #include <linux/pci.h>
+
+#include <asm/init.h>
 #include <asm/prom.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -227,8 +229,8 @@
 
 static volatile u32 *sysctrl_regs;
 
-__initfunc(void
-pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p))
+void __init
+pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p)
 {
 	struct device_node *cpu;
 	int *fp;
@@ -308,7 +310,7 @@
 /*
  * Tweak the PCI-PCI bridge chip on the blue & white G3s.
  */
-__initfunc(static void init_p2pbridge(void))
+static void __init init_p2pbridge(void)
 {
 	struct device_node *p2pbridge;
 	unsigned char bus, devfn;
@@ -330,7 +332,7 @@
 	pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val);
 }
 
-__initfunc(static void ohare_init(void))
+static void __init ohare_init(void)
 {
 	/*
 	 * Turn on the L2 cache.
@@ -355,8 +357,8 @@
 int boot_part;
 kdev_t boot_dev;
 
-__initfunc(void
-pmac_init2(void))
+void __init
+pmac_init2(void)
 {
 	adb_init();
 	pmac_nvram_init();
@@ -364,8 +366,8 @@
 }
 
 #ifdef CONFIG_SCSI
-__initfunc(void
-note_scsi_host(struct device_node *node, void *host))
+void __init
+note_scsi_host(struct device_node *node, void *host)
 {
 	int l;
 	char *p;
@@ -399,7 +401,7 @@
 extern struct device_node *pmac_ide_node[];
 static int ide_majors[] = { 3, 22, 33, 34, 56, 57, 88, 89 };
 
-__initfunc(kdev_t find_ide_boot(void))
+kdev_t __init find_ide_boot(void)
 {
 	char *p;
 	int i, n;
@@ -426,7 +428,7 @@
 }
 #endif /* CONFIG_BLK_DEV_IDE_PMAC */
 
-__initfunc(void find_boot_device(void))
+void __init find_boot_device(void)
 {
 #ifdef CONFIG_SCSI
 	if (boot_host != NULL) {
@@ -440,7 +442,7 @@
 #endif
 }
 
-/* can't be initfunc - can be called whenever a disk is first accessed */
+/* can't be __init - can be called whenever a disk is first accessed */
 __pmac
 void note_bootable_part(kdev_t dev, int part)
 {
@@ -589,9 +591,9 @@
 #endif
 #endif
 
-__initfunc(void
+void __init
 pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	  unsigned long r6, unsigned long r7))
+	  unsigned long r6, unsigned long r7)
 {
 	pmac_setup_pci_ptrs();
 
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/pmac_support.c linux/arch/ppc/kernel/pmac_support.c
--- v2.3.15/linux/arch/ppc/kernel/pmac_support.c	Wed Aug  4 16:36:41 1999
+++ linux/arch/ppc/kernel/pmac_support.c	Tue Aug 31 11:36:43 1999
@@ -6,6 +6,7 @@
 #include <linux/reboot.h>
 #include <linux/nvram.h>
 #include <linux/init.h>
+#include <asm/init.h>
 #include <asm/ptrace.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c
--- v2.3.15/linux/arch/ppc/kernel/pmac_time.c	Tue Aug  4 23:57:51 1998
+++ linux/arch/ppc/kernel/pmac_time.c	Tue Aug 31 11:36:43 1999
@@ -15,6 +15,8 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+
+#include <asm/init.h>
 #include <asm/adb.h>
 #include <asm/cuda.h>
 #include <asm/pmu.h>
@@ -91,7 +93,7 @@
  * Calibrate the decrementer register using VIA timer 1.
  * This is used both on powermacs and CHRP machines.
  */
-__initfunc(int via_calibrate_decr(void))
+int __init via_calibrate_decr(void)
 {
 	struct device_node *vias;
 	volatile unsigned char *via;
@@ -168,7 +170,7 @@
  * This was taken from the pmac time_init() when merging the prep/pmac
  * time functions.
  */
-__initfunc(void pmac_calibrate_decr(void))
+void __init pmac_calibrate_decr(void)
 {
 	struct device_node *cpu;
 	int freq, *fp, divisor;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/ppc-stub.c linux/arch/ppc/kernel/ppc-stub.c
--- v2.3.15/linux/arch/ppc/kernel/ppc-stub.c	Tue Jul 13 02:29:35 1999
+++ linux/arch/ppc/kernel/ppc-stub.c	Tue Aug 31 11:36:43 1999
@@ -1,4 +1,4 @@
-/* $Id: ppc-stub.c,v 1.4 1998/07/28 08:25:01 paulus Exp $
+/* $Id: ppc-stub.c,v 1.6 1999/08/12 22:18:11 cort Exp $
  * ppc-stub.c:  KGDB support for the Linux kernel.
  *
  * adapted from arch/sparc/kernel/sparc-stub.c for the PowerPC
@@ -438,13 +438,13 @@
 	{ 0x400, SIGBUS },			/* instruction bus error */
 	{ 0x500, SIGINT },			/* interrupt */
 	{ 0x600, SIGBUS },			/* alingment */
-	{ 0x700, SIGILL },			/* reserved instruction or sumpin' */
+	{ 0x700, SIGTRAP },			/* breakpoint trap */
 	{ 0x800, SIGFPE },			/* fpu unavail */
 	{ 0x900, SIGALRM },			/* decrementer */
 	{ 0xa00, SIGILL },			/* reserved */
 	{ 0xb00, SIGILL },			/* reserved */
 	{ 0xc00, SIGCHLD },			/* syscall */
-	{ 0xd00, SIGINT },			/* watch */
+	{ 0xd00, SIGTRAP },			/* single-step/watch */
 	{ 0xe00, SIGFPE },			/* fp assist */
 	{ 0, 0}				/* Must be last */
 };
@@ -482,8 +482,10 @@
 	}
 	kgdb_active = 1;
 
+#ifdef KGDB_DEBUG
 	printk("kgdb: entering handle_exception; trap [0x%x]\n",
 	       (unsigned int)regs->trap);
+#endif
 
 	kgdb_interruptible(0);
 	lock_kernel();
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/ppc_asm.h linux/arch/ppc/kernel/ppc_asm.h
--- v2.3.15/linux/arch/ppc/kernel/ppc_asm.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/ppc_asm.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,73 @@
+/*
+ * arch/ppc/kernel/ppc_asm.h
+ *
+ * Definitions used by various bits of low-level assembly code on PowerPC.
+ *
+ * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.
+ *
+ *  This program is free software; you can redistribute 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 "ppc_asm.tmpl"
+#include "ppc_defs.h"
+
+/*
+ * Macros for storing registers into and loading registers from
+ * exception frames.
+ */
+#define SAVE_GPR(n, base)	stw	n,GPR0+4*(n)(base)
+#define SAVE_2GPRS(n, base)	SAVE_GPR(n, base); SAVE_GPR(n+1, base)
+#define SAVE_4GPRS(n, base)	SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
+#define SAVE_8GPRS(n, base)	SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
+#define SAVE_10GPRS(n, base)	SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
+#define REST_GPR(n, base)	lwz	n,GPR0+4*(n)(base)
+#define REST_2GPRS(n, base)	REST_GPR(n, base); REST_GPR(n+1, base)
+#define REST_4GPRS(n, base)	REST_2GPRS(n, base); REST_2GPRS(n+2, base)
+#define REST_8GPRS(n, base)	REST_4GPRS(n, base); REST_4GPRS(n+4, base)
+#define REST_10GPRS(n, base)	REST_8GPRS(n, base); REST_2GPRS(n+8, base)
+
+#define SAVE_FPR(n, base)	stfd	n,THREAD_FPR0+8*(n)(base)
+#define SAVE_2FPRS(n, base)	SAVE_FPR(n, base); SAVE_FPR(n+1, base)
+#define SAVE_4FPRS(n, base)	SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
+#define SAVE_8FPRS(n, base)	SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
+#define SAVE_16FPRS(n, base)	SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
+#define SAVE_32FPRS(n, base)	SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
+#define REST_FPR(n, base)	lfd	n,THREAD_FPR0+8*(n)(base)
+#define REST_2FPRS(n, base)	REST_FPR(n, base); REST_FPR(n+1, base)
+#define REST_4FPRS(n, base)	REST_2FPRS(n, base); REST_2FPRS(n+2, base)
+#define REST_8FPRS(n, base)	REST_4FPRS(n, base); REST_4FPRS(n+4, base)
+#define REST_16FPRS(n, base)	REST_8FPRS(n, base); REST_8FPRS(n+8, base)
+#define REST_32FPRS(n, base)	REST_16FPRS(n, base); REST_16FPRS(n+16, base)
+
+#define SYNC \
+	sync; \
+	isync
+
+/* This instruction is not implemented on the PPC 603 or 601 */
+#define tlbia \
+	li	r4,128; \
+	mtctr	r4; \
+	lis	r4,KERNELBASE@h; \
+0:	tlbie	r4; \
+	addi	r4,r4,0x1000; \
+	bdnz	0b
+
+/*
+ * On APUS (Amiga PowerPC cpu upgrade board), we don't know the
+ * physical base address of RAM at compile time.
+ */
+#define tophys(rd,rs)				\
+0:	addis	rd,rs,-KERNELBASE@h;		\
+	.section ".vtop_fixup","aw";		\
+	.align  1;				\
+	.long   0b;				\
+	.previous
+
+#define tovirt(rd,rs)				\
+0:	addis	rd,rs,KERNELBASE@h;		\
+	.section ".ptov_fixup","aw";		\
+	.align  1;				\
+	.long   0b;				\
+	.previous
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.3.15/linux/arch/ppc/kernel/ppc_ksyms.c	Mon Aug  9 11:39:37 1999
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,6 @@
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/threads.h>
 #include <linux/smp.h>
 #include <linux/elfcore.h>
 #include <linux/sched.h>
@@ -35,7 +36,6 @@
 #define EXPORT_SYMTAB_STROPS
 
 extern void transfer_to_handler(void);
-extern void int_return(void);
 extern void syscall_trace(void);
 extern void do_IRQ(struct pt_regs *regs, int isfake);
 extern void MachineCheckException(struct pt_regs *regs);
@@ -53,7 +53,6 @@
 EXPORT_SYMBOL(do_signal);
 EXPORT_SYMBOL(syscall_trace);
 EXPORT_SYMBOL(transfer_to_handler);
-EXPORT_SYMBOL(int_return);
 EXPORT_SYMBOL(do_IRQ);
 EXPORT_SYMBOL(init_task_union);
 EXPORT_SYMBOL(MachineCheckException);
@@ -153,11 +152,9 @@
 EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(kernel_thread);
 
-EXPORT_SYMBOL(__cli);
-EXPORT_SYMBOL(__sti);
 /*EXPORT_SYMBOL(__restore_flags);*/
-EXPORT_SYMBOL(_disable_interrupts);
-EXPORT_SYMBOL(_enable_interrupts);
+/*EXPORT_SYMBOL(_disable_interrupts);
+  EXPORT_SYMBOL(_enable_interrupts);*/
 EXPORT_SYMBOL(flush_instruction_cache);
 EXPORT_SYMBOL(_get_PVR);
 EXPORT_SYMBOL(giveup_fpu);
@@ -189,6 +186,7 @@
 EXPORT_SYMBOL(pmu_poll);
 #ifdef CONFIG_PMAC_PBOOK
 EXPORT_SYMBOL(sleep_notifier_list);
+EXPORT_SYMBOL(pmu_enable_irled);
 #endif CONFIG_PMAC_PBOOK
 EXPORT_SYMBOL(abort);
 EXPORT_SYMBOL(find_devices);
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/prep_nvram.c linux/arch/ppc/kernel/prep_nvram.c
--- v2.3.15/linux/arch/ppc/kernel/prep_nvram.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/prep_nvram.c	Tue Aug 31 11:36:43 1999
@@ -9,6 +9,7 @@
 #include <linux/malloc.h>
 #include <linux/ioport.h>
 
+#include <asm/init.h>
 #include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/processor.h>
@@ -57,7 +58,7 @@
 	rs_pcNvRAM[addr]=val;
 }
   
-__initfunc(void init_prep_nvram(void))
+void __init init_prep_nvram(void)
 {
 	unsigned char *nvp;
 	int  i;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
--- v2.3.15/linux/arch/ppc/kernel/prep_pci.c	Sat May 22 13:03:00 1999
+++ linux/arch/ppc/kernel/prep_pci.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: prep_pci.c,v 1.35 1999/05/10 23:31:03 cort Exp $
+ * $Id: prep_pci.c,v 1.39 1999/08/31 15:42:39 cort Exp $
  * PReP pci functions.
  * Originally by Gary Thomas
  * rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/openpic.h>
 
+#include <asm/init.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/ptrace.h>
@@ -685,7 +686,7 @@
 int prep_keybd_present = 1;
 int MotMPIC = 0;
 
-__initfunc(int raven_init(void))
+int __init raven_init(void)
 {
 	unsigned int	devid;
 	unsigned int	pci_membase;
@@ -788,7 +789,7 @@
 	{0x000, 0x00, 0x00, "",					NULL,			NULL}
 };
 
-__initfunc(unsigned long prep_route_pci_interrupts(void))
+unsigned long __init prep_route_pci_interrupts(void)
 {
 	unsigned char *ibc_pirq = (unsigned char *)0x80800860;
 	unsigned char *ibc_pcicon = (unsigned char *)0x80800840;
@@ -976,9 +977,8 @@
 	return 0;
 }
 
-__initfunc(
-void
-prep_pcibios_fixup(void))
+void __init
+prep_pcibios_fixup(void)
 {
         struct pci_dev *dev;
         extern unsigned char *Motherboard_map;
@@ -1017,17 +1017,17 @@
 
 		for ( i = 0 ; i <= 5 ; i++ )
 		{
-		        if ( dev->base_address[i] > 0x10000000 )
+		        if ( dev->resource[i].start > 0x10000000 )
 		        {
 		                printk("Relocating PCI address %lx -> %lx\n",
-		                       dev->base_address[i],
-		                       (dev->base_address[i] & 0x00FFFFFF)
+		                       dev->resource[i].start,
+		                       (dev->resource[i].start & 0x00FFFFFF)
 		                       | 0x01000000);
-		                dev->base_address[i] =
-		                  (dev->base_address[i] & 0x00FFFFFF) | 0x01000000;
+		                dev->resource[i].start =
+		                  (dev->resource[i].start & 0x00FFFFFF) | 0x01000000;
 		                pci_write_config_dword(dev,
 		                        PCI_BASE_ADDRESS_0+(i*0x4),
-		                       dev->base_address[i] );
+		                       dev->resource[i].start );
 		        }
 		}
 #if 0
@@ -1044,9 +1044,8 @@
 
 decl_config_access_method(indirect);
 
-__initfunc(
-void
-prep_setup_pci_ptrs(void))
+void __init
+prep_setup_pci_ptrs(void)
 {
 	PPC_DEVICE *hostbridge;
 
@@ -1055,7 +1054,7 @@
         {
 		pci_config_address = (unsigned *)0x80000cf8;
 		pci_config_data = (char *)0x80000cfc;
-                set_config_access_method(indirect);		
+		set_config_access_method(indirect);		
         }
         else
         {
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.3.15/linux/arch/ppc/kernel/prep_setup.c	Tue Jul 13 02:29:35 1999
+++ linux/arch/ppc/kernel/prep_setup.c	Tue Aug 31 11:36:43 1999
@@ -35,6 +35,7 @@
 #include <linux/openpic.h>
 #include <linux/ide.h>
 
+#include <asm/init.h>
 #include <asm/mmu.h>
 #include <asm/processor.h>
 #include <asm/residual.h>
@@ -211,8 +212,8 @@
 	return len;
 }
 
-__initfunc(void
-prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
+void __init
+prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
 	extern char cmd_line[];
 	unsigned char reg;
@@ -365,7 +366,7 @@
  * This allows for a faster boot as we do not need to calibrate the
  * decrementer against another clock. This is important for embedded systems.
  */
-__initfunc(void prep_res_calibrate_decr(void))
+void __init prep_res_calibrate_decr(void)
 {
 	int freq, divisor;
 
@@ -386,10 +387,10 @@
 int calibrate_done = 0;
 volatile int *done_ptr = &calibrate_done;
 
-__initfunc(void
+void __init
 prep_calibrate_decr_handler(int            irq,
 			    void           *dev,
-			    struct pt_regs *regs))
+			    struct pt_regs *regs)
 {
 	unsigned long freq, divisor;
 	static unsigned long t1 = 0, t2 = 0;
@@ -412,7 +413,7 @@
 	}
 }
 
-__initfunc(void prep_calibrate_decr(void))
+void __init prep_calibrate_decr(void)
 {
 	unsigned long flags;
 
@@ -437,7 +438,7 @@
 
 
 /* We use the NVRAM RTC to time a second to calibrate the decrementer. */
-__initfunc(void mk48t59_calibrate_decr(void))
+void __init mk48t59_calibrate_decr(void)
 {
 	unsigned long freq, divisor;
 	unsigned long t1, t2;
@@ -491,7 +492,7 @@
         unsigned long i = 10000;
 
 
-        _disable_interrupts();
+	__cli();
 
         /* set exception prefix high - to the prom */
         _nmask_and_or_msr(0, MSR_IP);
@@ -518,7 +519,7 @@
 	 * This will ALWAYS work regardless of port 92
 	 * functionality
 	 */
-	_disable_interrupts();
+	__cli();
 
 	__asm__ __volatile__("\n\
 	mtspr   26, %1  /* SRR0 */
@@ -535,7 +536,7 @@
 prep_halt(void)
 {
         unsigned long flags;
-	_disable_interrupts();
+	__cli();
 	/* set exception prefix high - to the prom */
 	save_flags( flags );
 	restore_flags( flags|MSR_IP );
@@ -603,8 +604,8 @@
         ppc_irq_dispatch_handler( regs, irq );
 }		
 
-__initfunc(void
-prep_init_IRQ(void))
+void __init
+prep_init_IRQ(void)
 {
 	int i;
 
@@ -691,8 +692,8 @@
 {
 }
 
-__initfunc(void
-prep_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq))
+void __init
+prep_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
 	ide_ioreg_t reg = data_port;
 	int i;
@@ -711,9 +712,9 @@
 }
 #endif
 
-__initfunc(void
+void __init
 prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	  unsigned long r6, unsigned long r7))
+	  unsigned long r6, unsigned long r7)
 {
 	/* make a copy of residual data */
 	if ( r3 )
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/prep_time.c linux/arch/ppc/kernel/prep_time.c
--- v2.3.15/linux/arch/ppc/kernel/prep_time.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/prep_time.c	Tue Aug 31 11:36:43 1999
@@ -19,6 +19,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
 
+#include <asm/init.h>
 #include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/processor.h>
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.3.15/linux/arch/ppc/kernel/process.c	Mon Jul 26 22:41:09 1999
+++ linux/arch/ppc/kernel/process.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: process.c,v 1.87 1999/07/03 08:57:07 davem Exp $
+ * $Id: process.c,v 1.95 1999/08/31 06:54:07 davem Exp $
  *
  *  linux/arch/ppc/kernel/process.c
  *
@@ -50,7 +50,10 @@
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
 struct mm_struct init_mm = INIT_MM(init_mm);
-union task_union init_task_union = { INIT_TASK(init_task_union.task) };
+/* this is 16-byte aligned because it has a stack in it */
+union task_union __attribute((aligned(16))) init_task_union = {
+	INIT_TASK(init_task_union.task)
+};
 /* only used to get secondary processor up */
 struct task_struct *current_set[NR_CPUS] = {&init_task, };
 
@@ -74,7 +77,7 @@
 {
 	if (regs->msr & MSR_FP)
 		giveup_fpu(current);
-	memcpy(fpregs, &current->tss.fpr[0], sizeof(*fpregs));
+	memcpy(fpregs, &current->thread.fpr[0], sizeof(*fpregs));
 	return 1;
 }
 
@@ -82,7 +85,7 @@
 enable_kernel_fp(void)
 {
 #ifdef __SMP__
-	if (current->tss.regs && (current->tss.regs->msr & MSR_FP))
+	if (current->thread.regs && (current->thread.regs->msr & MSR_FP))
 		giveup_fpu(current);
 	else
 		giveup_fpu(NULL);	/* just enables FP for kernel */
@@ -99,11 +102,11 @@
 	int ret = 0;
 
 #if 0	
-	/* check tss magic */
-	if ( tsk->tss.magic != TSS_MAGIC )
+	/* check thread magic */
+	if ( tsk->thread.magic != THREAD_MAGIC )
 	{
 		ret |= 1;
-		printk("tss.magic bad: %08x\n", tsk->tss.magic);
+		printk("thread.magic bad: %08x\n", tsk->thread.magic);
 	}
 #endif
 
@@ -111,12 +114,12 @@
 		printk("check_stack(): tsk bad tsk %p\n",tsk);
 	
 	/* check if stored ksp is bad */
-	if ( (tsk->tss.ksp > stack_top) || (tsk->tss.ksp < tsk_top) )
+	if ( (tsk->thread.ksp > stack_top) || (tsk->thread.ksp < tsk_top) )
 	{
 		printk("stack out of bounds: %s/%d\n"
 		       " tsk_top %08lx ksp %08lx stack_top %08lx\n",
 		       tsk->comm,tsk->pid,
-		       tsk_top, tsk->tss.ksp, stack_top);
+		       tsk_top, tsk->thread.ksp, stack_top);
 		ret |= 2;
 	}
 	
@@ -158,8 +161,11 @@
 _switch_to(struct task_struct *prev, struct task_struct *new,
 	  struct task_struct **last)
 {
-	struct thread_struct *new_tss, *old_tss;
-	int s = _disable_interrupts();
+	struct thread_struct *new_thread, *old_thread;
+	int s;
+	
+	__save_flags(s);
+	__cli();
 #if CHECK_STACK
 	check_stack(prev);
 	check_stack(new);
@@ -168,7 +174,7 @@
 #ifdef SHOW_TASK_SWITCHES
 	printk("%s/%d -> %s/%d NIP %08lx cpu %d root %x/%x\n",
 	       prev->comm,prev->pid,
-	       new->comm,new->pid,new->tss.regs->nip,new->processor,
+	       new->comm,new->pid,new->thread.regs->nip,new->processor,
 	       new->fs->root,prev->fs->root);
 #endif
 #ifdef __SMP__
@@ -181,16 +187,16 @@
 	 * every switch, just a save.
 	 *  -- Cort
 	 */
-	if (prev->tss.regs && (prev->tss.regs->msr & MSR_FP))
+	if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP))
 		giveup_fpu(prev);
 
 	prev->last_processor = prev->processor;
 	current_set[smp_processor_id()] = new;
 #endif /* __SMP__ */
-	new_tss = &new->tss;
-	old_tss = &current->tss;
-	*last = _switch(old_tss, new_tss, new->mm->context);
-	_enable_interrupts(s);
+	new_thread = &new->thread;
+	old_thread = &current->thread;
+	*last = _switch(old_thread, new_thread);
+	__restore_flags(s);
 }
 
 void show_regs(struct pt_regs * regs)
@@ -204,9 +210,9 @@
 	       regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
 	       regs->msr&MSR_IR ? 1 : 0,
 	       regs->msr&MSR_DR ? 1 : 0);
-	printk("TASK = %p[%d] '%s' mm->pgd %p ",
-	       current, current->pid, current->comm, current->mm->pgd);
-	printk("Last syscall: %ld ", current->tss.last_syscall);
+	printk("TASK = %p[%d] '%s' ",
+	       current, current->pid, current->comm);
+	printk("Last syscall: %ld ", current->thread.last_syscall);
 	printk("\nlast math %p", last_task_used_math);
 	
 #ifdef __SMP__	
@@ -271,10 +277,10 @@
 	if ((childregs->msr & MSR_PR) == 0)
 		childregs->gpr[2] = (unsigned long) p;	/* `current' in new task */
 	childregs->gpr[3] = 0;  /* Result from fork() */
-	p->tss.regs = childregs;
-	p->tss.ksp = (unsigned long) childregs - STACK_FRAME_OVERHEAD;
-	p->tss.ksp -= sizeof(struct pt_regs ) + STACK_FRAME_OVERHEAD;
-	kregs = (struct pt_regs *)(p->tss.ksp + STACK_FRAME_OVERHEAD);
+	p->thread.regs = childregs;
+	p->thread.ksp = (unsigned long) childregs - STACK_FRAME_OVERHEAD;
+	p->thread.ksp -= sizeof(struct pt_regs ) + STACK_FRAME_OVERHEAD;
+	kregs = (struct pt_regs *)(p->thread.ksp + STACK_FRAME_OVERHEAD);
 #ifdef __SMP__
 	kregs->nip = (unsigned long)ret_from_smpfork;
 #else	
@@ -291,7 +297,7 @@
 		/* Provided stack is in user space */
 		childregs->gpr[1] = usp;
 	}
-	p->tss.last_syscall = -1;
+	p->thread.last_syscall = -1;
 	  
 	/*
 	 * copy fpu info - assume lazy fpu switch now always
@@ -300,11 +306,10 @@
 	if (regs->msr & MSR_FP)
 		giveup_fpu(current);
 
-	memcpy(&p->tss.fpr, &current->tss.fpr, sizeof(p->tss.fpr));
-	p->tss.fpscr = current->tss.fpscr;
+	memcpy(&p->thread.fpr, &current->thread.fpr, sizeof(p->thread.fpr));
+	p->thread.fpscr = current->thread.fpscr;
 	childregs->msr &= ~MSR_FP;
 
-	p->processor = 0;
 #ifdef __SMP__
 	p->last_processor = NO_PROC_ID;
 #endif /* __SMP__ */
@@ -362,7 +367,7 @@
 	shove_aux_table(sp);
 	if (last_task_used_math == current)
 		last_task_used_math = 0;
-	current->tss.fpscr = 0;
+	current->thread.fpscr = 0;
 }
 
 asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
@@ -453,7 +458,7 @@
 /*
  * Low level print for debugging - Cort
  */
-__initfunc(int ll_printk(const char *fmt, ...))
+int __init ll_printk(const char *fmt, ...)
 {
         va_list args;
 	char buf[256];
@@ -482,7 +487,7 @@
 	prom_print(buf);
 }
 
-__initfunc(void ll_puts(const char *s))
+void __init ll_puts(const char *s)
 {
 	int x,y;
 	char *vidmem = (char *)/*(_ISA_MEM_BASE + 0xB8000) */0xD00B8000;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- v2.3.15/linux/arch/ppc/kernel/prom.c	Mon Jul 12 15:12:55 1999
+++ linux/arch/ppc/kernel/prom.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: prom.c,v 1.62 1999/07/02 19:59:31 cort Exp $
+ * $Id: prom.c,v 1.70 1999/08/25 21:26:08 cort Exp $
  *
  * Procedures for interfacing to the Open Firmware PROM on
  * Power Macintosh computers.
@@ -16,6 +16,8 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/version.h>
+
+#include <asm/init.h>
 #include <asm/spinlock.h>
 #include <asm/prom.h>
 #include <asm/page.h>
@@ -257,6 +259,9 @@
 	}
 }
 
+unsigned long smp_ibm_chrp_hack __initdata = 0;
+unsigned long smp_chrp_cpu_nr __initdata = 1;
+
 /*
  * We enter here early on, when the Open Firmware prom is still
  * handling exceptions and the MMU hash table for us.
@@ -266,7 +271,7 @@
 prom_init(int r3, int r4, prom_entry pp)
 {
 #ifdef CONFIG_SMP	
-	int cpu = 0, i;
+	int i;
 	phandle node;
 	char type[16], *path;
 #endif	
@@ -275,7 +280,7 @@
 	unsigned long offset = reloc_offset();
 	int l;
 	char *p, *d;
-	
+
 	/* check if we're apus, return if we are */
 	if ( r3 == 0x61707573 )
 		return;
@@ -524,17 +529,18 @@
 				    node, path, 255) < 0)
 			continue;
 		/* XXX: hack - don't start cpu 0, this cpu -- Cort */
-		if ( cpu++ == 0 )
+		if ( smp_chrp_cpu_nr++ == 0 )
 			continue;
+		RELOC(smp_ibm_chrp_hack) = 1;
 		prom_print(RELOC("starting cpu "));
 		prom_print(path);
 		*(unsigned long *)(0x4) = 0;
 		asm volatile("dcbf 0,%0": : "r" (0x4) : "memory");
-		call_prom(RELOC("start-cpu"), 3, 0, node, 8<<20, cpu-1);
+		call_prom(RELOC("start-cpu"), 3, 0, node, 8<<20, smp_chrp_cpu_nr-1);
 		for ( i = 0 ; (i < 10000) &&
 			      (*(ulong *)(0x4) == (ulong)0); i++ )
 			;
-		if (*(ulong *)(0x4) == (ulong)cpu-1 )
+		if (*(ulong *)(0x4) == (ulong)smp_chrp_cpu_nr-1 )
 			prom_print(RELOC("...ok\n"));
 		else
 			prom_print(RELOC("...failed\n"));
@@ -1296,8 +1302,6 @@
 }
 #endif
 
-spinlock_t rtas_lock = SPIN_LOCK_UNLOCKED;
-
 /* this can be called after setup -- Cort */
 __openfirmware
 int
@@ -1328,12 +1332,12 @@
 	for (i = 0; i < nargs; ++i)
 		u.words[i+3] = va_arg(list, unsigned long);
 	va_end(list);
+
+	save_flags(s);
+	cli();
 	
-	s = _disable_interrupts();
-	spin_lock(&rtas_lock);
 	enter_rtas((void *)__pa(&u));
-	spin_unlock(&rtas_lock);
-	_enable_interrupts(s);
+	restore_flags(s);
 	if (nret > 1 && outputs != NULL)
 		for (i = 0; i < nret-1; ++i)
 			outputs[i] = u.words[i+nargs+4];
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
--- v2.3.15/linux/arch/ppc/kernel/ptrace.c	Mon Jul 12 15:12:55 1999
+++ linux/arch/ppc/kernel/ptrace.c	Tue Aug 31 11:36:43 1999
@@ -47,7 +47,7 @@
 static inline long get_reg(struct task_struct *task, int regno)
 {
 	if (regno < sizeof(struct pt_regs) / sizeof(unsigned long))
-		return ((unsigned long *)task->tss.regs)[regno];
+		return ((unsigned long *)task->thread.regs)[regno];
 	return (0);
 }
 
@@ -60,8 +60,8 @@
 	if (regno <= PT_MQ) {
 		if (regno == PT_MSR)
 			data = (data & MSR_DEBUGCHANGE)
-				| (task->tss.regs->msr & ~MSR_DEBUGCHANGE);
-		((unsigned long *)task->tss.regs)[regno] = data;
+				| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
+		((unsigned long *)task->thread.regs)[regno] = data;
 		return 0;
 	}
 	return -1;
@@ -70,14 +70,14 @@
 static inline void
 set_single_step(struct task_struct *task)
 {
-	struct pt_regs *regs = task->tss.regs;
+	struct pt_regs *regs = task->thread.regs;
 	regs->msr |= MSR_SE;
 }
 
 static inline void
 clear_single_step(struct task_struct *task)
 {
-	struct pt_regs *regs = task->tss.regs;
+	struct pt_regs *regs = task->thread.regs;
 	regs->msr &= ~MSR_SE;
 }
 
@@ -384,9 +384,9 @@
 				tmp = get_reg(child, addr);
 			}
 			else if (addr >= PT_FPR0 && addr <= PT_FPSCR) {
-				if (child->tss.regs->msr & MSR_FP)
+				if (child->thread.regs->msr & MSR_FP)
 					giveup_fpu(child);
-				tmp = ((long *)child->tss.fpr)[addr - PT_FPR0];
+				tmp = ((long *)child->thread.fpr)[addr - PT_FPR0];
 			}
 			else
 				ret = -EIO;
@@ -419,9 +419,9 @@
 				goto out;
 			}
 			if (addr >= PT_FPR0 && addr < PT_FPR0 + 64) {
-				if (child->tss.regs->msr & MSR_FP)
+				if (child->thread.regs->msr & MSR_FP)
 					giveup_fpu(child);
-				((long *)child->tss.fpr)[addr - PT_FPR0] = data;
+				((long *)child->thread.fpr)[addr - PT_FPR0] = data;
 				ret = 0;
 				goto out;
 			}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/semaphore.c linux/arch/ppc/kernel/semaphore.c
--- v2.3.15/linux/arch/ppc/kernel/semaphore.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/semaphore.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,139 @@
+/*
+ * $Id: semaphore.c,v 1.1 1999/08/31 15:11:44 cort Exp $
+ *
+ * PowerPC-specific semaphore code.
+ *
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ *
+ * This program is free software; you can redistribute 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/sched.h>
+
+#include <asm/semaphore.h>
+#include <asm/semaphore-helper.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit.  ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore.  The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+	wake_one_more(sem);
+	wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function.  Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible.  This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return.  If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR				\
+	struct task_struct *tsk = current;	\
+	wait_queue_t wait;			\
+	init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state)						\
+									\
+									\
+	tsk->state = (task_state);					\
+	add_wait_queue(&sem->wait, &wait);				\
+									\
+	/*								\
+	 * Ok, we're set up.  sem->count is known to be less than zero	\
+	 * so we must wait.						\
+	 *								\
+	 * We can let go the lock for purposes of waiting.		\
+	 * We re-acquire it after awaking so as to protect		\
+	 * all semaphore operations.					\
+	 *								\
+	 * If "up()" is called before we call waking_non_zero() then	\
+	 * we will catch it right away.  If it is called later then	\
+	 * we will have to go through a wakeup cycle to catch it.	\
+	 *								\
+	 * Multiple waiters contend for the semaphore lock to see	\
+	 * who gets to gate through and who has to wait some more.	\
+	 */								\
+	for (;;) {
+
+#define DOWN_TAIL(task_state)			\
+		tsk->state = (task_state);	\
+	}					\
+	tsk->state = TASK_RUNNING;		\
+	remove_wait_queue(&sem->wait, &wait);
+
+void __down(struct semaphore * sem)
+{
+	DOWN_VAR
+	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+	if (waking_non_zero(sem))
+		break;
+	schedule();
+	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+	int ret = 0;
+	DOWN_VAR
+	DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+	ret = waking_non_zero_interruptible(sem, tsk);
+	if (ret)
+	{
+		if (ret == 1)
+			/* ret != 0 only if we get interrupted -arca */
+			ret = 0;
+		break;
+	}
+	schedule();
+	DOWN_TAIL(TASK_INTERRUPTIBLE)
+	return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+	return waking_non_zero_trylock(sem);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.3.15/linux/arch/ppc/kernel/setup.c	Fri Jul 23 12:20:23 1999
+++ linux/arch/ppc/kernel/setup.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: setup.c,v 1.138 1999/07/11 16:32:21 cort Exp $
+ * $Id: setup.c,v 1.146 1999/08/31 06:54:08 davem Exp $
  * Common prep/pmac/chrp boot and setup code.
  */
 
@@ -12,6 +12,7 @@
 #include <linux/delay.h>
 #include <linux/blk.h>
 
+#include <asm/init.h>
 #include <asm/adb.h>
 #include <asm/cuda.h>
 #include <asm/pmu.h>
@@ -63,6 +64,12 @@
                       unsigned long r6,
                       unsigned long r7);
 
+extern void gemini_init(unsigned long r3,
+                      unsigned long r4,
+                      unsigned long r5,
+                      unsigned long r6,
+                      unsigned long r7);
+
 extern boot_infos_t *boot_infos;
 extern char cmd_line[512];
 char saved_command_line[256];
@@ -121,11 +128,11 @@
 /*
  * I really need to add multiple-console support... -- Cort
  */
-__initfunc(int pmac_display_supported(char *name))
+int __init pmac_display_supported(char *name)
 {
 	return 0;
 }
-__initfunc(void pmac_find_display(void))
+void __init pmac_find_display(void)
 {
 }
 
@@ -267,6 +274,15 @@
 			
 			cpu_node = find_type_devices("cpu");
 			if ( !cpu_node ) break;
+			{
+				int s;
+				for ( s = 0; (s < i) && cpu_node->next ;
+				      s++, cpu_node = cpu_node->next )
+					/* nothing */ ;
+				if ( s != i )
+					printk("get_cpuinfo(): ran out of "
+					       "cpu nodes.\n");
+			}
 			fp = (int *) get_property(cpu_node, "clock-frequency", NULL);
 			if ( !fp ) break;
 			len += sprintf(len+buffer, "clock\t\t: %dMHz\n",
@@ -392,6 +408,8 @@
 	_machine = _MACH_fads;
 #elif defined(CONFIG_APUS)
 	_machine = _MACH_apus;
+#elif defined(CONFIG_GEMINI)
+	_machine = _MACH_gemini;
 #else
 #error "Machine not defined correctly"
 #endif /* CONFIG_APUS */
@@ -475,6 +493,9 @@
                 mbx_init(r3, r4, r5, r6, r7);
                 break;
 #endif
+	case _MACH_gemini:
+		gemini_init(r3, r4, r5, r6, r7);
+		break;
 	default:
 		printk("Unknown machine type in identify_machine!\n");
 	}
@@ -500,16 +521,18 @@
 	}
 }
 
-__initfunc(void
-	   ppc_init(void))
+void __init ppc_init(void)
 {
+	/* clear the progress line */
+	if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
+	
 	if (ppc_md.init != NULL) {
 		ppc_md.init();
 	}
 }
 
-__initfunc(void setup_arch(char **cmdline_p,
-			   unsigned long * memory_start_p, unsigned long * memory_end_p))
+void __init setup_arch(char **cmdline_p,
+		       unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
 	extern int panic_timeout;
 	extern char _etext[], _edata[];
@@ -526,7 +549,7 @@
  
 	/* reboot on panic */	
 	panic_timeout = 180;
-	
+
 	init_mm.start_code = PAGE_OFFSET;
 	init_mm.end_code = (unsigned long) _etext;
 	init_mm.end_data = (unsigned long) _edata;
@@ -541,7 +564,7 @@
 
 	ppc_md.setup_arch(memory_start_p, memory_end_p);
 	/* clear the progress line */
-	if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff);
+	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
 }
 
 void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c
--- v2.3.15/linux/arch/ppc/kernel/signal.c	Thu Jul 22 09:47:55 1999
+++ linux/arch/ppc/kernel/signal.c	Tue Aug 31 11:36:43 1999
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/ppc/kernel/signal.c
  *
- *  $Id: signal.c,v 1.25 1999/06/17 05:40:20 paulus Exp $
+ *  $Id: signal.c,v 1.27 1999/08/03 19:16:38 cort Exp $
  *
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -227,7 +227,7 @@
 			| (saved_regs[PT_MSR] & MSR_USERCHANGE);
 		memcpy(regs, saved_regs, GP_REGS_SIZE);
 
-		if (copy_from_user(current->tss.fpr, &sr->fp_regs,
+		if (copy_from_user(current->thread.fpr, &sr->fp_regs,
 				   sizeof(sr->fp_regs)))
 			goto badframe;
 
@@ -269,7 +269,7 @@
 		if (regs->msr & MSR_FP)
 			giveup_fpu(current);
 	if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
-	    || __copy_to_user(&frame->fp_regs, current->tss.fpr,
+	    || __copy_to_user(&frame->fp_regs, current->thread.fpr,
 			      ELF_NFPREG * sizeof(double))
 	    || __put_user(0x38007777UL, &frame->tramp[0])    /* li r0,0x7777 */
 	    || __put_user(0x44000002UL, &frame->tramp[1]))   /* sc */
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.3.15/linux/arch/ppc/kernel/smp.c	Thu Aug 12 11:50:14 1999
+++ linux/arch/ppc/kernel/smp.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: smp.c,v 1.55 1999/07/03 08:57:09 davem Exp $
+ * $Id: smp.c,v 1.61 1999/08/24 22:06:26 cort Exp $
  *
  * Smp support for ppc.
  *
@@ -12,7 +12,6 @@
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/tasks.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
@@ -31,8 +30,10 @@
 #include <asm/spinlock.h>
 #include <asm/hardirq.h>
 #include <asm/softirq.h>
+#include <asm/init.h>
 #include <asm/io.h>
 #include <asm/prom.h>
+#include <asm/smp.h>
 
 #include "time.h"
 int first_cpu_booted = 0;
@@ -241,6 +242,7 @@
 void __init smp_boot_cpus(void)
 {
 	extern struct task_struct *current_set[NR_CPUS];
+	extern unsigned long smp_chrp_cpu_nr;
 	extern void __secondary_start_psurge(void);
 	extern void __secondary_start_chrp(void);
 	int i, cpu_nr;
@@ -285,9 +287,13 @@
 		cpu_nr = 2; 
 		break;
 	case _MACH_chrp:
+		/* openpic doesn't report # of cpus, just # possible -- Cort */
+#if 0		
 		cpu_nr = ((openpic_read(&OpenPIC->Global.Feature_Reporting0)
 				 & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
 				OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT)+1;
+#endif
+		cpu_nr = smp_chrp_cpu_nr;
 		break;
 	}
 
@@ -301,7 +307,7 @@
 		
 		/* create a process for the processor */
 		kernel_thread(start_secondary, NULL, CLONE_PID);
-		p = task[i];
+		p = init_tasks[i];
 		if ( !p )
 			panic("No idle task for secondary processor\n");
 		p->processor = i;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/softemu8xx.c linux/arch/ppc/kernel/softemu8xx.c
--- v2.3.15/linux/arch/ppc/kernel/softemu8xx.c	Sat May 22 13:03:00 1999
+++ linux/arch/ppc/kernel/softemu8xx.c	Tue Aug 31 11:36:43 1999
@@ -64,7 +64,7 @@
 	disp = instword & 0xffff;
 
 	ea = (uint *)(regs->gpr[idxreg] + disp);
-	ip = (uint *)&current->tss.fpr[flreg];
+	ip = (uint *)&current->thread.fpr[flreg];
 
 	switch ( inst )
 	{
@@ -108,7 +108,7 @@
 		break;
 	case FMR:
 		/* assume this is a fp move -- Cort */
-		memcpy( ip, &current->tss.fpr[(instword>>11)&0x1f],
+		memcpy( ip, &current->thread.fpr[(instword>>11)&0x1f],
 			sizeof(double) );
 		break;
 	default:
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.3.15/linux/arch/ppc/kernel/time.c	Mon Jun 28 13:40:39 1999
+++ linux/arch/ppc/kernel/time.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: time.c,v 1.50 1999/06/05 00:23:20 cort Exp $
+ * $Id: time.c,v 1.55 1999/08/31 06:54:09 davem Exp $
  * Common time routines among all ppc machines.
  *
  * Written by Cort Dougan (cort@cs.nmt.edu) to merge
@@ -52,7 +52,7 @@
 void smp_local_timer_interrupt(struct pt_regs *);
 
 /* keep track of when we need to update the rtc */
-unsigned long last_rtc_update = 0;
+time_t last_rtc_update = 0;
 
 /* The decrementer counts down by 128 every 128ns on a 601. */
 #define DECREMENTER_COUNT_601	(1000000000 / HZ)
@@ -110,15 +110,15 @@
 			/*
 			 * update the rtc when needed
 			 */
-			if ( xtime.tv_sec > last_rtc_update + 660 )
+			if ( (time_status & STA_UNSYNC) &&
+			     ((xtime.tv_sec > last_rtc_update + 60) ||
+			      (xtime.tv_sec < last_rtc_update)) )
 			{
-				if (ppc_md.set_rtc_time(xtime.tv_sec) == 0) {
+				if (ppc_md.set_rtc_time(xtime.tv_sec) == 0)
 					last_rtc_update = xtime.tv_sec;
-				}
-				else {
+				else
 					/* do it again in 60 s */
-					last_rtc_update = xtime.tv_sec - 60;
-				}
+					last_rtc_update = xtime.tv_sec;
 			}
 		}
 	}
@@ -176,7 +176,7 @@
 }
 
 
-__initfunc(void time_init(void))
+void __init time_init(void)
 {
         if (ppc_md.time_init != NULL)
         {
@@ -196,10 +196,8 @@
         xtime.tv_usec = 0;
 
 	set_dec(decrementer_count);
-	/* mark the rtc/on-chip timer as in sync
-	 * so we don't update right away
-	 */
-	last_rtc_update = xtime.tv_sec;
+	/* allow setting the time right away */
+	last_rtc_update = 0;
 }
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/time.h linux/arch/ppc/kernel/time.h
--- v2.3.15/linux/arch/ppc/kernel/time.h	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/time.h	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: time.h,v 1.11 1999/03/18 04:16:34 cort Exp $
+ * $Id: time.h,v 1.12 1999/08/27 04:21:23 cort Exp $
  * Common time prototypes and such for all ppc machines.
  *
  * Written by Cort Dougan (cort@cs.nmt.edu) to merge
@@ -15,7 +15,7 @@
 extern unsigned long mktime(unsigned int, unsigned int, unsigned int,
 			    unsigned int, unsigned int, unsigned int);
 extern void to_tm(int tim, struct rtc_time * tm);
-extern unsigned long last_rtc_update;
+extern time_t last_rtc_update;
 
 int via_calibrate_decr(void);
 
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/totalmp.c linux/arch/ppc/kernel/totalmp.c
--- v2.3.15/linux/arch/ppc/kernel/totalmp.c	Wed Sep 30 10:14:17 1998
+++ linux/arch/ppc/kernel/totalmp.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: totalmp.c,v 1.5 1998/08/26 13:58:50 cort Exp $
+ * $Id: totalmp.c,v 1.6 1999/08/31 06:54:10 davem Exp $
  *
  * Support for Total Impact's TotalMP PowerPC accelerator board.
  *
@@ -25,7 +25,7 @@
 
 extern inline void openpic_writefield(volatile u_int *addr, u_int mask,
 				      u_int field);
-__initfunc(void totalmp_init(void))
+void __init totalmp_init(void)
 {
 	struct pci_dev *dev;
 	u32 val;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v2.3.15/linux/arch/ppc/kernel/traps.c	Sat May 22 13:03:00 1999
+++ linux/arch/ppc/kernel/traps.c	Tue Aug 31 11:36:43 1999
@@ -229,26 +229,26 @@
 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);	
+	extern int do_mathemu(struct pt_regs *);
+	int errcode;
 
-	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);
-		}
-	}
-	else {
+	if (!user_mode(regs)) {
+		show_regs(regs);
+#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
+		debugger(regs);
+#endif
+		print_backtrace((unsigned long *)regs->gpr[1]);
 		panic("Kernel Mode Software FPU Emulation");
 	}
+
+	if ((errcode = do_mathemu(regs))) {
+		if (errcode > 0)
+			_exception(SIGFPE, regs);
+		else if (errcode == -EFAULT;
+			_exception(SIGSEGV, regs);
+		else
+			_exception(SIGILL, regs);
+	}
 }
 #endif
 
@@ -259,6 +259,6 @@
 	       regs->nip, regs->msr, regs->trap);
 }
 
-__initfunc(void trap_init(void))
+void __init trap_init(void)
 {
 }
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/lib/locks.c linux/arch/ppc/lib/locks.c
--- v2.3.15/linux/arch/ppc/lib/locks.c	Wed Mar 10 21:30:32 1999
+++ linux/arch/ppc/lib/locks.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: locks.c,v 1.23 1999/02/12 07:06:32 cort Exp $
+ * $Id: locks.c,v 1.24 1999/08/03 19:16:47 cort Exp $
  *
  * Locks for smp ppc 
  * 
@@ -113,7 +113,7 @@
 #ifdef DEBUG_LOCKS
 	if ( rw->lock == 0 )
 		printk("_read_unlock(): %s/%d (nip %08lX) lock %lx\n",
-		       current->comm,current->pid,current->tss.regs->nip,
+		       current->comm,current->pid,current->thread.regs->nip,
 		      rw->lock);
 #endif /* DEBUG_LOCKS */
 	wmb();
@@ -173,7 +173,7 @@
 #ifdef DEBUG_LOCKS
 	if ( !(rw->lock & (1<<31)) )
 		printk("_write_lock(): %s/%d (nip %08lX) lock %lx\n",
-		      current->comm,current->pid,current->tss.regs->nip,
+		      current->comm,current->pid,current->thread.regs->nip,
 		      rw->lock);
 #endif /* DEBUG_LOCKS */
 	wmb();
@@ -189,7 +189,7 @@
 	if ( (signed long)(task->lock_depth) < 0 )
 	{
 		printk("__lock_kernel(): %s/%d (nip %08lX) lock depth %x\n",
-		      task->comm,task->pid,task->tss.regs->nip,
+		      task->comm,task->pid,task->thread.regs->nip,
 		      task->lock_depth);
 	}
 #endif /* DEBUG_LOCKS */
@@ -219,7 +219,7 @@
 	{
 		printk("__unlock_kernel(): %s/%d (nip %08lX) "
 		       "lock depth %x flags %lx\n",
-		       task->comm,task->pid,task->tss.regs->nip,
+		       task->comm,task->pid,task->thread.regs->nip,
 		       task->lock_depth, klock_info.kernel_flag);
 		klock_info.akp = NO_PROC_ID;		
 		klock_info.kernel_flag = 0;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/Makefile linux/arch/ppc/math-emu/Makefile
--- v2.3.15/linux/arch/ppc/math-emu/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/Makefile	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,20 @@
+#
+#
+#
+
+O_TARGET := math-emu.o
+
+O_OBJS   := math.o fmr.o lfd.o stfd.o
+
+ifdef CONFIG_MATH_EMULATION
+O_OBJS +=   fabs.o fadd.o fadds.o fcmpo.o fcmpu.o fctiw.o fctiwz.o	\
+	    fdiv.o fdivs.o fmadd.o fmadds.o fmsub.o fmsubs.o 		\
+	    fmul.o fmuls.o fnabs.o fneg.o fnmadd.o fnmadds.o		\
+	    fnmsub.o fnmsubs.o fres.o frsp.o frsqrte.o fsel.o		\
+	    fsqrt.o fsqrts.o fsub.o fsubs.o lfs.o			\
+	    mcrfs.o mffs.o mtfsb0.o mtfsb1.o mtfsf.o mtfsfi.o		\
+	    stfiwx.o stfs.o udivmodti4.o types.o
+endif
+
+include $(TOPDIR)/Rules.make
+
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/double.h linux/arch/ppc/math-emu/double.h
--- v2.3.15/linux/arch/ppc/math-emu/double.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/double.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,129 @@
+/*
+ * Definitions for IEEE Double Precision
+ */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel kid.  Go buy yourself a real computer."
+#endif
+
+#if _FP_W_TYPE_SIZE < 64
+#define _FP_FRACTBITS_D		(2 * _FP_W_TYPE_SIZE)
+#else
+#define _FP_FRACTBITS_D		_FP_W_TYPE_SIZE
+#endif
+
+#define _FP_FRACBITS_D		53
+#define _FP_FRACXBITS_D		(_FP_FRACTBITS_D - _FP_FRACBITS_D)
+#define _FP_WFRACBITS_D		(_FP_WORKBITS + _FP_FRACBITS_D)
+#define _FP_WFRACXBITS_D	(_FP_FRACTBITS_D - _FP_WFRACBITS_D)
+#define _FP_EXPBITS_D		11
+#define _FP_EXPBIAS_D		1023
+#define _FP_EXPMAX_D		2047
+
+#define _FP_QNANBIT_D		\
+	((_FP_W_TYPE)1 << ((_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE))
+#define _FP_IMPLBIT_D		\
+	((_FP_W_TYPE)1 << ((_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE))
+#define _FP_OVERFLOW_D		\
+	((_FP_W_TYPE)1 << (_FP_WFRACBITS_D % _FP_W_TYPE_SIZE))
+
+#if _FP_W_TYPE_SIZE < 64
+
+union _FP_UNION_D
+{
+  double flt;
+  struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned sign  : 1;
+    unsigned exp   : _FP_EXPBITS_D;
+    unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
+    unsigned frac0 : _FP_W_TYPE_SIZE;
+#else
+    unsigned frac0 : _FP_W_TYPE_SIZE;
+    unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
+    unsigned exp   : _FP_EXPBITS_D;
+    unsigned sign  : 1;
+#endif
+  } bits __attribute__((packed));
+};
+
+#define FP_DECL_D(X)		_FP_DECL(2,X)
+#define FP_UNPACK_RAW_D(X,val)	_FP_UNPACK_RAW_2(D,X,val)
+#define FP_PACK_RAW_D(val,X)	_FP_PACK_RAW_2(D,val,X)
+
+#define FP_UNPACK_D(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_2(D,X,val);		\
+    _FP_UNPACK_CANONICAL(D,2,X);	\
+  } while (0)
+
+#define FP_PACK_D(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(D,2,X);		\
+    _FP_PACK_RAW_2(D,val,X);		\
+  } while (0)
+
+#define FP_NEG_D(R,X)		_FP_NEG(D,2,R,X)
+#define FP_ADD_D(R,X,Y)		_FP_ADD(D,2,R,X,Y)
+#define FP_SUB_D(R,X,Y)		_FP_SUB(D,2,R,X,Y)
+#define FP_MUL_D(R,X,Y)		_FP_MUL(D,2,R,X,Y)
+#define FP_DIV_D(R,X,Y)		_FP_DIV(D,2,R,X,Y)
+#define FP_SQRT_D(R,X)		_FP_SQRT(D,2,R,X)
+
+#define FP_CMP_D(r,X,Y,un)	_FP_CMP(D,2,r,X,Y,un)
+#define FP_CMP_EQ_D(r,X,Y)	_FP_CMP_EQ(D,2,r,X,Y)
+
+#define FP_TO_INT_D(r,X,rsz,rsg)  _FP_TO_INT(D,2,r,X,rsz,rsg)
+#define FP_FROM_INT_D(X,r,rs,rt)  _FP_FROM_INT(D,2,X,r,rs,rt)
+
+#else
+
+union _FP_UNION_D
+{
+  double flt;
+  struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned sign : 1;
+    unsigned exp  : _FP_EXPBITS_D;
+    unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
+#else
+    unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
+    unsigned exp  : _FP_EXPBITS_D;
+    unsigned sign : 1;
+#endif
+  } bits __attribute__((packed));
+};
+
+#define FP_DECL_D(X)		_FP_DECL(1,X)
+#define FP_UNPACK_RAW_D(X,val)	_FP_UNPACK_RAW_1(D,X,val)
+#define FP_PACK_RAW_D(val,X)	_FP_PACK_RAW_1(D,val,X)
+
+#define FP_UNPACK_D(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_1(D,X,val);		\
+    _FP_UNPACK_CANONICAL(D,1,X);	\
+  } while (0)
+
+#define FP_PACK_D(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(D,1,X);		\
+    _FP_PACK_RAW_1(D,val,X);		\
+  } while (0)
+
+#define FP_NEG_D(R,X)		_FP_NEG(D,1,R,X)
+#define FP_ADD_D(R,X,Y)		_FP_ADD(D,1,R,X,Y)
+#define FP_SUB_D(R,X,Y)		_FP_SUB(D,1,R,X,Y)
+#define FP_MUL_D(R,X,Y)		_FP_MUL(D,1,R,X,Y)
+#define FP_DIV_D(R,X,Y)		_FP_DIV(D,1,R,X,Y)
+#define FP_SQRT_D(R,X)		_FP_SQRT(D,1,R,X)
+
+/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
+   the target machine.  */
+
+#define FP_CMP_D(r,X,Y,un)	_FP_CMP(D,1,r,X,Y,un)
+#define FP_CMP_EQ_D(r,X,Y)	_FP_CMP_EQ(D,1,r,X,Y)
+
+#define FP_TO_INT_D(r,X,rsz,rsg)  _FP_TO_INT(D,1,r,X,rsz,rsg)
+#define FP_FROM_INT_D(X,r,rs,rt)  _FP_FROM_INT(D,1,X,r,rs,rt)
+
+#endif /* W_TYPE_SIZE < 64 */
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fabs.c linux/arch/ppc/math-emu/fabs.c
--- v2.3.15/linux/arch/ppc/math-emu/fabs.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fabs.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,21 @@
+/* $Id: fabs.c,v 1.1 1999/08/23 18:59:21 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+fabs(u32 *frD, u32 *frB)
+{
+	frD[0] = frB[0] & 0x7fffffff;
+	frD[1] = frB[1];
+
+#ifdef DEBUG
+	printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
+	dump_double(frD);
+	printk("\n");
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fadd.c linux/arch/ppc/math-emu/fadd.c
--- v2.3.15/linux/arch/ppc/math-emu/fadd.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fadd.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,41 @@
+/* $Id: fadd.c,v 1.1 1999/08/23 18:59:22 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fadd(void *frD, void *frA, void *frB)
+{
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(R);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+	if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
+		ret |= EFLAG_VXISI;
+
+	FP_ADD_D(R, A, B);
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_D(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fadds.c linux/arch/ppc/math-emu/fadds.c
--- v2.3.15/linux/arch/ppc/math-emu/fadds.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fadds.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,42 @@
+/* $Id: fadds.c,v 1.1 1999/08/23 18:59:25 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fadds(void *frD, void *frA, void *frB)
+{
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(R);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+	if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
+		ret |= EFLAG_VXISI;
+
+	FP_ADD_D(R, A, B);
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_DS(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fcmpo.c linux/arch/ppc/math-emu/fcmpo.c
--- v2.3.15/linux/arch/ppc/math-emu/fcmpo.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fcmpo.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,49 @@
+/* $Id: fcmpo.c,v 1.1 1999/08/23 18:59:26 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fcmpo(u32 *ccr, int crfD, void *frA, void *frB)
+{
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	int code[4] = { (1 << 3), (1 << 1), (1 << 2), (1 << 0) };
+	long cmp;
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crfD, frA, frB);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+	if (A_c == FP_CLS_NAN || B_c == FP_CLS_NAN)
+		ret |= EFLAG_VXVC;
+
+	FP_CMP_D(cmp, A, B, 2);
+	cmp = code[(cmp + 1) & 3];
+
+	__FPU_FPSCR &= ~(0x1f000);
+	__FPU_FPSCR |= (cmp << 12);
+
+	*ccr &= ~(15 << ((7 - crfD) << 2));
+	*ccr |= (cmp << ((7 - crfD) << 2));
+ 
+#ifdef DEBUG
+	printk("CR: %08x\n", *ccr);
+#endif
+
+	return ret;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fcmpu.c linux/arch/ppc/math-emu/fcmpu.c
--- v2.3.15/linux/arch/ppc/math-emu/fcmpu.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fcmpu.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,45 @@
+/* $Id: fcmpu.c,v 1.1 1999/08/23 18:59:28 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fcmpu(u32 *ccr, int crfD, void *frA, void *frB)
+{
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	int code[4] = { (1 << 3), (1 << 1), (1 << 2), (1 << 0) };
+	long cmp;
+
+#ifdef DEBUG
+	printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crfD, frA, frB);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+	FP_CMP_D(cmp, A, B, 2);
+	cmp = code[(cmp + 1) & 3];
+
+	__FPU_FPSCR &= ~(0x1f000);
+	__FPU_FPSCR |= (cmp << 12);
+
+	*ccr &= ~(15 << ((7 - crfD) << 2));
+	*ccr |= (cmp << ((7 - crfD) << 2));
+
+#ifdef DEBUG
+	printk("CR: %08x\n", *ccr);
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fctiw.c linux/arch/ppc/math-emu/fctiw.c
--- v2.3.15/linux/arch/ppc/math-emu/fctiw.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fctiw.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,28 @@
+/* $Id: fctiw.c,v 1.1 1999/08/23 18:59:30 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fctiw(u32 *frD, void *frB)
+{
+	FP_DECL_D(B);
+	unsigned int r;
+
+	__FP_UNPACK_D(B, frB);
+	FP_TO_INT_D(r, B, 32, 1);
+	frD[1] = r;
+
+#ifdef DEBUG
+	printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
+	dump_double(frD);
+	printk("\n");
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fctiwz.c linux/arch/ppc/math-emu/fctiwz.c
--- v2.3.15/linux/arch/ppc/math-emu/fctiwz.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fctiwz.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,35 @@
+/* $Id: fctiwz.c,v 1.1 1999/08/23 18:59:31 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fctiwz(u32 *frD, void *frB)
+{
+	FP_DECL_D(B);
+	u32 fpscr;
+	unsigned int r;
+
+	fpscr = __FPU_FPSCR;
+	__FPU_FPSCR &= ~(3);
+	__FPU_FPSCR |= FP_RND_ZERO;
+
+	__FP_UNPACK_D(B, frB);
+	FP_TO_INT_D(r, B, 32, 1);
+	frD[1] = r;
+
+	__FPU_FPSCR = fpscr;
+
+#ifdef DEBUG
+	printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
+	dump_double(frD);
+	printk("\n");
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fdiv.c linux/arch/ppc/math-emu/fdiv.c
--- v2.3.15/linux/arch/ppc/math-emu/fdiv.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fdiv.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,56 @@
+/* $Id: fdiv.c,v 1.1 1999/08/23 18:59:33 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fdiv(void *frD, void *frA, void *frB)
+{
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(R);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+	if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) {
+		ret |= EFLAG_VXZDZ;
+#ifdef DEBUG
+		printk("%s: FPSCR_VXZDZ raised\n", __FUNCTION__);
+#endif
+	}
+	if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) {
+		ret |= EFLAG_VXIDI;
+#ifdef DEBUG
+		printk("%s: FPSCR_VXIDI raised\n", __FUNCTION__);
+#endif
+	}
+
+	if (B_c == FP_CLS_ZERO && A_c != FP_CLS_ZERO) {
+		ret |= EFLAG_DIVZERO;
+		if (__FPU_TRAP_P(EFLAG_DIVZERO))
+			return ret;
+	}
+	FP_DIV_D(R, A, B);
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_D(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fdivs.c linux/arch/ppc/math-emu/fdivs.c
--- v2.3.15/linux/arch/ppc/math-emu/fdivs.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fdivs.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,58 @@
+/* $Id: fdivs.c,v 1.1 1999/08/23 18:59:35 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fdivs(void *frD, void *frA, void *frB)
+{
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(R);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+	if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) {
+		ret |= EFLAG_VXZDZ;
+#ifdef DEBUG
+		printk("%s: FPSCR_VXZDZ raised\n", __FUNCTION__);
+#endif
+	}
+	if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) {
+		ret |= EFLAG_VXIDI;
+#ifdef DEBUG
+		printk("%s: FPSCR_VXIDI raised\n", __FUNCTION__);
+#endif
+	}
+
+	if (B_c == FP_CLS_ZERO && A_c != FP_CLS_ZERO) {
+		ret |= EFLAG_DIVZERO;
+		if (__FPU_TRAP_P(EFLAG_DIVZERO))
+			return ret;
+	}
+
+	FP_DIV_D(R, A, B);
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_DS(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fmadd.c linux/arch/ppc/math-emu/fmadd.c
--- v2.3.15/linux/arch/ppc/math-emu/fmadd.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fmadd.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,51 @@
+/* $Id: fmadd.c,v 1.1 1999/08/23 18:59:36 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fmadd(void *frD, void *frA, void *frB, void *frC)
+{
+	FP_DECL_D(R);
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(C);
+	FP_DECL_D(T);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+	__FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+	printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+	if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+	    (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+                ret |= EFLAG_VXIMZ;
+
+	FP_MUL_D(T, A, C);
+
+	if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+		ret |= EFLAG_VXISI;
+
+	FP_ADD_D(R, T, B);
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_D(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fmadds.c linux/arch/ppc/math-emu/fmadds.c
--- v2.3.15/linux/arch/ppc/math-emu/fmadds.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fmadds.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,52 @@
+/* $Id: fmadds.c,v 1.1 1999/08/23 18:59:38 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fmadds(void *frD, void *frA, void *frB, void *frC)
+{
+	FP_DECL_D(R);
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(C);
+	FP_DECL_D(T);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+	__FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+	printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+	if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+	    (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+                ret |= EFLAG_VXIMZ;
+
+	FP_MUL_D(T, A, C);
+
+	if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+		ret |= EFLAG_VXISI;
+
+	FP_ADD_D(R, T, B);
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_DS(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fmr.c linux/arch/ppc/math-emu/fmr.c
--- v2.3.15/linux/arch/ppc/math-emu/fmr.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fmr.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,21 @@
+/* $Id: fmr.c,v 1.1 1999/08/23 18:59:40 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+fmr(u32 *frD, u32 *frB)
+{
+	frD[0] = frB[0];
+	frD[1] = frB[1];
+
+#ifdef DEBUG
+	printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
+	dump_double(frD);
+	printk("\n");
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fmsub.c linux/arch/ppc/math-emu/fmsub.c
--- v2.3.15/linux/arch/ppc/math-emu/fmsub.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fmsub.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,54 @@
+/* $Id: fmsub.c,v 1.1 1999/08/23 18:59:41 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fmsub(void *frD, void *frA, void *frB, void *frC)
+{
+	FP_DECL_D(R);
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(C);
+	FP_DECL_D(T);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+	__FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+	printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+	if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+	    (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+		ret |= EFLAG_VXIMZ;
+
+	FP_MUL_D(T, A, C);
+
+	if (B_c != FP_CLS_NAN)
+		B_s ^= 1;
+
+	if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+		ret |= EFLAG_VXISI;
+
+	FP_ADD_D(R, T, B);
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_D(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fmsubs.c linux/arch/ppc/math-emu/fmsubs.c
--- v2.3.15/linux/arch/ppc/math-emu/fmsubs.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fmsubs.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,55 @@
+/* $Id: fmsubs.c,v 1.1 1999/08/23 18:59:42 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fmsubs(void *frD, void *frA, void *frB, void *frC)
+{
+	FP_DECL_D(R);
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(C);
+	FP_DECL_D(T);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+	__FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+	printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+	if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+	    (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+		ret |= EFLAG_VXIMZ;
+
+	FP_MUL_D(T, A, C);
+
+	if (B_c != FP_CLS_NAN)
+		B_s ^= 1;
+
+	if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+		ret |= EFLAG_VXISI;
+
+	FP_ADD_D(R, T, B);
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_DS(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fmul.c linux/arch/ppc/math-emu/fmul.c
--- v2.3.15/linux/arch/ppc/math-emu/fmul.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fmul.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,45 @@
+/* $Id: fmul.c,v 1.1 1999/08/23 18:59:44 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fmul(void *frD, void *frA, void *frB)
+{
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(R);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+	       A_s, A_f1, A_f0, A_e, A_c, A_f1, A_f0, A_e + 1023);
+	printk("B: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+	       B_s, B_f1, B_f0, B_e, B_c, B_f1, B_f0, B_e + 1023);
+#endif
+
+	if ((A_c == FP_CLS_INF && B_c == FP_CLS_ZERO) ||
+	    (A_c == FP_CLS_ZERO && B_c == FP_CLS_INF))
+		ret |= EFLAG_VXIMZ;
+
+	FP_MUL_D(R, A, B);
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+	       R_s, R_f1, R_f0, R_e, R_c, R_f1, R_f0, R_e + 1023);
+#endif
+
+	return (ret | __FP_PACK_D(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fmuls.c linux/arch/ppc/math-emu/fmuls.c
--- v2.3.15/linux/arch/ppc/math-emu/fmuls.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fmuls.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,46 @@
+/* $Id: fmuls.c,v 1.1 1999/08/23 18:59:45 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fmuls(void *frD, void *frA, void *frB)
+{
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(R);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+	       A_s, A_f1, A_f0, A_e, A_c, A_f1, A_f0, A_e + 1023);
+	printk("B: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+	       B_s, B_f1, B_f0, B_e, B_c, B_f1, B_f0, B_e + 1023);
+#endif
+
+	if ((A_c == FP_CLS_INF && B_c == FP_CLS_ZERO) ||
+	    (A_c == FP_CLS_ZERO && B_c == FP_CLS_INF))
+		ret |= EFLAG_VXIMZ;
+
+	FP_MUL_D(R, A, B);
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n",
+	       R_s, R_f1, R_f0, R_e, R_c, R_f1, R_f0, R_e + 1023);
+#endif
+
+	return (ret | __FP_PACK_DS(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fnabs.c linux/arch/ppc/math-emu/fnabs.c
--- v2.3.15/linux/arch/ppc/math-emu/fnabs.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fnabs.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,21 @@
+/* $Id: fnabs.c,v 1.1 1999/08/23 18:59:47 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+fnabs(u32 *frD, u32 *frB)
+{
+	frD[0] = frB[0] | 0x80000000;
+	frD[1] = frB[1];
+
+#ifdef DEBUG
+	printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
+	dump_double(frD);
+	printk("\n");
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fneg.c linux/arch/ppc/math-emu/fneg.c
--- v2.3.15/linux/arch/ppc/math-emu/fneg.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fneg.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,21 @@
+/* $Id: fneg.c,v 1.1 1999/08/23 18:59:48 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+fneg(u32 *frD, u32 *frB)
+{
+	frD[0] = frB[0] ^ 0x80000000;
+	frD[1] = frB[1];
+
+#ifdef DEBUG
+	printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB);
+	dump_double(frD);
+	printk("\n");
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fnmadd.c linux/arch/ppc/math-emu/fnmadd.c
--- v2.3.15/linux/arch/ppc/math-emu/fnmadd.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fnmadd.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,54 @@
+/* $Id: fnmadd.c,v 1.1 1999/08/23 18:59:50 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fnmadd(void *frD, void *frA, void *frB, void *frC)
+{
+	FP_DECL_D(R);
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(C);
+	FP_DECL_D(T);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+	__FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+	printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+	if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+	    (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+                ret |= EFLAG_VXIMZ;
+
+	FP_MUL_D(T, A, C);
+
+	if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+		ret |= EFLAG_VXISI;
+
+	FP_ADD_D(R, T, B);
+
+	if (R_c != FP_CLS_NAN)
+		R_s ^= 1;
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_D(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fnmadds.c linux/arch/ppc/math-emu/fnmadds.c
--- v2.3.15/linux/arch/ppc/math-emu/fnmadds.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fnmadds.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,55 @@
+/* $Id: fnmadds.c,v 1.1 1999/08/23 18:59:51 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fnmadds(void *frD, void *frA, void *frB, void *frC)
+{
+	FP_DECL_D(R);
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(C);
+	FP_DECL_D(T);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+	__FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+	printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+	if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+	    (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+                ret |= EFLAG_VXIMZ;
+
+	FP_MUL_D(T, A, C);
+
+	if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+		ret |= EFLAG_VXISI;
+
+	FP_ADD_D(R, T, B);
+
+	if (R_c != FP_CLS_NAN)
+		R_s ^= 1;
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_DS(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fnmsub.c linux/arch/ppc/math-emu/fnmsub.c
--- v2.3.15/linux/arch/ppc/math-emu/fnmsub.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fnmsub.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,57 @@
+/* $Id: fnmsub.c,v 1.1 1999/08/23 18:59:53 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fnmsub(void *frD, void *frA, void *frB, void *frC)
+{
+	FP_DECL_D(R);
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(C);
+	FP_DECL_D(T);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+	__FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+	printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+	if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+	    (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+		ret |= EFLAG_VXIMZ;
+
+	FP_MUL_D(T, A, C);
+
+	if (B_c != FP_CLS_NAN)
+		B_s ^= 1;
+
+	if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+		ret |= EFLAG_VXISI;
+
+	FP_ADD_D(R, T, B);
+
+	if (R_c != FP_CLS_NAN)
+		R_s ^= 1;
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_D(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fnmsubs.c linux/arch/ppc/math-emu/fnmsubs.c
--- v2.3.15/linux/arch/ppc/math-emu/fnmsubs.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fnmsubs.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,58 @@
+/* $Id: fnmsubs.c,v 1.1 1999/08/23 18:59:54 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fnmsubs(void *frD, void *frA, void *frB, void *frC)
+{
+	FP_DECL_D(R);
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(C);
+	FP_DECL_D(T);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+	__FP_UNPACK_D(C, frC);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+	printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c);
+#endif
+
+	if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
+	    (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
+		ret |= EFLAG_VXIMZ;
+
+	FP_MUL_D(T, A, C);
+
+	if (B_c != FP_CLS_NAN)
+		B_s ^= 1;
+
+	if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
+		ret |= EFLAG_VXISI;
+
+	FP_ADD_D(R, T, B);
+
+	if (R_c != FP_CLS_NAN)
+		R_s ^= 1;
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_DS(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fres.c linux/arch/ppc/math-emu/fres.c
--- v2.3.15/linux/arch/ppc/math-emu/fres.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fres.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,15 @@
+/* $Id: fres.c,v 1.1 1999/08/23 18:59:56 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+fres(void *frD, void *frB)
+{
+#ifdef DEBUG
+	printk("%s: %p %p\n", __FUNCTION__, frD, frB);
+#endif
+	return -ENOSYS;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/frsp.c linux/arch/ppc/math-emu/frsp.c
--- v2.3.15/linux/arch/ppc/math-emu/frsp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/frsp.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,28 @@
+/* $Id: frsp.c,v 1.1 1999/08/23 18:59:57 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+frsp(void *frD, void *frB)
+{
+	FP_DECL_D(B);
+
+#ifdef DEBUG
+	printk("%s: D %p, B %p\n", __FUNCTION__, frD, frB);
+#endif
+
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+	return __FP_PACK_DS(frD, B);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/frsqrte.c linux/arch/ppc/math-emu/frsqrte.c
--- v2.3.15/linux/arch/ppc/math-emu/frsqrte.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/frsqrte.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,15 @@
+/* $Id: frsqrte.c,v 1.1 1999/08/23 18:59:58 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+frsqrte(void *frD, void *frB)
+{
+#ifdef DEBUG
+	printk("%s: %p %p\n", __FUNCTION__, frD, frB);
+#endif
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fsel.c linux/arch/ppc/math-emu/fsel.c
--- v2.3.15/linux/arch/ppc/math-emu/fsel.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fsel.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,41 @@
+/* $Id: fsel.c,v 1.1 1999/08/23 18:59:59 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fsel(u32 *frD, void *frA, u32 *frB, u32 *frC)
+{
+	FP_DECL_D(A);
+
+#ifdef DEBUG
+	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %08x %08x\n", frB[0], frB[1]);
+	printk("C: %08x %08x\n", frC[0], frC[1]);
+#endif
+
+	if (A_c == FP_CLS_NAN || (A_c != FP_CLS_ZERO && A_s)) {
+		frD[0] = frB[0];
+		frD[1] = frB[1];
+	} else {
+		frD[0] = frC[0];
+		frD[1] = frC[1];
+	}
+
+#ifdef DEBUG
+	printk("D: %08x.%08x\n", frD[0], frD[1]);
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fsqrt.c linux/arch/ppc/math-emu/fsqrt.c
--- v2.3.15/linux/arch/ppc/math-emu/fsqrt.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fsqrt.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,40 @@
+/* $Id: fsqrt.c,v 1.1 1999/08/23 19:00:01 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fsqrt(void *frD, void *frB)
+{
+	FP_DECL_D(B);
+	FP_DECL_D(R);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frB);
+#endif
+
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+	if (B_s && B_c != FP_CLS_ZERO)
+		ret |= EFLAG_VXSQRT;
+	if (B_c == FP_CLS_NAN)
+		ret |= EFLAG_VXSNAN;
+
+	FP_SQRT_D(R, B);
+
+#ifdef DEBUG
+	printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_D(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fsqrts.c linux/arch/ppc/math-emu/fsqrts.c
--- v2.3.15/linux/arch/ppc/math-emu/fsqrts.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fsqrts.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,41 @@
+/* $Id: fsqrts.c,v 1.1 1999/08/23 19:00:03 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fsqrts(void *frD, void *frB)
+{
+	FP_DECL_D(B);
+	FP_DECL_D(R);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frB);
+#endif
+
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+	if (B_s && B_c != FP_CLS_ZERO)
+		ret |= EFLAG_VXSQRT;
+	if (B_c == FP_CLS_NAN)
+		ret |= EFLAG_VXSNAN;
+
+	FP_SQRT_D(R, B);
+
+#ifdef DEBUG
+	printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_DS(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fsub.c linux/arch/ppc/math-emu/fsub.c
--- v2.3.15/linux/arch/ppc/math-emu/fsub.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fsub.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,44 @@
+/* $Id: fsub.c,v 1.1 1999/08/23 19:00:05 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+fsub(void *frD, void *frA, void *frB)
+{
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(R);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+	if (B_c != FP_CLS_NAN)
+		B_s ^= 1;
+
+	if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
+		ret |= EFLAG_VXISI;
+
+	FP_ADD_D(R, A, B);
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_D(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/fsubs.c linux/arch/ppc/math-emu/fsubs.c
--- v2.3.15/linux/arch/ppc/math-emu/fsubs.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/fsubs.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,45 @@
+/* $Id: fsubs.c,v 1.1 1999/08/23 19:00:07 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+fsubs(void *frD, void *frA, void *frB)
+{
+	FP_DECL_D(A);
+	FP_DECL_D(B);
+	FP_DECL_D(R);
+	int ret = 0;
+
+#ifdef DEBUG
+	printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB);
+#endif
+
+	__FP_UNPACK_D(A, frA);
+	__FP_UNPACK_D(B, frB);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+	printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c);
+#endif
+
+	if (B_c != FP_CLS_NAN)
+		B_s ^= 1;
+
+	if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
+		ret |= EFLAG_VXISI;
+
+	FP_ADD_D(R, A, B);
+
+#ifdef DEBUG
+	printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return (ret | __FP_PACK_DS(frD, R));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/lfd.c linux/arch/ppc/math-emu/lfd.c
--- v2.3.15/linux/arch/ppc/math-emu/lfd.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/lfd.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,22 @@
+/* $Id: lfd.c,v 1.1 1999/08/23 19:00:08 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "sfp-machine.h"
+#include "double.h"
+
+int
+lfd(void *frD, void *ea)
+{
+	if (copy_from_user(frD, ea, sizeof(double)))
+		return -EFAULT;
+#ifdef DEBUG
+	printk("%s: D %p, ea %p: ", __FUNCTION__, frD, ea);
+	dump_double(frD);
+	printk("\n");
+#endif
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/lfs.c linux/arch/ppc/math-emu/lfs.c
--- v2.3.15/linux/arch/ppc/math-emu/lfs.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/lfs.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,40 @@
+/* $Id: lfs.c,v 1.1 1999/08/23 19:00:10 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+lfs(void *frD, void *ea)
+{
+	FP_DECL_D(R);
+	FP_DECL_S(A);
+	float f;
+
+#ifdef DEBUG
+	printk("%s: D %p, ea %p\n", __FUNCTION__, frD, ea);
+#endif
+
+	if (copy_from_user(&f, ea, sizeof(float)))
+		return -EFAULT;
+
+	__FP_UNPACK_S(A, &f);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %ld (%ld) [%08lx]\n", A_s, A_f, A_e, A_c,
+	       *(unsigned long *)&f);
+#endif
+
+	FP_CONV(D, S, 2, 1, R, A);
+
+#ifdef DEBUG
+	printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c);
+#endif
+
+	return __FP_PACK_D(frD, R);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/math.c linux/arch/ppc/math-emu/math.c
--- v2.3.15/linux/arch/ppc/math-emu/math.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/math.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,485 @@
+/* $Id: math.c,v 1.1 1999/08/23 19:00:11 cort Exp $
+ * arch/ppc/math-emu/math.c
+ *
+ * Copyright (C) 1999  Eddie C. Dost  (ecd@atecom.com)
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+
+#include "sfp-machine.h"
+#include "double.h"
+
+#define FLOATFUNC(x)	extern int x(void *, void *, void *, void *)
+
+FLOATFUNC(fadd);
+FLOATFUNC(fadds);
+FLOATFUNC(fdiv);
+FLOATFUNC(fdivs);
+FLOATFUNC(fmul);
+FLOATFUNC(fmuls);
+FLOATFUNC(fsub);
+FLOATFUNC(fsubs);
+
+FLOATFUNC(fmadd);
+FLOATFUNC(fmadds);
+FLOATFUNC(fmsub);
+FLOATFUNC(fmsubs);
+FLOATFUNC(fnmadd);
+FLOATFUNC(fnmadds);
+FLOATFUNC(fnmsub);
+FLOATFUNC(fnmsubs);
+
+FLOATFUNC(fctiw);
+FLOATFUNC(fctiwz);
+FLOATFUNC(frsp);
+
+FLOATFUNC(fcmpo);
+FLOATFUNC(fcmpu);
+
+FLOATFUNC(mcrfs);
+FLOATFUNC(mffs);
+FLOATFUNC(mtfsb0);
+FLOATFUNC(mtfsb1);
+FLOATFUNC(mtfsf);
+FLOATFUNC(mtfsfi);
+
+FLOATFUNC(lfd);
+FLOATFUNC(lfs);
+
+FLOATFUNC(stfd);
+FLOATFUNC(stfs);
+FLOATFUNC(stfiwx);
+
+FLOATFUNC(fabs);
+FLOATFUNC(fmr);
+FLOATFUNC(fnabs);
+FLOATFUNC(fneg);
+
+/* Optional */
+FLOATFUNC(fres);
+FLOATFUNC(frsqrte);
+FLOATFUNC(fsel);
+FLOATFUNC(fsqrt);
+FLOATFUNC(fsqrts);
+
+
+#define OP31		0x1f		/*   31 */
+#define LFS		0x30		/*   48 */
+#define LFSU		0x31		/*   49 */
+#define LFD		0x32		/*   50 */
+#define LFDU		0x33		/*   51 */
+#define STFS		0x34		/*   52 */
+#define STFSU		0x35		/*   53 */
+#define STFD		0x36		/*   54 */
+#define STFDU		0x37		/*   55 */
+#define OP59		0x3b		/*   59 */
+#define OP63		0x3f		/*   63 */
+
+/* Opcode 31: */
+/* X-Form: */
+#define LFSX		0x217		/*  535 */
+#define LFSUX		0x237		/*  567 */
+#define LFDX		0x257		/*  599 */
+#define LFDUX		0x277		/*  631 */
+#define STFSX		0x297		/*  663 */
+#define STFSUX		0x2b7		/*  695 */
+#define STFDX		0x2d7		/*  727 */
+#define STFDUX		0x2f7		/*  759 */
+#define STFIWX		0x3d7		/*  983 */
+
+/* Opcode 59: */
+/* A-Form: */
+#define FDIVS		0x012		/*   18 */
+#define FSUBS		0x014		/*   20 */
+#define FADDS		0x015		/*   21 */
+#define FSQRTS		0x016		/*   22 */
+#define FRES		0x018		/*   24 */
+#define FMULS		0x019		/*   25 */
+#define FMSUBS		0x01c		/*   28 */
+#define FMADDS		0x01d		/*   29 */
+#define FNMSUBS		0x01e		/*   30 */
+#define FNMADDS		0x01f		/*   31 */
+
+/* Opcode 63: */
+/* A-Form: */
+#define FDIV		0x012		/*   18 */
+#define FSUB		0x014		/*   20 */
+#define FADD		0x015		/*   21 */
+#define FSQRT		0x016		/*   22 */
+#define FSEL		0x017		/*   23 */
+#define FMUL		0x019		/*   25 */
+#define FRSQRTE		0x01a		/*   26 */
+#define FMSUB		0x01c		/*   28 */
+#define FMADD		0x01d		/*   29 */
+#define FNMSUB		0x01e		/*   30 */
+#define FNMADD		0x01f		/*   31 */
+
+/* X-Form: */
+#define FCMPU		0x000		/*    0	*/
+#define FRSP		0x00c		/*   12 */
+#define FCTIW		0x00e		/*   14 */
+#define FCTIWZ		0x00f		/*   15 */
+#define FCMPO		0x020		/*   32 */
+#define MTFSB1		0x026		/*   38 */
+#define FNEG		0x028		/*   40 */
+#define MCRFS		0x040		/*   64 */
+#define MTFSB0		0x046		/*   70 */
+#define FMR		0x048		/*   72 */
+#define MTFSFI		0x086		/*  134 */
+#define FNABS		0x088		/*  136 */
+#define FABS		0x108		/*  264 */
+#define MFFS		0x247		/*  583 */
+#define MTFSF		0x2c7		/*  711 */
+
+
+#define AB	2
+#define AC	3
+#define ABC	4
+#define D	5
+#define DU	6
+#define X	7
+#define XA	8
+#define XB	9
+#define XCR	11
+#define XCRB	12
+#define XCRI	13
+#define XCRL	16
+#define XE	14
+#define XEU	15
+#define XFLB	10
+
+#ifdef CONFIG_MATH_EMULATION
+static int
+record_exception(struct pt_regs *regs, int eflag)
+{
+	u32 fpscr;
+
+	fpscr = __FPU_FPSCR;
+
+	if (eflag) {
+		fpscr |= FPSCR_FX;
+		if (eflag & EFLAG_OVERFLOW)
+			fpscr |= FPSCR_OX;
+		if (eflag & EFLAG_UNDERFLOW)
+			fpscr |= FPSCR_UX;
+		if (eflag & EFLAG_DIVZERO)
+			fpscr |= FPSCR_ZX;
+		if (eflag & EFLAG_INEXACT)
+			fpscr |= FPSCR_XX;
+		if (eflag & EFLAG_VXSNAN)
+			fpscr |= FPSCR_VXSNAN;
+		if (eflag & EFLAG_VXISI)
+			fpscr |= FPSCR_VXISI;
+		if (eflag & EFLAG_VXIDI)
+			fpscr |= FPSCR_VXIDI;
+		if (eflag & EFLAG_VXZDZ)
+			fpscr |= FPSCR_VXZDZ;
+		if (eflag & EFLAG_VXIMZ)
+			fpscr |= FPSCR_VXIMZ;
+		if (eflag & EFLAG_VXVC)
+			fpscr |= FPSCR_VXVC;
+		if (eflag & EFLAG_VXSOFT)
+			fpscr |= FPSCR_VXSOFT;
+		if (eflag & EFLAG_VXSQRT)
+			fpscr |= FPSCR_VXSQRT;
+		if (eflag & EFLAG_VXCVI)
+			fpscr |= FPSCR_VXCVI;
+	}
+
+	fpscr &= ~(FPSCR_VX);
+	if (fpscr & (FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI |
+		     FPSCR_VXZDZ | FPSCR_VXIMZ | FPSCR_VXVC |
+		     FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI))
+		fpscr |= FPSCR_VX;
+
+	fpscr &= ~(FPSCR_FEX);
+	if (((fpscr & FPSCR_VX) && (fpscr & FPSCR_VE)) ||
+	    ((fpscr & FPSCR_OX) && (fpscr & FPSCR_OE)) ||
+	    ((fpscr & FPSCR_UX) && (fpscr & FPSCR_UE)) ||
+	    ((fpscr & FPSCR_ZX) && (fpscr & FPSCR_ZE)) ||
+	    ((fpscr & FPSCR_XX) && (fpscr & FPSCR_XE)))
+		fpscr |= FPSCR_FEX;
+
+	__FPU_FPSCR = fpscr;
+
+	return (fpscr & FPSCR_FEX) ? 1 : 0;
+}
+#endif /* CONFIG_MATH_EMULATION */
+
+int
+do_mathemu(struct pt_regs *regs)
+{
+	void *op0 = 0, *op1 = 0, *op2 = 0, *op3 = 0;
+	unsigned long pc = regs->nip;
+	signed short sdisp;
+	u32 insn = 0;
+	int idx = 0;
+#ifdef CONFIG_MATH_EMULATION
+	int (*func)(void *, void *, void *, void *);
+	int type = 0;
+	int eflag, trap;
+#endif
+
+	if (get_user(insn, (u32 *)pc))
+		return -EFAULT;
+
+#ifndef CONFIG_MATH_EMULATION
+	switch (insn >> 26) {
+	case LFD:
+		idx = (insn >> 16) & 0x1f;
+		sdisp = (insn & 0xffff);
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp);
+		lfd(op0, op1, op2, op3);
+		break;
+	case LFDU:
+		idx = (insn >> 16) & 0x1f;
+		sdisp = (insn & 0xffff);
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp);
+		lfd(op0, op1, op2, op3);
+		regs->gpr[idx] = (unsigned long)op1;
+		break;
+	case STFD:
+		idx = (insn >> 16) & 0x1f;
+		sdisp = (insn & 0xffff);
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp);
+		stfd(op0, op1, op2, op3);
+		break;
+	case STFDU:
+		idx = (insn >> 16) & 0x1f;
+		sdisp = (insn & 0xffff);
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp);
+		stfd(op0, op1, op2, op3);
+		regs->gpr[idx] = (unsigned long)op1;
+		break;
+	case OP63:
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)&current->tss.fpr[(insn >> 11) & 0x1f];
+		fmr(op0, op1, op2, op3);
+		break;
+	default:
+		goto illegal;
+	}
+#else /* CONFIG_MATH_EMULATION */
+	switch (insn >> 26) {
+	case LFS:	func = lfs;	type = D;	break;
+	case LFSU:	func = lfs;	type = DU;	break;
+	case LFD:	func = lfd;	type = D;	break;
+	case LFDU:	func = lfd;	type = DU;	break;
+	case STFS:	func = stfs;	type = D;	break;
+	case STFSU:	func = stfs;	type = DU;	break;
+	case STFD:	func = stfd;	type = D;	break;
+	case STFDU:	func = stfd;	type = DU;	break;
+
+	case OP31:
+		switch ((insn >> 1) & 0x3ff) {
+		case LFSX:	func = lfs;	type = XE;	break;
+		case LFSUX:	func = lfs;	type = XEU;	break;
+		case LFDX:	func = lfd;	type = XE;	break;
+		case LFDUX:	func = lfd;	type = XEU;	break;
+		case STFSX:	func = stfs;	type = XE;	break;
+		case STFSUX:	func = stfs;	type = XEU;	break;
+		case STFDX:	func = stfd;	type = XE;	break;
+		case STFDUX:	func = stfd;	type = XEU;	break;
+		case STFIWX:	func = stfiwx;	type = XE;	break;
+		default:
+			goto illegal;
+		}
+		break;
+
+	case OP59:
+		switch ((insn >> 1) & 0x1f) {
+		case FDIVS:	func = fdivs;	type = AB;	break;
+		case FSUBS:	func = fsubs;	type = AB;	break;
+		case FADDS:	func = fadds;	type = AB;	break;
+		case FSQRTS:	func = fsqrts;	type = AB;	break;
+		case FRES:	func = fres;	type = AB;	break;
+		case FMULS:	func = fmuls;	type = AC;	break;
+		case FMSUBS:	func = fmsubs;	type = ABC;	break;
+		case FMADDS:	func = fmadds;	type = ABC;	break;
+		case FNMSUBS:	func = fnmsubs;	type = ABC;	break;
+		case FNMADDS:	func = fnmadds;	type = ABC;	break;
+		default:
+			goto illegal;
+		}
+		break;
+
+	case OP63:
+		if (insn & 0x20) {
+			switch ((insn >> 1) & 0x1f) {
+			case FDIV:	func = fdiv;	type = AB;	break;
+			case FSUB:	func = fsub;	type = AB;	break;
+			case FADD:	func = fadd;	type = AB;	break;
+			case FSQRT:	func = fsqrt;	type = AB;	break;
+			case FSEL:	func = fsel;	type = ABC;	break;
+			case FMUL:	func = fmul;	type = AC;	break;
+			case FRSQRTE:	func = frsqrte;	type = AB;	break;
+			case FMSUB:	func = fmsub;	type = ABC;	break;
+			case FMADD:	func = fmadd;	type = ABC;	break;
+			case FNMSUB:	func = fnmsub;	type = ABC;	break;
+			case FNMADD:	func = fnmadd;	type = ABC;	break;
+			default:
+				goto illegal;
+			}
+			break;
+		}
+
+		switch ((insn >> 1) & 0x3ff) {
+		case FCMPU:	func = fcmpu;	type = XCR;	break;
+		case FRSP:	func = frsp;	type = XB;	break;
+		case FCTIW:	func = fctiw;	type = XB;	break;
+		case FCTIWZ:	func = fctiwz;	type = XB;	break;
+		case FCMPO:	func = fcmpo;	type = XCR;	break;
+		case MTFSB1:	func = mtfsb1;	type = XCRB;	break;
+		case FNEG:	func = fneg;	type = XB;	break;
+		case MCRFS:	func = mcrfs;	type = XCRL;	break;
+		case MTFSB0:	func = mtfsb0;	type = XCRB;	break;
+		case FMR:	func = fmr;	type = XB;	break;
+		case MTFSFI:	func = mtfsfi;	type = XCRI;	break;
+		case FNABS:	func = fnabs;	type = XB;	break;
+		case FABS:	func = fabs;	type = XB;	break;
+		case MFFS:	func = mffs;	type = X;	break;
+		case MTFSF:	func = mtfsf;	type = XFLB;	break;
+		default:
+			goto illegal;
+		}
+		break;
+
+	default:
+		goto illegal;
+	}
+
+	switch (type) {
+	case AB:
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)&current->tss.fpr[(insn >> 16) & 0x1f];
+		op2 = (void *)&current->tss.fpr[(insn >> 11) & 0x1f];
+		break;
+
+	case AC:
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)&current->tss.fpr[(insn >> 16) & 0x1f];
+		op2 = (void *)&current->tss.fpr[(insn >>  6) & 0x1f];
+		break;
+
+	case ABC:
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)&current->tss.fpr[(insn >> 16) & 0x1f];
+		op2 = (void *)&current->tss.fpr[(insn >> 11) & 0x1f];
+		op3 = (void *)&current->tss.fpr[(insn >>  6) & 0x1f];
+		break;
+
+	case D:
+		idx = (insn >> 16) & 0x1f;
+		sdisp = (insn & 0xffff);
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp);
+		break;
+
+	case DU:
+		idx = (insn >> 16) & 0x1f;
+		if (!idx)
+			goto illegal;
+
+		sdisp = (insn & 0xffff);
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)(regs->gpr[idx] + sdisp);
+		break;
+
+	case X:
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		break;
+
+	case XA:
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)&current->tss.fpr[(insn >> 16) & 0x1f];
+		break;
+
+	case XB:
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)&current->tss.fpr[(insn >> 11) & 0x1f];
+		break;
+
+	case XE:
+		idx = (insn >> 16) & 0x1f;
+		if (!idx)
+			goto illegal;
+
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]);
+		break;
+
+	case XEU:
+		idx = (insn >> 16) & 0x1f;
+		op0 = (void *)&current->tss.fpr[(insn >> 21) & 0x1f];
+		op1 = (void *)((idx ? regs->gpr[idx] : 0)
+				+ regs->gpr[(insn >> 11) & 0x1f]);
+		break;
+
+	case XCR:
+		op0 = (void *)&regs->ccr;
+		op1 = (void *)((insn >> 23) & 0x7);
+		op2 = (void *)&current->tss.fpr[(insn >> 16) & 0x1f];
+		op3 = (void *)&current->tss.fpr[(insn >> 11) & 0x1f];
+		break;
+
+	case XCRL:
+		op0 = (void *)&regs->ccr;
+		op1 = (void *)((insn >> 23) & 0x7);
+		op2 = (void *)((insn >> 18) & 0x7);
+		break;
+
+	case XCRB:
+		op0 = (void *)((insn >> 21) & 0x1f);
+		break;
+
+	case XCRI:
+		op0 = (void *)((insn >> 23) & 0x7);
+		op1 = (void *)((insn >> 12) & 0xf);
+		break;
+
+	case XFLB:
+		op0 = (void *)((insn >> 17) & 0xff);
+		op1 = (void *)&current->tss.fpr[(insn >> 11) & 0x1f];
+		break;
+
+	default:
+		goto illegal;
+	}
+
+	eflag = func(op0, op1, op2, op3);
+
+	if (insn & 1) {
+		regs->ccr &= ~(0x0f000000);
+		regs->ccr |= (__FPU_FPSCR >> 4) & 0x0f000000;
+	}
+
+	trap = record_exception(regs, eflag);
+	if (trap)
+		return 1;
+
+	switch (type) {
+	case DU:
+	case XEU:
+		regs->gpr[idx] = (unsigned long)op1;
+		break;
+
+	default:
+		break;
+	}
+#endif /* CONFIG_MATH_EMULATION */
+
+	regs->nip += 4;
+	return 0;
+
+illegal:
+	return -ENOSYS;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/mcrfs.c linux/arch/ppc/math-emu/mcrfs.c
--- v2.3.15/linux/arch/ppc/math-emu/mcrfs.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/mcrfs.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,34 @@
+/* $Id: mcrfs.c,v 1.1 1999/08/23 19:00:13 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+
+int
+mcrfs(u32 *ccr, u32 crfD, u32 crfS)
+{
+	u32 value, clear;
+
+#ifdef DEBUG
+	printk("%s: %p (%08x) %d %d\n", __FUNCTION__, ccr, *ccr, crfD, crfS);
+#endif
+
+	clear = 15 << ((7 - crfS) << 2);
+	if (!crfS)
+		clear = 0x90000000;
+
+	value = (__FPU_FPSCR >> ((7 - crfS) << 2)) & 15;
+	__FPU_FPSCR &= ~(clear);
+
+	*ccr &= ~(15 << ((7 - crfD) << 2));
+	*ccr |= (value << ((7 - crfD) << 2));
+
+#ifdef DEBUG
+	printk("CR: %08x\n", __FUNCTION__, *ccr);
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/mffs.c linux/arch/ppc/math-emu/mffs.c
--- v2.3.15/linux/arch/ppc/math-emu/mffs.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/mffs.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,20 @@
+/* $Id: mffs.c,v 1.1 1999/08/23 19:00:14 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+
+int
+mffs(u32 *frD)
+{
+	frD[1] = __FPU_FPSCR;
+
+#ifdef DEBUG
+	printk("%s: frD %p: %08x.%08x\n", __FUNCTION__, frD, frD[0], frD[1]);
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/mtfsb0.c linux/arch/ppc/math-emu/mtfsb0.c
--- v2.3.15/linux/arch/ppc/math-emu/mtfsb0.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/mtfsb0.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,21 @@
+/* $Id: mtfsb0.c,v 1.1 1999/08/23 19:00:16 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+
+int
+mtfsb0(int crbD)
+{
+	if ((crbD != 1) && (crbD != 2))
+		__FPU_FPSCR &= ~(1 << (31 - crbD));
+
+#ifdef DEBUG
+	printk("%s: %d %08lx\n", __FUNCTION__, crbD, __FPU_FPSCR);
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/mtfsb1.c linux/arch/ppc/math-emu/mtfsb1.c
--- v2.3.15/linux/arch/ppc/math-emu/mtfsb1.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/mtfsb1.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,21 @@
+/* $Id: mtfsb1.c,v 1.1 1999/08/23 19:00:17 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+
+int
+mtfsb1(int crbD)
+{
+	if ((crbD != 1) && (crbD != 2))
+		__FPU_FPSCR |= (1 << (31 - crbD));
+
+#ifdef DEBUG
+	printk("%s: %d %08lx\n", __FUNCTION__, crbD, __FPU_FPSCR);
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/mtfsf.c linux/arch/ppc/math-emu/mtfsf.c
--- v2.3.15/linux/arch/ppc/math-emu/mtfsf.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/mtfsf.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,48 @@
+/* $Id: mtfsf.c,v 1.1 1999/08/23 19:00:19 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+
+int
+mtfsf(unsigned int FM, u32 *frB)
+{
+	u32 mask;
+
+	if (FM == 0)
+		return 0;
+
+	if (FM == 0xff)
+		mask = 0x9fffffff;
+	else {
+		mask = 0;
+		if (FM & (1 << 0))
+			mask |= 0x90000000;
+		if (FM & (1 << 1))
+			mask |= 0x0f000000;
+		if (FM & (1 << 2))
+			mask |= 0x00f00000;
+		if (FM & (1 << 3))
+			mask |= 0x000f0000;
+		if (FM & (1 << 4))
+			mask |= 0x0000f000;
+		if (FM & (1 << 5))
+			mask |= 0x00000f00;
+		if (FM & (1 << 6))
+			mask |= 0x000000f0;
+		if (FM & (1 << 7))
+			mask |= 0x0000000f;
+	}
+
+	__FPU_FPSCR &= ~(mask);
+	__FPU_FPSCR |= (frB[1] & mask);
+
+#ifdef DEBUG
+	printk("%s: %02x %p: %08lx\n", __FUNCTION__, FM, frB, __FPU_FPSCR);
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/mtfsfi.c linux/arch/ppc/math-emu/mtfsfi.c
--- v2.3.15/linux/arch/ppc/math-emu/mtfsfi.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/mtfsfi.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,26 @@
+/* $Id: mtfsfi.c,v 1.1 1999/08/23 19:00:20 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+
+int
+mtfsfi(unsigned int crfD, unsigned int IMM)
+{
+	u32 mask = 0xf;
+
+	if (!crfD)
+		mask = 9;
+
+	__FPU_FPSCR &= ~(mask << ((7 - crfD) << 2));
+	__FPU_FPSCR |= (IMM & 0xf) << ((7 - crfD) << 2);
+
+#ifdef DEBUG
+	printk("%s: %d %x: %08lx\n", __FUNCTION__, crfD, IMM, __FPU_FPSCR);
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/op-1.h linux/arch/ppc/math-emu/op-1.h
--- v2.3.15/linux/arch/ppc/math-emu/op-1.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/op-1.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,245 @@
+/*
+ * Basic one-word fraction declaration and manipulation.
+ */
+
+#define _FP_FRAC_DECL_1(X)	_FP_W_TYPE X##_f
+#define _FP_FRAC_COPY_1(D,S)	(D##_f = S##_f)
+#define _FP_FRAC_SET_1(X,I)	(X##_f = I)
+#define _FP_FRAC_HIGH_1(X)	(X##_f)
+#define _FP_FRAC_LOW_1(X)	(X##_f)
+#define _FP_FRAC_WORD_1(X,w)	(X##_f)
+
+#define _FP_FRAC_ADDI_1(X,I)	(X##_f += I)
+#define _FP_FRAC_SLL_1(X,N)			\
+  do {						\
+    if (__builtin_constant_p(N) && (N) == 1)	\
+      X##_f += X##_f;				\
+    else					\
+      X##_f <<= (N);				\
+  } while (0)
+#define _FP_FRAC_SRL_1(X,N)	(X##_f >>= N)
+
+/* Right shift with sticky-lsb.  */
+#define _FP_FRAC_SRS_1(X,N,sz)	__FP_FRAC_SRS_1(X##_f, N, sz)
+
+#define __FP_FRAC_SRS_1(X,N,sz)						\
+   (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1		\
+		     ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
+
+#define _FP_FRAC_ADD_1(R,X,Y)	(R##_f = X##_f + Y##_f)
+#define _FP_FRAC_SUB_1(R,X,Y)	(R##_f = X##_f - Y##_f)
+#define _FP_FRAC_CLZ_1(z, X)	__FP_CLZ(z, X##_f)
+
+/* Predicates */
+#define _FP_FRAC_NEGP_1(X)	((_FP_WS_TYPE)X##_f < 0)
+#define _FP_FRAC_ZEROP_1(X)	(X##_f == 0)
+#define _FP_FRAC_OVERP_1(fs,X)	(X##_f & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_EQ_1(X, Y)	(X##_f == Y##_f)
+#define _FP_FRAC_GE_1(X, Y)	(X##_f >= Y##_f)
+#define _FP_FRAC_GT_1(X, Y)	(X##_f > Y##_f)
+
+#define _FP_ZEROFRAC_1		0
+#define _FP_MINFRAC_1		1
+
+/*
+ * Unpack the raw bits of a native fp value.  Do not classify or
+ * normalize the data.
+ */
+
+#define _FP_UNPACK_RAW_1(fs, X, val)				\
+  do {								\
+    union _FP_UNION_##fs _flo; _flo.flt = (val);		\
+								\
+    X##_f = _flo.bits.frac;					\
+    X##_e = _flo.bits.exp;					\
+    X##_s = _flo.bits.sign;					\
+  } while (0)
+
+
+/*
+ * Repack the raw bits of a native fp value.
+ */
+
+#define _FP_PACK_RAW_1(fs, val, X)				\
+  do {								\
+    union _FP_UNION_##fs _flo;					\
+								\
+    _flo.bits.frac = X##_f;					\
+    _flo.bits.exp  = X##_e;					\
+    _flo.bits.sign = X##_s;					\
+								\
+    (val) = _flo.flt;						\
+  } while (0)
+
+
+/*
+ * Multiplication algorithms:
+ */
+
+/* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
+   multiplication immediately.  */
+
+#define _FP_MUL_MEAT_1_imm(fs, R, X, Y)					\
+  do {									\
+    R##_f = X##_f * Y##_f;						\
+    /* Normalize since we know where the msb of the multiplicands	\
+       were (bit B), we know that the msb of the of the product is	\
+       at either 2B or 2B-1.  */					\
+    _FP_FRAC_SRS_1(R, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs);	\
+  } while (0)
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
+
+#define _FP_MUL_MEAT_1_wide(fs, R, X, Y, doit)				\
+  do {									\
+    _FP_W_TYPE _Z_f0, _Z_f1;						\
+    doit(_Z_f1, _Z_f0, X##_f, Y##_f);					\
+    /* Normalize since we know where the msb of the multiplicands	\
+       were (bit B), we know that the msb of the of the product is	\
+       at either 2B or 2B-1.  */					\
+    _FP_FRAC_SRS_2(_Z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs);	\
+    R##_f = _Z_f0;							\
+  } while (0)
+
+/* Finally, a simple widening multiply algorithm.  What fun!  */
+
+#define _FP_MUL_MEAT_1_hard(fs, R, X, Y)				\
+  do {									\
+    _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1;		\
+									\
+    /* split the words in half */					\
+    _xh = X##_f >> (_FP_W_TYPE_SIZE/2);					\
+    _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1);		\
+    _yh = Y##_f >> (_FP_W_TYPE_SIZE/2);					\
+    _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1);		\
+									\
+    /* multiply the pieces */						\
+    _z_f0 = _xl * _yl;							\
+    _a_f0 = _xh * _yl;							\
+    _a_f1 = _xl * _yh;							\
+    _z_f1 = _xh * _yh;							\
+									\
+    /* reassemble into two full words */				\
+    if ((_a_f0 += _a_f1) < _a_f1)					\
+      _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2);			\
+    _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2);				\
+    _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2);				\
+    _FP_FRAC_ADD_2(_z, _z, _a);						\
+									\
+    /* normalize */							\
+    _FP_FRAC_SRS_2(_z, _FP_WFRACBITS_##fs - 1, 2*_FP_WFRACBITS_##fs);	\
+    R##_f = _z_f0;							\
+  } while (0)
+
+
+/*
+ * Division algorithms:
+ */
+
+/* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
+   division immediately.  Give this macro either _FP_DIV_HELP_imm for
+   C primitives or _FP_DIV_HELP_ldiv for the ISO function.  Which you
+   choose will depend on what the compiler does with divrem4.  */
+
+#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit)		\
+  do {							\
+    _FP_W_TYPE _q, _r;					\
+    X##_f <<= (X##_f < Y##_f				\
+	       ? R##_e--, _FP_WFRACBITS_##fs		\
+	       : _FP_WFRACBITS_##fs - 1);		\
+    doit(_q, _r, X##_f, Y##_f);				\
+    R##_f = _q | (_r != 0);				\
+  } while (0)
+
+/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
+   that may be useful in this situation.  This first is for a primitive
+   that requires normalization, the second for one that does not.  Look
+   for UDIV_NEEDS_NORMALIZATION to tell which your machine needs.  */
+
+#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y)				\
+  do {									\
+    _FP_W_TYPE _nh, _nl, _q, _r;					\
+									\
+    /* Normalize Y -- i.e. make the most significant bit set.  */	\
+    Y##_f <<= _FP_WFRACXBITS_##fs - 1;					\
+									\
+    /* Shift X op correspondingly high, that is, up one full word.  */	\
+    if (X##_f <= Y##_f)							\
+      {									\
+	_nl = 0;							\
+	_nh = X##_f;							\
+      }									\
+    else								\
+      {									\
+	R##_e++;							\
+	_nl = X##_f << (_FP_W_TYPE_SIZE-1);				\
+	_nh = X##_f >> 1;						\
+      }									\
+    									\
+    udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);				\
+    R##_f = _q | (_r != 0);						\
+  } while (0)
+
+#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y)		\
+  do {							\
+    _FP_W_TYPE _nh, _nl, _q, _r;			\
+    if (X##_f < Y##_f)					\
+      {							\
+	R##_e--;					\
+	_nl = X##_f << _FP_WFRACBITS_##fs;		\
+	_nh = X##_f >> _FP_WFRACXBITS_##fs;		\
+      }							\
+    else						\
+      {							\
+	_nl = X##_f << (_FP_WFRACBITS_##fs - 1);	\
+	_nh = X##_f >> (_FP_WFRACXBITS_##fs + 1);	\
+      }							\
+    udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);		\
+    R##_f = _q | (_r != 0);				\
+  } while (0)
+  
+  
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ */
+ 
+#define _FP_SQRT_MEAT_1(R, S, T, X, q)			\
+  do {							\
+    while (q)						\
+      {							\
+        T##_f = S##_f + q;				\
+        if (T##_f <= X##_f)				\
+          {						\
+            S##_f = T##_f + q;				\
+            X##_f -= T##_f;				\
+            R##_f += q;					\
+          }						\
+        _FP_FRAC_SLL_1(X, 1);				\
+        q >>= 1;					\
+      }							\
+  } while (0)
+
+/*
+ * Assembly/disassembly for converting to/from integral types.  
+ * No shifting or overflow handled here.
+ */
+
+#define _FP_FRAC_ASSEMBLE_1(r, X, rsize)	(r = X##_f)
+#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize)	(X##_f = r)
+
+
+/*
+ * Convert FP values between word sizes
+ */
+
+#define _FP_FRAC_CONV_1_1(dfs, sfs, D, S)				\
+  do {									\
+    D##_f = S##_f;							\
+    if (_FP_WFRACBITS_##sfs > _FP_WFRACBITS_##dfs)			\
+      _FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs),	\
+		     _FP_WFRACBITS_##sfs);				\
+    else								\
+      D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs;		\
+  } while (0)
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/op-2.h linux/arch/ppc/math-emu/op-2.h
--- v2.3.15/linux/arch/ppc/math-emu/op-2.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/op-2.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,433 @@
+/*
+ * Basic two-word fraction declaration and manipulation.
+ */
+
+#define _FP_FRAC_DECL_2(X)	_FP_W_TYPE X##_f0, X##_f1
+#define _FP_FRAC_COPY_2(D,S)	(D##_f0 = S##_f0, D##_f1 = S##_f1)
+#define _FP_FRAC_SET_2(X,I)	__FP_FRAC_SET_2(X, I)
+#define _FP_FRAC_HIGH_2(X)	(X##_f1)
+#define _FP_FRAC_LOW_2(X)	(X##_f0)
+#define _FP_FRAC_WORD_2(X,w)	(X##_f##w)
+
+#define _FP_FRAC_SLL_2(X,N)						\
+  do {									\
+    if ((N) < _FP_W_TYPE_SIZE)						\
+      {									\
+        if (__builtin_constant_p(N) && (N) == 1) 			\
+          {								\
+            X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0);	\
+            X##_f0 += X##_f0;						\
+          }								\
+        else								\
+          {								\
+	    X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N));	\
+	    X##_f0 <<= (N);						\
+	  }								\
+      }									\
+    else								\
+      {									\
+	X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE);			\
+	X##_f0 = 0;							\
+      }									\
+  } while (0)
+
+#define _FP_FRAC_SRL_2(X,N)						\
+  do {									\
+    if ((N) < _FP_W_TYPE_SIZE)						\
+      {									\
+	X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N));	\
+	X##_f1 >>= (N);							\
+      }									\
+    else								\
+      {									\
+	X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE);			\
+	X##_f1 = 0;							\
+      }									\
+  } while (0)
+
+/* Right shift with sticky-lsb.  */
+#define _FP_FRAC_SRS_2(X,N,sz)						\
+  do {									\
+    if ((N) < _FP_W_TYPE_SIZE)						\
+      {									\
+	X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) |	\
+		  (__builtin_constant_p(N) && (N) == 1			\
+		   ? X##_f0 & 1						\
+		   : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0));	\
+	X##_f1 >>= (N);							\
+      }									\
+    else								\
+      {									\
+	X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) |			\
+	          (((X##_f1 << (sz - (N))) | X##_f0) != 0));		\
+	X##_f1 = 0;							\
+      }									\
+  } while (0)
+
+#define _FP_FRAC_ADDI_2(X,I) \
+  __FP_FRAC_ADDI_2(X##_f1, X##_f0, I)
+
+#define _FP_FRAC_ADD_2(R,X,Y) \
+  __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_SUB_2(R,X,Y) \
+  __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_CLZ_2(R,X)	\
+  do {				\
+    if (X##_f1)			\
+      __FP_CLZ(R,X##_f1);	\
+    else 			\
+    {				\
+      __FP_CLZ(R,X##_f0);	\
+      R += _FP_W_TYPE_SIZE;	\
+    }				\
+  } while(0)
+
+/* Predicates */
+#define _FP_FRAC_NEGP_2(X)	((_FP_WS_TYPE)X##_f1 < 0)
+#define _FP_FRAC_ZEROP_2(X)	((X##_f1 | X##_f0) == 0)
+#define _FP_FRAC_OVERP_2(fs,X)	(X##_f1 & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_EQ_2(X, Y)	(X##_f1 == Y##_f1 && X##_f0 == Y##_f0)
+#define _FP_FRAC_GT_2(X, Y)	\
+  ((X##_f1 > Y##_f1) || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0))
+#define _FP_FRAC_GE_2(X, Y)	\
+  ((X##_f1 > Y##_f1) || (X##_f1 == Y##_f1 && X##_f0 >= Y##_f0))
+
+#define _FP_ZEROFRAC_2		0, 0
+#define _FP_MINFRAC_2		0, 1
+
+/*
+ * Internals 
+ */
+
+#define __FP_FRAC_SET_2(X,I1,I0)	(X##_f0 = I0, X##_f1 = I1)
+
+#define __FP_CLZ_2(R, xh, xl)	\
+  do {				\
+    if (xh)			\
+      __FP_CLZ(R,xl);		\
+    else 			\
+    {				\
+      __FP_CLZ(R,xl);		\
+      R += _FP_W_TYPE_SIZE;	\
+    }				\
+  } while(0)
+
+#if 0
+
+#ifndef __FP_FRAC_ADDI_2
+#define __FP_FRAC_ADDI_2(xh, xl, i) \
+  (xh += ((xl += i) < i))
+#endif
+#ifndef __FP_FRAC_ADD_2
+#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \
+  (rh = xh + yh + ((rl = xl + yl) < xl))
+#endif
+#ifndef __FP_FRAC_SUB_2
+#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \
+  (rh = xh - yh - ((rl = xl - yl) > xl))
+#endif
+
+#else
+
+#undef __FP_FRAC_ADDI_2
+#define __FP_FRAC_ADDI_2(xh, xl, i)	add_ssaaaa(xh, xl, xh, xl, 0, i)
+#undef __FP_FRAC_ADD_2
+#define __FP_FRAC_ADD_2			add_ssaaaa
+#undef __FP_FRAC_SUB_2
+#define __FP_FRAC_SUB_2			sub_ddmmss
+
+#endif
+
+/*
+ * Unpack the raw bits of a native fp value.  Do not classify or
+ * normalize the data.
+ */
+
+#define _FP_UNPACK_RAW_2(fs, X, val)			\
+  do {							\
+    union _FP_UNION_##fs _flo; _flo.flt = (val);	\
+							\
+    X##_f0 = _flo.bits.frac0;				\
+    X##_f1 = _flo.bits.frac1;				\
+    X##_e  = _flo.bits.exp;				\
+    X##_s  = _flo.bits.sign;				\
+  } while (0)
+
+
+/*
+ * Repack the raw bits of a native fp value.
+ */
+
+#define _FP_PACK_RAW_2(fs, val, X)			\
+  do {							\
+    union _FP_UNION_##fs _flo;				\
+							\
+    _flo.bits.frac0 = X##_f0;				\
+    _flo.bits.frac1 = X##_f1;				\
+    _flo.bits.exp   = X##_e;				\
+    _flo.bits.sign  = X##_s;				\
+							\
+    (val) = _flo.flt;					\
+  } while (0)
+
+
+/*
+ * Multiplication algorithms:
+ */
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
+
+#define _FP_MUL_MEAT_2_wide(fs, R, X, Y, doit)				\
+  do {									\
+    _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	\
+									\
+    doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
+    doit(_b_f1, _b_f0, X##_f0, Y##_f1);					\
+    doit(_c_f1, _c_f0, X##_f1, Y##_f0);					\
+    doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \
+									\
+    __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0),	\
+		    0, _b_f1, _b_f0, 0,					\
+		    _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0));	\
+    __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0),	\
+		    0, _c_f1, _c_f0, 0,					\
+		    _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0));	\
+									\
+    /* Normalize since we know where the msb of the multiplicands	\
+       were (bit B), we know that the msb of the of the product is	\
+       at either 2B or 2B-1.  */					\
+    _FP_FRAC_SRS_4(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs);	\
+    R##_f0 = _FP_FRAC_WORD_4(_z,0);					\
+    R##_f1 = _FP_FRAC_WORD_4(_z,1);					\
+  } while (0)
+
+/* This next macro appears to be totally broken. Fortunately nowhere
+ * seems to use it :-> The problem is that we define _z[4] but
+ * then use it in _FP_FRAC_SRS_4, which will attempt to access
+ * _z_f[n] which will cause an error. The fix probably involves 
+ * declaring it with _FP_FRAC_DECL_4, see previous macro. -- PMM 02/1998 
+ */
+#define _FP_MUL_MEAT_2_gmp(fs, R, X, Y)					\
+  do {									\
+    _FP_W_TYPE _x[2], _y[2], _z[4];					\
+    _x[0] = X##_f0; _x[1] = X##_f1;					\
+    _y[0] = Y##_f0; _y[1] = Y##_f1;					\
+									\
+    mpn_mul_n(_z, _x, _y, 2);						\
+									\
+    /* Normalize since we know where the msb of the multiplicands	\
+       were (bit B), we know that the msb of the of the product is	\
+       at either 2B or 2B-1.  */					\
+    _FP_FRAC_SRS_4(_z, _FP_WFRACBITS##_fs-1, 2*_FP_WFRACBITS_##fs);	\
+    R##_f0 = _z[0];							\
+    R##_f1 = _z[1];							\
+  } while (0)
+
+
+/*
+ * Division algorithms:
+ * This seems to be giving me difficulties -- PMM 
+ * Look, NetBSD seems to be able to comment algorithms. Can't you?
+ * I've thrown printks at the problem.
+ * This now appears to work, but I still don't really know why.
+ * Also, I don't think the result is properly normalised...
+ */
+
+#define _FP_DIV_MEAT_2_udiv_64(fs, R, X, Y)				\
+  do {									\
+    extern void _fp_udivmodti4(_FP_W_TYPE q[2], _FP_W_TYPE r[2],	\
+			       _FP_W_TYPE n1, _FP_W_TYPE n0,		\
+			       _FP_W_TYPE d1, _FP_W_TYPE d0);		\
+    _FP_W_TYPE _n_f3, _n_f2, _n_f1, _n_f0, _r_f1, _r_f0;		\
+    _FP_W_TYPE _q_f1, _q_f0, _m_f1, _m_f0;				\
+    _FP_W_TYPE _rmem[2], _qmem[2];					\
+    /* I think this check is to ensure that the result is normalised.   \
+     * Assuming X,Y normalised (ie in [1.0,2.0)) X/Y will be in         \
+     * [0.5,2.0). Furthermore, it will be less than 1.0 iff X < Y.      \
+     * In this case we tweak things. (this is based on comments in      \
+     * the NetBSD FPU emulation code. )                                 \
+     * We know X,Y are normalised because we ensure this as part of     \
+     * the unpacking process. -- PMM                                    \
+     */									\
+    if (_FP_FRAC_GT_2(X, Y))						\
+      {									\
+/*	R##_e++; */							\
+	_n_f3 = X##_f1 >> 1;						\
+	_n_f2 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1;		\
+	_n_f1 = X##_f0 << (_FP_W_TYPE_SIZE - 1);			\
+	_n_f0 = 0;							\
+      }									\
+    else								\
+      {									\
+	R##_e--;							\
+	_n_f3 = X##_f1;							\
+	_n_f2 = X##_f0;							\
+	_n_f1 = _n_f0 = 0;						\
+      }									\
+									\
+    /* Normalize, i.e. make the most significant bit of the 		\
+       denominator set.  CHANGED: - 1 to nothing -- PMM */		\
+    _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs /* -1 */);			\
+									\
+    /* Do the 256/128 bit division given the 128-bit _fp_udivmodtf4 	\
+       primitive snagged from libgcc2.c.  */				\
+									\
+    _fp_udivmodti4(_qmem, _rmem, _n_f3, _n_f2, 0, Y##_f1);		\
+    _q_f1 = _qmem[0];							\
+    umul_ppmm(_m_f1, _m_f0, _q_f1, Y##_f0);				\
+    _r_f1 = _rmem[0];							\
+    _r_f0 = _n_f1;							\
+    if (_FP_FRAC_GT_2(_m, _r))						\
+      {									\
+	_q_f1--;							\
+	_FP_FRAC_ADD_2(_r, _r, Y);					\
+	if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))		\
+	  {								\
+	    _q_f1--;							\
+	    _FP_FRAC_ADD_2(_r, _r, Y);					\
+	  }								\
+      }									\
+    _FP_FRAC_SUB_2(_r, _r, _m);						\
+									\
+    _fp_udivmodti4(_qmem, _rmem, _r_f1, _r_f0, 0, Y##_f1);		\
+    _q_f0 = _qmem[0];							\
+    umul_ppmm(_m_f1, _m_f0, _q_f0, Y##_f0);				\
+    _r_f1 = _rmem[0];							\
+    _r_f0 = _n_f0;							\
+    if (_FP_FRAC_GT_2(_m, _r))						\
+      {									\
+	_q_f0--;							\
+	_FP_FRAC_ADD_2(_r, _r, Y);					\
+	if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))		\
+	  {								\
+	    _q_f0--;							\
+	    _FP_FRAC_ADD_2(_r, _r, Y);					\
+	  }								\
+      }									\
+    _FP_FRAC_SUB_2(_r, _r, _m);						\
+									\
+    R##_f1 = _q_f1;							\
+    R##_f0 = _q_f0 | ((_r_f1 | _r_f0) != 0);				\
+    /* adjust so answer is normalized again. I'm not sure what the 	\
+     * final sz param should be. In practice it's never used since      \
+     * N is 1 which is always going to be < _FP_W_TYPE_SIZE...		\
+     */									\
+    /* _FP_FRAC_SRS_2(R,1,_FP_WFRACBITS_##fs);	*/			\
+  } while (0)
+
+
+#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y)					\
+  do {									\
+    _FP_W_TYPE _x[4], _y[2], _z[4];					\
+    _y[0] = Y##_f0; _y[1] = Y##_f1;					\
+    _x[0] = _x[3] = 0;							\
+    if (_FP_FRAC_GT_2(X, Y))						\
+      {									\
+	R##_e++;							\
+	_x[1] = (X##_f0 << (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE) |	\
+		 X##_f1 >> (_FP_W_TYPE_SIZE -				\
+			    (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE)));	\
+	_x[2] = X##_f1 << (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE);		\
+      }									\
+    else								\
+      {									\
+	_x[1] = (X##_f0 << (_FP_WFRACBITS - _FP_W_TYPE_SIZE) |		\
+		 X##_f1 >> (_FP_W_TYPE_SIZE -				\
+			    (_FP_WFRACBITS - _FP_W_TYPE_SIZE)));	\
+	_x[2] = X##_f1 << (_FP_WFRACBITS - _FP_W_TYPE_SIZE);		\
+      }									\
+									\
+    (void) mpn_divrem (_z, 0, _x, 4, _y, 2);				\
+    R##_f1 = _z[1];							\
+    R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0);				\
+  } while (0)
+
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ */
+ 
+#define _FP_SQRT_MEAT_2(R, S, T, X, q)			\
+  do {							\
+    while (q)						\
+      {							\
+        T##_f1 = S##_f1 + q;				\
+        if (T##_f1 <= X##_f1)				\
+          {						\
+            S##_f1 = T##_f1 + q;			\
+            X##_f1 -= T##_f1;				\
+            R##_f1 += q;				\
+          }						\
+        _FP_FRAC_SLL_2(X, 1);				\
+        q >>= 1;					\
+      }							\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
+    while (q)						\
+      {							\
+        T##_f0 = S##_f0 + q;				\
+        T##_f1 = S##_f1;				\
+        if (T##_f1 < X##_f1 || 				\
+            (T##_f1 == X##_f1 && T##_f0 < X##_f0))	\
+          {						\
+            S##_f0 = T##_f0 + q;			\
+            if (((_FP_WS_TYPE)T##_f0) < 0 &&		\
+                ((_FP_WS_TYPE)S##_f0) >= 0)		\
+              S##_f1++;					\
+            _FP_FRAC_SUB_2(X, X, T);			\
+            R##_f0 += q;				\
+          }						\
+        _FP_FRAC_SLL_2(X, 1);				\
+        q >>= 1;					\
+      }							\
+  } while (0)
+
+
+/*
+ * Assembly/disassembly for converting to/from integral types.  
+ * No shifting or overflow handled here.
+ */
+
+#define _FP_FRAC_ASSEMBLE_2(r, X, rsize)	\
+  do {						\
+    if (rsize <= _FP_W_TYPE_SIZE)		\
+      r = X##_f0;				\
+    else					\
+      {						\
+	r = X##_f1;				\
+	r <<= _FP_W_TYPE_SIZE;			\
+	r += X##_f0;				\
+      }						\
+  } while (0)
+
+#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize)				\
+  do {									\
+    X##_f0 = r;								\
+    X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);	\
+  } while (0)
+
+/*
+ * Convert FP values between word sizes
+ */
+
+#define _FP_FRAC_CONV_1_2(dfs, sfs, D, S)				\
+  do {									\
+    _FP_FRAC_SRS_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),	\
+		   _FP_WFRACBITS_##sfs);				\
+    D##_f = S##_f0;							\
+  } while (0)
+
+#define _FP_FRAC_CONV_2_1(dfs, sfs, D, S)				\
+  do {									\
+    D##_f0 = S##_f;							\
+    D##_f1 = 0;								\
+    _FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));	\
+  } while (0)
+
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/op-4.h linux/arch/ppc/math-emu/op-4.h
--- v2.3.15/linux/arch/ppc/math-emu/op-4.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/op-4.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,297 @@
+/*
+ * Basic four-word fraction declaration and manipulation.
+ *
+ * When adding quadword support for 32 bit machines, we need
+ * to be a little careful as double multiply uses some of these
+ * macros: (in op-2.h)
+ * _FP_MUL_MEAT_2_wide() uses _FP_FRAC_DECL_4, _FP_FRAC_WORD_4,
+ * _FP_FRAC_ADD_4, _FP_FRAC_SRS_4
+ * _FP_MUL_MEAT_2_gmp() uses _FP_FRAC_SRS_4 (and should use
+ * _FP_FRAC_DECL_4: it appears to be broken and is not used 
+ * anywhere anyway. )
+ *
+ * I've now fixed all the macros that were here from the sparc64 code.
+ * [*none* of the shift macros were correct!] -- PMM 02/1998
+ * 
+ * The only quadword stuff that remains to be coded is: 
+ * 1) the conversion to/from ints, which requires 
+ * that we check (in op-common.h) that the following do the right thing
+ * for quadwords: _FP_TO_INT(Q,4,r,X,rsz,rsg), _FP_FROM_INT(Q,4,X,r,rs,rt)
+ * 2) multiply, divide and sqrt, which require:
+ * _FP_MUL_MEAT_4_*(R,X,Y), _FP_DIV_MEAT_4_*(R,X,Y), _FP_SQRT_MEAT_4(R,S,T,X,q),
+ * This also needs _FP_MUL_MEAT_Q and _FP_DIV_MEAT_Q to be defined to
+ * some suitable _FP_MUL_MEAT_4_* macros in sfp-machine.h.
+ * [we're free to choose whatever FP_MUL_MEAT_4_* macros we need for
+ * these; they are used nowhere else. ]
+ */
+
+#define _FP_FRAC_DECL_4(X)	_FP_W_TYPE X##_f[4]
+#define _FP_FRAC_COPY_4(D,S)			\
+  (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1],	\
+   D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
+/* The _FP_FRAC_SET_n(X,I) macro is intended for use with another
+ * macro such as _FP_ZEROFRAC_n which returns n comma separated values.
+ * The result is that we get an expansion of __FP_FRAC_SET_n(X,I0,I1,I2,I3)
+ * which just assigns the In values to the array X##_f[]. 
+ * This is why the number of parameters doesn't appear to match
+ * at first glance...      -- PMM 
+ */
+#define _FP_FRAC_SET_4(X,I)	__FP_FRAC_SET_4(X, I)
+#define _FP_FRAC_HIGH_4(X)	(X##_f[3])
+#define _FP_FRAC_LOW_4(X)	(X##_f[0])
+#define _FP_FRAC_WORD_4(X,w)	(X##_f[w])
+
+#define _FP_FRAC_SLL_4(X,N)						\
+  do {									\
+    _FP_I_TYPE _up, _down, _skip, _i;					\
+    _skip = (N) / _FP_W_TYPE_SIZE;					\
+    _up = (N) % _FP_W_TYPE_SIZE;					\
+    _down = _FP_W_TYPE_SIZE - _up;					\
+    for (_i = 3; _i > _skip; --_i)					\
+      X##_f[_i] = X##_f[_i-_skip] << _up | X##_f[_i-_skip-1] >> _down;	\
+/* bugfixed: was X##_f[_i] <<= _up;  -- PMM 02/1998 */                  \
+    X##_f[_i] = X##_f[0] << _up; 	                                \
+    for (--_i; _i >= 0; --_i)						\
+      X##_f[_i] = 0;							\
+  } while (0)
+
+/* This one was broken too */
+#define _FP_FRAC_SRL_4(X,N)						\
+  do {									\
+    _FP_I_TYPE _up, _down, _skip, _i;					\
+    _skip = (N) / _FP_W_TYPE_SIZE;					\
+    _down = (N) % _FP_W_TYPE_SIZE;					\
+    _up = _FP_W_TYPE_SIZE - _down;					\
+    for (_i = 0; _i < 3-_skip; ++_i)					\
+      X##_f[_i] = X##_f[_i+_skip] >> _down | X##_f[_i+_skip+1] << _up;	\
+    X##_f[_i] = X##_f[3] >> _down;			         	\
+    for (++_i; _i < 4; ++_i)						\
+      X##_f[_i] = 0;							\
+  } while (0)
+
+
+/* Right shift with sticky-lsb. 
+ * What this actually means is that we do a standard right-shift,
+ * but that if any of the bits that fall off the right hand side
+ * were one then we always set the LSbit.
+ */
+#define _FP_FRAC_SRS_4(X,N,size)					\
+  do {									\
+    _FP_I_TYPE _up, _down, _skip, _i;					\
+    _FP_W_TYPE _s;							\
+    _skip = (N) / _FP_W_TYPE_SIZE;					\
+    _down = (N) % _FP_W_TYPE_SIZE;					\
+    _up = _FP_W_TYPE_SIZE - _down;					\
+    for (_s = _i = 0; _i < _skip; ++_i)					\
+      _s |= X##_f[_i];							\
+    _s |= X##_f[_i] << _up;						\
+/* s is now != 0 if we want to set the LSbit */                         \
+    for (_i = 0; _i < 3-_skip; ++_i)					\
+      X##_f[_i] = X##_f[_i+_skip] >> _down | X##_f[_i+_skip+1] << _up;	\
+    X##_f[_i] = X##_f[3] >> _down;					\
+    for (++_i; _i < 4; ++_i)						\
+      X##_f[_i] = 0;							\
+    /* don't fix the LSB until the very end when we're sure f[0] is stable */ \
+    X##_f[0] |= (_s != 0);                                              \
+  } while (0)
+
+#define _FP_FRAC_ADD_4(R,X,Y)						\
+  __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0],		\
+		  X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
+		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_SUB_4(R,X,Y)                                           \
+  __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0],		\
+		  X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
+		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_ADDI_4(X,I)                                            \
+  __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
+
+#define _FP_ZEROFRAC_4  0,0,0,0
+#define _FP_MINFRAC_4   0,0,0,1
+
+#define _FP_FRAC_ZEROP_4(X)     ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
+#define _FP_FRAC_NEGP_4(X)      ((_FP_WS_TYPE)X##_f[3] < 0)
+#define _FP_FRAC_OVERP_4(fs,X)  (X##_f[0] & _FP_OVERFLOW_##fs)
+
+#define _FP_FRAC_EQ_4(X,Y)                              \
+ (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1]          \
+  && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
+
+#define _FP_FRAC_GT_4(X,Y)                              \
+ (X##_f[3] > Y##_f[3] ||                                \
+  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||      \
+   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||     \
+    (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0])       \
+   ))                                                   \
+  ))                                                    \
+ )
+
+#define _FP_FRAC_GE_4(X,Y)                              \
+ (X##_f[3] > Y##_f[3] ||                                \
+  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||      \
+   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||     \
+    (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0])      \
+   ))                                                   \
+  ))                                                    \
+ )
+
+
+#define _FP_FRAC_CLZ_4(R,X)             \
+  do {                                  \
+    if (X##_f[3])                       \
+    {                                   \
+        __FP_CLZ(R,X##_f[3]);           \
+    }                                   \
+    else if (X##_f[2])                  \
+    {                                   \
+        __FP_CLZ(R,X##_f[2]);           \
+        R += _FP_W_TYPE_SIZE;           \
+    }                                   \
+    else if (X##_f[1])                  \
+    {                                   \
+        __FP_CLZ(R,X##_f[2]);           \
+        R += _FP_W_TYPE_SIZE*2;         \
+    }                                   \
+    else                                \
+    {                                   \
+        __FP_CLZ(R,X##_f[0]);           \
+        R += _FP_W_TYPE_SIZE*3;         \
+    }                                   \
+  } while(0)
+
+
+#define _FP_UNPACK_RAW_4(fs, X, val)                            \
+  do {                                                          \
+    union _FP_UNION_##fs _flo; _flo.flt = (val);        	\
+    X##_f[0] = _flo.bits.frac0;                                 \
+    X##_f[1] = _flo.bits.frac1;                                 \
+    X##_f[2] = _flo.bits.frac2;                                 \
+    X##_f[3] = _flo.bits.frac3;                                 \
+    X##_e  = _flo.bits.exp;                                     \
+    X##_s  = _flo.bits.sign;                                    \
+  } while (0)
+
+#define _FP_PACK_RAW_4(fs, val, X)                              \
+  do {                                                          \
+    union _FP_UNION_##fs _flo;					\
+    _flo.bits.frac0 = X##_f[0];                                 \
+    _flo.bits.frac1 = X##_f[1];                                 \
+    _flo.bits.frac2 = X##_f[2];                                 \
+    _flo.bits.frac3 = X##_f[3];                                 \
+    _flo.bits.exp   = X##_e;                                    \
+    _flo.bits.sign  = X##_s;                                    \
+    (val) = _flo.flt;                                   	\
+  } while (0)
+
+
+/*
+ * Internals 
+ */
+
+#define __FP_FRAC_SET_4(X,I3,I2,I1,I0)					\
+  (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)
+
+#ifndef __FP_FRAC_ADD_4
+#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
+  (r0 = x0 + y0,							\
+   r1 = x1 + y1 + (r0 < x0),						\
+   r2 = x2 + y2 + (r1 < x1),						\
+   r3 = x3 + y3 + (r2 < x2))
+#endif
+
+#ifndef __FP_FRAC_SUB_4
+#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
+  (r0 = x0 - y0,                                                        \
+   r1 = x1 - y1 - (r0 > x0),                                            \
+   r2 = x2 - y2 - (r1 > x1),                                            \
+   r3 = x3 - y3 - (r2 > x2))
+#endif
+
+#ifndef __FP_FRAC_ADDI_4
+/* I always wanted to be a lisp programmer :-> */
+#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i)                                 \
+  (x3 += ((x2 += ((x1 += ((x0 += i) < x0)) < x1) < x2)))
+#endif
+
+/* Convert FP values between word sizes. This appears to be more
+ * complicated than I'd have expected it to be, so these might be
+ * wrong... These macros are in any case somewhat bogus because they
+ * use information about what various FRAC_n variables look like 
+ * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do
+ * the ones in op-2.h and op-1.h. 
+ */
+#define _FP_FRAC_CONV_1_4(dfs, sfs, D, S)                               \
+   do {                                                                 \
+     _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),     \
+                        _FP_WFRACBITS_##sfs);                           \
+     D##_f = S##_f[0];                                                   \
+  } while (0)
+
+#define _FP_FRAC_CONV_2_4(dfs, sfs, D, S)                               \
+   do {                                                                 \
+     _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),     \
+                        _FP_WFRACBITS_##sfs);                           \
+     D##_f0 = S##_f[0];                                                  \
+     D##_f1 = S##_f[1];                                                  \
+  } while (0)
+
+/* Assembly/disassembly for converting to/from integral types.  
+ * No shifting or overflow handled here.
+ */
+/* Put the FP value X into r, which is an integer of size rsize. */
+#define _FP_FRAC_ASSEMBLE_4(r, X, rsize)                                \
+  do {                                                                  \
+    if (rsize <= _FP_W_TYPE_SIZE)                                       \
+      r = X##_f[0];                                                     \
+    else if (rsize <= 2*_FP_W_TYPE_SIZE)                                \
+    {                                                                   \
+      r = X##_f[1];                                                     \
+      r <<= _FP_W_TYPE_SIZE;                                            \
+      r += X##_f[0];                                                    \
+    }                                                                   \
+    else                                                                \
+    {                                                                   \
+      /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \
+      /* and int == 4words as a single case.                         */ \
+      r = X##_f[3];                                                     \
+      r <<= _FP_W_TYPE_SIZE;                                            \
+      r += X##_f[2];                                                    \
+      r <<= _FP_W_TYPE_SIZE;                                            \
+      r += X##_f[1];                                                    \
+      r <<= _FP_W_TYPE_SIZE;                                            \
+      r += X##_f[0];                                                    \
+    }                                                                   \
+  } while (0)
+
+/* "No disassemble Number Five!" */
+/* move an integer of size rsize into X's fractional part. We rely on
+ * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid
+ * having to mask the values we store into it.
+ */
+#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize)                             \
+  do {                                                                  \
+    X##_f[0] = r;                                                       \
+    X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);   \
+    X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
+    X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
+  } while (0);
+
+#define _FP_FRAC_CONV_4_1(dfs, sfs, D, S)                               \
+   do {                                                                 \
+     D##_f[0] = S##_f;                                                  \
+     D##_f[1] = D##_f[2] = D##_f[3] = 0;                                \
+     _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));    \
+   } while (0)
+
+#define _FP_FRAC_CONV_4_2(dfs, sfs, D, S)                               \
+   do {                                                                 \
+     D##_f[0] = S##_f0;                                                 \
+     D##_f[1] = S##_f1;                                                 \
+     D##_f[2] = D##_f[3] = 0;                                           \
+     _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));    \
+   } while (0)
+
+/* FIXME! This has to be written */
+#define _FP_SQRT_MEAT_4(R, S, T, X, q)
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/op-common.h linux/arch/ppc/math-emu/op-common.h
--- v2.3.15/linux/arch/ppc/math-emu/op-common.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/op-common.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,690 @@
+
+#define _FP_DECL(wc, X)			\
+  _FP_I_TYPE X##_c, X##_s, X##_e;	\
+  _FP_FRAC_DECL_##wc(X)
+
+/*
+ * Finish truely unpacking a native fp value by classifying the kind
+ * of fp value and normalizing both the exponent and the fraction.
+ */
+
+#define _FP_UNPACK_CANONICAL(fs, wc, X)					\
+do {									\
+  switch (X##_e)							\
+  {									\
+  default:								\
+    _FP_FRAC_HIGH_##wc(X) |= _FP_IMPLBIT_##fs;				\
+    _FP_FRAC_SLL_##wc(X, _FP_WORKBITS);					\
+    X##_e -= _FP_EXPBIAS_##fs;						\
+    X##_c = FP_CLS_NORMAL;						\
+    break;								\
+									\
+  case 0:								\
+    if (_FP_FRAC_ZEROP_##wc(X))						\
+      X##_c = FP_CLS_ZERO;						\
+    else								\
+      {									\
+	/* a denormalized number */					\
+	_FP_I_TYPE _shift;						\
+	_FP_FRAC_CLZ_##wc(_shift, X);					\
+	_shift -= _FP_FRACXBITS_##fs;					\
+	_FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS));			\
+	X##_e -= _FP_EXPBIAS_##fs - 1 + _shift;				\
+	X##_c = FP_CLS_NORMAL;						\
+      }									\
+    break;								\
+									\
+  case _FP_EXPMAX_##fs:							\
+    if (_FP_FRAC_ZEROP_##wc(X))						\
+      X##_c = FP_CLS_INF;						\
+    else								\
+      /* we don't differentiate between signaling and quiet nans */	\
+      X##_c = FP_CLS_NAN;						\
+    break;								\
+  }									\
+} while (0)
+
+
+/*
+ * Before packing the bits back into the native fp result, take care
+ * of such mundane things as rounding and overflow.  Also, for some
+ * kinds of fp values, the original parts may not have been fully
+ * extracted -- but that is ok, we can regenerate them now.
+ */
+
+#define _FP_PACK_CANONICAL(fs, wc, X)				\
+({int __ret = 0;						\
+  switch (X##_c)						\
+  {								\
+  case FP_CLS_NORMAL:						\
+    X##_e += _FP_EXPBIAS_##fs;					\
+    if (X##_e > 0)						\
+      {								\
+	__ret |= _FP_ROUND(wc, X);				\
+	if (_FP_FRAC_OVERP_##wc(fs, X))				\
+	  {							\
+	    _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1));		\
+	    X##_e++;						\
+	  }							\
+	else							\
+	  _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);			\
+	if (X##_e >= _FP_EXPMAX_##fs)				\
+	  {							\
+	    /* overflow to infinity */				\
+	    X##_e = _FP_EXPMAX_##fs;				\
+	    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);		\
+            __ret |= EFLAG_OVERFLOW;				\
+	  }							\
+      }								\
+    else							\
+      {								\
+	/* we've got a denormalized number */			\
+	X##_e = -X##_e + 1;					\
+	if (X##_e <= _FP_WFRACBITS_##fs)			\
+	  {							\
+	    _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);	\
+	    __ret |= _FP_ROUND(wc, X);				\
+	    _FP_FRAC_SLL_##wc(X, 1);				\
+	    if (_FP_FRAC_OVERP_##wc(fs, X))			\
+	      {							\
+	        X##_e = 1;					\
+	        _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);	\
+	      }							\
+	    else						\
+	      {							\
+		X##_e = 0;					\
+		_FP_FRAC_SRL_##wc(X, _FP_WORKBITS+1);		\
+                __ret |= EFLAG_UNDERFLOW;			\
+	      }							\
+	  }							\
+	else							\
+	  {							\
+	    /* underflow to zero */				\
+	    X##_e = 0;						\
+	    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);		\
+            __ret |= EFLAG_UNDERFLOW;				\
+	  }							\
+      }								\
+    break;							\
+								\
+  case FP_CLS_ZERO:						\
+    X##_e = 0;							\
+    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			\
+    break;							\
+								\
+  case FP_CLS_INF:						\
+    X##_e = _FP_EXPMAX_##fs;					\
+    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			\
+    break;							\
+								\
+  case FP_CLS_NAN:						\
+    X##_e = _FP_EXPMAX_##fs;					\
+    if (!_FP_KEEPNANFRACP)					\
+      {								\
+	_FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);			\
+	X##_s = 0;						\
+      }								\
+    else							\
+      _FP_FRAC_HIGH_##wc(X) |= _FP_QNANBIT_##fs;		\
+    break;							\
+  }								\
+  __ret;							\
+})
+
+
+/*
+ * Main addition routine.  The input values should be cooked.
+ */
+
+#define _FP_ADD(fs, wc, R, X, Y)					     \
+do {									     \
+  switch (_FP_CLS_COMBINE(X##_c, Y##_c))				     \
+  {									     \
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):			     \
+    {									     \
+      /* shift the smaller number so that its exponent matches the larger */ \
+      _FP_I_TYPE diff = X##_e - Y##_e;					     \
+									     \
+      if (diff < 0)							     \
+	{								     \
+	  diff = -diff;							     \
+	  if (diff <= _FP_WFRACBITS_##fs)				     \
+	    _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs);		     \
+	  else if (!_FP_FRAC_ZEROP_##wc(X))				     \
+	    _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);			     \
+	  else								     \
+	    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			     \
+	  R##_e = Y##_e;						     \
+	}								     \
+      else								     \
+	{								     \
+	  if (diff > 0)							     \
+	    {								     \
+	      if (diff <= _FP_WFRACBITS_##fs)				     \
+	        _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs);		     \
+	      else if (!_FP_FRAC_ZEROP_##wc(Y))				     \
+	        _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);			     \
+	      else							     \
+	        _FP_FRAC_SET_##wc(Y, _FP_ZEROFRAC_##wc);		     \
+	    }								     \
+	  R##_e = X##_e;						     \
+	}								     \
+									     \
+      R##_c = FP_CLS_NORMAL;						     \
+									     \
+      if (X##_s == Y##_s)						     \
+	{								     \
+	  R##_s = X##_s;						     \
+	  _FP_FRAC_ADD_##wc(R, X, Y);					     \
+	  if (_FP_FRAC_OVERP_##wc(fs, R))				     \
+	    {								     \
+	      _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);		     \
+	      R##_e++;							     \
+	    }								     \
+	}								     \
+      else								     \
+	{								     \
+	  R##_s = X##_s;						     \
+	  _FP_FRAC_SUB_##wc(R, X, Y);					     \
+	  if (_FP_FRAC_ZEROP_##wc(R))					     \
+	    {								     \
+	      /* return an exact zero */				     \
+	      if (FP_ROUNDMODE == FP_RND_MINF)				     \
+		R##_s |= Y##_s;						     \
+	      else							     \
+		R##_s &= Y##_s;						     \
+	      R##_c = FP_CLS_ZERO;					     \
+	    }								     \
+	  else								     \
+	    {								     \
+	      if (_FP_FRAC_NEGP_##wc(R))				     \
+		{							     \
+		  _FP_FRAC_SUB_##wc(R, Y, X);				     \
+		  R##_s = Y##_s;					     \
+		}							     \
+									     \
+	      /* renormalize after subtraction */			     \
+	      _FP_FRAC_CLZ_##wc(diff, R);				     \
+	      diff -= _FP_WFRACXBITS_##fs;				     \
+	      if (diff)							     \
+		{							     \
+		  R##_e -= diff;					     \
+		  _FP_FRAC_SLL_##wc(R, diff);				     \
+		}							     \
+	    }								     \
+	}								     \
+      break;								     \
+    }									     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):				     \
+    _FP_CHOOSENAN(fs, wc, R, X, Y);					     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):			     \
+    R##_e = X##_e;							     \
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):			     \
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):				     \
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):				     \
+    _FP_FRAC_COPY_##wc(R, X);						     \
+    R##_s = X##_s;							     \
+    R##_c = X##_c;							     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):			     \
+    R##_e = Y##_e;							     \
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):			     \
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):				     \
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):				     \
+    _FP_FRAC_COPY_##wc(R, Y);						     \
+    R##_s = Y##_s;							     \
+    R##_c = Y##_c;							     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):				     \
+    if (X##_s != Y##_s)							     \
+      {									     \
+	/* +INF + -INF => NAN */					     \
+	_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);				     \
+	R##_s = X##_s ^ Y##_s;						     \
+	R##_c = FP_CLS_NAN;						     \
+	break;								     \
+      }									     \
+    /* FALLTHRU */							     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):			     \
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):				     \
+    R##_s = X##_s;							     \
+    R##_c = FP_CLS_INF;							     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):			     \
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):				     \
+    R##_s = Y##_s;							     \
+    R##_c = FP_CLS_INF;							     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):			     \
+    /* make sure the sign is correct */					     \
+    if (FP_ROUNDMODE == FP_RND_MINF)					     \
+      R##_s = X##_s | Y##_s;						     \
+    else								     \
+      R##_s = X##_s & Y##_s;						     \
+    R##_c = FP_CLS_ZERO;						     \
+    break;								     \
+									     \
+  default:								     \
+    abort();								     \
+  }									     \
+} while (0)
+
+
+/*
+ * Main negation routine.  FIXME -- when we care about setting exception
+ * bits reliably, this will not do.  We should examine all of the fp classes.
+ */
+
+#define _FP_NEG(fs, wc, R, X)		\
+  do {					\
+    _FP_FRAC_COPY_##wc(R, X);		\
+    R##_c = X##_c;			\
+    R##_e = X##_e;			\
+    R##_s = 1 ^ X##_s;			\
+  } while (0)
+
+
+/*
+ * Main multiplication routine.  The input values should be cooked.
+ */
+
+#define _FP_MUL(fs, wc, R, X, Y)			\
+do {							\
+  R##_s = X##_s ^ Y##_s;				\
+  switch (_FP_CLS_COMBINE(X##_c, Y##_c))		\
+  {							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):	\
+    R##_c = FP_CLS_NORMAL;				\
+    R##_e = X##_e + Y##_e + 1;				\
+							\
+    _FP_MUL_MEAT_##fs(R,X,Y);				\
+							\
+    if (_FP_FRAC_OVERP_##wc(fs, R))			\
+      _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);	\
+    else						\
+      R##_e--;						\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):		\
+    _FP_CHOOSENAN(fs, wc, R, X, Y);			\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):	\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):		\
+    R##_s = X##_s;					\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):	\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):	\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):	\
+    _FP_FRAC_COPY_##wc(R, X);				\
+    R##_c = X##_c;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):	\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):		\
+    R##_s = Y##_s;					\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):	\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):	\
+    _FP_FRAC_COPY_##wc(R, Y);				\
+    R##_c = Y##_c;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):		\
+    R##_c = FP_CLS_NAN;					\
+    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
+    break;						\
+							\
+  default:						\
+    abort();						\
+  }							\
+} while (0)
+
+
+/*
+ * Main division routine.  The input values should be cooked.
+ */
+
+#define _FP_DIV(fs, wc, R, X, Y)			\
+do {							\
+  R##_s = X##_s ^ Y##_s;				\
+  switch (_FP_CLS_COMBINE(X##_c, Y##_c))		\
+  {							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):	\
+    R##_c = FP_CLS_NORMAL;				\
+    R##_e = X##_e - Y##_e;				\
+							\
+    _FP_DIV_MEAT_##fs(R,X,Y);				\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):		\
+    _FP_CHOOSENAN(fs, wc, R, X, Y);			\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):	\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):		\
+    R##_s = X##_s;					\
+    _FP_FRAC_COPY_##wc(R, X);				\
+    R##_c = X##_c;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):	\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):		\
+    R##_s = Y##_s;					\
+    _FP_FRAC_COPY_##wc(R, Y);				\
+    R##_c = Y##_c;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):	\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):	\
+    R##_c = FP_CLS_ZERO;				\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):	\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):		\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):	\
+    R##_c = FP_CLS_INF;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):	\
+    R##_c = FP_CLS_NAN;					\
+    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
+    break;						\
+							\
+  default:						\
+    abort();						\
+  }							\
+} while (0)
+
+
+/*
+ * Main differential comparison routine.  The inputs should be raw not
+ * cooked.  The return is -1,0,1 for normal values, 2 otherwise.
+ */
+
+#define _FP_CMP(fs, wc, ret, X, Y, un)					\
+  do {									\
+    /* NANs are unordered */						\
+    if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))		\
+	|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))	\
+      {									\
+	ret = un;							\
+      }									\
+    else								\
+      {									\
+        int __x_zero = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0;	\
+        int __y_zero = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0;	\
+									\
+	if (__x_zero && __y_zero)					\
+	  ret = 0;							\
+	else if (__x_zero)						\
+	  ret = Y##_s ? 1 : -1;						\
+	else if (__y_zero)						\
+	  ret = X##_s ? -1 : 1;						\
+	else if (X##_s != Y##_s)					\
+	  ret = X##_s ? -1 : 1;						\
+	else if (X##_e > Y##_e)						\
+	  ret = X##_s ? -1 : 1;						\
+	else if (X##_e < Y##_e)						\
+	  ret = X##_s ? 1 : -1;						\
+	else if (_FP_FRAC_GT_##wc(X, Y))				\
+	  ret = X##_s ? -1 : 1;						\
+	else if (_FP_FRAC_GT_##wc(Y, X))				\
+	  ret = X##_s ? 1 : -1;						\
+	else								\
+	  ret = 0;							\
+      }									\
+  } while (0)
+
+
+/* Simplification for strict equality.  */
+
+#define _FP_CMP_EQ(fs, wc, ret, X, Y)					  \
+  do {									  \
+    /* NANs are unordered */						  \
+    if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))		  \
+	|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))	  \
+      {									  \
+	ret = 1;							  \
+      }									  \
+    else								  \
+      {									  \
+	ret = !(X##_e == Y##_e						  \
+		&& _FP_FRAC_EQ_##wc(X, Y)				  \
+		&& (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
+      }									  \
+  } while (0)
+
+/*
+ * Main square root routine.  The input value should be cooked.
+ */
+
+#define _FP_SQRT(fs, wc, R, X)						\
+do {									\
+    _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S);			\
+    _FP_W_TYPE q;							\
+    switch (X##_c)							\
+    {									\
+    case FP_CLS_NAN:							\
+    	R##_s = 0;							\
+    	R##_c = FP_CLS_NAN;						\
+    	_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			\
+    	break;								\
+    case FP_CLS_INF:							\
+    	if (X##_s)							\
+    	  {								\
+    	    R##_s = 0;							\
+	    R##_c = FP_CLS_NAN; /* sNAN */				\
+    	  }								\
+    	else								\
+    	  {								\
+    	    R##_s = 0;							\
+    	    R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */			\
+    	  }								\
+    	break;								\
+    case FP_CLS_ZERO:							\
+	R##_s = X##_s;							\
+    	R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */			\
+	break;								\
+    case FP_CLS_NORMAL:							\
+    	R##_s = 0;							\
+        if (X##_s)							\
+          {								\
+	    R##_c = FP_CLS_NAN; /* sNAN */				\
+	    break;							\
+          }								\
+    	R##_c = FP_CLS_NORMAL;						\
+        if (X##_e & 1)							\
+          _FP_FRAC_SLL_##wc(X, 1);					\
+        R##_e = X##_e >> 1;						\
+        _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc);			\
+        _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc);			\
+        q = _FP_OVERFLOW_##fs;						\
+        _FP_FRAC_SLL_##wc(X, 1);					\
+        _FP_SQRT_MEAT_##wc(R, S, T, X, q);				\
+        _FP_FRAC_SRL_##wc(R, 1);					\
+    }									\
+  } while (0)
+
+/*
+ * Convert from FP to integer
+ */
+
+/* "When a NaN, infinity, large positive argument >= 2147483648.0, or 
+ * large negative argument <= -2147483649.0 is converted to an integer,
+ * the invalid_current bit...should be set and fp_exception_IEEE_754 should
+ * be raised. If the floating point invalid trap is disabled, no trap occurs
+ * and a numerical result is generated: if the sign bit of the operand
+ * is 0, the result is 2147483647; if the sign bit of the operand is 1,
+ * the result is -2147483648."
+ * Similarly for conversion to extended ints, except that the boundaries
+ * are >= 2^63, <= -(2^63 + 1), and the results are 2^63 + 1 for s=0 and
+ * -2^63 for s=1.
+ * -- SPARC Architecture Manual V9, Appendix B, which specifies how
+ * SPARCs resolve implementation dependencies in the IEEE-754 spec.
+ * I don't believe that the code below follows this. I'm not even sure
+ * it's right! 
+ * It doesn't cope with needing to convert to an n bit integer when there
+ * is no n bit integer type. Fortunately gcc provides long long so this
+ * isn't a problem for sparc32.
+ * I have, however, fixed its NaN handling to conform as above.
+ *         -- PMM 02/1998
+ * NB: rsigned is not 'is r declared signed?' but 'should the value stored
+ * in r be signed or unsigned?'. r is always(?) declared unsigned.
+ * Comments below are mine, BTW -- PMM 
+ */
+#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)			\
+  do {									\
+    switch (X##_c)							\
+      {									\
+      case FP_CLS_NORMAL:						\
+	if (X##_e < 0)							\
+	  {								\
+	  /* case FP_CLS_NAN: see above! */				\
+	  case FP_CLS_ZERO:						\
+	    r = 0;							\
+	  }								\
+	else if (X##_e >= rsize - (rsigned != 0))			\
+	  {	/* overflow */						\
+	  case FP_CLS_NAN:                                              \
+          case FP_CLS_INF:						\
+	    if (rsigned)						\
+	      {								\
+		r = 1;							\
+		r <<= rsize - 1;					\
+		r -= 1 - X##_s;						\
+	      }								\
+	    else							\
+	      {								\
+		r = 0;							\
+		if (!X##_s)						\
+		  r = ~r;						\
+	      }								\
+	  }								\
+	else								\
+	  {								\
+	    if (_FP_W_TYPE_SIZE*wc < rsize)				\
+	      {								\
+		_FP_FRAC_ASSEMBLE_##wc(r, X, rsize);			\
+		r <<= X##_e - _FP_WFRACBITS_##fs;			\
+	      }								\
+	    else							\
+	      {								\
+		if (X##_e >= _FP_WFRACBITS_##fs)			\
+		  _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));\
+		else							\
+		  _FP_FRAC_SRL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));\
+		_FP_FRAC_ASSEMBLE_##wc(r, X, rsize);			\
+	      }								\
+	    if (rsigned && X##_s)					\
+	      r = -r;							\
+	  }								\
+	break;								\
+      }									\
+  } while (0)
+
+#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)			\
+  do {									\
+    if (r)								\
+      {									\
+	X##_c = FP_CLS_NORMAL;						\
+									\
+	if ((X##_s = (r < 0)))						\
+	  r = -r;							\
+	/* Note that `r' is now considered unsigned, so we don't have	\
+	   to worry about the single signed overflow case.  */		\
+									\
+	if (rsize <= _FP_W_TYPE_SIZE)					\
+	  __FP_CLZ(X##_e, r);						\
+	else								\
+	  __FP_CLZ_2(X##_e, (_FP_W_TYPE)(r >> _FP_W_TYPE_SIZE), 	\
+		     (_FP_W_TYPE)r);					\
+	if (rsize < _FP_W_TYPE_SIZE)					\
+		X##_e -= (_FP_W_TYPE_SIZE - rsize);			\
+	X##_e = rsize - X##_e - 1;					\
+									\
+	if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e)	\
+	  __FP_FRAC_SRS_1(r, (X##_e - _FP_WFRACBITS_##fs), rsize);	\
+	r &= ~((_FP_W_TYPE)1 << X##_e);					\
+	_FP_FRAC_DISASSEMBLE_##wc(X, ((unsigned rtype)r), rsize);	\
+	_FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));		\
+      }									\
+    else								\
+      {									\
+	X##_c = FP_CLS_ZERO, X##_s = 0;					\
+      }									\
+  } while (0)
+
+
+#define FP_CONV(dfs,sfs,dwc,swc,D,S)			\
+  do {							\
+    _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S);	\
+    D##_e = S##_e;					\
+    D##_c = S##_c;					\
+    D##_s = S##_s;					\
+  } while (0)
+
+/*
+ * Helper primitives.
+ */
+
+/* Count leading zeros in a word.  */
+
+#ifndef __FP_CLZ
+#if _FP_W_TYPE_SIZE < 64
+/* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
+#define __FP_CLZ(r, x)				\
+  do {						\
+    _FP_W_TYPE _t = (x);			\
+    r = _FP_W_TYPE_SIZE - 1;			\
+    if (_t > 0xffff) r -= 16;			\
+    if (_t > 0xffff) _t >>= 16;			\
+    if (_t > 0xff) r -= 8;			\
+    if (_t > 0xff) _t >>= 8;			\
+    if (_t & 0xf0) r -= 4;			\
+    if (_t & 0xf0) _t >>= 4;			\
+    if (_t & 0xc) r -= 2;			\
+    if (_t & 0xc) _t >>= 2;			\
+    if (_t & 0x2) r -= 1;			\
+  } while (0)
+#else /* not _FP_W_TYPE_SIZE < 64 */
+#define __FP_CLZ(r, x)				\
+  do {						\
+    _FP_W_TYPE _t = (x);			\
+    r = _FP_W_TYPE_SIZE - 1;			\
+    if (_t > 0xffffffff) r -= 32;		\
+    if (_t > 0xffffffff) _t >>= 32;		\
+    if (_t > 0xffff) r -= 16;			\
+    if (_t > 0xffff) _t >>= 16;			\
+    if (_t > 0xff) r -= 8;			\
+    if (_t > 0xff) _t >>= 8;			\
+    if (_t & 0xf0) r -= 4;			\
+    if (_t & 0xf0) _t >>= 4;			\
+    if (_t & 0xc) r -= 2;			\
+    if (_t & 0xc) _t >>= 2;			\
+    if (_t & 0x2) r -= 1;			\
+  } while (0)
+#endif /* not _FP_W_TYPE_SIZE < 64 */
+#endif /* ndef __FP_CLZ */
+
+#define _FP_DIV_HELP_imm(q, r, n, d)		\
+  do {						\
+    q = n / d, r = n % d;			\
+  } while (0)
+
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/sfp-machine.h linux/arch/ppc/math-emu/sfp-machine.h
--- v2.3.15/linux/arch/ppc/math-emu/sfp-machine.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/sfp-machine.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,377 @@
+/* Machine-dependent software floating-point definitions.  PPC version.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+   Actually, this is a PPC (32bit) version, written based on the
+   i386, sparc, and sparc64 versions, by me, 
+   Peter Maydell (pmaydell@chiark.greenend.org.uk).
+   Comments are by and large also mine, although they may be inaccurate.
+
+   In picking out asm fragments I've gone with the lowest common
+   denominator, which also happens to be the hardware I have :->
+   That is, a SPARC without hardware multiply and divide.
+ */
+
+/* basic word size definitions */
+#define _FP_W_TYPE_SIZE		32
+#define _FP_W_TYPE		unsigned long
+#define _FP_WS_TYPE		signed long
+#define _FP_I_TYPE		long
+
+#define __ll_B			((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t)		((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t)	((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+/* You can optionally code some things like addition in asm. For
+ * example, i386 defines __FP_FRAC_ADD_2 as asm. If you don't
+ * then you get a fragment of C code [if you change an #ifdef 0
+ * in op-2.h] or a call to add_ssaaaa (see below).
+ * Good places to look for asm fragments to use are gcc and glibc.
+ * gcc's longlong.h is useful.
+ */
+
+/* We need to know how to multiply and divide. If the host word size
+ * is >= 2*fracbits you can use FP_MUL_MEAT_n_imm(t,R,X,Y) which
+ * codes the multiply with whatever gcc does to 'a * b'.
+ * _FP_MUL_MEAT_n_wide(t,R,X,Y,f) is used when you have an asm 
+ * function that can multiply two 1W values and get a 2W result. 
+ * Otherwise you're stuck with _FP_MUL_MEAT_n_hard(t,R,X,Y) which
+ * does bitshifting to avoid overflow.
+ * For division there is FP_DIV_MEAT_n_imm(t,R,X,Y,f) for word size
+ * >= 2*fracbits, where f is either _FP_DIV_HELP_imm or 
+ * _FP_DIV_HELP_ldiv (see op-1.h).
+ * _FP_DIV_MEAT_udiv() is if you have asm to do 2W/1W => (1W, 1W).
+ * [GCC and glibc have longlong.h which has the asm macro udiv_qrnnd
+ * to do this.]
+ * In general, 'n' is the number of words required to hold the type,
+ * and 't' is either S, D or Q for single/double/quad.
+ *           -- PMM
+ */
+/* Example: SPARC64:
+ * #define _FP_MUL_MEAT_S(R,X,Y)	_FP_MUL_MEAT_1_imm(S,R,X,Y)
+ * #define _FP_MUL_MEAT_D(R,X,Y)	_FP_MUL_MEAT_1_wide(D,R,X,Y,umul_ppmm)
+ * #define _FP_MUL_MEAT_Q(R,X,Y)	_FP_MUL_MEAT_2_wide(Q,R,X,Y,umul_ppmm)
+ *
+ * #define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
+ * #define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv(D,R,X,Y)
+ * #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv_64(Q,R,X,Y)
+ *
+ * Example: i386:
+ * #define _FP_MUL_MEAT_S(R,X,Y)   _FP_MUL_MEAT_1_wide(S,R,X,Y,_i386_mul_32_64)
+ * #define _FP_MUL_MEAT_D(R,X,Y)   _FP_MUL_MEAT_2_wide(D,R,X,Y,_i386_mul_32_64)
+ *
+ * #define _FP_DIV_MEAT_S(R,X,Y)   _FP_DIV_MEAT_1_udiv(S,R,X,Y,_i386_div_64_32)
+ * #define _FP_DIV_MEAT_D(R,X,Y)   _FP_DIV_MEAT_2_udiv_64(D,R,X,Y)
+ */
+
+#define _FP_MUL_MEAT_S(R,X,Y)   _FP_MUL_MEAT_1_wide(S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y)   _FP_MUL_MEAT_2_wide(D,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)   _FP_DIV_MEAT_1_udiv(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y)   _FP_DIV_MEAT_2_udiv_64(D,R,X,Y)
+
+/* These macros define what NaN looks like. They're supposed to expand to 
+ * a comma-separated set of 32bit unsigned ints that encode NaN.
+ */
+#define _FP_NANFRAC_S		_FP_QNANBIT_S
+#define _FP_NANFRAC_D		_FP_QNANBIT_D, 0
+#define _FP_NANFRAC_Q           _FP_QNANBIT_Q, 0, 0, 0
+
+#define _FP_KEEPNANFRACP 1
+
+/* This macro appears to be called when both X and Y are NaNs, and 
+ * has to choose one and copy it to R. i386 goes for the larger of the
+ * two, sparc64 just picks Y. I don't understand this at all so I'll
+ * go with sparc64 because it's shorter :->   -- PMM 
+ */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y)			\
+  do {							\
+    R##_s = Y##_s;					\
+    _FP_FRAC_COPY_##wc(R,Y);				\
+    R##_c = FP_CLS_NAN;					\
+  } while (0)
+  
+
+extern void fp_unpack_d(long *, unsigned long *, unsigned long *,
+			long *, long *, void *);
+extern int  fp_pack_d(void *, long, unsigned long, unsigned long, long, long);
+extern int  fp_pack_ds(void *, long, unsigned long, unsigned long, long, long);
+
+#define __FP_UNPACK_RAW_1(fs, X, val)			\
+  do {							\
+    union _FP_UNION_##fs *_flo =			\
+    	(union _FP_UNION_##fs *)val;			\
+							\
+    X##_f = _flo->bits.frac;				\
+    X##_e = _flo->bits.exp;				\
+    X##_s = _flo->bits.sign;				\
+  } while (0)
+
+#define __FP_UNPACK_RAW_2(fs, X, val)			\
+  do {							\
+    union _FP_UNION_##fs *_flo =			\
+    	(union _FP_UNION_##fs *)val;			\
+							\
+    X##_f0 = _flo->bits.frac0;				\
+    X##_f1 = _flo->bits.frac1;				\
+    X##_e  = _flo->bits.exp;				\
+    X##_s  = _flo->bits.sign;				\
+  } while (0)
+
+#define __FP_UNPACK_S(X,val)		\
+  do {					\
+    __FP_UNPACK_RAW_1(S,X,val);		\
+    _FP_UNPACK_CANONICAL(S,1,X);	\
+  } while (0)
+
+#define __FP_UNPACK_D(X,val)		\
+	fp_unpack_d(&X##_s, &X##_f1, &X##_f0, &X##_e, &X##_c, val)
+
+#define __FP_PACK_RAW_1(fs, val, X)			\
+  do {							\
+    union _FP_UNION_##fs *_flo =			\
+    	(union _FP_UNION_##fs *)val;			\
+							\
+    _flo->bits.frac = X##_f;				\
+    _flo->bits.exp  = X##_e;				\
+    _flo->bits.sign = X##_s;				\
+  } while (0)
+  
+#define __FP_PACK_RAW_2(fs, val, X)			\
+  do {							\
+    union _FP_UNION_##fs *_flo =			\
+    	(union _FP_UNION_##fs *)val;			\
+							\
+    _flo->bits.frac0 = X##_f0;				\
+    _flo->bits.frac1 = X##_f1;				\
+    _flo->bits.exp   = X##_e;				\
+    _flo->bits.sign  = X##_s;				\
+  } while (0)
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#define __FPU_FPSCR	(current->tss.fpscr)
+
+/* We only actually write to the destination register
+ * if exceptions signalled (if any) will not trap.
+ */
+#define __FPU_ENABLED_EXC \
+({						\
+	(__FPU_FPSCR >> 3) & 0x1f;	\
+})
+
+#define __FPU_TRAP_P(bits) \
+	((__FPU_ENABLED_EXC & (bits)) != 0)
+
+#define __FP_PACK_S(val,X)			\
+({  int __exc = _FP_PACK_CANONICAL(S,1,X);	\
+    if(!__exc || !__FPU_TRAP_P(__exc))		\
+        __FP_PACK_RAW_1(S,val,X);		\
+    __exc;					\
+})
+
+#define __FP_PACK_D(val,X)			\
+	fp_pack_d(val, X##_s, X##_f1, X##_f0, X##_e, X##_c)
+
+#define __FP_PACK_DS(val,X)			\
+	fp_pack_ds(val, X##_s, X##_f1, X##_f0, X##_e, X##_c)
+
+/* Obtain the current rounding mode. */
+#define FP_ROUNDMODE			\
+({					\
+	__FPU_FPSCR & 0x3;		\
+})
+
+/* the asm fragments go here: all these are taken from glibc-2.0.5's
+ * stdlib/longlong.h
+ */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+/* add_ssaaaa is used in op-2.h and should be equivalent to
+ * #define add_ssaaaa(sh,sl,ah,al,bh,bl) (sh = ah+bh+ (( sl = al+bl) < al))
+ * add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
+ * high_addend_2, low_addend_2) adds two UWtype integers, composed by
+ * HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
+ * respectively.  The result is placed in HIGH_SUM and LOW_SUM.  Overflow
+ * (i.e. carry out) is not stored anywhere, and is lost.
+ */
+#define add_ssaaaa(sh, sl, ah, al, bh, bl)				\
+  do {									\
+    if (__builtin_constant_p (bh) && (bh) == 0)				\
+      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2"		\
+	     : "=r" ((USItype)(sh)),					\
+	       "=&r" ((USItype)(sl))					\
+	     : "%r" ((USItype)(ah)),					\
+	       "%r" ((USItype)(al)),					\
+	       "rI" ((USItype)(bl)));					\
+    else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0)		\
+      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2"		\
+	     : "=r" ((USItype)(sh)),					\
+	       "=&r" ((USItype)(sl))					\
+	     : "%r" ((USItype)(ah)),					\
+	       "%r" ((USItype)(al)),					\
+	       "rI" ((USItype)(bl)));					\
+    else								\
+      __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3"		\
+	     : "=r" ((USItype)(sh)),					\
+	       "=&r" ((USItype)(sl))					\
+	     : "%r" ((USItype)(ah)),					\
+	       "r" ((USItype)(bh)),					\
+	       "%r" ((USItype)(al)),					\
+	       "rI" ((USItype)(bl)));					\
+  } while (0)
+
+/* sub_ddmmss is used in op-2.h and udivmodti4.c and should be equivalent to
+ * #define sub_ddmmss(sh, sl, ah, al, bh, bl) (sh = ah-bh - ((sl = al-bl) > al))
+ * sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
+ * high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
+ * composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
+ * LOW_SUBTRAHEND_2 respectively.  The result is placed in HIGH_DIFFERENCE
+ * and LOW_DIFFERENCE.  Overflow (i.e. carry out) is not stored anywhere,
+ * and is lost.
+ */
+#define sub_ddmmss(sh, sl, ah, al, bh, bl)				\
+  do {									\
+    if (__builtin_constant_p (ah) && (ah) == 0)				\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2"	\
+	       : "=r" ((USItype)(sh)),					\
+		 "=&r" ((USItype)(sl))					\
+	       : "r" ((USItype)(bh)),					\
+		 "rI" ((USItype)(al)),					\
+		 "r" ((USItype)(bl)));					\
+    else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0)		\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2"	\
+	       : "=r" ((USItype)(sh)),					\
+		 "=&r" ((USItype)(sl))					\
+	       : "r" ((USItype)(bh)),					\
+		 "rI" ((USItype)(al)),					\
+		 "r" ((USItype)(bl)));					\
+    else if (__builtin_constant_p (bh) && (bh) == 0)			\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2"		\
+	       : "=r" ((USItype)(sh)),					\
+		 "=&r" ((USItype)(sl))					\
+	       : "r" ((USItype)(ah)),					\
+		 "rI" ((USItype)(al)),					\
+		 "r" ((USItype)(bl)));					\
+    else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0)		\
+      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2"		\
+	       : "=r" ((USItype)(sh)),					\
+		 "=&r" ((USItype)(sl))					\
+	       : "r" ((USItype)(ah)),					\
+		 "rI" ((USItype)(al)),					\
+		 "r" ((USItype)(bl)));					\
+    else								\
+      __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2"	\
+	       : "=r" ((USItype)(sh)),					\
+		 "=&r" ((USItype)(sl))					\
+	       : "r" ((USItype)(ah)),					\
+		 "r" ((USItype)(bh)),					\
+		 "rI" ((USItype)(al)),					\
+		 "r" ((USItype)(bl)));					\
+  } while (0)
+
+/* asm fragments for mul and div */	 
+
+/* umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
+ * UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
+ * word product in HIGH_PROD and LOW_PROD.
+ */
+#define umul_ppmm(ph, pl, m0, m1)					\
+  do {									\
+    USItype __m0 = (m0), __m1 = (m1);					\
+    __asm__ ("mulhwu %0,%1,%2"						\
+	     : "=r" ((USItype)(ph))					\
+	     : "%r" (__m0),						\
+               "r" (__m1));						\
+    (pl) = __m0 * __m1;							\
+  } while (0)
+
+/* udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
+ * denominator) divides a UDWtype, composed by the UWtype integers
+ * HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
+ * in QUOTIENT and the remainder in REMAINDER.  HIGH_NUMERATOR must be less
+ * than DENOMINATOR for correct operation.  If, in addition, the most
+ * significant bit of DENOMINATOR must be 1, then the pre-processor symbol
+ * UDIV_NEEDS_NORMALIZATION is defined to 1.
+ */
+#define udiv_qrnnd(q, r, n1, n0, d)					\
+  do {									\
+    UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m;			\
+    __d1 = __ll_highpart (d);						\
+    __d0 = __ll_lowpart (d);						\
+									\
+    __r1 = (n1) % __d1;							\
+    __q1 = (n1) / __d1;							\
+    __m = (UWtype) __q1 * __d0;						\
+    __r1 = __r1 * __ll_B | __ll_highpart (n0);				\
+    if (__r1 < __m)							\
+      {									\
+	__q1--, __r1 += (d);						\
+	if (__r1 >= (d)) /* we didn't get carry when adding to __r1 */	\
+	  if (__r1 < __m)						\
+	    __q1--, __r1 += (d);					\
+      }									\
+    __r1 -= __m;							\
+									\
+    __r0 = __r1 % __d1;							\
+    __q0 = __r1 / __d1;							\
+    __m = (UWtype) __q0 * __d0;						\
+    __r0 = __r0 * __ll_B | __ll_lowpart (n0);				\
+    if (__r0 < __m)							\
+      {									\
+	__q0--, __r0 += (d);						\
+	if (__r0 >= (d))						\
+	  if (__r0 < __m)						\
+	    __q0--, __r0 += (d);					\
+      }									\
+    __r0 -= __m;							\
+									\
+    (q) = (UWtype) __q1 * __ll_B | __q0;				\
+    (r) = __r0;								\
+  } while (0)
+
+#define UDIV_NEEDS_NORMALIZATION 1
+
+#define abort()								\
+	return 0
+
+#ifdef __BIG_ENDIAN
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+/* Exception flags. */
+#define EFLAG_INVALID		(1 << (31 - 2))
+#define EFLAG_OVERFLOW		(1 << (31 - 3))
+#define EFLAG_UNDERFLOW		(1 << (31 - 4))
+#define EFLAG_DIVZERO		(1 << (31 - 5))
+#define EFLAG_INEXACT		(1 << (31 - 6))
+
+#define EFLAG_VXSNAN		(1 << (31 - 7))
+#define EFLAG_VXISI		(1 << (31 - 8))
+#define EFLAG_VXIDI		(1 << (31 - 9))
+#define EFLAG_VXZDZ		(1 << (31 - 10))
+#define EFLAG_VXIMZ		(1 << (31 - 11))
+#define EFLAG_VXVC		(1 << (31 - 12))
+#define EFLAG_VXSOFT		(1 << (31 - 21))
+#define EFLAG_VXSQRT		(1 << (31 - 22))
+#define EFLAG_VXCVI		(1 << (31 - 23))
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/single.h linux/arch/ppc/math-emu/single.h
--- v2.3.15/linux/arch/ppc/math-emu/single.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/single.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,66 @@
+/*
+ * Definitions for IEEE Single Precision
+ */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel kid.  Go buy yourself a real computer."
+#endif
+
+#define _FP_FRACBITS_S		24
+#define _FP_FRACXBITS_S		(_FP_W_TYPE_SIZE - _FP_FRACBITS_S)
+#define _FP_WFRACBITS_S		(_FP_WORKBITS + _FP_FRACBITS_S)
+#define _FP_WFRACXBITS_S	(_FP_W_TYPE_SIZE - _FP_WFRACBITS_S)
+#define _FP_EXPBITS_S		8
+#define _FP_EXPBIAS_S		127
+#define _FP_EXPMAX_S		255
+#define _FP_QNANBIT_S		((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2))
+#define _FP_IMPLBIT_S		((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1))
+#define _FP_OVERFLOW_S		((_FP_W_TYPE)1 << (_FP_WFRACBITS_S))
+
+/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be
+   chosen by the target machine.  */
+
+union _FP_UNION_S
+{
+  float flt;
+  struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned sign : 1;
+    unsigned exp  : _FP_EXPBITS_S;
+    unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
+#else
+    unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
+    unsigned exp  : _FP_EXPBITS_S;
+    unsigned sign : 1;
+#endif
+  } bits __attribute__((packed));
+};
+
+#define FP_DECL_S(X)		_FP_DECL(1,X)
+#define FP_UNPACK_RAW_S(X,val)	_FP_UNPACK_RAW_1(S,X,val)
+#define FP_PACK_RAW_S(val,X)	_FP_PACK_RAW_1(S,val,X)
+
+#define FP_UNPACK_S(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_1(S,X,val);		\
+    _FP_UNPACK_CANONICAL(S,1,X);	\
+  } while (0)
+
+#define FP_PACK_S(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(S,1,X);		\
+    _FP_PACK_RAW_1(S,val,X);		\
+  } while (0)
+
+#define FP_NEG_S(R,X)		_FP_NEG(S,1,R,X)
+#define FP_ADD_S(R,X,Y)		_FP_ADD(S,1,R,X,Y)
+#define FP_SUB_S(R,X,Y)		_FP_SUB(S,1,R,X,Y)
+#define FP_MUL_S(R,X,Y)		_FP_MUL(S,1,R,X,Y)
+#define FP_DIV_S(R,X,Y)		_FP_DIV(S,1,R,X,Y)
+#define FP_SQRT_S(R,X)		_FP_SQRT(S,1,R,X)
+
+#define FP_CMP_S(r,X,Y,un)	_FP_CMP(S,1,r,X,Y,un)
+#define FP_CMP_EQ_S(r,X,Y)	_FP_CMP_EQ(S,1,r,X,Y)
+
+#define FP_TO_INT_S(r,X,rsz,rsg)  _FP_TO_INT(S,1,r,X,rsz,rsg)
+#define FP_FROM_INT_S(X,r,rs,rt)  _FP_FROM_INT(S,1,X,r,rs,rt)
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/soft-fp.h linux/arch/ppc/math-emu/soft-fp.h
--- v2.3.15/linux/arch/ppc/math-emu/soft-fp.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/soft-fp.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,104 @@
+#ifndef SOFT_FP_H
+#define SOFT_FP_H
+
+#include "sfp-machine.h"
+
+#define _FP_WORKBITS		3
+#define _FP_WORK_LSB		((_FP_W_TYPE)1 << 3)
+#define _FP_WORK_ROUND		((_FP_W_TYPE)1 << 2)
+#define _FP_WORK_GUARD		((_FP_W_TYPE)1 << 1)
+#define _FP_WORK_STICKY		((_FP_W_TYPE)1 << 0)
+
+#ifndef FP_RND_NEAREST
+# define FP_RND_NEAREST		0
+# define FP_RND_ZERO		1
+# define FP_RND_PINF		2
+# define FP_RND_MINF		3
+#ifndef FP_ROUNDMODE
+# define FP_ROUNDMODE		FP_RND_NEAREST
+#endif
+#endif
+
+#define _FP_ROUND_NEAREST(wc, X)			\
+({  int __ret = 0;					\
+    int __frac = _FP_FRAC_LOW_##wc(X) & 15;		\
+    if (__frac & 7) {					\
+      __ret = EFLAG_INEXACT;				\
+      if ((__frac & 7) != _FP_WORK_ROUND)		\
+        _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND);		\
+      else if (__frac & _FP_WORK_LSB)			\
+        _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND);		\
+    }							\
+    __ret;						\
+})
+
+#define _FP_ROUND_ZERO(wc, X)				\
+({  int __ret = 0;					\
+    if (_FP_FRAC_LOW_##wc(X) & 7)			\
+      __ret = EFLAG_INEXACT;				\
+    __ret;						\
+})
+
+#define _FP_ROUND_PINF(wc, X)				\
+({  int __ret = EFLAG_INEXACT;				\
+    if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7))		\
+      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);		\
+    else __ret = 0;					\
+    __ret;						\
+})
+
+#define _FP_ROUND_MINF(wc, X)				\
+({  int __ret = EFLAG_INEXACT;				\
+    if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7))		\
+      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);		\
+    else __ret = 0;					\
+    __ret;						\
+})
+
+#define _FP_ROUND(wc, X)			\
+({	int __ret = 0;				\
+	switch (FP_ROUNDMODE)			\
+	{					\
+	  case FP_RND_NEAREST:			\
+	    __ret |= _FP_ROUND_NEAREST(wc,X);	\
+	    break;				\
+	  case FP_RND_ZERO:			\
+	    __ret |= _FP_ROUND_ZERO(wc,X);	\
+	    break;				\
+	  case FP_RND_PINF:			\
+	    __ret |= _FP_ROUND_PINF(wc,X);	\
+	    break;				\
+	  case FP_RND_MINF:			\
+	    __ret |= _FP_ROUND_MINF(wc,X);	\
+	    break;				\
+	};					\
+	__ret;					\
+})
+
+#define FP_CLS_NORMAL		0
+#define FP_CLS_ZERO		1
+#define FP_CLS_INF		2
+#define FP_CLS_NAN		3
+
+#define _FP_CLS_COMBINE(x,y)	(((x) << 2) | (y))
+
+#include "op-1.h"
+#include "op-2.h"
+#include "op-4.h"
+#include "op-common.h"
+
+/* Sigh.  Silly things longlong.h needs.  */
+#define UWtype		_FP_W_TYPE
+#define W_TYPE_SIZE	_FP_W_TYPE_SIZE
+
+typedef int SItype __attribute__((mode(SI)));
+typedef int DItype __attribute__((mode(DI)));
+typedef unsigned int USItype __attribute__((mode(SI)));
+typedef unsigned int UDItype __attribute__((mode(DI)));
+#if _FP_W_TYPE_SIZE == 32
+typedef unsigned int UHWtype __attribute__((mode(HI)));
+#elif _FP_W_TYPE_SIZE == 64
+typedef USItype UHWtype;
+#endif
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/stfd.c linux/arch/ppc/math-emu/stfd.c
--- v2.3.15/linux/arch/ppc/math-emu/stfd.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/stfd.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,23 @@
+/* $Id: stfd.c,v 1.1 1999/08/23 19:00:33 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+ 
+int
+stfd(void *frS, void *ea)
+{
+#if 0
+#ifdef DEBUG
+	printk("%s: S %p, ea %p: ", __FUNCTION__, frS, ea);
+	dump_double(frS);
+	printk("\n");
+#endif
+#endif
+
+	if (copy_to_user(ea, frS, sizeof(double)))
+		return -EFAULT;
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/stfiwx.c linux/arch/ppc/math-emu/stfiwx.c
--- v2.3.15/linux/arch/ppc/math-emu/stfiwx.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/stfiwx.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,19 @@
+/* $Id: stfiwx.c,v 1.1 1999/08/23 19:00:34 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+int
+stfiwx(u32 *frS, void *ea)
+{
+#ifdef DEBUG
+	printk("%s: %p %p\n", __FUNCTION__, frS, ea);
+#endif
+
+	if (copy_to_user(ea, &frS[1], sizeof(frS[1])))
+		return -EFAULT;
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/stfs.c linux/arch/ppc/math-emu/stfs.c
--- v2.3.15/linux/arch/ppc/math-emu/stfs.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/stfs.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,44 @@
+/* $Id: stfs.c,v 1.1 1999/08/23 19:00:35 cort Exp $
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+int
+stfs(void *frS, void *ea)
+{
+	FP_DECL_D(A);
+	FP_DECL_S(R);
+	float f;
+	int err;
+
+#ifdef DEBUG
+	printk("%s: S %p, ea %p\n", __FUNCTION__, frS, ea);
+#endif
+
+	__FP_UNPACK_D(A, frS);
+
+#ifdef DEBUG
+	printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c);
+#endif
+
+	FP_CONV(S, D, 1, 2, R, A);
+
+#ifdef DEBUG
+	printk("R: %ld %lu %ld (%ld)\n", R_s, R_f, R_e, R_c);
+#endif
+
+	err = _FP_PACK_CANONICAL(S, 1, R);
+	if (!err || !__FPU_TRAP_P(err)) {
+		__FP_PACK_RAW_1(S, &f, R);
+		if (copy_to_user(ea, &f, sizeof(float)))
+			return -EFAULT;
+	}
+
+	return err;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/types.c linux/arch/ppc/math-emu/types.c
--- v2.3.15/linux/arch/ppc/math-emu/types.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/types.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,52 @@
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+
+void
+fp_unpack_d(long *_s, unsigned long *_f1, unsigned long *_f0,
+	    long *_e, long *_c, void *val)
+{
+	FP_DECL_D(X);
+
+	__FP_UNPACK_RAW_2(D, X, val);
+
+	_FP_UNPACK_CANONICAL(D, 2, X);
+
+	*_s = X_s;
+	*_f1 = X_f1;
+	*_f0 = X_f0;
+	*_e = X_e;
+	*_c = X_c;
+}
+
+int
+fp_pack_d(void *val, long X_s, unsigned long X_f1,
+	  unsigned long X_f0, long X_e, long X_c)
+{
+	int exc;
+
+	exc = _FP_PACK_CANONICAL(D, 2, X);
+	if (!exc || !__FPU_TRAP_P(exc))
+		__FP_PACK_RAW_2(D, val, X);
+	return exc;
+}
+
+int
+fp_pack_ds(void *val, long X_s, unsigned long X_f1,
+	   unsigned long X_f0, long X_e, long X_c)
+{
+	FP_DECL_S(__X);
+	int exc;
+
+	FP_CONV(S, D, 1, 2, __X, X);
+	exc = _FP_PACK_CANONICAL(S, 1, __X);
+	if (!exc || !__FPU_TRAP_P(exc)) {
+		_FP_UNPACK_CANONICAL(S, 1, __X);
+		FP_CONV(D, S, 2, 1, X, __X);
+		exc |= _FP_PACK_CANONICAL(D, 2, X);
+		if (!exc || !__FPU_TRAP_P(exc))
+			__FP_PACK_RAW_2(D, val, X);
+	}
+	return exc;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/math-emu/udivmodti4.c linux/arch/ppc/math-emu/udivmodti4.c
--- v2.3.15/linux/arch/ppc/math-emu/udivmodti4.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/math-emu/udivmodti4.c	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,191 @@
+/* This has so very few changes over libgcc2's __udivmoddi4 it isn't funny.  */
+
+#include "soft-fp.h"
+
+#undef count_leading_zeros
+#define count_leading_zeros  __FP_CLZ
+
+void
+_fp_udivmodti4(_FP_W_TYPE q[2], _FP_W_TYPE r[2],
+	       _FP_W_TYPE n1, _FP_W_TYPE n0,
+	       _FP_W_TYPE d1, _FP_W_TYPE d0)
+{
+  _FP_W_TYPE q0, q1, r0, r1;
+  _FP_I_TYPE b, bm;
+
+  if (d1 == 0)
+    {
+#if !UDIV_NEEDS_NORMALIZATION
+      if (d0 > n1)
+	{
+	  /* 0q = nn / 0D */
+
+	  udiv_qrnnd (q0, n0, n1, n0, d0);
+	  q1 = 0;
+
+	  /* Remainder in n0.  */
+	}
+      else
+	{
+	  /* qq = NN / 0d */
+
+	  if (d0 == 0)
+	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
+
+	  udiv_qrnnd (q1, n1, 0, n1, d0);
+	  udiv_qrnnd (q0, n0, n1, n0, d0);
+
+	  /* Remainder in n0.  */
+	}
+
+      r0 = n0;
+      r1 = 0;
+
+#else /* UDIV_NEEDS_NORMALIZATION */
+
+      if (d0 > n1)
+	{
+	  /* 0q = nn / 0D */
+
+	  count_leading_zeros (bm, d0);
+
+	  if (bm != 0)
+	    {
+	      /* Normalize, i.e. make the most significant bit of the
+		 denominator set.  */
+
+	      d0 = d0 << bm;
+	      n1 = (n1 << bm) | (n0 >> (_FP_W_TYPE_SIZE - bm));
+	      n0 = n0 << bm;
+	    }
+
+	  udiv_qrnnd (q0, n0, n1, n0, d0);
+	  q1 = 0;
+
+	  /* Remainder in n0 >> bm.  */
+	}
+      else
+	{
+	  /* qq = NN / 0d */
+
+	  if (d0 == 0)
+	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
+
+	  count_leading_zeros (bm, d0);
+
+	  if (bm == 0)
+	    {
+	      /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
+		 conclude (the most significant bit of n1 is set) /\ (the
+		 leading quotient digit q1 = 1).
+
+		 This special case is necessary, not an optimization.
+		 (Shifts counts of SI_TYPE_SIZE are undefined.)  */
+
+	      n1 -= d0;
+	      q1 = 1;
+	    }
+	  else
+	    {
+	      _FP_W_TYPE n2;
+
+	      /* Normalize.  */
+
+	      b = _FP_W_TYPE_SIZE - bm;
+
+	      d0 = d0 << bm;
+	      n2 = n1 >> b;
+	      n1 = (n1 << bm) | (n0 >> b);
+	      n0 = n0 << bm;
+
+	      udiv_qrnnd (q1, n1, n2, n1, d0);
+	    }
+
+	  /* n1 != d0...  */
+
+	  udiv_qrnnd (q0, n0, n1, n0, d0);
+
+	  /* Remainder in n0 >> bm.  */
+	}
+
+      r0 = n0 >> bm;
+      r1 = 0;
+#endif /* UDIV_NEEDS_NORMALIZATION */
+    }
+  else
+    {
+      if (d1 > n1)
+	{
+	  /* 00 = nn / DD */
+
+	  q0 = 0;
+	  q1 = 0;
+
+	  /* Remainder in n1n0.  */
+	  r0 = n0;
+	  r1 = n1;
+	}
+      else
+	{
+	  /* 0q = NN / dd */
+
+	  count_leading_zeros (bm, d1);
+	  if (bm == 0)
+	    {
+	      /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
+		 conclude (the most significant bit of n1 is set) /\ (the
+		 quotient digit q0 = 0 or 1).
+
+		 This special case is necessary, not an optimization.  */
+
+	      /* The condition on the next line takes advantage of that
+		 n1 >= d1 (true due to program flow).  */
+	      if (n1 > d1 || n0 >= d0)
+		{
+		  q0 = 1;
+		  sub_ddmmss (n1, n0, n1, n0, d1, d0);
+		}
+	      else
+		q0 = 0;
+
+	      q1 = 0;
+
+	      r0 = n0;
+	      r1 = n1;
+	    }
+	  else
+	    {
+	      _FP_W_TYPE m1, m0, n2;
+
+	      /* Normalize.  */
+
+	      b = _FP_W_TYPE_SIZE - bm;
+
+	      d1 = (d1 << bm) | (d0 >> b);
+	      d0 = d0 << bm;
+	      n2 = n1 >> b;
+	      n1 = (n1 << bm) | (n0 >> b);
+	      n0 = n0 << bm;
+
+	      udiv_qrnnd (q0, n1, n2, n1, d1);
+	      umul_ppmm (m1, m0, q0, d0);
+
+	      if (m1 > n1 || (m1 == n1 && m0 > n0))
+		{
+		  q0--;
+		  sub_ddmmss (m1, m0, m1, m0, d1, d0);
+		}
+
+	      q1 = 0;
+
+	      /* Remainder in (n1n0 - m1m0) >> bm.  */
+	      sub_ddmmss (n1, n0, n1, n0, m1, m0);
+	      r0 = (n1 << b) | (n0 >> bm);
+	      r1 = n1 >> bm;
+	    }
+	}
+    }
+
+  q[0] = q0; q[1] = q1;
+  r[0] = r0, r[1] = r1;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c
--- v2.3.15/linux/arch/ppc/mm/fault.c	Fri Jul 23 12:20:23 1999
+++ linux/arch/ppc/mm/fault.c	Tue Aug 31 11:36:43 1999
@@ -82,20 +82,16 @@
 			return;
 	}
 #endif
-	if (in_interrupt() || !mm) {
+	if (in_interrupt()) {
 		static int complained;
 		if (complained < 20) {
 			++complained;
 			printk("page fault in interrupt handler, addr=%lx\n",
 			       address);
 			show_regs(regs);
-#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
-			if (debugger_kernel_faults)
-				debugger(regs);
-#endif
 		}
 	}
-	if (current == NULL) {
+	if (current == NULL || mm == NULL) {
 		bad_page_fault(regs, address);
 		return;
 	}
@@ -161,6 +157,7 @@
 bad_page_fault(struct pt_regs *regs, unsigned long address)
 {
 	unsigned long fixup;
+
 	if (user_mode(regs)) {
 		force_sig(SIGSEGV, current);
 		return;
@@ -174,11 +171,11 @@
 
 	/* kernel has accessed a bad area */
 	show_regs(regs);
-	print_backtrace( (unsigned long *)regs->gpr[1] );
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
 	if (debugger_kernel_faults)
 		debugger(regs);
 #endif
+	print_backtrace( (unsigned long *)regs->gpr[1] );
 	panic("kernel access of bad area pc %lx lr %lx address %lX tsk %s/%d",
 	      regs->nip,regs->link,address,current->comm,current->pid);
 }
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.3.15/linux/arch/ppc/mm/init.c	Sun Jul 25 13:45:25 1999
+++ linux/arch/ppc/mm/init.c	Tue Aug 31 11:36:43 1999
@@ -1,5 +1,5 @@
 /*
- *  $Id: init.c,v 1.171 1999/07/08 23:20:14 cort Exp $
+ *  $Id: init.c,v 1.180 1999/08/31 06:54:13 davem Exp $
  *
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -51,10 +51,9 @@
 #include <asm/smp.h>
 #include <asm/bootx.h>
 #include <asm/machdep.h>
-/* APUS includes */
 #include <asm/setup.h>
 #include <asm/amigahw.h>
-/* END APUS includes */
+#include <asm/gemini.h>
 
 int prom_trashed;
 atomic_t next_mmu_context;
@@ -66,6 +65,7 @@
 extern char __init_begin, __init_end;
 extern char __prep_begin, __prep_end;
 extern char __pmac_begin, __pmac_end;
+extern char __apus_begin, __apus_end;
 extern char __openfirmware_begin, __openfirmware_end;
 char *klimit = _end;
 struct device_node *memory_node;
@@ -84,6 +84,7 @@
 unsigned long *prep_find_end_of_memory(void);
 unsigned long *pmac_find_end_of_memory(void);
 unsigned long *apus_find_end_of_memory(void);
+unsigned long *gemini_find_end_of_memory(void);
 extern unsigned long *find_end_of_memory(void);
 #ifdef CONFIG_MBX
 unsigned long *mbx_find_end_of_memory(void);
@@ -126,6 +127,7 @@
 unsigned long _SDR1;
 #endif
 static void hash_init(void);
+
 union ubat {			/* BAT register values to be loaded */
 	BAT	bat;
 #ifdef CONFIG_PPC64
@@ -140,8 +142,38 @@
 	unsigned long limit;
 	unsigned long phys;
 } bat_addrs[4];
-unsigned long inline v_mapped_by_bats(unsigned long);
-unsigned long inline p_mapped_by_bats(unsigned long);
+
+/*
+ * Return PA for this VA if it is mapped by a BAT, or 0
+ */
+static inline unsigned long v_mapped_by_bats(unsigned long va)
+{
+	int b;
+	for (b = 0; b < 4; ++b)
+		if (va >= bat_addrs[b].start && va < bat_addrs[b].limit)
+			return bat_addrs[b].phys + (va - bat_addrs[b].start);
+	return 0;
+}
+
+/*
+ * Return VA for a given PA or 0 if not mapped
+ */
+static inline unsigned long p_mapped_by_bats(unsigned long pa)
+{
+	int b;
+	for (b = 0; b < 4; ++b)
+		if (pa >= bat_addrs[b].phys
+	    	    && pa < (bat_addrs[b].limit-bat_addrs[b].start)
+		              +bat_addrs[b].phys)
+			return bat_addrs[b].start+(pa-bat_addrs[b].phys);
+	return 0;
+}
+
+#else /* CONFIG_8xx */
+
+/* 8xx doesn't have BATs */
+#define v_mapped_by_bats(x)	(0UL)
+#define p_mapped_by_bats(x)	(0UL)
 #endif /* CONFIG_8xx */
 
 /*
@@ -151,8 +183,6 @@
  */
 int __map_without_bats = 0;
 
-/* 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)
 {
@@ -162,10 +192,12 @@
 
 pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
 {
-        pte_t *pte/* = (pte_t *) __get_free_page(GFP_KERNEL)*/;
+        pte_t *pte;
 
         if (pmd_none(*pmd)) {
-		if ( (pte = (pte_t *) get_zero_page_fast()) == NULL  )
+		if (!mem_init_done)
+			pte = (pte_t *) MMU_get_page();
+		else if ((pte = (pte_t *) get_zero_page_fast()) == NULL)
 			if ((pte = (pte_t *) __get_free_page(GFP_KERNEL)))
 				clear_page((unsigned long)pte);
                 if (pte) {
@@ -175,7 +207,6 @@
 		pmd_val(*pmd) = (unsigned long)BAD_PAGETABLE;
                 return NULL;
         }
-        /*free_page((unsigned long)pte);*/
         if (pmd_bad(*pmd)) {
                 __bad_pte(pmd);
                 return NULL;
@@ -258,7 +289,7 @@
 #ifdef CONFIG_NET
 	show_net_buffers();
 #endif
-	printk("%-8s %3s %3s %8s %8s %8s %9s %8s", "Process", "Pid", "Cnt",
+	printk("%-8s %3s %8s %8s %8s %9s %8s", "Process", "Pid",
 	       "Ctx", "Ctx<<4", "Last Sys", "pc", "task");
 #ifdef __SMP__
 	printk(" %3s", "CPU");
@@ -266,14 +297,13 @@
 	printk("\n");
 	for_each_task(p)
 	{
-		printk("%-8.8s %3d %3d %8ld %8ld %8ld %c%08lx %08lx ",
+		printk("%-8.8s %3d %8ld %8ld %8ld %c%08lx %08lx ",
 		       p->comm,p->pid,
-		       (p->mm)?atomic_read(&p->mm->count):0,
 		       (p->mm)?p->mm->context:0,
 		       (p->mm)?(p->mm->context<<4):0,
-		       p->tss.last_syscall,
-		       (p->tss.regs)?user_mode(p->tss.regs) ? 'u' : 'k' : '?',
-		       (p->tss.regs)?p->tss.regs->nip:0,
+		       p->thread.last_syscall,
+		       (p->thread.regs)?user_mode(p->thread.regs) ? 'u' : 'k' : '?',
+		       (p->thread.regs)?p->thread.regs->nip:0,
 		       (ulong)p);
 		{
 			int iscur = 0;
@@ -369,7 +399,6 @@
 	if (size == 0)
 		return NULL;
 
-#ifndef CONFIG_8xx
 	/*
 	 * Is it already mapped?  Perhaps overlapped by a previous
 	 * BAT mapping.  If the whole area is mapped then we're done,
@@ -381,9 +410,8 @@
 	 * same virt address (and this is contiguous).
 	 *  -- Cort
 	 */
-	if ( (v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ )
+	if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ )
 		goto out;
-#endif /* CONFIG_8xx */
 	
 	if (mem_init_done) {
 		struct vm_struct *area;
@@ -403,11 +431,9 @@
 	if (flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU))
 		flags |= _PAGE_GUARDED;
 
-#ifndef CONFIG_8xx	
 	/*
 	 * Is it a candidate for a BAT mapping?
 	 */
-#endif /* CONFIG_8xx */
 	
 	for (i = 0; i < size; i += PAGE_SIZE)
 		map_page(&init_task, v+i, p+i, flags);
@@ -422,27 +448,15 @@
 
 unsigned long iopa(unsigned long addr)
 {
-	unsigned long idx;
+	unsigned long pa;
 	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 */
+	pa = v_mapped_by_bats(addr);
+	if (pa)
+		return pa;
+
 	/* Do we have a page table? */
 	if (init_mm.pgd == NULL)
 		return 0;
@@ -454,36 +468,21 @@
 
 	/* Use middle 10 bits of addr to index the second-level map */
 	pg = pte_offset(pd, addr);
-	return (pte_val(*pg) & PAGE_MASK) | idx;
+	return (pte_val(*pg) & PAGE_MASK) | (addr & ~PAGE_MASK);
 }
 
 void
 map_page(struct task_struct *tsk, unsigned long va,
 	 unsigned long pa, int flags)
 {
-	pmd_t *pd;
-	pte_t *pg;
-	
-	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)) {
-		if ( v_mapped_by_bats(va) )
-			return;
-		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
+	pte_t * pte;
+
+	pte = pte_alloc(pmd_offset(pgd_offset_k(va), va), va);
+	set_pte(pte, mk_pte_phys(pa, __pgprot(flags)));
 	flush_hash_page(0, va);
-#endif	
 }
 
+#ifndef CONFIG_8xx
 /*
  * TLB flushing:
  *
@@ -504,12 +503,8 @@
 void
 local_flush_tlb_all(void)
 {
-#ifndef CONFIG_8xx
 	__clear_user(Hash, Hash_size);
 	_tlbia();
-#else
-	asm volatile ("tlbia" : : );
-#endif
 }
 
 /*
@@ -520,26 +515,18 @@
 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
+		activate_mm(mm, mm);
 }
 
 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
 }
 
 
@@ -553,7 +540,6 @@
 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)
@@ -566,9 +552,6 @@
 	{
 		flush_hash_page(mm->context, start);
 	}
-#else
-	asm volatile ("tlbia" : : );
-#endif
 }
 
 /*
@@ -580,7 +563,6 @@
 void
 mmu_context_overflow(void)
 {
-#ifndef CONFIG_8xx
 	struct task_struct *tsk;
 
 	printk(KERN_DEBUG "mmu_context_overflow\n");
@@ -595,19 +577,13 @@
 	/* make sure current always has a context */
 	current->mm->context = MUNGE_CONTEXT(atomic_inc_return(&next_mmu_context));
 	set_context(current->mm->context);
-#else
-	/* We set the value to -1 because it is pre-incremented before
-	 * before use.
-	 */
-	atomic_set(&next_mmu_context, -1);
-#endif
 }
+#endif /* CONFIG_8xx */
 
 /*
  * Scan a region for a piece of a given size with the required alignment.
  */
-__initfunc(void *
-find_mem_piece(unsigned size, unsigned align))
+void __init *find_mem_piece(unsigned size, unsigned align)
 {
 	int i;
 	unsigned a, e;
@@ -630,9 +606,9 @@
 /*
  * Remove some memory from an array of pieces
  */
-__initfunc(static void
+static void __init 
 remove_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size,
-		 int must_exist))
+		 int must_exist)
 {
 	int i, j;
 	unsigned end, rs, re;
@@ -686,7 +662,7 @@
 	}
 }
 
-__initfunc(static void print_mem_pieces(struct mem_pieces *mp))
+static void __init print_mem_pieces(struct mem_pieces *mp)
 {
 	int i;
 
@@ -699,8 +675,8 @@
 /*
  * Add some memory to an array of pieces
  */
-__initfunc(static void
-	   append_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size))
+static void __init
+append_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size)
 {
 	struct reg_property *rp;
 
@@ -717,34 +693,7 @@
 static void sort_mem_pieces(struct mem_pieces *);
 static void coalesce_mem_pieces(struct mem_pieces *);
 
-/*
- * Return 1 if this VA is mapped by BATs
- */
-unsigned long inline v_mapped_by_bats(unsigned long va)
-{
-	int b;
-	for (b = 0; b < 4; ++b)
-		if (va >= bat_addrs[b].start
-	    	    && va < bat_addrs[b].limit)
-			return 1;
-	return 0;
-}
-
-/*
- * Return VA for a given PA or 0 if not mapped
- */
-unsigned long inline p_mapped_by_bats(unsigned long pa)
-{
-	int b;
-	for (b = 0; b < 4; ++b)
-		if (pa >= bat_addrs[b].phys
-	    	    && pa < (bat_addrs[b].limit-bat_addrs[b].start)
-		              +bat_addrs[b].phys)
-			return bat_addrs[b].start+(pa-bat_addrs[b].phys);
-	return 0;
-}
-
-__initfunc(static void sort_mem_pieces(struct mem_pieces *mp))
+static void __init sort_mem_pieces(struct mem_pieces *mp)
 {
 	unsigned long a, s;
 	int i, j;
@@ -762,7 +711,7 @@
 	}
 }
 
-__initfunc(static void coalesce_mem_pieces(struct mem_pieces *mp))
+static void __init coalesce_mem_pieces(struct mem_pieces *mp)
 {
 	unsigned long a, s, ns;
 	int i, j, d;
@@ -788,7 +737,7 @@
  * Read in a property describing some pieces of memory.
  */
 
-__initfunc(static void get_mem_prop(char *name, struct mem_pieces *mp))
+static void __init get_mem_prop(char *name, struct mem_pieces *mp)
 {
 	struct reg_property *rp;
 	int s;
@@ -807,16 +756,13 @@
 	coalesce_mem_pieces(mp);
 }
 
-#endif /* CONFIG_8xx */
-
-#ifndef CONFIG_8xx
 /*
  * 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.
  */
-__initfunc(void setbat(int index, unsigned long virt, unsigned long phys,
-       unsigned int size, int flags))
+void __init setbat(int index, unsigned long virt, unsigned long phys,
+       unsigned int size, int flags)
 {
 	unsigned int bl;
 	int wimgxpp;
@@ -870,7 +816,7 @@
  */
 #define PAGE_KERNEL_RO	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
 
-__initfunc(static void mapin_ram(void))
+static void __init mapin_ram(void)
 {
 	int i;
 	unsigned long v, p, s, f;
@@ -922,15 +868,22 @@
 				/* On the powerpc, no user access
 				   forces R/W kernel access */
 				f |= _PAGE_USER;
+			map_page(&init_task, v, p, f);
+			v += PAGE_SIZE;
+			p += PAGE_SIZE;
+		}
+	}	    
+
 #else	/* CONFIG_8xx */
-            for (i = 0; i < phys_mem.n_regions; ++i) {
-                    v = (ulong)__va(phys_mem.regions[i].address);
-                    p = phys_mem.regions[i].address;
-                    for (s = 0; s < phys_mem.regions[i].size; s += PAGE_SIZE) {
+
+	for (i = 0; i < phys_mem.n_regions; ++i) {
+		v = (ulong)__va(phys_mem.regions[i].address);
+		p = phys_mem.regions[i].address;
+		for (s = 0; s < phys_mem.regions[i].size; s += PAGE_SIZE) {
                         /* On the MPC8xx, we want the page shared so we
                          * don't get ASID compares on kernel space.
                          */
-                            f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
+			f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
 
                         /* I don't really need the rest of this code, but
                          * I grabbed it because I think the line:
@@ -940,18 +893,18 @@
                          * the MPC8xx, the PAGE_DIRTY takes care of that
                          * for us (along with the RW software state).
                          */
-                            if ((char *) v < _stext || (char *) v >= etext)
-                                    f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
-#endif /* CONFIG_8xx */
+			if ((char *) v < _stext || (char *) v >= etext)
+				f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
 			map_page(&init_task, v, p, f);
 			v += PAGE_SIZE;
 			p += PAGE_SIZE;
 		}
 	}	    
+#endif /* CONFIG_8xx */
 }
 
-/* This can get called from ioremap, so don't make it an initfunc, OK? */
-static void *MMU_get_page(void)
+/* This can get called from ioremap, so don't make it an __init, OK? */
+static void __init *MMU_get_page(void)
 {
 	void *p;
 
@@ -966,11 +919,12 @@
 	return p;
 }
 
-__initfunc(void free_initmem(void))
+void __init free_initmem(void)
 {
 	unsigned long a;
 	unsigned long num_freed_pages = 0, num_prep_pages = 0,
-		num_pmac_pages = 0, num_openfirmware_pages = 0;
+		num_pmac_pages = 0, num_openfirmware_pages = 0,
+		num_apus_pages = 0;
 #define FREESEC(START,END,CNT) do { \
 	a = (unsigned long)(&START); \
 	for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \
@@ -985,16 +939,24 @@
 	switch (_machine)
 	{
 	case _MACH_Pmac:
+		FREESEC(__apus_begin,__apus_end,num_apus_pages);
 		FREESEC(__prep_begin,__prep_end,num_prep_pages);
 		break;
 	case _MACH_chrp:
+		FREESEC(__apus_begin,__apus_end,num_apus_pages);
 		FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
 		FREESEC(__prep_begin,__prep_end,num_prep_pages);
 		break;
 	case _MACH_prep:
+		FREESEC(__apus_begin,__apus_end,num_apus_pages);
 		FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
 		break;
 	case _MACH_mbx:
+		FREESEC(__apus_begin,__apus_end,num_apus_pages);
+		FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
+		FREESEC(__prep_begin,__prep_end,num_prep_pages);
+		break;
+	case _MACH_apus:
 		FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
 		FREESEC(__prep_begin,__prep_end,num_prep_pages);
 		break;
@@ -1012,6 +974,8 @@
 		printk(" %ldk pmac",(num_pmac_pages*PAGE_SIZE)>>10);
 	if ( num_openfirmware_pages )
 		printk(" %ldk open firmware",(num_openfirmware_pages*PAGE_SIZE)>>10);
+	if ( num_apus_pages )
+		printk(" %ldk apus",(num_apus_pages*PAGE_SIZE)>>10);
 	printk("\n");
 }
 
@@ -1022,7 +986,7 @@
  * still be merged.
  * -- Cort
  */
-__initfunc(void MMU_init(void))
+void __init MMU_init(void)
 {
 #ifdef __SMP__
 	if ( first_cpu_booted ) return;
@@ -1035,6 +999,8 @@
 	else if (_machine == _MACH_apus )
 		end_of_DRAM = apus_find_end_of_memory();
 #endif
+	else if ( _machine == _MACH_gemini )
+		end_of_DRAM = gemini_find_end_of_memory();
 	else /* prep */
 		end_of_DRAM = prep_find_end_of_memory();
 
@@ -1083,6 +1049,10 @@
 		   (kernel_map) remaps individual IO regions to
 		   0x90000000. */
 		break;
+	case _MACH_gemini:
+		setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE);
+		setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
+		break;
 	}
 	ioremap_bot = ioremap_base;
 #else /* CONFIG_8xx */
@@ -1114,7 +1084,7 @@
  * that setup_arch returns, making sure that there are at
  * least 32 pages unused before this for MMU_get_page to use.
  */
-__initfunc(unsigned long find_available_memory(void))
+unsigned long __init find_available_memory(void)
 {
 	int i, rn;
 	unsigned long a, free;
@@ -1150,7 +1120,7 @@
 /*
  * paging_init() sets up the page tables - in fact we've already done this.
  */
-__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem)
 {
 	extern unsigned long free_area_init(unsigned long, unsigned long);
 	/*
@@ -1166,7 +1136,7 @@
 	return start_mem;
 }
 
-__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
+void __init mem_init(unsigned long start_mem, unsigned long end_mem)
 {
 	unsigned long addr;
 	int i;
@@ -1262,7 +1232,7 @@
  * functions in the image just to get prom_init, all we really need right
  * now is the initialization of the physical memory region.
  */
-__initfunc(unsigned long *mbx_find_end_of_memory(void))
+unsigned long __init *mbx_find_end_of_memory(void)
 {
 	unsigned long kstart, ksize;
 	bd_t	*binfo;
@@ -1299,6 +1269,7 @@
 	return ret;
 }
 #endif /* CONFIG_MBX */
+
 #ifndef CONFIG_8xx
 /*
  * On systems with Open Firmware, collect information about
@@ -1307,7 +1278,7 @@
  * Our text, data, bss use something over 1MB, starting at 0.
  * Open Firmware may be using 1MB at the 4MB point.
  */
-__initfunc(unsigned long *pmac_find_end_of_memory(void))
+unsigned long __init *pmac_find_end_of_memory(void)
 {
 	unsigned long a, total;
 	unsigned long kstart, ksize;
@@ -1399,7 +1370,7 @@
  * this will likely stay separate from the pmac.
  * -- Cort
  */
-__initfunc(unsigned long *prep_find_end_of_memory(void))
+unsigned long __init *prep_find_end_of_memory(void)
 {
 	unsigned long kstart, ksize;
 	unsigned long total;
@@ -1425,9 +1396,30 @@
 	return (__va(total));
 }
 
+unsigned long __init *gemini_find_end_of_memory(void)
+{
+	unsigned long total, kstart, ksize, *ret;
+	unsigned char reg;
+
+	reg = readb(GEMINI_MEMCFG);
+	total = ((1<<((reg & 0x7) - 1)) *
+		 (8<<((reg >> 3) & 0x7)));
+	total *= (1024*1024);
+	phys_mem.regions[0].address = 0;
+	phys_mem.regions[0].size = total;
+	phys_mem.n_regions = 1;
+	
+	ret = __va(phys_mem.regions[0].size);
+	phys_avail = phys_mem;
+	kstart = __pa(_stext);
+	ksize = PAGE_ALIGN( _end - _stext );
+	remove_mem_piece( &phys_avail, kstart, ksize, 0 );
+	return ret;
+}
+
 #ifdef CONFIG_APUS
 #define HARDWARE_MAPPED_SIZE (512*1024)
-__initfunc(unsigned long *apus_find_end_of_memory(void))
+unsigned long __init *apus_find_end_of_memory(void)
 {
 	int shadow = 0;
 
@@ -1505,7 +1497,7 @@
 /*
  * Initialize the hash table and patch the instructions in head.S.
  */
-__initfunc(static void hash_init(void))
+static void __init hash_init(void)
 {
 	int Hash_bits;
 	unsigned long h, ramsize;
@@ -1532,7 +1524,6 @@
 	Hash_mask = (h >> 6) - 1;
 #endif	
 	
-#ifdef NO_RELOAD_HTAB
 	/* shrink the htab since we don't use it on 603's -- Cort */
 	switch (_get_PVR()>>16) {
 	case 3: /* 603 */
@@ -1545,7 +1536,6 @@
 	        /* on 601/4 let things be */
 		break;
  	}
-#endif /* NO_RELOAD_HTAB */
 	
 	if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
 	/* Find some memory for the hash table. */
@@ -1558,12 +1548,6 @@
 	       ramsize >> 20, Hash_size >> 10, Hash);
 	if ( Hash_size )
 	{
-#ifdef CONFIG_APUS
-#define b(x) ((unsigned int*)(((unsigned long)(x)) - KERNELBASE + 0xfff00000))
-#else
-#define b(x) (x)
-#endif
-		
 		Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
 		__clear_user(Hash, Hash_size);
 		
@@ -1572,20 +1556,20 @@
 		 * Patch up the instructions in head.S:hash_page
 		 */
 		Hash_bits = ffz(~Hash_size) - 6;
-		*b(hash_page_patch_A) = (*b(hash_page_patch_A) & ~0xffff)
+		hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)
 			| (__pa(Hash) >> 16);
-		*b(hash_page_patch_A + 1) = (*b(hash_page_patch_A + 1)& ~0x7c0)
+		hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0)
 			| ((26 - Hash_bits) << 6);
 		if (Hash_bits > 16)
 			Hash_bits = 16;
-		*b(hash_page_patch_A + 2) = (*b(hash_page_patch_A + 2)& ~0x7c0)
+		hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0)
 			| ((26 - Hash_bits) << 6);
-		*b(hash_page_patch_B) = (*b(hash_page_patch_B) & ~0xffff)
+		hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff)
 			| (Hash_mask >> 10);
-		*b(hash_page_patch_C) = (*b(hash_page_patch_C) & ~0xffff)
+		hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff)
 			| (Hash_mask >> 10);
 #if 0	/* see hash_page in head.S, note also patch_C ref below */
-		*b(hash_page_patch_D) = (*b(hash_page_patch_D) & ~0xffff)
+		hash_page_patch_D[0] = (hash_page_patch_D[0] & ~0xffff)
 			| (Hash_mask >> 10);
 #endif
 		/*
@@ -1593,8 +1577,8 @@
 		 * out from the data cache and invalidated in the instruction
 		 * cache, on those machines with split caches.
 		 */
-		flush_icache_range((unsigned long) b(hash_page_patch_A),
-				   (unsigned long) b(hash_page_patch_C + 1));
+		flush_icache_range((unsigned long) &hash_page_patch_A[0],
+				   (unsigned long) &hash_page_patch_C[1]);
 	}
 	else {
 		Hash_end = 0;
@@ -1603,9 +1587,9 @@
 		 * start of hash_page, since we can still get DSI
 		 * exceptions on a 603.
 		 */
-		*b(hash_page) = 0x4e800020;
-		flush_icache_range((unsigned long) b(hash_page),
-				   (unsigned long) b(hash_page + 1));
+		hash_page[0] = 0x4e800020;
+		flush_icache_range((unsigned long) &hash_page[0],
+				   (unsigned long) &hash_page[1]);
 	}
 	if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
 }
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds
--- v2.3.15/linux/arch/ppc/vmlinux.lds	Wed Dec 30 10:55:07 1998
+++ linux/arch/ppc/vmlinux.lds	Tue Aug 31 11:36:43 1999
@@ -70,10 +70,24 @@
   . = ALIGN(4096);
   __init_begin = .;
   .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
+  .data.init : { 
+    *(.data.init);
+    __vtop_table_begin = .;
+    *(.vtop_fixup);
+    __vtop_table_end = .;
+    __ptov_table_begin = .;
+    *(.ptov_fixup);
+    __ptov_table_end = .;
+  }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
   . = ALIGN(4096);
   __init_end = .;
-
   . = ALIGN(4096);
   __pmac_begin = .;
   .text.pmac : { *(.text.pmac) }
@@ -87,6 +101,13 @@
   .data.prep : { *(.data.prep) }
   . = ALIGN(4096);
   __prep_end = .;
+
+  . = ALIGN(4096);
+  __apus_begin = .;
+  .text.apus : { *(.text.apus) }
+  .data.apus : { *(.data.apus) }
+  . = ALIGN(4096);
+  __apus_end = .;
 
   . = ALIGN(4096);
   __openfirmware_begin = .;
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/xmon/start.c linux/arch/ppc/xmon/start.c
--- v2.3.15/linux/arch/ppc/xmon/start.c	Mon Jun 28 13:40:39 1999
+++ linux/arch/ppc/xmon/start.c	Tue Aug 31 11:36:43 1999
@@ -13,7 +13,7 @@
 unsigned long TXRDY, RXRDY;
 extern void xmon_printf(const char *fmt, ...);
 
-static int console = 0;
+static int console = 1;
 
 void buf_access(void)
 {
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/xmon/subr_prf.c linux/arch/ppc/xmon/subr_prf.c
--- v2.3.15/linux/arch/ppc/xmon/subr_prf.c	Sat May 22 13:03:00 1999
+++ linux/arch/ppc/xmon/subr_prf.c	Tue Aug 31 11:36:43 1999
@@ -1,6 +1,7 @@
 /*
- * Written by Cort Dougan to replace the version written by
- * Paul Mackerras that had copyright conflicts with Linux.
+ * Written by Cort Dougan to replace the version originally used
+ * by Paul Mackerras, which came from NetBSD and thus had copyright
+ * conflicts with Linux.
  *
  * This file makes liberal use of the standard linux utility
  * routines to reduce the size of the binary.  We assume we can
@@ -20,9 +21,11 @@
 void
 xmon_vfprintf(void *f, const char *fmt, va_list ap)
 {
-	char buf[2048];
-	vsprintf( buf, fmt, ap );
-	xmon_write( f, buf, strlen(buf) );
+	static char xmon_buf[2048];
+	int n;
+
+	n = vsprintf(xmon_buf, fmt, ap);
+	xmon_write(f, xmon_buf, n);
 }
 
 void
diff -u --recursive --new-file v2.3.15/linux/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
--- v2.3.15/linux/arch/ppc/xmon/xmon.c	Mon Jun 28 13:40:39 1999
+++ linux/arch/ppc/xmon/xmon.c	Tue Aug 31 11:36:43 1999
@@ -116,13 +116,11 @@
 	struct pt_regs regs;
 	int msr, cmd;
 
-	printk("Entering xmon kernel debugger.\n");
-	
 	if (excp == NULL) {
 		asm volatile ("stw	0,0(%0)\n\
 			lwz	0,0(1)\n\
 			stw	0,4(%0)\n\
-			stmw	2,8(%0)" : : "r" (&regs));
+			stmw	2,8(%0)" : : "b" (&regs));
 		regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
 		regs.msr = get_msr();
 		regs.ctr = get_ctr();
@@ -472,8 +470,9 @@
 	unsigned sp;
 	unsigned stack[2];
 	struct pt_regs regs;
-	extern char int_return, syscall_ret_1, syscall_ret_2;
+	extern char ret_from_int, ret_from_syscall_1, ret_from_syscall_2;
 	extern char lost_irq_ret, do_bottom_half_ret, do_signal_ret;
+	extern char ret_from_except;
 
 	if (excp != NULL)
 		sp = excp->gpr[1];
@@ -485,9 +484,10 @@
 		if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
 			break;
 		printf("%x ", stack[1]);
-		if (stack[1] == (unsigned) &int_return
-		    || stack[1] == (unsigned) &syscall_ret_1
-		    || stack[1] == (unsigned) &syscall_ret_2
+		if (stack[1] == (unsigned) &ret_from_int
+		    || stack[1] == (unsigned) &ret_from_except
+		    || stack[1] == (unsigned) &ret_from_syscall_1
+		    || stack[1] == (unsigned) &ret_from_syscall_2
 		    || stack[1] == (unsigned) &lost_irq_ret
 		    || stack[1] == (unsigned) &do_bottom_half_ret
 		    || stack[1] == (unsigned) &do_signal_ret) {
diff -u --recursive --new-file v2.3.15/linux/arch/sh/Makefile linux/arch/sh/Makefile
--- v2.3.15/linux/arch/sh/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/Makefile	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,82 @@
+# $Id$
+#
+# 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.
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+#
+
+#
+# Select the object file format to substitute into the linker script.
+#
+tool-prefix	= sh-gniibe-
+oformat		= elf
+
+ifdef CONFIG_CROSSCOMPILE
+CROSS_COMPILE  = $(tool-prefix)
+endif
+
+LINKFLAGS	= # -EL # -static #-N
+MODFLAGS	+=
+
+#
+#
+CFLAGS		+= -m3 # -ml
+LINKFLAGS	+=
+LDFLAGS		+= # -EL
+
+#
+#
+HOSTCC        = cc
+
+#
+# Choosing incompatible machines durings configuration will result in
+# error messages during linking.  Select a default linkscript if
+# none has been choosen above.
+#
+LINKSCRIPT    = arch/sh/vmlinux.lds
+LINKFLAGS     += -T $(word 1,$(LINKSCRIPT)) -e __stext
+
+ifdef LOADADDR
+LINKFLAGS     += -Ttext $(word 1,$(LOADADDR))
+endif
+
+#
+CFLAGS		+= -pipe
+
+HEAD := arch/sh/kernel/head.o arch/sh/kernel/init_task.o
+
+SUBDIRS := $(SUBDIRS) $(addprefix arch/sh/, kernel mm lib)
+CORE_FILES := arch/sh/kernel/kernel.o arch/sh/mm/mm.o $(CORE_FILES)
+LIBS := $(TOPDIR)/arch/sh/lib/lib.a $(LIBS) $(TOPDIR)/arch/sh/lib/lib.a /home/niibe/lib/gcc-lib/sh-gniibe-elf/egcs-2.91.66/libgcc.a
+
+MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+
+vmlinux: arch/sh/vmlinux.lds
+
+arch/sh/vmlinux.lds: arch/sh/vmlinux.lds.S FORCE
+	gcc -E -C -P -I$(HPATH) -imacros $(HPATH)/linux/config.h -Ush arch/sh/vmlinux.lds.S >arch/sh/vmlinux.lds
+
+FORCE: ;
+
+zImage: vmlinux
+	@$(MAKEBOOT) zImage
+
+compressed: zImage
+
+zdisk: vmlinux
+	@$(MAKEBOOT) zdisk
+
+archclean:
+	@$(MAKEBOOT) clean
+	$(MAKE) -C arch/$(ARCH)/kernel clean
+#	$(MAKE) -C arch/$(ARCH)/tools clean
+
+archmrproper:
+
+archdep:
+	@$(MAKEBOOT) dep
diff -u --recursive --new-file v2.3.15/linux/arch/sh/boot/Makefile linux/arch/sh/boot/Makefile
--- v2.3.15/linux/arch/sh/boot/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/boot/Makefile	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,41 @@
+#
+# arch/mips/boot/Makefile
+#
+# 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.
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+OBJS  = 
+
+#
+# Drop some uninteresting sections in the kernel.
+#
+drop-sections	= .reginfo .mdebug
+strip-flags	= $(addprefix --remove-section=,$(drop-sections))
+
+#
+# Fake compressed boot
+#
+zImage:	$(CONFIGURE) mkboot $(TOPDIR)/vmlinux
+	$(OBJCOPY) $(strip-flags) $(TOPDIR)/vmlinux zImage.tmp
+	./mkboot zImage.tmp zImage
+	rm -f zImage.tmp
+
+mkboot: mkboot.c
+	$(HOSTCC) -o $@ $^
+
+# Don't build dependencies, this may die if $(CC) isn't gcc
+dep:
+
+clean:
+	rm -f zImage zImage.tmp mkboot
+
+dummy:
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.15/linux/arch/sh/config.in linux/arch/sh/config.in
--- v2.3.15/linux/arch/sh/config.in	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/config.in	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,78 @@
+#
+# For a description of the syntax of this configuration file,
+# see the Configure script.
+#
+mainmenu_name "Linux/SuperH Kernel Configuration"
+
+mainmenu_option next_comment
+comment 'Code maturity level options'
+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+endmenu
+
+mainmenu_option next_comment
+comment 'Processor type and features'
+choice 'Processor family' \
+	"SH3		CONFIG_CPU_SH3 \
+	 SH4		CONFIG_CPU_SH4" SH3
+bool 'Little Endian' CONFIG_LITTLE_ENDIAN
+hex 'Physical memory start address' CONFIG_MEMORY_START 0c000000
+endmenu
+
+mainmenu_option next_comment
+comment 'Loadable module support'
+bool 'Enable loadable module support' CONFIG_MODULES
+if [ "$CONFIG_MODULES" = "y" ]; then
+  bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
+  bool 'Kernel module loader' CONFIG_KMOD
+fi
+endmenu
+
+define_bool CONFIG_SERIAL n
+define_bool CONFIG_SH3SCI_SERIAL y
+define_bool CONFIG_SERIAL_CONSOLE y
+
+mainmenu_option next_comment
+comment 'Floppy, IDE, and other block devices'
+
+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 ELF binaries' CONFIG_BINFMT_ELF
+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+
+tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
+if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
+  bool '   Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
+fi
+
+tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
+tristate 'Network block device support' CONFIG_BLK_DEV_NBD
+endmenu
+
+if [ "$CONFIG_NET" = "y" ]; then
+	source net/Config.in
+fi
+
+mainmenu_option next_comment
+comment 'Unix 98 PTY support'
+bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
+if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
+	int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
+fi
+endmenu
+
+source fs/Config.in
+
+mainmenu_option next_comment
+comment 'Watchdog'
+
+tristate 'Software watchdog' CONFIG_SOFT_WATCHDOG
+endmenu
+
+mainmenu_option next_comment
+comment 'Kernel hacking'
+
+bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+endmenu
diff -u --recursive --new-file v2.3.15/linux/arch/sh/defconfig linux/arch/sh/defconfig
--- v2.3.15/linux/arch/sh/defconfig	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/defconfig	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,101 @@
+#
+# Automatically generated make config: don't edit
+#
+
+#
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+
+#
+# Processor type and features
+#
+CONFIG_CPU_SH3=y
+# CONFIG_CPU_SH4 is not set
+# CONFIG_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0c000000
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+# CONFIG_SERIAL is not set
+CONFIG_SH3SCI_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+
+#
+# Floppy, IDE, and other block devices
+#
+# CONFIG_NET is not set
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK is not set
+# CONFIG_FIREWALL is not set
+# CONFIG_FILTER is not set
+# CONFIG_UNIX is not set
+# CONFIG_INET is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Unix 98 PTY support
+#
+# CONFIG_UNIX98_PTYS is not set
+
+#
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMD_DISKLABEL is not set
+# CONFIG_SGI_DISKLABEL is not set
+# CONFIG_NLS is not set
+
+#
+# Watchdog
+#
+# CONFIG_SOFT_WATCHDOG is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_MAGIC_SYSRQ is not set
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/Makefile linux/arch/sh/kernel/Makefile
--- v2.3.15/linux/arch/sh/kernel/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/Makefile	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,27 @@
+#
+# Makefile for the Linux/SuperH 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.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+
+O_TARGET := kernel.o
+O_OBJS   := process.o signal.o entry.o traps.o irq.o irq_onchip.o \
+            ptrace.o setup.o time.o sys_sh.o test-img.o semaphore.o
+OX_OBJS  := sh_ksyms.o
+MX_OBJS  :=
+
+all: kernel.o head.o init_task.o
+
+entry.o: entry.S
+
+head.o: head.S
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/entry.S linux/arch/sh/kernel/entry.S
--- v2.3.15/linux/arch/sh/kernel/entry.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/entry.S	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,683 @@
+/* $Id$
+ *
+ *  linux/arch/sh/entry.S
+ *
+ *  Copyright (C) 1999  Niibe Yutaka
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+
+! NOTE:
+! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
+! to be jumped is too far, but it causes illegal slot exception.
+
+/*	
+ * entry.S contains the system-call and fault low-level handling routines.
+ * This also contains the timer-interrupt handler, as well as all interrupts
+ * and faults that can result in a task-switch.
+ *
+ * NOTE: This code handles signal-recognition, which happens every time
+ * after a timer-interrupt and after each system call.
+ *
+ * Stack layout in 'ret_from_syscall':
+ * 	ptrace needs to have all regs on the stack.
+ *	if the order here is changed, it needs to be
+ *	updated in process.c:copy_thread, signal.c:do_signal,
+ *	ptrace.c and ptrace.h
+ *
+ *	syscall #	
+ *	r0
+ *      ...
+ *	r15
+ *	gbr
+ *	mach
+ *	macl
+ *	pr
+ *	ssr
+ *	spc
+ *
+ */
+
+/*
+ * these are offsets into the task-struct.
+ */
+state		=  0
+flags		=  4
+sigpending	=  8
+addr_limit	= 12
+need_resched	= 20
+
+PF_TRACESYS  = 0x20
+
+ENOSYS = 38
+
+TRA    = 0xffffffd0
+EXPEVT = 0xffffffd4
+INTEVT = 0xffffffd8
+
+/* Offsets to the stack */
+SYSCALL_NR =  0
+R0         =  4
+R15	   =  64
+
+#define k0	r0
+#define k1	r1
+#define k2	r2
+#define k3	r3
+
+#define kernel_sp	r4	/* r4_bank1 */
+#define ksp		r4_bank	/* r4_bank1 */
+#define k_ex_code	r2_bank	/* r2_bank1 */
+
+/* Kernel mode register usage:
+	k0	scratch
+	k1	scratch
+	k2	scratch (Exception code)
+	k3	scratch (Return address)
+	k4	Stack base = current+8192
+	k5	reserved
+	k6	reserved
+	k7	reserved
+*/
+
+!
+! TLB Miss / Initial Page write exception handling
+!			_and_
+! TLB hits, but the access violate the protection.
+! It can be valid access, such as stack grow and/or C-O-W.
+!
+!
+! Find the pmd/pte entry and loadtlb
+! If it's not found, cause address error (SEGV)
+!
+! Although this could be written in assembly language (and it'd be faster),
+! this first version depends *much* on C implementation.
+!
+MMU_TEA = 0xfffffffc		! TLB Exception Address Register
+
+#define DO_FAULT(write) \
+	mov	#MMU_TEA,r0; \
+	mov.l	@r0,r6; \
+	/* STI */ \
+	mov.l	3f,r1; \
+	stc	sr,r0; \
+	and	r1,r0; \
+	ldc	r0,sr; \
+	/*    */ \
+	mov	r15,r4; \
+	mov.l	2f,r0; \
+	jmp	@r0; \
+	 mov	#write,r5;
+
+	.balign	4
+tlb_protection_violation_load:
+tlb_miss_load:
+	mov	#-1,r0
+	mov.l	r0,@r15		! syscall nr = -1
+	DO_FAULT(0)
+
+	.balign	4
+tlb_protection_violation_store:
+tlb_miss_store:
+initial_page_write:
+	mov	#-1,r0
+	mov.l	r0,@r15		! syscall nr = -1
+	DO_FAULT(1)
+
+	.balign 4
+2:	.long	SYMBOL_NAME(do_page_fault)
+3:	.long	0xefffffff	! BL=0
+
+
+	.balign	4
+error:	mov	#-1,r0
+	! STI
+	mov.l	2f,r1
+	stc	sr,r0
+	and	r1,r0
+	ldc	r0,sr
+	!
+	mov.l	r0,@r15		! syscall nr = -1
+	mov.l	1f,r1
+	jmp	@r1
+	 nop
+	.balign	4
+1:	.long	SYMBOL_NAME(do_exception_error)
+
+reschedule:
+	mova	SYMBOL_NAME(ret_from_syscall),r0
+	mov.l	1f,r1
+	jmp	@r1
+	 lds	r0,pr
+	.balign	4
+1:	.long	SYMBOL_NAME(schedule)
+
+badsys:	mov	#-ENOSYS,r0
+	bra	SYMBOL_NAME(ret_from_syscall)
+	 mov.l	r0,@(R0,r15)
+
+signal_return:
+	! We can reach here from an interrupt handler,
+	! so, we need to unblock interrupt.
+	mov.l	1f,r1
+	stc	sr,r0
+	and	r1,r0
+	ldc	r0,sr
+	!
+	mov	r15,r4
+	mov	#0,r5
+	mov.l	2f,r1
+	mova	restore_all,r0
+	jmp	@r1
+	 lds	r0,pr
+	.balign	4
+1:	.long	0xefffffff		! BL=0
+2:	.long	SYMBOL_NAME(do_signal)
+
+!
+!
+!
+ENTRY(ret_from_fork)
+	bra	SYMBOL_NAME(ret_from_syscall)
+	 add	#4,r15		! pop down bogus r0
+
+!
+! The immediate value of "trapa" indicates the number of arguments
+! placed on the stack.
+!
+system_call:
+	mov	#TRA,r2
+	mov.l	@r2,r8
+	! STI
+	mov.l	2f,r1
+	stc	sr,r2
+	and	r1,r2
+	ldc	r2,sr
+	!
+	mov.l	__n_sys,r1
+	cmp/ge	r1,r0
+	bt	badsys
+	!
+	stc	ksp,r1		!
+	mov.l	__tsk_flags,r0	!
+	add	r0,r1		!
+	mov.l	@r1,r0		! Is it trace?
+	tst	#PF_TRACESYS,r0
+	bt	6f
+	!                     Trace system call
+	mov	#-ENOSYS,r1
+	mov.l	r1,@(R0,r15)
+	mov.l	3f,r1
+	jsr	@r1
+	 nop
+	mova	4f,r0
+	bra	7f
+	 lds	r0,pr
+	!
+6:	mova	1f,r0
+	lds	r0,pr
+	!			Build the stack frame if TRA > 0
+7:	cmp/pl	r8
+	bf	9f
+	shll2	r8		! x4
+	mov	#R15,r0
+	mov.l	@(r0,r15),r0	! get original stack
+8:	add	#-4,r8
+	mov.l	@(r0,r8),r1
+	mov.l	r1,@-r15
+	cmp/pl	r8
+	bt	8b
+	!
+9:	mov.l	@(SYSCALL_NR,r15),r0
+	shll2	r0		! x4
+	mov.l	__sct,r1
+	add	r1,r0
+	mov.l	@r0,r1
+	jmp	@r1
+	 nop
+	.balign	4
+4:	mov.l	r0,@(R0,r15)	! save the return value
+	mov.l	3f,r1
+	mova	SYMBOL_NAME(ret_from_syscall),r0
+	jmp	@r1
+	 lds	r0,pr
+	.balign	4
+3:	.long	SYMBOL_NAME(syscall_trace)
+2:	.long	0xefffffff	! BL=0
+1:	mov.l	r0,@(R0,r15)	! save the return value
+	/* fall through */
+
+ENTRY(ret_from_syscall)
+ENTRY(ret_from_irq)
+	mov.l	__bh_mask,r0
+	mov.l	@r0,r1
+	mov.l	__bh_active,r0
+	mov.l	@r0,r2
+	tst	r2,r1
+	bt	ret_with_reschedule
+handle_bottom_half:
+	mov.l	__dbh,r0
+	jsr	@r0
+	 nop
+ret_with_reschedule:
+	stc	ksp,r1
+	mov.l	__minus8192,r0
+	add	r0,r1
+	mov.l	@(need_resched,r1),r0
+	tst	#0xff,r0
+	bf	reschedule
+	mov.l	@(sigpending,r1),r0
+	tst	#0xff,r0
+	bf	signal_return
+	!
+	.balign	4
+restore_all:
+	add	#4,r15		! skip syscall number
+	mov.l	@r15+,r0
+	mov.l	@r15+,r1
+	mov.l	@r15+,r2
+	mov.l	@r15+,r3
+	mov.l	@r15+,r4
+	mov.l	@r15+,r5
+	mov.l	@r15+,r6
+	mov.l	@r15+,r7
+	stc	sr,r14
+	mov.l	__blrb_flags,r9		! BL =1, RB=1
+	or	r9,r14
+	ldc	r14,sr			! here, change the register bank
+	mov.l	@r15+,r8
+	mov.l	@r15+,r9
+	mov.l	@r15+,r10
+	mov.l	@r15+,r11
+	mov.l	@r15+,r12
+	mov.l	@r15+,r13
+	mov.l	@r15+,r14
+	mov.l	@r15+,k0
+	ldc.l	@r15+,gbr
+	lds.l	@r15+,mach
+	lds.l	@r15+,macl
+	lds.l	@r15+,pr
+	ldc.l	@r15+,ssr
+	ldc.l	@r15+,spc
+	mov	k0,r15
+	rte
+	 nop
+
+	.balign	4
+__n_sys:	.long	NR_syscalls
+__sct:		.long	SYMBOL_NAME(sys_call_table)
+__bh_mask:	.long	SYMBOL_NAME(bh_mask)
+__bh_active:	.long	SYMBOL_NAME(bh_active)
+__dbh:		.long	SYMBOL_NAME(do_bottom_half)
+__blrb_flags:	.long	0x30000000
+__minus8192:	.long	-8192		! offset from stackbase to tsk
+__tsk_flags:	.long	flags-8192	! offset from stackbase to tsk->flags
+
+
+! Exception Vector Base
+!
+!	Should be aligned page boundary.
+!
+	.balign 	4096,0,4096
+ENTRY(vbr_base)
+	.long	0
+!
+	.balign 	256,0,256
+general_exception:
+	mov	#EXPEVT,k2
+	mov.l	2f,k3
+	bra	handle_exception
+	 mov.l	@k2,k2
+	.balign	4
+2:	.long	SYMBOL_NAME(ret_from_syscall)
+!
+!
+	.balign 	1024,0,1024
+tlb_miss:
+	mov	#EXPEVT,k2
+	mov.l	3f,k3
+	bra	handle_exception
+	 mov.l	@k2,k2
+!
+	.balign 	512,0,512
+interrupt:
+	mov	#INTEVT,k2
+	mov.l	4f,k3
+	bra	handle_exception
+	 mov.l	@k2,k2
+
+	.balign	4
+3:	.long	SYMBOL_NAME(ret_from_syscall)
+4:	.long	SYMBOL_NAME(ret_from_irq)
+
+!
+!
+handle_exception:
+	! Using k0, k1 for scratch registers (r0_bank1, and r1_bank1),
+	! save all registers onto stack.
+	!
+	mov.l	2f,k1
+	stc	ssr,k0		! from kernel space?
+	shll	k0		! Check MD bit (bit30)
+	shll	k0
+	bt/s	1f		! it's from kernel to kernel transition
+	 mov	r15,k0		! save original stack to k0 anyway
+	mov	kernel_sp,r15	! change to kernel stack
+1:	stc.l	spc,@-r15	! save control registers
+	stc.l	ssr,@-r15
+	sts.l	pr,@-r15
+	!
+	lds	k3,pr		! Set the return address to pr
+	!
+	sts.l	macl,@-r15
+	sts.l	mach,@-r15
+	stc.l	gbr,@-r15
+	mov.l	k0,@-r15	! save orignal stack, and general registers
+	mov.l	r14,@-r15
+	!
+	stc	sr,r14		! back to normal register bank, and
+	and	k1,r14		! ..
+	ldc	r14,sr		! ...changed here.
+	!
+	mov.l	r13,@-r15
+	mov.l	r12,@-r15
+	mov.l	r11,@-r15
+	mov.l	r10,@-r15
+	mov.l	r9,@-r15
+	mov.l	r8,@-r15
+	mov.l	r7,@-r15
+	mov.l	r6,@-r15
+	mov.l	r5,@-r15
+	mov.l	r4,@-r15
+	mov.l	r3,@-r15
+	mov.l	r2,@-r15
+	mov.l	r1,@-r15
+	mov.l	r0,@-r15
+	mov.l	r0,@-r15	! push r0 again (for syscall number)
+	! Then, dispatch to the handler, according to the excepiton code.
+	stc	k_ex_code,r1
+	shlr2	r1
+	shlr	r1
+	mov.l	1f,r0
+	add	r1,r0
+	mov.l	@r0,r0
+	jmp	@r0
+	 mov.l	@r15,r0		! recovering r0..
+	.balign	4
+1:	.long	SYMBOL_NAME(exception_handling_table)
+2:	.long	0xdfffffff	! RB=0, BL=1
+
+.data
+ENTRY(exception_handling_table)
+	.long	0
+	.long	0
+	.long	tlb_miss_load
+	.long	tlb_miss_store
+	.long	initial_page_write
+	.long	tlb_protection_violation_load
+	.long	tlb_protection_violation_store
+	.long	error	! address_error_load        (filled by trap_init)
+	.long	error	! address_error_store       (filled by trap_init)
+	.long	0
+	.long	0
+	.long	system_call			! Unconditional Trap
+	.long	error	! reserved_instruction      (filled by trap_init)
+	.long	error	! illegal_slot_instruction  (filled by trap_init)
+ENTRY(nmi_slot)
+	.long	error				! Not implemented yet
+ENTRY(user_break_point_trap)
+	.long	error				! Not implemented yet
+ENTRY(interrupt_table)
+	! external hardware
+	.long	SYMBOL_NAME(do_IRQ)	! 0000
+	.long	SYMBOL_NAME(do_IRQ)	! 0001
+	.long	SYMBOL_NAME(do_IRQ)	! 0010
+	.long	SYMBOL_NAME(do_IRQ)	! 0011
+	.long	SYMBOL_NAME(do_IRQ)	! 0100
+	.long	SYMBOL_NAME(do_IRQ)	! 0101
+	.long	SYMBOL_NAME(do_IRQ)	! 0110
+	.long	SYMBOL_NAME(do_IRQ)	! 0111
+	.long	SYMBOL_NAME(do_IRQ)	! 1000
+	.long	SYMBOL_NAME(do_IRQ)	! 1001
+	.long	SYMBOL_NAME(do_IRQ)	! 1010
+	.long	SYMBOL_NAME(do_IRQ)	! 1011
+	.long	SYMBOL_NAME(do_IRQ)	! 1100
+	.long	SYMBOL_NAME(do_IRQ)	! 1101
+	.long	SYMBOL_NAME(do_IRQ)	! 1110
+	.long	0
+	! Internal hardware
+	.long	SYMBOL_NAME(do_IRQ)	! TMU0 tuni0
+	.long	SYMBOL_NAME(do_IRQ)	! TMU1 tuni1
+	.long	SYMBOL_NAME(do_IRQ)	! TMU2 tuni2
+	.long	SYMBOL_NAME(do_IRQ)	!      ticpi2
+	.long	SYMBOL_NAME(do_IRQ)	! RTC  ati
+	.long	SYMBOL_NAME(do_IRQ)	!      pri
+	.long	SYMBOL_NAME(do_IRQ)	!      cui
+	.long	SYMBOL_NAME(do_IRQ)	! SCI  eri
+	.long	SYMBOL_NAME(do_IRQ)	!      rxi
+	.long	SYMBOL_NAME(do_IRQ)	!      txi
+	.long	SYMBOL_NAME(do_IRQ)	!      tei
+	.long	SYMBOL_NAME(do_IRQ)	! WDT  iti
+	.long	SYMBOL_NAME(do_IRQ)	! REF  rcmi
+	.long	SYMBOL_NAME(do_IRQ)	!      rovi
+	.long	SYMBOL_NAME(do_IRQ)
+	.long	SYMBOL_NAME(do_IRQ)
+	.long	SYMBOL_NAME(do_IRQ)
+	.long	SYMBOL_NAME(do_IRQ)
+	.long	SYMBOL_NAME(do_IRQ)
+	.long	SYMBOL_NAME(do_IRQ)
+	.long	SYMBOL_NAME(do_IRQ)
+	.long	SYMBOL_NAME(do_IRQ)
+	.long	SYMBOL_NAME(do_IRQ)
+	.long	SYMBOL_NAME(do_IRQ)
+
+ENTRY(sys_call_table)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* 0  -  old "setup()" system call*/
+	.long SYMBOL_NAME(sys_exit)
+	.long SYMBOL_NAME(sys_fork)
+	.long SYMBOL_NAME(sys_read)
+	.long SYMBOL_NAME(sys_write)
+	.long SYMBOL_NAME(sys_open)		/* 5 */
+	.long SYMBOL_NAME(sys_close)
+	.long SYMBOL_NAME(sys_waitpid)
+	.long SYMBOL_NAME(sys_creat)
+	.long SYMBOL_NAME(sys_link)
+	.long SYMBOL_NAME(sys_unlink)		/* 10 */
+	.long SYMBOL_NAME(sys_execve)
+	.long SYMBOL_NAME(sys_chdir)
+	.long SYMBOL_NAME(sys_time)
+	.long SYMBOL_NAME(sys_mknod)
+	.long SYMBOL_NAME(sys_chmod)		/* 15 */
+	.long SYMBOL_NAME(sys_lchown)
+	.long SYMBOL_NAME(sys_ni_syscall)				/* old break syscall holder */
+	.long SYMBOL_NAME(sys_stat)
+	.long SYMBOL_NAME(sys_lseek)
+	.long SYMBOL_NAME(sys_getpid)		/* 20 */
+	.long SYMBOL_NAME(sys_mount)
+	.long SYMBOL_NAME(sys_oldumount)
+	.long SYMBOL_NAME(sys_setuid)
+	.long SYMBOL_NAME(sys_getuid)
+	.long SYMBOL_NAME(sys_stime)		/* 25 */
+	.long SYMBOL_NAME(sys_ptrace)
+	.long SYMBOL_NAME(sys_alarm)
+	.long SYMBOL_NAME(sys_fstat)
+	.long SYMBOL_NAME(sys_pause)
+	.long SYMBOL_NAME(sys_utime)		/* 30 */
+	.long SYMBOL_NAME(sys_ni_syscall)				/* old stty syscall holder */
+	.long SYMBOL_NAME(sys_ni_syscall)				/* old gtty syscall holder */
+	.long SYMBOL_NAME(sys_access)
+	.long SYMBOL_NAME(sys_nice)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* 35 */		/* old ftime syscall holder */
+	.long SYMBOL_NAME(sys_sync)
+	.long SYMBOL_NAME(sys_kill)
+	.long SYMBOL_NAME(sys_rename)
+	.long SYMBOL_NAME(sys_mkdir)
+	.long SYMBOL_NAME(sys_rmdir)		/* 40 */
+	.long SYMBOL_NAME(sys_dup)
+	.long SYMBOL_NAME(sys_pipe)
+	.long SYMBOL_NAME(sys_times)
+	.long SYMBOL_NAME(sys_ni_syscall)				/* old prof syscall holder */
+	.long SYMBOL_NAME(sys_brk)		/* 45 */
+	.long SYMBOL_NAME(sys_setgid)
+	.long SYMBOL_NAME(sys_getgid)
+	.long SYMBOL_NAME(sys_signal)
+	.long SYMBOL_NAME(sys_geteuid)
+	.long SYMBOL_NAME(sys_getegid)		/* 50 */
+	.long SYMBOL_NAME(sys_acct)
+	.long SYMBOL_NAME(sys_umount)					/* recycled never used phys() */
+	.long SYMBOL_NAME(sys_ni_syscall)				/* old lock syscall holder */
+	.long SYMBOL_NAME(sys_ioctl)
+	.long SYMBOL_NAME(sys_fcntl)		/* 55 */
+	.long SYMBOL_NAME(sys_ni_syscall)				/* old mpx syscall holder */
+	.long SYMBOL_NAME(sys_setpgid)
+	.long SYMBOL_NAME(sys_ni_syscall)				/* old ulimit syscall holder */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_olduname */
+	.long SYMBOL_NAME(sys_umask)		/* 60 */
+	.long SYMBOL_NAME(sys_chroot)
+	.long SYMBOL_NAME(sys_ustat)
+	.long SYMBOL_NAME(sys_dup2)
+	.long SYMBOL_NAME(sys_getppid)
+	.long SYMBOL_NAME(sys_getpgrp)		/* 65 */
+	.long SYMBOL_NAME(sys_setsid)
+	.long SYMBOL_NAME(sys_sigaction)
+	.long SYMBOL_NAME(sys_sgetmask)
+	.long SYMBOL_NAME(sys_ssetmask)
+	.long SYMBOL_NAME(sys_setreuid)		/* 70 */
+	.long SYMBOL_NAME(sys_setregid)
+	.long SYMBOL_NAME(sys_sigsuspend)
+	.long SYMBOL_NAME(sys_sigpending)
+	.long SYMBOL_NAME(sys_sethostname)
+	.long SYMBOL_NAME(sys_setrlimit)	/* 75 */
+	.long SYMBOL_NAME(sys_getrlimit)
+	.long SYMBOL_NAME(sys_getrusage)
+	.long SYMBOL_NAME(sys_gettimeofday)
+	.long SYMBOL_NAME(sys_settimeofday)
+	.long SYMBOL_NAME(sys_getgroups)	/* 80 */
+	.long SYMBOL_NAME(sys_setgroups)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old_select */
+	.long SYMBOL_NAME(sys_symlink)
+	.long SYMBOL_NAME(sys_lstat)
+	.long SYMBOL_NAME(sys_readlink)		/* 85 */
+	.long SYMBOL_NAME(sys_uselib)
+	.long SYMBOL_NAME(sys_swapon)
+	.long SYMBOL_NAME(sys_reboot)
+	.long SYMBOL_NAME(old_readdir)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old_mmap */	/* 90 */
+	.long SYMBOL_NAME(sys_munmap)
+	.long SYMBOL_NAME(sys_truncate)
+	.long SYMBOL_NAME(sys_ftruncate)
+	.long SYMBOL_NAME(sys_fchmod)
+	.long SYMBOL_NAME(sys_fchown)		/* 95 */
+	.long SYMBOL_NAME(sys_getpriority)
+	.long SYMBOL_NAME(sys_setpriority)
+	.long SYMBOL_NAME(sys_ni_syscall)				/* old profil syscall holder */
+	.long SYMBOL_NAME(sys_statfs)
+	.long SYMBOL_NAME(sys_fstatfs)		/* 100 */
+	.long SYMBOL_NAME(sys_ni_syscall)		/* ioperm */
+	.long SYMBOL_NAME(sys_socketcall)
+	.long SYMBOL_NAME(sys_syslog)
+	.long SYMBOL_NAME(sys_setitimer)
+	.long SYMBOL_NAME(sys_getitimer)	/* 105 */
+	.long SYMBOL_NAME(sys_newstat)
+	.long SYMBOL_NAME(sys_newlstat)
+	.long SYMBOL_NAME(sys_newfstat)
+	.long SYMBOL_NAME(sys_uname)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* 110 */ /* iopl */
+	.long SYMBOL_NAME(sys_vhangup)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* idle */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* vm86old */
+	.long SYMBOL_NAME(sys_wait4)
+	.long SYMBOL_NAME(sys_swapoff)		/* 115 */
+	.long SYMBOL_NAME(sys_sysinfo)
+	.long SYMBOL_NAME(sys_ipc)
+	.long SYMBOL_NAME(sys_fsync)
+	.long SYMBOL_NAME(sys_sigreturn)
+	.long SYMBOL_NAME(sys_clone)		/* 120 */
+	.long SYMBOL_NAME(sys_setdomainname)
+	.long SYMBOL_NAME(sys_newuname)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_modify_ldt */
+	.long SYMBOL_NAME(sys_adjtimex)
+	.long SYMBOL_NAME(sys_mprotect)		/* 125 */
+	.long SYMBOL_NAME(sys_sigprocmask)
+	.long SYMBOL_NAME(sys_create_module)
+	.long SYMBOL_NAME(sys_init_module)
+	.long SYMBOL_NAME(sys_delete_module)
+	.long SYMBOL_NAME(sys_get_kernel_syms)	/* 130 */
+	.long SYMBOL_NAME(sys_quotactl)
+	.long SYMBOL_NAME(sys_getpgid)
+	.long SYMBOL_NAME(sys_fchdir)
+	.long SYMBOL_NAME(sys_bdflush)
+	.long SYMBOL_NAME(sys_sysfs)		/* 135 */
+	.long SYMBOL_NAME(sys_personality)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* for afs_syscall */
+	.long SYMBOL_NAME(sys_setfsuid)
+	.long SYMBOL_NAME(sys_setfsgid)
+	.long SYMBOL_NAME(sys_llseek)		/* 140 */
+	.long SYMBOL_NAME(sys_getdents)
+	.long SYMBOL_NAME(sys_select)
+	.long SYMBOL_NAME(sys_flock)
+	.long SYMBOL_NAME(sys_msync)
+	.long SYMBOL_NAME(sys_readv)		/* 145 */
+	.long SYMBOL_NAME(sys_writev)
+	.long SYMBOL_NAME(sys_getsid)
+	.long SYMBOL_NAME(sys_fdatasync)
+	.long SYMBOL_NAME(sys_sysctl)
+	.long SYMBOL_NAME(sys_mlock)		/* 150 */
+	.long SYMBOL_NAME(sys_munlock)
+	.long SYMBOL_NAME(sys_mlockall)
+	.long SYMBOL_NAME(sys_munlockall)
+	.long SYMBOL_NAME(sys_sched_setparam)
+	.long SYMBOL_NAME(sys_sched_getparam)   /* 155 */
+	.long SYMBOL_NAME(sys_sched_setscheduler)
+	.long SYMBOL_NAME(sys_sched_getscheduler)
+	.long SYMBOL_NAME(sys_sched_yield)
+	.long SYMBOL_NAME(sys_sched_get_priority_max)
+	.long SYMBOL_NAME(sys_sched_get_priority_min)  /* 160 */
+	.long SYMBOL_NAME(sys_sched_rr_get_interval)
+	.long SYMBOL_NAME(sys_nanosleep)
+	.long SYMBOL_NAME(sys_mremap)
+	.long SYMBOL_NAME(sys_setresuid)
+	.long SYMBOL_NAME(sys_getresuid)	/* 165 */
+	.long SYMBOL_NAME(sys_ni_syscall)		/* vm86 */
+	.long SYMBOL_NAME(sys_query_module)
+	.long SYMBOL_NAME(sys_poll)
+	.long SYMBOL_NAME(sys_nfsservctl)
+	.long SYMBOL_NAME(sys_setresgid)	/* 170 */
+	.long SYMBOL_NAME(sys_getresgid)
+	.long SYMBOL_NAME(sys_prctl)
+	.long SYMBOL_NAME(sys_rt_sigreturn)
+	.long SYMBOL_NAME(sys_rt_sigaction)
+	.long SYMBOL_NAME(sys_rt_sigprocmask)	/* 175 */
+	.long SYMBOL_NAME(sys_rt_sigpending)
+	.long SYMBOL_NAME(sys_rt_sigtimedwait)
+	.long SYMBOL_NAME(sys_rt_sigqueueinfo)
+	.long SYMBOL_NAME(sys_rt_sigsuspend)
+	.long SYMBOL_NAME(sys_pread)		/* 180 */
+	.long SYMBOL_NAME(sys_pwrite)
+	.long SYMBOL_NAME(sys_chown)
+	.long SYMBOL_NAME(sys_getcwd)
+	.long SYMBOL_NAME(sys_capget)
+	.long SYMBOL_NAME(sys_capset)           /* 185 */
+	.long SYMBOL_NAME(sys_sigaltstack)
+	.long SYMBOL_NAME(sys_sendfile)
+	.long SYMBOL_NAME(sys_ni_syscall)		/* streams1 */
+	.long SYMBOL_NAME(sys_ni_syscall)		/* streams2 */
+	.long SYMBOL_NAME(sys_vfork)            /* 190 */
+
+	/*
+	 * NOTE!! This doesn't have to be exact - we just have
+	 * to make sure we have _enough_ of the "sys_ni_syscall"
+	 * entries. Don't panic if you notice that this hasn't
+	 * been shrunk every time we add a new system call.
+	 */
+	.rept NR_syscalls-190
+		.long SYMBOL_NAME(sys_ni_syscall)
+	.endr
+
+/* End of entry.S */
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/head.S linux/arch/sh/kernel/head.S
--- v2.3.15/linux/arch/sh/kernel/head.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/head.S	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,69 @@
+/* $Id$
+ *
+ *  arch/sh/kernel/head.S
+ *
+ *  Copyright (C) 1999  Niibe Yutaka
+ *
+ * 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.
+ *
+ * Head.S contains the SH exception handlers and startup code.
+ */
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/linkage.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#ifdef CONFIG_CPU_SH3
+/* Following values are assumed to be as small as immediate. */
+#define CCR		0xffffffec	/* Address of Cache Control Register */
+#define CACHE_INIT	0x00000009	/* 8k-byte cache, flush, enable */
+#elif CONFIG_CPU_SH4
+/* Should fill here. */
+#endif
+
+ENTRY(_stext)
+	!			Switch to register bank 0
+	stc	sr,r1		!
+	mov.l	1f,r0		! RB=0, BL=1
+	and	r1,r0
+	ldc	r0,sr
+	!			Enable cache
+#ifdef CONFIG_CPU_SH3
+	mov	#CCR,r1
+	mov.l	@r1,r0
+	cmp/eq	#1,r0		! If it's enabled already, don't flush it
+	bt/s	8f
+	 mov	#CACHE_INIT,r0
+	mov.l	r0,@r1
+#elif CONFIG_CPU_SH4
+	! Should fill here.
+#endif
+8:
+	!
+	mov.l	2f,r0
+	mov	r0,r15		! Set initial r15 (stack pointer)
+	ldc	r0,r4_bank	!   and stack base
+	!			Clear BSS area
+	mov.l	3f,r1
+	mov.l	4f,r2
+	mov	#0,r0
+9:	mov.l	r0,@r1
+	cmp/hs	r2,r1
+	bf/s	9b
+	 add	#4,r1
+	!			Start kernel
+	mov.l	5f,r0
+	jmp	@r0
+	 nop
+
+	.balign 4
+1:	.long 0xdfffffff		! RB=0, BL=1
+2:	.long SYMBOL_NAME(stack)
+3:	.long SYMBOL_NAME(__bss_start)
+4:	.long SYMBOL_NAME(_end)
+5:	.long SYMBOL_NAME(start_kernel)
+
+.data
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/init_task.c linux/arch/sh/kernel/init_task.c
--- v2.3.15/linux/arch/sh/kernel/init_task.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/init_task.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,23 @@
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static struct vm_area_struct init_mmap = INIT_MMAP;
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS;
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+/*
+ * Initial task structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+union task_union init_task_union 
+	__attribute__((__section__(".data.init_task"))) =
+		{ INIT_TASK(init_task_union.task) };
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/irq.c linux/arch/sh/kernel/irq.c
--- v2.3.15/linux/arch/sh/kernel/irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/irq.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,485 @@
+/*
+ * linux/arch/sh/kernel/irq.c
+ *
+ *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ *
+ *  SuperH version:  Copyright (C) 1999  Niibe Yutaka
+ */
+
+/*
+ * IRQs are in fact implemented a bit like signal handlers for the kernel.
+ * Naturally it's not a 1:1 relation, but there are similarities.
+ */
+
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/smp.h>
+#include <asm/pgtable.h>
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <linux/irq.h>
+
+
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+
+/*
+ * Micro-access to controllers is serialized over the whole
+ * system. We never hold this lock when we call the actual
+ * IRQ handler.
+ */
+spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
+/*
+ * Controller mappings for all interrupt sources:
+ */
+irq_desc_t irq_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }};
+
+/*
+ * Special irq handlers.
+ */
+
+void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+
+/*
+ * Generic, controller-independent functions:
+ */
+
+int get_irq_list(char *buf)
+{
+	int i, j;
+	struct irqaction * action;
+	char *p = buf;
+
+	p += sprintf(p, "           ");
+	for (j=0; j<smp_num_cpus; j++)
+		p += sprintf(p, "CPU%d       ",j);
+	*p++ = '\n';
+
+	for (i = 0 ; i < NR_IRQS ; i++) {
+		action = irq_desc[i].action;
+		if (!action) 
+			continue;
+		p += sprintf(p, "%3d: ",i);
+		p += sprintf(p, "%10u ", kstat_irqs(i));
+		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
+		p += sprintf(p, "  %s", action->name);
+
+		for (action=action->next; action; action = action->next) {
+			p += sprintf(p, ", %s", action->name);
+		}
+		*p++ = '\n';
+	}
+	return p - buf;
+}
+
+/*
+ * This should really return information about whether
+ * we should do bottom half handling etc. Right now we
+ * end up _always_ checking the bottom half, which is a
+ * waste of time and is not what some drivers would
+ * prefer.
+ */
+int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
+{
+	int status;
+	int cpu = smp_processor_id();
+
+	irq_enter(cpu, irq);
+
+	status = 1;	/* Force the "do bottom halves" bit */
+
+	if (!(action->flags & SA_INTERRUPT))
+		__sti();
+
+	do {
+		status |= action->flags;
+		action->handler(irq, action->dev_id, regs);
+		action = action->next;
+	} while (action);
+	if (status & SA_SAMPLE_RANDOM)
+		add_interrupt_randomness(irq);
+	__cli();
+
+	irq_exit(cpu, irq);
+
+	return status;
+}
+
+/*
+ * Generic enable/disable code: this just calls
+ * down into the PIC-specific version for the actual
+ * hardware disable after having gotten the irq
+ * controller lock. 
+ */
+void disable_irq_nosync(unsigned int irq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&irq_controller_lock, flags);
+	if (!irq_desc[irq].depth++) {
+		irq_desc[irq].status |= IRQ_DISABLED;
+		irq_desc[irq].handler->disable(irq);
+	}
+	spin_unlock_irqrestore(&irq_controller_lock, flags);
+}
+
+/*
+ * Synchronous version of the above, making sure the IRQ is
+ * no longer running on any other IRQ..
+ */
+void disable_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
+
+	if (!local_irq_count[smp_processor_id()]) {
+		do {
+			barrier();
+		} while (irq_desc[irq].status & IRQ_INPROGRESS);
+	}
+}
+
+void enable_irq(unsigned int irq)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&irq_controller_lock, flags);
+	switch (irq_desc[irq].depth) {
+	case 1: {
+		unsigned int status = irq_desc[irq].status & ~IRQ_DISABLED;
+		irq_desc[irq].status = status;
+		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+			irq_desc[irq].status = status | IRQ_REPLAY;
+			hw_resend_irq(irq_desc[irq].handler,irq);
+		}
+		irq_desc[irq].handler->enable(irq);
+		/* fall-through */
+	}
+	default:
+		irq_desc[irq].depth--;
+		break;
+	case 0:
+		printk("enable_irq() unbalanced from %p\n",
+		       __builtin_return_address(0));
+	}
+	spin_unlock_irqrestore(&irq_controller_lock, flags);
+}
+
+/*
+ * do_IRQ handles all normal device IRQ's.
+ */
+asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
+		      unsigned long r6, unsigned long r7,
+		      struct pt_regs regs)
+{	
+	/* 
+	 * We ack quickly, we don't want the irq controller
+	 * thinking we're snobs just because some other CPU has
+	 * disabled global interrupts (we have already done the
+	 * INT_ACK cycles, it's too late to try to pretend to the
+	 * controller that we aren't taking the interrupt).
+	 *
+	 * 0 return value means that this irq is already being
+	 * handled by some other CPU. (or is disabled)
+	 */
+	int irq;
+	int cpu = smp_processor_id();
+	irq_desc_t *desc;
+	struct irqaction * action;
+	unsigned int status;
+
+	/* Get IRQ number */
+	asm volatile("stc	r2_bank,%0\n\t"
+		     "shlr2	%0\n\t"
+		     "shlr2	%0\n\t"
+		     "shlr	%0\n\t"
+		     "add	#-16,%0\n\t"
+		     :"=z" (irq));
+
+	kstat.irqs[cpu][irq]++;
+	desc = irq_desc + irq;
+	spin_lock(&irq_controller_lock);
+	irq_desc[irq].handler->ack(irq);
+	/*
+	   REPLAY is when Linux resends an IRQ that was dropped earlier
+	   WAITING is used by probe to mark irqs that are being tested
+	   */
+	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
+	status |= IRQ_PENDING; /* we _want_ to handle it */
+
+	/*
+	 * If the IRQ is disabled for whatever reason, we cannot
+	 * use the action we have.
+	 */
+	action = NULL;
+	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+		action = desc->action;
+		status &= ~IRQ_PENDING; /* we commit to handling */
+		status |= IRQ_INPROGRESS; /* we are handling it */
+	}
+	desc->status = status;
+	spin_unlock(&irq_controller_lock);
+
+	/*
+	 * If there is no IRQ handler or it was disabled, exit early.
+	   Since we set PENDING, if another processor is handling
+	   a different instance of this same irq, the other processor
+	   will take care of it.
+	 */
+	if (!action)
+		return 1;
+
+	/*
+	 * Edge triggered interrupts need to remember
+	 * pending events.
+	 * This applies to any hw interrupts that allow a second
+	 * instance of the same irq to arrive while we are in do_IRQ
+	 * or in the handler. But the code here only handles the _second_
+	 * instance of the irq, not the third or fourth. So it is mostly
+	 * useful for irq hardware that does not mask cleanly in an
+	 * SMP environment.
+	 */
+	for (;;) {
+		handle_IRQ_event(irq, &regs, action);
+		spin_lock(&irq_controller_lock);
+		
+		if (!(desc->status & IRQ_PENDING))
+			break;
+		desc->status &= ~IRQ_PENDING;
+		spin_unlock(&irq_controller_lock);
+	}
+	desc->status &= ~IRQ_INPROGRESS;
+	if (!(desc->status & IRQ_DISABLED)){
+			irq_desc[irq].handler->end(irq);
+	}
+	spin_unlock(&irq_controller_lock);
+
+	/*
+	 * This should be conditional: we should really get
+	 * a return code from the irq handler to tell us
+	 * whether the handler wants us to do software bottom
+	 * half handling or not..
+	 */
+	if (1) {
+		if (bh_active & bh_mask)
+			do_bottom_half();
+	}
+	return 1;
+}
+
+int request_irq(unsigned int irq, 
+		void (*handler)(int, void *, struct pt_regs *),
+		unsigned long irqflags, 
+		const char * devname,
+		void *dev_id)
+{
+	int retval;
+	struct irqaction * action;
+
+	if (irq >= NR_IRQS)
+		return -EINVAL;
+	if (!handler)
+		return -EINVAL;
+
+	action = (struct irqaction *)
+			kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if (!action)
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	action->mask = 0;
+	action->name = devname;
+	action->next = NULL;
+	action->dev_id = dev_id;
+
+	retval = setup_irq(irq, action);
+	if (retval)
+		kfree(action);
+	return retval;
+}
+		
+void free_irq(unsigned int irq, void *dev_id)
+{
+	struct irqaction **p;
+	unsigned long flags;
+
+	if (irq >= NR_IRQS)
+		return;
+
+	spin_lock_irqsave(&irq_controller_lock,flags);
+	p = &irq_desc[irq].action;
+	for (;;) {
+		struct irqaction * action = *p;
+		if (action) {
+			struct irqaction **pp = p;
+			p = &action->next;
+			if (action->dev_id != dev_id)
+				continue;
+
+			/* Found it - now remove it from the list of entries */
+			*pp = action->next;
+			if (irq_desc[irq].action)
+				break;
+			irq_desc[irq].status |= IRQ_DISABLED;
+			irq_desc[irq].handler->shutdown(irq);
+			break;
+		}
+		printk("Trying to free free IRQ%d\n",irq);
+		break;
+	}
+	spin_unlock_irqrestore(&irq_controller_lock,flags);
+}
+
+/*
+ * IRQ autodetection code..
+ *
+ * This depends on the fact that any interrupt that
+ * comes in on to an unassigned handler will get stuck
+ * with "IRQ_WAITING" cleared and the interrupt
+ * disabled.
+ */
+unsigned long probe_irq_on(void)
+{
+	unsigned int i;
+	unsigned long delay;
+
+	/*
+	 * first, enable any unassigned irqs
+	 */
+	spin_lock_irq(&irq_controller_lock);
+	for (i = NR_IRQS-1; i > 0; i--) {
+		if (!irq_desc[i].action) {
+			irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING;
+			if(irq_desc[i].handler->startup(i))
+				irq_desc[i].status |= IRQ_PENDING;
+		}
+	}
+	spin_unlock_irq(&irq_controller_lock);
+
+	/*
+	 * Wait for spurious interrupts to trigger
+	 */
+	for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
+		/* about 100ms delay */ synchronize_irq();
+
+	/*
+	 * Now filter out any obviously spurious interrupts
+	 */
+	spin_lock_irq(&irq_controller_lock);
+	for (i=0; i<NR_IRQS; i++) {
+		unsigned int status = irq_desc[i].status;
+
+		if (!(status & IRQ_AUTODETECT))
+			continue;
+		
+		/* It triggered already - consider it spurious. */
+		if (!(status & IRQ_WAITING)) {
+			irq_desc[i].status = status & ~IRQ_AUTODETECT;
+			irq_desc[i].handler->shutdown(i);
+		}
+	}
+	spin_unlock_irq(&irq_controller_lock);
+
+	return 0x12345678;
+}
+
+int probe_irq_off(unsigned long unused)
+{
+	int i, irq_found, nr_irqs;
+
+	if (unused != 0x12345678)
+		printk("Bad IRQ probe from %lx\n", (&unused)[-1]);
+
+	nr_irqs = 0;
+	irq_found = 0;
+	spin_lock_irq(&irq_controller_lock);
+	for (i=0; i<NR_IRQS; i++) {
+		unsigned int status = irq_desc[i].status;
+
+		if (!(status & IRQ_AUTODETECT))
+			continue;
+
+		if (!(status & IRQ_WAITING)) {
+			if (!nr_irqs)
+				irq_found = i;
+			nr_irqs++;
+		}
+		irq_desc[i].status = status & ~IRQ_AUTODETECT;
+		irq_desc[i].handler->shutdown(i);
+	}
+	spin_unlock_irq(&irq_controller_lock);
+
+	if (nr_irqs > 1)
+		irq_found = -irq_found;
+	return irq_found;
+}
+
+int setup_irq(unsigned int irq, struct irqaction * new)
+{
+	int shared = 0;
+	struct irqaction *old, **p;
+	unsigned long flags;
+
+	/*
+	 * Some drivers like serial.c use request_irq() heavily,
+	 * so we have to be careful not to interfere with a
+	 * running system.
+	 */
+	if (new->flags & SA_SAMPLE_RANDOM) {
+		/*
+		 * This function might sleep, we want to call it first,
+		 * outside of the atomic block.
+		 * Yes, this might clear the entropy pool if the wrong
+		 * driver is attempted to be loaded, without actually
+		 * installing a new handler, but is this really a problem,
+		 * only the sysadmin is able to do this.
+		 */
+		rand_initialize_irq(irq);
+	}
+
+	/*
+	 * The following block of code has to be executed atomically
+	 */
+	spin_lock_irqsave(&irq_controller_lock,flags);
+	p = &irq_desc[irq].action;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ)) {
+			spin_unlock_irqrestore(&irq_controller_lock,flags);
+			return -EBUSY;
+		}
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	*p = new;
+
+	if (!shared) {
+		irq_desc[irq].depth = 0;
+		irq_desc[irq].status &= ~IRQ_DISABLED;
+		irq_desc[irq].handler->startup(irq);
+	}
+	spin_unlock_irqrestore(&irq_controller_lock,flags);
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/irq_onchip.c linux/arch/sh/kernel/irq_onchip.c
--- v2.3.15/linux/arch/sh/kernel/irq_onchip.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/irq_onchip.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,169 @@
+/*
+ * linux/arch/sh/kernel/irq_onchip.c
+ *
+ * Copyright (C) 1999  Niibe Yutaka
+ *
+ * Interrupt handling for on-chip supporting modules (TMU, RTC, etc.).
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/smp.h>
+#include <asm/pgtable.h>
+#include <asm/delay.h>
+
+#include <linux/irq.h>
+
+
+/*
+ * SH (non-)specific no controller code
+ */
+
+static void enable_none(unsigned int irq) { }
+static unsigned int startup_none(unsigned int irq) { return 0; }
+static void disable_none(unsigned int irq) { }
+static void ack_none(unsigned int irq)
+{
+}
+
+/* startup is the same as "enable", shutdown is same as "disable" */
+#define shutdown_none	disable_none
+#define end_none	enable_none
+
+struct hw_interrupt_type no_irq_type = {
+	"none",
+	startup_none,
+	shutdown_none,
+	enable_none,
+	disable_none,
+	ack_none,
+	end_none
+};
+
+struct ipr_data {
+	int offset;
+	int priority;
+};
+static struct ipr_data ipr_data[NR_IRQS-TIMER_IRQ];
+
+void set_ipr_data(unsigned int irq, int offset, int priority)
+{
+	ipr_data[irq-TIMER_IRQ].offset = offset;
+	ipr_data[irq-TIMER_IRQ].priority = priority;
+}
+
+static void enable_onChip_irq(unsigned int irq);
+void disable_onChip_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_onChip_irq	disable_onChip_irq
+
+static void mask_and_ack_onChip(unsigned int);
+static void end_onChip_irq(unsigned int irq);
+
+static unsigned int startup_onChip_irq(unsigned int irq)
+{ 
+	enable_onChip_irq(irq);
+	return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type onChip_irq_type = {
+	"On-Chip Supporting Module",
+	startup_onChip_irq,
+	shutdown_onChip_irq,
+	enable_onChip_irq,
+	disable_onChip_irq,
+	mask_and_ack_onChip,
+	end_onChip_irq
+};
+
+/*
+ * These have to be protected by the irq controller spinlock
+ * before being called.
+ *
+ *
+ * IPRA  15-12  11-8  7-4  3-0
+ * IPRB  15-12  11-8  7-4  3-0
+ * IPRC  15-12  11-8  7-4  3-0
+ *
+ */
+#define INTC_IPR	0xfffffee2UL	/* Word access */
+
+void disable_onChip_irq(unsigned int irq)
+{
+	/* Set priority in IPR to 0 */
+	int offset = ipr_data[irq-TIMER_IRQ].offset;
+	unsigned long intc_ipr_address = INTC_IPR + offset/16;
+	unsigned short mask = 0xffff ^ (0xf << (offset%16));
+	unsigned long __dummy;
+
+	asm volatile("mov.w	@%1,%0\n\t"
+		     "and	%2,%0\n\t"
+		     "mov.w	%0,@%1"
+		     : "=&z" (__dummy)
+		     : "r" (intc_ipr_address), "r" (mask)
+		     : "memory" );
+}
+
+static void enable_onChip_irq(unsigned int irq)
+{
+	/* Set priority in IPR back to original value */
+	int offset = ipr_data[irq-TIMER_IRQ].offset;
+	int priority = ipr_data[irq-TIMER_IRQ].priority;
+	unsigned long intc_ipr_address = INTC_IPR + offset/16;
+	unsigned short value = (priority << (offset%16));
+	unsigned long __dummy;
+
+	asm volatile("mov.w	@%1,%0\n\t"
+		     "or	%2,%0\n\t"
+		     "mov.w	%0,@%1"
+		     : "=&z" (__dummy)
+		     : "r" (intc_ipr_address), "r" (value)
+		     : "memory" );
+}
+
+void make_onChip_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
+	irq_desc[irq].handler = &onChip_irq_type;
+	enable_irq(irq);
+}
+
+static void mask_and_ack_onChip(unsigned int irq)
+{
+	disable_onChip_irq(irq);
+	sti();
+}
+
+static void end_onChip_irq(unsigned int irq)
+{
+	enable_onChip_irq(irq);
+	cli();
+}
+
+void __init init_IRQ(void)
+{
+	int i;
+
+	for (i = TIMER_IRQ; i < NR_IRQS; i++) {
+		irq_desc[i].handler = &onChip_irq_type;
+	}
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/process.c linux/arch/sh/kernel/process.c
--- v2.3.15/linux/arch/sh/kernel/process.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/process.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,304 @@
+/*
+ *  linux/arch/sh/kernel/process.c
+ *
+ *  Copyright (C) 1995  Linus Torvalds
+ *
+ *  SuperH version:  Copyright (C) 1999  Niibe Yutaka
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#define __KERNEL_SYSCALLS__
+#include <stdarg.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/interrupt.h>
+#include <linux/config.h>
+#include <linux/unistd.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/mmu_context.h>
+#include <asm/elf.h>
+
+#include <linux/irq.h>
+
+static int hlt_counter=0;
+
+#define HARD_IDLE_TIMEOUT (HZ / 3)
+
+void disable_hlt(void)
+{
+	hlt_counter++;
+}
+
+void enable_hlt(void)
+{
+	hlt_counter--;
+}
+
+/*
+ * The idle loop on a uniprocessor i386..
+ */ 
+void cpu_idle(void *unused)
+{
+	/* endless idle loop with no priority at all */
+	init_idle();
+	current->priority = 0;
+	current->counter = -100;
+
+	while (1) {
+		while (!current->need_resched) {
+			if (hlt_counter)
+				continue;
+			__sti();
+			asm volatile("sleep" : : : "memory");
+		}
+		schedule();
+		check_pgt_cache();
+	}
+}
+
+void machine_restart(char * __unused)
+{ /* Need to set MMU_TTB?? */
+}
+
+void machine_halt(void)
+{
+}
+
+void machine_power_off(void)
+{
+}
+
+void show_regs(struct pt_regs * regs)
+{
+	printk("\n");
+	printk("PC: [<%08lx>]", regs->pc);
+	printk(" SP: %08lx", regs->u_regs[UREG_SP]);
+	printk(" SR: %08lx\n", regs->sr);
+	printk("R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n",
+	       regs->u_regs[0],regs->u_regs[1],
+	       regs->u_regs[2],regs->u_regs[3]);
+	printk("R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n",
+	       regs->u_regs[4],regs->u_regs[5],
+	       regs->u_regs[6],regs->u_regs[7]);
+	printk("R8 : %08lx R9 : %08lx R10: %08lx R11: %08lx\n",
+	       regs->u_regs[8],regs->u_regs[9],
+	       regs->u_regs[10],regs->u_regs[11]);
+	printk("R12: %08lx R13: %08lx R14: %08lx\n",
+	       regs->u_regs[12],regs->u_regs[13],
+	       regs->u_regs[14]);
+	printk("MACH: %08lx MACL: %08lx GBR: %08lx PR: %08lx",
+	       regs->mach, regs->macl, regs->gbr, regs->pr);
+}
+
+struct task_struct * alloc_task_struct(void)
+{
+	/* Get two pages */
+	return (struct task_struct *) __get_free_pages(GFP_KERNEL,1);
+}
+
+void free_task_struct(struct task_struct *p)
+{
+	free_pages((unsigned long) p, 1);
+}
+
+/*
+ * Create a kernel thread
+ */
+
+/*
+ * This is the mechanism for creating a new kernel thread.
+ *
+ * NOTE! Only a kernel-only process(ie the swapper or direct descendants
+ * who haven't done an "execve()") should use this: it will work within
+ * a system call from a "real" process, but the process memory space will
+ * not be free'd until both the parent and the child have exited.
+ */
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{	/* Don't use this in BL=1(cli).  Or else, CPU resets! */
+	register unsigned long __sc0 __asm__ ("r0") = __NR_clone;
+	register unsigned long __sc4 __asm__ ("r4") = (long) flags | CLONE_VM;
+	register unsigned long __sc5 __asm__ ("r5") = 0;
+	register unsigned long __sc8 __asm__ ("r8") = (long) arg;
+	register unsigned long __sc9 __asm__ ("r9") = (long) fn;
+	__asm__ __volatile__(
+		"trapa	#0\n\t" 	/* Linux/SH system call */
+		"tst	#0xff,r0\n\t"	/* child or parent? */
+		"bf	1f\n\t"		/* parent - jump */
+		"jsr	@r9\n\t"	/* call fn */
+		" mov	r8,r4\n\t"	/* push argument */
+		"mov	r0,r4\n\t"	/* return value to arg of exit */
+		"mov	%2,r0\n\t"	/* exit */
+		"trapa	#0\n"
+		"1:"
+		:"=z" (__sc0)
+		:"0" (__sc0), "i" (__NR_exit),
+		 "r" (__sc4), "r" (__sc5), "r" (__sc8), "r" (__sc9)
+		:"memory");
+	return __sc0;
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+	/* nothing to do ... */
+}
+
+void flush_thread(void)
+{
+	/* do nothing */
+	/* Possibly, set clear debug registers */
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+	/* do nothing */
+}
+
+/* Fill in the fpu structure for a core dump.. */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
+{
+	return 0; /* Task didn't use the fpu at all. */
+}
+
+asmlinkage void ret_from_fork(void);
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+		struct task_struct *p, struct pt_regs *regs)
+{
+	struct pt_regs *childregs;
+
+	childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p)) - 1;
+
+	*childregs = *regs;
+	if (user_mode(regs)) {
+		childregs->u_regs[UREG_SP] = usp;
+	} else {
+		childregs->u_regs[UREG_SP] = (unsigned long)p+2*PAGE_SIZE;
+	}
+	childregs->u_regs[0] = 0; /* Set return value for child */
+
+	p->thread.sp = (unsigned long) childregs;
+	p->thread.pc = (unsigned long) ret_from_fork;
+	if (p->mm)
+		p->mm->context = NO_CONTEXT;
+
+	return 0;
+}
+
+/*
+ * fill in the user structure for a core dump..
+ */
+void dump_thread(struct pt_regs * regs, struct user * dump)
+{
+/* changed the size calculations - should hopefully work better. lbt */
+	dump->magic = CMAGIC;
+	dump->start_code = 0;
+	dump->start_stack = regs->u_regs[UREG_SP] & ~(PAGE_SIZE - 1);
+	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
+	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
+	dump->u_dsize -= dump->u_tsize;
+	dump->u_ssize = 0;
+	/* Debug registers will come here. */
+
+	if (dump->start_stack < TASK_SIZE)
+		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
+
+	dump->regs = *regs;
+}
+
+/*
+ *	switch_to(x,y) should switch tasks from x to y.
+ *
+ */
+void __switch_to(struct task_struct *prev, struct task_struct *next)
+{
+	/*
+	 * Restore the kernel stack onto kernel mode register
+	 *   	k4 (r4_bank1)
+	 */
+	asm volatile("ldc	%0,r4_bank"
+		     : /* no output */
+		     :"r" ((unsigned long)next+8192));
+}
+
+asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
+			unsigned long r6, unsigned long r7,
+			struct pt_regs regs)
+{
+	return do_fork(SIGCHLD, regs.u_regs[UREG_SP], &regs);
+}
+
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+			 unsigned long r6, unsigned long r7,
+			 struct pt_regs regs)
+{
+	if (!newsp)
+		newsp = regs.u_regs[UREG_SP];
+	return do_fork(clone_flags, newsp, &regs);
+}
+
+/*
+ * This is trivial, and on the face of it looks like it
+ * could equally well be done in user mode.
+ *
+ * Not so, for quite unobvious reasons - register pressure.
+ * In user mode vfork() cannot have a stack frame, and if
+ * done by calling the "clone()" system call directly, you
+ * do not have enough call-clobbered registers to hold all
+ * the information you need.
+ */
+asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
+			 unsigned long r6, unsigned long r7,
+			 struct pt_regs regs)
+{
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+		       regs.u_regs[UREG_SP], &regs);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(char *ufilename, char **uargv,
+			  char **uenvp, unsigned long r7,
+			  struct pt_regs regs)
+{
+	int error;
+	char *filename;
+
+	lock_kernel();
+	filename = getname(ufilename);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		goto out;
+	error = do_execve(filename, uargv, uenvp, &regs);
+	if (error == 0)
+		current->flags &= ~PF_DTRACE;
+	putname(filename);
+out:
+	unlock_kernel();
+	return error;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/ptrace.c linux/arch/sh/kernel/ptrace.c
--- v2.3.15/linux/arch/sh/kernel/ptrace.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/ptrace.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,477 @@
+/*
+ * Surely this doesn't work... (we need to design ptrace for SupreH)
+ * linux/arch/sh/kernel/ptrace.c
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+/* determines which flags the user has access to. */
+/* 1 = access 0 = no access */
+#define FLAG_MASK 0x00044dd5
+
+/* set's the trap flag. */
+#define TRAP_FLAG 0x100
+
+/*
+ * Offset of eflags on child stack..
+ */
+#define EFL_OFFSET ((EFL-2)*4-sizeof(struct pt_regs))
+
+/*
+ * this routine will get a word off of the processes privileged stack. 
+ * the offset is how far from the base addr as stored in the TSS.  
+ * this routine assumes that all the privileged stacks are in our
+ * data space.
+ */   
+static inline int get_stack_long(struct task_struct *task, int offset)
+{
+	unsigned char *stack;
+
+	stack = (unsigned char *)task->thread.sp;
+	stack += offset;
+	return (*((int *)stack));
+}
+
+/*
+ * this routine will put a word on the processes privileged stack. 
+ * the offset is how far from the base addr as stored in the TSS.  
+ * this routine assumes that all the privileged stacks are in our
+ * data space.
+ */
+static inline int put_stack_long(struct task_struct *task, int offset,
+	unsigned long data)
+{
+	unsigned char * stack;
+
+	stack = (unsigned char *) task->thread.sp;
+	stack += offset;
+	*(unsigned long *) stack = data;
+	return 0;
+}
+
+static int putreg(struct task_struct *child,
+	unsigned long regno, unsigned long value)
+{
+#if 0
+	switch (regno >> 2) {
+		case ORIG_EAX:
+			return -EIO;
+		case FS:
+			if (value && (value & 3) != 3)
+				return -EIO;
+			child->thread.fs = value;
+			return 0;
+		case GS:
+			if (value && (value & 3) != 3)
+				return -EIO;
+			child->thread.gs = value;
+			return 0;
+		case DS:
+		case ES:
+			if (value && (value & 3) != 3)
+				return -EIO;
+			value &= 0xffff;
+			break;
+		case SS:
+		case CS:
+			if ((value & 3) != 3)
+				return -EIO;
+			value &= 0xffff;
+			break;
+		case EFL:
+			value &= FLAG_MASK;
+			value |= get_stack_long(child, EFL_OFFSET) & ~FLAG_MASK;
+	}
+	if (regno > GS*4)
+		regno -= 2*4;
+	put_stack_long(child, regno - sizeof(struct pt_regs), value);
+#endif
+	return 0;
+}
+
+static unsigned long getreg(struct task_struct *child,
+	unsigned long regno)
+{
+	unsigned long retval = ~0UL;
+
+#if 0
+	switch (regno >> 2) {
+		case FS:
+			retval = child->thread.fs;
+			break;
+		case GS:
+			retval = child->thread.gs;
+			break;
+		case DS:
+		case ES:
+		case SS:
+		case CS:
+			retval = 0xffff;
+			/* fall through */
+		default:
+			if (regno > GS*4)
+				regno -= 2*4;
+			regno = regno - sizeof(struct pt_regs);
+			retval &= get_stack_long(child, regno);
+	}
+#endif
+	return retval;
+}
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+{
+	struct task_struct *child;
+	struct user * dummy = NULL;
+	unsigned long flags;
+	int i, ret;
+
+	lock_kernel();
+	ret = -EPERM;
+	if (request == PTRACE_TRACEME) {
+		/* are we already being traced? */
+		if (current->flags & PF_PTRACED)
+			goto out;
+		/* set the ptrace bit in the process flags. */
+		current->flags |= PF_PTRACED;
+		ret = 0;
+		goto out;
+	}
+	ret = -ESRCH;
+	read_lock(&tasklist_lock);
+	child = find_task_by_pid(pid);
+	read_unlock(&tasklist_lock);	/* FIXME!!! */
+	if (!child)
+		goto out;
+	ret = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
+		goto out;
+	if (request == PTRACE_ATTACH) {
+		if (child == current)
+			goto out;
+		if ((!child->dumpable ||
+		    (current->uid != child->euid) ||
+		    (current->uid != child->suid) ||
+		    (current->uid != child->uid) ||
+	 	    (current->gid != child->egid) ||
+	 	    (current->gid != child->sgid) ||
+	 	    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
+	 	    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+			goto out;
+		/* the same process cannot be attached many times */
+		if (child->flags & PF_PTRACED)
+			goto out;
+		child->flags |= PF_PTRACED;
+
+		write_lock_irqsave(&tasklist_lock, flags);
+		if (child->p_pptr != current) {
+			REMOVE_LINKS(child);
+			child->p_pptr = current;
+			SET_LINKS(child);
+		}
+		write_unlock_irqrestore(&tasklist_lock, flags);
+
+		send_sig(SIGSTOP, child, 1);
+		ret = 0;
+		goto out;
+	}
+	ret = -ESRCH;
+	if (!(child->flags & PF_PTRACED))
+		goto out;
+	if (child->state != TASK_STOPPED) {
+		if (request != PTRACE_KILL)
+			goto out;
+	}
+	if (child->p_pptr != current)
+		goto out;
+
+	switch (request) {
+	/* when I and D space are separate, these will need to be fixed. */
+		case PTRACE_PEEKTEXT: /* read word at location addr. */ 
+		case PTRACE_PEEKDATA: {
+			unsigned long tmp;
+			int copied;
+
+			copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+			ret = -EIO;
+			if (copied != sizeof(tmp))
+				goto out;
+			ret = put_user(tmp,(unsigned long *) data);
+			goto out;
+		}
+
+	/* read the word at location addr in the USER area. */
+		case PTRACE_PEEKUSR: {
+			unsigned long tmp;
+
+			ret = -EIO;
+			if ((addr & 3) || addr < 0 || 
+			    addr > sizeof(struct user) - 3)
+				goto out;
+
+			tmp = 0;  /* Default return condition */
+			if(addr < 17*sizeof(long))
+				tmp = getreg(child, addr);
+#if 0
+			if(addr >= (long) &dummy->u_debugreg[0] &&
+			   addr <= (long) &dummy->u_debugreg[7]){
+				addr -= (long) &dummy->u_debugreg[0];
+				addr = addr >> 2;
+				tmp = child->thread.debugreg[addr];
+			};
+#endif
+			ret = put_user(tmp,(unsigned long *) data);
+			goto out;
+		}
+
+      /* when I and D space are separate, this will have to be fixed. */
+		case PTRACE_POKETEXT: /* write the word at location addr. */
+		case PTRACE_POKEDATA:
+			ret = 0;
+			if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+				goto out;
+			ret = -EIO;
+			goto out;
+
+		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+			ret = -EIO;
+			if ((addr & 3) || addr < 0 || 
+			    addr > sizeof(struct user) - 3)
+				goto out;
+
+			if (addr < 17*sizeof(long)) {
+				ret = putreg(child, addr, data);
+				goto out;
+			}
+
+		  /* We need to be very careful here.  We implicitly
+		     want to modify a portion of the task_struct, and we
+		     have to be selective about what portions we allow someone
+		     to modify. */
+#if 0
+		  if(addr >= (long) &dummy->u_debugreg[0] &&
+		     addr <= (long) &dummy->u_debugreg[7]){
+
+			  if(addr == (long) &dummy->u_debugreg[4]) return -EIO;
+			  if(addr == (long) &dummy->u_debugreg[5]) return -EIO;
+			  if(addr < (long) &dummy->u_debugreg[4] &&
+			     ((unsigned long) data) >= TASK_SIZE-3) return -EIO;
+			  
+			  ret = -EIO;
+			  if(addr == (long) &dummy->u_debugreg[7]) {
+				  data &= ~DR_CONTROL_RESERVED;
+				  for(i=0; i<4; i++)
+					  if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
+						  goto out;
+			  };
+
+			  addr -= (long) &dummy->u_debugreg;
+			  addr = addr >> 2;
+			  child->thread.debugreg[addr] = data;
+			  ret = 0;
+			  goto out;
+		  };
+#endif
+		  ret = -EIO;
+		  goto out;
+
+		case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+		case PTRACE_CONT: { /* restart after signal. */
+			long tmp;
+
+			ret = -EIO;
+			if ((unsigned long) data > _NSIG)
+				goto out;
+			if (request == PTRACE_SYSCALL)
+				child->flags |= PF_TRACESYS;
+			else
+				child->flags &= ~PF_TRACESYS;
+			child->exit_code = data;
+	/* make sure the single step bit is not set. */
+#if 0
+			tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+			put_stack_long(child, EFL_OFFSET,tmp);
+#endif
+			wake_up_process(child);
+			ret = 0;
+			goto out;
+		}
+
+/*
+ * make the child exit.  Best I can do is send it a sigkill. 
+ * perhaps it should be put in the status that it wants to 
+ * exit.
+ */
+		case PTRACE_KILL: {
+			long tmp;
+
+			ret = 0;
+			if (child->state == TASK_ZOMBIE)	/* already dead */
+				goto out;
+			child->exit_code = SIGKILL;
+	/* make sure the single step bit is not set. */
+#if 0
+			tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+			put_stack_long(child, EFL_OFFSET, tmp);
+#endif
+			wake_up_process(child);
+			goto out;
+		}
+
+		case PTRACE_SINGLESTEP: {  /* set the trap flag. */
+			long tmp;
+
+			ret = -EIO;
+			if ((unsigned long) data > _NSIG)
+				goto out;
+			child->flags &= ~PF_TRACESYS;
+			if ((child->flags & PF_DTRACE) == 0) {
+				/* Spurious delayed TF traps may occur */
+				child->flags |= PF_DTRACE;
+			}
+#if 0
+			tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
+			put_stack_long(child, EFL_OFFSET, tmp);
+#endif
+			child->exit_code = data;
+	/* give it a chance to run. */
+			wake_up_process(child);
+			ret = 0;
+			goto out;
+		}
+
+		case PTRACE_DETACH: { /* detach a process that was attached. */
+			long tmp;
+
+			ret = -EIO;
+			if ((unsigned long) data > _NSIG)
+				goto out;
+			child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+			child->exit_code = data;
+			write_lock_irqsave(&tasklist_lock, flags);
+			REMOVE_LINKS(child);
+			child->p_pptr = child->p_opptr;
+			SET_LINKS(child);
+			write_unlock_irqrestore(&tasklist_lock, flags);
+	/* make sure the single step bit is not set. */
+#if 0
+			tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+			put_stack_long(child, EFL_OFFSET, tmp);
+#endif
+			wake_up_process(child);
+			ret = 0;
+			goto out;
+		}
+#if 0
+		case PTRACE_GETREGS: { /* Get all gp regs from the child. */
+		  	if (!access_ok(VERIFY_WRITE, (unsigned *)data,
+				       17*sizeof(long)))
+			  {
+			    ret = -EIO;
+			    goto out;
+			  }
+			for ( i = 0; i < 17*sizeof(long); i += sizeof(long) )
+			  {
+			    __put_user(getreg(child, i),(unsigned long *) data);
+			    data += sizeof(long);
+			  }
+			ret = 0;
+			goto out;
+		  };
+
+		case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+			unsigned long tmp;
+		  	if (!access_ok(VERIFY_READ, (unsigned *)data,
+				       17*sizeof(long)))
+			  {
+			    ret = -EIO;
+			    goto out;
+			  }
+			for ( i = 0; i < 17*sizeof(long); i += sizeof(long) )
+			  {
+			    __get_user(tmp, (unsigned long *) data);
+			    putreg(child, i, tmp);
+			    data += sizeof(long);
+			  }
+			ret = 0;
+			goto out;
+		  };
+
+		case PTRACE_GETFPREGS: { /* Get the child FPU state. */
+			if (!access_ok(VERIFY_WRITE, (unsigned *)data,
+				       sizeof(struct user_i387_struct)))
+			  {
+			    ret = -EIO;
+			    goto out;
+			  }
+			ret = 0;
+			if ( !child->used_math ) {
+			  /* Simulate an empty FPU. */
+			  child->thread.i387.hard.cwd = 0xffff037f;
+			  child->thread.i387.hard.swd = 0xffff0000;
+			  child->thread.i387.hard.twd = 0xffffffff;
+			}
+				__copy_to_user((void *)data, &child->thread.i387.hard,
+						sizeof(struct user_i387_struct));
+			goto out;
+		  };
+
+		case PTRACE_SETFPREGS: { /* Set the child FPU state. */
+			if (!access_ok(VERIFY_READ, (unsigned *)data,
+				       sizeof(struct user_i387_struct)))
+			  {
+			    ret = -EIO;
+			    goto out;
+			  }
+			child->used_math = 1;
+			  __copy_from_user(&child->thread.i387.hard, (void *)data,
+					   sizeof(struct user_i387_struct));
+			ret = 0;
+			goto out;
+		  };
+#endif
+		default:
+			ret = -EIO;
+			goto out;
+	}
+out:
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage void syscall_trace(void)
+{
+	if ((current->flags & (PF_PTRACED|PF_TRACESYS))
+			!= (PF_PTRACED|PF_TRACESYS))
+		return;
+	current->exit_code = SIGTRAP;
+	current->state = TASK_STOPPED;
+	notify_parent(current, SIGCHLD);
+	schedule();
+	/*
+	 * this isn't the same as continuing with a signal, but it will do
+	 * for normal use.  strace only continues with a signal if the
+	 * stopping signal is not SIGTRAP.  -brl
+	 */
+	if (current->exit_code) {
+		send_sig(current->exit_code, current, 1);
+		current->exit_code = 0;
+	}
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/semaphore.c linux/arch/sh/kernel/semaphore.c
--- v2.3.15/linux/arch/sh/kernel/semaphore.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/semaphore.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,133 @@
+/*
+ * Just taken from alpha implementation.
+ * This can't work well, perhaps.
+ */
+/*
+ *  Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/sched.h>
+#include <asm/semaphore-helper.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit.  ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore.  The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+	wake_one_more(sem);
+	wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function.  Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible.  This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return.  If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR				\
+	struct task_struct *tsk = current;	\
+	wait_queue_t wait;			\
+	init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state)						\
+									\
+									\
+	tsk->state = (task_state);					\
+	add_wait_queue(&sem->wait, &wait);				\
+									\
+	/*								\
+	 * Ok, we're set up.  sem->count is known to be less than zero	\
+	 * so we must wait.						\
+	 *								\
+	 * We can let go the lock for purposes of waiting.		\
+	 * We re-acquire it after awaking so as to protect		\
+	 * all semaphore operations.					\
+	 *								\
+	 * If "up()" is called before we call waking_non_zero() then	\
+	 * we will catch it right away.  If it is called later then	\
+	 * we will have to go through a wakeup cycle to catch it.	\
+	 *								\
+	 * Multiple waiters contend for the semaphore lock to see	\
+	 * who gets to gate through and who has to wait some more.	\
+	 */								\
+	for (;;) {
+
+#define DOWN_TAIL(task_state)			\
+		tsk->state = (task_state);	\
+	}					\
+	tsk->state = TASK_RUNNING;		\
+	remove_wait_queue(&sem->wait, &wait);
+
+void __down(struct semaphore * sem)
+{
+	DOWN_VAR
+	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+	if (waking_non_zero(sem))
+		break;
+	schedule();
+	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+	int ret = 0;
+	DOWN_VAR
+	DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+	ret = waking_non_zero_interruptible(sem, tsk);
+	if (ret)
+	{
+		if (ret == 1)
+			/* ret != 0 only if we get interrupted -arca */
+			ret = 0;
+		break;
+	}
+	schedule();
+	DOWN_TAIL(TASK_INTERRUPTIBLE)
+	return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+	return waking_non_zero_trylock(sem);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/setup.c linux/arch/sh/kernel/setup.c
--- v2.3.15/linux/arch/sh/kernel/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/setup.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,188 @@
+/*
+ *  linux/arch/sh/kernel/setup.c
+ *
+ *  Copyright (C) 1999  Niibe Yutaka
+ *
+ */
+
+/*
+ * This file handles the architecture-dependent parts of initialization
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#ifdef CONFIG_BLK_DEV_RAM
+#include <linux/blk.h>
+#endif
+#include <asm/processor.h>
+#include <linux/console.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+
+/*
+ * Machine setup..
+ */
+
+struct sh_cpuinfo boot_cpu_data = { 0, 0, 0, 0, };
+extern int _text, _etext, _edata, _end, _stext, __bss_start;
+
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;	/* starting block # of image */
+#endif
+
+extern int root_mountflags;
+
+#define COMMAND_LINE_SIZE 1024
+static char command_line[COMMAND_LINE_SIZE] = { 0, };
+       char saved_command_line[COMMAND_LINE_SIZE];
+
+extern unsigned char *root_fs_image;
+
+struct resource standard_io_resources[] = {
+	{ "dma1", 0x00, 0x1f },
+	{ "pic1", 0x20, 0x3f },
+	{ "timer", 0x40, 0x5f },
+	{ "keyboard", 0x60, 0x6f },
+	{ "dma page reg", 0x80, 0x8f },
+	{ "pic2", 0xa0, 0xbf },
+	{ "dma2", 0xc0, 0xdf },
+	{ "fpu", 0xf0, 0xff }
+};
+
+#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
+
+
+/* System RAM - interrupted by the 640kB-1M hole */
+#define code_resource (ram_resources[3])
+#define data_resource (ram_resources[4])
+static struct resource ram_resources[] = {
+	{ "System RAM", 0x000000, 0x09ffff, IORESOURCE_BUSY },
+	{ "System RAM", 0x100000, 0x100000, IORESOURCE_BUSY },
+	{ "Video RAM area", 0x0a0000, 0x0bffff },
+	{ "Kernel code", 0x100000, 0 },
+	{ "Kernel data", 0, 0 }
+};
+
+/* System ROM resources */
+#define MAXROMS 6
+static struct resource rom_resources[MAXROMS] = {
+	{ "System ROM", 0xF0000, 0xFFFFF, IORESOURCE_BUSY },
+	{ "Video ROM", 0xc0000, 0xc7fff }
+};
+
+
+void __init setup_arch(char **cmdline_p,
+		       unsigned long * memory_start_p,
+		       unsigned long * memory_end_p)
+{
+	*cmdline_p = command_line;
+	*memory_start_p = (unsigned long) &_end;
+	*memory_end_p = 0x8c400000; /* For my board. */
+	ram_resources[1].end = *memory_end_p-1;
+
+	init_mm.start_code = (unsigned long)&_stext;
+	init_mm.end_code = (unsigned long) &_etext;
+	init_mm.end_data = (unsigned long) &_edata;
+	init_mm.brk = (unsigned long) &_end;
+
+	code_resource.start = virt_to_bus(&_text);
+	code_resource.end = virt_to_bus(&_etext)-1;
+	data_resource.start = virt_to_bus(&_etext);
+	data_resource.end = virt_to_bus(&_edata)-1;
+
+ 	ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0);
+
+	initrd_below_start_ok = 1;
+	initrd_start = (long)&root_fs_image;
+	initrd_end = (long)&__bss_start;
+	mount_initrd = 1;
+
+
+#if 0
+	/* Request the standard RAM and ROM resources - they eat up PCI memory space */
+	request_resource(&iomem_resource, ram_resources+0);
+	request_resource(&iomem_resource, ram_resources+1);
+	request_resource(&iomem_resource, ram_resources+2);
+	request_resource(ram_resources+1, &code_resource);
+	request_resource(ram_resources+1, &data_resource);
+#endif
+
+#if 0
+	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+		request_resource(&ioport_resource, standard_io_resources+i);
+#endif
+
+#if 0
+	rd_image_start = (long)root_fs_image;
+	rd_prompt = 0;
+	rd_doload = 1;
+#endif
+
+#if 0
+ 	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
+
+#ifdef CONFIG_BLK_DEV_RAM
+	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+#endif
+
+	if (!MOUNT_ROOT_RDONLY)
+		root_mountflags &= ~MS_RDONLY;
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+#if 0
+	if (LOADER_TYPE) {
+		initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
+		initrd_end = initrd_start+INITRD_SIZE;
+		if (initrd_end > memory_end) {
+			printk("initrd extends beyond end of memory "
+			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+			    initrd_end,memory_end);
+			initrd_start = 0;
+		}
+	}
+#endif
+
+#endif
+}
+
+/*
+ *	Get CPU information for use by the procfs.
+ */
+
+int get_cpuinfo(char *buffer)
+{
+	char *p = buffer;
+
+#ifdef CONFIG_CPU_SH3
+	p += sprintf(p,"cpu family\t: SH3\n"
+		       "cache size\t: 8K-byte\n");
+#elif CONFIG_CPU_SH4
+	p += sprintf(p,"cpu family\t: SH4\n"
+		       "cache size\t: ??K-byte\n");
+#endif
+	p += sprintf(p, "bogomips\t: %lu.%02lu\n\n",
+		     (loops_per_sec+2500)/500000,
+		     ((loops_per_sec+2500)/5000) % 100);
+
+	return p - buffer;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/sh_ksyms.c linux/arch/sh/kernel/sh_ksyms.c
--- v2.3.15/linux/arch/sh/kernel/sh_ksyms.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/sh_ksyms.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,48 @@
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+#include <linux/mca.h>
+#include <linux/sched.h>
+#include <linux/in6.h>
+#include <linux/interrupt.h>
+#include <linux/smp_lock.h>
+
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+#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 *);
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
+extern struct drive_info_struct drive_info;
+EXPORT_SYMBOL(drive_info);
+#endif
+
+/* platform dependent support */
+EXPORT_SYMBOL(dump_thread);
+EXPORT_SYMBOL(dump_fpu);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(local_bh_count);
+EXPORT_SYMBOL(local_irq_count);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(kernel_thread);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial_copy);
+
+EXPORT_SYMBOL(strtok);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strstr);
+
+#ifdef CONFIG_VT
+EXPORT_SYMBOL(screen_info);
+#endif
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/signal.c linux/arch/sh/kernel/signal.c
--- v2.3.15/linux/arch/sh/kernel/signal.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/signal.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,597 @@
+/*
+ *  linux/arch/sh/kernel/signal.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
+ *
+ *  SuperH version:  Copyright (C) 1999  Niibe Yutaka
+ *
+ */
+
+#include <linux/config.h>
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+
+#define DEBUG_SIG 0
+
+#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(struct pt_regs *regs, sigset_t *oldset);
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int
+sys_sigsuspend(old_sigset_t mask,
+	       unsigned long r5, unsigned long r6, unsigned long r7,
+	       struct pt_regs regs)
+{
+	sigset_t saveset;
+
+	mask &= _BLOCKABLE;
+	spin_lock_irq(&current->sigmask_lock);
+	saveset = current->blocked;
+	siginitset(&current->blocked, mask);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	regs.u_regs[0] = -EINTR;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if (do_signal(&regs,&saveset))
+			return -EINTR;
+	}
+}
+
+asmlinkage int
+sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
+		  unsigned long r6, unsigned long r7,
+		  struct pt_regs regs)
+{
+	sigset_t saveset, newset;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&newset, unewset, sizeof(newset)))
+		return -EFAULT;
+	sigdelsetmask(&newset, ~_BLOCKABLE);
+
+	spin_lock_irq(&current->sigmask_lock);
+	saveset = current->blocked;
+	current->blocked = newset;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	regs.u_regs[0] = -EINTR;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if (do_signal(&regs, &saveset))
+			return -EINTR;
+	}
+}
+
+asmlinkage int 
+sys_sigaction(int sig, const struct old_sigaction *act,
+	      struct old_sigaction *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	if (act) {
+		old_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_restorer, &act->sa_restorer))
+			return -EFAULT;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	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_restorer, &oact->sa_restorer))
+			return -EFAULT;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+	}
+
+	return ret;
+}
+
+asmlinkage int
+sys_sigaltstack(const stack_t *uss, stack_t *uoss,
+		unsigned long r6, unsigned long r7,
+		struct pt_regs regs)
+{
+	return do_sigaltstack(uss, uoss, regs.u_regs[UREG_SP]);
+}
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+
+struct sigframe
+{
+	struct sigcontext sc;
+	/* FPU should come here: SH-3 has no FPU */
+	unsigned long extramask[_NSIG_WORDS-1];
+	char retcode[4];
+};
+
+struct rt_sigframe
+{
+	struct siginfo *pinfo;
+	void *puc;
+	struct siginfo info;
+	struct ucontext uc;
+	/* FPU should come here: SH-3 has no FPU */
+	char retcode[4];
+};
+
+
+static int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *r0_p)
+{
+	unsigned int err = 0;
+
+#define COPY(x)		err |= __get_user(regs->x, &sc->x)
+				COPY(u_regs[1]);
+	COPY(u_regs[2]);	COPY(u_regs[3]);
+	COPY(u_regs[4]);	COPY(u_regs[5]);
+	COPY(u_regs[6]);	COPY(u_regs[7]);
+	COPY(u_regs[8]);	COPY(u_regs[9]);
+	COPY(u_regs[10]);	COPY(u_regs[11]);
+	COPY(u_regs[12]);	COPY(u_regs[13]);
+	COPY(u_regs[14]);	COPY(u_regs[15]);
+	COPY(gbr);		COPY(mach);
+	COPY(macl);		COPY(pr);
+	COPY(sr);		COPY(pc);
+#undef COPY
+
+	regs->syscall_nr = -1;		/* disable syscall checks */
+	err |= __get_user(*r0_p, &sc->u_regs[0]);
+
+	return err;
+}
+
+asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
+			     unsigned long r6, unsigned long r7,
+			     struct pt_regs regs)
+{
+	struct sigframe *frame = (struct sigframe *)regs.u_regs[UREG_SP];
+	sigset_t set;
+	int r0;
+
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__get_user(set.sig[0], &frame->sc.oldmask)
+	    || (_NSIG_WORDS > 1
+		&& __copy_from_user(&set.sig[1], &frame->extramask,
+				    sizeof(frame->extramask))))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sigmask_lock);
+	current->blocked = set;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	if (restore_sigcontext(&regs, &frame->sc, &r0))
+		goto badframe;
+	return r0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
+				unsigned long r6, unsigned long r7,
+				struct pt_regs regs)
+{
+	struct rt_sigframe *frame = (struct rt_sigframe *)regs.u_regs[UREG_SP];
+	sigset_t set;
+	stack_t st;
+	int r0;
+
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sigmask_lock);
+	current->blocked = set;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+	
+	if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &r0))
+		goto badframe;
+
+	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+		goto badframe;
+	/* It is more difficult to avoid calling this function than to
+	   call it and ignore errors.  */
+	do_sigaltstack(&st, NULL, regs.u_regs[UREG_SP]);
+
+	return r0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}	
+
+/*
+ * Set up a signal frame.
+ */
+
+static int
+setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
+		 unsigned long mask)
+{
+	int err = 0;
+
+#define COPY(x)		err |= __put_user(regs->x, &sc->x)
+	COPY(u_regs[0]);	COPY(u_regs[1]);
+	COPY(u_regs[2]);	COPY(u_regs[3]);
+	COPY(u_regs[4]);	COPY(u_regs[5]);
+	COPY(u_regs[6]);	COPY(u_regs[7]);
+	COPY(u_regs[8]);	COPY(u_regs[9]);
+	COPY(u_regs[10]);	COPY(u_regs[11]);
+	COPY(u_regs[12]);	COPY(u_regs[13]);
+	COPY(u_regs[14]);	COPY(u_regs[15]);
+	COPY(gbr);		COPY(mach);
+	COPY(macl);		COPY(pr);
+	COPY(sr);		COPY(pc);
+#undef COPY
+
+	/* non-iBCS2 extensions.. */
+	err |= __put_user(mask, &sc->oldmask);
+
+	return err;
+}
+
+/*
+ * Determine which stack to use..
+ */
+static inline void *
+get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+{
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+		sp = current->sas_ss_sp + current->sas_ss_size;
+
+	return (void *)((sp - frame_size) & -8ul);
+}
+
+static void setup_frame(int sig, struct k_sigaction *ka,
+			sigset_t *set, struct pt_regs *regs)
+{
+	struct sigframe *frame;
+	int err = 0;
+	int signal;
+
+	frame = get_sigframe(ka, regs->u_regs[UREG_SP], sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto give_sigsegv;
+
+	signal = current->exec_domain
+		&& current->exec_domain->signal_invmap
+		&& sig < 32
+		? current->exec_domain->signal_invmap[sig]
+		: sig;
+
+	err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
+
+	if (_NSIG_WORDS > 1) {
+		err |= __copy_to_user(frame->extramask, &set->sig[1],
+				      sizeof(frame->extramask));
+	}
+
+	/* Set up to return from userspace.  If provided, use a stub
+	   already in userspace.  */
+	if (ka->sa.sa_flags & SA_RESTORER) {
+		regs->pr = (unsigned long) ka->sa.sa_restorer;
+	} else {
+		/* This is ; mov  #__NR_sigreturn,r0 ; trapa #0 */
+#ifdef CONFIG_LITTLE_ENDIAN
+		unsigned long code = 0x00c300e0 | (__NR_sigreturn << 8);
+#else
+		unsigned long code = 0xe000c300 | (__NR_sigreturn << 16);
+#endif
+
+		regs->pr = (unsigned long) frame->retcode;
+		err |= __put_user(code, (long *)(frame->retcode+0));
+	}
+
+	if (err)
+		goto give_sigsegv;
+
+	/* Set up registers for signal handler */
+	regs->u_regs[UREG_SP] = (unsigned long) frame;
+	regs->u_regs[4] = signal; /* Arg for signal handler */
+	regs->pc = (unsigned long) ka->sa.sa_handler;
+
+	set_fs(USER_DS);
+
+#if DEBUG_SIG
+	printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
+		current->comm, current->pid, frame, regs->pc, regs->pr);
+#endif
+
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+}
+
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+			   sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe *frame;
+	int err = 0;
+	int signal;
+
+	frame = get_sigframe(ka, regs->u_regs[UREG_SP], sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto give_sigsegv;
+
+	signal = current->exec_domain
+		&& current->exec_domain->signal_invmap
+		&& sig < 32
+		? current->exec_domain->signal_invmap[sig]
+		: sig;
+
+	err |= __put_user(&frame->info, &frame->pinfo);
+	err |= __put_user(&frame->uc, &frame->puc);
+	err |= __copy_to_user(&frame->info, info, sizeof(*info));
+
+	/* Create the ucontext.  */
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(0, &frame->uc.uc_link);
+	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_SP]),
+			  &frame->uc.uc_stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	err |= setup_sigcontext(&frame->uc.uc_mcontext,
+			        regs, set->sig[0]);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+	/* Set up to return from userspace.  If provided, use a stub
+	   already in userspace.  */
+	if (ka->sa.sa_flags & SA_RESTORER) {
+		regs->pr = (unsigned long) ka->sa.sa_restorer;
+	} else {
+		/* This is ; mov  #__NR_sigreturn,r0 ; trapa #0 */
+#ifdef CONFIG_LITTLE_ENDIAN
+		unsigned long code = 0x00c300e0 | (__NR_sigreturn << 8);
+#else
+		unsigned long code = 0xe000c300 | (__NR_sigreturn << 16);
+#endif
+
+		regs->pr = (unsigned long) frame->retcode;
+		err |= __put_user(code, (long *)(frame->retcode+0));
+	}
+
+	if (err)
+		goto give_sigsegv;
+
+	/* Set up registers for signal handler */
+	regs->u_regs[UREG_SP] = (unsigned long) frame;
+	regs->u_regs[4] = signal; /* Arg for signal handler */
+	regs->pc = (unsigned long) ka->sa.sa_handler;
+
+	set_fs(USER_DS);
+
+#if DEBUG_SIG
+	printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
+		current->comm, current->pid, frame, regs->pc, regs->pr);
+#endif
+
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+}
+
+/*
+ * OK, we're invoking a handler
+ */	
+
+static void
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+{
+	/* Are we from a system call? */
+	if (regs->syscall_nr >= 0) {
+		/* If so, check system call restarting.. */
+		switch (regs->u_regs[0]) {
+			case -ERESTARTNOHAND:
+				regs->u_regs[0] = -EINTR;
+				break;
+
+			case -ERESTARTSYS:
+				if (!(ka->sa.sa_flags & SA_RESTART)) {
+					regs->u_regs[0] = -EINTR;
+					break;
+				}
+			/* fallthrough */
+			case -ERESTARTNOINTR:
+				regs->u_regs[0] = regs->syscall_nr;
+				regs->pc -= 2;
+		}
+	}
+
+	/* Set up the stack frame */
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		setup_rt_frame(sig, ka, info, oldset, regs);
+	else
+		setup_frame(sig, ka, oldset, regs);
+
+	if (ka->sa.sa_flags & SA_ONESHOT)
+		ka->sa.sa_handler = SIG_DFL;
+
+	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);
+	}
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals that
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ */
+int do_signal(struct pt_regs *regs, sigset_t *oldset)
+{
+	siginfo_t info;
+	struct k_sigaction *ka;
+
+	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;
+
+			/* 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;
+			}
+		}
+
+		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)
+				/* nothing */;
+			continue;
+		}
+
+		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;
+
+			case SIGTSTP: case SIGTTIN: case SIGTTOU:
+				if (is_orphaned_pgrp(current->pgrp))
+					continue;
+				/* FALLTHRU */
+
+			case SIGSTOP:
+				current->state = TASK_STOPPED;
+				current->exit_code = signr;
+				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:
+				if (do_coredump(signr, regs))
+					exit_code |= 0x80;
+				/* FALLTHRU */
+
+			default:
+				lock_kernel();
+				sigaddset(&current->signal, signr);
+				recalc_sigpending(current);
+				current->flags |= PF_SIGNALED;
+				do_exit(exit_code);
+				/* NOTREACHED */
+			}
+		}
+
+		/* Whee!  Actually deliver the signal.  */
+		handle_signal(signr, ka, &info, oldset, regs);
+		return 1;
+	}
+
+	/* Did we come from a system call? */
+	if (regs->syscall_nr >= 0) {
+		/* Restart the system call - no handlers present */
+		if (regs->u_regs[0] == -ERESTARTNOHAND ||
+		    regs->u_regs[0] == -ERESTARTSYS ||
+		    regs->u_regs[0] == -ERESTARTNOINTR) {
+			regs->u_regs[0] = regs->syscall_nr;
+			regs->pc -= 2;
+		}
+	}
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/sys_sh.c linux/arch/sh/kernel/sys_sh.c
--- v2.3.15/linux/arch/sh/kernel/sys_sh.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/sys_sh.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,249 @@
+/*
+ * linux/arch/i386/kernel/sys_i386.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/i386
+ * platform.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/utsname.h>
+
+#include <asm/uaccess.h>
+#include <asm/ipc.h>
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way Unix traditionally does this, though.
+ */
+asmlinkage int sys_pipe(unsigned long * fildes)
+{
+	int fd[2];
+	int error;
+
+	lock_kernel();
+	error = do_pipe(fd);
+	unlock_kernel();
+	if (!error) {
+		if (copy_to_user(fildes, fd, 2*sizeof(int)))
+			error = -EFAULT;
+	}
+	return error;
+}
+
+/*
+ * Perform the select(nd, in, out, ex, tv) and mmap() system
+ * calls. Linux/i386 didn't use to be able to handle more than
+ * 4 system call parameters, so these system calls used a memory
+ * block for parameter passing..
+ */
+
+struct mmap_arg_struct {
+	unsigned long addr;
+	unsigned long len;
+	unsigned long prot;
+	unsigned long flags;
+	unsigned long fd;
+	unsigned long offset;
+};
+
+asmlinkage int old_mmap(struct mmap_arg_struct *arg)
+{
+	int error = -EFAULT;
+	struct file * file = NULL;
+	struct mmap_arg_struct a;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		return -EFAULT;
+
+	down(&current->mm->mmap_sem);
+	lock_kernel();
+	if (!(a.flags & MAP_ANONYMOUS)) {
+		error = -EBADF;
+		file = fget(a.fd);
+		if (!file)
+			goto out;
+	}
+	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+	error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset);
+	if (file)
+		fput(file);
+out:
+	unlock_kernel();
+	up(&current->mm->mmap_sem);
+	return error;
+}
+
+extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+
+struct sel_arg_struct {
+	unsigned long n;
+	fd_set *inp, *outp, *exp;
+	struct timeval *tvp;
+};
+
+asmlinkage int old_select(struct sel_arg_struct *arg)
+{
+	struct sel_arg_struct a;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		return -EFAULT;
+	/* sys_select() does the appropriate kernel locking */
+	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage int sys_ipc (uint call, int first, int second,
+			int third, void *ptr, long fifth)
+{
+	int version, ret;
+
+	version = call >> 16; /* hack for backward compatibility */
+	call &= 0xffff;
+
+	if (call <= SEMCTL)
+		switch (call) {
+		case SEMOP:
+			return sys_semop (first, (struct sembuf *)ptr, second);
+		case SEMGET:
+			return sys_semget (first, second, third);
+		case SEMCTL: {
+			union semun fourth;
+			if (!ptr)
+				return -EINVAL;
+			if (get_user(fourth.__pad, (void **) ptr))
+				return -EFAULT;
+			return sys_semctl (first, second, third, fourth);
+			}
+		default:
+			return -EINVAL;
+		}
+
+	if (call <= MSGCTL) 
+		switch (call) {
+		case MSGSND:
+			return sys_msgsnd (first, (struct msgbuf *) ptr, 
+					  second, third);
+		case MSGRCV:
+			switch (version) {
+			case 0: {
+				struct ipc_kludge tmp;
+				if (!ptr)
+					return -EINVAL;
+				
+				if (copy_from_user(&tmp,
+						   (struct ipc_kludge *) ptr, 
+						   sizeof (tmp)))
+					return -EFAULT;
+				return sys_msgrcv (first, tmp.msgp, second,
+						   tmp.msgtyp, third);
+				}
+			default:
+				return sys_msgrcv (first,
+						   (struct msgbuf *) ptr,
+						   second, fifth, third);
+			}
+		case MSGGET:
+			return sys_msgget ((key_t) first, second);
+		case MSGCTL:
+			return sys_msgctl (first, second,
+					   (struct msqid_ds *) ptr);
+		default:
+			return -EINVAL;
+		}
+	if (call <= SHMCTL) 
+		switch (call) {
+		case SHMAT:
+			switch (version) {
+			default: {
+				ulong raddr;
+				ret = sys_shmat (first, (char *) ptr,
+						 second, &raddr);
+				if (ret)
+					return ret;
+				return put_user (raddr, (ulong *) third);
+			}
+			case 1:	/* iBCS2 emulator entry point */
+				if (!segment_eq(get_fs(), get_ds()))
+					return -EINVAL;
+				return sys_shmat (first, (char *) ptr,
+						  second, (ulong *) third);
+			}
+		case SHMDT: 
+			return sys_shmdt ((char *)ptr);
+		case SHMGET:
+			return sys_shmget (first, second, third);
+		case SHMCTL:
+			return sys_shmctl (first, second,
+					   (struct shmid_ds *) ptr);
+		default:
+			return -EINVAL;
+		}
+	
+	return -EINVAL;
+}
+
+/*
+ * Old cruft
+ */
+asmlinkage int sys_uname(struct old_utsname * name)
+{
+	int err;
+	if (!name)
+		return -EFAULT;
+	down(&uts_sem);
+	err=copy_to_user(name, &system_utsname, sizeof (*name));
+	up(&uts_sem);
+	return err?-EFAULT:0;
+}
+
+asmlinkage int sys_olduname(struct oldold_utsname * name)
+{
+	int error;
+
+	if (!name)
+		return -EFAULT;
+	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
+		return -EFAULT;
+  
+  	down(&uts_sem);
+	
+	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+	error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+	error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+	error |= __put_user(0,name->release+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+	error |= __put_user(0,name->version+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+	error |= __put_user(0,name->machine+__OLD_UTS_LEN);
+	
+	up(&uts_sem);
+	
+	error = error ? -EFAULT : 0;
+
+	return error;
+}
+
+asmlinkage int sys_pause(void)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	return -ERESTARTNOHAND;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/test-img.c linux/arch/sh/kernel/test-img.c
--- v2.3.15/linux/arch/sh/kernel/test-img.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/test-img.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,69 @@
+unsigned char root_fs_image[]
+__attribute__((__section__(".data.disk_image"))) 
+= {
+0x1f,0x8b,0x08,0x08,0x5d,0xd5,0xc7,0x37,0x00,0x03,0x72,0x2e,0x62,0x69,0x6e,0x00,
+0xed,0xdc,0x3f,0x6c,0x1b,0x55,0x1c,0xc0,0xf1,0xdf,0xf9,0xdc,0x04,0x27,0x69,0xb1,
+0x93,0x14,0x10,0x48,0x91,0xd3,0x02,0x4d,0x8a,0xb8,0xd4,0x21,0x8a,0x09,0x02,0x02,
+0xb5,0x4a,0xab,0x52,0x65,0x69,0x11,0x03,0x42,0xc2,0xb1,0x8f,0xc4,0x92,0xe3,0x03,
+0x9f,0x8d,0xca,0x14,0xd8,0x88,0x2a,0xa6,0x0e,0x88,0xa9,0x20,0xb1,0x87,0x8d,0xa5,
+0x5b,0x86,0xcc,0x90,0x78,0x77,0xd4,0x60,0x75,0xa9,0x40,0xe2,0xdf,0xd0,0x42,0x78,
+0x77,0xef,0x9c,0x38,0x24,0x72,0x49,0x20,0xc9,0x70,0xdf,0x8f,0xf2,0xf3,0xd9,0x77,
+0xbf,0xf3,0xbb,0x67,0xbf,0xdf,0xf9,0x4f,0xf4,0x2c,0x02,0x20,0xac,0xe2,0x2a,0x5e,
+0x53,0x61,0xaa,0x18,0x0e,0xd6,0x19,0xad,0x09,0x49,0x1d,0x5e,0x5e,0x7d,0x75,0x39,
+0xfd,0x6c,0x6d,0x39,0x6d,0x48,0xbf,0x5c,0xfd,0xc9,0xf0,0xf3,0x56,0xd5,0x3a,0x99,
+0xba,0xf7,0xd0,0x76,0x8a,0x53,0x5f,0xc4,0xdf,0xcd,0x24,0x56,0x6e,0x9e,0x59,0xb9,
+0x30,0x3e,0x73,0x3b,0xf7,0x3f,0x76,0x01,0xc0,0x3e,0x79,0x75,0x1f,0x55,0x71,0x4c,
+0x74,0xfd,0x47,0x8f,0xf6,0x70,0x00,0x1c,0xa2,0x8d,0x8d,0x49,0x6f,0xf1,0xc9,0x06,
+0x00,0x00,0x08,0x8d,0xe6,0xfb,0x00,0xef,0x73,0x7c,0x33,0x0e,0xf3,0xfd,0xc7,0xbd,
+0xd7,0xc5,0xff,0xd0,0x31,0x5a,0x5b,0x4e,0xf7,0x05,0xa1,0xb7,0x1c,0x93,0x48,0x4b,
+0x5e,0xe7,0x61,0x1e,0x14,0x80,0x50,0xf0,0xcf,0x3f,0xe7,0x76,0x3b,0xff,0x45,0xe4,
+0x89,0x96,0xbc,0x47,0x54,0xc4,0x54,0x74,0xa9,0xe8,0x56,0xd1,0xa3,0xe2,0xb8,0x8a,
+0x13,0x2a,0x1e,0x15,0xfd,0xfd,0x68,0x42,0x45,0xaf,0x8a,0xbe,0xbd,0xb6,0xaf,0xce,
+0x7f,0x7f,0xaa,0x76,0xef,0x07,0xd1,0x6c,0xbf,0xf5,0xfc,0xd7,0xbf,0xf7,0xae,0x6d,
+0x32,0xda,0x6c,0x6b,0xb6,0x7f,0x56,0x9d,0x77,0x4f,0x05,0xb1,0x5b,0xfb,0x27,0x0f,
+0xa8,0xfd,0x6f,0x06,0xf5,0xf2,0xfe,0x8e,0xfe,0xff,0x63,0xaf,0xff,0xf0,0xc5,0x54,
+0xdb,0xfe,0x7f,0x7a,0xeb,0xf2,0x15,0x53,0xe4,0xe6,0xaa,0x7e,0xed,0x19,0x0b,0xda,
+0xbf,0x75,0xd9,0xd8,0xd6,0xff,0xc7,0xf6,0xdf,0x7c,0xdb,0xf6,0x37,0xbe,0xd6,0x63,
+0x6a,0xe7,0xe3,0xbf,0x7d,0x2f,0xcb,0x1a,0x29,0x16,0x4a,0xd5,0xeb,0xe5,0x7d,0x7c,
+0x73,0xde,0xae,0x7d,0xaf,0x8f,0x3d,0x2a,0xc3,0xda,0xbc,0x1e,0x51,0x6d,0xe9,0x31,
+0xde,0xaf,0x8e,0xac,0xe8,0xb8,0x95,0xe7,0xde,0x77,0xaa,0xa5,0xbc,0x1e,0xf3,0x3d,
+0x62,0x4a,0xde,0xfe,0xc8,0x1f,0xfb,0x3d,0xea,0x49,0x71,0xa7,0x0b,0x25,0x6f,0xfc,
+0xdf,0x36,0x3b,0x65,0xdf,0x07,0x08,0xe0,0x48,0xe8,0xd7,0xb2,0xad,0xfa,0xff,0xd5,
+0xd4,0xf5,0x0f,0x20,0x24,0xf8,0xa7,0x1f,0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f,
+0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f,
+0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f,0x10,0x5e,0xd4,0x3f,
+0x10,0x4a,0x7a,0x4e,0xcf,0xce,0xf9,0x3f,0xde,0xbc,0xb6,0xbb,0x66,0xa7,0xe4,0x9c,
+0x92,0xeb,0x14,0xed,0xa3,0x3d,0x48,0x00,0x07,0x42,0xcf,0xe3,0xdb,0x59,0xff,0xde,
+0x7c,0xd6,0xbb,0x66,0x54,0x0a,0xa5,0x42,0xe5,0x68,0x8f,0x10,0xc0,0x41,0x99,0xbf,
+0x70,0xe5,0x0d,0x23,0xd2,0x32,0x43,0x38,0x22,0x67,0xc5,0x9f,0x32,0x1c,0xff,0x4a,
+0x2d,0xc7,0xd4,0xd5,0x75,0x7f,0xfd,0x98,0x24,0xd5,0xb6,0x21,0x89,0xf9,0x53,0xe1,
+0x83,0x1d,0xe2,0x41,0x18,0xd3,0x3a,0xfc,0x9f,0x11,0x34,0x74,0x78,0xb7,0x07,0x83,
+0xd8,0xd4,0xe1,0x27,0x67,0xd6,0x8d,0x46,0x7c,0xa4,0x51,0x8f,0xd6,0x3a,0x4a,0xbf,
+0x2c,0xc9,0x7b,0xa7,0x3f,0x33,0x16,0xcc,0x5a,0xb4,0x61,0xd6,0xa3,0x4b,0xe2,0xdc,
+0x91,0xee,0xd2,0xef,0x22,0x89,0xa7,0x55,0xbc,0x38,0xd2,0x98,0xff,0xb9,0x1e,0xf1,
+0xb2,0xa6,0xcd,0xf3,0x89,0x85,0xce,0x75,0xa3,0xf6,0x78,0xe3,0xa4,0x97,0x27,0xb1,
+0xc5,0xbf,0x24,0x76,0x6a,0x68,0xa1,0x7b,0xa5,0x6f,0x4d,0x3e,0x34,0x52,0xe9,0x1b,
+0x0f,0xf2,0xa7,0x7f,0x34,0xea,0xcf,0x2c,0xc9,0xe2,0x1f,0x6b,0x6a,0xfb,0xf7,0x27,
+0xd6,0x0d,0xab,0xd7,0xbe,0xb3,0x26,0x03,0x89,0x86,0x0c,0xf4,0xd6,0x33,0x03,0x7d,
+0x4b,0xf2,0x43,0xd7,0xba,0x21,0xb1,0x5a,0xac,0x71,0xdc,0xbb,0x17,0x2f,0x4f,0xed,
+0x7b,0xe6,0xc6,0x83,0xc5,0xdf,0xbc,0xf5,0xaa,0xcd,0x97,0xe5,0x9d,0xcf,0xe7,0x55,
+0xbf,0x2a,0xf2,0xdd,0x93,0x1b,0xea,0xf6,0xb5,0x6b,0xb3,0x05,0x37,0xa9,0xfe,0xae,
+0x56,0x3f,0xb0,0xcb,0x97,0x06,0xbd,0xe9,0xda,0x32,0x39,0xd9,0x25,0xae,0x33,0x67,
+0x57,0x66,0x0b,0xa5,0x99,0x64,0xb5,0x54,0x75,0xab,0xd9,0xa2,0x65,0x59,0xde,0xc6,
+0x4b,0x76,0xb1,0xe8,0x24,0xdf,0x76,0xca,0xc5,0xbc,0x97,0x7c,0x31,0x93,0x79,0x29,
+0x39,0x74,0x71,0xea,0xad,0xe1,0xa4,0x3d,0x93,0x73,0x9f,0x1f,0xb5,0x26,0x52,0xd6,
+0xf8,0x78,0x32,0x35,0x31,0x31,0x71,0xee,0x85,0xd4,0x58,0x72,0xc8,0x5f,0x9d,0xb2,
+0x52,0xd6,0x68,0xb2,0x6c,0x17,0xed,0xac,0x6b,0x0f,0x8b,0x58,0xee,0xc7,0x73,0x95,
+0xec,0xb4,0x5a,0x56,0xca,0x7a,0x39,0xdb,0xbc,0x56,0xb1,0xaf,0x57,0xc4,0x2a,0x3b,
+0xf9,0x6c,0x25,0x2b,0x96,0xbe,0xcc,0x55,0x9c,0xb2,0xab,0x6e,0xe8,0xc5,0xb4,0xab,
+0x2e,0x72,0xce,0xdc,0x9c,0x5d,0xda,0xd3,0xe9,0xfb,0xa9,0xe0,0xf9,0xeb,0xf0,0xfb,
+0x2f,0xe2,0xc5,0xb7,0x2d,0xdb,0x9b,0x9f,0x14,0x07,0x83,0xbc,0x88,0x7e,0x9e,0x0c,
+0x15,0xf2,0xea,0x2e,0x79,0xc3,0x41,0x9e,0xa9,0xc7,0x81,0xd1,0x3a,0x16,0x64,0x6b,
+0x1c,0xc9,0xc8,0xd6,0xb8,0x69,0x9b,0x37,0xfe,0x2f,0xf3,0x5e,0x11,0xfd,0x93,0x0d,
+0x0f,0x6b,0xf7,0xbc,0x6c,0x9b,0x1e,0xef,0xe7,0xa5,0x77,0xc9,0x4b,0xe8,0xfb,0xda,
+0x5c,0xfd,0xa5,0xba,0x78,0x73,0x97,0x3c,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,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x87,0xe8,0x6f,0x20,0x01,0xec,0xc5,0x00,0x00,0x01,0x00,
+};
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/time.c linux/arch/sh/kernel/time.c
--- v2.3.15/linux/arch/sh/kernel/time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/time.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,225 @@
+/*
+ *  linux/arch/sh/kernel/time.c
+ *
+ *  Copyright (C) 1999  Niibe Yutaka
+ *
+ *  Some code taken from i386 version.
+ *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+
+#include <linux/timex.h>
+#include <linux/config.h>
+#include <linux/irq.h>
+
+#define TMU_TOCR	0xfffffe90	/* Byte access */
+#define TMU_TSTR	0xfffffe92	/* Byte access */
+
+#define TMU0_TCOR	0xfffffe94	/* Long access */
+#define TMU0_TCNT	0xfffffe98	/* Long access */
+#define TMU0_TCR	0xfffffe9c	/* Word access */
+
+#define TMU_TOCR_INIT	0x00
+#define TMU0_TCR_INIT	0x0020
+#define TMU_TSTR_INIT	1
+
+#define CLOCK_MHZ	(60/4)
+#define INTERVAL	37500 /* (1000000*CLOCK_MHZ/HZ/2) ??? */
+
+extern rwlock_t xtime_lock;
+#define TICK_SIZE tick
+
+void do_gettimeofday(struct timeval *tv)
+{
+	extern volatile unsigned long lost_ticks;
+	unsigned long flags;
+	unsigned long usec, sec;
+
+	read_lock_irqsave(&xtime_lock, flags);
+	usec = 0;
+	{
+		unsigned long lost = lost_ticks;
+		if (lost)
+			usec += lost * (1000000 / HZ);
+	}
+	sec = xtime.tv_sec;
+	usec += xtime.tv_usec;
+	read_unlock_irqrestore(&xtime_lock, flags);
+
+	while (usec >= 1000000) {
+		usec -= 1000000;
+		sec++;
+	}
+
+	tv->tv_sec = sec;
+	tv->tv_usec = usec;
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+	write_lock_irq(&xtime_lock);
+	xtime = *tv;
+	time_adjust = 0;		/* stop active adjtime() */
+	time_status |= STA_UNSYNC;
+	time_maxerror = NTP_PHASE_LIMIT;
+	time_esterror = NTP_PHASE_LIMIT;
+	write_unlock_irq(&xtime_lock);
+}
+
+/*
+ */
+static int set_rtc_time(unsigned long nowtime)
+{
+/* XXX  should be implemented XXXXXXXXXX */
+	int retval = -1;
+
+	return retval;
+}
+
+/* last time the RTC clock got updated */
+static long last_rtc_update = 0;
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	do_timer(regs);
+
+#if 0
+	if (!user_mode(regs))
+		sh_do_profile(regs->pc);
+#endif
+
+	/*
+	 * If we have an externally synchronized Linux clock, then update
+	 * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+	 * called as close as possible to 500 ms before the new second starts.
+	 */
+	if ((time_status & STA_UNSYNC) == 0 &&
+	    xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
+	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
+		if (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 */
+	}
+}
+
+/*
+ * This is the same as the above, except we _also_ save the current
+ * Time Stamp Counter value at the time of the timer interrupt, so that
+ * we later on can estimate the time of day more exactly.
+ */
+static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long __dummy;
+
+	/* Clear UNF bit */
+	asm volatile("mov.w	%1,%0\n\t"
+		     "and	%2,%0\n\t"
+		     "mov.w	%0,%1"
+		     : "=&z" (__dummy)
+		     : "m" (__m(TMU0_TCR)), "r" (~0x100));
+
+	/*
+	 * Here we are in the timer irq handler. We just have irqs locally
+	 * disabled but we don't know if the timer_bh is running on the other
+	 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
+	 * the irq version of write_lock because as just said we have irq
+	 * locally disabled. -arca
+	 */
+	write_lock(&xtime_lock);
+
+	do_timer_interrupt(irq, NULL, regs);
+
+	write_unlock(&xtime_lock);
+}
+
+/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines were long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+static inline unsigned long mktime(unsigned int year, unsigned int mon,
+	unsigned int day, unsigned int hour,
+	unsigned int min, unsigned int sec)
+{
+	if (0 >= (int) (mon -= 2)) {	/* 1..12 -> 11,12,1..10 */
+		mon += 12;	/* Puts Feb last since it has leap day */
+		year -= 1;
+	}
+	return (((
+	    (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
+	      year*365 - 719499
+	    )*24 + hour /* now have hours */
+	   )*60 + min /* now have minutes */
+	  )*60 + sec; /* finally seconds */
+}
+
+static unsigned long get_rtc_time(void)
+{
+/* XXX not implemented yet */
+	return 0;
+}
+
+static struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
+
+void __init time_init(void)
+{
+	unsigned long __dummy;
+
+	xtime.tv_sec = get_rtc_time();
+	xtime.tv_usec = 0;
+
+	set_ipr_data(TIMER_IRQ, TIMER_IRP_OFFSET, TIMER_PRIORITY);
+	setup_irq(TIMER_IRQ, &irq0);
+
+	/* Start TMU0 */
+	asm volatile("mov	%1,%0\n\t"
+		     "mov.b	%0,%2		! external clock input\n\t"
+		     "mov	%3,%0\n\t"
+		     "mov.w	%0,%4		! enable timer0 interrupt\n\t"
+		     "mov.l	%5,%6\n\t"
+		     "mov.l	%5,%7\n\t"
+		     "mov	%8,%0\n\t"
+		     "mov.b	%0,%9"
+		     : "=&z" (__dummy)
+		     : "i" (TMU_TOCR_INIT), "m" (__m(TMU_TOCR)),
+		       "i" (TMU0_TCR_INIT), "m" (__m(TMU0_TCR)),
+		       "r" (INTERVAL), "m" (__m(TMU0_TCOR)), "m" (__m(TMU0_TCNT)),
+		       "i" (TMU_TSTR_INIT), "m" (__m(TMU_TSTR)));
+#if 0
+	/* Start RTC */
+	asm volatile("");
+#endif
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/kernel/traps.c linux/arch/sh/kernel/traps.c
--- v2.3.15/linux/arch/sh/kernel/traps.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/traps.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,128 @@
+/*
+ *  linux/arch/sh/traps.c
+ *
+ *  SuperH version: Copyright (C) 1999  Niibe Yutaka
+ */
+
+/*
+ * 'Traps.c' handles hardware traps and faults after we have saved some
+ * state in 'entry.S'.
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/spinlock.h>
+#include <asm/atomic.h>
+
+static inline void console_verbose(void)
+{
+	extern int console_loglevel;
+	console_loglevel = 15;
+}
+
+#define DO_ERROR(trapnr, signr, str, name, tsk) \
+asmlinkage void do_##name(unsigned long r4, unsigned long r5, \
+			  unsigned long r6, unsigned long r7, \
+			  struct pt_regs regs) \
+{ \
+	unsigned long error_code; \
+ \
+	asm volatile("stc	r2_bank,%0": "=r" (error_code)); \
+	sti(); \
+	regs.syscall_nr = -1; \
+	tsk->thread.error_code = error_code; \
+	tsk->thread.trap_no = trapnr; \
+	force_sig(signr, tsk); \
+	die_if_no_fixup(str,&regs,error_code); \
+}
+
+/*
+ * These constants are for searching for possible module text
+ * segments.  VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
+ * a guess of how much space is likely to be vmalloced.
+ */
+#define VMALLOC_OFFSET (8*1024*1024)
+#define MODULE_RANGE (8*1024*1024)
+
+static void show_registers(struct pt_regs *regs)
+{/* Not implemented yet. */
+}	
+
+spinlock_t die_lock;
+
+void die(const char * str, struct pt_regs * regs, long err)
+{
+	console_verbose();
+	spin_lock_irq(&die_lock);
+	printk("%s: %04lx\n", str, err & 0xffff);
+	show_registers(regs);
+	spin_unlock_irq(&die_lock);
+	do_exit(SIGSEGV);
+}
+
+static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+{
+	if (!user_mode(regs))
+		die(str, regs, err);
+}
+
+static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
+{
+	if (!user_mode(regs))
+	{
+		unsigned long fixup;
+		fixup = search_exception_table(regs->pc);
+		if (fixup) {
+			regs->pc = fixup;
+			return;
+		}
+		die(str, regs, err);
+	}
+}
+
+DO_ERROR( 7, SIGSEGV, "address error (load)", address_error_load, current)
+DO_ERROR( 8, SIGSEGV, "address error (store)", address_error_store, current)
+DO_ERROR(12, SIGILL,  "reserved instruction", reserved_inst, current)
+DO_ERROR(13, SIGILL,  "illegal slot instruction", illegal_slot_inst, current)
+
+asmlinkage void do_exception_error (unsigned long r4, unsigned long r5,
+				    unsigned long r6, unsigned long r7,
+				    struct pt_regs regs)
+{
+	long ex;
+	asm volatile("stc	r2_bank,%0" : "=r" (ex));
+	die_if_kernel("exception", &regs, ex);
+}
+
+void __init trap_init(void)
+{
+	extern void *vbr_base;
+	extern void *exception_handling_table[14];
+
+	exception_handling_table[7] = (void *)do_address_error_load;
+	exception_handling_table[8] = (void *)do_address_error_store;
+	exception_handling_table[12] = (void *)do_reserved_inst;
+	exception_handling_table[13] = (void *)do_illegal_slot_inst;
+
+	/* NOTE: The VBR value should be at P1
+	   (or P2, virtural "fixed" address space).
+	   It's definitely should not in physical address.  */
+
+	asm volatile("ldc	%0,vbr"
+		     : /* no output */
+		     : "r" (&vbr_base)
+		     : "memory");
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/lib/Makefile linux/arch/sh/lib/Makefile
--- v2.3.15/linux/arch/sh/lib/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/lib/Makefile	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,14 @@
+#
+# Makefile for SuperH-specific library files..
+#
+
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+
+L_TARGET = lib.a
+# L_OBJS  = checksum.o old-checksum.o semaphore.o delay.o \
+# 	usercopy.o getuser.o putuser.o
+L_OBJS  = delay.o memcpy.o memset.o memmove.o csum_partial_copy.o \
+	  wordcopy.o checksum.o # usercopy.o getuser.o putuser.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.15/linux/arch/sh/lib/checksum.c linux/arch/sh/lib/checksum.c
--- v2.3.15/linux/arch/sh/lib/checksum.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/lib/checksum.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,170 @@
+/*
+ * Taken from:
+ * arch/alpha/lib/checksum.c
+ *
+ * This file contains network checksum routines that are better done
+ * in an architecture-specific manner due to speed..
+ */
+ 
+#include <linux/string.h>
+
+#include <asm/byteorder.h>
+
+static inline unsigned short from64to16(unsigned long long x)
+{
+	/* add up 32-bit words for 33 bits */
+	x = (x & 0xffffffff) + (x >> 32);
+	/* add up 16-bit and 17-bit words for 17+c bits */
+	x = (x & 0xffff) + (x >> 16);
+	/* add up 16-bit and 2-bit for 16+c bit */
+	x = (x & 0xffff) + (x >> 16);
+	/* add up carry.. */
+	x = (x & 0xffff) + (x >> 16);
+	return x;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented.
+ */
+unsigned short int csum_tcpudp_magic(unsigned long saddr,
+				   unsigned long daddr,
+				   unsigned short len,
+				   unsigned short proto,
+				   unsigned int sum)
+{
+	return ~from64to16(saddr + daddr + sum +
+		((unsigned long) ntohs(len) << 16) +
+		((unsigned long) proto << 8));
+}
+
+unsigned int csum_tcpudp_nofold(unsigned long saddr,
+				unsigned long daddr,
+				unsigned short len,
+				unsigned short proto,
+				unsigned int sum)
+{
+	unsigned long long result;
+
+	result = (saddr + daddr + sum +
+		  ((unsigned long) ntohs(len) << 16) +
+		  ((unsigned long) proto << 8));
+
+	/* Fold down to 32-bits so we don't loose in the typedef-less 
+	   network stack.  */
+	/* 64 to 33 */
+	result = (result & 0xffffffff) + (result >> 32);
+	/* 33 to 32 */
+	result = (result & 0xffffffff) + (result >> 32);
+	return result;
+}
+
+/*
+ * Do a 64-bit checksum on an arbitrary memory area..
+ *
+ * This isn't a great routine, but it's not _horrible_ either. The
+ * inner loop could be unrolled a bit further, and there are better
+ * ways to do the carry, but this is reasonable.
+ */
+static inline unsigned long do_csum(const unsigned char * buff, int len)
+{
+	int odd, count;
+	unsigned long long result = 0;
+
+	if (len <= 0)
+		goto out;
+	odd = 1 & (unsigned long) buff;
+	if (odd) {
+		result = *buff << 8;
+		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) {
+			if (4 & (unsigned long) buff) {
+				result += *(unsigned int *) buff;
+				count--;
+				len -= 4;
+				buff += 4;
+			}
+			count >>= 1;	/* nr of 64-bit words.. */
+			if (count) {
+				unsigned long carry = 0;
+				do {
+					unsigned long w = *(unsigned long *) buff;
+					count--;
+					buff += 8;
+					result += carry;
+					result += w;
+					carry = (w > result);
+				} while (count);
+				result += carry;
+				result = (result & 0xffffffff) + (result >> 32);
+			}
+			if (len & 4) {
+				result += *(unsigned int *) buff;
+				buff += 4;
+			}
+		}
+		if (len & 2) {
+			result += *(unsigned short *) buff;
+			buff += 2;
+		}
+	}
+	if (len & 1)
+		result += *buff;
+	result = from64to16(result);
+	if (odd)
+		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+	return result;
+}
+
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ */
+unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+{
+	return ~do_csum(iph,ihl*4);
+}
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+{
+	unsigned long long result = do_csum(buff, len);
+
+	/* add in old sum, and carry.. */
+	result += sum;
+	/* 32+c bits -> 32 bits */
+	result = (result & 0xffffffff) + (result >> 32);
+	return result;
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+	return ~from64to16(do_csum(buff,len));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/lib/csum_partial_copy.c linux/arch/sh/lib/csum_partial_copy.c
--- v2.3.15/linux/arch/sh/lib/csum_partial_copy.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/lib/csum_partial_copy.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,75 @@
+/*
+ * 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@waldorf-gmbh.de>
+ *		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: csum_partial_copy.c,v 1.2 1998/09/16 13:29:32 ralf Exp $
+ */
+#include <net/checksum.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+/*
+ * 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 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);
+}
+
+/*
+ * Copy to userspace and compute checksum.
+ */
+unsigned int csum_partial_copy_to_user (const char *src, char *dst,
+                                        int len, unsigned int sum,
+                                        int *err_ptr)
+{
+	sum = csum_partial(src, len, sum);
+
+	if (copy_to_user(dst, src, len)) {
+		*err_ptr = -EFAULT;
+		return sum;
+	}
+
+	return sum;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/lib/delay.c linux/arch/sh/lib/delay.c
--- v2.3.15/linux/arch/sh/lib/delay.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/lib/delay.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,21 @@
+/*
+ *	Precise Delay Loops for SuperH
+ *
+ *	Copyright (C) 1999 Niibe Yutaka
+ */
+
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+inline void __const_udelay(unsigned long xloops)
+{
+	xloops *= current_cpu_data.loops_per_sec;
+        __delay(xloops);
+}
+
+#if 0
+void __udelay(unsigned long usecs)
+{
+	__const_udelay(usecs * 0x000010c6);  /* 2**32 / 1000000 */
+}
+#endif
diff -u --recursive --new-file v2.3.15/linux/arch/sh/lib/memcpy.S linux/arch/sh/lib/memcpy.S
--- v2.3.15/linux/arch/sh/lib/memcpy.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/lib/memcpy.S	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,131 @@
+! Taken from newlib-1.8.0
+
+!
+! Fast SH memcpy
+!
+! by Toshiyasu Morita (tm@netcom.com)
+! hacked by J"orn Rernnecke (amylaar@cygnus.co.uk) ("o for o-umlaut)
+!
+! Entry: r4: destination pointer
+!        r5: source pointer
+!        r6: byte count
+!
+! Exit:  r0: destination pointer
+!        r1-r7: trashed
+!
+! Notes: Usually one wants to do small reads and write a longword, but
+!        unfortunately it is difficult in some cases to concatanate bytes
+!        into a longword on the SH, so this does a longword read and small
+!        writes.
+!
+! This implementation makes two assumptions about how it is called:
+!
+! 1.: If the byte count is nonzero, the address of the last byte to be
+!     copied is unsigned greater than the address of the first byte to
+!     be copied.  This could be easily swapped for a signed comparison,
+!     but the algorithm used needs some comparison.
+!
+! 2.: When there are two or three bytes in the last word of an 11-or-bore
+!     bytes memory chunk to b copied, the rest of the word can be read
+!     without size effects.
+!     This could be easily changed by increasing the minumum size of
+!     a fast memcpy and the amount subtracted from r7 before L_2l_loop be 2,
+!     however, this would cost a few extra cyles on average.
+!
+
+#include <linux/linkage.h>
+ENTRY(memcpy)
+	! Big endian version copies with decreasing addresses.
+	mov	r4,r0
+	add	r6,r0
+	sub	r4,r5
+	mov	#11,r1
+	cmp/hs	r1,r6
+	bf/s	L_small
+	 add	#-1,r5
+	mov	r5,r3
+	add	r0,r3
+	shlr	r3
+	bt/s	L_even
+	 mov	r4,r7
+	mov.b	@(r0,r5),r2
+	add	#-1,r3
+	mov.b	r2,@-r0
+L_even:
+	tst	#1,r0
+	add	#-1,r5
+	bf/s	L_odddst
+	 add	#8,r7
+	tst	#2,r0
+	bt	L_al4dst
+	add	#-1,r3
+	mov.w	@(r0,r5),r1
+	mov.w	r1,@-r0
+L_al4dst:
+	shlr	r3
+	bt	L_al4both
+	mov.w	@(r0,r5),r1
+	swap.w	r1,r1
+	add	#4,r7
+	add	#-4,r5
+	.align	2
+L_2l_loop:
+	mov.l	@(r0,r5),r2
+	xtrct	r2,r1
+	mov.l	r1,@-r0
+	cmp/hs	r7,r0
+	mov.l	@(r0,r5),r1
+	xtrct	r1,r2
+	mov.l	r2,@-r0
+	bt	L_2l_loop
+	bra	L_cleanup
+	 add	#5,r5
+
+	nop ! avoid nop in executed code.
+L_al4both:
+	add	#-2,r5
+	.align	2
+L_al4both_loop:
+	mov.l	@(r0,r5),r1
+	cmp/hs	r7,r0
+	bt/s	L_al4both_loop
+	 mov.l	r1,@-r0
+	bra	L_cleanup
+	 add	#3,r5
+
+	nop ! avoid nop in executed code.
+L_odddst:
+	shlr	r3
+	bt	L_al4src
+	mov.w	@(r0,r5),r1
+	mov.b	r1,@-r0
+	shlr8	r1
+	mov.b	r1,@-r0
+L_al4src:
+	add	#-2,r5
+	.align	2
+L_odd_loop:
+	mov.l	@(r0,r5),r2
+	cmp/hs	r7,r0
+	mov.b	r2,@-r0
+	shlr8	r2
+	mov.w	r2,@-r0
+	shlr16	r2
+	mov.b	r2,@-r0
+	bt	L_odd_loop
+
+	add	#3,r5
+L_cleanup:
+L_small:
+	cmp/eq	r4,r0
+	bt	L_ready
+	add	#1,r4
+	.align	2
+L_cleanup_loop:
+	mov.b	@(r0,r5),r2
+	cmp/eq	r4,r0
+	mov.b	r2,@-r0
+	bf	L_cleanup_loop
+L_ready:
+	rts
+	 nop
diff -u --recursive --new-file v2.3.15/linux/arch/sh/lib/memmove.S linux/arch/sh/lib/memmove.S
--- v2.3.15/linux/arch/sh/lib/memmove.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/lib/memmove.S	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,422 @@
+#include <linux/linkage.h>
+ENTRY(memmove)
+	mov.l	r8,@-r15
+	mov.l	r9,@-r15
+	mov.l	r14,@-r15
+	sts.l	pr,@-r15
+	add	#-28,r15
+	mov	r15,r14
+	mov.l	r4,@r14
+	mov.l	r5,@(4,r14)
+	mov.l	r6,@(8,r14)
+	mov.l	@r14,r1
+	mov.l	r1,@(12,r14)
+	mov.l	@(4,r14),r1
+	mov.l	r1,@(16,r14)
+	mov.l	@(12,r14),r1
+	mov.l	@(16,r14),r2
+	sub	r2,r1
+	mov.l	@(8,r14),r2
+	cmp/hs	r2,r1
+	bt	.L54
+	bra	.L2
+	nop
+.L54:
+	mov.l	@(8,r14),r1
+	mov	#15,r2
+	cmp/gt	r2,r1
+	bt	.LF100
+	bra	.L52
+	nop
+.LF100:
+	mov.l	@(12,r14),r2
+	neg	r2,r1
+	mov	#3,r2
+	and	r1,r2
+	mov.l	@(8,r14),r1
+	mov	r1,r9
+	sub	r2,r9
+	mov	r9,r2
+	mov.l	r2,@(8,r14)
+.L4:
+	mov.l	@(12,r14),r2
+	neg	r2,r1
+	mov	#3,r2
+	and	r1,r2
+	mov.l	r2,@(20,r14)
+.L7:
+	mov.l	@(20,r14),r1
+	cmp/pl	r1
+	bt	.L9
+	bra	.L6
+	nop
+	.align 2
+.L9:
+	mov	r14,r2
+	mov	r14,r1
+	add	#24,r1
+	mov.l	@(16,r14),r2
+	mov.b	@r2,r3
+	mov.b	r3,@r1
+	mov.l	@(16,r14),r1
+	mov	r1,r2
+	add	#1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(20,r14),r1
+	mov	r1,r2
+	add	#-1,r2
+	mov.l	r2,@(20,r14)
+	mov.l	@(12,r14),r1
+	mov	r14,r2
+	mov	r14,r3
+	add	#24,r3
+	mov.b	@r3,r2
+	mov.b	r2,@r1
+	mov.l	@(12,r14),r1
+	mov	r1,r2
+	add	#1,r2
+	mov.l	r2,@(12,r14)
+	bra	.L7
+	nop
+	.align 2
+.L8:
+.L6:
+	bra	.L5
+	nop
+	.align 2
+.L10:
+	bra	.L4
+	nop
+	.align 2
+.L5:
+	nop
+.L11:
+	mov.l	@(16,r14),r1
+	mov	#3,r2
+	and	r1,r2
+	tst	r2,r2
+	bf	.L14
+	mov	r15,r2
+	mov.l	@(12,r14),r1
+	mov.l	@(16,r14),r2
+	mov.l	@(8,r14),r7
+	mov	r7,r3
+	shlr2	r3
+	mov	r1,r4
+	mov	r2,r5
+	mov	r3,r6
+	mov.l	.L46,r8
+	jsr	@r8
+	nop
+	bra	.L15
+	nop
+	.align 2
+.L14:
+	mov	r15,r2
+	mov.l	@(12,r14),r1
+	mov.l	@(16,r14),r2
+	mov.l	@(8,r14),r7
+	mov	r7,r3
+	shlr2	r3
+	mov	r1,r4
+	mov	r2,r5
+	mov	r3,r6
+	mov.l	.L47,r8
+	jsr	@r8
+	nop
+.L15:
+	mov.l	@(8,r14),r1
+	mov	#-4,r2
+	and	r2,r1
+	mov.l	@(16,r14),r2
+	add	r2,r1
+	mov.l	r1,@(16,r14)
+	mov.l	@(8,r14),r1
+	mov	#-4,r2
+	and	r2,r1
+	mov.l	@(12,r14),r2
+	add	r2,r1
+	mov.l	r1,@(12,r14)
+	mov.l	@(8,r14),r1
+	mov	#3,r2
+	and	r1,r2
+	mov.l	r2,@(8,r14)
+.L13:
+.L52:
+	bra	.L3
+	nop
+	.align 2
+.L16:
+	bra	.L11
+	nop
+	.align 2
+.L12:
+.L3:
+	nop
+.L17:
+	mov.l	@(8,r14),r1
+	mov.l	r1,@(20,r14)
+.L20:
+	mov.l	@(20,r14),r1
+	cmp/pl	r1
+	bt	.L22
+	bra	.L19
+	nop
+	.align 2
+.L22:
+	mov	r14,r2
+	mov	r14,r1
+	add	#24,r1
+	mov.l	@(16,r14),r2
+	mov.b	@r2,r3
+	mov.b	r3,@r1
+	mov.l	@(16,r14),r1
+	mov	r1,r2
+	add	#1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(20,r14),r1
+	mov	r1,r2
+	add	#-1,r2
+	mov.l	r2,@(20,r14)
+	mov.l	@(12,r14),r1
+	mov	r14,r2
+	mov	r14,r3
+	add	#24,r3
+	mov.b	@r3,r2
+	mov.b	r2,@r1
+	mov.l	@(12,r14),r1
+	mov	r1,r2
+	add	#1,r2
+	mov.l	r2,@(12,r14)
+	bra	.L20
+	nop
+	.align 2
+.L21:
+.L19:
+	bra	.L18
+	nop
+	.align 2
+.L23:
+	bra	.L17
+	nop
+	.align 2
+.L18:
+	bra	.L24
+	nop
+	.align 2
+.L2:
+	mov.l	@(16,r14),r1
+	mov.l	@(8,r14),r2
+	add	r2,r1
+	mov.l	r1,@(16,r14)
+	mov.l	@(12,r14),r1
+	mov.l	@(8,r14),r2
+	add	r2,r1
+	mov.l	r1,@(12,r14)
+	mov.l	@(8,r14),r1
+	mov	#15,r2
+	cmp/gt	r2,r1
+	bt	.LF101
+	bra	.L53
+	nop
+.LF101:
+	mov.l	@(12,r14),r1
+	mov	#3,r2
+	and	r1,r2
+	mov.l	@(8,r14),r1
+	mov	r1,r9
+	sub	r2,r9
+	mov	r9,r2
+	mov.l	r2,@(8,r14)
+.L26:
+	mov.l	@(12,r14),r1
+	mov	#3,r2
+	and	r1,r2
+	mov.l	r2,@(20,r14)
+.L29:
+	mov.l	@(20,r14),r1
+	cmp/pl	r1
+	bt	.L31
+	bra	.L28
+	nop
+	.align 2
+.L31:
+	mov.l	@(16,r14),r1
+	mov	r1,r2
+	add	#-1,r2
+	mov.l	r2,@(16,r14)
+	mov	r14,r2
+	mov	r14,r1
+	add	#24,r1
+	mov.l	@(16,r14),r2
+	mov.b	@r2,r3
+	mov.b	r3,@r1
+	mov.l	@(12,r14),r1
+	mov	r1,r2
+	add	#-1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@(20,r14),r1
+	mov	r1,r2
+	add	#-1,r2
+	mov.l	r2,@(20,r14)
+	mov.l	@(12,r14),r1
+	mov	r14,r2
+	mov	r14,r3
+	add	#24,r3
+	mov.b	@r3,r2
+	mov.b	r2,@r1
+	bra	.L29
+	nop
+	.align 2
+.L30:
+.L28:
+	bra	.L27
+	nop
+	.align 2
+.L32:
+	bra	.L26
+	nop
+	.align 2
+.L27:
+	nop
+.L33:
+	mov.l	@(16,r14),r1
+	mov	#3,r2
+	and	r1,r2
+	tst	r2,r2
+	bf	.L36
+	mov	r15,r2
+	mov.l	@(12,r14),r1
+	mov.l	@(16,r14),r2
+	mov.l	@(8,r14),r7
+	mov	r7,r3
+	shlr2	r3
+	mov	r1,r4
+	mov	r2,r5
+	mov	r3,r6
+	mov.l	.L48,r8
+	jsr	@r8
+	nop
+	bra	.L37
+	nop
+	.align 2
+.L36:
+	mov	r15,r2
+	mov.l	@(12,r14),r1
+	mov.l	@(16,r14),r2
+	mov.l	@(8,r14),r7
+	mov	r7,r3
+	shlr2	r3
+	mov	r1,r4
+	mov	r2,r5
+	mov	r3,r6
+	mov.l	.L49,r8
+	jsr	@r8
+	nop
+.L37:
+	mov.l	@(8,r14),r1
+	mov	#-4,r2
+	and	r2,r1
+	mov.l	@(16,r14),r2
+	mov	r2,r9
+	sub	r1,r9
+	mov	r9,r1
+	mov.l	r1,@(16,r14)
+	mov.l	@(8,r14),r1
+	mov	#-4,r2
+	and	r2,r1
+	mov.l	@(12,r14),r2
+	mov	r2,r9
+	sub	r1,r9
+	mov	r9,r1
+	mov.l	r1,@(12,r14)
+	mov.l	@(8,r14),r1
+	mov	#3,r2
+	and	r1,r2
+	mov.l	r2,@(8,r14)
+.L35:
+.L53:
+	bra	.L25
+	nop
+	.align 2
+.L38:
+	bra	.L33
+	nop
+	.align 2
+.L34:
+.L25:
+	nop
+.L39:
+	mov.l	@(8,r14),r1
+	mov.l	r1,@(20,r14)
+.L42:
+	mov.l	@(20,r14),r1
+	cmp/pl	r1
+	bt	.L44
+	bra	.L41
+	nop
+	.align 2
+.L44:
+	mov.l	@(16,r14),r1
+	mov	r1,r2
+	add	#-1,r2
+	mov.l	r2,@(16,r14)
+	mov	r14,r2
+	mov	r14,r1
+	add	#24,r1
+	mov.l	@(16,r14),r2
+	mov.b	@r2,r3
+	mov.b	r3,@r1
+	mov.l	@(12,r14),r1
+	mov	r1,r2
+	add	#-1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@(20,r14),r1
+	mov	r1,r2
+	add	#-1,r2
+	mov.l	r2,@(20,r14)
+	mov.l	@(12,r14),r1
+	mov	r14,r2
+	mov	r14,r3
+	add	#24,r3
+	mov.b	@r3,r2
+	mov.b	r2,@r1
+	bra	.L42
+	nop
+	.align 2
+.L43:
+.L41:
+	bra	.L24
+	nop
+	.align 2
+.L45:
+	bra	.L39
+	nop
+	.align 2
+.L40:
+.L24:
+	mov.l	@r14,r1
+	mov	r1,r0
+	bra	.L1
+	nop
+	.align 2
+.L1:
+	add	#28,r14
+	mov	r14,r15
+	lds.l	@r15+,pr
+	mov.l	@r15+,r14
+	mov.l	@r15+,r9
+	mov.l	@r15+,r8
+	rts	
+	 nop
+.L50:
+	.align 2
+.L46:
+	.long	__wordcopy_fwd_aligned
+.L47:
+	.long	__wordcopy_fwd_dest_aligned
+.L48:
+	.long	__wordcopy_bwd_aligned
+.L49:
+	.long	__wordcopy_bwd_dest_aligned
+.Lfe1:
diff -u --recursive --new-file v2.3.15/linux/arch/sh/lib/memset.S linux/arch/sh/lib/memset.S
--- v2.3.15/linux/arch/sh/lib/memset.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/lib/memset.S	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,72 @@
+! Taken from newlib-1.8.0
+
+!
+! Fast SH memset
+!
+! by Toshiyasu Morita (tm@netcom.com)
+!
+! Entry: r4: destination pointer
+!        r5: fill value
+!        r6: byte count
+!
+! Exit:  r0-r3: trashed
+!
+#include <linux/linkage.h>
+
+ENTRY(memset)
+	mov	r4,r3	! Save return value
+	
+	mov	r6,r0	! Check explicitly for zero
+	cmp/eq	#0,r0
+	bt	L_exit
+
+	mov	#12,r0	! Check for small number of bytes
+	cmp/gt	r6,r0
+	bt	L_store_byte_loop
+
+	neg	r4,r0	! Align destination
+	add	#4,r0
+	and	#3,r0
+	tst	r0,r0
+	bt	L_dup_bytes
+	.balignw 4,0x0009
+L_align_loop:
+	mov.b	r5,@r4
+	add	#-1,r6
+	add	#1,r4
+	dt	r0
+	bf	L_align_loop
+
+L_dup_bytes:	
+	extu.b	r5,r5	! Duplicate bytes across longword
+	swap.b	r5,r0
+	or	r0,r5
+	swap.w	r5,r0
+	or	r0,r5
+
+	mov	r6,r2	! Calculate number of double longwords
+	shlr2	r2
+	shlr	r2
+
+	.balignw 4,0x0009
+L_store_long_loop:
+	mov.l	r5,@r4	! Store double longs to memory
+	dt	r2
+	mov.l	r5,@(4,r4)
+	add	#8,r4
+	bf	L_store_long_loop
+
+	mov	#7,r0
+	and	r0,r6
+	tst	r6,r6
+	bt	L_exit
+	.balignw 4,0x0009
+L_store_byte_loop:
+	mov.b	r5,@r4	! Store bytes to memory
+	add	#1,r4
+	dt	r6
+	bf	L_store_byte_loop
+
+L_exit:
+	rts
+	 mov	r3,r0
diff -u --recursive --new-file v2.3.15/linux/arch/sh/lib/old-checksum.c linux/arch/sh/lib/old-checksum.c
--- v2.3.15/linux/arch/sh/lib/old-checksum.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/lib/old-checksum.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,19 @@
+/*
+ * FIXME: old compatibility stuff, will be removed soon.
+ */
+
+#include <net/checksum.h>
+
+unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum)
+{
+	int src_err=0, dst_err=0;
+
+	sum = csum_partial_copy_generic ( src, dst, len, sum, &src_err, &dst_err);
+
+	if (src_err || dst_err)
+		printk("old csum_partial_copy_fromuser(), tell mingo to convert me.\n");
+
+	return sum;
+}
+
+
diff -u --recursive --new-file v2.3.15/linux/arch/sh/lib/wordcopy.S linux/arch/sh/lib/wordcopy.S
--- v2.3.15/linux/arch/sh/lib/wordcopy.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/lib/wordcopy.S	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,1289 @@
+#include <linux/linkage.h>
+ENTRY(_wordcopy_fwd_aligned)
+	mov.l	r14,@-r15
+	add	#-20,r15
+	mov	r15,r14
+	mov.l	r4,@r14
+	mov.l	r5,@(4,r14)
+	mov.l	r6,@(8,r14)
+	mov.l	@(8,r14),r2
+	mov	#7,r1
+	and	r2,r1
+	mov	#0,r2
+	mov	#7,r3
+	sub	r2,r1
+	cmp/hi	r3,r1
+	bf	.L29
+	bra	.L2
+	nop
+.L29:
+	mova	.L22,r0
+	add	r1,r1
+	mov.w	@(r0,r1),r1
+	add	r0,r1
+	jmp  @r1
+	nop
+	.align 2
+	.align 2
+.L22:
+	.word	.L15-.L22
+	.word	.L18-.L22
+	.word	.L3-.L22
+	.word	.L5-.L22
+	.word	.L7-.L22
+	.word	.L9-.L22
+	.word	.L11-.L22
+	.word	.L13-.L22
+	.align 2
+.L3:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-24,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-28,r2
+	mov.l	r2,@r14
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#6,r2
+	mov.l	r2,@(8,r14)
+	bra	.L4
+	nop
+	.align 2
+.L5:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-20,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-24,r2
+	mov.l	r2,@r14
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#5,r2
+	mov.l	r2,@(8,r14)
+	bra	.L6
+	nop
+	.align 2
+.L7:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-16,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-20,r2
+	mov.l	r2,@r14
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#4,r2
+	mov.l	r2,@(8,r14)
+	bra	.L8
+	nop
+	.align 2
+.L9:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-12,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-16,r2
+	mov.l	r2,@r14
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#3,r2
+	mov.l	r2,@(8,r14)
+	bra	.L10
+	nop
+	.align 2
+.L11:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-8,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-12,r2
+	mov.l	r2,@r14
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#2,r2
+	mov.l	r2,@(8,r14)
+	bra	.L12
+	nop
+	.align 2
+.L13:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-4,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-8,r2
+	mov.l	r2,@r14
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#1,r2
+	mov.l	r2,@(8,r14)
+	bra	.L14
+	nop
+	.align 2
+.L15:
+	bra	.L16
+	nop
+	bra	.L1
+	nop
+	.align 2
+.L16:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-4,r2
+	mov.l	r2,@r14
+	bra	.L17
+	nop
+	.align 2
+.L18:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#4,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#-1,r2
+	mov.l	r2,@(8,r14)
+	bra	.L19
+	nop
+	bra	.L20
+	nop
+	.align 2
+.L19:
+	bra	.L21
+	nop
+	.align 2
+.L23:
+.L2:
+	nop
+.L24:
+.L21:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@r14,r1
+	mov.l	@(16,r14),r2
+	mov.l	r2,@r1
+.L17:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#4,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#4,r1
+	mov.l	@(12,r14),r2
+	mov.l	r2,@r1
+.L14:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#8,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#8,r1
+	mov.l	@(16,r14),r2
+	mov.l	r2,@r1
+.L12:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#12,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#12,r1
+	mov.l	@(12,r14),r2
+	mov.l	r2,@r1
+.L10:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#16,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#16,r1
+	mov.l	@(16,r14),r2
+	mov.l	r2,@r1
+.L8:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#20,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#20,r1
+	mov.l	@(12,r14),r2
+	mov.l	r2,@r1
+.L6:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#24,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#24,r1
+	mov.l	@(16,r14),r2
+	mov.l	r2,@r1
+.L4:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#28,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#28,r1
+	mov.l	@(12,r14),r2
+	mov.l	r2,@r1
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#32,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#32,r2
+	mov.l	r2,@r14
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#-8,r2
+	mov.l	r2,@(8,r14)
+.L26:
+	mov.l	@(8,r14),r1
+	tst	r1,r1
+	bf	.L27
+	bra	.L25
+	nop
+	.align 2
+.L27:
+	bra	.L21
+	nop
+	.align 2
+.L25:
+	nop
+.L20:
+	mov.l	@r14,r1
+	mov.l	@(16,r14),r2
+	mov.l	r2,@r1
+.L1:
+	add	#20,r14
+	mov	r14,r15
+	mov.l	@r15+,r14
+	rts	
+	nop
+.Lfe1:
+	.size	 __wordcopy_fwd_aligned,.Lfe1-__wordcopy_fwd_aligned
+	.global	___lshrsi3
+	.global	___ashlsi3
+	.align 2
+	.global	__wordcopy_fwd_dest_aligned
+	.type	 __wordcopy_fwd_dest_aligned,@function
+__wordcopy_fwd_dest_aligned:
+	mov.l	r8,@-r15
+	mov.l	r9,@-r15
+	mov.l	r14,@-r15
+	sts.l	pr,@-r15
+	add	#-40,r15
+	mov	r15,r14
+	mov.l	r4,@r14
+	mov.l	r5,@(4,r14)
+	mov.l	r6,@(8,r14)
+	mov.l	@(4,r14),r1
+	mov	#3,r2
+	and	r1,r2
+	mov	r2,r1
+	mov	r1,r2
+	shll2	r2
+	add	r2,r2
+	mov.l	r2,@(28,r14)
+	mov.l	@(28,r14),r2
+	neg	r2,r1
+	add	#32,r1
+	mov.l	r1,@(32,r14)
+	mov.l	@(4,r14),r1
+	mov	#-4,r2
+	and	r2,r1
+	mov.l	r1,@(4,r14)
+	mov.l	@(8,r14),r2
+	mov	#3,r1
+	and	r2,r1
+	mov	#0,r2
+	mov	#3,r3
+	sub	r2,r1
+	cmp/hi	r3,r1
+	bf	.L53
+	bra	.L31
+	nop
+.L53:
+	mova	.L43,r0
+	add	r1,r1
+	mov.w	@(r0,r1),r1
+	add	r0,r1
+	jmp  @r1
+	nop
+	.align 2
+	.align 2
+.L43:
+	.word	.L36-.L43
+	.word	.L39-.L43
+	.word	.L32-.L43
+	.word	.L34-.L43
+	.align 2
+.L32:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#4,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(20,r14)
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-4,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-12,r2
+	mov.l	r2,@r14
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#2,r2
+	mov.l	r2,@(8,r14)
+	bra	.L33
+	nop
+	.align 2
+.L34:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#4,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-8,r2
+	mov.l	r2,@r14
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#1,r2
+	mov.l	r2,@(8,r14)
+	bra	.L35
+	nop
+	.align 2
+.L36:
+	bra	.L37
+	nop
+	bra	.L30
+	nop
+	.align 2
+.L37:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(24,r14)
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#4,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#4,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-4,r2
+	mov.l	r2,@r14
+	bra	.L38
+	nop
+	.align 2
+.L39:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(20,r14)
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#4,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(24,r14)
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#8,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#-1,r2
+	mov.l	r2,@(8,r14)
+	bra	.L40
+	nop
+	bra	.L41
+	nop
+	.align 2
+.L40:
+	bra	.L42
+	nop
+	.align 2
+.L44:
+.L31:
+	nop
+.L45:
+.L42:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@r14,r8
+	mov.l	.L49,r1
+	mov.l	@(20,r14),r4
+	mov.l	@(28,r14),r5
+	jsr	@r1
+	nop
+	mov	r0,r9
+	mov.l	.L50,r1
+	mov.l	@(24,r14),r4
+	mov.l	@(32,r14),r5
+	jsr	@r1
+	nop
+	mov.l	r0,@(36,r14)
+	mov.l	@(36,r14),r1
+	or	r9,r1
+	mov.l	r1,@r8
+.L38:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#4,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@r14,r1
+	mov	r1,r8
+	add	#4,r8
+	mov.l	.L49,r1
+	mov.l	@(24,r14),r4
+	mov.l	@(28,r14),r5
+	jsr	@r1
+	nop
+	mov	r0,r9
+	mov.l	.L50,r1
+	mov.l	@(12,r14),r4
+	mov.l	@(32,r14),r5
+	jsr	@r1
+	nop
+	mov.l	r0,@(36,r14)
+	mov.l	@(36,r14),r1
+	or	r9,r1
+	mov.l	r1,@r8
+.L35:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#8,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(20,r14)
+	mov.l	@r14,r1
+	mov	r1,r8
+	add	#8,r8
+	mov.l	.L49,r1
+	mov.l	@(12,r14),r4
+	mov.l	@(28,r14),r5
+	jsr	@r1
+	nop
+	mov	r0,r9
+	mov.l	.L50,r1
+	mov.l	@(16,r14),r4
+	mov.l	@(32,r14),r5
+	jsr	@r1
+	nop
+	mov.l	r0,@(36,r14)
+	mov.l	@(36,r14),r1
+	or	r9,r1
+	mov.l	r1,@r8
+.L33:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#12,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(24,r14)
+	mov.l	@r14,r1
+	mov	r1,r8
+	add	#12,r8
+	mov.l	.L49,r1
+	mov.l	@(16,r14),r4
+	mov.l	@(28,r14),r5
+	jsr	@r1
+	nop
+	mov	r0,r9
+	mov.l	.L50,r1
+	mov.l	@(20,r14),r4
+	mov.l	@(32,r14),r5
+	jsr	@r1
+	nop
+	mov.l	r0,@(36,r14)
+	mov.l	@(36,r14),r1
+	or	r9,r1
+	mov.l	r1,@r8
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#16,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#16,r2
+	mov.l	r2,@r14
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#-4,r2
+	mov.l	r2,@(8,r14)
+.L47:
+	mov.l	@(8,r14),r1
+	tst	r1,r1
+	bf	.L48
+	bra	.L46
+	nop
+	.align 2
+.L48:
+	bra	.L42
+	nop
+	.align 2
+.L46:
+	nop
+.L41:
+	mov.l	@r14,r8
+	mov.l	.L49,r1
+	mov.l	@(20,r14),r4
+	mov.l	@(28,r14),r5
+	jsr	@r1
+	nop
+	mov	r0,r9
+	mov.l	.L50,r1
+	mov.l	@(24,r14),r4
+	mov.l	@(32,r14),r5
+	jsr	@r1
+	nop
+	mov.l	r0,@(36,r14)
+	mov.l	@(36,r14),r1
+	or	r9,r1
+	mov.l	r1,@r8
+.L30:
+	add	#40,r14
+	mov	r14,r15
+	lds.l	@r15+,pr
+	mov.l	@r15+,r14
+	mov.l	@r15+,r9
+	mov.l	@r15+,r8
+	rts	
+	nop
+.L51:
+	.align 2
+.L49:
+	.long	___lshrsi3
+.L50:
+	.long	___ashlsi3
+.Lfe2:
+	.size	 __wordcopy_fwd_dest_aligned,.Lfe2-__wordcopy_fwd_dest_aligned
+	.align 2
+	.global	__wordcopy_bwd_aligned
+	.type	 __wordcopy_bwd_aligned,@function
+__wordcopy_bwd_aligned:
+	mov.l	r14,@-r15
+	add	#-20,r15
+	mov	r15,r14
+	mov.l	r4,@r14
+	mov.l	r5,@(4,r14)
+	mov.l	r6,@(8,r14)
+	mov.l	@(8,r14),r2
+	mov	#7,r1
+	and	r2,r1
+	mov	#0,r2
+	mov	#7,r3
+	sub	r2,r1
+	cmp/hi	r3,r1
+	bf	.L82
+	bra	.L55
+	nop
+.L82:
+	mova	.L75,r0
+	add	r1,r1
+	mov.w	@(r0,r1),r1
+	add	r0,r1
+	jmp  @r1
+	nop
+	.align 2
+	.align 2
+.L75:
+	.word	.L68-.L75
+	.word	.L71-.L75
+	.word	.L56-.L75
+	.word	.L58-.L75
+	.word	.L60-.L75
+	.word	.L62-.L75
+	.word	.L64-.L75
+	.word	.L66-.L75
+	.align 2
+.L56:
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-8,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-4,r2
+	mov.l	r2,@r14
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#4,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#6,r2
+	mov.l	r2,@(8,r14)
+	bra	.L57
+	nop
+	.align 2
+.L58:
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-12,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-8,r2
+	mov.l	r2,@r14
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#8,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#5,r2
+	mov.l	r2,@(8,r14)
+	bra	.L59
+	nop
+	.align 2
+.L60:
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-16,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-12,r2
+	mov.l	r2,@r14
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#12,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#4,r2
+	mov.l	r2,@(8,r14)
+	bra	.L61
+	nop
+	.align 2
+.L62:
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-20,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-16,r2
+	mov.l	r2,@r14
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#16,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#3,r2
+	mov.l	r2,@(8,r14)
+	bra	.L63
+	nop
+	.align 2
+.L64:
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-24,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-20,r2
+	mov.l	r2,@r14
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#20,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#2,r2
+	mov.l	r2,@(8,r14)
+	bra	.L65
+	nop
+	.align 2
+.L66:
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-28,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-24,r2
+	mov.l	r2,@r14
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#24,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#1,r2
+	mov.l	r2,@(8,r14)
+	bra	.L67
+	nop
+	.align 2
+.L68:
+	bra	.L69
+	nop
+	bra	.L54
+	nop
+	.align 2
+.L69:
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-32,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-28,r2
+	mov.l	r2,@r14
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#28,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	bra	.L70
+	nop
+	.align 2
+.L71:
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-36,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-32,r2
+	mov.l	r2,@r14
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#32,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#-1,r2
+	mov.l	r2,@(8,r14)
+	bra	.L72
+	nop
+	bra	.L73
+	nop
+	.align 2
+.L72:
+	bra	.L74
+	nop
+	.align 2
+.L76:
+.L55:
+	nop
+.L77:
+.L74:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#28,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#28,r1
+	mov.l	@(16,r14),r2
+	mov.l	r2,@r1
+.L70:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#24,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#24,r1
+	mov.l	@(12,r14),r2
+	mov.l	r2,@r1
+.L67:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#20,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#20,r1
+	mov.l	@(16,r14),r2
+	mov.l	r2,@r1
+.L65:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#16,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#16,r1
+	mov.l	@(12,r14),r2
+	mov.l	r2,@r1
+.L63:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#12,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#12,r1
+	mov.l	@(16,r14),r2
+	mov.l	r2,@r1
+.L61:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#8,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#8,r1
+	mov.l	@(12,r14),r2
+	mov.l	r2,@r1
+.L59:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#4,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#4,r1
+	mov.l	@(16,r14),r2
+	mov.l	r2,@r1
+.L57:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@r14,r1
+	mov.l	@(12,r14),r2
+	mov.l	r2,@r1
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-32,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-32,r2
+	mov.l	r2,@r14
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#-8,r2
+	mov.l	r2,@(8,r14)
+.L79:
+	mov.l	@(8,r14),r1
+	tst	r1,r1
+	bf	.L80
+	bra	.L78
+	nop
+	.align 2
+.L80:
+	bra	.L74
+	nop
+	.align 2
+.L78:
+	nop
+.L73:
+	mov.l	@r14,r2
+	mov	r2,r1
+	add	#28,r1
+	mov.l	@(16,r14),r2
+	mov.l	r2,@r1
+.L54:
+	add	#20,r14
+	mov	r14,r15
+	mov.l	@r15+,r14
+	rts	
+	nop
+.Lfe3:
+	.size	 __wordcopy_bwd_aligned,.Lfe3-__wordcopy_bwd_aligned
+	.align 2
+	.global	__wordcopy_bwd_dest_aligned
+	.type	 __wordcopy_bwd_dest_aligned,@function
+__wordcopy_bwd_dest_aligned:
+	mov.l	r8,@-r15
+	mov.l	r9,@-r15
+	mov.l	r14,@-r15
+	sts.l	pr,@-r15
+	add	#-40,r15
+	mov	r15,r14
+	mov.l	r4,@r14
+	mov.l	r5,@(4,r14)
+	mov.l	r6,@(8,r14)
+	mov.l	@(4,r14),r1
+	mov	#3,r2
+	and	r1,r2
+	mov	r2,r1
+	mov	r1,r2
+	shll2	r2
+	add	r2,r2
+	mov.l	r2,@(28,r14)
+	mov.l	@(28,r14),r2
+	neg	r2,r1
+	add	#32,r1
+	mov.l	r1,@(32,r14)
+	mov.l	@(4,r14),r1
+	mov	#-4,r2
+	and	r2,r1
+	mov.l	r1,@(4,r14)
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#4,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@(8,r14),r2
+	mov	#3,r1
+	and	r2,r1
+	mov	#0,r2
+	mov	#3,r3
+	sub	r2,r1
+	cmp/hi	r3,r1
+	bf	.L106
+	bra	.L84
+	nop
+.L106:
+	mova	.L96,r0
+	add	r1,r1
+	mov.w	@(r0,r1),r1
+	add	r0,r1
+	jmp  @r1
+	nop
+	.align 2
+	.align 2
+.L96:
+	.word	.L89-.L96
+	.word	.L92-.L96
+	.word	.L85-.L96
+	.word	.L87-.L96
+	.align 2
+.L85:
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-12,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-4,r2
+	mov.l	r2,@r14
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#8,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(20,r14)
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#4,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#2,r2
+	mov.l	r2,@(8,r14)
+	bra	.L86
+	nop
+	.align 2
+.L87:
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-16,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-8,r2
+	mov.l	r2,@r14
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#12,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(24,r14)
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#8,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(20,r14)
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#1,r2
+	mov.l	r2,@(8,r14)
+	bra	.L88
+	nop
+	.align 2
+.L89:
+	bra	.L90
+	nop
+	bra	.L83
+	nop
+	.align 2
+.L90:
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-20,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-12,r2
+	mov.l	r2,@r14
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#16,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#12,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(24,r14)
+	bra	.L91
+	nop
+	.align 2
+.L92:
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-24,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-16,r2
+	mov.l	r2,@r14
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#20,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#16,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#-1,r2
+	mov.l	r2,@(8,r14)
+	bra	.L93
+	nop
+	bra	.L94
+	nop
+	.align 2
+.L93:
+	bra	.L95
+	nop
+	.align 2
+.L97:
+.L84:
+	nop
+.L98:
+.L95:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#12,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(24,r14)
+	mov.l	@r14,r1
+	mov	r1,r8
+	add	#12,r8
+	mov.l	.L102,r1
+	mov.l	@(12,r14),r4
+	mov.l	@(28,r14),r5
+	jsr	@r1
+	nop
+	mov	r0,r9
+	mov.l	.L103,r1
+	mov.l	@(16,r14),r4
+	mov.l	@(32,r14),r5
+	jsr	@r1
+	nop
+	mov.l	r0,@(36,r14)
+	mov.l	@(36,r14),r1
+	or	r9,r1
+	mov.l	r1,@r8
+.L91:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#8,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(20,r14)
+	mov.l	@r14,r1
+	mov	r1,r8
+	add	#8,r8
+	mov.l	.L102,r1
+	mov.l	@(24,r14),r4
+	mov.l	@(28,r14),r5
+	jsr	@r1
+	nop
+	mov	r0,r9
+	mov.l	.L103,r1
+	mov.l	@(12,r14),r4
+	mov.l	@(32,r14),r5
+	jsr	@r1
+	nop
+	mov.l	r0,@(36,r14)
+	mov.l	@(36,r14),r1
+	or	r9,r1
+	mov.l	r1,@r8
+.L88:
+	mov.l	@(4,r14),r2
+	mov	r2,r1
+	add	#4,r1
+	mov.l	@r1,r2
+	mov.l	r2,@(16,r14)
+	mov.l	@r14,r1
+	mov	r1,r8
+	add	#4,r8
+	mov.l	.L102,r1
+	mov.l	@(20,r14),r4
+	mov.l	@(28,r14),r5
+	jsr	@r1
+	nop
+	mov	r0,r9
+	mov.l	.L103,r1
+	mov.l	@(24,r14),r4
+	mov.l	@(32,r14),r5
+	jsr	@r1
+	nop
+	mov.l	r0,@(36,r14)
+	mov.l	@(36,r14),r1
+	or	r9,r1
+	mov.l	r1,@r8
+.L86:
+	mov.l	@(4,r14),r1
+	mov.l	@r1,r2
+	mov.l	r2,@(12,r14)
+	mov.l	@r14,r8
+	mov.l	.L102,r1
+	mov.l	@(16,r14),r4
+	mov.l	@(28,r14),r5
+	jsr	@r1
+	nop
+	mov	r0,r9
+	mov.l	.L103,r1
+	mov.l	@(20,r14),r4
+	mov.l	@(32,r14),r5
+	jsr	@r1
+	nop
+	mov.l	r0,@(36,r14)
+	mov.l	@(36,r14),r1
+	or	r9,r1
+	mov.l	r1,@r8
+	mov.l	@(4,r14),r1
+	mov	r1,r2
+	add	#-16,r2
+	mov.l	r2,@(4,r14)
+	mov.l	@r14,r1
+	mov	r1,r2
+	add	#-16,r2
+	mov.l	r2,@r14
+	mov.l	@(8,r14),r1
+	mov	r1,r2
+	add	#-4,r2
+	mov.l	r2,@(8,r14)
+.L100:
+	mov.l	@(8,r14),r1
+	tst	r1,r1
+	bf	.L101
+	bra	.L99
+	nop
+	.align 2
+.L101:
+	bra	.L95
+	nop
+	.align 2
+.L99:
+	nop
+.L94:
+	mov.l	@r14,r1
+	mov	r1,r8
+	add	#12,r8
+	mov.l	.L102,r1
+	mov.l	@(12,r14),r4
+	mov.l	@(28,r14),r5
+	jsr	@r1
+	nop
+	mov	r0,r9
+	mov.l	.L103,r1
+	mov.l	@(16,r14),r4
+	mov.l	@(32,r14),r5
+	jsr	@r1
+	nop
+	mov.l	r0,@(36,r14)
+	mov.l	@(36,r14),r1
+	or	r9,r1
+	mov.l	r1,@r8
+.L83:
+	add	#40,r14
+	mov	r14,r15
+	lds.l	@r15+,pr
+	mov.l	@r15+,r14
+	mov.l	@r15+,r9
+	mov.l	@r15+,r8
+	rts	
+	nop
+.L104:
+	.align 2
+.L102:
+	.long	___lshrsi3
+.L103:
+	.long	___ashlsi3
+.Lfe4:
diff -u --recursive --new-file v2.3.15/linux/arch/sh/mm/Makefile linux/arch/sh/mm/Makefile
--- v2.3.15/linux/arch/sh/mm/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/mm/Makefile	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,13 @@
+#
+# Makefile for the Linux SuperH-specific parts of the memory manager.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := mm.o
+O_OBJS	 := init.o fault.o ioremap.o extable.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.15/linux/arch/sh/mm/extable.c linux/arch/sh/mm/extable.c
--- v2.3.15/linux/arch/sh/mm/extable.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/mm/extable.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,57 @@
+/*
+ * linux/arch/sh/mm/extable.c
+ *  Taken from:
+ *   linux/arch/i386/mm/extable.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+extern const struct exception_table_entry __start___ex_table[];
+extern const struct exception_table_entry __stop___ex_table[];
+
+static inline unsigned long
+search_one_table(const struct exception_table_entry *first,
+		 const struct exception_table_entry *last,
+		 unsigned long value)
+{
+        while (first <= last) {
+		const struct exception_table_entry *mid;
+		long diff;
+
+		mid = (last - first) / 2 + first;
+		diff = mid->insn - value;
+                if (diff == 0)
+                        return mid->fixup;
+                else if (diff < 0)
+                        first = mid+1;
+                else
+                        last = mid-1;
+        }
+        return 0;
+}
+
+unsigned long
+search_exception_table(unsigned long addr)
+{
+	unsigned long ret;
+
+#ifndef CONFIG_MODULES
+	/* There is only the kernel to search.  */
+	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
+	if (ret) return ret;
+#else
+	/* The kernel is the last "module" -- no need to treat it special.  */
+	struct module *mp;
+	for (mp = module_list; mp != NULL; mp = mp->next) {
+		if (mp->ex_table_start == NULL)
+			continue;
+		ret = search_one_table(mp->ex_table_start,
+				       mp->ex_table_end - 1, addr);
+		if (ret) return ret;
+	}
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/mm/fault.c linux/arch/sh/mm/fault.c
--- v2.3.15/linux/arch/sh/mm/fault.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/mm/fault.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,327 @@
+/*
+ *  linux/arch/sh/mm/fault.c
+ *  Copyright (C) 1999  Niibe Yutaka
+ *
+ *  Based on linux/arch/i386/mm/fault.c:
+ *   Copyright (C) 1995  Linus Torvalds
+ */
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/hardirq.h>
+#include <asm/uaccess.h>	/* to get __m() macro */
+#include <asm/mmu_context.h>
+
+extern void die(const char *,struct pt_regs *,long);
+
+/*
+ * Ugly, ugly, but the goto's result in better assembly..
+ */
+int __verify_write(const void * addr, unsigned long size)
+{
+	struct vm_area_struct * vma;
+	unsigned long start = (unsigned long) addr;
+
+	if (!size)
+		return 1;
+
+	vma = find_vma(current->mm, start);
+	if (!vma)
+		goto bad_area;
+	if (vma->vm_start > start)
+		goto check_stack;
+
+good_area:
+	if (!(vma->vm_flags & VM_WRITE))
+		goto bad_area;
+	size--;
+	size += start & ~PAGE_MASK;
+	size >>= PAGE_SHIFT;
+	start &= PAGE_MASK;
+
+	for (;;) {
+		if (handle_mm_fault(current, vma, start, 1) <= 0)
+			goto bad_area;
+		if (!size)
+			break;
+		size--;
+		start += PAGE_SIZE;
+		if (start < vma->vm_end)
+			continue;
+		vma = vma->vm_next;
+		if (!vma || vma->vm_start != start)
+			goto bad_area;
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;;
+	}
+	return 1;
+
+check_stack:
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+	if (expand_stack(vma, start) == 0)
+		goto good_area;
+
+bad_area:
+	return 0;
+}
+
+/*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ */
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
+			      unsigned long address)
+{
+	struct task_struct *tsk;
+	struct mm_struct *mm;
+	struct vm_area_struct * vma;
+	unsigned long page;
+	unsigned long fixup;
+
+	tsk = current;
+	mm = tsk->mm;
+
+	/*
+	 * If we're in an interrupt or have no user
+	 * context, we must not take the fault..
+	 */
+	if (in_interrupt() || !mm)
+		goto no_context;
+
+	down(&mm->mmap_sem);
+
+	vma = find_vma(mm, address);
+	if (!vma)
+		goto bad_area;
+	if (vma->vm_start <= address)
+		goto good_area;
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+	if (expand_stack(vma, address))
+		goto bad_area;
+/*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+	if (writeaccess) {
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;
+	} else {
+		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+			goto bad_area;
+	}
+
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+	{
+		int fault = handle_mm_fault(tsk, vma, address, writeaccess);
+		if (fault < 0)
+			goto out_of_memory;
+		if (!fault)
+			goto do_sigbus;
+	}
+
+	up(&mm->mmap_sem);
+	return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+	up(&mm->mmap_sem);
+
+	if (user_mode(regs)) {
+		tsk->thread.address = address;
+		tsk->thread.error_code = writeaccess;
+		force_sig(SIGSEGV, tsk);
+		return;
+	}
+
+no_context:
+	/* Are we prepared to handle this kernel fault?  */
+	fixup = search_exception_table(regs->pc);
+	if (fixup != 0) {
+		regs->pc = fixup;
+		return;
+	}
+
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ *
+ */
+	if (address < PAGE_SIZE)
+		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+	else
+		printk(KERN_ALERT "Unable to handle kernel paging request");
+	printk(" at virtual address %08lx\n",address);
+	printk(KERN_ALERT "pc = %08lx\n", regs->pc);
+	page = (unsigned long)mm->pgd;
+	page = ((unsigned long *) __va(page))[address >> 22];
+	printk(KERN_ALERT "*pde = %08lx\n", page);
+	if (page & 1) {
+		page &= PAGE_MASK;
+		address &= 0x003ff000;
+		page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
+		printk(KERN_ALERT "*pte = %08lx\n", page);
+	}
+	die("Oops", regs, writeaccess);
+	do_exit(SIGKILL);
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+	up(&mm->mmap_sem);
+	printk("VM: killing process %s\n", tsk->comm);
+	if (user_mode(regs))
+		do_exit(SIGKILL);
+	goto no_context;
+
+do_sigbus:
+	up(&mm->mmap_sem);
+
+	/*
+	 * Send a sigbus, regardless of whether we were in kernel
+	 * or user mode.
+	 */
+	tsk->thread.address = address;
+	tsk->thread.error_code = writeaccess;
+	tsk->thread.trap_no = 14;
+	force_sig(SIGBUS, tsk);
+
+	/* Kernel mode? Handle exceptions or die */
+	if (!user_mode(regs))
+		goto no_context;
+}
+
+void update_mmu_cache(struct vm_area_struct * vma,
+		      unsigned long address, pte_t pte)
+{
+	unsigned long flags;
+	unsigned long asid;
+	unsigned long pteval;
+
+	asid = get_asid();
+
+	save_and_cli(flags);
+	address &= PAGE_MASK;
+	/* Set PTEH register */
+	asm volatile ("mov.l	%0,%1"
+		      : /* no output */
+		      : "r" (address | asid), "m" (__m(MMU_PTEH)));
+
+	pteval = pte_val(pte);
+	pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
+	pteval |= _PAGE_FLAGS_HARDWARE_DEFAULT; /* add default flags */
+	/* Set PTEL register */
+	asm volatile ("mov.l	%0,%1"
+		      : /* no output */
+		      : "r" (pteval), "m" (__m(MMU_PTEL)));
+
+	/* Load the TLB */
+	asm volatile ("ldtlb" : /* no output */ : /* no input */
+		      : "memory");
+	restore_flags(flags);
+}
+
+static __inline__ void __flush_tlb_page(unsigned long asid, unsigned long page)
+{
+	unsigned long addr, data;
+
+	addr = MMU_TLB_ADDRESS_ARRAY | (page & 0x1F000) | MMU_PAGE_ASSOC_BIT;
+	data = page | asid; /* VALID bit is off */
+	__asm__ __volatile__ ("mov.l	%0,%1"
+			      : /* no output */
+			      : "r" (data), "m" (__m(addr)));
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	unsigned long asid;
+
+	if (vma->vm_mm->context != NO_CONTEXT) {
+		page &= PAGE_MASK;
+		asid = vma->vm_mm->context & MMU_CONTEXT_ASID_MASK;
+		__flush_tlb_page (asid, page);
+	}
+}
+
+void flush_tlb_range(struct mm_struct *mm, unsigned long start,
+		     unsigned long end)
+{
+	if (mm->context != NO_CONTEXT) {
+		unsigned long flags;
+		int size;
+
+		save_and_cli(flags);
+		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+		if (size > (MMU_NTLB_ENTRIES/4)) { /* So many TLB to flush */
+			get_new_mmu_context(mm);
+			if (mm == current->mm)
+				set_asid(mm->context & MMU_CONTEXT_ASID_MASK);
+		} else {
+			unsigned long asid;
+
+			asid = mm->context & MMU_CONTEXT_ASID_MASK;
+			start &= PAGE_MASK;
+			end += (PAGE_SIZE - 1);
+			end &= PAGE_MASK;
+			while (start < end) {
+				__flush_tlb_page (asid, start);
+				start += PAGE_SIZE;
+			}
+		}
+		restore_flags(flags);
+	}
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+	/* Invalidate all TLB of this process. */
+	/* Instead of flush TLBs, we get new MMU context. */
+	if (mm->context != NO_CONTEXT) {
+		unsigned long flags;
+
+		save_and_cli(flags);
+		get_new_mmu_context(mm);
+		if (mm == current->mm)
+			set_asid(mm->context & MMU_CONTEXT_ASID_MASK);
+		restore_flags(flags);
+	}
+}
+
+void flush_tlb_all(void)
+{
+	unsigned long flags, __dummy;
+
+	save_and_cli(flags);
+	asm volatile("mov.l	%1,%0\n\t"
+		     "or	#4,%0\n\t" /* Set TF-bit to flush */
+		     "mov.l	%0,%1"
+		     : "=&z" (__dummy)
+		     : "m" (__m(MMUCR)));
+	restore_flags(flags);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/mm/init.c linux/arch/sh/mm/init.c
--- v2.3.15/linux/arch/sh/mm/init.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/mm/init.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,294 @@
+/*
+ *  linux/arch/sh/mm/init.c
+ *
+ *  Copyright (C) 1999  Niibe Yutaka
+ *
+ *  Based on linux/arch/i386/mm/init.c:
+ *   Copyright (C) 1995  Linus Torvalds
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/blk.h>
+#endif
+
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+
+/*
+ * Cache of MMU context last used.
+ */
+unsigned long mmu_context_cache;
+
+static unsigned long totalram = 0;
+
+extern void show_net_buffers(void);
+extern unsigned long init_smp_mappings(unsigned long);
+
+void __bad_pte_kernel(pmd_t *pmd)
+{
+	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+	pmd_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE);
+}
+
+void __bad_pte(pmd_t *pmd)
+{
+	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+	pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
+}
+
+pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
+{
+	pte_t *pte;
+
+	pte = (pte_t *) __get_free_page(GFP_KERNEL);
+	if (pmd_none(*pmd)) {
+		if (pte) {
+			clear_page((unsigned long)pte);
+			pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte);
+			return pte + offset;
+		}
+		pmd_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE);
+		return NULL;
+	}
+	free_page((unsigned long)pte);
+	if (pmd_bad(*pmd)) {
+		__bad_pte_kernel(pmd);
+		return NULL;
+	}
+	return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
+{
+	unsigned long pte;
+
+	pte = (unsigned long) __get_free_page(GFP_KERNEL);
+	if (pmd_none(*pmd)) {
+		if (pte) {
+			clear_page(pte);
+			pmd_val(*pmd) = _PAGE_TABLE + __pa(pte);
+			return (pte_t *)(pte + offset);
+		}
+		pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
+		return NULL;
+	}
+	free_page(pte);
+	if (pmd_bad(*pmd)) {
+		__bad_pte(pmd);
+		return NULL;
+	}
+	return (pte_t *) (pmd_page(*pmd) + offset);
+}
+
+int do_check_pgt_cache(int low, int high)
+{
+	int freed = 0;
+	if(pgtable_cache_size > high) {
+		do {
+			if(pgd_quicklist)
+				free_pgd_slow(get_pgd_fast()), freed++;
+			if(pmd_quicklist)
+				free_pmd_slow(get_pmd_fast()), freed++;
+			if(pte_quicklist)
+				free_pte_slow(get_pte_fast()), freed++;
+		} while(pgtable_cache_size > low);
+	}
+	return freed;
+}
+
+/*
+ * BAD_PAGE is the page that is used for page faults when linux
+ * is out-of-memory. Older versions of linux just did a
+ * do_exit(), but using this instead means there is less risk
+ * for a process dying in kernel mode, possibly leaving an inode
+ * unused etc..
+ *
+ * BAD_PAGETABLE is the accompanying page-table: it is initialized
+ * to point to BAD_PAGE entries.
+ *
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+pte_t * __bad_pagetable(void)
+{
+	extern char empty_bad_page_table[PAGE_SIZE];
+	unsigned long page = (unsigned long)empty_bad_page_table;
+
+	clear_page(page);
+	return (pte_t *)empty_bad_page_table;
+}
+
+pte_t __bad_page(void)
+{
+	extern char empty_bad_page[PAGE_SIZE];
+	unsigned long page = (unsigned long)empty_bad_page;
+
+	clear_page(page);
+	return pte_mkdirty(mk_pte(page, PAGE_SHARED));
+}
+
+void show_mem(void)
+{
+	int i,free = 0,total = 0,reserved = 0;
+	int shared = 0, cached = 0;
+
+	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 (!page_count(mem_map+i))
+			free++;
+		else
+			shared += page_count(mem_map+i) - 1;
+	}
+	printk("%d pages of RAM\n",total);
+	printk("%d reserved pages\n",reserved);
+	printk("%d pages shared\n",shared);
+	printk("%d pages swap cached\n",cached);
+	printk("%ld pages in page table cache\n",pgtable_cache_size);
+#ifdef CONFIG_NET
+	show_net_buffers();
+#endif
+}
+
+extern unsigned long free_area_init(unsigned long, unsigned long);
+
+/* References to section boundaries */
+
+extern char _text, _etext, _edata, __bss_start, _end;
+extern char __init_begin, __init_end;
+
+pgd_t swapper_pg_dir[1024];
+
+/*
+ * paging_init() sets up the page tables
+ *
+ * This routines also unmaps the page at virtual kernel address 0, so
+ * that we can trap those pesky NULL-reference errors in the kernel.
+ */
+unsigned long __init
+paging_init(unsigned long start_mem, unsigned long end_mem)
+{
+	pgd_t * pg_dir;
+
+	start_mem = PAGE_ALIGN(start_mem);
+
+	/* We don't need kernel mapping as hardware support that. */
+	pg_dir = swapper_pg_dir;
+
+	/* Unmap the original low memory mappings to detect NULL reference */
+	pgd_val(pg_dir[0]) = 0;
+
+	/* Enable MMU */
+	__asm__ __volatile__ ("mov.l	%0,%1"
+			      : /* no output */
+			      : "r" (MMU_CONTROL_INIT), "m" (__m(MMUCR)));
+
+	return free_area_init(start_mem, end_mem);
+}
+
+unsigned long empty_bad_page[1024];
+unsigned long empty_bad_page_table[1024];
+unsigned long empty_zero_page[1024];
+
+void __init mem_init(unsigned long start_mem, unsigned long end_mem)
+{
+	int codepages = 0;
+	int reservedpages = 0;
+	int datapages = 0;
+	int initpages = 0;
+	unsigned long tmp;
+
+	end_mem &= PAGE_MASK;
+	high_memory = (void *) end_mem;
+	max_mapnr = num_physpages = MAP_NR(end_mem);
+
+	/* clear the zero-page */
+	memset(empty_zero_page, 0, PAGE_SIZE);
+
+	/* Mark (clear "reserved" bit) usable pages in the mem_map[] */
+	/*    Note that all are marked reserved already. */
+	tmp = start_mem = PAGE_ALIGN(start_mem);
+	while (tmp < end_mem) {
+		clear_bit(PG_reserved, &mem_map[MAP_NR(tmp)].flags);
+		clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
+		tmp += PAGE_SIZE;
+	}
+
+	for (tmp = PAGE_OFFSET; tmp < end_mem; tmp += PAGE_SIZE) {
+		if (PageReserved(mem_map+MAP_NR(tmp))) {
+			if (tmp >= (unsigned long) &_text && tmp < (unsigned long) &_edata) {
+				if (tmp < (unsigned long) &_etext)
+					codepages++;
+				else
+					datapages++;
+			} else if (tmp >= (unsigned long) &__init_begin
+				   && tmp < (unsigned long) &__init_end)
+				initpages++;
+			else if (tmp >= (unsigned long) &__bss_start
+				 && tmp < (unsigned long) start_mem)
+				datapages++;
+			else
+				reservedpages++;
+			continue;
+		}
+		set_page_count(mem_map+MAP_NR(tmp), 1);
+		totalram += PAGE_SIZE;
+#ifdef CONFIG_BLK_DEV_INITRD
+		if (!initrd_start || (tmp < initrd_start || tmp >= initrd_end))
+#endif
+			free_page(tmp);
+	}
+	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+		(unsigned long) nr_free_pages << (PAGE_SHIFT-10),
+		max_mapnr << (PAGE_SHIFT-10),
+		codepages << (PAGE_SHIFT-10),
+		reservedpages << (PAGE_SHIFT-10),
+		datapages << (PAGE_SHIFT-10),
+		initpages << (PAGE_SHIFT-10));
+}
+
+void free_initmem(void)
+{
+	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);
+		set_page_count(mem_map+MAP_NR(addr), 1);
+		free_page(addr);
+		totalram += PAGE_SIZE;
+	}
+	printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
+}
+
+void si_meminfo(struct sysinfo *val)
+{
+	val->totalram = totalram;
+	val->sharedram = 0;
+	val->freeram = nr_free_pages << PAGE_SHIFT;
+	val->bufferram = atomic_read(&buffermem);
+	return;
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/mm/ioremap.c linux/arch/sh/mm/ioremap.c
--- v2.3.15/linux/arch/sh/mm/ioremap.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/mm/ioremap.c	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,140 @@
+/*
+ * arch/sh/mm/ioremap.c
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ * This is needed for high PCI addresses that aren't mapped in the
+ * 640k-1MB IO memory area on PC's
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ */
+
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+
+static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+	unsigned long phys_addr, unsigned long flags)
+{
+	unsigned long end;
+
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	do {
+		if (!pte_none(*pte))
+			printk("remap_area_pte: page already exists\n");
+		set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | _PAGE_RW | 
+					_PAGE_DIRTY | _PAGE_ACCESSED | flags)));
+		address += PAGE_SIZE;
+		phys_addr += PAGE_SIZE;
+		pte++;
+	} while (address < end);
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
+	unsigned long phys_addr, unsigned long flags)
+{
+	unsigned long end;
+
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	phys_addr -= address;
+	do {
+		pte_t * pte = pte_alloc_kernel(pmd, address);
+		if (!pte)
+			return -ENOMEM;
+		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address < end);
+	return 0;
+}
+
+static int remap_area_pages(unsigned long address, unsigned long phys_addr,
+				 unsigned long size, unsigned long flags)
+{
+	pgd_t * dir;
+	unsigned long end = address + size;
+
+	phys_addr -= address;
+	dir = pgd_offset(&init_mm, address);
+	flush_cache_all();
+	while (address < end) {
+		pmd_t *pmd = pmd_alloc_kernel(dir, address);
+		if (!pmd)
+			return -ENOMEM;
+		if (remap_area_pmd(pmd, address, end - address,
+					 phys_addr + address, flags))
+			return -ENOMEM;
+		set_pgdir(address, *dir);
+		address = (address + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
+	}
+	flush_tlb_all();
+	return 0;
+}
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+	void * addr;
+	struct vm_struct * area;
+	unsigned long offset, last_addr;
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr)
+		return NULL;
+
+	/*
+	 * Don't remap the low PCI/ISA area, it's always mapped..
+	 */
+	if (phys_addr >= 0xA0000 && last_addr <= 0x100000)
+		return phys_to_virt(phys_addr);
+
+	/*
+	 * Don't allow anybody to remap normal RAM that we're using..
+	 */
+	if (phys_addr < virt_to_phys(high_memory))
+		return NULL;
+
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(last_addr) - phys_addr;
+
+	/*
+	 * Ok, go for it..
+	 */
+	area = get_vm_area(size);
+	if (!area)
+		return NULL;
+	addr = area->addr;
+	if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+		vfree(addr);
+		return NULL;
+	}
+	return (void *) (offset + (char *)addr);
+}
+
+void iounmap(void *addr)
+{
+	if (addr > high_memory)
+		return vfree((void *) (PAGE_MASK & (unsigned long) addr));
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sh/vmlinux.lds.S linux/arch/sh/vmlinux.lds.S
--- v2.3.15/linux/arch/sh/vmlinux.lds.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/vmlinux.lds.S	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,113 @@
+/* ld script to make SuperH Linux kernel
+ * Written by Niibe Yutaka
+ */
+#ifdef CONFIG_LITTLE_ENDIAN
+OUTPUT_FORMAT("elf32-shl", "elf32-shl", "elf32-shl")
+#else
+OUTPUT_FORMAT("elf32-sh", "elf32-sh", "elf32-sh")
+#endif
+OUTPUT_ARCH(sh)
+ENTRY(_start)
+SECTIONS
+{
+  . = 0x80000000 + CONFIG_MEMORY_START + 0x1000;
+  __text = .;			/* Text and read-only data */
+  _text = .;			/* Text and read-only data */
+  .text : {
+	*(.text)
+	*(.fixup)
+	*(.gnu.warning)
+	} = 0
+  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
+  .rodata : { *(.rodata) }
+  .kstrtab : { *(.kstrtab) }
+
+  . = ALIGN(16);		/* Exception table */
+  ___start___ex_table = .;
+  ___ex_table : { *(__ex_table) }
+  ___stop___ex_table = .;
+
+  ___start___ksymtab = .;	/* Kernel symbol table */
+  ___ksymtab : { *(__ksymtab) }
+  ___stop___ksymtab = .;
+
+  __etext = .;			/* End of text section */
+
+  .data : {			/* Data */
+	*(.data)
+	CONSTRUCTORS
+	}
+
+  __edata = .;			/* End of data section */
+
+  . = ALIGN(8192);		/* init_task */
+  .data.init_task : { *(.data.init_task) }
+  /* stack */
+  .stack : { _stack = .;  __stack = .; }
+
+  . = ALIGN(4096);		/* Init code and data */
+  ___init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(16);
+  ___setup_start = .;
+  .setup.init : { *(.setup.init) }
+  ___setup_end = .;
+  ___initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  ___initcall_end = .;
+  . = ALIGN(4096);
+  ___init_end = .;
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  . = ALIGN(4096);
+  .data.disk_image : { *(.data.disk_image) }
+
+  . = ALIGN(4);
+  ___bss_start = .;		/* BSS */
+  .bss : {
+	*(.bss)
+	}
+  . = ALIGN(4);
+  __end = . ;
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging section are relative to the beginning
+     of the section so we begin .debug at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* These must appear regardless of  .  */
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/Makefile linux/arch/sparc/Makefile
--- v2.3.15/linux/arch/sparc/Makefile	Wed Jun  9 14:44:25 1999
+++ linux/arch/sparc/Makefile	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.41 1999/06/04 13:29:05 jj Exp $
+# $Id: Makefile,v 1.44 1999/08/19 06:22:20 jj Exp $
 # sparc/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -15,7 +15,7 @@
 # Uncomment the first CFLAGS if you are doing kgdb source level
 # debugging of the kernel to get the proper debugging information.
 
-IS_EGCS := $(shell if $(CC) -c -m32 -o _tmp.o arch/sparc/math-emu/fnegs.c >/dev/null 2>&1; then echo y; else echo n; fi; rm -f _tmp.o)
+IS_EGCS := $(shell if $(CC) -m32 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
 NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
 
 ifeq ($(NEW_GAS),y)
@@ -62,10 +62,8 @@
 	-$(MAKE) -C arch/sparc/boot clean
 
 archmrproper:
-	-$(MAKE) -C arch/sparc/math-emu cleansymlinks
 
 archdep:
-	-$(MAKE) -C arch/sparc/math-emu symlinks
 
 check_asm:
 	$(MAKE) -C arch/sparc/kernel check_asm
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/ap1000/apmmu.c linux/arch/sparc/ap1000/apmmu.c
--- v2.3.15/linux/arch/sparc/ap1000/apmmu.c	Fri Jul 23 12:20:23 1999
+++ linux/arch/sparc/ap1000/apmmu.c	Tue Aug 31 11:23:29 1999
@@ -527,7 +527,7 @@
 {
 	printk("Kernel faults at addr=0x%08lx\n", address);
 	printk("PTE=%08lx\n", apmmu_hwprobe((address & PAGE_MASK)));
-	die_if_kernel("APMMU bolixed...", current->tss.kregs);
+	die_if_kernel("APMMU bolixed...", current->thread.kregs);
 }
 
 static inline void alloc_context(struct task_struct *tsk)
@@ -775,7 +775,7 @@
 	return (pte_t *) apmmu_early_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (APMMU_PTRS_PER_PTE - 1));
 }
 
-__initfunc(static inline void apmmu_allocate_ptable_skeleton(unsigned long start, unsigned long end))
+static inline void __init apmmu_allocate_ptable_skeleton(unsigned long start, unsigned long end)
 {
 	pgd_t *pgdp;
 	pmd_t *pmdp;
@@ -797,7 +797,7 @@
 }
 
 
-__initfunc(static void make_page(unsigned virt_page, unsigned phys_page, unsigned prot))
+static void __init make_page(unsigned virt_page, unsigned phys_page, unsigned prot)
 {
 	pgd_t *pgdp;
 	pmd_t *pmdp;
@@ -819,7 +819,7 @@
 }
 
 
-__initfunc(static void make_large_page(unsigned virt_page, unsigned phys_page, unsigned prot))
+static void __init make_large_page(unsigned virt_page, unsigned phys_page, unsigned prot)
 {
 	pgd_t *pgdp;
 	unsigned start = virt_page<<12;
@@ -829,7 +829,7 @@
 }
 
 
-__initfunc(static void ap_setup_mappings(void))
+static void __init ap_setup_mappings(void)
 {
 	unsigned Srwe = APMMU_PRIV | APMMU_VALID;
 	unsigned SrweUr = 0x14 | APMMU_VALID; /* weird! */
@@ -897,7 +897,7 @@
 	make_page(MSC_REMREPLY_DIRECT_END>>PAGE_SHIFT, 0xa0c004,Srwe);
 }
 
-__initfunc(static void map_kernel(void))
+static void __init map_kernel(void)
 {
 	int phys;
 
@@ -917,7 +917,7 @@
 extern int physmem_mapped_contig;
 extern int linux_num_cpus;
 
-__initfunc(unsigned long apmmu_paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init apmmu_paging_init(unsigned long start_mem, unsigned long end_mem)
 {
 	int i;
 
@@ -979,7 +979,7 @@
 {
 }
 
-__initfunc(static void poke_viking(void))
+static void __init poke_viking(void)
 {
 	unsigned long mreg = apmmu_get_mmureg();
 
@@ -991,7 +991,7 @@
 	apmmu_set_mmureg(mreg);
 }
 
-__initfunc(static void init_viking(void))
+static void __init init_viking(void)
 {
 	apmmu_name = "TI Viking/AP1000";
 
@@ -1024,7 +1024,7 @@
 		*iaddr = SPARC_BRANCH((unsigned long) daddr, (unsigned long) iaddr); \
 	} while(0);
 
-__initfunc(static void patch_window_trap_handlers(void))
+static void __init patch_window_trap_handlers(void)
 {
 	unsigned long *iaddr, *daddr;
 	
@@ -1038,7 +1038,7 @@
 }
 
 /* Load up routines and constants for apmmu */
-__initfunc(void ld_mmu_apmmu(void))
+void __init ld_mmu_apmmu(void)
 {
 	/* First the constants */
 	BTFIXUPSET_SIMM13(pmd_shift, APMMU_PMD_SHIFT);
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/ap1000/msc.c linux/arch/sparc/ap1000/msc.c
--- v2.3.15/linux/arch/sparc/ap1000/msc.c	Tue Aug  4 16:03:34 1998
+++ linux/arch/sparc/ap1000/msc.c	Tue Aug 31 11:23:29 1999
@@ -623,8 +623,8 @@
 		if (vaddr - MSC_REM_SIGNAL < _NSIG*PAGE_SIZE) {
 			handle_signal(context,vaddr);
 		} else {
-			task[tsk]->tss.sig_address = vaddr;
-			task[tsk]->tss.sig_desc = SUBSIG_NOMAPPING;
+			task[tsk]->thread.sig_address = vaddr;
+			task[tsk]->thread.sig_desc = SUBSIG_NOMAPPING;
 			send_sig(SIGSEGV, task[tsk], 1);
 		}
 	}
@@ -650,8 +650,8 @@
 		if (vaddr - MSC_REM_SIGNAL < _NSIG*PAGE_SIZE) {
 			handle_signal(context,vaddr);
 		} else {
-			task[tsk]->tss.sig_address = vaddr;
-			task[tsk]->tss.sig_desc = SUBSIG_NOMAPPING;
+			task[tsk]->thread.sig_address = vaddr;
+			task[tsk]->thread.sig_desc = SUBSIG_NOMAPPING;
 			send_sig(SIGSEGV, task[tsk], 1);
 		}
 	}	
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.3.15/linux/arch/sparc/config.in	Thu Aug 26 13:05:34 1999
+++ linux/arch/sparc/config.in	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.69 1999/06/25 11:00:20 davem Exp $
+# $Id: config.in,v 1.73 1999/08/31 10:09:01 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -50,6 +50,7 @@
 	# Global things across all Sun machines.
 	define_bool CONFIG_SBUS y
 	define_bool CONFIG_SBUSCHAR y
+	define_bool CONFIG_BUSMOUSE y
 	define_bool CONFIG_SUN_MOUSE y
 	define_bool CONFIG_SERIAL y
 	define_bool CONFIG_SUN_SERIAL y
@@ -72,6 +73,8 @@
 tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
 tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+source drivers/parport/Config.in
+dep_tristate '  Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
 endmenu
 
 mainmenu_option next_comment
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.3.15/linux/arch/sparc/defconfig	Fri Jun 25 01:05:12 1999
+++ linux/arch/sparc/defconfig	Tue Aug 31 11:23:29 1999
@@ -46,6 +46,7 @@
 # CONFIG_FBCON_FONTS is not set
 CONFIG_SBUS=y
 CONFIG_SBUSCHAR=y
+CONFIG_MOUSE=y
 CONFIG_SUN_MOUSE=y
 CONFIG_SERIAL=y
 CONFIG_SUN_SERIAL=y
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile
--- v2.3.15/linux/arch/sparc/kernel/Makefile	Wed Mar 10 16:53:36 1999
+++ linux/arch/sparc/kernel/Makefile	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.49 1999/01/02 16:45:37 davem Exp $
+# $Id: Makefile,v 1.50 1999/08/31 13:26:13 anton Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -22,7 +22,7 @@
 	    sys_sparc.o sunos_asm.o sparc-stub.o systbls.o sys_sunos.o  \
 	    sunos_ioctl.o time.o windows.o cpu.o devices.o \
 	    sclow.o solaris.o tadpole.o tick14.o ptrace.o sys_solaris.o \
-	    unaligned.o muldiv.o pcic.o
+	    unaligned.o muldiv.o pcic.o semaphore.o
 
 OX_OBJS  := sparc_ksyms.o
 
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/auxio.c linux/arch/sparc/kernel/auxio.c
--- v2.3.15/linux/arch/sparc/kernel/auxio.c	Sun Oct  4 10:22:42 1998
+++ linux/arch/sparc/kernel/auxio.c	Thu Aug 26 12:42:32 1999
@@ -13,7 +13,7 @@
 /* Probe and map in the Auxiliary I/O register */
 unsigned char *auxio_register;
 
-__initfunc(void auxio_probe(void))
+void __init auxio_probe(void)
 {
 	int node, auxio_nd;
 	struct linux_prom_registers auxregs[1];
@@ -68,7 +68,7 @@
 
 volatile unsigned char * auxio_power_register = NULL;
 
-__initfunc(void auxio_power_probe(void))
+void __init auxio_power_probe(void)
 {
 	struct linux_prom_registers regs;
 	int node;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/cpu.c linux/arch/sparc/kernel/cpu.c
--- v2.3.15/linux/arch/sparc/kernel/cpu.c	Tue Apr 14 17:44:18 1998
+++ linux/arch/sparc/kernel/cpu.c	Tue Aug 31 11:23:29 1999
@@ -7,7 +7,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/smp.h>
-#include <linux/tasks.h>
+#include <linux/threads.h>
 #include <asm/oplib.h>
 #include <asm/page.h>
 #include <asm/head.h>
@@ -123,7 +123,7 @@
 
 unsigned int fsr_storage;
 
-__initfunc(void cpu_probe(void))
+void __init cpu_probe(void)
 {
 	int psr_impl, psr_vers, fpu_vers;
 	int i, cpuid, psr;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/devices.c linux/arch/sparc/kernel/devices.c
--- v2.3.15/linux/arch/sparc/kernel/devices.c	Wed Mar 10 16:53:36 1999
+++ linux/arch/sparc/kernel/devices.c	Tue Aug 31 11:23:29 1999
@@ -5,7 +5,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/tasks.h>
+#include <linux/threads.h>
 #include <linux/config.h>
 #include <linux/init.h>
 
@@ -21,8 +21,8 @@
 extern void clock_stop_probe(void); /* tadpole.c */
 extern void sun4c_probe_memerr_reg(void);
 
-__initfunc(unsigned long
-device_scan(unsigned long mem_start))
+unsigned long __init
+device_scan(unsigned long mem_start)
 {
 	char node_str[128];
 	int thismid;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/ebus.c linux/arch/sparc/kernel/ebus.c
--- v2.3.15/linux/arch/sparc/kernel/ebus.c	Wed Jun  9 14:44:25 1999
+++ linux/arch/sparc/kernel/ebus.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.3 1999/06/03 15:02:09 davem Exp $
+/* $Id: ebus.c,v 1.4 1999/08/31 06:54:19 davem Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -57,8 +57,8 @@
 	return (unsigned long)kmalloc(size, GFP_ATOMIC);
 }
 
-__initfunc(void fill_ebus_child(int node, struct linux_prom_registers *preg,
-				struct linux_ebus_child *dev))
+void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
+				struct linux_ebus_child *dev)
 {
 	int regs[PROMREG_MAX];
 	int irqs[PROMREG_MAX];
@@ -128,7 +128,7 @@
 #endif
 }
 
-__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev))
+void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
 {
 	struct linux_prom_registers regs[PROMREG_MAX];
 	struct linux_ebus_child *child;
@@ -255,7 +255,7 @@
 	}
 }
 
-__initfunc(void ebus_init(void))
+void __init ebus_init(void)
 {
 	struct linux_prom_pci_registers regs[PROMREG_MAX];
 	struct linux_pbm_info *pbm;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S
--- v2.3.15/linux/arch/sparc/kernel/entry.S	Wed Jun  9 14:44:25 1999
+++ linux/arch/sparc/kernel/entry.S	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.160 1999/06/03 15:02:11 davem Exp $
+/* $Id: entry.S,v 1.161 1999/08/14 03:51:05 anton Exp $
  * arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1397,7 +1397,7 @@
 	rd	%wim, %g5
 	WRITE_PAUSE
 	mov	%fp, %o1			! arg1:	usp
-	std	%g4, [%curptr + AOFF_task_tss + AOFF_thread_fork_kpsr]
+	std	%g4, [%curptr + AOFF_task_thread + AOFF_thread_fork_kpsr]
 	add	%sp, REGWIN_SZ, %o2		! arg2:	pt_regs ptr
 	call	C_LABEL(do_fork)
 	 mov	%l5, %o7
@@ -1419,7 +1419,7 @@
 	 mov	%fp, %o1			! yes, use callers usp
 	andn	%o1, 7, %o1			! no, align to 8 bytes
 1:
-	std	%g4, [%curptr + AOFF_task_tss + AOFF_thread_fork_kpsr]
+	std	%g4, [%curptr + AOFF_task_thread + AOFF_thread_fork_kpsr]
 	add	%sp, REGWIN_SZ, %o2		! arg2:	pt_regs ptr
 	call	C_LABEL(do_fork)
 	 mov	%l5, %o7
@@ -1433,7 +1433,7 @@
 	WRITE_PAUSE
 	rd	%wim, %g5
 	WRITE_PAUSE
-	std	%g4, [%curptr + AOFF_task_tss + AOFF_thread_fork_kpsr]
+	std	%g4, [%curptr + AOFF_task_thread + AOFF_thread_fork_kpsr]
 	sethi	%hi(0x4000 | 0x0100 | SIGCHLD), %o0
 	mov	%fp, %o1
 	or	%o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
@@ -1854,7 +1854,7 @@
 	 * traps with the old method of just doing flush_user_windows().
 	 */
 C_LABEL(kill_user_windows):
-	ld	[%g6 + AOFF_task_tss + AOFF_thread_uwinmask], %o0	! get current umask
+	ld	[%g6 + AOFF_task_thread + AOFF_thread_uwinmask], %o0	! get current umask
 	orcc	%g0, %o0, %g0			! if no bits set, we are done
 	be	3f				! nothing to do
 	 rd	%psr, %o5			! must clear interrupts
@@ -1862,7 +1862,7 @@
 	wr	%o4, 0x0, %psr			! the uwinmask state
 	WRITE_PAUSE				! burn them cycles
 1:
-	ld	[%g6 + AOFF_task_tss + AOFF_thread_uwinmask], %o0	! get consistant state
+	ld	[%g6 + AOFF_task_thread + AOFF_thread_uwinmask], %o0	! get consistant state
 	orcc	%g0, %o0, %g0			! did an interrupt come in?
 	be	4f				! yep, we are done
 	 rd	%wim, %o3			! get current wim
@@ -1874,13 +1874,13 @@
 	bne	kuw_patch1			! not done yet
 	 srl	%o3, 1, %o4			! begin another save simulation
 	wr	%o3, 0x0, %wim			! set the new wim
-	st	%g0, [%g6 + AOFF_task_tss + AOFF_thread_uwinmask]	! clear uwinmask
+	st	%g0, [%g6 + AOFF_task_thread + AOFF_thread_uwinmask]	! clear uwinmask
 4:
 	wr	%o5, 0x0, %psr			! re-enable interrupts
 	WRITE_PAUSE				! burn baby burn
 3:
 	retl					! return
-	 st	%g0, [%g6 + AOFF_task_tss + AOFF_thread_w_saved]	! no windows saved
+	 st	%g0, [%g6 + AOFF_task_thread + AOFF_thread_w_saved]	! no windows saved
 
 	.align	4
 	.globl	C_LABEL(restore_current)
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/etrap.S linux/arch/sparc/kernel/etrap.S
--- v2.3.15/linux/arch/sparc/kernel/etrap.S	Tue Apr 14 17:44:18 1998
+++ linux/arch/sparc/kernel/etrap.S	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: etrap.S,v 1.29 1998/02/09 13:48:40 jj Exp $
+/* $Id: etrap.S,v 1.30 1999/08/14 03:51:08 anton Exp $
  * etrap.S: Sparc trap window preparation for entry into the
  *          Linux kernel.
  *
@@ -101,7 +101,7 @@
 	 mov	%t_kstack, %sp		! jump onto new stack
 
 trap_setup_kernel_spill:
-	ld	[%curptr + AOFF_task_tss + AOFF_thread_uwinmask], %g1
+	ld	[%curptr + AOFF_task_thread + AOFF_thread_uwinmask], %g1
 	orcc	%g0, %g1, %g0
 	bne	trap_setup_user_spill	! there are some user windows, yuck
 	/* Spill from kernel, but only kernel windows, adjust
@@ -153,8 +153,8 @@
 	and	%t_kstack, %curptr, %curptr
 #endif
 
-	/* Clear current->tss.w_saved */
-	st	%g0, [%curptr + AOFF_task_tss + AOFF_thread_w_saved]
+	/* Clear current->thread.w_saved */
+	st	%g0, [%curptr + AOFF_task_thread + AOFF_thread_w_saved]
 
 	/* See if we are in the trap window. */
 	andcc	%t_twinmask, %t_wim, %g0
@@ -185,7 +185,7 @@
 	andn	%g2, %t_twinmask, %g2
 tsetup_patch3:
 	and	%g2, 0xff, %g2			! patched on 7win Sparcs
-	st	%g2, [%curptr + AOFF_task_tss + AOFF_thread_uwinmask]	! store new umask
+	st	%g2, [%curptr + AOFF_task_thread + AOFF_thread_uwinmask]	! store new umask
 
 	jmpl	%t_retpc + 0x8, %g0		! return to caller
 	 mov	%t_kstack, %sp			! and onto kernel stack
@@ -206,7 +206,7 @@
 tsetup_patch6:
 	and	%g2, 0xff, %g2		! patched on 7win Sparcs
 	andn	%g1, %g2, %g1		! clear this bit in %g1
-	st	%g1, [%curptr + AOFF_task_tss + AOFF_thread_uwinmask]
+	st	%g1, [%curptr + AOFF_task_thread + AOFF_thread_uwinmask]
 
 	save	%g0, %g0, %g0
 
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S
--- v2.3.15/linux/arch/sparc/kernel/head.S	Wed Jun  9 14:44:25 1999
+++ linux/arch/sparc/kernel/head.S	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.96 1999/06/03 15:02:15 davem Exp $
+/* $Id: head.S,v 1.97 1999/08/14 03:51:10 anton Exp $
  * head.S: The initial boot code for the Sparc port of Linux.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1037,7 +1037,7 @@
 #endif
 		st	%g6, [%g2]
 
-		st	%g0, [%g6 + AOFF_task_tss + AOFF_thread_uwinmask]
+		st	%g0, [%g6 + AOFF_task_thread + AOFF_thread_uwinmask]
 
 /* Compute NWINDOWS and stash it away. Now uses %wim trick explained
  * in the V8 manual. Ok, this method seems to work, Sparc is cool...
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/idprom.c linux/arch/sparc/kernel/idprom.c
--- v2.3.15/linux/arch/sparc/kernel/idprom.c	Tue Aug  4 16:03:34 1998
+++ linux/arch/sparc/kernel/idprom.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: idprom.c,v 1.23 1998/07/28 16:52:44 jj Exp $
+/* $Id: idprom.c,v 1.24 1999/08/31 06:54:20 davem Exp $
  * idprom.c: Routines to load the idprom into kernel addresses and
  *           interpret the data contained within.
  *
@@ -46,7 +46,7 @@
 /* One entry for the OBP arch's which are sun4d, sun4e, and newer sun4m's */
 { "Sun4M OBP based system", (SM_SUN4M_OBP | 0x0) } };
 
-__initfunc(static void display_system_type(unsigned char machtype))
+static void __init display_system_type(unsigned char machtype)
 {
 	char sysname[128];
 	register int i;
@@ -69,7 +69,7 @@
 }
 
 /* Calculate the IDPROM checksum (xor of the data bytes). */
-__initfunc(static unsigned char calc_idprom_cksum(struct idprom *idprom))
+static unsigned char __init calc_idprom_cksum(struct idprom *idprom)
 {
 	unsigned char cksum, i, *ptr = (unsigned char *)idprom;
 
@@ -80,7 +80,7 @@
 }
 
 /* Create a local IDPROM copy, verify integrity, and display information. */
-__initfunc(void idprom_init(void))
+void __init idprom_init(void)
 {
 	prom_get_idprom((char *) &idprom_buffer, sizeof(idprom_buffer));
 
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- v2.3.15/linux/arch/sparc/kernel/irq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/kernel/irq.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/*  $Id: irq.c,v 1.94 1999/05/28 14:59:20 anton Exp $
+/*  $Id: irq.c,v 1.96 1999/08/31 06:54:21 davem Exp $
  *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
  *                            Sparc the IRQ's are basically 'cast in stone'
  *                            and you are supposed to probe the prom's device
@@ -25,7 +25,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/delay.h>
-#include <linux/tasks.h>
+#include <linux/threads.h>
 
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -711,7 +711,7 @@
  *
  */
 
-__initfunc(void init_IRQ(void))
+void __init init_IRQ(void)
 {
 	extern void sun4c_init_IRQ( void );
 	extern void sun4m_init_IRQ( void );
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/pcic.c linux/arch/sparc/kernel/pcic.c
--- v2.3.15/linux/arch/sparc/kernel/pcic.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc/kernel/pcic.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: pcic.c,v 1.7 1999/07/23 01:56:07 davem Exp $
+/* $Id: pcic.c,v 1.8 1999/08/31 06:54:22 davem Exp $
  * pcic.c: Sparc/PCI controller support
  *
  * Copyright (C) 1998 V. Roganov and G. Raiko
@@ -167,7 +167,7 @@
 static void pci_do_gettimeofday(struct timeval *tv);
 static void pci_do_settimeofday(struct timeval *tv);
 
-__initfunc(void pcic_probe(void))
+void __init pcic_probe(void)
 {
 	struct linux_prom_registers regs[PROMREG_MAX];
 	struct linux_pbm_info* pbm;
@@ -274,7 +274,7 @@
 	}
 }
 
-__initfunc(void pcibios_init(void))
+void __init pcibios_init(void)
 {
 	/*
 	 * PCIC should be initialized at start of the timer.
@@ -309,8 +309,8 @@
 	return pcic != NULL;
 }
 
-__initfunc(static int pdev_to_pnode(struct linux_pbm_info *pbm, 
-				    struct pci_dev *pdev))
+static int __init pdev_to_pnode(struct linux_pbm_info *pbm, 
+				    struct pci_dev *pdev)
 {
 	struct linux_prom_pci_registers regs[PROMREG_MAX];
 	int err;
@@ -506,7 +506,7 @@
 /*
  * Stolen from both i386 and sparc64 branch 
  */
-__initfunc(void pcibios_fixup(void))
+void __init pcibios_fixup(void)
 {
   struct pci_dev *dev;
   int i, has_io, has_mem;
@@ -611,7 +611,7 @@
 #define USECS_PER_JIFFY  10000  /* We have 100HZ "standard" timer for sparc */
 #define TICK_TIMER_LIMIT ((100*1000000/4)/100)
 
-__initfunc(void pci_time_init(void))
+void __init pci_time_init(void)
 {
 	unsigned long v;
 	int timer_irq, irq;
@@ -802,7 +802,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-__initfunc(char *pcibios_setup(char *str))
+char * __init pcibios_setup(char *str)
 {
 	return str;
 }
@@ -973,7 +973,7 @@
 	writel(get_irqmask(pil), pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR);
 }
 
-__initfunc(void sun4m_pci_init_IRQ(void))
+void __init sun4m_pci_init_IRQ(void)
 {
 	BTFIXUPSET_CALL(enable_irq, pcic_enable_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(disable_irq, pcic_disable_irq, BTFIXUPCALL_NORM);
@@ -985,7 +985,7 @@
 	BTFIXUPSET_CALL(__irq_itoa, pcic_irq_itoa, BTFIXUPCALL_NORM);
 }
 
-__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
 }
 
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v2.3.15/linux/arch/sparc/kernel/process.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc/kernel/process.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.138 1999/07/23 01:56:10 davem Exp $
+/*  $Id: process.c,v 1.139 1999/08/14 03:51:14 anton Exp $
  *  linux/arch/sparc/kernel/process.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -51,7 +51,7 @@
 /*
  * the idle loop on a Sparc... ;)
  */
-asmlinkage int sys_idle(void)
+int cpu_idle(void)
 {
 	int ret = -EPERM;
 
@@ -107,7 +107,7 @@
 #else
 
 /* This is being executed in task 0 'user space'. */
-int cpu_idle(void *unused)
+int cpu_idle(void)
 {
 	/* endless idle loop with no priority at all */
 	current->priority = 0;
@@ -123,15 +123,6 @@
 	}
 }
 
-asmlinkage int sys_idle(void)
-{
-	if(current->pid != 0)
-		return -EPERM;
-
-	cpu_idle(NULL);
-	return 0;
-}
-
 #endif
 
 extern char reboot_command [];
@@ -299,33 +290,33 @@
 }
 
 #if NOTUSED
-void show_thread(struct thread_struct *tss)
+void show_thread(struct thread_struct *thread)
 {
 	int i;
 
-	printk("uwinmask:          0x%08lx  kregs:             0x%08lx\n", tss->uwinmask, (unsigned long)tss->kregs);
-	show_regs(tss->kregs);
-	printk("sig_address:       0x%08lx  sig_desc:          0x%08lx\n", tss->sig_address, tss->sig_desc);
-	printk("ksp:               0x%08lx  kpc:               0x%08lx\n", tss->ksp, tss->kpc);
-	printk("kpsr:              0x%08lx  kwim:              0x%08lx\n", tss->kpsr, tss->kwim);
-	printk("fork_kpsr:         0x%08lx  fork_kwim:         0x%08lx\n", tss->fork_kpsr, tss->fork_kwim);
+	printk("uwinmask:          0x%08lx  kregs:             0x%08lx\n", thread->uwinmask, (unsigned long)thread->kregs);
+	show_regs(thread->kregs);
+	printk("sig_address:       0x%08lx  sig_desc:          0x%08lx\n", thread->sig_address, thread->sig_desc);
+	printk("ksp:               0x%08lx  kpc:               0x%08lx\n", thread->ksp, thread->kpc);
+	printk("kpsr:              0x%08lx  kwim:              0x%08lx\n", thread->kpsr, thread->kwim);
+	printk("fork_kpsr:         0x%08lx  fork_kwim:         0x%08lx\n", thread->fork_kpsr, thread->fork_kwim);
 
 	for (i = 0; i < NSWINS; i++) {
-		if (!tss->rwbuf_stkptrs[i])
+		if (!thread->rwbuf_stkptrs[i])
 			continue;
 		printk("reg_window[%d]:\n", i);
-		printk("stack ptr:         0x%08lx\n", tss->rwbuf_stkptrs[i]);
-		show_regwindow(&tss->reg_window[i]);
+		printk("stack ptr:         0x%08lx\n", thread->rwbuf_stkptrs[i]);
+		show_regwindow(&thread->reg_window[i]);
 	}
-	printk("w_saved:           0x%08lx\n", tss->w_saved);
+	printk("w_saved:           0x%08lx\n", thread->w_saved);
 
 	/* XXX missing: float_regs */
-	printk("fsr:               0x%08lx  fpqdepth:          0x%08lx\n", tss->fsr, tss->fpqdepth);
+	printk("fsr:               0x%08lx  fpqdepth:          0x%08lx\n", thread->fsr, thread->fpqdepth);
 	/* XXX missing: fpqueue */
 
-	printk("flags:             0x%08lx  current_ds:        0x%08lx\n", tss->flags, tss->current_ds.seg);
+	printk("flags:             0x%08lx  current_ds:        0x%08lx\n", thread->flags, thread->current_ds.seg);
 	
-	show_regwindow((struct reg_window *)tss->ksp);
+	show_regwindow((struct reg_window *)thread->ksp);
 
 	/* XXX missing: core_exec */
 }
@@ -343,8 +334,8 @@
 #endif
 		/* Keep process from leaving FPU in a bogon state. */
 		put_psr(get_psr() | PSR_EF);
-		fpsave(&current->tss.float_regs[0], &current->tss.fsr,
-		       &current->tss.fpqueue[0], &current->tss.fpqdepth);
+		fpsave(&current->thread.float_regs[0], &current->thread.fsr,
+		       &current->thread.fpqueue[0], &current->thread.fpqdepth);
 #ifndef __SMP__
 		last_task_used_math = NULL;
 #else
@@ -355,10 +346,10 @@
 
 void flush_thread(void)
 {
-	current->tss.w_saved = 0;
+	current->thread.w_saved = 0;
 
 	/* No new signal delivery by default */
-	current->tss.new_signal = 0;
+	current->thread.new_signal = 0;
 #ifndef __SMP__
 	if(last_task_used_math == current) {
 #else
@@ -366,8 +357,8 @@
 #endif
 		/* Clean the fpu. */
 		put_psr(get_psr() | PSR_EF);
-		fpsave(&current->tss.float_regs[0], &current->tss.fsr,
-		       &current->tss.fpqueue[0], &current->tss.fpqdepth);
+		fpsave(&current->thread.float_regs[0], &current->thread.fsr,
+		       &current->thread.fpqueue[0], &current->thread.fpqdepth);
 #ifndef __SMP__
 		last_task_used_math = NULL;
 #else
@@ -376,24 +367,15 @@
 	}
 
 	/* Now, this task is no longer a kernel thread. */
-	current->tss.current_ds = USER_DS;
-	if (current->tss.flags & SPARC_FLAG_KTHREAD) {
-		current->tss.flags &= ~SPARC_FLAG_KTHREAD;
+	current->thread.current_ds = USER_DS;
+	if (current->thread.flags & SPARC_FLAG_KTHREAD) {
+		current->thread.flags &= ~SPARC_FLAG_KTHREAD;
 
 		/* We must fixup kregs as well. */
-		current->tss.kregs = (struct pt_regs *)
+		current->thread.kregs = (struct pt_regs *)
 			(((unsigned long)current) +
 			 (TASK_UNION_SIZE - TRACEREG_SZ));
 	}
-
-	/* Exec'ing out of a vfork() shared address space is
-	 * tricky on sparc32.  exec_mmap will not set the mmu
-	 * context because it sets the new current->mm after
-	 * calling init_new_context and activate_context is
-	 * a nop on sparc32, so we gotta catch it here.  And
-	 * clone()'s had the same problem.  -DaveM
-	 */
-	switch_to_context(current);
 }
 
 static __inline__ void copy_regs(struct pt_regs *dst, struct pt_regs *src)
@@ -457,12 +439,10 @@
 	 * temporarily so we can build the child clone stack frame
 	 * without deadlocking.
 	 */
-	up(&current->mm->mmap_sem);
 	if (copy_to_user(sp, src, size))
 		sp = (struct sparc_stackf *) 0;
 	else if (put_user(dst, &sp->fp))
 		sp = (struct sparc_stackf *) 0;
-	down(&current->mm->mmap_sem);
 
 	return sp;
 }
@@ -499,8 +479,8 @@
 	if(current->flags & PF_USEDFPU) {
 #endif
 		put_psr(get_psr() | PSR_EF);
-		fpsave(&p->tss.float_regs[0], &p->tss.fsr,
-		       &p->tss.fpqueue[0], &p->tss.fpqdepth);
+		fpsave(&p->thread.float_regs[0], &p->thread.fsr,
+		       &p->thread.fpqueue[0], &p->thread.fpqdepth);
 #ifdef __SMP__
 		current->flags &= ~PF_USEDFPU;
 #endif
@@ -516,36 +496,36 @@
 	new_stack = (((struct reg_window *) childregs) - 1);
 	copy_regwin(new_stack, (((struct reg_window *) regs) - 1));
 
-	p->tss.ksp = (unsigned long) new_stack;
+	p->thread.ksp = (unsigned long) new_stack;
 #ifdef __SMP__
-	p->tss.kpc = (((unsigned long) ret_from_smpfork) - 0x8);
-	p->tss.kpsr = current->tss.fork_kpsr | PSR_PIL;
+	p->thread.kpc = (((unsigned long) ret_from_smpfork) - 0x8);
+	p->thread.kpsr = current->thread.fork_kpsr | PSR_PIL;
 #else
-	p->tss.kpc = (((unsigned long) ret_from_syscall) - 0x8);
-	p->tss.kpsr = current->tss.fork_kpsr;
+	p->thread.kpc = (((unsigned long) ret_from_syscall) - 0x8);
+	p->thread.kpsr = current->thread.fork_kpsr;
 #endif
-	p->tss.kwim = current->tss.fork_kwim;
+	p->thread.kwim = current->thread.fork_kwim;
 
 	if(regs->psr & PSR_PS) {
 		extern struct pt_regs fake_swapper_regs;
 
-		p->tss.kregs = &fake_swapper_regs;
+		p->thread.kregs = &fake_swapper_regs;
 		new_stack = (struct reg_window *)
 			((((unsigned long)p) +
 			  (TASK_UNION_SIZE)) -
 			 (REGWIN_SZ));
 		childregs->u_regs[UREG_FP] = (unsigned long) new_stack;
-		p->tss.flags |= SPARC_FLAG_KTHREAD;
-		p->tss.current_ds = KERNEL_DS;
+		p->thread.flags |= SPARC_FLAG_KTHREAD;
+		p->thread.current_ds = KERNEL_DS;
 		memcpy((void *)new_stack,
 		       (void *)regs->u_regs[UREG_FP],
 		       sizeof(struct reg_window));
 		childregs->u_regs[UREG_G6] = (unsigned long) p;
 	} else {
-		p->tss.kregs = childregs;
+		p->thread.kregs = childregs;
 		childregs->u_regs[UREG_FP] = sp;
-		p->tss.flags &= ~SPARC_FLAG_KTHREAD;
-		p->tss.current_ds = USER_DS;
+		p->thread.flags &= ~SPARC_FLAG_KTHREAD;
+		p->thread.current_ds = USER_DS;
 
 		if (sp != regs->u_regs[UREG_FP]) {
 			struct sparc_stackf *childstack;
@@ -601,7 +581,7 @@
 	dump->regs.y = regs->y;
 	/* fuck me plenty */
 	memcpy(&dump->regs.regs[0], &regs->u_regs[1], (sizeof(unsigned long) * 15));
-	dump->uexec = current->tss.core_exec;
+	dump->uexec = current->thread.core_exec;
 	dump->u_tsize = (((unsigned long) current->mm->end_code) -
 		((unsigned long) current->mm->start_code)) & ~(PAGE_SIZE - 1);
 	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1)));
@@ -609,13 +589,13 @@
 	dump->u_dsize &= ~(PAGE_SIZE - 1);
 	first_stack_page = (regs->u_regs[UREG_FP] & ~(PAGE_SIZE - 1));
 	dump->u_ssize = (TASK_SIZE - first_stack_page) & ~(PAGE_SIZE - 1);
-	memcpy(&dump->fpu.fpstatus.fregs.regs[0], &current->tss.float_regs[0], (sizeof(unsigned long) * 32));
-	dump->fpu.fpstatus.fsr = current->tss.fsr;
+	memcpy(&dump->fpu.fpstatus.fregs.regs[0], &current->thread.float_regs[0], (sizeof(unsigned long) * 32));
+	dump->fpu.fpstatus.fsr = current->thread.fsr;
 	dump->fpu.fpstatus.flags = dump->fpu.fpstatus.extra = 0;
-	dump->fpu.fpstatus.fpq_count = current->tss.fpqdepth;
-	memcpy(&dump->fpu.fpstatus.fpq[0], &current->tss.fpqueue[0],
+	dump->fpu.fpstatus.fpq_count = current->thread.fpqdepth;
+	memcpy(&dump->fpu.fpstatus.fpq[0], &current->thread.fpqueue[0],
 	       ((sizeof(unsigned long) * 2) * 16));
-	dump->sigcode = current->tss.sig_desc;
+	dump->sigcode = current->thread.sig_desc;
 }
 
 /*
@@ -631,30 +611,30 @@
 #ifdef __SMP__
 	if (current->flags & PF_USEDFPU) {
 		put_psr(get_psr() | PSR_EF);
-		fpsave(&current->tss.float_regs[0], &current->tss.fsr,
-		       &current->tss.fpqueue[0], &current->tss.fpqdepth);
+		fpsave(&current->thread.float_regs[0], &current->thread.fsr,
+		       &current->thread.fpqueue[0], &current->thread.fpqdepth);
 		regs->psr &= ~(PSR_EF);
 		current->flags &= ~(PF_USEDFPU);
 	}
 #else
 	if (current == last_task_used_math) {
 		put_psr(get_psr() | PSR_EF);
-		fpsave(&current->tss.float_regs[0], &current->tss.fsr,
-		       &current->tss.fpqueue[0], &current->tss.fpqdepth);
+		fpsave(&current->thread.float_regs[0], &current->thread.fsr,
+		       &current->thread.fpqueue[0], &current->thread.fpqdepth);
 		last_task_used_math = 0;
 		regs->psr &= ~(PSR_EF);
 	}
 #endif
 	memcpy(&fpregs->pr_fr.pr_regs[0],
-	       &current->tss.float_regs[0],
+	       &current->thread.float_regs[0],
 	       (sizeof(unsigned long) * 32));
-	fpregs->pr_fsr = current->tss.fsr;
-	fpregs->pr_qcnt = current->tss.fpqdepth;
+	fpregs->pr_fsr = current->thread.fsr;
+	fpregs->pr_qcnt = current->thread.fpqdepth;
 	fpregs->pr_q_entrysize = 8;
 	fpregs->pr_en = 1;
 	if(fpregs->pr_qcnt != 0) {
 		memcpy(&fpregs->pr_q[0],
-		       &current->tss.fpqueue[0],
+		       &current->thread.fpqueue[0],
 		       sizeof(struct fpq) * fpregs->pr_qcnt);
 	}
 	/* Zero out the rest. */
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c
--- v2.3.15/linux/arch/sparc/kernel/ptrace.c	Mon Jul  5 11:30:11 1999
+++ linux/arch/sparc/kernel/ptrace.c	Tue Aug 31 11:23:29 1999
@@ -70,8 +70,8 @@
 static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset,
 				   struct task_struct *tsk, long *addr)
 {
-	struct pt_regs *cregs = tsk->tss.kregs;
-	struct thread_struct *t = &tsk->tss;
+	struct pt_regs *cregs = tsk->thread.kregs;
+	struct thread_struct *t = &tsk->thread;
 	int v;
 	
 	if(offset >= 1024)
@@ -128,7 +128,7 @@
 		v = cregs->u_regs[UREG_I6];
 		break;
 	case 924:
-		if(tsk->tss.flags & MAGIC_CONSTANT)
+		if(tsk->thread.flags & MAGIC_CONSTANT)
 			v = cregs->u_regs[UREG_G1];
 		else
 			v = 0;
@@ -165,8 +165,8 @@
 static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset,
 				    struct task_struct *tsk)
 {
-	struct pt_regs *cregs = tsk->tss.kregs;
-	struct thread_struct *t = &tsk->tss;
+	struct pt_regs *cregs = tsk->thread.kregs;
+	struct thread_struct *t = &tsk->thread;
 	unsigned long value = regs->u_regs[UREG_I3];
 
 	if(offset >= 1024)
@@ -398,7 +398,7 @@
 
 	case PTRACE_GETREGS: {
 		struct pt_regs *pregs = (struct pt_regs *) addr;
-		struct pt_regs *cregs = child->tss.kregs;
+		struct pt_regs *cregs = child->thread.kregs;
 		int rval;
 
 		rval = verify_area(VERIFY_WRITE, pregs, sizeof(struct pt_regs));
@@ -421,7 +421,7 @@
 
 	case PTRACE_SETREGS: {
 		struct pt_regs *pregs = (struct pt_regs *) addr;
-		struct pt_regs *cregs = child->tss.kregs;
+		struct pt_regs *cregs = child->thread.kregs;
 		unsigned long psr, pc, npc, y;
 		int i;
 
@@ -471,15 +471,15 @@
 			goto out;
 		}
 		for(i = 0; i < 32; i++)
-			__put_user(child->tss.float_regs[i], (&fps->regs[i]));
-		__put_user(child->tss.fsr, (&fps->fsr));
-		__put_user(child->tss.fpqdepth, (&fps->fpqd));
+			__put_user(child->thread.float_regs[i], (&fps->regs[i]));
+		__put_user(child->thread.fsr, (&fps->fsr));
+		__put_user(child->thread.fpqdepth, (&fps->fpqd));
 		__put_user(0, (&fps->flags));
 		__put_user(0, (&fps->extra));
 		for(i = 0; i < 16; i++) {
-			__put_user(child->tss.fpqueue[i].insn_addr,
+			__put_user(child->thread.fpqueue[i].insn_addr,
 				   (&fps->fpq[i].insnaddr));
-			__put_user(child->tss.fpqueue[i].insn, (&fps->fpq[i].insn));
+			__put_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn));
 		}
 		pt_succ_return(regs, 0);
 		goto out;
@@ -504,13 +504,13 @@
 			pt_error_return(regs, -i);
 			goto out;
 		}
-		copy_from_user(&child->tss.float_regs[0], &fps->regs[0], (32 * sizeof(unsigned long)));
-		__get_user(child->tss.fsr, (&fps->fsr));
-		__get_user(child->tss.fpqdepth, (&fps->fpqd));
+		copy_from_user(&child->thread.float_regs[0], &fps->regs[0], (32 * sizeof(unsigned long)));
+		__get_user(child->thread.fsr, (&fps->fsr));
+		__get_user(child->thread.fpqdepth, (&fps->fpqd));
 		for(i = 0; i < 16; i++) {
-			__get_user(child->tss.fpqueue[i].insn_addr,
+			__get_user(child->thread.fpqueue[i].insn_addr,
 				   (&fps->fpq[i].insnaddr));
-			__get_user(child->tss.fpqueue[i].insn, (&fps->fpq[i].insn));
+			__get_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn));
 		}
 		pt_succ_return(regs, 0);
 		goto out;
@@ -560,11 +560,11 @@
 				goto out;
 			}
 #ifdef DEBUG_PTRACE
-			printk ("Original: %08lx %08lx\n", child->tss.kregs->pc, child->tss.kregs->npc);
+			printk ("Original: %08lx %08lx\n", child->thread.kregs->pc, child->thread.kregs->npc);
 			printk ("Continuing with %08lx %08lx\n", addr, addr+4);
 #endif
-			child->tss.kregs->pc = addr;
-			child->tss.kregs->npc = addr + 4;
+			child->thread.kregs->pc = addr;
+			child->thread.kregs->npc = addr + 4;
 		}
 
 		if (request == PTRACE_SYSCALL)
@@ -576,8 +576,8 @@
 #ifdef DEBUG_PTRACE
 		printk("CONT: %s [%d]: set exit_code = %x %x %x\n", child->comm,
 			child->pid, child->exit_code,
-			child->tss.kregs->pc,
-			child->tss.kregs->npc);
+			child->thread.kregs->pc,
+			child->thread.kregs->npc);
 		       
 #endif
 		wake_up_process(child);
@@ -639,7 +639,7 @@
 		return;
 	current->exit_code = SIGTRAP;
 	current->state = TASK_STOPPED;
-	current->tss.flags ^= MAGIC_CONSTANT;
+	current->thread.flags ^= MAGIC_CONSTANT;
 	notify_parent(current, SIGCHLD);
 	schedule();
 	/*
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/rtrap.S linux/arch/sparc/kernel/rtrap.S
--- v2.3.15/linux/arch/sparc/kernel/rtrap.S	Tue Aug  4 16:03:34 1998
+++ linux/arch/sparc/kernel/rtrap.S	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.51 1998/07/26 03:02:38 davem Exp $
+/* $Id: rtrap.S,v 1.52 1999/08/14 03:51:18 anton Exp $
  * rtrap.S: Return from Sparc trap low-level code.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -95,7 +95,7 @@
 	wr	%t_psr, 0x0, %psr
 	WRITE_PAUSE
 
-	ld	[%curptr + AOFF_task_tss + AOFF_thread_w_saved], %twin_tmp1
+	ld	[%curptr + AOFF_task_thread + AOFF_thread_w_saved], %twin_tmp1
 	orcc	%g0, %twin_tmp1, %g0
 	be	ret_trap_nobufwins
 	 nop
@@ -119,7 +119,7 @@
 	/* If there are already live user windows in the
 	 * set we can return from trap safely.
 	 */
-	ld	[%curptr + AOFF_task_tss + AOFF_thread_uwinmask], %twin_tmp1
+	ld	[%curptr + AOFF_task_thread + AOFF_thread_uwinmask], %twin_tmp1
 	orcc	%g0, %twin_tmp1, %g0
 	bne	ret_trap_userwins_ok
 	 nop
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/semaphore.c linux/arch/sparc/kernel/semaphore.c
--- v2.3.15/linux/arch/sparc/kernel/semaphore.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc/kernel/semaphore.c	Tue Aug 31 11:23:29 1999
@@ -0,0 +1,129 @@
+/* $Id: semaphore.c,v 1.1 1999/08/31 13:26:15 anton Exp $
+ *  Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/sched.h>
+#include <asm/semaphore-helper.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit.  ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore.  The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+	wake_one_more(sem);
+	wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function.  Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible.  This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return.  If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR				\
+	struct task_struct *tsk = current;	\
+	wait_queue_t wait;			\
+	init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state)						\
+									\
+									\
+	tsk->state = (task_state);					\
+	add_wait_queue(&sem->wait, &wait);				\
+									\
+	/*								\
+	 * Ok, we're set up.  sem->count is known to be less than zero	\
+	 * so we must wait.						\
+	 *								\
+	 * We can let go the lock for purposes of waiting.		\
+	 * We re-acquire it after awaking so as to protect		\
+	 * all semaphore operations.					\
+	 *								\
+	 * If "up()" is called before we call waking_non_zero() then	\
+	 * we will catch it right away.  If it is called later then	\
+	 * we will have to go through a wakeup cycle to catch it.	\
+	 *								\
+	 * Multiple waiters contend for the semaphore lock to see	\
+	 * who gets to gate through and who has to wait some more.	\
+	 */								\
+	for (;;) {
+
+#define DOWN_TAIL(task_state)			\
+		tsk->state = (task_state);	\
+	}					\
+	tsk->state = TASK_RUNNING;		\
+	remove_wait_queue(&sem->wait, &wait);
+
+void __down(struct semaphore * sem)
+{
+	DOWN_VAR
+	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+	if (waking_non_zero(sem))
+		break;
+	schedule();
+	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+	int ret = 0;
+	DOWN_VAR
+	DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+	ret = waking_non_zero_interruptible(sem, tsk);
+	if (ret)
+	{
+		if (ret == 1)
+			/* ret != 0 only if we get interrupted -arca */
+			ret = 0;
+		break;
+	}
+	schedule();
+	DOWN_TAIL(TASK_INTERRUPTIBLE)
+	return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+	return waking_non_zero_trylock(sem);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c
--- v2.3.15/linux/arch/sparc/kernel/setup.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc/kernel/setup.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.108 1999/07/30 09:35:03 davem Exp $
+/*  $Id: setup.c,v 1.110 1999/08/31 06:54:23 davem Exp $
  *  linux/arch/sparc/kernel/setup.c
  *
  *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
@@ -153,7 +153,7 @@
  * Process kernel command line switches that are specific to the
  * SPARC or that require special low-level processing.
  */
-__initfunc(static void process_switch(char c))
+static void __init process_switch(char c)
 {
 	switch (c) {
 	case 'd':
@@ -172,7 +172,7 @@
 	}
 }
 
-__initfunc(static void boot_flags_init(char *commands))
+static void __init boot_flags_init(char *commands)
 {
 	while (*commands) {
 		/* Move to the start of the next "argument". */
@@ -297,8 +297,8 @@
 	"PROM", prom_cons_write, 0, 0, 0, 0, 0, CON_PRINTBUFFER, 0, 0, 0
 };
 
-__initfunc(void setup_arch(char **cmdline_p,
-	unsigned long * memory_start_p, unsigned long * memory_end_p))
+void __init setup_arch(char **cmdline_p,
+	unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
 	int total, i, packed;
 
@@ -425,6 +425,8 @@
 				initrd_start -= KERNBASE;
 				initrd_end -= KERNBASE;
 				break;
+			default:
+				break;
 			}
 		}
 	}
@@ -493,7 +495,7 @@
 	init_mm.mmap->vm_start = KERNBASE;
 	init_mm.mmap->vm_end = *memory_end_p;
 	init_mm.context = (unsigned long) NO_CONTEXT;
-	init_task.tss.kregs = &fake_swapper_regs;
+	init_task.thread.kregs = &fake_swapper_regs;
 
 	if (serial_console)
 		conswitchp = NULL;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c
--- v2.3.15/linux/arch/sparc/kernel/signal.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc/kernel/signal.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.94 1999/07/30 09:35:04 davem Exp $
+/*  $Id: signal.c,v 1.95 1999/08/14 03:51:22 anton Exp $
  *  linux/arch/sparc/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -211,12 +211,12 @@
 	if (verify_area (VERIFY_READ, fpu, sizeof(*fpu)))
 		return -EFAULT;
 
-	err = __copy_from_user(&current->tss.float_regs[0], &fpu->si_float_regs[0],
+	err = __copy_from_user(&current->thread.float_regs[0], &fpu->si_float_regs[0],
 			       (sizeof(unsigned long) * 32));
-	err |= __get_user(current->tss.fsr, &fpu->si_fsr);
-	err |= __get_user(current->tss.fpqdepth, &fpu->si_fpqdepth);
-	if (current->tss.fpqdepth != 0)
-		err |= __copy_from_user(&current->tss.fpqueue[0],
+	err |= __get_user(current->thread.fsr, &fpu->si_fsr);
+	err |= __get_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
+	if (current->thread.fpqdepth != 0)
+		err |= __copy_from_user(&current->thread.fpqueue[0],
 					&fpu->si_fpqueue[0],
 					((sizeof(unsigned long) +
 					(sizeof(unsigned long *)))*16));
@@ -289,7 +289,7 @@
 
 	synchronize_user_stack();
 
-	if (current->tss.new_signal)
+	if (current->thread.new_signal)
 		return do_new_sigreturn (regs);
 
 	scptr = (struct sigcontext *) regs->u_regs[UREG_I0];
@@ -459,28 +459,28 @@
 	err |= __put_user(regs->psr, &sc->sigc_psr);
 	err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
 	err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
-	err |= __put_user(current->tss.w_saved, &sc->sigc_oswins);
-	if(current->tss.w_saved)
-		for(window = 0; window < current->tss.w_saved; window++) {
+	err |= __put_user(current->thread.w_saved, &sc->sigc_oswins);
+	if(current->thread.w_saved)
+		for(window = 0; window < current->thread.w_saved; window++) {
 			sc->sigc_spbuf[window] =
-				(char *)current->tss.rwbuf_stkptrs[window];
+				(char *)current->thread.rwbuf_stkptrs[window];
 			err |= __copy_to_user(&sc->sigc_wbuf[window],
-					      &current->tss.reg_window[window],
+					      &current->thread.reg_window[window],
 					      sizeof(struct reg_window));
 		}
 	else
 		err |= __copy_to_user(sframep, (char *)regs->u_regs[UREG_FP],
 				      sizeof(struct reg_window));
 
-	current->tss.w_saved = 0; /* So process is allowed to execute. */
+	current->thread.w_saved = 0; /* So process is allowed to execute. */
 	err |= __put_user(signr, &sframep->sig_num);
 	if(signr == SIGSEGV ||
 	   signr == SIGILL ||
 	   signr == SIGFPE ||
 	   signr == SIGBUS ||
 	   signr == SIGEMT) {
-		err |= __put_user(current->tss.sig_desc, &sframep->sig_code);
-		err |= __put_user(current->tss.sig_address, &sframep->sig_address);
+		err |= __put_user(current->thread.sig_desc, &sframep->sig_code);
+		err |= __put_user(current->thread.sig_address, &sframep->sig_address);
 	} else {
 		err |= __put_user(0, &sframep->sig_code);
 		err |= __put_user(0, &sframep->sig_address);
@@ -508,26 +508,26 @@
 #ifdef __SMP__
 	if (current->flags & PF_USEDFPU) {
 		put_psr(get_psr() | PSR_EF);
-		fpsave(&current->tss.float_regs[0], &current->tss.fsr,
-		       &current->tss.fpqueue[0], &current->tss.fpqdepth);
+		fpsave(&current->thread.float_regs[0], &current->thread.fsr,
+		       &current->thread.fpqueue[0], &current->thread.fpqdepth);
 		regs->psr &= ~(PSR_EF);
 		current->flags &= ~(PF_USEDFPU);
 	}
 #else
 	if (current == last_task_used_math) {
 		put_psr(get_psr() | PSR_EF);
-		fpsave(&current->tss.float_regs[0], &current->tss.fsr,
-		       &current->tss.fpqueue[0], &current->tss.fpqdepth);
+		fpsave(&current->thread.float_regs[0], &current->thread.fsr,
+		       &current->thread.fpqueue[0], &current->thread.fpqdepth);
 		last_task_used_math = 0;
 		regs->psr &= ~(PSR_EF);
 	}
 #endif
-	err |= __copy_to_user(&fpu->si_float_regs[0], &current->tss.float_regs[0],
+	err |= __copy_to_user(&fpu->si_float_regs[0], &current->thread.float_regs[0],
 			      (sizeof(unsigned long) * 32));
-	err |= __put_user(current->tss.fsr, &fpu->si_fsr);
-	err |= __put_user(current->tss.fpqdepth, &fpu->si_fpqdepth);
-	if (current->tss.fpqdepth != 0)
-		err |= __copy_to_user(&fpu->si_fpqueue[0], &current->tss.fpqueue[0],
+	err |= __put_user(current->thread.fsr, &fpu->si_fsr);
+	err |= __put_user(current->thread.fpqdepth, &fpu->si_fpqdepth);
+	if (current->thread.fpqdepth != 0)
+		err |= __copy_to_user(&fpu->si_fpqueue[0], &current->thread.fpqueue[0],
 				      ((sizeof(unsigned long) +
 				      (sizeof(unsigned long *)))*16));
 	current->used_math = 0;
@@ -553,7 +553,7 @@
 	if (invalid_frame_pointer (sf, sigframe_size))
 		goto sigill_and_return;
 
-	if (current->tss.w_saved != 0) {
+	if (current->thread.w_saved != 0) {
 #ifdef DEBUG_SIGNALS 
 		printk ("%s [%d]: Invalid user stack frame for "
 			"signal delivery.\n", current->comm, current->pid);
@@ -631,7 +631,7 @@
 	sf = (struct rt_signal_frame *)get_sigframe(&ka->sa, regs, sigframe_size);
 	if(invalid_frame_pointer(sf, sigframe_size))
 		goto sigill;
-	if(current->tss.w_saved != 0)
+	if(current->thread.w_saved != 0)
 		goto sigill;
 
 	err  = __put_user(regs->pc, &sf->regs.pc);
@@ -764,7 +764,7 @@
 	err |= __put_user(gw, &mc->gwin);
 	    
 	/* 2. Number of windows to restore at setcontext (): */
-	err |= __put_user(current->tss.w_saved, &gw->count);
+	err |= __put_user(current->thread.w_saved, &gw->count);
 
 	/* 3. Save each valid window
 	 *    Currently, it makes a copy of the windows from the kernel copy.
@@ -777,21 +777,21 @@
 	 *    These windows are just used in case synchronize_user_stack failed
 	 *    to flush the user windows.
 	 */
-	for(window = 0; window < current->tss.w_saved; window++) {
+	for(window = 0; window < current->thread.w_saved; window++) {
 		err |= __put_user((int *) &(gw->win [window]), &gw->winptr [window]);
 		err |= __copy_to_user(&gw->win [window],
-				      &current->tss.reg_window [window],
+				      &current->thread.reg_window [window],
 				      sizeof (svr4_rwindow_t));
 		err |= __put_user(0, gw->winptr [window]);
 	}
 
 	/* 4. We just pay attention to the gw->count field on setcontext */
-	current->tss.w_saved = 0; /* So process is allowed to execute. */
+	current->thread.w_saved = 0; /* So process is allowed to execute. */
 
 	/* Setup the signal information.  Solaris expects a bunch of
 	 * information to be passed to the signal handler, we don't provide
 	 * that much currently, should use those that David already
-	 * is providing with tss.sig_desc
+	 * is providing with thread.sig_desc
 	 */
 	err |= __put_user(signr, &si->siginfo.signo);
 	err |= __put_user(SVR4_SINOINFO, &si->siginfo.code);
@@ -837,7 +837,7 @@
 
 	synchronize_user_stack();
 
-	if (current->tss.w_saved)
+	if (current->thread.w_saved)
 		goto sigsegv_and_return;
 
 	err = clear_user(uc, sizeof (*uc));
@@ -884,7 +884,7 @@
 /* Set the context for a svr4 application, this is Solaris way to sigreturn */
 asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs)
 {
-	struct thread_struct *tp = &current->tss;
+	struct thread_struct *tp = &current->thread;
 	svr4_gregset_t  *gr;
 	unsigned long pc, npc, psr;
 	sigset_t set;
@@ -973,7 +973,7 @@
 	else {
 		if (ka->sa.sa_flags & SA_SIGINFO)
 			new_setup_rt_frame(ka, regs, signr, oldset, info);
-		else if (current->tss.new_signal)
+		else if (current->thread.new_signal)
 			new_setup_frame (ka, regs, signr, oldset);
 		else
 			setup_frame(&ka->sa, regs->pc, regs->npc, regs, signr, oldset);
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c
--- v2.3.15/linux/arch/sparc/kernel/smp.c	Wed Mar 10 16:53:36 1999
+++ linux/arch/sparc/kernel/smp.c	Tue Aug 31 11:23:29 1999
@@ -74,7 +74,7 @@
 volatile int smp_commenced = 0;
 
 /* Not supported on Sparc yet. */
-__initfunc(void smp_setup(char *str, int *ints))
+void __init smp_setup(char *str, int *ints)
 {
 }
 
@@ -83,12 +83,12 @@
  *	a given CPU
  */
 
-__initfunc(void smp_store_cpu_info(int id))
+void __init smp_store_cpu_info(int id)
 {
 	cpu_data[id].udelay_val = loops_per_sec; /* this is it on sparc. */
 }
 
-__initfunc(void smp_commence(void))
+void __init smp_commence(void)
 {
 	/*
 	 *	Lets the callin's below out of their loop.
@@ -103,17 +103,17 @@
 /* Only broken Intel needs this, thus it should not even be referenced
  * globally...
  */
-__initfunc(void initialize_secondary(void))
+void __init initialize_secondary(void)
 {
 }
 
-extern int cpu_idle(void *unused);
+extern int cpu_idle(void);
 
 /* Activate a secondary processor. */
 int start_secondary(void *unused)
 {
 	prom_printf("Start secondary called. Should not happen\n");
-	return cpu_idle(NULL);
+	return cpu_idle();
 }
 
 void cpu_panic(void)
@@ -129,7 +129,7 @@
 extern struct prom_cpuinfo linux_cpus[NR_CPUS];
 struct linux_prom_registers smp_penguin_ctable __initdata = { 0 };
 
-__initfunc(void smp_boot_cpus(void))
+void __init smp_boot_cpus(void)
 {
 	extern void smp4m_boot_cpus(void);
 	extern void smp4d_boot_cpus(void);
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/solaris.c linux/arch/sparc/kernel/solaris.c
--- v2.3.15/linux/arch/sparc/kernel/solaris.c	Sun Jan 26 02:07:07 1997
+++ linux/arch/sparc/kernel/solaris.c	Tue Aug 31 11:23:29 1999
@@ -13,8 +13,6 @@
 #include <asm/errno.h>
 #include <asm/solerrno.h>
 
-extern asmlinkage int sys_open(const char *,int,int);
-
 asmlinkage int solaris_open(const char *filename, int flags, int mode)
 {
 	int newflags;
@@ -39,5 +37,3 @@
 	unlock_kernel();
 	return ret;
 }
-
-
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/sun4c_irq.c linux/arch/sparc/kernel/sun4c_irq.c
--- v2.3.15/linux/arch/sparc/kernel/sun4c_irq.c	Sun Oct  4 10:22:42 1998
+++ linux/arch/sparc/kernel/sun4c_irq.c	Thu Aug 26 12:42:32 1999
@@ -138,7 +138,7 @@
 	/* Errm.. not sure how to do this.. */
 }
 
-__initfunc(static void sun4c_init_timers(void (*counter_fn)(int, void *, struct pt_regs *)))
+static void __init sun4c_init_timers(void (*counter_fn)(int, void *, struct pt_regs *))
 {
 	int irq;
 
@@ -184,7 +184,7 @@
 
 extern char *sun4m_irq_itoa(unsigned int irq);
 
-__initfunc(void sun4c_init_IRQ(void))
+void __init sun4c_init_IRQ(void)
 {
 	struct linux_prom_registers int_regs[2];
 	int ie_node;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c
--- v2.3.15/linux/arch/sparc/kernel/sun4d_irq.c	Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc/kernel/sun4d_irq.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/*  $Id: sun4d_irq.c,v 1.18 1999/04/20 13:22:30 anton Exp $
+/*  $Id: sun4d_irq.c,v 1.19 1999/08/31 06:54:25 davem Exp $
  *  arch/sparc/kernel/sun4d_irq.c:
  *			SS1000/SC2000 interrupt handling.
  *
@@ -366,7 +366,7 @@
 }
 
 /* Setup IRQ distribution scheme. */
-__initfunc(void sun4d_distribute_irqs(void))
+void __init sun4d_distribute_irqs(void)
 {
 #ifdef DISTRIBUTE_IRQS
 	struct linux_sbus *sbus;
@@ -431,7 +431,7 @@
 	bw_set_prof_limit(cpu, limit);
 }
 
-__initfunc(static void sun4d_init_timers(void (*counter_fn)(int, void *, struct pt_regs *)))
+static void __init sun4d_init_timers(void (*counter_fn)(int, void *, struct pt_regs *))
 {
 	int irq;
 	extern struct prom_cpuinfo linux_cpus[NR_CPUS];
@@ -492,7 +492,7 @@
 #endif
 }
 
-__initfunc(void sun4d_init_sbi_irq(void))
+void __init sun4d_init_sbi_irq(void)
 {
 	struct linux_sbus *sbus;
 	unsigned mask;
@@ -529,7 +529,7 @@
 	return buff;
 }
 
-__initfunc(void sun4d_init_IRQ(void))
+void __init sun4d_init_IRQ(void)
 {
 	__cli();
 
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/sun4d_smp.c linux/arch/sparc/kernel/sun4d_smp.c
--- v2.3.15/linux/arch/sparc/kernel/sun4d_smp.c	Fri Jul 23 12:20:23 1999
+++ linux/arch/sparc/kernel/sun4d_smp.c	Thu Aug 26 12:42:32 1999
@@ -83,7 +83,7 @@
 extern void cpu_probe(void);
 extern void sun4d_distribute_irqs(void);
 
-__initfunc(void smp4d_callin(void))
+void __init smp4d_callin(void)
 {
 	int cpuid = hard_smp4d_processor_id();
 	extern spinlock_t sun4d_imsk_lock;
@@ -161,7 +161,7 @@
 extern unsigned long trapbase_cpu2[];
 extern unsigned long trapbase_cpu3[];
 
-__initfunc(void smp4d_boot_cpus(void))
+void __init smp4d_boot_cpus(void)
 {
 	int cpucount = 0;
 	int i = 0;
@@ -499,7 +499,7 @@
 
 extern unsigned int lvl14_resolution;
 
-__initfunc(static void smp_setup_percpu_timer(void))
+static void __init smp_setup_percpu_timer(void)
 {
 	int cpu = hard_smp4d_processor_id();
 
@@ -507,7 +507,7 @@
 	load_profile_irq(cpu, lvl14_resolution);
 }
 
-__initfunc(void smp4d_blackbox_id(unsigned *addr))
+void __init smp4d_blackbox_id(unsigned *addr)
 {
 	int rd = *addr & 0x3e000000;
 	
@@ -516,7 +516,7 @@
 	addr[2] = 0x01000000;    		/* nop */
 }
 
-__initfunc(void smp4d_blackbox_current(unsigned *addr))
+void __init smp4d_blackbox_current(unsigned *addr)
 {
 	/* We have a nice Linux current register :) */
 	int rd = addr[1] & 0x3e000000;
@@ -525,7 +525,7 @@
 	addr[1] = 0xc0800820 | rd;		/* lda [%g0] ASI_M_VIKING_TMP2, reg */
 }
 
-__initfunc(void sun4d_init_smp(void))
+void __init sun4d_init_smp(void)
 {
 	int i;
 	extern unsigned int patchme_store_new_current[];
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/sun4m_irq.c linux/arch/sparc/kernel/sun4m_irq.c
--- v2.3.15/linux/arch/sparc/kernel/sun4m_irq.c	Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc/kernel/sun4m_irq.c	Thu Aug 26 12:42:32 1999
@@ -220,7 +220,7 @@
 	return buff;
 }
 
-__initfunc(static void sun4m_init_timers(void (*counter_fn)(int, void *, struct pt_regs *)))
+static void __init sun4m_init_timers(void (*counter_fn)(int, void *, struct pt_regs *))
 {
 	int reg_count, irq, cpu;
 	struct linux_prom_registers cnt_regs[PROMREG_MAX];
@@ -303,7 +303,7 @@
 #endif
 }
 
-__initfunc(void sun4m_init_IRQ(void))
+void __init sun4m_init_IRQ(void)
 {
 	int ie_node,i;
 	struct linux_prom_registers int_regs[PROMREG_MAX];
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c
--- v2.3.15/linux/arch/sparc/kernel/sun4m_smp.c	Fri Jul 23 12:20:23 1999
+++ linux/arch/sparc/kernel/sun4m_smp.c	Thu Aug 26 12:42:32 1999
@@ -77,7 +77,7 @@
 static void smp_setup_percpu_timer(void);
 extern void cpu_probe(void);
 
-__initfunc(void smp4m_callin(void))
+void __init smp4m_callin(void)
 {
 	int cpuid = hard_smp_processor_id();
 
@@ -135,7 +135,7 @@
 extern unsigned long trapbase_cpu2[];
 extern unsigned long trapbase_cpu3[];
 
-__initfunc(void smp4m_boot_cpus(void))
+void __init smp4m_boot_cpus(void)
 {
 	int cpucount = 0;
 	int i = 0;
@@ -479,7 +479,7 @@
 
 extern unsigned int lvl14_resolution;
 
-__initfunc(static void smp_setup_percpu_timer(void))
+static void __init smp_setup_percpu_timer(void)
 {
 	int cpu = smp_processor_id();
 
@@ -490,7 +490,7 @@
 		enable_pil_irq(14);
 }
 
-__initfunc(void smp4m_blackbox_id(unsigned *addr))
+void __init smp4m_blackbox_id(unsigned *addr)
 {
 	int rd = *addr & 0x3e000000;
 	int rs1 = rd >> 11;
@@ -500,7 +500,7 @@
 	addr[2] = 0x80082003 | rd | rs1;	/* and reg, 3, reg */
 }
 
-__initfunc(void smp4m_blackbox_current(unsigned *addr))
+void __init smp4m_blackbox_current(unsigned *addr)
 {
 	int rd = *addr & 0x3e000000;
 	int rs1 = rd >> 11;
@@ -510,7 +510,7 @@
 	addr[4] = 0x8008200c | rd | rs1;	/* and reg, 3, reg */
 }
 
-__initfunc(void sun4m_init_smp(void))
+void __init sun4m_init_smp(void)
 {
 	BTFIXUPSET_BLACKBOX(smp_processor_id, smp4m_blackbox_id);
 	BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/sun4setup.c linux/arch/sparc/kernel/sun4setup.c
--- v2.3.15/linux/arch/sparc/kernel/sun4setup.c	Tue Aug  4 23:57:51 1998
+++ linux/arch/sparc/kernel/sun4setup.c	Thu Aug 26 12:42:32 1999
@@ -23,7 +23,7 @@
 int sun4_esp_physaddr;
 int sun4_ie_physaddr; 
 
-__initfunc(void sun4setup())
+void __init sun4setup(void)
 {
 	printk("Sun4 Hardware Setup v1.0 18/May/98 Chris Davis (cdavis@cois.on.ca). ");
 	/*
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c
--- v2.3.15/linux/arch/sparc/kernel/sys_sparc.c	Tue May 11 08:24:31 1999
+++ linux/arch/sparc/kernel/sys_sparc.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.52 1999/05/08 08:09:48 anton Exp $
+/* $Id: sys_sparc.c,v 1.53 1999/08/14 03:51:25 anton Exp $
  * linux/arch/sparc/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -263,7 +263,7 @@
 	int ret;
 
 	if (sig < 0) {
-		current->tss.new_signal = 1;
+		current->thread.new_signal = 1;
 		sig = -sig;
 	}
 
@@ -313,7 +313,7 @@
 	/* All tasks which use RT signals (effectively) use
 	 * new style signals.
 	 */
-	current->tss.new_signal = 1;
+	current->thread.new_signal = 1;
 
 	if (act) {
 		new_ka.ka_restorer = restorer;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.3.15/linux/arch/sparc/kernel/sys_sunos.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc/kernel/sys_sunos.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.102 1999/07/23 01:56:19 davem Exp $
+/* $Id: sys_sunos.c,v 1.104 1999/08/31 12:30:50 anton Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -597,9 +597,9 @@
 	struct pt_regs *regs;
 
 	lock_kernel();
-	regs = current->tss.kregs;
-	current->tss.sig_address = regs->pc;
-	current->tss.sig_desc = regs->u_regs[UREG_G1];
+	regs = current->thread.kregs;
+	current->thread.sig_address = regs->pc;
+	current->thread.sig_desc = regs->u_regs[UREG_G1];
 	send_sig(SIGSYS, current, 1);
 	printk("Process makes ni_syscall number %d, register dump:\n",
 	       (int) regs->u_regs[UREG_G1]);
@@ -1009,10 +1009,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg);
-extern asmlinkage int sys_semget (key_t key, int nsems, int semflg);
-extern asmlinkage int sys_semop  (int semid, struct sembuf *tsops, unsigned nsops);
-
 asmlinkage int sunos_semsys(int op, unsigned long arg1, unsigned long arg2,
 			    unsigned long arg3, void *ptr)
 {
@@ -1059,13 +1055,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_msgget (key_t key, int msgflg);
-extern asmlinkage int sys_msgrcv (int msqid, struct msgbuf *msgp,
-				  size_t msgsz, long msgtyp, int msgflg);
-extern asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp,
-				  size_t msgsz, int msgflg);
-extern asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf);
-
 asmlinkage int sunos_msgsys(int op, unsigned long arg1, unsigned long arg2,
 			    unsigned long arg3, unsigned long arg4)
 {
@@ -1083,7 +1072,7 @@
 				  (struct msqid_ds *)arg3);
 		break;
 	case 2:
-		sp = (struct sparc_stackf *)current->tss.kregs->u_regs[UREG_FP];
+		sp = (struct sparc_stackf *)current->thread.kregs->u_regs[UREG_FP];
 		arg5 = sp->xxargs[0];
 		rval = sys_msgrcv((int)arg1, (struct msgbuf *)arg2,
 				  (size_t)arg3, (long)arg4, (int)arg5);
@@ -1099,11 +1088,6 @@
 	unlock_kernel();
 	return rval;
 }
-
-extern asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr);
-extern asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
-extern asmlinkage int sys_shmdt (char *shmaddr);
-extern asmlinkage int sys_shmget (key_t key, int size, int shmflg);
 
 asmlinkage int sunos_shmsys(int op, unsigned long arg1, unsigned long arg2,
 			    unsigned long arg3)
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S
--- v2.3.15/linux/arch/sparc/kernel/systbls.S	Wed Jul 28 10:30:10 1999
+++ linux/arch/sparc/kernel/systbls.S	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.83 1999/04/07 17:14:06 davem Exp $
+/* $Id: systbls.S,v 1.84 1999/08/14 03:51:29 anton Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -58,7 +58,7 @@
 /*195*/	.long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
 /*200*/	.long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
 /*205*/	.long sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
-/*210*/	.long sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
+/*210*/	.long sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
 /*215*/	.long sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex
 /*220*/	.long sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
 /*225*/	.long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/tadpole.c linux/arch/sparc/kernel/tadpole.c
--- v2.3.15/linux/arch/sparc/kernel/tadpole.c	Tue Apr 14 17:44:19 1998
+++ linux/arch/sparc/kernel/tadpole.c	Thu Aug 26 12:42:32 1999
@@ -95,7 +95,7 @@
 	clk_ctrl[0] = 0;
 }
 
-__initfunc(void clock_stop_probe(void))
+void __init clock_stop_probe(void)
 {
 	unsigned int node, clk_nd;
 	char name[20];
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c
--- v2.3.15/linux/arch/sparc/kernel/time.c	Mon Mar 15 16:10:43 1999
+++ linux/arch/sparc/kernel/time.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.43 1999/03/15 22:13:31 davem Exp $
+/* $Id: time.c,v 1.46 1999/08/31 13:11:26 anton Exp $
  * linux/arch/sparc/kernel/time.c
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -42,8 +42,8 @@
 extern rwlock_t xtime_lock;
 
 enum sparc_clock_type sp_clock_typ;
-struct mostek48t02 *mstk48t02_regs = 0;
-struct mostek48t08 *mstk48t08_regs = 0;
+unsigned long mstk48t02_regs = 0UL;
+static struct mostek48t08 *mstk48t08_regs = 0;
 static int set_rtc_mmss(unsigned long);
 static void sbus_do_settimeofday(struct timeval *tv);
 
@@ -140,9 +140,9 @@
 }
 
 /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
-__initfunc(static void kick_start_clock(void))
+static void __init kick_start_clock(void)
 {
-	register struct mostek48t02 *regs = mstk48t02_regs;
+	struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
 	unsigned char sec;
 	int i, count;
 
@@ -191,7 +191,7 @@
 /* Return nonzero if the clock chip battery is low. */
 static __inline__ int has_low_battery(void)
 {
-	register struct mostek48t02 *regs = mstk48t02_regs;
+	struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
 	unsigned char data1, data2;
 
 	data1 = regs->eeprom[0];	/* Read some data. */
@@ -210,15 +210,15 @@
 
 	if( idprom->id_machtype == (SM_SUN4 | SM_4_330) ) {
 		sp_clock_typ = MSTK48T02;
-		mstk48t02_regs = (struct mostek48t02 *) 
+		mstk48t02_regs = (unsigned long) 
 				sparc_alloc_io(sun4_clock_physaddr, 0,
-				       sizeof(*mstk48t02_regs),
+				       sizeof(struct mostek48t02),
 				       "clock", 0x0, 0x0);
 		mstk48t08_regs = 0;  /* To catch weirdness */
 		intersil_clock = 0;  /* just in case */
 
 		/* Kick start the clock if it is completely stopped. */
-		if (mstk48t02_regs->sec & MSTK_STOP)
+		if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)
 			kick_start_clock();
 	} else if( idprom->id_machtype == (SM_SUN4 | SM_4_260)) {
 		/* intersil setup code */
@@ -297,9 +297,9 @@
 		else
 			prom_apply_obio_ranges(clk_reg, 1);
 		/* Map the clock register io area read-only */
-		mstk48t02_regs = (struct mostek48t02 *) 
+		mstk48t02_regs = (unsigned long) 
 			sparc_alloc_io(clk_reg[0].phys_addr,
-				       (void *) 0, sizeof(*mstk48t02_regs),
+				       (void *) 0, sizeof(struct mostek48t02),
 				       "clock", clk_reg[0].which_io, 0x0);
 		mstk48t08_regs = 0;  /* To catch weirdness */
 	} else if (strcmp(model, "mk48t08") == 0) {
@@ -319,7 +319,7 @@
 				       (void *) 0, sizeof(*mstk48t08_regs),
 				       "clock", clk_reg[0].which_io, 0x0);
 
-		mstk48t02_regs = &mstk48t08_regs->regs;
+		mstk48t02_regs = (unsigned long)&mstk48t08_regs->regs;
 	} else {
 		prom_printf("CLOCK: Unknown model name '%s'\n",model);
 		prom_halt();
@@ -330,11 +330,11 @@
 		printk(KERN_CRIT "NVRAM: Low battery voltage!\n");
 
 	/* Kick start the clock if it is completely stopped. */
-	if (mstk48t02_regs->sec & MSTK_STOP)
+	if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)
 		kick_start_clock();
 }
 
-__initfunc(void sbus_time_init(void))
+void __init sbus_time_init(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
 	struct mostek48t02 *mregs;
@@ -364,7 +364,7 @@
 #ifdef CONFIG_SUN4
 	if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) {
 #endif
-	mregs = mstk48t02_regs;
+	mregs = (struct mostek48t02 *)mstk48t02_regs;
 	if(!mregs) {
 		prom_printf("Something wrong, clock regs not mapped yet.\n");
 		prom_halt();
@@ -416,7 +416,7 @@
 	__sti();
 }
 
-__initfunc(void time_init(void))
+void __init time_init(void)
 {
 #ifdef CONFIG_PCI
 	extern void pci_time_init(void);
@@ -521,7 +521,7 @@
 static int set_rtc_mmss(unsigned long nowtime)
 {
 	int real_seconds, real_minutes, mostek_minutes;
-	struct mostek48t02 *regs = mstk48t02_regs;
+	struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
 #ifdef CONFIG_SUN4
 	struct intersil *iregs = intersil_clock;
 	int temp;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/traps.c linux/arch/sparc/kernel/traps.c
--- v2.3.15/linux/arch/sparc/kernel/traps.c	Wed Mar 10 16:53:36 1999
+++ linux/arch/sparc/kernel/traps.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.59 1999/03/06 12:07:31 anton Exp $
+/* $Id: traps.c,v 1.60 1999/08/14 03:51:31 anton Exp $
  * arch/sparc/kernel/traps.c
  *
  * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -132,17 +132,17 @@
 	if(type < 0x80) {
 		/* Sun OS's puke from bad traps, Linux survives! */
 		printk("Unimplemented Sparc TRAP, type = %02lx\n", type);
-		die_if_kernel("Whee... Hello Mr. Penguin", current->tss.kregs);
+		die_if_kernel("Whee... Hello Mr. Penguin", current->thread.kregs);
 	}	
 
 	if(type == SP_TRAP_SBPT) {
 		send_sig(SIGTRAP, current, 1);
 	} else {
 		if(psr & PSR_PS)
-			die_if_kernel("Kernel bad trap", current->tss.kregs);
+			die_if_kernel("Kernel bad trap", current->thread.kregs);
 
-		current->tss.sig_desc = SUBSIG_BADTRAP(type - 0x80);
-		current->tss.sig_address = pc;
+		current->thread.sig_desc = SUBSIG_BADTRAP(type - 0x80);
+		current->thread.sig_address = pc;
 		send_sig(SIGILL, current, 1);
 	}
 	unlock_kernel();
@@ -163,8 +163,8 @@
 		if (!do_user_muldiv (regs, pc))
 			goto out;
 	}
-	current->tss.sig_address = pc;
-	current->tss.sig_desc = SUBSIG_ILLINST;
+	current->thread.sig_address = pc;
+	current->thread.sig_desc = SUBSIG_ILLINST;
 	send_sig(SIGILL, current, 1);
 out:
 	unlock_kernel();
@@ -176,8 +176,8 @@
 	lock_kernel();
 	if(psr & PSR_PS)
 		die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
-	current->tss.sig_address = pc;
-	current->tss.sig_desc = SUBSIG_PRIVINST;
+	current->thread.sig_address = pc;
+	current->thread.sig_desc = SUBSIG_PRIVINST;
 	send_sig(SIGILL, current, 1);
 	unlock_kernel();
 }
@@ -194,8 +194,8 @@
 		die_if_kernel("BOGUS", regs);
 		/* die_if_kernel("Kernel MNA access", regs); */
 	}
-	current->tss.sig_address = pc;
-	current->tss.sig_desc = SUBSIG_PRIVINST;
+	current->thread.sig_address = pc;
+	current->thread.sig_desc = SUBSIG_PRIVINST;
 #if 0
 	show_regs (regs);
 	instruction_dump ((unsigned long *) regs->pc);
@@ -232,12 +232,12 @@
 	if(last_task_used_math) {
 		/* Other processes fpu state, save away */
 		struct task_struct *fptask = last_task_used_math;
-		fpsave(&fptask->tss.float_regs[0], &fptask->tss.fsr,
-		       &fptask->tss.fpqueue[0], &fptask->tss.fpqdepth);
+		fpsave(&fptask->thread.float_regs[0], &fptask->thread.fsr,
+		       &fptask->thread.fpqueue[0], &fptask->thread.fpqdepth);
 	}
 	last_task_used_math = current;
 	if(current->used_math) {
-		fpload(&current->tss.float_regs[0], &current->tss.fsr);
+		fpload(&current->thread.float_regs[0], &current->thread.fsr);
 	} else {
 		/* Set initial sane state. */
 		fpload(&init_fregs[0], &init_fsr);
@@ -248,7 +248,7 @@
 		fpload(&init_fregs[0], &init_fsr);
 		current->used_math = 1;
 	} else {
-		fpload(&current->tss.float_regs[0], &current->tss.fsr);
+		fpload(&current->thread.float_regs[0], &current->thread.fsr);
 	}
 	current->flags |= PF_USEDFPU;
 #endif
@@ -290,13 +290,13 @@
 		regs->psr &= ~PSR_EF;
 		goto out;
 	}
-	fpsave(&fpt->tss.float_regs[0], &fpt->tss.fsr,
-	       &fpt->tss.fpqueue[0], &fpt->tss.fpqdepth);
+	fpsave(&fpt->thread.float_regs[0], &fpt->thread.fsr,
+	       &fpt->thread.fpqueue[0], &fpt->thread.fpqdepth);
 #ifdef DEBUG_FPU
-	printk("Hmm, FP exception, fsr was %016lx\n", fpt->tss.fsr);
+	printk("Hmm, FP exception, fsr was %016lx\n", fpt->thread.fsr);
 #endif
 
-	switch ((fpt->tss.fsr & 0x1c000)) {
+	switch ((fpt->thread.fsr & 0x1c000)) {
 	/* switch on the contents of the ftt [floating point trap type] field */
 #ifdef DEBUG_FPU
 	case (1 << 14):
@@ -321,13 +321,13 @@
 	}
 	/* If we successfully emulated the FPop, we pretend the trap never happened :-> */
 	if (ret) {
-		fpload(&current->tss.float_regs[0], &current->tss.fsr);
+		fpload(&current->thread.float_regs[0], &current->thread.fsr);
 		return;
 	}
 	/* nope, better SIGFPE the offending process... */
 	       
-	fpt->tss.sig_address = pc;
-	fpt->tss.sig_desc = SUBSIG_FPERROR; /* as good as any */
+	fpt->thread.sig_address = pc;
+	fpt->thread.sig_desc = SUBSIG_FPERROR; /* as good as any */
 #ifdef __SMP__
 	fpt->flags &= ~PF_USEDFPU;
 #endif
@@ -362,8 +362,8 @@
 	lock_kernel();
 	if(psr & PSR_PS)
 		die_if_kernel("Penguin overflow trap from kernel mode", regs);
-	current->tss.sig_address = pc;
-	current->tss.sig_desc = SUBSIG_TAG; /* as good as any */
+	current->thread.sig_address = pc;
+	current->thread.sig_desc = SUBSIG_TAG; /* as good as any */
 	send_sig(SIGEMT, current, 1);
 	unlock_kernel();
 }
@@ -436,4 +436,11 @@
 
 void trap_init(void)
 {
+	/* Attach to the address space of init_task. */
+	atomic_inc(&init_mm.mm_count);
+	current->active_mm = &init_mm;
+
+	/* NOTE: Other cpus have this done as they are started
+	 *       up on SMP.
+	 */
 }
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/unaligned.c linux/arch/sparc/kernel/unaligned.c
--- v2.3.15/linux/arch/sparc/kernel/unaligned.c	Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc/kernel/unaligned.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: unaligned.c,v 1.18 1999/04/03 11:36:17 anton Exp $
+/* $Id: unaligned.c,v 1.19 1999/08/14 03:51:33 anton Exp $
  * unaligned.c: Unaligned load/store trap handling with special
  *              cases for the kernel to do them more quickly.
  *
@@ -61,7 +61,7 @@
 		return 2;
 	else {
 		printk("Impossible unaligned trap. insn=%08x\n", insn);
-		die_if_kernel("Byte sized unaligned access?!?!", current->tss.kregs);
+		die_if_kernel("Byte sized unaligned access?!?!", current->thread.kregs);
 		return 4; /* just to keep gcc happy. */
 	}
 }
@@ -422,8 +422,8 @@
 
 void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
 {
-	current->tss.sig_address = regs->pc;
-	current->tss.sig_desc = SUBSIG_PRIVINST;
+	current->thread.sig_address = regs->pc;
+	current->thread.sig_desc = SUBSIG_PRIVINST;
 	send_sig(SIGBUS, current, 1);
 }
 
@@ -432,7 +432,7 @@
 	enum direction dir;
 
 	lock_kernel();
-	if(!(current->tss.flags & SPARC_FLAG_UNALIGNED) ||
+	if(!(current->thread.flags & SPARC_FLAG_UNALIGNED) ||
 	   (((insn >> 30) & 3) != 3))
 		goto kill_user;
 	dir = decode_direction(insn);
@@ -487,8 +487,8 @@
 	}
 
 kill_user:
-	current->tss.sig_address = regs->pc;
-	current->tss.sig_desc = SUBSIG_PRIVINST;
+	current->thread.sig_address = regs->pc;
+	current->thread.sig_desc = SUBSIG_PRIVINST;
 	send_sig(SIGBUS, current, 1);
 out:
 	unlock_kernel();
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/windows.c linux/arch/sparc/kernel/windows.c
--- v2.3.15/linux/arch/sparc/kernel/windows.c	Mon Apr 14 16:28:07 1997
+++ linux/arch/sparc/kernel/windows.c	Tue Aug 31 11:23:29 1999
@@ -32,7 +32,7 @@
 	 restore %%g0, %%g0, %%g0"
 	: "=&r" (ctr)
 	: "0" (ctr),
-	  "i" ((const unsigned long)(&(((struct task_struct *)0)->tss.uwinmask)))
+	  "i" ((const unsigned long)(&(((struct task_struct *)0)->thread.uwinmask)))
 	: "g4", "cc");
 }
 
@@ -61,7 +61,7 @@
 	int window;
 
 	flush_user_windows();
-	tp = &current->tss;
+	tp = &current->thread;
 	if(!tp->w_saved)
 		return;
 
@@ -115,7 +115,7 @@
 
 	lock_kernel();
 	flush_user_windows();
-	tp = &current->tss;
+	tp = &current->thread;
 	for(window = 0; window < tp->w_saved; window++) {
 		unsigned long sp = tp->rwbuf_stkptrs[window];
 
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/wof.S linux/arch/sparc/kernel/wof.S
--- v2.3.15/linux/arch/sparc/kernel/wof.S	Tue Apr 14 17:44:19 1998
+++ linux/arch/sparc/kernel/wof.S	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: wof.S,v 1.38 1998/02/06 14:14:22 jj Exp $
+/* $Id: wof.S,v 1.39 1999/08/14 03:51:35 anton Exp $
  * wof.S: Sparc window overflow handler.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -62,7 +62,7 @@
 	 * andcc %l0, PSR_PS, %g0
 	 */
 
-	/* Datum current->tss.uwinmask contains at all times a bitmask
+	/* Datum current->thread.uwinmask contains at all times a bitmask
 	 * where if any user windows are active, at least one bit will
 	 * be set in to mask.  If no user windows are active, the bitmask
 	 * will be all zeroes.
@@ -96,7 +96,7 @@
 	 save	%g0, %g0, %g0				! Go where saving will occur
 	
 	/* See if any user windows are active in the set. */
-	ld	[%curptr + AOFF_task_tss + AOFF_thread_uwinmask], %twin_tmp	! grab win mask
+	ld	[%curptr + AOFF_task_thread + AOFF_thread_uwinmask], %twin_tmp	! grab win mask
 	orcc	%g0, %twin_tmp, %g0			! check for set bits
 	bne	spwin_exist_uwins			! yep, there are some
 	 andn	%twin_tmp, %glob_tmp, %twin_tmp		! compute new umask
@@ -139,7 +139,7 @@
 	 * But first, store the new user window mask calculated
 	 * above.
 	 */
-	st	%twin_tmp, [%curptr + AOFF_task_tss + AOFF_thread_uwinmask]
+	st	%twin_tmp, [%curptr + AOFF_task_thread + AOFF_thread_uwinmask]
 	save	%g0, %g0, %g0		! Go to where the saving will occur
 
 spwin_fromuser:
@@ -212,15 +212,15 @@
 	/* Oh well, throw this one window into the per-task window
 	 * buffer, the first one.
 	 */
-	st	%sp, [%curptr + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]
-	STORE_WINDOW(curptr + AOFF_task_tss + AOFF_thread_reg_window)
+	st	%sp, [%curptr + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs]
+	STORE_WINDOW(curptr + AOFF_task_thread + AOFF_thread_reg_window)
 	restore	%g0, %g0, %g0
 
 	/* LOCATION: Trap Window */
 
 	/* Back in the trap window, update winbuffer save count. */
 	mov	1, %glob_tmp
-	st	%glob_tmp, [%curptr + AOFF_task_tss + AOFF_thread_w_saved]
+	st	%glob_tmp, [%curptr + AOFF_task_thread + AOFF_thread_w_saved]
 
 		/* Compute new user window mask.  What we are basically
 		 * doing is taking two windows, the invalid one at trap
@@ -232,7 +232,7 @@
 		or	%twin_tmp, %t_wim, %twin_tmp
 		not	%twin_tmp
 spnwin_patch3:	and	%twin_tmp, 0xff, %twin_tmp	! patched on 7win Sparcs
-		st	%twin_tmp, [%curptr + AOFF_task_tss + AOFF_thread_uwinmask]
+		st	%twin_tmp, [%curptr + AOFF_task_thread + AOFF_thread_uwinmask]
 
 #define STACK_OFFSET	(TASK_UNION_SIZE - TRACEREG_SZ - REGWIN_SZ)
 
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/kernel/wuf.S linux/arch/sparc/kernel/wuf.S
--- v2.3.15/linux/arch/sparc/kernel/wuf.S	Tue Apr 14 17:44:19 1998
+++ linux/arch/sparc/kernel/wuf.S	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: wuf.S,v 1.37 1998/02/19 21:25:50 ecd Exp $
+/* $Id: wuf.S,v 1.38 1999/08/14 03:51:36 anton Exp $
  * wuf.S: Window underflow trap handler for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller
@@ -40,7 +40,7 @@
 	 * andcc %l0, PSR_PS, %g0
 	 */
 
-	/* Datum current->tss.uwinmask contains at all times a bitmask
+	/* Datum current->thread.uwinmask contains at all times a bitmask
 	 * where if any user windows are active, at least one bit will
 	 * be set in to mask.  If no user windows are active, the bitmask
 	 * will be all zeroes.
@@ -184,8 +184,8 @@
 	/* Fix users window mask and buffer save count. */
 	mov	0x1, %g5
 	sll	%g5, %g3, %g5
-	st	%g5, [%curptr + AOFF_task_tss + AOFF_thread_uwinmask]		! one live user window still
-	st	%g0, [%curptr + AOFF_task_tss + AOFF_thread_w_saved]		! no windows in the buffer
+	st	%g5, [%curptr + AOFF_task_thread + AOFF_thread_uwinmask]		! one live user window still
+	st	%g0, [%curptr + AOFF_task_thread + AOFF_thread_w_saved]		! no windows in the buffer
 
 	wr	%t_psr, PSR_ET, %psr			! enable traps
 	nop
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/lib/debuglocks.c linux/arch/sparc/lib/debuglocks.c
--- v2.3.15/linux/arch/sparc/lib/debuglocks.c	Fri Aug  6 11:58:00 1999
+++ linux/arch/sparc/lib/debuglocks.c	Tue Aug 31 11:23:29 1999
@@ -1,4 +1,4 @@
-/* $Id: debuglocks.c,v 1.8 1999/08/05 09:49:59 anton Exp $
+/* $Id: debuglocks.c,v 1.9 1999/08/14 03:51:39 anton Exp $
  * debuglocks.c: Debugging versions of SMP locking primitives.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -7,7 +7,7 @@
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/tasks.h>	/* For NR_CPUS */
+#include <linux/threads.h>	/* For NR_CPUS */
 #include <asm/psr.h>
 #include <asm/system.h>
 #include <asm/spinlock.h>
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/Makefile linux/arch/sparc/math-emu/Makefile
--- v2.3.15/linux/arch/sparc/math-emu/Makefile	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/Makefile	Tue Aug 31 11:23:30 1999
@@ -8,19 +8,7 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := math-emu.o
-O_OBJS   := math.o ashldi3.o fabss.o faddd.o faddq.o fadds.o 		\
-		fcmpd.o fcmped.o fcmpeq.o fcmpes.o fcmpq.o fcmps.o	\
-		fdivd.o fdivq.o fdivs.o fdmulq.o fdtoi.o fdtoq.o	\
-		fdtos.o fitoq.o fmovs.o fmuld.o fmulq.o fmuls.o		\
-		fnegs.o fqtod.o fqtoi.o fqtos.o fsmuld.o fsqrtd.o	\
-		fsqrtq.o fsqrts.o fstod.o fstoi.o fstoq.o fsubd.o 	\
-		fsubq.o	fsubs.o
-
-LINKS	 := double.h faddd.c faddq.c fadds.c fdivd.c fdivq.c fdivs.c	\
-		fdtoi.c fitoq.c fmuld.c fmulq.c fmuls.c fqtoi.c		\
-		fsqrtd.c fsqrtq.c fsqrts.c fstoi.c fsubd.c 		\
-		fsubq.c	fsubs.c op-1.h op-2.h op-4.h op-8.h		\
-		op-common.h quad.h single.h soft-fp.h
+O_OBJS   := math.o ashldi3.o
 
 .S.s:
 	$(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s
@@ -28,10 +16,6 @@
 .S.o:
 	$(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
 
-include $(TOPDIR)/Rules.make
-
-symlinks:
-	ln -sf $(patsubst %,../../sparc64/math-emu/%,$(LINKS)) .
+CFLAGS += -I. -I$(TOPDIR)/include/math-emu -w
 
-cleansymlinks:
-	rm -f $(LINKS)
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fabss.c linux/arch/sparc/math-emu/fabss.c
--- v2.3.15/linux/arch/sparc/math-emu/fabss.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fabss.c	Wed Dec 31 16:00:00 1969
@@ -1,12 +0,0 @@
-/* $Id: fabss.c,v 1.8 1999/05/28 13:41:33 jj Exp $
- * arch/sparc/math-emu/fabss.c
- *
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-int FABSS(unsigned long *rd, unsigned long *rs2)
-{
-	rd[0] = rs2[0] & 0x7fffffffUL;
-	return 0;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fcmpd.c linux/arch/sparc/math-emu/fcmpd.c
--- v2.3.15/linux/arch/sparc/math-emu/fcmpd.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fcmpd.c	Wed Dec 31 16:00:00 1969
@@ -1,33 +0,0 @@
-/* $Id: fcmpd.c,v 1.8 1999/05/28 13:41:36 jj Exp $
- * arch/sparc/math-emu/fcmpd.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FCMPD(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A); FP_DECL_D(B);
-	long ret;
-	unsigned long fsr;
-	
-	FP_UNPACK_RAW_DP(A, rs1);
-	FP_UNPACK_RAW_DP(B, rs2);
-	FP_CMP_D(ret, B, A, 3);
-	if (ret == 3 && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
-		FP_SET_EXCEPTION(FP_EX_INVALID);
-	if (!FP_INHIBIT_RESULTS) {
-		if (ret == -1) ret = 2;
-		fsr = *(long *)rd;
-		fsr &= ~0xc00;
-		fsr |= (ret << 10);
-		*(long *)rd = fsr;
-	}
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fcmped.c linux/arch/sparc/math-emu/fcmped.c
--- v2.3.15/linux/arch/sparc/math-emu/fcmped.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fcmped.c	Wed Dec 31 16:00:00 1969
@@ -1,33 +0,0 @@
-/* $Id: fcmped.c,v 1.8 1999/05/28 13:41:38 jj Exp $
- * arch/sparc/math-emu/fcmped.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FCMPED(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A); FP_DECL_D(B);
-	long ret;
-	unsigned long fsr;
-	
-	FP_UNPACK_RAW_DP(A, rs1);
-	FP_UNPACK_RAW_DP(B, rs2);
-	FP_CMP_D(ret, B, A, 3);
-	if (ret == 3)
-		FP_SET_EXCEPTION(FP_EX_INVALID);
-	if (!FP_INHIBIT_RESULTS) {
-		if (ret == -1) ret = 2;
-		fsr = *(long *)rd;
-		fsr &= ~0xc00;
-		fsr |= (ret << 10);
-		*(long *)rd = fsr;
-	}
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fcmpeq.c linux/arch/sparc/math-emu/fcmpeq.c
--- v2.3.15/linux/arch/sparc/math-emu/fcmpeq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fcmpeq.c	Wed Dec 31 16:00:00 1969
@@ -1,33 +0,0 @@
-/* $Id: fcmpeq.c,v 1.8 1999/05/28 13:41:42 jj Exp $
- * arch/sparc/math-emu/fcmpeq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FCMPEQ(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_Q(B);
-	long ret;
-	unsigned long fsr;
-	
-	FP_UNPACK_RAW_QP(A, rs1);
-	FP_UNPACK_RAW_QP(B, rs2);
-	FP_CMP_Q(ret, B, A, 3);
-	if (ret == 3)
-		FP_SET_EXCEPTION(FP_EX_INVALID);
-	if (!FP_INHIBIT_RESULTS) {
-		if (ret == -1) ret = 2;
-		fsr = *(long *)rd;
-		fsr &= ~0xc00;
-		fsr |= (ret << 10);
-		*(long *)rd = fsr;
-	}
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fcmpes.c linux/arch/sparc/math-emu/fcmpes.c
--- v2.3.15/linux/arch/sparc/math-emu/fcmpes.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fcmpes.c	Wed Dec 31 16:00:00 1969
@@ -1,33 +0,0 @@
-/* $Id: fcmpes.c,v 1.8 1999/05/28 13:41:45 jj Exp $
- * arch/sparc/math-emu/fcmpes.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FCMPES(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A); FP_DECL_S(B);
-	long ret;
-	unsigned long fsr;
-	
-	FP_UNPACK_RAW_SP(A, rs1);
-	FP_UNPACK_RAW_SP(B, rs2);
-	FP_CMP_S(ret, B, A, 3);
-	if (ret == 3)
-		FP_SET_EXCEPTION(FP_EX_INVALID);
-	if (!FP_INHIBIT_RESULTS) {
-		if (ret == -1) ret = 2;
-		fsr = *(long *)rd;
-		fsr &= ~0xc00;
-		fsr |= (ret << 10);
-		*(long *)rd = fsr;
-	}
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fcmpq.c linux/arch/sparc/math-emu/fcmpq.c
--- v2.3.15/linux/arch/sparc/math-emu/fcmpq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fcmpq.c	Wed Dec 31 16:00:00 1969
@@ -1,33 +0,0 @@
-/* $Id: fcmpq.c,v 1.8 1999/05/28 13:41:48 jj Exp $
- * arch/sparc/math-emu/fcmpq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FCMPQ(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_Q(B);
-	long ret;
-	unsigned long fsr;
-	
-	FP_UNPACK_RAW_QP(A, rs1);
-	FP_UNPACK_RAW_QP(B, rs2);
-	FP_CMP_Q(ret, B, A, 3);
-	if (ret == 3 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
-		FP_SET_EXCEPTION(FP_EX_INVALID);
-	if (!FP_INHIBIT_RESULTS) {
-		if (ret == -1) ret = 2;
-		fsr = *(long *)rd;
-		fsr &= ~0xc00;
-		fsr |= (ret << 10);
-		*(long *)rd = fsr;
-	}
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fcmps.c linux/arch/sparc/math-emu/fcmps.c
--- v2.3.15/linux/arch/sparc/math-emu/fcmps.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fcmps.c	Wed Dec 31 16:00:00 1969
@@ -1,33 +0,0 @@
-/* $Id: fcmps.c,v 1.8 1999/05/28 13:41:51 jj Exp $
- * arch/sparc/math-emu/fcmps.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FCMPS(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A); FP_DECL_S(B);
-	long ret;
-	unsigned long fsr;
-	
-	FP_UNPACK_RAW_SP(A, rs1);
-	FP_UNPACK_RAW_SP(B, rs2);
-	FP_CMP_S(ret, B, A, 3);
-	if (ret == 3 && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
-		FP_SET_EXCEPTION(FP_EX_INVALID);
-	if (!FP_INHIBIT_RESULTS) {
-		if (ret == -1) ret = 2;
-		fsr = *(long *)rd;
-		fsr &= ~0xc00;
-		fsr |= (ret << 10);
-		*(long *)rd = fsr;
-	}
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fdmulq.c linux/arch/sparc/math-emu/fdmulq.c
--- v2.3.15/linux/arch/sparc/math-emu/fdmulq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fdmulq.c	Wed Dec 31 16:00:00 1969
@@ -1,26 +0,0 @@
-/* $Id: fdmulq.c,v 1.9 1999/05/28 13:41:56 jj Exp $
- * arch/sparc/math-emu/fdmulq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "double.h"
-
-int FDMULQ(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_D(IN); FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
-
-	FP_UNPACK_DP(IN, rs1);
-	FP_CONV(Q,D,4,2,A,IN);
-	FP_UNPACK_DP(IN, rs2);
-	FP_CONV(Q,D,4,2,B,IN);
-	FP_MUL_Q(R, A, B);
-	FP_PACK_QP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fdtoq.c linux/arch/sparc/math-emu/fdtoq.c
--- v2.3.15/linux/arch/sparc/math-emu/fdtoq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fdtoq.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fdtoq.c,v 1.9 1999/05/28 13:42:01 jj Exp $
- * arch/sparc/math-emu/fdtoq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "double.h"
-
-int FDTOQ(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A); FP_DECL_Q(R);
-
-	FP_UNPACK_DP(A, rs2);
-	FP_CONV(Q,D,4,2,R,A);
-	FP_PACK_QP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fdtos.c linux/arch/sparc/math-emu/fdtos.c
--- v2.3.15/linux/arch/sparc/math-emu/fdtos.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fdtos.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fdtos.c,v 1.9 1999/05/28 13:42:03 jj Exp $
- * arch/sparc/math-emu/fdtos.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
-
-int FDTOS(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A); FP_DECL_S(R);
-
-	FP_UNPACK_DP(A, rs2);
-	FP_CONV(S,D,1,2,R,A);
-	FP_PACK_SP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fmovs.c linux/arch/sparc/math-emu/fmovs.c
--- v2.3.15/linux/arch/sparc/math-emu/fmovs.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fmovs.c	Wed Dec 31 16:00:00 1969
@@ -1,12 +0,0 @@
-/* $Id: fmovs.c,v 1.7 1999/05/28 13:42:05 jj Exp $
- * arch/sparc/math-emu/fmovs.c
- *
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-int FMOVS(unsigned long *rd, unsigned long *rs2)
-{
-	rd[0] = rs2[0];
-	return 0;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fnegs.c linux/arch/sparc/math-emu/fnegs.c
--- v2.3.15/linux/arch/sparc/math-emu/fnegs.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fnegs.c	Wed Dec 31 16:00:00 1969
@@ -1,13 +0,0 @@
-/* $Id: fnegs.c,v 1.9 1999/05/28 13:42:06 jj Exp $
- * arch/sparc/math-emu/fnegs.c
- *
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-int FNEGS(unsigned long *rd, unsigned long *rs2)
-{
- 	/* just change the sign bit */
-	rd[0] = rs2[0] ^ 0x80000000UL;
-	return 0;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fqtod.c linux/arch/sparc/math-emu/fqtod.c
--- v2.3.15/linux/arch/sparc/math-emu/fqtod.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fqtod.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fqtod.c,v 1.9 1999/05/28 13:42:08 jj Exp $
- * arch/sparc/math-emu/fqtod.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "double.h"
-
-int FQTOD(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_D(R);
-
-	FP_UNPACK_QP(A, rs2);
-	FP_CONV(D,Q,2,4,R,A);
-	FP_PACK_DP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fqtos.c linux/arch/sparc/math-emu/fqtos.c
--- v2.3.15/linux/arch/sparc/math-emu/fqtos.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fqtos.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fqtos.c,v 1.9 1999/05/28 13:42:10 jj Exp $
- * arch/sparc/math-emu/fqtos.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "single.h"
-
-int FQTOS(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_S(R);
-
-	FP_UNPACK_QP(A, rs2);
-	FP_CONV(S,Q,1,4,R,A);
-	FP_PACK_SP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fsmuld.c linux/arch/sparc/math-emu/fsmuld.c
--- v2.3.15/linux/arch/sparc/math-emu/fsmuld.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fsmuld.c	Wed Dec 31 16:00:00 1969
@@ -1,26 +0,0 @@
-/* $Id: fsmuld.c,v 1.9 1999/05/28 13:42:12 jj Exp $
- * arch/sparc/math-emu/fsmuld.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
-
-int FSMULD(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_S(IN); FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
-
-	FP_UNPACK_SP(IN, rs1);
-	FP_CONV(D,S,2,1,A,IN);
-	FP_UNPACK_SP(IN, rs2);
-	FP_CONV(D,S,2,1,B,IN);
-	FP_MUL_D(R, A, B);
-	FP_PACK_DP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fstod.c linux/arch/sparc/math-emu/fstod.c
--- v2.3.15/linux/arch/sparc/math-emu/fstod.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fstod.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fstod.c,v 1.9 1999/05/28 13:42:14 jj Exp $
- * arch/sparc/math-emu/fstod.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
-
-int FSTOD(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A); FP_DECL_D(R);
-
-	FP_UNPACK_SP(A, rs2);
-	FP_CONV(D,S,2,1,R,A);
-	FP_PACK_DP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/fstoq.c linux/arch/sparc/math-emu/fstoq.c
--- v2.3.15/linux/arch/sparc/math-emu/fstoq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/fstoq.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fstoq.c,v 1.9 1999/05/28 13:42:16 jj Exp $
- * arch/sparc/math-emu/fstoq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 Peter Maydell (pmaydell@chiark.greenend.org.uk)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "single.h"
-
-int FSTOQ(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A); FP_DECL_Q(R);
-
-	FP_UNPACK_SP(A, rs2);
-	FP_CONV(Q,S,4,1,R,A);
-	FP_PACK_QP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/math.c linux/arch/sparc/math-emu/math.c
--- v2.3.15/linux/arch/sparc/math-emu/math.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc/math-emu/math.c	Tue Aug 31 11:23:30 1999
@@ -71,6 +71,9 @@
 
 #include "sfp-util.h"
 #include "soft-fp.h"
+#include "single.h"
+#include "double.h"
+#include "quad.h"
 
 #define FLOATFUNC(x) extern int x(void *,void *,void *)
 
@@ -78,45 +81,45 @@
  * each insn is. This is from the binutils source :->
  */
 /* quadword instructions */
-FLOATFUNC(FSQRTQ);                                /* v8 */
-FLOATFUNC(FADDQ);                                 /* v8 */
-FLOATFUNC(FSUBQ);                                 /* v8 */
-FLOATFUNC(FMULQ);                                 /* v8 */
-FLOATFUNC(FDIVQ);                                 /* v8 */
-FLOATFUNC(FDMULQ);                                /* v8 */
-FLOATFUNC(FQTOS);                                 /* v8 */
-FLOATFUNC(FQTOD);                                 /* v8 */
-FLOATFUNC(FITOQ);                                 /* v8 */
-FLOATFUNC(FSTOQ);                                 /* v8 */
-FLOATFUNC(FDTOQ);                                 /* v8 */
-FLOATFUNC(FQTOI);                                 /* v8 */
-FLOATFUNC(FCMPQ);                                 /* v8 */
-FLOATFUNC(FCMPEQ);                                /* v8 */
+#define FSQRTQ	0x02b		/* v8 */
+#define FADDQ	0x043		/* v8 */
+#define FSUBQ	0x047		/* v8 */
+#define FMULQ	0x04b		/* v8 */
+#define FDIVQ	0x04f		/* v8 */
+#define FDMULQ	0x06e		/* v8 */
+#define FQTOS	0x0c7		/* v8 */
+#define FQTOD	0x0cb		/* v8 */
+#define FITOQ	0x0cc		/* v8 */
+#define FSTOQ	0x0cd		/* v8 */
+#define FDTOQ	0x0ce		/* v8 */
+#define FQTOI	0x0d3		/* v8 */
+#define FCMPQ	0x053		/* v8 */
+#define FCMPEQ	0x057		/* v8 */
 /* single/double instructions (subnormal): should all work */
-FLOATFUNC(FSQRTS);                                /* v7 */
-FLOATFUNC(FSQRTD);                                /* v7 */
-FLOATFUNC(FADDS);                                 /* v6 */
-FLOATFUNC(FADDD);                                 /* v6 */
-FLOATFUNC(FSUBS);                                 /* v6 */
-FLOATFUNC(FSUBD);                                 /* v6 */
-FLOATFUNC(FMULS);                                 /* v6 */
-FLOATFUNC(FMULD);                                 /* v6 */
-FLOATFUNC(FDIVS);                                 /* v6 */
-FLOATFUNC(FDIVD);                                 /* v6 */
-FLOATFUNC(FSMULD);                                /* v8 */
-FLOATFUNC(FDTOS);                                 /* v6 */
-FLOATFUNC(FSTOD);                                 /* v6 */
-FLOATFUNC(FSTOI);                                 /* v6 */
-FLOATFUNC(FDTOI);                                 /* v6 */
-FLOATFUNC(FABSS);                                 /* v6 */
-FLOATFUNC(FCMPS);                                 /* v6 */
-FLOATFUNC(FCMPES);                                /* v6 */
-FLOATFUNC(FCMPD);                                 /* v6 */
-FLOATFUNC(FCMPED);                                /* v6 */
-FLOATFUNC(FMOVS);                                 /* v6 */
-FLOATFUNC(FNEGS);                                 /* v6 */
-FLOATFUNC(FITOS);                                 /* v6 */
-FLOATFUNC(FITOD);                                 /* v6 */
+#define FSQRTS	0x029		/* v7 */
+#define FSQRTD	0x02a		/* v7 */
+#define FADDS	0x041		/* v6 */
+#define FADDD	0x042		/* v6 */
+#define FSUBS	0x045		/* v6 */
+#define FSUBD	0x046		/* v6 */
+#define FMULS	0x049		/* v6 */
+#define FMULD	0x04a		/* v6 */
+#define FDIVS	0x04d		/* v6 */
+#define FDIVD	0x04e		/* v6 */
+#define FSMULD	0x069		/* v6 */
+#define FDTOS	0x0c6		/* v6 */
+#define FSTOD	0x0c9		/* v6 */
+#define FSTOI	0x0d1		/* v6 */
+#define FDTOI	0x0d2		/* v6 */
+#define FABSS	0x009		/* v6 */
+#define FCMPS	0x051		/* v6 */
+#define FCMPES	0x055		/* v6 */
+#define FCMPD	0x052		/* v6 */
+#define FCMPED	0x056		/* v6 */
+#define FMOVS	0x001		/* v6 */
+#define FNEGS	0x005		/* v6 */
+#define FITOS	0x0c4		/* v6 */
+#define FITOD	0x0c8		/* v6 */
 
 #define FSR_TEM_SHIFT	23UL
 #define FSR_TEM_MASK	(0x1fUL << FSR_TEM_SHIFT)
@@ -162,18 +165,18 @@
 
 #ifdef DEBUG_MATHEMU
 	printk("In do_mathemu()... pc is %08lx\n", regs->pc);
-	printk("fpqdepth is %ld\n", fpt->tss.fpqdepth);
-	for (i = 0; i < fpt->tss.fpqdepth; i++)
-		printk("%d: %08lx at %08lx\n", i, fpt->tss.fpqueue[i].insn,
-		       (unsigned long)fpt->tss.fpqueue[i].insn_addr);
+	printk("fpqdepth is %ld\n", fpt->thread.fpqdepth);
+	for (i = 0; i < fpt->thread.fpqdepth; i++)
+		printk("%d: %08lx at %08lx\n", i, fpt->thread.fpqueue[i].insn,
+		       (unsigned long)fpt->thread.fpqueue[i].insn_addr);
 #endif
 
-	if (fpt->tss.fpqdepth == 0) {                   /* no queue, guilty insn is at regs->pc */
+	if (fpt->thread.fpqdepth == 0) {                   /* no queue, guilty insn is at regs->pc */
 #ifdef DEBUG_MATHEMU
 		printk("precise trap at %08lx\n", regs->pc);
 #endif
 		if (!get_user(insn, (u32 *)regs->pc)) {
-			retcode = do_one_mathemu(insn, &fpt->tss.fsr, fpt->tss.float_regs);
+			retcode = do_one_mathemu(insn, &fpt->thread.fsr, fpt->thread.float_regs);
 			if (retcode) {
 				/* in this case we need to fix up PC & nPC */
 				regs->pc = regs->npc;
@@ -184,17 +187,17 @@
 	}
 
 	/* Normal case: need to empty the queue... */
-	for (i = 0; i < fpt->tss.fpqdepth; i++) {
-		retcode = do_one_mathemu(fpt->tss.fpqueue[i].insn, &(fpt->tss.fsr), fpt->tss.float_regs);
+	for (i = 0; i < fpt->thread.fpqdepth; i++) {
+		retcode = do_one_mathemu(fpt->thread.fpqueue[i].insn, &(fpt->thread.fsr), fpt->thread.float_regs);
 		if (!retcode)                               /* insn failed, no point doing any more */
 			break;
 	}
 	/* Now empty the queue and clear the queue_not_empty flag */
 	if(retcode)
-		fpt->tss.fsr &= ~(0x3000 | FSR_CEXC_MASK);
+		fpt->thread.fsr &= ~(0x3000 | FSR_CEXC_MASK);
 	else
-		fpt->tss.fsr &= ~0x3000;
-	fpt->tss.fpqdepth = 0;
+		fpt->thread.fsr &= ~0x3000;
+	fpt->thread.fpqdepth = 0;
 
 	return retcode;
 }
@@ -207,7 +210,7 @@
  *
  * We return 0 if a SIGFPE should be sent, 1 otherwise.
  */
-static int record_exception(unsigned long *pfsr, int eflag)
+static inline int record_exception(unsigned long *pfsr, int eflag)
 {
 	unsigned long fsr = *pfsr;
 	int would_trap;
@@ -259,19 +262,28 @@
 	return (would_trap ? 0 : 1);
 }
 
-static int do_one_mathemu(u32 insn, unsigned long *fsr, unsigned long *fregs)
+typedef union {
+	u32 s;
+	u64 d;
+	u64 q[2];
+} *argp;
+
+static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs)
 {
 	/* Emulate the given insn, updating fsr and fregs appropriately. */
 	int type = 0;
-	/* 01 is single, 10 is double, 11 is quad,
-	 * 000011 is rs1, 001100 is rs2, 110000 is rd (00 in rd is fcc)
-	 * 111100000000 tells which ftt that may happen in
-	 * (this field not used on sparc32 code, as we can't
-	 * extract trap type info for ops on the FP queue)
-	 */
-	int freg, eflag;
-	int (*func)(void *,void *,void *) = NULL;
-	void *rs1 = NULL, *rs2 = NULL, *rd = NULL;
+	/* r is rd, b is rs2 and a is rs1. The *u arg tells
+	   whether the argument should be packed/unpacked (0 - do not unpack/pack, 1 - unpack/pack)
+	   non-u args tells the size of the argument (0 - no argument, 1 - single, 2 - double, 3 - quad */
+#define TYPE(dummy, r, ru, b, bu, a, au) type = (au << 2) | (a << 0) | (bu << 5) | (b << 3) | (ru << 8) | (r << 6)
+	int freg;
+	argp rs1 = NULL, rs2 = NULL, rd = NULL;
+	FP_DECL_EX;
+	FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
+	FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
+	FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR);
+	int IR;
+	long fsr;
 
 #ifdef DEBUG_MATHEMU
 	printk("In do_mathemu(), emulating %08lx\n", insn);
@@ -279,38 +291,38 @@
 
 	if ((insn & 0xc1f80000) == 0x81a00000)	/* FPOP1 */ {
 		switch ((insn >> 5) & 0x1ff) {
-		/* QUAD - ftt == 3 */
-		case 0x001: type = 0x314; func = FMOVS; break;
-		case 0x005: type = 0x314; func = FNEGS; break;
-		case 0x009: type = 0x314; func = FABSS; break;
-		case 0x02b: type = 0x33c; func = FSQRTQ; break;
-		case 0x043: type = 0x33f; func = FADDQ; break;
-		case 0x047: type = 0x33f; func = FSUBQ; break;
-		case 0x04b: type = 0x33f; func = FMULQ; break;
-		case 0x04f: type = 0x33f; func = FDIVQ; break;
-		case 0x06e: type = 0x33a; func = FDMULQ; break;
-		case 0x0c7: type = 0x31c; func = FQTOS; break;
-		case 0x0cb: type = 0x32c; func = FQTOD; break;
-		case 0x0cc: type = 0x334; func = FITOQ; break;
-		case 0x0cd: type = 0x334; func = FSTOQ; break;
-		case 0x0ce: type = 0x338; func = FDTOQ; break;
-		case 0x0d3: type = 0x31c; func = FQTOI; break;
-		/* SUBNORMAL - ftt == 2 */
-		case 0x029: type = 0x214; func = FSQRTS; break;
-		case 0x02a: type = 0x228; func = FSQRTD; break;
-		case 0x041: type = 0x215; func = FADDS; break;
-		case 0x042: type = 0x22a; func = FADDD; break;
-		case 0x045: type = 0x215; func = FSUBS; break;
-		case 0x046: type = 0x22a; func = FSUBD; break;
-		case 0x049: type = 0x215; func = FMULS; break;
-		case 0x04a: type = 0x22a; func = FMULD; break;
-		case 0x04d: type = 0x215; func = FDIVS; break;
-		case 0x04e: type = 0x22a; func = FDIVD; break;
-		case 0x069: type = 0x225; func = FSMULD; break;
-		case 0x0c6: type = 0x218; func = FDTOS; break;
-		case 0x0c9: type = 0x224; func = FSTOD; break;
-		case 0x0d1: type = 0x214; func = FSTOI; break;
-		case 0x0d2: type = 0x218; func = FDTOI; break;
+		case FSQRTQ: TYPE(3,3,1,3,1,0,0); break;
+		case FADDQ:
+		case FSUBQ:
+		case FMULQ:
+		case FDIVQ: TYPE(3,3,1,3,1,3,1); break;
+		case FDMULQ: TYPE(3,3,1,2,1,2,1); break;
+		case FQTOS: TYPE(3,1,1,3,1,0,0); break;
+		case FQTOD: TYPE(3,2,1,3,1,0,0); break;
+		case FITOQ: TYPE(3,3,1,1,0,0,0); break;
+		case FSTOQ: TYPE(3,3,1,1,1,0,0); break;
+		case FDTOQ: TYPE(3,3,1,2,1,0,0); break;
+		case FQTOI: TYPE(3,1,0,3,1,0,0); break;
+		case FSQRTS: TYPE(2,1,1,1,1,0,0); break;
+		case FSQRTD: TYPE(2,2,1,2,1,0,0); break;
+		case FADDD:
+		case FSUBD:
+		case FMULD:
+		case FDIVD: TYPE(2,2,1,2,1,2,1); break;
+		case FADDS:
+		case FSUBS:
+		case FMULS:
+		case FDIVS: TYPE(2,1,1,1,1,1,1); break;
+		case FSMULD: TYPE(2,2,1,1,1,1,1); break;
+		case FDTOS: TYPE(2,1,1,2,1,0,0); break;
+		case FSTOD: TYPE(2,2,1,1,1,0,0); break;
+		case FSTOI: TYPE(2,1,0,1,1,0,0); break;
+		case FDTOI: TYPE(2,1,0,2,1,0,0); break;
+		case FITOS: TYPE(2,1,1,1,0,0,0); break;
+		case FITOD: TYPE(2,2,1,1,0,0,0); break;
+		case FMOVS:
+		case FABSS:
+		case FNEGS: TYPE(2,1,0,1,0,0,0); break;
 		default:
 #ifdef DEBUG_MATHEMU
 			printk("unknown FPop1: %03lx\n",(insn>>5)&0x1ff);
@@ -318,12 +330,12 @@
 		}
 	} else if ((insn & 0xc1f80000) == 0x81a80000)	/* FPOP2 */ {
 		switch ((insn >> 5) & 0x1ff) {
-		case 0x051: type = 0x305; func = FCMPS; break;
-		case 0x052: type = 0x30a; func = FCMPD; break;
-		case 0x053: type = 0x30f; func = FCMPQ; break;
-		case 0x055: type = 0x305; func = FCMPES; break;
-		case 0x056: type = 0x30a; func = FCMPED; break;
-		case 0x057: type = 0x30f; func = FCMPEQ; break;
+		case FCMPS: TYPE(3,0,0,1,1,1,1); break;
+		case FCMPES: TYPE(3,0,0,1,1,1,1); break;
+		case FCMPD: TYPE(3,0,0,2,1,2,1); break;
+		case FCMPED: TYPE(3,0,0,2,1,2,1); break;
+		case FCMPQ: TYPE(3,0,0,3,1,3,1); break;
+		case FCMPEQ: TYPE(3,0,0,3,1,3,1); break;
 		default:
 #ifdef DEBUG_MATHEMU
 			printk("unknown FPop2: %03lx\n",(insn>>5)&0x1ff);
@@ -332,67 +344,78 @@
 	}
 
 	if (!type) {	/* oops, didn't recognise that FPop */
+#ifdef DEBUG_MATHEMU
 		printk("attempt to emulate unrecognised FPop!\n");
+#endif
 		return 0;
 	}
 
 	/* Decode the registers to be used */
-	freg = (*fsr >> 14) & 0xf;
-
-	*fsr &= ~0x1c000;				/* clear the traptype bits */
+	freg = (*pfsr >> 14) & 0xf;
 
+	*pfsr &= ~0x1c000;				/* clear the traptype bits */
+	
 	freg = ((insn >> 14) & 0x1f);
 	switch (type & 0x3) {				/* is rs1 single, double or quad? */
 	case 3:
 		if (freg & 3) {				/* quadwords must have bits 4&5 of the */
 							/* encoded reg. number set to zero. */
-			*fsr |= (6 << 14);
+			*pfsr |= (6 << 14);
 			return 0;			/* simulate invalid_fp_register exception */
 		}
 	/* fall through */
 	case 2:
 		if (freg & 1) {				/* doublewords must have bit 5 zeroed */
-			*fsr |= (6 << 14);
+			*pfsr |= (6 << 14);
 			return 0;
 		}
 	}
-	rs1 = (void *)&fregs[freg];
+	rs1 = (argp)&fregs[freg];
+	switch (type & 0x7) {
+	case 7: FP_UNPACK_QP (QA, rs1); break;
+	case 6: FP_UNPACK_DP (DA, rs1); break;
+	case 5: FP_UNPACK_SP (SA, rs1); break;
+	}
 	freg = (insn & 0x1f);
-	switch ((type >> 2) & 0x3) {			/* same again for rs2 */
+	switch ((type >> 3) & 0x3) {			/* same again for rs2 */
 	case 3:
 		if (freg & 3) {				/* quadwords must have bits 4&5 of the */
 							/* encoded reg. number set to zero. */
-			*fsr |= (6 << 14);
+			*pfsr |= (6 << 14);
 			return 0;			/* simulate invalid_fp_register exception */
 		}
 	/* fall through */
 	case 2:
 		if (freg & 1) {				/* doublewords must have bit 5 zeroed */
-			*fsr |= (6 << 14);
+			*pfsr |= (6 << 14);
 			return 0;
 		}
 	}
-	rs2 = (void *)&fregs[freg];
+	rs2 = (argp)&fregs[freg];
+	switch ((type >> 3) & 0x7) {
+	case 7: FP_UNPACK_QP (QB, rs2); break;
+	case 6: FP_UNPACK_DP (DB, rs2); break;
+	case 5: FP_UNPACK_SP (SB, rs2); break;
+	}
 	freg = ((insn >> 25) & 0x1f);
-	switch ((type >> 4) & 0x3) {			/* and finally rd. This one's a bit different */
+	switch ((type >> 6) & 0x3) {			/* and finally rd. This one's a bit different */
 	case 0:						/* dest is fcc. (this must be FCMPQ or FCMPEQ) */
 		if (freg) {				/* V8 has only one set of condition codes, so */
 							/* anything but 0 in the rd field is an error */
-			*fsr |= (6 << 14);		/* (should probably flag as invalid opcode */
+			*pfsr |= (6 << 14);		/* (should probably flag as invalid opcode */
 			return 0;			/* but SIGFPE will do :-> ) */
 		}
-		rd = (void *)(fsr);			/* FCMPQ and FCMPEQ are special and only  */
-		break;					/* set bits they're supposed to :-> */
+		break;
 	case 3:
 		if (freg & 3) {				/* quadwords must have bits 4&5 of the */
 							/* encoded reg. number set to zero. */
-			*fsr |= (6 << 14);
+			*pfsr |= (6 << 14);
 			return 0;			/* simulate invalid_fp_register exception */
 		}
 	/* fall through */
 	case 2:
 		if (freg & 1) {				/* doublewords must have bit 5 zeroed */
-			*fsr |= (6 << 14);
+			*pfsr |= (6 << 14);
 			return 0;
 		}
 	/* fall through */
@@ -403,8 +426,94 @@
 #ifdef DEBUG_MATHEMU
 	printk("executing insn...\n");
 #endif
-	eflag = func(rd, rs2, rs1);			/* do the Right Thing */
-	if(eflag == 0)
+	/* do the Right Thing */
+	switch ((insn >> 5) & 0x1ff) {
+	/* + */
+	case FADDS: FP_ADD_S (SR, SA, SB); break;
+	case FADDD: FP_ADD_D (DR, DA, DB); break;
+	case FADDQ: FP_ADD_Q (QR, QA, QB); break;
+	/* - */
+	case FSUBS: FP_SUB_S (SR, SA, SB); break;
+	case FSUBD: FP_SUB_D (DR, DA, DB); break;
+	case FSUBQ: FP_SUB_Q (QR, QA, QB); break;
+	/* * */
+	case FMULS: FP_MUL_S (SR, SA, SB); break;
+	case FSMULD: FP_CONV (D, S, 2, 1, DA, SA);
+		     FP_CONV (D, S, 2, 1, DB, SB);
+	case FMULD: FP_MUL_D (DR, DA, DB); break;
+	case FDMULQ: FP_CONV (Q, D, 4, 2, QA, DA);
+		     FP_CONV (Q, D, 4, 2, QB, DB);
+	case FMULQ: FP_MUL_Q (QR, QA, QB); break;
+	/* / */
+	case FDIVS: FP_DIV_S (SR, SA, SB); break;
+	case FDIVD: FP_DIV_D (DR, DA, DB); break;
+	case FDIVQ: FP_DIV_Q (QR, QA, QB); break;
+	/* sqrt */
+	case FSQRTS: FP_SQRT_S (SR, SB); break;
+	case FSQRTD: FP_SQRT_D (DR, DB); break;
+	case FSQRTQ: FP_SQRT_Q (QR, QB); break;
+	/* mov */
+	case FMOVS: rd->s = rs2->s; break;
+	case FABSS: rd->s = rs2->s & 0x7fffffff; break;
+	case FNEGS: rd->s = rs2->s ^ 0x80000000; break;
+	/* float to int */
+	case FSTOI: FP_TO_INT_S (IR, SB, 32, 1); break;
+	case FDTOI: FP_TO_INT_D (IR, DB, 32, 1); break;
+	case FQTOI: FP_TO_INT_Q (IR, QB, 32, 1); break;
+	/* int to float */
+	case FITOS: IR = rs2->s; FP_FROM_INT_S (SR, IR, 32, int); break;
+	case FITOD: IR = rs2->s; FP_FROM_INT_D (DR, IR, 32, int); break;
+	case FITOQ: IR = rs2->s; FP_FROM_INT_Q (QR, IR, 32, int); break;
+	/* float to float */
+	case FSTOD: FP_CONV (D, S, 2, 1, DR, SB); break;
+	case FSTOQ: FP_CONV (Q, S, 4, 1, QR, SB); break;
+	case FDTOQ: FP_CONV (Q, D, 4, 2, QR, DB); break;
+	case FDTOS: FP_CONV (S, D, 1, 2, SR, DB); break;
+	case FQTOS: FP_CONV (S, Q, 1, 4, SR, QB); break;
+	case FQTOD: FP_CONV (D, Q, 2, 4, DR, QB); break;
+	/* comparison */
+	case FCMPS:
+	case FCMPES:
+		FP_CMP_S(IR, SB, SA, 3);
+		if (IR == 3 &&
+		    (((insn >> 5) & 0x1ff) == FCMPES ||
+		     FP_ISSIGNAN_S(SA) ||
+		     FP_ISSIGNAN_S(SB)))
+			FP_SET_EXCEPTION (FP_EX_INVALID);
+		break;
+	case FCMPD:
+	case FCMPED:
+		FP_CMP_D(IR, DB, DA, 3);
+		if (IR == 3 &&
+		    (((insn >> 5) & 0x1ff) == FCMPED ||
+		     FP_ISSIGNAN_D(DA) ||
+		     FP_ISSIGNAN_D(DB)))
+			FP_SET_EXCEPTION (FP_EX_INVALID);
+		break;
+	case FCMPQ:
+	case FCMPEQ:
+		FP_CMP_Q(IR, QB, QA, 3);
+		if (IR == 3 &&
+		    (((insn >> 5) & 0x1ff) == FCMPEQ ||
+		     FP_ISSIGNAN_Q(QA) ||
+		     FP_ISSIGNAN_Q(QB)))
+			FP_SET_EXCEPTION (FP_EX_INVALID);
+	}
+	if (!FP_INHIBIT_RESULTS) {
+		switch ((type >> 6) & 0x7) {
+		case 0: fsr = *pfsr;
+			if (IR == -1) IR = 2;
+			/* fcc is always fcc0 */
+			fsr &= ~0xc00; fsr |= (IR << 10); break;
+			*pfsr = fsr;
+			break;
+		case 1: rd->s = IR; break;
+		case 5: FP_PACK_SP (rd, SR); break;
+		case 6: FP_PACK_DP (rd, DR); break;
+		case 7: FP_PACK_QP (rd, QR); break;
+		}
+	}
+	if(_fex == 0)
 		return 1;				/* success! */
-	return record_exception(fsr, eflag);
+	return record_exception(pfsr, _fex);
 }
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/math-emu/sfp-machine.h linux/arch/sparc/math-emu/sfp-machine.h
--- v2.3.15/linux/arch/sparc/math-emu/sfp-machine.h	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc/math-emu/sfp-machine.h	Tue Aug 31 11:23:30 1999
@@ -31,7 +31,7 @@
 #define _FP_I_TYPE		long
 
 #define _FP_MUL_MEAT_S(R,X,Y)					\
-  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y)
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
 #define _FP_MUL_MEAT_D(R,X,Y)					\
   _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
 #define _FP_MUL_MEAT_Q(R,X,Y)					\
@@ -181,9 +181,9 @@
 /* Obtain the current rounding mode. */
 #ifndef FP_ROUNDMODE
 #ifdef __SMP__
-#define FP_ROUNDMODE	((current->tss.fsr >> 30) & 0x3)
+#define FP_ROUNDMODE	((current->thread.fsr >> 30) & 0x3)
 #else
-#define FP_ROUNDMODE	((last_task_used_math->tss.fsr >> 30) & 0x3)
+#define FP_ROUNDMODE	((last_task_used_math->thread.fsr >> 30) & 0x3)
 #endif
 #endif
 
@@ -197,9 +197,9 @@
 #define FP_HANDLE_EXCEPTIONS return _fex
 
 #ifdef __SMP__
-#define FP_INHIBIT_RESULTS ((current->tss.fsr >> 23) & _fex)
+#define FP_INHIBIT_RESULTS ((current->thread.fsr >> 23) & _fex)
 #else
-#define FP_INHIBIT_RESULTS ((last_task_used_math->tss.fsr >> 23) & _fex)
+#define FP_INHIBIT_RESULTS ((last_task_used_math->thread.fsr >> 23) & _fex)
 #endif
 
 #endif
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/Makefile linux/arch/sparc/mm/Makefile
--- v2.3.15/linux/arch/sparc/mm/Makefile	Wed Mar 10 16:53:36 1999
+++ linux/arch/sparc/mm/Makefile	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.33 1999/01/02 16:45:47 davem Exp $
+# $Id: Makefile,v 1.34 1999/08/14 03:51:42 anton Exp $
 # Makefile for the linux Sparc-specific parts of the memory manager.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -8,7 +8,10 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := mm.o
-O_OBJS   := fault.o init.o loadmmu.o generic.o asyncd.o extable.o btfixup.o
+O_OBJS   := fault.o init.o loadmmu.o generic.o extable.o btfixup.o
+ifeq ($(CONFIG_AP1000),y)
+O_OBJS	 += asyncd.o
+endif
 ifeq ($(CONFIG_SUN4),y)
 O_OBJS	 += nosrmmu.o
 else
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/asyncd.c linux/arch/sparc/mm/asyncd.c
--- v2.3.15/linux/arch/sparc/mm/asyncd.c	Wed Aug  4 15:39:46 1999
+++ linux/arch/sparc/mm/asyncd.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/*  $Id: asyncd.c,v 1.16 1999/08/04 03:19:16 davem Exp $
+/*  $Id: asyncd.c,v 1.17 1999/08/14 03:51:44 anton Exp $
  *  The asyncd kernel daemon. This handles paging on behalf of 
  *  processes that receive page faults due to remote (async) memory
  *  accesses. 
@@ -178,8 +178,8 @@
 	
 bad_area:	  
 	stats.failure++;
-	tsk->tss.sig_address = address;
-	tsk->tss.sig_desc = SUBSIG_NOMAPPING;
+	tsk->thread.sig_address = address;
+	tsk->thread.sig_desc = SUBSIG_NOMAPPING;
 	send_sig(SIGSEGV, tsk, 1);
 	return 1;
 }
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/btfixup.c linux/arch/sparc/mm/btfixup.c
--- v2.3.15/linux/arch/sparc/mm/btfixup.c	Tue Apr 14 17:44:20 1998
+++ linux/arch/sparc/mm/btfixup.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: btfixup.c,v 1.7 1998/03/09 14:03:56 jj Exp $
+/* $Id: btfixup.c,v 1.8 1999/08/31 06:54:31 davem Exp $
  * btfixup.c: Boot time code fixup and relocator, so that
  * we can get rid of most indirect calls to achieve single
  * image sun4c and srmmu kernel.
@@ -48,7 +48,7 @@
 static char wrong_setaddr[] __initdata = "Garbled CALL/INT patch at %p[%08x,%08x,%08x]=%08x\n";
 
 #ifdef BTFIXUP_OPTIMIZE_OTHER
-__initfunc(static void set_addr(unsigned int *addr, unsigned int q1, int fmangled, unsigned int value))
+static void __init set_addr(unsigned int *addr, unsigned int q1, int fmangled, unsigned int value)
 {
 	if (!fmangled)
 		*addr = value;
@@ -74,7 +74,7 @@
 }
 #endif
 
-__initfunc(void btfixup(void))
+void __init btfixup(void)
 {
 	unsigned int *p, *q;
 	int type, count;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c
--- v2.3.15/linux/arch/sparc/mm/fault.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc/mm/fault.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.106 1999/07/30 09:35:07 davem Exp $
+/* $Id: fault.c,v 1.107 1999/08/14 03:51:46 anton Exp $
  * fault.c:  Page fault handlers for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -12,7 +12,7 @@
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/mman.h>
-#include <linux/tasks.h>
+#include <linux/threads.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/mm.h>
@@ -280,8 +280,8 @@
 		printk("Fault whee %s [%d]: segfaults at %08lx pc=%08lx\n",
 		       tsk->comm, tsk->pid, address, regs->pc);
 #endif
-		tsk->tss.sig_address = address;
-		tsk->tss.sig_desc = SUBSIG_NOMAPPING;
+		tsk->thread.sig_address = address;
+		tsk->thread.sig_desc = SUBSIG_NOMAPPING;
 		force_sig(SIGSEGV, tsk);
 		return;
 	}
@@ -290,8 +290,8 @@
 
 do_sigbus:
 	up(&mm->mmap_sem);
-	tsk->tss.sig_address = address;
-	tsk->tss.sig_desc = SUBSIG_MISCERROR;
+	tsk->thread.sig_address = address;
+	tsk->thread.sig_desc = SUBSIG_MISCERROR;
 	force_sig(SIGBUS, tsk);
 	if (! from_user)
 		goto do_kernel_fault;
@@ -399,15 +399,15 @@
 	printk("Window whee %s [%d]: segfaults at %08lx\n",
 	       tsk->comm, tsk->pid, address);
 #endif
-	tsk->tss.sig_address = address;
-	tsk->tss.sig_desc = SUBSIG_NOMAPPING;
+	tsk->thread.sig_address = address;
+	tsk->thread.sig_desc = SUBSIG_NOMAPPING;
 	send_sig(SIGSEGV, tsk, 1);
 	return;
 
 do_sigbus:
 	up(&mm->mmap_sem);
-	tsk->tss.sig_address = address;
-	tsk->tss.sig_desc = SUBSIG_MISCERROR;
+	tsk->thread.sig_address = address;
+	tsk->thread.sig_desc = SUBSIG_MISCERROR;
 	force_sig(SIGBUS, tsk);
 }
 
@@ -416,7 +416,7 @@
 	unsigned long sp;
 
 	lock_kernel();
-	sp = current->tss.rwbuf_stkptrs[0];
+	sp = current->thread.rwbuf_stkptrs[0];
 	if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
 		force_user_fault(sp + 0x38, 1);
 	force_user_fault(sp, 1);
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/hypersparc.S linux/arch/sparc/mm/hypersparc.S
--- v2.3.15/linux/arch/sparc/mm/hypersparc.S	Tue Apr 14 17:44:20 1998
+++ linux/arch/sparc/mm/hypersparc.S	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: hypersparc.S,v 1.13 1998/02/13 15:35:09 jj Exp $
+/* $Id: hypersparc.S,v 1.14 1999/08/14 03:51:47 anton Exp $
  * hypersparc.S: High speed Hypersparc mmu/cache operations.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -13,7 +13,7 @@
 
 #define WINDOW_FLUSH(tmp1, tmp2)					\
 	mov	0, tmp1;						\
-98:	ld	[%g6 + AOFF_task_tss + AOFF_thread_uwinmask], tmp2;	\
+98:	ld	[%g6 + AOFF_task_thread + AOFF_thread_uwinmask], tmp2;	\
 	orcc	%g0, tmp2, %g0;						\
 	add	tmp1, 1, tmp1;						\
 	bne	98b;							\
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- v2.3.15/linux/arch/sparc/mm/init.c	Tue Jun 29 09:22:08 1999
+++ linux/arch/sparc/mm/init.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.67 1999/06/29 12:33:59 davem Exp $
+/*  $Id: init.c,v 1.68 1999/08/31 06:54:32 davem Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -113,7 +113,7 @@
 
 extern pgprot_t protection_map[16];
 
-__initfunc(unsigned long sparc_context_init(unsigned long start_mem, int numctx))
+unsigned long __init sparc_context_init(unsigned long start_mem, int numctx)
 {
 	int ctx;
 
@@ -142,8 +142,8 @@
 extern unsigned long srmmu_paging_init(unsigned long, unsigned long);
 extern unsigned long device_scan(unsigned long);
 
-__initfunc(unsigned long 
-paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init
+paging_init(unsigned long start_mem, unsigned long end_mem)
 {
 	switch(sparc_cpu_model) {
 	case sun4c:
@@ -202,7 +202,7 @@
 
 int physmem_mapped_contig __initdata = 1;
 
-__initfunc(static void taint_real_pages(unsigned long start_mem, unsigned long end_mem))
+static void __init taint_real_pages(unsigned long start_mem, unsigned long end_mem)
 {
 	unsigned long addr, tmp2 = 0;
 
@@ -234,7 +234,7 @@
 	}
 }
 
-__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
+void __init mem_init(unsigned long start_mem, unsigned long end_mem)
 {
 	int codepages = 0;
 	int datapages = 0;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/io-unit.c linux/arch/sparc/mm/io-unit.c
--- v2.3.15/linux/arch/sparc/mm/io-unit.c	Sun Jul 25 13:45:25 1999
+++ linux/arch/sparc/mm/io-unit.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: io-unit.c,v 1.13 1998/11/08 11:13:57 davem Exp $
+/* $Id: io-unit.c,v 1.14 1999/08/31 06:54:33 davem Exp $
  * io-unit.c:  IO-UNIT specific routines for memory management.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek    (jj@sunsite.mff.cuni.cz)
@@ -26,8 +26,8 @@
 #define IOPERM        (IOUPTE_CACHE | IOUPTE_WRITE | IOUPTE_VALID)
 #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM)
 
-__initfunc(void
-iounit_init(int sbi_node, int io_node, struct linux_sbus *sbus))
+void __init
+iounit_init(int sbi_node, int io_node, struct linux_sbus *sbus)
 {
 	iopte_t *xpt, *xptend;
 	struct iounit_struct *iounit;
@@ -217,7 +217,7 @@
 /* FIXME: Write this */
 }
 
-__initfunc(void ld_mmu_iounit(void))
+void __init ld_mmu_iounit(void)
 {
 	BTFIXUPSET_CALL(mmu_lockarea, iounit_lockarea, BTFIXUPCALL_RETO0);
 	BTFIXUPSET_CALL(mmu_unlockarea, iounit_unlockarea, BTFIXUPCALL_NOP);
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/iommu.c linux/arch/sparc/mm/iommu.c
--- v2.3.15/linux/arch/sparc/mm/iommu.c	Sun Jul 25 13:45:25 1999
+++ linux/arch/sparc/mm/iommu.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: iommu.c,v 1.10 1999/05/07 17:03:34 jj Exp $
+/* $Id: iommu.c,v 1.11 1999/08/31 06:54:34 davem Exp $
  * iommu.c:  IOMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -44,8 +44,8 @@
 	}
 }
 
-__initfunc(void
-iommu_init(int iommund, struct linux_sbus *sbus))
+void __init
+iommu_init(int iommund, struct linux_sbus *sbus)
 {
 	unsigned int impl, vers, ptsize;
 	unsigned long tmp;
@@ -264,7 +264,7 @@
 {
 }
 
-__initfunc(void ld_mmu_iommu(void))
+void __init ld_mmu_iommu(void)
 {
 	viking_flush = (BTFIXUPVAL_CALL(flush_page_for_dma) == (unsigned long)viking_flush_page);
 	BTFIXUPSET_CALL(mmu_lockarea, iommu_lockarea, BTFIXUPCALL_RETO0);
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/loadmmu.c linux/arch/sparc/mm/loadmmu.c
--- v2.3.15/linux/arch/sparc/mm/loadmmu.c	Tue Apr 14 17:44:20 1998
+++ linux/arch/sparc/mm/loadmmu.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: loadmmu.c,v 1.50 1998/02/05 14:19:02 jj Exp $
+/* $Id: loadmmu.c,v 1.51 1999/08/31 06:54:35 davem Exp $
  * loadmmu.c:  This code loads up all the mm function pointers once the
  *             machine type has been determined.  It also sets the static
  *             mmu values such as PAGE_NONE, etc.
@@ -31,7 +31,7 @@
 extern void ld_mmu_sun4c(void);
 extern void ld_mmu_srmmu(void);
 
-__initfunc(void load_mmu(void))
+void __init load_mmu(void)
 {
 	switch(sparc_cpu_model) {
 	case sun4c:
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/nosrmmu.c linux/arch/sparc/mm/nosrmmu.c
--- v2.3.15/linux/arch/sparc/mm/nosrmmu.c	Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc/mm/nosrmmu.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: nosrmmu.c,v 1.2 1999/03/30 10:17:39 jj Exp $
+/* $Id: nosrmmu.c,v 1.3 1999/08/31 06:54:35 davem Exp $
  * nosrmmu.c: This file is a bunch of dummies for sun4 compiles, 
  *         so that it does not need srmmu and avoid ifdefs.
  *
@@ -14,24 +14,24 @@
 
 enum mbus_module srmmu_modtype;
 
-__initfunc(static void should_not_happen(void))
+static void __init should_not_happen(void)
 {
 	prom_printf(shouldnothappen);
 	prom_halt();
 }
 
-__initfunc(void srmmu_frob_mem_map(unsigned long start_mem))
+void __init srmmu_frob_mem_map(unsigned long start_mem)
 {
 	should_not_happen();
 }
 
-__initfunc(unsigned long srmmu_paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init srmmu_paging_init(unsigned long start_mem, unsigned long end_mem)
 {
 	should_not_happen();
 	return 0;
 }
 
-__initfunc(void ld_mmu_srmmu(void))
+void __init ld_mmu_srmmu(void)
 {
 	should_not_happen();
 }
@@ -44,7 +44,7 @@
 {
 }
 
-__initfunc(void srmmu_end_memory(unsigned long memory_size, unsigned long *mem_end_p))
+void __init srmmu_end_memory(unsigned long memory_size, unsigned long *mem_end_p)
 {
 	return 0;
 }
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/nosun4c.c linux/arch/sparc/mm/nosun4c.c
--- v2.3.15/linux/arch/sparc/mm/nosun4c.c	Tue Apr 14 17:44:20 1998
+++ linux/arch/sparc/mm/nosun4c.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: nosun4c.c,v 1.1 1998/03/09 14:04:16 jj Exp $
+/* $Id: nosun4c.c,v 1.2 1999/08/31 06:54:36 davem Exp $
  * nosun4c.c: This file is a bunch of dummies for SMP compiles, 
  *         so that it does not need sun4c and avoid ifdefs.
  *
@@ -23,19 +23,19 @@
 unsigned long sun4c_kernel_faults;
 unsigned long *sun4c_memerr_reg;
 
-__initfunc(static void should_not_happen(void))
+static void __init should_not_happen(void)
 {
 	prom_printf(shouldnothappen);
 	prom_halt();
 }
 
-__initfunc(unsigned long sun4c_paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init sun4c_paging_init(unsigned long start_mem, unsigned long end_mem)
 {
 	should_not_happen();
 	return 0;
 }
 
-__initfunc(void ld_mmu_sun4c(void))
+void __init ld_mmu_sun4c(void)
 {
 	should_not_happen();
 }
@@ -66,12 +66,12 @@
 {
 }
 
-__initfunc(void sun4c_probe_vac(void))
+void __init sun4c_probe_vac(void)
 {
 	should_not_happen();
 }
 
-__initfunc(void sun4c_probe_memerr_reg(void))
+void __init sun4c_probe_memerr_reg(void)
 {
 	should_not_happen();
 }
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v2.3.15/linux/arch/sparc/mm/srmmu.c	Mon Aug  9 11:29:37 1999
+++ linux/arch/sparc/mm/srmmu.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.190 1999/08/07 17:47:01 anton Exp $
+/* $Id: srmmu.c,v 1.191 1999/08/31 06:54:38 davem Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -204,7 +204,7 @@
 #define PGSKIP_DEBUG(from,to) do { } while (0)
 #endif
 
-__initfunc(void srmmu_frob_mem_map(unsigned long start_mem))
+void __init srmmu_frob_mem_map(unsigned long start_mem)
 {
 	unsigned long bank_start, bank_end = 0;
 	unsigned long addr;
@@ -1503,7 +1503,7 @@
  * looking at the prom's page table directly which is what most
  * other OS's do.  Yuck... this is much better.
  */
-__initfunc(void srmmu_inherit_prom_mappings(unsigned long start,unsigned long end))
+void __init srmmu_inherit_prom_mappings(unsigned long start,unsigned long end)
 {
 	pgd_t *pgdp;
 	pmd_t *pmdp;
@@ -1571,7 +1571,7 @@
 static int srmmu_low_pa __initdata = 0;
 static unsigned long end_of_phys_memory __initdata = 0;
 
-__initfunc(void srmmu_end_memory(unsigned long memory_size, unsigned long *end_mem_p))
+void __init srmmu_end_memory(unsigned long memory_size, unsigned long *end_mem_p)
 {
 	unsigned int sum = 0;
 	unsigned long last = 0xff000000;
@@ -1633,7 +1633,7 @@
 #define KERNEL_PTE(page_shifted) ((page_shifted)|SRMMU_CACHE|SRMMU_PRIV|SRMMU_VALID)
 
 /* Create a third-level SRMMU 16MB page mapping. */
-__initfunc(static void do_large_mapping(unsigned long vaddr, unsigned long phys_base))
+static void __init do_large_mapping(unsigned long vaddr, unsigned long phys_base)
 {
 	pgd_t *pgdp = srmmu_pgd_offset(&init_mm, vaddr);
 	unsigned long big_pte;
@@ -1664,7 +1664,7 @@
  * array of char's, each member indicating if that spbank is mapped
  * yet or not.
  */
-__initfunc(static int find_free_spbank(char *taken_vector))
+static int __init find_free_spbank(char *taken_vector)
 {
 	int entry;
 
@@ -1678,7 +1678,7 @@
 
 /* Map sp_bank entry SP_ENTRY, starting at virtual address VBASE.
  */
-__initfunc(static unsigned long map_spbank(unsigned long vbase, int sp_entry))
+static unsigned long __init map_spbank(unsigned long vbase, int sp_entry)
 {
 	unsigned long pstart = (sp_banks[sp_entry].base_addr & SRMMU_PGDIR_MASK);
 	unsigned long vstart = (vbase & SRMMU_PGDIR_MASK);
@@ -1943,7 +1943,7 @@
 
 void (*poke_srmmu)(void) __initdata = NULL;
 
-__initfunc(unsigned long srmmu_paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init srmmu_paging_init(unsigned long start_mem, unsigned long end_mem)
 {
 	unsigned long ptables_start;
 	int i, cpunode;
@@ -2157,13 +2157,13 @@
 }
 
 /* Init various srmmu chip types. */
-__initfunc(static void srmmu_is_bad(void))
+static void __init srmmu_is_bad(void)
 {
 	prom_printf("Could not determine SRMMU chip type.\n");
 	prom_halt();
 }
 
-__initfunc(static void init_vac_layout(void))
+static void __init init_vac_layout(void)
 {
 	int nd, cache_lines;
 	char node_str[128];
@@ -2217,7 +2217,7 @@
 	       (int)vac_cache_size, (int)vac_line_size);
 }
 
-__initfunc(static void poke_hypersparc(void))
+static void __init poke_hypersparc(void)
 {
 	volatile unsigned long clear;
 	unsigned long mreg = srmmu_get_mmureg();
@@ -2240,7 +2240,7 @@
 	clear = srmmu_get_fstatus();
 }
 
-__initfunc(static void init_hypersparc(void))
+static void __init init_hypersparc(void)
 {
 	srmmu_name = "ROSS HyperSparc";
 
@@ -2277,7 +2277,7 @@
 	hypersparc_setup_blockops();
 }
 
-__initfunc(static void poke_cypress(void))
+static void __init poke_cypress(void)
 {
 	unsigned long mreg = srmmu_get_mmureg();
 	unsigned long faddr, tagval;
@@ -2316,7 +2316,7 @@
 	srmmu_set_mmureg(mreg);
 }
 
-__initfunc(static void init_cypress_common(void))
+static void __init init_cypress_common(void)
 {
 	init_vac_layout();
 
@@ -2345,14 +2345,14 @@
 	poke_srmmu = poke_cypress;
 }
 
-__initfunc(static void init_cypress_604(void))
+static void __init init_cypress_604(void)
 {
 	srmmu_name = "ROSS Cypress-604(UP)";
 	srmmu_modtype = Cypress;
 	init_cypress_common();
 }
 
-__initfunc(static void init_cypress_605(unsigned long mrev))
+static void __init init_cypress_605(unsigned long mrev)
 {
 	srmmu_name = "ROSS Cypress-605(MP)";
 	if(mrev == 0xe) {
@@ -2369,7 +2369,7 @@
 	init_cypress_common();
 }
 
-__initfunc(static void poke_swift(void))
+static void __init poke_swift(void)
 {
 	unsigned long mreg = srmmu_get_mmureg();
 
@@ -2390,7 +2390,7 @@
 }
 
 #define SWIFT_MASKID_ADDR  0x10003018
-__initfunc(static void init_swift(void))
+static void __init init_swift(void)
 {
 	unsigned long swift_rev;
 
@@ -2552,7 +2552,7 @@
 }
 
 
-__initfunc(static void poke_turbosparc(void))
+static void __init poke_turbosparc(void)
 {
 	unsigned long mreg = srmmu_get_mmureg();
 	unsigned long ccreg;
@@ -2592,7 +2592,7 @@
 	srmmu_set_mmureg(mreg);
 }
 
-__initfunc(static void init_turbosparc(void))
+static void __init init_turbosparc(void)
 {
 	srmmu_name = "Fujitsu TurboSparc";
 	srmmu_modtype = TurboSparc;
@@ -2616,7 +2616,7 @@
 	poke_srmmu = poke_turbosparc;
 }
 
-__initfunc(static void poke_tsunami(void))
+static void __init poke_tsunami(void)
 {
 	unsigned long mreg = srmmu_get_mmureg();
 
@@ -2627,7 +2627,7 @@
 	srmmu_set_mmureg(mreg);
 }
 
-__initfunc(static void init_tsunami(void))
+static void __init init_tsunami(void)
 {
 	/* Tsunami's pretty sane, Sun and TI actually got it
 	 * somewhat right this time.  Fujitsu should have
@@ -2656,7 +2656,7 @@
 	poke_srmmu = poke_tsunami;
 }
 
-__initfunc(static void poke_viking(void))
+static void __init poke_viking(void)
 {
 	unsigned long mreg = srmmu_get_mmureg();
 	static int smp_catch = 0;
@@ -2711,7 +2711,7 @@
 #endif
 }
 
-__initfunc(static void init_viking(void))
+static void __init init_viking(void)
 {
 	unsigned long mreg = srmmu_get_mmureg();
 
@@ -2776,7 +2776,7 @@
 }
 
 /* Probe for the srmmu chip version. */
-__initfunc(static void get_srmmu_type(void))
+static void __init get_srmmu_type(void)
 {
 	unsigned long mreg, psr;
 	unsigned long mod_typ, mod_rev, psr_typ, psr_vers;
@@ -2942,7 +2942,7 @@
 		*iaddr = SPARC_BRANCH((unsigned long) daddr, (unsigned long) iaddr); \
 	} while(0);
 
-__initfunc(static void patch_window_trap_handlers(void))
+static void __init patch_window_trap_handlers(void)
 {
 	unsigned long *iaddr, *daddr;
 	
@@ -2965,7 +2965,7 @@
 #endif
 
 /* Load up routines and constants for sun4m and sun4d mmu */
-__initfunc(void ld_mmu_srmmu(void))
+void __init ld_mmu_srmmu(void)
 {
 	extern void ld_mmu_iommu(void);
 	extern void ld_mmu_iounit(void);
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- v2.3.15/linux/arch/sparc/mm/sun4c.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc/mm/sun4c.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.175 1999/07/30 09:35:10 davem Exp $
+/* $Id: sun4c.c,v 1.176 1999/08/31 06:54:42 davem Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -437,7 +437,7 @@
 	sun4c_set_context(savectx);
 }
 
-__initfunc(void sun4c_probe_vac(void))
+void __init sun4c_probe_vac(void)
 {
 	sun4c_disable_vac();
 
@@ -601,7 +601,7 @@
 	}
 }
 
-__initfunc(static void sun4c_probe_mmu(void))
+static void __init sun4c_probe_mmu(void)
 {
 	if (ARCH_SUN4) {
 		switch(idprom->id_machtype) {
@@ -652,7 +652,7 @@
 
 volatile unsigned long *sun4c_memerr_reg = 0;
 
-__initfunc(void sun4c_probe_memerr_reg(void))
+void __init sun4c_probe_memerr_reg(void)
 {
 	int node;
 	struct linux_prom_registers regs[1];
@@ -730,7 +730,7 @@
 
 static struct sun4c_mmu_entry mmu_entry_pool[SUN4C_MAX_SEGMAPS];
 
-__initfunc(static void sun4c_init_mmu_entry_pool(void))
+static void __init sun4c_init_mmu_entry_pool(void)
 {
 	int i;
 
@@ -788,7 +788,7 @@
 	}
 }
 
-__initfunc(static void sun4c_init_lock_area(unsigned long start, unsigned long end))
+static void __init sun4c_init_lock_area(unsigned long start, unsigned long end)
 {
 	int i, ctx;
 
@@ -897,7 +897,7 @@
         add_ring(&sun4c_kfree_ring, entry);
 }
 
-__initfunc(static void sun4c_init_fill_kernel_ring(int howmany))
+static void __init sun4c_init_fill_kernel_ring(int howmany)
 {
 	int i;
 
@@ -912,7 +912,7 @@
 	}
 }
 
-__initfunc(static void sun4c_init_fill_user_ring(void))
+static void __init sun4c_init_fill_user_ring(void)
 {
 	int i;
 
@@ -1372,7 +1372,7 @@
 	garbage_collect(entry);
 }
 
-__initfunc(static void sun4c_init_buckets(void))
+static void __init sun4c_init_buckets(void)
 {
 	int entry;
 
@@ -1534,7 +1534,7 @@
 
 struct vm_area_struct sun4c_kstack_vma;
 
-__initfunc(static unsigned long sun4c_init_lock_areas(unsigned long start_mem))
+static unsigned long __init sun4c_init_lock_areas(unsigned long start_mem)
 {
 	unsigned long sun4c_taskstack_start;
 	unsigned long sun4c_taskstack_end;
@@ -2745,7 +2745,7 @@
 extern unsigned long sparc_context_init(unsigned long, int);
 extern unsigned long end;
 
-__initfunc(unsigned long sun4c_paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init sun4c_paging_init(unsigned long start_mem, unsigned long end_mem)
 {
 	int i, cnt;
 	unsigned long kernel_end, vaddr;
@@ -2798,7 +2798,7 @@
 }
 
 /* Load up routines and constants for sun4c mmu */
-__initfunc(void ld_mmu_sun4c(void))
+void __init ld_mmu_sun4c(void)
 {
 	extern void ___xchg32_sun4c(void);
 	
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/tsunami.S linux/arch/sparc/mm/tsunami.S
--- v2.3.15/linux/arch/sparc/mm/tsunami.S	Thu May 15 16:48:02 1997
+++ linux/arch/sparc/mm/tsunami.S	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: tsunami.S,v 1.1 1997/05/03 05:09:09 davem Exp $
+/* $Id: tsunami.S,v 1.2 1999/08/14 03:51:48 anton Exp $
  * tsunami.S: High speed MicroSparc-I mmu/cache operations.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -12,7 +12,7 @@
 
 #define WINDOW_FLUSH(tmp1, tmp2)					\
 	mov	0, tmp1;						\
-98:	ld	[%g6 + AOFF_task_tss + AOFF_thread_uwinmask], tmp2;	\
+98:	ld	[%g6 + AOFF_task_thread + AOFF_thread_uwinmask], tmp2;	\
 	orcc	%g0, tmp2, %g0;						\
 	add	tmp1, 1, tmp1;						\
 	bne	98b;							\
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/mm/viking.S linux/arch/sparc/mm/viking.S
--- v2.3.15/linux/arch/sparc/mm/viking.S	Thu Mar 25 09:23:33 1999
+++ linux/arch/sparc/mm/viking.S	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: viking.S,v 1.13 1999/03/24 11:42:32 davem Exp $
+/* $Id: viking.S,v 1.14 1999/08/14 03:51:50 anton Exp $
  * viking.S: High speed Viking cache/mmu operations
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -144,7 +144,7 @@
 
 #define WINDOW_FLUSH(tmp1, tmp2)					\
 	mov	0, tmp1;						\
-98:	ld	[%g6 + AOFF_task_tss + AOFF_thread_uwinmask], tmp2;	\
+98:	ld	[%g6 + AOFF_task_thread + AOFF_thread_uwinmask], tmp2;	\
 	orcc	%g0, tmp2, %g0;						\
 	add	tmp1, 1, tmp1;						\
 	bne	98b;							\
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/prom/bootstr.c linux/arch/sparc/prom/bootstr.c
--- v2.3.15/linux/arch/sparc/prom/bootstr.c	Tue Apr 14 17:44:20 1998
+++ linux/arch/sparc/prom/bootstr.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: bootstr.c,v 1.17 1998/02/09 13:26:21 jj Exp $
+/* $Id: bootstr.c,v 1.18 1999/08/31 06:54:45 davem Exp $
  * bootstr.c:  Boot string/argument acquisition from the PROM.
  *
  * Copyright(C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -16,8 +16,8 @@
 
 extern linux_sun4_romvec *sun4_romvec;
 
-__initfunc(char *
-prom_getbootargs(void))
+char * __init
+prom_getbootargs(void)
 {
 	int iter;
 	char *cp, *arg;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/prom/init.c linux/arch/sparc/prom/init.c
--- v2.3.15/linux/arch/sparc/prom/init.c	Tue Apr 14 17:44:20 1998
+++ linux/arch/sparc/prom/init.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.12 1998/01/30 10:59:02 jj Exp $
+/* $Id: init.c,v 1.13 1999/08/31 06:54:45 davem Exp $
  * init.c:  Initialize internal variables used by the PROM
  *          library functions.
  *
@@ -35,7 +35,7 @@
 extern void prom_meminit(void);
 extern void prom_ranges_init(void);
 
-__initfunc(void prom_init(struct linux_romvec *rp))
+void __init prom_init(struct linux_romvec *rp)
 {
 #ifdef CONFIG_SUN4
 	extern struct linux_romvec *sun4_prom_init(void);
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/prom/memory.c linux/arch/sparc/prom/memory.c
--- v2.3.15/linux/arch/sparc/prom/memory.c	Tue Apr 14 17:44:20 1998
+++ linux/arch/sparc/prom/memory.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: memory.c,v 1.13 1998/01/30 10:59:03 jj Exp $
+/* $Id: memory.c,v 1.14 1999/08/31 06:54:46 davem Exp $
  * memory.c: Prom routine for acquiring various bits of information
  *           about RAM on the machine, both virtual and physical.
  *
@@ -39,8 +39,8 @@
 /* Internal Prom library routine to sort a linux_mlist_v0 memory
  * list.  Used below in initialization.
  */
-__initfunc(static void
-prom_sortmemlist(struct linux_mlist_v0 *thislist))
+static void __init
+prom_sortmemlist(struct linux_mlist_v0 *thislist)
 {
 	int swapi = 0;
 	int i, mitr, tmpsize;
@@ -69,7 +69,7 @@
 }
 
 /* Initialize the memory lists based upon the prom version. */
-__initfunc(void prom_meminit(void))
+void __init prom_meminit(void)
 {
 	int node = 0;
 	unsigned int iter, num_regs;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/prom/ranges.c linux/arch/sparc/prom/ranges.c
--- v2.3.15/linux/arch/sparc/prom/ranges.c	Tue Apr 14 17:44:20 1998
+++ linux/arch/sparc/prom/ranges.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: ranges.c,v 1.11 1998/01/30 10:59:05 jj Exp $
+/* $Id: ranges.c,v 1.12 1999/08/31 06:54:47 davem Exp $
  * ranges.c: Handle ranges in newer proms for obio/sbus.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -82,7 +82,7 @@
 	}
 }
 
-__initfunc(void prom_ranges_init(void))
+void __init prom_ranges_init(void)
 {
 	int node, obio_node;
 	int success;
@@ -107,7 +107,7 @@
 	return;
 }
 
-__initfunc(void prom_sbus_ranges_init(int parentnd, struct linux_sbus *sbus))
+void __init prom_sbus_ranges_init(int parentnd, struct linux_sbus *sbus)
 {
 	int success;
 	
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/prom/sun4prom.c linux/arch/sparc/prom/sun4prom.c
--- v2.3.15/linux/arch/sparc/prom/sun4prom.c	Tue Apr 14 17:44:20 1998
+++ linux/arch/sparc/prom/sun4prom.c	Thu Aug 26 12:42:32 1999
@@ -114,7 +114,7 @@
 	
 static int synch_hook;
 
-__initfunc(struct linux_romvec *sun4_prom_init(void))
+struct linux_romvec * __init sun4_prom_init(void)
 {
 	int i;
 	unsigned char x;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc/vmlinux.lds linux/arch/sparc/vmlinux.lds
--- v2.3.15/linux/arch/sparc/vmlinux.lds	Wed Mar 10 16:53:36 1999
+++ linux/arch/sparc/vmlinux.lds	Tue Aug 31 11:23:30 1999
@@ -32,16 +32,23 @@
   __ksymtab  : { *(__ksymtab) }
   __stop___ksymtab = .;
 
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
   . = ALIGN(4096);
   __init_begin = .;
   .text.init : { *(.text.init) }
   __init_text_end = .;
   .data.init : { *(.data.init) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup_init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
   . = ALIGN(4096);
   __init_end = .;
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
   __bss_start = .;
   .sbss      : { *(.sbss) *(.scommon) }
   .bss       :
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile
--- v2.3.15/linux/arch/sparc64/Makefile	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/Makefile	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.38 1999/08/02 12:06:06 jj Exp $
+# $Id: Makefile,v 1.40 1999/08/19 02:31:57 davem Exp $
 # sparc64/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -15,7 +15,7 @@
 CC		:= sparc64-linux-gcc -D__KERNEL__ -I$(TOPDIR)/include
 
 CC_HAS_ARGS := $(shell if echo "$(CC)" | grep '\(__KERNEL__\| 	\)' > /dev/null; then echo y; else echo n; fi)
-IS_EGCS := $(shell if $(CC) -c -m64 -mcmodel=medlow -o /dev/null /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
+IS_EGCS := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
 NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
 
 ifneq ($(CC_HAS_ARGS),y)
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.3.15/linux/arch/sparc64/config.in	Thu Aug 26 13:05:34 1999
+++ linux/arch/sparc64/config.in	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.73 1999/08/06 12:11:47 davem Exp $
+# $Id: config.in,v 1.77 1999/08/31 12:49:42 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -36,7 +36,7 @@
 # Global things across all Sun machines.
 define_bool CONFIG_SBUS y
 define_bool CONFIG_SBUSCHAR y
-define_bool CONFIG_MOUSE y
+define_bool CONFIG_BUSMOUSE y
 define_bool CONFIG_SUN_MOUSE y
 define_bool CONFIG_SERIAL y
 define_bool CONFIG_SUN_SERIAL y
@@ -64,10 +64,9 @@
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   tristate 'Solaris binary emulation' CONFIG_SOLARIS_EMUL
 fi
-
+source drivers/parport/Config.in
+dep_tristate '  Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
 if [ "$CONFIG_PCI" = "y" ]; then
-  source drivers/parport/Config.in
-  dep_tristate '  Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
   tristate 'SUNW,envctrl support' CONFIG_ENVCTRL
 fi
 endmenu
@@ -205,6 +204,7 @@
 		if [ "$CONFIG_PCI" = "y" ]; then
 			tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
 			tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
+			tristate 'Adaptec Starfire support' CONFIG_ADAPTEC_STARFIRE
 		fi
 #		bool 'FDDI driver support' CONFIG_FDDI
 #		if [ "$CONFIG_FDDI" = "y" ]; then
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.3.15/linux/arch/sparc64/defconfig	Fri Aug  6 11:58:00 1999
+++ linux/arch/sparc64/defconfig	Tue Aug 31 11:23:30 1999
@@ -27,6 +27,7 @@
 CONFIG_PROM_CONSOLE=y
 CONFIG_FB=y
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CLGEN is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_MATROX is not set
 CONFIG_FB_ATY=y
@@ -49,7 +50,7 @@
 # CONFIG_FBCON_FONTS is not set
 CONFIG_SBUS=y
 CONFIG_SBUSCHAR=y
-CONFIG_MOUSE=y
+CONFIG_BUSMOUSE=y
 CONFIG_SUN_MOUSE=y
 CONFIG_SERIAL=y
 CONFIG_SUN_SERIAL=y
@@ -82,7 +83,6 @@
 # CONFIG_SPARCAUDIO_DBRI is not set
 # CONFIG_SPARCAUDIO_DUMMY is not set
 CONFIG_SUN_OPENPROMFS=m
-CONFIG_PCI_OLD_PROC=y
 CONFIG_NET=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
@@ -99,6 +99,7 @@
 # CONFIG_PARPORT_AMIGA is not set
 # CONFIG_PARPORT_MFC3 is not set
 # CONFIG_PARPORT_ATARI is not set
+# CONFIG_PARPORT_SUNBPP is not set
 # CONFIG_PARPORT_OTHER is not set
 CONFIG_PARPORT_1284=y
 CONFIG_PRINTER=m
@@ -108,11 +109,7 @@
 # Floppy, IDE, and other block devices
 #
 CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=m
-CONFIG_MD_STRIPED=m
-CONFIG_MD_MIRRORING=m
-CONFIG_MD_RAID5=m
+# CONFIG_BLK_DEV_MD is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_BLK_DEV_LOOP=m
@@ -134,8 +131,9 @@
 # Networking options
 #
 CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
 # CONFIG_NETLINK is not set
-# CONFIG_FIREWALL is not set
+# CONFIG_NETFILTER is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -151,10 +149,11 @@
 #
 # (it is safe to leave these untouched)
 #
-CONFIG_INET_RARP=m
 CONFIG_SKB_LARGE=y
 CONFIG_IPV6=m
 # CONFIG_IPV6_EUI64 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
 
 #
 #  
@@ -175,7 +174,6 @@
 # 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
 
 #
 # QoS and/or fair queueing
@@ -259,6 +257,7 @@
 CONFIG_MYRI_SBUS=m
 CONFIG_DE4X5=m
 CONFIG_VORTEX=m
+CONFIG_ADAPTEC_STARFIRE=m
 
 #
 # Unix 98 PTY support
@@ -322,13 +321,13 @@
 #
 # Partition Types
 #
-CONFIG_BSD_DISKLABEL=y
-# CONFIG_MAC_PARTITION is not set
-CONFIG_SMD_DISKLABEL=y
-CONFIG_SOLARIS_X86_PARTITION=y
-# CONFIG_SGI_DISKLABEL is not set
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
-CONFIG_AMIGA_PARTITION=y
+# CONFIG_SGI_PARTITION is not set
+CONFIG_SUN_PARTITION=y
 CONFIG_NLS=y
 
 #
@@ -359,6 +358,7 @@
 # CONFIG_NLS_ISO8859_7 is not set
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
 
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile
--- v2.3.15/linux/arch/sparc64/kernel/Makefile	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/kernel/Makefile	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.44 1999/08/02 12:05:53 jj Exp $
+# $Id: Makefile,v 1.46 1999/08/31 04:39:34 davem Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -20,7 +20,9 @@
 	    traps.o devices.o auxio.o ioport.o \
 	    irq.o ptrace.o time.o sys_sparc.o signal.o \
 	    unaligned.o sys_sunos32.o sunos_ioctl32.o \
-	    central.o psycho.o starfire.o
+	    central.o pci.o pci_common.o pci_iommu.o \
+	    pci_psycho.o pci_sabre.o starfire.o semaphore.o \
+	    power.o
 OX_OBJS  := sparc64_ksyms.o
 
 ifdef CONFIG_PCI
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/auxio.c linux/arch/sparc64/kernel/auxio.c
--- v2.3.15/linux/arch/sparc64/kernel/auxio.c	Tue Aug  4 16:03:35 1998
+++ linux/arch/sparc64/kernel/auxio.c	Tue Aug 31 11:23:30 1999
@@ -22,7 +22,7 @@
 /* Probe and map in the Auxiliary I/O register */
 unsigned char *auxio_register;
 
-__initfunc(void auxio_probe(void))
+void __init auxio_probe(void)
 {
         struct linux_sbus *bus;
         struct linux_sbus_device *sdev = 0;
@@ -51,17 +51,7 @@
 	ebus_done:
 
 		if (edev) {
-			if (check_region(edev->base_address[0],
-					 sizeof(unsigned int))) {
-				prom_printf("%s: Can't get region %lx, %d\n",
-					    __FUNCTION__, edev->base_address[0],
-					    sizeof(unsigned int));
-				prom_halt();
-			}
-			request_region(edev->base_address[0],
-				       sizeof(unsigned int), "LED auxio");
-
-			led_auxio = edev->base_address[0];
+			led_auxio = edev->resource[0].start;
 			outl(0x01, led_auxio);
 			return;
 		}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/binfmt_aout32.c linux/arch/sparc64/kernel/binfmt_aout32.c
--- v2.3.15/linux/arch/sparc64/kernel/binfmt_aout32.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/kernel/binfmt_aout32.c	Thu Aug 26 12:42:32 1999
@@ -453,7 +453,7 @@
 }
 
 
-__initfunc(int init_aout32_binfmt(void))
+int __init init_aout32_binfmt(void)
 {
 	return register_binfmt(&aout32_format);
 }
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/cpu.c linux/arch/sparc64/kernel/cpu.c
--- v2.3.15/linux/arch/sparc64/kernel/cpu.c	Tue May 11 08:24:31 1999
+++ linux/arch/sparc64/kernel/cpu.c	Thu Aug 26 12:42:32 1999
@@ -58,7 +58,7 @@
 
 unsigned int fsr_storage;
 
-__initfunc(void cpu_probe(void))
+void __init cpu_probe(void)
 {
 	int manuf, impl;
 	unsigned i, cpuid;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/devices.c linux/arch/sparc64/kernel/devices.c
--- v2.3.15/linux/arch/sparc64/kernel/devices.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/kernel/devices.c	Thu Aug 26 12:42:32 1999
@@ -21,8 +21,8 @@
 extern void cpu_probe(void);
 extern unsigned long central_probe(unsigned long);
 
-__initfunc(unsigned long
-device_scan(unsigned long mem_start))
+unsigned long __init
+device_scan(unsigned long mem_start)
 {
 	char node_str[128];
 	int nd, prom_node_cpu, thismid;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c
--- v2.3.15/linux/arch/sparc64/kernel/ebus.c	Fri Aug  6 11:58:00 1999
+++ linux/arch/sparc64/kernel/ebus.c	Tue Aug 31 11:23:30 1999
@@ -1,7 +1,8 @@
-/* $Id: ebus.c,v 1.38 1999/08/06 10:37:32 davem Exp $
+/* $Id: ebus.c,v 1.42 1999/08/31 09:12:31 davem Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
+ * Copyright (C) 1999  David S. Miller (davem@redhat.com)
  */
 
 #include <linux/config.h>
@@ -19,15 +20,6 @@
 #include <asm/bpp.h>
 #include <asm/irq.h>
 
-#undef PROM_DEBUG
-#undef DEBUG_FILL_EBUS_DEV
-
-#ifdef PROM_DEBUG
-#define dprintf	prom_printf
-#else
-#define dprintf	printk
-#endif
-
 struct linux_ebus *ebus_chain = 0;
 
 extern void prom_ebus_ranges_init(struct linux_ebus *);
@@ -46,11 +38,11 @@
 extern int envctrl_init(void);
 #endif
 
-static inline unsigned long ebus_alloc(size_t size)
+static inline void *ebus_alloc(size_t size)
 {
-	unsigned long mem;
+	void *mem;
 
-	mem = (unsigned long)kmalloc(size, GFP_ATOMIC);
+	mem = kmalloc(size, GFP_ATOMIC);
 	if (!mem)
 		panic(__FUNCTION__ ": out of memory");
 	memset((char *)mem, 0, size);
@@ -89,23 +81,26 @@
 {
 	int regs[PROMREG_MAX];
 	int irqs[PROMREG_MAX];
-	char lbuf[128];
 	int i, len;
 
 	dev->prom_node = node;
-	prom_getstring(node, "name", lbuf, sizeof(lbuf));
-	strcpy(dev->prom_name, lbuf);
+	prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
+	printk("(%s)", dev->prom_name);
 
 	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
 	dev->num_addrs = len / sizeof(regs[0]);
 
 	for (i = 0; i < dev->num_addrs; i++) {
-		if (regs[i] >= dev->parent->num_addrs) {
+		int rnum = regs[i];
+		if (rnum >= dev->parent->num_addrs) {
 			prom_printf("UGH: property for %s was %d, need < %d\n",
 				    dev->prom_name, len, dev->parent->num_addrs);
 			panic(__FUNCTION__);
 		}
-		dev->base_address[i] = dev->parent->base_address[regs[i]];
+		dev->resource[i].start = dev->parent->resource[i].start;
+		dev->resource[i].end = dev->parent->resource[i].end;
+		dev->resource[i].flags = IORESOURCE_MEM;
+		dev->resource[i].name = dev->prom_name;
 	}
 
 	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
@@ -129,25 +124,13 @@
 	} else {
 		dev->num_irqs = len / sizeof(irqs[0]);
 		for (i = 0; i < dev->num_irqs; i++) {
+			struct pci_pbm_info *pbm = dev->bus->parent;
+			struct pci_controller_info *p = pbm->parent;
+
 			ebus_intmap_match(dev->bus, preg, &irqs[i]);
-			dev->irqs[i] = psycho_irq_build(dev->bus->parent,
-							dev->bus->self, irqs[i]);
+			dev->irqs[i] = p->irq_build(p, dev->bus->self, irqs[i]);
 		}
 	}
-
-#ifdef DEBUG_FILL_EBUS_DEV
-	dprintf("child '%s': address%s ", dev->prom_name,
-	       dev->num_addrs > 1 ? "es" : "");
-	for (i = 0; i < dev->num_addrs; i++)
-		dprintf("%016lx ", dev->base_address[i]);
-	dprintf("\n");
-	if (dev->num_irqs) {
-		dprintf("        IRQ%s", dev->num_irqs > 1 ? "s" : "");
-		for (i = 0; i < dev->num_irqs; i++)
-			dprintf(" %s", __irq_itoa(dev->irqs[i]));
-		dprintf("\n");
-	}
-#endif
 }
 
 void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
@@ -155,27 +138,32 @@
 	struct linux_prom_registers regs[PROMREG_MAX];
 	struct linux_ebus_child *child;
 	int irqs[PROMINTR_MAX];
-	char lbuf[128];
 	int i, n, len;
 
 	dev->prom_node = node;
-	prom_getstring(node, "name", lbuf, sizeof(lbuf));
-	strcpy(dev->prom_name, lbuf);
+	prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
+	printk(" [%s", dev->prom_name);
 
 	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
 	if (len % sizeof(struct linux_prom_registers)) {
 		prom_printf("UGH: proplen for %s was %d, need multiple of %d\n",
 			    dev->prom_name, len,
 			    (int)sizeof(struct linux_prom_registers));
-		panic(__FUNCTION__);
+		prom_halt();
 	}
 	dev->num_addrs = len / sizeof(struct linux_prom_registers);
 
 	for (i = 0; i < dev->num_addrs; i++) {
 		n = (regs[i].which_io - 0x10) >> 2;
 
-		dev->base_address[i] = dev->bus->self->resource[n].start;
-		dev->base_address[i] += (unsigned long)regs[i].phys_addr;
+		dev->resource[i].start  = dev->bus->self->resource[n].start;
+		dev->resource[i].start += (unsigned long)regs[i].phys_addr;
+		dev->resource[i].end    =
+			(dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL);
+		dev->resource[i].flags  = IORESOURCE_MEM;
+		dev->resource[i].name   = dev->prom_name;
+		request_resource(&dev->bus->self->resource[n],
+				 &dev->resource[i]);
 	}
 
 	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
@@ -184,28 +172,17 @@
 	} else {
 		dev->num_irqs = len / sizeof(irqs[0]);
 		for (i = 0; i < dev->num_irqs; i++) {
+			struct pci_pbm_info *pbm = dev->bus->parent;
+			struct pci_controller_info *p = pbm->parent;
+
 			ebus_intmap_match(dev->bus, &regs[0], &irqs[i]);
-			dev->irqs[i] = psycho_irq_build(dev->bus->parent,
-							dev->bus->self, irqs[i]);
+			dev->irqs[i] = p->irq_build(p, dev->bus->self, irqs[i]);
 		}
 	}
 
-#ifdef DEBUG_FILL_EBUS_DEV
-	dprintf("'%s': address%s ", dev->prom_name,
-	       dev->num_addrs > 1 ? "es" : "");
-	for (i = 0; i < dev->num_addrs; i++)
-		dprintf("%016lx ", dev->base_address[i]);
-	dprintf("\n");
-	if (dev->num_irqs) {
-		dprintf("  IRQ%s", dev->num_irqs > 1 ? "s" : "");
-		for (i = 0; i < dev->num_irqs; i++)
-			dprintf(" %s", __irq_itoa(dev->irqs[i]));
-		dprintf("\n");
-	}
-#endif
 	if ((node = prom_getchild(node))) {
-		dev->children = (struct linux_ebus_child *)
-			ebus_alloc(sizeof(struct linux_ebus_child));
+		printk(" ->");
+		dev->children = ebus_alloc(sizeof(struct linux_ebus_child));
 
 		child = dev->children;
 		child->next = 0;
@@ -214,8 +191,7 @@
 		fill_ebus_child(node, &regs[0], child);
 
 		while ((node = prom_getsibling(node))) {
-			child->next = (struct linux_ebus_child *)
-				ebus_alloc(sizeof(struct linux_ebus_child));
+			child->next = ebus_alloc(sizeof(struct linux_ebus_child));
 
 			child = child->next;
 			child->next = 0;
@@ -224,24 +200,21 @@
 			fill_ebus_child(node, &regs[0], child);
 		}
 	}
+	printk("]");
 }
 
 extern void clock_probe(void);
+extern void power_init(void);
 
 void __init ebus_init(void)
 {
-	struct linux_prom_pci_registers regs[PROMREG_MAX];
-	struct linux_pbm_info *pbm;
+	struct pci_pbm_info *pbm;
 	struct linux_ebus_device *dev;
 	struct linux_ebus *ebus;
 	struct pci_dev *pdev;
 	struct pcidev_cookie *cookie;
-	char lbuf[128];
-	struct resource *base;
-	unsigned long addr;
 	unsigned short pci_command;
-	int nd, len, ebusnd;
-	int reg, rng, nreg;
+	int nd, ebusnd;
 	int num_ebus = 0;
 
 	if (!pci_present())
@@ -250,17 +223,13 @@
 	pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0);
 	if (!pdev) {
 		printk("ebus: No EBus's found.\n");
-#ifdef PROM_DEBUG
-		dprintf("ebus: No EBus's found.\n");
-#endif
 		return;
 	}
 
 	cookie = pdev->sysdata;
 	ebusnd = cookie->prom_node;
 
-	ebus_chain = ebus = (struct linux_ebus *)
-			ebus_alloc(sizeof(struct linux_ebus));
+	ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus));
 	ebus->next = 0;
 
 	while (ebusnd) {
@@ -277,9 +246,6 @@
 				if (ebus == ebus_chain) {
 					ebus_chain = NULL;
 					printk("ebus: No EBus's found.\n");
-#ifdef PROM_DEBUG
-					dprintf("ebus: No EBus's found.\n");
-#endif
 					return;
 				}
 				break;
@@ -290,14 +256,10 @@
 			continue;
 		}
 		printk("ebus%d:", num_ebus);
-#ifdef PROM_DEBUG
-		dprintf("ebus%d:", num_ebus);
-#endif
 
-		prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf));
+		prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name));
+		ebus->index = num_ebus;
 		ebus->prom_node = ebusnd;
-		strcpy(ebus->prom_name, lbuf);
-
 		ebus->self = pdev;
 		ebus->parent = pbm = cookie->pbm;
 
@@ -310,56 +272,7 @@
 		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
 
 		/* NOTE: Cache line size is in 32-bit word units. */
-		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x10);
-
-		len = prom_getproperty(ebusnd, "reg", (void *)regs,
-				       sizeof(regs));
-		if (len == 0 || len == -1) {
-			prom_printf("%s: can't find reg property\n",
-				    __FUNCTION__);
-			prom_halt();
-		}
-		nreg = len / sizeof(struct linux_prom_pci_registers);
-
-		base = &ebus->self->resource[0];
-		for (reg = 0; reg < nreg; reg++) {
-			if (!(regs[reg].phys_hi & 0x03000000))
-				continue;
-
-			for (rng = 0; rng < pbm->num_pbm_ranges; rng++) {
-				struct linux_prom_pci_ranges *rp =
-						&pbm->pbm_ranges[rng];
-
-				if ((rp->child_phys_hi ^ regs[reg].phys_hi)
-								& 0x03000000)
-					continue;
-
-				addr = (u64)regs[reg].phys_lo;
-				addr += (u64)regs[reg].phys_mid << 32UL;
-				addr += (u64)rp->parent_phys_lo;
-				addr += (u64)rp->parent_phys_hi << 32UL;
-
-				base->name = "EBUS";
-				base->start = (unsigned long)__va(addr);
-				base->end = base->start + regs[reg].size_lo - 1;
-				base->flags = 0;
-				request_resource(&ioport_resource, base);
-
-				base += 1;
-
-				printk(" %lx[%x]", (unsigned long)__va(addr),
-				       regs[reg].size_lo);
-#ifdef PROM_DEBUG
-				dprintf(" %lx[%x]", (unsigned long)__va(addr),
-				        regs[reg].size_lo);
-#endif
-				break;
-			}
-		}
-		printk("\n");
-#ifdef PROM_DEBUG
-		dprintf("\n");
-#endif
+		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 64/sizeof(u32));
 
 		prom_ebus_ranges_init(ebus);
 		prom_ebus_intmap_init(ebus);
@@ -368,8 +281,7 @@
 		if (!nd)
 			goto next_ebus;
 
-		ebus->devices = (struct linux_ebus_device *)
-				ebus_alloc(sizeof(struct linux_ebus_device));
+		ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device));
 
 		dev = ebus->devices;
 		dev->next = 0;
@@ -378,8 +290,7 @@
 		fill_ebus_device(nd, dev);
 
 		while ((nd = prom_getsibling(nd))) {
-			dev->next = (struct linux_ebus_device *)
-				ebus_alloc(sizeof(struct linux_ebus_device));
+			dev->next = ebus_alloc(sizeof(struct linux_ebus_device));
 
 			dev = dev->next;
 			dev->next = 0;
@@ -389,6 +300,8 @@
 		}
 
 	next_ebus:
+		printk("\n");
+
 		pdev = pci_find_device(PCI_VENDOR_ID_SUN,
 				       PCI_DEVICE_ID_SUN_EBUS, pdev);
 		if (!pdev)
@@ -397,8 +310,7 @@
 		cookie = pdev->sysdata;
 		ebusnd = cookie->prom_node;
 
-		ebus->next = (struct linux_ebus *)
-			ebus_alloc(sizeof(struct linux_ebus));
+		ebus->next = ebus_alloc(sizeof(struct linux_ebus));
 		ebus = ebus->next;
 		ebus->next = 0;
 		++num_ebus;
@@ -420,4 +332,5 @@
 	flash_init();
 #endif
 	clock_probe();
+	power_init();
 }
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/idprom.c linux/arch/sparc64/kernel/idprom.c
--- v2.3.15/linux/arch/sparc64/kernel/idprom.c	Wed Apr 23 19:01:16 1997
+++ linux/arch/sparc64/kernel/idprom.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: idprom.c,v 1.2 1997/04/17 02:28:10 miguel Exp $
+/* $Id: idprom.c,v 1.3 1999/08/31 06:54:53 davem Exp $
  * idprom.c: Routines to load the idprom into kernel addresses and
  *           interpret the data contained within.
  *
@@ -16,7 +16,7 @@
 static struct idprom idprom_buffer;
 
 /* Calculate the IDPROM checksum (xor of the data bytes). */
-__initfunc(static unsigned char calc_idprom_cksum(struct idprom *idprom))
+static unsigned char __init calc_idprom_cksum(struct idprom *idprom)
 {
 	unsigned char cksum, i, *ptr = (unsigned char *)idprom;
 
@@ -27,7 +27,7 @@
 }
 
 /* Create a local IDPROM copy and verify integrity. */
-__initfunc(void idprom_init(void))
+void __init idprom_init(void)
 {
 	prom_get_idprom((char *) &idprom_buffer, sizeof(idprom_buffer));
 
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.3.15/linux/arch/sparc64/kernel/ioctl32.c	Wed Aug 18 11:39:01 1999
+++ linux/arch/sparc64/kernel/ioctl32.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.66 1999/08/08 01:37:06 davem Exp $
+/* $Id: ioctl32.c,v 1.67 1999/08/20 00:27:08 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997  Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- v2.3.15/linux/arch/sparc64/kernel/irq.c	Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc64/kernel/irq.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.76 1999/04/02 14:54:30 davem Exp $
+/* $Id: irq.c,v 1.78 1999/08/31 06:54:54 davem Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
@@ -31,11 +31,6 @@
 #include <asm/hardirq.h>
 #include <asm/softirq.h>
 
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
-#include <asm/pbm.h>
-#endif
-
 /* Internal flag, should not be visible elsewhere at all. */
 #define SA_IMAP_MASKED		0x100
 #define SA_DMA_SYNC		0x200
@@ -79,15 +74,6 @@
 	  NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
 };
 
-/* Only 8-bits are available, be careful.  -DaveM */
-#define IBF_DMA_SYNC	0x01	/* DMA synchronization behind PCI bridge needed. */
-#define IBF_PCI		0x02	/* Indicates PSYCHO/SCHIZO PCI interrupt.	 */
-#define IBF_ACTIVE	0x04	/* This interrupt is active and has a handler.	 */
-#define IBF_MULTI	0x08	/* On PCI, indicates shared bucket.		 */
-
-#define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq))
-#define __irq(bucket) ((unsigned int)(unsigned long)(bucket))
-
 int get_irq_list(char *buf)
 {
 	int i, len = 0;
@@ -183,67 +169,22 @@
 /* Convert Interrupt Mapping register pointer to assosciated
  * Interrupt Clear register pointer, SYSIO specific version.
  */
-static unsigned int *sysio_imap_to_iclr(unsigned int *imap)
+static volatile unsigned int *sysio_imap_to_iclr(volatile unsigned int *imap)
 {
 	unsigned long diff;
 
 	diff = offset(iclr_unused0) - offset(imap_slot0);
-	return (unsigned int *) (((unsigned long)imap) + diff);
+	return (volatile unsigned int *) (((unsigned long)imap) + diff);
 }
 
 #undef offset
 
-#ifdef CONFIG_PCI
-/* PCI PSYCHO INO number to Sparc PIL level. */
-unsigned char psycho_ino_to_pil[] = {
-	7, 5, 4, 2,			/* PCI A slot 0  Int A, B, C, D */
-	7, 5, 4, 2,			/* PCI A slot 1  Int A, B, C, D */
-	7, 5, 4, 2,			/* PCI A slot 2  Int A, B, C, D */
-	7, 5, 4, 2,			/* PCI A slot 3  Int A, B, C, D */
-	6, 4, 3, 1,			/* PCI B slot 0  Int A, B, C, D */
-	6, 4, 3, 1,			/* PCI B slot 1  Int A, B, C, D */
-	6, 4, 3, 1,			/* PCI B slot 2  Int A, B, C, D */
-	6, 4, 3, 1,			/* PCI B slot 3  Int A, B, C, D */
-	3,  /* SCSI */
-	5,  /* Ethernet */
-	8,  /* Parallel Port */
-	13, /* Audio Record */
-	14, /* Audio Playback */
-	15, /* PowerFail */
-	3,  /* second SCSI */
-	11, /* Floppy */
-	2,  /* Spare Hardware */
-	9,  /* Keyboard */
-	4,  /* Mouse */
-	12, /* Serial */
-	10, /* Timer 0 */
-	11, /* Timer 1 */
-	15, /* Uncorrectable ECC */
-	15, /* Correctable ECC */
-	15, /* PCI Bus A Error */
-	15, /* PCI Bus B Error */
-	1, /* Power Management */
-};
-
-/* INO number to IMAP register offset for PSYCHO external IRQ's. */
-#define psycho_offset(x) ((unsigned long)(&(((struct psycho_regs *)0)->x)))
-
-#define psycho_imap_offset(ino)						      \
-	((ino & 0x20) ? (psycho_offset(imap_scsi) + (((ino) & 0x1f) << 3)) :  \
-			(psycho_offset(imap_a_slot0) + (((ino) & 0x3c) << 1)))
-
-#define psycho_iclr_offset(ino)						      \
-	((ino & 0x20) ? (psycho_offset(iclr_scsi) + (((ino) & 0x1f) << 3)) :  \
-			(psycho_offset(iclr_a_slot0[0]) + (((ino) & 0x1f)<<3)))
-
-#endif
-
 /* Now these are always passed a true fully specified sun4u INO. */
 void enable_irq(unsigned int irq)
 {
 	extern int this_is_starfire;
 	struct ino_bucket *bucket = __bucket(irq);
-	unsigned int *imap;
+	volatile unsigned int *imap;
 	unsigned long tid;
 
 	imap = bucket->imap;
@@ -257,7 +198,7 @@
 				     : "i" (ASI_UPA_CONFIG));
 		tid = ((tid & UPA_CONFIG_MID) << 9);
 	} else {
-		extern unsigned int starfire_translate(unsigned int *imap,
+		extern unsigned int starfire_translate(volatile unsigned int *imap,
 						       unsigned int upaid);
 
 		tid = (starfire_translate(imap, current->processor) << 26);
@@ -278,7 +219,7 @@
 void disable_irq(unsigned int irq)
 {
 	struct ino_bucket *bucket = __bucket(irq);
-	unsigned int *imap;
+	volatile unsigned int *imap;
 
 	imap = bucket->imap;
 	if (imap != NULL) {
@@ -306,7 +247,7 @@
 	NULL,	/* imap */
 };
 
-unsigned int build_irq(int pil, int inofixup, unsigned int *iclr, unsigned int *imap)
+unsigned int build_irq(int pil, int inofixup, volatile unsigned int *iclr, volatile unsigned int *imap)
 {
 	struct ino_bucket *bucket;
 	int ino;
@@ -365,7 +306,7 @@
 	struct sysio_regs *sregs = sbus->iommu->sysio_regs;
 	unsigned long offset;
 	int pil;
-	unsigned int *imap, *iclr;
+	volatile unsigned int *imap, *iclr;
 	int sbus_level = 0;
 
 	pil = sysio_ino_to_pil[ino];
@@ -380,7 +321,7 @@
 		panic("BAD SYSIO IRQ offset...");
 	}
 	offset += ((unsigned long)sregs);
-	imap = ((unsigned int *)offset);
+	imap = ((volatile unsigned int *)offset);
 
 	/* SYSIO inconsistancy.  For external SLOTS, we have to select
 	 * the right ICLR register based upon the lower SBUS irq level
@@ -412,81 +353,11 @@
 
 		iclraddr = (unsigned long) iclr;
 		iclraddr += ((sbus_level - 1) * 8);
-		iclr = (unsigned int *) iclraddr;
+		iclr = (volatile unsigned int *) iclraddr;
 	}
 	return build_irq(pil, sbus_level, iclr, imap);
 }
 
-#ifdef CONFIG_PCI
-unsigned int psycho_build_irq(void *buscookie, int imap_off, int ino, int need_dma_sync)
-{
-	struct linux_psycho *psycho = (struct linux_psycho *)buscookie;
-	struct psycho_regs *pregs = psycho->psycho_regs;
-	unsigned long addr;
-	struct ino_bucket *bucket;
-	int pil;
-	unsigned int *imap, *iclr;
-	int inofixup = 0;
-
-	pil = psycho_ino_to_pil[ino & PCI_IRQ_INO];
-	
-	addr = (unsigned long) &pregs->imap_a_slot0;
-	addr = addr + imap_off;
-	imap = ((unsigned int *)addr) + 1;
-
-	addr = (unsigned long) pregs;
-	addr += psycho_iclr_offset(ino & (PCI_IRQ_INO));
-	iclr = ((unsigned int *)addr) + 1;
-
-	if(!(ino & 0x20))
-		inofixup = ino & 0x03;
-
-	/* First check for sharing. */
-	ino = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)) + inofixup;
-	if (ino > NUM_IVECS) {
-		prom_printf("PSYCHO: Invalid INO %04x (%d:%d:%016lx:%016lx)\n",
-			    ino, pil, inofixup, iclr, imap);
-		prom_halt();
-	}
-	bucket = &ivector_table[ino];
-	if(bucket->flags & IBF_ACTIVE) {
-		void *old_handler = bucket->irq_info;
-		unsigned long flags;
-
-		if(old_handler == NULL) {
-			prom_printf("PSYCHO: Active bucket, but no handler.\n");
-			prom_halt();
-		}
-		save_and_cli(flags);
-		if((bucket->flags & IBF_MULTI) == 0) {
-			void **vector;
-
-			vector = kmalloc(sizeof(void *) * 4,
-					 GFP_KERNEL);
-
-			/* We might have slept. */
-			if((bucket->flags & IBF_MULTI) != 0) {
-				kfree(vector);
-			} else {
-				vector[0] = old_handler;
-				vector[1] = vector[2] = vector[3] = NULL;
-				bucket->irq_info = vector;
-				bucket->flags |= IBF_MULTI;
-			}
-		}
-		restore_flags(flags);
-	} else {
-		/* Just init the bucket */
-		bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
-	}	
-	if (need_dma_sync)
-		bucket->flags |= IBF_DMA_SYNC;
-		
-	bucket->flags |= IBF_PCI;
-	return __irq(bucket);
-}
-#endif
-
 static void atomic_bucket_insert(struct ino_bucket *bucket)
 {
 	unsigned long pstate;
@@ -731,7 +602,7 @@
 		*(bucket->pil + irq_action) = action->next;
 
 	if(action->flags & SA_IMAP_MASKED) {
-		unsigned int *imap = bucket->imap;
+		volatile unsigned int *imap = bucket->imap;
 		void **vector, *orig;
 		int ent;
 
@@ -1286,7 +1157,7 @@
 {
 	extern int this_is_starfire;
 	struct ino_bucket *bucket = __bucket(p->mask);
-	unsigned int *imap = bucket->imap;
+	volatile unsigned int *imap = bucket->imap;
 	unsigned int tid;
 
 	/* Never change this, it causes problems on Ex000 systems. */
@@ -1296,7 +1167,7 @@
 	if(this_is_starfire == 0) {
 		tid = __cpu_logical_map[goal_cpu] << 26;
 	} else {
-		extern unsigned int starfire_translate(unsigned int *imap,
+		extern unsigned int starfire_translate(volatile unsigned int *imap,
 						       unsigned int upaid);
 
 		tid = (starfire_translate(imap, __cpu_logical_map[goal_cpu]) << 26);
@@ -1399,7 +1270,7 @@
 	prom_timers->count0 = 0;
 }
 
-__initfunc(void init_IRQ(void))
+void __init init_IRQ(void)
 {
 	static int called = 0;
 
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c
--- v2.3.15/linux/arch/sparc64/kernel/pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/pci.c	Tue Aug 31 11:23:30 1999
@@ -0,0 +1,361 @@
+/* $Id: pci.c,v 1.1 1999/08/30 10:00:42 davem Exp $
+ * pci.c: UltraSparc PCI controller support.
+ *
+ * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1998, 1999 Eddie C. Dost   (ecd@skynet.be)
+ * Copyright (C) 1999 Jakub Jelinek   (jj@ultra.linux.cz)
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/capability.h>
+#include <linux/errno.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/pbm.h>
+#include <asm/irq.h>
+#include <asm/ebus.h>
+
+/* This is the base address of IOMMU translated space
+ * on PCI bus segments.  This means that any PCI address
+ * greater than or equal this value will be translated
+ * into a physical address and transferred on the system
+ * bus.  Any address less than it will be considered a
+ * PCI peer-to-peer transaction.  For example, given a
+ * value of 0x80000000:
+ *
+ *	If a PCI device bus masters the address 0x80001000
+ *	then then PCI controller's IOMMU will take the offset
+ *	portion (0x1000) and translate that into a physical
+ *	address.  The data transfer will be performed to/from
+ *	that physical address on the system bus.
+ *
+ *	If the PCI device bus masters the address 0x00002000
+ *	then the PCI controller will not do anything, it will
+ *	proceed as a PCI peer-to-peer transfer.
+ *
+ * This all stems from the fact that PCI drivers in Linux are
+ * not conscious of DMA mappings to the extent they need to
+ * be for systems like Sparc64 and Alpha which have IOMMU's.
+ * Plans are already in the works to fix this.  So what we do
+ * at the moment is linearly map all of physical ram with the
+ * IOMMU in consistant mode, thus providing the illusion of
+ * a simplistic linear DMA mapping scheme to the drivers.
+ * This, while it works, is bad for performance (streaming
+ * DMA is not used) and limits the amount of total memory we
+ * can support (2GB on Psycho, 512MB on Sabre/APB).
+ */
+unsigned long pci_dvma_offset = 0x00000000UL;
+
+/* Given a valid PCI dma address (ie. >= pci_dvma_addset) this
+ * mask will give you the offset into the DMA space of a
+ * PCI bus.
+ */
+unsigned long pci_dvma_mask   = 0xffffffffUL;
+
+unsigned long pci_dvma_v2p_hash[PCI_DVMA_HASHSZ];
+unsigned long pci_dvma_p2v_hash[PCI_DVMA_HASHSZ];
+
+#ifndef CONFIG_PCI
+/* A "nop" PCI implementation. */
+int pcibios_present(void) { return 0; }
+asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn,
+				  unsigned long off, unsigned long len,
+				  unsigned char *buf)
+{
+	return 0;
+}
+asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn,
+				   unsigned long off, unsigned long len,
+				   unsigned char *buf)
+{
+	return 0;
+}
+#else
+
+/* List of all PCI controllers found in the system. */
+spinlock_t pci_controller_lock = SPIN_LOCK_UNLOCKED;
+struct pci_controller_info *pci_controller_root = NULL;
+
+/* Each PCI controller found gets a unique index. */
+int pci_num_controllers = 0;
+
+/* Given an 8-bit PCI bus number, this yields the
+ * controlling PBM module info.
+ *
+ * Some explanation is in order here.  The Linux APIs for
+ * the PCI subsystem require that the configuration space
+ * types are enough to signify PCI configuration space
+ * accesses correctly.  This gives us 8-bits for the bus
+ * number, however we have multiple PCI controllers on
+ * UltraSparc systems.
+ *
+ * So what we do is give the PCI busses under each controller
+ * a unique portion of the 8-bit PCI bus number space.
+ * Therefore one can obtain the controller from the bus
+ * number.  For example, say PSYCHO PBM-A a subordinate bus
+ * space of 0 to 4, and PBM-B has a space of 0 to 2.  PBM-A
+ * will use 0 to 4, and PBM-B will use 5 to 7.
+ */
+struct pci_pbm_info *pci_bus2pbm[256];
+unsigned char pci_highest_busnum = 0;
+
+/* At boot time the user can give the kernel a command
+ * line option which controls if and how PCI devices
+ * are reordered at PCI bus probing time.
+ */
+int pci_device_reorder = 0;
+
+spinlock_t pci_poke_lock = SPIN_LOCK_UNLOCKED;
+volatile int pci_poke_in_progress;
+volatile int pci_poke_faulted;
+
+/* Probe for all PCI controllers in the system. */
+extern void sabre_init(int);
+extern void psycho_init(int);
+
+static struct {
+	char *model_name;
+	void (*init)(int);
+} pci_controller_table[] = {
+	{ "SUNW,sabre", sabre_init },
+	{ "SUNW,psycho", psycho_init }
+};
+#define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
+				  sizeof(pci_controller_table[0]))
+
+static void pci_controller_init(char *model_name, int namelen, int node)
+{
+	int i;
+
+	for (i = 0; i < PCI_NUM_CONTROLLER_TYPES; i++) {
+		if (!strncmp(model_name,
+			     pci_controller_table[i].model_name,
+			     namelen)) {
+			pci_controller_table[i].init(node);
+			return;
+		}
+	}
+	printk("PCI: Warning unknown controller, model name [%s]\n",
+	       model_name);
+	printk("PCI: Ignoring controller...\n");
+}
+
+/* Find each controller in the system, attach and initialize
+ * software state structure for each and link into the
+ * pci_controller_root.  Setup the controller enough such
+ * that bus scanning can be done.
+ */
+static void pci_controller_probe(void)
+{
+	char namebuf[16];
+	int node;
+
+	printk("PCI: Probing for controllers.\n");
+	node = prom_getchild(prom_root_node);
+	while ((node = prom_searchsiblings(node, "pci")) != 0) {
+		int len;
+
+		len = prom_getproperty(node, "model",
+				       namebuf, sizeof(namebuf));
+		if (len > 0)
+			pci_controller_init(namebuf, len, node);
+		node = prom_getsibling(node);
+		if (!node)
+			break;
+	}
+}
+
+static void pci_scan_each_controller_bus(void)
+{
+	struct pci_controller_info *p;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pci_controller_lock, flags);
+	for (p = pci_controller_root; p; p = p->next)
+		p->scan_bus(p);
+	spin_unlock_irqrestore(&pci_controller_lock, flags);
+}
+
+/* Reorder the pci_dev chain, so that onboard devices come first
+ * and then come the pluggable cards.
+ */
+static void __init pci_reorder_devs(void)
+{
+	struct pci_dev **pci_onboard = &pci_devices;
+	struct pci_dev **pci_tail = &pci_devices;
+	struct pci_dev *pdev = pci_devices, *pci_other = NULL;
+
+	while (pdev) {
+		if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) {
+			if (pci_other) {
+				*pci_onboard = pdev;
+				pci_onboard = &pdev->next;
+				pdev = pdev->next;
+				*pci_onboard = pci_other;
+				*pci_tail = pdev;
+				continue;
+			} else
+				pci_onboard = &pdev->next;
+		} else if (!pci_other)
+			pci_other = pdev;
+		pci_tail = &pdev->next;
+		pdev = pdev->next;
+	}
+}
+
+void __init pcibios_init(void)
+{
+	pci_controller_probe();
+	if (pci_controller_root == NULL)
+		return;
+
+	pci_scan_each_controller_bus();
+
+	if (pci_device_reorder)
+		pci_reorder_devs();
+
+	ebus_init();
+}
+
+struct pci_fixup pcibios_fixups[] = {
+	{ 0 }
+};
+
+void pcibios_fixup_bus(struct pci_bus *pbus)
+{
+}
+
+char * __init pcibios_setup(char *str)
+{
+	if (!strcmp(str, "onboardfirst")) {
+		pci_device_reorder = 1;
+		return NULL;
+	}
+	if (!strcmp(str, "noreorder")) {
+		pci_device_reorder = 0;
+		return NULL;
+	}
+	return str;
+}
+
+asmlinkage int sys_pciconfig_read(unsigned long bus,
+				  unsigned long dfn,
+				  unsigned long off,
+				  unsigned long len,
+				  unsigned char *buf)
+{
+	struct pci_dev *dev;
+	u8 byte;
+	u16 word;
+	u32 dword;
+	int err = 0;
+
+	if(!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	dev = pci_find_slot(bus, dfn);
+	if (!dev) {
+		/* Xfree86 is such a turd, it does not check the
+		 * return value and just relies on the buffer being
+		 * set to all 1's to mean "device not present".
+		 */
+		switch(len) {
+		case 1:
+			put_user(0xff, (unsigned char *)buf);
+			break;
+		case 2:
+			put_user(0xffff, (unsigned short *)buf);
+			break;
+		case 4:
+			put_user(0xffffffff, (unsigned int *)buf);
+			break;
+		default:
+			err = -EINVAL;
+			break;
+		};
+		goto out;
+	}
+
+	lock_kernel();
+	switch(len) {
+	case 1:
+		pci_read_config_byte(dev, off, &byte);
+		put_user(byte, (unsigned char *)buf);
+		break;
+	case 2:
+		pci_read_config_word(dev, off, &word);
+		put_user(word, (unsigned short *)buf);
+		break;
+	case 4:
+		pci_read_config_dword(dev, off, &dword);
+		put_user(dword, (unsigned int *)buf);
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+	};
+	unlock_kernel();
+out:
+	return err;
+}
+
+asmlinkage int sys_pciconfig_write(unsigned long bus,
+				   unsigned long dfn,
+				   unsigned long off,
+				   unsigned long len,
+				   unsigned char *buf)
+{
+	struct pci_dev *dev;
+	u8 byte;
+	u16 word;
+	u32 dword;
+	int err = 0;
+
+	if(!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	dev = pci_find_slot(bus, dfn);
+	if (!dev) {
+		/* See commentary above about Xfree86 */
+		goto out;
+	}
+
+	lock_kernel();
+	switch(len) {
+	case 1:
+		err = get_user(byte, (u8 *)buf);
+		if(err)
+			break;
+		pci_write_config_byte(dev, off, byte);
+		break;
+
+	case 2:
+		err = get_user(word, (u16 *)buf);
+		if(err)
+			break;
+		pci_write_config_byte(dev, off, word);
+		break;
+
+	case 4:
+		err = get_user(dword, (u32 *)buf);
+		if(err)
+			break;
+		pci_write_config_byte(dev, off, dword);
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+
+	};
+	unlock_kernel();
+
+out:
+	return err;
+}
+
+#endif /* !(CONFIG_PCI) */
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/pci_common.c linux/arch/sparc64/kernel/pci_common.c
--- v2.3.15/linux/arch/sparc64/kernel/pci_common.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/pci_common.c	Tue Aug 31 11:23:30 1999
@@ -0,0 +1,638 @@
+/* $Id: pci_common.c,v 1.2 1999/08/31 09:12:33 davem Exp $
+ * pci_common.c: PCI controller common support.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+
+#include <asm/pbm.h>
+
+/* Find the OBP PROM device tree node for a PCI device.
+ * Return zero if not found.
+ */
+static int __init find_device_prom_node(struct pci_pbm_info *pbm,
+					struct pci_dev *pdev,
+					int bus_prom_node,
+					struct linux_prom_pci_registers *pregs,
+					int *nregs)
+{
+	int node;
+
+	node = prom_getchild(bus_prom_node);
+	while (node != 0) {
+		int err = prom_getproperty(node, "reg",
+					   (char *)pregs,
+					   sizeof(*pregs) * PROMREG_MAX);
+		if (err == 0 || err == -1)
+			goto do_next_sibling;
+		if (((pregs[0].phys_hi >> 8) & 0xff) == pdev->devfn) {
+			*nregs = err / sizeof(*pregs);
+			return node;
+		}
+
+	do_next_sibling:
+		node = prom_getsibling(node);
+	}
+	return 0;
+}
+
+/* Remove a PCI device from the device trees, then
+ * free it up.  Note that this must run before
+ * the device's resources are registered because we
+ * do not handle unregistering them here.
+ */
+static void pci_device_delete(struct pci_dev *pdev)
+{
+	struct pci_dev **dpp;
+
+	/* First, unlink from list of all devices. */
+	dpp = &pci_devices;
+	while (*dpp != NULL) {
+		if (*dpp == pdev) {
+			*dpp = pdev->next;
+			pdev->next = NULL;
+			break;
+		}
+		dpp = &(*dpp)->next;
+	}
+
+	/* Next, unlink from bus sibling chain. */
+	dpp = &pdev->bus->devices;
+	while (*dpp != NULL) {
+		if (*dpp == pdev) {
+			*dpp = pdev->sibling;
+			pdev->sibling = NULL;
+			break;
+		}
+		dpp = &(*dpp)->sibling;
+	}
+
+	/* Ok, all references are gone, free it up. */
+	kfree(pdev);
+}
+
+/* Fill in the PCI device cookie sysdata for the given
+ * PCI device.  This cookie is the means by which one
+ * can get to OBP and PCI controller specific information
+ * for a PCI device.
+ */
+static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm,
+				      struct pci_dev *pdev,
+				      int bus_prom_node)
+{
+	struct linux_prom_pci_registers pregs[PROMREG_MAX];
+	struct pcidev_cookie *pcp;
+	int device_prom_node, nregs, err;
+
+	device_prom_node = find_device_prom_node(pbm, pdev, bus_prom_node,
+						 pregs, &nregs);
+	if (device_prom_node == 0) {
+		/* If it is not in the OBP device tree then
+		 * there must be a damn good reason for it.
+		 *
+		 * So what we do is delete the device from the
+		 * PCI device tree completely.  This scenerio
+		 * is seen, for example, on CP1500 for the
+		 * second EBUS/HappyMeal pair if the external
+		 * connector for it is not present.
+		 */
+		pci_device_delete(pdev);
+		return;
+	}
+
+	pcp = kmalloc(sizeof(*pcp), GFP_ATOMIC);
+	if (pcp == NULL) {
+		prom_printf("PCI_COOKIE: Fatal malloc error, aborting...\n");
+		prom_halt();
+	}
+	pcp->pbm = pbm;
+	pcp->prom_node = device_prom_node;
+	memcpy(pcp->prom_regs, pregs, sizeof(pcp->prom_regs));
+	pcp->num_prom_regs = nregs;
+	err = prom_getproperty(device_prom_node, "name",
+			       pcp->prom_name, sizeof(pcp->prom_name));
+	if (err > 0)
+		pcp->prom_name[err] = 0;
+	else
+		pcp->prom_name[0] = 0;
+	if (strcmp(pcp->prom_name, "ebus") == 0) {
+		struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX];
+		int iter;
+
+		/* EBUS is special... */
+		err = prom_getproperty(device_prom_node, "ranges",
+				       (char *)&erng[0], sizeof(erng));
+		if (err == 0 || err == -1) {
+			prom_printf("EBUS: Fatal error, no range property\n");
+			prom_halt();
+		}
+		err = (err / sizeof(erng[0]));
+		for(iter = 0; iter < err; iter++) {
+			struct linux_prom_ebus_ranges *ep = &erng[iter];
+			struct linux_prom_pci_registers *ap;
+
+			ap = &pcp->prom_assignments[iter];
+
+			ap->phys_hi = ep->parent_phys_hi;
+			ap->phys_mid = ep->parent_phys_mid;
+			ap->phys_lo = ep->parent_phys_lo;
+			ap->size_hi = 0;
+			ap->size_lo = ep->size;
+		}
+		pcp->num_prom_assignments = err;
+	} else {
+		err = prom_getproperty(device_prom_node,
+				       "assigned-addresses",
+				       (char *)pcp->prom_assignments,
+				       sizeof(pcp->prom_assignments));
+		if (err == 0 || err == -1)
+			pcp->num_prom_assignments = 0;
+		else
+			pcp->num_prom_assignments =
+				(err / sizeof(pcp->prom_assignments[0]));
+	}
+
+	pdev->sysdata = pcp;
+}
+
+void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus,
+				    struct pci_pbm_info *pbm,
+				    int prom_node)
+{
+	struct pci_dev *pdev;
+
+	/* This loop is coded like this because the cookie
+	 * fillin routine can delete devices from the tree.
+	 */
+	pdev = pbus->devices;
+	while (pdev != NULL) {
+		struct pci_dev *next = pdev->sibling;
+
+		pdev_cookie_fillin(pbm, pdev, prom_node);
+
+		pdev = next;
+	}
+
+	for (pbus = pbus->children; pbus; pbus = pbus->next) {
+		struct pcidev_cookie *pcp = pbus->self->sysdata;
+		pci_fill_in_pbm_cookies(pbus, pbm, pcp->prom_node);
+	}
+}
+
+static void __init bad_assignment(struct linux_prom_pci_registers *ap,
+				  struct resource *res,
+				  int do_prom_halt)
+{
+	prom_printf("PCI: Bogus PROM assignment.\n");
+	if (ap)
+		prom_printf("PCI: phys[%08x:%08x:%08x] size[%08x:%08x]\n",
+			    ap->phys_hi, ap->phys_mid, ap->phys_lo,
+			    ap->size_hi, ap->size_lo);
+	if (res)
+		prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n",
+			    res->start, res->end, res->flags);
+	prom_printf("Please email this information to davem@redhat.com\n");
+	if (do_prom_halt)
+		prom_halt();
+}
+
+static struct resource *
+__init get_root_resource(struct linux_prom_pci_registers *ap,
+			 struct pci_pbm_info *pbm)
+{
+	int space = (ap->phys_hi >> 24) & 3;
+
+	switch (space) {
+	case 0:
+		/* Configuration space, silently ignore it. */
+		return NULL;
+
+	case 1:
+		/* 16-bit IO space */
+		return &pbm->io_space;
+
+	case 2:
+		/* 32-bit MEM space */
+		return &pbm->mem_space;
+
+	case 3:
+	default:
+		/* 64-bit MEM space, unsupported. */
+		printk("PCI: 64-bit MEM assignment??? "
+		       "Tell davem@redhat.com about it!\n");
+		return NULL;
+	};
+}
+
+static struct resource *
+__init get_device_resource(struct linux_prom_pci_registers *ap,
+			   struct pci_dev *pdev)
+{
+	int breg = (ap->phys_hi & 0xff);
+	int space = (ap->phys_hi >> 24) & 3;
+
+	switch (breg) {
+	case  PCI_ROM_ADDRESS:
+		/* It had better be MEM space. */
+		if (space != 2)
+			bad_assignment(ap, NULL, 0);
+
+		return &pdev->resource[PCI_ROM_RESOURCE];
+
+	case PCI_BASE_ADDRESS_0:
+	case PCI_BASE_ADDRESS_1:
+	case PCI_BASE_ADDRESS_2:
+	case PCI_BASE_ADDRESS_3:
+	case PCI_BASE_ADDRESS_4:
+	case PCI_BASE_ADDRESS_5:
+		return &pdev->resource[(breg - PCI_BASE_ADDRESS_0) / 4];
+
+	default:
+		bad_assignment(ap, NULL, 0);
+		return NULL;
+	};
+}
+
+static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
+					   struct pci_dev *pdev)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	int i;
+
+	for (i = 0; i < pcp->num_prom_assignments; i++) {
+		struct linux_prom_pci_registers *ap;
+		struct resource *root, *res;
+
+		/* The format of this property is specified in
+		 * the PCI Bus Binding to IEEE1275-1994.
+		 */
+		ap = &pcp->prom_assignments[i];
+		root = get_root_resource(ap, pbm);
+		res = get_device_resource(ap, pdev);
+		if (root == NULL || res == NULL)
+			continue;
+
+		/* Ok we know which resource this PROM assignment is
+		 * for, sanity check it.
+		 */
+		if ((res->start & 0xffffffffUL) != ap->phys_lo)
+			bad_assignment(ap, res, 1);
+
+		/* Adjust the resource into the physical address space
+		 * of this PBM.
+		 */
+		pbm->parent->resource_adjust(pdev, res, root);
+
+		if (request_resource(root, res) < 0) {
+			/* OK, there is some conflict.  But this is fine
+			 * since we'll reassign it in the fixup pass.
+			 * Nevertheless notify the user that OBP made
+			 * an error.
+			 */
+			printk(KERN_ERR "PCI: Address space collision on region %ld "
+			       "of device %s\n",
+			       (res - &pdev->resource[0]), pdev->name);
+		}
+	}
+}
+
+void __init pci_record_assignments(struct pci_pbm_info *pbm,
+				   struct pci_bus *pbus)
+{
+	struct pci_dev *pdev;
+
+	for (pdev = pbus->devices; pdev; pdev = pdev->sibling)
+		pdev_record_assignments(pbm, pdev);
+
+	for (pbus = pbus->children; pbus; pbus = pbus->next)
+		pci_record_assignments(pbm, pbus);
+}
+
+static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm,
+					  struct pci_dev *pdev)
+{
+	u32 reg;
+	u16 cmd;
+	int i, io_seen, mem_seen;
+
+	io_seen = mem_seen = 0;
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		struct resource *root, *res;
+		unsigned long size, min, max, align;
+
+		res = &pdev->resource[i];
+
+		if (res->flags & IORESOURCE_IO)
+			io_seen++;
+		else if (res->flags & IORESOURCE_MEM)
+			mem_seen++;
+
+		/* If it is already assigned or the resource does
+		 * not exist, there is nothing to do.
+		 */
+		if (res->parent != NULL || res->flags == 0UL)
+			continue;
+
+		/* Determine the root we allocate from. */
+		if (res->flags & IORESOURCE_IO) {
+			root = &pbm->io_space;
+			min = root->start + 0x400UL;
+			max = root->end;
+		} else {
+			root = &pbm->mem_space;
+			min = root->start;
+			max = min + 0x80000000UL;
+		}
+
+		size = res->end - res->start;
+		align = size + 1;
+		if (allocate_resource(root, res, size + 1, min, max, align) < 0) {
+			/* uh oh */
+			prom_printf("PCI: Failed to allocate resource %d for %s\n",
+				    i, pdev->name);
+			prom_halt();
+		}
+
+		/* Update PCI config space. */
+		pbm->parent->base_address_update(pdev, i);
+	}
+
+	/* Special case, disable the ROM.  Several devices
+	 * act funny (ie. do not respond to memory space writes)
+	 * when it is left enabled.  A good example are Qlogic,ISP
+	 * adapters.
+	 */
+	pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &reg);
+	reg &= ~PCI_ROM_ADDRESS_ENABLE;
+	pci_write_config_dword(pdev, PCI_ROM_ADDRESS, reg);
+
+	/* If we saw I/O or MEM resources, enable appropriate
+	 * bits in PCI command register.
+	 */
+	if (io_seen || mem_seen) {
+		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+		if (io_seen)
+			cmd |= PCI_COMMAND_IO;
+		if (mem_seen)
+			cmd |= PCI_COMMAND_MEMORY;
+		pci_write_config_word(pdev, PCI_COMMAND, cmd);
+	}
+
+	/* If this is a PCI bridge or an IDE controller,
+	 * enable bus mastering.  In the former case also
+	 * set the cache line size correctly.
+	 */
+	if (((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI) ||
+	    (((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) &&
+	     ((pdev->class & 0x80) != 0))) {
+		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+		cmd |= PCI_COMMAND_MASTER;
+		pci_write_config_word(pdev, PCI_COMMAND, cmd);
+
+		if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
+			pci_write_config_byte(pdev,
+					      PCI_CACHE_LINE_SIZE,
+					      (64 / sizeof(u32)));
+	}
+}
+
+void __init pci_assign_unassigned(struct pci_pbm_info *pbm,
+				  struct pci_bus *pbus)
+{
+	struct pci_dev *pdev;
+
+	for (pdev = pbus->devices; pdev; pdev = pdev->sibling)
+		pdev_assign_unassigned(pbm, pdev);
+
+	for (pbus = pbus->children; pbus; pbus = pbus->next)
+		pci_assign_unassigned(pbm, pbus);
+}
+
+static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt)
+{
+	struct pcidev_cookie *dev_pcp = pdev->sysdata;
+	struct pci_pbm_info *pbm = dev_pcp->pbm;
+	struct linux_prom_pci_registers *pregs = dev_pcp->prom_regs;
+	unsigned int hi, mid, lo, irq;
+	int i;
+
+	if (pbm->num_pbm_intmap == 0)
+		return 0;
+
+	/* If we are underneath a PCI bridge, use PROM register
+	 * property of parent bridge.
+	 */
+	if (pdev->bus->number != pbm->pci_first_busno) {
+		struct pcidev_cookie *bus_pcp;
+		int offset;
+
+		bus_pcp = pdev->bus->self->sysdata;
+		pregs = bus_pcp->prom_regs;
+		offset = prom_getint(bus_pcp->prom_node,
+				     "fcode-rom-offset");
+
+		/* Did PROM know better and assign an interrupt other
+		 * than #INTA to the device? - We test here for presence of
+		 * FCODE on the card, in this case we assume PROM has set
+		 * correct 'interrupts' property, unless it is quadhme.
+		 */
+		if (offset == -1 ||
+		    !strcmp(bus_pcp->prom_name, "SUNW,qfe") ||
+		    !strcmp(bus_pcp->prom_name, "qfe")) {
+			/*
+			 * No, use low slot number bits of child as IRQ line.
+			 */
+			*interrupt = ((*interrupt - 1 + PCI_SLOT(pdev->devfn)) & 3) + 1;
+		}
+	}
+
+	hi   = pregs->phys_hi & pbm->pbm_intmask.phys_hi;
+	mid  = pregs->phys_mid & pbm->pbm_intmask.phys_mid;
+	lo   = pregs->phys_lo & pbm->pbm_intmask.phys_lo;
+	irq  = *interrupt & pbm->pbm_intmask.interrupt;
+
+	for (i = 0; i < pbm->num_pbm_intmap; i++) {
+		if (pbm->pbm_intmap[i].phys_hi  == hi	&&
+		    pbm->pbm_intmap[i].phys_mid == mid	&&
+		    pbm->pbm_intmap[i].phys_lo  == lo	&&
+		    pbm->pbm_intmap[i].interrupt == irq) {
+			*interrupt = pbm->pbm_intmap[i].cinterrupt;
+			return 1;
+		}
+	}
+
+	prom_printf("pbm_intmap_match: bus %02x, devfn %02x: ",
+		    pdev->bus->number, pdev->devfn);
+	prom_printf("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n",
+		    pregs->phys_hi, pregs->phys_mid, pregs->phys_lo, *interrupt);
+	prom_printf("Please email this information to davem@redhat.com\n");
+	prom_halt();
+}
+
+static void __init pdev_fixup_irq(struct pci_dev *pdev)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_pbm_info *pbm = pcp->pbm;
+	struct pci_controller_info *p = pbm->parent;
+	unsigned int portid = p->portid;
+	unsigned int prom_irq;
+	int prom_node = pcp->prom_node;
+	int err;
+
+	err = prom_getproperty(prom_node, "interrupts",
+			       (char *)&prom_irq, sizeof(prom_irq));
+	if (err == 0 || err == -1) {
+		pdev->irq = 0;
+		return;
+	}
+
+	/* Fully specified already? */
+	if (((prom_irq & PCI_IRQ_IGN) >> 6) == portid) {
+		pdev->irq = p->irq_build(p, pdev, prom_irq);
+		goto have_irq;
+	}
+
+	/* An onboard device? (bit 5 set) */
+	if ((prom_irq & PCI_IRQ_INO) & 0x20) {
+		pdev->irq = p->irq_build(p, pdev, (portid << 6 | prom_irq));
+		goto have_irq;
+	}
+
+	/* Can we find a matching entry in the interrupt-map? */
+	if (pci_intmap_match(pdev, &prom_irq)) {
+		pdev->irq = p->irq_build(p, pdev, (portid << 6) | prom_irq);
+		goto have_irq;
+	}
+
+	/* Ok, we have to do it the hard way. */
+	{
+		unsigned int bus, slot, line;
+
+		bus = (pbm == &pbm->parent->pbm_B) ? (1 << 4) : 0;
+
+		/* If we have a legal interrupt property, use it as
+		 * the IRQ line.
+		 */
+		if (prom_irq > 0 && prom_irq < 5) {
+			line = ((prom_irq - 1) & 3);
+		} else {
+			u8 pci_irq_line;
+
+			/* Else just directly consult PCI config space. */
+			pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pci_irq_line);
+			line = ((pci_irq_line - 1) & 3);
+		}
+
+		/* Now figure out the slot. */
+		if (pdev->bus->number == pbm->pci_first_busno) {
+			if (pbm == &pbm->parent->pbm_A)
+				slot = (pdev->devfn >> 3) - 1;
+			else
+				slot = (pdev->devfn >> 3) - 2;
+		} else {
+			if (pbm == &pbm->parent->pbm_A)
+				slot = (pdev->bus->self->devfn >> 3) - 1;
+			else
+				slot = (pdev->bus->self->devfn >> 3) - 2;
+		}
+		slot = slot << 2;
+
+		pdev->irq = p->irq_build(p, pdev,
+					 ((portid << 6) & PCI_IRQ_IGN) |
+					 (bus | slot | line));
+	}
+
+have_irq:
+	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE,
+			      pdev->irq & PCI_IRQ_INO);
+}
+
+void __init pci_fixup_irq(struct pci_pbm_info *pbm,
+			  struct pci_bus *pbus)
+{
+	struct pci_dev *pdev;
+
+	for (pdev = pbus->devices; pdev; pdev = pdev->sibling)
+		pdev_fixup_irq(pdev);
+
+	for (pbus = pbus->children; pbus; pbus = pbus->next)
+		pci_fixup_irq(pbm, pbus);
+}
+
+/* Generic helper routines for PCI error reporting. */
+void pci_scan_for_target_abort(struct pci_controller_info *p,
+			       struct pci_pbm_info *pbm,
+			       struct pci_bus *pbus)
+{
+	struct pci_dev *pdev;
+
+	for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+		u16 status, error_bits;
+
+		pci_read_config_word(pdev, PCI_STATUS, &status);
+		error_bits =
+			(status & (PCI_STATUS_SIG_TARGET_ABORT |
+				   PCI_STATUS_REC_TARGET_ABORT));
+		if (error_bits) {
+			pci_write_config_word(pdev, PCI_STATUS, error_bits);
+			printk("PCI%d(PBM%c): Device [%s] saw Target Abort [%016x]\n",
+			       p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'),
+			       pdev->name, status);
+		}
+	}
+
+	for (pbus = pbus->children; pbus; pbus = pbus->next)
+		pci_scan_for_target_abort(p, pbm, pbus);
+}
+
+void pci_scan_for_master_abort(struct pci_controller_info *p,
+			       struct pci_pbm_info *pbm,
+			       struct pci_bus *pbus)
+{
+	struct pci_dev *pdev;
+
+	for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+		u16 status, error_bits;
+
+		pci_read_config_word(pdev, PCI_STATUS, &status);
+		error_bits =
+			(status & (PCI_STATUS_REC_MASTER_ABORT));
+		if (error_bits) {
+			pci_write_config_word(pdev, PCI_STATUS, error_bits);
+			printk("PCI%d(PBM%c): Device [%s] received Master Abort [%016x]\n",
+			       p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'),
+			       pdev->name, status);
+		}
+	}
+
+	for (pbus = pbus->children; pbus; pbus = pbus->next)
+		pci_scan_for_master_abort(p, pbm, pbus);
+}
+
+void pci_scan_for_parity_error(struct pci_controller_info *p,
+			       struct pci_pbm_info *pbm,
+			       struct pci_bus *pbus)
+{
+	struct pci_dev *pdev;
+
+	for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+		u16 status, error_bits;
+
+		pci_read_config_word(pdev, PCI_STATUS, &status);
+		error_bits =
+			(status & (PCI_STATUS_PARITY |
+				   PCI_STATUS_DETECTED_PARITY));
+		if (error_bits) {
+			pci_write_config_word(pdev, PCI_STATUS, error_bits);
+			printk("PCI%d(PBM%c): Device [%s] saw Parity Error [%016x]\n",
+			       p->index, ((pbm == &p->pbm_A) ? 'A' : 'B'),
+			       pdev->name, status);
+		}
+	}
+
+	for (pbus = pbus->children; pbus; pbus = pbus->next)
+		pci_scan_for_parity_error(p, pbm, pbus);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/pci_impl.h linux/arch/sparc64/kernel/pci_impl.h
--- v2.3.15/linux/arch/sparc64/kernel/pci_impl.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/pci_impl.h	Tue Aug 31 11:23:30 1999
@@ -0,0 +1,166 @@
+/* $Id: pci_impl.h,v 1.1 1999/08/30 10:00:44 davem Exp $
+ * pci_impl.h: Helper definitions for PCI controller support.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef PCI_IMPL_H
+#define PCI_IMPL_H
+
+#include <linux/types.h>
+#include <asm/spinlock.h>
+#include <asm/io.h>
+
+extern spinlock_t pci_controller_lock;
+extern struct pci_controller_info *pci_controller_root;
+
+extern struct pci_pbm_info *pci_bus2pbm[256];
+extern unsigned char pci_highest_busnum;
+extern int pci_num_controllers;
+
+/* PCI bus scanning and fixup support. */
+extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus,
+				    struct pci_pbm_info *pbm,
+				    int prom_node);
+extern void pci_record_assignments(struct pci_pbm_info *pbm,
+				   struct pci_bus *pbus);
+extern void pci_assign_unassigned(struct pci_pbm_info *pbm,
+				  struct pci_bus *pbus);
+extern void pci_fixup_irq(struct pci_pbm_info *pbm,
+			  struct pci_bus *pbus);
+
+/* Error reporting support. */
+extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
+extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
+extern void pci_scan_for_parity_error(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
+
+/* IOMMU/DVMA initialization. */
+extern unsigned long pci_dvma_offset;
+extern unsigned long pci_dvma_mask;
+#define PCI_DVMA_HASH_NONE	~0UL
+static __inline__ void set_dvma_hash(unsigned long paddr, unsigned long daddr)
+{
+	unsigned long dvma_addr = pci_dvma_offset + daddr;
+	unsigned long vaddr = (unsigned long)__va(paddr);
+
+	pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] = dvma_addr - vaddr;
+	pci_dvma_p2v_hash[pci_dvma_ahashfn(dvma_addr)] = vaddr - dvma_addr;
+}
+
+/* Configuration space access. */
+extern spinlock_t pci_poke_lock;
+extern volatile int pci_poke_in_progress;
+extern volatile int pci_poke_faulted;
+
+static __inline__ void pci_config_read8(u8 *addr, u8 *ret)
+{
+	unsigned long flags;
+	u8 byte;
+
+	spin_lock_irqsave(&pci_poke_lock, flags);
+	pci_poke_in_progress = 1;
+	pci_poke_faulted = 0;
+	__asm__ __volatile__("membar #Sync\n\t"
+			     "lduba [%1] %2, %0\n\t"
+			     "membar #Sync"
+			     : "=r" (byte)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+	pci_poke_in_progress = 0;
+	if (!pci_poke_faulted)
+		*ret = byte;
+	spin_unlock_irqrestore(&pci_poke_lock, flags);
+}
+
+static __inline__ void pci_config_read16(u16 *addr, u16 *ret)
+{
+	unsigned long flags;
+	u16 word;
+
+	spin_lock_irqsave(&pci_poke_lock, flags);
+	pci_poke_in_progress = 1;
+	pci_poke_faulted = 0;
+	__asm__ __volatile__("membar #Sync\n\t"
+			     "lduha [%1] %2, %0\n\t"
+			     "membar #Sync"
+			     : "=r" (word)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+	pci_poke_in_progress = 0;
+	if (!pci_poke_faulted)
+		*ret = word;
+	spin_unlock_irqrestore(&pci_poke_lock, flags);
+}
+
+static __inline__ void pci_config_read32(u32 *addr, u32 *ret)
+{
+	unsigned long flags;
+	u32 dword;
+
+	spin_lock_irqsave(&pci_poke_lock, flags);
+	pci_poke_in_progress = 1;
+	pci_poke_faulted = 0;
+	__asm__ __volatile__("membar #Sync\n\t"
+			     "lduwa [%1] %2, %0\n\t"
+			     "membar #Sync"
+			     : "=r" (dword)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+	pci_poke_in_progress = 0;
+	if (!pci_poke_faulted)
+		*ret = dword;
+	spin_unlock_irqrestore(&pci_poke_lock, flags);
+}
+
+static __inline__ void pci_config_write8(u8 *addr, u8 val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pci_poke_lock, flags);
+	pci_poke_in_progress = 1;
+	pci_poke_faulted = 0;
+	__asm__ __volatile__("membar #Sync\n\t"
+			     "stba %0, [%1] %2\n\t"
+			     "membar #Sync"
+			     : /* no outputs */
+			     : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+	pci_poke_in_progress = 0;
+	spin_unlock_irqrestore(&pci_poke_lock, flags);
+}
+
+static __inline__ void pci_config_write16(u16 *addr, u16 val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pci_poke_lock, flags);
+	pci_poke_in_progress = 1;
+	pci_poke_faulted = 0;
+	__asm__ __volatile__("membar #Sync\n\t"
+			     "stha %0, [%1] %2\n\t"
+			     "membar #Sync"
+			     : /* no outputs */
+			     : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+	pci_poke_in_progress = 0;
+	spin_unlock_irqrestore(&pci_poke_lock, flags);
+}
+
+static __inline__ void pci_config_write32(u32 *addr, u32 val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&pci_poke_lock, flags);
+	pci_poke_in_progress = 1;
+	pci_poke_faulted = 0;
+	__asm__ __volatile__("membar #Sync\n\t"
+			     "stwa %0, [%1] %2\n\t"
+			     "membar #Sync"
+			     : /* no outputs */
+			     : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L)
+			     : "memory");
+	pci_poke_in_progress = 0;
+	spin_unlock_irqrestore(&pci_poke_lock, flags);
+}
+
+#endif /* !(PCI_IMPL_H) */
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/pci_iommu.c linux/arch/sparc64/kernel/pci_iommu.c
--- v2.3.15/linux/arch/sparc64/kernel/pci_iommu.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/pci_iommu.c	Tue Aug 31 11:23:30 1999
@@ -0,0 +1,510 @@
+/* $Id: pci_iommu.c,v 1.1 1999/08/30 10:00:47 davem Exp $
+ * pci_iommu.c: UltraSparc PCI controller IOM/STC support.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include <asm/pbm.h>
+#include <asm/iommu.h>
+#include <asm/scatterlist.h>
+
+#define PCI_STC_CTXMATCH_ADDR(STC, CTX)	\
+	((STC)->strbuf_ctxmatch_base + ((CTX) << 3))
+
+/* Accessing IOMMU and Streaming Buffer registers.
+ * REG parameter is a physical address.  All registers
+ * are 64-bits in size.
+ */
+#define pci_iommu_read(__reg) \
+({	u64 __ret; \
+	__asm__ __volatile__("ldxa [%1] %2, %0" \
+			     : "=r" (__ret) \
+			     : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
+			     : "memory"); \
+	__ret; \
+})
+#define pci_iommu_write(__reg, __val) \
+	__asm__ __volatile__("stxa %0, [%1] %2" \
+			     : /* no outputs */ \
+			     : "r" (__val), "r" (__reg), \
+			       "i" (ASI_PHYS_BYPASS_EC_E))
+
+/* Find a range of iommu mappings of size NPAGES in page
+ * table PGT.  Return pointer to first iopte.
+ */
+static iopte_t *iommu_find_range(unsigned long npages, iopte_t *pgt, int pgt_size)
+{
+	int i;
+
+	pgt_size -= npages;
+	for (i = 0; i < pgt_size; i++) {
+		if (!iopte_val(pgt[i]) & IOPTE_VALID) {
+			int scan;
+
+			for (scan = 1; scan < npages; scan++) {
+				if (iopte_val(pgt[i + scan]) & IOPTE_VALID) {
+					i += scan;
+					goto do_next;
+				}
+			}
+			return &pgt[i];
+		}
+	do_next:
+	}
+	return NULL;
+}
+
+#define IOPTE_CONSISTANT(CTX, PADDR) \
+	(IOPTE_VALID | IOPTE_CACHE | IOPTE_WRITE | \
+	 (((CTX) << 47) & IOPTE_CONTEXT) | \
+	 ((PADDR) & IOPTE_PAGE))
+
+#define IOPTE_STREAMING(CTX, PADDR) \
+	(IOPTE_CONSISTANT(CTX, PADDR) | IOPTE_STBUF)
+
+#define IOPTE_INVALID	0UL
+
+/* Map kernel buffer at ADDR of size SZ using consistant mode
+ * DMA for PCI device PDEV.  Return 32-bit PCI DMA address.
+ */
+u32 pci_map_consistant(struct pci_dev *pdev, void *addr, int sz)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+	iopte_t *base;
+	unsigned long flags, npages, oaddr;
+	u32 ret;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	oaddr = (unsigned long)addr;
+	npages = PAGE_ALIGN(oaddr + sz) - (oaddr & PAGE_MASK);
+	npages >>= PAGE_SHIFT;
+	base = iommu_find_range(npages,
+				iommu->page_table, iommu->page_table_sz);
+	ret = 0;
+	if (base != NULL) {
+		unsigned long i, base_paddr, ctx;
+
+		ret = (iommu->page_table_map_base +
+		       ((base - iommu->page_table) << PAGE_SHIFT));
+		ret |= (oaddr & ~PAGE_MASK);
+		base_paddr = __pa(oaddr & PAGE_MASK);
+		ctx = 0;
+		if (iommu->iommu_has_ctx_flush)
+			ctx = iommu->iommu_cur_ctx++;
+		for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE)
+			iopte_val(*base) = IOPTE_CONSISTANT(ctx, base_paddr);
+	}
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	return ret;
+}
+
+/* Unmap a consistant DMA translation. */
+void pci_unmap_consistant(struct pci_dev *pdev, u32 bus_addr, int sz)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+	iopte_t *base;
+	unsigned long flags, npages, i, ctx;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK);
+	npages >>= PAGE_SHIFT;
+	base = iommu->page_table +
+		((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT);
+
+	/* Data for consistant mappings cannot enter the streaming
+	 * buffers, so we only need to update the TSB and flush
+	 * those entries from the IOMMU's TLB.
+	 */
+
+	/* Step 1: Clear out the TSB entries.  Save away
+	 *         the context if necessary.
+	 */
+	ctx = 0;
+	if (iommu->iommu_has_ctx_flush)
+		ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+	for (i = 0; i < npages; i++, base++)
+		iopte_val(*base) = IOPTE_INVALID;
+
+	/* Step 2: Flush from IOMMU TLB. */
+	if (iommu->iommu_has_ctx_flush) {
+		pci_iommu_write(iommu->iommu_ctxflush, ctx);
+	} else {
+		bus_addr &= PAGE_MASK;
+		for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE)
+			pci_iommu_write(iommu->iommu_flush, bus_addr);
+	}
+
+	/* Step 3: Ensure completion of previous PIO writes. */
+	(void) pci_iommu_read(iommu->write_complete_reg);
+
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+/* Map a single buffer at PTR of SZ bytes for PCI DMA
+ * in streaming mode.
+ */
+u32 pci_map_single(struct pci_dev *pdev, void *ptr, int sz)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+	iopte_t *base;
+	unsigned long flags, npages, oaddr;
+	u32 ret;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	oaddr = (unsigned long)ptr;
+	npages = PAGE_ALIGN(oaddr + sz) - (oaddr & PAGE_MASK);
+	npages >>= PAGE_SHIFT;
+	base = iommu_find_range(npages,
+				iommu->page_table, iommu->page_table_sz);
+	ret = 0;
+	if (base != NULL) {
+		unsigned long i, base_paddr, ctx;
+
+		ret = (iommu->page_table_map_base +
+		       ((base - iommu->page_table) << PAGE_SHIFT));
+		ret |= (oaddr & ~PAGE_MASK);
+		base_paddr = __pa(oaddr & PAGE_MASK);
+		ctx = 0;
+		if (iommu->iommu_has_ctx_flush)
+			ctx = iommu->iommu_cur_ctx++;
+		for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE)
+			iopte_val(*base) = IOPTE_STREAMING(ctx, base_paddr);
+	}
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	return ret;
+}
+
+/* Unmap a single streaming mode DMA translation. */
+void pci_unmap_single(struct pci_dev *pdev, u32 bus_addr, int sz)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+	struct pci_strbuf *strbuf = &pcp->pbm->stc;
+	iopte_t *base;
+	unsigned long flags, npages, i, ctx;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK);
+	npages >>= PAGE_SHIFT;
+	base = iommu->page_table +
+		((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT);
+	bus_addr &= PAGE_MASK;
+
+	/* Step 1: Record the context, if any. */
+	ctx = 0;
+	if (iommu->iommu_has_ctx_flush)
+		ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+
+	/* Step 2: Kick data out of streaming buffers if necessary. */
+	if (strbuf->strbuf_enabled) {
+		u32 vaddr = bus_addr;
+
+		PCI_STC_FLUSHFLAG_INIT(strbuf);
+		if (strbuf->strbuf_has_ctx_flush &&
+		    iommu->iommu_has_ctx_flush) {
+			unsigned long matchreg, flushreg;
+
+			flushreg = strbuf->strbuf_ctxflush;
+			matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+			do {
+				pci_iommu_write(flushreg, ctx);
+			} while(((long)pci_iommu_read(matchreg)) < 0L);
+		} else {
+			for (i = 0; i < npages; i++, vaddr += PAGE_SIZE)
+				pci_iommu_write(strbuf->strbuf_pflush, vaddr);
+		}
+
+		pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+		(void) pci_iommu_read(iommu->write_complete_reg);
+		while (!PCI_STC_FLUSHFLAG_SET(strbuf))
+			membar("#LoadLoad");
+	}
+
+	/* Step 3: Clear out TSB entries. */
+	for (i = 0; i < npages; i++, base++)
+		iopte_val(*base) = IOPTE_INVALID;
+
+	/* Step 4: Flush the IOMMU TLB. */
+	if (iommu->iommu_has_ctx_flush) {
+		pci_iommu_write(iommu->iommu_ctxflush, ctx);
+	} else {
+		for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE)
+			pci_iommu_write(iommu->iommu_flush, bus_addr);
+	}
+
+	/* Step 5: Ensure completion of previous PIO writes. */
+	(void) pci_iommu_read(iommu->write_complete_reg);
+
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+/* Map a set of buffers described by SGLIST with NELEMS array
+ * elements in streaming mode for PCI DMA.
+ */
+void pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+	unsigned long flags, ctx, i;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+
+	/* Step 1: Choose a context if necessary. */
+	ctx = 0;
+	if (iommu->iommu_has_ctx_flush)
+		ctx = iommu->iommu_cur_ctx++;
+
+	/* Step 2: Create the mappings. */
+	for (i = 0; i < nelems; i++) {
+		unsigned long oaddr, npages;
+		iopte_t *base;
+
+		oaddr = (unsigned long)sglist[i].address;
+		npages = PAGE_ALIGN(oaddr + sglist[i].length) - (oaddr & PAGE_MASK);
+		npages >>= PAGE_SHIFT;
+		base = iommu_find_range(npages,
+					iommu->page_table, iommu->page_table_sz);
+		if (base != NULL) {
+			unsigned long j, base_paddr;
+			u32 dvma_addr;
+
+			dvma_addr = (iommu->page_table_map_base +
+				     ((base - iommu->page_table) << PAGE_SHIFT));
+			dvma_addr |= (oaddr & ~PAGE_MASK);
+			sglist[i].dvma_address = dvma_addr;
+			sglist[i].dvma_length = sglist[i].length;
+			base_paddr = __pa(oaddr & PAGE_MASK);
+			for (j = 0; j < npages; j++, base++, base_paddr += PAGE_SIZE)
+				iopte_val(*base) = IOPTE_STREAMING(ctx, base_paddr);
+		} else {
+			sglist[i].dvma_address = 0;
+			sglist[i].dvma_length = 0;
+		}
+	}
+
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+/* Unmap a set of streaming mode DMA translations. */
+void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+	struct pci_strbuf *strbuf = &pcp->pbm->stc;
+	unsigned long flags, ctx, i;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+
+	/* Step 1: Record the context, if any. */
+	ctx = 0;
+	if (iommu->iommu_has_ctx_flush) {
+		iopte_t *iopte;
+
+		iopte = iommu->page_table +
+			((sglist[0].dvma_address - iommu->page_table_map_base) >> PAGE_SHIFT);
+		ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
+	}
+
+	/* Step 2: Kick data out of streaming buffers if necessary. */
+	if (strbuf->strbuf_enabled) {
+		PCI_STC_FLUSHFLAG_INIT(strbuf);
+		if (strbuf->strbuf_has_ctx_flush &&
+		    iommu->iommu_has_ctx_flush) {
+			unsigned long matchreg, flushreg;
+
+			flushreg = strbuf->strbuf_ctxflush;
+			matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+			do {
+				pci_iommu_write(flushreg, ctx);
+			} while(((long)pci_iommu_read(matchreg)) < 0L);
+		} else {
+			for (i = 0; i < nelems; i++) {
+				unsigned long j, npages;
+				u32 vaddr;
+
+				j = sglist[i].dvma_length;
+				if (!j)
+					break;
+				vaddr = sglist[i].dvma_address;
+				npages = PAGE_ALIGN(vaddr + j) - (vaddr & PAGE_MASK);
+				npages >>= PAGE_SHIFT;
+				vaddr &= PAGE_MASK;
+				for (j = 0; j < npages; j++, vaddr += PAGE_SIZE)
+					pci_iommu_write(strbuf->strbuf_pflush, vaddr);
+			}
+
+			pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+			(void) pci_iommu_read(iommu->write_complete_reg);
+			while (!PCI_STC_FLUSHFLAG_SET(strbuf))
+				membar("#LoadLoad");
+		}
+	}
+
+	/* Step 3: Clear out TSB entries. */
+	for (i = 0; i < nelems; i++) {
+		unsigned long j, npages;
+		iopte_t *base;
+		u32 vaddr;
+
+		j = sglist[i].dvma_length;
+		if (!j)
+			break;
+		vaddr = sglist[i].dvma_address;
+		npages = PAGE_ALIGN(vaddr + j) - (vaddr & PAGE_MASK);
+		npages >>= PAGE_SHIFT;
+		base = iommu->page_table +
+			((vaddr - iommu->page_table_map_base) >> PAGE_SHIFT);
+		for (j = 0; j < npages; j++, base++)
+			iopte_val(*base) = IOPTE_INVALID;
+	}
+
+	/* Step 4: Flush the IOMMU TLB. */
+	if (iommu->iommu_has_ctx_flush) {
+		pci_iommu_write(iommu->iommu_ctxflush, ctx);
+	} else {
+		for (i = 0; i < nelems; i++) {
+			unsigned long j, npages;
+			u32 vaddr;
+
+			j = sglist[i].dvma_length;
+			if (!j)
+				break;
+			vaddr = sglist[i].dvma_address;
+			npages = PAGE_ALIGN(vaddr + j) - (vaddr & PAGE_MASK);
+			npages >>= PAGE_SHIFT;
+			for (j = 0; j < npages; j++, vaddr += PAGE_SIZE)
+				pci_iommu_write(iommu->iommu_flush, vaddr);
+		}
+	}
+
+	/* Step 5: Ensure completion of previous PIO writes. */
+	(void) pci_iommu_read(iommu->write_complete_reg);
+
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+/* Make physical memory consistant for a single
+ * streaming mode DMA translation after a transfer.
+ */
+void pci_dma_sync_single(struct pci_dev *pdev, u32 bus_addr, int sz)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+	struct pci_strbuf *strbuf = &pcp->pbm->stc;
+	unsigned long flags, ctx, npages;
+
+	if (!strbuf->strbuf_enabled)
+		return;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+
+	npages = PAGE_ALIGN(bus_addr + sz) - (bus_addr & PAGE_MASK);
+	npages >>= PAGE_SHIFT;
+	bus_addr &= PAGE_MASK;
+
+	/* Step 1: Record the context, if any. */
+	ctx = 0;
+	if (iommu->iommu_has_ctx_flush &&
+	    strbuf->strbuf_has_ctx_flush) {
+		iopte_t *iopte;
+
+		iopte = iommu->page_table +
+			((bus_addr - iommu->page_table_map_base)>>PAGE_SHIFT);
+		ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
+	}
+
+	/* Step 2: Kick data out of streaming buffers. */
+	PCI_STC_FLUSHFLAG_INIT(strbuf);
+	if (iommu->iommu_has_ctx_flush &&
+	    strbuf->strbuf_has_ctx_flush) {
+		unsigned long matchreg, flushreg;
+
+		flushreg = strbuf->strbuf_ctxflush;
+		matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+		do {
+			pci_iommu_write(flushreg, ctx);
+		} while(((long)pci_iommu_read(matchreg)) < 0L);
+	} else {
+		unsigned long i;
+
+		for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE)
+			pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
+	}
+
+	/* Step 3: Perform flush synchronization sequence. */
+	pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+	(void) pci_iommu_read(iommu->write_complete_reg);
+	while (!PCI_STC_FLUSHFLAG_SET(strbuf))
+		membar("#LoadLoad");
+
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+/* Make physical memory consistant for a set of streaming
+ * mode DMA translations after a transfer.
+ */
+void pci_dma_sync_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
+	struct pci_strbuf *strbuf = &pcp->pbm->stc;
+	unsigned long flags, ctx;
+
+	if (!strbuf->strbuf_enabled)
+		return;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+
+	/* Step 1: Record the context, if any. */
+	ctx = 0;
+	if (iommu->iommu_has_ctx_flush &&
+	    strbuf->strbuf_has_ctx_flush) {
+		iopte_t *iopte;
+
+		iopte = iommu->page_table +
+			((sglist[0].dvma_address - iommu->page_table_map_base) >> PAGE_SHIFT);
+		ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
+	}
+
+	/* Step 2: Kick data out of streaming buffers. */
+	PCI_STC_FLUSHFLAG_INIT(strbuf);
+	if (iommu->iommu_has_ctx_flush &&
+	    strbuf->strbuf_has_ctx_flush) {
+		unsigned long matchreg, flushreg;
+
+		flushreg = strbuf->strbuf_ctxflush;
+		matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+		do {
+			pci_iommu_write(flushreg, ctx);
+		} while (((long)pci_iommu_read(matchreg)) < 0L);
+	} else {
+		unsigned long i;
+
+		for(i = 0; i < nelems; i++) {
+			unsigned long bus_addr, npages, j;
+
+			j = sglist[i].dvma_length;
+			if (!j)
+				break;
+			bus_addr = sglist[i].dvma_address;
+			npages = PAGE_ALIGN(bus_addr + j) - (bus_addr & PAGE_MASK);
+			npages >>= PAGE_SHIFT;
+			bus_addr &= PAGE_MASK;
+			for(j = 0; i < npages; i++, bus_addr += PAGE_SIZE)
+				pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
+		}
+	}
+
+	/* Step 3: Perform flush synchronization sequence. */
+	pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+	(void) pci_iommu_read(iommu->write_complete_reg);
+	while (!PCI_STC_FLUSHFLAG_SET(strbuf))
+		membar("#LoadLoad");
+
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c
--- v2.3.15/linux/arch/sparc64/kernel/pci_psycho.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/pci_psycho.c	Tue Aug 31 11:23:30 1999
@@ -0,0 +1,1604 @@
+/* $Id: pci_psycho.c,v 1.2 1999/08/31 09:12:34 davem Exp $
+ * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
+ *
+ * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
+ * Copyright (C) 1998, 1999 Eddie C. Dost   (ecd@skynet.be)
+ * Copyright (C) 1999 Jakub Jelinek   (jj@ultra.linux.cz)
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+
+#include <asm/pbm.h>
+#include <asm/iommu.h>
+#include <asm/irq.h>
+
+#include "pci_impl.h"
+
+/* All PSYCHO registers are 64-bits.  The following accessor
+ * routines are how they are accessed.  The REG parameter
+ * is a physical address.
+ */
+#define psycho_read(__reg) \
+({	u64 __ret; \
+	__asm__ __volatile__("ldxa [%1] %2, %0" \
+			     : "=r" (__ret) \
+			     : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
+			     : "memory"); \
+	__ret; \
+})
+#define psycho_write(__reg, __val) \
+	__asm__ __volatile__("stxa %0, [%1] %2" \
+			     : /* no outputs */ \
+			     : "r" (__val), "r" (__reg), \
+			       "i" (ASI_PHYS_BYPASS_EC_E))
+
+/* Misc. PSYCHO PCI controller register offsets and definitions. */
+#define PSYCHO_CONTROL		0x0010UL
+#define  PSYCHO_CONTROL_IMPL	 0xf000000000000000 /* Implementation of this PSYCHO*/
+#define  PSYCHO_CONTROL_VER	 0x0f00000000000000 /* Version of this PSYCHO       */
+#define  PSYCHO_CONTROL_MID	 0x00f8000000000000 /* UPA Module ID of PSYCHO      */
+#define  PSYCHO_CONTROL_IGN	 0x0007c00000000000 /* Interrupt Group Number       */
+#define  PSYCHO_CONTROL_RESV     0x00003ffffffffff0 /* Reserved                     */
+#define  PSYCHO_CONTROL_APCKEN	 0x0000000000000008 /* Address Parity Check Enable  */
+#define  PSYCHO_CONTROL_APERR	 0x0000000000000004 /* Incoming System Addr Parerr  */
+#define  PSYCHO_CONTROL_IAP	 0x0000000000000002 /* Invert UPA Parity            */
+#define  PSYCHO_CONTROL_MODE	 0x0000000000000001 /* PSYCHO clock mode            */
+#define PSYCHO_PCIA_CTRL	0x2000UL
+#define PSYCHO_PCIB_CTRL	0x4000UL
+#define  PSYCHO_PCICTRL_RESV1	 0xfffffff000000000 /* Reserved                     */
+#define  PSYCHO_PCICTRL_SBH_ERR	 0x0000000800000000 /* Streaming byte hole error    */
+#define  PSYCHO_PCICTRL_SERR	 0x0000000400000000 /* SERR signal asserted         */
+#define  PSYCHO_PCICTRL_SPEED	 0x0000000200000000 /* PCI speed (1 is U2P clock)   */
+#define  PSYCHO_PCICTRL_RESV2	 0x00000001ffc00000 /* Reserved                     */
+#define  PSYCHO_PCICTRL_ARB_PARK 0x0000000000200000 /* PCI arbitration parking      */
+#define  PSYCHO_PCICTRL_RESV3	 0x00000000001ff800 /* Reserved                     */
+#define  PSYCHO_PCICTRL_SBH_INT	 0x0000000000000400 /* Streaming byte hole int enab */
+#define  PSYCHO_PCICTRL_WEN	 0x0000000000000200 /* Power Mgmt Wake Enable       */
+#define  PSYCHO_PCICTRL_EEN	 0x0000000000000100 /* PCI Error Interrupt Enable   */
+#define  PSYCHO_PCICTRL_RESV4	 0x00000000000000c0 /* Reserved                     */
+#define  PSYCHO_PCICTRL_AEN	 0x000000000000003f /* PCI DVMA Arbitration Enable  */
+
+/* U2P Programmer's Manual, page 13-55, configuration space
+ * address format:
+ * 
+ *  32             24 23 16 15    11 10       8 7   2  1 0
+ * ---------------------------------------------------------
+ * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 |
+ * ---------------------------------------------------------
+ */
+#define PSYCHO_CONFIG_BASE(PBM)	\
+	((PBM)->parent->config_space | (1UL << 24))
+#define PSYCHO_CONFIG_ENCODE(BUS, DEVFN, REG)	\
+	(((unsigned long)(BUS)   << 16) |	\
+	 ((unsigned long)(DEVFN) << 8)  |	\
+	 ((unsigned long)(REG)))
+
+static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm,
+				      unsigned char bus,
+				      unsigned int devfn,
+				      int where)
+{
+	if (!pbm)
+		return NULL;
+	return (void *)
+		(PSYCHO_CONFIG_BASE(pbm) |
+		 PSYCHO_CONFIG_ENCODE(bus, devfn, where));
+}
+
+static int psycho_out_of_range(struct pci_pbm_info *pbm,
+			       unsigned char bus,
+			       unsigned char devfn)
+{
+	return ((pbm->parent == 0) ||
+		((pbm == &pbm->parent->pbm_B) &&
+		 (bus == pbm->pci_first_busno) &&
+		 PCI_SLOT(devfn) > 8) ||
+		((pbm == &pbm->parent->pbm_A) &&
+		 (bus == pbm->pci_first_busno) &&
+		 PCI_SLOT(devfn) > 8));
+}
+
+/* PSYCHO PCI configuration space accessors. */
+
+static int psycho_read_byte(struct pci_dev *dev, int where, u8 *value)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+	unsigned char bus = dev->bus->number;
+	unsigned int devfn = dev->devfn;
+	u8 *addr;
+
+	*value = 0xff;
+	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	if (psycho_out_of_range(pbm, bus, devfn))
+		return PCIBIOS_SUCCESSFUL;
+	pci_config_read8(addr, value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int psycho_read_word(struct pci_dev *dev, int where, u16 *value)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+	unsigned char bus = dev->bus->number;
+	unsigned int devfn = dev->devfn;
+	u16 *addr;
+
+	*value = 0xffff;
+	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	if (psycho_out_of_range(pbm, bus, devfn))
+		return PCIBIOS_SUCCESSFUL;
+
+	if (where & 0x01) {
+		printk("pcibios_read_config_word: misaligned reg [%x]\n",
+		       where);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	pci_config_read16(addr, value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int psycho_read_dword(struct pci_dev *dev, int where, u32 *value)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+	unsigned char bus = dev->bus->number;
+	unsigned int devfn = dev->devfn;
+	u32 *addr;
+
+	*value = 0xffffffff;
+	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	if (psycho_out_of_range(pbm, bus, devfn))
+		return PCIBIOS_SUCCESSFUL;
+
+	if (where & 0x03) {
+		printk("pcibios_read_config_dword: misaligned reg [%x]\n",
+		       where);
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	pci_config_read32(addr, value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int psycho_write_byte(struct pci_dev *dev, int where, u8 value)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+	unsigned char bus = dev->bus->number;
+	unsigned int devfn = dev->devfn;
+	u8 *addr;
+
+	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	if (psycho_out_of_range(pbm, bus, devfn))
+		return PCIBIOS_SUCCESSFUL;
+
+	pci_config_write8(addr, value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int psycho_write_word(struct pci_dev *dev, int where, u16 value)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+	unsigned char bus = dev->bus->number;
+	unsigned int devfn = dev->devfn;
+	u16 *addr;
+
+	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	if (psycho_out_of_range(pbm, bus, devfn))
+		return PCIBIOS_SUCCESSFUL;
+
+	if (where & 0x01) {
+		printk("pcibios_write_config_word: misaligned reg [%x]\n",
+		       where);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	pci_config_write16(addr, value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int psycho_write_dword(struct pci_dev *dev, int where, u32 value)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+	unsigned char bus = dev->bus->number;
+	unsigned int devfn = dev->devfn;
+	u32 *addr;
+
+	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	if (psycho_out_of_range(pbm, bus, devfn))
+		return PCIBIOS_SUCCESSFUL;
+
+	if (where & 0x03) {
+		printk("pcibios_write_config_dword: misaligned reg [%x]\n",
+		       where);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	pci_config_write32(addr, value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops psycho_ops = {
+	psycho_read_byte,
+	psycho_read_word,
+	psycho_read_dword,
+	psycho_write_byte,
+	psycho_write_word,
+	psycho_write_dword
+};
+
+/* PSYCHO interrupt mapping support. */
+#define PSYCHO_IMAP_A_SLOT0	0x0c00UL
+#define PSYCHO_IMAP_B_SLOT0	0x0c20UL
+static unsigned long psycho_pcislot_imap_offset(unsigned long ino)
+{
+	unsigned int bus =  (ino & 0x10) >> 4;
+	unsigned int slot = (ino & 0x0c) >> 2;
+
+	if (bus == 0)
+		return PSYCHO_IMAP_A_SLOT0 + (slot * 8);
+	else
+		return PSYCHO_IMAP_B_SLOT0 + (slot * 8);
+}
+
+#define PSYCHO_IMAP_SCSI	0x1000UL
+#define PSYCHO_IMAP_ETH		0x1008UL
+#define PSYCHO_IMAP_BPP		0x1010UL
+#define PSYCHO_IMAP_AU_REC	0x1018UL
+#define PSYCHO_IMAP_AU_PLAY	0x1020UL
+#define PSYCHO_IMAP_PFAIL	0x1028UL
+#define PSYCHO_IMAP_KMS		0x1030UL
+#define PSYCHO_IMAP_FLPY	0x1038UL
+#define PSYCHO_IMAP_SHW		0x1040UL
+#define PSYCHO_IMAP_KBD		0x1048UL
+#define PSYCHO_IMAP_MS		0x1050UL
+#define PSYCHO_IMAP_SER		0x1058UL
+#define PSYCHO_IMAP_TIM0	0x1060UL
+#define PSYCHO_IMAP_TIM1	0x1068UL
+#define PSYCHO_IMAP_UE		0x1070UL
+#define PSYCHO_IMAP_CE		0x1078UL
+#define PSYCHO_IMAP_A_ERR	0x1080UL
+#define PSYCHO_IMAP_B_ERR	0x1088UL
+#define PSYCHO_IMAP_PMGMT	0x1090UL
+#define PSYCHO_IMAP_GFX		0x1098UL
+#define PSYCHO_IMAP_EUPA	0x10a0UL
+
+static unsigned long __onboard_imap_off[] = {
+/*0x20*/	PSYCHO_IMAP_SCSI,
+/*0x21*/	PSYCHO_IMAP_ETH,
+/*0x22*/	PSYCHO_IMAP_BPP,
+/*0x23*/	PSYCHO_IMAP_AU_REC,
+/*0x24*/	PSYCHO_IMAP_AU_PLAY,
+/*0x25*/	PSYCHO_IMAP_PFAIL,
+/*0x26*/	PSYCHO_IMAP_KMS,
+/*0x27*/	PSYCHO_IMAP_FLPY,
+/*0x28*/	PSYCHO_IMAP_SHW,
+/*0x29*/	PSYCHO_IMAP_KBD,
+/*0x2a*/	PSYCHO_IMAP_MS,
+/*0x2b*/	PSYCHO_IMAP_SER,
+/*0x2c*/	PSYCHO_IMAP_TIM0,
+/*0x2d*/	PSYCHO_IMAP_TIM1,
+/*0x2e*/	PSYCHO_IMAP_UE,
+/*0x2f*/	PSYCHO_IMAP_CE,
+/*0x30*/	PSYCHO_IMAP_A_ERR,
+/*0x31*/	PSYCHO_IMAP_B_ERR,
+/*0x32*/	PSYCHO_IMAP_PMGMT
+};
+#define PSYCHO_ONBOARD_IRQ_BASE		0x20
+#define PSYCHO_ONBOARD_IRQ_LAST		0x32
+#define psycho_onboard_imap_offset(__ino) \
+	__onboard_imap_off[(__ino) - PSYCHO_ONBOARD_IRQ_BASE]
+
+#define PSYCHO_ICLR_A_SLOT0	0x1400UL
+#define PSYCHO_ICLR_SCSI	0x1800UL
+
+#define psycho_iclr_offset(ino)					      \
+	((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
+			(PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
+
+/* PCI PSYCHO INO number to Sparc PIL level. */
+static unsigned char psycho_pil_table[] = {
+/*0x00*/0, 0, 0, 0,	/* PCI A slot 0  Int A, B, C, D */
+/*0x04*/0, 0, 0, 0,	/* PCI A slot 1  Int A, B, C, D */
+/*0x08*/0, 0, 0, 0,	/* PCI A slot 2  Int A, B, C, D */
+/*0x0c*/0, 0, 0, 0,	/* PCI A slot 3  Int A, B, C, D */
+/*0x10*/0, 0, 0, 0,	/* PCI B slot 0  Int A, B, C, D */
+/*0x14*/0, 0, 0, 0,	/* PCI B slot 1  Int A, B, C, D */
+/*0x18*/0, 0, 0, 0,	/* PCI B slot 2  Int A, B, C, D */
+/*0x1c*/0, 0, 0, 0,	/* PCI B slot 3  Int A, B, C, D */
+/*0x20*/3,		/* SCSI				*/
+/*0x21*/5,		/* Ethernet			*/
+/*0x22*/8,		/* Parallel Port		*/
+/*0x23*/13,		/* Audio Record			*/
+/*0x24*/14,		/* Audio Playback		*/
+/*0x25*/15,		/* PowerFail			*/
+/*0x26*/3,		/* second SCSI			*/
+/*0x27*/11,		/* Floppy			*/
+/*0x28*/2,		/* Spare Hardware		*/
+/*0x29*/9,		/* Keyboard			*/
+/*0x2a*/4,		/* Mouse			*/
+/*0x2b*/12,		/* Serial			*/
+/*0x2c*/10,		/* Timer 0			*/
+/*0x2d*/11,		/* Timer 1			*/
+/*0x2e*/15,		/* Uncorrectable ECC		*/
+/*0x2f*/15,		/* Correctable ECC		*/
+/*0x30*/15,		/* PCI Bus A Error		*/
+/*0x31*/15,		/* PCI Bus B Error		*/
+/*0x32*/1,		/* Power Management		*/
+};
+
+static int __init psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
+{
+	int ret;
+
+	ret = psycho_pil_table[ino];
+	if (ret == 0 && pdev == NULL) {
+		ret = 1;
+	} else if (ret == 0) {
+		switch ((pdev->class >> 16) & 0x0f) {
+		case PCI_BASE_CLASS_STORAGE:
+			ret = 4;
+
+		case PCI_BASE_CLASS_NETWORK:
+			ret = 6;
+
+		case PCI_BASE_CLASS_DISPLAY:
+			ret = 9;
+
+		case PCI_BASE_CLASS_MULTIMEDIA:
+		case PCI_BASE_CLASS_MEMORY:
+		case PCI_BASE_CLASS_BRIDGE:
+			ret = 10;
+
+		default:
+			ret = 1;
+		};
+	}
+
+	return ret;
+}
+
+static unsigned int __init psycho_irq_build(struct pci_controller_info *p,
+					    struct pci_dev *pdev,
+					    unsigned int ino)
+{
+	struct ino_bucket *bucket;
+	volatile unsigned int *imap, *iclr;
+	unsigned long imap_off, iclr_off;
+	int pil, inofixup = 0;
+
+	ino &= PCI_IRQ_INO;
+	if (ino < PSYCHO_ONBOARD_IRQ_BASE) {
+		/* PCI slot */
+		imap_off = psycho_pcislot_imap_offset(ino);
+	} else {
+		/* Onboard device */
+		if (ino > PSYCHO_ONBOARD_IRQ_LAST) {
+			prom_printf("psycho_irq_build: Wacky INO [%x]\n", ino);
+			prom_halt();
+		}
+		imap_off = psycho_onboard_imap_offset(ino);
+	}
+
+	/* Now build the IRQ bucket. */
+	pil = psycho_ino_to_pil(pdev, ino);
+	imap = (volatile unsigned int *)__va(p->controller_regs + imap_off);
+	imap += 1;
+
+	iclr_off = psycho_iclr_offset(ino);
+	iclr = (volatile unsigned int *)__va(p->controller_regs + iclr_off);
+	iclr += 1;
+
+	if ((ino & 0x20) == 0)
+		inofixup = ino & 0x03;
+
+	bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
+	bucket->flags |= IBF_PCI;
+
+	return __irq(bucket);
+}
+
+/* PSYCHO error handling support. */
+enum psycho_error_type {
+	UE_ERR, CE_ERR, PCI_ERR
+};
+
+/* Helper function of IOMMU error checking, which checks out
+ * the state of the streaming buffers.  The IOMMU lock is
+ * held when this is called.
+ *
+ * For the PCI error case we know which PBM (and thus which
+ * streaming buffer) caused the error, but for the uncorrectable
+ * error case we do not.  So we always check both streaming caches.
+ */
+#define PSYCHO_STRBUF_CONTROL_A 0x2800UL
+#define PSYCHO_STRBUF_CONTROL_B 0x4800UL
+#define  PSYCHO_STRBUF_CTRL_LPTR    0x00000000000000f0 /* LRU Lock Pointer */
+#define  PSYCHO_STRBUF_CTRL_LENAB   0x0000000000000008 /* LRU Lock Enable */
+#define  PSYCHO_STRBUF_CTRL_RRDIS   0x0000000000000004 /* Rerun Disable */
+#define  PSYCHO_STRBUF_CTRL_DENAB   0x0000000000000002 /* Diagnostic Mode Enable */
+#define  PSYCHO_STRBUF_CTRL_ENAB    0x0000000000000001 /* Streaming Buffer Enable */
+#define PSYCHO_STRBUF_FLUSH_A   0x2808UL
+#define PSYCHO_STRBUF_FLUSH_B   0x4808UL
+#define PSYCHO_STRBUF_FSYNC_A   0x2810UL
+#define PSYCHO_STRBUF_FSYNC_B   0x4810UL
+#define PSYCHO_STC_DATA_A	0xb000UL
+#define PSYCHO_STC_DATA_B	0xc000UL
+#define PSYCHO_STC_ERR_A	0xb400UL
+#define PSYCHO_STC_ERR_B	0xc400UL
+#define  PSYCHO_STCERR_WRITE	 0x0000000000000002	/* Write Error */
+#define  PSYCHO_STCERR_READ	 0x0000000000000001	/* Read Error */
+#define PSYCHO_STC_TAG_A	0xb800UL
+#define PSYCHO_STC_TAG_B	0xc800UL
+#define  PSYCHO_STCTAG_PPN	 0x0fffffff00000000	/* Physical Page Number */
+#define  PSYCHO_STCTAG_VPN	 0x00000000ffffe000	/* Virtual Page Number */
+#define  PSYCHO_STCTAG_VALID	 0x0000000000000002	/* Valid */
+#define  PSYCHO_STCTAG_WRITE	 0x0000000000000001	/* Writable */
+#define PSYCHO_STC_LINE_A	0xb900UL
+#define PSYCHO_STC_LINE_B	0xc900UL
+#define  PSYCHO_STCLINE_LINDX	 0x0000000001e00000	/* LRU Index */
+#define  PSYCHO_STCLINE_SPTR	 0x00000000001f8000	/* Dirty Data Start Pointer */
+#define  PSYCHO_STCLINE_LADDR	 0x0000000000007f00	/* Line Address */
+#define  PSYCHO_STCLINE_EPTR	 0x00000000000000fc	/* Dirty Data End Pointer */
+#define  PSYCHO_STCLINE_VALID	 0x0000000000000002	/* Valid */
+#define  PSYCHO_STCLINE_FOFN	 0x0000000000000001	/* Fetch Outstanding / Flush Necessary */
+
+static spinlock_t stc_buf_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long stc_error_buf[128];
+static unsigned long stc_tag_buf[16];
+static unsigned long stc_line_buf[16];
+
+static void __psycho_check_one_stc(struct pci_controller_info *p,
+				   struct pci_pbm_info *pbm,
+				   int is_pbm_a)
+{
+	struct pci_strbuf *strbuf = &pbm->stc;
+	unsigned long regbase = p->controller_regs;
+	unsigned long err_base, tag_base, line_base;
+	u64 control;
+	int i;
+
+	if (is_pbm_a) {
+		err_base = regbase + PSYCHO_STC_ERR_A;
+		tag_base = regbase + PSYCHO_STC_TAG_A;
+		line_base = regbase + PSYCHO_STC_LINE_A;
+	} else {
+		err_base = regbase + PSYCHO_STC_ERR_A;
+		tag_base = regbase + PSYCHO_STC_TAG_A;
+		line_base = regbase + PSYCHO_STC_LINE_A;
+	}
+
+	spin_lock(&stc_buf_lock);
+
+	/* This is __REALLY__ dangerous.  When we put the
+	 * streaming buffer into diagnostic mode to probe
+	 * it's tags and error status, we _must_ clear all
+	 * of the line tag valid bits before re-enabling
+	 * the streaming buffer.  If any dirty data lives
+	 * in the STC when we do this, we will end up
+	 * invalidating it before it has a chance to reach
+	 * main memory.
+	 */
+	control = psycho_read(strbuf->strbuf_control);
+	psycho_write(strbuf->strbuf_control,
+		     (control | PSYCHO_STRBUF_CTRL_DENAB));
+	for (i = 0; i < 128; i++) {
+		unsigned long val;
+
+		val = psycho_read(err_base + (i * 8UL));
+		psycho_write(err_base + (i * 8UL), 0UL);
+		stc_error_buf[i] = val;
+	}
+	for (i = 0; i < 16; i++) {
+		stc_tag_buf[i] = psycho_read(tag_base + (i * 8UL));
+		stc_line_buf[i] = psycho_read(line_base + (i * 8UL));
+		psycho_write(tag_base + (i * 8UL), 0UL);
+		psycho_write(line_base + (i * 8UL), 0UL);
+	}
+
+	/* OK, state is logged, exit diagnostic mode. */
+	psycho_write(strbuf->strbuf_control, control);
+
+	for (i = 0; i < 16; i++) {
+		int j, saw_error, first, last;
+
+		saw_error = 0;
+		first = i * 8;
+		last = first + 8;
+		for (j = first; j < last; j++) {
+			unsigned long errval = stc_error_buf[j];
+			if (errval != 0) {
+				saw_error++;
+				printk("PSYCHO%d(PBM%c): STC_ERR(%d)[wr(%d)rd(%d)]\n",
+				       p->index,
+				       (is_pbm_a ? 'A' : 'B'),
+				       j,
+				       (errval & PSYCHO_STCERR_WRITE) ? 1 : 0,
+				       (errval & PSYCHO_STCERR_READ) ? 1 : 0);
+			}
+		}
+		if (saw_error != 0) {
+			unsigned long tagval = stc_tag_buf[i];
+			unsigned long lineval = stc_line_buf[i];
+			printk("PSYCHO%d(PBM%c): STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n",
+			       p->index,
+			       (is_pbm_a ? 'A' : 'B'),
+			       i,
+			       ((tagval & PSYCHO_STCTAG_PPN) >> 19UL),
+			       (tagval & PSYCHO_STCTAG_VPN),
+			       ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0),
+			       ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0));
+			printk("PSYCHO%d(PBM%c): STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)"
+			       "V(%d)FOFN(%d)]\n",
+			       p->index,
+			       (is_pbm_a ? 'A' : 'B'),
+			       i,
+			       ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL),
+			       ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL),
+			       ((lineval & PSYCHO_STCLINE_LADDR) >> 8UL),
+			       ((lineval & PSYCHO_STCLINE_EPTR) >> 2UL),
+			       ((lineval & PSYCHO_STCLINE_VALID) ? 1 : 0),
+			       ((lineval & PSYCHO_STCLINE_FOFN) ? 1 : 0));
+		}
+	}
+
+	spin_unlock(&stc_buf_lock);
+}
+
+static void __psycho_check_stc_error(struct pci_controller_info *p,
+				     unsigned long afsr,
+				     unsigned long afar,
+				     enum psycho_error_type type)
+{
+	struct pci_pbm_info *pbm;
+
+	pbm = &p->pbm_A;
+	if (pbm->stc.strbuf_enabled)
+		__psycho_check_one_stc(p, pbm, 1);
+
+	pbm = &p->pbm_B;
+	if (pbm->stc.strbuf_enabled)
+		__psycho_check_one_stc(p, pbm, 0);
+}
+
+/* When an Uncorrectable Error or a PCI Error happens, we
+ * interrogate the IOMMU state to see if it is the cause.
+ */
+#define PSYCHO_IOMMU_CONTROL	0x0200UL
+#define  PSYCHO_IOMMU_CTRL_RESV     0xfffffffff9000000 /* Reserved                      */
+#define  PSYCHO_IOMMU_CTRL_XLTESTAT 0x0000000006000000 /* Translation Error Status      */
+#define  PSYCHO_IOMMU_CTRL_XLTEERR  0x0000000001000000 /* Translation Error encountered */
+#define  PSYCHO_IOMMU_CTRL_LCKEN    0x0000000000800000 /* Enable translation locking    */
+#define  PSYCHO_IOMMU_CTRL_LCKPTR   0x0000000000780000 /* Translation lock pointer      */
+#define  PSYCHO_IOMMU_CTRL_TSBSZ    0x0000000000070000 /* TSB Size                      */
+#define  PSYCHO_IOMMU_TSBSZ_1K      0x0000000000000000 /* TSB Table 1024 8-byte entries */
+#define  PSYCHO_IOMMU_TSBSZ_2K      0x0000000000010000 /* TSB Table 2048 8-byte entries */
+#define  PSYCHO_IOMMU_TSBSZ_4K      0x0000000000020000 /* TSB Table 4096 8-byte entries */
+#define  PSYCHO_IOMMU_TSBSZ_8K      0x0000000000030000 /* TSB Table 8192 8-byte entries */
+#define  PSYCHO_IOMMU_TSBSZ_16K     0x0000000000040000 /* TSB Table 16k 8-byte entries  */
+#define  PSYCHO_IOMMU_TSBSZ_32K     0x0000000000050000 /* TSB Table 32k 8-byte entries  */
+#define  PSYCHO_IOMMU_TSBSZ_64K     0x0000000000060000 /* TSB Table 64k 8-byte entries  */
+#define  PSYCHO_IOMMU_TSBSZ_128K    0x0000000000070000 /* TSB Table 128k 8-byte entries */
+#define  PSYCHO_IOMMU_CTRL_RESV2    0x000000000000fff8 /* Reserved                      */
+#define  PSYCHO_IOMMU_CTRL_TBWSZ    0x0000000000000004 /* Assumed page size, 0=8k 1=64k */
+#define  PSYCHO_IOMMU_CTRL_DENAB    0x0000000000000002 /* Diagnostic mode enable        */
+#define  PSYCHO_IOMMU_CTRL_ENAB     0x0000000000000001 /* IOMMU Enable                  */
+#define PSYCHO_IOMMU_TSBBASE	0x0208UL
+#define PSYCHO_IOMMU_FLUSH	0x0210UL
+#define PSYCHO_IOMMU_TAG	0xa580UL
+#define  PSYCHO_IOMMU_TAG_ERRSTS (0x3UL << 23UL)
+#define  PSYCHO_IOMMU_TAG_ERR	 (0x1UL << 22UL)
+#define  PSYCHO_IOMMU_TAG_WRITE	 (0x1UL << 21UL)
+#define  PSYCHO_IOMMU_TAG_STREAM (0x1UL << 20UL)
+#define  PSYCHO_IOMMU_TAG_SIZE	 (0x1UL << 19UL)
+#define  PSYCHO_IOMMU_TAG_VPAGE	 0x7ffffUL
+#define PSYCHO_IOMMU_DATA	0xa600UL
+#define  PSYCHO_IOMMU_DATA_VALID (1UL << 30UL)
+#define  PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL)
+#define  PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL
+static void psycho_check_iommu_error(struct pci_controller_info *p,
+				     unsigned long afsr,
+				     unsigned long afar,
+				     enum psycho_error_type type)
+{
+	unsigned long iommu_tag[16];
+	unsigned long iommu_data[16];
+	unsigned long flags;
+	u64 control;
+	int i;
+
+	spin_lock_irqsave(&p->iommu.lock, flags);
+	control = psycho_read(p->iommu.iommu_control);
+	if (control & PSYCHO_IOMMU_CTRL_XLTEERR) {
+		char *type_string;
+
+		/* Clear the error encountered bit. */
+		control &= ~PSYCHO_IOMMU_CTRL_XLTEERR;
+		psycho_write(p->iommu.iommu_control, control);
+
+		switch((control & PSYCHO_IOMMU_CTRL_XLTESTAT) >> 25UL) {
+		case 0:
+			type_string = "Protection Error";
+			break;
+		case 1:
+			type_string = "Invalid Error";
+			break;
+		case 2:
+			type_string = "TimeOut Error";
+			break;
+		case 3:
+		default:
+			type_string = "ECC Error";
+			break;
+		};
+		printk("PSYCHO%d: IOMMU Error, type[%s]\n",
+		       p->index, type_string);
+
+		/* Put the IOMMU into diagnostic mode and probe
+		 * it's TLB for entries with error status.
+		 *
+		 * It is very possible for another DVMA to occur
+		 * while we do this probe, and corrupt the system
+		 * further.  But we are so screwed at this point
+		 * that we are likely to crash hard anyways, so
+		 * get as much diagnostic information to the
+		 * console as we can.
+		 */
+		psycho_write(p->iommu.iommu_control,
+			     control | PSYCHO_IOMMU_CTRL_DENAB);
+		for (i = 0; i < 16; i++) {
+			unsigned long base = p->controller_regs;
+
+			iommu_tag[i] =
+				psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL));
+			iommu_data[i] =
+				psycho_read(base + PSYCHO_IOMMU_DATA + (i * 8UL));
+
+			/* Now clear out the entry. */
+			psycho_write(base + PSYCHO_IOMMU_TAG + (i * 8UL), 0);
+			psycho_write(base + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
+		}
+
+		/* Leave diagnostic mode. */
+		psycho_write(p->iommu.iommu_control, control);
+
+		for (i = 0; i < 16; i++) {
+			unsigned long tag, data;
+
+			tag = iommu_tag[i];
+			if (!(tag & PSYCHO_IOMMU_TAG_ERR))
+				continue;
+
+			data = iommu_data[i];
+			switch((tag & PSYCHO_IOMMU_TAG_ERRSTS) >> 23UL) {
+			case 0:
+				type_string = "Protection Error";
+				break;
+			case 1:
+				type_string = "Invalid Error";
+				break;
+			case 2:
+				type_string = "TimeOut Error";
+				break;
+			case 3:
+			default:
+				type_string = "ECC Error";
+				break;
+			};
+			printk("PSYCHO%d: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n",
+			       p->index, i, type_string,
+			       ((tag & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0),
+			       ((tag & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0),
+			       ((tag & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8),
+			       (tag & PSYCHO_IOMMU_TAG_VPAGE) << PAGE_SHIFT);
+			printk("PSYCHO%d: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n",
+			       p->index, i,
+			       ((data & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0),
+			       ((data & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0),
+			       (data & PSYCHO_IOMMU_DATA_PPAGE) << PAGE_SHIFT);
+		}
+	}
+	__psycho_check_stc_error(p, afsr, afar, type);
+	spin_unlock_irqrestore(&p->iommu.lock, flags);
+}
+
+/* Uncorrectable Errors.  Cause of the error and the address are
+ * recorded in the UE_AFSR and UE_AFAR of PSYCHO.  They are errors
+ * relating to UPA interface transactions.
+ */
+#define PSYCHO_UE_AFSR	0x0030UL
+#define  PSYCHO_UEAFSR_PPIO	0x8000000000000000 /* Primary PIO is cause         */
+#define  PSYCHO_UEAFSR_PDRD	0x4000000000000000 /* Primary DVMA read is cause   */
+#define  PSYCHO_UEAFSR_PDWR	0x2000000000000000 /* Primary DVMA write is cause  */
+#define  PSYCHO_UEAFSR_SPIO	0x1000000000000000 /* Secondary PIO is cause       */
+#define  PSYCHO_UEAFSR_SDRD	0x0800000000000000 /* Secondary DVMA read is cause */
+#define  PSYCHO_UEAFSR_SDWR	0x0400000000000000 /* Secondary DVMA write is cause*/
+#define  PSYCHO_UEAFSR_RESV1	0x03ff000000000000 /* Reserved                     */
+#define  PSYCHO_UEAFSR_BMSK	0x0000ffff00000000 /* Bytemask of failed transfer  */
+#define  PSYCHO_UEAFSR_DOFF	0x00000000e0000000 /* Doubleword Offset            */
+#define  PSYCHO_UEAFSR_MID	0x000000001f000000 /* UPA MID causing the fault    */
+#define  PSYCHO_UEAFSR_BLK	0x0000000000800000 /* Trans was block operation    */
+#define  PSYCHO_UEAFSR_RESV2	0x00000000007fffff /* Reserved                     */
+#define PSYCHO_UE_AFAR	0x0038UL
+
+static void psycho_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct pci_controller_info *p = dev_id;
+	unsigned long afsr_reg = p->controller_regs + PSYCHO_UE_AFSR;
+	unsigned long afar_reg = p->controller_regs + PSYCHO_UE_AFAR;
+	unsigned long afsr, afar, error_bits;
+	int reported;
+
+	/* Latch uncorrectable error status. */
+	afar = psycho_read(afar_reg);
+	afsr = psycho_read(afsr_reg);
+
+	/* Clear the primary/secondary error status bits. */
+	error_bits = afsr &
+		(PSYCHO_UEAFSR_PPIO | PSYCHO_UEAFSR_PDRD | PSYCHO_UEAFSR_PDWR |
+		 PSYCHO_UEAFSR_SPIO | PSYCHO_UEAFSR_SDRD | PSYCHO_UEAFSR_SDWR);
+	psycho_write(afsr_reg, error_bits);
+
+	/* Log the error. */
+	printk("PSYCHO%d: Uncorrectable Error, primary error type[%s]\n",
+	       p->index,
+	       (((error_bits & PSYCHO_UEAFSR_PPIO) ?
+		 "PIO" :
+		 ((error_bits & PSYCHO_UEAFSR_PDRD) ?
+		  "DMA Read" :
+		  ((error_bits & PSYCHO_UEAFSR_PDWR) ?
+		   "DMA Write" : "???")))));
+	printk("PSYCHO%d: bytemask[%04lx] dword_offset[%lx] UPA_MID[%02lx] was_block(%d)\n",
+	       p->index,
+	       (afsr & PSYCHO_UEAFSR_BMSK) >> 32UL,
+	       (afsr & PSYCHO_UEAFSR_DOFF) >> 29UL,
+	       (afsr & PSYCHO_UEAFSR_MID) >> 24UL,
+	       ((afsr & PSYCHO_UEAFSR_BLK) ? 1 : 0));
+	printk("PSYCHO%d: UE AFAR [%016lx]\n", p->index, afar);
+	printk("PSYCHO%d: UE Secondary errors [", p->index);
+	reported = 0;
+	if (afsr & PSYCHO_UEAFSR_SPIO) {
+		reported++;
+		printk("(PIO)");
+	}
+	if (afsr & PSYCHO_UEAFSR_SDRD) {
+		reported++;
+		printk("(DMA Read)");
+	}
+	if (afsr & PSYCHO_UEAFSR_SDWR) {
+		reported++;
+		printk("(DMA Write)");
+	}
+	if (!reported)
+		printk("(none)");
+	printk("]\n");
+
+	/* Interrogate IOMMU for error status. */
+	psycho_check_iommu_error(p, afsr, afar, UE_ERR);
+}
+
+/* Correctable Errors. */
+#define PSYCHO_CE_AFSR	0x0040UL
+#define  PSYCHO_CEAFSR_PPIO	0x8000000000000000 /* Primary PIO is cause         */
+#define  PSYCHO_CEAFSR_PDRD	0x4000000000000000 /* Primary DVMA read is cause   */
+#define  PSYCHO_CEAFSR_PDWR	0x2000000000000000 /* Primary DVMA write is cause  */
+#define  PSYCHO_CEAFSR_SPIO	0x1000000000000000 /* Secondary PIO is cause       */
+#define  PSYCHO_CEAFSR_SDRD	0x0800000000000000 /* Secondary DVMA read is cause */
+#define  PSYCHO_CEAFSR_SDWR	0x0400000000000000 /* Secondary DVMA write is cause*/
+#define  PSYCHO_CEAFSR_RESV1	0x0300000000000000 /* Reserved                     */
+#define  PSYCHO_CEAFSR_ESYND	0x00ff000000000000 /* Syndrome Bits                */
+#define  PSYCHO_CEAFSR_BMSK	0x0000ffff00000000 /* Bytemask of failed transfer  */
+#define  PSYCHO_CEAFSR_DOFF	0x00000000e0000000 /* Double Offset                */
+#define  PSYCHO_CEAFSR_MID	0x000000001f000000 /* UPA MID causing the fault    */
+#define  PSYCHO_CEAFSR_BLK	0x0000000000800000 /* Trans was block operation    */
+#define  PSYCHO_CEAFSR_RESV2	0x00000000007fffff /* Reserved                     */
+#define PSYCHO_CE_AFAR	0x0040UL
+
+static void psycho_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct pci_controller_info *p = dev_id;
+	unsigned long afsr_reg = p->controller_regs + PSYCHO_CE_AFSR;
+	unsigned long afar_reg = p->controller_regs + PSYCHO_CE_AFAR;
+	unsigned long afsr, afar, error_bits;
+	int reported;
+
+	/* Latch error status. */
+	afar = psycho_read(afar_reg);
+	afsr = psycho_read(afsr_reg);
+
+	/* Clear primary/secondary error status bits. */
+	error_bits = afsr &
+		(PSYCHO_CEAFSR_PPIO | PSYCHO_CEAFSR_PDRD | PSYCHO_CEAFSR_PDWR |
+		 PSYCHO_CEAFSR_SPIO | PSYCHO_CEAFSR_SDRD | PSYCHO_CEAFSR_SDWR);
+	psycho_write(afsr_reg, error_bits);
+
+	/* Log the error. */
+	printk("PSYCHO%d: Correctable Error, primary error type[%s]\n",
+	       p->index,
+	       (((error_bits & PSYCHO_CEAFSR_PPIO) ?
+		 "PIO" :
+		 ((error_bits & PSYCHO_CEAFSR_PDRD) ?
+		  "DMA Read" :
+		  ((error_bits & PSYCHO_CEAFSR_PDWR) ?
+		   "DMA Write" : "???")))));
+	printk("PSYCHO%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] "
+	       "UPA_MID[%02lx] was_block(%d)\n",
+	       p->index,
+	       (afsr & PSYCHO_CEAFSR_ESYND) >> 48UL,
+	       (afsr & PSYCHO_CEAFSR_BMSK) >> 32UL,
+	       (afsr & PSYCHO_CEAFSR_DOFF) >> 29UL,
+	       (afsr & PSYCHO_CEAFSR_MID) >> 24UL,
+	       ((afsr & PSYCHO_CEAFSR_BLK) ? 1 : 0));
+	printk("PSYCHO%d: CE AFAR [%016lx]\n", p->index, afar);
+	printk("PSYCHO%d: CE Secondary errors [", p->index);
+	reported = 0;
+	if (afsr & PSYCHO_CEAFSR_SPIO) {
+		reported++;
+		printk("(PIO)");
+	}
+	if (afsr & PSYCHO_CEAFSR_SDRD) {
+		reported++;
+		printk("(DMA Read)");
+	}
+	if (afsr & PSYCHO_CEAFSR_SDWR) {
+		reported++;
+		printk("(DMA Write)");
+	}
+	if (!reported)
+		printk("(none)");
+	printk("]\n");
+}
+
+/* PCI Errors.  They are signalled by the PCI bus module since they
+ * are assosciated with a specific bus segment.
+ */
+#define PSYCHO_PCI_AFSR_A	0x2010UL
+#define PSYCHO_PCI_AFSR_B	0x4010UL
+#define  PSYCHO_PCIAFSR_PMA	0x8000000000000000 /* Primary Master Abort Error   */
+#define  PSYCHO_PCIAFSR_PTA	0x4000000000000000 /* Primary Target Abort Error   */
+#define  PSYCHO_PCIAFSR_PRTRY	0x2000000000000000 /* Primary Excessive Retries    */
+#define  PSYCHO_PCIAFSR_PPERR	0x1000000000000000 /* Primary Parity Error         */
+#define  PSYCHO_PCIAFSR_SMA	0x0800000000000000 /* Secondary Master Abort Error */
+#define  PSYCHO_PCIAFSR_STA	0x0400000000000000 /* Secondary Target Abort Error */
+#define  PSYCHO_PCIAFSR_SRTRY	0x0200000000000000 /* Secondary Excessive Retries  */
+#define  PSYCHO_PCIAFSR_SPERR	0x0100000000000000 /* Secondary Parity Error       */
+#define  PSYCHO_PCIAFSR_RESV1	0x00ff000000000000 /* Reserved                     */
+#define  PSYCHO_PCIAFSR_BMSK	0x0000ffff00000000 /* Bytemask of failed transfer  */
+#define  PSYCHO_PCIAFSR_BLK	0x0000000080000000 /* Trans was block operation    */
+#define  PSYCHO_PCIAFSR_RESV2	0x0000000040000000 /* Reserved                     */
+#define  PSYCHO_PCIAFSR_MID	0x000000003e000000 /* MID causing the error        */
+#define  PSYCHO_PCIAFSR_RESV3	0x0000000001ffffff /* Reserved                     */
+#define PSYCHO_PCI_AFAR_A	0x2018UL
+#define PSYCHO_PCI_AFAR_B	0x4018UL
+
+static void psycho_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct pci_pbm_info *pbm = dev_id;
+	struct pci_controller_info *p = pbm->parent;
+	unsigned long afsr_reg, afar_reg;
+	unsigned long afsr, afar, error_bits;
+	int is_pbm_a, reported;
+
+	is_pbm_a = (pbm == &pbm->parent->pbm_A);
+	if (is_pbm_a) {
+		afsr_reg = p->controller_regs + PSYCHO_PCI_AFSR_A;
+		afar_reg = p->controller_regs + PSYCHO_PCI_AFAR_A;
+	} else {
+		afsr_reg = p->controller_regs + PSYCHO_PCI_AFSR_B;
+		afar_reg = p->controller_regs + PSYCHO_PCI_AFAR_B;
+	}
+
+	/* Latch error status. */
+	afar = psycho_read(afar_reg);
+	afsr = psycho_read(afsr_reg);
+
+	/* Clear primary/secondary error status bits. */
+	error_bits = afsr &
+		(PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_PTA |
+		 PSYCHO_PCIAFSR_PRTRY | PSYCHO_PCIAFSR_PPERR |
+		 PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA |
+		 PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR);
+	psycho_write(afsr_reg, error_bits);
+
+	/* Log the error. */
+	printk("PSYCHO%d(PBM%c): PCI Error, primary error type[%s]\n",
+	       p->index, (is_pbm_a ? 'A' : 'B'),
+	       (((error_bits & PSYCHO_PCIAFSR_PMA) ?
+		 "Master Abort" :
+		 ((error_bits & PSYCHO_PCIAFSR_PTA) ?
+		  "Target Abort" :
+		  ((error_bits & PSYCHO_PCIAFSR_PRTRY) ?
+		   "Excessive Retries" :
+		   ((error_bits & PSYCHO_PCIAFSR_PPERR) ?
+		    "Parity Error" : "???"))))));
+	printk("PSYCHO%d(PBM%c): bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n",
+	       p->index, (is_pbm_a ? 'A' : 'B'),
+	       (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL,
+	       (afsr & PSYCHO_PCIAFSR_MID) >> 25UL,
+	       (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0);
+	printk("PSYCHO%d(PBM%c): PCI AFAR [%016lx]\n",
+	       p->index, (is_pbm_a ? 'A' : 'B'), afar);
+	printk("PSYCHO%d(PBM%c): PCI Secondary errors [",
+	       p->index, (is_pbm_a ? 'A' : 'B'));
+	reported = 0;
+	if (afsr & PSYCHO_PCIAFSR_SMA) {
+		reported++;
+		printk("(Master Abort)");
+	}
+	if (afsr & PSYCHO_PCIAFSR_STA) {
+		reported++;
+		printk("(Target Abort)");
+	}
+	if (afsr & PSYCHO_PCIAFSR_SRTRY) {
+		reported++;
+		printk("(Excessive Retries)");
+	}
+	if (afsr & PSYCHO_PCIAFSR_SPERR) {
+		reported++;
+		printk("(Parity Error)");
+	}
+	if (!reported)
+		printk("(none)");
+	printk("]\n");
+
+	/* For the error types shown, scan PBM's PCI bus for devices
+	 * which have logged that error type.
+	 */
+
+	/* If we see a Target Abort, this could be the result of an
+	 * IOMMU translation error of some sort.  It is extremely
+	 * useful to log this information as usually it indicates
+	 * a bug in the IOMMU support code or a PCI device driver.
+	 */
+	if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) {
+		psycho_check_iommu_error(p, afsr, afar, PCI_ERR);
+		pci_scan_for_target_abort(p, pbm, pbm->pci_bus);
+	}
+	if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA))
+		pci_scan_for_master_abort(p, pbm, pbm->pci_bus);
+
+	/* For excessive retries, PSYCHO/PBM will abort the device
+	 * and there is no way to specifically check for excessive
+	 * retries in the config space status registers.  So what
+	 * we hope is that we'll catch it via the master/target
+	 * abort events.
+	 */
+
+	if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR))
+		pci_scan_for_parity_error(p, pbm, pbm->pci_bus);
+}
+
+/* XXX What about PowerFail/PowerManagement??? -DaveM */
+#define PSYCHO_ECC_CTRL		0x0020
+#define  PSYCHO_ECCCTRL_EE	 0x8000000000000000 /* Enable ECC Checking */
+#define  PSYCHO_ECCCTRL_UE	 0x4000000000000000 /* Enable UE Interrupts */
+#define  PSYCHO_ECCCTRL_CE	 0x2000000000000000 /* Enable CE INterrupts */
+#define PSYCHO_UE_INO		0x2e
+#define PSYCHO_CE_INO		0x2f
+#define PSYCHO_PCIERR_A_INO	0x30
+#define PSYCHO_PCIERR_B_INO	0x31
+static void __init psycho_register_error_handlers(struct pci_controller_info *p)
+{
+	unsigned long base = p->controller_regs;
+	unsigned int irq, portid = p->portid;
+	u64 tmp;
+
+	/* Build IRQs and register handlers. */
+	irq = psycho_irq_build(p, NULL, (portid << 6) | PSYCHO_UE_INO);
+	if (request_irq(irq, psycho_ue_intr,
+			SA_SHIRQ, "PSYCHO UE", p) < 0) {
+		prom_printf("PSYCHO%d: Cannot register UE interrupt.\n",
+			    p->index);
+		prom_halt();
+	}
+
+	irq = psycho_irq_build(p, NULL, (portid << 6) | PSYCHO_CE_INO);
+	if (request_irq(irq, psycho_ce_intr,
+			SA_SHIRQ, "PSYCHO CE", p) < 0) {
+		prom_printf("PSYCHO%d: Cannot register CE interrupt.\n",
+			    p->index);
+		prom_halt();
+	}
+
+	irq = psycho_irq_build(p, NULL, (portid << 6) | PSYCHO_PCIERR_A_INO);
+	if (request_irq(irq, psycho_pcierr_intr,
+			SA_SHIRQ, "PSYCHO PCIERR", &p->pbm_A) < 0) {
+		prom_printf("PSYCHO%d(PBMA): Cannot register PciERR interrupt.\n",
+			    p->index);
+		prom_halt();
+	}
+
+	irq = psycho_irq_build(p, NULL, (portid << 6) | PSYCHO_PCIERR_B_INO);
+	if (request_irq(irq, psycho_pcierr_intr,
+			SA_SHIRQ, "PSYCHO PCIERR", &p->pbm_B) < 0) {
+		prom_printf("PSYCHO%d(PBMB): Cannot register PciERR interrupt.\n",
+			    p->index);
+		prom_halt();
+	}
+
+	/* Enable UE and CE interrupts for controller. */
+	psycho_write(base + PSYCHO_ECC_CTRL,
+		     (PSYCHO_ECCCTRL_EE |
+		      PSYCHO_ECCCTRL_UE |
+		      PSYCHO_ECCCTRL_CE));
+
+	/* Enable PCI Error interrupts and clear error
+	 * bits for each PBM.
+	 */
+	tmp = psycho_read(base + PSYCHO_PCIA_CTRL);
+	tmp |= (PSYCHO_PCICTRL_SBH_ERR |
+		PSYCHO_PCICTRL_SERR |
+		PSYCHO_PCICTRL_SBH_INT |
+		PSYCHO_PCICTRL_EEN);
+	psycho_write(base + PSYCHO_PCIA_CTRL, tmp);
+		     
+	tmp = psycho_read(base + PSYCHO_PCIB_CTRL);
+	tmp |= (PSYCHO_PCICTRL_SBH_ERR |
+		PSYCHO_PCICTRL_SERR |
+		PSYCHO_PCICTRL_SBH_INT |
+		PSYCHO_PCICTRL_EEN);
+	psycho_write(base + PSYCHO_PCIB_CTRL, tmp);
+}
+
+/* PSYCHO boot time probing and initialization. */
+static void __init psycho_resource_adjust(struct pci_dev *pdev,
+					  struct resource *res,
+					  struct resource *root)
+{
+	res->start += root->start;
+	res->end += root->start;
+}
+
+static void __init psycho_base_address_update(struct pci_dev *pdev, int resource)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_pbm_info *pbm = pcp->pbm;
+	struct resource *res = &pdev->resource[resource];
+	struct resource *root;
+	u32 reg;
+	int where, size;
+
+	if (res->flags & IORESOURCE_IO)
+		root = &pbm->io_space;
+	else
+		root = &pbm->mem_space;
+
+	where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	size = res->end - res->start;
+	pci_read_config_dword(pdev, where, &reg);
+	reg = ((reg & size) |
+	       (((u32)(res->start - root->start)) & ~size));
+	pci_write_config_dword(pdev, where, reg);
+}
+
+/* We have to do the config space accesses by hand, thus... */
+#define PBM_BRIDGE_BUS		0x40
+#define PBM_BRIDGE_SUBORDINATE	0x41
+static void __init pbm_renumber(struct pci_pbm_info *pbm, u8 orig_busno)
+{
+	u8 *addr, busno;
+	int nbus;
+
+	busno = pci_highest_busnum;
+	nbus = pbm->pci_last_busno - pbm->pci_first_busno;
+
+	addr = psycho_pci_config_mkaddr(pbm, orig_busno,
+					0, PBM_BRIDGE_BUS);
+	pci_config_write8(addr, busno);
+	addr = psycho_pci_config_mkaddr(pbm, busno,
+					0, PBM_BRIDGE_SUBORDINATE);
+	pci_config_write8(addr, busno + nbus);
+
+	pbm->pci_first_busno = busno;
+	pbm->pci_last_busno = busno + nbus;
+	pci_highest_busnum = busno + nbus + 1;
+
+	do {
+		pci_bus2pbm[busno++] = pbm;
+	} while (nbus--);
+}
+
+/* We have to do the config space accesses by hand here since
+ * the pci_bus2pbm array is not ready yet.
+ */
+static void __init pbm_pci_bridge_renumber(struct pci_pbm_info *pbm,
+					   u8 busno)
+{
+	u32 devfn, l, class;
+	u8 hdr_type;
+	int is_multi = 0;
+
+	for(devfn = 0; devfn < 0xff; ++devfn) {
+		u32 *dwaddr;
+		u8 *baddr;
+
+		if (PCI_FUNC(devfn) != 0 && is_multi == 0)
+			continue;
+
+		/* Anything there? */
+		dwaddr = psycho_pci_config_mkaddr(pbm, busno, devfn, PCI_VENDOR_ID);
+		l = 0xffffffff;
+		pci_config_read32(dwaddr, &l);
+		if (l == 0xffffffff || l == 0x00000000 ||
+		    l == 0x0000ffff || l == 0xffff0000) {
+			is_multi = 0;
+			continue;
+		}
+
+		baddr = psycho_pci_config_mkaddr(pbm, busno, devfn, PCI_HEADER_TYPE);
+		pci_config_read8(baddr, &hdr_type);
+		if (PCI_FUNC(devfn) == 0)
+			is_multi = hdr_type & 0x80;
+
+		dwaddr = psycho_pci_config_mkaddr(pbm, busno, devfn, PCI_CLASS_REVISION);
+		class = 0xffffffff;
+		pci_config_read32(dwaddr, &class);
+		if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
+			u32 buses = 0xffffffff;
+
+			dwaddr = psycho_pci_config_mkaddr(pbm, busno, devfn,
+							  PCI_PRIMARY_BUS);
+			pci_config_read32(dwaddr, &buses);
+			pbm_pci_bridge_renumber(pbm, (buses >> 8) & 0xff);
+			buses &= 0xff000000;
+			pci_config_write32(dwaddr, buses);
+		}
+	}
+}
+
+static void __init pbm_bridge_reconfigure(struct pci_controller_info *p)
+{
+	struct pci_pbm_info *pbm;
+	u8 *addr;
+
+	/* Clear out primary/secondary/subordinate bus numbers on
+	 * all PCI-to-PCI bridges under each PBM.  The generic bus
+	 * probing will fix them up.
+	 */
+	pbm_pci_bridge_renumber(&p->pbm_B, p->pbm_B.pci_first_busno);
+	pbm_pci_bridge_renumber(&p->pbm_A, p->pbm_A.pci_first_busno);
+
+	/* Move PBM A out of the way. */
+	pbm = &p->pbm_A;
+	addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno,
+					0, PBM_BRIDGE_BUS);
+	pci_config_write8(addr, 0xff);
+	addr = psycho_pci_config_mkaddr(pbm, 0xff,
+					0, PBM_BRIDGE_SUBORDINATE);
+	pci_config_write8(addr, 0xff);
+
+	/* Now we can safely renumber both PBMs. */
+	pbm_renumber(&p->pbm_B, p->pbm_B.pci_first_busno);
+	pbm_renumber(&p->pbm_A, 0xff);
+}
+
+static void __init pbm_scan_bus(struct pci_controller_info *p,
+				struct pci_pbm_info *pbm)
+{
+	pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,
+				    p->pci_ops,
+				    pbm);
+	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
+	pci_record_assignments(pbm, pbm->pci_bus);
+	pci_assign_unassigned(pbm, pbm->pci_bus);
+	pci_fixup_irq(pbm, pbm->pci_bus);
+}
+
+static void __init psycho_scan_bus(struct pci_controller_info *p)
+{
+	pbm_bridge_reconfigure(p);
+	pbm_scan_bus(p, &p->pbm_B);
+	pbm_scan_bus(p, &p->pbm_A);
+
+	/* After the PCI bus scan is complete, we can register
+	 * the error interrupt handlers.
+	 */
+	psycho_register_error_handlers(p);
+}
+
+static void __init psycho_iommu_init(struct pci_controller_info *p, int tsbsize)
+{
+	extern int this_is_starfire;
+	extern void *starfire_hookup(int);
+	struct linux_mlist_p1275 *mlist;
+	unsigned long tsbbase, i, n, order;
+	iopte_t *iopte;
+	u64 control;
+
+	/* Setup initial software IOMMU state. */
+	spin_lock_init(&p->iommu.lock);
+	p->iommu.iommu_cur_ctx = 0;
+
+	/* PSYCHO's IOMMU lacks ctx flushing. */
+	p->iommu.iommu_has_ctx_flush = 0;
+
+	/* Register addresses. */
+	p->iommu.iommu_control  = p->controller_regs + PSYCHO_IOMMU_CONTROL;
+	p->iommu.iommu_tsbbase  = p->controller_regs + PSYCHO_IOMMU_TSBBASE;
+	p->iommu.iommu_flush    = p->controller_regs + PSYCHO_IOMMU_FLUSH;
+	p->iommu.iommu_ctxflush = 0;
+
+	/* We use the main control register of PSYCHO as the write
+	 * completion register.
+	 */
+	p->iommu.write_complete_reg = p->controller_regs + PSYCHO_CONTROL;
+
+	/*
+	 * Invalidate TLB Entries.
+	 */
+	control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL);
+	control |= PSYCHO_IOMMU_CTRL_DENAB;
+	psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
+	for(i = 0; i < 16; i++)
+		psycho_write(p->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
+
+	control &= ~(PSYCHO_IOMMU_CTRL_DENAB);
+	psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
+
+	for(order = 0;; order++)
+		if((PAGE_SIZE << order) >= ((tsbsize * 1024) * 8))
+			break;
+
+	tsbbase = __get_free_pages(GFP_DMA, order);
+	if (!tsbbase) {
+		prom_printf("PSYCHO_IOMMU: Error, gfp(tsb) failed.\n");
+		prom_halt();
+	}
+	p->iommu.page_table = iopte = (iopte_t *)tsbbase;
+	p->iommu.page_table_sz = (tsbsize * 1024);
+
+	/* Initialize to "none" settings. */
+	for(i = 0; i < PCI_DVMA_HASHSZ; i++) {
+		pci_dvma_v2p_hash[i] = PCI_DVMA_HASH_NONE;
+		pci_dvma_p2v_hash[i] = PCI_DVMA_HASH_NONE;
+	}
+
+	n = 0;
+	mlist = *prom_meminfo()->p1275_totphys;
+	while (mlist) {
+		unsigned long paddr = mlist->start_adr;
+		unsigned long num_bytes = mlist->num_bytes;
+
+		if(paddr >= (((unsigned long) high_memory) - PAGE_OFFSET))
+			goto next;
+
+		if((paddr + num_bytes) >= (((unsigned long) high_memory) - PAGE_OFFSET))
+			num_bytes = (((unsigned long) high_memory) - PAGE_OFFSET) - paddr;
+
+		/* Align base and length so we map whole hash table sized chunks
+		 * at a time (and therefore full 64K IOMMU pages).
+		 */
+		paddr &= ~((1UL << 24UL) - 1);
+		num_bytes = (num_bytes + ((1UL << 24UL) - 1)) & ~((1UL << 24) - 1);
+
+		/* Move up the base for mappings already created. */
+		while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] !=
+		      PCI_DVMA_HASH_NONE) {
+			paddr += (1UL << 24UL);
+			num_bytes -= (1UL << 24UL);
+			if(num_bytes == 0UL)
+				goto next;
+		}
+
+		/* Move down the size for tail mappings already created. */
+		while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr + num_bytes - (1UL << 24UL))] !=
+		      PCI_DVMA_HASH_NONE) {
+			num_bytes -= (1UL << 24UL);
+			if(num_bytes == 0UL)
+				goto next;
+		}
+
+		/* Now map the rest. */
+		for (i = 0; i < ((num_bytes + ((1 << 16) - 1)) >> 16); i++) {
+			iopte_val(*iopte) = ((IOPTE_VALID | IOPTE_64K |
+					      IOPTE_CACHE | IOPTE_WRITE) |
+					     (paddr & IOPTE_PAGE));
+
+			if (!(n & 0xff))
+				set_dvma_hash(paddr, (n << 16));
+
+			if (++n > (tsbsize * 1024))
+				goto out;
+
+			paddr += (1 << 16);
+			iopte++;
+		}
+	next:
+		mlist = mlist->theres_more;
+	}
+out:
+	if (mlist) {
+		prom_printf("WARNING: not all physical memory mapped in IOMMU\n");
+		prom_printf("Try booting with mem=xxxM or similar\n");
+		prom_halt();
+	}
+
+	psycho_write(p->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase));
+
+	control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL);
+	control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ);
+	control |= (PSYCHO_IOMMU_CTRL_TBWSZ | PSYCHO_IOMMU_CTRL_ENAB);
+	switch(tsbsize) {
+	case 8:
+		p->iommu.page_table_map_base = 0xe0000000;
+		pci_dvma_mask = 0x1fffffffUL;
+		control |= PSYCHO_IOMMU_TSBSZ_8K;
+		break;
+	case 16:
+		p->iommu.page_table_map_base = 0xc0000000;
+		pci_dvma_mask = 0x3fffffffUL;
+		control |= PSYCHO_IOMMU_TSBSZ_16K;
+		break;
+	case 32:
+		p->iommu.page_table_map_base = 0x80000000;
+		pci_dvma_mask = 0x7fffffffUL;
+		control |= PSYCHO_IOMMU_TSBSZ_32K;
+		break;
+	default:
+		prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
+		prom_halt();
+		break;
+	}
+	psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
+
+	/* If necessary, hook us up for starfire IRQ translations. */
+	if(this_is_starfire)
+		p->starfire_cookie = starfire_hookup(p->portid);
+	else
+		p->starfire_cookie = NULL;
+}
+
+#define PSYCHO_IRQ_RETRY	0x1a00UL
+#define PSYCHO_PCIA_DIAG	0x2020UL
+#define PSYCHO_PCIB_DIAG	0x4020UL
+#define  PSYCHO_PCIDIAG_RESV	 0xffffffffffffff80 /* Reserved                     */
+#define  PSYCHO_PCIDIAG_DRETRY	 0x0000000000000040 /* Disable retry limit          */
+#define  PSYCHO_PCIDIAG_DISYNC	 0x0000000000000020 /* Disable DMA wr / irq sync    */
+#define  PSYCHO_PCIDIAG_DDWSYNC	 0x0000000000000010 /* Disable DMA wr / PIO rd sync */
+#define  PSYCHO_PCIDIAG_IDDPAR	 0x0000000000000008 /* Invert DMA data parity       */
+#define  PSYCHO_PCIDIAG_IPDPAR	 0x0000000000000004 /* Invert PIO data parity       */
+#define  PSYCHO_PCIDIAG_IPAPAR	 0x0000000000000002 /* Invert PIO address parity    */
+#define  PSYCHO_PCIDIAG_LPBACK	 0x0000000000000001 /* Enable loopback mode         */
+
+static void psycho_controller_hwinit(struct pci_controller_info *p)
+{
+	u64 tmp;
+
+	/* PROM sets the IRQ retry value too low, increase it. */
+	psycho_write(p->controller_regs + PSYCHO_IRQ_RETRY, 0xff);
+
+	/* Enable arbiter for all PCI slots. */
+	tmp = psycho_read(p->controller_regs + PSYCHO_PCIA_CTRL);
+	tmp |= PSYCHO_PCICTRL_AEN;
+	psycho_write(p->controller_regs + PSYCHO_PCIA_CTRL, tmp);
+
+	tmp = psycho_read(p->controller_regs + PSYCHO_PCIB_CTRL);
+	tmp |= PSYCHO_PCICTRL_AEN;
+	psycho_write(p->controller_regs + PSYCHO_PCIB_CTRL, tmp);
+
+	/* Disable DMA write / PIO read synchronization on
+	 * both PCI bus segments.
+	 * [ U2P Erratum 1243770, STP2223BGA data sheet ]
+	 */
+	tmp = psycho_read(p->controller_regs + PSYCHO_PCIA_DIAG);
+	tmp |= PSYCHO_PCIDIAG_DDWSYNC;
+	psycho_write(p->controller_regs + PSYCHO_PCIA_DIAG, tmp);
+
+	tmp = psycho_read(p->controller_regs + PSYCHO_PCIB_DIAG);
+	tmp |= PSYCHO_PCIDIAG_DDWSYNC;
+	psycho_write(p->controller_regs + PSYCHO_PCIB_DIAG, tmp);
+}
+
+static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
+						   struct pci_pbm_info *pbm)
+{
+	char *name = pbm->name;
+
+	sprintf(name, "PSYCHO%d PBM%c",
+		p->index,
+		(pbm == &p->pbm_A ? 'A' : 'B'));
+	pbm->io_space.name = pbm->mem_space.name = name;
+
+	request_resource(&ioport_resource, &pbm->io_space);
+	request_resource(&iomem_resource, &pbm->mem_space);
+}
+
+static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
+				   struct pci_pbm_info *pbm,
+				   int is_pbm_a)
+{
+	unsigned long base = p->controller_regs;
+
+	/* Currently we don't even use it. */
+	pbm->stc.strbuf_enabled = 0;
+
+	/* PSYCHO's streaming buffer lacks ctx flushing. */
+	pbm->stc.strbuf_has_ctx_flush = 0;
+
+	if (is_pbm_a) {
+		pbm->stc.strbuf_control  = base + PSYCHO_STRBUF_CONTROL_A;
+		pbm->stc.strbuf_pflush   = base + PSYCHO_STRBUF_FLUSH_A;
+		pbm->stc.strbuf_fsync    = base + PSYCHO_STRBUF_FSYNC_A;
+	} else {
+		pbm->stc.strbuf_control  = base + PSYCHO_STRBUF_CONTROL_B;
+		pbm->stc.strbuf_pflush   = base + PSYCHO_STRBUF_FLUSH_B;
+		pbm->stc.strbuf_fsync    = base + PSYCHO_STRBUF_FSYNC_B;
+	}
+	pbm->stc.strbuf_ctxflush      = 0;
+	pbm->stc.strbuf_ctxmatch_base = 0;
+
+	pbm->stc.strbuf_flushflag = (volatile unsigned long *)
+		((((unsigned long)&pbm->stc.__flushflag_buf[0])
+		  + 63UL)
+		 & ~63UL);
+	pbm->stc.strbuf_flushflag_pa = (unsigned long)
+		__pa(pbm->stc.strbuf_flushflag);
+
+#if 0
+	/* And when we do enable it, these are the sorts of things
+	 * we'll do.
+	 */
+	control = psycho_read(pbm->stc.strbuf_control);
+	control |= PSYCHO_SBUFCTRL_SB_EN;
+	psycho_write(pbm->stc.strbuf_control, control);
+#endif
+}
+
+#define PSYCHO_IOSPACE_A	0x002000000UL
+#define PSYCHO_IOSPACE_B	0x002010000UL
+#define PSYCHO_IOSPACE_SIZE	0x00000ffffUL
+#define PSYCHO_MEMSPACE_A	0x100000000UL
+#define PSYCHO_MEMSPACE_B	0x180000000UL
+#define PSYCHO_MEMSPACE_SIZE	0x07fffffffUL
+
+static void psycho_pbm_init(struct pci_controller_info *p,
+			    int prom_node, int is_pbm_a)
+{
+	unsigned int busrange[2];
+	struct pci_pbm_info *pbm;
+	int err;
+
+	if (is_pbm_a) {
+		pbm = &p->pbm_A;
+		pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_A;
+		pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_A;
+	} else {
+		pbm = &p->pbm_B;
+		pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_B;
+		pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_B;
+	}
+	pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE;
+	pbm->io_space.flags = IORESOURCE_IO;
+	pbm->mem_space.end = pbm->mem_space.start + PSYCHO_MEMSPACE_SIZE;
+	pbm->mem_space.flags = IORESOURCE_MEM;
+	pbm_register_toplevel_resources(p, pbm);
+
+	pbm->parent = p;
+	pbm->prom_node = prom_node;
+	prom_getstring(prom_node, "name",
+		       pbm->prom_name,
+		       sizeof(pbm->prom_name));
+
+	err = prom_getproperty(prom_node, "ranges",
+			       (char *)pbm->pbm_ranges,
+			       sizeof(pbm->pbm_ranges));
+	if (err != -1)
+		pbm->num_pbm_ranges =
+			(err / sizeof(struct linux_prom_pci_ranges));
+	else
+		pbm->num_pbm_ranges = 0;
+
+	err = prom_getproperty(prom_node, "interrupt-map",
+			       (char *)pbm->pbm_intmap,
+			       sizeof(pbm->pbm_intmap));
+	if (err != -1) {
+		pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
+		err = prom_getproperty(prom_node, "interrupt-map-mask",
+				       (char *)&pbm->pbm_intmask,
+				       sizeof(pbm->pbm_intmask));
+		if (err == -1) {
+			prom_printf("PSYCHO-PBM: Fatal error, no "
+				    "interrupt-map-mask.\n");
+			prom_halt();
+		}
+	} else {
+		pbm->num_pbm_intmap = 0;
+		memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
+	}
+
+	err = prom_getproperty(prom_node, "bus-range",
+			       (char *)&busrange[0],
+			       sizeof(busrange));
+	if (err == 0 || err == -1) {
+		prom_printf("PSYCHO-PBM: Fatal error, no bus-range.\n");
+		prom_halt();
+	}
+	pbm->pci_first_busno = busrange[0];
+	pbm->pci_last_busno = busrange[1];
+
+	psycho_pbm_strbuf_init(p, pbm, is_pbm_a);
+}
+
+#define PSYCHO_CONFIGSPACE	0x001000000UL
+
+void __init psycho_init(int node)
+{
+	struct linux_prom64_registers pr_regs[3];
+	struct pci_controller_info *p;
+	unsigned long flags;
+	u32 upa_portid;
+	int is_pbm_a, err;
+
+	upa_portid = prom_getintdefault(node, "upa-portid", 0xff);
+
+	spin_lock_irqsave(&pci_controller_lock, flags);
+	for(p = pci_controller_root; p; p = p->next) {
+		if (p->portid == upa_portid) {
+			spin_unlock_irqrestore(&pci_controller_lock, flags);
+			is_pbm_a = (p->pbm_A.prom_node == 0);
+			psycho_pbm_init(p, node, is_pbm_a);
+			return;
+		}
+	}
+	spin_unlock_irqrestore(&pci_controller_lock, flags);
+
+	p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
+	if (!p) {
+		prom_printf("PSYCHO: Fatal memory allocation error.\n");
+		prom_halt();
+	}
+	memset(p, 0, sizeof(*p));
+
+	spin_lock_irqsave(&pci_controller_lock, flags);
+	p->next = pci_controller_root;
+	pci_controller_root = p;
+	spin_unlock_irqrestore(&pci_controller_lock, flags);
+
+	p->portid = upa_portid;
+	p->index = pci_num_controllers++;
+	p->scan_bus = psycho_scan_bus;
+	p->irq_build = psycho_irq_build;
+	p->base_address_update = psycho_base_address_update;
+	p->resource_adjust = psycho_resource_adjust;
+	p->pci_ops = &psycho_ops;
+
+	err = prom_getproperty(node, "reg",
+			       (char *)&pr_regs[0],
+			       sizeof(pr_regs));
+	if (err == 0 || err == -1) {
+		prom_printf("PSYCHO: Fatal error, no reg property.\n");
+		prom_halt();
+	}
+
+	p->controller_regs = pr_regs[2].phys_addr;
+	printk("PCI: Found PSYCHO, control regs at %016lx\n",
+	       p->controller_regs);
+
+	p->config_space = pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE;
+	printk("PSYCHO: PCI config space at %016lx\n", p->config_space);
+
+	psycho_controller_hwinit(p);
+
+	pci_dvma_offset = 0x80000000UL;
+	psycho_iommu_init(p, 32);
+
+	is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
+	psycho_pbm_init(p, node, is_pbm_a);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c
--- v2.3.15/linux/arch/sparc64/kernel/pci_sabre.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/pci_sabre.c	Tue Aug 31 11:23:30 1999
@@ -0,0 +1,1492 @@
+/* $Id: pci_sabre.c,v 1.1 1999/08/30 10:00:32 davem Exp $
+ * pci_sabre.c: Sabre specific PCI controller support.
+ *
+ * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
+ * Copyright (C) 1998, 1999 Eddie C. Dost   (ecd@skynet.be)
+ * Copyright (C) 1999 Jakub Jelinek   (jj@ultra.linux.cz)
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+
+#include <asm/apb.h>
+#include <asm/pbm.h>
+#include <asm/iommu.h>
+#include <asm/irq.h>
+
+#include "pci_impl.h"
+
+/* All SABRE registers are 64-bits.  The following accessor
+ * routines are how they are accessed.  The REG parameter
+ * is a physical address.
+ */
+#define sabre_read(__reg) \
+({	u64 __ret; \
+	__asm__ __volatile__("ldxa [%1] %2, %0" \
+			     : "=r" (__ret) \
+			     : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \
+			     : "memory"); \
+	__ret; \
+})
+#define sabre_write(__reg, __val) \
+	__asm__ __volatile__("stxa %0, [%1] %2" \
+			     : /* no outputs */ \
+			     : "r" (__val), "r" (__reg), \
+			       "i" (ASI_PHYS_BYPASS_EC_E))
+
+/* SABRE PCI controller register offsets and definitions. */
+#define SABRE_UE_AFSR		0x0030UL
+#define  SABRE_UEAFSR_PDRD	 0x4000000000000000UL	/* Primary PCI DMA Read */
+#define  SABRE_UEAFSR_PDWR	 0x2000000000000000UL	/* Primary PCI DMA Write */
+#define  SABRE_UEAFSR_SDRD	 0x0800000000000000UL	/* Secondary PCI DMA Read */
+#define  SABRE_UEAFSR_SDWR	 0x0400000000000000UL	/* Secondary PCI DMA Write */
+#define  SABRE_UEAFSR_SDTE	 0x0200000000000000UL	/* Secondary DMA Translation Error */
+#define  SABRE_UEAFSR_PDTE	 0x0100000000000000UL	/* Primary DMA Translation Error */
+#define  SABRE_UEAFSR_BMSK	 0x0000ffff00000000UL	/* Bytemask */
+#define  SABRE_UEAFSR_OFF	 0x00000000e0000000UL	/* Offset (AFAR bits [5:3] */
+#define  SABRE_UEAFSR_BLK	 0x0000000000800000UL	/* Was block operation */
+#define SABRE_UECE_AFAR		0x0038UL
+#define SABRE_CE_AFSR		0x0040UL
+#define  SABRE_CEAFSR_PDRD	 0x4000000000000000UL	/* Primary PCI DMA Read */
+#define  SABRE_CEAFSR_PDWR	 0x2000000000000000UL	/* Primary PCI DMA Write */
+#define  SABRE_CEAFSR_SDRD	 0x0800000000000000UL	/* Secondary PCI DMA Read */
+#define  SABRE_CEAFSR_SDWR	 0x0400000000000000UL	/* Secondary PCI DMA Write */
+#define  SABRE_CEAFSR_ESYND	 0x00ff000000000000UL	/* ECC Syndrome */
+#define  SABRE_CEAFSR_BMSK	 0x0000ffff00000000UL	/* Bytemask */
+#define  SABRE_CEAFSR_OFF	 0x00000000e0000000UL	/* Offset */
+#define  SABRE_CEAFSR_BLK	 0x0000000000800000UL	/* Was block operation */
+#define SABRE_UECE_AFAR_ALIAS	0x0048UL	/* Aliases to 0x0038 */
+#define SABRE_IOMMU_CONTROL	0x0200UL
+#define  SABRE_IOMMUCTRL_ERRSTS	 0x0000000006000000UL	/* Error status bits */
+#define  SABRE_IOMMUCTRL_ERR	 0x0000000001000000UL	/* Error present in IOTLB */
+#define  SABRE_IOMMUCTRL_LCKEN	 0x0000000000800000UL	/* IOTLB lock enable */
+#define  SABRE_IOMMUCTRL_LCKPTR	 0x0000000000780000UL	/* IOTLB lock pointer */
+#define  SABRE_IOMMUCTRL_TSBSZ	 0x0000000000070000UL	/* TSB Size */
+#define  SABRE_IOMMUCTRL_TBWSZ	 0x0000000000000004UL	/* TSB assumed page size */
+#define  SABRE_IOMMUCTRL_DENAB	 0x0000000000000002UL	/* Diagnostic Mode Enable */
+#define  SABRE_IOMMUCTRL_ENAB	 0x0000000000000001UL	/* IOMMU Enable */
+#define SABRE_IOMMU_TSBBASE	0x0208UL
+#define SABRE_IOMMU_FLUSH	0x0210UL
+#define SABRE_IMAP_A_SLOT0	0x0c00UL
+#define SABRE_IMAP_B_SLOT0	0x0c20UL
+#define SABRE_IMAP_SCSI		0x1000UL
+#define SABRE_IMAP_ETH		0x1008UL
+#define SABRE_IMAP_BPP		0x1010UL
+#define SABRE_IMAP_AU_REC	0x1018UL
+#define SABRE_IMAP_AU_PLAY	0x1020UL
+#define SABRE_IMAP_PFAIL	0x1028UL
+#define SABRE_IMAP_KMS		0x1030UL
+#define SABRE_IMAP_FLPY		0x1038UL
+#define SABRE_IMAP_SHW		0x1040UL
+#define SABRE_IMAP_KBD		0x1048UL
+#define SABRE_IMAP_MS		0x1050UL
+#define SABRE_IMAP_SER		0x1058UL
+#define SABRE_IMAP_UE		0x1070UL
+#define SABRE_IMAP_CE		0x1078UL
+#define SABRE_IMAP_PCIERR	0x1080UL
+#define SABRE_IMAP_GFX		0x1098UL
+#define SABRE_IMAP_EUPA		0x10a0UL
+#define SABRE_ICLR_A_SLOT0	0x1400UL
+#define SABRE_ICLR_B_SLOT0	0x1480UL
+#define SABRE_ICLR_SCSI		0x1800UL
+#define SABRE_ICLR_ETH		0x1808UL
+#define SABRE_ICLR_BPP		0x1810UL
+#define SABRE_ICLR_AU_REC	0x1818UL
+#define SABRE_ICLR_AU_PLAY	0x1820UL
+#define SABRE_ICLR_PFAIL	0x1828UL
+#define SABRE_ICLR_KMS		0x1830UL
+#define SABRE_ICLR_FLPY		0x1838UL
+#define SABRE_ICLR_SHW		0x1840UL
+#define SABRE_ICLR_KBD		0x1848UL
+#define SABRE_ICLR_MS		0x1850UL
+#define SABRE_ICLR_SER		0x1858UL
+#define SABRE_ICLR_UE		0x1870UL
+#define SABRE_ICLR_CE		0x1878UL
+#define SABRE_ICLR_PCIERR	0x1880UL
+#define SABRE_WRSYNC		0x1c20UL
+#define SABRE_PCICTRL		0x2000UL
+#define  SABRE_PCICTRL_MRLEN	 0x0000001000000000UL	/* Use MemoryReadLine for block loads/stores */
+#define  SABRE_PCICTRL_SERR	 0x0000000400000000UL	/* Set when SERR asserted on PCI bus */
+#define  SABRE_PCICTRL_ARBPARK	 0x0000000000200000UL	/* Bus Parking 0=Ultra-IIi 1=prev-bus-owner */
+#define  SABRE_PCICTRL_CPUPRIO	 0x0000000000100000UL	/* Ultra-IIi granted every other bus cycle */
+#define  SABRE_PCICTRL_ARBPRIO	 0x00000000000f0000UL	/* Slot which is granted every other bus cycle */
+#define  SABRE_PCICTRL_ERREN	 0x0000000000000100UL	/* PCI Error Interrupt Enable */
+#define  SABRE_PCICTRL_RTRYWE	 0x0000000000000080UL	/* DMA Flow Control 0=wait-if-possible 1=retry */
+#define  SABRE_PCICTRL_AEN	 0x000000000000000fUL	/* Slot PCI arbitration enables */
+#define SABRE_PIOAFSR		0x2010UL
+#define  SABRE_PIOAFSR_PMA	 0x8000000000000000UL	/* Primary Master Abort */
+#define  SABRE_PIOAFSR_PTA	 0x4000000000000000UL	/* Primary Target Abort */
+#define  SABRE_PIOAFSR_PRTRY	 0x2000000000000000UL	/* Primary Excessive Retries */
+#define  SABRE_PIOAFSR_PPERR	 0x1000000000000000UL	/* Primary Parity Error */
+#define  SABRE_PIOAFSR_SMA	 0x0800000000000000UL	/* Secondary Master Abort */
+#define  SABRE_PIOAFSR_STA	 0x0400000000000000UL	/* Secondary Target Abort */
+#define  SABRE_PIOAFSR_SRTRY	 0x0200000000000000UL	/* Secondary Excessive Retries */
+#define  SABRE_PIOAFSR_SPERR	 0x0100000000000000UL	/* Secondary Parity Error */
+#define  SABRE_PIOAFSR_BMSK	 0x0000ffff00000000UL	/* Byte Mask */
+#define  SABRE_PIOAFSR_BLK	 0x0000000080000000UL	/* Was Block Operation */
+#define SABRE_PIOAFAR		0x2018UL
+#define SABRE_PCIDIAG		0x2020UL
+#define  SABRE_PCIDIAG_DRTRY	 0x0000000000000040UL	/* Disable PIO Retry Limit */
+#define  SABRE_PCIDIAG_IPAPAR	 0x0000000000000008UL	/* Invert PIO Address Parity */
+#define  SABRE_PCIDIAG_IPDPAR	 0x0000000000000004UL	/* Invert PIO Data Parity */
+#define  SABRE_PCIDIAG_IDDPAR	 0x0000000000000002UL	/* Invert DMA Data Parity */
+#define  SABRE_PCIDIAG_ELPBK	 0x0000000000000001UL	/* Loopback Enable - not supported */
+#define SABRE_PCITASR		0x2028UL
+#define  SABRE_PCITASR_EF	 0x0000000000000080UL	/* Respond to 0xe0000000-0xffffffff */
+#define  SABRE_PCITASR_CD	 0x0000000000000040UL	/* Respond to 0xc0000000-0xdfffffff */
+#define  SABRE_PCITASR_AB	 0x0000000000000020UL	/* Respond to 0xa0000000-0xbfffffff */
+#define  SABRE_PCITASR_89	 0x0000000000000010UL	/* Respond to 0x80000000-0x9fffffff */
+#define  SABRE_PCITASR_67	 0x0000000000000008UL	/* Respond to 0x60000000-0x7fffffff */
+#define  SABRE_PCITASR_45	 0x0000000000000004UL	/* Respond to 0x40000000-0x5fffffff */
+#define  SABRE_PCITASR_23	 0x0000000000000002UL	/* Respond to 0x20000000-0x3fffffff */
+#define  SABRE_PCITASR_01	 0x0000000000000001UL	/* Respond to 0x00000000-0x1fffffff */
+#define SABRE_PIOBUF_DIAG	0x5000UL
+#define SABRE_DMABUF_DIAGLO	0x5100UL
+#define SABRE_DMABUF_DIAGHI	0x51c0UL
+#define SABRE_IMAP_GFX_ALIAS	0x6000UL	/* Aliases to 0x1098 */
+#define SABRE_IMAP_EUPA_ALIAS	0x8000UL	/* Aliases to 0x10a0 */
+#define SABRE_IOMMU_VADIAG	0xa400UL
+#define SABRE_IOMMU_TCDIAG	0xa408UL
+#define SABRE_IOMMU_TAG		0xa580UL
+#define  SABRE_IOMMUTAG_ERRSTS	 0x0000000001800000UL	/* Error status bits */
+#define  SABRE_IOMMUTAG_ERR	 0x0000000000400000UL	/* Error present */
+#define  SABRE_IOMMUTAG_WRITE	 0x0000000000200000UL	/* Page is writable */
+#define  SABRE_IOMMUTAG_STREAM	 0x0000000000100000UL	/* Streamable bit - unused */
+#define  SABRE_IOMMUTAG_SIZE	 0x0000000000080000UL	/* 0=8k 1=16k */
+#define  SABRE_IOMMUTAG_VPN	 0x000000000007ffffUL	/* Virtual Page Number [31:13] */
+#define SABRE_IOMMU_DATA	0xa600UL
+#define SABRE_IOMMUDATA_VALID	 0x0000000040000000UL	/* Valid */
+#define SABRE_IOMMUDATA_USED	 0x0000000020000000UL	/* Used (for LRU algorithm) */
+#define SABRE_IOMMUDATA_CACHE	 0x0000000010000000UL	/* Cacheable */
+#define SABRE_IOMMUDATA_PPN	 0x00000000001fffffUL	/* Physical Page Number [33:13] */
+#define SABRE_PCI_IRQSTATE	0xa800UL
+#define SABRE_OBIO_IRQSTATE	0xa808UL
+#define SABRE_FFBCFG		0xf000UL
+#define  SABRE_FFBCFG_SPRQS	 0x000000000f000000	/* Slave P_RQST queue size */
+#define  SABRE_FFBCFG_ONEREAD	 0x0000000000004000	/* Slave supports one outstanding read */
+#define SABRE_MCCTRL0		0xf010UL
+#define  SABRE_MCCTRL0_RENAB	 0x0000000080000000	/* Refresh Enable */
+#define  SABRE_MCCTRL0_EENAB	 0x0000000010000000	/* Enable all ECC functions */
+#define  SABRE_MCCTRL0_11BIT	 0x0000000000001000	/* Enable 11-bit column addressing */
+#define  SABRE_MCCTRL0_DPP	 0x0000000000000f00	/* DIMM Pair Present Bits */
+#define  SABRE_MCCTRL0_RINTVL	 0x00000000000000ff	/* Refresh Interval */
+#define SABRE_MCCTRL1		0xf018UL
+#define  SABRE_MCCTRL1_AMDC	 0x0000000038000000	/* Advance Memdata Clock */
+#define  SABRE_MCCTRL1_ARDC	 0x0000000007000000	/* Advance DRAM Read Data Clock */
+#define  SABRE_MCCTRL1_CSR	 0x0000000000e00000	/* CAS to RAS delay for CBR refresh */
+#define  SABRE_MCCTRL1_CASRW	 0x00000000001c0000	/* CAS length for read/write */
+#define  SABRE_MCCTRL1_RCD	 0x0000000000038000	/* RAS to CAS delay */
+#define  SABRE_MCCTRL1_CP	 0x0000000000007000	/* CAS Precharge */
+#define  SABRE_MCCTRL1_RP	 0x0000000000000e00	/* RAS Precharge */
+#define  SABRE_MCCTRL1_RAS	 0x00000000000001c0	/* Length of RAS for refresh */
+#define  SABRE_MCCTRL1_CASRW2	 0x0000000000000038	/* Must be same as CASRW */
+#define  SABRE_MCCTRL1_RSC	 0x0000000000000007	/* RAS after CAS hold time */
+#define SABRE_RESETCTRL		0xf020UL
+
+#define SABRE_CONFIGSPACE	0x001000000UL
+#define SABRE_IOSPACE		0x002000000UL
+#define SABRE_IOSPACE_SIZE	0x00000ffffUL
+#define SABRE_MEMSPACE		0x100000000UL
+#define SABRE_MEMSPACE_SIZE	0x07fffffffUL
+
+/* UltraSparc-IIi Programmer's Manual, page 325, PCI
+ * configuration space address format:
+ * 
+ *  32             24 23 16 15    11 10       8 7   2  1 0
+ * ---------------------------------------------------------
+ * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 |
+ * ---------------------------------------------------------
+ */
+#define SABRE_CONFIG_BASE(PBM)	\
+	((PBM)->parent->config_space | (1UL << 24))
+#define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG)	\
+	(((unsigned long)(BUS)   << 16) |	\
+	 ((unsigned long)(DEVFN) << 8)  |	\
+	 ((unsigned long)(REG)))
+
+static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm,
+				     unsigned char bus,
+				     unsigned int devfn,
+				     int where)
+{
+	if (!pbm)
+		return NULL;
+	return (void *)
+		(SABRE_CONFIG_BASE(pbm) |
+		 SABRE_CONFIG_ENCODE(bus, devfn, where));
+}
+
+static int sabre_out_of_range(unsigned char devfn)
+{
+	return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) ||
+		((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) ||
+		(PCI_SLOT(devfn) > 1));
+}
+
+static int __sabre_out_of_range(struct pci_pbm_info *pbm,
+				unsigned char bus,
+				unsigned char devfn)
+{
+	return ((pbm->parent == 0) ||
+		((pbm == &pbm->parent->pbm_B) &&
+		 (bus == pbm->pci_first_busno) &&
+		 PCI_SLOT(devfn) > 8) ||
+		((pbm == &pbm->parent->pbm_A) &&
+		 (bus == pbm->pci_first_busno) &&
+		 PCI_SLOT(devfn) > 8));
+}
+
+static int __sabre_read_byte(struct pci_dev *dev, int where, u8 *value)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+	unsigned char bus = dev->bus->number;
+	unsigned int devfn = dev->devfn;
+	u8 *addr;
+
+	*value = 0xff;
+	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	if (__sabre_out_of_range(pbm, bus, devfn))
+		return PCIBIOS_SUCCESSFUL;
+	pci_config_read8(addr, value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int __sabre_read_word(struct pci_dev *dev, int where, u16 *value)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+	unsigned char bus = dev->bus->number;
+	unsigned int devfn = dev->devfn;
+	u16 *addr;
+
+	*value = 0xffff;
+	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	if (__sabre_out_of_range(pbm, bus, devfn))
+		return PCIBIOS_SUCCESSFUL;
+
+	if (where & 0x01) {
+		printk("pcibios_read_config_word: misaligned reg [%x]\n",
+		       where);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	pci_config_read16(addr, value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int __sabre_read_dword(struct pci_dev *dev, int where, u32 *value)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+	unsigned char bus = dev->bus->number;
+	unsigned int devfn = dev->devfn;
+	u32 *addr;
+
+	*value = 0xffffffff;
+	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	if (__sabre_out_of_range(pbm, bus, devfn))
+		return PCIBIOS_SUCCESSFUL;
+
+	if (where & 0x03) {
+		printk("pcibios_read_config_dword: misaligned reg [%x]\n",
+		       where);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	pci_config_read32(addr, value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sabre_read_byte(struct pci_dev *dev, int where, u8 *value)
+{
+	if (dev->bus->number)
+		return __sabre_read_byte(dev, where, value);
+
+	if (sabre_out_of_range(dev->devfn)) {
+		*value = 0xff;
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	if (where < 8) {
+		u16 tmp;
+
+		__sabre_read_word(dev, where & ~1, &tmp);
+		if (where & 1)
+			*value = tmp >> 8;
+		else
+			*value = tmp & 0xff;
+		return PCIBIOS_SUCCESSFUL;
+	} else
+		return __sabre_read_byte(dev, where, value);
+}
+
+static int sabre_read_word(struct pci_dev *dev, int where, u16 *value)
+{
+	if (dev->bus->number)
+		return __sabre_read_word(dev, where, value);
+
+	if (sabre_out_of_range(dev->devfn)) {
+		*value = 0xffff;
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	if (where < 8)
+		return __sabre_read_word(dev, where, value);
+	else {
+		u8 tmp;
+
+		__sabre_read_byte(dev, where, &tmp);
+		*value = tmp;
+		__sabre_read_byte(dev, where + 1, &tmp);
+		*value |= tmp << 8;
+		return PCIBIOS_SUCCESSFUL;
+	}
+}
+
+static int sabre_read_dword(struct pci_dev *dev, int where, u32 *value)
+{
+	u16 tmp;
+
+	if (dev->bus->number)
+		return __sabre_read_dword(dev, where, value);
+
+	if (sabre_out_of_range(dev->devfn)) {
+		*value = 0xffffffff;
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	sabre_read_word(dev, where, &tmp);
+	*value = tmp;
+	sabre_read_word(dev, where + 2, &tmp);
+	*value |= tmp << 16;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int __sabre_write_byte(struct pci_dev *dev, int where, u8 value)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+	unsigned char bus = dev->bus->number;
+	unsigned int devfn = dev->devfn;
+	u8 *addr;
+
+	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	if (__sabre_out_of_range(pbm, bus, devfn))
+		return PCIBIOS_SUCCESSFUL;
+	pci_config_write8(addr, value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int __sabre_write_word(struct pci_dev *dev, int where, u16 value)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+	unsigned char bus = dev->bus->number;
+	unsigned int devfn = dev->devfn;
+	u16 *addr;
+
+	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	if (__sabre_out_of_range(pbm, bus, devfn))
+		return PCIBIOS_SUCCESSFUL;
+
+	if (where & 0x01) {
+		printk("pcibios_write_config_word: misaligned reg [%x]\n",
+		       where);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	pci_config_write16(addr, value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int __sabre_write_dword(struct pci_dev *dev, int where, u32 value)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[dev->bus->number];
+	unsigned char bus = dev->bus->number;
+	unsigned int devfn = dev->devfn;
+	u32 *addr;
+
+	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	if (__sabre_out_of_range(pbm, bus, devfn))
+		return PCIBIOS_SUCCESSFUL;
+
+	if (where & 0x03) {
+		printk("pcibios_write_config_dword: misaligned reg [%x]\n",
+		       where);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	pci_config_write32(addr, value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sabre_write_byte(struct pci_dev *dev, int where, u8 value)
+{
+	if (dev->bus->number)
+		return __sabre_write_byte(dev, where, value);
+
+	if (sabre_out_of_range(dev->devfn))
+		return PCIBIOS_SUCCESSFUL;
+
+	if (where < 8) {
+		u16 tmp;
+
+		__sabre_read_word(dev, where & ~1, &tmp);
+		if (where & 1) {
+			value &= 0x00ff;
+			value |= tmp << 8;
+		} else {
+			value &= 0xff00;
+			value |= tmp;
+		}
+		return __sabre_write_word(dev, where & ~1, tmp);
+	} else
+		return __sabre_write_byte(dev, where, value);
+}
+
+static int sabre_write_word(struct pci_dev *dev, int where, u16 value)
+{
+	if (dev->bus->number)
+		return __sabre_write_word(dev, where, value);
+
+	if (sabre_out_of_range(dev->devfn))
+		return PCIBIOS_SUCCESSFUL;
+
+	if (where < 8)
+		return __sabre_write_word(dev, where, value);
+	else {
+		__sabre_write_byte(dev, where, value & 0xff);
+		__sabre_write_byte(dev, where + 1, value >> 8);
+		return PCIBIOS_SUCCESSFUL;
+	}
+}
+
+static int sabre_write_dword(struct pci_dev *dev, int where, u32 value)
+{
+	if (dev->bus->number)
+		return __sabre_write_dword(dev, where, value);
+
+	if (sabre_out_of_range(dev->devfn))
+		return PCIBIOS_SUCCESSFUL;
+
+	sabre_write_word(dev, where, value & 0xffff);
+	sabre_write_word(dev, where + 2, value >> 16);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops sabre_ops = {
+	sabre_read_byte,
+	sabre_read_word,
+	sabre_read_dword,
+	sabre_write_byte,
+	sabre_write_word,
+	sabre_write_dword
+};
+
+static unsigned long sabre_pcislot_imap_offset(unsigned long ino)
+{
+	unsigned int bus =  (ino & 0x10) >> 4;
+	unsigned int slot = (ino & 0x0c) >> 2;
+
+	if (bus == 0)
+		return SABRE_IMAP_A_SLOT0 + (slot * 8);
+	else
+		return SABRE_IMAP_B_SLOT0 + (slot * 8);
+}
+
+static unsigned long __onboard_imap_off[] = {
+/*0x20*/	SABRE_IMAP_SCSI,
+/*0x21*/	SABRE_IMAP_ETH,
+/*0x22*/	SABRE_IMAP_BPP,
+/*0x23*/	SABRE_IMAP_AU_REC,
+/*0x24*/	SABRE_IMAP_AU_PLAY,
+/*0x25*/	SABRE_IMAP_PFAIL,
+/*0x26*/	SABRE_IMAP_KMS,
+/*0x27*/	SABRE_IMAP_FLPY,
+/*0x28*/	SABRE_IMAP_SHW,
+/*0x29*/	SABRE_IMAP_KBD,
+/*0x2a*/	SABRE_IMAP_MS,
+/*0x2b*/	SABRE_IMAP_SER,
+/*0x2c*/	0 /* reserved */,
+/*0x2d*/	0 /* reserved */,
+/*0x2e*/	SABRE_IMAP_UE,
+/*0x2f*/	SABRE_IMAP_CE,
+/*0x30*/	SABRE_IMAP_PCIERR,
+};
+#define SABRE_ONBOARD_IRQ_BASE		0x20
+#define SABRE_ONBOARD_IRQ_LAST		0x30
+#define sabre_onboard_imap_offset(__ino) \
+	__onboard_imap_off[(__ino) - SABRE_ONBOARD_IRQ_BASE]
+
+#define sabre_iclr_offset(ino)					      \
+	((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
+			(SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
+
+/* PCI SABRE INO number to Sparc PIL level. */
+static unsigned char sabre_pil_table[] = {
+/*0x00*/0, 0, 0, 0,	/* PCI A slot 0  Int A, B, C, D */
+/*0x04*/0, 0, 0, 0,	/* PCI A slot 1  Int A, B, C, D */
+/*0x08*/0, 0, 0, 0,	/* PCI A slot 2  Int A, B, C, D */
+/*0x0c*/0, 0, 0, 0,	/* PCI A slot 3  Int A, B, C, D */
+/*0x10*/0, 0, 0, 0,	/* PCI B slot 0  Int A, B, C, D */
+/*0x14*/0, 0, 0, 0,	/* PCI B slot 1  Int A, B, C, D */
+/*0x18*/0, 0, 0, 0,	/* PCI B slot 2  Int A, B, C, D */
+/*0x1c*/0, 0, 0, 0,	/* PCI B slot 3  Int A, B, C, D */
+/*0x20*/3,		/* SCSI				*/
+/*0x21*/5,		/* Ethernet			*/
+/*0x22*/8,		/* Parallel Port		*/
+/*0x23*/13,		/* Audio Record			*/
+/*0x24*/14,		/* Audio Playback		*/
+/*0x25*/15,		/* PowerFail			*/
+/*0x26*/3,		/* second SCSI			*/
+/*0x27*/11,		/* Floppy			*/
+/*0x28*/2,		/* Spare Hardware		*/
+/*0x29*/9,		/* Keyboard			*/
+/*0x2a*/4,		/* Mouse			*/
+/*0x2b*/12,		/* Serial			*/
+/*0x2c*/10,		/* Timer 0			*/
+/*0x2d*/11,		/* Timer 1			*/
+/*0x2e*/15,		/* Uncorrectable ECC		*/
+/*0x2f*/15,		/* Correctable ECC		*/
+/*0x30*/15,		/* PCI Bus A Error		*/
+/*0x31*/15,		/* PCI Bus B Error		*/
+/*0x32*/1,		/* Power Management		*/
+};
+
+static int __init sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
+{
+	int ret;
+
+	ret = sabre_pil_table[ino];
+	if (ret == 0 && pdev == NULL) {
+		ret = 1;
+	} else if (ret == 0) {
+		switch ((pdev->class >> 16) & 0x0f) {
+		case PCI_BASE_CLASS_STORAGE:
+			ret = 4;
+
+		case PCI_BASE_CLASS_NETWORK:
+			ret = 6;
+
+		case PCI_BASE_CLASS_DISPLAY:
+			ret = 9;
+
+		case PCI_BASE_CLASS_MULTIMEDIA:
+		case PCI_BASE_CLASS_MEMORY:
+		case PCI_BASE_CLASS_BRIDGE:
+			ret = 10;
+
+		default:
+			ret = 1;
+		};
+	}
+	return ret;
+}
+
+static unsigned int __init sabre_irq_build(struct pci_controller_info *p,
+					   struct pci_dev *pdev,
+					   unsigned int ino)
+{
+	struct ino_bucket *bucket;
+	volatile unsigned int *imap, *iclr;
+	unsigned long imap_off, iclr_off;
+	int pil, inofixup = 0;
+
+	ino &= PCI_IRQ_INO;
+	if (ino < SABRE_ONBOARD_IRQ_BASE) {
+		/* PCI slot */
+		imap_off = sabre_pcislot_imap_offset(ino);
+	} else {
+		/* onboard device */
+		if (ino > SABRE_ONBOARD_IRQ_LAST) {
+			prom_printf("sabre_irq_build: Wacky INO [%x]\n", ino);
+			prom_halt();
+		}
+		imap_off = sabre_onboard_imap_offset(ino);
+	}
+
+	/* Now build the IRQ bucket. */
+	pil = sabre_ino_to_pil(pdev, ino);
+	imap = (volatile unsigned int *)__va(p->controller_regs + imap_off);
+	imap += 1;
+
+	iclr_off = sabre_iclr_offset(ino);
+	iclr = (volatile unsigned int *)__va(p->controller_regs + iclr_off);
+	iclr += 1;
+
+	if ((ino & 0x20) == 0)
+		inofixup = ino & 0x03;
+
+	bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
+	bucket->flags |= IBF_PCI;
+
+	/* XXX We still need to code up support for this in irq.c
+	 * XXX It's easy to code up since only one SIMBA can exist
+	 * XXX in a machine and this is where the sync register is. -DaveM
+	 */
+	if (pdev) {
+		struct pcidev_cookie *pcp = pdev->sysdata;
+		if (pdev->bus->number != pcp->pbm->pci_first_busno)
+			bucket->flags |= IBF_DMA_SYNC;
+	}
+	return __irq(bucket);
+}
+
+/* SABRE error handling support. */
+static void sabre_check_iommu_error(struct pci_controller_info *p,
+				    unsigned long afsr,
+				    unsigned long afar)
+{
+	unsigned long iommu_tag[16];
+	unsigned long iommu_data[16];
+	unsigned long flags;
+	u64 control;
+	int i;
+
+	spin_lock_irqsave(&p->iommu.lock, flags);
+	control = sabre_read(p->iommu.iommu_control);
+	if (control & SABRE_IOMMUCTRL_ERR) {
+		char *type_string;
+
+		/* Clear the error encountered bit.
+		 * NOTE: On Sabre this is write 1 to clear,
+		 *       which is different from Psycho.
+		 */
+		sabre_write(p->iommu.iommu_control, control);
+		switch((control & SABRE_IOMMUCTRL_ERRSTS) >> 25UL) {
+		case 1:
+			type_string = "Invalid Error";
+			break;
+		case 3:
+			type_string = "ECC Error";
+			break;
+		default:
+			type_string = "Unknown";
+			break;
+		};
+		printk("SABRE%d: IOMMU Error, type[%s]\n",
+		       p->index, type_string);
+
+		/* Enter diagnostic mode and probe for error'd
+		 * entries in the IOTLB.
+		 */
+		control &= ~(SABRE_IOMMUCTRL_ERRSTS | SABRE_IOMMUCTRL_ERR);
+		sabre_write(p->iommu.iommu_control,
+			    (control | SABRE_IOMMUCTRL_DENAB));
+		for (i = 0; i < 16; i++) {
+			unsigned long base = p->controller_regs;
+
+			iommu_tag[i] =
+				sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL));
+			iommu_data[i] =
+				sabre_read(base + SABRE_IOMMU_DATA + (i * 8UL));
+			sabre_write(base + SABRE_IOMMU_TAG + (i * 8UL), 0);
+			sabre_write(base + SABRE_IOMMU_DATA + (i * 8UL), 0);
+		}
+		sabre_write(p->iommu.iommu_control, control);
+
+		for (i = 0; i < 16; i++) {
+			unsigned long tag, data;
+
+			tag = iommu_tag[i];
+			if (!(tag & SABRE_IOMMUTAG_ERR))
+				continue;
+
+			data = iommu_data[i];
+			switch((tag & SABRE_IOMMUTAG_ERRSTS) >> 23UL) {
+			case 1:
+				type_string = "Invalid Error";
+				break;
+			case 3:
+				type_string = "ECC Error";
+				break;
+			default:
+				type_string = "Unknown";
+				break;
+			};
+			printk("SABRE%d: IOMMU TAG(%d)[error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n",
+			       p->index, i, type_string,
+			       ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0),
+			       ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8),
+			       ((tag & SABRE_IOMMUTAG_VPN) << PAGE_SHIFT));
+			printk("SABRE%d: IOMMU DATA(%d)[valid(%d)used(%d)cache(%d)ppg(%016lx)\n",
+			       p->index, i,
+			       ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0),
+			       ((data & SABRE_IOMMUDATA_USED) ? 1 : 0),
+			       ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0),
+			       ((data & SABRE_IOMMUDATA_PPN) << PAGE_SHIFT));
+		}
+	}
+	spin_unlock_irqrestore(&p->iommu.lock, flags);
+}
+
+static void sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct pci_controller_info *p = dev_id;
+	unsigned long afsr_reg = p->controller_regs + SABRE_UE_AFSR;
+	unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR;
+	unsigned long afsr, afar, error_bits;
+	int reported;
+
+	/* Latch uncorrectable error status. */
+	afar = sabre_read(afar_reg);
+	afsr = sabre_read(afsr_reg);
+
+	/* Clear the primary/secondary error status bits. */
+	error_bits = afsr &
+		(SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR |
+		 SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR |
+		 SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE);
+	sabre_write(afsr_reg, error_bits);
+
+	/* Log the error. */
+	printk("SABRE%d: Uncorrectable Error, primary error type[%s%s]\n",
+	       p->index,
+	       ((error_bits & SABRE_UEAFSR_PDRD) ?
+		"DMA Read" :
+		((error_bits & SABRE_UEAFSR_PDWR) ?
+		 "DMA Write" : "???")),
+	       ((error_bits & SABRE_UEAFSR_PDTE) ?
+		":Translation Error" : ""));
+	printk("SABRE%d: bytemask[%04lx] dword_offset[%lx] was_block(%d)\n",
+	       p->index,
+	       (afsr & SABRE_UEAFSR_BMSK) >> 32UL,
+	       (afsr & SABRE_UEAFSR_OFF) >> 29UL,
+	       ((afsr & SABRE_UEAFSR_BLK) ? 1 : 0));
+	printk("SABRE%d: UE AFAR [%016lx]\n", p->index, afar);
+	printk("SABRE%d: UE Secondary errors [", p->index);
+	reported = 0;
+	if (afsr & SABRE_UEAFSR_SDRD) {
+		reported++;
+		printk("(DMA Read)");
+	}
+	if (afsr & SABRE_UEAFSR_SDWR) {
+		reported++;
+		printk("(DMA Write)");
+	}
+	if (afsr & SABRE_UEAFSR_SDTE) {
+		reported++;
+		printk("(Translation Error)");
+	}
+	if (!reported)
+		printk("(none)");
+	printk("]\n");
+
+	/* Interrogate IOMMU for error status. */
+	sabre_check_iommu_error(p, afsr, afar);
+}
+
+static void sabre_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct pci_controller_info *p = dev_id;
+	unsigned long afsr_reg = p->controller_regs + SABRE_CE_AFSR;
+	unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR;
+	unsigned long afsr, afar, error_bits;
+	int reported;
+
+	/* Latch error status. */
+	afar = sabre_read(afar_reg);
+	afsr = sabre_read(afsr_reg);
+
+	/* Clear primary/secondary error status bits. */
+	error_bits = afsr &
+		(SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR |
+		 SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR);
+	sabre_write(afsr_reg, error_bits);
+
+	/* Log the error. */
+	printk("SABRE%d: Correctable Error, primary error type[%s]\n",
+	       p->index,
+	       ((error_bits & SABRE_CEAFSR_PDRD) ?
+		"DMA Read" :
+		((error_bits & SABRE_CEAFSR_PDWR) ?
+		 "DMA Write" : "???")));
+	printk("SABRE%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] "
+	       "was_block(%d)\n",
+	       p->index,
+	       (afsr & SABRE_CEAFSR_ESYND) >> 48UL,
+	       (afsr & SABRE_CEAFSR_BMSK) >> 32UL,
+	       (afsr & SABRE_CEAFSR_OFF) >> 29UL,
+	       ((afsr & SABRE_CEAFSR_BLK) ? 1 : 0));
+	printk("SABRE%d: CE AFAR [%016lx]\n", p->index, afar);
+	printk("SABRE%d: CE Secondary errors [", p->index);
+	reported = 0;
+	if (afsr & SABRE_CEAFSR_SDRD) {
+		reported++;
+		printk("(DMA Read)");
+	}
+	if (afsr & SABRE_CEAFSR_SDWR) {
+		reported++;
+		printk("(DMA Write)");
+	}
+	if (!reported)
+		printk("(none)");
+	printk("]\n");
+}
+
+static void sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct pci_controller_info *p = dev_id;
+	unsigned long afsr_reg, afar_reg;
+	unsigned long afsr, afar, error_bits;
+	int reported;
+
+	afsr_reg = p->controller_regs + SABRE_PIOAFSR;
+	afar_reg = p->controller_regs + SABRE_PIOAFAR;
+
+	/* Latch error status. */
+	afar = sabre_read(afar_reg);
+	afsr = sabre_read(afsr_reg);
+
+	/* Clear primary/secondary error status bits. */
+	error_bits = afsr &
+		(SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_PTA |
+		 SABRE_PIOAFSR_PRTRY | SABRE_PIOAFSR_PPERR |
+		 SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA |
+		 SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR);
+	sabre_write(afsr_reg, error_bits);
+
+	/* Log the error. */
+	printk("SABRE%d: PCI Error, primary error type[%s]\n",
+	       p->index,
+	       (((error_bits & SABRE_PIOAFSR_PMA) ?
+		 "Master Abort" :
+		 ((error_bits & SABRE_PIOAFSR_PTA) ?
+		  "Target Abort" :
+		  ((error_bits & SABRE_PIOAFSR_PRTRY) ?
+		   "Excessive Retries" :
+		   ((error_bits & SABRE_PIOAFSR_PPERR) ?
+		    "Parity Error" : "???"))))));
+	printk("SABRE%d: bytemask[%04lx] was_block(%d)\n",
+	       p->index,
+	       (afsr & SABRE_PIOAFSR_BMSK) >> 32UL,
+	       (afsr & SABRE_PIOAFSR_BLK) ? 1 : 0);
+	printk("SABRE%d: PCI AFAR [%016lx]\n", p->index, afar);
+	printk("SABRE%d: PCI Secondary errors [", p->index);
+	reported = 0;
+	if (afsr & SABRE_PIOAFSR_SMA) {
+		reported++;
+		printk("(Master Abort)");
+	}
+	if (afsr & SABRE_PIOAFSR_STA) {
+		reported++;
+		printk("(Target Abort)");
+	}
+	if (afsr & SABRE_PIOAFSR_SRTRY) {
+		reported++;
+		printk("(Excessive Retries)");
+	}
+	if (afsr & SABRE_PIOAFSR_SPERR) {
+		reported++;
+		printk("(Parity Error)");
+	}
+	if (!reported)
+		printk("(none)");
+	printk("]\n");
+
+	/* For the error types shown, scan both PCI buses for devices
+	 * which have logged that error type.
+	 */
+
+	/* If we see a Target Abort, this could be the result of an
+	 * IOMMU translation error of some sort.  It is extremely
+	 * useful to log this information as usually it indicates
+	 * a bug in the IOMMU support code or a PCI device driver.
+	 */
+	if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) {
+		sabre_check_iommu_error(p, afsr, afar);
+		pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus);
+		pci_scan_for_target_abort(p, &p->pbm_B, p->pbm_B.pci_bus);
+	}
+	if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) {
+		pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus);
+		pci_scan_for_master_abort(p, &p->pbm_B, p->pbm_B.pci_bus);
+	}
+	/* For excessive retries, SABRE/PBM will abort the device
+	 * and there is no way to specifically check for excessive
+	 * retries in the config space status registers.  So what
+	 * we hope is that we'll catch it via the master/target
+	 * abort events.
+	 */
+
+	if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) {
+		pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus);
+		pci_scan_for_parity_error(p, &p->pbm_B, p->pbm_B.pci_bus);
+	}
+}
+
+/* XXX What about PowerFail/PowerManagement??? -DaveM */
+#define SABRE_UE_INO		0x2e
+#define SABRE_CE_INO		0x2f
+#define SABRE_PCIERR_INO	0x30
+static void __init sabre_register_error_handlers(struct pci_controller_info *p)
+{
+	unsigned long base = p->controller_regs;
+	unsigned long irq, portid = p->portid;
+	u64 tmp;
+
+	/* We clear the error bits in the appropriate AFSR before
+	 * registering the handler so that we don't get spurious
+	 * interrupts.
+	 */
+	sabre_write(base + SABRE_UE_AFSR,
+		    (SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR |
+		     SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR |
+		     SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE));
+	irq = sabre_irq_build(p, NULL, (portid << 6) | SABRE_UE_INO);
+	if (request_irq(irq, sabre_ue_intr,
+			SA_SHIRQ, "SABRE UE", p) < 0) {
+		prom_printf("SABRE%d: Cannot register UE interrupt.\n",
+			    p->index);
+		prom_halt();
+	}
+
+	sabre_write(base + SABRE_CE_AFSR,
+		    (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR |
+		     SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR));
+	irq = sabre_irq_build(p, NULL, (portid << 6) | SABRE_CE_INO);
+	if (request_irq(irq, sabre_ce_intr,
+			SA_SHIRQ, "SABRE CE", p) < 0) {
+		prom_printf("SABRE%d: Cannot register CE interrupt.\n",
+			    p->index);
+		prom_halt();
+	}
+
+	irq = sabre_irq_build(p, NULL, (portid << 6) | SABRE_PCIERR_INO);
+	if (request_irq(irq, sabre_pcierr_intr,
+			SA_SHIRQ, "SABRE PCIERR", p) < 0) {
+		prom_printf("SABRE%d: Cannot register PciERR interrupt.\n",
+			    p->index);
+		prom_halt();
+	}
+
+	tmp = sabre_read(base + SABRE_PCICTRL);
+	tmp |= SABRE_PCICTRL_ERREN;
+	sabre_write(base + SABRE_PCICTRL, tmp);
+}
+
+static void __init sabre_resource_adjust(struct pci_dev *pdev,
+					 struct resource *res,
+					 struct resource *root)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_controller_info *p = pcp->pbm->parent;
+	unsigned long base;
+
+	if (res->flags & IORESOURCE_IO)
+		base = p->controller_regs + SABRE_IOSPACE;
+	else
+		base = p->controller_regs + SABRE_MEMSPACE;
+
+	res->start += base;
+	res->end += base;
+}
+
+static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_pbm_info *pbm = pcp->pbm;
+	struct pci_controller_info *p = pbm->parent;
+	struct resource *res = &pdev->resource[resource];
+	unsigned long base;
+	u32 reg;
+	int where, size;
+
+	if (res->flags & IORESOURCE_IO)
+		base = p->controller_regs + SABRE_IOSPACE;
+	else
+		base = p->controller_regs + SABRE_MEMSPACE;
+
+	where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	size = res->end - res->start;
+	pci_read_config_dword(pdev, where, &reg);
+	reg = ((reg & size) |
+	       (((u32)(res->start - base)) & ~size));
+	pci_write_config_dword(pdev, where, reg);
+}
+
+static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
+{
+	struct pci_dev *pdev;
+	u32 dword;
+	u16 word;
+
+	for(pdev = pci_devices; pdev; pdev = pdev->next) {
+		if(pdev->vendor == PCI_VENDOR_ID_SUN &&
+		   pdev->device == PCI_DEVICE_ID_SUN_SABRE) {
+			sabre_write_byte(pdev, PCI_LATENCY_TIMER, 64);
+			break;
+		}
+	}
+
+	for (pdev = sabre_bus->devices; pdev; pdev = pdev->sibling) {
+		if (pdev->vendor == PCI_VENDOR_ID_SUN &&
+		    pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
+			sabre_read_word(pdev, PCI_COMMAND, &word);
+			word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
+				PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY |
+				PCI_COMMAND_IO;
+			sabre_write_word(pdev, PCI_COMMAND, word);
+
+			/* Status register bits are "write 1 to clear". */
+			sabre_write_word(pdev, PCI_STATUS, 0xffff);
+			sabre_write_word(pdev, PCI_SEC_STATUS, 0xffff);
+
+			sabre_read_word(pdev, PCI_BRIDGE_CONTROL, &word);
+			word = PCI_BRIDGE_CTL_MASTER_ABORT |
+			       PCI_BRIDGE_CTL_SERR |
+			       PCI_BRIDGE_CTL_PARITY;
+			sabre_write_word(pdev, PCI_BRIDGE_CONTROL, word);
+
+			sabre_read_dword(pdev, APB_PCI_CONTROL_HIGH, &dword);
+			dword = APB_PCI_CTL_HIGH_SERR |
+				APB_PCI_CTL_HIGH_ARBITER_EN;
+			sabre_write_dword(pdev, APB_PCI_CONTROL_HIGH, dword);
+
+			/* Systems with SIMBA are usually workstations, so
+			 * we configure to park to SIMBA not to the previous
+			 * bus owner.
+			 */
+			sabre_read_dword(pdev, APB_PCI_CONTROL_LOW, &dword);
+			dword = APB_PCI_CTL_LOW_ERRINT_EN | 0x0f;
+			sabre_write_dword(pdev, APB_PCI_CONTROL_LOW, dword);
+
+			/* Don't mess with the retry limit and PIO/DMA latency
+			 * timer settings.  But do set primary and secondary
+			 * latency timers.
+			 */
+			sabre_write_byte(pdev, PCI_LATENCY_TIMER, 64);
+			sabre_write_byte(pdev, PCI_SEC_LATENCY_TIMER, 64);
+		}
+	}
+}
+
+static void __init sabre_scan_bus(struct pci_controller_info *p)
+{
+	static int once = 0;
+	struct pci_bus *sabre_bus, *pbus;
+
+	/* Unlike for PSYCHO, we can only have one SABRE
+	 * in a system.  Having multiple SABREs is thus
+	 * and error, and as a consequence we do not need
+	 * to do any bus renumbering but we do have to have
+	 * the pci_bus2pbm array setup properly.
+	 *
+	 * Also note that the SABRE host bridge is hardwired
+	 * to live at bus 0.
+	 */
+	if (once != 0) {
+		prom_printf("SABRE: Multiple controllers unsupported.\n");
+		prom_halt();
+	}
+	once++;
+
+	/* The pci_bus2pbm table has already been setup in sabre_init. */
+	sabre_bus = pci_scan_bus(p->pci_first_busno,
+				 p->pci_ops,
+				 &p->pbm_A);
+	apb_init(p, sabre_bus);
+
+	for (pbus = sabre_bus->children; pbus; pbus = pbus->next) {
+		struct pci_pbm_info *pbm;
+
+		if (pbus->number == p->pbm_A.pci_first_busno) {
+			pbm = &p->pbm_A;
+		} else if (pbus->number == p->pbm_B.pci_first_busno) {
+			pbm = &p->pbm_B;
+		} else
+			continue;
+
+		pbus->sysdata = pbm;
+		pbm->pci_bus = pbus;
+		pci_fill_in_pbm_cookies(pbus, pbm, pbm->prom_node);
+		pci_record_assignments(pbm, pbus);
+		pci_assign_unassigned(pbm, pbus);
+		pci_fixup_irq(pbm, pbus);
+	}
+
+	sabre_register_error_handlers(p);
+}
+
+static void __init sabre_iommu_init(struct pci_controller_info *p, int tsbsize)
+{
+	struct linux_mlist_p1275 *mlist;
+	unsigned long tsbbase, i, n, order;
+	iopte_t *iopte;
+	u64 control;
+
+	/* Invalidate TLB Entries. */
+	control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);
+	control |= IOMMU_CTRL_DENAB;
+	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
+
+	for(i = 0; i < 16; i++)
+		sabre_write(p->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0);
+
+	control &= ~(IOMMU_CTRL_DENAB);
+	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
+
+	for(order = 0;; order++)
+		if((PAGE_SIZE << order) >= ((tsbsize * 1024) * 8))
+			break;
+
+	tsbbase = __get_free_pages(GFP_DMA, order);
+	if (!tsbbase) {
+		prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n");
+		prom_halt();
+	}
+	iopte = (iopte_t *)tsbbase;
+
+	/* Initialize to "none" settings. */
+	for(i = 0; i < PCI_DVMA_HASHSZ; i++) {
+		pci_dvma_v2p_hash[i] = PCI_DVMA_HASH_NONE;
+		pci_dvma_p2v_hash[i] = PCI_DVMA_HASH_NONE;
+	}
+
+	n = 0;
+	mlist = *prom_meminfo()->p1275_totphys;
+	while (mlist) {
+		unsigned long paddr = mlist->start_adr;
+		unsigned long num_bytes = mlist->num_bytes;
+
+		if(paddr >= (((unsigned long) high_memory) - PAGE_OFFSET))
+			goto next;
+
+		if((paddr + num_bytes) >= (((unsigned long) high_memory) - PAGE_OFFSET))
+			num_bytes =
+				(((unsigned long) high_memory) -
+				 PAGE_OFFSET) - paddr;
+
+		/* Align base and length so we map whole hash table sized chunks
+		 * at a time (and therefore full 64K IOMMU pages).
+		 */
+		paddr &= ~((1UL << 24UL) - 1);
+		num_bytes = (num_bytes + ((1UL << 24UL) - 1)) & ~((1UL << 24) - 1);
+
+		/* Move up the base for mappings already created. */
+		while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] !=
+		      PCI_DVMA_HASH_NONE) {
+			paddr += (1UL << 24UL);
+			num_bytes -= (1UL << 24UL);
+			if(num_bytes == 0UL)
+				goto next;
+		}
+
+		/* Move down the size for tail mappings already created. */
+		while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr + num_bytes - (1UL << 24UL))] !=
+		      PCI_DVMA_HASH_NONE) {
+			num_bytes -= (1UL << 24UL);
+			if(num_bytes == 0UL)
+				goto next;
+		}
+
+		/* Now map the rest. */
+		for (i = 0; i < ((num_bytes + ((1 << 16) - 1)) >> 16); i++) {
+			iopte_val(*iopte) = ((IOPTE_VALID | IOPTE_64K |
+					      IOPTE_CACHE | IOPTE_WRITE) |
+					     (paddr & IOPTE_PAGE));
+
+			if (!(n & 0xff))
+				set_dvma_hash(paddr, (n << 16));
+
+			if (++n > (tsbsize * 1024))
+				goto out;
+
+			paddr += (1 << 16);
+			iopte++;
+		}
+	next:
+		mlist = mlist->theres_more;
+	}
+out:
+	if (mlist) {
+		prom_printf("WARNING: not all physical memory mapped in IOMMU\n");
+		prom_printf("Try booting with mem=xxxM or similar\n");
+		prom_halt();
+	}
+
+	sabre_write(p->controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
+
+	control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);
+	control &= ~(IOMMU_CTRL_TSBSZ);
+	control |= (IOMMU_CTRL_TBWSZ | IOMMU_CTRL_ENAB);
+	switch(tsbsize) {
+	case 8:
+		pci_dvma_mask = 0x1fffffffUL;
+		control |= IOMMU_TSBSZ_8K;
+		break;
+	case 16:
+		pci_dvma_mask = 0x3fffffffUL;
+		control |= IOMMU_TSBSZ_16K;
+		break;
+	case 32:
+		pci_dvma_mask = 0x7fffffffUL;
+		control |= IOMMU_TSBSZ_32K;
+		break;
+	default:
+		prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
+		prom_halt();
+		break;
+	}
+	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
+}
+
+static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
+						   struct pci_pbm_info *pbm)
+{
+	char *name = pbm->name;
+	unsigned long ibase = p->controller_regs + SABRE_IOSPACE;
+	unsigned long mbase = p->controller_regs + SABRE_MEMSPACE;
+	unsigned int devfn;
+	unsigned long first, last, i;
+	u8 *addr, map;
+
+	sprintf(name, "SABRE%d PBM%c",
+		p->index,
+		(pbm == &p->pbm_A ? 'A' : 'B'));
+	pbm->io_space.name = pbm->mem_space.name = name;
+
+	devfn = PCI_DEVFN(1, (pbm == &p->pbm_A) ? 0 : 1);
+	addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_IO_ADDRESS_MAP);
+	map = 0;
+	pci_config_read8(addr, &map);
+
+	first = 8;
+	last = 0;
+	for (i = 0; i < 8; i++) {
+		if ((map & (1 << i)) != 0) {
+			if (first > i)
+				first = i;
+			if (last < i)
+				last = i;
+		}
+	}
+	pbm->io_space.start = ibase + (first << 21UL);
+	pbm->io_space.end   = ibase + (last << 21UL) + ((1 << 21UL) - 1);
+	pbm->io_space.flags = IORESOURCE_IO;
+
+	addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_MEM_ADDRESS_MAP);
+	map = 0;
+	pci_config_read8(addr, &map);
+
+	first = 8;
+	last = 0;
+	for (i = 0; i < 8; i++) {
+		if ((map & (1 << i)) != 0) {
+			if (first > i)
+				first = i;
+			if (last < i)
+				last = i;
+		}
+	}
+	pbm->mem_space.start = mbase + (first << 29UL);
+	pbm->mem_space.end   = mbase + (last << 29UL) + ((1 << 29UL) - 1);
+	pbm->mem_space.flags = IORESOURCE_MEM;
+
+	if (request_resource(&ioport_resource, &pbm->io_space) < 0) {
+		prom_printf("Cannot register PBM-%c's IO space.\n",
+			    (pbm == &p->pbm_A ? 'A' : 'B'));
+		prom_halt();
+	}
+	if (request_resource(&iomem_resource, &pbm->mem_space) < 0) {
+		prom_printf("Cannot register PBM-%c's MEM space.\n",
+			    (pbm == &p->pbm_A ? 'A' : 'B'));
+		prom_halt();
+	}
+}
+
+static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node)
+{
+	char namebuf[128];
+	u32 busrange[2];
+	int node;
+
+	node = prom_getchild(sabre_node);
+	while ((node = prom_searchsiblings(node, "pci")) != 0) {
+		struct pci_pbm_info *pbm;
+		int err;
+
+		err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
+		if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err))
+			goto next_pci;
+
+		err = prom_getproperty(node, "bus-range",
+				       (char *)&busrange[0], sizeof(busrange));
+		if (err == 0 || err == -1) {
+			prom_printf("APB: Error, cannot get PCI bus-range.\n");
+			prom_halt();
+		}
+
+		if (busrange[0] == 1)
+			pbm = &p->pbm_B;
+		else
+			pbm = &p->pbm_A;
+		pbm->parent = p;
+		pbm->prom_node = node;
+		pbm->pci_first_busno = busrange[0];
+		pbm->pci_last_busno = busrange[1];
+		for (err = pbm->pci_first_busno;
+		     err <= pbm->pci_last_busno;
+		     err++)
+			pci_bus2pbm[err] = pbm;
+
+
+		prom_getstring(node, "name", pbm->prom_name, sizeof(pbm->prom_name));
+		err = prom_getproperty(node, "ranges",
+				       (char *)pbm->pbm_ranges,
+				       sizeof(pbm->pbm_ranges));
+		if (err != -1)
+			pbm->num_pbm_ranges =
+				(err / sizeof(struct linux_prom_pci_ranges));
+		else
+			pbm->num_pbm_ranges = 0;
+
+		err = prom_getproperty(node, "interrupt-map",
+				       (char *)pbm->pbm_intmap,
+				       sizeof(pbm->pbm_intmap));
+		if (err != -1) {
+			pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
+			err = prom_getproperty(node, "interrupt-map-mask",
+					       (char *)&pbm->pbm_intmask,
+					       sizeof(pbm->pbm_intmask));
+			if (err == -1) {
+				prom_printf("APB: Fatal error, no interrupt-map-mask.\n");
+				prom_halt();
+			}
+		} else {
+			pbm->num_pbm_intmap = 0;
+			memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
+		}
+
+		pbm_register_toplevel_resources(p, pbm);
+
+	next_pci:
+		node = prom_getsibling(node);
+		if (!node)
+			break;
+	}
+}
+
+void __init sabre_init(int pnode)
+{
+	struct linux_prom64_registers pr_regs[2];
+	struct pci_controller_info *p;
+	unsigned long flags;
+	int tsbsize, err;
+	u32 busrange[2];
+	u32 vdma[2];
+	u32 upa_portid;
+	int bus;
+
+	p = kmalloc(sizeof(*p), GFP_ATOMIC);
+	if (!p) {
+		prom_printf("SABRE: Error, kmalloc(pci_controller_info) failed.\n");
+		prom_halt();
+	}
+
+	upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff);
+
+	memset(p, 0, sizeof(*p));
+
+	spin_lock_irqsave(&pci_controller_lock, flags);
+	p->next = pci_controller_root;
+	pci_controller_root = p;
+	spin_unlock_irqrestore(&pci_controller_lock, flags);
+
+	p->portid = upa_portid;
+	p->index = pci_num_controllers++;
+	p->scan_bus = sabre_scan_bus;
+	p->irq_build = sabre_irq_build;
+	p->base_address_update = sabre_base_address_update;
+	p->resource_adjust = sabre_resource_adjust;
+	p->pci_ops = &sabre_ops;
+
+	/*
+	 * Map in SABRE register set and report the presence of this SABRE.
+	 */
+	err = prom_getproperty(pnode, "reg",
+			       (char *)&pr_regs[0], sizeof(pr_regs));
+	if(err == 0 || err == -1) {
+		prom_printf("SABRE: Error, cannot get U2P registers "
+			    "from PROM.\n");
+		prom_halt();
+	}
+
+	/*
+	 * First REG in property is base of entire SABRE register space.
+	 */
+	p->controller_regs = pr_regs[0].phys_addr;
+	printk("PCI: Found SABRE, main regs at %016lx\n", p->controller_regs);
+
+	/* Error interrupts are enabled later after the bus scan. */
+	sabre_write(p->controller_regs + SABRE_PCICTRL,
+		    (SABRE_PCICTRL_MRLEN   | SABRE_PCICTRL_SERR |
+		     SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN));
+
+	/* Now map in PCI config space for entire SABRE. */
+	p->config_space = p->controller_regs + SABRE_CONFIGSPACE;
+	printk("SABRE: PCI config space at %016lx\n", p->config_space);
+
+	err = prom_getproperty(pnode, "virtual-dma",
+			       (char *)&vdma[0], sizeof(vdma));
+	if(err == 0 || err == -1) {
+		prom_printf("SABRE: Error, cannot get virtual-dma property "
+			    "from PROM.\n");
+		prom_halt();
+	}
+
+	switch(vdma[1]) {
+		case 0x20000000:
+			tsbsize = 8;
+			break;
+		case 0x40000000:
+			tsbsize = 16;
+			break;
+		case 0x80000000:
+			tsbsize = 32;
+			break;
+		default:
+			prom_printf("SABRE: strange virtual-dma size.\n");
+			prom_halt();
+	}
+
+	pci_dvma_offset = vdma[0];
+	sabre_iommu_init(p, tsbsize);
+
+	printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);
+
+	err = prom_getproperty(pnode, "bus-range",
+				       (char *)&busrange[0], sizeof(busrange));
+	if(err == 0 || err == -1) {
+		prom_printf("SABRE: Error, cannot get PCI bus-range "
+			    " from PROM.\n");
+		prom_halt();
+	}
+
+	p->pci_first_busno = busrange[0];
+	p->pci_last_busno = busrange[1];
+
+	/*
+	 * Handle config space reads through any Simba on APB.
+	 */
+	for (bus = p->pci_first_busno; bus <= p->pci_last_busno; bus++)
+		pci_bus2pbm[bus] = &p->pbm_A;
+
+	/*
+	 * Look for APB underneath.
+	 */
+	sabre_pbm_init(p, pnode);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/power.c linux/arch/sparc64/kernel/power.c
--- v2.3.15/linux/arch/sparc64/kernel/power.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/power.c	Tue Aug 31 11:23:30 1999
@@ -0,0 +1,105 @@
+/* $Id: power.c,v 1.2 1999/08/31 04:39:38 davem Exp $
+ * power.c: Power management driver.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/delay.h>
+
+#include <asm/ebus.h>
+
+#define __KERNEL_SYSCALLS__
+#include <linux/unistd.h>
+
+#ifdef CONFIG_PCI
+static unsigned long power_reg = 0UL;
+#define POWER_SYSTEM_OFF (1 << 0)
+#define POWER_COURTESY_OFF (1 << 1)
+
+static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
+static int button_pressed = 0;
+
+static void power_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	if (button_pressed == 0) {
+		wake_up(&powerd_wait);
+		button_pressed = 1;
+	}
+}
+#endif /* CONFIG_PCI */
+
+extern void machine_halt(void);
+
+void machine_power_off(void)
+{
+#ifdef CONFIG_PCI
+	if (power_reg != 0UL) {
+		/* Both register bits seem to have the
+		 * same effect, so until I figure out
+		 * what the difference is...
+		 */
+		writel(POWER_COURTESY_OFF | POWER_SYSTEM_OFF, power_reg);
+	}
+#endif /* CONFIG_PCI */
+	machine_halt();
+}
+
+#ifdef CONFIG_PCI
+static int powerd(void *__unused)
+{
+	static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
+	char *argv[] = { "/usr/bin/shutdown", "-h", "now", NULL };
+
+	current->session = 1;
+	current->pgrp = 1;
+	sprintf(current->comm, "powerd");
+
+again:
+	while(button_pressed == 0) {
+		spin_lock_irq(&current->sigmask_lock);
+		flush_signals(current);
+		spin_unlock_irq(&current->sigmask_lock);
+		interruptible_sleep_on(&powerd_wait);
+	}
+
+	/* Ok, down we go... */
+	if (execve("/usr/bin/shutdown", argv, envp) < 0) {
+		printk("powerd: shutdown execution failed\n");
+		button_pressed = 0;
+		goto again;
+	}
+	return 0;
+}
+
+void __init power_init(void)
+{
+	struct linux_ebus *ebus;
+	struct linux_ebus_device *edev;
+
+	for_each_ebus(ebus) {
+		for_each_ebusdev(edev, ebus) {
+			if (!strcmp(edev->prom_name, "power"))
+				goto found;
+		}
+	}
+	return;
+
+found:
+	power_reg = edev->resource[0].start;
+	printk("power: Control reg at %016lx ... ", power_reg);
+	if (kernel_thread(powerd, 0, CLONE_FS) < 0) {
+		printk("Failed to start power daemon.\n");
+		return;
+	}
+	printk("powerd running.\n");
+	if (request_irq(edev->irqs[0],
+			power_handler, SA_SHIRQ, "power",
+			(void *) power_reg) < 0)
+		printk("power: Error, cannot register IRQ handler.\n");
+}
+#endif /* CONFIG_PCI */
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- v2.3.15/linux/arch/sparc64/kernel/process.c	Wed Aug  4 15:39:46 1999
+++ linux/arch/sparc64/kernel/process.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.99 1999/08/04 03:19:20 davem Exp $
+/*  $Id: process.c,v 1.100 1999/08/31 04:39:39 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -141,11 +141,6 @@
 		prom_reboot(reboot_command);
 	prom_reboot("");
 	panic("Reboot failed!");
-}
-
-void machine_power_off(void)
-{
-	machine_halt();
 }
 
 static void show_regwindow32(struct pt_regs *regs)
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/psycho.c linux/arch/sparc64/kernel/psycho.c
--- v2.3.15/linux/arch/sparc64/kernel/psycho.c	Fri Aug  6 11:58:00 1999
+++ linux/arch/sparc64/kernel/psycho.c	Wed Dec 31 16:00:00 1969
@@ -1,2905 +0,0 @@
-/* $Id: psycho.c,v 1.89 1999/08/06 10:37:35 davem Exp $
- * psycho.c: Ultra/AX U2P PCI controller support.
- *
- * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu)
- * Copyright (C) 1998 Eddie C. Dost   (ecd@skynet.be)
- * Copyright (C) 1999 Jakub Jelinek   (jj@ultra.linux.cz)
- */
-
-#include <linux/config.h>
-#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... */
-#include <asm/irq.h>
-#include <asm/io.h>
-
-#undef PROM_DEBUG
-#undef FIXUP_REGS_DEBUG
-#undef FIXUP_IRQ_DEBUG
-#undef FIXUP_VMA_DEBUG
-#undef PCI_COOKIE_DEBUG
-
-#ifdef PROM_DEBUG
-#define dprintf	prom_printf
-#else
-#define dprintf printk
-#endif
-
-unsigned long pci_dvma_offset = 0x00000000UL;
-unsigned long pci_dvma_mask = 0xffffffffUL;
-
-#define PCI_DVMA_HASH_NONE	0xffffffffffffffffUL
-unsigned long pci_dvma_v2p_hash[PCI_DVMA_HASHSZ];
-unsigned long pci_dvma_p2v_hash[PCI_DVMA_HASHSZ];
-
-#ifndef CONFIG_PCI
-
-int pcibios_present(void)
-{
-	return 0;
-}
-
-asmlinkage int sys_pciconfig_read(unsigned long bus,
-				  unsigned long dfn,
-				  unsigned long off,
-				  unsigned long len,
-				  unsigned char *buf)
-{
-	return 0;
-}
-
-asmlinkage int sys_pciconfig_write(unsigned long bus,
-				   unsigned long dfn,
-				   unsigned long off,
-				   unsigned long len,
-				   unsigned char *buf)
-{
-	return 0;
-}
-
-#else
-
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/pci.h>
-
-#include <asm/oplib.h>
-#include <asm/pbm.h>
-#include <asm/apb.h>
-#include <asm/uaccess.h>
-
-#define PSYCHO_REORDER_ONBOARDFIRST	1
-
-struct linux_psycho *psycho_root = NULL;
-int linux_num_psycho = 0;
-static struct linux_pbm_info *bus2pbm[256];
-static int psycho_reorder __initdata = 0;
-
-static int pbm_read_config_byte(struct linux_pbm_info *pbm,
-				unsigned char bus, unsigned char devfn,
-				unsigned char where, unsigned char *value);
-static int pbm_read_config_word(struct linux_pbm_info *pbm,
-				unsigned char bus, unsigned char devfn,
-				unsigned char where, unsigned short *value);
-static int pbm_read_config_dword(struct linux_pbm_info *pbm,
-				 unsigned char bus, unsigned char devfn,
-				 unsigned char where, unsigned int *value);
-static int pbm_write_config_byte(struct linux_pbm_info *pbm,
-				 unsigned char bus, unsigned char devfn,
-				 unsigned char where, unsigned char value);
-static int pbm_write_config_word(struct linux_pbm_info *pbm,
-				 unsigned char bus, unsigned char devfn,
-				 unsigned char where, unsigned short value);
-static int pbm_write_config_dword(struct linux_pbm_info *pbm,
-				  unsigned char bus, unsigned char devfn,
-				  unsigned char where, unsigned int value);
-
-/* This is used to make the scan_bus in the generic PCI code be
- * a nop, as we need to control the actual bus probing sequence.
- * After that we leave it on of course.
- */
-static int pci_probe_enable = 0;
-
-static __inline__ void set_dvma_hash(unsigned long paddr, unsigned long daddr)
-{
-	unsigned long dvma_addr = pci_dvma_offset + daddr;
-	unsigned long vaddr = (unsigned long)__va(paddr);
-
-	pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] = dvma_addr - vaddr;
-	pci_dvma_p2v_hash[pci_dvma_ahashfn(dvma_addr)] = vaddr - dvma_addr;
-}
-
-static void __init psycho_iommu_init(struct linux_psycho *psycho, int tsbsize)
-{
-	extern int this_is_starfire;
-	extern void *starfire_hookup(int);
-	struct linux_mlist_p1275 *mlist;
-	unsigned long tsbbase;
-	unsigned long control, i, n;
-	unsigned long *iopte;
-	unsigned long order;
-
-	/*
-	 * Invalidate TLB Entries.
-	 */
-	control = psycho->psycho_regs->iommu_control;
-	control |= IOMMU_CTRL_DENAB;
-	psycho->psycho_regs->iommu_control = control;
-	for(i = 0; i < 16; i++) {
-		psycho->psycho_regs->iommu_data[i] = 0;
-	}
-	control &= ~(IOMMU_CTRL_DENAB);
-	psycho->psycho_regs->iommu_control = control;
-
-	for(order = 0;; order++) {
-		if((PAGE_SIZE << order) >= ((tsbsize * 1024) * 8))
-			break;
-	}
-	tsbbase = __get_free_pages(GFP_DMA, order);
-	if (!tsbbase) {
-		prom_printf("IOMMU: Error, kmalloc(tsb) failed.\n");
-		prom_halt();
-	}
-	iopte = (unsigned long *)tsbbase;
-
-	/* Initialize to "none" settings. */
-	for(i = 0; i < PCI_DVMA_HASHSZ; i++) {
-		pci_dvma_v2p_hash[i] = PCI_DVMA_HASH_NONE;
-		pci_dvma_p2v_hash[i] = PCI_DVMA_HASH_NONE;
-	}
-
-	n = 0;
-	mlist = *prom_meminfo()->p1275_totphys;
-	while (mlist) {
-		unsigned long paddr = mlist->start_adr;
-		unsigned long num_bytes = mlist->num_bytes;
-
-		if(paddr >= (((unsigned long) high_memory) - PAGE_OFFSET))
-			goto next;
-
-		if((paddr + num_bytes) >= (((unsigned long) high_memory) - PAGE_OFFSET))
-			num_bytes = (((unsigned long) high_memory) - PAGE_OFFSET) - paddr;
-
-		/* Align base and length so we map whole hash table sized chunks
-		 * at a time (and therefore full 64K IOMMU pages).
-		 */
-		paddr &= ~((1UL << 24UL) - 1);
-		num_bytes = (num_bytes + ((1UL << 24UL) - 1)) & ~((1UL << 24) - 1);
-
-		/* Move up the base for mappings already created. */
-		while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] !=
-		      PCI_DVMA_HASH_NONE) {
-			paddr += (1UL << 24UL);
-			num_bytes -= (1UL << 24UL);
-			if(num_bytes == 0UL)
-				goto next;
-		}
-
-		/* Move down the size for tail mappings already created. */
-		while(pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr + num_bytes - (1UL << 24UL))] !=
-		      PCI_DVMA_HASH_NONE) {
-			num_bytes -= (1UL << 24UL);
-			if(num_bytes == 0UL)
-				goto next;
-		}
-
-		/* Now map the rest. */
-		for (i = 0; i < ((num_bytes + ((1 << 16) - 1)) >> 16); i++) {
-			*iopte = (IOPTE_VALID | IOPTE_64K |
-				  IOPTE_CACHE | IOPTE_WRITE);
-			*iopte |= paddr;
-
-			if (!(n & 0xff))
-				set_dvma_hash(paddr, (n << 16));
-
-			if (++n > (tsbsize * 1024))
-				goto out;
-
-			paddr += (1 << 16);
-			iopte++;
-		}
-	next:
-		mlist = mlist->theres_more;
-	}
-out:
-	if (mlist) {
-		prom_printf("WARNING: not all physical memory mapped in IOMMU\n");
-		prom_printf("Try booting with mem=xxxM or similar\n");
-		prom_halt();
-	}
-
-	psycho->psycho_regs->iommu_tsbbase = __pa(tsbbase);
-
-	control = psycho->psycho_regs->iommu_control;
-	control &= ~(IOMMU_CTRL_TSBSZ);
-	control |= (IOMMU_CTRL_TBWSZ | IOMMU_CTRL_ENAB);
-	switch(tsbsize) {
-	case 8:
-		pci_dvma_mask = 0x1fffffffUL;
-		control |= IOMMU_TSBSZ_8K;
-		break;
-	case 16:
-		pci_dvma_mask = 0x3fffffffUL;
-		control |= IOMMU_TSBSZ_16K;
-		break;
-	case 32:
-		pci_dvma_mask = 0x7fffffffUL;
-		control |= IOMMU_TSBSZ_32K;
-		break;
-	default:
-		prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
-		prom_halt();
-		break;
-	}
-	psycho->psycho_regs->iommu_control = control;
-
-	/* If necessary, hook us up for starfire IRQ translations. */
-	if(this_is_starfire)
-		psycho->starfire_cookie = starfire_hookup(psycho->upa_portid);
-	else
-		psycho->starfire_cookie = NULL;
-}
-
-extern void prom_pbm_ranges_init(int node, struct linux_pbm_info *pbm);
-extern void prom_pbm_intmap_init(int node, struct linux_pbm_info *pbm);
-
-/*
- * Poor man's PCI...
- */
-void __init sabre_init(int pnode)
-{
-	struct linux_prom64_registers pr_regs[2];
-	struct linux_psycho *sabre;
-	unsigned long ctrl;
-	int tsbsize, node, err;
-	u32 busrange[2];
-	u32 vdma[2];
-	u32 portid;
-	int bus;
-
-	sabre = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC);
-	if (!sabre) {
-		prom_printf("SABRE: Error, kmalloc(sabre) failed.\n");
-		prom_halt();
-	}
-
-	portid = prom_getintdefault(pnode, "upa-portid", 0xff);
-
-	memset(sabre, 0, sizeof(*sabre));
-
-	sabre->next = psycho_root;
-	psycho_root = sabre;
-
-	sabre->upa_portid = portid;
-	sabre->index = linux_num_psycho++;
-
-	/*
-	 * Map in SABRE register set and report the presence of this SABRE.
-	 */
-	err = prom_getproperty(pnode, "reg",
-			       (char *)&pr_regs[0], sizeof(pr_regs));
-	if(err == 0 || err == -1) {
-		prom_printf("SABRE: Error, cannot get U2P registers "
-			    "from PROM.\n");
-		prom_halt();
-	}
-
-	/*
-	 * First REG in property is base of entire SABRE register space.
-	 */
-	sabre->psycho_regs =
-			sparc_alloc_io((pr_regs[0].phys_addr & 0xffffffff),
-				       NULL, sizeof(struct psycho_regs),
-				       "SABRE Registers",
-				       (pr_regs[0].phys_addr >> 32), 0);
-	if(sabre->psycho_regs == NULL) {
-		prom_printf("SABRE: Error, cannot map SABRE main registers.\n");
-		prom_halt();
-	}
-
-	printk("PCI: Found SABRE, main regs at %p CTRL[%016lx]\n",
-	       sabre->psycho_regs, sabre->psycho_regs->control);
-#ifdef PROM_DEBUG
-	dprintf("PCI: Found SABRE, main regs at %p CTRL[%016lx]\n",
-		sabre->psycho_regs, sabre->psycho_regs->control);
-#endif
-
-	ctrl = sabre->psycho_regs->pci_a_control;
-	ctrl = (1UL << 36) | (1UL << 34) | (1UL << 21) | (1UL << 8) | 0x0fUL;
-	sabre->psycho_regs->pci_a_control = ctrl;
-
-	/* Now map in PCI config space for entire SABRE. */
-	sabre->pci_config_space =
-			sparc_alloc_io(((pr_regs[0].phys_addr & 0xffffffff)
-								+ 0x01000000),
-				       NULL, 0x01000000,
-				       "PCI Config Space",
-				       (pr_regs[0].phys_addr >> 32), 0);
-	if(sabre->pci_config_space == NULL) {
-		prom_printf("SABRE: Error, cannot map PCI config space.\n");
-		prom_halt();
-	}
-
-	/* Report some more info. */
-	printk("SABRE: PCI config space at %p\n", sabre->pci_config_space);
-#ifdef PROM_DEBUG
-	dprintf("SABRE: PCI config space at %p\n", sabre->pci_config_space);
-#endif
-
-	err = prom_getproperty(pnode, "virtual-dma",
-			       (char *)&vdma[0], sizeof(vdma));
-	if(err == 0 || err == -1) {
-		prom_printf("SABRE: Error, cannot get virtual-dma property "
-			    "from PROM.\n");
-		prom_halt();
-	}
-
-	switch(vdma[1]) {
-		case 0x20000000:
-			tsbsize = 8;
-			break;
-		case 0x40000000:
-			tsbsize = 16;
-			break;
-		case 0x80000000:
-			tsbsize = 32;
-			break;
-		default:
-			prom_printf("SABRE: strange virtual-dma size.\n");
-			prom_halt();
-	}
-
-	pci_dvma_offset = vdma[0];
-	psycho_iommu_init(sabre, tsbsize);
-
-	printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);
-#ifdef PROM_DEBUG
-	dprintf("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);
-#endif
-
-	err = prom_getproperty(pnode, "bus-range",
-				       (char *)&busrange[0], sizeof(busrange));
-	if(err == 0 || err == -1) {
-		prom_printf("SIMBA: Error, cannot get PCI bus-range "
-			    " from PROM.\n");
-		prom_halt();
-	}
-
-	sabre->pci_first_busno = busrange[0];
-	sabre->pci_last_busno = busrange[1];
-	sabre->pci_bus = &pci_root;
-
-	/*
-	 * Handle config space reads through any Simba on APB.
-	 */
-	for (bus = sabre->pci_first_busno; bus <= sabre->pci_last_busno; bus++)
-		bus2pbm[bus] = &sabre->pbm_A;
-
-	/*
-	 * Look for APB underneath.
-	 */
-	node = prom_getchild(pnode);
-	while ((node = prom_searchsiblings(node, "pci"))) {
-		struct linux_pbm_info *pbm;
-		char namebuf[128];
-
-		err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
-		if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err))
-			goto next_pci;
-
-		err = prom_getproperty(node, "bus-range",
-				       (char *)&busrange[0], sizeof(busrange));
-		if(err == 0 || err == -1) {
-			prom_printf("SIMBA: Error, cannot get PCI bus-range "
-				    " from PROM.\n");
-			prom_halt();
-		}
-
-		if (busrange[0] == 1)
-			pbm = &sabre->pbm_B;
-		else
-			pbm = &sabre->pbm_A;
-
-		pbm->parent = sabre;
-		pbm->IO_assignments = NULL;
-		pbm->MEM_assignments = NULL;
-		pbm->prom_node = node;
-
-		prom_getstring(node, "name", namebuf, sizeof(namebuf));
-		strcpy(pbm->prom_name, namebuf);
-
-		/* Now the ranges. */
-		prom_pbm_ranges_init(pnode, pbm);
-		prom_pbm_intmap_init(node, pbm);
-
-		pbm->pci_first_busno = busrange[0];
-		pbm->pci_last_busno = busrange[1];
-		memset(&pbm->pci_bus, 0, sizeof(struct pci_bus));
-
-		for (bus = pbm->pci_first_busno;
-		     bus <= pbm->pci_last_busno; bus++)
-			bus2pbm[bus] = pbm;
-
-	next_pci:
-		node = prom_getsibling(node);
-		if (!node)
-			break;
-	}
-}
-
-static __inline__ int
-apb_present(struct linux_psycho *psycho)
-{
-	return psycho->pci_bus ? 1 : 0;
-}
-
-void __init pcibios_init(void)
-{
-	struct linux_prom64_registers pr_regs[3];
-	struct linux_psycho *psycho;
-	char namebuf[128];
-	u32 portid;
-	int node;
-
-	printk("PCI: Probing for controllers.\n");
-#ifdef PROM_DEBUG
-	dprintf("PCI: Probing for controllers.\n");
-#endif
-
-	node = prom_getchild(prom_root_node);
-	while((node = prom_searchsiblings(node, "pci")) != 0) {
-		struct linux_psycho *search;
-		struct linux_pbm_info *pbm = NULL;
-		u32 busrange[2];
-		int err, is_pbm_a;
-
-		err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
-		if ((err > 0) && !strncmp(namebuf, "SUNW,sabre", err)) {
-			sabre_init(node);
-			goto next_pci;
-		}
-
-		portid = prom_getintdefault(node, "upa-portid", 0xff);
-		for(search = psycho_root; search; search = search->next) {
-			if(search->upa_portid == portid) {
-				psycho = search;
-
-				/* This represents _this_ instance, so it's
-				 * which ever one does _not_ have the prom node
-				 * info filled in yet.
-				 */
-				is_pbm_a = (psycho->pbm_A.prom_node == 0);
-				goto other_pbm;
-			}
-		}
-
-		psycho = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC);
-		if (!psycho) {
-			prom_printf("PSYCHO: Error, kmalloc(psycho) failed.\n");
-			prom_halt();
-		}
-		memset(psycho, 0, sizeof(*psycho));
-
-		psycho->next = psycho_root;
-		psycho_root = psycho;
-
-		psycho->upa_portid = portid;
-		psycho->index = linux_num_psycho++;
-
-		/*
-		 * Map in PSYCHO register set and report the presence
-		 * of this PSYCHO.
-		 */
-		err = prom_getproperty(node, "reg",
-				       (char *)&pr_regs[0], sizeof(pr_regs));
-		if(err == 0 || err == -1) {
-			prom_printf("PSYCHO: Error, cannot get U2P registers "
-				    "from PROM.\n");
-			prom_halt();
-		}
-
-		/*
-		 * Third REG in property is base of entire PSYCHO
-		 * register space.
-		 */
-		psycho->psycho_regs =
-			sparc_alloc_io((pr_regs[2].phys_addr & 0xffffffff),
-				       NULL, sizeof(struct psycho_regs),
-				       "PSYCHO Registers",
-				       (pr_regs[2].phys_addr >> 32), 0);
-		if(psycho->psycho_regs == NULL) {
-			prom_printf("PSYCHO: Error, cannot map PSYCHO "
-				    "main registers.\n");
-			prom_halt();
-		}
-
-		printk("PCI: Found PSYCHO, main regs at %p\n",
-		       psycho->psycho_regs);
-#ifdef PROM_DEBUG
-		dprintf("PCI: Found PSYCHO, main regs at %p\n",
-			psycho->psycho_regs);
-#endif
-
-		psycho->psycho_regs->irq_retry = 0xff;
-
-		/* Now map in PCI config space for entire PSYCHO. */
-		psycho->pci_config_space =
-			sparc_alloc_io(((pr_regs[2].phys_addr & 0xffffffff)
-								+ 0x01000000),
-				       NULL, 0x01000000,
-				       "PCI Config Space",
-				       (pr_regs[2].phys_addr >> 32), 0);
-		if(psycho->pci_config_space == NULL) {
-			prom_printf("PSYCHO: Error, cannot map PCI config space.\n");
-			prom_halt();
-		}
-
-		/* Report some more info. */
-		printk("PSYCHO: PCI config space at %p\n",
-		       psycho->pci_config_space);
-#ifdef PROM_DEBUG
-		dprintf("PSYCHO: PCI config space at %p\n",
-			psycho->pci_config_space);
-#endif
-
-		pci_dvma_offset = 0x80000000UL;
-		psycho_iommu_init(psycho, 32);
-
-		is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
-
-		/* Enable arbitration for all PCI slots. */
-		psycho->psycho_regs->pci_a_control |= PSYCHO_PCICTRL_AEN;
-		psycho->psycho_regs->pci_b_control |= PSYCHO_PCICTRL_AEN;
-
-		/* Disable DMA write / PIO rd synchronization on both
-		 * PCI bus segments.
-		 */
-		psycho->psycho_regs->pci_a_diag |= PSYCHO_PCIDIAG_DDWSYNC;
-		psycho->psycho_regs->pci_b_diag |= PSYCHO_PCIDIAG_DDWSYNC;
-
-	other_pbm:
-		if(is_pbm_a)
-			pbm = &psycho->pbm_A;
-		else
-			pbm = &psycho->pbm_B;
-
-		pbm->parent = psycho;
-		pbm->IO_assignments = NULL;
-		pbm->MEM_assignments = NULL;
-		pbm->prom_node = node;
-
-		prom_getstring(node, "name", namebuf, sizeof(namebuf));
-		strcpy(pbm->prom_name, namebuf);
-
-		/* Now the ranges. */
-		prom_pbm_ranges_init(node, pbm);
-		prom_pbm_intmap_init(node, pbm);
-
-		/* Finally grab the pci bus root array for this pbm after
-		 * having found the bus range existing under it.
-		 */
-		err = prom_getproperty(node, "bus-range",
-				       (char *)&busrange[0], sizeof(busrange));
-		if(err == 0 || err == -1) {
-			prom_printf("PSYCHO: Error, cannot get PCI bus range.\n");
-			prom_halt();
-		}
-		pbm->pci_first_busno = busrange[0];
-		pbm->pci_last_busno = busrange[1];
-		memset(&pbm->pci_bus, 0, sizeof(struct pci_bus));
-
-	next_pci:
-		node = prom_getsibling(node);
-		if(!node)
-			break;
-	}
-}
-
-int pcibios_present(void)
-{
-	return psycho_root != NULL;
-}
-
-static inline struct pci_vma *pci_find_vma(struct linux_pbm_info *pbm,
-					   unsigned long start,
-					   unsigned int offset, int io)
-{
-	struct pci_vma *vp = (io ? pbm->IO_assignments : pbm->MEM_assignments);
-
-	while (vp) {
-		if (offset && (vp->offset != offset))
-			goto next;
-		if (vp->end >= start)
-			break;
-	next:
-		vp = vp->next;
-	}
-	return vp;
-}
-
-static inline void pci_add_vma(struct linux_pbm_info *pbm, struct pci_vma *new, int io)
-{
-	struct pci_vma *vp = (io ? pbm->IO_assignments : pbm->MEM_assignments);
-
-	if(!vp) {
-		new->next = NULL;
-		if(io)
-			pbm->IO_assignments = new;
-		else
-			pbm->MEM_assignments = new;
-	} else {
-		struct pci_vma *prev = NULL;
-
-		while(vp && (vp->end < new->end)) {
-			prev = vp;
-			vp = vp->next;
-		}
-		new->next = vp;
-		if(!prev) {
-			if(io)
-				pbm->IO_assignments = new;
-			else
-				pbm->MEM_assignments = new;
-		} else {
-			prev->next = new;
-		}
-
-		/* Check for programming errors. */
-		if(vp &&
-		   ((vp->start >= new->start && vp->start < new->end) ||
-		    (vp->end >= new->start && vp->end < new->end))) {
-			prom_printf("pci_add_vma: Wheee, overlapping %s PCI vma's\n",
-				    io ? "IO" : "MEM");
-			prom_printf("pci_add_vma: vp[%016lx:%016lx] "
-				    "new[%016lx:%016lx]\n",
-				    vp->start, vp->end,
-				    new->start, new->end);
-		}
-	}
-}
-
-static inline struct pci_vma *pci_vma_alloc(void)
-{
-	return kmalloc(sizeof(struct pci_vma), GFP_ATOMIC);
-}
-
-static inline struct pcidev_cookie *pci_devcookie_alloc(void)
-{
-	return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC);
-}
-
-
-static void __init
-pbm_reconfigure_bridges(struct linux_pbm_info *pbm, unsigned char bus)
-{
-	unsigned int devfn, l, class;
-	unsigned char hdr_type = 0;
-	int is_multi = 0;
-
-	for (devfn = 0; devfn < 0xff; ++devfn) {
-		if (PCI_FUNC(devfn) != 0 && is_multi == 0) {
-			/* not a multi-function device */
-			continue;
-		}
-		pbm_read_config_byte(pbm, bus, devfn,
-				     PCI_HEADER_TYPE, &hdr_type);
-		if (PCI_FUNC(devfn) == 0)
-			is_multi = hdr_type & 0x80;
-
-		/* Check if there is anything here. */
-		pbm_read_config_dword(pbm, bus, devfn, PCI_VENDOR_ID, &l);
-		if (l == 0xffffffff || l == 0x00000000 ||
-		    l == 0x0000ffff || l == 0xffff0000) {
-			is_multi = 0;
-			continue;
-		}
-
-		/* See if this is a bridge device. */
-		pbm_read_config_dword(pbm, bus, devfn,
-				      PCI_CLASS_REVISION, &class);
-
-		if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
-			unsigned int buses;
-
-			pbm_read_config_dword(pbm, bus, devfn,
-					      PCI_PRIMARY_BUS, &buses);
-
-			/*
-			 * First reconfigure everything underneath the bridge.
-			 */
-			pbm_reconfigure_bridges(pbm, (buses >> 8) & 0xff);
-
-			/*
-			 * Unconfigure this bridges bus numbers,
-			 * pci_scan_bus() will fix this up properly.
-			 */
-			buses &= 0xff000000;
-			pbm_write_config_dword(pbm, bus, devfn,
-					       PCI_PRIMARY_BUS, buses);
-		}
-	}
-}
-
-static void __init pbm_fixup_busno(struct linux_pbm_info *pbm, unsigned char bus)
-{
-	unsigned int nbus;
-
-	/*
-	 * First, reconfigure all bridge devices underneath this pbm.
-	 */
-	pbm_reconfigure_bridges(pbm, pbm->pci_first_busno);
-
-	/*
-	 * Now reconfigure the pbm to it's new bus number and set up
-	 * our bus2pbm mapping for this pbm.
-	 */
-	nbus = pbm->pci_last_busno - pbm->pci_first_busno;
-
-	pbm_write_config_byte(pbm, pbm->pci_first_busno, 0, 0x40, bus);
-
-	pbm->pci_first_busno = bus;
-	pbm_write_config_byte(pbm, bus, 0, 0x41, 0xff);
-
-	do {
-		bus2pbm[bus++] = pbm;
-	} while (nbus--);
-}
-
-static void __init apb_init(struct linux_psycho *sabre)
-{
-	struct pci_dev *pdev;
-	unsigned short stmp;
-	unsigned int itmp;
-
-#if 0
-	for(pdev = pci_devices; pdev; pdev = pdev->next) {
-		if(pdev->vendor == PCI_VENDOR_ID_SUN &&
-		   pdev->device == PCI_DEVICE_ID_SUN_SABRE) {
-			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
-			break;
-		}
-	}
-#endif
-	for (pdev = sabre->pci_bus->devices; pdev; pdev = pdev->sibling) {
-		if (pdev->vendor == PCI_VENDOR_ID_SUN &&
-		    pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
-			pci_read_config_word(pdev, PCI_COMMAND, &stmp);
-			stmp |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
-				PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY |
-				PCI_COMMAND_IO;
-			pci_write_config_word(pdev, PCI_COMMAND, stmp);
-
-			/* Status register bits are "write 1 to clear". */
-			pci_write_config_word(pdev, PCI_STATUS, 0xffff);
-			pci_write_config_word(pdev, PCI_SEC_STATUS, 0xffff);
-
-			pci_read_config_word(pdev, PCI_BRIDGE_CONTROL, &stmp);
-			stmp = PCI_BRIDGE_CTL_MASTER_ABORT |
-			       PCI_BRIDGE_CTL_SERR |
-			       PCI_BRIDGE_CTL_PARITY;
-			pci_write_config_word(pdev, PCI_BRIDGE_CONTROL, stmp);
-
-			pci_read_config_dword(pdev, APB_PCI_CONTROL_HIGH, &itmp);
-			itmp = APB_PCI_CTL_HIGH_SERR |
-			       APB_PCI_CTL_HIGH_ARBITER_EN;
-			pci_write_config_dword(pdev, APB_PCI_CONTROL_HIGH, itmp);
-
-			/* Systems with SIMBA are usually workstations, so
-			 * we configure to park to SIMBA not to the previous
-			 * bus owner.
-			 */
-			pci_read_config_dword(pdev, APB_PCI_CONTROL_LOW, &itmp);
-			itmp = APB_PCI_CTL_LOW_ERRINT_EN | 0x0f;
-			pci_write_config_dword(pdev, APB_PCI_CONTROL_LOW, itmp);
-#if 0
-			/* Don't mess with the retry limit and PIO/DMA latency
-			 * timer settings.  But do set primary and secondary
-			 * latency timers.
-			 */
-			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
-			pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64);
-#endif
-		}
-	}
-}
-
-extern struct pci_bus pci_root;
-extern struct pci_dev *pci_devices;
-static struct pci_dev **pci_last_dev_p = &pci_devices;
-extern int pci_reverse;
-
-extern void pci_namedevice(struct pci_dev *);
-
-static void __init sparc64_pci_read_bases(struct pci_dev *dev, unsigned int howmany)
-{
-	unsigned int reg;
-	u32 l;
-
-	for(reg=0; reg < howmany; reg++) {
-		struct resource *res = dev->resource + reg;
-		unsigned long mask;
-		unsigned int newval, size;
-
-		res->name = dev->name;
-		pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &l);
-		if (l == 0xffffffff)
-			continue;
-
-		pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), 0xffffffff);
-		pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &newval);
-		pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), l);
-
-		mask = PCI_BASE_ADDRESS_MEM_MASK;
-		if (l & PCI_BASE_ADDRESS_SPACE_IO)
-			mask = PCI_BASE_ADDRESS_IO_MASK;
-
-		newval &= mask;
-		if (!newval)
-			continue;
-
-		res->start = l & mask;
-		res->flags = l & ~mask;
-
-		size = 1;
-		do {
-			size <<= 1;
-		} while (!(size & newval));
-
-		/* 64-bit memory? */
-		if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
-		    == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
-		    	unsigned int high;
-			reg++;
-			pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), &high);
-			if (high)
-				res->start |= ((unsigned long) high) << 32;
-		}
-		res->end = res->start + size - 1;
-	}
-}
-
-static unsigned int __init sparc64_pci_scan_bus(struct pci_bus *bus)
-{
-	unsigned int devfn, l, max, class;
-	unsigned char cmd, irq, tmp, hdr_type, is_multi = 0;
-	struct pci_dev *dev, **bus_last;
-	struct pci_bus *child;
-
-	bus_last = &bus->devices;
-	max = bus->secondary;
-	for (devfn = 0; devfn < 0xff; ++devfn) {
-		if (PCI_FUNC(devfn) && !is_multi) {
-			/* not a multi-function device */
-			continue;
-		}
-		if (pcibios_read_config_byte(bus->number, devfn, PCI_HEADER_TYPE, &hdr_type))
-			continue;
-		if (!PCI_FUNC(devfn))
-			is_multi = hdr_type & 0x80;
-
-		if (pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l) ||
-		    /* some broken boards return 0 if a slot is empty: */
-		    l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000)
-			continue;
-
-		dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
-		if(dev==NULL)
-		{
-			printk(KERN_ERR "pci: out of memory.\n");
-			continue;
-		}
-		memset(dev, 0, sizeof(*dev));
-		dev->bus = bus;
-		dev->devfn  = devfn;
-		dev->vendor = l & 0xffff;
-		dev->device = (l >> 16) & 0xffff;
-		pci_namedevice(dev);
-
-		/* non-destructively determine if device can be a master: */
-		pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, &cmd);
-		pcibios_write_config_byte(bus->number, devfn, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
-		pcibios_read_config_byte(bus->number, devfn, PCI_COMMAND, &tmp);
-		dev->master = ((tmp & PCI_COMMAND_MASTER) != 0);
-		pcibios_write_config_byte(bus->number, devfn, PCI_COMMAND, cmd);
-
-		pcibios_read_config_dword(bus->number, devfn, PCI_CLASS_REVISION, &class);
-		class >>= 8;				    /* upper 3 bytes */
-		dev->class = class;
-		class >>= 8;
-		dev->hdr_type = hdr_type;
-
-		switch (hdr_type & 0x7f) {		    /* header type */
-		case PCI_HEADER_TYPE_NORMAL:		    /* standard header */
-			if (class == PCI_CLASS_BRIDGE_PCI)
-				goto bad;
-			/*
-			 * If the card generates interrupts, read IRQ number
-			 * (some architectures change it during pcibios_fixup())
-			 */
-			pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq);
-			if (irq)
-				pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq);
-			dev->irq = irq;
-			sparc64_pci_read_bases(dev, 6);
-			pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l);
-			dev->rom_address = (l == 0xffffffff) ? 0 : l;
-			break;
-		case PCI_HEADER_TYPE_BRIDGE:		    /* bridge header */
-			if (class != PCI_CLASS_BRIDGE_PCI)
-				goto bad;
-			sparc64_pci_read_bases(dev, 2);
-			pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l);
-			dev->rom_address = (l == 0xffffffff) ? 0 : l;
-			break;
-		case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */
-			if (class != PCI_CLASS_BRIDGE_CARDBUS)
-				goto bad;
-			sparc64_pci_read_bases(dev, 1);
-			break;
-		default:				    /* unknown header */
-		bad:
-			printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n",
-			       bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type);
-			continue;
-		}
-
-		/*
-		 * Put it into the global PCI device chain. It's used to
-		 * find devices once everything is set up.
-		 */
-		if (!pci_reverse) {
-			*pci_last_dev_p = dev;
-			pci_last_dev_p = &dev->next;
-		} else {
-			dev->next = pci_devices;
-			pci_devices = dev;
-		}
-
-		/*
-		 * Now insert it into the list of devices held
-		 * by the parent bus.
-		 */
-		*bus_last = dev;
-		bus_last = &dev->sibling;
-	}
-
-	/*
-	 * After performing arch-dependent fixup of the bus, look behind
-	 * all PCI-to-PCI bridges on this bus.
-	 */
-	pcibios_fixup_bus(bus);
-	for(dev=bus->devices; dev; dev=dev->sibling)
-		/*
-		 * If it's a bridge, scan the bus behind it.
-		 */
-		if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-			unsigned int buses;
-			unsigned int devfn = dev->devfn;
-			unsigned short cr;
-
-			/*
-			 * Insert it into the tree of buses.
-			 */
-			child = kmalloc(sizeof(*child), GFP_ATOMIC);
-			if(child==NULL)
-			{
-				printk(KERN_ERR "pci: out of memory for bridge.\n");
-				continue;
-			}
-			memset(child, 0, sizeof(*child));
-			child->next = bus->children;
-			bus->children = child;
-			child->self = dev;
-			child->parent = bus;
-
-			/*
-			 * Set up the primary, secondary and subordinate
-			 * bus numbers.
-			 */
-			child->number = child->secondary = ++max;
-			child->primary = bus->secondary;
-			child->subordinate = 0xff;
-			/*
-			 * Clear all status bits and turn off memory,
-			 * I/O and master enables.
-			 */
-			pcibios_read_config_word(bus->number, devfn, PCI_COMMAND, &cr);
-			pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, 0x0000);
-			pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff);
-			/*
-			 * Read the existing primary/secondary/subordinate bus
-			 * number configuration to determine if the PCI bridge
-			 * has already been configured by the system.  If so,
-			 * do not modify the configuration, merely note it.
-			 */
-			pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses);
-			if ((buses & 0xFFFFFF) != 0)
-			  {
-			    unsigned int cmax;
-
-			    child->primary = buses & 0xFF;
-			    child->secondary = (buses >> 8) & 0xFF;
-			    child->subordinate = (buses >> 16) & 0xFF;
-			    child->number = child->secondary;
-			    cmax = sparc64_pci_scan_bus(child);
-			    if (cmax > max) max = cmax;
-			  }
-			else
-			  {
-			    /*
-			     * Configure the bus numbers for this bridge:
-			     */
-			    buses &= 0xff000000;
-			    buses |=
-			      (((unsigned int)(child->primary)     <<  0) |
-			       ((unsigned int)(child->secondary)   <<  8) |
-			       ((unsigned int)(child->subordinate) << 16));
-			    pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);
-			    /*
-			     * Now we can scan all subordinate buses:
-			     */
-			    max = sparc64_pci_scan_bus(child);
-			    /*
-			     * Set the subordinate bus number to its real
-			     * value:
-			     */
-			    child->subordinate = max;
-			    buses = (buses & 0xff00ffff)
-			      | ((unsigned int)(child->subordinate) << 16);
-			    pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);
-			  }
-			pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr);
-		}
-
-	/*
-	 * We've scanned the bus and so we know all about what's on
-	 * the other side of any bridges that may be on this bus plus
-	 * any devices.
-	 *
-	 * Return how far we've got finding sub-buses.
-	 */
-	return max;
-}
-
-static void __init sabre_probe(struct linux_psycho *sabre)
-{
-	struct pci_bus *pbus = sabre->pci_bus;
-	static unsigned char busno = 0;
-
-	pbus->number = pbus->secondary = busno;
-	pbus->sysdata = sabre;
-
-	pbus->subordinate = sparc64_pci_scan_bus(pbus);
-	busno = pbus->subordinate + 1;
-
-	for(pbus = pbus->children; pbus; pbus = pbus->next) {
-		if (pbus->number == sabre->pbm_A.pci_first_busno)
-			memcpy(&sabre->pbm_A.pci_bus, pbus, sizeof(*pbus));
-		if (pbus->number == sabre->pbm_B.pci_first_busno)
-			memcpy(&sabre->pbm_B.pci_bus, pbus, sizeof(*pbus));
-	}
-
-	apb_init(sabre);
-}
-
-
-static void __init pbm_probe(struct linux_pbm_info *pbm)
-{
-	static struct pci_bus *pchain = NULL;
-	struct pci_bus *pbus = &pbm->pci_bus;
-	static unsigned char busno = 0;
-
-	/* PSYCHO PBM's include child PCI bridges in bus-range property,
-	 * but we don't scan each of those ourselves, Linux generic PCI
-	 * probing code will find child bridges and link them into this
-	 * pbm's root PCI device hierarchy.
-	 */
-
-	pbus->number = pbus->secondary = busno;
-	pbus->sysdata = pbm;
-
-	pbm_fixup_busno(pbm, busno);
-
-	pbus->subordinate = sparc64_pci_scan_bus(pbus);
-
-	/*
-	 * Set the maximum subordinate bus of this pbm.
-	 */
-	pbm->pci_last_busno = pbus->subordinate;
-	pbm_write_config_byte(pbm, busno, 0, 0x41, pbm->pci_last_busno);
-
-	busno = pbus->subordinate + 1;
-
-	/*
-	 * Fixup the chain of primary PCI busses.
-	 */
-	if (pchain) {
-		pchain->next = &pbm->pci_bus;
-		pchain = pchain->next;
-	} else {
-		pchain = &pci_root;
-		memcpy(pchain, &pbm->pci_bus, sizeof(pci_root));
-	}
-}
-
-static int __init pdev_to_pnode_sibtraverse(struct linux_pbm_info *pbm,
-					    struct pci_dev *pdev,
-					    int pnode)
-{
-	struct linux_prom_pci_registers pregs[PROMREG_MAX];
-	int node;
-	int err;
-
-	node = prom_getchild(pnode);
-	while (node) {
-
-		err = prom_getproperty(node, "reg", (char *)&pregs[0], sizeof(pregs));
-		if(err != 0 && err != -1) {
-			u32 devfn = (pregs[0].phys_hi >> 8) & 0xff;
-
-			if(devfn == pdev->devfn)
-				return node; /* Match */
-		}
-
-		node = prom_getsibling(node);
-	}
-	return 0;
-}
-
-static void __init pdev_cookie_fillin(struct linux_pbm_info *pbm,
-				      struct pci_dev *pdev, int pnode)
-{
-	struct pcidev_cookie *pcp;
-	int node;
-
-	node = pdev_to_pnode_sibtraverse(pbm, pdev, pnode);
-	if(node == 0)
-		node = -1;
-	pcp = pci_devcookie_alloc();
-	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
-}
-
-static void __init fill_in_pbm_cookies(struct pci_bus *pbus,
-				       struct linux_pbm_info *pbm,
-				       int node)
-{
-	struct pci_dev *pdev;
-
-	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, node);
-
-	for(pbus = pbus->children; pbus; pbus = pbus->next) {
-		struct pcidev_cookie *pcp = pbus->self->sysdata;
-		fill_in_pbm_cookies(pbus, pbm, pcp->prom_node);
-	}
-}
-
-static void __init sabre_cookie_fillin(struct linux_psycho *sabre)
-{
-	struct pci_bus *pbus = sabre->pci_bus;
-
-	for(pbus = pbus->children; pbus; pbus = pbus->next) {
-		if (pbus->number == sabre->pbm_A.pci_first_busno)
-			pdev_cookie_fillin(&sabre->pbm_A, pbus->self,
-					   sabre->pbm_A.prom_node);
-		else if (pbus->number == sabre->pbm_B.pci_first_busno)
-			pdev_cookie_fillin(&sabre->pbm_B, pbus->self,
-					   sabre->pbm_B.prom_node);
-	}
-}
-
-/* Walk PROM device tree under PBM, looking for 'assigned-address'
- * properties, and recording them in pci_vma's linked in via
- * PBM->assignments.
- */
-static int __init gimme_ebus_assignments(int node, struct linux_prom_pci_registers *aregs)
-{
-	struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX];
-	int err, iter;
-
-	err = prom_getproperty(node, "ranges", (char *)&erng[0], sizeof(erng));
-	if(err == 0 || err == -1) {
-		prom_printf("EBUS: fatal error, no range property.\n");
-		prom_halt();
-	}
-	err = (err / sizeof(struct linux_prom_ebus_ranges));
-	for(iter = 0; iter < err; iter++) {
-		struct linux_prom_ebus_ranges *ep = &erng[iter];
-		struct linux_prom_pci_registers *ap = &aregs[iter];
-
-		ap->phys_hi = ep->parent_phys_hi;
-		ap->phys_mid = ep->parent_phys_mid;
-		ap->phys_lo = ep->parent_phys_lo;
-
-		ap->size_hi = 0;
-		ap->size_lo = ep->size;
-	}
-	return err;
-}
-
-static void __init assignment_process(struct linux_pbm_info *pbm, int node)
-{
-	struct linux_prom_pci_registers aregs[PROMREG_MAX];
-	char pname[256];
-	int err, iter, numa;
-
-	err = prom_getproperty(node, "name", (char *)&pname[0], sizeof(pname));
-	if (err > 0)
-		pname[err] = 0;
-#ifdef FIXUP_VMA_DEBUG
-	dprintf("%s: %s\n", __FUNCTION__, err > 0 ? pname : "???");
-#endif
-	if(strcmp(pname, "ebus") == 0) {
-		numa = gimme_ebus_assignments(node, &aregs[0]);
-	} else {
-		err = prom_getproperty(node, "assigned-addresses",
-				       (char *)&aregs[0], sizeof(aregs));
-
-		/* No assignments, nothing to do. */
-		if(err == 0 || err == -1)
-			return;
-
-		numa = (err / sizeof(struct linux_prom_pci_registers));
-	}
-
-	for(iter = 0; iter < numa; iter++) {
-		struct linux_prom_pci_registers *ap = &aregs[iter];
-		struct pci_vma *vp;
-		int space, breg, io;
-
-		space = (ap->phys_hi >> 24) & 3;
-		if(space != 1 && space != 2)
-			continue;
-		io = (space == 1);
-
-		breg = (ap->phys_hi & 0xff);
-
-		vp = pci_vma_alloc();
-
-		/* XXX Means we don't support > 32-bit range of
-		 * XXX PCI MEM space, PSYCHO/PBM does not support it
-		 * XXX either due to it's layout so...
-		 */
-		vp->start = ap->phys_lo;
-		vp->end = vp->start + ap->size_lo - 1;
-		vp->offset = (ap->phys_hi & 0xffffff);
-
-		pci_add_vma(pbm, vp, io);
-
-#ifdef FIXUP_VMA_DEBUG
-		dprintf("%s: BaseReg %02x", pname, breg);
-		dprintf(" %s vma [%08x,%08x]\n",
-			io ? "I/O" : breg == PCI_ROM_ADDRESS ? "ROM" : "MEM", vp->start, vp->end);
-#endif
-	}
-}
-
-static void __init assignment_walk_siblings(struct linux_pbm_info *pbm, int node)
-{
-	while(node) {
-		int child = prom_getchild(node);
-		if(child)
-			assignment_walk_siblings(pbm, child);
-
-		assignment_process(pbm, node);
-
-		node = prom_getsibling(node);
-	}
-}
-
-static inline void record_assignments(struct linux_pbm_info *pbm)
-{
-	struct pci_vma *vp;
-
-	if (apb_present(pbm->parent)) {
-		/*
-		 * Disallow anything that is not in our IO/MEM map on SIMBA.
-		 */
-		struct pci_bus *pbus = pbm->parent->pci_bus;
-		struct pci_dev *pdev;
-		unsigned char map;
-		int bit;
-
-		for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
-			struct pcidev_cookie *pcp = pdev->sysdata;
-			if (!pcp)
-				continue;
-			if (pcp->pbm == pbm)
-				break;
-		}
-
-		if (!pdev) {
-			prom_printf("record_assignments: no pdev for PBM\n");
-			prom_halt();
-		}
-
-		pci_read_config_byte(pdev, APB_IO_ADDRESS_MAP, &map);
-#ifdef FIXUP_VMA_DEBUG
-		dprintf("%s: IO   %02x\n", __FUNCTION__, map);
-#endif
-		for (bit = 0; bit < 8; bit++) {
-			if (!(map & (1 << bit))) {
-				vp = pci_vma_alloc();
-				vp->start = (bit << 21);
-				vp->end = vp->start + (1 << 21) - 1;
-				vp->offset = 0;
-				pci_add_vma(pbm, vp, 1);
-#ifdef FIXUP_VMA_DEBUG
-				dprintf("%s: IO   prealloc vma [%08x,%08x]\n",
-					__FUNCTION__, vp->start, vp->end);
-#endif
-			}
-		}
-		pci_read_config_byte(pdev, APB_MEM_ADDRESS_MAP, &map);
-#ifdef FIXUP_VMA_DEBUG
-		dprintf("%s: MEM  %02x\n", __FUNCTION__, map);
-#endif
-		for (bit = 0; bit < 8; bit++) {
-			if (!(map & (1 << bit))) {
-				vp = pci_vma_alloc();
-				vp->start = (bit << 29);
-				vp->end = vp->start + (1 << 29) - 1;
-				vp->offset = 0;
-				pci_add_vma(pbm, vp, 0);
-#ifdef FIXUP_VMA_DEBUG
-				dprintf("%s: MEM  prealloc vma [%08x,%08x]\n",
-					__FUNCTION__, vp->start, vp->end);
-#endif
-			}
-		}
-	}
-
-	assignment_walk_siblings(pbm, prom_getchild(pbm->prom_node));
-
-	/*
-	 * Protect ISA IO space from being used.
-	 */
-	vp = pci_find_vma(pbm, 0, 0, 1);
-	if (!vp || 0x400 <= vp->start) {
-		vp = pci_vma_alloc();
-		vp->start = 0;
-		vp->end = vp->start + 0x400 - 1;
-		vp->offset = 0;
-		pci_add_vma(pbm, vp, 1);
-	}
-
-#ifdef FIXUP_VMA_DEBUG
-	dprintf("PROM IO assignments for PBM %s:\n",
-		pbm == &pbm->parent->pbm_A ? "A" : "B");
-	vp = pbm->IO_assignments;
-	while (vp) {
-		dprintf("  [%08x,%08x] (%s)\n", vp->start, vp->end,
-			vp->offset ? "Register" : "Unmapped");
-		vp = vp->next;
-	}
-	dprintf("PROM MEM assignments for PBM %s:\n",
-		pbm == &pbm->parent->pbm_A ? "A" : "B");
-	vp = pbm->MEM_assignments;
-	while (vp) {
-		dprintf("  [%08x,%08x] (%s)\n", vp->start, vp->end,
-			vp->offset ? "Register" : "Unmapped");
-		vp = vp->next;
-	}
-#endif
-}
-
-static void __init fixup_regs(struct pci_dev *pdev,
-			      struct linux_pbm_info *pbm,
-			      struct linux_prom_pci_registers *pregs,
-			      int nregs,
-			      struct linux_prom_pci_registers *assigned,
-			      int numaa)
-{
-	int preg, rng;
-	int IO_seen = 0;
-	int MEM_seen = 0;
-
-	for(preg = 0; preg < nregs; preg++) {
-		struct linux_prom_pci_registers *ap = NULL;
-		int bustype = (pregs[preg].phys_hi >> 24) & 0x3;
-		int bsreg, brindex;
-		unsigned int rtmp;
-		u64 pci_addr, pci_size;
-
-		if(bustype == 0) {
-			/* Config space cookie, nothing to do. */
-			if(preg != 0)
-				printk("%s %02x.%02x [%04x,%04x]: "
-				       "strange, config space not 0\n",
-				       __FUNCTION__,
-				       pdev->bus->number, pdev->devfn,
-				       pdev->vendor, pdev->device);
-			continue;
-		} else if(bustype == 3) {
-			/* XXX add support for this... */
-			printk("%s %02x.%02x [%04x,%04x]: "
-			       "Warning, ignoring 64-bit PCI memory space, "
-			       "tell Eddie C. Dost (ecd@skynet.be).\n",
-			       __FUNCTION__,
-			       pdev->bus->number, pdev->devfn,
-			       pdev->vendor, pdev->device);
-			continue;
-		}
-
-		bsreg = (pregs[preg].phys_hi & 0xff);
-
-		/* Sanity */
-		if((bsreg < PCI_BASE_ADDRESS_0) ||
-		   ((bsreg > (PCI_BASE_ADDRESS_5 + 4)) && (bsreg != PCI_ROM_ADDRESS)) ||
-		   (bsreg & 3)) {
-			printk("%s %02x.%02x [%04x:%04x]: "
-			       "Warning, ignoring bogus basereg [%x]\n",
-			       __FUNCTION__, pdev->bus->number, pdev->devfn,
-			       pdev->vendor, pdev->device, bsreg);
-			printk("  PROM reg: %08x.%08x.%08x %08x.%08x\n",
-			       pregs[preg].phys_hi, pregs[preg].phys_mid,
-			       pregs[preg].phys_lo, pregs[preg].size_hi,
-			       pregs[preg].size_lo);
-			continue;
-		}
-
-		brindex = (bsreg - PCI_BASE_ADDRESS_0) >> 2;
-		if(numaa) {
-			int r;
-
-			for(r = 0; r < numaa; r++) {
-				int abreg;
-
-				abreg = (assigned[r].phys_hi & 0xff);
-				if(abreg == bsreg) {
-					ap = &assigned[r];
-					break;
-				}
-			}
-		}
-
-		/* Now construct UPA physical address. */
-		pci_addr  = (((u64)pregs[preg].phys_mid) << 32UL);
-		pci_addr |= (((u64)pregs[preg].phys_lo));
-		pci_size  = (((u64)pregs[preg].size_hi) << 32UL);
-		pci_size |= (((u64)pregs[preg].size_lo));
-
-		if(ap) {
-			pci_addr += ((u64)ap->phys_lo);
-			pci_addr += (((u64)ap->phys_mid) << 32UL);
-		}
-
-		/* Final step, apply PBM range. */
-		for(rng = 0; rng < pbm->num_pbm_ranges; rng++) {
-			struct linux_prom_pci_ranges *rngp = &pbm->pbm_ranges[rng];
-			int space = (rngp->child_phys_hi >> 24) & 3;
-
-			if(space == bustype) {
-				pci_addr += ((u64)rngp->parent_phys_lo);
-				pci_addr += (((u64)rngp->parent_phys_hi) << 32UL);
-				break;
-			}
-		}
-		if(rng == pbm->num_pbm_ranges) {
-			/* AIEEE */
-			prom_printf("fixup_doit: YIEEE, cannot find PBM ranges\n");
-		}
-		if (bsreg == PCI_ROM_ADDRESS) {
-			pdev->rom_address = (unsigned long)__va(pci_addr);
-			pdev->rom_address &= ~1UL;
-
-			/*
-			 * Disable access to the ROM.
-			 */
-			pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &rtmp);
-			pci_write_config_dword(pdev, PCI_ROM_ADDRESS, rtmp & ~1);
-		} else {
-			struct resource *root, *rp;
-
-			rp = &pdev->resource[brindex];
-
-			pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0 + (brindex * 4), &rtmp);
-			if (rtmp & 0x1)
-				rtmp &= 0x1;
-			else
-				rtmp &= 0xf;
-
-			rp->name = pdev->name;
-			rp->start = (unsigned long)__va(pci_addr);
-			rp->end = rp->start + pci_size - 1;
-
-			/* Keep track of what we've seen so far. */
-			if(rtmp & 0x1) {
-				IO_seen = 1;
-				root = &ioport_resource;
-			} else {
-				MEM_seen = 1;
-				root = &iomem_resource;
-			}
-			rp->flags = rtmp;
-			request_resource(root, rp);
-		}
-	}
-
-	/* Now handle assignments PROM did not take care of. */
-	if(nregs) {
-		unsigned int rtmp, ridx;
-		unsigned int offset, base;
-		struct pci_vma *vp;
-		u64 pci_addr;
-		int breg;
-
-		for(breg = PCI_BASE_ADDRESS_0; breg <= PCI_BASE_ADDRESS_5; breg += 4) {
-			struct resource *rp;
-			int io;
-
-			ridx = ((breg - PCI_BASE_ADDRESS_0) >> 2);
-			rp = &pdev->resource[ridx];
-			base = (unsigned int)rp->start;
-
-			/* Already handled? */
-			if(rp->start > PAGE_OFFSET)
-				continue;
-
-			pci_read_config_dword(pdev, breg, &rtmp);
-			io = (rtmp & 0x1);
-			offset = (pdev->bus->number << 16) | (pdev->devfn << 8) | breg;
-			vp = pci_find_vma(pbm, base, offset, io);
-			if(!vp || vp->start > base) {
-				unsigned int size, new_base;
-
-				pci_write_config_dword(pdev, breg, 0xffffffff);
-				pci_read_config_dword(pdev, breg, &size);
-
-				if(io)
-					size &= ~0x1;
-				else
-					size &= ~0xf;
-
-				size = (~(size) + 1);
-				if(!size)
-					continue;
-
-				new_base = 0;
-				for(vp = pci_find_vma(pbm, new_base, 0, io); ;
-				    vp = vp->next) {
-					if(!vp || new_base + size <= vp->start)
-						break;
-					new_base = (vp->end + (size - 1)) & ~(size-1);
-				}
-				if(vp && (new_base + size > vp->start)) {
-					prom_printf("PCI: Impossible full %s space.\n",
-						    (io ? "IO" : "MEM"));
-					prom_halt();
-				}
-				vp = pci_vma_alloc();
-				vp->start = new_base;
-				vp->end = vp->start + size - 1;
-				vp->offset = offset;
-
-				pci_add_vma(pbm, vp, io);
-
-#ifdef FIXUP_VMA_DEBUG
-				dprintf("%02x.%02x.%x: BaseReg %02x",
-					pdev->bus->number,
-					PCI_SLOT(pdev->devfn),
-					PCI_FUNC(pdev->devfn),
-					breg);
-				dprintf(" %s vma [%08x,%08x]\n",
-					io ? "I/O" : breg == PCI_ROM_ADDRESS ? "ROM" : "MEM", vp->start, vp->end);
-#endif
-				rtmp = new_base;
-				pci_read_config_dword(pdev, breg, &base);
-				if(io)
-					rtmp |= (base & ~PCI_BASE_ADDRESS_IO_MASK);
-				else
-					rtmp |= (base & ~PCI_BASE_ADDRESS_MEM_MASK);
-				pci_write_config_dword(pdev, breg, rtmp);
-
-				/* Apply PBM ranges and update pci_dev. */
-				pci_addr = new_base;
-				for(rng = 0; rng < pbm->num_pbm_ranges; rng++) {
-					struct linux_prom_pci_ranges *rngp;
-					int rspace;
-
-					rngp = &pbm->pbm_ranges[rng];
-					rspace = (rngp->child_phys_hi >> 24) & 3;
-					if(io && rspace != 1)
-						continue;
-					else if(!io && rspace != 2)
-						continue;
-					pci_addr += ((u64)rngp->parent_phys_lo);
-					pci_addr += (((u64)rngp->parent_phys_hi)<<32UL);
-					break;
-				}
-				if(rng == pbm->num_pbm_ranges) {
-					/* AIEEE */
-					prom_printf("fixup_doit: YIEEE, cannot find "
-						    "PBM ranges\n");
-				}
-				rp->name = pdev->name;
-				rp->start = (unsigned long) __va(pci_addr);
-				rp->end = rp->start + size - 1;
-
-				/* Keep track of what we've seen so far. */
-				if(io) {
-					IO_seen = 1;
-					rp->flags = rtmp & 0x1;
-					request_resource(&ioport_resource, rp);
-				} else {
-					MEM_seen = 1;
-					rp->flags = rtmp & 0xf;
-					request_resource(&iomem_resource, rp);
-				}
-			}
-		}
-
-		/*
-		 * Handle PCI_ROM_ADDRESS.
-		 */
-		breg = PCI_ROM_ADDRESS;
-		base = (unsigned int)pdev->rom_address;
-
-		if(pdev->rom_address > PAGE_OFFSET)
-			goto rom_address_done;
-
-		base &= PCI_ROM_ADDRESS_MASK;
-		offset = (pdev->bus->number << 16) | (pdev->devfn << 8) | breg;
-		vp = pci_find_vma(pbm, base, offset, 0);
-		if(!vp || vp->start > base) {
-			unsigned int size, new_base;
-
-			pci_read_config_dword(pdev, breg, &rtmp);
-			pci_write_config_dword(pdev, breg, 0xffffffff);
-			pci_read_config_dword(pdev, breg, &size);
-			size &= ~1;
-			size = (~(size) + 1);
-			if(!size)
-				goto rom_address_done;
-
-			new_base = 0;
-			for(vp = pci_find_vma(pbm, new_base, 0, 0); ; vp = vp->next) {
-				if(!vp || new_base + size <= vp->start)
-					break;
-				new_base = (vp->end + (size - 1)) & ~(size-1);
-			}
-			if(vp && (new_base + size > vp->start)) {
-				prom_printf("PCI: Impossible full MEM space.\n");
-				prom_halt();
-			}
-			vp = pci_vma_alloc();
-			vp->start = new_base;
-			vp->end = vp->start + size - 1;
-			vp->offset = offset;
-
-			pci_add_vma(pbm, vp, 0);
-
-#ifdef FIXUP_VMA_DEBUG
-			dprintf("%02x.%02x.%x: BaseReg %02x",
-				pdev->bus->number,
-				PCI_SLOT(pdev->devfn),
-				PCI_FUNC(pdev->devfn),
-				breg);
-			dprintf(" %s vma [%08x,%08x]\n",
-				"ROM", vp->start, vp->end);
-#endif
-
-			rtmp = new_base;
-			pci_read_config_dword(pdev, breg, &base);
-			rtmp &= ~(base & ~PCI_ROM_ADDRESS_MASK);
-			pci_write_config_dword(pdev, breg, rtmp);
-
-			/* Apply PBM ranges and update pci_dev. */
-			pci_addr = new_base;
-			for(rng = 0; rng < pbm->num_pbm_ranges; rng++) {
-				struct linux_prom_pci_ranges *rngp;
-				int rspace;
-
-				rngp = &pbm->pbm_ranges[rng];
-				rspace = (rngp->child_phys_hi >> 24) & 3;
-				if(rspace != 2)
-					continue;
-				pci_addr += ((u64)rngp->parent_phys_lo);
-				pci_addr += (((u64)rngp->parent_phys_hi)<<32UL);
-				break;
-			}
-			if(rng == pbm->num_pbm_ranges) {
-				/* AIEEE */
-				prom_printf("fixup_doit: YIEEE, cannot find "
-					    "PBM ranges\n");
-			}
-			pdev->rom_address = (unsigned long)__va(pci_addr);
-			pdev->rom_address &= ~(base & ~PCI_ROM_ADDRESS_MASK);
-			MEM_seen = 1;
-		}
-	rom_address_done:
-
-	}
-	if(IO_seen || MEM_seen) {
-		unsigned int l;
-
-		pci_read_config_dword(pdev, PCI_COMMAND, &l);
-#ifdef FIXUP_REGS_DEBUG
-		dprintf("[");
-#endif
-		if(IO_seen) {
-#ifdef FIXUP_REGS_DEBUG
-			dprintf("IO ");
-#endif
-			l |= PCI_COMMAND_IO;
-		}
-		if(MEM_seen) {
-#ifdef FIXUP_REGS_DEBUG
-			dprintf("MEM");
-#endif
-			l |= PCI_COMMAND_MEMORY;
-		}
-#ifdef FIXUP_REGS_DEBUG
-		dprintf("]");
-#endif
-		pci_write_config_dword(pdev, PCI_COMMAND, l);
-	}
-
-#ifdef FIXUP_REGS_DEBUG
-	dprintf("REG_FIXUP[%04x,%04x]: ", pdev->vendor, pdev->device);
-	for(preg = 0; preg < 6; preg++) {
-		if(pdev->resource[preg].start != 0)
-			dprintf("%d[%016lx] ", preg, pdev->resource[preg].start);
-	}
-	dprintf("\n");
-#endif
-}
-
-#define imap_offset(__member) \
-	((unsigned long)(&(((struct psycho_regs *)0)->__member)))
-
-static unsigned long __init psycho_pcislot_imap_offset(unsigned long ino)
-{
-	unsigned int bus, slot;
-
-	bus = (ino & 0x10) >> 4;
-	slot = (ino & 0x0c) >> 2;
-
-	if(bus == 0) {
-		switch(slot) {
-		case 0:
-			return imap_offset(imap_a_slot0);
-		case 1:
-			return imap_offset(imap_a_slot1);
-		case 2:
-			return imap_offset(imap_a_slot2);
-		case 3:
-		default:
-			return imap_offset(imap_a_slot3);
-		}
-	} else {
-		switch(slot) {
-		case 0:
-			return imap_offset(imap_b_slot0);
-		case 1:
-			return imap_offset(imap_b_slot1);
-		case 2:
-			return imap_offset(imap_b_slot2);
-		case 3:
-		default:
-			return imap_offset(imap_b_slot3);
-		}
-	}
-}
-
-/* Exported for EBUS probing layer. */
-unsigned int __init psycho_irq_build(struct linux_pbm_info *pbm,
-				     struct pci_dev *pdev,
-				     unsigned int ino)
-{
-	unsigned long imap_off;
-	int need_dma_sync = 0;
-
-	ino &= PSYCHO_IMAP_INO;
-
-	/* Compute IMAP register offset, generic IRQ layer figures out
-	 * the ICLR register address as this is simple given the 32-bit
-	 * irq number and IMAP register address.
-	 */
-	if((ino & 0x20) == 0)
-		imap_off = psycho_pcislot_imap_offset(ino);
-	else {
-		switch(ino) {
-		case 0x20:
-			/* Onboard SCSI. */
-			imap_off = imap_offset(imap_scsi);
-			break;
-
-		case 0x21:
-			/* Onboard Ethernet (ie. CheerIO/HME) */
-			imap_off = imap_offset(imap_eth);
-			break;
-
-		case 0x22:
-			/* Onboard Parallel Port */
-			imap_off = imap_offset(imap_bpp);
-			break;
-
-		case 0x23:
-			/* Audio Record */
-			imap_off = imap_offset(imap_au_rec);
-			break;
-
-		case 0x24:
-			/* Audio Play */
-			imap_off = imap_offset(imap_au_play);
-			break;
-
-		case 0x25:
-			/* Power Fail */
-			imap_off = imap_offset(imap_pfail);
-			break;
-
-		case 0x26:
-			/* Onboard KBD/MOUSE/SERIAL */
-			imap_off = imap_offset(imap_kms);
-			break;
-
-		case 0x27:
-			/* Floppy (ie. fdthree) */
-			imap_off = imap_offset(imap_flpy);
-			break;
-
-		case 0x28:
-			/* Spare HW INT */
-			imap_off = imap_offset(imap_shw);
-			break;
-
-		case 0x29:
-			/* Onboard Keyboard (only) */
-			imap_off = imap_offset(imap_kbd);
-			break;
-
-		case 0x2a:
-			/* Onboard Mouse (only) */
-			imap_off = imap_offset(imap_ms);
-			break;
-
-		case 0x2b:
-			/* Onboard Serial (only) */
-			imap_off = imap_offset(imap_ser);
-			break;
-
-		case 0x2c:
-			/* Onboard Timer 0 */
-			imap_off = imap_offset(imap_tim0);
-			break;
-
-		case 0x2d:
-			/* Onboard Timer 1 */
-			imap_off = imap_offset(imap_tim1);
-			break;
-
-		case 0x2e:
-			/* Psycho UE Interrupt */
-			imap_off = imap_offset(imap_ue);
-			break;
-
-		case 0x2f:
-			/* Psycho CE Interrupt */
-			imap_off = imap_offset(imap_ce);
-			break;
-
-		case 0x30:
-			/* Psycho PCI A Error Interrupt */
-			imap_off = imap_offset(imap_a_err);
-			break;
-
-		case 0x31:
-			/* Psycho PCI B Error Interrupt */
-			imap_off = imap_offset(imap_b_err);
-			break;
-
-		case 0x32:
-			/* Power Management */
-			imap_off = imap_offset(imap_pmgmt);
-			break;
-
-		default:
-			/* We don't expect anything else.
-			 */
-			prom_printf("psycho_irq_build: Wacky INO [%x]\n", ino);
-			prom_halt();
-		};
-	}
-	imap_off -= imap_offset(imap_a_slot0);
-
-	if (apb_present(pbm->parent) && (pdev->bus->number != pbm->pci_first_busno)) {
-		need_dma_sync = 1;
-	}
-
-	return psycho_build_irq(pbm->parent, imap_off, ino, need_dma_sync);
-}
-
-static int __init pbm_intmap_match(struct linux_pbm_info *pbm,
-				   struct pci_dev *pdev,
-				   struct linux_prom_pci_registers *preg,
-				   unsigned int *interrupt)
-{
-	struct linux_prom_pci_registers ppreg;
-	unsigned int hi, mid, lo, irq;
-	int i;
-
-#ifdef FIXUP_IRQ_DEBUG
-	dprintf("pbm_intmap_match: ");
-#endif
-	if (!pbm->num_pbm_intmap) {
-#ifdef FIXUP_IRQ_DEBUG
-		dprintf("No intmap UPA[%x:%c]\n",
-			pbm->parent->upa_portid,
-			(pbm == &pbm->parent->pbm_A) ? 'A' : 'B');
-#endif
-		return 0;
-	}
-	/*
-	 * Underneath a bridge, use register of parent bridge.
-	 */
-	if (pdev->bus->number != pbm->pci_first_busno) {
-		struct pcidev_cookie *pcp;
-		int node, offset;
-		char prom_name[64];
-
-#ifdef FIXUP_IRQ_DEBUG
-		dprintf("UnderBridge, ");
-#endif
-		pcp = pdev->bus->self->sysdata;
-		if (!pcp) {
-#ifdef FIXUP_IRQ_DEBUG
-			dprintf("No bus PCP\n");
-#endif
-			goto out;
-		}
-		node = pcp->prom_node;
-
-		i = prom_getproperty(node, "reg", (char*)&ppreg, sizeof(ppreg));
-		if(i == 0 || i == -1) {
-#ifdef FIXUP_IRQ_DEBUG
-			dprintf("No reg property.\n");
-#endif
-			goto out;
-		}
-		/*
-		 * Did PROM know better and assign an interrupt different
-		 * to #INTA to the device? - We test here for presence of
-		 * FCODE on the card, in this case we assume PROM has set
-		 * correct 'interrupts' property, unless it is quadhme.
-		 */
-		pcp = pdev->sysdata;
-		if (!pcp) {
-#ifdef FIXUP_IRQ_DEBUG
-			dprintf("No dev PCP\n");
-#endif
-			goto out;
-		}
-		node = pcp->prom_node;
-
-		offset = prom_getint(node, "fcode-rom-offset");
-		prom_getstring(node, "name", prom_name, sizeof(prom_name));
-		if (offset == -1 || 
-		    !strcmp(prom_name, "SUNW,qfe") ||
-		    !strcmp(prom_name, "qfe")) {
-			/*
-			 * No, use low slot number bits of child as IRQ line.
-			 */
-			*interrupt = ((*interrupt - 1 + PCI_SLOT(pdev->devfn)) & 3) + 1;
-		}
-		preg = &ppreg;
-	}
-
-	hi = preg->phys_hi & pbm->pbm_intmask.phys_hi;
-	mid = preg->phys_mid & pbm->pbm_intmask.phys_mid;
-	lo = preg->phys_lo & pbm->pbm_intmask.phys_lo;
-	irq = *interrupt & pbm->pbm_intmask.interrupt;
-#ifdef FIXUP_IRQ_DEBUG
-	dprintf("intmap_match: [%02x.%02x.%x] key: [%08x.%08x.%08x.%08x] ",
-		pdev->bus->number, pdev->devfn >> 3, pdev->devfn & 7,
-		hi, mid, lo, irq);
-#endif
-	for (i = 0; i < pbm->num_pbm_intmap; i++) {
-		if ((pbm->pbm_intmap[i].phys_hi == hi) &&
-		    (pbm->pbm_intmap[i].phys_mid == mid) &&
-		    (pbm->pbm_intmap[i].phys_lo == lo) &&
-		    (pbm->pbm_intmap[i].interrupt == irq)) {
-#ifdef FIXUP_IRQ_DEBUG
-			dprintf("irq: [%08x]", pbm->pbm_intmap[i].cinterrupt);
-#endif
-			*interrupt = pbm->pbm_intmap[i].cinterrupt;
-			return 1;
-		}
-	}
-
-out:
-	prom_printf("pbm_intmap_match: bus %02x, devfn %02x: ",
-		    pdev->bus->number, pdev->devfn);
-	prom_printf("IRQ [%08x.%08x.%08x.%08x] not found in interrupt-map\n",
-		    preg->phys_hi, preg->phys_mid, preg->phys_lo, *interrupt);
-	prom_halt();
-}
-
-static void __init fixup_irq(struct pci_dev *pdev,
-			     struct linux_pbm_info *pbm,
-			     struct linux_prom_pci_registers *preg,
-			     int node)
-{
-	unsigned int prom_irq, portid = pbm->parent->upa_portid;
-	int err;
-
-#ifdef FIXUP_IRQ_DEBUG
-	dprintf("fixup_irq[%04x:%04x]: ", pdev->vendor, pdev->device);
-#endif
-	err = prom_getproperty(node, "interrupts", (void *)&prom_irq, sizeof(prom_irq));
-	if(err == 0 || err == -1) {
-#ifdef FIXUP_IRQ_DEBUG
-		dprintf("No interrupts property.\n");
-#endif
-		pdev->irq = 0;
-		return;
-	}
-
-	/* See if fully specified already (ie. for onboard devices like hme) */
-	if(((prom_irq & PSYCHO_IMAP_IGN) >> 6) == pbm->parent->upa_portid) {
-		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,
-					     (pbm->parent->upa_portid << 6)
-					     | prom_irq);
-#ifdef FIXUP_IRQ_DEBUG
-		dprintf("partially specified prom_irq[%x] pdev->irq[%x]",
-		        prom_irq, pdev->irq);
-#endif
-	/* See if we find a matching interrupt-map entry. */
-	} else if (pbm_intmap_match(pbm, pdev, preg, &prom_irq)) {
-		pdev->irq = psycho_irq_build(pbm, pdev,
-					     (pbm->parent->upa_portid << 6)
-					     | prom_irq);
-#ifdef FIXUP_IRQ_DEBUG
-		dprintf("interrupt-map specified: prom_irq[%x] pdev->irq[%x]",
-			prom_irq, pdev->irq);
-#endif
-	} else {
-		unsigned int bus, slot, line;
-
-		bus = (pbm == &pbm->parent->pbm_B) ? (1 << 4) : 0;
-
-		/* Use the given interrupt property value as the line if it
-		 * is non-zero and legal.  Legal encodings are INTA=1, INTB=2,
-		 * INTC=3, INTD=4 as per PCI OBP binding spec version 2.1 -DaveM
-		 */
-		if(prom_irq > 0 && prom_irq < 5) {
-			line = ((prom_irq - 1) & 3);
-		} else {
-			unsigned char pci_irq_line;
-
-			/* The generic PCI probing layer will read the
-			 * interrupt line into pdev->irq if the interrupt
-			 * pin is non-zero, so we have to explicitly fetch
-			 * the pin here to be certain (the interrupt line is
-			 * typically left at zero by OBP).
-			 */
-			pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pci_irq_line);
-			line = ((pci_irq_line - 1) & 3);
-		}
-
-		/* Slot determination is only slightly complex.  Handle
-		 * the easy case first.
-		 */
-		if(pdev->bus->number == pbm->pci_first_busno) {
-			if(pbm == &pbm->parent->pbm_A)
-				slot = (pdev->devfn >> 3) - 1;
-			else
-				slot = (pdev->devfn >> 3) - 2;
-		} else {
-			/* Underneath a bridge, use slot number of parent
-			 * bridge.
-			 */
-			if(pbm == &pbm->parent->pbm_A)
-				slot = (pdev->bus->self->devfn >> 3) - 1;
-			else
-				slot = (pdev->bus->self->devfn >> 3) - 2;
-
-			/* Use low slot number bits of child as IRQ line. */
-			line = (pdev->devfn >> 3) & 0x03;
-		}
-		slot = (slot << 2);
-
-		pdev->irq = psycho_irq_build(pbm, pdev,
-					     (((portid << 6) & PSYCHO_IMAP_IGN)
-					     | (bus | slot | line)));
-
-#ifdef FIXUP_IRQ_DEBUG
-		do {
-			unsigned char iline, ipin;
-
-			pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &ipin);
-			pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &iline);
-			dprintf("FIXED portid[%x] bus[%x] slot[%x] line[%x] "
-				"irq[%x] iline[%x] ipin[%x] prom_irq[%x]",
-			        portid, bus>>4, slot>>2, line, pdev->irq,
-			        iline, ipin, prom_irq);
-		} while(0);
-#endif
-	}
-
-	/*
-	 * Write the INO to config space PCI_INTERRUPT_LINE.
-	 */
-	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE,
-			      pdev->irq & PCI_IRQ_INO);
-
-#ifdef FIXUP_IRQ_DEBUG
-	dprintf("\n");
-#endif
-}
-
-static void __init fixup_doit(struct pci_dev *pdev,
-			      struct linux_pbm_info *pbm,
-			      struct linux_prom_pci_registers *pregs,
-			      int nregs,
-			      int node)
-{
-	struct linux_prom_pci_registers assigned[PROMREG_MAX];
-	int numaa, err;
-
-	/* Get assigned addresses, if any. */
-	err = prom_getproperty(node, "assigned-addresses",
-			       (char *)&assigned[0], sizeof(assigned));
-	if(err == 0 || err == -1)
-		numaa = 0;
-	else
-		numaa = (err / sizeof(struct linux_prom_pci_registers));
-
-	/* First, scan and fixup base registers. */
-	fixup_regs(pdev, pbm, pregs, nregs, &assigned[0], numaa);
-
-	/* Next, fixup interrupt numbers. */
-	fixup_irq(pdev, pbm, &pregs[0], node);
-}
-
-static void __init fixup_pci_dev(struct pci_dev *pdev,
-				 struct pci_bus *pbus,
-				 struct linux_pbm_info *pbm)
-{
-	struct linux_prom_pci_registers pregs[PROMREG_MAX];
-	struct pcidev_cookie *pcp = pdev->sysdata;
-	int node, nregs, err;
-
-	/* If this is a PCI bridge, we must program it. */
-	if(pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI) {
-		unsigned short cmd;
-
-		/* First, enable bus mastering. */
-		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-		cmd |= PCI_COMMAND_MASTER;
-		pci_write_config_word(pdev, PCI_COMMAND, cmd);
-
-		/* Now, set cache line size to 64-bytes.
-		 * NOTE: Cache line size is in 32-bit word units.
-		 */
-		pci_write_config_byte(pdev,
-				      PCI_CACHE_LINE_SIZE,
-				      (64 / sizeof(u32)));
-	}
-
-	/* Ignore if this is one of the PBM's, EBUS, or a
-	 * sub-bridge underneath the PBM.  We only need to fixup
-	 * true devices.
-	 */
-	if((pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI) ||
-	   (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) ||
-	   (pdev->class >> 8 == PCI_CLASS_BRIDGE_OTHER) ||
-	   (pcp == NULL)) {
-		/*
-		 * Prevent access to PCI_ROM_ADDRESS, in case present
-		 * as we don't fixup the address.
-		 */
-		if (pdev->rom_address) {
-			pci_write_config_dword(pdev, PCI_ROM_ADDRESS, 0);
-			pdev->rom_address = 0;
-		}
-		return;
-	}
-
-	node = pcp->prom_node;
-
-	err = prom_getproperty(node, "reg", (char *)&pregs[0], sizeof(pregs));
-	if(err == 0 || err == -1) {
-		prom_printf("Cannot find REG for pci_dev\n");
-		prom_halt();
-	}
-
-	nregs = (err / sizeof(pregs[0]));
-
-	fixup_doit(pdev, pbm, &pregs[0], nregs, node);
-
-	/* Enable bus mastering on IDE interfaces. */
-	if ((pdev->class >> 8 == PCI_CLASS_STORAGE_IDE)
-	    && (pdev->class & 0x80)) {
-		unsigned short cmd;
-
-		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-		cmd |= PCI_COMMAND_MASTER;
-		pci_write_config_word(pdev, PCI_COMMAND, cmd);
-	}
-}
-
-static void __init fixup_pci_bus(struct pci_bus *pbus, struct linux_pbm_info *pbm)
-{
-	struct pci_dev *pdev;
-
-	for(pdev = pbus->devices; pdev; pdev = pdev->sibling)
-		fixup_pci_dev(pdev, pbus, pbm);
-
-	for(pbus = pbus->children; pbus; pbus = pbus->next)
-		fixup_pci_bus(pbus, pbm);
-}
-
-static void __init fixup_addr_irq(struct linux_pbm_info *pbm)
-{
-	struct pci_bus *pbus = &pbm->pci_bus;
-
-	/* Work through top level devices (not bridges, those and their
-	 * devices are handled specially in the next loop).
-	 */
-	fixup_pci_bus(pbus, pbm);
-}
-
-/* Walk all PCI devices probes, fixing up base registers and IRQ registers.
- * We use OBP for most of this work.
- */
-static void __init psycho_final_fixup(struct linux_psycho *psycho)
-{
-	/* Second, fixup base address registers and IRQ lines... */
-	if (psycho->pbm_A.parent)
-		fixup_addr_irq(&psycho->pbm_A);
-	if (psycho->pbm_B.parent)
-		fixup_addr_irq(&psycho->pbm_B);
-}
-
-/* Reorder the pci_dev chain, so that onboard devices come first
-   and then come the pluggable cards. */
-void __init psycho_reorder_devs(void)
-{
-	struct pci_dev **pci_onboard = &pci_devices;
-	struct pci_dev **pci_tail = &pci_devices;
-	struct pci_dev *pdev = pci_devices, *pci_other = NULL;
-
-	while (pdev) {
-		if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) {
-			if (pci_other) {
-				*pci_onboard = pdev;
-				pci_onboard = &pdev->next;
-				pdev = pdev->next;
-				*pci_onboard = pci_other;
-				*pci_tail = pdev;
-				continue;
-			} else
-				pci_onboard = &pdev->next;
-		} else if (!pci_other)
-			pci_other = pdev;
-		pci_tail = &pdev->next;
-		pdev = pdev->next;
-	}
-}
-
-void __init pcibios_fixup(void)
-{
-	struct linux_psycho *psycho;
-
-	pci_probe_enable = 1;
-
-	/* XXX Really this should be per-PSYCHO, but the config space
-	 * XXX reads and writes give us no way to know which PSYCHO
-	 * XXX in which the config space reads should occur.
-	 * XXX
-	 * XXX Further thought says that we cannot change this generic
-	 * XXX interface, else we'd break xfree86 and other parts of the
-	 * XXX kernel (but whats more important is breaking userland for
-	 * XXX the ix86/Alpha/etc. people).  So we should define our own
-	 * XXX internal extension initially, we can compile our own user
-	 * XXX apps that need to get at PCI configuration space.
-	 */
-
-	for (psycho = psycho_root; psycho; psycho = psycho->next) {
-		/* Probe bus on builtin PCI. */
-		if (apb_present(psycho)) {
-			sabre_probe(psycho);
-		} else {
-			/* Probe busses under PBM B. */
-			pbm_probe(&psycho->pbm_B);
-
-			/* Probe busses under PBM A. */
-			pbm_probe(&psycho->pbm_A);
-		}
-	}
-
-	/* 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 (apb_present(psycho))
-			sabre_cookie_fillin(psycho);
-
-		fill_in_pbm_cookies(&psycho->pbm_A.pci_bus,
-				    &psycho->pbm_A,
-				    psycho->pbm_A.prom_node);
-		fill_in_pbm_cookies(&psycho->pbm_B.pci_bus,
-				    &psycho->pbm_B,
-				    psycho->pbm_B.prom_node);
-
-		/* See what OBP has taken care of already. */
-		record_assignments(&psycho->pbm_A);
-		record_assignments(&psycho->pbm_B);
-
-		/* Now, fix it all up. */
-		psycho_final_fixup(psycho);
-	}
-
-	if (psycho_reorder & PSYCHO_REORDER_ONBOARDFIRST)
-		psycho_reorder_devs();
-
-	return ebus_init();
-}
-
-/* "PCI: The emerging standard..." 8-( */
-volatile int pci_poke_in_progress = 0;
-volatile int pci_poke_faulted = 0;
-
-/* XXX Current PCI support code is broken, it assumes one master PCI config
- * XXX space exists, on Ultra we can have many of them, especially with
- * XXX 'dual-pci' boards on Sunfire/Starfire/Wildfire.
- */
-static void *
-pci_mkaddr(struct linux_pbm_info *pbm, unsigned char bus,
-	   unsigned char devfn, unsigned char where)
-{
-	unsigned long ret;
-
-	if (!pbm)
-		return NULL;
-
-	ret = (unsigned long) pbm->parent->pci_config_space;
-
-	ret |= (1 << 24);
-	ret |= (bus << 16);
-	ret |= (devfn << 8);
-	ret |= where;
-
-	return (void *)ret;
-}
-
-static inline int
-out_of_range(struct linux_pbm_info *pbm, unsigned char bus, unsigned char devfn)
-{
-	return ((pbm->parent == 0) ||
-		((pbm == &pbm->parent->pbm_B) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 8) ||
-		((pbm == &pbm->parent->pbm_A) && (bus == pbm->pci_first_busno) && PCI_SLOT(devfn) > 8) ||
-		(pci_probe_enable == 0));
-}
-
-static inline int
-sabre_out_of_range(unsigned char devfn)
-{
-	return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) ||
-		((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) ||
-		(PCI_SLOT(devfn) > 1) ||
-		(pci_probe_enable == 0));
-}
-
-static int
-sabre_read_config_byte(struct linux_pbm_info *pbm,
-		       unsigned char bus, unsigned char devfn,
-		       unsigned char where, unsigned char *value)
-{
-	if (bus)
-		return pbm_read_config_byte(pbm, bus, devfn, where, value);
-
-	if (sabre_out_of_range(devfn)) {
-		*value = 0xff;
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	if (where < 8) {
-		unsigned short tmp;
-
-		pbm_read_config_word(pbm, bus, devfn, where & ~1, &tmp);
-		if (where & 1)
-			*value = tmp >> 8;
-		else
-			*value = tmp & 0xff;
-		return PCIBIOS_SUCCESSFUL;
-	} else
-		return pbm_read_config_byte(pbm, bus, devfn, where, value);
-}
-
-static int
-sabre_read_config_word(struct linux_pbm_info *pbm,
-		       unsigned char bus, unsigned char devfn,
-		       unsigned char where, unsigned short *value)
-{
-	if (bus)
-		return pbm_read_config_word(pbm, bus, devfn, where, value);
-
-	if (sabre_out_of_range(devfn)) {
-		*value = 0xffff;
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	if (where < 8)
-		return pbm_read_config_word(pbm, bus, devfn, where, value);
-	else {
-		unsigned char tmp;
-
-		pbm_read_config_byte(pbm, bus, devfn, where, &tmp);
-		*value = tmp;
-		pbm_read_config_byte(pbm, bus, devfn, where + 1, &tmp);
-		*value |= tmp << 8;
-		return PCIBIOS_SUCCESSFUL;
-	}
-}
-
-static int
-sabre_read_config_dword(struct linux_pbm_info *pbm,
-			unsigned char bus, unsigned char devfn,
-			unsigned char where, unsigned int *value)
-{
-	unsigned short tmp;
-
-	if (bus)
-		return pbm_read_config_dword(pbm, bus, devfn, where, value);
-
-	if (sabre_out_of_range(devfn)) {
-		*value = 0xffffffff;
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	sabre_read_config_word(pbm, bus, devfn, where, &tmp);
-	*value = tmp;
-	sabre_read_config_word(pbm, bus, devfn, where + 2, &tmp);
-	*value |= tmp << 16;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-sabre_write_config_byte(struct linux_pbm_info *pbm,
-			unsigned char bus, unsigned char devfn,
-			unsigned char where, unsigned char value)
-{
-	if (bus)
-		return pbm_write_config_byte(pbm, bus, devfn, where, value);
-
-	if (sabre_out_of_range(devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	if (where < 8) {
-		unsigned short tmp;
-
-		pbm_read_config_word(pbm, bus, devfn, where & ~1, &tmp);
-		if (where & 1) {
-			value &= 0x00ff;
-			value |= tmp << 8;
-		} else {
-			value &= 0xff00;
-			value |= tmp;
-		}
-		return pbm_write_config_word(pbm, bus, devfn, where & ~1, tmp);
-	} else
-		return pbm_write_config_byte(pbm, bus, devfn, where, value);
-}
-
-static int
-sabre_write_config_word(struct linux_pbm_info *pbm,
-			unsigned char bus, unsigned char devfn,
-			unsigned char where, unsigned short value)
-{
-	if (bus)
-		return pbm_write_config_word(pbm, bus, devfn, where, value);
-
-	if (sabre_out_of_range(devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	if (where < 8)
-		return pbm_write_config_word(pbm, bus, devfn, where, value);
-	else {
-		pbm_write_config_byte(pbm, bus, devfn, where, value & 0xff);
-		pbm_write_config_byte(pbm, bus, devfn, where + 1, value >> 8);
-		return PCIBIOS_SUCCESSFUL;
-	}
-}
-
-static int
-sabre_write_config_dword(struct linux_pbm_info *pbm,
-			 unsigned char bus, unsigned char devfn,
-			 unsigned char where, unsigned int value)
-{
-	if (bus)
-		return pbm_write_config_dword(pbm, bus, devfn, where, value);
-
-	if (sabre_out_of_range(devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	sabre_write_config_word(pbm, bus, devfn, where, value & 0xffff);
-	sabre_write_config_word(pbm, bus, devfn, where + 2, value >> 16);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pbm_read_config_byte(struct linux_pbm_info *pbm,
-		     unsigned char bus, unsigned char devfn,
-		     unsigned char where, unsigned char *value)
-{
-	unsigned char *addr = pci_mkaddr(pbm, bus, devfn, where);
-	unsigned int trapped;
-	unsigned char byte;
-
-	*value = 0xff;
-
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	pci_poke_in_progress = 1;
-	pci_poke_faulted = 0;
-	__asm__ __volatile__("membar #Sync\n\t"
-			     "lduba [%1] %2, %0\n\t"
-			     "membar #Sync"
-			     : "=r" (byte)
-			     : "r" (addr), "i" (ASI_PL));
-	pci_poke_in_progress = 0;
-	trapped = pci_poke_faulted;
-	pci_poke_faulted = 0;
-	if(!trapped)
-		*value = byte;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pbm_read_config_word(struct linux_pbm_info *pbm,
-		     unsigned char bus, unsigned char devfn,
-		     unsigned char where, unsigned short *value)
-{
-	unsigned short *addr = pci_mkaddr(pbm, bus, devfn, where);
-	unsigned int trapped;
-	unsigned short word;
-
-	*value = 0xffff;
-
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	if (where & 0x01) {
-		printk("pcibios_read_config_word: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	pci_poke_in_progress = 1;
-	pci_poke_faulted = 0;
-	__asm__ __volatile__("membar #Sync\n\t"
-			     "lduha [%1] %2, %0\n\t"
-			     "membar #Sync"
-			     : "=r" (word)
-			     : "r" (addr), "i" (ASI_PL));
-	pci_poke_in_progress = 0;
-	trapped = pci_poke_faulted;
-	pci_poke_faulted = 0;
-	if(!trapped)
-		*value = word;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pbm_read_config_dword(struct linux_pbm_info *pbm,
-		      unsigned char bus, unsigned char devfn,
-		      unsigned char where, unsigned int *value)
-{
-	unsigned int *addr = pci_mkaddr(pbm, bus, devfn, where);
-	unsigned int word, trapped;
-
-	*value = 0xffffffff;
-
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	if (where & 0x03) {
-		printk("pcibios_read_config_dword: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	pci_poke_in_progress = 1;
-	pci_poke_faulted = 0;
-	__asm__ __volatile__("membar #Sync\n\t"
-			     "lduwa [%1] %2, %0\n\t"
-			     "membar #Sync"
-			     : "=r" (word)
-			     : "r" (addr), "i" (ASI_PL));
-	pci_poke_in_progress = 0;
-	trapped = pci_poke_faulted;
-	pci_poke_faulted = 0;
-	if(!trapped)
-		*value = word;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pbm_write_config_byte(struct linux_pbm_info *pbm,
-		      unsigned char bus, unsigned char devfn,
-		      unsigned char where, unsigned char value)
-{
-	unsigned char *addr = pci_mkaddr(pbm, bus, devfn, where);
-
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	pci_poke_in_progress = 1;
-
-	/* Endianness doesn't matter but we have to get the memory
-	 * barriers in there so...
-	 */
-	__asm__ __volatile__("membar #Sync\n\t"
-			     "stba %0, [%1] %2\n\t"
-			     "membar #Sync\n\t"
-			     : /* no outputs */
-			     : "r" (value), "r" (addr), "i" (ASI_PL));
-	pci_poke_in_progress = 0;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pbm_write_config_word(struct linux_pbm_info *pbm,
-		      unsigned char bus, unsigned char devfn,
-		      unsigned char where, unsigned short value)
-{
-	unsigned short *addr = pci_mkaddr(pbm, bus, devfn, where);
-
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	if (where & 0x01) {
-		printk("pcibios_write_config_word: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	pci_poke_in_progress = 1;
-	__asm__ __volatile__("membar #Sync\n\t"
-			     "stha %0, [%1] %2\n\t"
-			     "membar #Sync\n\t"
-			     : /* no outputs */
-			     : "r" (value), "r" (addr), "i" (ASI_PL));
-	pci_poke_in_progress = 0;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-pbm_write_config_dword(struct linux_pbm_info *pbm,
-		       unsigned char bus, unsigned char devfn,
-		       unsigned char where, unsigned int value)
-{
-	unsigned int *addr = pci_mkaddr(pbm, bus, devfn, where);
-
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	if (where & 0x03) {
-		printk("pcibios_write_config_dword: misaligned reg [%x]\n",
-		       where);
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	pci_poke_in_progress = 1;
-	__asm__ __volatile__("membar #Sync\n\t"
-			     "stwa %0, [%1] %2\n\t"
-			     "membar #Sync"
-			     : /* no outputs */
-			     : "r" (value), "r" (addr), "i" (ASI_PL));
-	pci_poke_in_progress = 0;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char devfn,
-			      unsigned char where, unsigned char *value)
-{
-	struct linux_pbm_info *pbm = bus2pbm[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);
-}
-
-int pcibios_read_config_word (unsigned char bus, unsigned char devfn,
-			      unsigned char where, unsigned short *value)
-{
-	struct linux_pbm_info *pbm = bus2pbm[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);
-}
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char devfn,
-			       unsigned char where, unsigned int *value)
-{
-	struct linux_pbm_info *pbm = bus2pbm[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);
-}
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char devfn,
-			       unsigned char where, unsigned char value)
-{
-	struct linux_pbm_info *pbm = bus2pbm[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);
-}
-
-int pcibios_write_config_word (unsigned char bus, unsigned char devfn,
-			       unsigned char where, unsigned short value)
-{
-	struct linux_pbm_info *pbm = bus2pbm[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);
-}
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char devfn,
-			        unsigned char where, unsigned int value)
-{
-	struct linux_pbm_info *pbm = bus2pbm[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);
-}
-
-asmlinkage int sys_pciconfig_read(unsigned long bus,
-				  unsigned long dfn,
-				  unsigned long off,
-				  unsigned long len,
-				  unsigned char *buf)
-{
-	unsigned char ubyte;
-	unsigned short ushort;
-	unsigned int uint;
-	int err = 0;
-
-	if(!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	lock_kernel();
-	switch(len) {
-	case 1:
-		pcibios_read_config_byte(bus, dfn, off, &ubyte);
-		put_user(ubyte, (unsigned char *)buf);
-		break;
-	case 2:
-		pcibios_read_config_word(bus, dfn, off, &ushort);
-		put_user(ushort, (unsigned short *)buf);
-		break;
-	case 4:
-		pcibios_read_config_dword(bus, dfn, off, &uint);
-		put_user(uint, (unsigned int *)buf);
-		break;
-
-	default:
-		err = -EINVAL;
-		break;
-	};
-	unlock_kernel();
-
-	return err;
-}
-
-asmlinkage int sys_pciconfig_write(unsigned long bus,
-				   unsigned long dfn,
-				   unsigned long off,
-				   unsigned long len,
-				   unsigned char *buf)
-{
-	unsigned char ubyte;
-	unsigned short ushort;
-	unsigned int uint;
-	int err = 0;
-
-	if(!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	lock_kernel();
-	switch(len) {
-	case 1:
-		err = get_user(ubyte, (unsigned char *)buf);
-		if(err)
-			break;
-		pcibios_write_config_byte(bus, dfn, off, ubyte);
-		break;
-
-	case 2:
-		err = get_user(ushort, (unsigned short *)buf);
-		if(err)
-			break;
-		pcibios_write_config_byte(bus, dfn, off, ushort);
-		break;
-
-	case 4:
-		err = get_user(uint, (unsigned int *)buf);
-		if(err)
-			break;
-		pcibios_write_config_byte(bus, dfn, off, uint);
-		break;
-
-	default:
-		err = -EINVAL;
-		break;
-
-	};
-	unlock_kernel();
-
-	return err;
-}
-
-void __init pcibios_fixup_bus(struct pci_bus *bus)
-{
-}
-
-char * __init pcibios_setup(char *str)
-{
-	if (!strcmp(str, "onboardfirst")) {
-		psycho_reorder |= PSYCHO_REORDER_ONBOARDFIRST;
-		return NULL;
-	}
-	if (!strcmp(str, "noreorder")) {
-		psycho_reorder = 0;
-		return NULL;
-	}
-	return str;
-}
-
-#endif
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/semaphore.c linux/arch/sparc64/kernel/semaphore.c
--- v2.3.15/linux/arch/sparc64/kernel/semaphore.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/semaphore.c	Tue Aug 31 11:23:30 1999
@@ -0,0 +1,129 @@
+/* $Id: semaphore.c,v 1.1 1999/08/30 10:00:50 davem Exp $
+ *  Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/sched.h>
+#include <asm/semaphore-helper.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit.  ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore.  The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+	wake_one_more(sem);
+	wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function.  Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible.  This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return.  If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR				\
+	struct task_struct *tsk = current;	\
+	wait_queue_t wait;			\
+	init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state)						\
+									\
+									\
+	tsk->state = (task_state);					\
+	add_wait_queue(&sem->wait, &wait);				\
+									\
+	/*								\
+	 * Ok, we're set up.  sem->count is known to be less than zero	\
+	 * so we must wait.						\
+	 *								\
+	 * We can let go the lock for purposes of waiting.		\
+	 * We re-acquire it after awaking so as to protect		\
+	 * all semaphore operations.					\
+	 *								\
+	 * If "up()" is called before we call waking_non_zero() then	\
+	 * we will catch it right away.  If it is called later then	\
+	 * we will have to go through a wakeup cycle to catch it.	\
+	 *								\
+	 * Multiple waiters contend for the semaphore lock to see	\
+	 * who gets to gate through and who has to wait some more.	\
+	 */								\
+	for (;;) {
+
+#define DOWN_TAIL(task_state)			\
+		tsk->state = (task_state);	\
+	}					\
+	tsk->state = TASK_RUNNING;		\
+	remove_wait_queue(&sem->wait, &wait);
+
+void __down(struct semaphore * sem)
+{
+	DOWN_VAR
+	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+	if (waking_non_zero(sem))
+		break;
+	schedule();
+	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+	int ret = 0;
+	DOWN_VAR
+	DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+	ret = waking_non_zero_interruptible(sem, tsk);
+	if (ret)
+	{
+		if (ret == 1)
+			/* ret != 0 only if we get interrupted -arca */
+			ret = 0;
+		break;
+	}
+	schedule();
+	DOWN_TAIL(TASK_INTERRUPTIBLE)
+	return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+	return waking_non_zero_trylock(sem);
+}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- v2.3.15/linux/arch/sparc64/kernel/setup.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/kernel/setup.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.46 1999/08/02 08:39:36 davem Exp $
+/*  $Id: setup.c,v 1.47 1999/08/31 06:54:55 davem Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
@@ -316,7 +316,7 @@
  * Process kernel command line switches that are specific to the
  * SPARC or that require special low-level processing.
  */
-__initfunc(static void process_switch(char c))
+static void __init process_switch(char c)
 {
 	switch (c) {
 	case 'd':
@@ -335,7 +335,7 @@
 	}
 }
 
-__initfunc(static void boot_flags_init(char *commands))
+static void __init boot_flags_init(char *commands)
 {
 	while (*commands) {
 		/* Move to the start of the next "argument". */
@@ -438,8 +438,8 @@
 
 extern struct consw sun_serial_con;
 
-__initfunc(void setup_arch(char **cmdline_p,
-	unsigned long * memory_start_p, unsigned long * memory_end_p))
+void __init setup_arch(char **cmdline_p,
+	unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
 	extern int serial_console;  /* in console.c, of course */
 	unsigned long lowest_paddr, end_of_phys_memory = 0;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- v2.3.15/linux/arch/sparc64/kernel/smp.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/kernel/smp.c	Tue Aug 31 11:23:30 1999
@@ -83,7 +83,7 @@
 	return len;
 }
 
-__initfunc(void smp_store_cpu_info(int id))
+void __init smp_store_cpu_info(int id)
 {
 	int i;
 
@@ -103,7 +103,7 @@
 		cpu_data[id].irq_worklists[i] = 0;
 }
 
-__initfunc(void smp_commence(void))
+void __init smp_commence(void)
 {
 }
 
@@ -115,7 +115,7 @@
 extern void inherit_locked_prom_mappings(int save_p);
 extern void cpu_probe(void);
 
-__initfunc(void smp_callin(void))
+void __init smp_callin(void)
 {
 	int cpuid = hard_smp_processor_id();
 
@@ -192,7 +192,7 @@
  */
 static struct task_struct *cpu_new_task = NULL;
 
-__initfunc(void smp_boot_cpus(void))
+void __init smp_boot_cpus(void)
 {
 	int cpucount = 0, i;
 
@@ -547,10 +547,18 @@
 	atomic_dec(&smp_capture_registry);
 }
 
-static inline void sparc64_do_profile(unsigned long pc)
+static inline void sparc64_do_profile(unsigned long pc, unsigned long g3)
 {
 	if (prof_buffer && current->pid) {
 		extern int _stext;
+		extern int rwlock_impl_begin, rwlock_impl_end;
+		extern int atomic_impl_begin, atomic_impl_end;
+
+		if ((pc >= (unsigned long) &rwlock_impl_begin &&
+		     pc < (unsigned long) &rwlock_impl_end) ||
+		    (pc >= (unsigned long) &atomic_impl_begin &&
+		     pc < (unsigned long) &atomic_impl_end))
+			pc = g3;
 
 		pc -= (unsigned long) &_stext;
 		pc >>= prof_shift;
@@ -589,7 +597,7 @@
 	clear_softint((1UL << 0));
 	do {
 		if(!user)
-			sparc64_do_profile(regs->tpc);
+			sparc64_do_profile(regs->tpc, regs->u_regs[UREG_G3]);
 		if(!--prof_counter(cpu))
 		{
 			if (cpu == boot_cpu_id) {
@@ -647,7 +655,7 @@
 	} while (tick >= compare);
 }
 
-__initfunc(static void smp_setup_percpu_timer(void))
+static void __init smp_setup_percpu_timer(void)
 {
 	int cpu = smp_processor_id();
 
@@ -661,7 +669,7 @@
 			     : "g1");
 }
 
-__initfunc(void smp_tick_init(void))
+void __init smp_tick_init(void)
 {
 	int i;
 	
@@ -707,7 +715,7 @@
 
 cycles_t cacheflush_time;
 
-__initfunc(static void smp_tune_scheduling (void))
+static void __init smp_tune_scheduling (void)
 {
 	unsigned long flush_base, flags, *p;
 	unsigned int ecache_size;
@@ -775,7 +783,8 @@
 	       (int) cacheflush_time);
 }
 
-int __init setup_profiling_timer(unsigned int multiplier)
+/* /proc/profile writes can call this, don't __init it please. */
+int setup_profiling_timer(unsigned int multiplier)
 {
 	unsigned long flags;
 	int i;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/starfire.c linux/arch/sparc64/kernel/starfire.c
--- v2.3.15/linux/arch/sparc64/kernel/starfire.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/kernel/starfire.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: starfire.c,v 1.2 1998/12/09 18:53:11 davem Exp $
+/* $Id: starfire.c,v 1.3 1999/08/30 10:01:13 davem Exp $
  * starfire.c: Starfire/E10000 support.
  *
  * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
@@ -43,7 +43,7 @@
 
 int starfire_hard_smp_processor_id(void)
 {
-	return *((unsigned int *) __va(0x1fff40000d0));
+	return *((volatile unsigned int *) __va(0x1fff40000d0));
 }
 
 /* Each Starfire board has 32 registers which perform translation
@@ -52,8 +52,8 @@
  * bits than in all previous Sun5 systems.
  */
 struct starfire_irqinfo {
-	unsigned int *imap_slots[32];
-	unsigned int *tregs[32];
+	volatile unsigned int *imap_slots[32];
+	volatile unsigned int *tregs[32];
 	struct starfire_irqinfo *next;
 	int upaid, hwmid;
 };
@@ -80,7 +80,7 @@
 	treg_base += 0x200UL;
 	for(i = 0; i < 32; i++) {
 		p->imap_slots[i] = NULL;
-		p->tregs[i] = __va(treg_base + (i * 0x10));
+		p->tregs[i] = (volatile unsigned int *)__va(treg_base + (i * 0x10));
 	}
 	p->upaid = upaid;
 	p->next = sflist;
@@ -89,7 +89,7 @@
 	return (void *) p;
 }
 
-unsigned int starfire_translate(unsigned int *imap,
+unsigned int starfire_translate(volatile unsigned int *imap,
 				unsigned int upaid)
 {
 	struct starfire_irqinfo *p;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.3.15/linux/arch/sparc64/kernel/sys_sparc32.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.117 1999/08/02 08:39:40 davem Exp $
+/* $Id: sys_sparc32.c,v 1.118 1999/08/30 10:01:15 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -3741,7 +3741,7 @@
 }
 
 
-extern asmlinkage int sys_personality(unsigned long);
+extern asmlinkage long sys_personality(unsigned long);
 
 asmlinkage int sys32_personality(unsigned long personality)
 {
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- v2.3.15/linux/arch/sparc64/kernel/sys_sunos32.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.30 1999/07/30 09:35:31 davem Exp $
+/* $Id: sys_sunos32.c,v 1.31 1999/08/30 10:01:19 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -981,10 +981,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg);
-extern asmlinkage int sys_semget (key_t key, int nsems, int semflg);
-extern asmlinkage int sys_semop  (int semid, struct sembuf *tsops, unsigned nsops);
-
 asmlinkage int sunos_semsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 ptr)
 {
 	union semun arg4;
@@ -1119,13 +1115,6 @@
 	return 0;
 }
 
-extern asmlinkage int sys_msgget (key_t key, int msgflg);
-extern asmlinkage int sys_msgrcv (int msqid, struct msgbuf *msgp,
-				  size_t msgsz, long msgtyp, int msgflg);
-extern asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp,
-				  size_t msgsz, int msgflg);
-extern asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf);
-
 asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
 {
 	struct sparc_stackf32 *sp;
@@ -1241,11 +1230,6 @@
 		return -EFAULT;
 	return 0;
 }
-
-extern asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr);
-extern asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
-extern asmlinkage int sys_shmdt (char *shmaddr);
-extern asmlinkage int sys_shmget (key_t key, int size, int shmflg);
 
 asmlinkage int sunos_shmsys(int op, u32 arg1, u32 arg2, u32 arg3)
 {
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c
--- v2.3.15/linux/arch/sparc64/kernel/time.c	Mon Mar 15 16:10:43 1999
+++ linux/arch/sparc64/kernel/time.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.20 1999/03/15 22:13:40 davem Exp $
+/* $Id: time.c,v 1.22 1999/08/30 10:01:22 davem Exp $
  * time.c: UltraSparc timer and TOD clock support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -33,9 +33,9 @@
 
 extern rwlock_t xtime_lock;
 
-struct mostek48t02 *mstk48t02_regs = 0;
-static struct mostek48t08 *mstk48t08_regs = 0;
-static struct mostek48t59 *mstk48t59_regs = 0;
+unsigned long mstk48t02_regs = 0UL;
+static unsigned long mstk48t08_regs = 0UL;
+static unsigned long mstk48t59_regs = 0UL;
 
 static int set_rtc_mmss(unsigned long);
 
@@ -47,7 +47,7 @@
  */
 unsigned long timer_tick_offset;
 static unsigned long timer_tick_compare;
-static unsigned long timer_ticks_per_usec;
+static unsigned long timer_ticks_per_usec_quotient;
 
 static __inline__ void timer_check_rtc(void)
 {
@@ -146,17 +146,25 @@
 /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
 static void __init kick_start_clock(void)
 {
-	register struct mostek48t02 *regs = mstk48t02_regs;
-	unsigned char sec;
+	unsigned long regs = mstk48t02_regs;
+	u8 sec, tmp;
 	int i, count;
 
 	prom_printf("CLOCK: Clock was stopped. Kick start ");
 
 	/* Turn on the kick start bit to start the oscillator. */
-	regs->creg |= MSTK_CREG_WRITE;
-	regs->sec &= ~MSTK_STOP;
-	regs->hour |= MSTK_KICK_START;
-	regs->creg &= ~MSTK_CREG_WRITE;
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp |= MSTK_CREG_WRITE;
+	mostek_write(regs + MOSTEK_CREG, tmp);
+	tmp = mostek_read(regs + MOSTEK_SEC);
+	tmp &= ~MSTK_STOP;
+	mostek_write(regs + MOSTEK_SEC, tmp);
+	tmp = mostek_read(regs + MOSTEK_HOUR);
+	tmp |= MSTK_KICK_START;
+	mostek_write(regs + MOSTEK_HOUR, tmp);
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp &= ~MSTK_CREG_WRITE;
+	mostek_write(regs + MOSTEK_CREG, tmp);
 
 	/* Delay to allow the clock oscillator to start. */
 	sec = MSTK_REG_SEC(regs);
@@ -165,13 +173,17 @@
 			for (count = 0; count < 100000; count++)
 				/* nothing */ ;
 		prom_printf(".");
-		sec = regs->sec;
+		sec = MSTK_REG_SEC(regs);
 	}
 	prom_printf("\n");
 
 	/* Turn off kick start and set a "valid" time and date. */
-	regs->creg |= MSTK_CREG_WRITE;
-	regs->hour &= ~MSTK_KICK_START;
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp |= MSTK_CREG_WRITE;
+	mostek_write(regs + MOSTEK_CREG, tmp);
+	tmp = mostek_read(regs + MOSTEK_HOUR);
+	tmp &= ~MSTK_KICK_START;
+	mostek_write(regs + MOSTEK_HOUR, tmp);
 	MSTK_SET_REG_SEC(regs,0);
 	MSTK_SET_REG_MIN(regs,0);
 	MSTK_SET_REG_HOUR(regs,0);
@@ -179,14 +191,24 @@
 	MSTK_SET_REG_DOM(regs,1);
 	MSTK_SET_REG_MONTH(regs,8);
 	MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO);
-	regs->creg &= ~MSTK_CREG_WRITE;
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp &= ~MSTK_CREG_WRITE;
+	mostek_write(regs + MOSTEK_CREG, tmp);
 
 	/* Ensure the kick start bit is off. If it isn't, turn it off. */
-	while (regs->hour & MSTK_KICK_START) {
+	while (mostek_read(regs + MOSTEK_HOUR) & MSTK_KICK_START) {
 		prom_printf("CLOCK: Kick start still on!\n");
-		regs->creg |= MSTK_CREG_WRITE;
-		regs->hour &= ~MSTK_KICK_START;
-		regs->creg &= ~MSTK_CREG_WRITE;
+		tmp = mostek_read(regs + MOSTEK_CREG);
+		tmp |= MSTK_CREG_WRITE;
+		mostek_write(regs + MOSTEK_CREG, tmp);
+
+		tmp = mostek_read(regs + MOSTEK_HOUR);
+		tmp &= ~MSTK_KICK_START;
+		mostek_write(regs + MOSTEK_HOUR, tmp);
+
+		tmp = mostek_read(regs + MOSTEK_CREG);
+		tmp &= ~MSTK_CREG_WRITE;
+		mostek_write(regs + MOSTEK_CREG, tmp);
 	}
 
 	prom_printf("CLOCK: Kick start procedure successful.\n");
@@ -195,13 +217,13 @@
 /* Return nonzero if the clock chip battery is low. */
 static int __init has_low_battery(void)
 {
-	register struct mostek48t02 *regs = mstk48t02_regs;
-	unsigned char data1, data2;
+	unsigned long regs = mstk48t02_regs;
+	u8 data1, data2;
 
-	data1 = regs->eeprom[0];	/* Read some data. */
-	regs->eeprom[0] = ~data1;	/* Write back the complement. */
-	data2 = regs->eeprom[0];	/* Read back the complement. */
-	regs->eeprom[0] = data1;	/* Restore the original value. */
+	data1 = mostek_read(regs + MOSTEK_EEPROM);	/* Read some data. */
+	mostek_write(regs + MOSTEK_EEPROM, ~data1);	/* Write back the complement. */
+	data2 = mostek_read(regs + MOSTEK_EEPROM);	/* Read back the complement. */
+	mostek_write(regs + MOSTEK_EEPROM, data1);	/* Restore original value. */
 
 	return (data1 == data2);	/* Was the write blocked? */
 }
@@ -211,17 +233,20 @@
 static void __init set_system_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
-	struct mostek48t02 *mregs;
+	unsigned long mregs = mstk48t02_regs;
+	u8 tmp;
 
 	do_get_fast_time = do_gettimeofday;
 
-	mregs = mstk48t02_regs;
 	if(!mregs) {
 		prom_printf("Something wrong, clock regs not mapped yet.\n");
 		prom_halt();
 	}		
 
-	mregs->creg |= MSTK_CREG_READ;
+	tmp = mostek_read(mregs + MOSTEK_CREG);
+	tmp |= MSTK_CREG_READ;
+	mostek_write(mregs + MOSTEK_CREG, tmp);
+
 	sec = MSTK_REG_SEC(mregs);
 	min = MSTK_REG_MIN(mregs);
 	hour = MSTK_REG_HOUR(mregs);
@@ -230,7 +255,10 @@
 	year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
 	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
 	xtime.tv_usec = 0;
-	mregs->creg &= ~MSTK_CREG_READ;
+
+	tmp = mostek_read(mregs + MOSTEK_CREG);
+	tmp &= ~MSTK_CREG_READ;
+	mostek_write(mregs + MOSTEK_CREG, tmp);
 }
 
 void __init clock_probe(void)
@@ -315,19 +343,8 @@
 				prom_halt();
 			}
 
-			if (check_region(edev->base_address[0],
-					 sizeof(struct mostek48t59))) {
-				prom_printf("%s: Can't get region %lx, %d\n",
-					    __FUNCTION__, edev->base_address[0],
-					    sizeof(struct mostek48t59));
-				prom_halt();
-			}
-			request_region(edev->base_address[0],
-				       sizeof(struct mostek48t59), "clock");
-
-			mstk48t59_regs = (struct mostek48t59 *)
-						edev->base_address[0];
-			mstk48t02_regs = &mstk48t59_regs->regs;
+			mstk48t59_regs = edev->resource[0].start;
+			mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
 			break;
 		}
 #endif
@@ -338,22 +355,16 @@
 		}
 
 		if(model[5] == '0' && model[6] == '2') {
-			mstk48t02_regs = (struct mostek48t02 *)
-				sparc_alloc_io(clk_reg[0].phys_addr,
-					       (void *) 0, sizeof(*mstk48t02_regs),
-					       "clock", clk_reg[0].which_io, 0x0);
+			mstk48t02_regs = (((u64)clk_reg[0].phys_addr) |
+					  (((u64)clk_reg[0].which_io)<<32UL));
 		} else if(model[5] == '0' && model[6] == '8') {
-			mstk48t08_regs = (struct mostek48t08 *)
-				sparc_alloc_io(clk_reg[0].phys_addr,
-					       (void *) 0, sizeof(*mstk48t08_regs),
-					       "clock", clk_reg[0].which_io, 0x0);
-			mstk48t02_regs = &mstk48t08_regs->regs;
+			mstk48t08_regs = (((u64)clk_reg[0].phys_addr) |
+					  (((u64)clk_reg[0].which_io)<<32UL));
+			mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
 		} else {
-			mstk48t59_regs = (struct mostek48t59 *)
-				sparc_alloc_io(clk_reg[0].phys_addr,
-					       (void *) 0, sizeof(*mstk48t59_regs),
-					       "clock", clk_reg[0].which_io, 0x0);
-			mstk48t02_regs = &mstk48t59_regs->regs;
+			mstk48t59_regs = (((u64)clk_reg[0].phys_addr) |
+					  (((u64)clk_reg[0].which_io)<<32UL));
+			mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
 		}
 		break;
 	}
@@ -363,7 +374,7 @@
 		prom_printf("NVRAM: Low battery voltage!\n");
 
 	/* Kick start the clock if it is completely stopped. */
-	if (mstk48t02_regs->sec & MSTK_STOP)
+	if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)
 		kick_start_clock();
 
 	set_system_time();
@@ -392,7 +403,7 @@
 
 	init_timers(timer_interrupt, &clock);
 	timer_tick_offset = clock / HZ;
-	timer_ticks_per_usec = clock / 1000000;
+	timer_ticks_per_usec_quotient = ((1UL<<32) / (clock / 1000020));
 }
 
 static __inline__ unsigned long do_gettimeoffset(void)
@@ -408,7 +419,7 @@
 		: "r" (timer_tick_offset), "r" (timer_tick_compare)
 		: "g1", "g2");
 
-	return ticks / timer_ticks_per_usec;
+	return (ticks * timer_ticks_per_usec_quotient) >> 32UL;
 }
 
 /* This need not obtain the xtime_lock as it is coded in
@@ -431,24 +442,22 @@
 	or	%g2, %lo(xtime), %g2
 	or	%g1, %lo(timer_tick_compare), %g1
 1:	ldda	[%g2] 0x24, %o4
-	membar	#LoadLoad | #MemIssue
 	rd	%tick, %o1
 	ldx	[%g1], %g7
-	membar	#LoadLoad | #MemIssue
 	ldda	[%g2] 0x24, %o2
-	membar	#LoadLoad
 	xor	%o4, %o2, %o2
 	xor	%o5, %o3, %o3
 	orcc	%o2, %o3, %g0
 	bne,pn	%xcc, 1b
 	 sethi	%hi(lost_ticks), %o2
-	sethi	%hi(timer_ticks_per_usec), %o3
+	sethi	%hi(timer_ticks_per_usec_quotient), %o3
 	ldx	[%o2 + %lo(lost_ticks)], %o2
 	add	%g3, %o1, %o1
-	ldx	[%o3 + %lo(timer_ticks_per_usec)], %o3
+	ldx	[%o3 + %lo(timer_ticks_per_usec_quotient)], %o3
 	sub	%o1, %g7, %o1
+	mulx	%o3, %o1, %o1
 	brz,pt	%o2, 1f
-	 udivx	%o1, %o3, %o1
+	 srlx	%o1, 32, %o1
 	sethi	%hi(10000), %g2
 	or	%g2, %lo(10000), %g2
 	add	%o1, %g2, %o1
@@ -487,16 +496,23 @@
 static int set_rtc_mmss(unsigned long nowtime)
 {
 	int real_seconds, real_minutes, mostek_minutes;
-	struct mostek48t02 *regs = mstk48t02_regs;
+	unsigned long regs = mstk48t02_regs;
+	u8 tmp;
 
 	/* Not having a register set can lead to trouble. */
 	if (!regs) 
 		return -1;
 
 	/* Read the current RTC minutes. */
-	regs->creg |= MSTK_CREG_READ;
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp |= MSTK_CREG_READ;
+	mostek_write(regs + MOSTEK_CREG, tmp);
+
 	mostek_minutes = MSTK_REG_MIN(regs);
-	regs->creg &= ~MSTK_CREG_READ;
+
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp &= ~MSTK_CREG_READ;
+	mostek_write(regs + MOSTEK_CREG, tmp);
 
 	/*
 	 * since we're only adjusting minutes and seconds,
@@ -511,10 +527,16 @@
 	real_minutes %= 60;
 
 	if (abs(real_minutes - mostek_minutes) < 30) {
-		regs->creg |= MSTK_CREG_WRITE;
+		tmp = mostek_read(regs + MOSTEK_CREG);
+		tmp |= MSTK_CREG_WRITE;
+		mostek_write(regs + MOSTEK_CREG, tmp);
+
 		MSTK_SET_REG_SEC(regs,real_seconds);
 		MSTK_SET_REG_MIN(regs,real_minutes);
-		regs->creg &= ~MSTK_CREG_WRITE;
+
+		tmp = mostek_read(regs + MOSTEK_CREG);
+		tmp &= ~MSTK_CREG_WRITE;
+		mostek_write(regs + MOSTEK_CREG, tmp);
 	} else
 		return -1;
 
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/lib/atomic.S linux/arch/sparc64/lib/atomic.S
--- v2.3.15/linux/arch/sparc64/lib/atomic.S	Sun Jul  4 09:53:12 1999
+++ linux/arch/sparc64/lib/atomic.S	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: atomic.S,v 1.1 1999/07/03 22:11:04 davem Exp $
+/* $Id: atomic.S,v 1.2 1999/08/23 05:15:58 davem Exp $
  * atomic.S: These things are too big to do inline.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -9,7 +9,10 @@
 	.text
 	.align	64
 
+	.globl	atomic_impl_begin, atomic_impl_end
+
 	.globl	__atomic_add
+atomic_impl_begin:
 __atomic_add:
 	lduw	[%g1], %g5
 	add	%g5, %g2, %g7
@@ -30,3 +33,4 @@
 	 nop
 	jmpl	%g3 + 8, %g0
 	 sub	%g7, %g2, %g2
+atomic_impl_end:
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/lib/rwlock.S linux/arch/sparc64/lib/rwlock.S
--- v2.3.15/linux/arch/sparc64/lib/rwlock.S	Sun Jul  4 09:53:12 1999
+++ linux/arch/sparc64/lib/rwlock.S	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: rwlock.S,v 1.1 1999/07/03 22:11:06 davem Exp $
+/* $Id: rwlock.S,v 1.2 1999/08/23 05:15:58 davem Exp $
  * rwlocks.S: These things are too big to do inline.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -7,10 +7,13 @@
 	.text
 	.align	64
 
+	.globl	rwlock_impl_begin, rwlock_impl_end
+
 	/* The non-contention read lock usage is 2 cache lines. */
 
 	.globl	__read_lock, __read_unlock
 	/* g1=lock, g3=retpc, g5/g7=scratch */
+rwlock_impl_begin:
 __read_lock:
 	ldsw		[%g1], %g5
 	brlz,pn		%g5, __read_wait_for_writer
@@ -78,4 +81,5 @@
 	be,pn		%icc, 99b
 	 membar		#LoadLoad
 	b,a,pt		%xcc, 99b
+rwlock_impl_end:
 
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/Makefile linux/arch/sparc64/math-emu/Makefile
--- v2.3.15/linux/arch/sparc64/math-emu/Makefile	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/Makefile	Tue Aug 31 11:23:30 1999
@@ -8,12 +8,7 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := math-emu.o
-O_OBJS   := math.o fabsq.o faddq.o fdivq.o fdmulq.o fitoq.o 		\
-		fmovq.o fmulq.o fnegq.o fqtoi.o fqtox.o fsubq.o		\
-		fxtoq.o fdtoq.o fstoq.o fqtos.o fqtod.o fsqrtq.o	\
-		fcmpq.o fcmpeq.o					\
-		fsqrts.o fsqrtd.o fadds.o faddd.o fsubs.o fsubd.o	\
-		fmuls.o fmuld.o fdivs.o fdivd.o fsmuld.o		\
-		fstoi.o fdtoi.o fstox.o fdtox.o fstod.o fdtos.o
+O_OBJS   := math.o
+CFLAGS += -I. -I$(TOPDIR)/include/math-emu -w
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/double.h linux/arch/sparc64/math-emu/double.h
--- v2.3.15/linux/arch/sparc64/math-emu/double.h	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/double.h	Wed Dec 31 16:00:00 1969
@@ -1,197 +0,0 @@
-/* Software floating-point emulation.
-   Definitions for IEEE Double Precision
-   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Richard Henderson (rth@cygnus.com),
-		  Jakub Jelinek (jj@ultra.linux.cz),
-		  David S. Miller (davem@redhat.com) and
-		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel kid.  Go buy yourself a real computer."
-#endif
-
-#if _FP_W_TYPE_SIZE < 64
-#define _FP_FRACTBITS_D		(2 * _FP_W_TYPE_SIZE)
-#else
-#define _FP_FRACTBITS_D		_FP_W_TYPE_SIZE
-#endif
-
-#define _FP_FRACBITS_D		53
-#define _FP_FRACXBITS_D		(_FP_FRACTBITS_D - _FP_FRACBITS_D)
-#define _FP_WFRACBITS_D		(_FP_WORKBITS + _FP_FRACBITS_D)
-#define _FP_WFRACXBITS_D	(_FP_FRACTBITS_D - _FP_WFRACBITS_D)
-#define _FP_EXPBITS_D		11
-#define _FP_EXPBIAS_D		1023
-#define _FP_EXPMAX_D		2047
-
-#define _FP_QNANBIT_D		\
-	((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE)
-#define _FP_IMPLBIT_D		\
-	((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE)
-#define _FP_OVERFLOW_D		\
-	((_FP_W_TYPE)1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE)
-
-#if _FP_W_TYPE_SIZE < 64
-
-union _FP_UNION_D
-{
-  double flt;
-  struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
-    unsigned sign  : 1;
-    unsigned exp   : _FP_EXPBITS_D;
-    unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
-    unsigned frac0 : _FP_W_TYPE_SIZE;
-#else
-    unsigned frac0 : _FP_W_TYPE_SIZE;
-    unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
-    unsigned exp   : _FP_EXPBITS_D;
-    unsigned sign  : 1;
-#endif
-  } bits __attribute__((packed));
-};
-
-#define FP_DECL_D(X)		_FP_DECL(2,X)
-#define FP_UNPACK_RAW_D(X,val)	_FP_UNPACK_RAW_2(D,X,val)
-#define FP_UNPACK_RAW_DP(X,val)	_FP_UNPACK_RAW_2_P(D,X,val)
-#define FP_PACK_RAW_D(val,X)	_FP_PACK_RAW_2(D,val,X)
-#define FP_PACK_RAW_DP(val,X)		\
-  do {					\
-    if (!FP_INHIBIT_RESULTS)		\
-      _FP_PACK_RAW_2_P(D,val,X);	\
-  } while (0)
-
-#define FP_UNPACK_D(X,val)		\
-  do {					\
-    _FP_UNPACK_RAW_2(D,X,val);		\
-    _FP_UNPACK_CANONICAL(D,2,X);	\
-  } while (0)
-
-#define FP_UNPACK_DP(X,val)		\
-  do {					\
-    _FP_UNPACK_RAW_2_P(D,X,val);	\
-    _FP_UNPACK_CANONICAL(D,2,X);	\
-  } while (0)
-
-#define FP_PACK_D(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(D,2,X);		\
-    _FP_PACK_RAW_2(D,val,X);		\
-  } while (0)
-
-#define FP_PACK_DP(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(D,2,X);		\
-    if (!FP_INHIBIT_RESULTS)		\
-      _FP_PACK_RAW_2_P(D,val,X);	\
-  } while (0)
-
-#define FP_ISSIGNAN_D(X)		_FP_ISSIGNAN(D,2,X)
-#define FP_NEG_D(R,X)			_FP_NEG(D,2,R,X)
-#define FP_ADD_D(R,X,Y)			_FP_ADD(D,2,R,X,Y)
-#define FP_SUB_D(R,X,Y)			_FP_SUB(D,2,R,X,Y)
-#define FP_MUL_D(R,X,Y)			_FP_MUL(D,2,R,X,Y)
-#define FP_DIV_D(R,X,Y)			_FP_DIV(D,2,R,X,Y)
-#define FP_SQRT_D(R,X)			_FP_SQRT(D,2,R,X)
-#define _FP_SQRT_MEAT_D(R,S,T,X,Q)	_FP_SQRT_MEAT_2(R,S,T,X,Q)
-
-#define FP_CMP_D(r,X,Y,un)	_FP_CMP(D,2,r,X,Y,un)
-#define FP_CMP_EQ_D(r,X,Y)	_FP_CMP_EQ(D,2,r,X,Y)
-
-#define FP_TO_INT_D(r,X,rsz,rsg)	_FP_TO_INT(D,2,r,X,rsz,rsg)
-#define FP_FROM_INT_D(X,r,rs,rt)	_FP_FROM_INT(D,2,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_D(X)	_FP_FRAC_HIGH_2(X)
-#define _FP_FRAC_HIGH_RAW_D(X)	_FP_FRAC_HIGH_2(X)
-
-#else
-
-union _FP_UNION_D
-{
-  double flt;
-  struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
-    unsigned sign : 1;
-    unsigned exp  : _FP_EXPBITS_D;
-    unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
-#else
-    unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
-    unsigned exp  : _FP_EXPBITS_D;
-    unsigned sign : 1;
-#endif
-  } bits __attribute__((packed));
-};
-
-#define FP_DECL_D(X)		_FP_DECL(1,X)
-#define FP_UNPACK_RAW_D(X,val)	_FP_UNPACK_RAW_1(D,X,val)
-#define FP_UNPACK_RAW_DP(X,val)	_FP_UNPACK_RAW_1_P(D,X,val)
-#define FP_PACK_RAW_D(val,X)	_FP_PACK_RAW_1(D,val,X)
-#define FP_PACK_RAW_DP(val,X)		\
-  do {					\
-    if (!FP_INHIBIT_RESULTS)		\
-      _FP_PACK_RAW_1_P(D,val,X);	\
-  } while (0)
-
-#define FP_UNPACK_D(X,val)		\
-  do {					\
-    _FP_UNPACK_RAW_1(D,X,val);		\
-    _FP_UNPACK_CANONICAL(D,1,X);	\
-  } while (0)
-
-#define FP_UNPACK_DP(X,val)		\
-  do {					\
-    _FP_UNPACK_RAW_1_P(D,X,val);	\
-    _FP_UNPACK_CANONICAL(D,1,X);	\
-  } while (0)
-
-#define FP_PACK_D(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(D,1,X);		\
-    _FP_PACK_RAW_1(D,val,X);		\
-  } while (0)
-
-#define FP_PACK_DP(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(D,1,X);		\
-    if (!FP_INHIBIT_RESULTS)		\
-      _FP_PACK_RAW_1_P(D,val,X);	\
-  } while (0)
-
-#define FP_ISSIGNAN_D(X)		_FP_ISSIGNAN(D,1,X)
-#define FP_NEG_D(R,X)			_FP_NEG(D,1,R,X)
-#define FP_ADD_D(R,X,Y)			_FP_ADD(D,1,R,X,Y)
-#define FP_SUB_D(R,X,Y)			_FP_SUB(D,1,R,X,Y)
-#define FP_MUL_D(R,X,Y)			_FP_MUL(D,1,R,X,Y)
-#define FP_DIV_D(R,X,Y)			_FP_DIV(D,1,R,X,Y)
-#define FP_SQRT_D(R,X)			_FP_SQRT(D,1,R,X)
-#define _FP_SQRT_MEAT_D(R,S,T,X,Q)	_FP_SQRT_MEAT_1(R,S,T,X,Q)
-
-/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
-   the target machine.  */
-
-#define FP_CMP_D(r,X,Y,un)	_FP_CMP(D,1,r,X,Y,un)
-#define FP_CMP_EQ_D(r,X,Y)	_FP_CMP_EQ(D,1,r,X,Y)
-
-#define FP_TO_INT_D(r,X,rsz,rsg)	_FP_TO_INT(D,1,r,X,rsz,rsg)
-#define FP_FROM_INT_D(X,r,rs,rt)	_FP_FROM_INT(D,1,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_D(X)	_FP_FRAC_HIGH_1(X)
-#define _FP_FRAC_HIGH_RAW_D(X)	_FP_FRAC_HIGH_1(X)
-
-#endif /* W_TYPE_SIZE < 64 */
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/extended.h linux/arch/sparc64/math-emu/extended.h
--- v2.3.15/linux/arch/sparc64/math-emu/extended.h	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/extended.h	Wed Dec 31 16:00:00 1969
@@ -1,388 +0,0 @@
-/* Software floating-point emulation.
-   Definitions for IEEE Extended Precision.
-   Copyright (C) 1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Jakub Jelinek (jj@ultra.linux.cz).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel, kid. Go buy yourself a real computer."
-#endif
-
-#if _FP_W_TYPE_SIZE < 64
-#define _FP_FRACTBITS_E         (4*_FP_W_TYPE_SIZE)
-#else
-#define _FP_FRACTBITS_E		(2*_FP_W_TYPE_SIZE)
-#endif
-
-#define _FP_FRACBITS_E		64
-#define _FP_FRACXBITS_E		(_FP_FRACTBITS_E - _FP_FRACBITS_E)
-#define _FP_WFRACBITS_E		(_FP_WORKBITS + _FP_FRACBITS_E)
-#define _FP_WFRACXBITS_E	(_FP_FRACTBITS_E - _FP_WFRACBITS_E)
-#define _FP_EXPBITS_E		15
-#define _FP_EXPBIAS_E		16383
-#define _FP_EXPMAX_E		32767
-
-#define _FP_QNANBIT_E		\
-	((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2) % _FP_W_TYPE_SIZE)
-#define _FP_IMPLBIT_E		\
-	((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1) % _FP_W_TYPE_SIZE)
-#define _FP_OVERFLOW_E		\
-	((_FP_W_TYPE)1 << (_FP_WFRACBITS_E % _FP_W_TYPE_SIZE))
-
-#if _FP_W_TYPE_SIZE < 64
-
-union _FP_UNION_E
-{
-   long double flt;
-   struct 
-   {
-#if __BYTE_ORDER == __BIG_ENDIAN
-      unsigned long pad1 : _FP_W_TYPE_SIZE;
-      unsigned long pad2 : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
-      unsigned long sign : 1;
-      unsigned long exp : _FP_EXPBITS_E;
-      unsigned long frac1 : _FP_W_TYPE_SIZE;
-      unsigned long frac0 : _FP_W_TYPE_SIZE;
-#else
-      unsigned long frac0 : _FP_W_TYPE_SIZE;
-      unsigned long frac1 : _FP_W_TYPE_SIZE;
-      unsigned exp : _FP_EXPBITS_E;
-      unsigned sign : 1;
-#endif /* not bigendian */
-   } bits __attribute__((packed));
-};
-
-
-#define FP_DECL_E(X)		_FP_DECL(4,X)
-
-#define FP_UNPACK_RAW_E(X, val)				\
-  do {							\
-    union _FP_UNION_E _flo; _flo.flt = (val);		\
-							\
-    X##_f[2] = 0; X##_f[3] = 0;				\
-    X##_f[0] = _flo.bits.frac0;				\
-    X##_f[1] = _flo.bits.frac1;				\
-    X##_e  = _flo.bits.exp;				\
-    X##_s  = _flo.bits.sign;				\
-    if (!X##_e && (X##_f[1] || X##_f[0])		\
-        && !(X##_f[1] & _FP_IMPLBIT_E))			\
-      {							\
-        X##_e++;					\
-        FP_SET_EXCEPTION(FP_EX_DENORM);			\
-      }							\
-  } while (0)
-
-#define FP_UNPACK_RAW_EP(X, val)			\
-  do {							\
-    union _FP_UNION_E *_flo =				\
-    (union _FP_UNION_E *)(val);				\
-							\
-    X##_f[2] = 0; X##_f[3] = 0;				\
-    X##_f[0] = _flo->bits.frac0;			\
-    X##_f[1] = _flo->bits.frac1;			\
-    X##_e  = _flo->bits.exp;				\
-    X##_s  = _flo->bits.sign;				\
-    if (!X##_e && (X##_f[1] || X##_f[0])		\
-        && !(X##_f[1] & _FP_IMPLBIT_E))			\
-      {							\
-        X##_e++;					\
-        FP_SET_EXCEPTION(FP_EX_DENORM);			\
-      }							\
-  } while (0)
-
-#define FP_PACK_RAW_E(val, X)				\
-  do {							\
-    union _FP_UNION_E _flo;				\
-							\
-    if (X##_e) X##_f[1] |= _FP_IMPLBIT_E;		\
-    else X##_f[1] &= ~(_FP_IMPLBIT_E);			\
-    _flo.bits.frac0 = X##_f[0];				\
-    _flo.bits.frac1 = X##_f[1];				\
-    _flo.bits.exp   = X##_e;				\
-    _flo.bits.sign  = X##_s;				\
-							\
-    (val) = _flo.flt;					\
-  } while (0)
-
-#define FP_PACK_RAW_EP(val, X)				\
-  do {							\
-    if (!FP_INHIBIT_RESULTS)				\
-      {							\
-	union _FP_UNION_E *_flo =			\
-	  (union _FP_UNION_E *)(val);			\
-							\
-	if (X##_e) X##_f[1] |= _FP_IMPLBIT_E;		\
-	else X##_f[1] &= ~(_FP_IMPLBIT_E);		\
-	_flo->bits.frac0 = X##_f[0];			\
-	_flo->bits.frac1 = X##_f[1];			\
-	_flo->bits.exp   = X##_e;			\
-	_flo->bits.sign  = X##_s;			\
-      }							\
-  } while (0)
-
-#define FP_UNPACK_E(X,val)		\
-  do {					\
-    FP_UNPACK_RAW_E(X,val);		\
-    _FP_UNPACK_CANONICAL(E,4,X);	\
-  } while (0)
-
-#define FP_UNPACK_EP(X,val)		\
-  do {					\
-    FP_UNPACK_RAW_2_P(X,val);		\
-    _FP_UNPACK_CANONICAL(E,4,X);	\
-  } while (0)
-
-#define FP_PACK_E(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(E,4,X);		\
-    FP_PACK_RAW_E(val,X);		\
-  } while (0)
-
-#define FP_PACK_EP(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(E,4,X);		\
-    FP_PACK_RAW_EP(val,X);		\
-  } while (0)
-
-#define FP_ISSIGNAN_E(X)	_FP_ISSIGNAN(E,4,X)
-#define FP_NEG_E(R,X)		_FP_NEG(E,4,R,X)
-#define FP_ADD_E(R,X,Y)		_FP_ADD(E,4,R,X,Y)
-#define FP_SUB_E(R,X,Y)		_FP_SUB(E,4,R,X,Y)
-#define FP_MUL_E(R,X,Y)		_FP_MUL(E,4,R,X,Y)
-#define FP_DIV_E(R,X,Y)		_FP_DIV(E,4,R,X,Y)
-#define FP_SQRT_E(R,X)		_FP_SQRT(E,4,R,X)
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- * This has special _E version because standard _4 square
- * root would not work (it has to start normally with the
- * second word and not the first), but as we have to do it
- * anyway, we optimize it by doing most of the calculations
- * in two UWtype registers instead of four.
- */
- 
-#define _FP_SQRT_MEAT_E(R, S, T, X, q)			\
-  do {							\
-    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
-    _FP_FRAC_SRL_4(X, (_FP_WORKBITS));			\
-    while (q)						\
-      {							\
-	T##_f[1] = S##_f[1] + q;			\
-	if (T##_f[1] <= X##_f[1])			\
-	  {						\
-	    S##_f[1] = T##_f[1] + q;			\
-	    X##_f[1] -= T##_f[1];			\
-	    R##_f[1] += q;				\
-	  }						\
-	_FP_FRAC_SLL_2(X, 1);				\
-	q >>= 1;					\
-      }							\
-    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
-    while (q)						\
-      {							\
-	T##_f[0] = S##_f[0] + q;			\
-	T##_f[1] = S##_f[1];				\
-	if (T##_f[1] < X##_f[1] || 			\
-	    (T##_f[1] == X##_f[1] &&			\
-	     T##_f[0] <= X##_f[0]))			\
-	  {						\
-	    S##_f[0] = T##_f[0] + q;			\
-	    S##_f[1] += (T##_f[0] > S##_f[0]);		\
-	    _FP_FRAC_DEC_2(X, T);			\
-	    R##_f[0] += q;				\
-	  }						\
-	_FP_FRAC_SLL_2(X, 1);				\
-	q >>= 1;					\
-      }							\
-    _FP_FRAC_SLL_4(R, (_FP_WORKBITS));			\
-    if (X##_f[0] | X##_f[1])				\
-      {							\
-	if (S##_f[1] < X##_f[1] || 			\
-	    (S##_f[1] == X##_f[1] &&			\
-	     S##_f[0] < X##_f[0]))			\
-	  R##_f[0] |= _FP_WORK_ROUND;			\
-	R##_f[0] |= _FP_WORK_STICKY;			\
-      }							\
-  } while (0)
-
-#define FP_CMP_E(r,X,Y,un)	_FP_CMP(E,4,r,X,Y,un)
-#define FP_CMP_EQ_E(r,X,Y)	_FP_CMP_EQ(E,4,r,X,Y)
-
-#define FP_TO_INT_E(r,X,rsz,rsg)	_FP_TO_INT(E,4,r,X,rsz,rsg)
-#define FP_FROM_INT_E(X,r,rs,rt)	_FP_FROM_INT(E,4,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_E(X)	(X##_f[2])
-#define _FP_FRAC_HIGH_RAW_E(X)	(X##_f[1])
-
-#else   /* not _FP_W_TYPE_SIZE < 64 */
-union _FP_UNION_E
-{
-  long double flt /* __attribute__((mode(TF))) */ ;
-  struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
-    unsigned long pad : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
-    unsigned sign  : 1;
-    unsigned exp   : _FP_EXPBITS_E;
-    unsigned long frac : _FP_W_TYPE_SIZE;
-#else
-    unsigned long frac : _FP_W_TYPE_SIZE;
-    unsigned exp   : _FP_EXPBITS_E;
-    unsigned sign  : 1;
-#endif
-  } bits;
-};
-
-#define FP_DECL_E(X)		_FP_DECL(2,X)
-
-#define FP_UNPACK_RAW_E(X, val)					\
-  do {								\
-    union _FP_UNION_E _flo; _flo.flt = (val);			\
-								\
-    X##_f0 = _flo.bits.frac;					\
-    X##_f1 = 0;							\
-    X##_e = _flo.bits.exp;					\
-    X##_s = _flo.bits.sign;					\
-    if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E))		\
-      {								\
-        X##_e++;						\
-        FP_SET_EXCEPTION(FP_EX_DENORM);				\
-      }								\
-  } while (0)
-
-#define FP_UNPACK_RAW_EP(X, val)				\
-  do {								\
-    union _FP_UNION_E *_flo =					\
-      (union _FP_UNION_E *)(val);				\
-								\
-    X##_f0 = _flo->bits.frac;					\
-    X##_f1 = 0;							\
-    X##_e = _flo->bits.exp;					\
-    X##_s = _flo->bits.sign;					\
-    if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E))		\
-      {								\
-        X##_e++;						\
-        FP_SET_EXCEPTION(FP_EX_DENORM);				\
-      }								\
-  } while (0)
-
-#define FP_PACK_RAW_E(val, X)					\
-  do {								\
-    union _FP_UNION_E _flo;					\
-								\
-    if (X##_e) X##_f0 |= _FP_IMPLBIT_E;				\
-    else X##_f0 &= ~(_FP_IMPLBIT_E);				\
-    _flo.bits.frac = X##_f0;					\
-    _flo.bits.exp  = X##_e;					\
-    _flo.bits.sign = X##_s;					\
-								\
-    (val) = _flo.flt;						\
-  } while (0)
-
-#define FP_PACK_RAW_EP(fs, val, X)				\
-  do {								\
-    if (!FP_INHIBIT_RESULTS)					\
-      {								\
-	union _FP_UNION_E *_flo =				\
-	  (union _FP_UNION_E *)(val);				\
-								\
-	if (X##_e) X##_f0 |= _FP_IMPLBIT_E;			\
-	else X##_f0 &= ~(_FP_IMPLBIT_E);			\
-	_flo->bits.frac = X##_f0;				\
-	_flo->bits.exp  = X##_e;				\
-	_flo->bits.sign = X##_s;				\
-      }								\
-  } while (0)
-
-
-#define FP_UNPACK_E(X,val)		\
-  do {					\
-    FP_UNPACK_RAW_E(X,val);		\
-    _FP_UNPACK_CANONICAL(E,2,X);	\
-  } while (0)
-
-#define FP_UNPACK_EP(X,val)		\
-  do {					\
-    FP_UNPACK_RAW_EP(X,val);		\
-    _FP_UNPACK_CANONICAL(E,2,X);	\
-  } while (0)
-
-#define FP_PACK_E(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(E,2,X);		\
-    FP_PACK_RAW_E(val,X);		\
-  } while (0)
-
-#define FP_PACK_EP(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(E,2,X);		\
-    FP_PACK_RAW_EP(val,X);		\
-  } while (0)
-
-#define FP_ISSIGNAN_E(X)	_FP_ISSIGNAN(E,2,X)
-#define FP_NEG_E(R,X)		_FP_NEG(E,2,R,X)
-#define FP_ADD_E(R,X,Y)		_FP_ADD(E,2,R,X,Y)
-#define FP_SUB_E(R,X,Y)		_FP_SUB(E,2,R,X,Y)
-#define FP_MUL_E(R,X,Y)		_FP_MUL(E,2,R,X,Y)
-#define FP_DIV_E(R,X,Y)		_FP_DIV(E,2,R,X,Y)
-#define FP_SQRT_E(R,X)		_FP_SQRT(E,2,R,X)
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- * We optimize it by doing most of the calculations
- * in one UWtype registers instead of two, although we don't
- * have to.
- */
-#define _FP_SQRT_MEAT_E(R, S, T, X, q)			\
-  do {							\
-    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
-    _FP_FRAC_SRL_2(X, (_FP_WORKBITS));			\
-    while (q)						\
-      {							\
-        T##_f0 = S##_f0 + q;				\
-        if (T##_f0 <= X##_f0)				\
-          {						\
-            S##_f0 = T##_f0 + q;			\
-            X##_f0 -= T##_f0;				\
-            R##_f0 += q;				\
-          }						\
-        _FP_FRAC_SLL_1(X, 1);				\
-        q >>= 1;					\
-      }							\
-    _FP_FRAC_SLL_2(R, (_FP_WORKBITS));			\
-    if (X##_f0)						\
-      {							\
-	if (S##_f0 < X##_f0)				\
-	  R##_f0 |= _FP_WORK_ROUND;			\
-	R##_f0 |= _FP_WORK_STICKY;			\
-      }							\
-  } while (0)
- 
-#define FP_CMP_E(r,X,Y,un)	_FP_CMP(E,2,r,X,Y,un)
-#define FP_CMP_EQ_E(r,X,Y)	_FP_CMP_EQ(E,2,r,X,Y)
-
-#define FP_TO_INT_E(r,X,rsz,rsg)	_FP_TO_INT(E,2,r,X,rsz,rsg)
-#define FP_FROM_INT_E(X,r,rs,rt)	_FP_FROM_INT(E,2,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_E(X)	(X##_f1)
-#define _FP_FRAC_HIGH_RAW_E(X)	(X##_f0)
-
-#endif /* not _FP_W_TYPE_SIZE < 64 */
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fabsq.c linux/arch/sparc64/math-emu/fabsq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fabsq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fabsq.c	Wed Dec 31 16:00:00 1969
@@ -1,13 +0,0 @@
-/* $Id: fabsq.c,v 1.5 1999/05/28 13:42:27 jj Exp $
- * arch/sparc64/math-emu/fabsq.c
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@ultra.linux.cz)
- *
- */
-
-int FABSQ(unsigned long *rd, unsigned long *rs2)
-{
-	rd[0] = rs2[0] & 0x7fffffffffffffffUL;
-	rd[1] = rs2[1];
-	return 0;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/faddd.c linux/arch/sparc64/math-emu/faddd.c
--- v2.3.15/linux/arch/sparc64/math-emu/faddd.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/faddd.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: faddd.c,v 1.4 1999/05/28 13:43:17 jj Exp $
- * arch/sparc64/math-emu/faddd.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FADDD(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
-
-	FP_UNPACK_DP(A, rs1);
-	FP_UNPACK_DP(B, rs2);
-	FP_ADD_D(R, A, B);
-	FP_PACK_DP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/faddq.c linux/arch/sparc64/math-emu/faddq.c
--- v2.3.15/linux/arch/sparc64/math-emu/faddq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/faddq.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: faddq.c,v 1.4 1999/05/28 13:43:19 jj Exp $
- * arch/sparc64/math-emu/faddq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FADDQ(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
-
-	FP_UNPACK_QP(A, rs1);
-	FP_UNPACK_QP(B, rs2);
-	FP_ADD_Q(R, A, B);
-	FP_PACK_QP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fadds.c linux/arch/sparc64/math-emu/fadds.c
--- v2.3.15/linux/arch/sparc64/math-emu/fadds.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fadds.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fadds.c,v 1.4 1999/05/28 13:43:25 jj Exp $
- * arch/sparc64/math-emu/fadds.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FADDS(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
-
-	FP_UNPACK_SP(A, rs1);
-	FP_UNPACK_SP(B, rs2);
-	FP_ADD_S(R, A, B);
-	FP_PACK_SP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fcmpeq.c linux/arch/sparc64/math-emu/fcmpeq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fcmpeq.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/math-emu/fcmpeq.c	Wed Dec 31 16:00:00 1969
@@ -1,39 +0,0 @@
-/* $Id: fcmpeq.c,v 1.6 1999/07/30 09:35:40 davem Exp $
- * arch/sparc64/math-emu/fcmpeq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FCMPEQ(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_Q(B);
-	long ret;
-	long fccno = (long)rd;
-	unsigned long fsr;
-	
-	FP_UNPACK_RAW_QP(A, rs1);
-	FP_UNPACK_RAW_QP(B, rs2);
-	FP_CMP_Q(ret, B, A, 3);
-	if (ret == 3)
-		FP_SET_EXCEPTION(FP_EX_INVALID);
-	if (!FP_INHIBIT_RESULTS) {
-		rd = (void *)(((long)rd)&~3);
-		if (ret == -1) ret = 2;
-		fsr = current->thread.xfsr[0];
-		switch (fccno) {
-		case 0: fsr &= ~0xc00; fsr |= (ret << 10); break;
-		case 1: fsr &= ~0x300000000UL; fsr |= (ret << 32); break;
-		case 2: fsr &= ~0xc00000000UL; fsr |= (ret << 34); break;
-		case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break;
-		}
-		current->thread.xfsr[0] = fsr;
-	}
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fcmpq.c linux/arch/sparc64/math-emu/fcmpq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fcmpq.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/math-emu/fcmpq.c	Wed Dec 31 16:00:00 1969
@@ -1,39 +0,0 @@
-/* $Id: fcmpq.c,v 1.6 1999/07/30 09:35:40 davem Exp $
- * arch/sparc64/math-emu/fcmpq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FCMPQ(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_Q(B);
-	long ret;
-	long fccno = (long)rd;
-	unsigned long fsr;
-	
-	FP_UNPACK_RAW_QP(A, rs1);
-	FP_UNPACK_RAW_QP(B, rs2);
-	FP_CMP_Q(ret, B, A, 3);
-	if (ret == 3 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
-		FP_SET_EXCEPTION(FP_EX_INVALID);
-	if (!FP_INHIBIT_RESULTS) {
-		rd = (void *)(((long)rd)&~3);
-		if (ret == -1) ret = 2;
-		fsr = current->thread.xfsr[0];
-		switch (fccno) {
-		case 0: fsr &= ~0xc00; fsr |= (ret << 10); break;
-		case 1: fsr &= ~0x300000000UL; fsr |= (ret << 32); break;
-		case 2: fsr &= ~0xc00000000UL; fsr |= (ret << 34); break;
-		case 3: fsr &= ~0x3000000000UL; fsr |= (ret << 36); break;
-		}
-		current->thread.xfsr[0] = fsr;
-	}
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fdivd.c linux/arch/sparc64/math-emu/fdivd.c
--- v2.3.15/linux/arch/sparc64/math-emu/fdivd.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fdivd.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fdivd.c,v 1.4 1999/05/28 13:43:36 jj Exp $
- * arch/sparc64/math-emu/fdivd.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FDIVD(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
-
-	FP_UNPACK_DP(A, rs1);
-	FP_UNPACK_DP(B, rs2);
-	FP_DIV_D(R, A, B);
-	FP_PACK_DP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fdivq.c linux/arch/sparc64/math-emu/fdivq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fdivq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fdivq.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fdivq.c,v 1.4 1999/05/28 13:43:41 jj Exp $
- * arch/sparc64/math-emu/fdivq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FDIVQ(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
-
-	FP_UNPACK_QP(A, rs1);
-	FP_UNPACK_QP(B, rs2);
-	FP_DIV_Q(R, A, B);
-	FP_PACK_QP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fdivs.c linux/arch/sparc64/math-emu/fdivs.c
--- v2.3.15/linux/arch/sparc64/math-emu/fdivs.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fdivs.c	Wed Dec 31 16:00:00 1969
@@ -1,24 +0,0 @@
-/* $Id: fdivs.c,v 1.4 1999/05/28 13:43:45 jj Exp $
- * arch/sparc64/math-emu/fdivs.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FDIVS(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
-
-	FP_UNPACK_SP(A, rs1);
-	FP_UNPACK_SP(B, rs2);
-	FP_DIV_S(R, A, B);
-	FP_PACK_SP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
-
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fdmulq.c linux/arch/sparc64/math-emu/fdmulq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fdmulq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fdmulq.c	Wed Dec 31 16:00:00 1969
@@ -1,26 +0,0 @@
-/* $Id: fdmulq.c,v 1.4 1999/05/28 13:43:48 jj Exp $
- * arch/sparc64/math-emu/fdmulq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "double.h"
-
-int FDMULQ(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_D(IN); FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
-
-	FP_UNPACK_DP(IN, rs1);
-	FP_CONV(Q,D,2,1,A,IN);
-	FP_UNPACK_DP(IN, rs2);
-	FP_CONV(Q,D,2,1,B,IN);
-	FP_MUL_Q(R, A, B);
-	FP_PACK_QP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fdtoi.c linux/arch/sparc64/math-emu/fdtoi.c
--- v2.3.15/linux/arch/sparc64/math-emu/fdtoi.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fdtoi.c	Wed Dec 31 16:00:00 1969
@@ -1,25 +0,0 @@
-/* $Id: fdtoi.c,v 1.3 1999/05/28 13:43:52 jj Exp $
- * arch/sparc64/math-emu/fdtoi.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#define FP_ROUNDMODE FP_RND_ZERO
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FDTOI(int *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A);
-	int r;
-
-	FP_UNPACK_DP(A, rs2);
-	FP_TO_INT_D(r, A, 32, 1);
-	if (!FP_INHIBIT_RESULTS)
-		*rd = r;
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fdtoq.c linux/arch/sparc64/math-emu/fdtoq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fdtoq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fdtoq.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fdtoq.c,v 1.4 1999/05/28 13:43:56 jj Exp $
- * arch/sparc64/math-emu/fdtoq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "double.h"
-
-int FDTOQ(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A); FP_DECL_Q(R);
-
-	FP_UNPACK_DP(A, rs2);
-	FP_CONV(Q,D,2,1,R,A);
-	FP_PACK_QP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fdtos.c linux/arch/sparc64/math-emu/fdtos.c
--- v2.3.15/linux/arch/sparc64/math-emu/fdtos.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fdtos.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fdtos.c,v 1.4 1999/05/28 13:43:58 jj Exp $
- * arch/sparc64/math-emu/fdtos.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
-
-int FDTOS(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A); FP_DECL_S(R);
-
-	FP_UNPACK_DP(A, rs2);
-	FP_CONV(S,D,1,1,R,A);
-	FP_PACK_SP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fdtox.c linux/arch/sparc64/math-emu/fdtox.c
--- v2.3.15/linux/arch/sparc64/math-emu/fdtox.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fdtox.c	Wed Dec 31 16:00:00 1969
@@ -1,25 +0,0 @@
-/* $Id: fdtox.c,v 1.3 1999/05/28 13:44:02 jj Exp $
- * arch/sparc64/math-emu/fdtox.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#define FP_ROUNDMODE FP_RND_ZERO
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FDTOX(long *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A);
-	long r;
-
-	FP_UNPACK_DP(A, rs2);
-	FP_TO_INT_D(r, A, 64, 1);
-	if (!FP_INHIBIT_RESULTS)
-		*rd = r;
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fitoq.c linux/arch/sparc64/math-emu/fitoq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fitoq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fitoq.c	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-/* $Id: fitoq.c,v 1.5 1999/05/28 13:44:06 jj Exp $
- * arch/sparc64/math-emu/fitoq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FITOQ(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(R);
-	int a = *(int *)rs2;
-
-	FP_FROM_INT_Q(R, a, 32, int);
-	FP_PACK_QP(rd, R);
-	return 0;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fmovq.c linux/arch/sparc64/math-emu/fmovq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fmovq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fmovq.c	Wed Dec 31 16:00:00 1969
@@ -1,13 +0,0 @@
-/* $Id: fmovq.c,v 1.2 1999/05/28 13:44:09 jj Exp $
- * arch/sparc64/math-emu/fmovq.c
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@ultra.linux.cz)
- *
- */
-
-int FMOVQ(unsigned long *rd, unsigned long *rs2)
-{
-	rd[0] = rs2[0];
-	rd[1] = rs2[1];
-	return 0;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fmuld.c linux/arch/sparc64/math-emu/fmuld.c
--- v2.3.15/linux/arch/sparc64/math-emu/fmuld.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fmuld.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fmuld.c,v 1.4 1999/05/28 13:44:11 jj Exp $
- * arch/sparc64/math-emu/fmuld.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FMULD(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
-
-	FP_UNPACK_DP(A, rs1);
-	FP_UNPACK_DP(B, rs2);
-	FP_MUL_D(R, A, B);
-	FP_PACK_DP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fmulq.c linux/arch/sparc64/math-emu/fmulq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fmulq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fmulq.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fmulq.c,v 1.4 1999/05/28 13:44:14 jj Exp $
- * arch/sparc64/math-emu/fmulq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FMULQ(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
-
-	FP_UNPACK_QP(A, rs1);
-	FP_UNPACK_QP(B, rs2);
-	FP_MUL_Q(R, A, B);
-	FP_PACK_QP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fmuls.c linux/arch/sparc64/math-emu/fmuls.c
--- v2.3.15/linux/arch/sparc64/math-emu/fmuls.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fmuls.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fmuls.c,v 1.4 1999/05/28 13:44:18 jj Exp $
- * arch/sparc64/math-emu/fmuls.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FMULS(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
-
-	FP_UNPACK_SP(A, rs1);
-	FP_UNPACK_SP(B, rs2);
-	FP_MUL_S(R, A, B);
-	FP_PACK_SP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fnegq.c linux/arch/sparc64/math-emu/fnegq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fnegq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fnegq.c	Wed Dec 31 16:00:00 1969
@@ -1,13 +0,0 @@
-/* $Id: fnegq.c,v 1.6 1999/05/28 13:44:21 jj Exp $
- * arch/sparc64/math-emu/fnegq.c
- *
- * Copyright (C) 1997 Jakub Jelinek (jj@ultra.linux.cz)
- *
- */
-
-int FNEGQ(unsigned long *rd, unsigned long *rs2)
-{
-	rd[0] = rs2[0] ^ 0x8000000000000000UL;
-	rd[1] = rs2[1];
-	return 0;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fqtod.c linux/arch/sparc64/math-emu/fqtod.c
--- v2.3.15/linux/arch/sparc64/math-emu/fqtod.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fqtod.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fqtod.c,v 1.4 1999/05/28 13:44:24 jj Exp $
- * arch/sparc64/math-emu/fqtod.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "double.h"
-
-int FQTOD(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_D(R);
-
-	FP_UNPACK_QP(A, rs2);
-	FP_CONV(D,Q,1,2,R,A);
-	FP_PACK_DP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fqtoi.c linux/arch/sparc64/math-emu/fqtoi.c
--- v2.3.15/linux/arch/sparc64/math-emu/fqtoi.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fqtoi.c	Wed Dec 31 16:00:00 1969
@@ -1,25 +0,0 @@
-/* $Id: fqtoi.c,v 1.4 1999/05/28 13:44:26 jj Exp $
- * arch/sparc64/math-emu/fqtoi.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#define FP_ROUNDMODE FP_RND_ZERO
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FQTOI(int *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A);
-	int r;
-
-	FP_UNPACK_QP(A, rs2);
-	FP_TO_INT_Q(r, A, 32, 1);
-	if (!FP_INHIBIT_RESULTS)
-		*rd = r;
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fqtos.c linux/arch/sparc64/math-emu/fqtos.c
--- v2.3.15/linux/arch/sparc64/math-emu/fqtos.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fqtos.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fqtos.c,v 1.4 1999/05/28 13:44:30 jj Exp $
- * arch/sparc64/math-emu/fqtos.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "single.h"
-
-int FQTOS(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_S(R);
-
-	FP_UNPACK_QP(A, rs2);
-	FP_CONV(S,Q,1,2,R,A);
-	FP_PACK_SP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fqtox.c linux/arch/sparc64/math-emu/fqtox.c
--- v2.3.15/linux/arch/sparc64/math-emu/fqtox.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fqtox.c	Wed Dec 31 16:00:00 1969
@@ -1,25 +0,0 @@
-/* $Id: fqtox.c,v 1.4 1999/05/28 13:44:34 jj Exp $
- * arch/sparc64/math-emu/fqtox.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#define FP_ROUNDMODE FP_RND_ZERO
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FQTOX(long *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A);
-	long r;
-
-	FP_UNPACK_QP(A, rs2);
-	FP_TO_INT_Q(r, A, 64, 1);
-	if (!FP_INHIBIT_RESULTS)
-		*rd = r;
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fsmuld.c linux/arch/sparc64/math-emu/fsmuld.c
--- v2.3.15/linux/arch/sparc64/math-emu/fsmuld.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fsmuld.c	Wed Dec 31 16:00:00 1969
@@ -1,26 +0,0 @@
-/* $Id: fsmuld.c,v 1.4 1999/05/28 13:44:37 jj Exp $
- * arch/sparc64/math-emu/fsmuld.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
-
-int FSMULD(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_S(IN); FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
-
-	FP_UNPACK_SP(IN, rs1);
-	FP_CONV(D,S,1,1,A,IN);
-	FP_UNPACK_SP(IN, rs2);
-	FP_CONV(D,S,1,1,B,IN);
-	FP_MUL_D(R, A, B);
-	FP_PACK_DP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fsqrtd.c linux/arch/sparc64/math-emu/fsqrtd.c
--- v2.3.15/linux/arch/sparc64/math-emu/fsqrtd.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fsqrtd.c	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-/* $Id: fsqrtd.c,v 1.4 1999/05/28 13:44:39 jj Exp $
- * arch/sparc64/math-emu/fsqrtd.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FSQRTD(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A); FP_DECL_D(R);
-        
-	FP_UNPACK_DP(A, rs2);
-	FP_SQRT_D(R, A);
-	FP_PACK_DP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fsqrtq.c linux/arch/sparc64/math-emu/fsqrtq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fsqrtq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fsqrtq.c	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-/* $Id: fsqrtq.c,v 1.5 1999/05/28 13:44:44 jj Exp $
- * arch/sparc64/math-emu/fsqrtq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FSQRTQ(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_Q(R);
-        
-	FP_UNPACK_QP(A, rs2);
-	FP_SQRT_Q(R, A);
-	FP_PACK_QP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fsqrts.c linux/arch/sparc64/math-emu/fsqrts.c
--- v2.3.15/linux/arch/sparc64/math-emu/fsqrts.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fsqrts.c	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-/* $Id: fsqrts.c,v 1.4 1999/05/28 13:44:48 jj Exp $
- * arch/sparc64/math-emu/fsqrts.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FSQRTS(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A); FP_DECL_S(R);
-        
-	FP_UNPACK_SP(A, rs2);
-	FP_SQRT_S(R, A);
-	FP_PACK_SP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fstod.c linux/arch/sparc64/math-emu/fstod.c
--- v2.3.15/linux/arch/sparc64/math-emu/fstod.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fstod.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fstod.c,v 1.4 1999/05/28 13:44:51 jj Exp $
- * arch/sparc64/math-emu/fstod.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-#include "single.h"
-
-int FSTOD(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A); FP_DECL_D(R);
-
-	FP_UNPACK_SP(A, rs2);
-	FP_CONV(D,S,1,1,R,A);
-	FP_PACK_DP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fstoi.c linux/arch/sparc64/math-emu/fstoi.c
--- v2.3.15/linux/arch/sparc64/math-emu/fstoi.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fstoi.c	Wed Dec 31 16:00:00 1969
@@ -1,25 +0,0 @@
-/* $Id: fstoi.c,v 1.3 1999/05/28 13:44:54 jj Exp $
- * arch/sparc64/math-emu/fstoi.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#define FP_ROUNDMODE FP_RND_ZERO
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FSTOI(int *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A);
-	int r;
-
-	FP_UNPACK_SP(A, rs2);
-	FP_TO_INT_S(r, A, 32, 1);
-	if (!FP_INHIBIT_RESULTS)
-		*rd = r;
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fstoq.c linux/arch/sparc64/math-emu/fstoq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fstoq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fstoq.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fstoq.c,v 1.4 1999/05/28 13:44:58 jj Exp $
- * arch/sparc64/math-emu/fstoq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-#include "single.h"
-
-int FSTOQ(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A); FP_DECL_Q(R);
-
-	FP_UNPACK_SP(A, rs2);
-	FP_CONV(Q,S,2,1,R,A);
-	FP_PACK_QP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fstox.c linux/arch/sparc64/math-emu/fstox.c
--- v2.3.15/linux/arch/sparc64/math-emu/fstox.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fstox.c	Wed Dec 31 16:00:00 1969
@@ -1,25 +0,0 @@
-/* $Id: fstox.c,v 1.3 1999/05/28 13:45:01 jj Exp $
- * arch/sparc64/math-emu/fstox.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#define FP_ROUNDMODE FP_RND_ZERO
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FSTOX(long *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A);
-	long r;
-
-	FP_UNPACK_SP(A, rs2);
-	FP_TO_INT_S(r, A, 64, 1);
-	if (!FP_INHIBIT_RESULTS)
-		*rd = r;
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fsubd.c linux/arch/sparc64/math-emu/fsubd.c
--- v2.3.15/linux/arch/sparc64/math-emu/fsubd.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/math-emu/fsubd.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fsubd.c,v 1.5 1999/08/02 14:08:04 jj Exp $
- * arch/sparc64/math-emu/fsubd.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "double.h"
-
-int FSUBD(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
-
-	FP_UNPACK_DP(A, rs1);
-	FP_UNPACK_DP(B, rs2);
-	FP_SUB_D(R, A, B);
-	FP_PACK_DP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fsubq.c linux/arch/sparc64/math-emu/fsubq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fsubq.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/math-emu/fsubq.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fsubq.c,v 1.5 1999/08/02 14:08:06 jj Exp $
- * arch/sparc64/math-emu/fsubq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FSUBQ(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
-
-	FP_UNPACK_QP(A, rs1);
-	FP_UNPACK_QP(B, rs2);
-	FP_SUB_Q(R, A, B);
-	FP_PACK_QP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fsubs.c linux/arch/sparc64/math-emu/fsubs.c
--- v2.3.15/linux/arch/sparc64/math-emu/fsubs.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/math-emu/fsubs.c	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/* $Id: fsubs.c,v 1.5 1999/08/02 14:08:07 jj Exp $
- * arch/sparc64/math-emu/fsubs.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "single.h"
-
-int FSUBS(void *rd, void *rs2, void *rs1)
-{
-	FP_DECL_EX;
-	FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
-
-	FP_UNPACK_SP(A, rs1);
-	FP_UNPACK_SP(B, rs2);
-	FP_SUB_S(R, A, B);
-	FP_PACK_SP(rd, R);
-	FP_HANDLE_EXCEPTIONS;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/fxtoq.c linux/arch/sparc64/math-emu/fxtoq.c
--- v2.3.15/linux/arch/sparc64/math-emu/fxtoq.c	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/fxtoq.c	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-/* $Id: fxtoq.c,v 1.5 1999/05/28 13:45:15 jj Exp $
- * arch/sparc64/math-emu/fxtoq.c
- *
- * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
- *
- */
-
-#include "sfp-util.h"
-#include "soft-fp.h"
-#include "quad.h"
-
-int FXTOQ(void *rd, void *rs2)
-{
-	FP_DECL_EX;
-	FP_DECL_Q(R);
-	long a = *(long *)rs2;
-
-	FP_FROM_INT_Q(R, a, 64, long);
-	FP_PACK_QP(rd, R);
-	return 0;
-}
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/math.c linux/arch/sparc64/math-emu/math.c
--- v2.3.15/linux/arch/sparc64/math-emu/math.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/math-emu/math.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: math.c,v 1.9 1999/07/30 09:35:41 davem Exp $
+/* $Id: math.c,v 1.10 1999/08/13 16:02:06 jj Exp $
  * arch/sparc64/math-emu/math.c
  *
  * Copyright (C) 1997,1999 Jakub Jelinek (jj@ultra.linux.cz)
@@ -17,46 +17,61 @@
 
 #include "sfp-util.h"
 #include "soft-fp.h"
-
-#define FLOATFUNC(x) extern int x(void *,void *,void *);
-
-FLOATFUNC(FMOVQ)
-FLOATFUNC(FNEGQ)
-FLOATFUNC(FABSQ)
-FLOATFUNC(FSQRTQ)
-FLOATFUNC(FADDQ)
-FLOATFUNC(FSUBQ)
-FLOATFUNC(FMULQ)
-FLOATFUNC(FDIVQ)
-FLOATFUNC(FDMULQ)
-FLOATFUNC(FQTOX)
-FLOATFUNC(FXTOQ)
-FLOATFUNC(FQTOS)
-FLOATFUNC(FQTOD)
-FLOATFUNC(FITOQ)
-FLOATFUNC(FSTOQ)
-FLOATFUNC(FDTOQ)
-FLOATFUNC(FQTOI)
-FLOATFUNC(FCMPQ)
-FLOATFUNC(FCMPEQ)
-
-FLOATFUNC(FSQRTS)
-FLOATFUNC(FSQRTD)
-FLOATFUNC(FADDS)
-FLOATFUNC(FADDD)
-FLOATFUNC(FSUBS)
-FLOATFUNC(FSUBD)
-FLOATFUNC(FMULS)
-FLOATFUNC(FMULD)
-FLOATFUNC(FDIVS)
-FLOATFUNC(FDIVD)
-FLOATFUNC(FSMULD)
-FLOATFUNC(FSTOX)
-FLOATFUNC(FDTOX)
-FLOATFUNC(FDTOS)
-FLOATFUNC(FSTOD)
-FLOATFUNC(FSTOI)
-FLOATFUNC(FDTOI)
+#include "single.h"
+#include "double.h"
+#include "quad.h"
+
+/* QUAD - ftt == 3 */
+#define FMOVQ	0x003
+#define FNEGQ	0x007
+#define FABSQ	0x00b
+#define FSQRTQ	0x02b
+#define FADDQ	0x043
+#define FSUBQ	0x047
+#define FMULQ	0x04b
+#define FDIVQ	0x04f
+#define FDMULQ	0x06e
+#define FQTOX	0x083
+#define FXTOQ	0x08c
+#define FQTOS	0x0c7
+#define FQTOD	0x0cb
+#define FITOQ	0x0cc
+#define FSTOQ	0x0cd
+#define FDTOQ	0x0ce
+#define FQTOI	0x0d3
+/* SUBNORMAL - ftt == 2 */
+#define FSQRTS	0x029
+#define FSQRTD	0x02a
+#define FADDS	0x041
+#define FADDD	0x042
+#define FSUBS	0x045
+#define FSUBD	0x046
+#define FMULS	0x049
+#define FMULD	0x04a
+#define FDIVS	0x04d
+#define FDIVD	0x04e
+#define FSMULD	0x069
+#define FSTOX	0x081
+#define FDTOX	0x082
+#define FDTOS	0x0c6
+#define FSTOD	0x0c9
+#define FSTOI	0x0d1
+#define FDTOI	0x0d2
+/* FPOP2 */
+#define FCMPQ	0x053
+#define FCMPEQ	0x057
+#define FMOVQ0	0x003
+#define FMOVQ1	0x043
+#define FMOVQ2	0x083
+#define FMOVQ3	0x0c3
+#define FMOVQI	0x103
+#define FMOVQX	0x183
+#define FMOVQZ	0x027
+#define FMOVQLE	0x047
+#define FMOVQLZ 0x067
+#define FMOVQNZ	0x0a7
+#define FMOVQGZ	0x0c7
+#define FMOVQGE 0x0e7
 
 #define FSR_TEM_SHIFT	23UL
 #define FSR_TEM_MASK	(0x1fUL << FSR_TEM_SHIFT)
@@ -73,7 +88,7 @@
  *
  * We return 0 if a SIGFPE should be sent, 1 otherwise.
  */
-static int record_exception(struct pt_regs *regs, int eflag)
+static inline int record_exception(struct pt_regs *regs, int eflag)
 {
 	u64 fsr = current->thread.xfsr[0];
 	int would_trap;
@@ -133,18 +148,31 @@
 	return (would_trap ? 0 : 1);
 }
 
+typedef union {
+	u32 s;
+	u64 d;
+	u64 q[2];
+} *argp;
+
 int do_mathemu(struct pt_regs *regs, struct fpustate *f)
 {
 	unsigned long pc = regs->tpc;
 	unsigned long tstate = regs->tstate;
 	u32 insn = 0;
-	int type = 0; /* 01 is single, 10 is double, 11 is quad, 
-			 000011 is rs1, 001100 is rs2, 110000 is rd (00 in rd is fcc)
-			 111100000000 tells which ftt may that happen in */
+	int type = 0;
+	/* ftt tells which ftt it may happen in, r is rd, b is rs2 and a is rs1. The *u arg tells
+	   whether the argument should be packed/unpacked (0 - do not unpack/pack, 1 - unpack/pack)
+	   non-u args tells the size of the argument (0 - no argument, 1 - single, 2 - double, 3 - quad */
+#define TYPE(ftt, r, ru, b, bu, a, au) type = (au << 2) | (a << 0) | (bu << 5) | (b << 3) | (ru << 8) | (r << 6) | (ftt << 9)
 	int freg;
 	static u64 zero[2] = { 0L, 0L };
 	int flags;
-	int (*func)(void *,void *,void *) = NULL;
+	FP_DECL_EX;
+	FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
+	FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
+	FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR);
+	int IR;
+	long XR, xfsr;
 
 	if(tstate & TSTATE_PRIV)
 		die_if_kernel("FPQuad from kernel", regs);
@@ -154,55 +182,145 @@
 		if ((insn & 0xc1f80000) == 0x81a00000) /* FPOP1 */ {
 			switch ((insn >> 5) & 0x1ff) {
 			/* QUAD - ftt == 3 */
-			case 0x003: type = 0x33c; func = FMOVQ; break;
-			case 0x007: type = 0x33c; func = FNEGQ; break;
-			case 0x00b: type = 0x33c; func = FABSQ; break;
-			case 0x02b: type = 0x33c; func = FSQRTQ; break;
-			case 0x043: type = 0x33f; func = FADDQ; break;
-			case 0x047: type = 0x33f; func = FSUBQ; break;
-			case 0x04b: type = 0x33f; func = FMULQ; break;
-			case 0x04f: type = 0x33f; func = FDIVQ; break;
-			case 0x06e: type = 0x33a; func = FDMULQ; break;
-			case 0x083: type = 0x32c; func = FQTOX; break;
-			case 0x08c: type = 0x338; func = FXTOQ; break;
-			case 0x0c7: type = 0x31c; func = FQTOS; break;
-			case 0x0cb: type = 0x32c; func = FQTOD; break;
-			case 0x0cc: type = 0x334; func = FITOQ; break;
-			case 0x0cd: type = 0x334; func = FSTOQ; break;
-			case 0x0ce: type = 0x338; func = FDTOQ; break;
-			case 0x0d3: type = 0x31c; func = FQTOI; break;
+			case FMOVQ:
+			case FNEGQ:
+			case FABSQ: TYPE(3,3,0,3,0,0,0); break;
+			case FSQRTQ: TYPE(3,3,1,3,1,0,0); break;
+			case FADDQ:
+			case FSUBQ:
+			case FMULQ:
+			case FDIVQ: TYPE(3,3,1,3,1,3,1); break;
+			case FDMULQ: TYPE(3,3,1,2,1,2,1); break;
+			case FQTOX: TYPE(3,2,0,3,1,0,0); break;
+			case FXTOQ: TYPE(3,3,1,2,0,0,0); break;
+			case FQTOS: TYPE(3,1,1,3,1,0,0); break;
+			case FQTOD: TYPE(3,2,1,3,1,0,0); break;
+			case FITOQ: TYPE(3,3,1,1,0,0,0); break;
+			case FSTOQ: TYPE(3,3,1,1,1,0,0); break;
+			case FDTOQ: TYPE(3,3,1,2,1,0,0); break;
+			case FQTOI: TYPE(3,1,0,3,1,0,0); break;
 			/* SUBNORMAL - ftt == 2 */
-			case 0x029: type = 0x214; func = FSQRTS; break;
-			case 0x02a: type = 0x228; func = FSQRTD; break;
-			case 0x041: type = 0x215; func = FADDS; break;
-			case 0x042: type = 0x22a; func = FADDD; break;
-			case 0x045: type = 0x215; func = FSUBS; break;
-			case 0x046: type = 0x22a; func = FSUBD; break;
-			case 0x049: type = 0x215; func = FMULS; break;
-			case 0x04a: type = 0x22a; func = FMULD; break;
-			case 0x04d: type = 0x215; func = FDIVS; break;
-			case 0x04e: type = 0x22a; func = FDIVD; break;
-			case 0x069: type = 0x225; func = FSMULD; break;
-			case 0x081: type = 0x224; func = FSTOX; break;
-			case 0x082: type = 0x228; func = FDTOX; break;
-			case 0x0c6: type = 0x218; func = FDTOS; break;
-			case 0x0c9: type = 0x224; func = FSTOD; break;
-			case 0x0d1: type = 0x214; func = FSTOI; break;
-			case 0x0d2: type = 0x218; func = FDTOI; break;
+			case FSQRTS: TYPE(2,1,1,1,1,0,0); break;
+			case FSQRTD: TYPE(2,2,1,2,1,0,0); break;
+			case FADDD:
+			case FSUBD:
+			case FMULD:
+			case FDIVD: TYPE(2,2,1,2,1,2,1); break;
+			case FADDS:
+			case FSUBS:
+			case FMULS:
+			case FDIVS: TYPE(2,1,1,1,1,1,1); break;
+			case FSMULD: TYPE(2,2,1,1,1,1,1); break;
+			case FSTOX: TYPE(2,2,0,1,1,0,0); break;
+			case FDTOX: TYPE(2,2,0,2,1,0,0); break;
+			case FDTOS: TYPE(2,1,1,2,1,0,0); break;
+			case FSTOD: TYPE(2,2,1,1,1,0,0); break;
+			case FSTOI: TYPE(2,1,0,1,1,0,0); break;
+			case FDTOI: TYPE(2,1,0,2,1,0,0); break;
 			}
 		}
 		else if ((insn & 0xc1f80000) == 0x81a80000) /* FPOP2 */ {
+			IR = 2;
 			switch ((insn >> 5) & 0x1ff) {
-			case 0x053: type = 0x30f; func = FCMPQ; break;
-			case 0x057: type = 0x30f; func = FCMPEQ; break;
+			case FCMPQ: TYPE(3,0,0,3,1,3,1); break;
+			case FCMPEQ: TYPE(3,0,0,3,1,3,1); break;
+			/* Now the conditional fmovq support */
+			case FMOVQ0:
+			case FMOVQ1:
+			case FMOVQ2:
+			case FMOVQ3:
+				/* fmovq %fccX, %fY, %fZ */
+				if (!((insn >> 11) & 3))
+					XR = current->thread.xfsr[0] >> 10;
+				else
+					XR = current->thread.xfsr[0] >> (30 + ((insn >> 10) & 0x6));
+				XR &= 3;
+				IR = 0;
+				switch ((insn >> 14) & 0x7) {
+				/* case 0: IR = 0; break; */			/* Never */
+				case 1: if (XR) IR = 1; break;			/* Not Equal */
+				case 2: if (XR == 1 || XR == 2) IR = 1; break;	/* Less or Greater */
+				case 3: if (XR & 1) IR = 1; break;		/* Unordered or Less */
+				case 4: if (XR == 1) IR = 1; break;		/* Less */
+				case 5: if (XR & 2) IR = 1; break;		/* Unordered or Greater */
+				case 6: if (XR == 2) IR = 1; break;		/* Greater */
+				case 7: if (XR == 3) IR = 1; break;		/* Unordered */
+				}
+				if ((insn >> 14) & 8)
+					IR ^= 1;
+				break;
+			case FMOVQI:
+			case FMOVQX:
+				/* fmovq %[ix]cc, %fY, %fZ */
+				XR = regs->tstate >> 32;
+				if ((insn >> 5) & 0x80)
+					XR >>= 4;
+				XR &= 0xf;
+				IR = 0;
+				freg = ((XR >> 2) ^ XR) & 2;
+				switch ((insn >> 14) & 0x7) {
+				/* case 0: IR = 0; break; */			/* Never */
+				case 1: if (XR & 4) IR = 1; break;		/* Equal */
+				case 2: if ((XR & 4) || freg) IR = 1; break;	/* Less or Equal */
+				case 3: if (freg) IR = 1; break;		/* Less */
+				case 4: if (XR & 5) IR = 1; break;		/* Less or Equal Unsigned */
+				case 5: if (XR & 1) IR = 1; break;		/* Carry Set */
+				case 6: if (XR & 8) IR = 1; break;		/* Negative */
+				case 7: if (XR & 2) IR = 1; break;		/* Overflow Set */
+				}
+				if ((insn >> 14) & 8)
+					IR ^= 1;
+				break;
+			case FMOVQZ:
+			case FMOVQLE:
+			case FMOVQLZ:
+			case FMOVQNZ:
+			case FMOVQGZ:
+			case FMOVQGE:
+				freg = (insn >> 14) & 0x1f;
+				if (!freg)
+					XR = 0;
+				else if (freg < 16)
+					XR = regs->u_regs[freg];
+				else if (current->thread.flags & SPARC_FLAG_32BIT) {
+					struct reg_window32 *win32;
+					flushw_user ();
+					win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+					get_user(XR, &win32->locals[freg - 16]);
+				} else {
+					struct reg_window *win;
+					flushw_user ();
+					win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+					get_user(XR, &win->locals[freg - 16]);
+				}
+				IR = 0;
+				switch ((insn >> 10) & 3) {
+				case 1: if (!XR) IR = 1; break;			/* Register Zero */
+				case 2: if (XR <= 0) IR = 1; break;		/* Register Less Than or Equal to Zero */
+				case 3: if (XR < 0) IR = 1; break;		/* Register Less Than Zero */
+				}
+				if ((insn >> 10) & 4)
+					IR ^= 1;
+				break;
+			}
+			if (IR == 0) {
+				/* The fmov test was false. Do a nop instead */
+				current->thread.xfsr[0] &= ~(FSR_CEXC_MASK);
+				regs->tpc = regs->tnpc;
+				regs->tnpc += 4;
+				return 1;
+			} else if (IR == 1) {
+				/* Change the instruction into plain fmovq */
+				insn = (insn & 0x3e00001f) | 0x81a00060;
+				TYPE(3,3,0,3,0,0,0); 
 			}
 		}
 	}
 	if (type) {
-		void *rs1 = NULL, *rs2 = NULL, *rd = NULL;
+		argp rs1 = NULL, rs2 = NULL, rd = NULL;
 		
 		freg = (current->thread.xfsr[0] >> 14) & 0xf;
-		if (freg != (type >> 8))
+		if (freg != (type >> 9))
 			goto err;
 		current->thread.xfsr[0] &= ~0x1c000;
 		freg = ((insn >> 14) & 0x1f);
@@ -212,34 +330,43 @@
 				goto err;
 			}
 		case 2: freg = ((freg & 1) << 5) | (freg & 0x1e);
-		case 1: rs1 = (void *)&f->regs[freg]; 
+		case 1: rs1 = (argp)&f->regs[freg];
 			flags = (freg < 32) ? FPRS_DL : FPRS_DU; 
 			if (!(current->thread.fpsaved[0] & flags))
-				rs1 = (void *)&zero;
+				rs1 = (argp)&zero;
 			break;
 		}
+		switch (type & 0x7) {
+		case 7: FP_UNPACK_QP (QA, rs1); break;
+		case 6: FP_UNPACK_DP (DA, rs1); break;
+		case 5: FP_UNPACK_SP (SA, rs1); break;
+		}
 		freg = (insn & 0x1f);
-		switch ((type >> 2) & 0x3) {
+		switch ((type >> 3) & 0x3) {
 		case 3: if (freg & 2) {
 				current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
 				goto err;
 			}
 		case 2: freg = ((freg & 1) << 5) | (freg & 0x1e);
-		case 1: rs2 = (void *)&f->regs[freg];
+		case 1: rs2 = (argp)&f->regs[freg];
 			flags = (freg < 32) ? FPRS_DL : FPRS_DU; 
 			if (!(current->thread.fpsaved[0] & flags))
-				rs2 = (void *)&zero;
+				rs2 = (argp)&zero;
 			break;
 		}
+		switch ((type >> 3) & 0x7) {
+		case 7: FP_UNPACK_QP (QB, rs2); break;
+		case 6: FP_UNPACK_DP (DB, rs2); break;
+		case 5: FP_UNPACK_SP (SB, rs2); break;
+		}
 		freg = ((insn >> 25) & 0x1f);
-		switch ((type >> 4) & 0x3) {
-		case 0: rd = (void *)(long)(freg & 3); break;
+		switch ((type >> 6) & 0x3) {
 		case 3: if (freg & 2) {
 				current->thread.xfsr[0] |= (6 << 14) /* invalid_fp_register */;
 				goto err;
 			}
 		case 2: freg = ((freg & 1) << 5) | (freg & 0x1e);
-		case 1: rd = (void *)&f->regs[freg];
+		case 1: rd = (argp)&f->regs[freg];
 			flags = (freg < 32) ? FPRS_DL : FPRS_DU; 
 			if (!(current->thread.fpsaved[0] & FPRS_FEF)) {
 				current->thread.fpsaved[0] = FPRS_FEF;
@@ -254,9 +381,85 @@
 			current->thread.fpsaved[0] |= flags;
 			break;
 		}
-		flags = func(rd, rs2, rs1);
-		if(flags != 0)
-			return record_exception(regs, flags);
+		switch ((insn >> 5) & 0x1ff) {
+		/* + */
+		case FADDS: FP_ADD_S (SR, SA, SB); break;
+		case FADDD: FP_ADD_D (DR, DA, DB); break;
+		case FADDQ: FP_ADD_Q (QR, QA, QB); break;
+		/* - */
+		case FSUBS: FP_SUB_S (SR, SA, SB); break;
+		case FSUBD: FP_SUB_D (DR, DA, DB); break;
+		case FSUBQ: FP_SUB_Q (QR, QA, QB); break;
+		/* * */
+		case FMULS: FP_MUL_S (SR, SA, SB); break;
+		case FSMULD: FP_CONV (D, S, 1, 1, DA, SA);
+			     FP_CONV (D, S, 1, 1, DB, SB);
+		case FMULD: FP_MUL_D (DR, DA, DB); break;
+		case FDMULQ: FP_CONV (Q, D, 2, 1, QA, DA);
+			     FP_CONV (Q, D, 2, 1, QB, DB);
+		case FMULQ: FP_MUL_Q (QR, QA, QB); break;
+		/* / */
+		case FDIVS: FP_DIV_S (SR, SA, SB); break;
+		case FDIVD: FP_DIV_D (DR, DA, DB); break;
+		case FDIVQ: FP_DIV_Q (QR, QA, QB); break;
+		/* sqrt */
+		case FSQRTS: FP_SQRT_S (SR, SB); break;
+		case FSQRTD: FP_SQRT_D (DR, DB); break;
+		case FSQRTQ: FP_SQRT_Q (QR, QB); break;
+		/* mov */
+		case FMOVQ: rd->q[0] = rs2->q[0]; rd->q[1] = rs2->q[1]; break;
+		case FABSQ: rd->q[0] = rs2->q[0] & 0x7fffffffffffffffUL; rd->q[1] = rs2->q[1]; break;
+		case FNEGQ: rd->q[0] = rs2->q[0] ^ 0x8000000000000000UL; rd->q[1] = rs2->q[1]; break;
+		/* float to int */
+		case FSTOI: FP_TO_INT_S (IR, SB, 32, 1); break;
+		case FDTOI: FP_TO_INT_D (IR, DB, 32, 1); break;
+		case FQTOI: FP_TO_INT_Q (IR, QB, 32, 1); break;
+		case FSTOX: FP_TO_INT_S (XR, SB, 64, 1); break;
+		case FDTOX: FP_TO_INT_D (XR, DB, 64, 1); break;
+		case FQTOX: FP_TO_INT_Q (XR, QB, 64, 1); break;
+		/* int to float */
+		case FITOQ: IR = rs2->s; FP_FROM_INT_Q (QR, IR, 32, int); break;
+		case FXTOQ: XR = rs2->d; FP_FROM_INT_Q (QR, XR, 64, long); break;
+		/* float to float */
+		case FSTOD: FP_CONV (D, S, 1, 1, DR, SB); break;
+		case FSTOQ: FP_CONV (Q, S, 2, 1, QR, SB); break;
+		case FDTOQ: FP_CONV (Q, D, 2, 1, QR, DB); break;
+		case FDTOS: FP_CONV (S, D, 1, 1, SR, DB); break;
+		case FQTOS: FP_CONV (S, Q, 1, 2, SR, QB); break;
+		case FQTOD: FP_CONV (D, Q, 1, 2, DR, QB); break;
+		/* comparison */
+		case FCMPQ:
+		case FCMPEQ:
+			FP_CMP_Q(XR, QB, QA, 3);
+			if (XR == 3 &&
+			    (((insn >> 5) & 0x1ff) == FCMPEQ ||
+			     FP_ISSIGNAN_Q(QA) ||
+			     FP_ISSIGNAN_Q(QB)))
+				FP_SET_EXCEPTION (FP_EX_INVALID);
+		}
+		if (!FP_INHIBIT_RESULTS) {
+			switch ((type >> 6) & 0x7) {
+			case 0: xfsr = current->thread.xfsr[0];
+				if (XR == -1) XR = 2;
+				switch (freg & 3) {
+				/* fcc0, 1, 2, 3 */
+				case 0: xfsr &= ~0xc00; xfsr |= (XR << 10); break;
+				case 1: xfsr &= ~0x300000000UL; xfsr |= (XR << 32); break;
+				case 2: xfsr &= ~0xc00000000UL; xfsr |= (XR << 34); break;
+				case 3: xfsr &= ~0x3000000000UL; xfsr |= (XR << 36); break;
+				}
+				current->thread.xfsr[0] = xfsr;
+				break;
+			case 1: rd->s = IR; break;
+			case 2: rd->d = XR; break;
+			case 5: FP_PACK_SP (rd, SR); break;
+			case 6: FP_PACK_DP (rd, DR); break;
+			case 7: FP_PACK_QP (rd, QR); break;
+			}
+		}
+
+		if(_fex != 0)
+			return record_exception(regs, _fex);
 
 		/* Success and no exceptions detected. */
 		current->thread.xfsr[0] &= ~(FSR_CEXC_MASK);
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/op-1.h linux/arch/sparc64/math-emu/op-1.h
--- v2.3.15/linux/arch/sparc64/math-emu/op-1.h	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/math-emu/op-1.h	Wed Dec 31 16:00:00 1969
@@ -1,297 +0,0 @@
-/* Software floating-point emulation.
-   Basic one-word fraction declaration and manipulation.
-   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Richard Henderson (rth@cygnus.com),
-		  Jakub Jelinek (jj@ultra.linux.cz),
-		  David S. Miller (davem@redhat.com) and
-		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#define _FP_FRAC_DECL_1(X)	_FP_W_TYPE X##_f
-#define _FP_FRAC_COPY_1(D,S)	(D##_f = S##_f)
-#define _FP_FRAC_SET_1(X,I)	(X##_f = I)
-#define _FP_FRAC_HIGH_1(X)	(X##_f)
-#define _FP_FRAC_LOW_1(X)	(X##_f)
-#define _FP_FRAC_WORD_1(X,w)	(X##_f)
-
-#define _FP_FRAC_ADDI_1(X,I)	(X##_f += I)
-#define _FP_FRAC_SLL_1(X,N)			\
-  do {						\
-    if (__builtin_constant_p(N) && (N) == 1)	\
-      X##_f += X##_f;				\
-    else					\
-      X##_f <<= (N);				\
-  } while (0)
-#define _FP_FRAC_SRL_1(X,N)	(X##_f >>= N)
-
-/* Right shift with sticky-lsb.  */
-#define _FP_FRAC_SRS_1(X,N,sz)	__FP_FRAC_SRS_1(X##_f, N, sz)
-
-#define __FP_FRAC_SRS_1(X,N,sz)						\
-   (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1		\
-		     ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
-
-#define _FP_FRAC_ADD_1(R,X,Y)	(R##_f = X##_f + Y##_f)
-#define _FP_FRAC_SUB_1(R,X,Y)	(R##_f = X##_f - Y##_f)
-#define _FP_FRAC_DEC_1(X,Y)	(X##_f -= Y##_f)
-#define _FP_FRAC_CLZ_1(z, X)	__FP_CLZ(z, X##_f)
-
-/* Predicates */
-#define _FP_FRAC_NEGP_1(X)	((_FP_WS_TYPE)X##_f < 0)
-#define _FP_FRAC_ZEROP_1(X)	(X##_f == 0)
-#define _FP_FRAC_OVERP_1(fs,X)	(X##_f & _FP_OVERFLOW_##fs)
-#define _FP_FRAC_EQ_1(X, Y)	(X##_f == Y##_f)
-#define _FP_FRAC_GE_1(X, Y)	(X##_f >= Y##_f)
-#define _FP_FRAC_GT_1(X, Y)	(X##_f > Y##_f)
-
-#define _FP_ZEROFRAC_1		0
-#define _FP_MINFRAC_1		1
-#define _FP_MAXFRAC_1		(~(_FP_WS_TYPE)0)
-
-/*
- * Unpack the raw bits of a native fp value.  Do not classify or
- * normalize the data.
- */
-
-#define _FP_UNPACK_RAW_1(fs, X, val)				\
-  do {								\
-    union _FP_UNION_##fs _flo; _flo.flt = (val);		\
-								\
-    X##_f = _flo.bits.frac;					\
-    X##_e = _flo.bits.exp;					\
-    X##_s = _flo.bits.sign;					\
-  } while (0)
-
-#define _FP_UNPACK_RAW_1_P(fs, X, val)				\
-  do {								\
-    union _FP_UNION_##fs *_flo =				\
-      (union _FP_UNION_##fs *)(val);				\
-								\
-    X##_f = _flo->bits.frac;					\
-    X##_e = _flo->bits.exp;					\
-    X##_s = _flo->bits.sign;					\
-  } while (0)
-
-/*
- * Repack the raw bits of a native fp value.
- */
-
-#define _FP_PACK_RAW_1(fs, val, X)				\
-  do {								\
-    union _FP_UNION_##fs _flo;					\
-								\
-    _flo.bits.frac = X##_f;					\
-    _flo.bits.exp  = X##_e;					\
-    _flo.bits.sign = X##_s;					\
-								\
-    (val) = _flo.flt;						\
-  } while (0)
-
-#define _FP_PACK_RAW_1_P(fs, val, X)				\
-  do {								\
-    union _FP_UNION_##fs *_flo =				\
-      (union _FP_UNION_##fs *)(val);				\
-								\
-    _flo->bits.frac = X##_f;					\
-    _flo->bits.exp  = X##_e;					\
-    _flo->bits.sign = X##_s;					\
-  } while (0)
-
-
-/*
- * Multiplication algorithms:
- */
-
-/* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
-   multiplication immediately.  */
-
-#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y)				\
-  do {									\
-    R##_f = X##_f * Y##_f;						\
-    /* Normalize since we know where the msb of the multiplicands	\
-       were (bit B), we know that the msb of the of the product is	\
-       at either 2B or 2B-1.  */					\
-    _FP_FRAC_SRS_1(R, wfracbits-1, 2*wfracbits);			\
-  } while (0)
-
-/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
-
-#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit)			\
-  do {									\
-    _FP_W_TYPE _Z_f0, _Z_f1;						\
-    doit(_Z_f1, _Z_f0, X##_f, Y##_f);					\
-    /* Normalize since we know where the msb of the multiplicands	\
-       were (bit B), we know that the msb of the of the product is	\
-       at either 2B or 2B-1.  */					\
-    _FP_FRAC_SRS_2(_Z, wfracbits-1, 2*wfracbits);			\
-    R##_f = _Z_f0;							\
-  } while (0)
-
-/* Finally, a simple widening multiply algorithm.  What fun!  */
-
-#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y)				\
-  do {									\
-    _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1;		\
-									\
-    /* split the words in half */					\
-    _xh = X##_f >> (_FP_W_TYPE_SIZE/2);					\
-    _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1);		\
-    _yh = Y##_f >> (_FP_W_TYPE_SIZE/2);					\
-    _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1);		\
-									\
-    /* multiply the pieces */						\
-    _z_f0 = _xl * _yl;							\
-    _a_f0 = _xh * _yl;							\
-    _a_f1 = _xl * _yh;							\
-    _z_f1 = _xh * _yh;							\
-									\
-    /* reassemble into two full words */				\
-    if ((_a_f0 += _a_f1) < _a_f1)					\
-      _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2);			\
-    _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2);				\
-    _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2);				\
-    _FP_FRAC_ADD_2(_z, _z, _a);						\
-									\
-    /* normalize */							\
-    _FP_FRAC_SRS_2(_z, wfracbits - 1, 2*wfracbits);			\
-    R##_f = _z_f0;							\
-  } while (0)
-
-
-/*
- * Division algorithms:
- */
-
-/* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
-   division immediately.  Give this macro either _FP_DIV_HELP_imm for
-   C primitives or _FP_DIV_HELP_ldiv for the ISO function.  Which you
-   choose will depend on what the compiler does with divrem4.  */
-
-#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit)		\
-  do {							\
-    _FP_W_TYPE _q, _r;					\
-    X##_f <<= (X##_f < Y##_f				\
-	       ? R##_e--, _FP_WFRACBITS_##fs		\
-	       : _FP_WFRACBITS_##fs - 1);		\
-    doit(_q, _r, X##_f, Y##_f);				\
-    R##_f = _q | (_r != 0);				\
-  } while (0)
-
-/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
-   that may be useful in this situation.  This first is for a primitive
-   that requires normalization, the second for one that does not.  Look
-   for UDIV_NEEDS_NORMALIZATION to tell which your machine needs.  */
-
-#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y)				\
-  do {									\
-    _FP_W_TYPE _nh, _nl, _q, _r;					\
-									\
-    /* Normalize Y -- i.e. make the most significant bit set.  */	\
-    Y##_f <<= _FP_WFRACXBITS_##fs - 1;					\
-									\
-    /* Shift X op correspondingly high, that is, up one full word.  */	\
-    if (X##_f <= Y##_f)							\
-      {									\
-	_nl = 0;							\
-	_nh = X##_f;							\
-      }									\
-    else								\
-      {									\
-	R##_e++;							\
-	_nl = X##_f << (_FP_W_TYPE_SIZE-1);				\
-	_nh = X##_f >> 1;						\
-      }									\
-    									\
-    udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);				\
-    R##_f = _q | (_r != 0);						\
-  } while (0)
-
-#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y)		\
-  do {							\
-    _FP_W_TYPE _nh, _nl, _q, _r;			\
-    if (X##_f < Y##_f)					\
-      {							\
-	R##_e--;					\
-	_nl = X##_f << _FP_WFRACBITS_##fs;		\
-	_nh = X##_f >> _FP_WFRACXBITS_##fs;		\
-      }							\
-    else						\
-      {							\
-	_nl = X##_f << (_FP_WFRACBITS_##fs - 1);	\
-	_nh = X##_f >> (_FP_WFRACXBITS_##fs + 1);	\
-      }							\
-    udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);		\
-    R##_f = _q | (_r != 0);				\
-  } while (0)
-  
-  
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- */
- 
-#define _FP_SQRT_MEAT_1(R, S, T, X, q)			\
-  do {							\
-    while (q != _FP_WORK_ROUND)				\
-      {							\
-        T##_f = S##_f + q;				\
-        if (T##_f <= X##_f)				\
-          {						\
-            S##_f = T##_f + q;				\
-            X##_f -= T##_f;				\
-            R##_f += q;					\
-          }						\
-        _FP_FRAC_SLL_1(X, 1);				\
-        q >>= 1;					\
-      }							\
-    if (X##_f)						\
-      {							\
-	if (S##_f < X##_f)				\
-	  R##_f |= _FP_WORK_ROUND;			\
-	R##_f |= _FP_WORK_STICKY;			\
-      }							\
-  } while (0)
-
-/*
- * Assembly/disassembly for converting to/from integral types.  
- * No shifting or overflow handled here.
- */
-
-#define _FP_FRAC_ASSEMBLE_1(r, X, rsize)	(r = X##_f)
-#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize)	(X##_f = r)
-
-
-/*
- * Convert FP values between word sizes
- */
-
-#define _FP_FRAC_CONV_1_1(dfs, sfs, D, S)				\
-  do {									\
-    D##_f = S##_f;							\
-    if (_FP_WFRACBITS_##sfs > _FP_WFRACBITS_##dfs)			\
-      {									\
-	if (S##_c != FP_CLS_NAN)					\
-	  _FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs),	\
-			 _FP_WFRACBITS_##sfs);				\
-	else								\
-	  _FP_FRAC_SRL_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs));	\
-      }									\
-    else								\
-      D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs;		\
-  } while (0)
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/op-2.h linux/arch/sparc64/math-emu/op-2.h
--- v2.3.15/linux/arch/sparc64/math-emu/op-2.h	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/math-emu/op-2.h	Wed Dec 31 16:00:00 1969
@@ -1,608 +0,0 @@
-/* Software floating-point emulation.
-   Basic two-word fraction declaration and manipulation.
-   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Richard Henderson (rth@cygnus.com),
-		  Jakub Jelinek (jj@ultra.linux.cz),
-		  David S. Miller (davem@redhat.com) and
-		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#define _FP_FRAC_DECL_2(X)	_FP_W_TYPE X##_f0, X##_f1
-#define _FP_FRAC_COPY_2(D,S)	(D##_f0 = S##_f0, D##_f1 = S##_f1)
-#define _FP_FRAC_SET_2(X,I)	__FP_FRAC_SET_2(X, I)
-#define _FP_FRAC_HIGH_2(X)	(X##_f1)
-#define _FP_FRAC_LOW_2(X)	(X##_f0)
-#define _FP_FRAC_WORD_2(X,w)	(X##_f##w)
-
-#define _FP_FRAC_SLL_2(X,N)						\
-  do {									\
-    if ((N) < _FP_W_TYPE_SIZE)						\
-      {									\
-	if (__builtin_constant_p(N) && (N) == 1) 			\
-	  {								\
-	    X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0);	\
-	    X##_f0 += X##_f0;						\
-	  }								\
-	else								\
-	  {								\
-	    X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N));	\
-	    X##_f0 <<= (N);						\
-	  }								\
-      }									\
-    else								\
-      {									\
-	X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE);			\
-	X##_f0 = 0;							\
-      }									\
-  } while (0)
-
-#define _FP_FRAC_SRL_2(X,N)						\
-  do {									\
-    if ((N) < _FP_W_TYPE_SIZE)						\
-      {									\
-	X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N));	\
-	X##_f1 >>= (N);							\
-      }									\
-    else								\
-      {									\
-	X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE);			\
-	X##_f1 = 0;							\
-      }									\
-  } while (0)
-
-/* Right shift with sticky-lsb.  */
-#define _FP_FRAC_SRS_2(X,N,sz)						\
-  do {									\
-    if ((N) < _FP_W_TYPE_SIZE)						\
-      {									\
-	X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) |	\
-		  (__builtin_constant_p(N) && (N) == 1			\
-		   ? X##_f0 & 1						\
-		   : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0));	\
-	X##_f1 >>= (N);							\
-      }									\
-    else								\
-      {									\
-	X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) |			\
-		  (((X##_f1 << (sz - (N))) | X##_f0) != 0));		\
-	X##_f1 = 0;							\
-      }									\
-  } while (0)
-
-#define _FP_FRAC_ADDI_2(X,I)	\
-  __FP_FRAC_ADDI_2(X##_f1, X##_f0, I)
-
-#define _FP_FRAC_ADD_2(R,X,Y)	\
-  __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
-
-#define _FP_FRAC_SUB_2(R,X,Y)	\
-  __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
-
-#define _FP_FRAC_DEC_2(X,Y)	\
-  __FP_FRAC_DEC_2(X##_f1, X##_f0, Y##_f1, Y##_f0)
-
-#define _FP_FRAC_CLZ_2(R,X)	\
-  do {				\
-    if (X##_f1)			\
-      __FP_CLZ(R,X##_f1);	\
-    else 			\
-    {				\
-      __FP_CLZ(R,X##_f0);	\
-      R += _FP_W_TYPE_SIZE;	\
-    }				\
-  } while(0)
-
-/* Predicates */
-#define _FP_FRAC_NEGP_2(X)	((_FP_WS_TYPE)X##_f1 < 0)
-#define _FP_FRAC_ZEROP_2(X)	((X##_f1 | X##_f0) == 0)
-#define _FP_FRAC_OVERP_2(fs,X)	(_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
-#define _FP_FRAC_EQ_2(X, Y)	(X##_f1 == Y##_f1 && X##_f0 == Y##_f0)
-#define _FP_FRAC_GT_2(X, Y)	\
-  (X##_f1 > Y##_f1 || X##_f1 == Y##_f1 && X##_f0 > Y##_f0)
-#define _FP_FRAC_GE_2(X, Y)	\
-  (X##_f1 > Y##_f1 || X##_f1 == Y##_f1 && X##_f0 >= Y##_f0)
-
-#define _FP_ZEROFRAC_2		0, 0
-#define _FP_MINFRAC_2		0, 1
-#define _FP_MAXFRAC_2		(~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
-
-/*
- * Internals 
- */
-
-#define __FP_FRAC_SET_2(X,I1,I0)	(X##_f0 = I0, X##_f1 = I1)
-
-#define __FP_CLZ_2(R, xh, xl)	\
-  do {				\
-    if (xh)			\
-      __FP_CLZ(R,xh);		\
-    else 			\
-    {				\
-      __FP_CLZ(R,xl);		\
-      R += _FP_W_TYPE_SIZE;	\
-    }				\
-  } while(0)
-
-#if 0
-
-#ifndef __FP_FRAC_ADDI_2
-#define __FP_FRAC_ADDI_2(xh, xl, i)	\
-  (xh += ((xl += i) < i))
-#endif
-#ifndef __FP_FRAC_ADD_2
-#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl)	\
-  (rh = xh + yh + ((rl = xl + yl) < xl))
-#endif
-#ifndef __FP_FRAC_SUB_2
-#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl)	\
-  (rh = xh - yh - ((rl = xl - yl) > xl))
-#endif
-#ifndef __FP_FRAC_DEC_2
-#define __FP_FRAC_DEC_2(xh, xl, yh, yl)	\
-  do {					\
-    UWtype _t = xl;			\
-    xh -= yh + ((xl -= yl) > _t);	\
-  } while (0)
-#endif
-
-#else
-
-#undef __FP_FRAC_ADDI_2
-#define __FP_FRAC_ADDI_2(xh, xl, i)	add_ssaaaa(xh, xl, xh, xl, 0, i)
-#undef __FP_FRAC_ADD_2
-#define __FP_FRAC_ADD_2			add_ssaaaa
-#undef __FP_FRAC_SUB_2
-#define __FP_FRAC_SUB_2			sub_ddmmss
-#undef __FP_FRAC_DEC_2
-#define __FP_FRAC_DEC_2(xh, xl, yh, yl)	sub_ddmmss(xh, xl, xh, xl, yh, yl)
-
-#endif
-
-/*
- * Unpack the raw bits of a native fp value.  Do not classify or
- * normalize the data.
- */
-
-#define _FP_UNPACK_RAW_2(fs, X, val)			\
-  do {							\
-    union _FP_UNION_##fs _flo; _flo.flt = (val);	\
-							\
-    X##_f0 = _flo.bits.frac0;				\
-    X##_f1 = _flo.bits.frac1;				\
-    X##_e  = _flo.bits.exp;				\
-    X##_s  = _flo.bits.sign;				\
-  } while (0)
-
-#define _FP_UNPACK_RAW_2_P(fs, X, val)			\
-  do {							\
-    union _FP_UNION_##fs *_flo =			\
-      (union _FP_UNION_##fs *)(val);			\
-							\
-    X##_f0 = _flo->bits.frac0;				\
-    X##_f1 = _flo->bits.frac1;				\
-    X##_e  = _flo->bits.exp;				\
-    X##_s  = _flo->bits.sign;				\
-  } while (0)
-
-
-/*
- * Repack the raw bits of a native fp value.
- */
-
-#define _FP_PACK_RAW_2(fs, val, X)			\
-  do {							\
-    union _FP_UNION_##fs _flo;				\
-							\
-    _flo.bits.frac0 = X##_f0;				\
-    _flo.bits.frac1 = X##_f1;				\
-    _flo.bits.exp   = X##_e;				\
-    _flo.bits.sign  = X##_s;				\
-							\
-    (val) = _flo.flt;					\
-  } while (0)
-
-#define _FP_PACK_RAW_2_P(fs, val, X)			\
-  do {							\
-    union _FP_UNION_##fs *_flo =			\
-      (union _FP_UNION_##fs *)(val);			\
-							\
-    _flo->bits.frac0 = X##_f0;				\
-    _flo->bits.frac1 = X##_f1;				\
-    _flo->bits.exp   = X##_e;				\
-    _flo->bits.sign  = X##_s;				\
-  } while (0)
-
-
-/*
- * Multiplication algorithms:
- */
-
-/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
-
-#define _FP_MUL_MEAT_2_wide(wfracbits, R, X, Y, doit)			\
-  do {									\
-    _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	\
-									\
-    doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0);	\
-    doit(_b_f1, _b_f0, X##_f0, Y##_f1);					\
-    doit(_c_f1, _c_f0, X##_f1, Y##_f0);					\
-    doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1);	\
-									\
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		    _FP_FRAC_WORD_4(_z,1), 0, _b_f1, _b_f0,		\
-		    _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		    _FP_FRAC_WORD_4(_z,1));				\
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		    _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0,		\
-		    _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		    _FP_FRAC_WORD_4(_z,1));				\
-									\
-    /* Normalize since we know where the msb of the multiplicands	\
-       were (bit B), we know that the msb of the of the product is	\
-       at either 2B or 2B-1.  */					\
-    _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits);			\
-    R##_f0 = _FP_FRAC_WORD_4(_z,0);					\
-    R##_f1 = _FP_FRAC_WORD_4(_z,1);					\
-  } while (0)
-
-/* Given a 1W * 1W => 2W primitive, do the extended multiplication.
-   Do only 3 multiplications instead of four. This one is for machines
-   where multiplication is much more expensive than subtraction.  */
-
-#define _FP_MUL_MEAT_2_wide_3mul(wfracbits, R, X, Y, doit)		\
-  do {									\
-    _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	\
-    _FP_W_TYPE _d;							\
-    int _c1, _c2;							\
-									\
-    _b_f0 = X##_f0 + X##_f1;						\
-    _c1 = _b_f0 < X##_f0;						\
-    _b_f1 = Y##_f0 + Y##_f1;						\
-    _c2 = _b_f1 < Y##_f0;						\
-    doit(_d, _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0);			\
-    doit(_FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1), _b_f0, _b_f1);	\
-    doit(_c_f1, _c_f0, X##_f1, Y##_f1);					\
-									\
-    _b_f0 &= -_c2;							\
-    _b_f1 &= -_c1;							\
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		    _FP_FRAC_WORD_4(_z,1), (_c1 & _c2), 0, _d,		\
-		    0, _FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1));	\
-    __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		     _b_f0);						\
-    __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		     _b_f1);						\
-    __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		    _FP_FRAC_WORD_4(_z,1),				\
-		    0, _d, _FP_FRAC_WORD_4(_z,0));			\
-    __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
-		    _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0);		\
-    __FP_FRAC_ADD_2(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2),	\
-		    _c_f1, _c_f0,					\
-		    _FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2));	\
-									\
-    /* Normalize since we know where the msb of the multiplicands	\
-       were (bit B), we know that the msb of the of the product is	\
-       at either 2B or 2B-1.  */					\
-    _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits);			\
-    R##_f0 = _FP_FRAC_WORD_4(_z,0);					\
-    R##_f1 = _FP_FRAC_WORD_4(_z,1);					\
-  } while (0)
-
-#define _FP_MUL_MEAT_2_gmp(wfracbits, R, X, Y)				\
-  do {									\
-    _FP_FRAC_DECL_4(_z);						\
-    _FP_W_TYPE _x[2], _y[2];						\
-    _x[0] = X##_f0; _x[1] = X##_f1;					\
-    _y[0] = Y##_f0; _y[1] = Y##_f1;					\
-									\
-    mpn_mul_n(_z_f, _x, _y, 2);						\
-									\
-    /* Normalize since we know where the msb of the multiplicands	\
-       were (bit B), we know that the msb of the of the product is	\
-       at either 2B or 2B-1.  */					\
-    _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits);			\
-    R##_f0 = _z_f[0];							\
-    R##_f1 = _z_f[1];							\
-  } while (0)
-
-/* Do at most 120x120=240 bits multiplication using double floating
-   point multiplication.  This is useful if floating point
-   multiplication has much bigger throughput than integer multiply.
-   It is supposed to work for _FP_W_TYPE_SIZE 64 and wfracbits
-   between 106 and 120 only.  
-   Caller guarantees that X and Y has (1LLL << (wfracbits - 1)) set.
-   SETFETZ is a macro which will disable all FPU exceptions and set rounding
-   towards zero,  RESETFE should optionally reset it back.  */
-
-#define _FP_MUL_MEAT_2_120_240_double(wfracbits, R, X, Y, setfetz, resetfe)	\
-  do {										\
-    static const double _const[] = {						\
-      /* 2^-24 */ 5.9604644775390625e-08,					\
-      /* 2^-48 */ 3.5527136788005009e-15,					\
-      /* 2^-72 */ 2.1175823681357508e-22,					\
-      /* 2^-96 */ 1.2621774483536189e-29,					\
-      /* 2^28 */ 2.68435456e+08,						\
-      /* 2^4 */ 1.600000e+01,							\
-      /* 2^-20 */ 9.5367431640625e-07,						\
-      /* 2^-44 */ 5.6843418860808015e-14,					\
-      /* 2^-68 */ 3.3881317890172014e-21,					\
-      /* 2^-92 */ 2.0194839173657902e-28,					\
-      /* 2^-116 */ 1.2037062152420224e-35};					\
-    double _a240, _b240, _c240, _d240, _e240, _f240, 				\
-	   _g240, _h240, _i240, _j240, _k240;					\
-    union { double d; UDItype i; } _l240, _m240, _n240, _o240,			\
-				   _p240, _q240, _r240, _s240;			\
-    UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0;			\
-										\
-    if (wfracbits < 106 || wfracbits > 120)					\
-      abort();									\
-										\
-    setfetz;									\
-										\
-    _e240 = (double)(long)(X##_f0 & 0xffffff);					\
-    _j240 = (double)(long)(Y##_f0 & 0xffffff);					\
-    _d240 = (double)(long)((X##_f0 >> 24) & 0xffffff);				\
-    _i240 = (double)(long)((Y##_f0 >> 24) & 0xffffff);				\
-    _c240 = (double)(long)(((X##_f1 << 16) & 0xffffff) | (X##_f0 >> 48));	\
-    _h240 = (double)(long)(((Y##_f1 << 16) & 0xffffff) | (Y##_f0 >> 48));	\
-    _b240 = (double)(long)((X##_f1 >> 8) & 0xffffff);				\
-    _g240 = (double)(long)((Y##_f1 >> 8) & 0xffffff);				\
-    _a240 = (double)(long)(X##_f1 >> 32);					\
-    _f240 = (double)(long)(Y##_f1 >> 32);					\
-    _e240 *= _const[3];								\
-    _j240 *= _const[3];								\
-    _d240 *= _const[2];								\
-    _i240 *= _const[2];								\
-    _c240 *= _const[1];								\
-    _h240 *= _const[1];								\
-    _b240 *= _const[0];								\
-    _g240 *= _const[0];								\
-    _s240.d =							      _e240*_j240;\
-    _r240.d =						_d240*_j240 + _e240*_i240;\
-    _q240.d =				  _c240*_j240 + _d240*_i240 + _e240*_h240;\
-    _p240.d =		    _b240*_j240 + _c240*_i240 + _d240*_h240 + _e240*_g240;\
-    _o240.d = _a240*_j240 + _b240*_i240 + _c240*_h240 + _d240*_g240 + _e240*_f240;\
-    _n240.d = _a240*_i240 + _b240*_h240 + _c240*_g240 + _d240*_f240;		\
-    _m240.d = _a240*_h240 + _b240*_g240 + _c240*_f240;				\
-    _l240.d = _a240*_g240 + _b240*_f240;					\
-    _k240 =   _a240*_f240;							\
-    _r240.d += _s240.d;								\
-    _q240.d += _r240.d;								\
-    _p240.d += _q240.d;								\
-    _o240.d += _p240.d;								\
-    _n240.d += _o240.d;								\
-    _m240.d += _n240.d;								\
-    _l240.d += _m240.d;								\
-    _k240 += _l240.d;								\
-    _s240.d -= ((_const[10]+_s240.d)-_const[10]);				\
-    _r240.d -= ((_const[9]+_r240.d)-_const[9]);					\
-    _q240.d -= ((_const[8]+_q240.d)-_const[8]);					\
-    _p240.d -= ((_const[7]+_p240.d)-_const[7]);					\
-    _o240.d += _const[7];							\
-    _n240.d += _const[6];							\
-    _m240.d += _const[5];							\
-    _l240.d += _const[4];							\
-    if (_s240.d != 0.0) _y240 = 1;						\
-    if (_r240.d != 0.0) _y240 = 1;						\
-    if (_q240.d != 0.0) _y240 = 1;						\
-    if (_p240.d != 0.0) _y240 = 1;						\
-    _t240 = (DItype)_k240;							\
-    _u240 = _l240.i;								\
-    _v240 = _m240.i;								\
-    _w240 = _n240.i;								\
-    _x240 = _o240.i;								\
-    R##_f1 = (_t240 << (128 - (wfracbits - 1)))					\
-	     | ((_u240 & 0xffffff) >> ((wfracbits - 1) - 104));			\
-    R##_f0 = ((_u240 & 0xffffff) << (168 - (wfracbits - 1)))			\
-    	     | ((_v240 & 0xffffff) << (144 - (wfracbits - 1)))			\
-    	     | ((_w240 & 0xffffff) << (120 - (wfracbits - 1)))			\
-    	     | ((_x240 & 0xffffff) >> ((wfracbits - 1) - 96))			\
-    	     | _y240;								\
-    resetfe;									\
-  } while (0)
-
-/*
- * Division algorithms:
- */
-
-#define _FP_DIV_MEAT_2_udiv(fs, R, X, Y)				\
-  do {									\
-    _FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0;		\
-    if (_FP_FRAC_GT_2(X, Y))						\
-      {									\
-	_n_f2 = X##_f1 >> 1;						\
-	_n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1;		\
-	_n_f0 = X##_f0 << (_FP_W_TYPE_SIZE - 1);			\
-      }									\
-    else								\
-      {									\
-	R##_e--;							\
-	_n_f2 = X##_f1;							\
-	_n_f1 = X##_f0;							\
-	_n_f0 = 0;							\
-      }									\
-									\
-    /* Normalize, i.e. make the most significant bit of the 		\
-       denominator set. */						\
-    _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs);				\
-									\
-    udiv_qrnnd(R##_f1, _r_f1, _n_f2, _n_f1, Y##_f1);			\
-    umul_ppmm(_m_f1, _m_f0, R##_f1, Y##_f0);				\
-    _r_f0 = _n_f0;							\
-    if (_FP_FRAC_GT_2(_m, _r))						\
-      {									\
-	R##_f1--;							\
-	_FP_FRAC_ADD_2(_r, Y, _r);					\
-	if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))		\
-	  {								\
-	    R##_f1--;							\
-	    _FP_FRAC_ADD_2(_r, Y, _r);					\
-	  }								\
-      }									\
-    _FP_FRAC_DEC_2(_r, _m);						\
-									\
-    if (_r_f1 == Y##_f1)						\
-      {									\
-	/* This is a special case, not an optimization			\
-	   (_r/Y##_f1 would not fit into UWtype).			\
-	   As _r is guaranteed to be < Y,  R##_f0 can be either		\
-	   (UWtype)-1 or (UWtype)-2.  But as we know what kind		\
-	   of bits it is (sticky, guard, round),  we don't care.	\
-	   We also don't care what the reminder is,  because the	\
-	   guard bit will be set anyway.  -jj */			\
-	R##_f0 = -1;							\
-      }									\
-    else								\
-      {									\
-	udiv_qrnnd(R##_f0, _r_f1, _r_f1, _r_f0, Y##_f1);		\
-	umul_ppmm(_m_f1, _m_f0, R##_f0, Y##_f0);			\
-	_r_f0 = 0;							\
-	if (_FP_FRAC_GT_2(_m, _r))					\
-	  {								\
-	    R##_f0--;							\
-	    _FP_FRAC_ADD_2(_r, Y, _r);					\
-	    if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))		\
-	      {								\
-		R##_f0--;						\
-		_FP_FRAC_ADD_2(_r, Y, _r);				\
-	      }								\
-	  }								\
-	if (!_FP_FRAC_EQ_2(_r, _m))					\
-	  R##_f0 |= _FP_WORK_STICKY;					\
-      }									\
-  } while (0)
-
-
-#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y)					\
-  do {									\
-    _FP_W_TYPE _x[4], _y[2], _z[4];					\
-    _y[0] = Y##_f0; _y[1] = Y##_f1;					\
-    _x[0] = _x[3] = 0;							\
-    if (_FP_FRAC_GT_2(X, Y))						\
-      {									\
-	R##_e++;							\
-	_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE) |	\
-		 X##_f1 >> (_FP_W_TYPE_SIZE -				\
-			    (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE)));	\
-	_x[2] = X##_f1 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE);	\
-      }									\
-    else								\
-      {									\
-	_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE) |	\
-		 X##_f1 >> (_FP_W_TYPE_SIZE -				\
-			    (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE)));	\
-	_x[2] = X##_f1 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE);	\
-      }									\
-									\
-    (void) mpn_divrem (_z, 0, _x, 4, _y, 2);				\
-    R##_f1 = _z[1];							\
-    R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0);				\
-  } while (0)
-
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- */
- 
-#define _FP_SQRT_MEAT_2(R, S, T, X, q)			\
-  do {							\
-    while (q)						\
-      {							\
-	T##_f1 = S##_f1 + q;				\
-	if (T##_f1 <= X##_f1)				\
-	  {						\
-	    S##_f1 = T##_f1 + q;			\
-	    X##_f1 -= T##_f1;				\
-	    R##_f1 += q;				\
-	  }						\
-	_FP_FRAC_SLL_2(X, 1);				\
-	q >>= 1;					\
-      }							\
-    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
-    while (q != _FP_WORK_ROUND)				\
-      {							\
-	T##_f0 = S##_f0 + q;				\
-	T##_f1 = S##_f1;				\
-	if (T##_f1 < X##_f1 || 				\
-	    (T##_f1 == X##_f1 && T##_f0 <= X##_f0))	\
-	  {						\
-	    S##_f0 = T##_f0 + q;			\
-	    S##_f1 += (T##_f0 > S##_f0);		\
-	    _FP_FRAC_DEC_2(X, T);			\
-	    R##_f0 += q;				\
-	  }						\
-	_FP_FRAC_SLL_2(X, 1);				\
-	q >>= 1;					\
-      }							\
-    if (X##_f0 | X##_f1)				\
-      {							\
-	if (S##_f1 < X##_f1 || 				\
-	    (S##_f1 == X##_f1 && S##_f0 < X##_f0))	\
-	  R##_f0 |= _FP_WORK_ROUND;			\
-	R##_f0 |= _FP_WORK_STICKY;			\
-      }							\
-  } while (0)
-
-
-/*
- * Assembly/disassembly for converting to/from integral types.  
- * No shifting or overflow handled here.
- */
-
-#define _FP_FRAC_ASSEMBLE_2(r, X, rsize)	\
-  do {						\
-    if (rsize <= _FP_W_TYPE_SIZE)		\
-      r = X##_f0;				\
-    else					\
-      {						\
-	r = X##_f1;				\
-	r <<= _FP_W_TYPE_SIZE;			\
-	r += X##_f0;				\
-      }						\
-  } while (0)
-
-#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize)				\
-  do {									\
-    X##_f0 = r;								\
-    X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);	\
-  } while (0)
-
-/*
- * Convert FP values between word sizes
- */
-
-#define _FP_FRAC_CONV_1_2(dfs, sfs, D, S)				\
-  do {									\
-    if (S##_c != FP_CLS_NAN)						\
-      _FP_FRAC_SRS_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),	\
-		     _FP_WFRACBITS_##sfs);				\
-    else								\
-      _FP_FRAC_SRL_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs));	\
-    D##_f = S##_f0;							\
-  } while (0)
-
-#define _FP_FRAC_CONV_2_1(dfs, sfs, D, S)				\
-  do {									\
-    D##_f0 = S##_f;							\
-    D##_f1 = 0;								\
-    _FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));	\
-  } while (0)
-
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/op-4.h linux/arch/sparc64/math-emu/op-4.h
--- v2.3.15/linux/arch/sparc64/math-emu/op-4.h	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/math-emu/op-4.h	Wed Dec 31 16:00:00 1969
@@ -1,661 +0,0 @@
-/* Software floating-point emulation.
-   Basic four-word fraction declaration and manipulation.
-   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Richard Henderson (rth@cygnus.com),
-		  Jakub Jelinek (jj@ultra.linux.cz),
-		  David S. Miller (davem@redhat.com) and
-		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#define _FP_FRAC_DECL_4(X)	_FP_W_TYPE X##_f[4]
-#define _FP_FRAC_COPY_4(D,S)			\
-  (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1],	\
-   D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
-#define _FP_FRAC_SET_4(X,I)	__FP_FRAC_SET_4(X, I)
-#define _FP_FRAC_HIGH_4(X)	(X##_f[3])
-#define _FP_FRAC_LOW_4(X)	(X##_f[0])
-#define _FP_FRAC_WORD_4(X,w)	(X##_f[w])
-
-#define _FP_FRAC_SLL_4(X,N)						\
-  do {									\
-    _FP_I_TYPE _up, _down, _skip, _i;					\
-    _skip = (N) / _FP_W_TYPE_SIZE;					\
-    _up = (N) % _FP_W_TYPE_SIZE;					\
-    _down = _FP_W_TYPE_SIZE - _up;					\
-    if (!_up)								\
-      for (_i = 3; _i >= _skip; --_i)					\
-	X##_f[_i] = X##_f[_i-_skip];					\
-    else								\
-      {									\
-	for (_i = 3; _i > _skip; --_i)					\
-	  X##_f[_i] = X##_f[_i-_skip] << _up				\
-		      | X##_f[_i-_skip-1] >> _down;			\
-	X##_f[_i--] = X##_f[0] << _up; 					\
-      }									\
-    for (; _i >= 0; --_i)						\
-      X##_f[_i] = 0;							\
-  } while (0)
-
-/* This one was broken too */
-#define _FP_FRAC_SRL_4(X,N)						\
-  do {									\
-    _FP_I_TYPE _up, _down, _skip, _i;					\
-    _skip = (N) / _FP_W_TYPE_SIZE;					\
-    _down = (N) % _FP_W_TYPE_SIZE;					\
-    _up = _FP_W_TYPE_SIZE - _down;					\
-    if (!_down)								\
-      for (_i = 0; _i <= 3-_skip; ++_i)					\
-	X##_f[_i] = X##_f[_i+_skip];					\
-    else								\
-      {									\
-	for (_i = 0; _i < 3-_skip; ++_i)				\
-	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
-		      | X##_f[_i+_skip+1] << _up;			\
-	X##_f[_i++] = X##_f[3] >> _down;				\
-      }									\
-    for (; _i < 4; ++_i)						\
-      X##_f[_i] = 0;							\
-  } while (0)
-
-
-/* Right shift with sticky-lsb. 
- * What this actually means is that we do a standard right-shift,
- * but that if any of the bits that fall off the right hand side
- * were one then we always set the LSbit.
- */
-#define _FP_FRAC_SRS_4(X,N,size)					\
-  do {									\
-    _FP_I_TYPE _up, _down, _skip, _i;					\
-    _FP_W_TYPE _s;							\
-    _skip = (N) / _FP_W_TYPE_SIZE;					\
-    _down = (N) % _FP_W_TYPE_SIZE;					\
-    _up = _FP_W_TYPE_SIZE - _down;					\
-    for (_s = _i = 0; _i < _skip; ++_i)					\
-      _s |= X##_f[_i];							\
-    _s |= X##_f[_i] << _up;						\
-/* s is now != 0 if we want to set the LSbit */				\
-    if (!_down)								\
-      for (_i = 0; _i <= 3-_skip; ++_i)					\
-	X##_f[_i] = X##_f[_i+_skip];					\
-    else								\
-      {									\
-	for (_i = 0; _i < 3-_skip; ++_i)				\
-	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
-		      | X##_f[_i+_skip+1] << _up;			\
-	X##_f[_i++] = X##_f[3] >> _down;				\
-      }									\
-    for (; _i < 4; ++_i)						\
-      X##_f[_i] = 0;							\
-    /* don't fix the LSB until the very end when we're sure f[0] is stable */	\
-    X##_f[0] |= (_s != 0);						\
-  } while (0)
-
-#define _FP_FRAC_ADD_4(R,X,Y)						\
-  __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0],		\
-		  X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
-		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
-
-#define _FP_FRAC_SUB_4(R,X,Y)						\
-  __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0],		\
-		  X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
-		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
-
-#define _FP_FRAC_DEC_4(X,Y)						\
-  __FP_FRAC_DEC_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
-		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
-
-#define _FP_FRAC_ADDI_4(X,I)						\
-  __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
-
-#define _FP_ZEROFRAC_4  0,0,0,0
-#define _FP_MINFRAC_4   0,0,0,1
-#define _FP_MAXFRAC_4	(~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
-
-#define _FP_FRAC_ZEROP_4(X)     ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
-#define _FP_FRAC_NEGP_4(X)      ((_FP_WS_TYPE)X##_f[3] < 0)
-#define _FP_FRAC_OVERP_4(fs,X)  (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
-
-#define _FP_FRAC_EQ_4(X,Y)				\
- (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1]		\
-  && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
-
-#define _FP_FRAC_GT_4(X,Y)				\
- (X##_f[3] > Y##_f[3] ||				\
-  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||	\
-   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||	\
-    (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0])	\
-   ))							\
-  ))							\
- )
-
-#define _FP_FRAC_GE_4(X,Y)				\
- (X##_f[3] > Y##_f[3] ||				\
-  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||	\
-   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||	\
-    (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0])	\
-   ))							\
-  ))							\
- )
-
-
-#define _FP_FRAC_CLZ_4(R,X)		\
-  do {					\
-    if (X##_f[3])			\
-    {					\
-	__FP_CLZ(R,X##_f[3]);		\
-    }					\
-    else if (X##_f[2])			\
-    {					\
-	__FP_CLZ(R,X##_f[2]);		\
-	R += _FP_W_TYPE_SIZE;		\
-    }					\
-    else if (X##_f[1])			\
-    {					\
-	__FP_CLZ(R,X##_f[2]);		\
-	R += _FP_W_TYPE_SIZE*2;		\
-    }					\
-    else				\
-    {					\
-	__FP_CLZ(R,X##_f[0]);		\
-	R += _FP_W_TYPE_SIZE*3;		\
-    }					\
-  } while(0)
-
-
-#define _FP_UNPACK_RAW_4(fs, X, val)				\
-  do {								\
-    union _FP_UNION_##fs _flo; _flo.flt = (val);		\
-    X##_f[0] = _flo.bits.frac0;					\
-    X##_f[1] = _flo.bits.frac1;					\
-    X##_f[2] = _flo.bits.frac2;					\
-    X##_f[3] = _flo.bits.frac3;					\
-    X##_e  = _flo.bits.exp;					\
-    X##_s  = _flo.bits.sign;					\
-  } while (0)
-
-#define _FP_UNPACK_RAW_4_P(fs, X, val)				\
-  do {								\
-    union _FP_UNION_##fs *_flo =				\
-      (union _FP_UNION_##fs *)(val);				\
-								\
-    X##_f[0] = _flo->bits.frac0;				\
-    X##_f[1] = _flo->bits.frac1;				\
-    X##_f[2] = _flo->bits.frac2;				\
-    X##_f[3] = _flo->bits.frac3;				\
-    X##_e  = _flo->bits.exp;					\
-    X##_s  = _flo->bits.sign;					\
-  } while (0)
-
-#define _FP_PACK_RAW_4(fs, val, X)				\
-  do {								\
-    union _FP_UNION_##fs _flo;					\
-    _flo.bits.frac0 = X##_f[0];					\
-    _flo.bits.frac1 = X##_f[1];					\
-    _flo.bits.frac2 = X##_f[2];					\
-    _flo.bits.frac3 = X##_f[3];					\
-    _flo.bits.exp   = X##_e;					\
-    _flo.bits.sign  = X##_s;					\
-    (val) = _flo.flt;				   		\
-  } while (0)
-
-#define _FP_PACK_RAW_4_P(fs, val, X)				\
-  do {								\
-    union _FP_UNION_##fs *_flo =				\
-      (union _FP_UNION_##fs *)(val);				\
-								\
-    _flo->bits.frac0 = X##_f[0];				\
-    _flo->bits.frac1 = X##_f[1];				\
-    _flo->bits.frac2 = X##_f[2];				\
-    _flo->bits.frac3 = X##_f[3];				\
-    _flo->bits.exp   = X##_e;					\
-    _flo->bits.sign  = X##_s;					\
-  } while (0)
-
-/*
- * Multiplication algorithms:
- */
-
-/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
-
-#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit)			    \
-  do {									    \
-    _FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	    \
-    _FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f);	    \
-									    \
-    doit(_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0), X##_f[0], Y##_f[0]); \
-    doit(_b_f1, _b_f0, X##_f[0], Y##_f[1]);				    \
-    doit(_c_f1, _c_f0, X##_f[1], Y##_f[0]);				    \
-    doit(_d_f1, _d_f0, X##_f[1], Y##_f[1]);				    \
-    doit(_e_f1, _e_f0, X##_f[0], Y##_f[2]);				    \
-    doit(_f_f1, _f_f0, X##_f[2], Y##_f[0]);				    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2),	    \
-		    _FP_FRAC_WORD_8(_z,1), 0,_b_f1,_b_f0,		    \
-		    0,0,_FP_FRAC_WORD_8(_z,1));				    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2),	    \
-		    _FP_FRAC_WORD_8(_z,1), 0,_c_f1,_c_f0,		    \
-		    _FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2),	    \
-		    _FP_FRAC_WORD_8(_z,1));				    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
-		    _FP_FRAC_WORD_8(_z,2), 0,_d_f1,_d_f0,		    \
-		    0,_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2));	    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
-		    _FP_FRAC_WORD_8(_z,2), 0,_e_f1,_e_f0,		    \
-		    _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
-		    _FP_FRAC_WORD_8(_z,2));				    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
-		    _FP_FRAC_WORD_8(_z,2), 0,_f_f1,_f_f0,		    \
-		    _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
-		    _FP_FRAC_WORD_8(_z,2));				    \
-    doit(_b_f1, _b_f0, X##_f[0], Y##_f[3]);				    \
-    doit(_c_f1, _c_f0, X##_f[3], Y##_f[0]);				    \
-    doit(_d_f1, _d_f0, X##_f[1], Y##_f[2]);				    \
-    doit(_e_f1, _e_f0, X##_f[2], Y##_f[1]);				    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
-		    _FP_FRAC_WORD_8(_z,3), 0,_b_f1,_b_f0,		    \
-		    0,_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3));	    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
-		    _FP_FRAC_WORD_8(_z,3), 0,_c_f1,_c_f0,		    \
-		    _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
-		    _FP_FRAC_WORD_8(_z,3));				    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
-		    _FP_FRAC_WORD_8(_z,3), 0,_d_f1,_d_f0,		    \
-		    _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
-		    _FP_FRAC_WORD_8(_z,3));				    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
-		    _FP_FRAC_WORD_8(_z,3), 0,_e_f1,_e_f0,		    \
-		    _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
-		    _FP_FRAC_WORD_8(_z,3));				    \
-    doit(_b_f1, _b_f0, X##_f[2], Y##_f[2]);				    \
-    doit(_c_f1, _c_f0, X##_f[1], Y##_f[3]);				    \
-    doit(_d_f1, _d_f0, X##_f[3], Y##_f[1]);				    \
-    doit(_e_f1, _e_f0, X##_f[2], Y##_f[3]);				    \
-    doit(_f_f1, _f_f0, X##_f[3], Y##_f[2]);				    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
-		    _FP_FRAC_WORD_8(_z,4), 0,_b_f1,_b_f0,		    \
-		    0,_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4));	    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
-		    _FP_FRAC_WORD_8(_z,4), 0,_c_f1,_c_f0,		    \
-		    _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
-		    _FP_FRAC_WORD_8(_z,4));				    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
-		    _FP_FRAC_WORD_8(_z,4), 0,_d_f1,_d_f0,		    \
-		    _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
-		    _FP_FRAC_WORD_8(_z,4));				    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
-		    _FP_FRAC_WORD_8(_z,5), 0,_e_f1,_e_f0,		    \
-		    0,_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5));	    \
-    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
-		    _FP_FRAC_WORD_8(_z,5), 0,_f_f1,_f_f0,		    \
-		    _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
-		    _FP_FRAC_WORD_8(_z,5));				    \
-    doit(_b_f1, _b_f0, X##_f[3], Y##_f[3]);				    \
-    __FP_FRAC_ADD_2(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
-		    _b_f1,_b_f0,					    \
-		    _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6));	    \
-									    \
-    /* Normalize since we know where the msb of the multiplicands	    \
-       were (bit B), we know that the msb of the of the product is	    \
-       at either 2B or 2B-1.  */					    \
-    _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits);			    \
-    __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2),	    \
-		    _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0));	    \
-  } while (0)
-
-#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y)				    \
-  do {									    \
-    _FP_FRAC_DECL_8(_z);						    \
-									    \
-    mpn_mul_n(_z_f, _x_f, _y_f, 4);					    \
-									    \
-    /* Normalize since we know where the msb of the multiplicands	    \
-       were (bit B), we know that the msb of the of the product is	    \
-       at either 2B or 2B-1.  */					    \
-    _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits);	 		    \
-    __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2),	    \
-		    _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0));	    \
-  } while (0)
-
-/*
- * Helper utility for _FP_DIV_MEAT_4_udiv:
- * pppp = m * nnn
- */
-#define umul_ppppmnnn(p3,p2,p1,p0,m,n2,n1,n0)				    \
-  do {									    \
-    UWtype _t;								    \
-    umul_ppmm(p1,p0,m,n0);						    \
-    umul_ppmm(p2,_t,m,n1);						    \
-    __FP_FRAC_ADDI_2(p2,p1,_t);						    \
-    umul_ppmm(p3,_t,m,n2);						    \
-    __FP_FRAC_ADDI_2(p3,p2,_t);						    \
-  } while (0)
-
-/*
- * Division algorithms:
- */
-
-#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y)				    \
-  do {									    \
-    int _i;								    \
-    _FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m);				    \
-    _FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4);					    \
-    if (_FP_FRAC_GT_4(X, Y))						    \
-      {									    \
-	_n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1);			    \
-	_FP_FRAC_SRL_4(X, 1);						    \
-      }									    \
-    else								    \
-      R##_e--;								    \
-									    \
-    /* Normalize, i.e. make the most significant bit of the 		    \
-       denominator set. */						    \
-    _FP_FRAC_SLL_4(Y, _FP_WFRACXBITS_##fs);				    \
-									    \
-    for (_i = 3; ; _i--)						    \
-      {									    \
-        if (X##_f[3] == Y##_f[3])					    \
-          {								    \
-            /* This is a special case, not an optimization		    \
-               (X##_f[3]/Y##_f[3] would not fit into UWtype).		    \
-               As X## is guaranteed to be < Y,  R##_f[_i] can be either	    \
-               (UWtype)-1 or (UWtype)-2.  */				    \
-            R##_f[_i] = -1;						    \
-            if (!_i)							    \
-	      break;							    \
-            __FP_FRAC_SUB_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0],	    \
-			    Y##_f[2], Y##_f[1], Y##_f[0], 0,		    \
-			    X##_f[2], X##_f[1], X##_f[0], _n_f[_i]);	    \
-            _FP_FRAC_SUB_4(X, Y, X);					    \
-            if (X##_f[3] > Y##_f[3])					    \
-              {								    \
-                R##_f[_i] = -2;						    \
-                _FP_FRAC_ADD_4(X, Y, X);				    \
-              }								    \
-          }								    \
-        else								    \
-          {								    \
-            udiv_qrnnd(R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]);  \
-            umul_ppppmnnn(_m_f[3], _m_f[2], _m_f[1], _m_f[0],		    \
-			  R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]);	    \
-            X##_f[2] = X##_f[1];					    \
-            X##_f[1] = X##_f[0];					    \
-            X##_f[0] = _n_f[_i];					    \
-            if (_FP_FRAC_GT_4(_m, X))					    \
-              {								    \
-                R##_f[_i]--;						    \
-                _FP_FRAC_ADD_4(X, Y, X);				    \
-                if (_FP_FRAC_GE_4(X, Y) && _FP_FRAC_GT_4(_m, X))	    \
-                  {							    \
-		    R##_f[_i]--;					    \
-		    _FP_FRAC_ADD_4(X, Y, X);				    \
-                  }							    \
-              }								    \
-            _FP_FRAC_DEC_4(X, _m);					    \
-            if (!_i)							    \
-	      {								    \
-		if (!_FP_FRAC_EQ_4(X, _m))				    \
-		  R##_f[0] |= _FP_WORK_STICKY;				    \
-		break;							    \
-	      }								    \
-          }								    \
-      }									    \
-  } while (0)
-
-
-/*
- * Square root algorithms:
- * We have just one right now, maybe Newton approximation
- * should be added for those machines where division is fast.
- */
- 
-#define _FP_SQRT_MEAT_4(R, S, T, X, q)				\
-  do {								\
-    while (q)							\
-      {								\
-	T##_f[3] = S##_f[3] + q;				\
-	if (T##_f[3] <= X##_f[3])				\
-	  {							\
-	    S##_f[3] = T##_f[3] + q;				\
-	    X##_f[3] -= T##_f[3];				\
-	    R##_f[3] += q;					\
-	  }							\
-	_FP_FRAC_SLL_4(X, 1);					\
-	q >>= 1;						\
-      }								\
-    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);			\
-    while (q)							\
-      {								\
-	T##_f[2] = S##_f[2] + q;				\
-	T##_f[3] = S##_f[3];					\
-	if (T##_f[3] < X##_f[3] || 				\
-	    (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2]))	\
-	  {							\
-	    S##_f[2] = T##_f[2] + q;				\
-	    S##_f[3] += (T##_f[2] > S##_f[2]);			\
-	    __FP_FRAC_DEC_2(X##_f[3], X##_f[2],			\
-			    T##_f[3], T##_f[2]);		\
-	    R##_f[2] += q;					\
-	  }							\
-	_FP_FRAC_SLL_4(X, 1);					\
-	q >>= 1;						\
-      }								\
-    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);			\
-    while (q)							\
-      {								\
-	T##_f[1] = S##_f[1] + q;				\
-	T##_f[2] = S##_f[2];					\
-	T##_f[3] = S##_f[3];					\
-	if (T##_f[3] < X##_f[3] || 				\
-	    (T##_f[3] == X##_f[3] && (T##_f[2] < X##_f[2] ||	\
-	     (T##_f[2] == X##_f[2] && T##_f[1] <= X##_f[1]))))	\
-	  {							\
-	    S##_f[1] = T##_f[1] + q;				\
-	    S##_f[2] += (T##_f[1] > S##_f[1]);			\
-	    S##_f[3] += (T##_f[2] > S##_f[2]);			\
-	    __FP_FRAC_DEC_3(X##_f[3], X##_f[2], X##_f[1],	\
-	    		    T##_f[3], T##_f[2], T##_f[1]);	\
-	    R##_f[1] += q;					\
-	  }							\
-	_FP_FRAC_SLL_4(X, 1);					\
-	q >>= 1;						\
-      }								\
-    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);			\
-    while (q != _FP_WORK_ROUND)					\
-      {								\
-	T##_f[0] = S##_f[0] + q;				\
-	T##_f[1] = S##_f[1];					\
-	T##_f[2] = S##_f[2];					\
-	T##_f[3] = S##_f[3];					\
-	if (_FP_FRAC_GE_4(X,T))					\
-	  {							\
-	    S##_f[0] = T##_f[0] + q;				\
-	    S##_f[1] += (T##_f[0] > S##_f[0]);			\
-	    S##_f[2] += (T##_f[1] > S##_f[1]);			\
-	    S##_f[3] += (T##_f[2] > S##_f[2]);			\
-	    _FP_FRAC_DEC_4(X, T);				\
-	    R##_f[0] += q;					\
-	  }							\
-	_FP_FRAC_SLL_4(X, 1);					\
-	q >>= 1;						\
-      }								\
-    if (!_FP_FRAC_ZEROP_4(X))					\
-      {								\
-	if (_FP_FRAC_GT_4(X,S))					\
-	  R##_f[0] |= _FP_WORK_ROUND;				\
-	R##_f[0] |= _FP_WORK_STICKY;				\
-      }								\
-  } while (0)
-
-
-/*
- * Internals 
- */
-
-#define __FP_FRAC_SET_4(X,I3,I2,I1,I0)					\
-  (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)
-
-#ifndef __FP_FRAC_ADD_3
-#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)			\
-  (r0 = x0 + y0,							\
-   r1 = x1 + y1 + (r0 < x0),						\
-   r2 = x2 + y2 + (r1 < x1))
-#endif
-
-#ifndef __FP_FRAC_ADD_4
-#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
-  (r0 = x0 + y0,							\
-   r1 = x1 + y1 + (r0 < x0),						\
-   r2 = x2 + y2 + (r1 < x1),						\
-   r3 = x3 + y3 + (r2 < x2))
-#endif
-
-#ifndef __FP_FRAC_SUB_3
-#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)			\
-  (r0 = x0 - y0,							\
-   r1 = x1 - y1 - (r0 > x0),						\
-   r2 = x2 - y2 - (r1 > x1))
-#endif
-
-#ifndef __FP_FRAC_SUB_4
-#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
-  (r0 = x0 - y0,							\
-   r1 = x1 - y1 - (r0 > x0),						\
-   r2 = x2 - y2 - (r1 > x1),						\
-   r3 = x3 - y3 - (r2 > x2))
-#endif
-
-#ifndef __FP_FRAC_DEC_3
-#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0)				\
-  do {									\
-    UWtype _t0, _t1;							\
-    _t0 = x0;								\
-    x0 -= y0;								\
-    _t1 = x1;								\
-    x1 -= y1 + (x0 > _t0);						\
-    x2 -= y2 + (x1 > _t1);						\
-  } while (0)
-#endif
-
-#ifndef __FP_FRAC_DEC_4
-#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0)			\
-  do {									\
-    UWtype _t0, _t1;							\
-    _t0 = x0;								\
-    x0 -= y0;								\
-    _t1 = x1;								\
-    x1 -= y1 + (x0 > _t0);						\
-    _t0 = x2;								\
-    x2 -= y2 + (x1 > _t1);						\
-    x3 -= y3 + (x2 > _t0);						\
-  } while (0)
-#endif
-
-#ifndef __FP_FRAC_ADDI_4
-#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i)					\
-  do {									\
-    UWtype _t;								\
-    _t = ((x0 += i) < i);						\
-    x1 += _t; _t = (x1 < _t);						\
-    x2 += _t; _t = (x2 < _t);						\
-    x3 += _t;								\
-  } while (0)
-#endif
-
-/* Convert FP values between word sizes. This appears to be more
- * complicated than I'd have expected it to be, so these might be
- * wrong... These macros are in any case somewhat bogus because they
- * use information about what various FRAC_n variables look like 
- * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do
- * the ones in op-2.h and op-1.h. 
- */
-#define _FP_FRAC_CONV_1_4(dfs, sfs, D, S)				\
-   do {									\
-     if (S##_c != FP_CLS_NAN)						\
-       _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),	\
-			  _FP_WFRACBITS_##sfs);				\
-     else								\
-       _FP_FRAC_SRL_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs));	\
-     D##_f = S##_f[0];							\
-  } while (0)
-
-#define _FP_FRAC_CONV_2_4(dfs, sfs, D, S)				\
-   do {									\
-     if (S##_c != FP_CLS_NAN)						\
-       _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),	\
-		      _FP_WFRACBITS_##sfs);				\
-     else								\
-       _FP_FRAC_SRL_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs));	\
-     D##_f0 = S##_f[0];							\
-     D##_f1 = S##_f[1];							\
-  } while (0)
-
-/* Assembly/disassembly for converting to/from integral types.  
- * No shifting or overflow handled here.
- */
-/* Put the FP value X into r, which is an integer of size rsize. */
-#define _FP_FRAC_ASSEMBLE_4(r, X, rsize)				\
-  do {									\
-    if (rsize <= _FP_W_TYPE_SIZE)					\
-      r = X##_f[0];							\
-    else if (rsize <= 2*_FP_W_TYPE_SIZE)				\
-    {									\
-      r = X##_f[1];							\
-      r <<= _FP_W_TYPE_SIZE;						\
-      r += X##_f[0];							\
-    }									\
-    else								\
-    {									\
-      /* I'm feeling lazy so we deal with int == 3words (implausible)*/	\
-      /* and int == 4words as a single case.			 */	\
-      r = X##_f[3];							\
-      r <<= _FP_W_TYPE_SIZE;						\
-      r += X##_f[2];							\
-      r <<= _FP_W_TYPE_SIZE;						\
-      r += X##_f[1];							\
-      r <<= _FP_W_TYPE_SIZE;						\
-      r += X##_f[0];							\
-    }									\
-  } while (0)
-
-/* "No disassemble Number Five!" */
-/* move an integer of size rsize into X's fractional part. We rely on
- * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid
- * having to mask the values we store into it.
- */
-#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize)				\
-  do {									\
-    X##_f[0] = r;							\
-    X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);	\
-    X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
-    X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
-  } while (0);
-
-#define _FP_FRAC_CONV_4_1(dfs, sfs, D, S)				\
-   do {									\
-     D##_f[0] = S##_f;							\
-     D##_f[1] = D##_f[2] = D##_f[3] = 0;				\
-     _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));	\
-   } while (0)
-
-#define _FP_FRAC_CONV_4_2(dfs, sfs, D, S)				\
-   do {									\
-     D##_f[0] = S##_f0;							\
-     D##_f[1] = S##_f1;							\
-     D##_f[2] = D##_f[3] = 0;						\
-     _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));	\
-   } while (0)
-
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/op-8.h linux/arch/sparc64/math-emu/op-8.h
--- v2.3.15/linux/arch/sparc64/math-emu/op-8.h	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/op-8.h	Wed Dec 31 16:00:00 1969
@@ -1,103 +0,0 @@
-/* Software floating-point emulation.
-   Basic eight-word fraction declaration and manipulation.
-   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Richard Henderson (rth@cygnus.com),
-		  Jakub Jelinek (jj@ultra.linux.cz) and
-		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
-                                                         
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-/* We need just a few things from here for op-4, if we ever need some
-   other macros, they can be added. */
-#define _FP_FRAC_DECL_8(X)	_FP_W_TYPE X##_f[8]
-#define _FP_FRAC_HIGH_8(X)	(X##_f[7])
-#define _FP_FRAC_LOW_8(X)	(X##_f[0])
-#define _FP_FRAC_WORD_8(X,w)	(X##_f[w])
-
-#define _FP_FRAC_SLL_8(X,N)						\
-  do {									\
-    _FP_I_TYPE _up, _down, _skip, _i;					\
-    _skip = (N) / _FP_W_TYPE_SIZE;					\
-    _up = (N) % _FP_W_TYPE_SIZE;					\
-    _down = _FP_W_TYPE_SIZE - _up;					\
-    if (!_up)								\
-      for (_i = 7; _i >= _skip; --_i)					\
-	X##_f[_i] = X##_f[_i-_skip];					\
-    else								\
-      {									\
-	for (_i = 7; _i > _skip; --_i)					\
-	  X##_f[_i] = X##_f[_i-_skip] << _up				\
-		      | X##_f[_i-_skip-1] >> _down;			\
-	X##_f[_i--] = X##_f[0] << _up; 					\
-      }									\
-    for (; _i >= 0; --_i)						\
-      X##_f[_i] = 0;							\
-  } while (0)
-
-#define _FP_FRAC_SRL_8(X,N)						\
-  do {									\
-    _FP_I_TYPE _up, _down, _skip, _i;					\
-    _skip = (N) / _FP_W_TYPE_SIZE;					\
-    _down = (N) % _FP_W_TYPE_SIZE;					\
-    _up = _FP_W_TYPE_SIZE - _down;					\
-    if (!_down)								\
-      for (_i = 0; _i <= 7-_skip; ++_i)					\
-	X##_f[_i] = X##_f[_i+_skip];					\
-    else								\
-      {									\
-	for (_i = 0; _i < 7-_skip; ++_i)				\
-	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
-		      | X##_f[_i+_skip+1] << _up;			\
-	X##_f[_i++] = X##_f[7] >> _down;				\
-      }									\
-    for (; _i < 8; ++_i)						\
-      X##_f[_i] = 0;							\
-  } while (0)
-
-
-/* Right shift with sticky-lsb. 
- * What this actually means is that we do a standard right-shift,
- * but that if any of the bits that fall off the right hand side
- * were one then we always set the LSbit.
- */
-#define _FP_FRAC_SRS_8(X,N,size)					\
-  do {									\
-    _FP_I_TYPE _up, _down, _skip, _i;					\
-    _FP_W_TYPE _s;							\
-    _skip = (N) / _FP_W_TYPE_SIZE;					\
-    _down = (N) % _FP_W_TYPE_SIZE;					\
-    _up = _FP_W_TYPE_SIZE - _down;					\
-    for (_s = _i = 0; _i < _skip; ++_i)					\
-      _s |= X##_f[_i];							\
-    _s |= X##_f[_i] << _up;						\
-/* s is now != 0 if we want to set the LSbit */				\
-    if (!_down)								\
-      for (_i = 0; _i <= 7-_skip; ++_i)					\
-	X##_f[_i] = X##_f[_i+_skip];					\
-    else								\
-      {									\
-	for (_i = 0; _i < 7-_skip; ++_i)				\
-	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
-		      | X##_f[_i+_skip+1] << _up;			\
-	X##_f[_i++] = X##_f[7] >> _down;				\
-      }									\
-    for (; _i < 8; ++_i)						\
-      X##_f[_i] = 0;							\
-    /* don't fix the LSB until the very end when we're sure f[0] is stable */	\
-    X##_f[0] |= (_s != 0);						\
-  } while (0)
-
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/op-common.h linux/arch/sparc64/math-emu/op-common.h
--- v2.3.15/linux/arch/sparc64/math-emu/op-common.h	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/math-emu/op-common.h	Wed Dec 31 16:00:00 1969
@@ -1,767 +0,0 @@
-/* Software floating-point emulation. Common operations.
-   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Richard Henderson (rth@cygnus.com),
-		  Jakub Jelinek (jj@ultra.linux.cz),
-		  David S. Miller (davem@redhat.com) and
-		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#define _FP_DECL(wc, X)			\
-  _FP_I_TYPE X##_c, X##_s, X##_e;	\
-  _FP_FRAC_DECL_##wc(X)
-
-/*
- * Finish truely unpacking a native fp value by classifying the kind
- * of fp value and normalizing both the exponent and the fraction.
- */
-
-#define _FP_UNPACK_CANONICAL(fs, wc, X)					\
-do {									\
-  switch (X##_e)							\
-  {									\
-  default:								\
-    _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs;			\
-    _FP_FRAC_SLL_##wc(X, _FP_WORKBITS);					\
-    X##_e -= _FP_EXPBIAS_##fs;						\
-    X##_c = FP_CLS_NORMAL;						\
-    break;								\
-									\
-  case 0:								\
-    if (_FP_FRAC_ZEROP_##wc(X))						\
-      X##_c = FP_CLS_ZERO;						\
-    else								\
-      {									\
-	/* a denormalized number */					\
-	_FP_I_TYPE _shift;						\
-	_FP_FRAC_CLZ_##wc(_shift, X);					\
-	_shift -= _FP_FRACXBITS_##fs;					\
-	_FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS));			\
-	X##_e -= _FP_EXPBIAS_##fs - 1 + _shift;				\
-	X##_c = FP_CLS_NORMAL;						\
-	FP_SET_EXCEPTION(FP_EX_DENORM);					\
-      }									\
-    break;								\
-									\
-  case _FP_EXPMAX_##fs:							\
-    if (_FP_FRAC_ZEROP_##wc(X))						\
-      X##_c = FP_CLS_INF;						\
-    else								\
-      {									\
-	X##_c = FP_CLS_NAN;						\
-	/* Check for signaling NaN */					\
-	if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))		\
-	  FP_SET_EXCEPTION(FP_EX_INVALID);				\
-      }									\
-    break;								\
-  }									\
-} while (0)
-
-/*
- * Before packing the bits back into the native fp result, take care
- * of such mundane things as rounding and overflow.  Also, for some
- * kinds of fp values, the original parts may not have been fully
- * extracted -- but that is ok, we can regenerate them now.
- */
-
-#define _FP_PACK_CANONICAL(fs, wc, X)				\
-do {								\
-  switch (X##_c)						\
-  {								\
-  case FP_CLS_NORMAL:						\
-    X##_e += _FP_EXPBIAS_##fs;					\
-    if (X##_e > 0)						\
-      {								\
-	_FP_ROUND(wc, X);					\
-	if (_FP_FRAC_OVERP_##wc(fs, X))				\
-	  {							\
-	    _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1));		\
-	    X##_e++;						\
-	  }							\
-	else							\
-	  _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);			\
-	if (X##_e >= _FP_EXPMAX_##fs)				\
-	  {							\
-	    /* overflow */					\
-	    switch (FP_ROUNDMODE)				\
-	      {							\
-	      case FP_RND_NEAREST:				\
-		X##_c = FP_CLS_INF;				\
-		break;						\
-	      case FP_RND_PINF:					\
-		if (!X##_s) X##_c = FP_CLS_INF;			\
-		break;						\
-	      case FP_RND_MINF:					\
-		if (X##_s) X##_c = FP_CLS_INF;			\
-		break;						\
-	      }							\
-	    if (X##_c == FP_CLS_INF)				\
-	      {							\
-		/* Overflow to infinity */			\
-		X##_e = _FP_EXPMAX_##fs;			\
-		_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);	\
-	      }							\
-	    else						\
-	      {							\
-		/* Overflow to maximum normal */		\
-		X##_e = _FP_EXPMAX_##fs - 1;			\
-		_FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc);		\
-	      }							\
-	    FP_SET_EXCEPTION(FP_EX_OVERFLOW);			\
-            FP_SET_EXCEPTION(FP_EX_INEXACT);			\
-	  }							\
-      }								\
-    else							\
-      {								\
-	/* we've got a denormalized number */			\
-	X##_e = -X##_e + 1;					\
-	if (X##_e <= _FP_WFRACBITS_##fs)			\
-	  {							\
-	    _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);	\
-	    _FP_ROUND(wc, X);					\
-	    if (_FP_FRAC_HIGH_##fs(X)				\
-		& (_FP_OVERFLOW_##fs >> 1))			\
-	      {							\
-	        X##_e = 1;					\
-	        _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);	\
-	      }							\
-	    else						\
-	      {							\
-		X##_e = 0;					\
-		_FP_FRAC_SRL_##wc(X, _FP_WORKBITS);		\
-		FP_SET_EXCEPTION(FP_EX_UNDERFLOW);		\
-	      }							\
-	  }							\
-	else							\
-	  {							\
-	    /* underflow to zero */				\
-	    X##_e = 0;						\
-	    if (!_FP_FRAC_ZEROP_##wc(X))			\
-	      {							\
-	        _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);		\
-	        _FP_ROUND(wc, X);				\
-	        _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS);	\
-	      }							\
-	    FP_SET_EXCEPTION(FP_EX_UNDERFLOW);			\
-	  }							\
-      }								\
-    break;							\
-								\
-  case FP_CLS_ZERO:						\
-    X##_e = 0;							\
-    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			\
-    break;							\
-								\
-  case FP_CLS_INF:						\
-    X##_e = _FP_EXPMAX_##fs;					\
-    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			\
-    break;							\
-								\
-  case FP_CLS_NAN:						\
-    X##_e = _FP_EXPMAX_##fs;					\
-    if (!_FP_KEEPNANFRACP)					\
-      {								\
-	_FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);			\
-	X##_s = _FP_NANSIGN_##fs;				\
-      }								\
-    else							\
-      _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;		\
-    break;							\
-  }								\
-} while (0)
-
-/* This one accepts raw argument and not cooked,  returns
- * 1 if X is a signaling NaN.
- */
-#define _FP_ISSIGNAN(fs, wc, X)					\
-({								\
-  int __ret = 0;						\
-  if (X##_e == _FP_EXPMAX_##fs)					\
-    {								\
-      if (!_FP_FRAC_ZEROP_##wc(X)				\
-	  && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))	\
-	__ret = 1;						\
-    }								\
-  __ret;							\
-})
-
-
-
-
-
-/*
- * Main addition routine.  The input values should be cooked.
- */
-
-#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP)				     \
-do {									     \
-  switch (_FP_CLS_COMBINE(X##_c, Y##_c))				     \
-  {									     \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):			     \
-    {									     \
-      /* shift the smaller number so that its exponent matches the larger */ \
-      _FP_I_TYPE diff = X##_e - Y##_e;					     \
-									     \
-      if (diff < 0)							     \
-	{								     \
-	  diff = -diff;							     \
-	  if (diff <= _FP_WFRACBITS_##fs)				     \
-	    _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs);		     \
-	  else if (!_FP_FRAC_ZEROP_##wc(X))				     \
-	    _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);			     \
-	  R##_e = Y##_e;						     \
-	}								     \
-      else								     \
-	{								     \
-	  if (diff > 0)							     \
-	    {								     \
-	      if (diff <= _FP_WFRACBITS_##fs)				     \
-	        _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs);		     \
-	      else if (!_FP_FRAC_ZEROP_##wc(Y))				     \
-	        _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);			     \
-	    }								     \
-	  R##_e = X##_e;						     \
-	}								     \
-									     \
-      R##_c = FP_CLS_NORMAL;						     \
-									     \
-      if (X##_s == Y##_s)						     \
-	{								     \
-	  R##_s = X##_s;						     \
-	  _FP_FRAC_ADD_##wc(R, X, Y);					     \
-	  if (_FP_FRAC_OVERP_##wc(fs, R))				     \
-	    {								     \
-	      _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);		     \
-	      R##_e++;							     \
-	    }								     \
-	}								     \
-      else								     \
-	{								     \
-	  R##_s = X##_s;						     \
-	  _FP_FRAC_SUB_##wc(R, X, Y);					     \
-	  if (_FP_FRAC_ZEROP_##wc(R))					     \
-	    {								     \
-	      /* return an exact zero */				     \
-	      if (FP_ROUNDMODE == FP_RND_MINF)				     \
-		R##_s |= Y##_s;						     \
-	      else							     \
-		R##_s &= Y##_s;						     \
-	      R##_c = FP_CLS_ZERO;					     \
-	    }								     \
-	  else								     \
-	    {								     \
-	      if (_FP_FRAC_NEGP_##wc(R))				     \
-		{							     \
-		  _FP_FRAC_SUB_##wc(R, Y, X);				     \
-		  R##_s = Y##_s;					     \
-		}							     \
-									     \
-	      /* renormalize after subtraction */			     \
-	      _FP_FRAC_CLZ_##wc(diff, R);				     \
-	      diff -= _FP_WFRACXBITS_##fs;				     \
-	      if (diff)							     \
-		{							     \
-		  R##_e -= diff;					     \
-		  _FP_FRAC_SLL_##wc(R, diff);				     \
-		}							     \
-	    }								     \
-	}								     \
-      break;								     \
-    }									     \
-									     \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):				     \
-    _FP_CHOOSENAN(fs, wc, R, X, Y, OP);					     \
-    break;								     \
-									     \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):			     \
-    R##_e = X##_e;							     \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):			     \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):				     \
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):				     \
-    _FP_FRAC_COPY_##wc(R, X);						     \
-    R##_s = X##_s;							     \
-    R##_c = X##_c;							     \
-    break;								     \
-									     \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):			     \
-    R##_e = Y##_e;							     \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):			     \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):				     \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):				     \
-    _FP_FRAC_COPY_##wc(R, Y);						     \
-    R##_s = Y##_s;							     \
-    R##_c = Y##_c;							     \
-    break;								     \
-									     \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):				     \
-    if (X##_s != Y##_s)							     \
-      {									     \
-	/* +INF + -INF => NAN */					     \
-	_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);				     \
-	R##_s = _FP_NANSIGN_##fs;					     \
-	R##_c = FP_CLS_NAN;						     \
-	FP_SET_EXCEPTION(FP_EX_INVALID);				     \
-	break;								     \
-      }									     \
-    /* FALLTHRU */							     \
-									     \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):			     \
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):				     \
-    R##_s = X##_s;							     \
-    R##_c = FP_CLS_INF;							     \
-    break;								     \
-									     \
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):			     \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):				     \
-    R##_s = Y##_s;							     \
-    R##_c = FP_CLS_INF;							     \
-    break;								     \
-									     \
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):			     \
-    /* make sure the sign is correct */					     \
-    if (FP_ROUNDMODE == FP_RND_MINF)					     \
-      R##_s = X##_s | Y##_s;						     \
-    else								     \
-      R##_s = X##_s & Y##_s;						     \
-    R##_c = FP_CLS_ZERO;						     \
-    break;								     \
-									     \
-  default:								     \
-    abort();								     \
-  }									     \
-} while (0)
-
-#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
-#define _FP_SUB(fs, wc, R, X, Y)					     \
-  do {									     \
-    if (Y##_c != FP_CLS_NAN) Y##_s ^= 1;				     \
-    _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-');				     \
-  } while (0)
-
-
-/*
- * Main negation routine.  FIXME -- when we care about setting exception
- * bits reliably, this will not do.  We should examine all of the fp classes.
- */
-
-#define _FP_NEG(fs, wc, R, X)		\
-  do {					\
-    _FP_FRAC_COPY_##wc(R, X);		\
-    R##_c = X##_c;			\
-    R##_e = X##_e;			\
-    R##_s = 1 ^ X##_s;			\
-  } while (0)
-
-
-/*
- * Main multiplication routine.  The input values should be cooked.
- */
-
-#define _FP_MUL(fs, wc, R, X, Y)			\
-do {							\
-  R##_s = X##_s ^ Y##_s;				\
-  switch (_FP_CLS_COMBINE(X##_c, Y##_c))		\
-  {							\
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):	\
-    R##_c = FP_CLS_NORMAL;				\
-    R##_e = X##_e + Y##_e + 1;				\
-							\
-    _FP_MUL_MEAT_##fs(R,X,Y);				\
-							\
-    if (_FP_FRAC_OVERP_##wc(fs, R))			\
-      _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);	\
-    else						\
-      R##_e--;						\
-    break;						\
-							\
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):		\
-    _FP_CHOOSENAN(fs, wc, R, X, Y, '*');		\
-    break;						\
-							\
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):	\
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):		\
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):		\
-    R##_s = X##_s;					\
-							\
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):		\
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):	\
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):	\
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):	\
-    _FP_FRAC_COPY_##wc(R, X);				\
-    R##_c = X##_c;					\
-    break;						\
-							\
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):	\
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):		\
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):		\
-    R##_s = Y##_s;					\
-							\
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):	\
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):	\
-    _FP_FRAC_COPY_##wc(R, Y);				\
-    R##_c = Y##_c;					\
-    break;						\
-							\
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):		\
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):		\
-    R##_s = _FP_NANSIGN_##fs;				\
-    R##_c = FP_CLS_NAN;					\
-    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
-    FP_SET_EXCEPTION(FP_EX_INVALID);			\
-    break;						\
-							\
-  default:						\
-    abort();						\
-  }							\
-} while (0)
-
-
-/*
- * Main division routine.  The input values should be cooked.
- */
-
-#define _FP_DIV(fs, wc, R, X, Y)			\
-do {							\
-  R##_s = X##_s ^ Y##_s;				\
-  switch (_FP_CLS_COMBINE(X##_c, Y##_c))		\
-  {							\
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):	\
-    R##_c = FP_CLS_NORMAL;				\
-    R##_e = X##_e - Y##_e;				\
-							\
-    _FP_DIV_MEAT_##fs(R,X,Y);				\
-    break;						\
-							\
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):		\
-    _FP_CHOOSENAN(fs, wc, R, X, Y, '/');		\
-    break;						\
-							\
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):	\
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):		\
-  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):		\
-    R##_s = X##_s;					\
-    _FP_FRAC_COPY_##wc(R, X);				\
-    R##_c = X##_c;					\
-    break;						\
-							\
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):	\
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):		\
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):		\
-    R##_s = Y##_s;					\
-    _FP_FRAC_COPY_##wc(R, Y);				\
-    R##_c = Y##_c;					\
-    break;						\
-							\
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):	\
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):		\
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):	\
-    R##_c = FP_CLS_ZERO;				\
-    break;						\
-							\
-  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):	\
-    FP_SET_EXCEPTION(FP_EX_DIVZERO);			\
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):		\
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):	\
-    R##_c = FP_CLS_INF;					\
-    break;						\
-							\
-  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):		\
-  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):	\
-    R##_s = _FP_NANSIGN_##fs;				\
-    R##_c = FP_CLS_NAN;					\
-    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
-    FP_SET_EXCEPTION(FP_EX_INVALID);			\
-    break;						\
-							\
-  default:						\
-    abort();						\
-  }							\
-} while (0)
-
-
-/*
- * Main differential comparison routine.  The inputs should be raw not
- * cooked.  The return is -1,0,1 for normal values, 2 otherwise.
- */
-
-#define _FP_CMP(fs, wc, ret, X, Y, un)					\
-  do {									\
-    /* NANs are unordered */						\
-    if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))		\
-	|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))	\
-      {									\
-	ret = un;							\
-      }									\
-    else								\
-      {									\
-	int __is_zero_x;						\
-	int __is_zero_y;						\
-									\
-	__is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0;	\
-	__is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0;	\
-									\
-	if (__is_zero_x && __is_zero_y)					\
-		ret = 0;						\
-	else if (__is_zero_x)						\
-		ret = Y##_s ? 1 : -1;					\
-	else if (__is_zero_y)						\
-		ret = X##_s ? -1 : 1;					\
-	else if (X##_s != Y##_s)					\
-	  ret = X##_s ? -1 : 1;						\
-	else if (X##_e > Y##_e)						\
-	  ret = X##_s ? -1 : 1;						\
-	else if (X##_e < Y##_e)						\
-	  ret = X##_s ? 1 : -1;						\
-	else if (_FP_FRAC_GT_##wc(X, Y))				\
-	  ret = X##_s ? -1 : 1;						\
-	else if (_FP_FRAC_GT_##wc(Y, X))				\
-	  ret = X##_s ? 1 : -1;						\
-	else								\
-	  ret = 0;							\
-      }									\
-  } while (0)
-
-
-/* Simplification for strict equality.  */
-
-#define _FP_CMP_EQ(fs, wc, ret, X, Y)					  \
-  do {									  \
-    /* NANs are unordered */						  \
-    if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))		  \
-	|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))	  \
-      {									  \
-	ret = 1;							  \
-      }									  \
-    else								  \
-      {									  \
-	ret = !(X##_e == Y##_e						  \
-		&& _FP_FRAC_EQ_##wc(X, Y)				  \
-		&& (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
-      }									  \
-  } while (0)
-
-/*
- * Main square root routine.  The input value should be cooked.
- */
-
-#define _FP_SQRT(fs, wc, R, X)						\
-do {									\
-    _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S);			\
-    _FP_W_TYPE q;							\
-    switch (X##_c)							\
-    {									\
-    case FP_CLS_NAN:							\
-	_FP_FRAC_COPY_##wc(R, X);					\
-	R##_s = X##_s;							\
-    	R##_c = FP_CLS_NAN;						\
-    	break;								\
-    case FP_CLS_INF:							\
-    	if (X##_s)							\
-    	  {								\
-    	    R##_s = _FP_NANSIGN_##fs;					\
-	    R##_c = FP_CLS_NAN; /* NAN */				\
-	    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);			\
-	    FP_SET_EXCEPTION(FP_EX_INVALID);				\
-    	  }								\
-    	else								\
-    	  {								\
-    	    R##_s = 0;							\
-    	    R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */			\
-    	  }								\
-    	break;								\
-    case FP_CLS_ZERO:							\
-	R##_s = X##_s;							\
-	R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */			\
-	break;								\
-    case FP_CLS_NORMAL:							\
-    	R##_s = 0;							\
-        if (X##_s)							\
-          {								\
-	    R##_c = FP_CLS_NAN; /* sNAN */				\
-	    R##_s = _FP_NANSIGN_##fs;					\
-	    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);			\
-	    FP_SET_EXCEPTION(FP_EX_INVALID);				\
-	    break;							\
-          }								\
-    	R##_c = FP_CLS_NORMAL;						\
-        if (X##_e & 1)							\
-          _FP_FRAC_SLL_##wc(X, 1);					\
-        R##_e = X##_e >> 1;						\
-        _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc);			\
-        _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc);			\
-        q = _FP_OVERFLOW_##fs >> 1;					\
-        _FP_SQRT_MEAT_##wc(R, S, T, X, q);				\
-    }									\
-  } while (0)
-
-/*
- * Convert from FP to integer
- */
-
-/* RSIGNED can have following values:
- * 0:  the number is required to be 0..(2^rsize)-1, if not, NV is set plus
- *     the result is either 0 or (2^rsize)-1 depending on the sign in such case.
- * 1:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
- *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
- *     on the sign in such case.
- * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
- *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
- *     on the sign in such case.
- */
-#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)				\
-  do {										\
-    switch (X##_c)								\
-      {										\
-      case FP_CLS_NORMAL:							\
-	if (X##_e < 0)								\
-	  {									\
-	    FP_SET_EXCEPTION(FP_EX_INEXACT);					\
-	  case FP_CLS_ZERO:							\
-	    r = 0;								\
-	  }									\
-	else if (X##_e >= rsize - (rsigned > 0 || X##_s)			\
-		 || (!rsigned && X##_s))					\
-	  {	/* overflow */							\
-	  case FP_CLS_NAN:                                                      \
-	  case FP_CLS_INF:							\
-	    if (rsigned)							\
-	      {									\
-		r = 1;								\
-		r <<= rsize - 1;						\
-		r -= 1 - X##_s;							\
-	      } else {								\
-		r = 0;								\
-		if (X##_s)							\
-		  r = ~r;							\
-	      }									\
-	    FP_SET_EXCEPTION(FP_EX_INVALID);					\
-	  }									\
-	else									\
-	  {									\
-	    if (_FP_W_TYPE_SIZE*wc < rsize)					\
-	      {									\
-		_FP_FRAC_ASSEMBLE_##wc(r, X, rsize);				\
-		r <<= X##_e - _FP_WFRACBITS_##fs;				\
-	      }									\
-	    else								\
-	      {									\
-		if (X##_e >= _FP_WFRACBITS_##fs)				\
-		  _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));	\
-		else if (X##_e < _FP_WFRACBITS_##fs - 1)			\
-		  {								\
-		    _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2),	\
-				      _FP_WFRACBITS_##fs);			\
-		    if (_FP_FRAC_LOW_##wc(X) & 1)				\
-		      FP_SET_EXCEPTION(FP_EX_INEXACT);				\
-		    _FP_FRAC_SRL_##wc(X, 1);					\
-		  }								\
-		_FP_FRAC_ASSEMBLE_##wc(r, X, rsize);				\
-	      }									\
-	    if (rsigned && X##_s)						\
-	      r = -r;								\
-	  }									\
-	break;									\
-      }										\
-  } while (0)
-
-#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)			\
-  do {									\
-    if (r)								\
-      {									\
-	X##_c = FP_CLS_NORMAL;						\
-									\
-	if ((X##_s = (r < 0)))						\
-	  r = -r;							\
-									\
-	if (rsize <= _FP_W_TYPE_SIZE)					\
-	  __FP_CLZ(X##_e, r);						\
-	else								\
-	  __FP_CLZ_2(X##_e, (_FP_W_TYPE)(r >> _FP_W_TYPE_SIZE), 	\
-		     (_FP_W_TYPE)r);					\
-	if (rsize < _FP_W_TYPE_SIZE)					\
-		X##_e -= (_FP_W_TYPE_SIZE - rsize);			\
-	X##_e = rsize - X##_e - 1;					\
-									\
-	if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e)	\
-	  __FP_FRAC_SRS_1(r, (X##_e - _FP_WFRACBITS_##fs), rsize);	\
-	r &= ~((rtype)1 << X##_e);					\
-	_FP_FRAC_DISASSEMBLE_##wc(X, ((unsigned rtype)r), rsize);	\
-	_FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));		\
-      }									\
-    else								\
-      {									\
-	X##_c = FP_CLS_ZERO, X##_s = 0;					\
-      }									\
-  } while (0)
-
-
-#define FP_CONV(dfs,sfs,dwc,swc,D,S)			\
-  do {							\
-    _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S);	\
-    D##_e = S##_e;					\
-    D##_c = S##_c;					\
-    D##_s = S##_s;					\
-  } while (0)
-
-/*
- * Helper primitives.
- */
-
-/* Count leading zeros in a word.  */
-
-#ifndef __FP_CLZ
-#if _FP_W_TYPE_SIZE < 64
-/* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
-#define __FP_CLZ(r, x)				\
-  do {						\
-    _FP_W_TYPE _t = (x);			\
-    r = _FP_W_TYPE_SIZE - 1;			\
-    if (_t > 0xffff) r -= 16;			\
-    if (_t > 0xffff) _t >>= 16;			\
-    if (_t > 0xff) r -= 8;			\
-    if (_t > 0xff) _t >>= 8;			\
-    if (_t & 0xf0) r -= 4;			\
-    if (_t & 0xf0) _t >>= 4;			\
-    if (_t & 0xc) r -= 2;			\
-    if (_t & 0xc) _t >>= 2;			\
-    if (_t & 0x2) r -= 1;			\
-  } while (0)
-#else /* not _FP_W_TYPE_SIZE < 64 */
-#define __FP_CLZ(r, x)				\
-  do {						\
-    _FP_W_TYPE _t = (x);			\
-    r = _FP_W_TYPE_SIZE - 1;			\
-    if (_t > 0xffffffff) r -= 32;		\
-    if (_t > 0xffffffff) _t >>= 32;		\
-    if (_t > 0xffff) r -= 16;			\
-    if (_t > 0xffff) _t >>= 16;			\
-    if (_t > 0xff) r -= 8;			\
-    if (_t > 0xff) _t >>= 8;			\
-    if (_t & 0xf0) r -= 4;			\
-    if (_t & 0xf0) _t >>= 4;			\
-    if (_t & 0xc) r -= 2;			\
-    if (_t & 0xc) _t >>= 2;			\
-    if (_t & 0x2) r -= 1;			\
-  } while (0)
-#endif /* not _FP_W_TYPE_SIZE < 64 */
-#endif /* ndef __FP_CLZ */
-
-#define _FP_DIV_HELP_imm(q, r, n, d)		\
-  do {						\
-    q = n / d, r = n % d;			\
-  } while (0)
-
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/quad.h linux/arch/sparc64/math-emu/quad.h
--- v2.3.15/linux/arch/sparc64/math-emu/quad.h	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/math-emu/quad.h	Wed Dec 31 16:00:00 1969
@@ -1,201 +0,0 @@
-/* Software floating-point emulation.
-   Definitions for IEEE Quad Precision.
-   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Richard Henderson (rth@cygnus.com),
-		  Jakub Jelinek (jj@ultra.linux.cz),
-		  David S. Miller (davem@redhat.com) and
-		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel, kid. Go buy yourself a real computer."
-#endif
-
-#if _FP_W_TYPE_SIZE < 64
-#define _FP_FRACTBITS_Q         (4*_FP_W_TYPE_SIZE)
-#else
-#define _FP_FRACTBITS_Q		(2*_FP_W_TYPE_SIZE)
-#endif
-
-#define _FP_FRACBITS_Q		113
-#define _FP_FRACXBITS_Q		(_FP_FRACTBITS_Q - _FP_FRACBITS_Q)
-#define _FP_WFRACBITS_Q		(_FP_WORKBITS + _FP_FRACBITS_Q)
-#define _FP_WFRACXBITS_Q	(_FP_FRACTBITS_Q - _FP_WFRACBITS_Q)
-#define _FP_EXPBITS_Q		15
-#define _FP_EXPBIAS_Q		16383
-#define _FP_EXPMAX_Q		32767
-
-#define _FP_QNANBIT_Q		\
-	((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2) % _FP_W_TYPE_SIZE)
-#define _FP_IMPLBIT_Q		\
-	((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1) % _FP_W_TYPE_SIZE)
-#define _FP_OVERFLOW_Q		\
-	((_FP_W_TYPE)1 << (_FP_WFRACBITS_Q % _FP_W_TYPE_SIZE))
-
-#if _FP_W_TYPE_SIZE < 64
-
-union _FP_UNION_Q
-{
-   long double flt;
-   struct 
-   {
-#if __BYTE_ORDER == __BIG_ENDIAN
-      unsigned sign : 1;
-      unsigned exp : _FP_EXPBITS_Q;
-      unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
-      unsigned long frac2 : _FP_W_TYPE_SIZE;
-      unsigned long frac1 : _FP_W_TYPE_SIZE;
-      unsigned long frac0 : _FP_W_TYPE_SIZE;
-#else
-      unsigned long frac0 : _FP_W_TYPE_SIZE;
-      unsigned long frac1 : _FP_W_TYPE_SIZE;
-      unsigned long frac2 : _FP_W_TYPE_SIZE;
-      unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
-      unsigned exp : _FP_EXPBITS_Q;
-      unsigned sign : 1;
-#endif /* not bigendian */
-   } bits __attribute__((packed));
-};
-
-
-#define FP_DECL_Q(X)		_FP_DECL(4,X)
-#define FP_UNPACK_RAW_Q(X,val)	_FP_UNPACK_RAW_4(Q,X,val)
-#define FP_UNPACK_RAW_QP(X,val)	_FP_UNPACK_RAW_4_P(Q,X,val)
-#define FP_PACK_RAW_Q(val,X)	_FP_PACK_RAW_4(Q,val,X)
-#define FP_PACK_RAW_QP(val,X)		\
-  do {					\
-    if (!FP_INHIBIT_RESULTS)		\
-      _FP_PACK_RAW_4_P(Q,val,X);	\
-  } while (0)
-
-#define FP_UNPACK_Q(X,val)		\
-  do {					\
-    _FP_UNPACK_RAW_4(Q,X,val);		\
-    _FP_UNPACK_CANONICAL(Q,4,X);	\
-  } while (0)
-
-#define FP_UNPACK_QP(X,val)		\
-  do {					\
-    _FP_UNPACK_RAW_4_P(Q,X,val);	\
-    _FP_UNPACK_CANONICAL(Q,4,X);	\
-  } while (0)
-
-#define FP_PACK_Q(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(Q,4,X);		\
-    _FP_PACK_RAW_4(Q,val,X);		\
-  } while (0)
-
-#define FP_PACK_QP(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(Q,4,X);		\
-    if (!FP_INHIBIT_RESULTS)		\
-      _FP_PACK_RAW_4_P(Q,val,X);	\
-  } while (0)
-
-#define FP_ISSIGNAN_Q(X)		_FP_ISSIGNAN(Q,4,X)
-#define FP_NEG_Q(R,X)			_FP_NEG(Q,4,R,X)
-#define FP_ADD_Q(R,X,Y)			_FP_ADD(Q,4,R,X,Y)
-#define FP_SUB_Q(R,X,Y)			_FP_SUB(Q,4,R,X,Y)
-#define FP_MUL_Q(R,X,Y)			_FP_MUL(Q,4,R,X,Y)
-#define FP_DIV_Q(R,X,Y)			_FP_DIV(Q,4,R,X,Y)
-#define FP_SQRT_Q(R,X)			_FP_SQRT(Q,4,R,X)
-#define _FP_SQRT_MEAT_Q(R,S,T,X,Q)	_FP_SQRT_MEAT_4(R,S,T,X,Q)
-
-#define FP_CMP_Q(r,X,Y,un)	_FP_CMP(Q,4,r,X,Y,un)
-#define FP_CMP_EQ_Q(r,X,Y)	_FP_CMP_EQ(Q,4,r,X,Y)
-
-#define FP_TO_INT_Q(r,X,rsz,rsg)	_FP_TO_INT(Q,4,r,X,rsz,rsg)
-#define FP_FROM_INT_Q(X,r,rs,rt)	_FP_FROM_INT(Q,4,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_Q(X)	_FP_FRAC_HIGH_4(X)
-#define _FP_FRAC_HIGH_RAW_Q(X)	_FP_FRAC_HIGH_4(X)
-
-#else   /* not _FP_W_TYPE_SIZE < 64 */
-union _FP_UNION_Q
-{
-  long double flt /* __attribute__((mode(TF))) */ ;
-  struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
-    unsigned sign  : 1;
-    unsigned exp   : _FP_EXPBITS_Q;
-    unsigned long frac1 : _FP_FRACBITS_Q-(_FP_IMPLBIT_Q != 0)-_FP_W_TYPE_SIZE;
-    unsigned long frac0 : _FP_W_TYPE_SIZE;
-#else
-    unsigned long frac0 : _FP_W_TYPE_SIZE;
-    unsigned long frac1 : _FP_FRACBITS_Q-(_FP_IMPLBIT_Q != 0)-_FP_W_TYPE_SIZE;
-    unsigned exp   : _FP_EXPBITS_Q;
-    unsigned sign  : 1;
-#endif
-  } bits;
-};
-
-#define FP_DECL_Q(X)		_FP_DECL(2,X)
-#define FP_UNPACK_RAW_Q(X,val)	_FP_UNPACK_RAW_2(Q,X,val)
-#define FP_UNPACK_RAW_QP(X,val)	_FP_UNPACK_RAW_2_P(Q,X,val)
-#define FP_PACK_RAW_Q(val,X)	_FP_PACK_RAW_2(Q,val,X)
-#define FP_PACK_RAW_QP(val,X)		\
-  do {					\
-    if (!FP_INHIBIT_RESULTS)		\
-      _FP_PACK_RAW_2_P(Q,val,X);	\
-  } while (0)
-
-#define FP_UNPACK_Q(X,val)		\
-  do {					\
-    _FP_UNPACK_RAW_2(Q,X,val);		\
-    _FP_UNPACK_CANONICAL(Q,2,X);	\
-  } while (0)
-
-#define FP_UNPACK_QP(X,val)		\
-  do {					\
-    _FP_UNPACK_RAW_2_P(Q,X,val);	\
-    _FP_UNPACK_CANONICAL(Q,2,X);	\
-  } while (0)
-
-#define FP_PACK_Q(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(Q,2,X);		\
-    _FP_PACK_RAW_2(Q,val,X);		\
-  } while (0)
-
-#define FP_PACK_QP(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(Q,2,X);		\
-    if (!FP_INHIBIT_RESULTS)		\
-      _FP_PACK_RAW_2_P(Q,val,X);	\
-  } while (0)
-
-#define FP_ISSIGNAN_Q(X)		_FP_ISSIGNAN(Q,2,X)
-#define FP_NEG_Q(R,X)			_FP_NEG(Q,2,R,X)
-#define FP_ADD_Q(R,X,Y)			_FP_ADD(Q,2,R,X,Y)
-#define FP_SUB_Q(R,X,Y)			_FP_SUB(Q,2,R,X,Y)
-#define FP_MUL_Q(R,X,Y)			_FP_MUL(Q,2,R,X,Y)
-#define FP_DIV_Q(R,X,Y)			_FP_DIV(Q,2,R,X,Y)
-#define FP_SQRT_Q(R,X)			_FP_SQRT(Q,2,R,X)
-#define _FP_SQRT_MEAT_Q(R,S,T,X,Q)	_FP_SQRT_MEAT_2(R,S,T,X,Q)
-
-#define FP_CMP_Q(r,X,Y,un)	_FP_CMP(Q,2,r,X,Y,un)
-#define FP_CMP_EQ_Q(r,X,Y)	_FP_CMP_EQ(Q,2,r,X,Y)
-
-#define FP_TO_INT_Q(r,X,rsz,rsg)	_FP_TO_INT(Q,2,r,X,rsz,rsg)
-#define FP_FROM_INT_Q(X,r,rs,rt)	_FP_FROM_INT(Q,2,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_Q(X)	_FP_FRAC_HIGH_2(X)
-#define _FP_FRAC_HIGH_RAW_Q(X)	_FP_FRAC_HIGH_2(X)
-
-#endif /* not _FP_W_TYPE_SIZE < 64 */
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/single.h linux/arch/sparc64/math-emu/single.h
--- v2.3.15/linux/arch/sparc64/math-emu/single.h	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/single.h	Wed Dec 31 16:00:00 1969
@@ -1,110 +0,0 @@
-/* Software floating-point emulation.
-   Definitions for IEEE Single Precision.
-   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Richard Henderson (rth@cygnus.com),
-		  Jakub Jelinek (jj@ultra.linux.cz),
-		  David S. Miller (davem@redhat.com) and
-		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#if _FP_W_TYPE_SIZE < 32
-#error "Here's a nickel kid.  Go buy yourself a real computer."
-#endif
-
-#define _FP_FRACBITS_S		24
-#define _FP_FRACXBITS_S		(_FP_W_TYPE_SIZE - _FP_FRACBITS_S)
-#define _FP_WFRACBITS_S		(_FP_WORKBITS + _FP_FRACBITS_S)
-#define _FP_WFRACXBITS_S	(_FP_W_TYPE_SIZE - _FP_WFRACBITS_S)
-#define _FP_EXPBITS_S		8
-#define _FP_EXPBIAS_S		127
-#define _FP_EXPMAX_S		255
-#define _FP_QNANBIT_S		((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2))
-#define _FP_IMPLBIT_S		((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1))
-#define _FP_OVERFLOW_S		((_FP_W_TYPE)1 << (_FP_WFRACBITS_S))
-
-/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be
-   chosen by the target machine.  */
-
-union _FP_UNION_S
-{
-  float flt;
-  struct {
-#if __BYTE_ORDER == __BIG_ENDIAN
-    unsigned sign : 1;
-    unsigned exp  : _FP_EXPBITS_S;
-    unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
-#else
-    unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
-    unsigned exp  : _FP_EXPBITS_S;
-    unsigned sign : 1;
-#endif
-  } bits __attribute__((packed));
-};
-
-#define FP_DECL_S(X)		_FP_DECL(1,X)
-#define FP_UNPACK_RAW_S(X,val)	_FP_UNPACK_RAW_1(S,X,val)
-#define FP_UNPACK_RAW_SP(X,val)	_FP_UNPACK_RAW_1_P(S,X,val)
-#define FP_PACK_RAW_S(val,X)	_FP_PACK_RAW_1(S,val,X)
-#define FP_PACK_RAW_SP(val,X)		\
-  do {					\
-    if (!FP_INHIBIT_RESULTS)		\
-      _FP_PACK_RAW_1_P(S,val,X);	\
-  } while (0)
-
-#define FP_UNPACK_S(X,val)		\
-  do {					\
-    _FP_UNPACK_RAW_1(S,X,val);		\
-    _FP_UNPACK_CANONICAL(S,1,X);	\
-  } while (0)
-
-#define FP_UNPACK_SP(X,val)		\
-  do {					\
-    _FP_UNPACK_RAW_1_P(S,X,val);	\
-    _FP_UNPACK_CANONICAL(S,1,X);	\
-  } while (0)
-
-#define FP_PACK_S(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(S,1,X);		\
-    _FP_PACK_RAW_1(S,val,X);		\
-  } while (0)
-
-#define FP_PACK_SP(val,X)		\
-  do {					\
-    _FP_PACK_CANONICAL(S,1,X);		\
-    if (!FP_INHIBIT_RESULTS)		\
-      _FP_PACK_RAW_1_P(S,val,X);	\
-  } while (0)
-
-#define FP_ISSIGNAN_S(X)		_FP_ISSIGNAN(S,1,X)
-#define FP_NEG_S(R,X)			_FP_NEG(S,1,R,X)
-#define FP_ADD_S(R,X,Y)			_FP_ADD(S,1,R,X,Y)
-#define FP_SUB_S(R,X,Y)			_FP_SUB(S,1,R,X,Y)
-#define FP_MUL_S(R,X,Y)			_FP_MUL(S,1,R,X,Y)
-#define FP_DIV_S(R,X,Y)			_FP_DIV(S,1,R,X,Y)
-#define FP_SQRT_S(R,X)			_FP_SQRT(S,1,R,X)
-#define _FP_SQRT_MEAT_S(R,S,T,X,Q)	_FP_SQRT_MEAT_1(R,S,T,X,Q)
-
-#define FP_CMP_S(r,X,Y,un)	_FP_CMP(S,1,r,X,Y,un)
-#define FP_CMP_EQ_S(r,X,Y)	_FP_CMP_EQ(S,1,r,X,Y)
-
-#define FP_TO_INT_S(r,X,rsz,rsg)	_FP_TO_INT(S,1,r,X,rsz,rsg)
-#define FP_FROM_INT_S(X,r,rs,rt)	_FP_FROM_INT(S,1,X,r,rs,rt)
-
-#define _FP_FRAC_HIGH_S(X)	_FP_FRAC_HIGH_1(X)
-#define _FP_FRAC_HIGH_RAW_S(X)	_FP_FRAC_HIGH_1(X)
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/math-emu/soft-fp.h linux/arch/sparc64/math-emu/soft-fp.h
--- v2.3.15/linux/arch/sparc64/math-emu/soft-fp.h	Sat May 29 11:09:04 1999
+++ linux/arch/sparc64/math-emu/soft-fp.h	Wed Dec 31 16:00:00 1969
@@ -1,176 +0,0 @@
-/* Software floating-point emulation.
-   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Richard Henderson (rth@cygnus.com),
-		  Jakub Jelinek (jj@ultra.linux.cz),
-		  David S. Miller (davem@redhat.com) and
-		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Library General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Library General Public License for more details.
-
-   You should have received a copy of the GNU Library General Public
-   License along with the GNU C Library; see the file COPYING.LIB.  If
-   not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#ifndef SOFT_FP_H
-#define SOFT_FP_H
-
-#include "sfp-machine.h"
-
-/* Allow sfp-machine to have its own byte order definitions. */
-#ifndef __BYTE_ORDER
-#include <endian.h>
-#endif
-
-#define _FP_WORKBITS		3
-#define _FP_WORK_LSB		((_FP_W_TYPE)1 << 3)
-#define _FP_WORK_ROUND		((_FP_W_TYPE)1 << 2)
-#define _FP_WORK_GUARD		((_FP_W_TYPE)1 << 1)
-#define _FP_WORK_STICKY		((_FP_W_TYPE)1 << 0)
-
-#ifndef FP_RND_NEAREST
-# define FP_RND_NEAREST		0
-# define FP_RND_ZERO		1
-# define FP_RND_PINF		2
-# define FP_RND_MINF		3
-#ifndef FP_ROUNDMODE
-# define FP_ROUNDMODE		FP_RND_NEAREST
-#endif
-#endif
-
-/* By default don't care about exceptions. */
-#ifndef FP_EX_INVALID
-#define FP_EX_INVALID		0
-#endif
-#ifndef FP_EX_OVERFLOW
-#define FP_EX_OVERFLOW		0
-#endif
-#ifndef FP_EX_UNDERFLOW
-#define FP_EX_UNDERFLOW		
-#endif
-#ifndef FP_EX_DIVZERO
-#define FP_EX_DIVZERO		0
-#endif
-#ifndef FP_EX_INEXACT
-#define FP_EX_INEXACT		0
-#endif
-#ifndef FP_EX_DENORM
-#define FP_EX_DENORM		0
-#endif
-
-#ifdef _FP_DECL_EX
-#define FP_DECL_EX					\
-  int _fex = 0;						\
-  _FP_DECL_EX
-#else
-#define FP_DECL_EX int _fex = 0
-#endif
-  
-#ifndef FP_INIT_ROUNDMODE
-#define FP_INIT_ROUNDMODE do {} while (0)
-#endif
-
-#ifndef FP_HANDLE_EXCEPTIONS
-#define FP_HANDLE_EXCEPTIONS do {} while (0)
-#endif
-
-#ifndef FP_INHIBIT_RESULTS
-/* By default we write the results always.
- * sfp-machine may override this and e.g.
- * check if some exceptions are unmasked
- * and inhibit it in such a case.
- */
-#define FP_INHIBIT_RESULTS 0
-#endif
-
-#define FP_SET_EXCEPTION(ex)				\
-  _fex |= (ex)
-  
-#define FP_UNSET_EXCEPTION(ex)				\
-  _fex &= ~(ex)
-
-#define FP_CLEAR_EXCEPTIONS				\
-  _fex = 0
-
-#define _FP_ROUND_NEAREST(wc, X)			\
-do {							\
-    if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND)	\
-      _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND);		\
-} while (0)
-
-#define _FP_ROUND_ZERO(wc, X)		0
-
-#define _FP_ROUND_PINF(wc, X)				\
-do {							\
-    if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7))		\
-      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);		\
-} while (0)
-
-#define _FP_ROUND_MINF(wc, X)				\
-do {							\
-    if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7))		\
-      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);		\
-} while (0)
-
-#define _FP_ROUND(wc, X)			\
-do {						\
-	if (_FP_FRAC_LOW_##wc(X) & 7)		\
-	  FP_SET_EXCEPTION(FP_EX_INEXACT);	\
-	switch (FP_ROUNDMODE)			\
-	{					\
-	  case FP_RND_NEAREST:			\
-	    _FP_ROUND_NEAREST(wc,X);		\
-	    break;				\
-	  case FP_RND_ZERO:			\
-	    _FP_ROUND_ZERO(wc,X);		\
-	    break;				\
-	  case FP_RND_PINF:			\
-	    _FP_ROUND_PINF(wc,X);		\
-	    break;				\
-	  case FP_RND_MINF:			\
-	    _FP_ROUND_MINF(wc,X);		\
-	    break;				\
-	}					\
-} while (0)
-
-#define FP_CLS_NORMAL		0
-#define FP_CLS_ZERO		1
-#define FP_CLS_INF		2
-#define FP_CLS_NAN		3
-
-#define _FP_CLS_COMBINE(x,y)	(((x) << 2) | (y))
-
-#include "op-1.h"
-#include "op-2.h"
-#include "op-4.h"
-#include "op-8.h"
-#include "op-common.h"
-
-/* Sigh.  Silly things longlong.h needs.  */
-#define UWtype		_FP_W_TYPE
-#define W_TYPE_SIZE	_FP_W_TYPE_SIZE
-
-typedef int SItype __attribute__((mode(SI)));
-typedef int DItype __attribute__((mode(DI)));
-typedef unsigned int USItype __attribute__((mode(SI)));
-typedef unsigned int UDItype __attribute__((mode(DI)));
-#if _FP_W_TYPE_SIZE == 32
-typedef unsigned int UHWtype __attribute__((mode(HI)));
-#elif _FP_W_TYPE_SIZE == 64
-typedef USItype UHWtype;
-#endif
-
-#ifndef umul_ppmm
-#include <stdlib/longlong.h>
-#endif
-
-#endif
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c
--- v2.3.15/linux/arch/sparc64/mm/fault.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/mm/fault.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.38 1999/08/02 08:39:50 davem Exp $
+/* $Id: fault.c,v 1.39 1999/08/30 10:07:09 davem Exp $
  * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -312,6 +312,16 @@
 				return;
 			}
 		} else {
+#if 0
+			extern void __show_regs(struct pt_regs *);
+			printk("SHIT(%s:%d:cpu(%d)): PC[%016lx] ADDR[%016lx]\n",
+			       current->comm, current->pid, smp_processor_id(),
+			       regs->tpc, address);
+			__show_regs(regs);
+			__sti();
+			while(1)
+				barrier();
+#endif
 			current->thread.sig_address = address;
 			current->thread.sig_desc = SUBSIG_NOMAPPING;
 			force_sig(SIGSEGV, current);
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.3.15/linux/arch/sparc64/mm/init.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/mm/init.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.131 1999/07/30 09:35:45 davem Exp $
+/*  $Id: init.c,v 1.134 1999/08/31 06:54:58 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -166,7 +166,7 @@
 static unsigned long dvmaiobase = 0;
 static unsigned long dvmaiosz __initdata = 0;
 
-__initfunc(void dvmaio_init(void))
+void __init dvmaio_init(void)
 {
 	long i;
 	
@@ -187,7 +187,7 @@
 	}
 }
 
-__initfunc(void iommu_init(int iommu_node, struct linux_sbus *sbus))
+void __init iommu_init(int iommu_node, struct linux_sbus *sbus)
 {
 	extern int this_is_starfire;
 	extern void *starfire_hookup(int);
@@ -586,7 +586,8 @@
 	struct linux_sbus *sbus = sdev->my_bus;
 	struct sysio_regs *sregs = sbus->iommu->sysio_regs;
 	int slot = sdev->slot;
-	u64 *cfg, tmp;
+	volatile u64 *cfg;
+	u64 tmp;
 
 	switch(slot) {
 	case 0:
@@ -1044,8 +1045,8 @@
 	return NULL;
 }
 
-__initfunc(static void
-allocate_ptable_skeleton(unsigned long start, unsigned long end))
+static void __init
+allocate_ptable_skeleton(unsigned long start, unsigned long end)
 {
 	pgd_t *pgdp;
 	pmd_t *pmdp;
@@ -1142,8 +1143,8 @@
 extern unsigned long free_area_init(unsigned long, unsigned long);
 extern unsigned long sun_serial_setup(unsigned long);
 
-__initfunc(unsigned long 
-paging_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init
+paging_init(unsigned long start_mem, unsigned long end_mem)
 {
 	extern pmd_t swapper_pmd_dir[1024];
 	extern unsigned int sparc64_vpte_patchme1[1];
@@ -1262,7 +1263,7 @@
 	return device_scan (PAGE_ALIGN (start_mem));
 }
 
-__initfunc(static void taint_real_pages(unsigned long start_mem, unsigned long end_mem))
+static void __init taint_real_pages(unsigned long start_mem, unsigned long end_mem)
 {
 	unsigned long tmp = 0, paddr, endaddr;
 	unsigned long end = __pa(end_mem);
@@ -1308,7 +1309,7 @@
 	}
 }
 
-__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
+void __init mem_init(unsigned long start_mem, unsigned long end_mem)
 {
 	int codepages = 0;
 	int datapages = 0;
@@ -1322,6 +1323,7 @@
 	max_mapnr = MAP_NR(end_mem);
 	high_memory = (void *) end_mem;
 	
+	start_mem = ((start_mem + 7UL) & ~7UL);
 	sparc64_valid_addr_bitmap = (unsigned long *)start_mem;
 	i = max_mapnr >> ((22 - PAGE_SHIFT) + 6);
 	i += 1;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/prom/bootstr.c linux/arch/sparc64/prom/bootstr.c
--- v2.3.15/linux/arch/sparc64/prom/bootstr.c	Tue Apr 14 17:44:21 1998
+++ linux/arch/sparc64/prom/bootstr.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: bootstr.c,v 1.5 1998/01/23 08:51:39 jj Exp $
+/* $Id: bootstr.c,v 1.6 1999/08/31 06:55:01 davem Exp $
  * bootstr.c:  Boot string/argument acquisition from the PROM.
  *
  * Copyright(C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -14,8 +14,8 @@
 static int bootstr_valid = 0;
 static char bootstr_buf[BARG_LEN] = { 0 };
 
-__initfunc(char *
-prom_getbootargs(void))
+char * __init
+prom_getbootargs(void)
 {
 	/* This check saves us from a panic when bootfd patches args. */
 	if (bootstr_valid) return bootstr_buf;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/prom/init.c linux/arch/sparc64/prom/init.c
--- v2.3.15/linux/arch/sparc64/prom/init.c	Tue Apr 14 17:44:21 1998
+++ linux/arch/sparc64/prom/init.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.8 1998/03/15 10:14:44 ecd Exp $
+/* $Id: init.c,v 1.9 1999/08/31 06:55:03 davem Exp $
  * init.c:  Initialize internal variables used by the PROM
  *          library functions.
  *
@@ -31,7 +31,7 @@
 extern void prom_ranges_init(void);
 extern void prom_cif_init(void *, void *);
 
-__initfunc(void prom_init(void *cif_handler, void *cif_stack))
+void __init prom_init(void *cif_handler, void *cif_stack)
 {
 	char buffer[80], *p;
 	int ints[3];
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/prom/memory.c linux/arch/sparc64/prom/memory.c
--- v2.3.15/linux/arch/sparc64/prom/memory.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/prom/memory.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: memory.c,v 1.4 1998/11/25 10:04:06 jj Exp $
+/* $Id: memory.c,v 1.5 1999/08/31 06:55:04 davem Exp $
  * memory.c: Prom routine for acquiring various bits of information
  *           about RAM on the machine, both virtual and physical.
  *
@@ -37,8 +37,8 @@
 /* Internal Prom library routine to sort a linux_mlist_p1275 memory
  * list.  Used below in initialization.
  */
-__initfunc(static void
-prom_sortmemlist(struct linux_mlist_p1275 *thislist))
+static void __init
+prom_sortmemlist(struct linux_mlist_p1275 *thislist)
 {
 	int swapi = 0;
 	int i, mitr;
@@ -65,7 +65,7 @@
 }
 
 /* Initialize the memory lists based upon the prom version. */
-__initfunc(void prom_meminit(void))
+void __init prom_meminit(void)
 {
 	int node = 0;
 	unsigned int iter, num_regs;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/prom/ranges.c linux/arch/sparc64/prom/ranges.c
--- v2.3.15/linux/arch/sparc64/prom/ranges.c	Tue Apr 14 17:44:21 1998
+++ linux/arch/sparc64/prom/ranges.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: ranges.c,v 1.10 1998/03/24 05:54:29 ecd Exp $
+/* $Id: ranges.c,v 1.12 1999/08/31 06:55:05 davem Exp $
  * ranges.c: Handle ranges in newer proms for obio/sbus.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -87,11 +87,11 @@
 				 central->num_central_ranges);
 }
 
-__initfunc(void prom_ranges_init(void))
+void __init prom_ranges_init(void)
 {
 }
 
-__initfunc(void prom_sbus_ranges_init(int iommund, struct linux_sbus *sbus))
+void __init prom_sbus_ranges_init(int iommund, struct linux_sbus *sbus)
 {
 	int success;
 	
@@ -103,7 +103,7 @@
 		sbus->num_sbus_ranges = (success/sizeof(struct linux_prom_ranges));
 }
 
-__initfunc(void prom_central_ranges_init(int cnode, struct linux_central *central))
+void __init prom_central_ranges_init(int cnode, struct linux_central *central)
 {
 	int success;
 	
@@ -115,7 +115,7 @@
 		central->num_central_ranges = (success/sizeof(struct linux_prom_ranges));
 }
 
-__initfunc(void prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc))
+void __init prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc)
 {
 	int success;
 	
@@ -128,7 +128,7 @@
 }
 
 #ifdef CONFIG_PCI
-__initfunc(void prom_ebus_ranges_init(struct linux_ebus *ebus))
+void __init prom_ebus_ranges_init(struct linux_ebus *ebus)
 {
 	int success;
 
@@ -140,7 +140,7 @@
 		ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges));
 }
 
-__initfunc(void prom_ebus_intmap_init(struct linux_ebus *ebus))
+void __init prom_ebus_intmap_init(struct linux_ebus *ebus)
 {
 	int success;
 
@@ -156,40 +156,6 @@
 	success = prom_getproperty(ebus->prom_node, "interrupt-map-mask",
 				   (char *)&ebus->ebus_intmask,
 				   sizeof(ebus->ebus_intmask));
-	if (success == -1) {
-		prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__);
-		prom_halt();
-	}
-}
-
-__initfunc(void prom_pbm_ranges_init(int pnode, struct linux_pbm_info *pbm))
-{
-	int success;
-
-	pbm->num_pbm_ranges = 0;
-	success = prom_getproperty(pnode, "ranges",
-				   (char *)&pbm->pbm_ranges,
-				   sizeof(pbm->pbm_ranges));
-	if(success != -1)
-		pbm->num_pbm_ranges = (success/sizeof(struct linux_prom_pci_ranges));
-}
-
-__initfunc(void prom_pbm_intmap_init(int pnode, struct linux_pbm_info *pbm))
-{
-	int success;
-
-	pbm->num_pbm_intmap = 0;
-	success = prom_getproperty(pnode, "interrupt-map",
-				   (char *)pbm->pbm_intmap,
-				   sizeof(pbm->pbm_intmap));
-	if (success == -1)
-		return;
-
-	pbm->num_pbm_intmap = (success/sizeof(struct linux_prom_pci_intmap));
-
-	success = prom_getproperty(pnode, "interrupt-map-mask",
-				   (char *)&pbm->pbm_intmask,
-				   sizeof(pbm->pbm_intmask));
 	if (success == -1) {
 		prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__);
 		prom_halt();
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/solaris/ioctl.c linux/arch/sparc64/solaris/ioctl.c
--- v2.3.15/linux/arch/sparc64/solaris/ioctl.c	Wed Aug 18 11:39:02 1999
+++ linux/arch/sparc64/solaris/ioctl.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: ioctl.c,v 1.12 1999/07/23 01:57:03 davem Exp $
+/* $Id: ioctl.c,v 1.13 1999/08/20 00:27:15 davem Exp $
  * ioctl.c: Solaris ioctl emulation.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/solaris/socksys.c linux/arch/sparc64/solaris/socksys.c
--- v2.3.15/linux/arch/sparc64/solaris/socksys.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/solaris/socksys.c	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: socksys.c,v 1.9 1999/07/23 01:57:07 davem Exp $
+/* $Id: socksys.c,v 1.10 1999/08/31 06:55:08 davem Exp $
  * socksys.c: /dev/inet/ stuff for Solaris emulation.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -174,8 +174,8 @@
 	socksys_release,/* release */
 };
 
-__initfunc(int
-init_socksys(void))
+int __init
+init_socksys(void)
 {
 	int ret;
 	struct file * file;
diff -u --recursive --new-file v2.3.15/linux/arch/sparc64/solaris/timod.c linux/arch/sparc64/solaris/timod.c
--- v2.3.15/linux/arch/sparc64/solaris/timod.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/solaris/timod.c	Tue Aug 31 11:30:47 1999
@@ -677,7 +677,7 @@
 		wait = &wait_table;
 		for(;;) {
 			SOLD("loop");
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			/* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ 
 			/* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ 
 			/* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ 
diff -u --recursive --new-file v2.3.15/linux/drivers/acorn/char/keyb_arc.c linux/drivers/acorn/char/keyb_arc.c
--- v2.3.15/linux/drivers/acorn/char/keyb_arc.c	Mon Jul  5 20:35:18 1999
+++ linux/drivers/acorn/char/keyb_arc.c	Mon Aug 30 18:15:19 1999
@@ -419,7 +419,7 @@
 };
 #endif
 
-__initfunc(void a5kkbd_init_hw (void))
+void __init a5kkbd_init_hw (void)
 {
 	unsigned long flags;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/acorn/char/keyb_ps2.c linux/drivers/acorn/char/keyb_ps2.c
--- v2.3.15/linux/drivers/acorn/char/keyb_ps2.c	Thu Jun 17 01:11:35 1999
+++ linux/drivers/acorn/char/keyb_ps2.c	Thu Aug 26 12:42:33 1999
@@ -325,7 +325,7 @@
 {
 }
 
-__initfunc(int ps2kbd_init_hw(void))
+int __init ps2kbd_init_hw(void)
 {
 	unsigned long flags;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/acorn/net/ether1.c linux/drivers/acorn/net/ether1.c
--- v2.3.15/linux/drivers/acorn/net/ether1.c	Wed Aug 18 11:38:59 1999
+++ linux/drivers/acorn/net/ether1.c	Mon Aug 30 18:15:21 1999
@@ -254,8 +254,8 @@
 	}
 }
 
-__initfunc(static int
-ether1_ramtest (struct net_device *dev, unsigned char byte))
+static int __init
+ether1_ramtest (struct net_device *dev, unsigned char byte)
 {
 	unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL);
 	int i, ret = BUFFER_SIZE;
@@ -308,8 +308,8 @@
 	return BUS_16;
 }
 
-__initfunc(static int
-ether1_init_2 (struct net_device *dev))
+static int __init
+ether1_init_2 (struct net_device *dev)
 {
 	int i;
 	dev->mem_start = 0;
@@ -612,8 +612,8 @@
 	return failures ? 1 : 0;
 }
 
-__initfunc(static int
-ether1_probe1 (struct net_device *dev))
+static int __init
+ether1_probe1 (struct net_device *dev)
 {
 	static unsigned int version_printed = 0;
 	struct ether1_priv *priv;
@@ -664,8 +664,8 @@
     
 /* ------------------------------------------------------------------------- */
 
-__initfunc(static void
-ether1_addr (struct net_device *dev))
+static void __init
+ether1_addr (struct net_device *dev)
 {
 	int i;
     
@@ -673,8 +673,8 @@
 		dev->dev_addr[i] = inb (IDPROM_ADDRESS + i);
 }
 
-__initfunc(int
-ether1_probe (struct net_device *dev))
+int __init
+ether1_probe (struct net_device *dev)
 {
 #ifndef MODULE
 	struct expansion_card *ec;
diff -u --recursive --new-file v2.3.15/linux/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c
--- v2.3.15/linux/drivers/acorn/net/ether3.c	Wed Aug 18 11:38:59 1999
+++ linux/drivers/acorn/net/ether3.c	Mon Aug 30 18:15:21 1999
@@ -199,8 +199,8 @@
  * Read the ethernet address string from the on board rom.
  * This is an ascii string!!!
  */
-__initfunc(static void
-ether3_addr(char *addr, struct expansion_card *ec))
+static void __init
+ether3_addr(char *addr, struct expansion_card *ec)
 {
 	struct in_chunk_dir cd;
 	char *s;
@@ -224,8 +224,8 @@
 
 /* --------------------------------------------------------------------------- */
 
-__initfunc(static int
-ether3_ramtest(struct net_device *dev, unsigned char byte))
+static int __init
+ether3_ramtest(struct net_device *dev, unsigned char byte)
 {
 	unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL);
 	int i,ret = 0;
@@ -273,8 +273,8 @@
 
 /* ------------------------------------------------------------------------------- */
 
-__initfunc(static int
-ether3_init_2(struct net_device *dev))
+static int __init
+ether3_init_2(struct net_device *dev)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 	int i;
@@ -400,8 +400,8 @@
 /*
  * This is the real probe routine.
  */
-__initfunc(static int
-ether3_probe1(struct net_device *dev))
+static int __init
+ether3_probe1(struct net_device *dev)
 {
 	static unsigned version_printed = 0;
 	struct dev_priv *priv;
@@ -478,8 +478,8 @@
 	return error;
 }
 
-__initfunc(static void
-ether3_get_dev(struct net_device *dev, struct expansion_card *ec))
+static void __init
+ether3_get_dev(struct net_device *dev, struct expansion_card *ec)
 {
 	ecard_claim(ec);
 
@@ -498,8 +498,8 @@
 }
 
 #ifndef MODULE
-__initfunc(int
-ether3_probe(struct net_device *dev))
+int __init
+ether3_probe(struct net_device *dev)
 {
 	struct expansion_card *ec;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/acorn/net/etherh.c linux/drivers/acorn/net/etherh.c
--- v2.3.15/linux/drivers/acorn/net/etherh.c	Wed Aug 18 11:38:59 1999
+++ linux/drivers/acorn/net/etherh.c	Mon Aug 30 18:15:21 1999
@@ -84,8 +84,8 @@
  * Read the ethernet address string from the on board rom.
  * This is an ascii string...
  */
-__initfunc(static int
-etherh_addr(char *addr, struct expansion_card *ec))
+static int __init
+etherh_addr(char *addr, struct expansion_card *ec)
 {
 	struct in_chunk_dir cd;
 	char *s;
@@ -352,8 +352,8 @@
 /*
  * This is the real probe routine.
  */
-__initfunc(static int
-etherh_probe1(struct net_device *dev))
+static int __init
+etherh_probe1(struct net_device *dev)
 {
 	static int version_printed;
 	unsigned int addr, i, reg0, tmp;
@@ -463,8 +463,8 @@
 	NULL
 };
 
-__initfunc(static void
-etherh_initdev(ecard_t *ec, struct net_device *dev))
+static void __init
+etherh_initdev(ecard_t *ec, struct net_device *dev)
 {
 	ecard_claim (ec);
 	
@@ -496,8 +496,8 @@
 }
 
 #ifndef MODULE
-__initfunc(int
-etherh_probe(struct net_device *dev))
+int __init
+etherh_probe(struct net_device *dev)
 {
 	if (!dev)
 		return ENODEV;
diff -u --recursive --new-file v2.3.15/linux/drivers/acorn/net/net-probe.c linux/drivers/acorn/net/net-probe.c
--- v2.3.15/linux/drivers/acorn/net/net-probe.c	Wed Aug 18 11:38:59 1999
+++ linux/drivers/acorn/net/net-probe.c	Thu Aug 26 12:42:33 1999
@@ -12,7 +12,7 @@
 extern int ether3_probe (struct net_device *dev);
 extern int etherh_probe (struct net_device *dev);
 
-__initfunc(int acorn_ethif_probe(struct net_device *dev))
+int __init acorn_ethif_probe(struct net_device *dev)
 {
 	if (1
 #ifdef CONFIG_ARM_ETHERH
diff -u --recursive --new-file v2.3.15/linux/drivers/atm/Makefile linux/drivers/atm/Makefile
--- v2.3.15/linux/drivers/atm/Makefile	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/Makefile	Mon Aug 30 10:18:40 1999
@@ -21,10 +21,10 @@
 endif
 
 ifeq ($(CONFIG_ATM_ZATM),y)
-L_OBJS += zatm.o uPD98402.o
+LX_OBJS += zatm.o uPD98402.o
 else
   ifeq ($(CONFIG_ATM_ZATM),m)
-  M_OBJS += zatm.o uPD98402.o
+  MX_OBJS += zatm.o uPD98402.o
   endif
 endif
 
diff -u --recursive --new-file v2.3.15/linux/drivers/atm/ambassador.c linux/drivers/atm/ambassador.c
--- v2.3.15/linux/drivers/atm/ambassador.c	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/ambassador.c	Mon Aug 30 10:18:40 1999
@@ -2338,8 +2338,8 @@
     
     // read resources from PCI configuration space
     u32 * membase = bus_to_virt
-      (pci_dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK);
-    u32 iobase = pci_dev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
+      (pci_dev->resource[0].start);
+    u32 iobase = pci_dev->resource[1].start;
     u8 irq = pci_dev->irq;
     
     // check IO region
diff -u --recursive --new-file v2.3.15/linux/drivers/atm/atmdev_init.c linux/drivers/atm/atmdev_init.c
--- v2.3.15/linux/drivers/atm/atmdev_init.c	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/atmdev_init.c	Thu Aug 26 12:42:33 1999
@@ -30,7 +30,7 @@
 #endif
 
 
-__initfunc(int atmdev_init(void))
+int __init atmdev_init(void)
 {
 	int devs;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/atm/eni.c linux/drivers/atm/eni.c
--- v2.3.15/linux/drivers/atm/eni.c	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/eni.c	Mon Aug 30 10:18:40 1999
@@ -1548,7 +1548,7 @@
   } })
 
 
-__initfunc(static int get_esi_asic(struct atm_dev *dev))
+static int __init get_esi_asic(struct atm_dev *dev)
 {
 	struct eni_dev *eni_dev;
 	unsigned char tonga;
@@ -1640,7 +1640,7 @@
 #undef GET_SEPROM
 
 
-__initfunc(static int get_esi_fpga(struct atm_dev *dev,unsigned long base))
+static int __init get_esi_fpga(struct atm_dev *dev,unsigned long base)
 {
 	unsigned long mac_base;
 	int i;
@@ -1651,7 +1651,7 @@
 }
 
 
-__initfunc(static int eni_init(struct atm_dev *dev))
+static int __init eni_init(struct atm_dev *dev)
 {
 	struct midway_eprom *eprom;
 	struct eni_dev *eni_dev;
@@ -1666,7 +1666,7 @@
 	dev->link_rate = ATM_OC3_PCR;
 	eni_dev = ENI_DEV(dev);
 	pci_dev = eni_dev->pci_dev;
-	real_base = pci_dev->base_address[0] & MEM_VALID; /* strip flags */
+	real_base = pci_dev->resource[0].start;
 	eni_dev->irq = pci_dev->irq;
 	error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision);
 	if (error) {
@@ -1740,7 +1740,7 @@
 }
 
 
-__initfunc(static int eni_start(struct atm_dev *dev))
+static int __init eni_start(struct atm_dev *dev)
 {
 	struct eni_dev *eni_dev;
 	unsigned long buf,buffer_mem;
@@ -2190,7 +2190,7 @@
 };
 
 
-__initfunc(int eni_detect(void))
+int __init eni_detect(void)
 {
 	struct atm_dev *dev;
 	struct eni_dev *eni_dev;
diff -u --recursive --new-file v2.3.15/linux/drivers/atm/horizon.c linux/drivers/atm/horizon.c
--- v2.3.15/linux/drivers/atm/horizon.c	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/horizon.c	Mon Aug 30 10:18:40 1999
@@ -2517,7 +2517,7 @@
   
   // clear error and grab cell rate resource lock
   error = 0;
-  spin_lock (&dev->rates_lock);
+  spin_lock (&dev->rate_lock);
   
   if (vcc.tx_rate > dev->tx_avail) {
     PRINTD (DBG_QOS, "not enough TX PCR left");
@@ -2538,7 +2538,7 @@
   }
   
   // release lock and exit on error
-  spin_unlock (&dev->rates_lock);
+  spin_unlock (&dev->rate_lock);
   if (error) {
     PRINTD (DBG_QOS|DBG_VCC, "insufficient cell rate resources");
     kfree (vccp);
@@ -2618,12 +2618,12 @@
   }
   
   // atomically release our rate reservation
-  spin_lock (&dev->rates_lock);
+  spin_lock (&dev->rate_lock);
   PRINTD (DBG_QOS|DBG_VCC, "releasing %u TX PCR and %u RX PCR",
 	  vcc->tx_rate, vcc->rx_rate);
   dev->tx_avail += vcc->tx_rate;
   dev->rx_avail += vcc->rx_rate;
-  spin_unlock (&dev->rates_lock);
+  spin_unlock (&dev->rate_lock);
   
   // free our structure
   kfree (vcc);
@@ -2790,9 +2790,8 @@
     hrz_dev * dev;
     
     // adapter slot free, read resources from PCI configuration space
-    u32 iobase = pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
-    u32 * membase = bus_to_virt
-      (pci_dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK);
+    u32 iobase = pci_dev->resource[0].start;
+    u32 * membase = bus_to_virt(pci_dev->resource[1].start);
     u8 irq = pci_dev->irq;
     
     // check IO region
diff -u --recursive --new-file v2.3.15/linux/drivers/atm/nicstar.c linux/drivers/atm/nicstar.c
--- v2.3.15/linux/drivers/atm/nicstar.c	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/nicstar.c	Mon Aug 30 10:18:40 1999
@@ -344,7 +344,7 @@
 
 #else
 
-__initfunc(int nicstar_detect(void))
+int __init nicstar_detect(void)
 {
    int i;
    unsigned error = 0;	/* Initialized to remove compile warning */
@@ -454,7 +454,7 @@
       
    card->index = i;
    card->pcidev = pcidev;
-   card->membase = (u32) (pcidev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK);
+   card->membase = (u32) pcidev->resource[1].start;
 #ifdef __powerpc__
    /* Compensate for different memory map between host CPU and PCI bus.
       Shouldn't we use a macro for this? */
diff -u --recursive --new-file v2.3.15/linux/drivers/atm/suni.c linux/drivers/atm/suni.c
--- v2.3.15/linux/drivers/atm/suni.c	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/suni.c	Thu Aug 26 12:42:33 1999
@@ -264,7 +264,7 @@
 };
 
 
-__initfunc(int suni_init(struct atm_dev *dev))
+int __init suni_init(struct atm_dev *dev)
 {
 	unsigned char mri;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/atm/uPD98402.c linux/drivers/atm/uPD98402.c
--- v2.3.15/linux/drivers/atm/uPD98402.c	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/uPD98402.c	Thu Aug 26 12:42:33 1999
@@ -196,7 +196,7 @@
 };
 
 
-__initfunc(int uPD98402_init(struct atm_dev *dev))
+int __init uPD98402_init(struct atm_dev *dev)
 {
 DPRINTK("phy_init\n");
 	dev->phy = &uPD98402_ops;
diff -u --recursive --new-file v2.3.15/linux/drivers/atm/zatm.c linux/drivers/atm/zatm.c
--- v2.3.15/linux/drivers/atm/zatm.c	Thu Aug 26 13:05:34 1999
+++ linux/drivers/atm/zatm.c	Mon Aug 30 10:18:40 1999
@@ -460,7 +460,7 @@
 }
 
 
-__initfunc(static void zatm_clock_init(struct zatm_dev *zatm_dev))
+static void __init zatm_clock_init(struct zatm_dev *zatm_dev)
 {
 	static int start_timer = 1;
 	unsigned long flags;
@@ -1289,8 +1289,8 @@
 /*----------------------------- (E)EPROM access -----------------------------*/
 
 
-__initfunc(static void eprom_set(struct zatm_dev *zatm_dev,unsigned long value,
-    unsigned short cmd))
+static void __init eprom_set(struct zatm_dev *zatm_dev,unsigned long value,
+    unsigned short cmd)
 {
 	int error;
 
@@ -1300,8 +1300,8 @@
 }
 
 
-__initfunc(static unsigned long eprom_get(struct zatm_dev *zatm_dev,
-    unsigned short cmd))
+static unsigned long __init eprom_get(struct zatm_dev *zatm_dev,
+    unsigned short cmd)
 {
 	unsigned int value;
 	int error;
@@ -1313,8 +1313,8 @@
 }
 
 
-__initfunc(static void eprom_put_bits(struct zatm_dev *zatm_dev,
-    unsigned long data,int bits,unsigned short cmd))
+static void __init eprom_put_bits(struct zatm_dev *zatm_dev,
+    unsigned long data,int bits,unsigned short cmd)
 {
 	unsigned long value;
 	int i;
@@ -1328,8 +1328,8 @@
 }
 
 
-__initfunc(static void eprom_get_byte(struct zatm_dev *zatm_dev,
-    unsigned char *byte,unsigned short cmd))
+static void __init eprom_get_byte(struct zatm_dev *zatm_dev,
+    unsigned char *byte,unsigned short cmd)
 {
 	int i;
 
@@ -1344,8 +1344,8 @@
 }
 
 
-__initfunc(static unsigned char eprom_try_esi(struct atm_dev *dev,
-    unsigned short cmd,int offset,int swap))
+static unsigned char __init eprom_try_esi(struct atm_dev *dev,
+    unsigned short cmd,int offset,int swap)
 {
 	unsigned char buf[ZEPROM_SIZE];
 	struct zatm_dev *zatm_dev;
@@ -1365,7 +1365,7 @@
 }
 
 
-__initfunc(static void eprom_get_esi(struct atm_dev *dev))
+static void __init eprom_get_esi(struct atm_dev *dev)
 {
 	if (eprom_try_esi(dev,ZEPROM_V1_REG,ZEPROM_V1_ESI_OFF,1)) return;
 	(void) eprom_try_esi(dev,ZEPROM_V2_REG,ZEPROM_V2_ESI_OFF,0);
@@ -1375,7 +1375,7 @@
 /*--------------------------------- entries ---------------------------------*/
 
 
-__initfunc(static int zatm_init(struct atm_dev *dev))
+static int __init zatm_init(struct atm_dev *dev)
 {
 	struct zatm_dev *zatm_dev;
 	struct pci_dev *pci_dev;
@@ -1387,7 +1387,7 @@
 	DPRINTK(">zatm_init\n");
 	zatm_dev = ZATM_DEV(dev);
 	pci_dev = zatm_dev->pci_dev;
-	zatm_dev->base = pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+	zatm_dev->base = pci_dev->resource[0].start;
 	zatm_dev->irq = pci_dev->irq;
 	if ((error = pci_read_config_word(pci_dev,PCI_COMMAND,&command)) ||
 	    (error = pci_read_config_byte(pci_dev,PCI_REVISION_ID,&revision))) {
@@ -1457,7 +1457,7 @@
 }
 
 
-__initfunc(static int zatm_start(struct atm_dev *dev))
+static int __init zatm_start(struct atm_dev *dev)
 {
 	struct zatm_dev *zatm_dev;
 	unsigned long curr;
@@ -1816,7 +1816,7 @@
 };
 
 
-__initfunc(int zatm_detect(void))
+int __init zatm_detect(void)
 {
 	struct atm_dev *dev;
 	struct zatm_dev *zatm_dev;
diff -u --recursive --new-file v2.3.15/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.3.15/linux/drivers/block/Config.in	Thu Aug  5 18:48:45 1999
+++ linux/drivers/block/Config.in	Thu Aug 26 13:44:03 1999
@@ -51,7 +51,9 @@
         bool '     Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
         bool '     AEC6210 chipset support' CONFIG_BLK_DEV_AEC6210
         if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
-          bool '     ALI M15x3 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_ALI15X3
+          if [ "$CONFIG_X86" = "y" ]; then
+            bool '     ALI M15x3 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_ALI15X3
+          fi
           bool '     CMD646 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CMD646
           bool '     CY82C693 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CY82C693
         fi
@@ -61,10 +63,12 @@
           bool '       HPT34X DMA support (DANGEROUS)' CONFIG_BLK_DEV_HPT34X_DMA
         fi
         bool '     HPT366 chipset support' CONFIG_BLK_DEV_HPT366
-        bool '     Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX
-        if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" -a \
-             "$CONFIG_BLK_DEV_PIIX" = "y" ]; then
-          bool '       PIIXn Tuning support (EXPERIMENTAL)' CONFIG_BLK_DEV_PIIX_TUNING
+        if [ "$CONFIG_X86" = "y" ]; then
+          bool '     Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX
+          if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" -a \
+               "$CONFIG_BLK_DEV_PIIX" = "y" ]; then
+            bool '       PIIXn Tuning support (EXPERIMENTAL)' CONFIG_BLK_DEV_PIIX_TUNING
+          fi
         fi
         if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
           bool '     NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415
@@ -80,10 +84,14 @@
             bool '       Special Mode Feature (DANGEROUS)' PDC202XX_FORCE_MASTER_MODE
           fi
         fi
-        bool '     SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513
+        if [ "$CONFIG_X86" = "y" ]; then
+          bool '     SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513
+        fi
         if [ "$IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
           bool '     Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290
-          bool '     VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586
+          if [ "$CONFIG_X86" = "y" ]; then
+            bool '     VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586
+          fi
         fi
       fi
       if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then
diff -u --recursive --new-file v2.3.15/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- v2.3.15/linux/drivers/block/DAC960.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/DAC960.c	Mon Aug 30 10:24:14 1999
@@ -0,0 +1,3570 @@
+/*
+
+  Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers
+
+  Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+
+  This program is free software; you may redistribute and/or modify it under
+  the terms of the GNU General Public License Version 2 as published by the
+  Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  for complete details.
+
+  The author respectfully requests that any modifications to this software be
+  sent directly to him for evaluation and testing.
+
+*/
+
+
+#define DAC960_DriverVersion			"2.2.4"
+#define DAC960_DriverDate			"23 August 1999"
+
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/blk.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/locks.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/proc_fs.h>
+#include <linux/reboot.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/spinlock.h>
+#include <asm/uaccess.h>
+#include "DAC960.h"
+
+
+/*
+  DAC960_ControllerCount is the number of DAC960 Controllers detected.
+*/
+
+static int
+  DAC960_ControllerCount =			0;
+
+
+/*
+  DAC960_ActiveControllerCount is the number of Active DAC960 Controllers
+  detected.
+*/
+
+static int
+  DAC960_ActiveControllerCount =		0;
+
+
+/*
+  DAC960_Controllers is an array of pointers to the DAC960 Controller
+  structures.
+*/
+
+static DAC960_Controller_T
+  *DAC960_Controllers[DAC960_MaxControllers] =	{ NULL };
+
+
+/*
+  DAC960_FileOperations is the File Operations structure for DAC960 Logical
+  Disk Devices.
+*/
+
+static FileOperations_T
+  DAC960_FileOperations =
+    { llseek:		    NULL,
+      read:		    block_read,
+      write:		    block_write,
+      readdir:		    NULL,
+      poll:		    NULL,
+      ioctl:		    DAC960_IOCTL,
+      mmap:		    NULL,
+      open:		    DAC960_Open,
+      release:		    DAC960_Release,
+      fsync:		    block_fsync,
+      fasync:		    NULL,
+      check_media_change:   NULL,
+      revalidate:	    NULL };
+
+
+/*
+  DAC960_ProcDirectoryEntry is the DAC960 /proc/rd directory entry.
+*/
+
+static PROC_DirectoryEntry_T
+  DAC960_ProcDirectoryEntry;
+
+
+/*
+  DAC960_NotifierBlock is the Notifier Block structure for DAC960 Driver.
+*/
+
+static NotifierBlock_T
+  DAC960_NotifierBlock =    { DAC960_Finalize, NULL, 0 };
+
+
+/*
+  DAC960_AnnounceDriver announces the Driver Version and Date, Author's Name,
+  Copyright Notice, and Electronic Mail Address.
+*/
+
+static void DAC960_AnnounceDriver(DAC960_Controller_T *Controller)
+{
+  DAC960_Announce("***** DAC960 RAID Driver Version "
+		  DAC960_DriverVersion " of "
+		  DAC960_DriverDate " *****\n", Controller);
+  DAC960_Announce("Copyright 1998-1999 by Leonard N. Zubkoff "
+		  "<lnz@dandelion.com>\n", Controller);
+}
+
+
+/*
+  DAC960_Failure prints a standardized error message, and then returns false.
+*/
+
+static boolean DAC960_Failure(DAC960_Controller_T *Controller,
+			      char *ErrorMessage)
+{
+  DAC960_Error("While configuring DAC960 PCI RAID Controller at\n",
+	       Controller);
+  if (Controller->IO_Address == 0)
+    DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "
+		 "PCI Address 0x%X\n", Controller,
+		 Controller->Bus, Controller->Device,
+		 Controller->Function, Controller->PCI_Address);
+  else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
+		    "0x%X PCI Address 0x%X\n", Controller,
+		    Controller->Bus, Controller->Device,
+		    Controller->Function, Controller->IO_Address,
+		    Controller->PCI_Address);
+  DAC960_Error("%s FAILED - DETACHING\n", Controller, ErrorMessage);
+  return false;
+}
+
+
+/*
+  DAC960_ClearCommand clears critical fields of Command.
+*/
+
+static inline void DAC960_ClearCommand(DAC960_Command_T *Command)
+{
+  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+  CommandMailbox->Words[0] = 0;
+  CommandMailbox->Words[1] = 0;
+  CommandMailbox->Words[2] = 0;
+  CommandMailbox->Words[3] = 0;
+  Command->CommandStatus = 0;
+}
+
+
+/*
+  DAC960_AllocateCommand allocates a Command structure from Controller's
+  free list.
+*/
+
+static inline DAC960_Command_T *DAC960_AllocateCommand(DAC960_Controller_T
+						       *Controller)
+{
+  DAC960_Command_T *Command = Controller->FreeCommands;
+  if (Command == NULL) return NULL;
+  Controller->FreeCommands = Command->Next;
+  Command->Next = NULL;
+  return Command;
+}
+
+
+/*
+  DAC960_DeallocateCommand deallocates Command, returning it to Controller's
+  free list.
+*/
+
+static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  Command->Next = Controller->FreeCommands;
+  Controller->FreeCommands = Command;
+}
+
+
+/*
+  DAC960_QueueCommand queues Command.
+*/
+
+static void DAC960_QueueCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+  DAC960_CommandMailbox_T *NextCommandMailbox;
+  CommandMailbox->Common.CommandIdentifier = Command - Controller->Commands;
+  switch (Controller->ControllerType)
+    {
+    case DAC960_V5_Controller:
+      NextCommandMailbox = Controller->NextCommandMailbox;
+      DAC960_V5_WriteCommandMailbox(NextCommandMailbox, CommandMailbox);
+      if (Controller->PreviousCommandMailbox1->Words[0] == 0 ||
+	  Controller->PreviousCommandMailbox2->Words[0] == 0)
+	{
+	  if (Controller->DualModeMemoryMailboxInterface)
+	    DAC960_V5_MemoryMailboxNewCommand(ControllerBaseAddress);
+	  else DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress);
+	}
+      Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1;
+      Controller->PreviousCommandMailbox1 = NextCommandMailbox;
+      if (++NextCommandMailbox > Controller->LastCommandMailbox)
+	NextCommandMailbox = Controller->FirstCommandMailbox;
+      Controller->NextCommandMailbox = NextCommandMailbox;
+      break;
+    case DAC960_V4_Controller:
+      NextCommandMailbox = Controller->NextCommandMailbox;
+      DAC960_V4_WriteCommandMailbox(NextCommandMailbox, CommandMailbox);
+      if (Controller->PreviousCommandMailbox1->Words[0] == 0 ||
+	  Controller->PreviousCommandMailbox2->Words[0] == 0)
+	{
+	  if (Controller->DualModeMemoryMailboxInterface)
+	    DAC960_V4_MemoryMailboxNewCommand(ControllerBaseAddress);
+	  else DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress);
+	}
+      Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1;
+      Controller->PreviousCommandMailbox1 = NextCommandMailbox;
+      if (++NextCommandMailbox > Controller->LastCommandMailbox)
+	NextCommandMailbox = Controller->FirstCommandMailbox;
+      Controller->NextCommandMailbox = NextCommandMailbox;
+      break;
+    case DAC960_V3_Controller:
+      while (DAC960_V3_MailboxFullP(ControllerBaseAddress))
+	udelay(1);
+      DAC960_V3_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox);
+      DAC960_V3_NewCommand(ControllerBaseAddress);
+      break;
+    }
+}
+
+
+/*
+  DAC960_ExecuteCommand executes Command and waits for completion.  It
+  returns true on success and false on failure.
+*/
+
+static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  Semaphore_T Semaphore = MUTEX_LOCKED;
+  unsigned long ProcessorFlags;
+  Command->Semaphore = &Semaphore;
+  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+  DAC960_QueueCommand(Command);
+  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+  if (!in_interrupt())
+    down(&Semaphore);
+  return Command->CommandStatus == DAC960_NormalCompletion;
+}
+
+
+/*
+  DAC960_ExecuteType3 executes a DAC960 Type 3 Command and waits for
+  completion.  It returns true on success and false on failure.
+*/
+
+static boolean DAC960_ExecuteType3(DAC960_Controller_T *Controller,
+				   DAC960_CommandOpcode_T CommandOpcode,
+				   void *DataPointer)
+{
+  DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
+  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+  boolean Result;
+  DAC960_ClearCommand(Command);
+  Command->CommandType = DAC960_ImmediateCommand;
+  CommandMailbox->Type3.CommandOpcode = CommandOpcode;
+  CommandMailbox->Type3.BusAddress = Virtual_to_Bus(DataPointer);
+  Result = DAC960_ExecuteCommand(Command);
+  DAC960_DeallocateCommand(Command);
+  return Result;
+}
+
+
+/*
+  DAC960_ExecuteType3D executes a DAC960 Type 3D Command and waits for
+  completion.  It returns true on success and false on failure.
+*/
+
+static boolean DAC960_ExecuteType3D(DAC960_Controller_T *Controller,
+				    DAC960_CommandOpcode_T CommandOpcode,
+				    unsigned char Channel,
+				    unsigned char TargetID,
+				    void *DataPointer)
+{
+  DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
+  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+  boolean Result;
+  DAC960_ClearCommand(Command);
+  Command->CommandType = DAC960_ImmediateCommand;
+  CommandMailbox->Type3D.CommandOpcode = CommandOpcode;
+  CommandMailbox->Type3D.Channel = Channel;
+  CommandMailbox->Type3D.TargetID = TargetID;
+  CommandMailbox->Type3D.BusAddress = Virtual_to_Bus(DataPointer);
+  Result = DAC960_ExecuteCommand(Command);
+  DAC960_DeallocateCommand(Command);
+  return Result;
+}
+
+
+/*
+  DAC960_EnableMemoryMailboxInterface enables the Memory Mailbox Interface.
+*/
+
+static boolean DAC960_EnableMemoryMailboxInterface(DAC960_Controller_T
+						   *Controller)
+{
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_CommandMailbox_T *CommandMailboxesMemory;
+  DAC960_StatusMailbox_T *StatusMailboxesMemory;
+  DAC960_CommandMailbox_T CommandMailbox;
+  DAC960_CommandStatus_T CommandStatus;
+  void *SavedMemoryMailboxesAddress = NULL;
+  short NextCommandMailboxIndex = 0;
+  short NextStatusMailboxIndex = 0;
+  int TimeoutCounter = 1000000, i;
+  if (Controller->ControllerType == DAC960_V5_Controller)
+    DAC960_V5_RestoreMemoryMailboxInfo(Controller,
+				       &SavedMemoryMailboxesAddress,
+				       &NextCommandMailboxIndex,
+				       &NextStatusMailboxIndex);
+  else DAC960_V4_RestoreMemoryMailboxInfo(Controller,
+					  &SavedMemoryMailboxesAddress,
+					  &NextCommandMailboxIndex,
+					  &NextStatusMailboxIndex);
+  if (SavedMemoryMailboxesAddress == NULL)
+    CommandMailboxesMemory =
+      (DAC960_CommandMailbox_T *) __get_free_pages(GFP_KERNEL, 1);
+  else CommandMailboxesMemory = SavedMemoryMailboxesAddress;
+  memset(CommandMailboxesMemory, 0, PAGE_SIZE << 1);
+  Controller->FirstCommandMailbox = CommandMailboxesMemory;
+  CommandMailboxesMemory += DAC960_CommandMailboxCount - 1;
+  Controller->LastCommandMailbox = CommandMailboxesMemory;
+  Controller->NextCommandMailbox =
+    &Controller->FirstCommandMailbox[NextCommandMailboxIndex];
+  if (--NextCommandMailboxIndex < 0)
+    NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1;
+  Controller->PreviousCommandMailbox1 =
+    &Controller->FirstCommandMailbox[NextCommandMailboxIndex];
+  if (--NextCommandMailboxIndex < 0)
+    NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1;
+  Controller->PreviousCommandMailbox2 =
+    &Controller->FirstCommandMailbox[NextCommandMailboxIndex];
+  StatusMailboxesMemory =
+    (DAC960_StatusMailbox_T *) (CommandMailboxesMemory + 1);
+  Controller->FirstStatusMailbox = StatusMailboxesMemory;
+  StatusMailboxesMemory += DAC960_StatusMailboxCount - 1;
+  Controller->LastStatusMailbox = StatusMailboxesMemory;
+  Controller->NextStatusMailbox =
+    &Controller->FirstStatusMailbox[NextStatusMailboxIndex];
+  if (SavedMemoryMailboxesAddress != NULL) return true;
+  /* Enable the Memory Mailbox Interface. */
+  Controller->DualModeMemoryMailboxInterface = true;
+  CommandMailbox.TypeX.CommandOpcode = 0x2B;
+  CommandMailbox.TypeX.CommandIdentifier = 0;
+  CommandMailbox.TypeX.CommandOpcode2 = 0x14;
+  CommandMailbox.TypeX.CommandMailboxesBusAddress =
+    Virtual_to_Bus(Controller->FirstCommandMailbox);
+  CommandMailbox.TypeX.StatusMailboxesBusAddress =
+    Virtual_to_Bus(Controller->FirstStatusMailbox);
+  for (i = 0; i < 2; i++)
+    switch (Controller->ControllerType)
+      {
+      case DAC960_V5_Controller:
+	while (--TimeoutCounter >= 0)
+	  {
+	    if (DAC960_V5_HardwareMailboxEmptyP(ControllerBaseAddress))
+	      break;
+	    udelay(10);
+	  }
+	if (TimeoutCounter < 0) return false;
+	DAC960_V5_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
+	DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress);
+	while (--TimeoutCounter >= 0)
+	  {
+	    if (DAC960_V5_HardwareMailboxStatusAvailableP(
+		  ControllerBaseAddress))
+	      break;
+	    udelay(10);
+	  }
+	if (TimeoutCounter < 0) return false;
+	CommandStatus = DAC960_V5_ReadStatusRegister(ControllerBaseAddress);
+	DAC960_V5_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress);
+	DAC960_V5_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress);
+	if (CommandStatus == DAC960_NormalCompletion) return true;
+	Controller->DualModeMemoryMailboxInterface = false;
+	CommandMailbox.TypeX.CommandOpcode2 = 0x10;
+	break;
+      case DAC960_V4_Controller:
+	while (--TimeoutCounter >= 0)
+	  {
+	    if (!DAC960_V4_HardwareMailboxFullP(ControllerBaseAddress))
+	      break;
+	    udelay(10);
+	  }
+	if (TimeoutCounter < 0) return false;
+	DAC960_V4_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
+	DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress);
+	while (--TimeoutCounter >= 0)
+	  {
+	    if (DAC960_V4_HardwareMailboxStatusAvailableP(
+		  ControllerBaseAddress))
+	      break;
+	    udelay(10);
+	  }
+	if (TimeoutCounter < 0) return false;
+	CommandStatus = DAC960_V4_ReadStatusRegister(ControllerBaseAddress);
+	DAC960_V4_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress);
+	DAC960_V4_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress);
+	if (CommandStatus == DAC960_NormalCompletion) return true;
+	Controller->DualModeMemoryMailboxInterface = false;
+	CommandMailbox.TypeX.CommandOpcode2 = 0x10;
+	break;
+      default:
+	break;
+      }
+  return false;
+}
+
+
+/*
+  DAC960_DetectControllers detects DAC960 PCI RAID Controllers by interrogating
+  the PCI Configuration Space for Controller Type.
+*/
+
+static void DAC960_DetectControllers(DAC960_ControllerType_T ControllerType)
+{
+  unsigned short VendorID = 0, DeviceID = 0;
+  unsigned int MemoryWindowSize = 0;
+  PCI_Device_T *PCI_Device = NULL;
+  switch (ControllerType)
+    {
+    case DAC960_V5_Controller:
+      VendorID = PCI_VENDOR_ID_DEC;
+      DeviceID = PCI_DEVICE_ID_DEC_21285;
+      MemoryWindowSize = DAC960_V5_RegisterWindowSize;
+      break;
+    case DAC960_V4_Controller:
+      VendorID = PCI_VENDOR_ID_MYLEX;
+      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V4;
+      MemoryWindowSize = DAC960_V4_RegisterWindowSize;
+      break;
+    case DAC960_V3_Controller:
+      VendorID = PCI_VENDOR_ID_MYLEX;
+      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V3;
+      MemoryWindowSize = DAC960_V3_RegisterWindowSize;
+      break;
+    }
+  while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL)
+    {
+      DAC960_Controller_T *Controller = (DAC960_Controller_T *)
+	kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
+      DAC960_IO_Address_T IO_Address = 0;
+      DAC960_PCI_Address_T PCI_Address = 0;
+      unsigned char Bus = PCI_Device->bus->number;
+      unsigned char DeviceFunction = PCI_Device->devfn;
+      unsigned char Device = DeviceFunction >> 3;
+      unsigned char Function = DeviceFunction & 0x7;
+      unsigned int IRQ_Channel = PCI_Device->irq;
+      unsigned long BaseAddress0 = PCI_Device->base_address[0];
+      unsigned long BaseAddress1 = PCI_Device->base_address[1];
+      unsigned short SubsystemVendorID, SubsystemDeviceID;
+      int CommandIdentifier;
+      pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_VENDOR_ID,
+			   &SubsystemVendorID);
+      pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_ID,
+			   &SubsystemDeviceID);
+      switch (ControllerType)
+	{
+	case DAC960_V5_Controller:
+	  if (!(SubsystemVendorID == PCI_VENDOR_ID_MYLEX &&
+		SubsystemDeviceID == PCI_DEVICE_ID_MYLEX_DAC960P_V5))
+	    goto Ignore;
+	  PCI_Address = BaseAddress0 & PCI_BASE_ADDRESS_MEM_MASK;
+	  break;
+	case DAC960_V4_Controller:
+	  PCI_Address = BaseAddress0 & PCI_BASE_ADDRESS_MEM_MASK;
+	  break;
+	case DAC960_V3_Controller:
+	  IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
+	  PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK;
+	  break;
+	}
+      if (DAC960_ControllerCount == DAC960_MaxControllers)
+	{
+	  DAC960_Error("More than %d DAC960 Controllers detected - "
+		       "ignoring from Controller at\n",
+		       NULL, DAC960_MaxControllers);
+	  goto Ignore;
+	}
+      if (Controller == NULL)
+	{
+	  DAC960_Error("Unable to allocate Controller structure for "
+		       "Controller at\n", NULL);
+	  goto Ignore;
+	}
+      memset(Controller, 0, sizeof(DAC960_Controller_T));
+      init_waitqueue_head(&Controller->CommandWaitQueue);
+      Controller->ControllerNumber = DAC960_ControllerCount;
+      DAC960_Controllers[DAC960_ControllerCount++] = Controller;
+      DAC960_AnnounceDriver(Controller);
+      Controller->ControllerType = ControllerType;
+      Controller->IO_Address = IO_Address;
+      Controller->PCI_Address = PCI_Address;
+      Controller->Bus = Bus;
+      Controller->Device = Device;
+      Controller->Function = Function;
+      sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
+      /*
+	Acquire shared access to the IRQ Channel.
+      */
+      if (IRQ_Channel == 0)
+	{
+	  DAC960_Error("IRQ Channel %d illegal for Controller at\n",
+		       Controller, IRQ_Channel);
+	  goto Failure;
+	}
+      strcpy(Controller->FullModelName, "DAC960");
+      if (request_irq(IRQ_Channel, DAC960_InterruptHandler,
+		      SA_SHIRQ, Controller->FullModelName, Controller) < 0)
+	{
+	  DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
+		       Controller, IRQ_Channel);
+	  goto Failure;
+	}
+      Controller->IRQ_Channel = IRQ_Channel;
+      /*
+	Map the Controller Register Window.
+      */
+      if (MemoryWindowSize < PAGE_SIZE)
+	MemoryWindowSize = PAGE_SIZE;
+      Controller->MemoryMappedAddress =
+	ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize);
+      Controller->BaseAddress =
+	Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK);
+      if (Controller->MemoryMappedAddress == NULL)
+	{
+	  DAC960_Error("Unable to map Controller Register Window for "
+		       "Controller at\n", Controller);
+	  goto Failure;
+	}
+      switch (ControllerType)
+	{
+	case DAC960_V5_Controller:
+	  DAC960_V5_DisableInterrupts(Controller->BaseAddress);
+	  if (!DAC960_EnableMemoryMailboxInterface(Controller))
+	    {
+	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
+			   "for Controller at\n", Controller);
+	      goto Failure;
+	    }
+	  DAC960_V5_EnableInterrupts(Controller->BaseAddress);
+	  break;
+	case DAC960_V4_Controller:
+	  DAC960_V4_DisableInterrupts(Controller->BaseAddress);
+	  if (!DAC960_EnableMemoryMailboxInterface(Controller))
+	    {
+	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
+			   "for Controller at\n", Controller);
+	      goto Failure;
+	    }
+	  DAC960_V4_EnableInterrupts(Controller->BaseAddress);
+	  break;
+	case DAC960_V3_Controller:
+	  request_region(Controller->IO_Address, 0x80,
+			 Controller->FullModelName);
+	  DAC960_V3_EnableInterrupts(Controller->BaseAddress);
+	  break;
+	}
+      DAC960_ActiveControllerCount++;
+      for (CommandIdentifier = 0;
+	   CommandIdentifier < DAC960_MaxChannels;
+	   CommandIdentifier++)
+	{
+	  Controller->Commands[CommandIdentifier].Controller = Controller;
+	  Controller->Commands[CommandIdentifier].Next =
+	    Controller->FreeCommands;
+	  Controller->FreeCommands = &Controller->Commands[CommandIdentifier];
+	}
+      continue;
+    Failure:
+      if (IO_Address == 0)
+	DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "
+		     "PCI Address 0x%X\n", Controller,
+		     Bus, Device, Function, PCI_Address);
+      else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
+			"0x%X PCI Address 0x%X\n", Controller,
+			Bus, Device, Function, IO_Address, PCI_Address);
+      if (Controller == NULL) break;
+      if (Controller->IRQ_Channel > 0)
+	free_irq(IRQ_Channel, Controller);
+      if (Controller->MemoryMappedAddress != NULL)
+	iounmap(Controller->MemoryMappedAddress);
+      DAC960_Controllers[Controller->ControllerNumber] = NULL;
+    Ignore:
+      kfree(Controller);
+    }
+}
+
+
+/*
+  DAC960_ReadControllerConfiguration reads the Configuration Information
+  from Controller and initializes the Controller structure.
+*/
+
+static boolean DAC960_ReadControllerConfiguration(DAC960_Controller_T
+						  *Controller)
+{
+  DAC960_Enquiry2_T Enquiry2;
+  DAC960_Config2_T Config2;
+  int LogicalDriveNumber, Channel, TargetID;
+  if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry,
+			   &Controller->Enquiry[0]))
+    return DAC960_Failure(Controller, "ENQUIRY");
+  if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry2, &Enquiry2))
+    return DAC960_Failure(Controller, "ENQUIRY2");
+  if (!DAC960_ExecuteType3(Controller, DAC960_ReadConfig2, &Config2))
+    return DAC960_Failure(Controller, "READ CONFIG2");
+  if (!DAC960_ExecuteType3(Controller, DAC960_GetLogicalDriveInformation,
+			   &Controller->LogicalDriveInformation[0]))
+    return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION");
+  for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++)
+    for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
+      if (!DAC960_ExecuteType3D(Controller, DAC960_GetDeviceState,
+				Channel, TargetID,
+				&Controller->DeviceState[0][Channel][TargetID]))
+	return DAC960_Failure(Controller, "GET DEVICE STATE");
+  /*
+    Initialize the Controller Model Name and Full Model Name fields.
+  */
+  switch (Enquiry2.HardwareID.SubModel)
+    {
+    case DAC960_P_PD_PU:
+      if (Enquiry2.SCSICapability.BusSpeed == DAC960_Ultra)
+	strcpy(Controller->ModelName, "DAC960PU");
+      else strcpy(Controller->ModelName, "DAC960PD");
+      break;
+    case DAC960_PL:
+      strcpy(Controller->ModelName, "DAC960PL");
+      break;
+    case DAC960_PG:
+      strcpy(Controller->ModelName, "DAC960PG");
+      break;
+    case DAC960_PJ:
+      strcpy(Controller->ModelName, "DAC960PJ");
+      break;
+    case DAC960_PR:
+      strcpy(Controller->ModelName, "DAC960PR");
+      break;
+    case DAC960_PT:
+      strcpy(Controller->ModelName, "DAC960PT");
+      break;
+    case DAC960_PTL0:
+      strcpy(Controller->ModelName, "DAC960PTL0");
+      break;
+    case DAC960_PRL:
+      strcpy(Controller->ModelName, "DAC960PRL");
+      break;
+    case DAC960_PTL1:
+      strcpy(Controller->ModelName, "DAC960PTL1");
+      break;
+    case DAC1164_P:
+      strcpy(Controller->ModelName, "DAC1164P");
+      break;
+    default:
+      return DAC960_Failure(Controller, "MODEL VERIFICATION");
+    }
+  strcpy(Controller->FullModelName, "Mylex ");
+  strcat(Controller->FullModelName, Controller->ModelName);
+  /*
+    Initialize the Controller Firmware Version field and verify that it
+    is a supported firmware version.  The supported firmware versions are:
+
+    DAC1164P		    5.06 and above
+    DAC960PTL/PRL/PJ/PG	    4.06 and above
+    DAC960PU/PD/PL	    3.51 and above
+  */
+  sprintf(Controller->FirmwareVersion, "%d.%02d-%c-%02d",
+	  Enquiry2.FirmwareID.MajorVersion, Enquiry2.FirmwareID.MinorVersion,
+	  Enquiry2.FirmwareID.FirmwareType, Enquiry2.FirmwareID.TurnID);
+  if (!((Controller->FirmwareVersion[0] == '5' &&
+	 strcmp(Controller->FirmwareVersion, "5.06") >= 0) ||
+	(Controller->FirmwareVersion[0] == '4' &&
+	 strcmp(Controller->FirmwareVersion, "4.06") >= 0) ||
+	(Controller->FirmwareVersion[0] == '3' &&
+	 strcmp(Controller->FirmwareVersion, "3.51") >= 0)))
+    {
+      DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION");
+      DAC960_Error("Firmware Version = '%s'\n", Controller,
+		   Controller->FirmwareVersion);
+      return false;
+    }
+  /*
+    Initialize the Controller Channels, Memory Size, and SAF-TE Enclosure
+    Management Enabled fields.
+  */
+  Controller->Channels = Enquiry2.ActualChannels;
+  Controller->MemorySize = Enquiry2.MemorySize >> 20;
+  Controller->SAFTE_EnclosureManagementEnabled =
+    Enquiry2.FaultManagementType == DAC960_SAFTE;
+  /*
+    Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive
+    Count, Maximum Blocks per Command, and Maximum Scatter/Gather Segments.
+    The Driver Queue Depth must be at most one less than the Controller Queue
+    Depth to allow for an automatic drive rebuild operation.
+  */
+  Controller->ControllerQueueDepth = Controller->Enquiry[0].MaxCommands;
+  Controller->DriverQueueDepth = Controller->ControllerQueueDepth - 1;
+  Controller->LogicalDriveCount = Controller->Enquiry[0].NumberOfLogicalDrives;
+  Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand;
+  Controller->MaxScatterGatherSegments = Enquiry2.MaxScatterGatherEntries;
+  /*
+    Initialize the Stripe Size, Segment Size, and Geometry Translation.
+  */
+  Controller->StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor
+			   >> (10 - DAC960_BlockSizeBits);
+  Controller->SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor
+			    >> (10 - DAC960_BlockSizeBits);
+  switch (Config2.DriveGeometry)
+    {
+    case DAC960_Geometry_128_32:
+      Controller->GeometryTranslationHeads = 128;
+      Controller->GeometryTranslationSectors = 32;
+      break;
+    case DAC960_Geometry_255_63:
+      Controller->GeometryTranslationHeads = 255;
+      Controller->GeometryTranslationSectors = 63;
+      break;
+    default:
+      return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY");
+    }
+  /*
+    Initialize the Logical Drive Initial State.
+  */
+  for (LogicalDriveNumber = 0;
+       LogicalDriveNumber < Controller->LogicalDriveCount;
+       LogicalDriveNumber++)
+    Controller->LogicalDriveInitialState[LogicalDriveNumber] =
+      Controller->LogicalDriveInformation[0]
+		  [LogicalDriveNumber].LogicalDriveState;
+  Controller->LastRebuildStatus = DAC960_NoRebuildOrCheckInProgress;
+  return true;
+}
+
+
+/*
+  DAC960_ReportControllerConfiguration reports the Configuration Information of
+  Controller.
+*/
+
+static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T
+						    *Controller)
+{
+  DAC960_Info("Configuring Mylex %s PCI RAID Controller\n",
+	      Controller, Controller->ModelName);
+  DAC960_Info("  Firmware Version: %s, Channels: %d, Memory Size: %dMB\n",
+	      Controller, Controller->FirmwareVersion,
+	      Controller->Channels, Controller->MemorySize);
+  DAC960_Info("  PCI Bus: %d, Device: %d, Function: %d, I/O Address: ",
+	      Controller, Controller->Bus,
+	      Controller->Device, Controller->Function);
+  if (Controller->IO_Address == 0)
+    DAC960_Info("Unassigned\n", Controller);
+  else DAC960_Info("0x%X\n", Controller, Controller->IO_Address);
+  DAC960_Info("  PCI Address: 0x%X mapped at 0x%lX, IRQ Channel: %d\n",
+	      Controller, Controller->PCI_Address,
+	      (unsigned long) Controller->BaseAddress,
+	      Controller->IRQ_Channel);
+  DAC960_Info("  Controller Queue Depth: %d, "
+	      "Maximum Blocks per Command: %d\n",
+	      Controller, Controller->ControllerQueueDepth,
+	      Controller->MaxBlocksPerCommand);
+  DAC960_Info("  Driver Queue Depth: %d, "
+	      "Maximum Scatter/Gather Segments: %d\n",
+	      Controller, Controller->DriverQueueDepth,
+	      Controller->MaxScatterGatherSegments);
+  DAC960_Info("  Stripe Size: %dKB, Segment Size: %dKB, "
+	      "BIOS Geometry: %d/%d\n", Controller,
+	      Controller->StripeSize,
+	      Controller->SegmentSize,
+	      Controller->GeometryTranslationHeads,
+	      Controller->GeometryTranslationSectors);
+  if (Controller->SAFTE_EnclosureManagementEnabled)
+    DAC960_Info("  SAF-TE Enclosure Management Enabled\n", Controller);
+  return true;
+}
+
+
+/*
+  DAC960_ReadDeviceConfiguration reads the Device Configuration Information by
+  requesting the SCSI Inquiry and SCSI Inquiry Unit Serial Number information
+  for each device connected to Controller.
+*/
+
+static boolean DAC960_ReadDeviceConfiguration(DAC960_Controller_T *Controller)
+{
+  DAC960_DCDB_T DCDBs[DAC960_MaxChannels], *DCDB;
+  Semaphore_T Semaphores[DAC960_MaxChannels], *Semaphore;
+  unsigned long ProcessorFlags;
+  int Channel, TargetID;
+  for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
+    {
+      for (Channel = 0; Channel < Controller->Channels; Channel++)
+	{
+	  DAC960_Command_T *Command = &Controller->Commands[Channel];
+	  DAC960_SCSI_Inquiry_T *InquiryStandardData =
+	    &Controller->InquiryStandardData[Channel][TargetID];
+	  InquiryStandardData->PeripheralDeviceType = 0x1F;
+	  Semaphore = &Semaphores[Channel];
+	  *Semaphore = MUTEX_LOCKED;
+	  DCDB = &DCDBs[Channel];
+	  DAC960_ClearCommand(Command);
+	  Command->CommandType = DAC960_ImmediateCommand;
+	  Command->Semaphore = Semaphore;
+	  Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB;
+	  Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB);
+	  DCDB->Channel = Channel;
+	  DCDB->TargetID = TargetID;
+	  DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem;
+	  DCDB->EarlyStatus = false;
+	  DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds;
+	  DCDB->NoAutomaticRequestSense = false;
+	  DCDB->DisconnectPermitted = true;
+	  DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T);
+	  DCDB->BusAddress = Virtual_to_Bus(InquiryStandardData);
+	  DCDB->CDBLength = 6;
+	  DCDB->TransferLengthHigh4 = 0;
+	  DCDB->SenseLength = sizeof(DCDB->SenseData);
+	  DCDB->CDB[0] = 0x12; /* INQUIRY */
+	  DCDB->CDB[1] = 0; /* EVPD = 0 */
+	  DCDB->CDB[2] = 0; /* Page Code */
+	  DCDB->CDB[3] = 0; /* Reserved */
+	  DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T);
+	  DCDB->CDB[5] = 0; /* Control */
+	  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	  DAC960_QueueCommand(Command);
+	  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+	}
+      for (Channel = 0; Channel < Controller->Channels; Channel++)
+	{
+	  DAC960_Command_T *Command = &Controller->Commands[Channel];
+	  DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
+	    &Controller->InquiryUnitSerialNumber[Channel][TargetID];
+	  InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+	  Semaphore = &Semaphores[Channel];
+	  down(Semaphore);
+	  if (Command->CommandStatus != DAC960_NormalCompletion) continue;
+	  Command->Semaphore = Semaphore;
+	  DCDB = &DCDBs[Channel];
+	  DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+	  DCDB->BusAddress = Virtual_to_Bus(InquiryUnitSerialNumber);
+	  DCDB->SenseLength = sizeof(DCDB->SenseData);
+	  DCDB->CDB[0] = 0x12; /* INQUIRY */
+	  DCDB->CDB[1] = 1; /* EVPD = 1 */
+	  DCDB->CDB[2] = 0x80; /* Page Code */
+	  DCDB->CDB[3] = 0; /* Reserved */
+	  DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+	  DCDB->CDB[5] = 0; /* Control */
+	  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	  DAC960_QueueCommand(Command);
+	  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+	  down(Semaphore);
+	}
+    }
+  return true; 
+}
+
+
+/*
+  DAC960_ReportDeviceConfiguration reports the Device Configuration Information
+  of Controller.
+*/
+
+static boolean DAC960_ReportDeviceConfiguration(DAC960_Controller_T *Controller)
+{
+  int LogicalDriveNumber, Channel, TargetID;
+  DAC960_Info("  Physical Devices:\n", Controller);
+  for (Channel = 0; Channel < Controller->Channels; Channel++)
+    for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
+      {
+	DAC960_SCSI_Inquiry_T *InquiryStandardData =
+	  &Controller->InquiryStandardData[Channel][TargetID];
+	DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
+	  &Controller->InquiryUnitSerialNumber[Channel][TargetID];
+	DAC960_DeviceState_T *DeviceState =
+	  &Controller->DeviceState[Controller->DeviceStateIndex]
+				  [Channel][TargetID];
+	DAC960_ErrorTable_T *ErrorTable =
+	  &Controller->ErrorTable[Controller->ErrorTableIndex];
+	DAC960_ErrorTableEntry_T *ErrorEntry =
+	  &ErrorTable->ErrorTableEntries[Channel][TargetID];
+	char Vendor[1+sizeof(InquiryStandardData->VendorIdentification)];
+	char Model[1+sizeof(InquiryStandardData->ProductIdentification)];
+	char Revision[1+sizeof(InquiryStandardData->ProductRevisionLevel)];
+	char SerialNumber[1+sizeof(InquiryUnitSerialNumber
+				   ->ProductSerialNumber)];
+	int i;
+	if (InquiryStandardData->PeripheralDeviceType == 0x1F) continue;
+	for (i = 0; i < sizeof(Vendor)-1; i++)
+	  {
+	    unsigned char VendorCharacter =
+	      InquiryStandardData->VendorIdentification[i];
+	    Vendor[i] = (VendorCharacter >= ' ' && VendorCharacter <= '~'
+			 ? VendorCharacter : ' ');
+	  }
+	Vendor[sizeof(Vendor)-1] = '\0';
+	for (i = 0; i < sizeof(Model)-1; i++)
+	  {
+	    unsigned char ModelCharacter =
+	      InquiryStandardData->ProductIdentification[i];
+	    Model[i] = (ModelCharacter >= ' ' && ModelCharacter <= '~'
+			? ModelCharacter : ' ');
+	  }
+	Model[sizeof(Model)-1] = '\0';
+	for (i = 0; i < sizeof(Revision)-1; i++)
+	  {
+	    unsigned char RevisionCharacter =
+	      InquiryStandardData->ProductRevisionLevel[i];
+	    Revision[i] = (RevisionCharacter >= ' ' && RevisionCharacter <= '~'
+			   ? RevisionCharacter : ' ');
+	  }
+	Revision[sizeof(Revision)-1] = '\0';
+	DAC960_Info("    %d:%d%s Vendor: %s  Model: %s  Revision: %s\n",
+		    Controller, Channel, TargetID, (TargetID < 10 ? " " : ""),
+		    Vendor, Model, Revision);
+	if (InquiryUnitSerialNumber->PeripheralDeviceType != 0x1F)
+	  {
+	    int SerialNumberLength = InquiryUnitSerialNumber->PageLength;
+	    if (SerialNumberLength >
+		sizeof(InquiryUnitSerialNumber->ProductSerialNumber))
+	      SerialNumberLength =
+		sizeof(InquiryUnitSerialNumber->ProductSerialNumber);
+	    for (i = 0; i < SerialNumberLength; i++)
+	      {
+		unsigned char SerialNumberCharacter =
+		  InquiryUnitSerialNumber->ProductSerialNumber[i];
+		SerialNumber[i] =
+		  (SerialNumberCharacter >= ' ' && SerialNumberCharacter <= '~'
+		   ? SerialNumberCharacter : ' ');
+	      }
+	    SerialNumber[SerialNumberLength] = '\0';
+	    DAC960_Info("         Serial Number: %s\n",
+			Controller, SerialNumber);
+	  }
+	if (DeviceState->Present && DeviceState->DeviceType == DAC960_DiskType)
+	  {
+	    if (Controller->DeviceResetCount[Channel][TargetID] > 0)
+	      DAC960_Info("         Disk Status: %s, %d blocks, %d resets\n",
+			  Controller,
+			  (DeviceState->DeviceState == DAC960_Device_Dead
+			   ? "Dead"
+			   : DeviceState->DeviceState == DAC960_Device_WriteOnly
+			   ? "Write-Only"
+			   : DeviceState->DeviceState == DAC960_Device_Online
+			   ? "Online" : "Standby"),
+			  DeviceState->DiskSize,
+			  Controller->DeviceResetCount[Channel][TargetID]);
+	    else
+	      DAC960_Info("         Disk Status: %s, %d blocks\n", Controller,
+			  (DeviceState->DeviceState == DAC960_Device_Dead
+			   ? "Dead"
+			   : DeviceState->DeviceState == DAC960_Device_WriteOnly
+			   ? "Write-Only"
+			   : DeviceState->DeviceState == DAC960_Device_Online
+			   ? "Online" : "Standby"),
+			  DeviceState->DiskSize);
+	  }
+	if (ErrorEntry->ParityErrorCount > 0 ||
+	    ErrorEntry->SoftErrorCount > 0 ||
+	    ErrorEntry->HardErrorCount > 0 ||
+	    ErrorEntry->MiscErrorCount > 0)
+	  DAC960_Info("         Errors - Parity: %d, Soft: %d, "
+		      "Hard: %d, Misc: %d\n", Controller,
+		      ErrorEntry->ParityErrorCount,
+		      ErrorEntry->SoftErrorCount,
+		      ErrorEntry->HardErrorCount,
+		      ErrorEntry->MiscErrorCount);
+      }
+  DAC960_Info("  Logical Drives:\n", Controller);
+  for (LogicalDriveNumber = 0;
+       LogicalDriveNumber < Controller->LogicalDriveCount;
+       LogicalDriveNumber++)
+    {
+      DAC960_LogicalDriveInformation_T *LogicalDriveInformation =
+	&Controller->LogicalDriveInformation
+	   [Controller->LogicalDriveInformationIndex][LogicalDriveNumber];
+      DAC960_Info("    /dev/rd/c%dd%d: RAID-%d, %s, %d blocks, %s\n",
+		  Controller, Controller->ControllerNumber, LogicalDriveNumber,
+		  LogicalDriveInformation->RAIDLevel,
+		  (LogicalDriveInformation->LogicalDriveState ==
+		     DAC960_LogicalDrive_Online
+		   ? "Online"
+		   : LogicalDriveInformation->LogicalDriveState ==
+		     DAC960_LogicalDrive_Critical
+		     ? "Critical" : "Offline"),
+		  LogicalDriveInformation->LogicalDriveSize,
+		  (LogicalDriveInformation->WriteBack
+		   ? "Write Back" : "Write Thru"));
+    }
+  return true;
+}
+
+
+/*
+  DAC960_RegisterBlockDevice registers the Block Device structures
+  associated with Controller.
+*/
+
+static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
+{
+  static void (*RequestFunctions[DAC960_MaxControllers])(void) =
+    { DAC960_RequestFunction0, DAC960_RequestFunction1,
+      DAC960_RequestFunction2, DAC960_RequestFunction3,
+      DAC960_RequestFunction4, DAC960_RequestFunction5,
+      DAC960_RequestFunction6, DAC960_RequestFunction7 };
+  int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
+  GenericDiskInfo_T *GenericDiskInfo;
+  int MinorNumber;
+  /*
+    Register the Block Device Major Number for this DAC960 Controller.
+  */
+  if (register_blkdev(MajorNumber, "rd", &DAC960_FileOperations) < 0)
+    {
+      DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n",
+		   Controller, MajorNumber);
+      return false;
+    }
+  /*
+    Initialize the I/O Request Function.
+  */
+  blk_dev[MajorNumber].request_fn =
+    RequestFunctions[Controller->ControllerNumber];
+  /*
+    Initialize the Disk Partitions array, Partition Sizes array, Block Sizes
+    array, Max Sectors per Request array, and Max Segments per Request array.
+  */
+  for (MinorNumber = 0; MinorNumber < DAC960_MinorCount; MinorNumber++)
+    {
+      Controller->BlockSizes[MinorNumber] = BLOCK_SIZE;
+      Controller->MaxSectorsPerRequest[MinorNumber] =
+	Controller->MaxBlocksPerCommand;
+      Controller->MaxSegmentsPerRequest[MinorNumber] =
+	Controller->MaxScatterGatherSegments;
+    }
+  Controller->GenericDiskInfo.part = Controller->DiskPartitions;
+  Controller->GenericDiskInfo.sizes = Controller->PartitionSizes;
+  blksize_size[MajorNumber] = Controller->BlockSizes;
+  max_sectors[MajorNumber] = Controller->MaxSectorsPerRequest;
+  max_segments[MajorNumber] = Controller->MaxSegmentsPerRequest;
+  /*
+    Initialize Read Ahead to 128 sectors.
+  */
+  read_ahead[MajorNumber] = 128;
+  /*
+    Complete initialization of the Generic Disk Information structure.
+  */
+  Controller->GenericDiskInfo.major = MajorNumber;
+  Controller->GenericDiskInfo.major_name = "rd";
+  Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits;
+  Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions;
+  Controller->GenericDiskInfo.max_nr = DAC960_MaxLogicalDrives;
+  Controller->GenericDiskInfo.init = DAC960_InitializeGenericDiskInfo;
+  Controller->GenericDiskInfo.nr_real = Controller->LogicalDriveCount;
+  Controller->GenericDiskInfo.real_devices = Controller;
+  Controller->GenericDiskInfo.next = NULL;
+  /*
+    Install the Generic Disk Information structure at the end of the list.
+  */
+  if ((GenericDiskInfo = gendisk_head) != NULL)
+    {
+      while (GenericDiskInfo->next != NULL)
+	GenericDiskInfo = GenericDiskInfo->next;
+      GenericDiskInfo->next = &Controller->GenericDiskInfo;
+    }
+  else gendisk_head = &Controller->GenericDiskInfo;
+  /*
+    Indicate the Block Device Registration completed successfully,
+  */
+  return true;
+}
+
+
+/*
+  DAC960_UnregisterBlockDevice unregisters the Block Device structures
+  associated with Controller.
+*/
+
+static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller)
+{
+  int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
+  /*
+    Unregister the Block Device Major Number for this DAC960 Controller.
+  */
+  unregister_blkdev(MajorNumber, "rd");
+  /*
+    Remove the I/O Request Function.
+  */
+  blk_dev[MajorNumber].request_fn = NULL;
+  /*
+    Remove the Disk Partitions array, Partition Sizes array, Block Sizes
+    array, Max Sectors per Request array, and Max Segments per Request array.
+  */
+  Controller->GenericDiskInfo.part = NULL;
+  Controller->GenericDiskInfo.sizes = NULL;
+  blk_size[MajorNumber] = NULL;
+  blksize_size[MajorNumber] = NULL;
+  max_sectors[MajorNumber] = NULL;
+  max_segments[MajorNumber] = NULL;
+  /*
+    Remove the Generic Disk Information structure from the list.
+  */
+  if (gendisk_head != &Controller->GenericDiskInfo)
+    {
+      GenericDiskInfo_T *GenericDiskInfo = gendisk_head;
+      while (GenericDiskInfo != NULL &&
+	     GenericDiskInfo->next != &Controller->GenericDiskInfo)
+	GenericDiskInfo = GenericDiskInfo->next;
+      if (GenericDiskInfo != NULL)
+	GenericDiskInfo->next = GenericDiskInfo->next->next;
+    }
+  else gendisk_head = Controller->GenericDiskInfo.next;
+}
+
+
+/*
+  DAC960_InitializeController initializes Controller.
+*/
+
+static void DAC960_InitializeController(DAC960_Controller_T *Controller)
+{
+  if (DAC960_ReadControllerConfiguration(Controller) &&
+      DAC960_ReportControllerConfiguration(Controller) &&
+      DAC960_ReadDeviceConfiguration(Controller) &&
+      DAC960_ReportDeviceConfiguration(Controller) &&
+      DAC960_RegisterBlockDevice(Controller))
+    {
+      /*
+	Initialize the Command structures.
+      */
+      DAC960_Command_T *Commands = Controller->Commands;
+      int CommandIdentifier;
+      Controller->FreeCommands = NULL;
+      for (CommandIdentifier = 0;
+	   CommandIdentifier < Controller->DriverQueueDepth;
+	   CommandIdentifier++)
+	{
+	  Commands[CommandIdentifier].Controller = Controller;
+	  Commands[CommandIdentifier].Next = Controller->FreeCommands;
+	  Controller->FreeCommands = &Commands[CommandIdentifier];
+	}
+      /*
+	Initialize the Monitoring Timer.
+      */
+      init_timer(&Controller->MonitoringTimer);
+      Controller->MonitoringTimer.expires =
+	jiffies + DAC960_MonitoringTimerInterval;
+      Controller->MonitoringTimer.data = (unsigned long) Controller;
+      Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction;
+      add_timer(&Controller->MonitoringTimer);
+      Controller->ControllerInitialized = true;
+    }
+  else DAC960_FinalizeController(Controller);
+}
+
+
+/*
+  DAC960_FinalizeController finalizes Controller.
+*/
+
+static void DAC960_FinalizeController(DAC960_Controller_T *Controller)
+{
+  if (Controller->ControllerInitialized)
+    {
+      del_timer(&Controller->MonitoringTimer);
+      DAC960_Notice("Flushing Cache...", Controller);
+      DAC960_ExecuteType3(Controller, DAC960_Flush, NULL);
+      DAC960_Notice("done\n", Controller);
+      switch (Controller->ControllerType)
+	{
+	case DAC960_V5_Controller:
+	  if (!Controller->DualModeMemoryMailboxInterface)
+	    DAC960_V5_SaveMemoryMailboxInfo(Controller);
+	  break;
+	case DAC960_V4_Controller:
+	  if (!Controller->DualModeMemoryMailboxInterface)
+	    DAC960_V4_SaveMemoryMailboxInfo(Controller);
+	  break;
+	case DAC960_V3_Controller:
+	  break;
+	}
+    }
+  free_irq(Controller->IRQ_Channel, Controller);
+  iounmap(Controller->MemoryMappedAddress);
+  if (Controller->IO_Address > 0)
+    release_region(Controller->IO_Address, 0x80);
+  DAC960_UnregisterBlockDevice(Controller);
+  DAC960_Controllers[Controller->ControllerNumber] = NULL;
+  kfree(Controller);
+}
+
+
+/*
+  DAC960_Initialize initializes the DAC960 Driver.
+*/
+
+void DAC960_Initialize(void)
+{
+  int ControllerNumber;
+  DAC960_DetectControllers(DAC960_V5_Controller);
+  DAC960_DetectControllers(DAC960_V4_Controller);
+  DAC960_DetectControllers(DAC960_V3_Controller);
+  if (DAC960_ActiveControllerCount == 0) return;
+  for (ControllerNumber = 0;
+       ControllerNumber < DAC960_ControllerCount;
+       ControllerNumber++)
+    if (DAC960_Controllers[ControllerNumber] != NULL)
+      DAC960_InitializeController(DAC960_Controllers[ControllerNumber]);
+  DAC960_CreateProcEntries();
+  register_reboot_notifier(&DAC960_NotifierBlock);
+}
+
+
+/*
+  DAC960_Finalize finalizes the DAC960 Driver.
+*/
+
+static int DAC960_Finalize(NotifierBlock_T *NotifierBlock,
+			   unsigned long Event,
+			   void *Buffer)
+{
+  int ControllerNumber;
+  if (!(Event == SYS_RESTART || Event == SYS_HALT || Event == SYS_POWER_OFF))
+    return NOTIFY_DONE;
+  if (DAC960_ActiveControllerCount == 0) return NOTIFY_OK;
+  for (ControllerNumber = 0;
+       ControllerNumber < DAC960_ControllerCount;
+       ControllerNumber++)
+    if (DAC960_Controllers[ControllerNumber] != NULL)
+      DAC960_FinalizeController(DAC960_Controllers[ControllerNumber]);
+  DAC960_DestroyProcEntries();
+  unregister_reboot_notifier(&DAC960_NotifierBlock);
+  return NOTIFY_OK;
+}
+
+
+/*
+  DAC960_ProcessRequest attempts to remove one I/O Request from Controller's
+  I/O Request Queue and queues it to the Controller.  WaitForCommand is true if
+  this function should wait for a Command to become available if necessary.
+  This function returns true if an I/O Request was queued and false otherwise.
+*/
+
+static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller,
+				     boolean WaitForCommand)
+{
+  IO_Request_T **RequestQueuePointer =
+    &blk_dev[DAC960_MAJOR + Controller->ControllerNumber].current_request;
+  IO_Request_T *Request;
+  DAC960_Command_T *Command;
+  char *RequestBuffer;
+  while (true)
+    {
+      Request = *RequestQueuePointer;
+      if (Request == NULL || Request->rq_status == RQ_INACTIVE) return false;
+      Command = DAC960_AllocateCommand(Controller);
+      if (Command != NULL) break;
+      if (!WaitForCommand) return false;
+      spin_unlock(&io_request_lock);
+      sleep_on(&Controller->CommandWaitQueue);
+      spin_lock_irq(&io_request_lock);
+    }
+  DAC960_ClearCommand(Command);
+  if (Request->cmd == READ)
+    Command->CommandType = DAC960_ReadCommand;
+  else Command->CommandType = DAC960_WriteCommand;
+  Command->Semaphore = Request->sem;
+  Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev);
+  Command->BlockNumber =
+    Request->sector
+    + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect;
+  Command->BlockCount = Request->nr_sectors;
+  Command->SegmentCount = Request->nr_segments;
+  Command->BufferHeader = Request->bh;
+  RequestBuffer = Request->buffer;
+  Request->rq_status = RQ_INACTIVE;
+  *RequestQueuePointer = Request->next;
+  wake_up(&wait_for_request);
+  if (Command->SegmentCount == 1)
+    {
+      DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+      if (Command->CommandType == DAC960_ReadCommand)
+	CommandMailbox->Type5.CommandOpcode = DAC960_Read;
+      else CommandMailbox->Type5.CommandOpcode = DAC960_Write;
+      CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
+      CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
+      CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
+      CommandMailbox->Type5.BusAddress = Virtual_to_Bus(RequestBuffer);
+    }
+  else
+    {
+      DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+      DAC960_ScatterGatherSegment_T
+	*ScatterGatherList = Command->ScatterGatherList;
+      BufferHeader_T *BufferHeader = Command->BufferHeader;
+      char *LastDataEndPointer = NULL;
+      int SegmentNumber = 0;
+      if (Command->CommandType == DAC960_ReadCommand)
+	CommandMailbox->Type5.CommandOpcode = DAC960_ReadWithOldScatterGather;
+      else
+	CommandMailbox->Type5.CommandOpcode = DAC960_WriteWithOldScatterGather;
+      CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
+      CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
+      CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
+      CommandMailbox->Type5.BusAddress = Virtual_to_Bus(ScatterGatherList);
+      CommandMailbox->Type5.ScatterGatherCount = Command->SegmentCount;
+      while (BufferHeader != NULL)
+	{
+	  if (BufferHeader->b_data == LastDataEndPointer)
+	    {
+	      ScatterGatherList[SegmentNumber-1].SegmentByteCount +=
+		BufferHeader->b_size;
+	      LastDataEndPointer += BufferHeader->b_size;
+	    }
+	  else
+	    {
+	      ScatterGatherList[SegmentNumber].SegmentDataPointer =
+		Virtual_to_Bus(BufferHeader->b_data);
+	      ScatterGatherList[SegmentNumber].SegmentByteCount =
+		BufferHeader->b_size;
+	      LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size;
+	      if (SegmentNumber++ > Controller->MaxScatterGatherSegments)
+		panic("DAC960: Scatter/Gather Segment Overflow\n");
+	    }
+	  BufferHeader = BufferHeader->b_reqnext;
+	}
+      if (SegmentNumber != Command->SegmentCount)
+	panic("DAC960: SegmentNumber != SegmentCount\n");
+    }
+  DAC960_QueueCommand(Command);
+  return true;
+}
+
+
+/*
+  DAC960_ProcessRequests attempts to remove as many I/O Requests as possible
+  from Controller's I/O Request Queue and queue them to the Controller.
+*/
+
+static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller)
+{
+  int Counter = 0;
+  while (DAC960_ProcessRequest(Controller, Counter++ == 0)) ;
+}
+
+
+/*
+  DAC960_RequestFunction0 is the I/O Request Function for DAC960 Controller 0.
+*/
+
+static void DAC960_RequestFunction0(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[0];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction1 is the I/O Request Function for DAC960 Controller 1.
+*/
+
+static void DAC960_RequestFunction1(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[1];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction2 is the I/O Request Function for DAC960 Controller 2.
+*/
+
+static void DAC960_RequestFunction2(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[2];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction3 is the I/O Request Function for DAC960 Controller 3.
+*/
+
+static void DAC960_RequestFunction3(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[3];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction4 is the I/O Request Function for DAC960 Controller 4.
+*/
+
+static void DAC960_RequestFunction4(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[4];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction5 is the I/O Request Function for DAC960 Controller 5.
+*/
+
+static void DAC960_RequestFunction5(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[5];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction6 is the I/O Request Function for DAC960 Controller 6.
+*/
+
+static void DAC960_RequestFunction6(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[6];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction7 is the I/O Request Function for DAC960 Controller 7.
+*/
+
+static void DAC960_RequestFunction7(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[7];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_ReadWriteError prints an appropriate error message for Command when
+  an error occurs on a Read or Write operation.
+*/
+
+static void DAC960_ReadWriteError(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  char *CommandName = "UNKNOWN";
+  switch (Command->CommandType)
+    {
+    case DAC960_ReadCommand:
+    case DAC960_ReadRetryCommand:
+      CommandName = "READ";
+      break;
+    case DAC960_WriteCommand:
+    case DAC960_WriteRetryCommand:
+      CommandName = "WRITE";
+      break;
+    case DAC960_MonitoringCommand:
+    case DAC960_ImmediateCommand:
+    case DAC960_QueuedCommand:
+      break;
+    }
+  switch (Command->CommandStatus)
+    {
+    case DAC960_IrrecoverableDataError:
+      DAC960_Error("Irrecoverable Data Error on %s:\n",
+		   Controller, CommandName);
+      break;
+    case DAC960_LogicalDriveNonexistentOrOffline:
+      DAC960_Error("Logical Drive Nonexistent or Offline on %s:\n",
+		   Controller, CommandName);
+      break;
+    case DAC960_AccessBeyondEndOfLogicalDrive:
+      DAC960_Error("Attempt to Access Beyond End of Logical Drive "
+		   "on %s:\n", Controller, CommandName);
+      break;
+    case DAC960_BadDataEncountered:
+      DAC960_Error("Bad Data Encountered on %s:\n", Controller, CommandName);
+      break;
+    default:
+      DAC960_Error("Unexpected Error Status %04X on %s:\n",
+		   Controller, Command->CommandStatus, CommandName);
+      break;
+    }
+  DAC960_Error("  /dev/rd/c%dd%d:   absolute blocks %d..%d\n",
+	       Controller, Controller->ControllerNumber,
+	       Command->LogicalDriveNumber, Command->BlockNumber,
+	       Command->BlockNumber + Command->BlockCount - 1);
+  if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0)
+    DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %d..%d\n",
+		 Controller, Controller->ControllerNumber,
+		 Command->LogicalDriveNumber,
+		 DAC960_PartitionNumber(Command->BufferHeader->b_rdev),
+		 Command->BufferHeader->b_rsector,
+		 Command->BufferHeader->b_rsector + Command->BlockCount - 1);
+}
+
+
+/*
+  DAC960_ProcessCompletedBuffer performs completion processing for an
+  individual Buffer.
+*/
+
+static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader,
+						 boolean SuccessfulIO)
+{
+  BufferHeader->b_end_io(BufferHeader, SuccessfulIO);
+}
+
+
+/*
+  DAC960_ProcessCompletedCommand performs completion processing for Command.
+*/
+
+static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  DAC960_CommandType_T CommandType = Command->CommandType;
+  DAC960_CommandOpcode_T CommandOpcode =
+    Command->CommandMailbox.Common.CommandOpcode;
+  DAC960_CommandStatus_T CommandStatus = Command->CommandStatus;
+  BufferHeader_T *BufferHeader = Command->BufferHeader;
+  if (CommandType == DAC960_ReadCommand ||
+      CommandType == DAC960_WriteCommand)
+    {
+      if (CommandStatus == DAC960_NormalCompletion)
+	{
+	  /*
+	    Perform completion processing for all buffers in this I/O Request.
+	  */
+	  while (BufferHeader != NULL)
+	    {
+	      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
+	      BufferHeader->b_reqnext = NULL;
+	      DAC960_ProcessCompletedBuffer(BufferHeader, true);
+	      BufferHeader = NextBufferHeader;
+	    }
+	  /*
+	    Wake up requestor for swap file paging requests.
+	  */
+	  if (Command->Semaphore != NULL)
+	    {
+	      up(Command->Semaphore);
+	      Command->Semaphore = NULL;
+	    }
+	  add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber);
+	}
+      else if ((CommandStatus == DAC960_IrrecoverableDataError ||
+		CommandStatus == DAC960_BadDataEncountered) &&
+	       BufferHeader != NULL &&
+	       BufferHeader->b_reqnext != NULL)
+	{
+	  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+	  if (CommandType == DAC960_ReadCommand)
+	    {
+	      Command->CommandType = DAC960_ReadRetryCommand;
+	      CommandMailbox->Type5.CommandOpcode = DAC960_Read;
+	    }
+	  else
+	    {
+	      Command->CommandType = DAC960_WriteRetryCommand;
+	      CommandMailbox->Type5.CommandOpcode = DAC960_Write;
+	    }
+	  Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits;
+	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
+	  CommandMailbox->Type5.BusAddress =
+	    Virtual_to_Bus(BufferHeader->b_data);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      else
+	{
+	  if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline)
+	    DAC960_ReadWriteError(Command);
+	  /*
+	    Perform completion processing for all buffers in this I/O Request.
+	  */
+	  while (BufferHeader != NULL)
+	    {
+	      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
+	      BufferHeader->b_reqnext = NULL;
+	      DAC960_ProcessCompletedBuffer(BufferHeader, false);
+	      BufferHeader = NextBufferHeader;
+	    }
+	  /*
+	    Wake up requestor for swap file paging requests.
+	  */
+	  if (Command->Semaphore != NULL)
+	    {
+	      up(Command->Semaphore);
+	      Command->Semaphore = NULL;
+	    }
+	}
+    }
+  else if (CommandType == DAC960_ReadRetryCommand ||
+	   CommandType == DAC960_WriteRetryCommand)
+    {
+      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
+      BufferHeader->b_reqnext = NULL;
+      /*
+	Perform completion processing for this single buffer.
+      */
+      if (CommandStatus == DAC960_NormalCompletion)
+	DAC960_ProcessCompletedBuffer(BufferHeader, true);
+      else
+	{
+	  if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline)
+	    DAC960_ReadWriteError(Command);
+	  DAC960_ProcessCompletedBuffer(BufferHeader, false);
+	}
+      if (NextBufferHeader != NULL)
+	{
+	  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+	  Command->BlockNumber +=
+	    BufferHeader->b_size >> DAC960_BlockSizeBits;
+	  Command->BlockCount =
+	    NextBufferHeader->b_size >> DAC960_BlockSizeBits;
+	  Command->BufferHeader = NextBufferHeader;
+	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
+	  CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
+	  CommandMailbox->Type5.BusAddress =
+	    Virtual_to_Bus(NextBufferHeader->b_data);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+    }
+  else if (CommandType == DAC960_MonitoringCommand ||
+	   CommandOpcode == DAC960_Enquiry ||
+	   CommandOpcode == DAC960_GetRebuildProgress)
+    {
+      if (CommandType != DAC960_MonitoringCommand)
+	{
+	  if (CommandOpcode == DAC960_Enquiry)
+	    memcpy(&Controller->Enquiry[Controller->EnquiryIndex ^ 1],
+		   Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress),
+		   sizeof(DAC960_Enquiry_T));
+	  else if (CommandOpcode == DAC960_GetRebuildProgress)
+	    memcpy(&Controller->RebuildProgress,
+		   Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress),
+		   sizeof(DAC960_RebuildProgress_T));
+	}
+      if (CommandOpcode == DAC960_Enquiry)
+	{
+	  DAC960_Enquiry_T *OldEnquiry =
+	    &Controller->Enquiry[Controller->EnquiryIndex];
+	  DAC960_Enquiry_T *NewEnquiry =
+	    &Controller->Enquiry[Controller->EnquiryIndex ^= 1];
+	  unsigned int OldCriticalLogicalDriveCount =
+	    OldEnquiry->CriticalLogicalDriveCount;
+	  unsigned int NewCriticalLogicalDriveCount =
+	    NewEnquiry->CriticalLogicalDriveCount;
+	  if (NewEnquiry->StatusFlags.DeferredWriteError !=
+	      OldEnquiry->StatusFlags.DeferredWriteError)
+	    DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller,
+			    (NewEnquiry->StatusFlags.DeferredWriteError
+			     ? "TRUE" : "FALSE"));
+	  if ((NewCriticalLogicalDriveCount > 0 ||
+	       NewCriticalLogicalDriveCount != OldCriticalLogicalDriveCount) ||
+	      (NewEnquiry->OfflineLogicalDriveCount > 0 ||
+	       NewEnquiry->OfflineLogicalDriveCount !=
+	       OldEnquiry->OfflineLogicalDriveCount) ||
+	      (NewEnquiry->DeadDriveCount > 0 ||
+	       NewEnquiry->DeadDriveCount !=
+	       OldEnquiry->DeadDriveCount) ||
+	      (NewEnquiry->EventLogSequenceNumber !=
+	       OldEnquiry->EventLogSequenceNumber) ||
+	      Controller->MonitoringTimerCount == 0 ||
+	      (jiffies - Controller->SecondaryMonitoringTime
+	       >= DAC960_SecondaryMonitoringInterval))
+	    {
+	      Controller->NeedLogicalDriveInformation = true;
+	      Controller->NewEventLogSequenceNumber =
+		NewEnquiry->EventLogSequenceNumber;
+	      Controller->NeedErrorTableInformation = true;
+	      Controller->NeedDeviceStateInformation = true;
+	      Controller->DeviceStateChannel = 0;
+	      Controller->DeviceStateTargetID = -1;
+	      Controller->SecondaryMonitoringTime = jiffies;
+	    }
+	  if (NewEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress ||
+	      NewEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress ||
+	      OldEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress ||
+	      OldEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress)
+	    Controller->NeedRebuildProgress = true;
+	  if (OldEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress)
+	    switch (NewEnquiry->RebuildFlag)
+	      {
+	      case DAC960_NoStandbyRebuildOrCheckInProgress:
+		DAC960_Progress("Consistency Check Completed Successfully\n",
+				Controller);
+		break;
+	      case DAC960_StandbyRebuildInProgress:
+	      case DAC960_BackgroundRebuildInProgress:
+		break;
+	      case DAC960_BackgroundCheckInProgress:
+		Controller->NeedConsistencyCheckProgress = true;
+		break;
+	      case DAC960_StandbyRebuildCompletedWithError:
+		DAC960_Progress("Consistency Check Completed with Error\n",
+				Controller);
+		break;
+	      case DAC960_BackgroundRebuildOrCheckFailed_DriveFailed:
+		DAC960_Progress("Consistency Check Failed - "
+				"Physical Drive Failed\n", Controller);
+		break;
+	      case DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed:
+		DAC960_Progress("Consistency Check Failed - "
+				"Logical Drive Failed\n", Controller);
+		break;
+	      case DAC960_BackgroundRebuildOrCheckFailed_OtherCauses:
+		DAC960_Progress("Consistency Check Failed - Other Causes\n",
+				Controller);
+		break;
+	      case DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated:
+		DAC960_Progress("Consistency Check Successfully Terminated\n",
+				Controller);
+		break;
+	      }
+	  else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress)
+	    Controller->NeedConsistencyCheckProgress = true;
+	}
+      else if (CommandOpcode == DAC960_PerformEventLogOperation)
+	{
+	  static char
+	    *DAC960_EventMessages[] =
+	       { "killed because write recovery failed",
+		 "killed because of SCSI bus reset failure",
+		 "killed because of double check condition",
+		 "killed because it was removed",
+		 "killed because of gross error on SCSI chip",
+		 "killed because of bad tag returned from drive",
+		 "killed because of timeout on SCSI command",
+		 "killed because of reset SCSI command issued from system",
+		 "killed because busy or parity error count exceeded limit",
+		 "killed because of 'kill drive' command from system",
+		 "killed because of selection timeout",
+		 "killed due to SCSI phase sequence error",
+		 "killed due to unknown status" };
+	  DAC960_EventLogEntry_T *EventLogEntry = &Controller->EventLogEntry;
+	  if (EventLogEntry->SequenceNumber ==
+	      Controller->OldEventLogSequenceNumber)
+	    {
+	      unsigned char SenseKey = EventLogEntry->SenseKey;
+	      unsigned char AdditionalSenseCode =
+		EventLogEntry->AdditionalSenseCode;
+	      unsigned char AdditionalSenseCodeQualifier =
+		EventLogEntry->AdditionalSenseCodeQualifier;
+	      if (SenseKey == 9 &&
+		  AdditionalSenseCode == 0x80 &&
+		  AdditionalSenseCodeQualifier <
+		  sizeof(DAC960_EventMessages) / sizeof(char *))
+		DAC960_Critical("Physical Drive %d:%d %s\n", Controller,
+				EventLogEntry->Channel,
+				EventLogEntry->TargetID,
+				DAC960_EventMessages[
+				  AdditionalSenseCodeQualifier]);
+	      else if (SenseKey == 6 && AdditionalSenseCode == 0x29)
+		{
+		  if (Controller->MonitoringTimerCount > 0)
+		    Controller->DeviceResetCount[EventLogEntry->Channel]
+						[EventLogEntry->TargetID]++;
+		}
+	      else if (!(SenseKey == 0 ||
+			 (SenseKey == 2 &&
+			  AdditionalSenseCode == 0x04 &&
+			  (AdditionalSenseCodeQualifier == 0x01 ||
+			   AdditionalSenseCodeQualifier == 0x02))))
+		{
+		  DAC960_Critical("Physical Drive %d:%d Error Log: "
+				  "Sense Key = %d, ASC = %02X, ASCQ = %02X\n",
+				  Controller,
+				  EventLogEntry->Channel,
+				  EventLogEntry->TargetID,
+				  SenseKey,
+				  AdditionalSenseCode,
+				  AdditionalSenseCodeQualifier);
+		  DAC960_Critical("Physical Drive %d:%d Error Log: "
+				  "Information = %02X%02X%02X%02X "
+				  "%02X%02X%02X%02X\n",
+				  Controller,
+				  EventLogEntry->Channel,
+				  EventLogEntry->TargetID,
+				  EventLogEntry->Information[0],
+				  EventLogEntry->Information[1],
+				  EventLogEntry->Information[2],
+				  EventLogEntry->Information[3],
+				  EventLogEntry->CommandSpecificInformation[0],
+				  EventLogEntry->CommandSpecificInformation[1],
+				  EventLogEntry->CommandSpecificInformation[2],
+				  EventLogEntry->CommandSpecificInformation[3]);
+		}
+	    }
+	  Controller->OldEventLogSequenceNumber++;
+	}
+      else if (CommandOpcode == DAC960_GetErrorTable)
+	{
+	  DAC960_ErrorTable_T *OldErrorTable =
+	    &Controller->ErrorTable[Controller->ErrorTableIndex];
+	  DAC960_ErrorTable_T *NewErrorTable =
+	    &Controller->ErrorTable[Controller->ErrorTableIndex ^= 1];
+	  int Channel, TargetID;
+	  for (Channel = 0; Channel < Controller->Channels; Channel++)
+	    for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
+	      {
+		DAC960_ErrorTableEntry_T *NewErrorEntry =
+		  &NewErrorTable->ErrorTableEntries[Channel][TargetID];
+		DAC960_ErrorTableEntry_T *OldErrorEntry =
+		  &OldErrorTable->ErrorTableEntries[Channel][TargetID];
+		if ((NewErrorEntry->ParityErrorCount !=
+		     OldErrorEntry->ParityErrorCount) ||
+		    (NewErrorEntry->SoftErrorCount !=
+		     OldErrorEntry->SoftErrorCount) ||
+		    (NewErrorEntry->HardErrorCount !=
+		     OldErrorEntry->HardErrorCount) ||
+		    (NewErrorEntry->MiscErrorCount !=
+		     OldErrorEntry->MiscErrorCount))
+		  DAC960_Critical("Physical Drive %d:%d Errors: "
+				  "Parity = %d, Soft = %d, "
+				  "Hard = %d, Misc = %d\n",
+				  Controller, Channel, TargetID,
+				  NewErrorEntry->ParityErrorCount,
+				  NewErrorEntry->SoftErrorCount,
+				  NewErrorEntry->HardErrorCount,
+				  NewErrorEntry->MiscErrorCount);
+	      }
+	}
+      else if (CommandOpcode == DAC960_GetDeviceState)
+	{
+	  DAC960_DeviceState_T *OldDeviceState =
+	    &Controller->DeviceState[Controller->DeviceStateIndex]
+				    [Controller->DeviceStateChannel]
+				    [Controller->DeviceStateTargetID];
+	  DAC960_DeviceState_T *NewDeviceState =
+	    &Controller->DeviceState[Controller->DeviceStateIndex ^ 1]
+				    [Controller->DeviceStateChannel]
+				    [Controller->DeviceStateTargetID];
+	  if (NewDeviceState->DeviceState != OldDeviceState->DeviceState)
+	    DAC960_Critical("Physical Drive %d:%d is now %s\n", Controller,
+			    Controller->DeviceStateChannel,
+			    Controller->DeviceStateTargetID,
+			    (NewDeviceState->DeviceState == DAC960_Device_Dead
+			     ? "DEAD"
+			     : NewDeviceState->DeviceState
+			       == DAC960_Device_WriteOnly
+			       ? "WRITE-ONLY"
+			       : NewDeviceState->DeviceState
+				 == DAC960_Device_Online
+				 ? "ONLINE" : "STANDBY"));
+	  if (OldDeviceState->DeviceState == DAC960_Device_Dead &&
+	      NewDeviceState->DeviceState != DAC960_Device_Dead)
+	    {
+	      Controller->NeedDeviceInquiryInformation = true;
+	      Controller->NeedDeviceSerialNumberInformation = true;
+	    }
+	}
+      else if (CommandOpcode == DAC960_GetLogicalDriveInformation)
+	{
+	  int LogicalDriveNumber;
+	  for (LogicalDriveNumber = 0;
+	       LogicalDriveNumber < Controller->LogicalDriveCount;
+	       LogicalDriveNumber++)
+	    {
+	      DAC960_LogicalDriveInformation_T *OldLogicalDriveInformation =
+		&Controller->LogicalDriveInformation
+			     [Controller->LogicalDriveInformationIndex]
+			     [LogicalDriveNumber];
+	      DAC960_LogicalDriveInformation_T *NewLogicalDriveInformation =
+		&Controller->LogicalDriveInformation
+			     [Controller->LogicalDriveInformationIndex ^ 1]
+			     [LogicalDriveNumber];
+	      if (NewLogicalDriveInformation->LogicalDriveState !=
+		  OldLogicalDriveInformation->LogicalDriveState)
+		DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
+				"is now %s\n", Controller,
+				LogicalDriveNumber,
+				Controller->ControllerNumber,
+				LogicalDriveNumber,
+				(NewLogicalDriveInformation->LogicalDriveState
+				 == DAC960_LogicalDrive_Online
+				 ? "ONLINE"
+				 : NewLogicalDriveInformation->LogicalDriveState
+				 == DAC960_LogicalDrive_Critical
+				 ? "CRITICAL" : "OFFLINE"));
+	      if (NewLogicalDriveInformation->WriteBack !=
+		  OldLogicalDriveInformation->WriteBack)
+		DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
+				"is now %s\n", Controller,
+				LogicalDriveNumber,
+				Controller->ControllerNumber,
+				LogicalDriveNumber,
+				(NewLogicalDriveInformation->WriteBack
+				 ? "WRITE BACK" : "WRITE THRU"));
+	    }
+	  Controller->LogicalDriveInformationIndex ^= 1;
+	}
+      else if (CommandOpcode == DAC960_GetRebuildProgress)
+	{
+	  unsigned int LogicalDriveNumber =
+	    Controller->RebuildProgress.LogicalDriveNumber;
+	  unsigned int LogicalDriveSize =
+	    Controller->RebuildProgress.LogicalDriveSize;
+	  unsigned int BlocksCompleted =
+	    LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks;
+	  switch (CommandStatus)
+	    {
+	    case DAC960_NormalCompletion:
+	      Controller->EphemeralProgressMessage = true;
+	      DAC960_Progress("Rebuild in Progress: "
+			      "Logical Drive %d (/dev/rd/c%dd%d) "
+			      "%d%% completed\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber,
+			      (100 * (BlocksCompleted >> 7))
+			      / (LogicalDriveSize >> 7));
+	      Controller->EphemeralProgressMessage = false;
+	      break;
+	    case DAC960_RebuildFailed_LogicalDriveFailure:
+	      DAC960_Progress("Rebuild Failed due to "
+			      "Logical Drive Failure\n", Controller);
+	      break;
+	    case DAC960_RebuildFailed_BadBlocksOnOther:
+	      DAC960_Progress("Rebuild Failed due to "
+			      "Bad Blocks on Other Drives\n", Controller);
+	      break;
+	    case DAC960_RebuildFailed_NewDriveFailed:
+	      DAC960_Progress("Rebuild Failed due to "
+			      "Failure of Drive Being Rebuilt\n", Controller);
+	      break;
+	    case DAC960_NoRebuildOrCheckInProgress:
+	      if (Controller->LastRebuildStatus != DAC960_NormalCompletion)
+		break;
+	    case DAC960_RebuildSuccessful:
+	      DAC960_Progress("Rebuild Completed Successfully\n", Controller);
+	      break;
+	    }
+	  Controller->LastRebuildStatus = CommandStatus;
+	}
+      else if (CommandOpcode == DAC960_RebuildStat)
+	{
+	  unsigned int LogicalDriveNumber =
+	    Controller->RebuildProgress.LogicalDriveNumber;
+	  unsigned int LogicalDriveSize =
+	    Controller->RebuildProgress.LogicalDriveSize;
+	  unsigned int BlocksCompleted =
+	    LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks;
+	  if (CommandStatus == DAC960_NormalCompletion)
+	    {
+	      Controller->EphemeralProgressMessage = true;
+	      DAC960_Progress("Consistency Check in Progress: "
+			      "Logical Drive %d (/dev/rd/c%dd%d) "
+			      "%d%% completed\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber,
+			      (100 * (BlocksCompleted >> 7))
+			      / (LogicalDriveSize >> 7));
+	      Controller->EphemeralProgressMessage = false;
+	    }
+	}
+    }
+  if (CommandType == DAC960_MonitoringCommand)
+    {
+      if (Controller->NewEventLogSequenceNumber
+	  - Controller->OldEventLogSequenceNumber > 0)
+	{
+	  Command->CommandMailbox.Type3E.CommandOpcode =
+	    DAC960_PerformEventLogOperation;
+	  Command->CommandMailbox.Type3E.OperationType =
+	    DAC960_GetEventLogEntry;
+	  Command->CommandMailbox.Type3E.OperationQualifier = 1;
+	  Command->CommandMailbox.Type3E.SequenceNumber =
+	    Controller->OldEventLogSequenceNumber;
+	  Command->CommandMailbox.Type3E.BusAddress =
+	    Virtual_to_Bus(&Controller->EventLogEntry);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      if (Controller->NeedErrorTableInformation)
+	{
+	  Controller->NeedErrorTableInformation = false;
+	  Command->CommandMailbox.Type3.CommandOpcode = DAC960_GetErrorTable;
+	  Command->CommandMailbox.Type3.BusAddress =
+	    Virtual_to_Bus(
+	      &Controller->ErrorTable[Controller->ErrorTableIndex ^ 1]);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      if (Controller->NeedRebuildProgress && 
+	  Controller->Enquiry[Controller->EnquiryIndex]
+		      .CriticalLogicalDriveCount <
+	  Controller->Enquiry[Controller->EnquiryIndex ^ 1]
+		      .CriticalLogicalDriveCount)
+	{
+	  Controller->NeedRebuildProgress = false;
+	  Command->CommandMailbox.Type3.CommandOpcode =
+	    DAC960_GetRebuildProgress;
+	  Command->CommandMailbox.Type3.BusAddress =
+	    Virtual_to_Bus(&Controller->RebuildProgress);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      if (Controller->NeedDeviceStateInformation)
+	{
+	  if (Controller->NeedDeviceInquiryInformation)
+	    {
+	      DAC960_DCDB_T *DCDB = &Controller->MonitoringDCDB;
+	      DAC960_SCSI_Inquiry_T *InquiryStandardData =
+		&Controller->InquiryStandardData
+			       [Controller->DeviceStateChannel]
+			       [Controller->DeviceStateTargetID];
+	      InquiryStandardData->PeripheralDeviceType = 0x1F;
+	      Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB;
+	      Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB);
+	      DCDB->Channel = Controller->DeviceStateChannel;
+	      DCDB->TargetID = Controller->DeviceStateTargetID;
+	      DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem;
+	      DCDB->EarlyStatus = false;
+	      DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds;
+	      DCDB->NoAutomaticRequestSense = false;
+	      DCDB->DisconnectPermitted = true;
+	      DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T);
+	      DCDB->BusAddress = Virtual_to_Bus(InquiryStandardData);
+	      DCDB->CDBLength = 6;
+	      DCDB->TransferLengthHigh4 = 0;
+	      DCDB->SenseLength = sizeof(DCDB->SenseData);
+	      DCDB->CDB[0] = 0x12; /* INQUIRY */
+	      DCDB->CDB[1] = 0; /* EVPD = 0 */
+	      DCDB->CDB[2] = 0; /* Page Code */
+	      DCDB->CDB[3] = 0; /* Reserved */
+	      DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T);
+	      DCDB->CDB[5] = 0; /* Control */
+	      DAC960_QueueCommand(Command);
+	      Controller->NeedDeviceInquiryInformation = false;
+	      return;
+	    }
+	  if (Controller->NeedDeviceSerialNumberInformation)
+	    {
+	      DAC960_DCDB_T *DCDB = &Controller->MonitoringDCDB;
+	      DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
+		&Controller->InquiryUnitSerialNumber
+			       [Controller->DeviceStateChannel]
+			       [Controller->DeviceStateTargetID];
+	      InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+	      Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB;
+	      Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB);
+	      DCDB->Channel = Controller->DeviceStateChannel;
+	      DCDB->TargetID = Controller->DeviceStateTargetID;
+	      DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem;
+	      DCDB->EarlyStatus = false;
+	      DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds;
+	      DCDB->NoAutomaticRequestSense = false;
+	      DCDB->DisconnectPermitted = true;
+	      DCDB->TransferLength =
+		sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+	      DCDB->BusAddress = Virtual_to_Bus(InquiryUnitSerialNumber);
+	      DCDB->CDBLength = 6;
+	      DCDB->TransferLengthHigh4 = 0;
+	      DCDB->SenseLength = sizeof(DCDB->SenseData);
+	      DCDB->CDB[0] = 0x12; /* INQUIRY */
+	      DCDB->CDB[1] = 1; /* EVPD = 1 */
+	      DCDB->CDB[2] = 0x80; /* Page Code */
+	      DCDB->CDB[3] = 0; /* Reserved */
+	      DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+	      DCDB->CDB[5] = 0; /* Control */
+	      DAC960_QueueCommand(Command);
+	      Controller->NeedDeviceSerialNumberInformation = false;
+	      return;
+	    }
+	  if (++Controller->DeviceStateTargetID == DAC960_MaxTargets)
+	    {
+	      Controller->DeviceStateChannel++;
+	      Controller->DeviceStateTargetID = 0;
+	    }
+	  while (Controller->DeviceStateChannel < Controller->Channels)
+	    {
+	      DAC960_DeviceState_T *OldDeviceState =
+		&Controller->DeviceState[Controller->DeviceStateIndex]
+					[Controller->DeviceStateChannel]
+					[Controller->DeviceStateTargetID];
+	      if (OldDeviceState->Present &&
+		  OldDeviceState->DeviceType == DAC960_DiskType)
+		{
+		  Command->CommandMailbox.Type3D.CommandOpcode =
+		    DAC960_GetDeviceState;
+		  Command->CommandMailbox.Type3D.Channel =
+		    Controller->DeviceStateChannel;
+		  Command->CommandMailbox.Type3D.TargetID =
+		    Controller->DeviceStateTargetID;
+		  Command->CommandMailbox.Type3D.BusAddress =
+		    Virtual_to_Bus(&Controller->DeviceState
+				      [Controller->DeviceStateIndex ^ 1]
+				      [Controller->DeviceStateChannel]
+				      [Controller->DeviceStateTargetID]);
+		  DAC960_QueueCommand(Command);
+		  return;
+		}
+	      if (++Controller->DeviceStateTargetID == DAC960_MaxTargets)
+		{
+		  Controller->DeviceStateChannel++;
+		  Controller->DeviceStateTargetID = 0;
+		}
+	    }
+	  Controller->NeedDeviceStateInformation = false;
+	  Controller->DeviceStateIndex ^= 1;
+	}
+      if (Controller->NeedLogicalDriveInformation)
+	{
+	  Controller->NeedLogicalDriveInformation = false;
+	  Command->CommandMailbox.Type3.CommandOpcode =
+	    DAC960_GetLogicalDriveInformation;
+	  Command->CommandMailbox.Type3.BusAddress =
+	    Virtual_to_Bus(
+	      &Controller->LogicalDriveInformation
+			   [Controller->LogicalDriveInformationIndex ^ 1]);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      if (Controller->NeedRebuildProgress)
+	{
+	  Controller->NeedRebuildProgress = false;
+	  Command->CommandMailbox.Type3.CommandOpcode =
+	    DAC960_GetRebuildProgress;
+	  Command->CommandMailbox.Type3.BusAddress =
+	    Virtual_to_Bus(&Controller->RebuildProgress);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      if (Controller->NeedConsistencyCheckProgress)
+	{
+	  Controller->NeedConsistencyCheckProgress = false;
+	  Command->CommandMailbox.Type3.CommandOpcode = DAC960_RebuildStat;
+	  Command->CommandMailbox.Type3.BusAddress =
+	    Virtual_to_Bus(&Controller->RebuildProgress);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      Controller->MonitoringTimerCount++;
+      Controller->MonitoringTimer.expires =
+	jiffies + DAC960_MonitoringTimerInterval;
+      add_timer(&Controller->MonitoringTimer);
+    }
+  if (CommandType == DAC960_ImmediateCommand)
+    {
+      up(Command->Semaphore);
+      Command->Semaphore = NULL;
+      return;
+    }
+  if (CommandType == DAC960_QueuedCommand)
+    {
+      DAC960_KernelCommand_T *KernelCommand = Command->KernelCommand;
+      KernelCommand->CommandStatus = CommandStatus;
+      Command->KernelCommand = NULL;
+      if (CommandOpcode == DAC960_DCDB)
+	Controller->DirectCommandActive[KernelCommand->DCDB->Channel]
+				       [KernelCommand->DCDB->TargetID] = false;
+      DAC960_DeallocateCommand(Command);
+      KernelCommand->CompletionFunction(KernelCommand);
+      return;
+    }
+  /*
+    Queue a Status Monitoring Command to the Controller using the just
+    completed Command if one was deferred previously due to lack of a
+    free Command when the Monitoring Timer Function was called.
+  */
+  if (Controller->MonitoringCommandDeferred)
+    {
+      Controller->MonitoringCommandDeferred = false;
+      DAC960_QueueMonitoringCommand(Command);
+      return;
+    }
+  /*
+    Deallocate the Command, and wake up any processes waiting on a free Command.
+  */
+  DAC960_DeallocateCommand(Command);
+  wake_up(&Controller->CommandWaitQueue);
+}
+
+
+/*
+  DAC960_InterruptHandler handles hardware interrupts from DAC960 Controllers.
+*/
+
+static void DAC960_InterruptHandler(int IRQ_Channel,
+				    void *DeviceIdentifier,
+				    Registers_T *InterruptRegisters)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_StatusMailbox_T *NextStatusMailbox;
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags);
+  /*
+    Process Hardware Interrupts for Controller.
+  */
+  switch (Controller->ControllerType)
+    {
+    case DAC960_V5_Controller:
+      DAC960_V5_AcknowledgeInterrupt(ControllerBaseAddress);
+      NextStatusMailbox = Controller->NextStatusMailbox;
+      while (NextStatusMailbox->Fields.Valid)
+	{
+	  DAC960_CommandIdentifier_T CommandIdentifier =
+	    NextStatusMailbox->Fields.CommandIdentifier;
+	  DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
+	  Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus;
+	  NextStatusMailbox->Word = 0;
+	  if (++NextStatusMailbox > Controller->LastStatusMailbox)
+	    NextStatusMailbox = Controller->FirstStatusMailbox;
+	  DAC960_ProcessCompletedCommand(Command);
+	}
+      Controller->NextStatusMailbox = NextStatusMailbox;
+      break;
+    case DAC960_V4_Controller:
+      DAC960_V4_AcknowledgeInterrupt(ControllerBaseAddress);
+      NextStatusMailbox = Controller->NextStatusMailbox;
+      while (NextStatusMailbox->Fields.Valid)
+	{
+	  DAC960_CommandIdentifier_T CommandIdentifier =
+	    NextStatusMailbox->Fields.CommandIdentifier;
+	  DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
+	  Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus;
+	  NextStatusMailbox->Word = 0;
+	  if (++NextStatusMailbox > Controller->LastStatusMailbox)
+	    NextStatusMailbox = Controller->FirstStatusMailbox;
+	  DAC960_ProcessCompletedCommand(Command);
+	}
+      Controller->NextStatusMailbox = NextStatusMailbox;
+      break;
+    case DAC960_V3_Controller:
+      while (DAC960_V3_StatusAvailableP(ControllerBaseAddress))
+	{
+	  DAC960_CommandIdentifier_T CommandIdentifier =
+	    DAC960_V3_ReadStatusCommandIdentifier(ControllerBaseAddress);
+	  DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
+	  Command->CommandStatus =
+	    DAC960_V3_ReadStatusRegister(ControllerBaseAddress);
+	  DAC960_V3_AcknowledgeInterrupt(ControllerBaseAddress);
+	  DAC960_V3_AcknowledgeStatus(ControllerBaseAddress);
+	  DAC960_ProcessCompletedCommand(Command);
+	}
+      break;
+    }
+  /*
+    Attempt to remove additional I/O Requests from the Controller's
+    I/O Request Queue and queue them to the Controller.
+  */
+  while (DAC960_ProcessRequest(Controller, false)) ;
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_QueueMonitoringCommand queues a Monitoring Command to Controller.
+*/
+
+static void DAC960_QueueMonitoringCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+  DAC960_ClearCommand(Command);
+  Command->CommandType = DAC960_MonitoringCommand;
+  CommandMailbox->Type3.CommandOpcode = DAC960_Enquiry;
+  CommandMailbox->Type3.BusAddress =
+    Virtual_to_Bus(&Controller->Enquiry[Controller->EnquiryIndex ^ 1]);
+  DAC960_QueueCommand(Command);
+}
+
+
+/*
+  DAC960_MonitoringTimerFunction is the timer function for monitoring
+  the status of DAC960 Controllers.
+*/
+
+static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) TimerData;
+  DAC960_Command_T *Command;
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+  /*
+    Queue a Status Monitoring Command to Controller.
+  */
+  Command = DAC960_AllocateCommand(Controller);
+  if (Command != NULL)
+    DAC960_QueueMonitoringCommand(Command);
+  else Controller->MonitoringCommandDeferred = true;
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_Open is the Device Open Function for the DAC960 Driver.
+*/
+
+static int DAC960_Open(Inode_T *Inode, File_T *File)
+{
+  int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
+  int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
+  DAC960_Controller_T *Controller;
+  if (ControllerNumber == 0 && LogicalDriveNumber == 0 &&
+      (File->f_flags & O_NONBLOCK))
+    goto ModuleOnly;
+  if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1)
+    return -ENXIO;
+  Controller = DAC960_Controllers[ControllerNumber];
+  if (Controller == NULL ||
+      LogicalDriveNumber > Controller->LogicalDriveCount - 1)
+    return -ENXIO;
+  if (Controller->LogicalDriveInformation
+		  [Controller->LogicalDriveInformationIndex]
+		  [LogicalDriveNumber].LogicalDriveState
+      == DAC960_LogicalDrive_Offline)
+    return -ENXIO;
+  if (Controller->LogicalDriveInitialState[LogicalDriveNumber]
+      == DAC960_LogicalDrive_Offline)
+    {
+      Controller->LogicalDriveInitialState[LogicalDriveNumber] =
+	DAC960_LogicalDrive_Online;
+      DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo);
+      resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
+    }
+  if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0)
+    return -ENXIO;
+  /*
+    Increment Controller and Logical Drive Usage Counts.
+  */
+  Controller->ControllerUsageCount++;
+  Controller->LogicalDriveUsageCount[LogicalDriveNumber]++;
+ ModuleOnly:
+  MOD_INC_USE_COUNT;
+  return 0;
+}
+
+
+/*
+  DAC960_Release is the Device Release Function for the DAC960 Driver.
+*/
+
+static int DAC960_Release(Inode_T *Inode, File_T *File)
+{
+  int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
+  int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
+  DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+  if (ControllerNumber == 0 && LogicalDriveNumber == 0 &&
+      File != NULL && (File->f_flags & O_NONBLOCK))
+    goto ModuleOnly;
+  /*
+    Force any buffered data to be written.
+  */
+  fsync_dev(Inode->i_rdev);
+  /*
+    Decrement the Logical Drive and Controller Usage Counts.
+  */
+  Controller->LogicalDriveUsageCount[LogicalDriveNumber]--;
+  Controller->ControllerUsageCount--;
+ ModuleOnly:
+  MOD_DEC_USE_COUNT;
+  return 0;
+}
+
+
+/*
+  DAC960_IOCTL is the Device IOCTL Function for the DAC960 Driver.
+*/
+
+static int DAC960_IOCTL(Inode_T *Inode, File_T *File,
+			unsigned int Request, unsigned long Argument)
+{
+  int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
+  int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
+  DiskGeometry_T Geometry, *UserGeometry;
+  DAC960_Controller_T *Controller;
+  int PartitionNumber;
+  if (File->f_flags & O_NONBLOCK)
+    return DAC960_UserIOCTL(Inode, File, Request, Argument);
+  if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1)
+    return -ENXIO;
+  Controller = DAC960_Controllers[ControllerNumber];
+  if (Controller == NULL ||
+      LogicalDriveNumber > Controller->LogicalDriveCount - 1)
+    return -ENXIO;
+  switch (Request)
+    {
+    case HDIO_GETGEO:
+      /* Get BIOS Disk Geometry. */
+      UserGeometry = (DiskGeometry_T *) Argument;
+      if (UserGeometry == NULL) return -EINVAL;
+      Geometry.heads = Controller->GeometryTranslationHeads;
+      Geometry.sectors = Controller->GeometryTranslationSectors;
+      Geometry.cylinders =
+	Controller->LogicalDriveInformation
+		    [Controller->LogicalDriveInformationIndex]
+		    [LogicalDriveNumber].LogicalDriveSize
+	/ (Controller->GeometryTranslationHeads *
+	   Controller->GeometryTranslationSectors);
+      Geometry.start = Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)]
+						  .start_sect;
+      return copy_to_user(UserGeometry, &Geometry, sizeof(DiskGeometry_T));
+    case BLKGETSIZE:
+      /* Get Device Size. */
+      if ((long *) Argument == NULL) return -EINVAL;
+      return put_user(Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)]
+						 .nr_sects,
+		      (long *) Argument);
+    case BLKRAGET:
+      /* Get Read-Ahead. */
+      if ((int *) Argument == NULL) return -EINVAL;
+      return put_user(read_ahead[MAJOR(Inode->i_rdev)], (int *) Argument);
+    case BLKRASET:
+      /* Set Read-Ahead. */
+      if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+      if (Argument > 256) return -EINVAL;
+      read_ahead[MAJOR(Inode->i_rdev)] = Argument;
+      return 0;
+    case BLKFLSBUF:
+      /* Flush Buffers. */
+      if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+      fsync_dev(Inode->i_rdev);
+      invalidate_buffers(Inode->i_rdev);
+      return 0;
+    case BLKRRPART:
+      /* Re-Read Partition Table. */
+      if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+      if (Controller->LogicalDriveUsageCount[LogicalDriveNumber] > 1)
+	return -EBUSY;
+      for (PartitionNumber = 0;
+	   PartitionNumber < DAC960_MaxPartitions;
+	   PartitionNumber++)
+	{
+	  KernelDevice_T Device = DAC960_KernelDevice(ControllerNumber,
+						      LogicalDriveNumber,
+						      PartitionNumber);
+	  int MinorNumber = DAC960_MinorNumber(LogicalDriveNumber,
+					       PartitionNumber);
+	  SuperBlock_T *SuperBlock = get_super(Device);
+	  if (Controller->GenericDiskInfo.part[MinorNumber].nr_sects == 0)
+	    continue;
+	  /*
+	    Flush all changes and invalidate buffered state.
+	  */
+	  sync_dev(Device);
+	  if (SuperBlock != NULL)
+	    invalidate_inodes(SuperBlock);
+	  invalidate_buffers(Device);
+	  /*
+	    Clear existing partition sizes.
+	  */
+	  if (PartitionNumber > 0)
+	    {
+	      Controller->GenericDiskInfo.part[MinorNumber].start_sect = 0;
+	      Controller->GenericDiskInfo.part[MinorNumber].nr_sects = 0;
+	    }
+	  /*
+	    Reset the Block Size so that the partition table can be read.
+	  */
+	  set_blocksize(Device, BLOCK_SIZE);
+	}
+      resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
+      return 0;
+    }
+  return -EINVAL;
+}
+
+
+/*
+  DAC960_UserIOCTL is the User IOCTL Function for the DAC960 Driver.
+*/
+
+static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
+			    unsigned int Request, unsigned long Argument)
+{
+  int ErrorCode;
+  if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+  switch (Request)
+    {
+    case DAC960_IOCTL_GET_CONTROLLER_COUNT:
+      return DAC960_ControllerCount;
+    case DAC960_IOCTL_GET_CONTROLLER_INFO:
+      {
+	DAC960_ControllerInfo_T *UserSpaceControllerInfo =
+	  (DAC960_ControllerInfo_T *) Argument;
+	DAC960_ControllerInfo_T ControllerInfo;
+	DAC960_Controller_T *Controller;
+	int ControllerNumber;
+	if (UserSpaceControllerInfo == NULL) return -EINVAL;
+	ErrorCode = get_user(ControllerNumber,
+			     &UserSpaceControllerInfo->ControllerNumber);
+	if (ErrorCode != 0) return ErrorCode;
+	if (ControllerNumber < 0 ||
+	    ControllerNumber > DAC960_ControllerCount - 1)
+	  return -ENXIO;
+	Controller = DAC960_Controllers[ControllerNumber];
+	if (Controller == NULL)
+	  return -ENXIO;
+	memset(&ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T));
+	ControllerInfo.ControllerNumber = ControllerNumber;
+	ControllerInfo.PCI_Bus = Controller->Bus;
+	ControllerInfo.PCI_Device = Controller->Device;
+	ControllerInfo.PCI_Function = Controller->Function;
+	ControllerInfo.IRQ_Channel = Controller->IRQ_Channel;
+	ControllerInfo.Channels = Controller->Channels;
+	ControllerInfo.PCI_Address = Controller->PCI_Address;
+	strcpy(ControllerInfo.ModelName, Controller->ModelName);
+	strcpy(ControllerInfo.FirmwareVersion, Controller->FirmwareVersion);
+	return copy_to_user(UserSpaceControllerInfo, &ControllerInfo,
+			    sizeof(DAC960_ControllerInfo_T));
+      }
+    case DAC960_IOCTL_EXECUTE_COMMAND:
+      {
+	DAC960_UserCommand_T *UserSpaceUserCommand =
+	  (DAC960_UserCommand_T *) Argument;
+	DAC960_UserCommand_T UserCommand;
+	DAC960_Controller_T *Controller;
+	DAC960_Command_T *Command = NULL;
+	DAC960_CommandOpcode_T CommandOpcode;
+	DAC960_CommandStatus_T CommandStatus;
+	DAC960_DCDB_T DCDB;
+	ProcessorFlags_T ProcessorFlags;
+	int ControllerNumber, DataTransferLength;
+	unsigned char *DataTransferBuffer = NULL;
+	if (UserSpaceUserCommand == NULL) return -EINVAL;
+	ErrorCode = copy_from_user(&UserCommand, UserSpaceUserCommand,
+				   sizeof(DAC960_UserCommand_T));
+	if (ErrorCode != 0) goto Failure;
+	ControllerNumber = UserCommand.ControllerNumber;
+	if (ControllerNumber < 0 ||
+	    ControllerNumber > DAC960_ControllerCount - 1)
+	  return -ENXIO;
+	Controller = DAC960_Controllers[ControllerNumber];
+	if (Controller == NULL)
+	  return -ENXIO;
+	CommandOpcode = UserCommand.CommandMailbox.Common.CommandOpcode;
+	DataTransferLength = UserCommand.DataTransferLength;
+	if (CommandOpcode & 0x80) return -EINVAL;
+	if (CommandOpcode == DAC960_DCDB)
+	  {
+	    ErrorCode =
+	      copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_DCDB_T));
+	    if (ErrorCode != 0) goto Failure;
+	    if (!((DataTransferLength == 0 &&
+		   DCDB.Direction == DAC960_DCDB_NoDataTransfer) ||
+		  (DataTransferLength > 0 &&
+		   DCDB.Direction == DAC960_DCDB_DataTransferDeviceToSystem) ||
+		  (DataTransferLength < 0 &&
+		   DCDB.Direction == DAC960_DCDB_DataTransferSystemToDevice)))
+	      return -EINVAL;
+	    if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength)
+		!= abs(DataTransferLength))
+	      return -EINVAL;
+	  }
+	if (DataTransferLength > 0)
+	  {
+	    DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL);
+	    if (DataTransferBuffer == NULL) return -ENOMEM;
+	    memset(DataTransferBuffer, 0, DataTransferLength);
+	  }
+	else if (DataTransferLength < 0)
+	  {
+	    DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL);
+	    if (DataTransferBuffer == NULL) return -ENOMEM;
+	    ErrorCode = copy_from_user(DataTransferBuffer,
+				       UserCommand.DataTransferBuffer,
+				       -DataTransferLength);
+	    if (ErrorCode != 0) goto Failure;
+	  }
+	if (CommandOpcode == DAC960_DCDB)
+	  {
+	    while (true)
+	      {
+		DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+		if (!Controller->DirectCommandActive[DCDB.Channel]
+						    [DCDB.TargetID])
+		  Command = DAC960_AllocateCommand(Controller);
+		if (Command != NULL)
+		  Controller->DirectCommandActive[DCDB.Channel]
+						 [DCDB.TargetID] = true;
+		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+		if (Command != NULL) break;
+		sleep_on(&Controller->CommandWaitQueue);
+	      }
+	    DAC960_ClearCommand(Command);
+	    Command->CommandType = DAC960_ImmediateCommand;
+	    memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox,
+		   sizeof(DAC960_CommandMailbox_T));
+	    Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(&DCDB);
+	    DCDB.BusAddress = Virtual_to_Bus(DataTransferBuffer);
+	  }
+	else
+	  {
+	    while (true)
+	      {
+		DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+		Command = DAC960_AllocateCommand(Controller);
+		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+		if (Command != NULL) break;
+		sleep_on(&Controller->CommandWaitQueue);
+	      }
+	    DAC960_ClearCommand(Command);
+	    Command->CommandType = DAC960_ImmediateCommand;
+	    memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox,
+		   sizeof(DAC960_CommandMailbox_T));
+	    if (DataTransferBuffer != NULL)
+	      Command->CommandMailbox.Type3.BusAddress =
+		Virtual_to_Bus(DataTransferBuffer);
+	  }
+	DAC960_ExecuteCommand(Command);
+	CommandStatus = Command->CommandStatus;
+	DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	DAC960_DeallocateCommand(Command);
+	DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+	if (CommandStatus == DAC960_NormalCompletion &&
+	    DataTransferLength > 0)
+	  {
+	    ErrorCode = copy_to_user(UserCommand.DataTransferBuffer,
+				     DataTransferBuffer, DataTransferLength);
+	    if (ErrorCode != 0) goto Failure;
+	  }
+	if (CommandOpcode == DAC960_DCDB)
+	  {
+	    Controller->DirectCommandActive[DCDB.Channel]
+					   [DCDB.TargetID] = false;
+	    ErrorCode =
+	      copy_to_user(UserCommand.DCDB, &DCDB, sizeof(DAC960_DCDB_T));
+	    if (ErrorCode != 0) goto Failure;
+	  }
+	ErrorCode = CommandStatus;
+      Failure:
+	if (DataTransferBuffer != NULL)
+	  kfree(DataTransferBuffer);
+	return ErrorCode;
+      }
+    }
+  return -EINVAL;
+}
+
+
+/*
+  DAC960_KernelIOCTL is the Kernel IOCTL Function for the DAC960 Driver.
+*/
+
+int DAC960_KernelIOCTL(unsigned int Request, void *Argument)
+{
+  switch (Request)
+    {
+    case DAC960_IOCTL_GET_CONTROLLER_COUNT:
+      return DAC960_ControllerCount;
+    case DAC960_IOCTL_GET_CONTROLLER_INFO:
+      {
+	DAC960_ControllerInfo_T *ControllerInfo =
+	  (DAC960_ControllerInfo_T *) Argument;
+	DAC960_Controller_T *Controller;
+	int ControllerNumber;
+	if (ControllerInfo == NULL) return -EINVAL;
+	ControllerNumber = ControllerInfo->ControllerNumber;
+	if (ControllerNumber < 0 ||
+	    ControllerNumber > DAC960_ControllerCount - 1)
+	  return -ENXIO;
+	Controller = DAC960_Controllers[ControllerNumber];
+	if (Controller == NULL)
+	  return -ENXIO;
+	memset(ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T));
+	ControllerInfo->ControllerNumber = ControllerNumber;
+	ControllerInfo->PCI_Bus = Controller->Bus;
+	ControllerInfo->PCI_Device = Controller->Device;
+	ControllerInfo->PCI_Function = Controller->Function;
+	ControllerInfo->IRQ_Channel = Controller->IRQ_Channel;
+	ControllerInfo->Channels = Controller->Channels;
+	ControllerInfo->PCI_Address = Controller->PCI_Address;
+	strcpy(ControllerInfo->ModelName, Controller->ModelName);
+	strcpy(ControllerInfo->FirmwareVersion, Controller->FirmwareVersion);
+	return 0;
+      }
+    case DAC960_IOCTL_EXECUTE_COMMAND:
+      {
+	DAC960_KernelCommand_T *KernelCommand =
+	  (DAC960_KernelCommand_T *) Argument;
+	DAC960_Controller_T *Controller;
+	DAC960_Command_T *Command = NULL;
+	DAC960_CommandOpcode_T CommandOpcode;
+	DAC960_DCDB_T *DCDB = NULL;
+	ProcessorFlags_T ProcessorFlags;
+	int ControllerNumber, DataTransferLength;
+	unsigned char *DataTransferBuffer = NULL;
+	if (KernelCommand == NULL) return -EINVAL;
+	ControllerNumber = KernelCommand->ControllerNumber;
+	if (ControllerNumber < 0 ||
+	    ControllerNumber > DAC960_ControllerCount - 1)
+	  return -ENXIO;
+	Controller = DAC960_Controllers[ControllerNumber];
+	if (Controller == NULL)
+	  return -ENXIO;
+	CommandOpcode = KernelCommand->CommandMailbox.Common.CommandOpcode;
+	DataTransferLength = KernelCommand->DataTransferLength;
+	DataTransferBuffer = KernelCommand->DataTransferBuffer;
+	if (CommandOpcode & 0x80) return -EINVAL;
+	if (CommandOpcode == DAC960_DCDB)
+	  {
+	    DCDB = KernelCommand->DCDB;
+	    if (!((DataTransferLength == 0 &&
+		   DCDB->Direction == DAC960_DCDB_NoDataTransfer) ||
+		  (DataTransferLength > 0 &&
+		   DCDB->Direction == DAC960_DCDB_DataTransferDeviceToSystem) ||
+		  (DataTransferLength < 0 &&
+		   DCDB->Direction == DAC960_DCDB_DataTransferSystemToDevice)))
+	      return -EINVAL;
+	    if (((DCDB->TransferLengthHigh4 << 16) | DCDB->TransferLength)
+		!= abs(DataTransferLength))
+	      return -EINVAL;
+	  }
+	if (DataTransferLength != 0 && DataTransferBuffer == NULL)
+	  return -EINVAL;
+	if (DataTransferLength > 0)
+	  memset(DataTransferBuffer, 0, DataTransferLength);
+	if (CommandOpcode == DAC960_DCDB)
+	  {
+	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	    if (!Controller->DirectCommandActive[DCDB->Channel]
+						[DCDB->TargetID])
+	      Command = DAC960_AllocateCommand(Controller);
+	    if (Command == NULL)
+	      {
+		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+		return -EBUSY;
+	      }
+	    else Controller->DirectCommandActive[DCDB->Channel]
+						[DCDB->TargetID] = true;
+	    DAC960_ClearCommand(Command);
+	    Command->CommandType = DAC960_QueuedCommand;
+	    memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox,
+		   sizeof(DAC960_CommandMailbox_T));
+	    Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB);
+	    Command->KernelCommand = KernelCommand;
+	    DCDB->BusAddress = Virtual_to_Bus(DataTransferBuffer);
+	    DAC960_QueueCommand(Command);
+	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+	  }
+	else
+	  {
+	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	    Command = DAC960_AllocateCommand(Controller);
+	    if (Command == NULL)
+	      {
+		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+		return -EBUSY;
+	      }
+	    DAC960_ClearCommand(Command);
+	    Command->CommandType = DAC960_QueuedCommand;
+	    memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox,
+		   sizeof(DAC960_CommandMailbox_T));
+	    if (DataTransferBuffer != NULL)
+	      Command->CommandMailbox.Type3.BusAddress =
+		Virtual_to_Bus(DataTransferBuffer);
+	    Command->KernelCommand = KernelCommand;
+	    DAC960_QueueCommand(Command);
+	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+	  }
+	return 0;
+      }
+    }
+  return -EINVAL;
+}
+
+
+/*
+  DAC960_GenericDiskInit is the Generic Disk Information Initialization
+  Function for the DAC960 Driver.
+*/
+
+static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo)
+{
+  DAC960_Controller_T *Controller =
+    (DAC960_Controller_T *) GenericDiskInfo->real_devices;
+  DAC960_LogicalDriveInformation_T *LogicalDriveInformation =
+    Controller->LogicalDriveInformation
+		[Controller->LogicalDriveInformationIndex];
+  int LogicalDriveNumber;
+  for (LogicalDriveNumber = 0;
+       LogicalDriveNumber < Controller->LogicalDriveCount;
+       LogicalDriveNumber++)
+    GenericDiskInfo->part[DAC960_MinorNumber(LogicalDriveNumber, 0)].nr_sects =
+      LogicalDriveInformation[LogicalDriveNumber].LogicalDriveSize;
+}
+
+
+/*
+  DAC960_Message prints Driver Messages.
+*/
+
+static void DAC960_Message(DAC960_MessageLevel_T MessageLevel,
+			   char *Format,
+			   DAC960_Controller_T *Controller,
+			   ...)
+{
+  static char Buffer[DAC960_LineBufferSize];
+  static boolean BeginningOfLine = true;
+  va_list Arguments;
+  int Length = 0;
+  va_start(Arguments, Controller);
+  Length = vsprintf(Buffer, Format, Arguments);
+  va_end(Arguments);
+  if (Controller == NULL)
+    printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+	   DAC960_ControllerCount, Buffer);
+  else if (MessageLevel == DAC960_AnnounceLevel ||
+	   MessageLevel == DAC960_InfoLevel)
+    {
+      if (!Controller->ControllerInitialized)
+	{
+	  strcpy(&Controller->InitialStatusBuffer[
+		    Controller->InitialStatusLength], Buffer);
+	  Controller->InitialStatusLength += Length;
+	  if (MessageLevel == DAC960_AnnounceLevel)
+	    {
+	      static int AnnouncementLines = 0;
+	      if (++AnnouncementLines <= 2)
+		printk("%sDAC960: %s", DAC960_MessageLevelMap[MessageLevel],
+		       Buffer);
+	    }
+	  else
+	    {
+	      if (BeginningOfLine)
+		{
+		  if (Buffer[0] != '\n' || Length > 1)
+		    printk("%sDAC960#%d: %s",
+			   DAC960_MessageLevelMap[MessageLevel],
+			   Controller->ControllerNumber, Buffer);
+		}
+	      else printk("%s", Buffer);
+	    }
+	}
+      else
+	{
+	  strcpy(&Controller->CurrentStatusBuffer[
+		    Controller->CurrentStatusLength], Buffer);
+	  Controller->CurrentStatusLength += Length;
+	}
+    }
+  else if (MessageLevel == DAC960_ProgressLevel)
+    {
+      strcpy(Controller->RebuildProgressBuffer, Buffer);
+      Controller->RebuildProgressLength = Length;
+      if (Controller->EphemeralProgressMessage)
+	{
+	  if (jiffies - Controller->LastProgressReportTime
+	      >= DAC960_ProgressReportingInterval)
+	    {
+	      printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+		     Controller->ControllerNumber, Buffer);
+	      Controller->LastProgressReportTime = jiffies;
+	    }
+	}
+      else printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+		  Controller->ControllerNumber, Buffer);
+    }
+  else if (MessageLevel == DAC960_UserCriticalLevel)
+    {
+      strcpy(&Controller->UserStatusBuffer[Controller->UserStatusLength],
+	     Buffer);
+      Controller->UserStatusLength += Length;
+      if (Buffer[0] != '\n' || Length > 1)
+	printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+	       Controller->ControllerNumber, Buffer);
+    }
+  else
+    {
+      if (BeginningOfLine)
+	printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+	       Controller->ControllerNumber, Buffer);
+      else printk("%s", Buffer);
+    }
+  BeginningOfLine = (Buffer[Length-1] == '\n');
+}
+
+
+/*
+  DAC960_ParsePhysicalDrive parses spaces followed by a Physical Drive
+  Channel:TargetID specification from a User Command string.  It updates
+  Channel and TargetID and returns true on success and returns false otherwise.
+*/
+
+static boolean DAC960_ParsePhysicalDrive(DAC960_Controller_T *Controller,
+					 char *UserCommandString,
+					 unsigned char *Channel,
+					 unsigned char *TargetID)
+{
+  char *NewUserCommandString = UserCommandString;
+  unsigned long XChannel, XTargetID;
+  while (*UserCommandString == ' ') UserCommandString++;
+  if (UserCommandString == NewUserCommandString)
+    return false;
+  XChannel = simple_strtoul(UserCommandString, &NewUserCommandString, 10);
+  if (NewUserCommandString == UserCommandString ||
+      *NewUserCommandString != ':' ||
+      XChannel >= Controller->Channels)
+    return false;
+  UserCommandString = ++NewUserCommandString;
+  XTargetID = simple_strtoul(UserCommandString, &NewUserCommandString, 10);
+  if (NewUserCommandString == UserCommandString ||
+      *NewUserCommandString != '\0' ||
+      XTargetID >= DAC960_MaxTargets)
+    return false;
+  *Channel = XChannel;
+  *TargetID = XTargetID;
+  return true;
+}
+
+
+/*
+  DAC960_ParseLogicalDrive parses spaces followed by a Logical Drive Number
+  specification from a User Command string.  It updates LogicalDriveNumber and
+  returns true on success and returns false otherwise.
+*/
+
+static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller,
+					char *UserCommandString,
+					unsigned char *LogicalDriveNumber)
+{
+  char *NewUserCommandString = UserCommandString;
+  unsigned long XLogicalDriveNumber;
+  while (*UserCommandString == ' ') UserCommandString++;
+  if (UserCommandString == NewUserCommandString)
+    return false;
+  XLogicalDriveNumber =
+    simple_strtoul(UserCommandString, &NewUserCommandString, 10);
+  if (NewUserCommandString == UserCommandString ||
+      *NewUserCommandString != '\0' ||
+      XLogicalDriveNumber >= Controller->LogicalDriveCount)
+    return false;
+  *LogicalDriveNumber = XLogicalDriveNumber;
+  return true;
+}
+
+
+/*
+  DAC960_SetDeviceState sets the Device State for a Physical Drive.
+*/
+
+static void DAC960_SetDeviceState(DAC960_Controller_T *Controller,
+				  DAC960_Command_T *Command,
+				  unsigned char Channel,
+				  unsigned char TargetID,
+				  DAC960_PhysicalDeviceState_T DeviceState,
+				  const char *DeviceStateString)
+{
+  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+  CommandMailbox->Type3D.CommandOpcode = DAC960_StartDevice;
+  CommandMailbox->Type3D.Channel = Channel;
+  CommandMailbox->Type3D.TargetID = TargetID;
+  CommandMailbox->Type3D.DeviceState = DeviceState;
+  CommandMailbox->Type3D.Modifier = 0;
+  DAC960_ExecuteCommand(Command);
+  switch (Command->CommandStatus)
+    {
+    case DAC960_NormalCompletion:
+      DAC960_UserCritical("%s of Physical Drive %d:%d Succeeded\n", Controller,
+			  DeviceStateString, Channel, TargetID);
+      break;
+    case DAC960_UnableToStartDevice:
+      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+			  "Unable to Start Device\n", Controller,
+			  DeviceStateString, Channel, TargetID);
+      break;
+    case DAC960_NoDeviceAtAddress:
+      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+			  "No Device at Address\n", Controller,
+			  DeviceStateString, Channel, TargetID);
+      break;
+    case DAC960_InvalidChannelOrTargetOrModifier:
+      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+			  "Invalid Channel or Target or Modifier\n",
+			  Controller, DeviceStateString, Channel, TargetID);
+      break;
+    case DAC960_ChannelBusy:
+      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+			  "Channel Busy\n", Controller,
+			  DeviceStateString, Channel, TargetID);
+      break;
+    default:
+      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+			  "Unexpected Status %04X\n", Controller,
+			  DeviceStateString, Channel, TargetID,
+			  Command->CommandStatus);
+      break;
+    }
+}
+
+
+/*
+  DAC960_ExecuteUserCommand executes a User Command.
+*/
+
+static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller,
+					 char *UserCommand)
+{
+  DAC960_Command_T *Command;
+  DAC960_CommandMailbox_T *CommandMailbox;
+  ProcessorFlags_T ProcessorFlags;
+  unsigned char Channel, TargetID, LogicalDriveNumber;
+  while (true)
+    {
+      DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+      Command = DAC960_AllocateCommand(Controller);
+      DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+      if (Command != NULL) break;
+      sleep_on(&Controller->CommandWaitQueue);
+    }
+  Controller->UserStatusLength = 0;
+  DAC960_ClearCommand(Command);
+  Command->CommandType = DAC960_ImmediateCommand;
+  CommandMailbox = &Command->CommandMailbox;
+  if (strcmp(UserCommand, "flush-cache") == 0)
+    {
+      CommandMailbox->Type3.CommandOpcode = DAC960_Flush;
+      DAC960_ExecuteCommand(Command);
+      DAC960_UserCritical("Cache Flush Completed\n", Controller);
+    }
+  else if (strncmp(UserCommand, "kill", 4) == 0 &&
+	   DAC960_ParsePhysicalDrive(Controller, &UserCommand[4],
+				     &Channel, &TargetID))
+    {
+      DAC960_DeviceState_T *DeviceState =
+	&Controller->DeviceState[Controller->DeviceStateIndex]
+				[Channel][TargetID];
+      if (DeviceState->Present &&
+	  DeviceState->DeviceType == DAC960_DiskType &&
+	  DeviceState->DeviceState != DAC960_Device_Dead)
+	DAC960_SetDeviceState(Controller, Command, Channel, TargetID,
+			      DAC960_Device_Dead, "Kill");
+      else DAC960_UserCritical("Kill of Physical Drive %d:%d Illegal\n",
+			       Controller, Channel, TargetID);
+    }
+  else if (strncmp(UserCommand, "make-online", 11) == 0 &&
+	   DAC960_ParsePhysicalDrive(Controller, &UserCommand[11],
+				     &Channel, &TargetID))
+    {
+      DAC960_DeviceState_T *DeviceState =
+	&Controller->DeviceState[Controller->DeviceStateIndex]
+				[Channel][TargetID];
+      if (DeviceState->Present &&
+	  DeviceState->DeviceType == DAC960_DiskType &&
+	  DeviceState->DeviceState == DAC960_Device_Dead)
+	DAC960_SetDeviceState(Controller, Command, Channel, TargetID,
+			      DAC960_Device_Online, "Make Online");
+      else DAC960_UserCritical("Make Online of Physical Drive %d:%d Illegal\n",
+			       Controller, Channel, TargetID);
+
+    }
+  else if (strncmp(UserCommand, "make-standby", 12) == 0 &&
+	   DAC960_ParsePhysicalDrive(Controller, &UserCommand[12],
+				     &Channel, &TargetID))
+    {
+      DAC960_DeviceState_T *DeviceState =
+	&Controller->DeviceState[Controller->DeviceStateIndex]
+				[Channel][TargetID];
+      if (DeviceState->Present &&
+	  DeviceState->DeviceType == DAC960_DiskType &&
+	  DeviceState->DeviceState == DAC960_Device_Dead)
+	DAC960_SetDeviceState(Controller, Command, Channel, TargetID,
+			      DAC960_Device_Standby, "Make Standby");
+      else DAC960_UserCritical("Make Standby of Physical Drive %d:%d Illegal\n",
+			       Controller, Channel, TargetID);
+    }
+  else if (strncmp(UserCommand, "rebuild", 7) == 0 &&
+	   DAC960_ParsePhysicalDrive(Controller, &UserCommand[7],
+				     &Channel, &TargetID))
+    {
+      CommandMailbox->Type3D.CommandOpcode = DAC960_RebuildAsync;
+      CommandMailbox->Type3D.Channel = Channel;
+      CommandMailbox->Type3D.TargetID = TargetID;
+      DAC960_ExecuteCommand(Command);
+      switch (Command->CommandStatus)
+	{
+	case DAC960_NormalCompletion:
+	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Initiated\n",
+			      Controller, Channel, TargetID);
+	  break;
+	case DAC960_AttemptToRebuildOnlineDrive:
+	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+			      "Attempt to Rebuild Online or "
+			      "Unresponsive Drive\n",
+			      Controller, Channel, TargetID);
+	  break;
+	case DAC960_NewDiskFailedDuringRebuild:
+	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+			      "New Disk Failed During Rebuild\n",
+			      Controller, Channel, TargetID);
+	  break;
+	case DAC960_InvalidDeviceAddress:
+	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+			      "Invalid Device Address\n",
+			      Controller, Channel, TargetID);
+	  break;
+	case DAC960_RebuildOrCheckAlreadyInProgress:
+	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+			      "Rebuild or Consistency Check Already "
+			      "in Progress\n", Controller, Channel, TargetID);
+	  break;
+	default:
+	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+			      "Unexpected Status %04X\n", Controller,
+			      Channel, TargetID, Command->CommandStatus);
+	  break;
+	}
+    }
+  else if (strncmp(UserCommand, "check-consistency", 17) == 0 &&
+	   DAC960_ParseLogicalDrive(Controller, &UserCommand[17],
+				    &LogicalDriveNumber))
+    {
+      CommandMailbox->Type3C.CommandOpcode = DAC960_CheckConsistencyAsync;
+      CommandMailbox->Type3C.LogicalDriveNumber = LogicalDriveNumber;
+      CommandMailbox->Type3C.AutoRestore = true;
+      DAC960_ExecuteCommand(Command);
+      switch (Command->CommandStatus)
+	{
+	case DAC960_NormalCompletion:
+	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
+			      "(/dev/rd/c%dd%d) Initiated\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber);
+	  break;
+	case DAC960_DependentDiskIsDead:
+	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
+			      "(/dev/rd/c%dd%d) Failed - "
+			      "Dependent Physical Drive is DEAD\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber);
+	  break;
+	case DAC960_InvalidOrNonredundantLogicalDrive:
+	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
+			      "(/dev/rd/c%dd%d) Failed - "
+			      "Invalid or Nonredundant Logical Drive\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber);
+	  break;
+	case DAC960_RebuildOrCheckAlreadyInProgress:
+	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
+			      "(/dev/rd/c%dd%d) Failed - Rebuild or "
+			      "Consistency Check Already in Progress\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber);
+	  break;
+	default:
+	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
+			      "(/dev/rd/c%dd%d) Failed - "
+			      "Unexpected Status %04X\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber, Command->CommandStatus);
+	  break;
+	}
+    }
+  else if (strcmp(UserCommand, "cancel-rebuild") == 0 ||
+	   strcmp(UserCommand, "cancel-consistency-check") == 0)
+    {
+      unsigned char OldRebuildRateConstant;
+      CommandMailbox->Type3R.CommandOpcode = DAC960_RebuildControl;
+      CommandMailbox->Type3R.RebuildRateConstant = 0xFF;
+      CommandMailbox->Type3R.BusAddress =
+	Virtual_to_Bus(&OldRebuildRateConstant);
+      DAC960_ExecuteCommand(Command);
+      switch (Command->CommandStatus)
+	{
+	case DAC960_NormalCompletion:
+	  DAC960_UserCritical("Rebuild or Consistency Check Cancelled\n",
+			      Controller);
+	  break;
+	default:
+	  DAC960_UserCritical("Cancellation of Rebuild or "
+			      "Consistency Check Failed - "
+			      "Unexpected Status %04X\n",
+			      Controller, Command->CommandStatus);
+	  break;
+	}
+    }
+  else DAC960_UserCritical("Illegal User Command: '%s'\n",
+			   Controller, UserCommand);
+  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+  DAC960_DeallocateCommand(Command);
+  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+  return true;
+}
+
+
+/*
+  DAC960_ProcReadStatus implements reading /proc/rd/status.
+*/
+
+static int DAC960_ProcReadStatus(char *Page, char **Start, off_t Offset,
+				 int Count, int *EOF, void *Data)
+{
+  char *StatusMessage = "OK\n";
+  int ControllerNumber, BytesAvailable;
+  for (ControllerNumber = 0;
+       ControllerNumber < DAC960_ControllerCount;
+       ControllerNumber++)
+    {
+      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+      DAC960_Enquiry_T *Enquiry;
+      if (Controller == NULL) continue;
+      Enquiry = &Controller->Enquiry[Controller->EnquiryIndex];
+      if (Enquiry->CriticalLogicalDriveCount > 0 ||
+	  Enquiry->OfflineLogicalDriveCount > 0 ||
+	  Enquiry->DeadDriveCount > 0)
+	{
+	  StatusMessage = "ALERT\n";
+	  break;
+	}
+    }
+  BytesAvailable = strlen(StatusMessage) - Offset;
+  if (Count >= BytesAvailable)
+    {
+      Count = BytesAvailable;
+      *EOF = true;
+    }
+  if (Count <= 0) return 0;
+  *Start = Page;
+  memcpy(Page, &StatusMessage[Offset], Count);
+  return Count;
+}
+
+
+/*
+  DAC960_ProcReadInitialStatus implements reading /proc/rd/cN/initial_status.
+*/
+
+static int DAC960_ProcReadInitialStatus(char *Page, char **Start, off_t Offset,
+					int Count, int *EOF, void *Data)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
+  int BytesAvailable = Controller->InitialStatusLength - Offset;
+  if (Count >= BytesAvailable)
+    {
+      Count = BytesAvailable;
+      *EOF = true;
+    }
+  if (Count <= 0) return 0;
+  *Start = Page;
+  memcpy(Page, &Controller->InitialStatusBuffer[Offset], Count);
+  return Count;
+}
+
+
+/*
+  DAC960_ProcReadCurrentStatus implements reading /proc/rd/cN/current_status.
+*/
+
+static int DAC960_ProcReadCurrentStatus(char *Page, char **Start, off_t Offset,
+					int Count, int *EOF, void *Data)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
+  int BytesAvailable;
+  if (jiffies != Controller->LastCurrentStatusTime)
+    {
+      Controller->CurrentStatusLength = 0;
+      DAC960_AnnounceDriver(Controller);
+      DAC960_ReportControllerConfiguration(Controller);
+      DAC960_ReportDeviceConfiguration(Controller);
+      Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' ';
+      Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' ';
+      if (Controller->RebuildProgressLength > 0)
+	{
+	  strcpy(&Controller->CurrentStatusBuffer
+			      [Controller->CurrentStatusLength],
+		 Controller->RebuildProgressBuffer);
+	  Controller->CurrentStatusLength += Controller->RebuildProgressLength;
+	}
+      else
+	{
+	  char *StatusMessage = "No Rebuild or Consistency Check in Progress\n";
+	  strcpy(&Controller->CurrentStatusBuffer
+			      [Controller->CurrentStatusLength],
+		 StatusMessage);
+	  Controller->CurrentStatusLength += strlen(StatusMessage);
+	}
+      Controller->LastCurrentStatusTime = jiffies;
+    }
+  BytesAvailable = Controller->CurrentStatusLength - Offset;
+  if (Count >= BytesAvailable)
+    {
+      Count = BytesAvailable;
+      *EOF = true;
+    }
+  if (Count <= 0) return 0;
+  *Start = Page;
+  memcpy(Page, &Controller->CurrentStatusBuffer[Offset], Count);
+  return Count;
+}
+
+
+/*
+  DAC960_ProcReadUserCommand implements reading /proc/rd/cN/user_command.
+*/
+
+static int DAC960_ProcReadUserCommand(char *Page, char **Start, off_t Offset,
+				      int Count, int *EOF, void *Data)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
+  int BytesAvailable = Controller->UserStatusLength - Offset;
+  if (Count >= BytesAvailable)
+    {
+      Count = BytesAvailable;
+      *EOF = true;
+    }
+  if (Count <= 0) return 0;
+  *Start = Page;
+  memcpy(Page, &Controller->UserStatusBuffer[Offset], Count);
+  return Count;
+}
+
+
+/*
+  DAC960_ProcWriteUserCommand implements writing /proc/rd/cN/user_command.
+*/
+
+static int DAC960_ProcWriteUserCommand(File_T *File, const char *Buffer,
+				       unsigned long Count, void *Data)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
+  char CommandBuffer[80];
+  int Length;
+  if (Count > sizeof(CommandBuffer)-1) return -EINVAL;
+  copy_from_user(CommandBuffer, Buffer, Count);
+  CommandBuffer[Count] = '\0';
+  Length = strlen(CommandBuffer);
+  if (CommandBuffer[Length-1] == '\n')
+    CommandBuffer[--Length] = '\0';
+  return (DAC960_ExecuteUserCommand(Controller, CommandBuffer)
+	  ? Count : -EBUSY);
+}
+
+
+/*
+  DAC960_CreateProcEntries creates the /proc/rd/... entries for the DAC960
+  Driver.
+*/
+
+static void DAC960_CreateProcEntries(void)
+{
+  static PROC_DirectoryEntry_T StatusProcEntry;
+  int ControllerNumber;
+  DAC960_ProcDirectoryEntry.name = "rd";
+  DAC960_ProcDirectoryEntry.namelen = strlen(DAC960_ProcDirectoryEntry.name);
+  DAC960_ProcDirectoryEntry.mode = S_IFDIR | S_IRUGO | S_IXUGO;
+  proc_register(&proc_root, &DAC960_ProcDirectoryEntry);
+  StatusProcEntry.name = "status";
+  StatusProcEntry.namelen = strlen(StatusProcEntry.name);
+  StatusProcEntry.mode = S_IFREG | S_IRUGO;
+  StatusProcEntry.read_proc = DAC960_ProcReadStatus;
+  proc_register(&DAC960_ProcDirectoryEntry, &StatusProcEntry);
+  for (ControllerNumber = 0;
+       ControllerNumber < DAC960_ControllerCount;
+       ControllerNumber++)
+    {
+      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+      PROC_DirectoryEntry_T *ControllerProcEntry, *InitialStatusProcEntry;
+      PROC_DirectoryEntry_T *CurrentStatusProcEntry, *UserCommandProcEntry;
+      if (Controller == NULL) continue;
+      ControllerProcEntry = &Controller->ControllerProcEntry;
+      ControllerProcEntry->name = Controller->ControllerName;
+      ControllerProcEntry->namelen = strlen(ControllerProcEntry->name);
+      ControllerProcEntry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+      proc_register(&DAC960_ProcDirectoryEntry, ControllerProcEntry);
+      InitialStatusProcEntry = &Controller->InitialStatusProcEntry;
+      InitialStatusProcEntry->name = "initial_status";
+      InitialStatusProcEntry->namelen = strlen(InitialStatusProcEntry->name);
+      InitialStatusProcEntry->mode = S_IFREG | S_IRUGO;
+      InitialStatusProcEntry->data = Controller;
+      InitialStatusProcEntry->read_proc = DAC960_ProcReadInitialStatus;
+      proc_register(ControllerProcEntry, InitialStatusProcEntry);
+      CurrentStatusProcEntry = &Controller->CurrentStatusProcEntry;
+      CurrentStatusProcEntry->name = "current_status";
+      CurrentStatusProcEntry->namelen = strlen(CurrentStatusProcEntry->name);
+      CurrentStatusProcEntry->mode = S_IFREG | S_IRUGO;
+      CurrentStatusProcEntry->data = Controller;
+      CurrentStatusProcEntry->read_proc = DAC960_ProcReadCurrentStatus;
+      proc_register(ControllerProcEntry, CurrentStatusProcEntry);
+      UserCommandProcEntry = &Controller->UserCommandProcEntry;
+      UserCommandProcEntry->name = "user_command";
+      UserCommandProcEntry->namelen = strlen(UserCommandProcEntry->name);
+      UserCommandProcEntry->mode = S_IFREG | S_IWUSR | S_IRUSR;
+      UserCommandProcEntry->data = Controller;
+      UserCommandProcEntry->read_proc = DAC960_ProcReadUserCommand;
+      UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand;
+      proc_register(ControllerProcEntry, UserCommandProcEntry);
+    }
+}
+
+
+/*
+  DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the DAC960
+  Driver.
+*/
+
+static void DAC960_DestroyProcEntries(void)
+{
+  proc_unregister(&proc_root, DAC960_ProcDirectoryEntry.low_ino);
+}
+
+
+/*
+  Include Module support if requested.
+*/
+
+#ifdef MODULE
+
+
+int init_module(void)
+{
+  int ControllerNumber, LogicalDriveNumber;
+  DAC960_Initialize();
+  if (DAC960_ActiveControllerCount == 0) return -1;
+  for (ControllerNumber = 0;
+       ControllerNumber < DAC960_ControllerCount;
+       ControllerNumber++)
+    {
+      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+      if (Controller == NULL) continue;
+      DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo);
+      for (LogicalDriveNumber = 0;
+	   LogicalDriveNumber < Controller->LogicalDriveCount;
+	   LogicalDriveNumber++)
+	resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
+    }
+  return 0;
+}
+
+
+void cleanup_module(void)
+{
+  DAC960_Finalize(&DAC960_NotifierBlock, SYS_RESTART, NULL);
+}
+
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/drivers/block/DAC960.h linux/drivers/block/DAC960.h
--- v2.3.15/linux/drivers/block/DAC960.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/DAC960.h	Mon Aug 30 10:24:14 1999
@@ -0,0 +1,2244 @@
+/*
+
+  Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers
+
+  Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+
+  This program is free software; you may redistribute and/or modify it under
+  the terms of the GNU General Public License Version 2 as published by the
+  Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
+  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  for complete details.
+
+  The author respectfully requests that any modifications to this software be
+  sent directly to him for evaluation and testing.
+
+*/
+
+
+/*
+  Define the maximum number of DAC960 Controllers supported by this driver.
+*/
+
+#define DAC960_MaxControllers			8
+
+
+/*
+  Define the maximum number of Controller Channels supported by this driver.
+*/
+
+#define DAC960_MaxChannels			3
+
+
+/*
+  Define the maximum number of Targets per Channel supported by this driver.
+*/
+
+#define DAC960_MaxTargets			16
+
+
+/*
+  Define the maximum number of Logical Drives supported by any DAC960 model.
+*/
+
+#define DAC960_MaxLogicalDrives			32
+
+
+/*
+  Define a Boolean data type.
+*/
+
+typedef enum { false, true } __attribute__ ((packed)) boolean;
+
+
+/*
+  Define a 32 bit I/O Address data type.
+*/
+
+typedef unsigned int DAC960_IO_Address_T;
+
+
+/*
+  Define a 32 bit PCI Bus Address data type.
+*/
+
+typedef unsigned int DAC960_PCI_Address_T;
+
+
+/*
+  Define a 32 bit Bus Address data type.
+*/
+
+typedef unsigned int DAC960_BusAddress_T;
+
+
+/*
+  Define a 32 bit Byte Count data type.
+*/
+
+typedef unsigned int DAC960_ByteCount_T;
+
+
+/*
+  Define the DAC960 Command Opcodes.
+*/
+
+typedef enum
+{
+  /* I/O Commands */
+  DAC960_ReadExtended =				0x33,
+  DAC960_WriteExtended =			0x34,
+  DAC960_ReadAheadExtended =			0x35,
+  DAC960_ReadExtendedWithScatterGather =	0xB3,
+  DAC960_WriteExtendedWithScatterGather =	0xB4,
+  DAC960_Read =					0x36,
+  DAC960_ReadWithOldScatterGather =		0xB6,
+  DAC960_Write =				0x37,
+  DAC960_WriteWithOldScatterGather =		0xB7,
+  DAC960_DCDB =					0x04,
+  DAC960_DCDBWithScatterGather =		0x84,
+  DAC960_Flush =				0x0A,
+  /* Controller Status Related Commands */
+  DAC960_Enquiry =				0x53,
+  DAC960_Enquiry2 =				0x1C,
+  DAC960_GetLogicalDriveElement =		0x55,
+  DAC960_GetLogicalDriveInformation =		0x19,
+  DAC960_IOPortRead =				0x39,
+  DAC960_IOPortWrite =				0x3A,
+  DAC960_GetSDStats =				0x3E,
+  DAC960_GetPDStats =				0x3F,
+  DAC960_PerformEventLogOperation =		0x72,
+  /* Device Related Commands */
+  DAC960_StartDevice =				0x10,
+  DAC960_GetDeviceState =			0x50,
+  DAC960_StopChannel =				0x13,
+  DAC960_StartChannel =				0x12,
+  DAC960_ResetChannel =				0x1A,
+  /* Commands Associated with Data Consistency and Errors */
+  DAC960_Rebuild =				0x09,
+  DAC960_RebuildAsync =				0x16,
+  DAC960_CheckConsistency =			0x0F,
+  DAC960_CheckConsistencyAsync =		0x1E,
+  DAC960_RebuildStat =				0x0C,
+  DAC960_GetRebuildProgress =			0x27,
+  DAC960_RebuildControl =			0x1F,
+  DAC960_ReadBadBlockTable =			0x0B,
+  DAC960_ReadBadDataTable =			0x25,
+  DAC960_ClearBadDataTable =			0x26,
+  DAC960_GetErrorTable =			0x17,
+  DAC960_AddCapacityAsync =			0x2A,
+  /* Configuration Related Commands */
+  DAC960_ReadConfig2 =				0x3D,
+  DAC960_WriteConfig2 =				0x3C,
+  DAC960_ReadConfigurationOnDisk =		0x4A,
+  DAC960_WriteConfigurationOnDisk =		0x4B,
+  DAC960_ReadConfiguration =			0x4E,
+  DAC960_ReadBackupConfiguration =		0x4D,
+  DAC960_WriteConfiguration =			0x4F,
+  DAC960_AddConfiguration =			0x4C,
+  DAC960_ReadConfigurationLabel =		0x48,
+  DAC960_WriteConfigurationLabel =		0x49,
+  /* Firmware Upgrade Related Commands */
+  DAC960_LoadImage =				0x20,
+  DAC960_StoreImage =				0x21,
+  DAC960_ProgramImage =				0x22,
+  /* Diagnostic Commands */
+  DAC960_SetDiagnosticMode =			0x31,
+  DAC960_RunDiagnostic =			0x32,
+  /* Subsystem Service Commands */
+  DAC960_GetSubsystemData =			0x70,
+  DAC960_SetSubsystemParameters =		0x71
+}
+__attribute__ ((packed))
+DAC960_CommandOpcode_T;
+
+
+/*
+  Define the DAC960 Command Identifier type.
+*/
+
+typedef unsigned char DAC960_CommandIdentifier_T;
+
+
+/*
+  Define the DAC960 Command Status Codes.
+*/
+
+#define DAC960_NormalCompletion			0x0000	/* Common */
+#define DAC960_CheckConditionReceived		0x0002	/* Common */
+#define DAC960_NoDeviceAtAddress		0x0102	/* Common */
+#define DAC960_InvalidDeviceAddress		0x0105	/* Common */
+#define DAC960_InvalidParameter			0x0105	/* Common */
+#define DAC960_IrrecoverableDataError		0x0001	/* I/O */
+#define DAC960_LogicalDriveNonexistentOrOffline	0x0002	/* I/O */
+#define DAC960_AccessBeyondEndOfLogicalDrive	0x0105	/* I/O */
+#define DAC960_BadDataEncountered		0x010C	/* I/O */
+#define DAC960_DeviceBusy			0x0008	/* DCDB */
+#define DAC960_DeviceNonresponsive		0x000E	/* DCDB */
+#define DAC960_CommandTerminatedAbnormally	0x000F	/* DCDB */
+#define DAC960_UnableToStartDevice		0x0002	/* Device */
+#define DAC960_InvalidChannelOrTargetOrModifier	0x0105	/* Device */
+#define DAC960_ChannelBusy			0x0106	/* Device */
+#define DAC960_ChannelNotStopped		0x0002	/* Device */
+#define DAC960_AttemptToRebuildOnlineDrive	0x0002	/* Consistency */
+#define DAC960_RebuildBadBlocksEncountered	0x0003	/* Consistency */
+#define DAC960_NewDiskFailedDuringRebuild	0x0004	/* Consistency */
+#define DAC960_RebuildOrCheckAlreadyInProgress	0x0106	/* Consistency */
+#define DAC960_DependentDiskIsDead		0x0002	/* Consistency */
+#define DAC960_InconsistentBlocksFound		0x0003	/* Consistency */
+#define DAC960_InvalidOrNonredundantLogicalDrive 0x0105	/* Consistency */
+#define DAC960_NoRebuildOrCheckInProgress	0x0105	/* Consistency */
+#define DAC960_RebuildInProgress_DataValid	0x0000	/* Consistency */
+#define DAC960_RebuildFailed_LogicalDriveFailure 0x0002	/* Consistency */
+#define DAC960_RebuildFailed_BadBlocksOnOther	0x0003	/* Consistency */
+#define DAC960_RebuildFailed_NewDriveFailed	0x0004	/* Consistency */
+#define DAC960_RebuildSuccessful		0x0100	/* Consistency */
+#define DAC960_AddCapacityInProgress		0x0004	/* Consistency */
+#define DAC960_AddCapacityFailedOrSuspended	0x00F4	/* Consistency */
+#define DAC960_Config2ChecksumError		0x0002	/* Configuration */
+#define DAC960_ConfigurationSuspended		0x0106	/* Configuration */
+#define DAC960_FailedToConfigureNVRAM		0x0105	/* Configuration */
+#define DAC960_ConfigurationNotSavedStateChange	0x0106	/* Configuration */
+#define DAC960_SubsystemNotInstalled		0x0001	/* Subsystem */
+#define DAC960_SubsystemFailed			0x0002	/* Subsystem */
+#define DAC960_SubsystemBusy			0x0106	/* Subsystem */
+
+typedef unsigned short DAC960_CommandStatus_T;
+
+
+/*
+  Define the Enquiry reply structure.
+*/
+
+typedef struct DAC960_Enquiry
+{
+  unsigned char NumberOfLogicalDrives;			/* Byte 0 */
+  unsigned int :24;					/* Bytes 1-3 */
+  unsigned int LogicalDriveSizes[32];			/* Bytes 4-131 */
+  unsigned short FlashAge;				/* Bytes 132-133 */
+  struct {
+    boolean DeferredWriteError:1;			/* Byte 134 Bit 0 */
+    boolean BatteryLow:1;				/* Byte 134 Bit 1 */
+    unsigned char :6;					/* Byte 134 Bits 2-7 */
+  } StatusFlags;
+  unsigned char :8;					/* Byte 135 */
+  unsigned char MinorFirmwareVersion;			/* Byte 136 */
+  unsigned char MajorFirmwareVersion;			/* Byte 137 */
+  enum {
+    DAC960_NoStandbyRebuildOrCheckInProgress =			0x00,
+    DAC960_StandbyRebuildInProgress =				0x01,
+    DAC960_BackgroundRebuildInProgress =			0x02,
+    DAC960_BackgroundCheckInProgress =				0x03,
+    DAC960_StandbyRebuildCompletedWithError =			0xFF,
+    DAC960_BackgroundRebuildOrCheckFailed_DriveFailed =		0xF0,
+    DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed =	0xF1,
+    DAC960_BackgroundRebuildOrCheckFailed_OtherCauses =		0xF2,
+    DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated =	0xF3
+  } __attribute__ ((packed)) RebuildFlag;		/* Byte 138 */
+  unsigned char MaxCommands;				/* Byte 139 */
+  unsigned char OfflineLogicalDriveCount;		/* Byte 140 */
+  unsigned char :8;					/* Byte 141 */
+  unsigned short EventLogSequenceNumber;		/* Bytes 142-143 */
+  unsigned char CriticalLogicalDriveCount;		/* Byte 144 */
+  unsigned int :24;					/* Bytes 145-147 */
+  unsigned char DeadDriveCount;				/* Byte 148 */
+  unsigned char :8;					/* Byte 149 */
+  unsigned char RebuildCount;				/* Byte 150 */
+  struct {
+    unsigned char :3;					/* Byte 151 Bits 0-2 */
+    boolean BatteryBackupUnitPresent:1;			/* Byte 151 Bit 3 */
+    unsigned char :3;					/* Byte 151 Bits 4-6 */
+    unsigned char :1;					/* Byte 151 Bit 7 */
+  } MiscFlags;
+  struct {
+    unsigned char TargetID;
+    unsigned char Channel;
+  } DeadDrives[21];					/* Bytes 152-194 */
+  unsigned char Reserved[62];				/* Bytes 195-255 */
+}
+__attribute__ ((packed))
+DAC960_Enquiry_T;
+
+
+/*
+  Define the Enquiry2 reply structure.
+*/
+
+typedef struct DAC960_Enquiry2
+{
+  struct {
+    enum {
+      DAC960_P_PD_PU =				0x01,
+      DAC960_PL =				0x02,
+      DAC960_PG =				0x10,
+      DAC960_PJ =				0x11,
+      DAC960_PR =				0x12,
+      DAC960_PT =				0x13,
+      DAC960_PTL0 =				0x14,
+      DAC960_PRL =				0x15,
+      DAC960_PTL1 =				0x16,
+      DAC1164_P =				0x20
+    } __attribute__ ((packed)) SubModel;		/* Byte 0 */
+    unsigned char ActualChannels;			/* Byte 1 */
+    enum {
+      DAC960_FiveChannelBoard =			0x01,
+      DAC960_ThreeChannelBoard =		0x02,
+      DAC960_TwoChannelBoard =			0x03,
+      DAC960_ThreeChannelASIC_DAC =		0x04
+    } __attribute__ ((packed)) Model;			/* Byte 2 */
+    enum {
+      DAC960_EISA_Controller =			0x01,
+      DAC960_MicroChannel_Controller =		0x02,
+      DAC960_PCI_Controller =			0x03,
+      DAC960_SCSItoSCSI_Controller =		0x08
+    } __attribute__ ((packed)) ProductFamily;		/* Byte 3 */
+  } HardwareID;						/* Bytes 0-3 */
+  /* MajorVersion.MinorVersion-FirmwareType-TurnID */
+  struct {
+    unsigned char MajorVersion;				/* Byte 4 */
+    unsigned char MinorVersion;				/* Byte 5 */
+    unsigned char TurnID;				/* Byte 6 */
+    char FirmwareType;					/* Byte 7 */
+  } FirmwareID;						/* Bytes 4-7 */
+  unsigned char :8;					/* Byte 8 */
+  unsigned int :24;					/* Bytes 9-11 */
+  unsigned char ConfiguredChannels;			/* Byte 12 */
+  unsigned char ActualChannels;				/* Byte 13 */
+  unsigned char MaxTargets;				/* Byte 14 */
+  unsigned char MaxTags;				/* Byte 15 */
+  unsigned char MaxLogicalDrives;			/* Byte 16 */
+  unsigned char MaxArms;				/* Byte 17 */
+  unsigned char MaxSpans;				/* Byte 18 */
+  unsigned char :8;					/* Byte 19 */
+  unsigned int :32;					/* Bytes 20-23 */
+  unsigned int MemorySize;				/* Bytes 24-27 */
+  unsigned int CacheSize;				/* Bytes 28-31 */
+  unsigned int FlashMemorySize;				/* Bytes 32-35 */
+  unsigned int NonVolatileMemorySize;			/* Bytes 36-39 */
+  struct {
+    enum {
+      DAC960_DRAM =				0x00,
+      DAC960_EDO =				0x01,
+      DAC960_SDRAM =				0x02
+    } __attribute__ ((packed)) RamType:3;		/* Byte 40 Bits 0-2 */
+    enum {
+      DAC960_None =				0x00,
+      DAC960_Parity =				0x01,
+      DAC960_ECC =				0x02
+    } __attribute__ ((packed)) ErrorCorrection:3;	/* Byte 40 Bits 3-5 */
+    boolean FastPageMode:1;				/* Byte 40 Bit 6 */
+    boolean LowPowerMemory:1;				/* Byte 40 Bit 7 */
+    unsigned char :8;					/* Bytes 41 */
+  } MemoryType;
+  unsigned short ClockSpeed;				/* Bytes 42-43 */
+  unsigned short MemorySpeed;				/* Bytes 44-45 */
+  unsigned short HardwareSpeed;				/* Bytes 46-47 */
+  unsigned int :32;					/* Bytes 48-51 */
+  unsigned int :32;					/* Bytes 52-55 */
+  unsigned char :8;					/* Byte 56 */
+  unsigned char :8;					/* Byte 57 */
+  unsigned short :16;					/* Bytes 58-59 */
+  unsigned short MaxCommands;				/* Bytes 60-61 */
+  unsigned short MaxScatterGatherEntries;		/* Bytes 62-63 */
+  unsigned short MaxDriveCommands;			/* Bytes 64-65 */
+  unsigned short MaxIODescriptors;			/* Bytes 66-67 */
+  unsigned short MaxCombinedSectors;			/* Bytes 68-69 */
+  unsigned char Latency;				/* Byte 70 */
+  unsigned char :8;					/* Byte 71 */
+  unsigned char SCSITimeout;				/* Byte 72 */
+  unsigned char :8;					/* Byte 73 */
+  unsigned short MinFreeLines;				/* Bytes 74-75 */
+  unsigned int :32;					/* Bytes 76-79 */
+  unsigned int :32;					/* Bytes 80-83 */
+  unsigned char RebuildRateConstant;			/* Byte 84 */
+  unsigned char :8;					/* Byte 85 */
+  unsigned char :8;					/* Byte 86 */
+  unsigned char :8;					/* Byte 87 */
+  unsigned int :32;					/* Bytes 88-91 */
+  unsigned int :32;					/* Bytes 92-95 */
+  unsigned short PhysicalDriveBlockSize;		/* Bytes 96-97 */
+  unsigned short LogicalDriveBlockSize;			/* Bytes 98-99 */
+  unsigned short MaxBlocksPerCommand;			/* Bytes 100-101 */
+  unsigned short BlockFactor;				/* Bytes 102-103 */
+  unsigned short CacheLineSize;				/* Bytes 104-105 */
+  struct {
+    enum {
+      DAC960_Narrow_8bit =			0x00,
+      DAC960_Wide_16bit =			0x01,
+      DAC960_Wide_32bit =			0x02
+    } __attribute__ ((packed)) BusWidth:2;		/* Byte 106 Bits 0-1 */
+    enum {
+      DAC960_Fast =				0x00,
+      DAC960_Ultra =				0x01,
+      DAC960_Ultra2 =				0x02
+    } __attribute__ ((packed)) BusSpeed:2;		/* Byte 106 Bits 2-3 */
+    boolean Differential:1;				/* Byte 106 Bit 4 */
+    unsigned char :3;					/* Byte 106 Bits 5-7 */
+  } SCSICapability;
+  unsigned char :8;					/* Byte 107 */
+  unsigned int :32;					/* Bytes 108-111 */
+  unsigned short FirmwareBuildNumber;			/* Bytes 112-113 */
+  enum {
+    DAC960_AEMI =				0x01,
+    DAC960_OEM1 =				0x02,
+    DAC960_OEM2 =				0x04,
+    DAC960_OEM3 =				0x08,
+    DAC960_Conner =				0x10,
+    DAC960_SAFTE =				0x20
+  } __attribute__ ((packed)) FaultManagementType;	/* Byte 114 */
+  unsigned char :8;					/* Byte 115 */
+  struct {
+    boolean Clustering:1;				/* Byte 116 Bit 0 */
+    boolean MylexOnlineRAIDExpansion:1;			/* Byte 116 Bit 1 */
+    unsigned int :30;					/* Bytes 116-119 */
+  } FirmwareFeatures;
+  unsigned int :32;					/* Bytes 120-123 */
+  unsigned int :32;					/* Bytes 124-127 */
+}
+DAC960_Enquiry2_T;
+
+
+/*
+  Define the Logical Drive State type.
+*/
+
+typedef enum
+{
+    DAC960_LogicalDrive_Online =		0x03,
+    DAC960_LogicalDrive_Critical =		0x04,
+    DAC960_LogicalDrive_Offline =		0xFF
+}
+__attribute__ ((packed))
+DAC960_LogicalDriveState_T;
+
+
+/*
+  Define the Get Logical Drive Information reply structure.
+*/
+
+typedef struct DAC960_LogicalDriveInformation
+{
+  unsigned int LogicalDriveSize;			/* Bytes 0-3 */
+  DAC960_LogicalDriveState_T LogicalDriveState;		/* Byte 4 */
+  unsigned char RAIDLevel:7;				/* Byte 5 Bits 0-6 */
+  boolean WriteBack:1;					/* Byte 5 Bit 7 */
+  unsigned int :16;					/* Bytes 6-7 */
+}
+DAC960_LogicalDriveInformation_T;
+
+
+/*
+  Define the Perform Event Log Operation Types.
+*/
+
+typedef enum
+{
+  DAC960_GetEventLogEntry =			0x00
+}
+__attribute__ ((packed))
+DAC960_PerformEventLogOpType_T;
+
+
+/*
+  Define the Get Event Log Entry reply structure.
+*/
+
+typedef struct DAC960_EventLogEntry
+{
+  unsigned char MessageType;				/* Byte 0 */
+  unsigned char MessageLength;				/* Byte 1 */
+  unsigned char TargetID:5;				/* Byte 2 Bits 0-4 */
+  unsigned char Channel:3;				/* Byte 2 Bits 5-7 */
+  unsigned char LogicalUnit:6;				/* Byte 3 Bits 0-5 */
+  unsigned char :2;					/* Byte 3 Bits 6-7 */
+  unsigned short SequenceNumber;			/* Bytes 4-5 */
+  unsigned char ErrorCode:7;				/* Byte 6 Bits 0-6 */
+  boolean Valid:1;					/* Byte 6 Bit 7 */
+  unsigned char SegmentNumber;				/* Byte 7 */
+  unsigned char SenseKey:4;				/* Byte 8 Bits 0-3 */
+  unsigned char :1;					/* Byte 8 Bit 4 */
+  boolean ILI:1;					/* Byte 8 Bit 5 */
+  boolean EOM:1;					/* Byte 8 Bit 6 */
+  boolean Filemark:1;					/* Byte 8 Bit 7 */
+  unsigned char Information[4];				/* Bytes 9-12 */
+  unsigned char AdditionalSenseLength;			/* Byte 13 */
+  unsigned char CommandSpecificInformation[4];		/* Bytes 14-17 */
+  unsigned char AdditionalSenseCode;			/* Byte 18 */
+  unsigned char AdditionalSenseCodeQualifier;		/* Byte 19 */
+  unsigned char Dummy[12];				/* Bytes 20-31 */
+}
+DAC960_EventLogEntry_T;
+
+
+/*
+  Define the Physical Device State type.
+*/
+
+typedef enum
+{
+    DAC960_Device_Dead =			0x00,
+    DAC960_Device_WriteOnly =			0x02,
+    DAC960_Device_Online =			0x03,
+    DAC960_Device_Standby =			0x10
+}
+__attribute__ ((packed))
+DAC960_PhysicalDeviceState_T;
+
+
+/*
+  Define the Get Device State reply structure.
+*/
+
+typedef struct DAC960_DeviceState
+{
+  boolean Present:1;					/* Byte 0 Bit 0 */
+  unsigned char :7;					/* Byte 0 Bits 1-7 */
+  enum {
+    DAC960_OtherType =				0x00,
+    DAC960_DiskType =				0x01,
+    DAC960_SequentialType =			0x02,
+    DAC960_CDROM_or_WORM_Type =			0x03
+    } __attribute__ ((packed)) DeviceType:2;		/* Byte 1 Bits 0-1 */
+  boolean :1;						/* Byte 1 Bit 2 */
+  boolean Fast20:1;					/* Byte 1 Bit 3 */
+  boolean Sync:1;					/* Byte 1 Bit 4 */
+  boolean Fast:1;					/* Byte 1 Bit 5 */
+  boolean Wide:1;					/* Byte 1 Bit 6 */
+  boolean TaggedQueuingSupported:1;			/* Byte 1 Bit 7 */
+  DAC960_PhysicalDeviceState_T DeviceState;		/* Byte 2 */
+  unsigned char :8;					/* Byte 3 */
+  unsigned char SynchronousMultiplier;			/* Byte 4 */
+  unsigned char SynchronousOffset:5;			/* Byte 5 Bits 0-4 */
+  unsigned char :3;					/* Byte 5 Bits 5-7 */
+  unsigned long DiskSize __attribute__ ((packed));	/* Bytes 6-9 */
+}
+DAC960_DeviceState_T;
+
+
+/*
+  Define the Get Rebuild Progress reply structure.
+*/
+
+typedef struct DAC960_RebuildProgress
+{
+  unsigned int LogicalDriveNumber;			/* Bytes 0-3 */
+  unsigned int LogicalDriveSize;			/* Bytes 4-7 */
+  unsigned int RemainingBlocks;				/* Bytes 8-11 */
+}
+DAC960_RebuildProgress_T;
+
+
+/*
+  Define the Error Table Entry and Get Error Table reply structure.
+*/
+
+typedef struct DAC960_ErrorTableEntry
+{
+  unsigned char ParityErrorCount;			/* Byte 0 */
+  unsigned char SoftErrorCount;				/* Byte 1 */
+  unsigned char HardErrorCount;				/* Byte 2 */
+  unsigned char MiscErrorCount;				/* Byte 3 */
+}
+DAC960_ErrorTableEntry_T;
+
+
+/*
+  Define the Get Error Table reply structure.
+*/
+
+typedef struct DAC960_ErrorTable
+{
+  DAC960_ErrorTableEntry_T
+    ErrorTableEntries[DAC960_MaxChannels][DAC960_MaxTargets];
+}
+DAC960_ErrorTable_T;
+
+
+/*
+  Define the Config2 reply structure.
+*/
+
+typedef struct DAC960_Config2
+{
+  unsigned char :1;					/* Byte 0 Bit 0 */
+  boolean ActiveNegationEnabled:1;			/* Byte 0 Bit 1 */
+  unsigned char :5;					/* Byte 0 Bits 2-6 */
+  boolean NoRescanIfResetReceivedDuringScan:1;		/* Byte 0 Bit 7 */
+  boolean StorageWorksSupportEnabled:1;			/* Byte 1 Bit 0 */
+  boolean HewlettPackardSupportEnabled:1;		/* Byte 1 Bit 1 */
+  boolean NoDisconnectOnFirstCommand:1;			/* Byte 1 Bit 2 */
+  unsigned char :2;					/* Byte 1 Bits 3-4 */
+  boolean AEMI_ARM:1;					/* Byte 1 Bit 5 */
+  boolean AEMI_OFM:1;					/* Byte 1 Bit 6 */
+  unsigned char :1;					/* Byte 1 Bit 7 */
+  enum {
+    DAC960_OEMID_Mylex =			0x00,
+    DAC960_OEMID_IBM =				0x08,
+    DAC960_OEMID_HP =				0x0A,
+    DAC960_OEMID_DEC =				0x0C,
+    DAC960_OEMID_Siemens =			0x10,
+    DAC960_OEMID_Intel =			0x12
+  } __attribute__ ((packed)) OEMID;			/* Byte 2 */
+  unsigned char OEMModelNumber;				/* Byte 3 */
+  unsigned char PhysicalSector;				/* Byte 4 */
+  unsigned char LogicalSector;				/* Byte 5 */
+  unsigned char BlockFactor;				/* Byte 6 */
+  boolean ReadAheadEnabled:1;				/* Byte 7 Bit 0 */
+  boolean LowBIOSDelay:1;				/* Byte 7 Bit 1 */
+  unsigned char :2;					/* Byte 7 Bits 2-3 */
+  boolean ReassignRestrictedToOneSector:1;		/* Byte 7 Bit 4 */
+  unsigned char :1;					/* Byte 7 Bit 5 */
+  boolean ForceUnitAccessDuringWriteRecovery:1;		/* Byte 7 Bit 6 */
+  boolean EnableLeftSymmetricRAID5Algorithm:1;		/* Byte 7 Bit 7 */
+  unsigned char DefaultRebuildRate;			/* Byte 8 */
+  unsigned char :8;					/* Byte 9 */
+  unsigned char BlocksPerCacheLine;			/* Byte 10 */
+  unsigned char BlocksPerStripe;			/* Byte 11 */
+  struct {
+    enum {
+      DAC960_Async =				0x00,
+      DAC960_Sync_8MHz =			0x01,
+      DAC960_Sync_5MHz =			0x02,
+      DAC960_Sync_10or20MHz =			0x03	/* Bits 0-1 */
+    } __attribute__ ((packed)) Speed:2;
+    boolean Force8Bit:1;				/* Bit 2 */
+    boolean DisableFast20:1;				/* Bit 3 */
+    unsigned char :3;					/* Bits 4-6 */
+    boolean EnableTaggedQueuing:1;			/* Bit 7 */
+  } __attribute__ ((packed)) ChannelParameters[6];	/* Bytes 12-17 */
+  unsigned char SCSIInitiatorID;			/* Byte 18 */
+  unsigned char :8;					/* Byte 19 */
+  enum {
+    DAC960_StartupMode_ControllerSpinUp =	0x00,
+    DAC960_StartupMode_PowerOnSpinUp =		0x01
+  } __attribute__ ((packed)) StartupMode;		/* Byte 20 */
+  unsigned char SimultaneousDeviceSpinUpCount;		/* Byte 21 */
+  unsigned char SecondsDelayBetweenSpinUps;		/* Byte 22 */
+  unsigned char Reserved1[29];				/* Bytes 23-51 */
+  boolean BIOSDisabled:1;				/* Byte 52 Bit 0 */
+  boolean CDROMBootEnabled:1;				/* Byte 52 Bit 1 */
+  unsigned char :3;					/* Byte 52 Bits 2-4 */
+  enum {
+    DAC960_Geometry_128_32 =			0x00,
+    DAC960_Geometry_255_63 =			0x01,
+    DAC960_Geometry_Reserved1 =			0x02,
+    DAC960_Geometry_Reserved2 =			0x03
+  } __attribute__ ((packed)) DriveGeometry:2;		/* Byte 52 Bits 5-6 */
+  unsigned char :1;					/* Byte 52 Bit 7 */
+  unsigned char Reserved2[9];				/* Bytes 53-61 */
+  unsigned short Checksum;				/* Bytes 62-63 */
+}
+DAC960_Config2_T;
+
+
+/*
+  Define the DCDB request structure.
+*/
+
+typedef struct DAC960_DCDB
+{
+  unsigned char TargetID:4;				 /* Byte 0 Bits 0-3 */
+  unsigned char Channel:4;				 /* Byte 0 Bits 4-7 */
+  enum {
+    DAC960_DCDB_NoDataTransfer = 0,
+    DAC960_DCDB_DataTransferDeviceToSystem = 1,
+    DAC960_DCDB_DataTransferSystemToDevice = 2,
+    DAC960_DCDB_IllegalDataTransfer = 3
+  } __attribute__ ((packed)) Direction:2;		 /* Byte 1 Bits 0-1 */
+  boolean EarlyStatus:1;				 /* Byte 1 Bit 2 */
+  unsigned char :1;					 /* Byte 1 Bit 3 */
+  enum {
+    DAC960_DCDB_Timeout_24_hours = 0,
+    DAC960_DCDB_Timeout_10_seconds = 1,
+    DAC960_DCDB_Timeout_60_seconds = 2,
+    DAC960_DCDB_Timeout_10_minutes = 3
+  } __attribute__ ((packed)) Timeout:2;			 /* Byte 1 Bits 4-5 */
+  boolean NoAutomaticRequestSense:1;			 /* Byte 1 Bit 6 */
+  boolean DisconnectPermitted:1;			 /* Byte 1 Bit 7 */
+  unsigned short TransferLength;			 /* Bytes 2-3 */
+  DAC960_BusAddress_T BusAddress;			 /* Bytes 4-7 */
+  unsigned char CDBLength:4;				 /* Byte 8 Bits 0-3 */
+  unsigned char TransferLengthHigh4:4;			 /* Byte 8 Bits 4-7 */
+  unsigned char SenseLength;				 /* Byte 9 */
+  unsigned char CDB[12];				 /* Bytes 10-21 */
+  unsigned char SenseData[64];				 /* Bytes 22-85 */
+  unsigned char Status;					 /* Byte 86 */
+  unsigned char :8;					 /* Byte 87 */
+}
+DAC960_DCDB_T;
+
+
+/*
+  Define the SCSI INQUIRY Standard Data reply structure.
+*/
+
+typedef struct DAC960_SCSI_Inquiry
+{
+  unsigned char PeripheralDeviceType:5;			/* Byte 0 Bits 0-4 */
+  unsigned char PeripheralQualifier:3;			/* Byte 0 Bits 5-7 */
+  unsigned char DeviceTypeModifier:7;			/* Byte 1 Bits 0-6 */
+  boolean RMB:1;					/* Byte 1 Bit 7 */
+  unsigned char ANSI_ApprovedVersion:3;			/* Byte 2 Bits 0-2 */
+  unsigned char ECMA_Version:3;				/* Byte 2 Bits 3-5 */
+  unsigned char ISO_Version:2;				/* Byte 2 Bits 6-7 */
+  unsigned char ResponseDataFormat:4;			/* Byte 3 Bits 0-3 */
+  unsigned char :2;					/* Byte 3 Bits 4-5 */
+  boolean TrmIOP:1;					/* Byte 3 Bit 6 */
+  boolean AENC:1;					/* Byte 3 Bit 7 */
+  unsigned char AdditionalLength;			/* Byte 4 */
+  unsigned char :8;					/* Byte 5 */
+  unsigned char :8;					/* Byte 6 */
+  boolean SftRe:1;					/* Byte 7 Bit 0 */
+  boolean CmdQue:1;					/* Byte 7 Bit 1 */
+  boolean :1;						/* Byte 7 Bit 2 */
+  boolean Linked:1;					/* Byte 7 Bit 3 */
+  boolean Sync:1;					/* Byte 7 Bit 4 */
+  boolean WBus16:1;					/* Byte 7 Bit 5 */
+  boolean WBus32:1;					/* Byte 7 Bit 6 */
+  boolean RelAdr:1;					/* Byte 7 Bit 7 */
+  unsigned char VendorIdentification[8];		/* Bytes 8-15 */
+  unsigned char ProductIdentification[16];		/* Bytes 16-31 */
+  unsigned char ProductRevisionLevel[4];		/* Bytes 32-35 */
+}
+DAC960_SCSI_Inquiry_T;
+
+
+/*
+  Define the SCSI INQUIRY Unit Serial Number reply structure.
+*/
+
+typedef struct DAC960_SCSI_Inquiry_UnitSerialNumber
+{
+  unsigned char PeripheralDeviceType:5;			/* Byte 0 Bits 0-4 */
+  unsigned char PeripheralQualifier:3;			/* Byte 0 Bits 5-7 */
+  unsigned char PageCode;				/* Byte 1 */
+  unsigned char :8;					/* Byte 2 */
+  unsigned char PageLength;				/* Byte 3 */
+  unsigned char ProductSerialNumber[28];		/* Bytes 4 - 31 */
+}
+DAC960_SCSI_Inquiry_UnitSerialNumber_T;
+
+
+/*
+  Define the Scatter/Gather List Type 1 32 Bit Address 32 Bit Byte Count
+  structure.
+*/
+
+typedef struct DAC960_ScatterGatherSegment
+{
+  DAC960_BusAddress_T SegmentDataPointer;		/* Bytes 0-3 */
+  DAC960_ByteCount_T SegmentByteCount;			/* Bytes 4-7 */
+}
+DAC960_ScatterGatherSegment_T;
+
+
+/*
+  Define the 13 Byte DAC960 Command Mailbox structure.  Bytes 13-15 are
+  not used.  The Command Mailbox structure is padded to 16 bytes for
+  efficient access.
+*/
+
+typedef union DAC960_CommandMailbox
+{
+  unsigned int Words[4];				/* Words 0-3 */
+  unsigned char Bytes[16];				/* Bytes 0-15 */
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char Dummy[14];				/* Bytes 2-15 */
+  } __attribute__ ((packed)) Common;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char Dummy1[6];				/* Bytes 2-7 */
+    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
+    unsigned char Dummy2[4];				/* Bytes 12-15 */
+  } __attribute__ ((packed)) Type3;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char Dummy1[5];				/* Bytes 2-6 */
+    unsigned char LogicalDriveNumber:6;			/* Byte 7 Bits 0-6 */
+    boolean AutoRestore:1;				/* Byte 7 Bit 7 */
+    unsigned char Dummy2[8];				/* Bytes 8-15 */
+  } __attribute__ ((packed)) Type3C;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char Channel;				/* Byte 2 */
+    unsigned char TargetID;				/* Byte 3 */
+    DAC960_PhysicalDeviceState_T DeviceState:5;		/* Byte 4 Bits 0-4 */
+    unsigned char Modifier:3;				/* Byte 4 Bits 5-7 */
+    unsigned char Dummy1[3];				/* Bytes 5-7 */
+    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
+    unsigned char Dummy2[4];				/* Bytes 12-15 */
+  } __attribute__ ((packed)) Type3D;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    DAC960_PerformEventLogOpType_T OperationType;	/* Byte 2 */
+    unsigned char OperationQualifier;			/* Byte 3 */
+    unsigned short SequenceNumber;			/* Bytes 4-5 */
+    unsigned char Dummy1[2];				/* Bytes 6-7 */
+    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
+    unsigned char Dummy2[4];				/* Bytes 12-15 */
+  } __attribute__ ((packed)) Type3E;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char Dummy1[2];				/* Bytes 2-3 */
+    unsigned char RebuildRateConstant;			/* Byte 4 */
+    unsigned char Dummy2[3];				/* Bytes 5-7 */
+    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
+    unsigned char Dummy3[4];				/* Bytes 12-15 */
+  } __attribute__ ((packed)) Type3R;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned short TransferLength;			/* Bytes 2-3 */
+    unsigned int LogicalBlockAddress;			/* Bytes 4-7 */
+    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
+    unsigned char LogicalDriveNumber;			/* Byte 12 */
+    unsigned char Dummy[3];				/* Bytes 13-15 */
+  } __attribute__ ((packed)) Type4;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    struct {
+      unsigned short TransferLength:11;			/* Bytes 2-3 */
+      unsigned char LogicalDriveNumber:5;		/* Byte 3 Bits 3-7 */
+    } __attribute__ ((packed)) LD;
+    unsigned int LogicalBlockAddress;			/* Bytes 4-7 */
+    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
+    unsigned char ScatterGatherCount:6;			/* Byte 12 Bits 0-5 */
+    enum {
+      DAC960_ScatterGather_32BitAddress_32BitByteCount =	0x0,
+      DAC960_ScatterGather_32BitAddress_16BitByteCount =	0x1,
+      DAC960_ScatterGather_32BitByteCount_32BitAddress =	0x2,
+      DAC960_ScatterGather_16BitByteCount_32BitAddress =	0x3
+    } __attribute__ ((packed)) ScatterGatherType:2;	/* Byte 12 Bits 6-7 */
+    unsigned char Dummy[3];				/* Bytes 13-15 */
+  } __attribute__ ((packed)) Type5;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char CommandOpcode2;			/* Byte 2 */
+    unsigned char :8;					/* Byte 3 */
+    DAC960_BusAddress_T CommandMailboxesBusAddress;	/* Bytes 4-7 */
+    DAC960_BusAddress_T StatusMailboxesBusAddress;	/* Bytes 8-11 */
+    unsigned char Dummy[4];				/* Bytes 12-15 */
+  } __attribute__ ((packed)) TypeX;
+}
+DAC960_CommandMailbox_T;
+
+
+/*
+  Define the DAC960 Driver IOCTL requests.
+*/
+
+#define DAC960_IOCTL_GET_CONTROLLER_COUNT	0xDAC001
+#define DAC960_IOCTL_GET_CONTROLLER_INFO	0xDAC002
+#define DAC960_IOCTL_EXECUTE_COMMAND		0xDAC003
+
+
+/*
+  Define the DAC960_IOCTL_GET_CONTROLLER_INFO reply structure.
+*/
+
+typedef struct DAC960_ControllerInfo
+{
+  unsigned char ControllerNumber;
+  unsigned char PCI_Bus;
+  unsigned char PCI_Device;
+  unsigned char PCI_Function;
+  unsigned char IRQ_Channel;
+  unsigned char Channels;
+  DAC960_PCI_Address_T PCI_Address;
+  unsigned char ModelName[16];
+  unsigned char FirmwareVersion[16];
+}
+DAC960_ControllerInfo_T;
+
+
+/*
+  Define the User Mode DAC960_IOCTL_EXECUTE_COMMAND request structure.
+*/
+
+typedef struct DAC960_UserCommand
+{
+  unsigned char ControllerNumber;
+  DAC960_CommandMailbox_T CommandMailbox;
+  int DataTransferLength;
+  void *DataTransferBuffer;
+  DAC960_DCDB_T *DCDB;
+}
+DAC960_UserCommand_T;
+
+
+/*
+  Define the Kernel Mode DAC960_IOCTL_EXECUTE_COMMAND request structure.
+*/
+
+typedef struct DAC960_KernelCommand
+{
+  unsigned char ControllerNumber;
+  DAC960_CommandMailbox_T CommandMailbox;
+  int DataTransferLength;
+  void *DataTransferBuffer;
+  DAC960_DCDB_T *DCDB;
+  DAC960_CommandStatus_T CommandStatus;
+  void (*CompletionFunction)(struct DAC960_KernelCommand *);
+  void *CompletionData;
+}
+DAC960_KernelCommand_T;
+
+
+/*
+  Import the Kernel Mode IOCTL interface.
+*/
+
+extern int DAC960_KernelIOCTL(unsigned int Request, void *Argument);
+
+
+/*
+  Virtual_to_Bus maps from Kernel Virtual Addresses to PCI Bus Addresses.
+*/
+
+static inline DAC960_BusAddress_T Virtual_to_Bus(void *VirtualAddress)
+{
+  return (DAC960_BusAddress_T) virt_to_bus(VirtualAddress);
+}
+
+
+/*
+  Bus_to_Virtual maps from PCI Bus Addresses to Kernel Virtual Addresses.
+*/
+
+static inline void *Bus_to_Virtual(DAC960_BusAddress_T BusAddress)
+{
+  return (void *) bus_to_virt(BusAddress);
+}
+
+
+/*
+  DAC960_DriverVersion protects the private portion of this file.
+*/
+
+#ifdef DAC960_DriverVersion
+
+
+/*
+  Define the maximum Driver Queue Depth and Controller Queue Depth supported
+  by any DAC960 model.
+*/
+
+#define DAC960_MaxDriverQueueDepth		127
+#define DAC960_MaxControllerQueueDepth		128
+
+
+/*
+  Define the maximum number of Scatter/Gather Segments supported by any
+  DAC960 model.
+*/
+
+#define DAC960_MaxScatterGatherSegments		33
+
+
+/*
+  Define the number of Command Mailboxes and Status Mailboxes used by the
+  Memory Mailbox Interface.
+*/
+
+#define DAC960_CommandMailboxCount		256
+#define DAC960_StatusMailboxCount		1024
+
+
+/*
+  Define the DAC960 Controller Monitoring Timer Interval.
+*/
+
+#define DAC960_MonitoringTimerInterval		(10 * HZ)
+
+
+/*
+  Define the DAC960 Controller Secondary Monitoring Interval.
+*/
+
+#define DAC960_SecondaryMonitoringInterval	(60 * HZ)
+
+
+/*
+  Define the DAC960 Controller Progress Reporting Interval.
+*/
+
+#define DAC960_ProgressReportingInterval	(60 * HZ)
+
+
+/*
+  Define the maximum number of Partitions allowed for each Logical Drive.
+*/
+
+#define DAC960_MaxPartitions			8
+#define DAC960_MaxPartitionsBits		3
+
+
+/*
+  Define macros to extract the Controller Number, Logical Drive Number, and
+  Partition Number from a Kernel Device, and to construct a Major Number, Minor
+  Number, and Kernel Device from the Controller Number, Logical Drive Number,
+  and Partition Number.  There is one Major Number assigned to each Controller.
+  The associated Minor Number is divided into the Logical Drive Number and
+  Partition Number.
+*/
+
+#define DAC960_ControllerNumber(Device) \
+  (MAJOR(Device) - DAC960_MAJOR)
+
+#define DAC960_LogicalDriveNumber(Device) \
+  (MINOR(Device) >> DAC960_MaxPartitionsBits)
+
+#define DAC960_PartitionNumber(Device) \
+  (MINOR(Device) & (DAC960_MaxPartitions - 1))
+
+#define DAC960_MajorNumber(ControllerNumber) \
+  (DAC960_MAJOR + (ControllerNumber))
+
+#define DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber) \
+   (((LogicalDriveNumber) << DAC960_MaxPartitionsBits) | (PartitionNumber))
+
+#define DAC960_MinorCount			(DAC960_MaxLogicalDrives \
+						 * DAC960_MaxPartitions)
+
+#define DAC960_KernelDevice(ControllerNumber,				       \
+			    LogicalDriveNumber,				       \
+			    PartitionNumber)				       \
+   MKDEV(DAC960_MajorNumber(ControllerNumber),				       \
+	 DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber))
+
+
+/*
+  Define the DAC960 Controller fixed Block Size and Block Size Bits.
+*/
+
+#define DAC960_BlockSize			512
+#define DAC960_BlockSizeBits			9
+
+
+/*
+  Define the Controller Line Buffer, Status Buffer, Rebuild Progress,
+  and User Message Sizes.
+*/
+
+#define DAC960_LineBufferSize			100
+#define DAC960_StatusBufferSize			16384
+#define DAC960_RebuildProgressSize		200
+#define DAC960_UserMessageSize			200
+
+
+/*
+  Define the types of DAC960 Controllers that are supported.
+*/
+
+typedef enum
+{
+  DAC960_V5_Controller =			1,	/* DAC1164P */
+  DAC960_V4_Controller =			2,	/* DAC960PTL/PJ/PG */
+  DAC960_V3_Controller =			3	/* DAC960PU/PD/PL */
+}
+DAC960_ControllerType_T;
+
+
+/*
+  Define the Driver Message Levels.
+*/
+
+typedef enum DAC960_MessageLevel
+{
+  DAC960_AnnounceLevel =			0,
+  DAC960_InfoLevel =				1,
+  DAC960_NoticeLevel =				2,
+  DAC960_WarningLevel =				3,
+  DAC960_ErrorLevel =				4,
+  DAC960_ProgressLevel =			5,
+  DAC960_CriticalLevel =			6,
+  DAC960_UserCriticalLevel =			7
+}
+DAC960_MessageLevel_T;
+
+static char
+  *DAC960_MessageLevelMap[] =
+    { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING,
+      KERN_ERR, KERN_CRIT, KERN_CRIT, KERN_CRIT };
+
+
+/*
+  Define Driver Message macros.
+*/
+
+#define DAC960_Announce(Format, Arguments...) \
+  DAC960_Message(DAC960_AnnounceLevel, Format, ##Arguments)
+
+#define DAC960_Info(Format, Arguments...) \
+  DAC960_Message(DAC960_InfoLevel, Format, ##Arguments)
+
+#define DAC960_Notice(Format, Arguments...) \
+  DAC960_Message(DAC960_NoticeLevel, Format, ##Arguments)
+
+#define DAC960_Warning(Format, Arguments...) \
+  DAC960_Message(DAC960_WarningLevel, Format, ##Arguments)
+
+#define DAC960_Error(Format, Arguments...) \
+  DAC960_Message(DAC960_ErrorLevel, Format, ##Arguments)
+
+#define DAC960_Progress(Format, Arguments...) \
+  DAC960_Message(DAC960_ProgressLevel, Format, ##Arguments)
+
+#define DAC960_Critical(Format, Arguments...) \
+  DAC960_Message(DAC960_CriticalLevel, Format, ##Arguments)
+
+#define DAC960_UserCritical(Format, Arguments...) \
+  DAC960_Message(DAC960_UserCriticalLevel, Format, ##Arguments)
+
+
+/*
+  Define types for some of the structures that interface with the rest
+  of the Linux Kernel and I/O Subsystem.
+*/
+
+typedef struct buffer_head BufferHeader_T;
+typedef struct file File_T;
+typedef struct file_operations FileOperations_T;
+typedef struct gendisk GenericDiskInfo_T;
+typedef struct hd_geometry DiskGeometry_T;
+typedef struct hd_struct DiskPartition_T;
+typedef struct inode Inode_T;
+typedef struct inode_operations InodeOperations_T;
+typedef kdev_t KernelDevice_T;
+typedef struct notifier_block NotifierBlock_T;
+typedef struct pci_dev PCI_Device_T;
+typedef struct proc_dir_entry PROC_DirectoryEntry_T;
+typedef unsigned long ProcessorFlags_T;
+typedef struct pt_regs Registers_T;
+typedef struct request IO_Request_T;
+typedef struct semaphore Semaphore_T;
+typedef struct super_block SuperBlock_T;
+typedef struct timer_list Timer_T;
+typedef wait_queue_head_t WaitQueue_T;
+
+
+/*
+  Define the DAC960 Controller Status Mailbox structure.
+*/
+
+typedef union DAC960_StatusMailbox
+{
+  unsigned int Word;					/* Bytes 0-3 */
+  struct {
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 0 */
+    unsigned char :7;					/* Byte 1 Bits 0-6 */
+    boolean Valid:1;					/* Byte 1 Bit 7 */
+    DAC960_CommandStatus_T CommandStatus;		/* Bytes 2-3 */
+  } Fields;
+}
+DAC960_StatusMailbox_T;
+
+
+/*
+  Define the DAC960 Driver Command Types.
+*/
+
+typedef enum
+{
+  DAC960_ReadCommand =				1,
+  DAC960_WriteCommand =				2,
+  DAC960_ReadRetryCommand =			3,
+  DAC960_WriteRetryCommand =			4,
+  DAC960_MonitoringCommand =			5,
+  DAC960_ImmediateCommand =			6,
+  DAC960_QueuedCommand =			7
+}
+DAC960_CommandType_T;
+
+
+/*
+  Define the DAC960 Driver Command structure.
+*/
+
+typedef struct DAC960_Command
+{
+  DAC960_CommandType_T CommandType;
+  DAC960_CommandMailbox_T CommandMailbox;
+  DAC960_CommandStatus_T CommandStatus;
+  struct DAC960_Controller *Controller;
+  struct DAC960_Command *Next;
+  Semaphore_T *Semaphore;
+  unsigned int LogicalDriveNumber;
+  unsigned int BlockNumber;
+  unsigned int BlockCount;
+  unsigned int SegmentCount;
+  BufferHeader_T *BufferHeader;
+  DAC960_KernelCommand_T *KernelCommand;
+  DAC960_ScatterGatherSegment_T
+    ScatterGatherList[DAC960_MaxScatterGatherSegments];
+}
+DAC960_Command_T;
+
+
+/*
+  Define the DAC960 Driver Controller structure.
+*/
+
+typedef struct DAC960_Controller
+{
+  void *BaseAddress;
+  void *MemoryMappedAddress;
+  DAC960_ControllerType_T ControllerType;
+  DAC960_IO_Address_T IO_Address;
+  DAC960_PCI_Address_T PCI_Address;
+  unsigned char ControllerNumber;
+  unsigned char ControllerName[4];
+  unsigned char ModelName[12];
+  unsigned char FullModelName[18];
+  unsigned char FirmwareVersion[14];
+  unsigned char Bus;
+  unsigned char Device;
+  unsigned char Function;
+  unsigned char IRQ_Channel;
+  unsigned char Channels;
+  unsigned char MemorySize;
+  unsigned char LogicalDriveCount;
+  unsigned char GeometryTranslationHeads;
+  unsigned char GeometryTranslationSectors;
+  unsigned short ControllerQueueDepth;
+  unsigned short DriverQueueDepth;
+  unsigned short MaxBlocksPerCommand;
+  unsigned short MaxScatterGatherSegments;
+  unsigned short StripeSize;
+  unsigned short SegmentSize;
+  unsigned short NewEventLogSequenceNumber;
+  unsigned short OldEventLogSequenceNumber;
+  unsigned short InitialStatusLength;
+  unsigned short CurrentStatusLength;
+  unsigned short UserStatusLength;
+  unsigned short RebuildProgressLength;
+  unsigned int ControllerUsageCount;
+  unsigned int EnquiryIndex;
+  unsigned int LogicalDriveInformationIndex;
+  unsigned int ErrorTableIndex;
+  unsigned int DeviceStateIndex;
+  unsigned int DeviceStateChannel;
+  unsigned int DeviceStateTargetID;
+  unsigned long MonitoringTimerCount;
+  unsigned long SecondaryMonitoringTime;
+  unsigned long LastProgressReportTime;
+  unsigned long LastCurrentStatusTime;
+  boolean DualModeMemoryMailboxInterface;
+  boolean SAFTE_EnclosureManagementEnabled;
+  boolean ControllerInitialized;
+  boolean MonitoringCommandDeferred;
+  boolean NeedLogicalDriveInformation;
+  boolean NeedErrorTableInformation;
+  boolean NeedDeviceStateInformation;
+  boolean NeedDeviceInquiryInformation;
+  boolean NeedDeviceSerialNumberInformation;
+  boolean NeedRebuildProgress;
+  boolean NeedConsistencyCheckProgress;
+  boolean EphemeralProgressMessage;
+  Timer_T MonitoringTimer;
+  GenericDiskInfo_T GenericDiskInfo;
+  DAC960_Command_T *FreeCommands;
+  DAC960_CommandMailbox_T *FirstCommandMailbox;
+  DAC960_CommandMailbox_T *LastCommandMailbox;
+  DAC960_CommandMailbox_T *NextCommandMailbox;
+  DAC960_CommandMailbox_T *PreviousCommandMailbox1;
+  DAC960_CommandMailbox_T *PreviousCommandMailbox2;
+  DAC960_StatusMailbox_T *FirstStatusMailbox;
+  DAC960_StatusMailbox_T *LastStatusMailbox;
+  DAC960_StatusMailbox_T *NextStatusMailbox;
+  PROC_DirectoryEntry_T ControllerProcEntry;
+  PROC_DirectoryEntry_T InitialStatusProcEntry;
+  PROC_DirectoryEntry_T CurrentStatusProcEntry;
+  PROC_DirectoryEntry_T UserCommandProcEntry;
+  WaitQueue_T CommandWaitQueue;
+  DAC960_DCDB_T MonitoringDCDB;
+  DAC960_Enquiry_T Enquiry[2];
+  DAC960_ErrorTable_T ErrorTable[2];
+  DAC960_EventLogEntry_T EventLogEntry;
+  DAC960_RebuildProgress_T RebuildProgress;
+  DAC960_CommandStatus_T LastRebuildStatus;
+  DAC960_LogicalDriveInformation_T
+    LogicalDriveInformation[2][DAC960_MaxLogicalDrives];
+  DAC960_LogicalDriveState_T LogicalDriveInitialState[DAC960_MaxLogicalDrives];
+  DAC960_DeviceState_T DeviceState[2][DAC960_MaxChannels][DAC960_MaxTargets];
+  DAC960_Command_T Commands[DAC960_MaxDriverQueueDepth];
+  DAC960_SCSI_Inquiry_T
+    InquiryStandardData[DAC960_MaxChannels][DAC960_MaxTargets];
+  DAC960_SCSI_Inquiry_UnitSerialNumber_T
+    InquiryUnitSerialNumber[DAC960_MaxChannels][DAC960_MaxTargets];
+  DiskPartition_T DiskPartitions[DAC960_MinorCount];
+  int LogicalDriveUsageCount[DAC960_MaxLogicalDrives];
+  int PartitionSizes[DAC960_MinorCount];
+  int BlockSizes[DAC960_MinorCount];
+  int MaxSectorsPerRequest[DAC960_MinorCount];
+  int MaxSegmentsPerRequest[DAC960_MinorCount];
+  int DeviceResetCount[DAC960_MaxChannels][DAC960_MaxTargets];
+  boolean DirectCommandActive[DAC960_MaxChannels][DAC960_MaxTargets];
+  char InitialStatusBuffer[DAC960_StatusBufferSize];
+  char CurrentStatusBuffer[DAC960_StatusBufferSize];
+  char UserStatusBuffer[DAC960_UserMessageSize];
+  char RebuildProgressBuffer[DAC960_RebuildProgressSize];
+}
+DAC960_Controller_T;
+
+
+/*
+  DAC960_AcquireControllerLock acquires exclusive access to Controller.
+*/
+
+static inline
+void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller,
+				  ProcessorFlags_T *ProcessorFlags)
+{
+  spin_lock_irqsave(&io_request_lock, *ProcessorFlags);
+}
+
+
+/*
+  DAC960_ReleaseControllerLock releases exclusive access to Controller.
+*/
+
+static inline
+void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller,
+				  ProcessorFlags_T *ProcessorFlags)
+{
+  spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags);
+}
+
+
+/*
+  DAC960_AcquireControllerLockRF acquires exclusive access to Controller,
+  but is only called from the request function with the io_request_lock held.
+*/
+
+static inline
+void DAC960_AcquireControllerLockRF(DAC960_Controller_T *Controller,
+				    ProcessorFlags_T *ProcessorFlags)
+{
+}
+
+
+/*
+  DAC960_ReleaseControllerLockRF releases exclusive access to Controller,
+  but is only called from the request function with the io_request_lock held.
+*/
+
+static inline
+void DAC960_ReleaseControllerLockRF(DAC960_Controller_T *Controller,
+				    ProcessorFlags_T *ProcessorFlags)
+{
+}
+
+
+/*
+  DAC960_AcquireControllerLockIH acquires exclusive access to Controller,
+  but is only called from the interrupt handler.
+*/
+
+static inline
+void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller,
+				    ProcessorFlags_T *ProcessorFlags)
+{
+  spin_lock_irqsave(&io_request_lock, *ProcessorFlags);
+}
+
+
+/*
+  DAC960_ReleaseControllerLockIH releases exclusive access to Controller,
+  but is only called from the interrupt handler.
+*/
+
+static inline
+void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller,
+				    ProcessorFlags_T *ProcessorFlags)
+{
+  spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags);
+}
+
+
+/*
+  Define the DAC960 V5 Controller Interface Register Offsets.
+*/
+
+#define DAC960_V5_RegisterWindowSize		0x80
+
+typedef enum
+{
+  DAC960_V5_InboundDoorBellRegisterOffset =	0x60,
+  DAC960_V5_OutboundDoorBellRegisterOffset =	0x61,
+  DAC960_V5_InterruptMaskRegisterOffset =	0x34,
+  DAC960_V5_CommandOpcodeRegisterOffset =	0x50,
+  DAC960_V5_CommandIdentifierRegisterOffset =	0x51,
+  DAC960_V5_MailboxRegister2Offset =		0x52,
+  DAC960_V5_MailboxRegister3Offset =		0x53,
+  DAC960_V5_MailboxRegister4Offset =		0x54,
+  DAC960_V5_MailboxRegister5Offset =		0x55,
+  DAC960_V5_MailboxRegister6Offset =		0x56,
+  DAC960_V5_MailboxRegister7Offset =		0x57,
+  DAC960_V5_MailboxRegister8Offset =		0x58,
+  DAC960_V5_MailboxRegister9Offset =		0x59,
+  DAC960_V5_MailboxRegister10Offset =		0x5A,
+  DAC960_V5_MailboxRegister11Offset =		0x5B,
+  DAC960_V5_MailboxRegister12Offset =		0x5C,
+  DAC960_V5_StatusCommandIdentifierRegOffset =	0x5D,
+  DAC960_V5_StatusRegisterOffset =		0x5E
+}
+DAC960_V5_RegisterOffsets_T;
+
+
+/*
+  Define the structure of the DAC960 V5 Inbound Door Bell Register.
+*/
+
+typedef union DAC960_V5_InboundDoorBellRegister
+{
+  unsigned char All;
+  struct {
+    boolean HardwareMailboxNewCommand:1;		/* Bit 0 */
+    boolean AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
+    boolean GenerateInterrupt:1;			/* Bit 2 */
+    boolean ControllerReset:1;				/* Bit 3 */
+    boolean MemoryMailboxNewCommand:1;			/* Bit 4 */
+    unsigned char :3;					/* Bits 5-7 */
+  } Write;
+  struct {
+    boolean HardwareMailboxEmpty:1;			/* Bit 0 */
+    unsigned char :7;					/* Bits 1-7 */
+  } Read;
+}
+DAC960_V5_InboundDoorBellRegister_T;
+
+
+/*
+  Define the structure of the DAC960 V5 Outbound Door Bell Register.
+*/
+
+typedef union DAC960_V5_OutboundDoorBellRegister
+{
+  unsigned char All;
+  struct {
+    boolean AcknowledgeHardwareMailboxInterrupt:1;	/* Bit 0 */
+    boolean AcknowledgeMemoryMailboxInterrupt:1;	/* Bit 1 */
+    unsigned char :6;					/* Bits 2-7 */
+  } Write;
+  struct {
+    boolean HardwareMailboxStatusAvailable:1;		/* Bit 0 */
+    boolean MemoryMailboxStatusAvailable:1;		/* Bit 1 */
+    unsigned char :6;					/* Bits 2-7 */
+  } Read;
+}
+DAC960_V5_OutboundDoorBellRegister_T;
+
+
+/*
+  Define the structure of the DAC960 V5 Interrupt Mask Register.
+*/
+
+typedef union DAC960_V5_InterruptMaskRegister
+{
+  unsigned char All;
+  struct {
+    unsigned char :2;					/* Bits 0-1 */
+    boolean DisableInterrupts:1;			/* Bit 2 */
+    unsigned char :5;					/* Bits 3-7 */
+  } Bits;
+}
+DAC960_V5_InterruptMaskRegister_T;
+
+
+/*
+  Define inline functions to provide an abstraction for reading and writing the
+  DAC960 V5 Controller Interface Registers.
+*/
+
+static inline
+void DAC960_V5_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_GenerateInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.GenerateInterrupt = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_ControllerReset(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.ControllerReset = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V5_HardwareMailboxEmptyP(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+  return InboundDoorBellRegister.Read.HardwareMailboxEmpty;
+}
+
+static inline
+void DAC960_V5_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+  writeb(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+  writeb(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_AcknowledgeInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+  writeb(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V5_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+{
+  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+  return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable;
+}
+
+static inline
+boolean DAC960_V5_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+{
+  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+  return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable;
+}
+
+static inline
+void DAC960_V5_EnableInterrupts(void *ControllerBaseAddress)
+{
+  DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.Bits.DisableInterrupts = false;
+  writeb(InterruptMaskRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
+}
+
+static inline
+void DAC960_V5_DisableInterrupts(void *ControllerBaseAddress)
+{
+  DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.Bits.DisableInterrupts = true;
+  writeb(InterruptMaskRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
+}
+
+static inline
+boolean DAC960_V5_InterruptsEnabledP(void *ControllerBaseAddress)
+{
+  DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
+  return !InterruptMaskRegister.Bits.DisableInterrupts;
+}
+
+static inline
+void DAC960_V5_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox,
+				   DAC960_CommandMailbox_T *CommandMailbox)
+{
+  NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
+  NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
+  NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
+  NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
+}
+
+static inline
+void DAC960_V5_WriteHardwareMailbox(void *ControllerBaseAddress,
+				    DAC960_CommandMailbox_T *CommandMailbox)
+{
+  writel(CommandMailbox->Words[0],
+	 ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset);
+  writel(CommandMailbox->Words[1],
+	 ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset);
+  writel(CommandMailbox->Words[2],
+	 ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset);
+  writeb(CommandMailbox->Bytes[12],
+	 ControllerBaseAddress + DAC960_V5_MailboxRegister12Offset);
+}
+
+static inline DAC960_CommandIdentifier_T
+DAC960_V5_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+{
+  return readb(ControllerBaseAddress
+	       + DAC960_V5_StatusCommandIdentifierRegOffset);
+}
+
+static inline DAC960_CommandStatus_T
+DAC960_V5_ReadStatusRegister(void *ControllerBaseAddress)
+{
+  return readw(ControllerBaseAddress + DAC960_V5_StatusRegisterOffset);
+}
+
+static inline
+void DAC960_V5_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
+{
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  writel(0x743C485E,
+	 ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset);
+  writel((unsigned long) Controller->FirstCommandMailbox,
+	 ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset);
+  writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox,
+	 ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset);
+  writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox,
+	 ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset);
+}
+
+static inline
+void DAC960_V5_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller,
+					void **MemoryMailboxAddress,
+					short *NextCommandMailboxIndex,
+					short *NextStatusMailboxIndex)
+{
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  if (readl(ControllerBaseAddress
+	    + DAC960_V5_CommandOpcodeRegisterOffset) != 0x743C485E)
+    return;
+  *MemoryMailboxAddress =
+    (void *) readl(ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset);
+  *NextCommandMailboxIndex =
+    readw(ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset);
+  *NextStatusMailboxIndex =
+    readw(ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset);
+}
+
+
+/*
+  Define the DAC960 V4 Controller Interface Register Offsets.
+*/
+
+#define DAC960_V4_RegisterWindowSize		0x2000
+
+typedef enum
+{
+  DAC960_V4_InboundDoorBellRegisterOffset =	0x0020,
+  DAC960_V4_OutboundDoorBellRegisterOffset =	0x002C,
+  DAC960_V4_InterruptMaskRegisterOffset =	0x0034,
+  DAC960_V4_CommandOpcodeRegisterOffset =	0x1000,
+  DAC960_V4_CommandIdentifierRegisterOffset =	0x1001,
+  DAC960_V4_MailboxRegister2Offset =		0x1002,
+  DAC960_V4_MailboxRegister3Offset =		0x1003,
+  DAC960_V4_MailboxRegister4Offset =		0x1004,
+  DAC960_V4_MailboxRegister5Offset =		0x1005,
+  DAC960_V4_MailboxRegister6Offset =		0x1006,
+  DAC960_V4_MailboxRegister7Offset =		0x1007,
+  DAC960_V4_MailboxRegister8Offset =		0x1008,
+  DAC960_V4_MailboxRegister9Offset =		0x1009,
+  DAC960_V4_MailboxRegister10Offset =		0x100A,
+  DAC960_V4_MailboxRegister11Offset =		0x100B,
+  DAC960_V4_MailboxRegister12Offset =		0x100C,
+  DAC960_V4_StatusCommandIdentifierRegOffset =	0x1018,
+  DAC960_V4_StatusRegisterOffset =		0x101A
+}
+DAC960_V4_RegisterOffsets_T;
+
+
+/*
+  Define the structure of the DAC960 V4 Inbound Door Bell Register.
+*/
+
+typedef union DAC960_V4_InboundDoorBellRegister
+{
+  unsigned int All;
+  struct {
+    boolean HardwareMailboxNewCommand:1;		/* Bit 0 */
+    boolean AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
+    boolean GenerateInterrupt:1;			/* Bit 2 */
+    boolean ControllerReset:1;				/* Bit 3 */
+    boolean MemoryMailboxNewCommand:1;			/* Bit 4 */
+    unsigned int :27;					/* Bits 5-31 */
+  } Write;
+  struct {
+    boolean HardwareMailboxFull:1;			/* Bit 0 */
+    unsigned int :31;					/* Bits 1-31 */
+  } Read;
+}
+DAC960_V4_InboundDoorBellRegister_T;
+
+
+/*
+  Define the structure of the DAC960 V4 Outbound Door Bell Register.
+*/
+
+typedef union DAC960_V4_OutboundDoorBellRegister
+{
+  unsigned int All;
+  struct {
+    boolean AcknowledgeHardwareMailboxInterrupt:1;	/* Bit 0 */
+    boolean AcknowledgeMemoryMailboxInterrupt:1;	/* Bit 1 */
+    unsigned int :30;					/* Bits 2-31 */
+  } Write;
+  struct {
+    boolean HardwareMailboxStatusAvailable:1;		/* Bit 0 */
+    boolean MemoryMailboxStatusAvailable:1;		/* Bit 1 */
+    unsigned int :30;					/* Bits 2-31 */
+  } Read;
+}
+DAC960_V4_OutboundDoorBellRegister_T;
+
+
+/*
+  Define the structure of the DAC960 V4 Interrupt Mask Register.
+*/
+
+typedef union DAC960_V4_InterruptMaskRegister
+{
+  unsigned int All;
+  struct {
+    unsigned int MessageUnitInterruptMask1:2;		/* Bits 0-1 */
+    boolean DisableInterrupts:1;			/* Bit 2 */
+    unsigned int MessageUnitInterruptMask2:5;		/* Bits 3-7 */
+    unsigned int Reserved0:24;				/* Bits 8-31 */
+  } Bits;
+}
+DAC960_V4_InterruptMaskRegister_T;
+
+
+/*
+  Define inline functions to provide an abstraction for reading and writing the
+  DAC960 V4 Controller Interface Registers.
+*/
+
+static inline
+void DAC960_V4_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_GenerateInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.GenerateInterrupt = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_ControllerReset(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.ControllerReset = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V4_HardwareMailboxFullP(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+  return InboundDoorBellRegister.Read.HardwareMailboxFull;
+}
+
+static inline
+void DAC960_V4_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+  writel(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+  writel(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_AcknowledgeInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+  writel(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V4_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+{
+  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All =
+    readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+  return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable;
+}
+
+static inline
+boolean DAC960_V4_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+{
+  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All =
+    readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+  return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable;
+}
+
+static inline
+void DAC960_V4_EnableInterrupts(void *ControllerBaseAddress)
+{
+  DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3;
+  InterruptMaskRegister.Bits.DisableInterrupts = false;
+  InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F;
+  writel(InterruptMaskRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset);
+}
+
+static inline
+void DAC960_V4_DisableInterrupts(void *ControllerBaseAddress)
+{
+  DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3;
+  InterruptMaskRegister.Bits.DisableInterrupts = true;
+  InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F;
+  writel(InterruptMaskRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset);
+}
+
+static inline
+boolean DAC960_V4_InterruptsEnabledP(void *ControllerBaseAddress)
+{
+  DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All =
+    readl(ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset);
+  return !InterruptMaskRegister.Bits.DisableInterrupts;
+}
+
+static inline
+void DAC960_V4_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox,
+				   DAC960_CommandMailbox_T *CommandMailbox)
+{
+  NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
+  NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
+  NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
+  NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
+}
+
+static inline
+void DAC960_V4_WriteHardwareMailbox(void *ControllerBaseAddress,
+				    DAC960_CommandMailbox_T *CommandMailbox)
+{
+  writel(CommandMailbox->Words[0],
+	 ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
+  writel(CommandMailbox->Words[1],
+	 ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
+  writel(CommandMailbox->Words[2],
+	 ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset);
+  writeb(CommandMailbox->Bytes[12],
+	 ControllerBaseAddress + DAC960_V4_MailboxRegister12Offset);
+}
+
+static inline DAC960_CommandIdentifier_T
+DAC960_V4_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+{
+  return readb(ControllerBaseAddress
+	       + DAC960_V4_StatusCommandIdentifierRegOffset);
+}
+
+static inline DAC960_CommandStatus_T
+DAC960_V4_ReadStatusRegister(void *ControllerBaseAddress)
+{
+  return readw(ControllerBaseAddress + DAC960_V4_StatusRegisterOffset);
+}
+
+static inline
+void DAC960_V4_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
+{
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  writel(0xAABBFFFF,
+	 ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
+  writel((unsigned long) Controller->FirstCommandMailbox,
+	 ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
+  writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox,
+	 ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset);
+  writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox,
+	 ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset);
+}
+
+static inline
+void DAC960_V4_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller,
+					void **MemoryMailboxAddress,
+					short *NextCommandMailboxIndex,
+					short *NextStatusMailboxIndex)
+{
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  if (readl(ControllerBaseAddress
+	    + DAC960_V4_CommandOpcodeRegisterOffset) != 0xAABBFFFF)
+    return;
+  *MemoryMailboxAddress =
+    (void *) readl(ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
+  *NextCommandMailboxIndex =
+    readw(ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset);
+  *NextStatusMailboxIndex =
+    readw(ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset);
+}
+
+
+/*
+  Define the DAC960 V3 Controller Interface Register Offsets.
+*/
+
+#define DAC960_V3_RegisterWindowSize		0x80
+
+typedef enum
+{
+  DAC960_V3_CommandOpcodeRegisterOffset =	0x00,
+  DAC960_V3_CommandIdentifierRegisterOffset =	0x01,
+  DAC960_V3_MailboxRegister2Offset =		0x02,
+  DAC960_V3_MailboxRegister3Offset =		0x03,
+  DAC960_V3_MailboxRegister4Offset =		0x04,
+  DAC960_V3_MailboxRegister5Offset =		0x05,
+  DAC960_V3_MailboxRegister6Offset =		0x06,
+  DAC960_V3_MailboxRegister7Offset =		0x07,
+  DAC960_V3_MailboxRegister8Offset =		0x08,
+  DAC960_V3_MailboxRegister9Offset =		0x09,
+  DAC960_V3_MailboxRegister10Offset =		0x0A,
+  DAC960_V3_MailboxRegister11Offset =		0x0B,
+  DAC960_V3_MailboxRegister12Offset =		0x0C,
+  DAC960_V3_StatusCommandIdentifierRegOffset =	0x0D,
+  DAC960_V3_StatusRegisterOffset =		0x0E,
+  DAC960_V3_InboundDoorBellRegisterOffset =	0x40,
+  DAC960_V3_OutboundDoorBellRegisterOffset =	0x41,
+  DAC960_V3_InterruptEnableRegisterOffset =	0x43
+}
+DAC960_V3_RegisterOffsets_T;
+
+
+/*
+  Define the structure of the DAC960 V3 Inbound Door Bell Register.
+*/
+
+typedef union DAC960_V3_InboundDoorBellRegister
+{
+  unsigned char All;
+  struct {
+    boolean NewCommand:1;				/* Bit 0 */
+    boolean AcknowledgeStatus:1;			/* Bit 1 */
+    boolean GenerateInterrupt:1;			/* Bit 2 */
+    boolean ControllerReset:1;				/* Bit 3 */
+    unsigned char :4;					/* Bits 4-7 */
+  } Write;
+  struct {
+    boolean MailboxFull:1;				/* Bit 0 */
+    unsigned char :7;					/* Bits 1-7 */
+  } Read;
+}
+DAC960_V3_InboundDoorBellRegister_T;
+
+
+/*
+  Define the structure of the DAC960 V3 Outbound Door Bell Register.
+*/
+
+typedef union DAC960_V3_OutboundDoorBellRegister
+{
+  unsigned char All;
+  struct {
+    boolean AcknowledgeInterrupt:1;			/* Bit 0 */
+    unsigned char :7;					/* Bits 1-7 */
+  } Write;
+  struct {
+    boolean StatusAvailable:1;				/* Bit 0 */
+    unsigned char :7;					/* Bits 1-7 */
+  } Read;
+}
+DAC960_V3_OutboundDoorBellRegister_T;
+
+
+/*
+  Define the structure of the DAC960 V3 Interrupt Enable Register.
+*/
+
+typedef union DAC960_V3_InterruptEnableRegister
+{
+  unsigned char All;
+  struct {
+    boolean EnableInterrupts:1;				/* Bit 0 */
+    unsigned char :7;					/* Bits 1-7 */
+  } Bits;
+}
+DAC960_V3_InterruptEnableRegister_T;
+
+
+/*
+  Define inline functions to provide an abstraction for reading and writing the
+  DAC960 V3 Controller Interface Registers.
+*/
+
+static inline
+void DAC960_V3_NewCommand(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.NewCommand = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V3_AcknowledgeStatus(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.AcknowledgeStatus = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V3_GenerateInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.GenerateInterrupt = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V3_ControllerReset(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.ControllerReset = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V3_MailboxFullP(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+  return InboundDoorBellRegister.Read.MailboxFull;
+}
+
+static inline
+void DAC960_V3_AcknowledgeInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeInterrupt = true;
+  writeb(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V3_StatusAvailableP(void *ControllerBaseAddress)
+{
+  DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset);
+  return OutboundDoorBellRegister.Read.StatusAvailable;
+}
+
+static inline
+void DAC960_V3_EnableInterrupts(void *ControllerBaseAddress)
+{
+  DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister;
+  InterruptEnableRegister.All = 0;
+  InterruptEnableRegister.Bits.EnableInterrupts = true;
+  writeb(InterruptEnableRegister.All,
+	 ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset);
+}
+
+static inline
+void DAC960_V3_DisableInterrupts(void *ControllerBaseAddress)
+{
+  DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister;
+  InterruptEnableRegister.All = 0;
+  InterruptEnableRegister.Bits.EnableInterrupts = false;
+  writeb(InterruptEnableRegister.All,
+	 ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset);
+}
+
+static inline
+boolean DAC960_V3_InterruptsEnabledP(void *ControllerBaseAddress)
+{
+  DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister;
+  InterruptEnableRegister.All =
+    readb(ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset);
+  return InterruptEnableRegister.Bits.EnableInterrupts;
+}
+
+static inline
+void DAC960_V3_WriteCommandMailbox(void *ControllerBaseAddress,
+				   DAC960_CommandMailbox_T *CommandMailbox)
+{
+  writel(CommandMailbox->Words[0],
+	 ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset);
+  writel(CommandMailbox->Words[1],
+	 ControllerBaseAddress + DAC960_V3_MailboxRegister4Offset);
+  writel(CommandMailbox->Words[2],
+	 ControllerBaseAddress + DAC960_V3_MailboxRegister8Offset);
+  writeb(CommandMailbox->Bytes[12],
+	 ControllerBaseAddress + DAC960_V3_MailboxRegister12Offset);
+}
+
+static inline DAC960_CommandIdentifier_T
+DAC960_V3_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+{
+  return readb(ControllerBaseAddress
+	       + DAC960_V3_StatusCommandIdentifierRegOffset);
+}
+
+static inline DAC960_CommandStatus_T
+DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress)
+{
+  return readw(ControllerBaseAddress + DAC960_V3_StatusRegisterOffset);
+}
+
+
+/*
+  Define compatibility macros between Linux 2.0 and Linux 2.1.
+*/
+
+#if LINUX_VERSION_CODE < 0x20100
+
+#define MODULE_PARM(Variable, Type)
+#define ioremap_nocache(Offset, Size)	vremap(Offset, Size)
+#define iounmap(Address)		vfree(Address)
+
+#endif
+
+
+/*
+  Define prototypes for the forward referenced DAC960 Driver Internal Functions.
+*/
+
+static void DAC960_FinalizeController(DAC960_Controller_T *);
+static int DAC960_Finalize(NotifierBlock_T *, unsigned long, void *);
+static void DAC960_RequestFunction0(void);
+static void DAC960_RequestFunction1(void);
+static void DAC960_RequestFunction2(void);
+static void DAC960_RequestFunction3(void);
+static void DAC960_RequestFunction4(void);
+static void DAC960_RequestFunction5(void);
+static void DAC960_RequestFunction6(void);
+static void DAC960_RequestFunction7(void);
+static void DAC960_InterruptHandler(int, void *, Registers_T *);
+static void DAC960_QueueMonitoringCommand(DAC960_Command_T *);
+static void DAC960_MonitoringTimerFunction(unsigned long);
+static int DAC960_Open(Inode_T *, File_T *);
+static int DAC960_Release(Inode_T *, File_T *);
+static int DAC960_IOCTL(Inode_T *, File_T *, unsigned int, unsigned long);
+static int DAC960_UserIOCTL(Inode_T *, File_T *, unsigned int, unsigned long);
+static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *);
+static void DAC960_Message(DAC960_MessageLevel_T, char *,
+			   DAC960_Controller_T *, ...);
+static void DAC960_CreateProcEntries(void);
+static void DAC960_DestroyProcEntries(void);
+
+
+/*
+  Export the Kernel Mode IOCTL interface.
+*/
+
+EXPORT_SYMBOL(DAC960_KernelIOCTL);
+
+
+#endif /* DAC960_DriverVersion */
diff -u --recursive --new-file v2.3.15/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v2.3.15/linux/drivers/block/Makefile	Thu Aug  5 18:48:45 1999
+++ linux/drivers/block/Makefile	Mon Aug 30 10:24:14 1999
@@ -20,7 +20,7 @@
 
 
 L_TARGET := block.a
-L_OBJS   := genhd.o
+L_OBJS   := genhd.o cmos-probe.o
 M_OBJS   :=
 MOD_LIST_NAME := BLOCK_MODULES
 LX_OBJS := ll_rw_blk.o blkpg.o
@@ -154,6 +154,10 @@
 IDE_OBJS += ht6560b.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_IDE_ICSIDE),y)
+IDE_OBJS += icside.o
+endif
+
 ifeq ($(CONFIG_BLK_DEV_IDEDMA),y)
 IDE_OBJS += ide-dma.o
 endif
@@ -194,6 +198,10 @@
 IDE_OBJS += qd6580.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_IDE_RAPIDE),y)
+IDE_OBJS += rapide.o
+endif
+
 ifeq ($(CONFIG_BLK_DEV_RZ1000),y)
 IDE_OBJS += rz1000.o
 endif
@@ -218,14 +226,6 @@
 IDE_OBJS += via82c586.o
 endif
 
-ifeq ($(CONFIG_BLK_DEV_IDE_ICSIDE),y)
-IDE_OBJS += icside.o
-endif
-
-ifeq ($(CONFIG_BLK_DEV_IDE_RAPIDE),y)
-IDE_OBJS += rapide.o
-endif
-
 ### if CONFIG_BLK_DEV_IDE is n, IDE_OBJS will be ignored
 
 ifeq ($(CONFIG_PROC_FS),y)
@@ -299,6 +299,14 @@
 else
   ifeq ($(CONFIG_BLK_CPQ_DA),m)
   M_OBJS += cpqarray.o
+  endif
+endif
+
+ifeq ($(CONFIG_BLK_DEV_DAC960),y)
+LX_OBJS += DAC960.o
+else
+  ifeq ($(CONFIG_BLK_DEV_DAC960),m)
+  MX_OBJS += DAC960.o
   endif
 endif
 
diff -u --recursive --new-file v2.3.15/linux/drivers/block/aec6210.c linux/drivers/block/aec6210.c
--- v2.3.15/linux/drivers/block/aec6210.c	Thu Aug  5 18:48:45 1999
+++ linux/drivers/block/aec6210.c	Mon Aug 30 10:18:40 1999
@@ -50,11 +50,11 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-__initfunc(unsigned int pci_init_aec6210 (struct pci_dev *dev, const char *name))
+unsigned int __init pci_init_aec6210 (struct pci_dev *dev, const char *name)
 {
-	if (dev->rom_address) {
-		pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
-		printk("%s: ROM enabled at 0x%08lx\n", name, dev->rom_address);
+	if (dev->resource[PCI_ROM_RESOURCE].start) {
+		pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+		printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
 	}
 	return dev->irq;
 }
diff -u --recursive --new-file v2.3.15/linux/drivers/block/alim15x3.c linux/drivers/block/alim15x3.c
--- v2.3.15/linux/drivers/block/alim15x3.c	Thu Jul  1 10:25:38 1999
+++ linux/drivers/block/alim15x3.c	Thu Aug 26 13:55:41 1999
@@ -110,7 +110,7 @@
 
 }
 
-__initfunc(unsigned int pci_init_ali15x3 (struct pci_dev *dev, const char *name))
+unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name)
 {
 	byte confreg0 = 0, confreg1 =0, progif = 0;
 	int errors = 0;
@@ -194,7 +194,7 @@
 	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
 }
 
-__initfunc(void ide_init_ali15x3 (ide_hwif_t *hwif))
+void __init ide_init_ali15x3 (ide_hwif_t *hwif)
 {
 	struct pci_dev *dev;
 	byte ideic, inmir, iderev;
diff -u --recursive --new-file v2.3.15/linux/drivers/block/cmos-probe.c linux/drivers/block/cmos-probe.c
--- v2.3.15/linux/drivers/block/cmos-probe.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/cmos-probe.c	Thu Aug 26 13:44:03 1999
@@ -0,0 +1,78 @@
+/*
+ *  linux/drivers/block/cmos-probe.c	Version 1.00  August 16, 1999
+ *
+ *  Copyright (C) 1994-1999  Linus Torvalds & authors (see below)
+ */
+
+#undef REALLY_SLOW_IO		/* most systems can safely undef this */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/major.h>
+#include <linux/errno.h>
+#include <linux/genhd.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+
+
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/*
+ * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc
+ * controller that is BIOS compatible with ST-506, and thus showing up in our
+ * BIOS table, but not register compatible, and therefore not present in CMOS.
+ *
+ * Furthermore, we will assume that our ST-506 drives <if any> are the primary
+ * drives in the system -- the ones reflected as drive 1 or 2.  The first
+ * drive is stored in the high nibble of CMOS byte 0x12, the second in the low
+ * nibble.  This will be either a 4 bit drive type or 0xf indicating use byte
+ * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.  A non-zero value
+ * means we have an AT controller hard disk for that drive.
+ *
+ * Of course, there is no guarantee that either drive is actually on the
+ * "primary" IDE interface, but we don't bother trying to sort that out here.
+ * If a drive is not actually on the primary interface, then these parameters
+ * will be ignored.  This results in the user having to supply the logical
+ * drive geometry as a boot parameter for each drive not on the primary i/f.
+ *
+ * The only "perfect" way to handle this would be to modify the setup.[cS] code
+ * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info
+ * for us during initialization.  I have the necessary docs -- any takers?  -ml
+ */
+void probe_cmos_for_drives (ide_hwif_t *hwif)
+{
+#ifdef __i386__
+	extern struct drive_info_struct drive_info;
+	byte cmos_disks, *BIOS = (byte *) &drive_info;
+	int unit;
+
+#ifdef CONFIG_BLK_DEV_PDC4030
+	if (hwif->chipset == ide_pdc4030 && hwif->channel != 0)
+		return;
+#endif /* CONFIG_BLK_DEV_PDC4030 */
+	outb_p(0x12,0x70);		/* specify CMOS address 0x12 */
+	cmos_disks = inb_p(0x71);	/* read the data from 0x12 */
+	/* Extract drive geometry from CMOS+BIOS if not already setup */
+	for (unit = 0; unit < MAX_DRIVES; ++unit) {
+		ide_drive_t *drive = &hwif->drives[unit];
+		if ((cmos_disks & (0xf0 >> (unit*4))) && !drive->present && !drive->nobios) {
+			drive->cyl   = drive->bios_cyl  = *(unsigned short *)BIOS;
+			drive->head  = drive->bios_head = *(BIOS+2);
+			drive->sect  = drive->bios_sect = *(BIOS+14);
+			drive->ctl   = *(BIOS+8);
+			drive->present = 1;
+		}
+		BIOS += 16;
+	}
+#endif
+}
diff -u --recursive --new-file v2.3.15/linux/drivers/block/cy82c693.c linux/drivers/block/cy82c693.c
--- v2.3.15/linux/drivers/block/cy82c693.c	Wed Jun  2 22:21:51 1999
+++ linux/drivers/block/cy82c693.c	Thu Aug 26 13:55:57 1999
@@ -369,6 +369,17 @@
 /*
  * this function is called during init and is used to setup the cy82c693 chip
  */
+/*
+ * FIXME! "pci_init_cy82c693" really should replace
+ * the "init_cy82c693_chip", it is the correct location to tinker/setup
+ * the device prior to INIT.
+ */
+
+unsigned int __init pci_init_cy82c693(struct pci_dev *dev, const char *name)
+{
+	return 0;
+}
+
 static void init_cy82c693_chip (struct pci_dev *dev)
 {
 	static int initDone = 0;
@@ -420,7 +431,7 @@
 /*
  * the init function - called for each ide channel once
  */
-__initfunc(void ide_init_cy82c693(ide_hwif_t *hwif))
+void __init ide_init_cy82c693(ide_hwif_t *hwif)
 {
 	hwif->chipset = ide_cy82c693;
 	if (hwif->dma_base)
diff -u --recursive --new-file v2.3.15/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.3.15/linux/drivers/block/genhd.c	Thu Aug 26 13:05:34 1999
+++ linux/drivers/block/genhd.c	Mon Aug 30 10:24:14 1999
@@ -18,6 +18,9 @@
 extern int parport_init(void);
 extern int chr_dev_init(void);
 extern int blk_dev_init(void);
+#ifdef CONFIG_BLK_DEV_DAC960
+extern void DAC960_Initialize(void);
+#endif
 extern int scsi_dev_init(void);
 extern int net_dev_init(void);
 extern void console_map_init(void);
@@ -39,6 +42,9 @@
 	chr_dev_init();
 	blk_dev_init();
 	sti();
+#ifdef CONFIG_BLK_DEV_DAC960
+	DAC960_Initialize();
+#endif
 #ifdef CONFIG_FC4_SOC
 	/* This has to be done before scsi_dev_init */
 	soc_probe();
@@ -49,7 +55,7 @@
 #ifdef CONFIG_BLK_CPQ_DA
 	cpqarray_init();
 #endif
-#ifdef CONFIG_INET
+#ifdef CONFIG_NET
 	net_dev_init();
 #endif
 #ifdef CONFIG_ATM
diff -u --recursive --new-file v2.3.15/linux/drivers/block/hpt34x.c linux/drivers/block/hpt34x.c
--- v2.3.15/linux/drivers/block/hpt34x.c	Thu Aug  5 18:48:45 1999
+++ linux/drivers/block/hpt34x.c	Mon Aug 30 10:18:40 1999
@@ -340,16 +340,16 @@
  */
 #define	HPT34X_PCI_INIT_REG		0x80
 
-__initfunc(unsigned int pci_init_hpt34x (struct pci_dev *dev, const char *name))
+unsigned int __init pci_init_hpt34x (struct pci_dev *dev, const char *name)
 {
 	unsigned short cmd;
 
 	pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00);
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 	if (cmd & PCI_COMMAND_MEMORY) {
-		if (dev->rom_address) {
-			pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
-			printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", dev->rom_address);
+		if (dev->resource[PCI_ROM_RESOURCE].start) {
+			pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+			printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", dev->resource[PCI_ROM_RESOURCE].start);
 		}
 		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0);
 	} else {
@@ -377,7 +377,7 @@
 	return dev->irq;
 }
 
-__initfunc(void ide_init_hpt34x (ide_hwif_t *hwif))
+void __init ide_init_hpt34x (ide_hwif_t *hwif)
 {
 	hwif->tuneproc = &hpt34x_tune_drive;
 	if (hwif->dma_base) {
@@ -385,7 +385,9 @@
 
 		pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd);
 #ifdef CONFIG_BLK_DEV_HPT34X_DMA
+#if 0
 		hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0;
+#endif
 #endif /* CONFIG_BLK_DEV_HPT34X_DMA */
 		hwif->dmaproc = &hpt34x_dmaproc;
 	} else {
diff -u --recursive --new-file v2.3.15/linux/drivers/block/hpt366.c linux/drivers/block/hpt366.c
--- v2.3.15/linux/drivers/block/hpt366.c	Fri Aug  6 11:16:54 1999
+++ linux/drivers/block/hpt366.c	Thu Aug 26 13:56:31 1999
@@ -1,7 +1,7 @@
 /*
- * linux/drivers/block/hpt366.c		Version 0.11	August 04, 1999
+ * linux/drivers/block/hpt366.c		Version 0.12	August 16, 1999
  *
- * Copyright (C) 1999			Andre Hedrick
+ * Copyright (C) 1999			Andre Hedrick <andre@suse.com>
  *
  * drive_number
  *	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
@@ -29,7 +29,6 @@
 
 const char *bad_ata66_4[] = {
 	"WDC AC310200R",
-	"QUANTUM FIREBALLP KA13.6",
 	NULL
 };
 
@@ -115,7 +114,7 @@
 };
 
 #define HPT366_DEBUG_DRIVE_INFO		0
-#define HPT366_ALLOW_ATA66_4		1
+#define HPT366_ALLOW_ATA66_4		0
 #define HPT366_ALLOW_ATA66_3		1
 #define HPT366_ALLOW_ATA33_2		1
 #define HPT366_ALLOW_ATA33_1		1
@@ -421,10 +420,9 @@
 }
 
 /*
- * hpt34x_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ * hpt366_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
  *
- * This is specific to the HPT343 UDMA bios-less chipset
- * and HPT345 UDMA bios chipset (stamped HPT363)
+ * This is specific to the HPT366 UDMA bios chipset
  * by HighPoint|Triones Technologies, Inc.
  */
 
@@ -463,7 +461,7 @@
 	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
 }
 
-__initfunc(unsigned int pci_init_hpt366 (struct pci_dev *dev, const char *name))
+unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name)
 {
 	byte ata66 = 0;
 
@@ -474,7 +472,7 @@
 	return dev->irq;
 }
 
-__initfunc(void ide_init_hpt366 (ide_hwif_t *hwif))
+void __init ide_init_hpt366 (ide_hwif_t *hwif)
 {
 	hwif->tuneproc = &hpt366_tune_drive;
 	if (hwif->dma_base) {
diff -u --recursive --new-file v2.3.15/linux/drivers/block/icside.c linux/drivers/block/icside.c
--- v2.3.15/linux/drivers/block/icside.c	Thu Jul  1 10:25:38 1999
+++ linux/drivers/block/icside.c	Thu Aug 26 13:44:03 1999
@@ -299,24 +299,7 @@
 		drive->drive_data = 250;
 	}
 
-#if 1
 	err = ide_config_drive_speed(drive, (byte) speed);
-#else
-	/*
-	 * Don't use ide_wait_cmd here - it will
-	 * attempt to set_geometry and recalibrate,
-	 * but for some reason these don't work at
-	 * this point (lost interrupt).
-	 */
-	SELECT_DRIVE(hwif, drive);
-	OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
-	OUT_BYTE(speed, IDE_NSECTOR_REG);
-	OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
-	OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
-
-	err = ide_wait_stat(drive, DRIVE_READY,
-			    BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD);
-#endif
 
 	if (err == 0) {
 		drive->id->dma_mword &= 0x00ff;
diff -u --recursive --new-file v2.3.15/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v2.3.15/linux/drivers/block/ide-cd.c	Mon Aug  9 12:34:22 1999
+++ linux/drivers/block/ide-cd.c	Tue Aug 31 16:05:22 1999
@@ -12,11 +12,13 @@
  *
  * Suggestions are welcome. Patches that work are more welcome though. ;-)
  * For those wishing to work on this driver, please be sure you download
- * and comply with the latest ATAPI standard. This document can be
- * obtained by anonymous ftp from:
- * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
+ * and comply with the latest Mt. Fuji (SFF8090 version 3) and ATAPI 
+ * (SFF-8020i rev 2.6) standards. These documents can be obtained by 
+ * anonymous ftp from:
+ * ftp://fission.dt.wdc.com/pub/standards/SFF/specs/INF-8020.PDF
+ * ftp://fission.dt.wdc.com/pub/standards/SFF/specs/INF-8090.PDF
  *
- * Drives that deviate from the ATAPI standard will be accomodated as much
+ * Drives that deviate from these standards will be accomodated as much
  * as possible via compile time or command-line options.  Since I only have
  * a few drives, you generally need to send me patches...
  *
@@ -255,11 +257,26 @@
  *			  cd-rom drivers. don't report select disc for
  *			  non-changers as well.
  *			- mask out audio playing, if the device can't do it.
- *                         
+ *
+ * 4.55  Sep 1, 1999	- Eliminated the rest of the audio ioctls, except
+ *			  for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers
+ *			  use this independently of the actual audio handling.
+ *			  They will disappear later when I get the time to
+ *			  do it cleanly.
+ *			- Minimize the TOC reading - only do it when we
+ *			  know a media change has occured.
+ *			- Moved all the CDROMREADx ioctls to the Uniform layer.
+ *			- Heiko Eissfeldt <heiko@colossus.escape.de> supplied
+ *			  some fixes for CDI.
+ *			- CD-ROM leaving door locked fix from Andries
+ *			  Brouwer <Andries.Brouwer@cwi.nl>
+ *			- Erik Andersen <andersen@xmission.com> unified
+ *			  commands across the various drivers and how
+ *			  sense errors are handled.
  *
  *************************************************************************/
  
-#define IDECD_VERSION "4.54"
+#define IDECD_VERSION "4.55"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -316,12 +333,12 @@
 		   uses this command to poll the drive, and we don't want
 		   to fill the syslog with useless errors. */
 		if (failed_command &&
-		    failed_command->c[0] == SCMD_READ_SUBCHANNEL)
+		    failed_command->c[0] == GPCMD_READ_SUBCHANNEL)
 			return;
 	}
 	if (reqbuf->error_code == 0x70 && reqbuf->sense_key  == 0x02
-	 && ((reqbuf->asc        == 0x3a && reqbuf->ascq       == 0x00) ||
-	     (reqbuf->asc        == 0x04 && reqbuf->ascq       == 0x01)))
+	 && ((reqbuf->asc      == 0x3a && reqbuf->ascq       == 0x00) ||
+	     (reqbuf->asc      == 0x04 && reqbuf->ascq       == 0x01)))
 	{
 		/*
 		 * Suppress the following errors:
@@ -358,15 +375,16 @@
 			s = buf;
 		} else {
 			int lo=0, mid, hi=ARY_LEN (sense_data_texts);
-			unsigned short key = (reqbuf->asc << 8);
+			unsigned long key = (reqbuf->sense_key << 16);
+			key |= (reqbuf->asc << 8);
 			if ( ! (reqbuf->ascq >= 0x80 && reqbuf->ascq <= 0xdd) )
 				key |= reqbuf->ascq;
-
 			s = NULL;
 
 			while (hi > lo) {
 				mid = (lo + hi) / 2;
-				if (sense_data_texts[mid].asc_ascq == key) {
+				if (sense_data_texts[mid].asc_ascq == key ||
+				    sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
 					s = sense_data_texts[mid].text;
 					break;
 				}
@@ -487,7 +505,7 @@
 	len = sizeof (*reqbuf) / 4;
 	len *= 4;
 
-	pc->c[0] = REQUEST_SENSE;
+	pc->c[0] = GPCMD_REQUEST_SENSE;
 	pc->c[4] = (unsigned char) len;
 	pc->buffer = (char *)reqbuf;
 	pc->buflen = len;
@@ -577,7 +595,7 @@
 				   because workman constantly polls the drive
 				   with this command, and we don't want
 				   to uselessly fill up the syslog. */
-				if (pc->c[0] != SCMD_READ_SUBCHANNEL)
+				if (pc->c[0] != GPCMD_READ_SUBCHANNEL)
 					printk ("%s: tray open or drive not ready\n", drive->name);
 #endif
 			} else if (sense_key == UNIT_ATTENTION) {
@@ -1073,7 +1091,7 @@
 
 	/* Set up the command */
 	memset (&pc.c, 0, sizeof (pc.c));
-	pc.c[0] = READ_10;
+	pc.c[0] = GPCMD_READ_10;
 	pc.c[7] = (nframes >> 8);
 	pc.c[8] = (nframes & 0xff);
 	put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]);
@@ -1118,7 +1136,7 @@
 	frame = sector / SECTORS_PER_FRAME;
 
 	memset (&pc.c, 0, sizeof (pc.c));
-	pc.c[0] = SEEK;
+	pc.c[0] = GPCMD_SEEK;
 	put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]);
 	(void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_seek_intr);
 }
@@ -1202,7 +1220,7 @@
 	if ((stat & DRQ_STAT) == 0) {
 		/* Some of the trailing request sense fields are optional, and
 		   some drives don't send them.  Sigh. */
-		if (pc->c[0] == REQUEST_SENSE &&
+		if (pc->c[0] == GPCMD_REQUEST_SENSE &&
 		    pc->buflen > 0 &&
 		    pc->buflen <= 5) {
 			while (pc->buflen > 0) {
@@ -1372,10 +1390,10 @@
 				   a disk.  Retry, but wait a little to give
 				   the drive time to complete the load. */
 				cdrom_sleep (HZ);
-			} else
+			} else {
 				/* Otherwise, don't retry. */
 				retries = 0;
-
+			}
 			--retries;
 		}
 
@@ -1392,12 +1410,13 @@
 		   and we think that the door is presently, lock it again.
 		   (The door was probably unlocked via an explicit
 		   CDROMEJECT ioctl.) */
-		if (CDROM_STATE_FLAGS (drive)->door_locked == 0 && drive->usage &&
-		    (pc->c[0] != REQUEST_SENSE &&
-		     pc->c[0] != ALLOW_MEDIUM_REMOVAL &&
-		     pc->c[0] != START_STOP &&
-		     pc->c[0] != MODE_SENSE_10 &&
-		     pc->c[0] != MODE_SELECT_10)) {
+		if (CDROM_STATE_FLAGS (drive)->door_locked == 0 &&
+		    (pc->c[0] != GPCMD_TEST_UNIT_READY &&
+		     pc->c[0] != GPCMD_REQUEST_SENSE &&
+		     pc->c[0] != GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL &&
+		     pc->c[0] != GPCMD_START_STOP_UNIT &&
+		     pc->c[0] != GPCMD_MODE_SENSE_10 &&
+		     pc->c[0] != GPCMD_MODE_SELECT_10)) {
 			(void) cdrom_lockdoor (drive, 1, NULL);
 		}
 		return 0;
@@ -1508,7 +1527,7 @@
 	memset (&pc, 0, sizeof (pc));
 
 	pc.sense_data = reqbuf;
-	pc.c[0] = TEST_UNIT_READY;
+	pc.c[0] = GPCMD_TEST_UNIT_READY;
 
 #if ! STANDARD_ATAPI
         /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to 
@@ -1540,7 +1559,7 @@
 		memset (&pc, 0, sizeof (pc));
 		pc.sense_data = reqbuf;
 
-		pc.c[0] = ALLOW_MEDIUM_REMOVAL;
+		pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
 		pc.c[4] = (lockflag != 0);
 		stat = cdrom_queue_packet_command (drive, &pc);
 	}
@@ -1585,7 +1604,7 @@
 	memset (&pc, 0, sizeof (pc));
 	pc.sense_data = reqbuf;
 
-	pc.c[0] = START_STOP;
+	pc.c[0] = GPCMD_START_STOP_UNIT;
 	pc.c[4] = 0x02 + (ejectflag != 0);
 	return cdrom_queue_packet_command (drive, &pc);
 }
@@ -1605,7 +1624,7 @@
 	memset (&pc, 0, sizeof (pc));
 	pc.sense_data = reqbuf;
 
-	pc.c[0] = READ_CAPACITY;
+	pc.c[0] = GPCMD_READ_CDVD_CAPACITY;
 	pc.buffer = (char *)&capbuf;
 	pc.buflen = sizeof (capbuf);
 
@@ -1629,7 +1648,7 @@
 
 	pc.buffer =  buf;
 	pc.buflen = buflen;
-	pc.c[0] = SCMD_READ_TOC;
+	pc.c[0] = GPCMD_READ_TOC_PMA_ATIP;
 	pc.c[6] = trackno;
 	pc.c[7] = (buflen >> 8);
 	pc.c[8] = (buflen & 0xff);
@@ -1657,11 +1676,10 @@
 		toc = (struct atapi_toc *) kmalloc (sizeof (struct atapi_toc),
 						    GFP_KERNEL);
 		info->toc = toc;
-	}
-
-	if (toc == NULL) {
-		printk ("%s: No cdrom TOC buffer!\n", drive->name);
-		return -EIO;
+		if (toc == NULL) {
+			printk ("%s: No cdrom TOC buffer!\n", drive->name);
+			return -ENOMEM;
+		}
 	}
 
 	/* Check to see if the existing data is still valid.
@@ -1673,9 +1691,7 @@
 
 	/* First read just the header, so we know how long the TOC is. */
 	stat = cdrom_read_tocentry (drive, 0, 1, 0, (char *)&toc->hdr,
-				    sizeof (struct atapi_toc_header) +
-				    sizeof (struct atapi_toc_entry),
-				    reqbuf);
+				    sizeof (struct atapi_toc_header), reqbuf);
 	if (stat) return stat;
 
 #if ! STANDARD_ATAPI
@@ -1690,12 +1706,46 @@
 	if (ntracks > MAX_TRACKS) ntracks = MAX_TRACKS;
 
 	/* Now read the whole schmeer. */
-	stat = cdrom_read_tocentry (drive, 0, 1, 0, (char *)&toc->hdr,
+	stat = cdrom_read_tocentry (drive, toc->hdr.first_track-1, 1, 0,
+				   (char *)&toc->hdr,
 				    sizeof (struct atapi_toc_header) +
 				    (ntracks+1) *
-				      sizeof (struct atapi_toc_entry),
-				    reqbuf);
-	if (stat) return stat;
+				    sizeof (struct atapi_toc_entry), reqbuf);
+
+	if (stat && toc->hdr.first_track > 1) {
+		/* Cds with CDI tracks only don't have any TOC entries,
+		   despite of this the returned values are
+		   first_track == last_track = number of CDI tracks + 1,
+		   so that this case is indistinguishable from the same
+		   layout plus an additional audio track.
+		   If we get an error for the regular case, we assume
+		   a CDI without additional audio tracks. In this case
+		   the readable TOC is empty (CDI tracks are not included)
+		   and only holds the Leadout entry. Heiko Eißfeldt */
+		ntracks = 0;
+		stat = cdrom_read_tocentry (drive, CDROM_LEADOUT, 1,
+					    0, (char *)&toc->hdr,
+					    sizeof (struct atapi_toc_header) +
+					   (ntracks+1) *
+					    sizeof (struct atapi_toc_entry),
+					    reqbuf);
+		if (stat) {
+			return stat;
+		}
+#if ! STANDARD_ATAPI
+		if (CDROM_CONFIG_FLAGS (drive)->toctracks_as_bcd) {
+			toc->hdr.first_track = bin2bcd(CDROM_LEADOUT);
+			toc->hdr.last_track = bin2bcd(CDROM_LEADOUT);
+		} else
+#endif  /* not STANDARD_ATAPI */
+		{
+			toc->hdr.first_track = CDROM_LEADOUT;
+			toc->hdr.last_track = CDROM_LEADOUT;
+		}
+	} else if (stat) {
+		return stat;
+	}
+
 	toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
 
 #if ! STANDARD_ATAPI
@@ -1719,10 +1769,18 @@
 	}
 
 	/* Read the multisession information. */
-	stat = cdrom_read_tocentry (drive, 0, 1, 1,
-				    (char *)&ms_tmp, sizeof (ms_tmp),
-				    reqbuf);
-	if (stat) return stat;
+	if (toc->hdr.first_track != CDROM_LEADOUT) {
+		/* Read the multisession information. */
+		stat = cdrom_read_tocentry (drive, toc->hdr.first_track-1, 1, 1,
+					   (char *)&ms_tmp, sizeof (ms_tmp),
+					    reqbuf);
+		if (stat) return stat;
+	} else {
+		ms_tmp.ent.addr.msf.minute = 0;
+		ms_tmp.ent.addr.msf.second = 2;
+		ms_tmp.ent.addr.msf.frame  = 0;
+		ms_tmp.hdr.first_track = ms_tmp.hdr.last_track = CDROM_LEADOUT;
+	}
 
 #if ! STANDARD_ATAPI
 	if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd)
@@ -1736,7 +1794,10 @@
 	toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
 
 	/* Now try to get the total cdrom capacity. */
-	stat = cdrom_read_capacity (drive, &toc->capacity, reqbuf);
+	stat = cdrom_get_last_written(MKDEV(HWIF(drive)->major,
+				      drive->select.b.unit << PARTN_BITS),
+				     (long *)&toc->capacity);
+	if (stat) stat = cdrom_read_capacity (drive, &toc->capacity, reqbuf);
 	if (stat) toc->capacity = 0x1fffff;
 
 	HWIF(drive)->gd->sizes[drive->select.b.unit << PARTN_BITS]
@@ -1762,7 +1823,7 @@
 
 	pc.buffer =  buf;
 	pc.buflen = buflen;
-	pc.c[0] = SCMD_READ_SUBCHANNEL;
+	pc.c[0] = GPCMD_READ_SUBCHANNEL;
 	pc.c[1] = 2;     /* MSF addressing */
 	pc.c[2] = 0x40;  /* request subQ data */
 	pc.c[3] = format;
@@ -1785,7 +1846,7 @@
 
 	pc.buffer =  buf;
 	pc.buflen = buflen;
-	pc.c[0] = MODE_SENSE_10;
+	pc.c[0] = GPCMD_MODE_SENSE_10;
 	pc.c[2] = pageno | (modeflag << 6);
 	pc.c[7] = (buflen >> 8);
 	pc.c[8] = (buflen & 0xff);
@@ -1803,7 +1864,7 @@
 
 	pc.buffer =  buf;
 	pc.buflen = - buflen;
-	pc.c[0] = MODE_SELECT_10;
+	pc.c[0] = GPCMD_MODE_SELECT_10;
 	pc.c[1] = 0x10;
 	pc.c[2] = pageno;
 	pc.c[7] = (buflen >> 8);
@@ -1826,7 +1887,7 @@
 	else
 	    speed *= 177;   /* Nx to kbytes/s */
 
-	pc.c[0] = SET_CD_SPEED;
+	pc.c[0] = GPCMD_SET_SPEED;
 	/* Read Drive speed in kbytes/second MSB */
 	pc.c[2] = (speed >> 8) & 0xff;	
 	/* Read Drive speed in kbytes/second LSB */
@@ -1842,67 +1903,6 @@
 	return cdrom_queue_packet_command (drive, &pc);
 }
 
-static int
-cdrom_play_lba_range_1 (ide_drive_t *drive, int lba_start, int lba_end,
-			    struct atapi_request_sense *reqbuf)
-{
-	struct packet_command pc;
-
-	memset (&pc, 0, sizeof (pc));
-	pc.sense_data = reqbuf;
-
-	pc.c[0] = SCMD_PLAYAUDIO_MSF;
-	lba_to_msf (lba_start, &pc.c[3], &pc.c[4], &pc.c[5]);
-	lba_to_msf (lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]);
-
-#if ! STANDARD_ATAPI
-	if (CDROM_CONFIG_FLAGS (drive)->playmsf_as_bcd) {
-		pc.c[3] = bin2bcd (pc.c[3]);
-		pc.c[4] = bin2bcd (pc.c[4]);
-		pc.c[5] = bin2bcd (pc.c[5]);
-		pc.c[6] = bin2bcd (pc.c[6]);
-		pc.c[7] = bin2bcd (pc.c[7]);
-		pc.c[8] = bin2bcd (pc.c[8]);
-	}
-#endif /* not STANDARD_ATAPI */
-
-	return cdrom_queue_packet_command (drive, &pc);
-}
-
-
-/* Play audio starting at LBA LBA_START and finishing with the
-   LBA before LBA_END. */
-static int
-cdrom_play_lba_range (ide_drive_t *drive, int lba_start, int lba_end,
-		      struct atapi_request_sense *reqbuf)
-{
-	int i, stat = 0;
-	struct atapi_request_sense my_reqbuf;
-
-	if (reqbuf == NULL)
-		reqbuf = &my_reqbuf;
-
-	/* Some drives, will, for certain audio cds,
-	   give an error if you ask them to play the entire cd using the
-	   values which are returned in the TOC.  The play will succeed,
-	   however, if the ending address is adjusted downwards
-	   by a few frames. */
-	for (i=0; i<75; i++) {
-		stat = cdrom_play_lba_range_1 (drive, lba_start, lba_end,
-					       reqbuf);
-
-		if (stat == 0 ||
-		    !(reqbuf->sense_key == ILLEGAL_REQUEST &&
-		      reqbuf->asc == 0x24))
-			return stat;
-
-		--lba_end;
-		if (lba_end <= lba_start) break;
-	}
-
-	return stat;
-}
-
 
 static
 int cdrom_get_toc_entry (ide_drive_t *drive, int track,
@@ -1910,17 +1910,12 @@
 			 struct atapi_request_sense *reqbuf)
 {
 	struct cdrom_info *info = drive->driver_data;
-	int stat, ntracks;
-	struct atapi_toc *toc;
-
-	/* Make sure our saved TOC is valid. */
-	stat = cdrom_read_toc (drive, reqbuf);
-	if (stat) return stat;
-
-	toc = info->toc;
+	struct atapi_toc *toc = info->toc;
+	int ntracks;
 
 	/* Check validity of requested track number. */
 	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
+	if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0;
 	if (track == CDROM_LEADOUT)
 		*ent = &toc->ent[ntracks];
 	else if (track < toc->hdr.first_track ||
@@ -1933,44 +1928,6 @@
 }
 
 
-static int
-cdrom_read_block (ide_drive_t *drive, int format, int lba, int nblocks,
-		  char *buf, int buflen,
-		  struct atapi_request_sense *reqbuf)
-{
-	struct packet_command pc;
-	struct atapi_request_sense my_reqbuf;
-
-	if (reqbuf == NULL)
-		reqbuf = &my_reqbuf;
-
-	memset (&pc, 0, sizeof (pc));
-	pc.sense_data = reqbuf;
-
-	pc.buffer = buf;
-	pc.buflen = buflen;
-
-#if ! STANDARD_ATAPI
-	if (CDROM_CONFIG_FLAGS (drive)->nec260)
-		pc.c[0] = 0xd4;
-	else
-#endif  /* not STANDARD_ATAPI */
-		pc.c[0] = READ_CD;
-
-	pc.c[1] = (format << 2);
-	put_unaligned(htonl(lba), (unsigned int *) &pc.c[2]);
-	pc.c[8] = (nblocks & 0xff);
-	pc.c[7] = ((nblocks>>8) & 0xff);
-	pc.c[6] = ((nblocks>>16) & 0xff);
-	if (format <= 1)
-		pc.c[9] = 0xf8;         /* returns 2352 for any format */
-	else
-		pc.c[9] = 0x10;
-
-	return cdrom_queue_packet_command (drive, &pc);
-}
-
-
 /* If SLOT<0, unload the current slot.  Otherwise, try to load SLOT. */
 static int
 cdrom_load_unload (ide_drive_t *drive, int slot,
@@ -2005,7 +1962,7 @@
 		memset (&pc, 0, sizeof (pc));
 		pc.sense_data = reqbuf;
 
-		pc.c[0] = LOAD_UNLOAD;
+		pc.c[0] = GPCMD_LOAD_UNLOAD;
 		pc.c[4] = 2 + (slot >= 0);
 		pc.c[8] = slot;
 		return cdrom_queue_packet_command (drive, &pc);
@@ -2026,7 +1983,7 @@
 
 	pc.buffer = buf;
 	pc.buflen = buflen;
-	pc.c[0] = MECHANISM_STATUS;
+	pc.c[0] = GPCMD_MECHANISM_STATUS;
 	pc.c[8] = (buflen >> 8);
 	pc.c[9] = (buflen & 0xff);
 	return cdrom_queue_packet_command (drive, &pc);
@@ -2098,124 +2055,8 @@
 			 
 {
 	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
-	struct cdrom_info *info = drive->driver_data;
-
 
 	switch (cmd) {
-	case CDROMREADRAW:
-	case CDROMREADMODE1:
-	case CDROMREADMODE2: {
-		struct cdrom_msf msf;
-		int blocksize, format, stat, lba;
-		struct atapi_toc *toc;
-		char *buf;
-
-		if (cmd == CDROMREADMODE1) {
-			blocksize = CD_FRAMESIZE;
-			format = 2;
-		} else {	/* for RAW and MODE2. */
-			blocksize = CD_FRAMESIZE_RAW;
-			format = 0;
-		}
-		
-		copy_from_user_ret(&msf, (void *)arg, sizeof (msf), -EFAULT); 
-
-		lba = msf_to_lba(msf.cdmsf_min0, 
-				 msf.cdmsf_sec0, 
-				 msf.cdmsf_frame0);
-
-		/* Make sure the TOC is up to date. */
-		if (cmd != CDROMREADRAW) {
-			stat = cdrom_read_toc (drive, NULL);
-			if (stat) 
-				return stat;
-
-			toc = info->toc;
-
-			if (lba < 0 || lba >= toc->capacity)
-				return -EINVAL;
-		}
-
-		buf = (char *) kmalloc (blocksize, GFP_KERNEL);
-		if (buf == NULL)
-			return -ENOMEM;
-
-		stat = cdrom_read_block (drive, format, lba, 1, buf,
-					 blocksize, NULL);
-
-		if (stat == 0) {
-			if (cmd == CDROMREADMODE2) {
-				/* For Mode2, skip the Sync, Header, and Subheader */
-				copy_to_user_ret((char *)arg, buf+16, CD_FRAMESIZE_RAW0, -EFAULT);
-			} else {
-				copy_to_user_ret((char *)arg, buf, blocksize, -EFAULT);
-			}
-		}
-
-		kfree (buf);
-		return stat;
-	}
-
-	/* Read 2352 byte blocks from audio tracks. */
-	case CDROMREADAUDIO: {
-		int stat, lba;
-		struct atapi_toc *toc;
-		struct cdrom_read_audio ra;
-		char *buf;
-
-		/* Make sure the TOC is up to date. */
-		stat = cdrom_read_toc (drive, NULL);
-		if (stat) return stat;
-
-		toc = info->toc;
-
-		if (copy_from_user(&ra, (void *)arg, sizeof (ra)))
-			return -EFAULT;
-
-		if (ra.nframes < 0 || ra.nframes > toc->capacity)
-			return -EINVAL;
-		else if (ra.nframes == 0)
-			return 0;
-
-		if (!access_ok(VERIFY_WRITE, ra.buf, ra.nframes * CD_FRAMESIZE_RAW))
-			return -EFAULT;
-
-		if (ra.addr_format == CDROM_MSF)
-			lba = msf_to_lba (ra.addr.msf.minute,
-					  ra.addr.msf.second,
-					  ra.addr.msf.frame);
-		else if (ra.addr_format == CDROM_LBA)
-			lba = ra.addr.lba;
-		else
-			return -EINVAL;
-
-		if (lba < 0 || lba >= toc->capacity)
-			return -EINVAL;
-
-		buf = (char *) kmalloc (CDROM_NBLOCKS_BUFFER*CD_FRAMESIZE_RAW,
-					GFP_KERNEL);
-		if (buf == NULL)
-			return -ENOMEM;
-
-		while (ra.nframes > 0) {
-			int this_nblocks = ra.nframes;
-			if (this_nblocks > CDROM_NBLOCKS_BUFFER)
-				this_nblocks = CDROM_NBLOCKS_BUFFER;
-			stat = cdrom_read_block
-				(drive, 1, lba, this_nblocks,
-				 buf, this_nblocks * CD_FRAMESIZE_RAW, NULL);
-			if (stat) break;
-
-			__copy_to_user(ra.buf, buf,this_nblocks * CD_FRAMESIZE_RAW);
-			ra.buf += this_nblocks * CD_FRAMESIZE_RAW;
-			ra.nframes -= this_nblocks;
-			lba += this_nblocks;
-		}
-
-		kfree (buf);
-		return stat;
-	}
-
  	case CDROMSETSPINDOWN: {
  		char spindown;
  		char buffer[16];
@@ -2224,13 +2065,13 @@
  		if (copy_from_user(&spindown, (void *) arg, sizeof(char)))
 			return -EFAULT;
  
- 		stat = cdrom_mode_sense (drive, PAGE_CDROM, 0, buffer,
+ 		stat = cdrom_mode_sense (drive, GPMODE_CDROM_PAGE, 0, buffer,
  					 sizeof (buffer), NULL);
  		if (stat) return stat;
 
  		buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
 
- 		return cdrom_mode_select (drive, PAGE_CDROM, buffer,
+ 		return cdrom_mode_select (drive, GPMODE_CDROM_PAGE, buffer,
  					  sizeof (buffer), NULL);			
  	} 
  
@@ -2239,7 +2080,7 @@
  		char buffer[16];
  		int stat;
  
- 		stat = cdrom_mode_sense (drive, PAGE_CDROM, 0, buffer,
+ 		stat = cdrom_mode_sense (drive, GPMODE_CDROM_PAGE, 0, buffer,
                                          sizeof (buffer), NULL);
  		if (stat) return stat;
  
@@ -2251,64 +2092,12 @@
  		return 0;
  	}
   
-#ifdef ALLOW_TEST_PACKETS
-	case 0x1234: {
-		int stat;
-		struct packet_command pc;
-		int len, lena;
-
-		memset (&pc, 0, sizeof (pc));
-
-		if (copy_from_user(&pc.c, (void *) arg, sizeof (pc.c)))
-			return -EFAULT;
-		
-		arg += sizeof (pc.c);
-
-		if (copy_from_user (&len, (void *) arg , sizeof (len)))
-			return -EFAULT;
-
-		arg += sizeof (len);
-
-		lena = len;
-		if (lena  < 0) lena = -lena;
-
-		{
-			char buf[lena];
-			if (len > 0) {
-				stat = verify_area (VERIFY_WRITE,
-						    (void *) arg, len);
-				if (stat) return stat;
-			}
-			else if (len < 0) {
-				stat = verify_area (VERIFY_READ,
-						    (void *) arg, -len);
-				if (stat) return stat;
-				copy_from_user (buf, (void*)arg, -len);
-			}
-
-			if (len != 0) {
-				pc.buflen = len;
-				pc.buffer = buf;
-			}
-
-			stat = cdrom_queue_packet_command (drive, &pc);
-
-			if (len > 0)
-				copy_to_user ((void *)arg, buf, len);
-		}
-
-		return stat;
-	}
-#endif
-
 	default:
 		return -EINVAL;
 	}
 
 }
 
-
-
 static
 int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
 			   unsigned int cmd, void *arg)
@@ -2318,47 +2107,6 @@
 	struct cdrom_info *info = drive->driver_data;
 
 	switch (cmd) {
-	case CDROMSUBCHNL: {
-		struct atapi_cdrom_subchnl scbuf;
-		int stat;
-		struct cdrom_subchnl *subchnl = (struct cdrom_subchnl *)arg;
-
-		stat = cdrom_read_subchannel (drive, 1, /* current position */
-					      (char *)&scbuf, sizeof (scbuf),
-					      NULL);
-		if (stat) return stat;
-
-#if ! STANDARD_ATAPI
-		if (CDROM_CONFIG_FLAGS (drive)->subchan_as_bcd) {
-			msf_from_bcd (&scbuf.acdsc_absaddr.msf);
-			msf_from_bcd (&scbuf.acdsc_reladdr.msf);
-		}
-		if (CDROM_CONFIG_FLAGS (drive)->tocaddr_as_bcd)
-			scbuf.acdsc_trk = bcd2bin (scbuf.acdsc_trk);
-#endif /* not STANDARD_ATAPI */
-
-		subchnl->cdsc_absaddr.msf.minute =
-			scbuf.acdsc_absaddr.msf.minute;
-		subchnl->cdsc_absaddr.msf.second =
-			scbuf.acdsc_absaddr.msf.second;
-		subchnl->cdsc_absaddr.msf.frame =
-			scbuf.acdsc_absaddr.msf.frame;
-
-		subchnl->cdsc_reladdr.msf.minute =
-			scbuf.acdsc_reladdr.msf.minute;
-		subchnl->cdsc_reladdr.msf.second =
-			scbuf.acdsc_reladdr.msf.second;
-		subchnl->cdsc_reladdr.msf.frame =
-			scbuf.acdsc_reladdr.msf.frame;
-
-		subchnl->cdsc_audiostatus = scbuf.acdsc_audiostatus;
-		subchnl->cdsc_ctrl = scbuf.acdsc_ctrl;
-		subchnl->cdsc_trk  = scbuf.acdsc_trk;
-		subchnl->cdsc_ind  = scbuf.acdsc_ind;
-
-		return 0;
-	}
-
 	case CDROMREADTOCHDR: {
 		int stat;
 		struct cdrom_tochdr *tochdr = (struct cdrom_tochdr *) arg;
@@ -2386,55 +2134,22 @@
 
 		tocentry->cdte_ctrl = toce->control;
 		tocentry->cdte_adr  = toce->adr;
-		tocentry->cdte_format = CDROM_LBA;
-		tocentry->cdte_addr.lba = toce->addr.lba;
+		if (tocentry->cdte_format == CDROM_MSF) {
+			lba_to_msf (toce->addr.lba,
+				   &tocentry->cdte_addr.msf.minute,
+				   &tocentry->cdte_addr.msf.second,
+				   &tocentry->cdte_addr.msf.frame);
+		} else
+			tocentry->cdte_addr.lba = toce->addr.lba;
 
 		return 0;
 	}
 
-	case CDROMPLAYMSF: {
-		struct cdrom_msf *msf = (struct cdrom_msf *) arg;
-		int lba_start, lba_end;
-
-		lba_start = msf_to_lba (msf->cdmsf_min0, msf->cdmsf_sec0,
-					msf->cdmsf_frame0);
-		lba_end = msf_to_lba (msf->cdmsf_min1, msf->cdmsf_sec1,
-				      msf->cdmsf_frame1) + 1;
-
-		if (lba_end <= lba_start) return -EINVAL;
-
-		return cdrom_play_lba_range (drive, lba_start, lba_end, NULL);
-	}
-
-	/* Like just about every other Linux cdrom driver, we ignore the
-	   index part of the request here. */
-	case CDROMPLAYTRKIND: {
-		int stat, lba_start, lba_end;
-		struct cdrom_ti *ti = (struct cdrom_ti *)arg;
-		struct atapi_toc_entry *first_toc, *last_toc;
-
-		stat = cdrom_get_toc_entry (drive, ti->cdti_trk0, &first_toc,
-					    NULL);
-		if (stat) return stat;
-		stat = cdrom_get_toc_entry (drive, ti->cdti_trk1, &last_toc,
-					    NULL);
-		if (stat) return stat;
-
-		if (ti->cdti_trk1 != CDROM_LEADOUT) ++last_toc;
-		lba_start = first_toc->addr.lba;
-		lba_end   = last_toc->addr.lba;
-
-		if (lba_end <= lba_start) return -EINVAL;
-
-		return cdrom_play_lba_range (drive, lba_start, lba_end, NULL);
-	}
-
 	default:
 		return -EINVAL;
 	}
 }
 
-
 static
 int ide_cdrom_reset (struct cdrom_device_info *cdi)
 {
@@ -2486,7 +2201,7 @@
         do {    /* we seem to get stat=0x01,err=0x00 the first time (??) */
                 if (attempts-- <= 0)
                         return 0;
-                stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0,
+                stat = cdrom_mode_sense (drive, GPMODE_CAPABILITIES_PAGE, 0,
                                         (char *)&buf, sizeof (buf), NULL);
         } while (stat);
 
@@ -2579,12 +2294,6 @@
 		if (stat && my_reqbuf.sense_key == NOT_READY)
 			return -ENOENT;
 
-		if (stat == 0 || my_reqbuf.sense_key == UNIT_ATTENTION) {
-			stat = cdrom_read_toc (drive, &my_reqbuf);
-			if (stat)
-				return stat;
-		}
-
 		if (was_locked)
 			(void) cdrom_lockdoor (drive, 1, NULL);
 
@@ -2639,15 +2348,10 @@
 int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
 				struct cdrom_multisession *ms_info)
 {
-	int stat;
 	struct atapi_toc *toc;
 	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
 	struct cdrom_info *info = drive->driver_data;
 
-	/* Make sure the TOC information is valid. */
-	stat = cdrom_read_toc (drive, NULL);
-	if (stat) return stat;
-
 	toc = info->toc;
 	ms_info->addr.lba = toc->last_session_lba;
 	ms_info->xa_flag = toc->xa_flag;
@@ -2655,7 +2359,6 @@
 	return 0;
 }
 
-
 static
 int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
 		       struct cdrom_mcn *mcn_info)
@@ -2689,9 +2392,9 @@
 {
 	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
 	struct cdrom_info *info = drive->driver_data;
-
+	struct atapi_request_sense reqbuf;
 	int retval;
-
+	
 	if (slot_nr == CDSL_CURRENT) {
 		(void) cdrom_check_status (drive, NULL);
 		retval = CDROM_STATE_FLAGS (drive)->media_changed;
@@ -2717,7 +2420,17 @@
 
 		retval = ci->slots[slot_nr].change;
 	}
-
+	
+	/* if the media has changed, check if a disc is in the drive
+	   and read the toc info. */
+	if (retval || !CDROM_STATE_FLAGS (drive)->toc_valid) {
+		/* if cdrom_read_toc fails, return 1 to indicate
+		   that a disc change has occured. there might not
+		   be a disc in the drive. */
+		if ((retval = cdrom_read_toc (drive, &reqbuf)))
+			return 1;
+	}
+		
 	return retval;
 }
 
@@ -2819,7 +2532,7 @@
 	do {	/* we seem to get stat=0x01,err=0x00 the first time (??) */
 		if (attempts-- <= 0)
 			return 0;
-		stat = cdrom_mode_sense (drive, PAGE_CAPABILITIES, 0,
+		stat = cdrom_mode_sense (drive, GPMODE_CAPABILITIES_PAGE, 0,
 				 	(char *)&buf, sizeof (buf), NULL);
 	} while (stat);
 
@@ -2989,7 +2702,7 @@
 	drive->special.all = 0;
 	drive->ready_stat = 0;
 
-	CDROM_STATE_FLAGS (drive)->media_changed = 0;
+	CDROM_STATE_FLAGS (drive)->media_changed = 1;
 	CDROM_STATE_FLAGS (drive)->toc_valid     = 0;
 	CDROM_STATE_FLAGS (drive)->door_locked   = 0;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/block/ide-cd.h linux/drivers/block/ide-cd.h
--- v2.3.15/linux/drivers/block/ide-cd.h	Wed Aug 18 16:43:30 1999
+++ linux/drivers/block/ide-cd.h	Tue Aug 31 16:11:58 1999
@@ -1,9 +1,9 @@
 #ifndef _IDE_CD_H
 #define _IDE_CD_H
 /*
- *  linux/drivers/block/ide_modes.h
+ *  linux/drivers/block/ide_cd.h
  *
- *  Copyright (C) 1996  Erik Andersen
+ *  Copyright (C) 1996, 1997, 1998  Erik Andersen
  *  Copyright (C) 1998, 1999 Jens Axboe
  */
 
@@ -55,65 +55,6 @@
 #define REQUEST_SENSE_COMMAND 4316
 #define RESET_DRIVE_COMMAND   4317
 
-/*
- * For controlling drive spindown time.
- */
-#define CDROMGETSPINDOWN        0x531d
-#define CDROMSETSPINDOWN        0x531e
- 
-
-/* Some ATAPI command opcodes (just like SCSI).
-   (Some other cdrom-specific codes are in cdrom.h.) */
-#define TEST_UNIT_READY         0x00
-#define REQUEST_SENSE           0x03
-#define INQUIRY                 0x12
-#define START_STOP              0x1b
-#define ALLOW_MEDIUM_REMOVAL    0x1e
-#define READ_CAPACITY           0x25
-#define READ_10                 0x28
-#define SEEK			0x2b
-#define READ_HEADER             0x44
-#define STOP_PLAY_SCAN		0x4e
-#define MODE_SELECT_10          0x55
-#define MODE_SENSE_10           0x5a
-#define LOAD_UNLOAD             0xa6
-#define READ_12                 0xa8
-#define READ_CD_MSF             0xb9
-#define SCAN			0xba
-#define SET_CD_SPEED            0xbb
-#define PLAY_CD                 0xbc
-#define MECHANISM_STATUS        0xbd
-#define READ_CD                 0xbe
-
-/* MMC2/MTFuji Opcodes */
-#define BLANK			0xa1
-#define CLOSE_TRACK		0x5b
-#define ERASE			0x2c
-#define FORMAT_UNIT		0x04
-#define GET_CONFIGURATION	0x46
-#define GET_EVENT		0xa4
-#define GET_PERFORMANCE		0xac
-#define READ_BUFFER		0x3c
-#define READ_DISC_INFO		0x51
-
-/* Page codes for mode sense/set */
-#define PAGE_READERR            0x01
-#define PAGE_CDROM              0x0d
-#define PAGE_AUDIO              0x0e
-#define PAGE_CAPABILITIES       0x2a
-#define PAGE_ALL                0x3f
-
-/* ATAPI sense keys (from table 140 of ATAPI 2.6) */
-#define NO_SENSE                0x00
-#define RECOVERED_ERROR         0x01
-#define NOT_READY               0x02
-#define MEDIUM_ERROR            0x03
-#define HARDWARE_ERROR          0x04
-#define ILLEGAL_REQUEST         0x05
-#define UNIT_ATTENTION          0x06
-#define DATA_PROTECT            0x07
-#define ABORTED_COMMAND         0x0b
-#define MISCOMPARE              0x0e
 
 /* Configuration flags.  These describe the capabilities of the drive.
    They generally do not change after initialization, unless we learn
@@ -287,6 +228,9 @@
 } mechtype_t;
 
 
+/* This should probably go into cdrom.h along with the other
+ * generic stuff now in the Mt. Fuji spec.
+ */
 struct atapi_capabilities_page {
 #if defined(__BIG_ENDIAN_BITFIELD)
 	__u8 parameters_saveable : 1;
@@ -608,11 +552,85 @@
 
 #define ARY_LEN(a) ((sizeof(a) / sizeof(a[0])))
 
+/* This stuff should be in cdrom.h, since it is now generic... */
+
+/* ATAPI sense keys (from table 140 of ATAPI 2.6) */
+#define NO_SENSE                0x00
+#define RECOVERED_ERROR         0x01
+#define NOT_READY               0x02
+#define MEDIUM_ERROR            0x03
+#define HARDWARE_ERROR          0x04
+#define ILLEGAL_REQUEST         0x05
+#define UNIT_ATTENTION          0x06
+#define DATA_PROTECT            0x07
+#define ABORTED_COMMAND         0x0b
+#define MISCOMPARE              0x0e
+
+ 
+
+/* This stuff should be in cdrom.h, since it is now generic... */
 #if VERBOSE_IDE_CD_ERRORS
 
-/* From Table 124 of the ATAPI 1.2 spec.
-   Unchanged in Table 140 of the ATAPI 2.6 draft standard. */
+ /* The generic packet command opcodes for CD/DVD Logical Units,
+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ 
+const struct {
+	unsigned short packet_command;
+	const char * const text;
+} packet_command_texts[] = {
+	{ GPCMD_TEST_UNIT_READY, "Test Unit Ready" },
+	{ GPCMD_REQUEST_SENSE, "Request Sense" },
+	{ GPCMD_FORMAT_UNIT, "Format Unit" },
+	{ GPCMD_INQUIRY, "Inquiry" },
+	{ GPCMD_START_STOP_UNIT, "Start/Stop Unit" },
+	{ GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" },
+	{ GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" },
+	{ GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" },
+	{ GPCMD_READ_10, "Read 10" },
+	{ GPCMD_WRITE_10, "Write 10" },
+	{ GPCMD_SEEK, "Seek" },
+	{ GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" },
+	{ GPCMD_VERIFY_10, "Verify 10" },
+	{ GPCMD_FLUSH_CACHE, "Flush Cache" },
+	{ GPCMD_READ_SUBCHANNEL, "Read Subchannel" },
+	{ GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" },
+	{ GPCMD_READ_HEADER, "Read Header" },
+	{ GPCMD_PLAY_AUDIO_10, "Play Audio 10" },
+	{ GPCMD_GET_CONFIGURATION, "Get Configuration" },
+	{ GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" },
+	{ GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" },
+	{ GPCMD_GET_EVENT_STATUS_NOTIFICATION, "Get Event Status Notification" },
+	{ GPCMD_PAUSE_RESUME, "Pause/Resume" },
+	{ GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" },
+	{ GPCMD_READ_DISC_INFO, "Read Disc Info" },
+	{ GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" },
+	{ GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" },
+	{ GPCMD_SEND_OPC, "Send OPC" },
+	{ GPCMD_MODE_SELECT_10, "Mode Select 10" },
+	{ GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" },
+	{ GPCMD_MODE_SENSE_10, "Mode Sense 10" },
+	{ GPCMD_CLOSE_TRACK, "Close Track" },
+	{ GPCMD_BLANK, "Blank" },
+	{ GPCMD_SEND_EVENT, "Send Event" },
+	{ GPCMD_SEND_KEY, "Send Key" },
+	{ GPCMD_REPORT_KEY, "Report Key" },
+	{ GPCMD_LOAD_UNLOAD, "Load/Unload" },
+	{ GPCMD_SET_READ_AHEAD, "Set Read-ahead" },
+	{ GPCMD_READ_12, "Read 12" },
+	{ GPCMD_GET_PERFORMANCE, "Get Performance" },
+	{ GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" },
+	{ GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" },
+	{ GPCMD_SET_STREAMING, "Set Streaming" },
+	{ GPCMD_READ_CD_MSF, "Read CD MSF" },
+	{ GPCMD_SCAN, "Scan" },
+	{ GPCMD_SET_SPEED, "Set Speed" },
+	{ GPCMD_PLAY_CD, "Play CD" },
+	{ GPCMD_MECHANISM_STATUS, "Mechanism Status" },
+	{ GPCMD_READ_CD, "Read CD" },
+};
 
+
+
+/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
 const char * const sense_key_texts[16] = {
 	"No sense data",
 	"Recovered error",
@@ -632,162 +650,108 @@
 	"(reserved)",
 };
 
-
-/* From Table 37 of the ATAPI 2.6 draft standard. */
-const struct {
-	unsigned short packet_command;
-	const char * const text;
-} packet_command_texts[] = {
-	{ TEST_UNIT_READY, "Test Unit Ready" },
-	{ REQUEST_SENSE, "Request Sense" },
-	{ INQUIRY, "Inquiry" },
-	{ START_STOP, "Start Stop Unit" },
-	{ ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" },
-	{ READ_CAPACITY, "Read CD-ROM Capacity" },
-	{ READ_10, "Read(10)" },
-	{ SEEK, "Seek" },
-	{ SCMD_READ_TOC, "Read TOC" },
-	{ SCMD_READ_SUBCHANNEL, "Read Sub-Channel" },
-	{ READ_HEADER, "Read Header" },
-	{ STOP_PLAY_SCAN, "Stop Play/Scan" },
-	{ SCMD_PLAYAUDIO10, "Play Audio" },
-	{ SCMD_PLAYAUDIO_MSF, "Play Audio MSF" },
-	{ SCMD_PAUSE_RESUME, "Pause/Resume" },
-	{ MODE_SELECT_10, "Mode Select" },
-	{ MODE_SENSE_10, "Mode Sense" },
-	{ LOAD_UNLOAD, "Load/Unload CD" },
-	{ READ_12, "Read(12)" },
-	{ GET_PERFORMANCE, "Get Performance" },
-	{ READ_CD_MSF, "Read CD MSF" },
-	{ SCAN, "Scan" },
-	{ SET_CD_SPEED, "Set CD Speed" },
-	{ PLAY_CD, "Play CD" },
-	{ MECHANISM_STATUS, "Mechanism Status" },
-	{ READ_CD, "Read CD" },
-};
-
-
-/* From Table 125 of the ATAPI 1.2 spec.,
-   with additions from Tables 141 and 142 of the ATAPI 2.6 draft standard. */
-
+/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
 const struct {
-	unsigned short asc_ascq;
+	unsigned long asc_ascq;
 	const char * const text;
 } sense_data_texts[] = {
-	{ 0x0000, "No additional sense information" },
-
-	{ 0x0011, "Audio play operation in progress" },
-	{ 0x0012, "Audio play operation paused" },
-	{ 0x0013, "Audio play operation successfully completed" },
-	{ 0x0014, "Audio play operation stopped due to error" },
-	{ 0x0015, "No current audio status to return" },
-
-	{ 0x0100, "Mechanical positioning or changer error" },
-
-	{ 0x0200, "No seek complete" },
-
-	{ 0x0400, "Logical unit not ready - cause not reportable" },
-	{ 0x0401,
-	  "Logical unit not ready - in progress (sic) of becoming ready" },
-	{ 0x0402, "Logical unit not ready - initializing command required" },
-	{ 0x0403, "Logical unit not ready - manual intervention required" },
-
-	{ 0x0501, "Media load - eject failed" },
-
-	{ 0x0600, "No reference position found" },
-
-	{ 0x0900, "Track following error" },
-	{ 0x0901, "Tracking servo failure" },
-	{ 0x0902, "Focus servo failure" },
-	{ 0x0903, "Spindle servo failure" },
-
-	{ 0x1100, "Unrecovered read error" },
-	{ 0x1106, "CIRC unrecovered error" },
-
-	{ 0x1500, "Random positioning error" },
-	{ 0x1501, "Mechanical positioning or changer error" },
-	{ 0x1502, "Positioning error detected by read of medium" },
-
-	{ 0x1700, "Recovered data with no error correction applied" },
-	{ 0x1701, "Recovered data with retries" },
-	{ 0x1702, "Recovered data with positive head offset" },
-	{ 0x1703, "Recovered data with negative head offset" },
-	{ 0x1704, "Recovered data with retries and/or CIRC applied" },
-	{ 0x1705, "Recovered data using previous sector ID" },
-
-	{ 0x1800, "Recovered data with error correction applied" },
-	{ 0x1801, "Recovered data with error correction and retries applied" },
-	{ 0x1802, "Recovered data - the data was auto-reallocated" },
-	{ 0x1803, "Recovered data with CIRC" },
-	{ 0x1804, "Recovered data with L-EC" },
-	/* Following two not in 2.6. */
-	{ 0x1805, "Recovered data - recommend reassignment" },
-	{ 0x1806, "Recovered data - recommend rewrite" },
-
-	{ 0x1a00, "Parameter list length error" },
-
-	{ 0x2000, "Invalid command operation code" },
-
-	{ 0x2100, "Logical block address out of range" },
-
-	{ 0x2400, "Invalid field in command packet" },
-
-	{ 0x2600, "Invalid field in parameter list" },
-	{ 0x2601, "Parameter not supported" },
-	{ 0x2602, "Parameter value invalid" },
-	/* Following code not in 2.6. */
-	{ 0x2603, "Threshold parameters not supported" },
-
-	{ 0x2800, "Not ready to ready transition, medium may have changed" },
-
-	{ 0x2900, "Power on, reset or bus device reset occurred" },
-
-	{ 0x2a00, "Parameters changed" },
-	{ 0x2a01, "Mode parameters changed" },
-
-	{ 0x3000, "Incompatible medium installed" },
-	{ 0x3001, "Cannot read medium - unknown format" },
-	{ 0x3002, "Cannot read medium - incompatible format" },
-
-	/* Following code not in 2.6. */
-	{ 0x3700, "Rounded parameter" },
-
-	{ 0x3900, "Saving parameters not supported" },
-
-	{ 0x3a00, "Medium not present" },
-
-	{ 0x3f00, "ATAPI CD-ROM drive operating conditions have changed" },
-	{ 0x3f01, "Microcode has been changed" },
-	/* Following two not in 2.6. */
-	{ 0x3f02, "Changed operating definition" },
-	{ 0x3f03, "Inquiry data has changed" },
-
-	{ 0x4000, "Diagnostic failure on component (ASCQ)" },
-
-	{ 0x4400, "Internal ATAPI CD-ROM drive failure" },
-
-	{ 0x4e00, "Overlapped commands attempted" },
-
-	{ 0x5300, "Media load or eject failed" },
-	{ 0x5302, "Medium removal prevented" },
-
-	{ 0x5700, "Unable to recover table of contents" },
-
-	{ 0x5a00, "Operator request or state change input (unspecified)" },
-	{ 0x5a01, "Operator medium removal request" },
-
-	/* Following two not in 2.6. */
-	{ 0x5b00, "Threshold condition met" },
-	{ 0x5c00, "Status change" },
-
-	{ 0x6300, "End of user area encountered on this track" },
-
-	{ 0x6400, "Illegal mode for this track or incompatible medium" },
-
-	/* Following error is misspelled in ATAPI 2.6 */
-	{ 0xb900, "Play operation oborted [sic]" },
-
-	{ 0xbf00, "Loss of streaming" },
+	{ 0x000000, "No additional sense information" },
+	{ 0x000011, "Play operation in progress" },
+	{ 0x000012, "Play operation paused" },
+	{ 0x000013, "Play operation successfully completed" },
+	{ 0x000014, "Play operation stopped due to error" },
+	{ 0x000015, "No current audio status to return" },
+	{ 0x011700, "Recovered data with no error correction applied" },
+	{ 0x011701, "Recovered data with retries" },
+	{ 0x011702, "Recovered data with positive head offset" },
+	{ 0x011703, "Recovered data with negative head offset" },
+	{ 0x011704, "Recovered data with retries and/or CIRC applied" },
+	{ 0x011705, "Recovered data using previous sector ID" },
+	{ 0x011800, "Recovered data with error correction applied" },
+	{ 0x011801, "Recovered data with error correction and retries applied"},
+	{ 0x011802, "Recovered data - the data was auto-reallocated" },
+	{ 0x011803, "Recovered data with CIRC" },
+	{ 0x011804, "Recovered data with L-EC" },
+	{ 0x015d00, 
+	    "Failure prediction threshold exceeded - Predicted logical unit failure" },
+	{ 0x015d01, 
+	    "Failure prediction threshold exceeded - Predicted media failure" },
+	{ 0x015dff, "Failure prediction threshold exceeded - False" },
+	{ 0x020400, "Logical unit not ready - cause not reportable" },
+	/* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */
+	{ 0x020401,
+	  "Logical unit not ready - in progress [sic] of becoming ready" },
+	{ 0x020402, "Logical unit not ready - initializing command required" },
+	{ 0x020403, "Logical unit not ready - manual intervention required" },
+	{ 0x020404, "In process of becoming ready - writing" },
+	{ 0x020600, "No reference position found (media may be upside down)" },
+	{ 0x023000, "Incompatible medium installed" },
+	{ 0x023a00, "Medium not present" },
+	{ 0x025300, "Media load or eject failed" },
+	{ 0x025700, "Unable to recover table of contents" },
+	{ 0x031100, "Unrecovered read error" },
+	{ 0x031106, "CIRC unrecovered error" },
+	{ 0x033101, "Format command failed" },
+	{ 0x040200, "No seek complete" },
+	{ 0x040300, "Write fault" },
+	{ 0x040900, "Track following error" },
+	{ 0x040901, "Tracking servo failure" },
+	{ 0x040902, "Focus servo failure" },
+	{ 0x040903, "Spindle servo failure" },
+	{ 0x041500, "Random positioning error" },
+	{ 0x041501, "Mechanical positioning or changer error" },
+	{ 0x041502, "Positioning error detected by read of medium" },
+	{ 0x043c00, "Mechanical positioning or changer error" },
+	{ 0x044000, "Diagnostic failure on component (ASCQ)" },
+	{ 0x044400, "Internal CD/DVD logical unit failure" },
+	{ 0x04b600, "Media load mechanism failed" },
+	{ 0x051a00, "Parameter list length error" },
+	{ 0x052000, "Invalid command operation code" },
+	{ 0x052c00, "Command sequence error" },
+	{ 0x052100, "Logical block address out of range" },
+	{ 0x052400, "Invalid field in command packet" },
+	{ 0x052600, "Invalid field in parameter list" },
+	{ 0x052601, "Parameter not supported" },
+	{ 0x052602, "Parameter value invalid" },
+	{ 0x052700, "Write protected media" },
+	{ 0x053001, "Cannot read medium - unknown format" },
+	{ 0x053002, "Cannot read medium - incompatible format" },
+	{ 0x053900, "Saving parameters not supported" },
+	{ 0x054e00, "Overlapped commands attempted" },
+	{ 0x055302, "Medium removal prevented" },
+	{ 0x055500, "System resource failure" },
+	{ 0x056300, "End of user area encountered on this track" },
+	{ 0x056400, "Illegal mode for this track or incompatible medium" },
+	{ 0x056f00, 
+	    "Copy protection key exchange failure - Authentication failure" },
+	{ 0x056f01, "Copy protection key exchange failure - Key not present" },
+	{ 0x056f02, 
+	    "Copy protection key exchange failure - Key not established" },
+	{ 0x05bf00, "Loss of streaming" },
+	{ 0x062800, "Not ready to ready transition, medium may have changed" },
+	{ 0x062900, "Power on, reset or hardware reset occurred" },
+	{ 0x062a00, "Parameters changed" },
+	{ 0x062a01, "Mode parameters changed" },
+	{ 0x062e00, "Insufficient time for operation" },
+	{ 0x063f00, "Logical unit operating conditions have changed" },
+	{ 0x063f01, "Microcode has been changed" },
+	{ 0x065a00, "Operator request or state change input (unspecified)" },
+	{ 0x065a01, "Operator medium removal request" },
+	{ 0x0bb900, "Play operation aborted" },
+
+	/* Here we use 0xff for the key (not a valid key) to signify
+	 * that these can have _any_ key value associated with them... */
+	{ 0xff0401, "Logical unit is in process of becoming ready" },
+	{ 0xff0400, "Logical unit not ready, cause not reportable" },
+	{ 0xff0402, "Logical unit not ready, initializing command required" },
+	{ 0xff0403, "Logical unit not ready, manual intervention required" },
+	{ 0xff0500, "Logical unit does not respond to selection" },
+	{ 0xff0800, "Logical unit communication failure" },
+	{ 0xff0802, "Logical unit communication parity error" },
+	{ 0xff0801, "Logical unit communication time-out" },
+	{ 0xff2500, "Logical unit not supported" },
+	{ 0xff4c00, "Logical unit failed self-configuration" },
+	{ 0xff3e00, "Logical unit has not self-configured yet" },
 };
 #endif
 
diff -u --recursive --new-file v2.3.15/linux/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c
--- v2.3.15/linux/drivers/block/ide-dma.c	Fri Aug  6 10:41:47 1999
+++ linux/drivers/block/ide-dma.c	Tue Aug 31 11:23:03 1999
@@ -470,7 +470,7 @@
 }
 
 /*
- *	This can be called for a dynamically installed interface. Don't initfunc it
+ *	This can be called for a dynamically installed interface. Don't __init it
  */
  
 void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)
diff -u --recursive --new-file v2.3.15/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c
--- v2.3.15/linux/drivers/block/ide-pci.c	Mon Aug  9 10:23:09 1999
+++ linux/drivers/block/ide-pci.c	Thu Aug 26 13:54:23 1999
@@ -130,9 +130,12 @@
 #endif
 
 #ifdef CONFIG_BLK_DEV_CY82C693
+extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *);
 extern void ide_init_cy82c693(ide_hwif_t *);
+#define PCI_CY82C693	&pci_init_cy82c693
 #define	INIT_CY82C693	&ide_init_cy82c693
 #else
+#define PCI_CY82C693	NULL
 #define	INIT_CY82C693	NULL
 #endif
 
@@ -240,7 +243,7 @@
 	{DEVID_HPT34X,	"HPT34X",	PCI_HPT34X,	INIT_HPT34X,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	NEVER_BOARD,	0,	16 },
 	{DEVID_HPT366,	"HPT366",	PCI_HPT366,	INIT_HPT366,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	1,	256 },
 	{DEVID_ALI15X3,	"ALI15X3",	PCI_ALI15X3,	INIT_ALI15X3,	NULL,		{{0x09,0x20,0x20}, {0x09,0x10,0x10}},	ON_BOARD,	0,	0 },
-	{DEVID_CY82C693,"CY82C693",	NULL,		INIT_CY82C693,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0,	0 },
+	{DEVID_CY82C693,"CY82C693",	PCI_CY82C693,	INIT_CY82C693,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0,	0 },
 	{DEVID_HINT,	"HINT_IDE",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0,	0 },
 	{DEVID_CX5530,	"CX5530",	NULL,		INIT_CX5530,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0,	0 },
 	{IDE_PCI_DEVID_NULL, "PCI_IDE",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0,	0 }};
@@ -262,15 +265,6 @@
 				pci_write_config_byte(dev, 0x80, 0x00);
 				pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
 				if (!(pcicmd & PCI_COMMAND_MEMORY)) {
-					/*
-					 * FIXME - this is too ugly, and looks senseless.
-					 * Why not just use resource[4]?
-					 *
-					 * This was a cleaner/quicker way to get the ioports
-					 * that the are not decode do to a flaw in the chipset
-					 * design.
-					 */
-
 					int i;
 					unsigned long hpt34xIoBase = dev->resource[4].start;
 
@@ -491,9 +485,16 @@
 		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port))
 			return;
 		if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) {
-			/* FIXME! This really should check that it really gets the IO/MEM part right! */
 			ctl  = dev->resource[(2*port)+1].start;
 			base = dev->resource[2*port].start;
+			if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) ||
+			    !(base & PCI_BASE_ADDRESS_IO_MASK)) {
+				printk("%s: IO baseregs (BIOS) are reported as MEM, report to <andre@suse.com>.\n", d->name);
+#if 0
+				/* FIXME! This really should check that it really gets the IO/MEM part right! */
+				continue;
+#endif
+			}
 		}
 		if ((ctl && !base) || (base && !ctl)) {
 			printk("%s: inconsistent baseregs (BIOS) for port %d, skipping\n", d->name, port);
@@ -579,7 +580,7 @@
 		printk("%s: neither IDE port enabled (BIOS)\n", d->name);
 }
 
-__initfunc(static void hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d))
+static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d)
 {
 	struct pci_dev *dev2;
 	ide_pci_device_t *d2;
@@ -610,7 +611,7 @@
 		d->name, dev->bus->number, dev->devfn);
 	ide_setup_pci_device(dev, d);
 
-	if (dev2) {
+	if (dev2 && !hpt363_shared_irq) {
 		printk("%s: IDE controller on PCI bus %02x dev %02x\n",
 			d2->name, dev2->bus->number, dev2->devfn);
 		ide_setup_pci_device(dev2, d2);
diff -u --recursive --new-file v2.3.15/linux/drivers/block/ide-pmac.c linux/drivers/block/ide-pmac.c
--- v2.3.15/linux/drivers/block/ide-pmac.c	Mon Aug  9 10:23:09 1999
+++ linux/drivers/block/ide-pmac.c	Tue Aug 31 11:23:03 1999
@@ -57,7 +57,7 @@
 #endif /* CONFIG_PMAC_PBOOK */
 
 /*
- * N.B. this can't be an initfunc, because the media-bay task can
+ * N.B. this can't be an __init, because the media-bay task can
  * call ide_[un]register at any time.
  */
 void pmac_ide_init_hwif_ports(hw_regs_t *hw,
@@ -117,7 +117,7 @@
 	}
 }
 
-__initfunc(void pmac_ide_probe(void))
+void __init pmac_ide_probe(void)
 {
 	struct device_node *np;
 	int i;
diff -u --recursive --new-file v2.3.15/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c
--- v2.3.15/linux/drivers/block/ide-probe.c	Thu Aug  5 18:48:45 1999
+++ linux/drivers/block/ide-probe.c	Thu Aug 26 13:44:03 1999
@@ -352,56 +352,6 @@
 }
 
 /*
- * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc
- * controller that is BIOS compatible with ST-506, and thus showing up in our
- * BIOS table, but not register compatible, and therefore not present in CMOS.
- *
- * Furthermore, we will assume that our ST-506 drives <if any> are the primary
- * drives in the system -- the ones reflected as drive 1 or 2.  The first
- * drive is stored in the high nibble of CMOS byte 0x12, the second in the low
- * nibble.  This will be either a 4 bit drive type or 0xf indicating use byte
- * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.  A non-zero value
- * means we have an AT controller hard disk for that drive.
- *
- * Of course, there is no guarantee that either drive is actually on the
- * "primary" IDE interface, but we don't bother trying to sort that out here.
- * If a drive is not actually on the primary interface, then these parameters
- * will be ignored.  This results in the user having to supply the logical
- * drive geometry as a boot parameter for each drive not on the primary i/f.
- *
- * The only "perfect" way to handle this would be to modify the setup.[cS] code
- * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info
- * for us during initialization.  I have the necessary docs -- any takers?  -ml
- */
-static void probe_cmos_for_drives (ide_hwif_t *hwif)
-{
-#ifdef __i386__
-	extern struct drive_info_struct drive_info;
-	byte cmos_disks, *BIOS = (byte *) &drive_info;
-	int unit;
-
-#ifdef CONFIG_BLK_DEV_PDC4030
-	if (hwif->chipset == ide_pdc4030 && hwif->channel != 0)
-		return;
-#endif /* CONFIG_BLK_DEV_PDC4030 */
-	outb_p(0x12,0x70);		/* specify CMOS address 0x12 */
-	cmos_disks = inb_p(0x71);	/* read the data from 0x12 */
-	/* Extract drive geometry from CMOS+BIOS if not already setup */
-	for (unit = 0; unit < MAX_DRIVES; ++unit) {
-		ide_drive_t *drive = &hwif->drives[unit];
-		if ((cmos_disks & (0xf0 >> (unit*4))) && !drive->present && !drive->nobios) {
-			drive->cyl   = drive->bios_cyl  = *(unsigned short *)BIOS;
-			drive->head  = drive->bios_head = *(BIOS+2);
-			drive->sect  = drive->bios_sect = *(BIOS+14);
-			drive->ctl   = *(BIOS+8);
-			drive->present = 1;
-		}
-		BIOS += 16;
-	}
-#endif
-}
-
-/*
  * This routine only knows how to look for drive units 0 and 1
  * on an interface, so any setting of MAX_DRIVES > 2 won't work here.
  */
@@ -418,8 +368,11 @@
 
 	if (hwif->noprobe)
 		return;
-	if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
+	if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) {
+		extern void probe_cmos_for_drives(ide_hwif_t *hwif);
+
 		probe_cmos_for_drives (hwif);
+	}
 
 	/*
 	 * Calculate the region that this interface occupies,
diff -u --recursive --new-file v2.3.15/linux/drivers/block/ide-proc.c linux/drivers/block/ide-proc.c
--- v2.3.15/linux/drivers/block/ide-proc.c	Sat Jul  3 10:46:04 1999
+++ linux/drivers/block/ide-proc.c	Thu Aug 26 13:44:03 1999
@@ -243,6 +243,7 @@
 					}
 #endif	/* CONFIG_BLK_DEV_IDEPCI */
 				} else {	/* not pci */
+#ifndef CONFIG_Q40
 					switch (digits) {
 						case 2:	outb(val, reg);
 							break;
@@ -251,6 +252,7 @@
 						case 8:	outl(val, reg);
 							break;
 					}
+#endif	/* CONFIG_Q40 */
 				}
 			}
 		}
diff -u --recursive --new-file v2.3.15/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.3.15/linux/drivers/block/ide.c	Wed Aug 18 16:14:46 1999
+++ linux/drivers/block/ide.c	Thu Aug 26 13:44:03 1999
@@ -1200,7 +1200,9 @@
 			return;
 		}
 		hwif = HWIF(drive);
-		if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) /* set nIEN for previous hwif */
+		if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif &&
+		    hwif->io_ports[IDE_CONTROL_OFFSET])
+			/* set nIEN for previous hwif */
 			OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]);
 		hwgroup->hwif = hwif;
 		hwgroup->drive = drive;
@@ -2277,7 +2279,8 @@
 	 * this point (lost interrupt).
 	 */
 	SELECT_DRIVE(HWIF(drive), drive);
-	OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+	    OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
 	OUT_BYTE(speed, IDE_NSECTOR_REG);
 	OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
 	OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
diff -u --recursive --new-file v2.3.15/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.3.15/linux/drivers/block/ll_rw_blk.c	Mon Aug  9 11:49:24 1999
+++ linux/drivers/block/ll_rw_blk.c	Mon Aug 30 18:12:12 1999
@@ -109,6 +109,11 @@
  */
 int * max_sectors[MAX_BLKDEV] = { NULL, NULL, };
 
+/*
+ * Max number of segments per request
+ */
+int * max_segments[MAX_BLKDEV] = { NULL, NULL, };
+
 static inline int get_max_sectors(kdev_t dev)
 {
 	if (!max_sectors[MAJOR(dev)])
@@ -116,6 +121,13 @@
 	return max_sectors[MAJOR(dev)][MINOR(dev)];
 }
 
+static inline int get_max_segments(kdev_t dev)
+{
+	if (!max_segments[MAJOR(dev)])
+		return MAX_SEGMENTS;
+	return max_segments[MAJOR(dev)][MINOR(dev)];
+}
+
 /*
  * Is called with the request spinlock aquired.
  * NOTE: the device-specific queue() functions
@@ -292,24 +304,31 @@
 
 void add_request(struct blk_dev_struct * dev, struct request * req)
 {
+	int major = MAJOR(req->rq_dev);
+	int minor = MINOR(req->rq_dev);
 	struct request * tmp, **current_request;
 	short		 disk_index;
 	unsigned long flags;
 	int queue_new_request = 0;
 
-	switch (MAJOR(req->rq_dev)) {
+	switch (major) {
+		case DAC960_MAJOR+0:
+			disk_index = (minor & 0x00f8) >> 3;
+			if (disk_index < 4)
+				drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
+			break;
 		case SCSI_DISK0_MAJOR:
-			disk_index = (MINOR(req->rq_dev) & 0x00f0) >> 4;
+			disk_index = (minor & 0x00f0) >> 4;
 			if (disk_index < 4)
 				drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
 			break;
 		case IDE0_MAJOR:	/* same as HD_MAJOR */
 		case XT_DISK_MAJOR:
-			disk_index = (MINOR(req->rq_dev) & 0x0040) >> 6;
+			disk_index = (minor & 0x0040) >> 6;
 			drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
 			break;
 		case IDE1_MAJOR:
-			disk_index = ((MINOR(req->rq_dev) & 0x0040) >> 6) + 2;
+			disk_index = ((minor & 0x0040) >> 6) + 2;
 			drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
 		default:
 			break;
@@ -345,10 +364,12 @@
 	tmp->next = req;
 
 /* for SCSI devices, call request_fn unconditionally */
-	if (scsi_blk_major(MAJOR(req->rq_dev)))
+	if (scsi_blk_major(major))
+		queue_new_request = 1;
+	if (major >= COMPAQ_SMART2_MAJOR+0 &&
+	    major <= COMPAQ_SMART2_MAJOR+7)
 		queue_new_request = 1;
-	if (MAJOR(req->rq_dev) >= COMPAQ_SMART2_MAJOR+0 &&
-	    MAJOR(req->rq_dev) <= COMPAQ_SMART2_MAJOR+7)
+	if (major >= DAC960_MAJOR+0 && major <= DAC960_MAJOR+7)
 		queue_new_request = 1;
 out:
 	if (queue_new_request)
@@ -511,6 +532,14 @@
 	     case SCSI_DISK6_MAJOR:
 	     case SCSI_DISK7_MAJOR:
 	     case SCSI_CDROM_MAJOR:
+	     case DAC960_MAJOR+0:
+	     case DAC960_MAJOR+1:
+	     case DAC960_MAJOR+2:
+	     case DAC960_MAJOR+3:
+	     case DAC960_MAJOR+4:
+	     case DAC960_MAJOR+5:
+	     case DAC960_MAJOR+6:
+	     case DAC960_MAJOR+7:
 	     case I2O_MAJOR:
 	     case COMPAQ_SMART2_MAJOR+0:
 	     case COMPAQ_SMART2_MAJOR+1:
@@ -791,7 +820,7 @@
 	floppy_init();
 #else
 #if !defined (__mc68000__) && !defined(CONFIG_PMAC) && !defined(__sparc__)\
-    && !defined(CONFIG_APUS)
+    && !defined(CONFIG_APUS) && !defined(__sh__)
 	outb_p(0xc, 0x3f2);
 #endif
 #endif
diff -u --recursive --new-file v2.3.15/linux/drivers/block/paride/pcd.c linux/drivers/block/paride/pcd.c
--- v2.3.15/linux/drivers/block/paride/pcd.c	Wed Nov  4 10:03:01 1998
+++ linux/drivers/block/paride/pcd.c	Tue Aug 31 16:03:17 1999
@@ -838,21 +838,21 @@
     
 	case CDROMPAUSE: 
 
-	{       char cmd[12]={SCMD_PAUSE_RESUME,0,0,0,0,0,0,0,0,0,0,0};
+	{       char cmd[12]={GPCMD_PAUSE_RESUME,0,0,0,0,0,0,0,0,0,0,0};
 
 		return (pcd_atapi(unit,cmd,0,NULL,"pause")) * EIO;
 	}
 
 	case CDROMRESUME:
 	
-	{       char cmd[12]={SCMD_PAUSE_RESUME,0,0,0,0,0,0,0,1,0,0,0};
+	{       char cmd[12]={GPCMD_PAUSE_RESUME,0,0,0,0,0,0,0,1,0,0,0};
 
 		return (pcd_atapi(unit,cmd,0,NULL,"resume")) * EIO;
 	}
 	
 	case CDROMPLAYMSF:
 
-	{	char cmd[12]={SCMD_PLAYAUDIO_MSF,0,0,0,0,0,0,0,0,0,0,0};
+	{	char cmd[12]={GPCMD_PLAY_AUDIO_MSF,0,0,0,0,0,0,0,0,0,0,0};
 		struct cdrom_msf* msf = (struct cdrom_msf*)arg;
 
 		cmd[3] = msf->cdmsf_min0;
@@ -867,7 +867,7 @@
 
     	case CDROMPLAYBLK:
 
-    	{	char cmd[12]={SCMD_PLAYAUDIO10,0,0,0,0,0,0,0,0,0,0,0};
+    	{	char cmd[12]={GPCMD_PLAY_AUDIO_10,0,0,0,0,0,0,0,0,0,0,0};
 		struct cdrom_blk* blk = (struct cdrom_blk*)arg;
 
 		cmd[2] = blk->from >> 24;
@@ -882,7 +882,7 @@
 		
     	case CDROMPLAYTRKIND:
 
-    	{	char cmd[12]={SCMD_PLAYAUDIO_TI,0,0,0,0,0,0,0,0,0,0,0};
+    	{	char cmd[12]={GPCMD_PLAYAUDIO_TI,0,0,0,0,0,0,0,0,0,0,0};
 		struct cdrom_ti* ti = (struct cdrom_ti*)arg;
 
 		cmd[4] = ti->cdti_trk0;
@@ -895,7 +895,7 @@
 	
     	case CDROMREADTOCHDR:
     
-	{	char cmd[12]={SCMD_READ_TOC,0,0,0,0,0,0,0,12,0,0,0};
+	{	char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0};
 		struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg;
 		char buffer[32];
 		int r;
@@ -910,7 +910,7 @@
 	
     	case CDROMREADTOCENTRY:
 
-    	{	char cmd[12]={SCMD_READ_TOC,0,0,0,0,0,0,0,12,0,0,0};
+    	{	char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0};
 
 		struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg;
 		unsigned char buffer[32];
@@ -938,21 +938,21 @@
 
     	case CDROMSTOP:
 
-	{	char cmd[12]={0x1b,1,0,0,0,0,0,0,0,0,0,0};
+	{	char cmd[12]={GPCMD_START_STOP_UNIT,1,0,0,0,0,0,0,0,0,0,0};
 
                 return (pcd_atapi(unit,cmd,0,NULL,"stop")) * EIO;
         }                                                         
 	
     	case CDROMSTART:
 
-        {       char cmd[12]={0x1b,1,0,0,1,0,0,0,0,0,0,0};
+        {       char cmd[12]={GPCMD_START_STOP_UNIT,1,0,0,1,0,0,0,0,0,0,0};
 
                 return (pcd_atapi(unit,cmd,0,NULL,"start")) * EIO;
         } 
 	
     	case CDROMVOLCTRL:
 
-	{	char cmd[12]={0x5a,0,0,0,0,0,0,0,0,0,0,0};
+	{	char cmd[12]={GPCMD_MODE_SENSE_10,0,0,0,0,0,0,0,0,0,0,0};
 		char buffer[32];
 		char mask[32];
 		struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
@@ -983,7 +983,7 @@
 
     	case CDROMVOLREAD:
 
-        {       char cmd[12]={0x5a,0,0,0,0,0,0,0,0,0,0,0};
+        {       char cmd[12]={GPCMD_MODE_SENSE_10,0,0,0,0,0,0,0,0,0,0,0};
                 char buffer[32];
                 struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
                 int     r;
@@ -1004,7 +1004,7 @@
 	
     	case CDROMSUBCHNL:
 
-	{	char cmd[12]={SCMD_READ_SUBCHANNEL,2,0x40,1,0,0,0,0,16,0,0,0};
+	{	char cmd[12]={GPCMD_READ_SUBCHANNEL,2,0x40,1,0,0,0,0,16,0,0,0};
 		struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg;
 		char buffer[32];
 	
@@ -1035,7 +1035,7 @@
 	
 static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
 
-{	char 	cmd[12]={SCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0};
+{	char 	cmd[12]={GPCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0};
         char 	buffer[32];
 	int	k;
 	int	unit = DEVICE_NR(cdi->dev);
diff -u --recursive --new-file v2.3.15/linux/drivers/block/pdc202xx.c linux/drivers/block/pdc202xx.c
--- v2.3.15/linux/drivers/block/pdc202xx.c	Thu Aug  5 18:48:45 1999
+++ linux/drivers/block/pdc202xx.c	Mon Aug 30 10:18:40 1999
@@ -491,16 +491,16 @@
 	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
 }
 
-__initfunc(unsigned int pci_init_pdc202xx (struct pci_dev *dev, const char *name))
+unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name)
 {
 	unsigned long high_16	= dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK;
 	byte udma_speed_flag	= inb(high_16 + 0x001f);
 	byte primary_mode	= inb(high_16 + 0x001a);
 	byte secondary_mode	= inb(high_16 + 0x001b);
 
-	if (dev->rom_address) {
-		pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
-		printk("%s: ROM enabled at 0x%08lx\n", name, dev->rom_address);
+	if (dev->resource[PCI_ROM_RESOURCE].start) {
+		pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+		printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
 	}
 
 	if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
@@ -547,7 +547,7 @@
 	return dev->irq;
 }
 
-__initfunc(void ide_init_pdc202xx (ide_hwif_t *hwif))
+void __init ide_init_pdc202xx (ide_hwif_t *hwif)
 {
 	if (hwif->dma_base) {
 		hwif->dmaproc = &pdc202xx_dmaproc;
diff -u --recursive --new-file v2.3.15/linux/drivers/block/raid5.c linux/drivers/block/raid5.c
--- v2.3.15/linux/drivers/block/raid5.c	Thu Aug 12 10:16:28 1999
+++ linux/drivers/block/raid5.c	Tue Aug 31 11:30:47 1999
@@ -97,7 +97,7 @@
 	sh->count++;
 	add_wait_queue(&sh->wait, &wait);
 repeat:
-	current->state = TASK_UNINTERRUPTIBLE;
+	set_current_state(TASK_UNINTERRUPTIBLE);
 	if (stripe_locked(sh)) {
 		schedule();
 		goto repeat;
diff -u --recursive --new-file v2.3.15/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.3.15/linux/drivers/block/rd.c	Mon Aug  9 10:23:09 1999
+++ linux/drivers/block/rd.c	Thu Aug 26 12:48:27 1999
@@ -74,15 +74,6 @@
 #include <linux/blk.h>
 #include <linux/blkpg.h>
 
-/*
- * We use a block size of 512 bytes in comparision to BLOCK_SIZE
- * defined in include/linux/blk.h. This because of the finer
- * granularity for filling up a RAM disk.
- */
-#define RDBLK_SIZE_BITS		9
-#define RDBLK_SIZE		(1<<RDBLK_SIZE_BITS)
-
-
 /* The RAM disk size is now a parameter */
 #define NUM_RAMDISKS 16		/* This cannot be overridden (yet) */ 
 
@@ -114,6 +105,18 @@
  * information). 
  */
 int rd_size = 4096;		/* Size of the RAM disks */
+/*
+ * It would be very desiderable to have a soft-blocksize (that in the case
+ * of the ramdisk driver is also the hardblocksize ;) of PAGE_SIZE because
+ * doing that we'll achieve a far better MM footprint. Using a rd_blocksize of
+ * BLOCK_SIZE in the worst case we'll make PAGE_SIZE/BLOCK_SIZE buffer-pages
+ * unfreeable. With a rd_blocksize of PAGE_SIZE instead we are sure that only
+ * 1 page will be protected. Depending on the size of the ramdisk you
+ * may want to change the ramdisk blocksize to achieve a better or worse MM
+ * behaviour. The default is still BLOCK_SIZE (needed by rd_load_image that
+ * supposes the filesystem in the image uses a BLOCK_SIZE blocksize).
+ */
+int rd_blocksize = BLOCK_SIZE;	/* Size of the RAM disks */
 
 #ifndef MODULE
 
@@ -184,9 +187,6 @@
 	unsigned long offset, len;
 
 repeat:
-	if (!CURRENT)
-		return;
-
 	INIT_REQUEST;
 	
 	minor = MINOR(CURRENT->rq_dev);
@@ -196,8 +196,8 @@
 		goto repeat;
 	}
 	
-	offset = CURRENT->sector << RDBLK_SIZE_BITS;
-	len = CURRENT->current_nr_sectors << RDBLK_SIZE_BITS;
+	offset = CURRENT->sector << 9;
+	len = CURRENT->current_nr_sectors << 9;
 
 	if ((offset + len) > rd_length[minor]) {
 		end_request(0);
@@ -243,7 +243,7 @@
 
          	case BLKGETSIZE:   /* Return device size */
 			if (!arg)  return -EINVAL;
-			return put_user(rd_length[minor] >> RDBLK_SIZE_BITS, (long *) arg);
+			return put_user(rd_kbsize[minor] << 1, (long *) arg);
 
 		case BLKROSET:
 		case BLKROGET:
@@ -347,6 +347,14 @@
 {
 	int		i;
 
+	if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
+	    (rd_blocksize & (rd_blocksize-1)))
+	{
+		printk("RAMDISK: wrong blocksize %d, reverting to defaults\n",
+		       rd_blocksize);
+		rd_blocksize = BLOCK_SIZE;
+	}
+
 	if (register_blkdev(MAJOR_NR, "ramdisk", &fd_fops)) {
 		printk("RAMDISK: Could not get major %d", MAJOR_NR);
 		return -EIO;
@@ -356,18 +364,19 @@
 
 	for (i = 0; i < NUM_RAMDISKS; i++) {
 		/* rd_size is given in kB */
-		rd_length[i] = (rd_size << BLOCK_SIZE_BITS);
-		rd_hardsec[i] = RDBLK_SIZE;
-		rd_blocksizes[i] = BLOCK_SIZE;
-		rd_kbsize[i] = (rd_length[i] >> BLOCK_SIZE_BITS);
+		rd_length[i] = rd_size << 10;
+		rd_hardsec[i] = rd_blocksize;
+		rd_blocksizes[i] = rd_blocksize;
+		rd_kbsize[i] = rd_size;
 	}
 
 	hardsect_size[MAJOR_NR] = rd_hardsec;		/* Size of the RAM disk blocks */
 	blksize_size[MAJOR_NR] = rd_blocksizes;		/* Avoid set_blocksize() check */
 	blk_size[MAJOR_NR] = rd_kbsize;			/* Size of the RAM disk in kB  */
 
-	printk("RAM disk driver initialized:  %d RAM disks of %dK size\n",
-							NUM_RAMDISKS, rd_size);
+	printk("RAMDISK driver initialized: "
+	       "%d RAM disks of %dK size %d blocksize\n",
+	       NUM_RAMDISKS, rd_size, rd_blocksize);
 
 	return 0;
 }
@@ -377,7 +386,9 @@
 #ifdef MODULE
 
 MODULE_PARM     (rd_size, "1i");
-MODULE_PARM_DESC(rd_size, "Size of each RAM disk.");
+MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
+MODULE_PARM     (rd_blocksize, "i");
+MODULE_PARM_DESC(rd_blocksize, "Blocksize of each RAM disk in bytes.");
 
 int init_module(void)
 {
@@ -564,9 +575,15 @@
 		goto done;
 	}
 
-	if (nblocks > (rd_length[unit] >> RDBLK_SIZE_BITS)) {
+	/*
+	 * NOTE NOTE: nblocks suppose that the blocksize is BLOCK_SIZE, so
+	 * rd_load_image will work only with filesystem BLOCK_SIZE wide!
+	 * So make sure to use 1k blocksize while generating ext2fs
+	 * ramdisk-images.
+	 */
+	if (nblocks > (rd_length[unit] >> BLOCK_SIZE_BITS)) {
 		printk("RAMDISK: image too big! (%d/%ld blocks)\n",
-		       nblocks, rd_length[unit] >> RDBLK_SIZE_BITS);
+		       nblocks, rd_length[unit] >> BLOCK_SIZE_BITS);
 		goto done;
 	}
 		
diff -u --recursive --new-file v2.3.15/linux/drivers/block/sis5513.c linux/drivers/block/sis5513.c
--- v2.3.15/linux/drivers/block/sis5513.c	Fri Aug  6 11:16:54 1999
+++ linux/drivers/block/sis5513.c	Thu Aug 26 13:55:08 1999
@@ -330,7 +330,7 @@
 	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
 }
 
-__initfunc(unsigned int pci_init_sis5513 (struct pci_dev *dev, const char *name))
+unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name)
 {
 	struct pci_dev *host;
 	byte latency = 0, reg48h = 0;
@@ -383,7 +383,7 @@
 	return 0;
 }
 
-__initfunc(void ide_init_sis5513 (ide_hwif_t *hwif))
+void __init ide_init_sis5513 (ide_hwif_t *hwif)
 {
 	byte reg48h = 0;
 	byte mask = hwif->channel ? 0x20 : 0x10;
diff -u --recursive --new-file v2.3.15/linux/drivers/block/sl82c105.c linux/drivers/block/sl82c105.c
--- v2.3.15/linux/drivers/block/sl82c105.c	Thu Aug  5 18:48:45 1999
+++ linux/drivers/block/sl82c105.c	Thu Aug 26 13:44:03 1999
@@ -68,7 +68,8 @@
 		 * the correct drive has been selected.
 		 */
 		SELECT_DRIVE(hwif, drive);
-		OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
+		if (IDE_CONTROL_REG)
+			OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG);
 		OUT_BYTE(0x08 | pio,  IDE_NSECTOR_REG);
 		OUT_BYTE(0x03, IDE_FEATURE_REG);
 		OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
@@ -79,8 +80,8 @@
 			       drive->name);
 			return 1;
 		}
-
-		OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
+		if (IDE_CONTROL_REG)
+			OUT_BYTE(drive->ctl, IDE_CONTROL_REG);
 	}
 
 	return 0;
diff -u --recursive --new-file v2.3.15/linux/drivers/block/trm290.c linux/drivers/block/trm290.c
--- v2.3.15/linux/drivers/block/trm290.c	Mon Aug  9 10:23:09 1999
+++ linux/drivers/block/trm290.c	Thu Aug 26 13:44:03 1999
@@ -263,7 +263,16 @@
 		old = inw(hwif->config_data) & ~1;
 		if (old != compat && inb(old+2) == 0xff) {
 			compat += (next_offset += 0x400);	/* leave lower 10 bits untouched */
-			hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2;	/* FIXME: should do a check_region */
+#if 1
+			if (ide_check_region(compat + 2, 1))
+				printk("Aieee %s: ide_check_region failure at 0x%04x\n", hwif->name, (compat + 2));
+			/*
+			 * The region check is not needed; however.........
+			 * Since this is the checked in ide-probe.c,
+			 * this is only an assignment.
+			 */
+#endif
+			hwif->io_ports[IDE_CONTROL_OFFSET] = compat + 2;
 			outw(compat|1, hwif->config_data);
 			printk("%s: control basereg workaround: old=0x%04x, new=0x%04x\n", hwif->name, old, inw(hwif->config_data) & ~1);
 		}
diff -u --recursive --new-file v2.3.15/linux/drivers/block/via82c586.c linux/drivers/block/via82c586.c
--- v2.3.15/linux/drivers/block/via82c586.c	Thu Aug  5 18:48:45 1999
+++ linux/drivers/block/via82c586.c	Thu Aug 26 13:55:23 1999
@@ -441,7 +441,7 @@
 	return 0;
 }
 
-__initfunc(unsigned int pci_init_via82c568 (struct pci_dev *dev, const char *name))
+unsigned int __init pci_init_via82c568 (struct pci_dev *dev, const char *name)
 {
 	struct pci_dev *host;
 	struct pci_dev *isa;
@@ -567,7 +567,7 @@
 	return 0;
 }
 
-__initfunc(void ide_init_via82c586 (ide_hwif_t *hwif))
+void __init ide_init_via82c586 (ide_hwif_t *hwif)
 {
 	set_via_timings(hwif);
 }
diff -u --recursive --new-file v2.3.15/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.3.15/linux/drivers/block/xd.c	Mon Aug  9 10:23:09 1999
+++ linux/drivers/block/xd.c	Thu Aug 26 12:50:51 1999
@@ -194,7 +194,7 @@
 }
 
 /* xd_detect: scan the possible BIOS ROM locations for the signature strings */
-static __init u_char xd_detect (u_char *controller, unsigned int *address)
+static u_char __init xd_detect (u_char *controller, unsigned int *address)
 {
 	u_char i,j,found = 0;
 
@@ -1204,5 +1204,10 @@
 			xd_dma_mem_free((unsigned long)xd_dma_buffer, xd_maxsectors * 0x200);
 	}
 }
+#else
+
+__setup ("xd=", xd_setup);
+__setup ("xd_geo=", xd_manual_geo_init);
+
 #endif /* MODULE */
 
diff -u --recursive --new-file v2.3.15/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.3.15/linux/drivers/cdrom/cdrom.c	Mon Aug  9 12:34:22 1999
+++ linux/drivers/cdrom/cdrom.c	Tue Aug 31 16:03:17 1999
@@ -22,12 +22,6 @@
  based tunable parameters such as whether the tray should auto-close for
  that drive. Suggestions (or patches) for this welcome!
 
- -- Change the CDROMREADMODE1, CDROMREADMODE2, CDROMREADAUDIO, and 
- CDROMREADRAW ioctls so they go through the Uniform CD-ROM driver.
- 
- -- Sync options and capability flags.
- 
-
 
  Revision History
  ----------------------------------
@@ -158,11 +152,22 @@
   DVD structures and ioctls in the first place! He designed the original
   DVD patches for ide-cd and while I rearranged and unified them, the
   interface is still the same.
+  
+  3.03 Sep 1, 1999 - Jens Axboe <axboe@image.dk>
+  -- Moved the rest of the audio ioctls from the CD-ROM drivers here. Only
+  CDROMREADTOCENTRY and CDROMREADTOCHDR are left.
+  -- Moved the CDROMREADxxx ioctls in here.
+  -- Defined the cdrom_get_last_written and cdrom_get_next_block as ioctls
+  and exported functions.
+  -- Erik Andersen <andersen@xmission.com> modified all SCMD_ commands
+  to now read GPCMD_ for the new generic packet interface. All low level
+  drivers are updated as well.
+  -- Various other cleanups.
 
 -------------------------------------------------------------------------*/
 
-#define REVISION "Revision: 3.02"
-#define VERSION "Id: cdrom.c 3.02 1999/08/08"
+#define REVISION "Revision: 3.03"
+#define VERSION "Id: cdrom.c 3.03 1999/09/01"
 
 /* I use an error-log mask to give fine grain control over the type of
    messages dumped to the system logs.  The available masks include: */
@@ -247,6 +252,10 @@
 		u_char * curr, u_char requested);
 static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
 		     unsigned long arg);
+
+int cdrom_get_last_written(kdev_t dev, long *last_written);
+int cdrom_get_next_writable(kdev_t dev, long *next_writable);
+
 #ifdef CONFIG_SYSCTL
 static void cdrom_sysctl_register(void);
 #endif /* CONFIG_SYSCTL */ 
@@ -463,8 +472,8 @@
 		if (cdi->options & CDO_CHECK_TYPE) {
 		    /* give people a warning shot, now that CDO_CHECK_TYPE
 		       is the default case! */
-		    printk("cdrom: pid %d is buggy!\n", (unsigned int)current->pid);
 		    cdinfo(CD_OPEN, "bummer. wrong media type.\n"); 
+		    cdinfo(CD_WARNING, "pid %d is buggy!\n", (unsigned int)current->pid); 
 		    ret=-EMEDIUMTYPE;
 		    goto clean_up_and_return;
 		}
@@ -731,19 +740,19 @@
 
 static void setup_report_key (struct cdrom_generic_command *cgc, unsigned agid, unsigned type)
 {
-	cgc->cmd[0] = DVD_REPORT_KEY;
+	cgc->cmd[0] = GPCMD_REPORT_KEY;
 	cgc->cmd[10] = type | (agid << 6);
 }
 
 static void setup_send_key (struct cdrom_generic_command *cgc, unsigned agid, unsigned type)
 {
-	cgc->cmd[0] = DVD_SEND_KEY;
+	cgc->cmd[0] = GPCMD_SEND_KEY;
 	cgc->cmd[10] = type | (agid << 6);
 }
 
 static int dvd_do_auth (struct cdrom_device_info *cdi, dvd_authinfo *ai)
 {
-	int rv;
+	int ret;
 	u_char buf[20];
 	struct cdrom_generic_command cgc;
 	struct cdrom_device_ops *cdo = cdi->ops;
@@ -759,9 +768,9 @@
 		setup_report_key (&cgc, 0, 0);
 		cgc.buflen = cgc.cmd[9] = 8;
 
-		rv = cdo->generic_packet(cdi, &cgc);
-		if (rv)
-			return rv;
+		ret = cdo->generic_packet(cdi, &cgc);
+		if (ret)
+			return ret;
 
 		ai->lsa.agid = buf[7] >> 6;
 		/* Returning data, let host change state */
@@ -772,9 +781,8 @@
 		setup_report_key (&cgc, ai->lsk.agid, 2);
 		cgc.buflen = cgc.cmd[9] = 12;
 
-		rv = cdo->generic_packet(cdi, &cgc);
-		if (rv)
-			return rv;
+		ret = cdo->generic_packet(cdi, &cgc);
+		if (ret) return ret;
 
 		copy_key(ai->lsk.key, &buf[4]);
 		/* Returning data, let host change state */
@@ -785,9 +793,8 @@
 		setup_report_key (&cgc, ai->lsc.agid, 1);
 		cgc.buflen = cgc.cmd[9] = 16;
 
-		rv = cdo->generic_packet(cdi, &cgc);
-		if (rv)
-			return rv;
+		ret = cdo->generic_packet(cdi, &cgc);
+		if (ret) return ret;
 
 		copy_chal(ai->lsc.chal, &buf[4]);
 		/* Returning data, let host change state */
@@ -803,9 +810,8 @@
 		cgc.cmd[2] = ai->lstk.lba >> 24;
 		cgc.buflen = cgc.cmd[9] = 12;
 
-		rv = cdo->generic_packet(cdi, &cgc);
-		if (rv)
-			return rv;
+		ret = cdo->generic_packet(cdi, &cgc);
+		if (ret) return ret;
 
 		ai->lstk.cpm = (buf[4] >> 7) & 1;
 		ai->lstk.cp_sec = (buf[4] >> 6) & 1;
@@ -819,9 +825,8 @@
 		setup_report_key (&cgc, ai->lsasf.asf, 5);
 		cgc.buflen = cgc.cmd[9] = 8;
 
-		rv = cdo->generic_packet(cdi, &cgc);
-		if (rv)
-			return rv;
+		ret = cdo->generic_packet(cdi, &cgc);
+		if (ret) return ret;
 
 		ai->lsasf.asf = buf[7] & 1;
 		break;
@@ -834,9 +839,8 @@
 		buf[1] = 14;
 		copy_chal (&buf[4], ai->hsc.chal);
 
-		rv = cdo->generic_packet(cdi, &cgc);
-		if (rv)
-			return rv;
+		ret = cdo->generic_packet(cdi, &cgc);
+		if (ret) return ret;
 
 		ai->type = DVD_LU_SEND_KEY1;
 		break;
@@ -848,10 +852,10 @@
 		buf[1] = 10;
 		copy_key (&buf[4], ai->hsk.key);
 
-		rv = cdo->generic_packet(cdi, &cgc);
-		if (rv) {
+		ret = cdo->generic_packet(cdi, &cgc);
+		if (ret) {
 			ai->type = DVD_AUTH_FAILURE;
-			return rv;
+			return ret;
 		}
 		ai->type = DVD_AUTH_ESTABLISHED;
 		break;
@@ -860,10 +864,8 @@
 	case DVD_INVALIDATE_AGID:
 		cdinfo(CD_DO_IOCTL, "entering DVD_INVALIDATE_AGID\n"); 
 		setup_report_key (&cgc, ai->lsa.agid, 0x3f);
-
-		rv = cdo->generic_packet(cdi, &cgc);
-		if (rv)
-			return rv;
+		ret = cdo->generic_packet(cdi, &cgc);
+		if (ret) return ret;
 		break;
 
 	default:
@@ -876,7 +878,7 @@
 
 static int dvd_read_physical (struct cdrom_device_info *cdi, dvd_struct *s)
 {
-	int rv, i;
+	int ret, i;
 	u_char buf[4 + 4 * 20], *base;
 	struct dvd_layer *layer;
 	struct cdrom_generic_command cgc;
@@ -886,14 +888,13 @@
 	memset(&cgc, 0, sizeof(cgc));
 	cgc.buffer = buf;
 	cgc.buflen = sizeof(buf);
-	cgc.cmd[0] = DVD_READ_STRUCTURE;
+	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
 	cgc.cmd[6] = s->physical.layer_num;
 	cgc.cmd[7] = s->type;
 	cgc.cmd[9] = cgc.buflen & 0xff;
 
-	rv = cdo->generic_packet(cdi, &cgc);
-	if (rv)
-		return rv;
+	ret = cdo->generic_packet(cdi, &cgc);
+	if (ret) return ret;
 
 	base = &buf[4];
 	layer = &s->physical.layer[0];
@@ -922,7 +923,7 @@
 
 static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
 {
-	int rv;
+	int ret;
 	u_char buf[8];
 	struct cdrom_generic_command cgc;
 	struct cdrom_device_ops *cdo = cdi->ops;
@@ -931,15 +932,15 @@
 	memset(&cgc, 0, sizeof(cgc));
 	cgc.buffer = buf;
 	cgc.buflen = sizeof(buf);
-	cgc.cmd[0] = DVD_READ_STRUCTURE;
+	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
 	cgc.cmd[6] = s->copyright.layer_num;
 	cgc.cmd[7] = s->type;
 	cgc.cmd[8] = cgc.buflen >> 8;
 	cgc.cmd[9] = cgc.buflen & 0xff;
 
-	rv = cdo->generic_packet(cdi, &cgc);
-	if (rv)
-		return rv;
+	ret = cdo->generic_packet(cdi, &cgc);
+	if (ret)
+		return ret;
 
 	s->copyright.cpst = buf[4];
 	s->copyright.rmi = buf[5];
@@ -949,7 +950,7 @@
 
 static int dvd_read_disckey (struct cdrom_device_info *cdi, dvd_struct *s)
 {
-	int rv;
+	int ret;
 	u_char buf[4 + 2048];
 	struct cdrom_generic_command cgc;
 	struct cdrom_device_ops *cdo = cdi->ops;
@@ -959,15 +960,14 @@
 
 	cgc.buffer = buf;
 	cgc.buflen = sizeof(buf);
-	cgc.cmd[0] = DVD_READ_STRUCTURE;
+	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
 	cgc.cmd[7] = s->type;
 	cgc.cmd[8] = sizeof(buf) >> 8;
 	cgc.cmd[9] = cgc.buflen & 0xff;
 	cgc.cmd[10] = s->disckey.agid << 6;
 
-	rv = cdo->generic_packet(cdi, &cgc);
-	if (rv)
-		return rv;
+	ret = cdo->generic_packet(cdi, &cgc);
+	if (ret) return ret;
 
 	memcpy (s->disckey.value, &buf[4], 2048);
 
@@ -976,7 +976,7 @@
 
 static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s)
 {
-	int rv;
+	int ret;
 	u_char buf[4 + 188];
 	struct cdrom_generic_command cgc;
 	struct cdrom_device_ops *cdo = cdi->ops;
@@ -985,13 +985,12 @@
 	memset(&cgc, 0, sizeof (cgc));
 	cgc.buffer = buf;
 	cgc.buflen = sizeof(buf);
-	cgc.cmd[0] = DVD_READ_STRUCTURE;
+	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
 	cgc.cmd[7] = s->type;
 	cgc.cmd[9] = cgc.buflen = 0xff;
 
-	rv = cdo->generic_packet(cdi, &cgc);
-	if (rv)
-		return rv;
+	ret = cdo->generic_packet(cdi, &cgc);
+	if (ret) return ret;
 
 	s->bca.len = buf[0] << 8 | buf[1];
 	if (s->bca.len < 12 || s->bca.len > 188) {
@@ -1005,7 +1004,7 @@
 
 static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s)
 {
-	int rv;
+	int ret;
 	u_char buf[4 + 2048];
 	struct cdrom_generic_command cgc;
 	struct cdrom_device_ops *cdo = cdi->ops;
@@ -1013,15 +1012,14 @@
 	memset(buf, 0, sizeof(buf));
 	memset(&cgc, 0, sizeof(cgc));
 	cgc.buffer = buf;
-	cgc.cmd[0] = DVD_READ_STRUCTURE;
+	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
 	cgc.cmd[7] = s->type;
 	cgc.buflen = sizeof(buf);
 	cgc.cmd[8] = sizeof(buf) >> 8;
 	cgc.cmd[9] = cgc.buflen & 0xff;
 
-	rv = cdo->generic_packet(cdi, &cgc);
-	if (rv)
-		return rv;
+	ret = cdo->generic_packet(cdi, &cgc);
+	if (ret) return ret;
 
 	s->manufact.len = buf[0] << 8 | buf[1];
 	if (s->manufact.len < 0 || s->manufact.len > 2048) {
@@ -1066,7 +1064,7 @@
 
 	memset(cgc->cmd, 0, sizeof(cgc->cmd));
 
-	cgc->cmd[0] = 0x5a;		/* MODE_SENSE_10 */
+	cgc->cmd[0] = GPCMD_MODE_SENSE_10;
 	cgc->cmd[2] = page_code | (page_control << 6);
 	cgc->cmd[7] = cgc->buflen >> 8;
 	cgc->cmd[8] = cgc->buflen & 0xff;
@@ -1080,7 +1078,7 @@
 
 	memset(cgc->cmd, 0, sizeof(cgc->cmd));
 	
-	cgc->cmd[0] = 0x55;		/* MODE_SELECT_10 */
+	cgc->cmd[0] = GPCMD_MODE_SELECT_10;
 	cgc->cmd[1] = 0x10;		/* PF */
 
 	/* generic_packet() wants the length as seen from the drive, i.e.
@@ -1092,6 +1090,70 @@
 	return cdo->generic_packet(cdi, cgc);
 }
 
+static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
+				 struct cdrom_subchnl *subchnl, int mcn)
+{
+	struct cdrom_device_ops *cdo = cdi->ops;
+	struct cdrom_generic_command cgc;
+	char buffer[32];
+	int ret;
+
+	memset(&cgc, 0, sizeof(cgc));
+	cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
+	cgc.cmd[1] = 2;     /* MSF addressing */
+	cgc.cmd[2] = 0x40;  /* request subQ data */
+	cgc.cmd[3] = mcn ? 2 : 1;
+	cgc.cmd[8] = cgc.buflen = 16;
+	cgc.buffer = buffer;
+
+	if ((ret = cdo->generic_packet(cdi, &cgc)))
+		return ret;
+
+	subchnl->cdsc_audiostatus = cgc.buffer[1];
+	subchnl->cdsc_format = CDROM_MSF;
+	subchnl->cdsc_ctrl = cgc.buffer[5] & 0xf;
+	subchnl->cdsc_trk = cgc.buffer[6];
+	subchnl->cdsc_ind = cgc.buffer[7];
+
+	subchnl->cdsc_reladdr.msf.minute = cgc.buffer[13];
+	subchnl->cdsc_reladdr.msf.second = cgc.buffer[14];
+	subchnl->cdsc_reladdr.msf.frame = cgc.buffer[15];
+	subchnl->cdsc_absaddr.msf.minute = cgc.buffer[9];
+	subchnl->cdsc_absaddr.msf.second = cgc.buffer[10];
+	subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11];
+
+	return 0;
+}
+
+/* very generic interface for reading the various types of blocks */
+static int cdrom_read_block(struct cdrom_device_info *cdi,
+			    struct cdrom_generic_command *cgc,
+			    int lba, int nblocks, int format, int blksize)
+{
+	struct cdrom_device_ops *cdo = cdi->ops;
+
+	memset(&cgc->cmd, 0, sizeof(cgc->cmd));
+	cgc->cmd[0] = GPCMD_READ_CD;
+	/* expected sector size - cdda,mode1,etc. */
+	cgc->cmd[1] = format << 2;
+	/* starting address */
+	cgc->cmd[2] = (lba >> 24) & 0xff;
+	cgc->cmd[3] = (lba >> 16) & 0xff;
+	cgc->cmd[4] = (lba >>  8) & 0xff;
+	cgc->cmd[5] = lba & 0xff;
+	/* number of blocks */
+	cgc->cmd[8] = nblocks;
+	cgc->buflen = blksize * nblocks;
+	switch (blksize) {
+	case CD_FRAMESIZE_RAW0	: cgc->cmd[9] = 0x58;
+	case CD_FRAMESIZE_RAW1	: cgc->cmd[9] = 0x78;
+	case CD_FRAMESIZE_RAW	: cgc->cmd[9] = 0xf8;
+	default			: cgc->cmd[9] = 0x10;
+	}
+	
+	return cdo->generic_packet(cdi, cgc);
+}
+
 /* Some of the cdrom ioctls are not implemented here, because these
  * appear to be either too device-specific, or it is not clear to me
  * what use they are. These are (number of drivers that support them
@@ -1231,7 +1293,7 @@
                 if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE)) 
 			return cdo->select_disc(cdi, arg);
 		if ((int)arg >= cdi->capacity)
-			return -EDRIVE_CANT_DO_THIS;
+			return -EINVAL;
 		return cdo->select_disc(cdi, arg);
 		}
 
@@ -1264,7 +1326,7 @@
 
 	case CDROM_GET_CAPABILITY: {
 		cdinfo(CD_DO_IOCTL, "entering CDROM_GET_CAPABILITY\n");
-		return cdo->capability;
+		return (cdo->capability & ~cdi->mask);
 		}
 
 /* The following function is implemented, although very few audio
@@ -1288,9 +1350,11 @@
 		cdinfo(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n"); 
 		if (!(cdo->capability & CDC_DRIVE_STATUS))
 			return -ENOSYS;
+		if (!CDROM_CAN(CDC_SELECT_DISC))
+			return cdo->drive_status(cdi, CDSL_CURRENT);
                 if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE)) 
-			return cdo->drive_status(cdi, arg);
-                if (((int)arg > cdi->capacity))
+			return cdo->drive_status(cdi, CDSL_CURRENT);
+		if (((int)arg >= cdi->capacity))
 			return -EINVAL;
 		return cdo->drive_status(cdi, arg);
 		}
@@ -1415,7 +1479,6 @@
 			return -ENOSYS;
 		cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); 
 		IOCTL_IN(arg, struct cdrom_msf, msf);
-		CHECKAUDIO;
 		return cdo->audio_ioctl(cdi, cmd, &msf);
 		}
 	case CDROMPLAYTRKIND: {
@@ -1464,22 +1527,164 @@
 	return -ENOSYS;
 }
 
+static inline
+int msf_to_lba (char m, char s, char f)
+{
+	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
+}
+
 static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
 		     unsigned long arg)
 {		
 	struct cdrom_device_ops *cdo = cdi->ops;
+	kdev_t dev = cdi->dev;
 	struct cdrom_generic_command cgc;
-	int rv;
+	char buffer[32];
+	int ret = 0;
 
 	memset(&cgc, 0, sizeof(cgc));
 
 	/* build a unified command and queue it through
 	   cdo->generic_packet() */
 	switch (cmd) {
+	case CDROMREADRAW:
+	case CDROMREADMODE1:
+	case CDROMREADMODE2: {
+		struct cdrom_msf msf;
+		int blocksize = 0, format = 0, lba;
+		
+		switch (cmd) {
+		case CDROMREADRAW:
+			blocksize = CD_FRAMESIZE_RAW;
+			format = 0;
+			break;
+		case CDROMREADMODE1:
+			blocksize = CD_FRAMESIZE; break;
+			format = 2;
+			break;
+		case CDROMREADMODE2:
+			blocksize = CD_FRAMESIZE_RAW0; break;
+			format = 0;
+			break;
+		}
+		IOCTL_IN(arg, struct cdrom_msf, msf);
+		lba = msf_to_lba(msf.cdmsf_min0,msf.cdmsf_sec0,msf.cdmsf_frame0);
+		/* FIXME: we need upper bound checking, too!! */
+		if (lba < 0)
+			return -EINVAL;
+		cgc.buffer = (char *) kmalloc(blocksize, GFP_KERNEL);
+		if (cgc.buffer == NULL)
+			return -ENOMEM;
+		ret = cdrom_read_block(cdi, &cgc, lba, 1, format, blocksize);
+		if (!ret)
+			if (copy_to_user((char *)arg, cgc.buffer, blocksize))
+				return -EFAULT;
+		kfree(cgc.buffer);
+		return ret;
+		}
+	case CDROMREADAUDIO: {
+		struct cdrom_read_audio ra;
+		int lba;
+
+		IOCTL_IN(arg, struct cdrom_read_audio, ra);
+
+		if (ra.addr_format == CDROM_MSF)
+			lba = msf_to_lba(ra.addr.msf.minute,
+					 ra.addr.msf.second,
+					 ra.addr.msf.frame);
+		else if (ra.addr_format == CDROM_LBA)
+			lba = ra.addr.lba;
+		else
+			return -EINVAL;
+
+		/* FIXME: we need upper bound checking, too!! */
+		if (lba < 0)
+			return -EINVAL;
+
+		/* do between 1 and 8 frames at the time */
+		if (ra.nframes > 8 || ra.nframes < 1)
+			return -EINVAL;
+
+		/* just a nice round figure */
+		if ((cgc.buffer = (char *) kmalloc(CD_FRAMESIZE_RAW*ra.nframes,
+						   GFP_KERNEL)) == NULL)
+			return -ENOMEM;
+
+		if (!access_ok(VERIFY_WRITE, ra.buf, ra.nframes*CD_FRAMESIZE_RAW))
+			return -EFAULT;
+
+		while (ra.nframes > 0) {
+			ret = cdrom_read_block(cdi, &cgc, lba, ra.nframes, 1,
+					       CD_FRAMESIZE_RAW);
+			if (ret) break;
+			__copy_to_user(ra.buf, cgc.buffer,
+				       CD_FRAMESIZE_RAW*ra.nframes);
+			ra.buf += (CD_FRAMESIZE_RAW * ra.nframes);
+			ra.nframes -= ra.nframes;
+			lba += ra.nframes;
+		}
+		kfree(cgc.buffer);
+		return ret;
+		}
+	case CDROMSUBCHNL: {
+		struct cdrom_subchnl q;
+		u_char requested, back;
+		IOCTL_IN(arg, struct cdrom_subchnl, q);
+		requested = q.cdsc_format;
+		if (!((requested == CDROM_MSF) ||
+		      (requested == CDROM_LBA)))
+			return -EINVAL;
+		q.cdsc_format = CDROM_MSF;
+		if ((ret = cdrom_read_subchannel(cdi, &q, 0)))
+			return ret;
+		back = q.cdsc_format; /* local copy */
+		sanitize_format(&q.cdsc_absaddr, &back, requested);
+		sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
+		IOCTL_OUT(arg, struct cdrom_subchnl, q);
+		/* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ 
+		return 0;
+		}
+	case CDROMPLAYTRKIND: {
+		struct cdrom_ti ti;
+		cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n");
+		IOCTL_IN(arg, struct cdrom_ti, ti);
+		cgc.cmd[0] = GPCMD_PLAYAUDIO_TI;
+		cgc.cmd[4] = ti.cdti_trk0;
+		cgc.cmd[5] = ti.cdti_ind0;
+		cgc.cmd[7] = ti.cdti_trk1;
+		cgc.cmd[8] = ti.cdti_ind1;
+		return cdo->generic_packet(cdi, &cgc);
+		}
+	case CDROMPLAYMSF: {
+		struct cdrom_msf msf;
+		cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
+		IOCTL_IN(arg, struct cdrom_msf, msf);
+		cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
+		cgc.cmd[3] = msf.cdmsf_min0;
+		cgc.cmd[4] = msf.cdmsf_sec0;
+		cgc.cmd[5] = msf.cdmsf_frame0;
+		cgc.cmd[6] = msf.cdmsf_min1;
+		cgc.cmd[7] = msf.cdmsf_sec1;
+		cgc.cmd[8] = msf.cdmsf_frame1;
+		return cdo->generic_packet(cdi, &cgc);
+		}
+	case CDROMPLAYBLK: {
+		struct cdrom_blk blk;
+		cdinfo(CD_DO_IOCTL, "entering CDROMPLAYBLK\n");
+		IOCTL_IN(arg, struct cdrom_blk, blk);
+		cgc.cmd[0] = GPCMD_PLAY_AUDIO_10;
+		cgc.cmd[2] = blk.from >> 24;
+		cgc.cmd[3] = blk.from >> 16;
+		cgc.cmd[4] = blk.from >> 8;
+		cgc.cmd[5] = blk.from;
+		cgc.cmd[7] = blk.len >> 8;
+		cgc.cmd[8] = blk.len;
+		return cdo->generic_packet(cdi, &cgc);
+		}
 	case CDROMVOLCTRL:
 	case CDROMVOLREAD: {
 		struct cdrom_volctrl volctrl;
-		char buffer[32], mask[32];
+		char mask[32];
 		unsigned short offset;
 		cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n");
 
@@ -1487,14 +1692,16 @@
 
 		cgc.buffer = buffer;
 		cgc.buflen = 24;
-		rv = cdrom_mode_sense(cdi, &cgc, 0xe, 0);
-		if (rv) return rv;
+		if ((ret = cdrom_mode_sense(cdi, &cgc, 
+				GPMODE_AUDIO_CTL_PAGE, 0)))
+		    return ret;
 		
 		/* some drives have longer pages, adjust and reread. */
 		if (buffer[1] > cgc.buflen) {
 			cgc.buflen = buffer[1] + 2;
-			rv = cdrom_mode_sense(cdi, &cgc, 0xe, 0);
-			if (rv) return rv;
+			if ((ret = cdrom_mode_sense(cdi, &cgc, 
+					GPMODE_AUDIO_CTL_PAGE, 0))) 
+			    return ret;
 		}
 		
 		/* get the offset from the length of the page. length
@@ -1514,8 +1721,9 @@
 		
 		/* get the volume mask */
 		cgc.buffer = mask;
-		rv = cdrom_mode_sense(cdi, &cgc, 0xe, 1);
-		if (rv) return rv;
+		if ((ret = cdrom_mode_sense(cdi, &cgc, 
+				GPMODE_AUDIO_CTL_PAGE, 1)))
+		    return ret;
 
 		buffer[offset+9] = volctrl.channel0 & mask[offset+9];
 		buffer[offset+11] = volctrl.channel1 & mask[offset+11];
@@ -1534,7 +1742,7 @@
 	case CDROMSTART:
 	case CDROMSTOP: {
 		cdinfo(CD_DO_IOCTL, "entering audio ioctl (start/stop)\n"); 
-		cgc.cmd[0] = 0x1b;
+		cgc.cmd[0] = GPCMD_START_STOP_UNIT;
 		cgc.cmd[1] = 1;
 		cgc.cmd[4] = (cmd == CDROMSTART) ? 1 : 0;
 		return cdo->generic_packet(cdi, &cgc);
@@ -1543,7 +1751,7 @@
 	case CDROMPAUSE:
 	case CDROMRESUME: {
 		cdinfo(CD_DO_IOCTL, "entering audio ioctl (pause/resume)\n"); 
-		cgc.cmd[0] = 0x4b;
+		cgc.cmd[0] = GPCMD_PAUSE_RESUME;
 		cgc.cmd[8] = (cmd == CDROMRESUME) ? 1 : 0;
 		return cdo->generic_packet(cdi, &cgc);
 		}
@@ -1554,11 +1762,11 @@
 			return -ENOSYS;
 		cdinfo(CD_DO_IOCTL, "entering dvd_read_struct\n"); 
 		IOCTL_IN(arg, dvd_struct, s);
-		if ((rv = dvd_read_struct(cdi, &s)) == 0) {
+		if ((ret = dvd_read_struct(cdi, &s)) == 0) {
 			IOCTL_OUT(arg, dvd_struct, s);
 			return 0;
 		}
-		return rv;
+		return ret;
 		}
 
 	case DVD_AUTH: {
@@ -1567,8 +1775,8 @@
 			return -ENOSYS;
 		cdinfo(CD_DO_IOCTL, "entering dvd_auth\n"); 
 		IOCTL_IN(arg, dvd_authinfo, ai);
-		if ((rv = dvd_do_auth (cdi, &ai)))
-			return rv;
+		if ((ret = dvd_do_auth (cdi, &ai)))
+			return ret;
 		IOCTL_OUT(arg, dvd_authinfo, ai);
 		return 0;
 		}
@@ -1579,20 +1787,173 @@
 		cdinfo(CD_DO_IOCTL, "entering send_packet\n"); 
 		IOCTL_IN(arg, struct cdrom_generic_command, cgc);
 		cgc.buffer = kmalloc(cgc.buflen, GFP_KERNEL);
-		rv = cdo->generic_packet(cdi, &cgc);
+		ret = cdo->generic_packet(cdi, &cgc);
 		if (copy_to_user((void*)arg, cgc.buffer, cgc.buflen)) {
 			kfree(cgc.buffer);
 			return -EFAULT;
 		}
 		kfree(cgc.buffer);
-		return rv;
+		return ret;
+		}
+	case CDROM_NEXT_WRITABLE: {
+		long next;
+		if ((ret = cdrom_get_next_writable(dev, &next)))
+			return ret;
+		IOCTL_OUT(arg, long, next);
+		return 0;
+		}
+	case CDROM_LAST_WRITTEN: {
+		long last;
+		if ((ret = cdrom_get_last_written(dev, &last)))
+			return ret;
+		IOCTL_OUT(arg, long, last);
+		return 0;
 		}
-
 	} /* switch */
 
 	return -ENOTTY;
 }
 
+static int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type,
+				 track_information *ti)
+{
+        struct cdrom_device_info *cdi = cdrom_find_device (dev);
+	struct cdrom_device_ops *cdo = cdi->ops;
+	struct cdrom_generic_command cgc;
+	int ret;
+
+	memset(&cgc, 0, sizeof(cgc));
+	cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO;
+	cgc.cmd[1] = type & 3;
+	cgc.cmd[4] = (track & 0xff00) >> 8;
+	cgc.cmd[5] = track & 0xff;
+	cgc.cmd[8] = cgc.buflen = 8;
+	cgc.buffer = (char *)ti;
+
+	ret = cdo->generic_packet(cdi, &cgc);
+	if (ret) return ret;
+	
+	cgc.cmd[8] = cgc.buflen = be16_to_cpu(ti->track_information_length) +
+		     sizeof(ti->track_information_length);
+	return cdo->generic_packet(cdi, &cgc);
+}
+
+static int cdrom_get_disc_info(kdev_t dev, disc_information *di)
+{
+	struct cdrom_device_info *cdi = cdrom_find_device (dev);
+	struct cdrom_device_ops *cdo = cdi->ops;
+	struct cdrom_generic_command cgc;
+
+	/* set up command and get the disc info */
+	memset(&cgc, 0, sizeof(cgc));
+	memset(di, 0, sizeof(disc_information));
+	cgc.cmd[0] = GPCMD_READ_DISC_INFO;
+	cgc.cmd[8] = cgc.buflen = sizeof(*di);
+	cgc.buffer = (char *)di;
+
+	return cdo->generic_packet(cdi, &cgc);
+}
+
+
+/* return the last written block on the CD-R media. this is for the udf
+   file system. */
+int cdrom_get_last_written(kdev_t dev, long *last_written)
+{	
+	struct cdrom_device_info *cdi = cdrom_find_device (dev);
+	struct cdrom_tocentry toc;
+	disc_information di;
+	track_information ti;
+	__u32 last_track;
+	int ret = -1;
+	
+	if (!CDROM_CAN(CDC_GENERIC_PACKET))
+		goto use_toc;
+	
+	if ((ret = cdrom_get_disc_info(dev, &di)))
+		goto use_toc;
+
+	last_track = (di.last_track_msb << 8) | di.last_track_lsb;
+	if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti)))
+		goto use_toc;
+
+	/* if this track is blank, try the previous. */
+	if (ti.blank) {
+		last_track--;
+		if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti)))
+			goto use_toc;
+	}
+
+	/* if last recorded field is valid, return it. */
+	if (ti.lra_v) {
+		*last_written = be32_to_cpu(ti.last_rec_address);
+	} else {
+		/* make it up instead */
+		*last_written = be32_to_cpu(ti.track_start) +
+				be32_to_cpu(ti.track_size);
+		if (ti.free_blocks)
+			*last_written -= (be32_to_cpu(ti.free_blocks) + 7);
+	}
+	return 0;
+
+	/* this is where we end up if the drive either can't do a
+	   GPCMD_READ_DISC_INFO or GPCMD_READ_TRACK_RZONE_INFO or if
+	   it fails. then we return the toc contents. */
+use_toc:
+	toc.cdte_format = CDROM_MSF;
+	toc.cdte_track = CDROM_LEADOUT;
+	if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc))
+		return ret;
+	sanitize_format(&toc.cdte_addr, &toc.cdte_format, CDROM_LBA);
+	*last_written = toc.cdte_addr.lba;
+	return 0;
+}
+
+/* return the next writable block. also for udf file system. */
+int cdrom_get_next_writable(kdev_t dev, long *next_writable)
+{
+	struct cdrom_device_info *cdi = cdrom_find_device (dev);
+	disc_information di;
+	track_information ti;
+	__u16 last_track;
+	int ret = -1;
+	
+	if (!CDROM_CAN(CDC_GENERIC_PACKET))
+		goto use_last_written;
+
+	if ((ret = cdrom_get_disc_info(dev, &di)))
+		goto use_last_written;
+
+	last_track = (di.last_track_msb << 8) | di.last_track_lsb;
+	if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti)))
+		goto use_last_written;
+
+        /* if this track is blank, try the previous. */
+	if (ti.blank) {
+		last_track--;
+		if ((ret = cdrom_get_track_info(dev, last_track, 1, &ti)))
+			goto use_last_written;
+	}
+
+	/* if next recordable address field is valid, use it. */
+	if (ti.nwa_v)
+		*next_writable = be32_to_cpu(ti.next_writable);
+	else
+		goto use_last_written;
+
+	return 0;
+
+use_last_written:
+	if ((ret = cdrom_get_last_written(dev, next_writable))) {
+		*next_writable = 0;
+		return ret;
+	} else {
+		*next_writable += 7;
+		return 0;
+	}
+}
+
+EXPORT_SYMBOL(cdrom_get_next_writable);
+EXPORT_SYMBOL(cdrom_get_last_written);
 EXPORT_SYMBOL(cdrom_count_tracks);
 EXPORT_SYMBOL(register_cdrom);
 EXPORT_SYMBOL(unregister_cdrom);
diff -u --recursive --new-file v2.3.15/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- v2.3.15/linux/drivers/cdrom/sonycd535.c	Tue Jul  6 19:05:48 1999
+++ linux/drivers/cdrom/sonycd535.c	Fri Aug 27 11:56:04 1999
@@ -1524,9 +1524,11 @@
 		printk(CDU535_MESSAGE_NAME ": my base address is not free!\n");
 		return -EIO;
 	}
+
 	/* look for the CD-ROM, follows the procedure in the DOS driver */
 	inb(select_unit_reg);
 	/* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */
+	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout((HZ+17)*40/18);
 	inb(result_reg);
 
diff -u --recursive --new-file v2.3.15/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.3.15/linux/drivers/char/Config.in	Thu Aug 26 13:05:34 1999
+++ linux/drivers/char/Config.in	Tue Aug 31 11:35:59 1999
@@ -69,6 +69,7 @@
   dep_tristate 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE $CONFIG_BUSMOUSE
   dep_tristate 'Logitech busmouse support' CONFIG_LOGIBUSMOUSE $CONFIG_BUSMOUSE
   dep_tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE $CONFIG_BUSMOUSE
+  dep_tristate 'Apple Desktop Bus mouse support' CONFIG_ADBMOUSE $CONFIG_BUSMOUSE
 fi
 
 tristate 'Mouse Support (not serial and bus mice)' CONFIG_MOUSE
@@ -195,6 +196,9 @@
 endmenu
 
 tristate 'Double Talk PC internal speech card support' CONFIG_DTLK
+
+tristate 'Siemens R3964 line discipline' CONFIG_R3964
+tristate 'Applicom intelligent fieldbus card support' CONFIG_APPLICOM
 
 mainmenu_option next_comment
 comment 'Ftape, the floppy tape device driver'
diff -u --recursive --new-file v2.3.15/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.3.15/linux/drivers/char/Makefile	Thu Aug 26 13:05:34 1999
+++ linux/drivers/char/Makefile	Mon Aug 30 18:05:57 1999
@@ -206,11 +206,11 @@
   endif
 endif
 
-ifeq ($(CONFIG_MOUSE),y)
+ifeq ($(CONFIG_BUSMOUSE),y)
 M = y
 OX_OBJS += busmouse.o
 else
-  ifeq ($(CONFIG_MOUSE),m)
+  ifeq ($(CONFIG_BUSMOUSE),m)
   MM = m
   MX_OBJS += busmouse.o
   endif
@@ -224,6 +224,22 @@
   endif
 endif
 
+ifeq ($(CONFIG_R3964),y)
+O_OBJS += n_r3964.o
+else
+  ifeq ($(CONFIG_R3964),m)
+  M_OBJS += n_r3964.o
+  endif
+endif
+
+ifeq ($(CONFIG_APPLICOM),y)
+O_OBJS += applicom.o
+else
+  ifeq ($(CONFIG_APPLICOM),m)
+  M_OBJS += applicom.o
+  endif
+endif
+
 ifeq ($(CONFIG_MS_BUSMOUSE),y)
 O_OBJS += msbusmouse.o
 else
@@ -385,7 +401,7 @@
 ifeq ($(CONFIG_VIDEO_ZORAN),y)
 O_OBJS += buz.o
 else
-  ifeq ($(CONFIG_VIDEO_LML33),m)
+  ifeq ($(CONFIG_VIDEO_ZORAN),m)
     M_OBJS += buz.o
   endif
 endif
diff -u --recursive --new-file v2.3.15/linux/drivers/char/adbmouse.c linux/drivers/char/adbmouse.c
--- v2.3.15/linux/drivers/char/adbmouse.c	Thu Aug 12 11:50:14 1999
+++ linux/drivers/char/adbmouse.c	Tue Aug 31 11:35:59 1999
@@ -145,10 +145,10 @@
 
 static struct busmouse adb_mouse =
 {
-	ADB_MOUSE_MINOR, "adbmouse", open_mouse, close_mouse, 7
+	ADB_MOUSE_MINOR, "adbmouse", open_mouse, release_mouse, 7
 };
 
-__initfunc(int adb_mouse_init(void))
+int __init adb_mouse_init(void)
 {
 #ifdef __powerpc__
 	if ((_machine != _MACH_chrp) && (_machine != _MACH_Pmac))
@@ -174,7 +174,7 @@
  * option, which is about using ADB keyboard buttons to emulate
  * mouse buttons. -- paulus
  */
-__initfunc(void adb_mouse_setup(char *str, int *ints))
+void __init adb_mouse_setup(char *str, int *ints)
 {
 	if (ints[0] >= 1) {
 		adb_emulate_buttons = ints[1] > 0;
diff -u --recursive --new-file v2.3.15/linux/drivers/char/applicom.c linux/drivers/char/applicom.c
--- v2.3.15/linux/drivers/char/applicom.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/applicom.c	Mon Aug 30 18:05:57 1999
@@ -0,0 +1,842 @@
+/* Derived from Applicom driver ac.c for SCO Unix                            */
+/* Ported by David Woodhouse, Axiom (Cambridge) Ltd.                         */
+/* Dave@mvhi.com  30/8/98                                                    */
+/* $Id: ac.c,v 1.16 1999/08/28 15:11:50 dwmw2 Exp $			     */
+/* This module is for Linux 2.1 and 2.2 series kernels.                      */
+/*****************************************************************************/
+/* J PAGET 18/02/94 passage V2.4.2 ioctl avec code 2 reset to les interrupt  */
+/* ceci pour reseter correctement apres une sortie sauvage                   */
+/* J PAGET 02/05/94 passage V2.4.3 dans le traitement de d'interruption,     */
+/* LoopCount n'etait pas initialise a 0.                                     */
+/* F LAFORSE 04/07/95 version V2.6.0 lecture bidon apres acces a une carte   */
+/*           pour liberer le bus                                             */
+/* J.PAGET 19/11/95 version V2.6.1 Nombre, addresse,irq n'est plus configure */
+/* et passe en argument a acinit, mais est scrute sur le bus pour s'adapter  */
+/* au nombre de cartes presentes sur le bus. IOCL code 6 affichait V2.4.3    */
+/* F.LAFORSE 28/11/95 creation de fichiers acXX.o avec les differentes       */
+/* adresses de base des cartes, IOCTL 6 plus complet                         */ 
+/* J.PAGET le 19/08/96 copie de la version V2.6 en V2.8.0 sans modification  */
+/* de code autre que le texte V2.6.1 en V2.8.0                               */
+/*****************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/pci.h>
+#include <linux/wait.h>
+#include <linux/init.h>
+#include "applicom.h"
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#undef DEBUG
+#define DEVPRIO PZERO+8
+#define FALSE 0
+#define TRUE  ~FALSE 
+#define MAX_BOARD 8                 /* maximum of pc board possible */
+#define MAX_ISA_BOARD 4
+#define LEN_RAM_IO 0x800
+#define AC_MINOR 157
+
+#ifndef PCI_VENDOR_ID_APPLICOM
+#define PCI_VENDOR_ID_APPLICOM                0x1389 
+#define PCI_DEVICE_ID_APPLICOM_PCIGENERIC     0x0001
+#define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002
+#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB     0x0003
+#define MAX_PCI_DEVICE_NUM 3
+#endif
+
+static char *applicom_pci_devnames[]={
+  "PCI board", "PCI2000IBS / PCI2000CAN", "PCI2000PFB"};
+
+MODULE_AUTHOR("David Woodhouse & Applicom International");
+MODULE_DESCRIPTION("Driver for Applicom Profibus card");
+MODULE_PARM(irq, "i");
+MODULE_PARM_DESC(irq, "IRQ of the Applicom board");
+MODULE_PARM(mem,"i");
+MODULE_PARM_DESC(mem, "Shared Memory Address of Applicom board");
+
+MODULE_SUPPORTED_DEVICE("ac");
+
+
+struct applicom_board {
+  unsigned long PhysIO;
+  unsigned long RamIO;
+#if LINUX_VERSION_CODE > 0x20300
+  wait_queue_head_t FlagSleepSend;
+#else
+  struct wait_queue *FlagSleepSend;
+#endif
+  long irq;
+} apbs[MAX_BOARD];
+
+static unsigned int irq=0;                    /* interrupt number IRQ       */
+static unsigned long mem=0;                   /* physical segment of board  */
+
+static unsigned int numboards;                /* number of installed boards */
+static volatile unsigned char Dummy;
+#if LINUX_VERSION_CODE > 0x20300
+static DECLARE_WAIT_QUEUE_HEAD (FlagSleepRec);
+#else
+static struct wait_queue *FlagSleepRec;
+#endif
+static unsigned int WriteErrorCount;          /* number of write error      */
+static unsigned int ReadErrorCount;           /* number of read error       */
+static unsigned int DeviceErrorCount;         /* number of device error     */
+
+static loff_t ac_llseek(struct file *file, loff_t offset, int origin);
+static int ac_open(struct inode *inode, struct file *filp);
+static ssize_t ac_read (struct file *filp, char *buf, size_t count, loff_t *ptr);
+static ssize_t ac_write (struct file *file, const char *buf, size_t count, loff_t *ppos);
+static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+static int ac_release(struct inode *inode, struct file *file);
+static void ac_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+
+struct file_operations ac_fops={
+	ac_llseek,      /* llseek */
+	ac_read,        /* read */
+	ac_write,       /* write */
+	NULL,           /* readdir */
+	NULL,           /* poll */
+       	ac_ioctl,       /* ioctl */
+       	NULL,           /* mmap */
+	ac_open,        /* open */
+	NULL,           /* flush */
+	ac_release,     /* release */
+	NULL            /* fsync */
+};
+
+struct miscdevice ac_miscdev={
+  AC_MINOR,
+  "ac",
+  &ac_fops
+};
+
+int ac_register_board(unsigned long physloc, unsigned long loc, 
+		      unsigned char boardno)
+{
+	volatile unsigned char byte_reset_it;
+
+	if((readb(loc + CONF_END_TEST)     != 0x00) ||
+	   (readb(loc + CONF_END_TEST + 1) != 0x55) ||
+	   (readb(loc + CONF_END_TEST + 2) != 0xAA) ||
+	   (readb(loc + CONF_END_TEST + 3) != 0xFF))
+	  return 0;
+
+
+	if (!boardno)
+	  boardno = readb(loc + NUMCARD_OWNER_TO_PC);
+
+	if (!boardno && boardno > MAX_BOARD)
+	  {
+	    printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n",boardno, physloc, MAX_BOARD);
+	    return 0;
+	  }
+
+	if (apbs[boardno-1].RamIO)
+	  {
+	    printk(KERN_WARNING "Board #%d (at 0x%lx) conflicts with previous board #%d (at 0x%lx)\n", 
+		   boardno, physloc, boardno, apbs[boardno-1].PhysIO);
+	    return 0;
+	  }
+
+	boardno--;
+
+	apbs[boardno].PhysIO = physloc;
+	apbs[boardno].RamIO = loc;
+#if LINUX_VERSION_CODE > 0x20300
+	init_waitqueue_head(&apbs[boardno].FlagSleepSend);
+#else
+	apbs[boardno].FlagSleepSend = NULL;
+#endif
+	byte_reset_it = readb(loc + RAM_IT_TO_PC);
+
+	numboards++;
+	return 	boardno+1;
+}
+
+#ifdef MODULE
+
+#define applicom_init init_module
+
+void cleanup_module(void)
+{
+	int i;
+
+	misc_deregister(&ac_miscdev);
+	for (i=0; i< MAX_BOARD; i++)
+	  {
+	    if (!apbs[i].RamIO)
+	      continue;
+	    iounmap((void *)apbs[i].RamIO);
+	    if (apbs[i].irq)
+	      free_irq(apbs[i].irq,&ac_open);     
+	  }
+	//	printk("Removing Applicom module\n");
+}
+
+#endif /* MODULE */
+
+__initfunc(int applicom_init(void))
+{
+	int i, numisa=0;
+	struct pci_dev *dev = NULL;
+	void *RamIO;
+	int boardno;
+#if LINUX_VERSION_CODE > 0x20300
+#define PCI_BASE_ADDRESS(dev) (dev->resource[0].start)
+#else
+#define PCI_BASE_ADDRESS(dev) (dev->base_address[0])
+#endif
+
+	printk(KERN_INFO "Applicom driver: $Id: ac.c,v 1.16 1999/08/28 15:11:50 dwmw2 Exp $\n");
+	
+	/* No mem and irq given - check for a PCI card */
+	
+	while ( (dev = pci_find_device(PCI_VENDOR_ID_APPLICOM, 1, dev)))
+	  {
+	    //	    mem = dev->base_address[0];
+	    // irq = dev->irq;
+
+	    RamIO = ioremap(PCI_BASE_ADDRESS(dev), LEN_RAM_IO);
+
+	    if (!RamIO) {
+	      printk(KERN_INFO "ac.o: Failed to ioremap PCI memory space at 0x%lx\n", PCI_BASE_ADDRESS(dev));
+	      return -EIO;
+	    }
+	    
+	    printk(KERN_INFO "Applicom %s found at mem 0x%lx, irq %d\n",
+		   applicom_pci_devnames[dev->device-1], PCI_BASE_ADDRESS(dev), 
+		   dev->irq);
+
+	    if (!(boardno = ac_register_board(PCI_BASE_ADDRESS(dev),
+					      (unsigned long)RamIO,0)))
+	      {
+		printk(KERN_INFO "ac.o: PCI Applicom device doesn't have correct signature.\n");
+		iounmap(RamIO);
+		continue;
+	      }
+	    
+	    if (request_irq(dev->irq, &ac_interrupt, SA_SHIRQ, "Applicom PCI", &ac_open))
+	      {
+		printk(KERN_INFO "Could not allocate IRQ %d for PCI Applicom device.\n", dev->irq);
+		iounmap(RamIO);
+		apbs[boardno-1].RamIO = 0;
+		continue;
+	      }
+
+	    /* Enable interrupts. */
+
+	    writeb(0x40, apbs[boardno-1].RamIO + RAM_IT_FROM_PC);
+
+	    apbs[boardno-1].irq = dev->irq;
+	  }
+	
+	/* Finished with PCI cards. If none registered, 
+	 * and there was no mem/irq specified, exit */
+
+	if (!mem || !irq)
+	  {
+	    if (numboards)
+	      goto fin;
+	    else
+	      {
+		printk(KERN_INFO "ac.o: No PCI boards found.\n");
+		printk(KERN_INFO "ac.o: For an ISA board you must supply memory and irq parameters.\n");
+		return -ENXIO;
+	      }
+	  }
+	
+	/* Now try the specified ISA cards */
+
+	RamIO = ioremap(mem, LEN_RAM_IO * MAX_ISA_BOARD); 
+
+	if (!RamIO) {
+	  printk(KERN_INFO "ac.o: Failed to ioremap ISA memory space at 0x%lx\n",mem);
+	}
+	
+	for (i=0; i< MAX_ISA_BOARD; i++)
+	  {
+	    RamIO = ioremap(mem+ (LEN_RAM_IO*i), LEN_RAM_IO); 
+
+	    if (!RamIO) {
+	      printk(KERN_INFO "ac.o: Failed to ioremap the ISA card's memory space (slot #%d)\n",i+1);
+	      continue;
+	    }
+
+	    if (!(boardno = ac_register_board((unsigned long)mem+ (LEN_RAM_IO*i),
+					      (unsigned long)RamIO,i+1))) {
+	      iounmap(RamIO);
+	      continue;
+	    }
+	    
+	    printk("Applicom ISA card found at mem 0x%lx, irq %d\n", mem + (LEN_RAM_IO*i), irq);
+
+	    if (!numisa)
+	      {
+		if (request_irq(irq, &ac_interrupt, SA_SHIRQ, "Applicom ISA", &ac_open))
+		  {
+		    printk("Could not allocate IRQ %d for ISA Applicom device.\n", irq);
+		    iounmap((void *)RamIO);
+		    apbs[boardno-1].RamIO = 0;
+		  }
+		apbs[boardno-1].irq=irq;
+	      }
+	    else
+	      apbs[boardno-1].irq=0;
+
+	    numisa++;
+	  }
+
+	if (!numisa)
+	  printk("ac.o: No valid ISA Applicom boards found at mem 0x%lx\n",mem);
+
+#if LINUX_VERSION_CODE > 0x20300
+	init_waitqueue_head(&FlagSleepRec);
+#else
+	FlagSleepRec     = NULL;
+#endif
+	WriteErrorCount  = 0;
+	ReadErrorCount   = 0;
+	DeviceErrorCount = 0;
+
+fin:
+	if (numboards)
+	  {
+	    misc_register (&ac_miscdev);
+	    for (i=0; i<MAX_BOARD; i++)
+	      {
+		int serial;
+		char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];
+
+		if (!apbs[i].RamIO)
+		  continue;
+		
+		for(serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++)
+		  boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial);
+		boardname[serial]=0;
+		
+
+		printk("Applicom board %d: %s, PROM V%d.%d",
+		       i+1, boardname,
+		       (int)(readb(apbs[i].RamIO + VERS) >> 4),
+		       (int)(readb(apbs[i].RamIO + VERS) & 0xF));
+
+		serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + 
+		  (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + 
+		  (readb(apbs[i].RamIO + SERIAL_NUMBER + 2) );
+		
+		if (serial != 0)
+		    printk (" S/N %d\n", serial);
+		else
+		  printk("\n");
+	      }
+	    return 0;
+	  }
+	
+	else
+	  return -ENXIO;
+}
+
+
+#ifndef MODULE
+__initcall (applicom_init);
+#endif
+
+static loff_t ac_llseek(struct file *file, loff_t offset, int origin)
+{
+	return -ESPIPE;
+}
+
+static int ac_open(struct inode *inode, struct file *filp)
+{
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int ac_release(struct inode *inode, struct file *file)
+{
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+
+static ssize_t ac_write (struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+  unsigned int NumCard;                /* Board number 1 -> 8           */
+  unsigned int IndexCard;              /* Index board number 0 -> 7     */
+  unsigned char TicCard;               /* Board TIC to send             */
+  unsigned long flags;                 /* Current priority              */
+  struct st_ram_io st_loc;
+  struct mailbox tmpmailbox;
+
+  if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) {
+	  printk("Hmmm. write() of Applicom card, length %d != expected %d\n",count,sizeof(struct st_ram_io) + sizeof(struct mailbox));
+	  return -EINVAL;
+  }
+
+  if(copy_from_user (&st_loc, buf, sizeof(struct st_ram_io))) {
+	  return -EFAULT;
+  }
+  if(copy_from_user (&tmpmailbox, &buf[sizeof(struct st_ram_io)], sizeof(struct mailbox))) {
+	  return -EFAULT;
+  }
+
+  NumCard   = st_loc.num_card;         /* board number to send          */
+  TicCard   = st_loc.tic_des_from_pc;  /* tic number to send            */
+  IndexCard = NumCard -1;
+  if((NumCard < 1) || (NumCard > MAX_BOARD) || !apbs[IndexCard].RamIO)
+  {                                    /* User board number not OK      */
+    // printk("Write to invalid Applicom board %d\n", NumCard);
+    return -EINVAL;                    /* Return error code user buffer */
+  }
+	  
+#ifdef DEBUG
+  {
+    int c;
+    
+    printk("Write to applicom card #%d. struct st_ram_io follows:",NumCard);
+    
+    
+    
+    for (c=0; c< sizeof(struct st_ram_io);)
+      {
+	printk("\n%5.5X: %2.2X",c,((unsigned char *)&st_loc)[c]);
+	
+	for (c++ ; c%8 && c<sizeof(struct st_ram_io); c++)
+	  {
+	    printk(" %2.2X",((unsigned char *)&st_loc)[c]);
+	  }
+      }
+
+	   printk("\nstruct mailbox follows:");
+	 
+    for (c=0; c< sizeof(struct mailbox);)
+      {
+	printk("\n%5.5X: %2.2X",c,((unsigned char *)&tmpmailbox)[c]);
+	
+	for (c++ ; c%8 && c<sizeof(struct mailbox); c++)
+	  {
+	    printk(" %2.2X",((unsigned char *)&tmpmailbox)[c]);
+	  }
+      }
+    
+    printk("\n");
+  }
+           	  
+#endif
+
+  save_flags (flags);
+  cli();                               /* disable interrupt             */
+
+  if(readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) > 2)  /* Test octet ready correct */
+  {
+    Dummy = readb(apbs[IndexCard].RamIO + VERS);
+    restore_flags(flags);
+    printk("APPLICOM driver write error board %d, DataFromPcReady = %d\n",
+           IndexCard,(int)readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY));
+    DeviceErrorCount++;
+    return -EIO;
+  }
+  while (readb(apbs[IndexCard].RamIO + DATA_FROM_PC_READY) != 0)
+  {
+    Dummy = readb(apbs[IndexCard].RamIO + VERS);
+    restore_flags(flags);
+    interruptible_sleep_on (&apbs[IndexCard].FlagSleepSend);
+    if (signal_pending(current))
+      return -EINTR;
+    save_flags(flags);
+    cli();
+  }
+  writeb(1, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
+
+  //  memcpy_toio ((void *)apbs[IndexCard].PtrRamFromPc, (void *)&tmpmailbox, sizeof(struct mailbox));
+  {
+    unsigned char *from = (unsigned char *)&tmpmailbox;
+    unsigned long to = (unsigned long)apbs[IndexCard].RamIO + RAM_FROM_PC;
+    int c;
+
+    for (c=0; c<sizeof(struct mailbox) ; c++)
+      writeb(*(from++), to++);
+  }
+  writeb(0x20, apbs[IndexCard].RamIO + TIC_OWNER_FROM_PC);
+  writeb(0xff, apbs[IndexCard].RamIO + NUMCARD_OWNER_FROM_PC);
+  writeb(TicCard, apbs[IndexCard].RamIO + TIC_DES_FROM_PC);
+  writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC);
+  writeb(2, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
+  writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
+  Dummy = readb(apbs[IndexCard].RamIO + VERS);
+  restore_flags (flags);
+  return 0;
+}
+
+static ssize_t ac_read (struct file *filp, char *buf, size_t count, loff_t *ptr)
+{
+  unsigned int NumCard;                /* board number 1 -> 8         */
+  unsigned int IndexCard;              /* index board number 0 -> 7   */
+  unsigned long flags;
+  unsigned int i;
+  unsigned char tmp=0;
+  struct st_ram_io st_loc;
+  struct mailbox tmpmailbox;           /* bounce buffer - can't copy to user space with cli() */
+
+
+  if (count != sizeof(struct st_ram_io) + sizeof(struct mailbox)) {
+	  printk("Hmmm. read() of Applicom card, length %d != expected %d\n",count,sizeof(struct st_ram_io) + sizeof(struct mailbox));
+	  return -EINVAL;
+  }
+
+  save_flags(flags);
+  cli();
+  
+  i = 0;
+
+  while (tmp != 2)
+    {
+      for (i=0; i < MAX_BOARD; i++)
+	{
+	  if (!apbs[i].RamIO)
+	    continue;
+	  
+	  tmp = readb(apbs[i].RamIO + DATA_TO_PC_READY);
+	  
+	  if (tmp == 2)
+	    break;
+	  
+	  if (tmp > 2)  /* Test octet ready correct */
+	    {
+	      Dummy = readb(apbs[i].RamIO + VERS);
+	      restore_flags(flags);
+	      printk("APPLICOM driver read error board %d, DataToPcReady = %d\n",
+		     i,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY));
+	      DeviceErrorCount++;
+	      return -EIO;
+	    }
+	  Dummy = readb(apbs[i].RamIO + VERS);
+
+	}
+      if (tmp != 2)
+	{
+	  restore_flags(flags);
+	  interruptible_sleep_on (&FlagSleepRec);
+	  if (signal_pending(current))
+	    return -EINTR;
+	  save_flags(flags);
+	  cli();
+	}
+    }
+
+  IndexCard = i;
+  NumCard   = i+1;
+  st_loc.tic_owner_to_pc     = readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC);
+  st_loc.numcard_owner_to_pc = readb(apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);
+
+
+  //  memcpy_fromio(&tmpmailbox, apbs[IndexCard].PtrRamToPc, sizeof(struct mailbox));
+ {
+    unsigned long from = (unsigned long)apbs[IndexCard].RamIO + RAM_TO_PC;
+    unsigned char *to = (unsigned char *)&tmpmailbox;
+    int c;
+
+    for (c=0; c<sizeof(struct mailbox) ; c++)
+      *(to++) = readb(from++);
+  }
+  writeb(1,apbs[IndexCard].RamIO + ACK_FROM_PC_READY);
+  writeb(1,apbs[IndexCard].RamIO + TYP_ACK_FROM_PC);
+  writeb(NumCard, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC);
+  writeb(readb(apbs[IndexCard].RamIO + TIC_OWNER_TO_PC), 
+	 apbs[IndexCard].RamIO + TIC_ACK_FROM_PC);
+  writeb(2, apbs[IndexCard].RamIO + ACK_FROM_PC_READY);
+  writeb(0, apbs[IndexCard].RamIO + DATA_TO_PC_READY);
+  writeb(2, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
+  Dummy = readb(apbs[IndexCard].RamIO + VERS);
+  restore_flags(flags);
+
+#ifdef DEBUG
+  { int c;
+
+    printk("Read from applicom card #%d. struct st_ram_io follows:",NumCard);
+    
+    for (c=0; c< sizeof(struct st_ram_io);)
+      {
+	printk("\n%5.5X: %2.2X",c,((unsigned char *)&st_loc)[c]);
+	
+	for (c++ ; c%8 && c<sizeof(struct st_ram_io); c++)
+	  {
+	    printk(" %2.2X",((unsigned char *)&st_loc)[c]);
+	  }
+      }
+
+	   printk("\nstruct mailbox follows:");
+	 
+    for (c=0; c< sizeof(struct mailbox);)
+      {
+	printk("\n%5.5X: %2.2X",c,((unsigned char *)&tmpmailbox)[c]);
+	
+	for (c++ ; c%8 && c<sizeof(struct mailbox); c++)
+	  {
+	    printk(" %2.2X",((unsigned char *)&tmpmailbox)[c]);
+	  }
+      }
+    printk("\n");
+    
+  }
+#endif
+           	  
+
+  /* Je suis stupide. DW. */
+
+  if(copy_to_user (buf, &st_loc, sizeof(struct st_ram_io)))
+    return -EFAULT;
+  if(copy_to_user (&buf[sizeof(struct st_ram_io)], &tmpmailbox, sizeof(struct mailbox)))
+    return -EFAULT;
+
+  return 0;
+}
+
+static void ac_interrupt(int vec, void *dev_instance, struct pt_regs *regs)
+{
+  unsigned int i;
+  unsigned int FlagInt;
+  unsigned int LoopCount;
+  //  volatile unsigned char ResetIntBoard;
+	
+  //    printk("Applicom interrupt on IRQ %d occurred\n", vec);
+  
+  LoopCount = 0;
+  // for(i=boardno;i<MAX_BOARD;i++)         /* loop for not configured board   */
+  //  if (apbs[i].RamIO)
+  //    ResetIntBoard = *apbs[i].PtrRamItToPc;    /* reset interrupt of unused boards */
+
+  do
+  {
+    FlagInt = FALSE;
+    for(i=0;i<MAX_BOARD;i++)
+    {
+      if (!apbs[i].RamIO)
+	  continue;
+
+      if(readb(apbs[i].RamIO + RAM_IT_TO_PC) != 0)
+	FlagInt = TRUE;
+      writeb(0, apbs[i].RamIO + RAM_IT_TO_PC);
+
+      if(readb(apbs[i].RamIO + DATA_TO_PC_READY) > 2)
+	{
+        printk("APPLICOM driver interrupt err board %d, DataToPcReady = %d\n",
+               i+1,(int)readb(apbs[i].RamIO + DATA_TO_PC_READY));
+        DeviceErrorCount++;
+      }
+      if((readb(apbs[i].RamIO + DATA_FROM_PC_READY) > 2) && 
+	 (readb(apbs[i].RamIO + DATA_FROM_PC_READY) != 6))
+      {
+        printk("APPLICOM driver interrupt err board %d, DataFromPcReady = %d\n",
+             i+1,(int)readb(apbs[i].RamIO + DATA_FROM_PC_READY));
+        DeviceErrorCount++;
+      }
+      if(readb(apbs[i].RamIO + DATA_TO_PC_READY) == 2)         /* mailbox sent by the card ?   */
+      {
+         wake_up_interruptible(&FlagSleepRec);
+      }
+      if(readb(apbs[i].RamIO + DATA_FROM_PC_READY) == 0)       /* ram i/o free for write by pc ? */
+      {
+        if(waitqueue_active(&apbs[i].FlagSleepSend))                /* process sleep during read ?    */
+        {
+          wake_up_interruptible(&apbs[i].FlagSleepSend);
+        }
+      }
+      Dummy = readb(apbs[i].RamIO + VERS);
+
+      if(readb(apbs[i].RamIO + RAM_IT_TO_PC))
+	i--;        /* There's another int waiting on this card */
+    }
+    if(FlagInt) LoopCount = 0;
+    else        LoopCount++;
+  }
+  while(LoopCount < 2);
+}
+
+
+static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+
+{                                           /* @ ADG ou ATO selon le cas */
+  int i;
+  unsigned char IndexCard;
+  unsigned long pmem ;
+  volatile unsigned char byte_reset_it;
+  struct st_ram_io adgl ;
+  unsigned char TmpRamIo[sizeof(struct st_ram_io)];
+
+
+  if (copy_from_user (&adgl, (void *)arg,sizeof(struct st_ram_io)))
+      return -EFAULT;
+
+  IndexCard = adgl.num_card-1;
+  if(cmd != 0 && cmd != 6 &&
+	((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO))
+  {
+    printk("APPLICOM driver IOCTL, bad board number %d\n",(int)IndexCard+1);
+    printk("apbs[%d].RamIO = %lx\n",IndexCard, apbs[IndexCard].RamIO);
+    return -EINVAL;
+  }
+
+  switch( cmd )
+  {
+    case 0 :
+      pmem = apbs[IndexCard].RamIO;
+      for(i=0;i<sizeof(struct st_ram_io);i++)TmpRamIo[i]=readb(pmem++);
+      if (copy_to_user((void *)arg, TmpRamIo, sizeof(struct st_ram_io)))
+	      return -EFAULT;
+      break;
+    case 1 :
+      pmem = apbs[IndexCard].RamIO + CONF_END_TEST;
+      for (i=0;i<4;i++)
+	adgl.conf_end_test[i] = readb(pmem++);
+      for (i=0;i<2;i++)
+	adgl.error_code[i] = readb(pmem++);
+      for (i=0;i<4;i++)
+	adgl.parameter_error[i] = readb(pmem++);
+      pmem = apbs[IndexCard].RamIO + VERS;
+      adgl.vers = readb(pmem);
+      pmem = apbs[IndexCard].RamIO + TYPE_CARD;
+      for (i=0;i<20;i++)
+        adgl.reserv1[i] = readb(pmem++);
+      *(int *)&adgl.reserv1[20] =  
+	(readb(apbs[IndexCard].RamIO + SERIAL_NUMBER) << 16) + 
+	(readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 1) << 8) + 
+	(readb(apbs[IndexCard].RamIO + SERIAL_NUMBER + 2) );
+
+      if (copy_to_user ((void *)arg, &adgl, sizeof(struct st_ram_io)))
+	      return -EFAULT;
+      break;
+    case 2 :
+      pmem = apbs[IndexCard].RamIO + CONF_END_TEST;
+      for (i=0;i<10;i++)
+	writeb(0xff, pmem++);
+      writeb(adgl.data_from_pc_ready, 
+	     apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
+
+      writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
+#if LINUX_VERSION_CODE > 0x20300
+      init_waitqueue_head (&FlagSleepRec);
+#else
+      FlagSleepRec     = NULL;
+#endif
+      for (i=0;i<MAX_BOARD;i++)
+      {
+	if (apbs[i].RamIO)
+	  {
+#if LINUX_VERSION_CODE > 0x20300
+	    init_waitqueue_head (&apbs[i].FlagSleepSend);
+#else
+	    apbs[i].FlagSleepSend = NULL;
+#endif
+	    byte_reset_it = readb(apbs[i].RamIO + RAM_IT_TO_PC);
+	  }
+      }
+      break ;
+    case 3 :
+      pmem = apbs[IndexCard].RamIO + TIC_DES_FROM_PC;
+      writeb(adgl.tic_des_from_pc, pmem);
+      break;
+    case 4 :
+      pmem = apbs[IndexCard].RamIO + TIC_OWNER_TO_PC;
+      adgl.tic_owner_to_pc     = readb(pmem++);
+      adgl.numcard_owner_to_pc = readb(pmem);
+      if (copy_to_user ((void *)arg, &adgl,sizeof(struct st_ram_io)))
+	      return -EFAULT;
+      break;
+    case 5 :
+      writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_OWNER_TO_PC);
+      writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_DES_FROM_PC);
+      writeb(adgl.num_card, apbs[IndexCard].RamIO + NUMCARD_ACK_FROM_PC);
+      writeb(4, apbs[IndexCard].RamIO + DATA_FROM_PC_READY);
+      writeb(1, apbs[IndexCard].RamIO + RAM_IT_FROM_PC);
+      break ;
+    case 6  :
+      printk("APPLICOM driver release .... V2.8.0\n");
+      printk("Number of installed boards . %d\n",(int)numboards);
+      printk("Segment of board ........... %X\n",(int)mem);
+      printk("Interrupt IRQ number ....... %d\n",(int)irq);
+      for(i=0;i<MAX_BOARD;i++)
+      {
+	int serial;
+	char boardname[(SERIAL_NUMBER - TYPE_CARD) + 1];
+
+	if (!apbs[i].RamIO)
+	  continue;
+
+	
+	for(serial = 0; serial < SERIAL_NUMBER - TYPE_CARD; serial++)
+	  boardname[serial] = readb(apbs[i].RamIO + TYPE_CARD + serial);
+	boardname[serial]=0;
+	
+	
+        printk("Prom version board %d ....... V%d.%d %s",
+               i+1,
+               (int)(readb(apbs[IndexCard].RamIO + VERS) >> 4),
+               (int)(readb(apbs[IndexCard].RamIO + VERS) & 0xF),
+               boardname);
+
+
+	serial = (readb(apbs[i].RamIO + SERIAL_NUMBER) << 16) + 
+	  (readb(apbs[i].RamIO + SERIAL_NUMBER + 1) << 8) + 
+	  (readb(apbs[i].RamIO + SERIAL_NUMBER + 2) );
+
+        if (serial != 0)
+          printk (" S/N %d\n", serial);
+        else
+          printk("\n");
+      }
+      if(DeviceErrorCount != 0)
+        printk("DeviceErrorCount ........... %d\n",DeviceErrorCount);
+      if(ReadErrorCount != 0)
+        printk("ReadErrorCount ............. %d\n",ReadErrorCount);
+      if(WriteErrorCount != 0)
+        printk("WriteErrorCount ............ %d\n",WriteErrorCount);
+      if(waitqueue_active(&FlagSleepRec))
+        printk("Process in read pending\n");
+      for(i=0;i<MAX_BOARD;i++)
+      {
+	if (apbs[i].RamIO && waitqueue_active(&apbs[i].FlagSleepSend))
+          printk("Process in write pending board %d\n",i+1);
+      }
+      break;
+    default :
+      printk("APPLICOM driver ioctl, unknown function code %d\n",cmd) ;
+      return -EINVAL;
+      break;
+  }
+  Dummy = readb(apbs[IndexCard].RamIO + VERS);
+  return 0;
+}
+
+#ifndef MODULE
+static int __init applicom_setup(char *str)
+{
+	int ints[4];
+	
+	(void)get_options(str, 4, ints);
+
+	if (ints[0] > 2) {
+		printk(KERN_WARNING "Too many arguments to 'applicom=', expected mem,irq only.\n");
+	}
+		
+	if (ints[0] < 2) {
+		printk("applicom numargs: %d\n", ints[0]);
+		return 0;
+	}
+	
+	mem=ints[1];
+	irq=ints[2];
+	return 1;
+}
+#if LINUX_VERSION_CODE > 0x20300
+__setup("applicom=", applicom_setup);
+#endif
+#endif /* MODULE */
+
diff -u --recursive --new-file v2.3.15/linux/drivers/char/applicom.h linux/drivers/char/applicom.h
--- v2.3.15/linux/drivers/char/applicom.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/applicom.h	Mon Aug 30 18:05:57 1999
@@ -0,0 +1,85 @@
+/* $Id: applicom.h,v 1.2 1999/08/28 15:09:49 dwmw2 Exp $ */
+
+
+#ifndef __LINUX_APPLICOM_H__
+#define __LINUX_APPLICOM_H__
+
+
+#define DATA_TO_PC_READY      0x00
+#define TIC_OWNER_TO_PC       0x01
+#define NUMCARD_OWNER_TO_PC   0x02
+#define TIC_DES_TO_PC         0x03
+#define NUMCARD_DES_TO_PC     0x04
+#define DATA_FROM_PC_READY    0x05
+#define TIC_OWNER_FROM_PC     0x06
+#define NUMCARD_OWNER_FROM_PC 0x07
+#define TIC_DES_FROM_PC       0x08
+#define NUMCARD_DES_FROM_PC   0x09
+#define ACK_FROM_PC_READY     0x0E
+#define TIC_ACK_FROM_PC       0x0F
+#define NUMCARD_ACK_FROM_PC   0x010
+#define TYP_ACK_FROM_PC       0x011
+#define CONF_END_TEST         0x012
+#define ERROR_CODE            0x016 
+#define PARAMETER_ERROR       0x018 
+#define VERS                  0x01E 
+#define RAM_TO_PC             0x040
+#define RAM_FROM_PC           0x0170
+#define TYPE_CARD             0x03C0
+#define SERIAL_NUMBER         0x03DA
+#define RAM_IT_FROM_PC        0x03FE
+#define RAM_IT_TO_PC          0x03FF
+
+struct mailbox{
+	u16  stjb_codef;		/* offset 00 */
+	s16  stjb_status;     		/* offset 02 */
+	u16  stjb_ticuser_root;		/* offset 04 */
+	u8   stjb_piduser[4];		/* offset 06 */
+	u16  stjb_mode;			/* offset 0A */
+	u16  stjb_time;			/* offset 0C */
+	u16  stjb_stop;			/* offset 0E */
+	u16  stjb_nfonc;		/* offset 10 */
+	u16  stjb_ncard;		/* offset 12 */
+	u16  stjb_nchan;		/* offset 14 */
+	u16  stjb_nes;			/* offset 16 */
+	u16  stjb_nb;			/* offset 18 */
+	u16  stjb_typvar;		/* offset 1A */
+	u32  stjb_adr;			/* offset 1C */
+	u16  stjb_ticuser_dispcyc;	/* offset 20 */
+	u16  stjb_ticuser_protocol;	/* offset 22 */
+	u8   stjb_filler[12];		/* offset 24 */
+	u8   stjb_data[256];		/* offset 30 */
+	};
+
+struct st_ram_io 
+{
+	unsigned char data_to_pc_ready;
+	unsigned char tic_owner_to_pc;
+	unsigned char numcard_owner_to_pc;
+	unsigned char tic_des_to_pc;
+	unsigned char numcard_des_to_pc;
+	unsigned char data_from_pc_ready;
+	unsigned char tic_owner_from_pc;
+	unsigned char numcard_owner_from_pc;
+	unsigned char tic_des_from_pc;
+	unsigned char numcard_des_from_pc;
+	unsigned char ack_to_pc_ready;
+	unsigned char tic_ack_to_pc;
+	unsigned char numcard_ack_to_pc;
+	unsigned char typ_ack_to_pc;
+	unsigned char ack_from_pc_ready;
+	unsigned char tic_ack_from_pc;
+	unsigned char numcard_ack_from_pc;
+	unsigned char typ_ack_from_pc;
+	unsigned char conf_end_test[4];
+	unsigned char error_code[2];
+	unsigned char parameter_error[4];
+	unsigned char time_base;
+	unsigned char nul_inc;
+	unsigned char vers;
+	unsigned char num_card;
+	unsigned char reserv1[32];
+};
+
+
+#endif /* __LINUX_APPLICOM_H__ */
diff -u --recursive --new-file v2.3.15/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.3.15/linux/drivers/char/bttv.c	Thu Aug 26 13:05:34 1999
+++ linux/drivers/char/bttv.c	Tue Aug 31 11:25:33 1999
@@ -1288,7 +1288,7 @@
 }
 
 
-static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt)
+static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt, int pllset)
 {
         u16 vscale, hscale;
 	u32 xsf, sr;
@@ -1297,9 +1297,13 @@
 	u16 inter;
 	u8 crop, vtc;  
 	struct tvnorm *tvn;
+	unsigned long flags;
  	
 	if (!width || !height)
 	        return;
+	        
+	save_flags(flags);
+	cli();
 
 	tvn=&tvnorms[btv->win.norm];
 	
@@ -1324,7 +1328,8 @@
 	btwrite(1, BT848_VBI_PACK_DEL);
 
         btv->pll.pll_ofreq = tvn->Fsc;
-        set_pll(btv);
+        if(pllset)
+        	set_pll(btv);
 
 	btwrite(fmt, BT848_COLOR_FMT);
 #ifdef __sparc__
@@ -1372,6 +1377,8 @@
 			hdelay, vdelay, crop);
 	bt848_set_eogeo(btv, 1, vtc, hscale, vscale, hactive, vactive,
 			hdelay, vdelay, crop);
+			
+	restore_flags(flags);
 }
 
 
@@ -1400,7 +1407,7 @@
 	else
 	        btor(BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL);
 
-        bt848_set_geo(btv, btv->win.width, btv->win.height, format);
+        bt848_set_geo(btv, btv->win.width, btv->win.height, format, 1);
 }
 
 /*
@@ -1976,7 +1983,8 @@
 		{
 			struct video_buffer v;
 #if LINUX_VERSION_CODE >= 0x020100
-			if(!capable(CAP_SYS_ADMIN))
+			if(!capable(CAP_SYS_ADMIN)
+			&& !capable(CAP_SYS_RAWIO))
 #else
 			if(!suser())
 #endif
@@ -2161,7 +2169,8 @@
 
 		case BTTV_WRITEE:
 #if LINUX_VERSION_CODE >= 0x020100
-			if(!capable(CAP_SYS_ADMIN))
+			if(!capable(CAP_SYS_ADMIN)
+			|| !capable(CAP_SYS_RAWIO))
 #else
 			if(!suser())
 #endif
@@ -3432,14 +3441,14 @@
 					btv->risc_jmp[11]=cpu_to_le32(btv->gre);
 					bt848_set_geo(btv, btv->gwidth,
 						      btv->gheight,
-						      btv->gfmt);
+						      btv->gfmt, 0);
 				} else {
 					bt848_set_risc_jmps(btv);
 					btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI);
 					btand(~BT848_VSCALE_COMB, BT848_O_VSCALE_HI);
                                         bt848_set_geo(btv, btv->win.width, 
 						      btv->win.height,
-						      btv->win.color_fmt);
+						      btv->win.color_fmt, 0);
 				}
 				wake_up_interruptible(&btv->capq);
 				break;
@@ -3450,7 +3459,7 @@
 				btv->risc_jmp[11]=cpu_to_le32(btv->gre);
 				btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP);
 				bt848_set_geo(btv, btv->gwidth, btv->gheight,
-					      btv->gfmt);
+					      btv->gfmt, 0);
 			}
 		}
 		if (astat&BT848_INT_OCERR) 
@@ -3586,11 +3595,7 @@
                 }
         }
         
-#ifdef __sparc__
-        btv->bt848_mem=(unsigned char *)btv->bt848_adr;
-#else
-        btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
-#endif
+        btv->bt848_mem = ioremap(btv->bt848_adr, 0x1000);
         
         /* clear interrupt mask */
 	btwrite(0, BT848_INT_MASK);
diff -u --recursive --new-file v2.3.15/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- v2.3.15/linux/drivers/char/busmouse.c	Sun Aug 15 11:48:40 1999
+++ linux/drivers/char/busmouse.c	Tue Aug 31 11:30:47 1999
@@ -49,7 +49,7 @@
 /*#define BROKEN_MOUSE*/
 
 extern int adb_mouse_init(void);
-extern int bus_mouse_init(void);
+extern int logi_busmouse_init(void);
 extern int ms_bus_mouse_init(void);
 extern int atixl_busmouse_init(void);
 extern int amiga_mouse_init(void);
@@ -273,7 +273,7 @@
 
 		add_wait_queue(&mse->wait, &wait);
 repeat:
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (!mse->ready && !signal_pending(current)) {
 			spin_unlock_irqrestore(&mse->lock, flags);
 			schedule();
@@ -432,11 +432,11 @@
 	return 0;
 }
 
-__initfunc(int
-bus_mouse_init(void))
+int __init
+bus_mouse_init(void)
 {
-#ifdef CONFIG_BUSMOUSE
-	bus_mouse_init();
+#ifdef CONFIG_LOGIBUSMOUSE
+	logi_busmouse_init();
 #endif
 #ifdef CONFIG_MS_BUSMOUSE
 	ms_bus_mouse_init();
diff -u --recursive --new-file v2.3.15/linux/drivers/char/buz.c linux/drivers/char/buz.c
--- v2.3.15/linux/drivers/char/buz.c	Thu Aug  5 15:04:52 1999
+++ linux/drivers/char/buz.c	Thu Aug 26 12:48:49 1999
@@ -2650,7 +2650,8 @@
 		{
 			struct video_buffer v;
 
-			if (!capable(CAP_SYS_ADMIN))
+			if (!capable(CAP_SYS_ADMIN)
+			|| !capable(CAP_SYS_RAWIO))
 				return -EPERM;
 
 			if (copy_from_user(&v, arg, sizeof(v)))
diff -u --recursive --new-file v2.3.15/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.3.15/linux/drivers/char/cyclades.c	Mon Aug  9 10:23:09 1999
+++ linux/drivers/char/cyclades.c	Tue Aug 31 11:30:48 1999
@@ -179,7 +179,7 @@
  * Change queue_task_irq_off to queue_task_irq.
  * The inline function queue_task_irq_off (tqueue.h)
  * was removed from latest releases of 2.1.x kernel.
- * Use of macro __initfunc to mark the initialization
+ * Use of macro __init to mark the initialization
  * routines, so memory can be reused.
  * Also incorporate implementation of critical region
  * in function cleanup_module() created by anonymous
@@ -2554,7 +2554,7 @@
 		}
 	    CY_UNLOCK(info, flags);
 
-	    current->state = TASK_INTERRUPTIBLE;
+	    set_current_state(TASK_INTERRUPTIBLE);
 	    if (tty_hung_up_p(filp)
 	    || !(info->flags & ASYNC_INITIALIZED) ){
 		return ((info->flags & ASYNC_HUP_NOTIFY) ? 
@@ -2615,7 +2615,7 @@
 		    printk("cyc:block_til_ready raising Z DTR\n");
 #endif
 
-	    current->state = TASK_INTERRUPTIBLE;
+	    set_current_state(TASK_INTERRUPTIBLE);
 	    if (tty_hung_up_p(filp)
 	    || !(info->flags & ASYNC_INITIALIZED) ){
 		return ((info->flags & ASYNC_HUP_NOTIFY) ?
@@ -2851,7 +2851,6 @@
 	    printk("Not clean (jiff=%lu)...", jiffies);
 #endif
 	    current->state = TASK_INTERRUPTIBLE;
-	    current->counter = 0;	/* make us low-priority */
 	    schedule_timeout(char_time);
 	    if (signal_pending(current))
 		break;
@@ -2864,7 +2863,6 @@
     }
     /* Run one more char cycle */
     current->state = TASK_INTERRUPTIBLE;
-    current->counter = 0;	/* make us low-priority */
     schedule_timeout(char_time * 5);
     current->state = TASK_RUNNING;
 #ifdef CY_DEBUG_WAIT_UNTIL_SENT
@@ -3752,7 +3750,7 @@
 	}
 
     }
-    return cy_put_user(result,(unsigned long *) value);
+    return cy_put_user(result,(unsigned int *) value);
 } /* get_modem_info */
 
 
@@ -4627,8 +4625,8 @@
 
 /* initialize chips on Cyclom-Y card -- return number of valid
    chips (which is number of ports/4) */
-__initfunc(static unsigned short
-cyy_init_card(volatile ucchar *true_base_addr,int index))
+static unsigned short __init
+cyy_init_card(volatile ucchar *true_base_addr,int index)
 {
   unsigned int chip_number;
   volatile ucchar* base_addr;
@@ -4713,8 +4711,8 @@
  * sets global variables and return the number of ISA boards found.
  * ---------------------------------------------------------------------
  */
-__initfunc(static int
-cy_detect_isa(void))
+static int __init
+cy_detect_isa(void)
 {
   unsigned short	cy_isa_irq,nboard;
   volatile ucchar	*cy_isa_address;
@@ -4841,8 +4839,8 @@
  * sets global variables and return the number of PCI boards found.
  * ---------------------------------------------------------------------
  */
-__initfunc(static int
-cy_detect_pci(void))
+static int __init
+cy_detect_pci(void)
 {
 #ifdef CONFIG_PCI
 
@@ -5357,8 +5355,8 @@
     extra ports are ignored.
  */
 
-__initfunc(int
-cy_init(void))
+int __init
+cy_init(void)
 {
   struct cyclades_port  *info;
   struct cyclades_card *cinfo;
diff -u --recursive --new-file v2.3.15/linux/drivers/char/dz.c linux/drivers/char/dz.c
--- v2.3.15/linux/drivers/char/dz.c	Mon Jul  5 20:35:18 1999
+++ linux/drivers/char/dz.c	Tue Aug 31 11:30:48 1999
@@ -902,7 +902,7 @@
   
   dz_out (info, DZ_TCR, tmp);
   
-  schedule_timeout(jiffies + duration);
+  schedule_timeout(duration);
   
   tmp &= ~mask;
   dz_out (info, DZ_TCR, tmp);
@@ -1093,7 +1093,7 @@
   if (info->blocked_open) {
     if (info->close_delay) {
       current->state = TASK_INTERRUPTIBLE;
-      schedule_timeout(jiffies + info->close_delay);
+      schedule_timeout(info->close_delay);
     }
     wake_up_interruptible (&info->open_wait);
   }
@@ -1194,7 +1194,7 @@
   info->count--;
   info->blocked_open++;
   while (1) {
-    current->state = TASK_INTERRUPTIBLE;
+    set_current_state(TASK_INTERRUPTIBLE);
     if (tty_hung_up_p (filp) || !(info->is_initialized)) {
       retval = -EAGAIN;
       break;
@@ -1281,7 +1281,7 @@
 }
 
 
-__initfunc(int dz_init(void))
+int __init dz_init(void)
 {
   int i, flags;
   struct dz_serial *info;
@@ -1454,7 +1454,7 @@
 	return MKDEV(TTY_MAJOR, 64 + c->index);
 }
 
-__initfunc(static int dz_console_setup(struct console *co, char *options))
+static int __init dz_console_setup(struct console *co, char *options)
 {
   	int	baud = 9600;
 	int	bits = 8;
@@ -1590,7 +1590,7 @@
 	NULL
 };
 
-__initfunc (long dz_serial_console_init(long kmem_start, long kmem_end))
+long __init dz_serial_console_init(long kmem_start, long kmem_end)
 {
 	register_console(&dz_sercons);
 
diff -u --recursive --new-file v2.3.15/linux/drivers/char/epca.c linux/drivers/char/epca.c
--- v2.3.15/linux/drivers/char/epca.c	Thu Aug  5 15:04:52 1999
+++ linux/drivers/char/epca.c	Tue Aug 31 11:30:48 1999
@@ -1367,7 +1367,7 @@
 	while(1) 
 	{ /* Begin forever while  */
 
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 
 		if (tty_hung_up_p(filp) ||
 		    !(ch->asyncflags & ASYNC_INITIALIZED)) 
@@ -3233,7 +3233,7 @@
 			if (error)
 				return error;
 
-			putUser(mflag, (unsigned long *) arg);
+			putUser(mflag, (unsigned int *) arg);
 
 			break;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/char/esp.c linux/drivers/char/esp.c
--- v2.3.15/linux/drivers/char/esp.c	Tue Jul  6 19:16:55 1999
+++ linux/drivers/char/esp.c	Tue Aug 31 11:30:48 1999
@@ -2317,7 +2317,7 @@
 				scratch | UART_MCR_DTR | UART_MCR_RTS);
 		}
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ASYNC_INITIALIZED)) {
 #ifdef SERIAL_DO_RESTART
diff -u --recursive --new-file v2.3.15/linux/drivers/char/ftape/lowlevel/ftape-io.c linux/drivers/char/ftape/lowlevel/ftape-io.c
--- v2.3.15/linux/drivers/char/ftape/lowlevel/ftape-io.c	Wed Nov  4 09:57:43 1998
+++ linux/drivers/char/ftape/lowlevel/ftape-io.c	Tue Aug 31 11:30:48 1999
@@ -95,19 +95,19 @@
 
 		TRACE(ft_t_any, "%d msec, %d ticks", time/1000, ticks);
 		timeout = ticks;
-		current->state = TASK_INTERRUPTIBLE;
 		save_flags(flags);
 		sti();
+		set_current_state(TASK_INTERRUPTIBLE);
 		do {
-			while (current->state != TASK_RUNNING) {
-				timeout = schedule_timeout(timeout);
-			}
 			/*  Mmm. Isn't current->blocked == 0xffffffff ?
 			 */
 			if (signal_pending(current)) {
 				TRACE(ft_t_err,
 				      "awoken by non-blocked signal :-(");
 				break;	/* exit on signal */
+			}
+			while (current->state != TASK_RUNNING) {
+				timeout = schedule_timeout(timeout);
 			}
 		} while (timeout);
 		restore_flags(flags);
diff -u --recursive --new-file v2.3.15/linux/drivers/char/generic_serial.c linux/drivers/char/generic_serial.c
--- v2.3.15/linux/drivers/char/generic_serial.c	Thu Aug  5 14:47:44 1999
+++ linux/drivers/char/generic_serial.c	Tue Aug 31 11:30:48 1999
@@ -94,7 +94,7 @@
 #ifndef TWO_THREE
 /* These are new in 2.3. The source now uses 2.3 syntax, and here is 
    the compatibility define... */
-#define waitq_head_t struct wait_queue *
+#define wait_queue_head_t struct wait_queue *
 #define DECLARE_MUTEX(name) struct semaphore name = MUTEX
 #define DECLARE_WAITQUEUE(wait, current) struct wait_queue wait = { current, NULL }
 
@@ -698,7 +698,7 @@
 	while (1) {
 		CD = port->rd->get_CD (port);
 		gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(port->flags & ASYNC_INITIALIZED)) {
 			if (port->flags & ASYNC_HUP_NOTIFY)
diff -u --recursive --new-file v2.3.15/linux/drivers/char/ip2/i2lib.c linux/drivers/char/ip2/i2lib.c
--- v2.3.15/linux/drivers/char/ip2/i2lib.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/char/ip2/i2lib.c	Tue Aug 31 11:30:48 1999
@@ -640,7 +640,6 @@
 		
 		if (!in_interrupt()) {
 			current->state = TASK_INTERRUPTIBLE;
-			current->counter = 0;
 			schedule_timeout(1);	// short nap 
 		} else {
 			// we cannot sched/sleep in interrrupt silly
@@ -1135,7 +1134,6 @@
 	ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );
 #endif
 					current->state = TASK_INTERRUPTIBLE;
-					current->counter = 0;
 					schedule_timeout(2);
 					if (signal_pending(current)) {
 						break;
diff -u --recursive --new-file v2.3.15/linux/drivers/char/ip2.c linux/drivers/char/ip2.c
--- v2.3.15/linux/drivers/char/ip2.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/char/ip2.c	Mon Aug 30 10:18:40 1999
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/init.h>
+#include <linux/wait.h>
 
 #include "./ip2/ip2types.h"		
 #include "./ip2/fip_firm.h"		// the meat
diff -u --recursive --new-file v2.3.15/linux/drivers/char/ip2main.c linux/drivers/char/ip2main.c
--- v2.3.15/linux/drivers/char/ip2main.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/char/ip2main.c	Tue Aug 31 11:30:48 1999
@@ -304,8 +304,8 @@
 
 // Some functions to keep track of what irq's we have
 
-__initfunc(static int 
-is_valid_irq(int irq) )
+static int __init
+is_valid_irq(int irq)
 {
 	int *i = Valid_Irqs;
 	
@@ -315,14 +315,14 @@
 	return (*i);
 }
 
-__initfunc( static void
-mark_requested_irq( char irq ))
+static void __init
+mark_requested_irq( char irq )
 {
 	rirqs[iindx++] = irq;
 }
 
-__initfunc( static int
-clear_requested_irq( char irq ))
+static int __init
+clear_requested_irq( char irq )
 {
 	int i;
 	for ( i = 0; i < IP2_MAX_BOARDS; ++i ) {
@@ -334,8 +334,8 @@
 	return 0;
 }
 
-__initfunc( static int
-have_requested_irq( char irq )) 
+static int __init
+have_requested_irq( char irq )
 {
 	// array init to zeros so 0 irq will not be requested as a side effect
 	int i;
@@ -470,8 +470,8 @@
 /* SA_RANDOM   - can be source for cert. random number generators */
 #define IP2_SA_FLAGS	0
 
-__initfunc( int
-old_ip2_init(void))
+int __init
+old_ip2_init(void)
 {
 	int i;
 	int err;
@@ -738,8 +738,8 @@
 /* the board, the channel structures are initialized, and the board details   */
 /* are reported on the console.                                               */
 /******************************************************************************/
-__initfunc( static void
-ip2_init_board( int boardnum ))
+static void __init
+ip2_init_board( int boardnum )
 {
 	int i,rc;
 	int nports = 0, nboxes = 0;
@@ -864,8 +864,8 @@
 /* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */
 /* it returns the base address of the controller.                             */
 /******************************************************************************/
-__initfunc( static unsigned short
-find_eisa_board( int start_slot ))
+static unsigned short __init
+find_eisa_board( int start_slot )
 {
 	int i, j;
 	unsigned int idm = 0;
@@ -1573,7 +1573,6 @@
 	if (pCh->wopen) {
 		if (pCh->ClosingDelay) {
 			current->state = TASK_INTERRUPTIBLE;
-			current->counter = 0;
 			schedule_timeout(pCh->ClosingDelay);
 		}
 		wake_up_interruptible(&pCh->open_wait);
diff -u --recursive --new-file v2.3.15/linux/drivers/char/isicom.c linux/drivers/char/isicom.c
--- v2.3.15/linux/drivers/char/isicom.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/char/isicom.c	Tue Aug 31 11:30:48 1999
@@ -995,7 +995,7 @@
 			raise_dtr_rts(port);
 		
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { 	
 			if (port->flags & ASYNC_HUP_NOTIFY)
 				retval = -EAGAIN;
@@ -1405,7 +1405,7 @@
 		((status & ISI_DSR) ? TIOCM_DSR : 0) |
 		((status & ISI_CTS) ? TIOCM_CTS : 0) |
 		((status & ISI_RI ) ? TIOCM_RI  : 0);
-	put_user(info, (unsigned long *) value);
+	put_user(info, (unsigned int *) value);
 	return 0;	
 }
 
diff -u --recursive --new-file v2.3.15/linux/drivers/char/joystick/joystick.c linux/drivers/char/joystick/joystick.c
--- v2.3.15/linux/drivers/char/joystick/joystick.c	Wed May 12 13:27:37 1999
+++ linux/drivers/char/joystick/joystick.c	Tue Aug 31 11:30:48 1999
@@ -525,8 +525,8 @@
 
 		if (GOF(curl->tail) == jd->bhead && curl->startup == jd->num_axes + jd->num_buttons) {
 
+			__set_current_state(TASK_INTERRUPTIBLE);
 			add_wait_queue(&jd->wait, &wait);
-			current->state = TASK_INTERRUPTIBLE;
 
 			while (GOF(curl->tail) == jd->bhead) {
 
diff -u --recursive --new-file v2.3.15/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v2.3.15/linux/drivers/char/keyboard.c	Thu Aug  5 14:43:32 1999
+++ linux/drivers/char/keyboard.c	Thu Aug 26 13:50:37 1999
@@ -901,7 +901,7 @@
 	}
 }
 
-__initfunc(int kbd_init(void))
+int __init kbd_init(void)
 {
 	int i;
 	struct kbd_struct kbd0;
diff -u --recursive --new-file v2.3.15/linux/drivers/char/logibusmouse.c linux/drivers/char/logibusmouse.c
--- v2.3.15/linux/drivers/char/logibusmouse.c	Mon Aug  2 09:54:29 1999
+++ linux/drivers/char/logibusmouse.c	Mon Aug 30 10:21:03 1999
@@ -118,7 +118,7 @@
 	LOGITECH_BUSMOUSE, "busmouse", open_mouse, close_mouse, 7
 };
 
-int __init bus_mouse_init(void)
+int __init logi_busmouse_init(void)
 {
 	if (check_region(LOGIBM_BASE, LOGIBM_EXTENT))
 		return -EIO;
@@ -146,7 +146,7 @@
 
 int init_module(void)
 {
-	return bus_mouse_init();
+	return logi_busmouse_init();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.15/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.3.15/linux/drivers/char/misc.c	Mon Aug  9 12:14:28 1999
+++ linux/drivers/char/misc.c	Mon Aug 30 10:21:03 1999
@@ -187,7 +187,7 @@
 	proc_misc = create_proc_entry("misc", 0, 0);
 	if (proc_misc)
 		proc_misc->read_proc = misc_read_proc;
-#ifdef CONFIG_MOUSE
+#ifdef CONFIG_BUSMOUSE
 	bus_mouse_init();
 #endif
 #if defined CONFIG_82C710_MOUSE
diff -u --recursive --new-file v2.3.15/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c
--- v2.3.15/linux/drivers/char/msbusmouse.c	Tue Aug  3 10:04:42 1999
+++ linux/drivers/char/msbusmouse.c	Thu Aug 26 13:50:57 1999
@@ -60,7 +60,7 @@
 MODULE_PARM(mouse_irq, "i");
 #endif
 
-__initfunc(void msmouse_setup(char *str, int *ints))
+void __init msmouse_setup(char *str, int *ints)
 {
 	if (ints[0] > 0)
 		mouse_irq=ints[1];
@@ -117,7 +117,7 @@
 	MICROSOFT_BUSMOUSE, "msbusmouse", open_mouse, release_mouse, 0
 };
 
-__initfunc(int ms_bus_mouse_init(void))
+int __init ms_bus_mouse_init(void)
 {
 	int present = 0;
 	int mse_byte, i;
diff -u --recursive --new-file v2.3.15/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c
--- v2.3.15/linux/drivers/char/msp3400.c	Wed May 12 08:41:07 1999
+++ linux/drivers/char/msp3400.c	Tue Aug 31 11:30:48 1999
@@ -795,9 +795,8 @@
 		UNLOCK_I2C_BUS(msp->bus);
 
 		/* wait 1 sec */
-		current->state = TASK_INTERRUPTIBLE;
-		current->timeout = jiffies + HZ;
-		schedule();
+		__set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ);
 		if (signal_pending(current))
 			goto done;
 		if (msp->restart) {
@@ -992,16 +991,16 @@
 }
 
 static /*const*/ struct file_operations msp3400c_mixer_fops = {
-        &msp3400c_mixer_llseek,
+        msp3400c_mixer_llseek,
         NULL,  /* read */
         NULL,  /* write */
         NULL,  /* readdir */
         NULL,  /* poll */
-        &msp3400c_mixer_ioctl,
+        msp3400c_mixer_ioctl,
         NULL,  /* mmap */
-        &msp3400c_mixer_open,
+        msp3400c_mixer_open,
 	NULL,
-        &msp3400c_mixer_release,
+        msp3400c_mixer_release,
         NULL,  /* fsync */
         NULL,  /* fasync */
         NULL,  /* check_media_change */
diff -u --recursive --new-file v2.3.15/linux/drivers/char/n_r3964.c linux/drivers/char/n_r3964.c
--- v2.3.15/linux/drivers/char/n_r3964.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/n_r3964.c	Mon Aug 30 18:05:19 1999
@@ -0,0 +1,1489 @@
+/* r3964 linediscipline for linux
+ *
+ * -----------------------------------------------------------
+ * Copyright by 
+ * Philips Automation Projects
+ * Kassel (Germany)
+ * http://www.pap-philips.de
+ * -----------------------------------------------------------
+ * This software may be used and distributed according to the terms of
+ * the GNU Public License, incorporated herein by reference.
+ *
+ * Author:
+ * L. Haag
+ *
+ * $Log: r3964.c,v $
+ * Revision 1.7  1999/28/08 11:41:50  dwmw2
+ * Port to 2.3 kernel
+ *
+ * Revision 1.6  1998/09/30 00:40:40  dwmw2
+ * Fixed compilation on 2.0.x kernels
+ * Updated to newly registered tty-ldisc number 9
+ *
+ * Revision 1.5  1998/09/04 21:57:36  dwmw2
+ * Signal handling bug fixes, port to 2.1.x.
+ *
+ * Revision 1.4  1998/04/02 20:26:59  lhaag
+ * select, blocking, ...
+ *
+ * Revision 1.3  1998/02/12 18:58:43  root
+ * fixed some memory leaks
+ * calculation of checksum characters
+ *
+ * Revision 1.2  1998/02/07 13:03:34  root
+ * ioctl read_telegram
+ *
+ * Revision 1.1  1998/02/06 19:21:03  root
+ * Initial revision
+ *
+ *
+ */
+#define R3964_VERSION "1.7"
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/sched.h>    /* to get the struct task_struct */
+#include <linux/string.h>   /* used in new tty drivers */
+#include <linux/signal.h>   /* used in new tty drivers */
+#include <linux/ioctl.h>
+#include <linux/n_r3964.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+
+
+//#define DEBUG_QUEUE
+
+/* Log successfull handshake and protocol operations  */
+//#define DEBUG_PROTO_S
+
+/* Log handshake and protocol errors: */
+//#define DEBUG_PROTO_E
+
+/* Log Linediscipline operations (open, close, read, write...): */
+//#define DEBUG_LDISC
+
+/* Log module and memory operations (init, cleanup; kmalloc, kfree): */
+//#define DEBUG_MODUL
+
+/* Macro helpers for debug output: */
+#define TRACE(format, args...) printk("r3964: " format "\n" , ## args);
+
+#ifdef DEBUG_MODUL
+#define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args);
+#else
+#define TRACE_M(fmt, arg...) /**/
+#endif
+
+#ifdef DEBUG_PROTO_S
+#define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args);
+#else
+#define TRACE_PS(fmt, arg...) /**/
+#endif
+
+#ifdef DEBUG_PROTO_E
+#define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args);
+#else
+#define TRACE_PE(fmt, arg...) /**/
+#endif
+
+#ifdef DEBUG_LDISC
+#define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args);
+#else
+#define TRACE_L(fmt, arg...) /**/
+#endif
+
+#ifdef DEBUG_QUEUE
+#define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args);
+#else
+#define TRACE_Q(fmt, arg...) /**/
+#endif
+
+void cleanup_module(void);
+
+static void on_timer_1(void*);
+static void on_timer_2(void*);
+static void add_tx_queue(struct r3964_info *, struct r3964_block_header *);
+static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code);
+static void put_char(struct r3964_info *pInfo, unsigned char ch);
+static void trigger_transmit(struct r3964_info *pInfo);
+static void retry_transmit(struct r3964_info *pInfo);
+static void transmit_block(struct r3964_info *pInfo);
+static void receive_char(struct r3964_info *pInfo, const unsigned char c);
+static void receive_error(struct r3964_info *pInfo, const char flag);
+static void on_timeout(struct r3964_info *pInfo);
+static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg);
+static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char *buf);
+static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
+             int error_code, struct r3964_block_header *pBlock);
+static struct r3964_message* remove_msg(struct r3964_info *pInfo, 
+             struct r3964_client_info *pClient);
+static void remove_client_block(struct r3964_info *pInfo, 
+                struct r3964_client_info *pClient);
+
+static int  r3964_open(struct tty_struct *tty);
+static void r3964_close(struct tty_struct *tty);
+static int  r3964_read(struct tty_struct *tty, struct file *file,
+                     unsigned char *buf, unsigned int nr);
+static int  r3964_write(struct tty_struct * tty, struct file * file,
+                      const unsigned char * buf, unsigned int nr);
+static int r3964_ioctl(struct tty_struct * tty, struct file * file,
+                       unsigned int cmd, unsigned long arg);
+static void r3964_set_termios(struct tty_struct *tty, struct termios * old);
+static unsigned int r3964_poll(struct tty_struct * tty, struct file * file,
+		      struct poll_table_struct  *wait);
+static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+                              char *fp, int count);
+static int  r3964_receive_room(struct tty_struct *tty);
+
+static struct tty_ldisc tty_ldisc_N_R3964 = {
+        TTY_LDISC_MAGIC,       /* magic */
+	"R3964",               /* name */
+        0,                     /* num */
+        0,                     /* flags */
+        r3964_open,            /* open */
+        r3964_close,           /* close */
+        0,                     /* flush_buffer */
+        0,                     /* chars_in_buffer */
+        r3964_read,            /* read */
+        r3964_write,           /* write */
+        r3964_ioctl,           /* ioctl */
+        r3964_set_termios,     /* set_termios */
+        r3964_poll,            /* poll */            
+        r3964_receive_buf,     /* receive_buf */
+        r3964_receive_room,    /* receive_room */
+        0                      /* write_wakeup */
+};
+
+
+
+static void dump_block(const unsigned char *block, unsigned int length)
+{
+   unsigned int i,j;
+   char linebuf[16*3+1];
+   
+   for(i=0;i<length;i+=16)
+   {
+      for(j=0;(j<16) && (j+i<length);j++)
+      {
+         sprintf(linebuf+3*j,"%02x ",block[i+j]);
+      }
+      linebuf[3*j]='\0';
+      TRACE_PS("%s",linebuf);
+   }
+}
+
+         
+
+
+/*************************************************************
+ * Driver initialisation
+ *************************************************************/
+
+
+/*************************************************************
+ * Module support routines
+ *************************************************************/
+
+#ifdef MODULE
+
+#define r3964_init init_module
+
+void cleanup_module(void)
+{
+   int status;
+   
+   TRACE_M ("cleanup_module()");
+
+   status=tty_register_ldisc(N_R3964, NULL);
+   
+   if(status!=0)
+   {
+      printk(KERN_ERR "r3964: error unregistering linediscipline: %d\n", status);
+   }
+   else
+   {
+      TRACE_L("linediscipline successfully unregistered");
+   }
+   
+}
+
+
+#endif /* MODULE */
+
+__initfunc(static int r3964_init(void))
+{
+   int status;
+   
+   printk ("r3964: Philips r3964 Driver V%s\n", R3964_VERSION);
+
+   /*
+    * Register the tty line discipline
+    */
+   
+   status = tty_register_ldisc (N_R3964, &tty_ldisc_N_R3964);
+   if (status == 0)
+     {
+       TRACE_L("line discipline %d registered", N_R3964);
+       TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags, 
+               tty_ldisc_N_R3964.num);
+       TRACE_L("open=%x", (int)tty_ldisc_N_R3964.open);
+       TRACE_L("tty_ldisc_N_R3964 = %x", (int)&tty_ldisc_N_R3964);
+     }
+   else
+     {
+       printk (KERN_ERR "r3964: error registering line discipline: %d\n", status);
+     }
+   return status;
+}
+
+#ifndef MODULE
+__initcall (r3964_init);
+#endif
+
+/*************************************************************
+ * Protocol implementation routines
+ *************************************************************/
+
+static void on_timer_1(void *arg)
+{
+   struct r3964_info *pInfo = (struct r3964_info *)arg;
+  
+   if(pInfo->count_down)
+   {
+      if(!--pInfo->count_down)
+      {
+         on_timeout(pInfo);
+      }
+   }
+   queue_task(&pInfo->bh_2, &tq_timer);
+}
+
+static void on_timer_2(void *arg)
+{
+   struct r3964_info *pInfo = (struct r3964_info *)arg;
+  
+   if(pInfo->count_down)
+   {
+      if(!--pInfo->count_down)
+      {
+         on_timeout(pInfo);
+      }
+   }
+   queue_task(&pInfo->bh_1, &tq_timer);
+}
+
+static void add_tx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader)
+{
+   unsigned long flags;
+   
+   save_flags(flags);
+   cli();
+
+   pHeader->next = NULL;
+
+   if(pInfo->tx_last == NULL)
+   {
+      pInfo->tx_first = pInfo->tx_last = pHeader;
+   }
+   else
+   {
+      pInfo->tx_last->next = pHeader;
+      pInfo->tx_last = pHeader;
+   }
+   
+   restore_flags(flags);
+
+   TRACE_Q("add_tx_queue %x, length %d, tx_first = %x", 
+          (int)pHeader, pHeader->length, (int)pInfo->tx_first );
+}
+
+static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code)
+{
+   struct r3964_block_header *pHeader;
+   unsigned long flags;
+#ifdef DEBUG_QUEUE
+   struct r3964_block_header *pDump;
+#endif
+   
+   pHeader = pInfo->tx_first;
+
+   if(pHeader==NULL)
+      return;
+
+#ifdef DEBUG_QUEUE
+   printk("r3964: remove_from_tx_queue: %x, length %d - ",
+          (int)pHeader, (int)pHeader->length );
+   for(pDump=pHeader;pDump;pDump=pDump->next)
+	 printk("%x ", (int)pDump);
+   printk("\n");
+#endif
+
+
+   if(pHeader->owner)
+   {
+      if(error_code)
+      {
+          add_msg(pHeader->owner, R3964_MSG_ACK, 0, 
+                  error_code, NULL);
+      }
+      else
+      {
+          add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length, 
+                  error_code, NULL);
+      }
+      wake_up_interruptible (&pInfo->read_wait);
+   }
+
+   save_flags(flags);
+   cli();
+
+   pInfo->tx_first = pHeader->next;
+   if(pInfo->tx_first==NULL)
+   {
+      pInfo->tx_last = NULL;
+   }
+
+   restore_flags(flags);
+
+   kfree(pHeader);
+   TRACE_M("remove_from_tx_queue - kfree %x",(int)pHeader);
+
+   TRACE_Q("remove_from_tx_queue: tx_first = %x, tx_last = %x",
+          (int)pInfo->tx_first, (int)pInfo->tx_last );
+}
+
+static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader)
+{
+   unsigned long flags;
+   
+   save_flags(flags);
+   cli();
+
+   pHeader->next = NULL;
+
+   if(pInfo->rx_last == NULL)
+   {
+      pInfo->rx_first = pInfo->rx_last = pHeader;
+   }
+   else
+   {
+      pInfo->rx_last->next = pHeader;
+      pInfo->rx_last = pHeader;
+   }
+   pInfo->blocks_in_rx_queue++;
+   
+   restore_flags(flags);
+
+   TRACE_Q("add_rx_queue: %x, length = %d, rx_first = %x, count = %d",
+          (int)pHeader, pHeader->length,
+          (int)pInfo->rx_first, pInfo->blocks_in_rx_queue);
+}
+
+static void remove_from_rx_queue(struct r3964_info *pInfo,
+                 struct r3964_block_header *pHeader)
+{
+   unsigned long flags;
+   struct r3964_block_header *pFind;
+   
+   if(pHeader==NULL)
+      return;
+
+   TRACE_Q("remove_from_rx_queue: rx_first = %x, rx_last = %x, count = %d",
+          (int)pInfo->rx_first, (int)pInfo->rx_last, pInfo->blocks_in_rx_queue );
+   TRACE_Q("remove_from_rx_queue: %x, length %d",
+          (int)pHeader, (int)pHeader->length );
+
+   save_flags(flags);
+   cli();
+
+   if(pInfo->rx_first == pHeader)
+   {
+      /* Remove the first block in the linked list: */
+      pInfo->rx_first = pHeader->next;
+      
+      if(pInfo->rx_first==NULL)
+      {
+         pInfo->rx_last = NULL;
+      }
+      pInfo->blocks_in_rx_queue--;
+   }
+   else 
+   {
+      /* Find block to remove: */
+      for(pFind=pInfo->rx_first; pFind; pFind=pFind->next)
+      {
+         if(pFind->next == pHeader) 
+         {
+            /* Got it. */
+            pFind->next = pHeader->next;
+            pInfo->blocks_in_rx_queue--;
+            if(pFind->next==NULL)
+            {
+               /* Oh, removed the last one! */
+               pInfo->rx_last = pFind;
+            }
+            break;
+         }
+      }
+   }
+
+   restore_flags(flags);
+
+   kfree(pHeader);
+   TRACE_M("remove_from_rx_queue - kfree %x",(int)pHeader);
+
+   TRACE_Q("remove_from_rx_queue: rx_first = %x, rx_last = %x, count = %d",
+          (int)pInfo->rx_first, (int)pInfo->rx_last, pInfo->blocks_in_rx_queue );
+}
+
+static void put_char(struct r3964_info *pInfo, unsigned char ch)
+{
+   struct tty_struct *tty = pInfo->tty;
+
+   if(tty==NULL)
+      return;
+
+   if(tty->driver.put_char)
+   {
+      tty->driver.put_char(tty, ch);
+   }
+   pInfo->bcc ^= ch;
+}
+
+static void flush(struct r3964_info *pInfo)
+{
+   struct tty_struct *tty = pInfo->tty;
+
+   if(tty==NULL)
+      return;
+
+   if(tty->driver.flush_chars)
+   {
+      tty->driver.flush_chars(tty);
+   }
+}
+
+static void trigger_transmit(struct r3964_info *pInfo)
+{
+   unsigned long flags;
+   
+
+   save_flags(flags);
+   cli();
+
+   if((pInfo->state == R3964_IDLE) && (pInfo->tx_first!=NULL))
+   {
+      pInfo->state = R3964_TX_REQUEST;
+      pInfo->count_down = R3964_TO_QVZ;
+      pInfo->nRetry=0;
+      pInfo->flags &= ~R3964_ERROR;
+      
+      restore_flags(flags);
+
+      TRACE_PS("trigger_transmit - sent STX");
+
+      put_char(pInfo, STX);
+      flush(pInfo);
+
+      pInfo->bcc = 0;
+   }
+   else
+   {
+      restore_flags(flags);
+   }
+}
+
+static void retry_transmit(struct r3964_info *pInfo)
+{
+   if(pInfo->nRetry<R3964_MAX_RETRIES)
+   {
+      TRACE_PE("transmission failed. Retry #%d", 
+             pInfo->nRetry);
+      pInfo->bcc = 0;
+      put_char(pInfo, STX);
+      flush(pInfo);
+      pInfo->state = R3964_TX_REQUEST;
+      pInfo->count_down = R3964_TO_QVZ;
+      pInfo->nRetry++;
+   }
+   else
+   {
+      TRACE_PE("transmission failed after %d retries", 
+             R3964_MAX_RETRIES);
+
+      remove_from_tx_queue(pInfo, R3964_TX_FAIL);
+      
+      put_char(pInfo, NAK);
+      flush(pInfo);
+      pInfo->state = R3964_IDLE;
+
+      trigger_transmit(pInfo);
+   }
+}
+
+
+static void transmit_block(struct r3964_info *pInfo)
+{
+   struct tty_struct *tty = pInfo->tty;
+   struct r3964_block_header *pBlock = pInfo->tx_first;
+   int room=0;
+
+   if((tty==NULL) || (pBlock==NULL))
+   {
+      return;
+   }
+
+   if(tty->driver.write_room)
+      room=tty->driver.write_room(tty);
+
+   TRACE_PS("transmit_block %x, room %d, length %d", 
+          (int)pBlock, room, pBlock->length);
+   
+   while(pInfo->tx_position < pBlock->length)
+   {
+      if(room<2)
+         break;
+ 
+      if(pBlock->data[pInfo->tx_position]==DLE)
+      {
+         /* send additional DLE char: */
+         put_char(pInfo, DLE);
+      }
+      put_char(pInfo, pBlock->data[pInfo->tx_position++]);
+      
+      room--;
+   }
+
+   if((pInfo->tx_position == pBlock->length) && (room>=3))
+   {
+      put_char(pInfo, DLE);
+      put_char(pInfo, ETX);
+      if(pInfo->flags & R3964_BCC)
+      {
+         put_char(pInfo, pInfo->bcc);
+      }
+      pInfo->state = R3964_WAIT_FOR_TX_ACK;
+      pInfo->count_down = R3964_TO_QVZ;
+   }
+   flush(pInfo);
+}
+
+static void on_receive_block(struct r3964_info *pInfo)
+{
+   unsigned int length;
+   struct r3964_client_info *pClient;
+   struct r3964_block_header *pBlock;
+   
+   length=pInfo->rx_position;
+
+   /* compare byte checksum characters: */
+   if(pInfo->flags & R3964_BCC)
+   {
+      if(pInfo->bcc!=pInfo->last_rx)
+      {
+         TRACE_PE("checksum error - got %x but expected %x",
+                pInfo->last_rx, pInfo->bcc);
+         pInfo->flags |= R3964_CHECKSUM;
+      }
+   }
+
+   /* check for errors (parity, overrun,...): */
+   if(pInfo->flags & R3964_ERROR)
+   {
+      TRACE_PE("on_receive_block - transmission failed error %x",
+             pInfo->flags & R3964_ERROR);
+      
+      put_char(pInfo, NAK);
+      flush(pInfo);
+      if(pInfo->nRetry<R3964_MAX_RETRIES)
+      {
+         pInfo->state=R3964_WAIT_FOR_RX_REPEAT;
+         pInfo->count_down = R3964_TO_RX_PANIC;
+         pInfo->nRetry++;
+      }
+      else
+      {
+         TRACE_PE("on_receive_block - failed after max retries");
+         pInfo->state=R3964_IDLE;
+      }
+      return;
+   }
+
+   
+   /* received block; submit DLE: */
+   put_char(pInfo, DLE);
+   flush(pInfo);
+   pInfo->count_down=0;
+   TRACE_PS(" rx success: got %d chars", length);
+
+   /* prepare struct r3964_block_header: */
+   pBlock = kmalloc(length+sizeof(struct r3964_block_header), GFP_KERNEL);
+   TRACE_M("on_receive_block - kmalloc %x",(int)pBlock);
+
+   if(pBlock==NULL)
+      return;
+
+   pBlock->length = length;
+   pBlock->data   = ((unsigned char*)pBlock)+sizeof(struct r3964_block_header);
+   pBlock->locks  = 0;
+   pBlock->next   = NULL;
+   pBlock->owner  = NULL;
+
+   memcpy(pBlock->data, pInfo->rx_buf, length);
+
+   /* queue block into rx_queue: */
+   add_rx_queue(pInfo, pBlock);
+
+   /* notify attached client processes: */
+   for(pClient=pInfo->firstClient; pClient; pClient=pClient->next)
+   {
+      if(pClient->sig_flags & R3964_SIG_DATA)
+      {
+         add_msg(pClient, R3964_MSG_DATA, length, R3964_OK, pBlock);
+      }
+   }
+   wake_up_interruptible (&pInfo->read_wait);
+   
+   pInfo->state = R3964_IDLE;
+
+   trigger_transmit(pInfo);
+}
+
+
+static void receive_char(struct r3964_info *pInfo, const unsigned char c)
+{
+   switch(pInfo->state)
+   {
+      case R3964_TX_REQUEST:
+         if(c==DLE)
+         {
+            TRACE_PS("TX_REQUEST - got DLE");
+
+            pInfo->state = R3964_TRANSMITTING;
+            pInfo->tx_position = 0;
+            
+            transmit_block(pInfo);
+         }
+         else if(c==STX)
+         {
+            if(pInfo->nRetry==0)
+            {
+               TRACE_PE("TX_REQUEST - init conflict");
+               if(pInfo->priority == R3964_SLAVE)
+               {
+                  goto start_receiving;
+               }
+            } 
+            else 
+            {
+               TRACE_PE("TX_REQUEST - secondary init conflict!?"
+                        " Switching to SLAVE mode for next rx.");
+               goto start_receiving;
+            }
+         }
+         else
+         {
+            TRACE_PE("TX_REQUEST - char != DLE: %x", c);
+            retry_transmit(pInfo);
+         }
+         break;
+      case R3964_TRANSMITTING:
+         if(c==NAK)
+         {
+            TRACE_PE("TRANSMITTING - got NAK");
+            retry_transmit(pInfo);
+         }
+         else
+         {
+            TRACE_PE("TRANSMITTING - got illegal char");
+ 
+            pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY;
+            pInfo->count_down = R3964_TO_ZVZ;
+         }
+         break;
+      case R3964_WAIT_FOR_TX_ACK:
+         if(c==DLE)
+         {
+            TRACE_PS("WAIT_FOR_TX_ACK - got DLE");
+            remove_from_tx_queue(pInfo, R3964_OK);
+            
+            pInfo->state = R3964_IDLE;
+            trigger_transmit(pInfo);
+         }
+         else
+         {
+            retry_transmit(pInfo);
+         }
+         break;
+      case R3964_WAIT_FOR_RX_REPEAT:
+         /* FALLTROUGH */
+      case R3964_IDLE:
+         if(c==STX)
+         {
+            /* Prevent rx_queue from overflow: */
+            if(pInfo->blocks_in_rx_queue >= R3964_MAX_BLOCKS_IN_RX_QUEUE)
+            {
+               TRACE_PE("IDLE - got STX but no space in rx_queue!");
+               pInfo->state=R3964_WAIT_FOR_RX_BUF;
+               pInfo->count_down = R3964_TO_NO_BUF;
+               break;
+            }
+start_receiving:
+            /* Ok, start receiving: */
+            TRACE_PS("IDLE - got STX");
+            pInfo->rx_position = 0;
+            pInfo->last_rx = 0;
+            pInfo->flags &= ~R3964_ERROR;
+            pInfo->state=R3964_RECEIVING;
+            pInfo->count_down = R3964_TO_ZVZ;
+            pInfo->nRetry = 0;
+            put_char(pInfo, DLE);
+            flush(pInfo);
+            pInfo->bcc = 0;
+         }
+         break;
+      case R3964_RECEIVING:
+         if(pInfo->rx_position < RX_BUF_SIZE)
+         {
+            pInfo->bcc ^= c;
+            
+            if(c==DLE)
+            {
+               if(pInfo->last_rx==DLE)
+               {
+                  pInfo->last_rx = 0;
+                  goto char_to_buf;
+               }
+               pInfo->last_rx = DLE;
+               break;
+            } 
+            else if((c==ETX) && (pInfo->last_rx==DLE))
+            {
+               if(pInfo->flags & R3964_BCC)
+               {
+                  pInfo->state = R3964_WAIT_FOR_BCC;
+                  pInfo->count_down = R3964_TO_ZVZ;
+               }
+               else 
+               {
+                  on_receive_block(pInfo);
+               }
+            }
+            else
+            {
+               pInfo->last_rx = c;
+char_to_buf:
+               pInfo->rx_buf[pInfo->rx_position++] = c;
+               pInfo->count_down = R3964_TO_ZVZ;
+            }
+         }
+        /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ 
+         break;
+      case R3964_WAIT_FOR_BCC:
+         pInfo->last_rx = c;
+         on_receive_block(pInfo);
+         break;
+   }
+}
+
+static void receive_error(struct r3964_info *pInfo, const char flag)
+{
+    switch (flag) 
+    {
+    case TTY_NORMAL:
+        break;
+    case TTY_BREAK:
+        TRACE_PE("received break")
+        pInfo->flags |= R3964_BREAK;
+        break;
+    case TTY_PARITY:
+        TRACE_PE("parity error")
+        pInfo->flags |= R3964_PARITY;
+        break;
+    case TTY_FRAME:
+        TRACE_PE("frame error")
+        pInfo->flags |= R3964_FRAME;
+        break;
+    case TTY_OVERRUN:
+        TRACE_PE("frame overrun")
+        pInfo->flags |= R3964_OVERRUN;
+        break;
+    default:
+        TRACE_PE("receive_error - unknown flag %d", flag);
+        pInfo->flags |= R3964_UNKNOWN;
+        break;
+    }
+}
+
+static void on_timeout(struct r3964_info *pInfo)
+{
+   switch(pInfo->state)
+   {
+      case R3964_TX_REQUEST:
+         TRACE_PE("TX_REQUEST - timeout");
+         retry_transmit(pInfo);
+         break;
+      case R3964_WAIT_ZVZ_BEFORE_TX_RETRY:
+         put_char(pInfo, NAK);
+         flush(pInfo);
+         retry_transmit(pInfo);
+         break;
+      case R3964_WAIT_FOR_TX_ACK:
+         TRACE_PE("WAIT_FOR_TX_ACK - timeout");
+         retry_transmit(pInfo);
+         break;
+      case R3964_WAIT_FOR_RX_BUF:
+         TRACE_PE("WAIT_FOR_RX_BUF - timeout");
+         put_char(pInfo, NAK);
+         flush(pInfo);
+         pInfo->state=R3964_IDLE;
+         break;
+      case R3964_RECEIVING:
+         TRACE_PE("RECEIVING - timeout after %d chars", 
+                  pInfo->rx_position);
+         put_char(pInfo, NAK);
+         flush(pInfo);
+         pInfo->state=R3964_IDLE;
+         break;
+      case R3964_WAIT_FOR_RX_REPEAT:
+         TRACE_PE("WAIT_FOR_RX_REPEAT - timeout");
+         pInfo->state=R3964_IDLE;
+         break;
+      case R3964_WAIT_FOR_BCC:
+         TRACE_PE("WAIT_FOR_BCC - timeout");
+         put_char(pInfo, NAK);
+         flush(pInfo);
+         pInfo->state=R3964_IDLE;
+         break;
+   }
+}
+
+static struct r3964_client_info *findClient(
+  struct r3964_info *pInfo, pid_t pid)
+{
+   struct r3964_client_info *pClient;
+   
+   for(pClient=pInfo->firstClient; pClient; pClient=pClient->next)
+   {
+      if(pClient->pid == pid)
+      {
+         return pClient;
+      }
+   }
+   return NULL;
+}
+
+static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg)
+{
+   struct r3964_client_info *pClient;
+   struct r3964_client_info **ppClient;
+   struct r3964_message *pMsg;
+   
+   if((arg & R3964_SIG_ALL)==0)
+   {
+      /* Remove client from client list */
+      for(ppClient=&pInfo->firstClient; *ppClient; ppClient=&(*ppClient)->next)
+      {
+         pClient = *ppClient;
+         
+         if(pClient->pid == pid)
+         {
+            TRACE_PS("removing client %d from client list", pid);
+            *ppClient = pClient->next;
+            while(pClient->msg_count)
+            {
+               pMsg=remove_msg(pInfo, pClient);
+               if(pMsg)
+               {
+                  kfree(pMsg);
+                  TRACE_M("enable_signals - msg kfree %x",(int)pMsg);
+               }
+            }
+            kfree(pClient);
+            TRACE_M("enable_signals - kfree %x",(int)pClient);
+            return 0;
+         }
+      }
+      return -EINVAL;
+   }
+   else
+   {
+      pClient=findClient(pInfo, pid);
+      if(pClient)
+      {
+         /* update signal options */
+         pClient->sig_flags=arg;
+      } 
+      else 
+      {
+         /* add client to client list */
+         pClient=kmalloc(sizeof(struct r3964_client_info), GFP_KERNEL);
+         TRACE_M("enable_signals - kmalloc %x",(int)pClient);
+         if(pClient==NULL)
+            return -ENOMEM;
+
+         TRACE_PS("add client %d to client list", pid);
+         pClient->sig_flags=arg;
+         pClient->pid = pid;
+         pClient->next=pInfo->firstClient;
+         pClient->first_msg = NULL;
+         pClient->last_msg = NULL;
+         pClient->next_block_to_read = NULL;
+         pClient->msg_count = 0;
+         pInfo->firstClient=pClient;
+      }
+   }
+
+   return 0;
+}
+
+static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char *buf)
+{
+    struct r3964_client_info *pClient;
+    struct r3964_block_header *block;
+
+    if(!buf)
+    {
+        return -EINVAL;
+    }
+
+    pClient=findClient(pInfo,pid);
+    if(pClient==NULL)
+    {
+       return -EINVAL;
+    }
+    
+    block=pClient->next_block_to_read;
+    if(!block)
+    {
+       return 0;
+    }
+    else
+    {
+      if (copy_to_user (buf, block->data, block->length))
+	return -EFAULT;
+
+       remove_client_block(pInfo, pClient);
+       return block->length;
+    }
+
+    return -EINVAL;
+}
+
+static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
+             int error_code, struct r3964_block_header *pBlock)
+{
+   struct r3964_message *pMsg;
+   unsigned long flags;
+   
+   if(pClient->msg_count<R3964_MAX_MSG_COUNT-1)
+   {
+queue_the_message:
+
+      save_flags(flags);
+      cli();
+
+      pMsg = kmalloc(sizeof(struct r3964_message), GFP_KERNEL);
+      TRACE_M("add_msg - kmalloc %x",(int)pMsg);
+      if(pMsg==NULL)
+         return;
+
+      pMsg->msg_id = msg_id;
+      pMsg->arg    = arg;
+      pMsg->error_code = error_code;
+      pMsg->block  = pBlock;
+      pMsg->next   = NULL;
+      
+      if(pClient->last_msg==NULL)
+      {
+         pClient->first_msg=pClient->last_msg=pMsg;
+      }
+      else
+      {
+         pClient->last_msg->next = pMsg;
+         pClient->last_msg=pMsg;
+      }
+
+      pClient->msg_count++;
+
+      if(pBlock!=NULL)
+      {
+         pBlock->locks++;
+      }
+      restore_flags(flags);
+   }
+   else
+   {
+      if((pClient->last_msg->msg_id == R3964_MSG_ACK)
+		 && (pClient->last_msg->error_code==R3964_OVERFLOW))
+      {
+         pClient->last_msg->arg++;
+		 TRACE_PE("add_msg - inc prev OVERFLOW-msg");
+      }
+      else
+      {
+         msg_id = R3964_MSG_ACK;
+         arg = 0;
+		 error_code = R3964_OVERFLOW;
+         pBlock = NULL;
+		 TRACE_PE("add_msg - queue OVERFLOW-msg");
+         goto queue_the_message;
+      }
+   }
+   /* Send SIGIO signal to client process: */
+   if(pClient->sig_flags & R3964_USE_SIGIO)
+   {
+      kill_proc(pClient->pid, SIGIO, 1);
+   }
+}
+
+static struct r3964_message *remove_msg(struct r3964_info *pInfo,
+                       struct r3964_client_info *pClient)
+{
+   struct r3964_message *pMsg=NULL;
+   unsigned long flags;
+
+   if(pClient->first_msg)
+   {
+      save_flags(flags);
+      cli();
+
+      pMsg = pClient->first_msg;
+      pClient->first_msg = pMsg->next;
+      if(pClient->first_msg==NULL)
+      {
+         pClient->last_msg = NULL;
+      }
+      
+      pClient->msg_count--;
+      if(pMsg->block)
+      {
+        remove_client_block(pInfo, pClient);
+        pClient->next_block_to_read = pMsg->block;
+      }
+      restore_flags(flags);
+   }
+   return pMsg;
+}
+
+static void remove_client_block(struct r3964_info *pInfo, 
+                struct r3964_client_info *pClient)
+{
+    struct r3964_block_header *block;
+
+    TRACE_PS("remove_client_block PID %d", pClient->pid);
+
+    block=pClient->next_block_to_read;
+    if(block)
+    {
+        block->locks--;
+        if(block->locks==0)
+        {
+            remove_from_rx_queue(pInfo, block);
+        }
+    }
+    pClient->next_block_to_read = NULL;
+}
+
+
+/*************************************************************
+ * Line discipline routines
+ *************************************************************/
+
+static int r3964_open(struct tty_struct *tty)
+{
+   struct r3964_info *pInfo;
+   
+   MOD_INC_USE_COUNT;
+
+   TRACE_L("open");
+   TRACE_L("tty=%x, PID=%d, disc_data=%x", 
+          (int)tty, current->pid, (int)tty->disc_data);
+   
+   pInfo=kmalloc(sizeof(struct r3964_info), GFP_KERNEL); 
+   TRACE_M("r3964_open - info kmalloc %x",(int)pInfo);
+
+   if(!pInfo)
+   {
+      printk(KERN_ERR "r3964: failed to alloc info structure\n");
+      return -ENOMEM;
+   }
+
+   pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
+   TRACE_M("r3964_open - rx_buf kmalloc %x",(int)pInfo->rx_buf);
+
+   if(!pInfo->rx_buf)
+   {
+      printk(KERN_ERR "r3964: failed to alloc receive buffer\n");
+      kfree(pInfo);
+      TRACE_M("r3964_open - info kfree %x",(int)pInfo);
+      return -ENOMEM;
+   }
+   
+   pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL);
+   TRACE_M("r3964_open - tx_buf kmalloc %x",(int)pInfo->tx_buf);
+
+   if(!pInfo->tx_buf)
+   {
+      printk(KERN_ERR "r3964: failed to alloc transmit buffer\n");
+      kfree(pInfo->rx_buf);
+      TRACE_M("r3964_open - rx_buf kfree %x",(int)pInfo->rx_buf);
+      kfree(pInfo);
+      TRACE_M("r3964_open - info kfree %x",(int)pInfo);
+      return -ENOMEM;
+   }
+
+   pInfo->tty = tty;
+   init_waitqueue_head (&pInfo->read_wait);
+   pInfo->priority = R3964_MASTER;
+   pInfo->rx_first = pInfo->rx_last = NULL;
+   pInfo->tx_first = pInfo->tx_last = NULL;
+   pInfo->rx_position = 0;
+   pInfo->tx_position = 0;
+   pInfo->last_rx = 0;
+   pInfo->blocks_in_rx_queue = 0;
+   pInfo->firstClient=NULL;
+   pInfo->state=R3964_IDLE;
+   pInfo->flags = R3964_DEBUG;
+   pInfo->count_down = 0;
+   pInfo->nRetry = 0;
+   
+   tty->disc_data = pInfo;
+
+   /*
+    * Add 'on_timer' to timer task queue
+    * (will be called from timer bh)
+    */
+   pInfo->bh_1.next = NULL;
+   pInfo->bh_1.sync = 0;
+   pInfo->bh_1.routine = &on_timer_1;
+   pInfo->bh_1.data = pInfo;
+   
+   pInfo->bh_2.next = NULL;
+   pInfo->bh_2.sync = 0;
+   pInfo->bh_2.routine = &on_timer_2;
+   pInfo->bh_2.data = pInfo;
+
+   queue_task(&pInfo->bh_1, &tq_timer);
+
+   return 0;
+}
+
+static void r3964_close(struct tty_struct *tty)
+{
+   struct tq_struct *tq, *prev;
+   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
+   struct r3964_client_info *pClient, *pNext;
+   struct r3964_message *pMsg;
+   struct r3964_block_header *pHeader, *pNextHeader;
+   unsigned long flags;
+
+   TRACE_L("close");
+
+    /*
+     * Make sure that our task queue isn't activated.  If it
+     * is, take it out of the linked list.
+     */
+    save_flags(flags);
+    cli();
+
+    for (tq=tq_timer, prev=0; tq; prev=tq, tq=tq->next) {
+         if ((tq == &pInfo->bh_1) || (tq==&pInfo->bh_2)) {
+             if (prev)
+                 prev->next = tq->next;
+             else
+                 tq_timer = tq->next;
+             break;
+         }
+    }
+    restore_flags(flags);
+
+   /* Remove client-structs and message queues: */
+    pClient=pInfo->firstClient;
+    while(pClient)
+    {
+       pNext=pClient->next;
+       while(pClient->msg_count)
+       {
+          pMsg=remove_msg(pInfo, pClient);
+          if(pMsg)
+          {
+             kfree(pMsg);
+             TRACE_M("r3964_close - msg kfree %x",(int)pMsg);
+          }
+       }
+       kfree(pClient);
+       TRACE_M("r3964_close - client kfree %x",(int)pClient);
+       pClient=pNext;
+    }
+    /* Remove jobs from tx_queue: */
+	save_flags(flags);
+        cli();
+	pHeader=pInfo->tx_first;
+	pInfo->tx_first=pInfo->tx_last=NULL;
+	restore_flags(flags);
+	
+    while(pHeader)
+	{
+	   pNextHeader=pHeader->next;
+	   kfree(pHeader);
+	   pHeader=pNextHeader;
+	}
+
+    /* Free buffers: */
+    wake_up_interruptible(&pInfo->read_wait);
+    kfree(pInfo->rx_buf);
+    TRACE_M("r3964_close - rx_buf kfree %x",(int)pInfo->rx_buf);
+    kfree(pInfo->tx_buf);
+    TRACE_M("r3964_close - tx_buf kfree %x",(int)pInfo->tx_buf);
+    kfree(pInfo);
+    TRACE_M("r3964_close - info kfree %x",(int)pInfo);
+
+    MOD_DEC_USE_COUNT;
+}
+
+static int r3964_read(struct tty_struct *tty, struct file *file,
+                     unsigned char *buf, unsigned int nr)
+{
+   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
+   struct r3964_client_info *pClient;
+   struct r3964_message *pMsg;
+   struct r3964_client_message theMsg;
+   DECLARE_WAITQUEUE (wait, current);
+   
+   int pid = current->pid;
+   int count;
+   
+   TRACE_L("read()");
+ 
+   pClient=findClient(pInfo, pid);
+   if(pClient)
+   {
+      pMsg = remove_msg(pInfo, pClient);
+      if(pMsg==NULL)
+      {
+		 /* no messages available. */
+         if (file->f_flags & O_NONBLOCK)
+		 {
+            return -EAGAIN;
+		 }
+         /* block until there is a message: */
+         add_wait_queue(&pInfo->read_wait, &wait);
+repeat:
+         pMsg = remove_msg(pInfo, pClient);
+         current->state = TASK_INTERRUPTIBLE;
+	 if (!pMsg && !signal_pending(current))
+		 {
+            schedule();
+            goto repeat;
+         }
+         current->state = TASK_RUNNING;
+         remove_wait_queue(&pInfo->read_wait, &wait);
+      }
+      
+      /* If we still haven't got a message, we must have been signalled */
+
+      if (!pMsg) return -EINTR;
+
+      /* deliver msg to client process: */
+      theMsg.msg_id = pMsg->msg_id;
+      theMsg.arg    = pMsg->arg;
+      theMsg.error_code = pMsg->error_code;
+      count = sizeof(struct r3964_client_message);
+
+      kfree(pMsg);
+      TRACE_M("r3964_read - msg kfree %x",(int)pMsg);
+
+      if (copy_to_user(buf,&theMsg, count))
+	return -EFAULT;
+
+      TRACE_PS("read - return %d", count);
+      return count;
+   }
+   return -EPERM;
+}
+
+static int r3964_write(struct tty_struct * tty, struct file * file,
+                      const unsigned char *data, unsigned int count)
+{
+   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
+   struct r3964_block_header *pHeader;
+   struct r3964_client_info *pClient;
+   unsigned char *new_data;
+   int status;
+   int pid;
+   
+   TRACE_L("write request, %d characters", count);
+/* 
+ * Verify the pointers 
+ */
+
+   if(!pInfo)
+      return -EIO;
+
+   status = verify_area (VERIFY_READ, data, count);
+   if (status != 0) 
+   {
+      return status;
+   }
+
+/*
+ * Ensure that the caller does not wish to send too much.
+ */
+   if (count > R3964_MTU) 
+   {
+      if (pInfo->flags & R3964_DEBUG)
+      {
+         TRACE_L (KERN_WARNING
+                 "r3964_write: truncating user packet "
+                 "from %u to mtu %d", count, R3964_MTU);
+      }
+      count = R3964_MTU;
+   }
+/*
+ * Allocate a buffer for the data and fetch it from the user space.
+ */
+   new_data = kmalloc (count+sizeof(struct r3964_block_header), GFP_KERNEL);
+   TRACE_M("r3964_write - kmalloc %x",(int)new_data);
+   if (new_data == NULL) {
+      if (pInfo->flags & R3964_DEBUG)
+      {
+         printk (KERN_ERR
+               "r3964_write: no memory\n");
+      }
+      return -ENOSPC;
+   }
+   
+   pHeader = (struct r3964_block_header *)new_data;
+   pHeader->data = new_data + sizeof(struct r3964_block_header);
+   pHeader->length = count;
+   pHeader->locks = 0;
+   pHeader->owner = NULL;
+   
+   pid=current->pid;
+   
+   pClient=findClient(pInfo, pid);
+   if(pClient)
+   {
+      pHeader->owner = pClient;
+   }
+
+   copy_from_user (pHeader->data, data, count); /* We already verified this */
+
+   if(pInfo->flags & R3964_DEBUG)
+   {
+      dump_block(pHeader->data, count);
+   }
+
+/*
+ * Add buffer to transmit-queue:
+ */
+   add_tx_queue(pInfo, pHeader);
+   trigger_transmit(pInfo);
+   
+   return 0;
+}
+
+static int r3964_ioctl(struct tty_struct * tty, struct file * file,
+               unsigned int cmd, unsigned long arg)
+{
+   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
+   if(pInfo==NULL)
+      return -EINVAL;
+   switch(cmd)
+   {
+      case R3964_ENABLE_SIGNALS:
+         return enable_signals(pInfo, current->pid, arg);
+      case R3964_SETPRIORITY:
+         if(arg<R3964_MASTER || arg>R3964_SLAVE)
+            return -EINVAL;
+         pInfo->priority = arg & 0xff;
+         return 0;
+      case R3964_USE_BCC:
+             if(arg)
+            pInfo->flags |= R3964_BCC;
+         else
+            pInfo->flags &= ~R3964_BCC;
+         return 0;
+      case R3964_READ_TELEGRAM:
+         return read_telegram(pInfo, current->pid, (unsigned char *)arg);
+      default:
+         return -ENOIOCTLCMD;
+   }
+}
+
+static void r3964_set_termios(struct tty_struct *tty, struct termios * old)
+{
+   TRACE_L("set_termios");
+}
+
+static unsigned int r3964_poll(struct tty_struct * tty, struct file * file,
+		      struct poll_table_struct *wait)
+{
+   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
+   int pid=current->pid;
+   struct r3964_client_info *pClient;
+   struct r3964_message *pMsg=NULL;
+   unsigned int flags;
+   int result = POLLOUT;
+
+   TRACE_L("POLL");
+
+   pClient=findClient(pInfo,pid);
+   if(pClient)
+     {
+       poll_wait(file, &pInfo->read_wait, wait);
+       save_flags(flags);
+       cli();
+       pMsg=pClient->first_msg;
+       restore_flags(flags);
+       if(pMsg)
+	   result |= POLLIN | POLLRDNORM;
+     }
+   else
+     {
+       result = -EINVAL;
+     }
+   return result;
+}
+
+static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+                              char *fp, int count)
+{
+   struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data;
+    const unsigned char *p;
+    char *f, flags = 0;
+    int i;
+
+    for (i=count, p = cp, f = fp; i; i--, p++) {
+        if (f)
+            flags = *f++;
+        if(flags==TTY_NORMAL)
+        {
+            receive_char(pInfo, *p);
+        }
+        else
+        {
+            receive_error(pInfo, flags);
+        }
+        
+    }
+}
+
+static int r3964_receive_room(struct tty_struct *tty)
+{
+   TRACE_L("receive_room");
+   return -1;
+}
+
diff -u --recursive --new-file v2.3.15/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- v2.3.15/linux/drivers/char/n_tty.c	Tue May 11 14:37:40 1999
+++ linux/drivers/char/n_tty.c	Tue Aug 31 11:30:48 1999
@@ -948,7 +948,7 @@
 		/* This statement must be first before checking for input
 		   so that any interrupt will set the state back to
 		   TASK_RUNNING. */
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		
 		if (((minimum - (b - buf)) < tty->minimum_to_wake) &&
 		    ((minimum - (b - buf)) >= 1))
@@ -1073,7 +1073,7 @@
 
 	add_wait_queue(&tty->write_wait, &wait);
 	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
 			break;
diff -u --recursive --new-file v2.3.15/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.3.15/linux/drivers/char/pc_keyb.c	Mon Aug  2 16:40:36 1999
+++ linux/drivers/char/pc_keyb.c	Tue Aug 31 11:30:48 1999
@@ -872,7 +872,7 @@
 			return -EAGAIN;
 		add_wait_queue(&queue->proc_list, &wait);
 repeat:
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (queue_empty() && !signal_pending(current)) {
 			schedule();
 			goto repeat;
diff -u --recursive --new-file v2.3.15/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c
--- v2.3.15/linux/drivers/char/pcxx.c	Thu Aug  5 14:34:01 1999
+++ linux/drivers/char/pcxx.c	Tue Aug 31 11:30:48 1999
@@ -356,7 +356,7 @@
 			memoff(info);
 		}
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if(tty_hung_up_p(filp) || (info->asyncflags & ASYNC_INITIALIZED) == 0) {
 			if(info->asyncflags & ASYNC_HUP_NOTIFY)
 				retval = -EAGAIN;
diff -u --recursive --new-file v2.3.15/linux/drivers/char/planb.c linux/drivers/char/planb.c
--- v2.3.15/linux/drivers/char/planb.c	Thu Aug  5 14:34:01 1999
+++ linux/drivers/char/planb.c	Tue Aug 31 11:30:48 1999
@@ -383,7 +383,7 @@
 
 	add_wait_queue(&pb->lockq, &wait);
 repeat:
-	current->state = TASK_UNINTERRUPTIBLE;
+	set_current_state(TASK_UNINTERRUPTIBLE);
 	if (pb->lock) {
 		schedule();
 		goto repeat;
@@ -1533,7 +1533,8 @@
 
 			DEBUG("PlanB: IOCTL VIDIOCSFBUF\n");
 
-                        if (!capable(CAP_SYS_ADMIN))
+                        if (!capable(CAP_SYS_ADMIN)
+			|| !capable(CAP_SYS_RAWIO))
                                 return -EPERM;
                         if (copy_from_user(&v, arg,sizeof(v)))
                                 return -EFAULT;
diff -u --recursive --new-file v2.3.15/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c
--- v2.3.15/linux/drivers/char/ppdev.c	Fri Jul 30 12:28:26 1999
+++ linux/drivers/char/ppdev.c	Fri Aug 27 12:24:35 1999
@@ -502,8 +502,8 @@
 	}
 
 	if (pp->pdev) {
-		kfree (pp->pdev->name);
 		parport_unregister_device (pp->pdev);
+		kfree (pp->pdev->name);
 		pp->pdev = NULL;
 		printk (KERN_DEBUG CHRDEV "%x: unregistered pardevice\n",
 			minor);
diff -u --recursive --new-file v2.3.15/linux/drivers/char/qpmouse.c linux/drivers/char/qpmouse.c
--- v2.3.15/linux/drivers/char/qpmouse.c	Tue May 11 14:37:40 1999
+++ linux/drivers/char/qpmouse.c	Tue Aug 31 11:30:48 1999
@@ -267,7 +267,7 @@
 			return -EAGAIN;
 		add_wait_queue(&queue->proc_list, &wait);
 repeat:
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (queue_empty() && !signal_pending(current)) {
 			schedule();
 			goto repeat;
diff -u --recursive --new-file v2.3.15/linux/drivers/char/radio-terratec.c linux/drivers/char/radio-terratec.c
--- v2.3.15/linux/drivers/char/radio-terratec.c	Mon Jul  5 20:07:02 1999
+++ linux/drivers/char/radio-terratec.c	Thu Aug 26 13:53:10 1999
@@ -299,7 +299,7 @@
 	NULL
 };
 
-__initfunc(int terratec_init(struct video_init *v))
+int __init terratec_init(struct video_init *v)
 {
 	if (check_region(io, 2)) 
 	{
diff -u --recursive --new-file v2.3.15/linux/drivers/char/random.c linux/drivers/char/random.c
--- v2.3.15/linux/drivers/char/random.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/char/random.c	Tue Aug 31 12:37:39 1999
@@ -1,10 +1,10 @@
 /*
  * random.c -- A strong random number generator
  *
- * Version 1.04, last modified 26-Apr-98
+ * Version 1.88, last modified 30-Aug-99
  * 
- * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998.  All rights
- * reserved.
+ * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999.  All
+ * rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,15 +27,16 @@
  * 
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
  */
 
 /*
@@ -223,8 +224,8 @@
  * The code for SHA transform was taken from Peter Gutmann's
  * implementation, which has been placed in the public domain.
  * The code for MD5 transform was taken from Colin Plumb's
- * implementation, which has been placed in the public domain.  The
- * MD5 cryptographic checksum was devised by Ronald Rivest, and is
+ * implementation, which has been placed in the public domain.
+ * The MD5 cryptographic checksum was devised by Ronald Rivest, and is
  * documented in RFC 1321, "The MD5 Message Digest Algorithm".
  * 
  * Further background information on this topic may be obtained from
@@ -232,11 +233,6 @@
  * Eastlake, Steve Crocker, and Jeff Schiller.
  */
 
-/*
- * Added a check for signal pending in the extract_entropy() loop to allow
- * the read(2) syscall to be interrupted. Copyright (C) 1998  Andrea Arcangeli
- */
-
 #include <linux/utsname.h>
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -256,72 +252,77 @@
 /*
  * Configuration information
  */
-#undef RANDOM_BENCHMARK
-#undef BENCHMARK_NOINT
-#define ROTATE_PARANOIA
-
-#define POOLWORDS 128    /* Power of 2 - note that this is 32-bit words */
-#define POOLBITS (POOLWORDS*32)
-/*
- * The pool is stirred with a primitive polynomial of degree POOLWORDS
- * over GF(2).  The taps for various sizes are defined below.  They are
- * chosen to be evenly spaced (minimum RMS distance from evenly spaced;
- * the numbers in the comments are a scaled squared error sum) except
- * for the last tap, which is 1 to get the twisting happening as fast
- * as possible.
- */
-#if POOLWORDS == 2048	/* 115 x^2048+x^1638+x^1231+x^819+x^411+x^1+1 */
-#define TAP1	1638
-#define TAP2	1231
-#define TAP3	819
-#define TAP4	411
-#define TAP5	1
-#elif POOLWORDS == 1024	/* 290 x^1024+x^817+x^615+x^412+x^204+x^1+1 */
-/* Alt: 115 x^1024+x^819+x^616+x^410+x^207+x^2+1 */
-#define TAP1	817
-#define TAP2	615
-#define TAP3	412
-#define TAP4	204
-#define TAP5	1
-#elif POOLWORDS == 512	/* 225 x^512+x^411+x^308+x^208+x^104+x+1 */
-/* Alt: 95 x^512+x^409+x^307+x^206+x^102+x^2+1
- *      95 x^512+x^409+x^309+x^205+x^103+x^2+1 */
-#define TAP1	411
-#define TAP2	308
-#define TAP3	208
-#define TAP4	104
-#define TAP5	1
-#elif POOLWORDS == 256	/* 125 x^256+x^205+x^155+x^101+x^52+x+1 */
-#define TAP1	205
-#define TAP2	155
-#define TAP3	101
-#define TAP4	52
-#define TAP5	1
-#elif POOLWORDS == 128	/* 105 x^128+x^103+x^76+x^51+x^25+x+1 */
-/* Alt: 70 x^128+x^103+x^78+x^51+x^27+x^2+1 */
-#define TAP1	103
-#define TAP2	76
-#define TAP3	51
-#define TAP4	25
-#define TAP5	1
-#elif POOLWORDS == 64	/* 15 x^64+x^52+x^39+x^26+x^14+x+1 */
-#define TAP1	52
-#define TAP2	39
-#define TAP3	26
-#define TAP4	14
-#define TAP5	1
-#elif POOLWORDS == 32	/* 15 x^32+x^26+x^20+x^14+x^7+x^1+1 */
-#define TAP1	26
-#define TAP2	20
-#define TAP3	14
-#define TAP4	7
-#define TAP5	1
-#elif POOLWORDS & (POOLWORDS-1)
-#error POOLWORDS must be a power of 2
-#else
-#error No primitive polynomial available for chosen POOLWORDS
+#define DEFAULT_POOL_SIZE 512
+#define SECONDARY_POOL_SIZE 128
+#define BATCH_ENTROPY_SIZE 256
+#define USE_SHA
+
+/*
+ * The minimum number of bits of entropy before we wake up a read on
+ * /dev/random.  Should always be at least 8, or at least 1 byte.
+ */
+static int random_read_wakeup_thresh = 8;
+
+/*
+ * If the entropy count falls under this number of bits, then we
+ * should wake up processes which are selecting or polling on write
+ * access to /dev/random.
+ */
+static int random_write_wakeup_thresh = 128;
+
+/*
+ * A pool of size POOLWORDS is stirred with a primitive polynomial
+ * of degree POOLWORDS over GF(2).  The taps for various sizes are
+ * defined below.  They are chosen to be evenly spaced (minimum RMS
+ * distance from evenly spaced; the numbers in the comments are a
+ * scaled squared error sum) except for the last tap, which is 1 to
+ * get the twisting happening as fast as possible.
+ */
+static struct poolinfo {
+	int	poolwords;
+	int	tap1, tap2, tap3, tap4, tap5;
+} poolinfo_table[] = {
+	/* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1  -- 115 */
+	{ 2048,	1638,	1231,	819, 	411,	1 },
+
+	/* x^1024 + x^817 + x^615 + x^412 + x^204 + x + 1 -- 290 */
+	{ 1024,	817, 	615,	412,	204,	1 },
+
+#if 0				/* Alternate polynomial */
+	/* x^1024 + x^819 + x^616 + x^410 + x^207 + x^2 + 1 -- 115 */
+	{ 1024,	819,	616,	410,	207,	2 },
+#endif
+	
+	/* x^512 + x^411 + x^308 + x^208 + x^104 + x + 1 -- 225 */
+	{ 512,	411,	308,	208,	104,	1 },
+
+#if 0				/* Alternates */
+	/* x^512 + x^409 + x^307 + x^206 + x^102 + x^2 + 1 -- 95 */
+	{ 512,	409,	307,	206,	102,	2 },
+	/* x^512 + x^409 + x^309 + x^205 + x^103 + x^2 + 1 -- 95 */
+	{ 512,	409,	309,	205,	103,	2 },
+#endif
+
+	/* x^256 + x^205 + x^155 + x^101 + x^52 + x + 1 -- 125 */
+	{ 256,	205,	155,	101,	52,	1 },
+	
+	/* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
+	{ 128,	103,	76,	51,	25,	1 },
+
+#if 0	/* Alternate polynomial */
+	/* x^128 + x^103 + x^78 + x^51 + x^27 + x^2 + 1 -- 70 */
+	{ 128,	103,	78,	51,	27,	2 },
 #endif
 
+	/* x^64 + x^52 + x^39 + x^26 + x^14 + x + 1 -- 15 */
+	{ 64,	52,	39,	26,	14,	1 },
+
+	/* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */
+	{ 32,	26,	20,	14,	7,	1 },
+
+	{ 0, 	0,	0,	0,	0,	0 },
+};		
+	
 /*
  * For the purposes of better mixing, we use the CRC-32 polynomial as
  * well to make a twisted Generalized Feedback Shift Reigster
@@ -332,25 +333,26 @@
  * II.  ACM Transactions on Mdeling and Computer Simulation 4:254-266)
  *
  * Thanks to Colin Plumb for suggesting this.
+ * 
  * We have not analyzed the resultant polynomial to prove it primitive;
  * in fact it almost certainly isn't.  Nonetheless, the irreducible factors
  * of a random large-degree polynomial over GF(2) are more than large enough
  * that periodicity is not a concern.
- *
- * The input hash is much less sensitive than the output hash.  All that
- * we want of it is that it be a good non-cryptographic hash; i.e. it
- * not produce collisions when fed "random" data of the sort we expect
- * to see.  As long as the pool state differs for different inputs, we
- * have preserved the input entropy and done a good job.  The fact that an
- * intelligent attacker can construct inputs that will produce controlled
- * alterations to the pool's state is not important because we don't
- * consider such inputs to contribute any randomness.
- * The only property we need with respect to them is
- * that the attacker can't increase his/her knowledge of the pool's state.
+ * 
+ * The input hash is much less sensitive than the output hash.  All
+ * that we want of it is that it be a good non-cryptographic hash;
+ * i.e. it not produce collisions when fed "random" data of the sort
+ * we expect to see.  As long as the pool state differs for different
+ * inputs, we have preserved the input entropy and done a good job.
+ * The fact that an intelligent attacker can construct inputs that
+ * will produce controlled alterations to the pool's state is not
+ * important because we don't consider such inputs to contribute any
+ * randomness.  The only property we need with respect to them is that
+ * the attacker can't increase his/her knowledge of the pool's state.
  * Since all additions are reversible (knowing the final state and the
  * input, you can reconstruct the initial state), if an attacker has
- * any uncertainty about the initial state, he/she can only shuffle that
- * uncertainty about, but never cause any collisions (which would
+ * any uncertainty about the initial state, he/she can only shuffle
+ * that uncertainty about, but never cause any collisions (which would
  * decrease the uncertainty).
  *
  * The chosen system lets the state of the pool be (essentially) the input
@@ -365,82 +367,36 @@
  */
 
 /*
- * The minimum number of bits to release a "wait on input".  Should
- * probably always be 8, since a /dev/random read can return a single
- * byte.
- */
-#define WAIT_INPUT_BITS 8
-/* 
- * The limit number of bits under which to release a "wait on
- * output".  Should probably always be the same as WAIT_INPUT_BITS, so
- * that an output wait releases when and only when a wait on input
- * would block.
- */
-#define WAIT_OUTPUT_BITS WAIT_INPUT_BITS
-
-/* There is actually only one of these, globally. */
-struct random_bucket {
-	unsigned add_ptr;
-	unsigned entropy_count;
-#ifdef ROTATE_PARANOIA	
-	int input_rotate;
+ * Linux 2.2 compatibility
+ */
+#ifndef DECLARE_WAITQUEUE
+#define DECLARE_WAITQUEUE(WAIT, PTR)	struct wait_queue WAIT = { PTR, NULL }
 #endif
-	__u32 pool[POOLWORDS];
-};
-
-#ifdef RANDOM_BENCHMARK
-/* For benchmarking only */
-struct random_benchmark {
-	unsigned long long 	start_time;
-	int			times;		/* # of samples */
-	unsigned long		min;
-	unsigned long		max;
-	unsigned long		accum;		/* accumulator for average */
-	const char		*descr;
-	int			unit;
-	unsigned long		flags;
-};
-
-#define BENCHMARK_INTERVAL 500
-
-static void initialize_benchmark(struct random_benchmark *bench,
-				 const char *descr, int unit);
-static void begin_benchmark(struct random_benchmark *bench);
-static void end_benchmark(struct random_benchmark *bench);
-
-struct random_benchmark timer_benchmark;
+#ifndef DECLARE_WAIT_QUEUE_HEAD
+#define DECLARE_WAIT_QUEUE_HEAD(WAIT) struct wait_queue *WAIT
 #endif
 
-/* There is one of these per entropy source */
-struct timer_rand_state {
-	__u32		last_time;
-	__s32		last_delta,last_delta2;
-	int		dont_count_entropy:1;
-};
-
-static struct random_bucket random_state;
-static struct timer_rand_state keyboard_timer_state;
-static struct timer_rand_state mouse_timer_state;
-static struct timer_rand_state extract_timer_state;
-static struct timer_rand_state *irq_timer_state[NR_IRQS];
-static struct timer_rand_state *blkdev_timer_state[MAX_BLKDEV];
+/*
+ * Static global variables
+ */
+static struct entropy_store *random_state; /* The default global store */
+static struct entropy_store *sec_random_state; /* secondary store */
 static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
 static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
 
-static ssize_t random_read(struct file * file, char * buf,
-			   size_t nbytes, loff_t *ppos);
-static ssize_t random_read_unlimited(struct file * file, char * buf,
-				     size_t nbytes, loff_t *ppos);
-static unsigned int random_poll(struct file *file, poll_table * wait);
-static ssize_t random_write(struct file * file, const char * buffer,
-			    size_t count, loff_t *ppos);
-static int random_ioctl(struct inode * inode, struct file * file,
-			unsigned int cmd, unsigned long arg);
-
-static inline void fast_add_entropy_words(struct random_bucket *r,
-					 __u32 x, __u32 y);
+/*
+ * Forward procedure declarations
+ */
+#ifdef CONFIG_SYSCTL
+static void sysctl_init_random(struct entropy_store *random_state);
+#endif
 
-static void add_entropy_words(struct random_bucket *r, __u32 x, __u32 y);
+/*****************************************************************
+ *
+ * Utility functions, with some ASM defined functions for speed
+ * purposes
+ * 
+ *****************************************************************/
 
 #ifndef MIN
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
@@ -504,185 +460,236 @@
 }
 #endif
 
-	
-/*
- * Initialize the random pool with standard stuff.
+/**********************************************************************
  *
- * NOTE: This is an OS-dependent function.
+ * OS independent entropy store.   Here are the functions which handle
+ * storing entropy in an entropy pool.
+ * 
+ **********************************************************************/
+
+struct entropy_store {
+	unsigned	add_ptr;
+	int		entropy_count;
+	int		input_rotate;
+	int		extract_count;
+	struct poolinfo poolinfo;
+	__u32		*pool;
+};
+
+/*
+ * Initialize the entropy store.  The input argument is the size of
+ * the random pool.
+ * 
+ * Returns an negative error if there is a problem.
  */
-static void init_std_data(struct random_bucket *r)
+static int create_entropy_store(int size, struct entropy_store **ret_bucket)
 {
-	__u32 words[2], *p;
-	int i;
-	struct timeval 	tv;
+	struct	entropy_store	*r;
+	struct	poolinfo	*p;
+	int	poolwords;
 
-	do_gettimeofday(&tv);
-	add_entropy_words(r, tv.tv_sec, tv.tv_usec);
+	poolwords = (size + 3) / 4; /* Convert bytes->words */
+	/* The pool size must be a multiple of 16 32-bit words */
+	poolwords = ((poolwords + 15) / 16) * 16; 
 
-	/*
-	 *	This doesnt lock system.utsname. Howeve we are generating
-	 *	entropy so a race with a name set here is fine.
-	 */
-	p = (__u32 *)&system_utsname;
-	for (i = sizeof(system_utsname) / sizeof(words); i; i--) {
-		memcpy(words, p, sizeof(words));
-		add_entropy_words(r, words[0], words[1]);
-		p += sizeof(words)/sizeof(*words);
+	for (p = poolinfo_table; p->poolwords; p++) {
+		if (poolwords == p->poolwords)
+			break;
 	}
-	
+	if (p->poolwords == 0)
+		return -EINVAL;
+
+	r = kmalloc(sizeof(struct entropy_store), GFP_KERNEL);
+	if (!r)
+		return -ENOMEM;
+
+	memset (r, 0, sizeof(struct entropy_store));
+	r->poolinfo = *p;
+
+	r->pool = kmalloc(poolwords*4, GFP_KERNEL);
+	if (!r->pool) {
+		kfree_s(r, sizeof(struct entropy_store));
+		return -ENOMEM;
+	}
+	memset(r->pool, 0, poolwords*4);
+	*ret_bucket = r;
+	return 0;
 }
 
 /* Clear the entropy pool and associated counters. */
-static void rand_clear_pool(void)
+static void clear_entropy_store(struct entropy_store *r)
 {
-	memset(&random_state, 0, sizeof(random_state));
-	init_std_data(&random_state);
+	r->add_ptr = 0;
+	r->entropy_count = 0;
+	r->input_rotate = 0;
+	r->extract_count = 0;
+	memset(r->pool, 0, r->poolinfo.poolwords*4);
 }
 
-void __init rand_initialize(void)
+static void free_entropy_store(struct entropy_store *r)
 {
-	int i;
-
-	rand_clear_pool();
-	for (i = 0; i < NR_IRQS; i++)
-		irq_timer_state[i] = NULL;
-	for (i = 0; i < MAX_BLKDEV; i++)
-		blkdev_timer_state[i] = NULL;
-	memset(&keyboard_timer_state, 0, sizeof(struct timer_rand_state));
-	memset(&mouse_timer_state, 0, sizeof(struct timer_rand_state));
-	memset(&extract_timer_state, 0, sizeof(struct timer_rand_state));
-#ifdef RANDOM_BENCHMARK
-	initialize_benchmark(&timer_benchmark, "timer", 0);
-#endif
-	extract_timer_state.dont_count_entropy = 1;
+	if (r->pool)
+		kfree(r->pool);
+	kfree_s(r, sizeof(struct entropy_store));
 }
 
-void rand_initialize_irq(int irq)
+/*
+ * This function adds a byte into the entropy "pool".  It does not
+ * update the entropy estimate.  The caller should call
+ * credit_entropy_store if this is appropriate.
+ * 
+ * The pool is stirred with a primitive polynomial of the appropriate
+ * degree, and then twisted.  We twist by three bits at a time because
+ * it's cheap to do so and helps slightly in the expected case where
+ * the entropy is concentrated in the low-order bits.
+ */
+static void add_entropy_words(struct entropy_store *r, const __u32 *in,
+			     int num)
 {
-	struct timer_rand_state *state;
-	
-	if (irq >= NR_IRQS || irq_timer_state[irq])
-		return;
-
-	/*
-	 * If kmalloc returns null, we just won't use that entropy
-	 * source.
-	 */
-	state = kmalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
-	if (state) {
-		irq_timer_state[irq] = state;
-		memset(state, 0, sizeof(struct timer_rand_state));
+	static __u32 const twist_table[8] = {
+		         0, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+		0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+	unsigned i;
+	int new_rotate;
+	__u32 w;
+
+	while (num--) {
+		w = rotate_left(r->input_rotate, *in);
+		i = r->add_ptr = (r->add_ptr - 1) & (r->poolinfo.poolwords-1);
+		/*
+		 * Normally, we add 7 bits of rotation to the pool.
+		 * At the beginning of the pool, add an extra 7 bits
+		 * rotation, so that successive passes spread the
+		 * input bits across the pool evenly.
+		 */
+		new_rotate = r->input_rotate + 14;
+		if (i)
+			new_rotate = r->input_rotate + 7;
+		r->input_rotate = new_rotate & 31;
+
+		/* XOR in the various taps */
+		w ^= r->pool[(i+r->poolinfo.tap1)&(r->poolinfo.poolwords-1)];
+		w ^= r->pool[(i+r->poolinfo.tap2)&(r->poolinfo.poolwords-1)];
+		w ^= r->pool[(i+r->poolinfo.tap3)&(r->poolinfo.poolwords-1)];
+		w ^= r->pool[(i+r->poolinfo.tap4)&(r->poolinfo.poolwords-1)];
+		w ^= r->pool[(i+r->poolinfo.tap5)&(r->poolinfo.poolwords-1)];
+		w ^= r->pool[i];
+		r->pool[i] = (w >> 3) ^ twist_table[w & 7];
 	}
 }
 
-void rand_initialize_blkdev(int major, int mode)
+/*
+ * Credit (or debit) the entropy store with n bits of entropy
+ */
+static void credit_entropy_store(struct entropy_store *r, int num)
 {
-	struct timer_rand_state *state;
-	
-	if (major >= MAX_BLKDEV || blkdev_timer_state[major])
-		return;
+	int	max_entropy = r->poolinfo.poolwords*32;
 
-	/*
-	 * If kmalloc returns null, we just won't use that entropy
-	 * source.
-	 */
-	state = kmalloc(sizeof(struct timer_rand_state), mode);
-	if (state) {
-		blkdev_timer_state[major] = state;
-		memset(state, 0, sizeof(struct timer_rand_state));
-	}
+	if (r->entropy_count + num < 0)
+		r->entropy_count = 0;
+	else if (r->entropy_count + num > max_entropy)
+		r->entropy_count = max_entropy;
+	else
+		r->entropy_count = r->entropy_count + num;
 }
 
-/*
- * This function adds a byte into the entropy "pool".  It does not
- * update the entropy estimate.  The caller must do this if appropriate.
+/**********************************************************************
  *
- * This function is tuned for speed above most other considerations.
+ * Entropy batch input management
  *
- * The pool is stirred with a primitive polynomial of the appropriate degree,
- * and then twisted.  We twist by three bits at a time because it's
- * cheap to do so and helps slightly in the expected case where the
- * entropy is concentrated in the low-order bits.
- */
-#define MASK(x) ((x) & (POOLWORDS-1))	/* Convenient abreviation */
-static inline void fast_add_entropy_words(struct random_bucket *r,
-					 __u32 x, __u32 y)
-{
-	static __u32 const twist_table[8] = {
-		         0, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
-		0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
-	unsigned i, j;
+ * We batch entropy to be added to avoid increasing interrupt latency
+ *
+ **********************************************************************/
 
-	i = MASK(r->add_ptr - 2);	/* i is always even */
-	r->add_ptr = i;
+static __u32	*batch_entropy_pool;
+static int	*batch_entropy_credit;
+static int	batch_max;
+static int	batch_head, batch_tail;
+static struct tq_struct	batch_tqueue;
+static void batch_entropy_process(void *private_);
 
-#ifdef ROTATE_PARANOIA
-	j = r->input_rotate + 14;
-	if (i)
-		j -= 7;
-	r->input_rotate = j & 31;
+/* note: the size must be a power of 2 */
+static int batch_entropy_init(int size, struct entropy_store *r)
+{
+	batch_entropy_pool = kmalloc(2*size*sizeof(__u32), GFP_KERNEL);
+	if (!batch_entropy_pool)
+		return -1;
+	batch_entropy_credit =kmalloc(size*sizeof(int), GFP_KERNEL);
+	if (!batch_entropy_credit) {
+		kfree(batch_entropy_pool);
+		return -1;
+	}
+	batch_head = batch_tail = 0;
+	batch_max = size;
+	batch_tqueue.routine = batch_entropy_process;
+	batch_tqueue.data = r;
+	return 0;
+}
 
-	x = rotate_left(r->input_rotate, x);
-	y = rotate_left(r->input_rotate, y);
-#endif
+static void batch_entropy_store(__u32 a, __u32 b, int num)
+{
+	int	new;
 
-	/*
-	 * XOR in the various taps.  Even though logically, we compute
-	 * x and then compute y, we read in y then x order because most
-	 * caches work slightly better with increasing read addresses.
-	 * If a tap is even then we can use the fact that i is even to
-	 * avoid a masking operation.  Every polynomial has at least one
-	 * even tap, so j is always used.
-	 * (Is there a nicer way to arrange this code?)
-	 */
-#if TAP1 & 1
-	y ^= r->pool[MASK(i+TAP1)];	x ^= r->pool[MASK(i+TAP1+1)];
-#else
-	j = MASK(i+TAP1);	y ^= r->pool[j];	x ^= r->pool[j+1];
-#endif
-#if TAP2 & 1
-	y ^= r->pool[MASK(i+TAP2)];	x ^= r->pool[MASK(i+TAP2+1)];
-#else
-	j = MASK(i+TAP2);	y ^= r->pool[j];	x ^= r->pool[j+1];
-#endif
-#if TAP3 & 1
-	y ^= r->pool[MASK(i+TAP3)];	x ^= r->pool[MASK(i+TAP3+1)];
-#else
-	j = MASK(i+TAP3);	y ^= r->pool[j];	x ^= r->pool[j+1];
-#endif
-#if TAP4 & 1
-	y ^= r->pool[MASK(i+TAP4)];	x ^= r->pool[MASK(i+TAP4+1)];
-#else
-	j = MASK(i+TAP4);	y ^= r->pool[j];	x ^= r->pool[j+1];
-#endif
-#if TAP5 == 1
-	/* We need to pretend to write pool[i+1] before computing y */
-	y ^= r->pool[i];
-	x ^= r->pool[i+1];
-	x ^= r->pool[MASK(i+TAP5+1)];
-	y ^= r->pool[i+1] = x = (x >> 3) ^ twist_table[x & 7];
-	r->pool[i] = (y >> 3) ^ twist_table[y & 7];
-#else
-# if TAP5 & 1
-	y ^= r->pool[MASK(i+TAP5)];	x ^= r->pool[MASK(i+TAP5+1)];
-# else
-	j = MASK(i+TAP5);	y ^= r->pool[j];	x ^= r->pool[j+1];
-# endif
-	y ^= r->pool[i];
-	x ^= r->pool[i+1];
-	r->pool[i] = (y >> 3) ^ twist_table[y & 7];
-	r->pool[i+1] = (x >> 3) ^ twist_table[x & 7];
+	if (!batch_max)
+		return;
+	
+	batch_entropy_pool[2*batch_head] = a;
+	batch_entropy_pool[(2*batch_head) + 1] = b;
+	batch_entropy_credit[batch_head] = num;
+
+	new = (batch_head+1) & (batch_max-1);
+	if (new != batch_tail) {
+		queue_task(&batch_tqueue, &tq_timer);
+		batch_head = new;
+	} else {
+#if 0
+		printk(KERN_NOTICE "random: batch entropy buffer full\n");
 #endif
+	}
 }
 
-/*
- * For places where we don't need the inlined version
- */
-static void add_entropy_words(struct random_bucket *r, __u32 x, __u32 y)
+static void batch_entropy_process(void *private_)
 {
-	fast_add_entropy_words(r, x, y);
+	int	num = 0;
+	int	max_entropy;
+	struct entropy_store *r	= (struct entropy_store *) private_, *p;
+	
+	if (!batch_max)
+		return;
+
+	max_entropy = r->poolinfo.poolwords*32;
+	while (batch_head != batch_tail) {
+		add_entropy_words(r, batch_entropy_pool + 2*batch_tail, 2);
+		p = r;
+		if (r->entropy_count > max_entropy && (num & 1))
+			r = sec_random_state;
+		credit_entropy_store(r, batch_entropy_credit[batch_tail]);
+		batch_tail = (batch_tail+1) & (batch_max-1);
+		num++;
+	}
+	if (r->entropy_count >= random_read_wakeup_thresh)
+		wake_up_interruptible(&random_read_wait);
 }
 
+/*********************************************************************
+ *
+ * Entropy input management
+ *
+ *********************************************************************/
+
+/* There is one of these per entropy source */
+struct timer_rand_state {
+	__u32		last_time;
+	__s32		last_delta,last_delta2;
+	int		dont_count_entropy:1;
+};
+
+static struct timer_rand_state keyboard_timer_state;
+static struct timer_rand_state mouse_timer_state;
+static struct timer_rand_state extract_timer_state;
+static struct timer_rand_state *irq_timer_state[NR_IRQS];
+static struct timer_rand_state *blkdev_timer_state[MAX_BLKDEV];
+
 /*
  * This function adds entropy to the entropy "pool" by using timing
  * delays.  It uses the timer_rand_state structure to make an estimate
@@ -695,15 +702,12 @@
  * are used for a high-resolution timer.
  *
  */
-static void add_timer_randomness(struct random_bucket *r,
-				 struct timer_rand_state *state, unsigned num)
+static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
 {
 	__u32		time;
 	__s32		delta, delta2, delta3;
+	int		entropy = 0;
 
-#ifdef RANDOM_BENCHMARK
-	begin_benchmark(&timer_benchmark);
-#endif
 #if defined (__i386__)
 	if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) {
 		__u32 high;
@@ -717,14 +721,12 @@
 	time = jiffies;
 #endif
 
-	fast_add_entropy_words(r, (__u32)num, time);
-	
 	/*
 	 * Calculate number of bits of randomness we probably added.
 	 * We take into account the first, second and third-order deltas
 	 * in order to make our estimate.
 	 */
-	if ((r->entropy_count < POOLBITS) && !state->dont_count_entropy) {
+	if (!state->dont_count_entropy) {
 		delta = time - state->last_time;
 		state->last_time = time;
 
@@ -753,30 +755,19 @@
 		delta >>= 1;
 		delta &= (1 << 12) - 1;
 
-		r->entropy_count += int_ln_12bits(delta);
-
-		/* Prevent overflow */
-		if (r->entropy_count > POOLBITS)
-			r->entropy_count = POOLBITS;
-
-		/* Wake up waiting processes, if we have enough entropy. */
-		if (r->entropy_count >= WAIT_INPUT_BITS)
-			wake_up_interruptible(&random_read_wait);
+		entropy = int_ln_12bits(delta);
 	}
-		
-#ifdef RANDOM_BENCHMARK
-	end_benchmark(&timer_benchmark);
-#endif
+	batch_entropy_store(num, time, entropy);
 }
 
 void add_keyboard_randomness(unsigned char scancode)
 {
-	add_timer_randomness(&random_state, &keyboard_timer_state, scancode);
+	add_timer_randomness(&keyboard_timer_state, scancode);
 }
 
 void add_mouse_randomness(__u32 mouse_data)
 {
-	add_timer_randomness(&random_state, &mouse_timer_state, mouse_data);
+	add_timer_randomness(&mouse_timer_state, mouse_data);
 }
 
 void add_interrupt_randomness(int irq)
@@ -784,7 +775,7 @@
 	if (irq >= NR_IRQS || irq_timer_state[irq] == 0)
 		return;
 
-	add_timer_randomness(&random_state, irq_timer_state[irq], 0x100+irq);
+	add_timer_randomness(irq_timer_state[irq], 0x100+irq);
 }
 
 void add_blkdev_randomness(int major)
@@ -798,10 +789,15 @@
 			return;
 	}
 		
-	add_timer_randomness(&random_state, blkdev_timer_state[major],
-			     0x200+major);
+	add_timer_randomness(blkdev_timer_state[major], 0x200+major);
 }
 
+/******************************************************************
+ *
+ * Hash function definition
+ *
+ *******************************************************************/
+
 /*
  * This chunk of code defines a function
  * void HASH_TRANSFORM(__u32 digest[HASH_BUFFER_SIZE + HASH_EXTRA_SIZE],
@@ -821,12 +817,11 @@
  * 3) 0x98badcfe
  * 4) 0x10325476
  * 5) 0xc3d2e1f0 (SHA only)
- *
+ * 
  * For /dev/random purposes, the length of the data being hashed is
- * fixed in length (at POOLWORDS words), so appending a bit count in
- * the usual way is not cryptographically necessary.
+ * fixed in length, so appending a bit count in the usual way is not
+ * cryptographically necessary.
  */
-#define USE_SHA
 
 #ifdef USE_SHA
 
@@ -1074,9 +1069,6 @@
 /*
  * MD5 transform algorithm, taken from code written by Colin Plumb,
  * and put into the public domain
- *
- * QUESTION: Replace this with SHA, which as generally received better
- * reviews from the cryptographic community?
  */
 
 /* The four core functions - F1 is optimized somewhat */
@@ -1187,39 +1179,94 @@
 
 #endif /* !USE_SHA */
 
+/*********************************************************************
+ *
+ * Entropy extraction routines
+ *
+ *********************************************************************/
+
+#define EXTRACT_ENTROPY_USER		1
+#define EXTRACT_ENTROPY_SECONDARY	2
+#define TMP_BUF_SIZE			(HASH_BUFFER_SIZE + HASH_EXTRA_SIZE)
+#define SEC_XFER_SIZE			(TMP_BUF_SIZE*4)
+
+static ssize_t extract_entropy(struct entropy_store *r, void * buf,
+			       size_t nbytes, int flags);
+
+/*
+ * This utility inline function is responsible for transfering entropy
+ * from the primary pool to the secondary extraction pool.  We pull 
+ * randomness under two conditions; one is if there isn't enough entropy 
+ * in the secondary pool.  The other is after we have extract 1024 bytes,
+ * at which point we do a "catastrophic reseeding".
+ */
+static inline void xfer_secondary_pool(struct entropy_store *r,
+				       size_t nbytes)
+{
+	__u32	tmp[TMP_BUF_SIZE];
+
+	if (r->entropy_count < nbytes*8) {
+		extract_entropy(random_state, tmp, sizeof(tmp), 0);
+		add_entropy_words(r, tmp, TMP_BUF_SIZE);
+		credit_entropy_store(r, TMP_BUF_SIZE*8);
+	}
+	if (r->extract_count > 1024) {
+		extract_entropy(random_state, tmp, sizeof(tmp), 0);
+		add_entropy_words(r, tmp, TMP_BUF_SIZE);
+		r->extract_count = 0;
+	}
+}
 
-#if POOLWORDS % 16 != 0
-#error extract_entropy() assumes that POOLWORDS is a multiple of 16 words.
-#endif
 /*
  * This function extracts randomness from the "entropy pool", and
  * returns it in a buffer.  This function computes how many remaining
  * bits of entropy are left in the pool, but it does not restrict the
- * number of bytes that are actually obtained.
+ * number of bytes that are actually obtained.  If the EXTRACT_ENTROPY_USER
+ * flag is given, then the buf pointer is assumed to be in user space.
+ * If the EXTRACT_ENTROPY_SECONDARY flag is given, then this function will 
+ *
+ * Note: extract_entropy() assumes that POOLWORDS is a multiple of 16 words.
  */
-static ssize_t extract_entropy(struct random_bucket *r, char * buf,
-			       size_t nbytes, int to_user)
+static ssize_t extract_entropy(struct entropy_store *r, void * buf,
+			       size_t nbytes, int flags)
 {
 	ssize_t ret, i;
-	__u32 tmp[HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];
+	__u32 tmp[TMP_BUF_SIZE];
 	__u32 x;
 
-	add_timer_randomness(r, &extract_timer_state, nbytes);
+	add_timer_randomness(&extract_timer_state, nbytes);
 	
 	/* Redundant, but just in case... */
-	if (r->entropy_count > POOLBITS) 
-		r->entropy_count = POOLBITS;
+	if (r->entropy_count > r->poolinfo.poolwords) 
+		r->entropy_count = r->poolinfo.poolwords;
+
+	if (flags & EXTRACT_ENTROPY_SECONDARY)
+		xfer_secondary_pool(r, nbytes);
 
-	ret = nbytes;
 	if (r->entropy_count / 8 >= nbytes)
 		r->entropy_count -= nbytes*8;
 	else
 		r->entropy_count = 0;
 
-	if (r->entropy_count < WAIT_OUTPUT_BITS)
+	if (r->entropy_count < random_write_wakeup_thresh)
 		wake_up_interruptible(&random_write_wait);
+
+	r->extract_count += nbytes;
 	
+	ret = 0;
 	while (nbytes) {
+		/*
+		 * Check if we need to break out or reschedule....
+		 */
+		if ((flags & EXTRACT_ENTROPY_USER) && current->need_resched) {
+			if (signal_pending(current)) {
+				if (ret == 0)
+					ret = -ERESTARTSYS;
+				break;
+			}
+			schedule();
+		}
+
 		/* Hash the pool to get the output */
 		tmp[0] = 0x67452301;
 		tmp[1] = 0xefcdab89;
@@ -1228,39 +1275,34 @@
 #ifdef USE_SHA
 		tmp[4] = 0xc3d2e1f0;
 #endif
-		for (i = 0; i < POOLWORDS; i += 16)
-			HASH_TRANSFORM(tmp, r->pool+i);
-
 		/*
-		 * The following code does two separate things that happen
-		 * to both work two words at a time, so are convenient
-		 * to do together.
-		 *
-		 * First, this feeds the output back into the pool so
-		 * that the next call will return different results.
-		 * Any perturbation of the pool's state would do, even
-		 * changing one bit, but this mixes the pool nicely.
-		 *
-		 * Second, this folds the output in half to hide the data
-		 * fed back into the pool from the user and further mask
-		 * any patterns in the hash output.  (The exact folding
-		 * pattern is not important; the one used here is quick.)
+		 * As we hash the pool, we mix intermediate values of
+		 * the hash back into the pool.  This eliminates
+		 * backtracking attacks (where the attacker knows
+		 * the state of the pool plus the current outputs, and
+		 * attempts to find previous ouputs), unless the hash
+		 * function can be inverted.
 		 */
-		for (i = 0; i <  HASH_BUFFER_SIZE/2; i++) {
-			x = tmp[i + (HASH_BUFFER_SIZE+1)/2];
-			add_entropy_words(r, tmp[i], x);
-			tmp[i] ^= x;
+		for (i = 0, x = 0; i < r->poolinfo.poolwords; i += 16, x+=2) {
+			HASH_TRANSFORM(tmp, r->pool+i);
+			add_entropy_words(r, &tmp[x%HASH_BUFFER_SIZE], 1);
 		}
+		
+		/*
+		 * In case the hash function has some recognizable
+		 * output pattern, we fold it in half.
+		 */
+		for (i = 0; i <  HASH_BUFFER_SIZE/2; i++)
+			tmp[i] ^= tmp[i + (HASH_BUFFER_SIZE+1)/2];
 #if HASH_BUFFER_SIZE & 1	/* There's a middle word to deal with */
 		x = tmp[HASH_BUFFER_SIZE/2];
-		add_entropy_words(r, x, (__u32)((unsigned long)buf));
 		x ^= (x >> 16);		/* Fold it in half */
 		((__u16 *)tmp)[HASH_BUFFER_SIZE-1] = (__u16)x;
 #endif
 		
 		/* Copy data to destination buffer */
 		i = MIN(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2);
-		if (to_user) {
+		if (flags & EXTRACT_ENTROPY_USER) {
 			i -= copy_to_user(buf, (__u8 const *)tmp, i);
 			if (!i) {
 				ret = -EFAULT;
@@ -1270,16 +1312,8 @@
 			memcpy(buf, (__u8 const *)tmp, i);
 		nbytes -= i;
 		buf += i;
-		add_timer_randomness(r, &extract_timer_state, nbytes);
-		if (to_user && current->need_resched)
-		{
-			if (signal_pending(current))
-			{
-				ret = -EINTR;
-				break;
-			}
-			schedule();
-		}
+		ret += i;
+		add_timer_randomness(&extract_timer_state, nbytes);
 	}
 
 	/* Wipe data just returned from memory */
@@ -1295,9 +1329,108 @@
  */
 void get_random_bytes(void *buf, int nbytes)
 {
-	extract_entropy(&random_state, (char *) buf, nbytes, 0);
+	extract_entropy(sec_random_state, (char *) buf, nbytes, 
+			EXTRACT_ENTROPY_SECONDARY);
+}
+
+/*********************************************************************
+ *
+ * Functions to interface with Linux
+ *
+ *********************************************************************/
+
+/*
+ * Initialize the random pool with standard stuff.
+ *
+ * NOTE: This is an OS-dependent function.
+ */
+static void init_std_data(struct entropy_store *r)
+{
+	struct timeval 	tv;
+	__u32		words[2];
+	char 		*p;
+	int		i;
+
+	do_gettimeofday(&tv);
+	words[0] = tv.tv_sec;
+	words[1] = tv.tv_usec;
+	add_entropy_words(r, words, 2);
+
+	/*
+	 *	This doesn't lock system.utsname. However, we are generating
+	 *	entropy so a race with a name set here is fine.
+	 */
+	p = (char *) &system_utsname;
+	for (i = sizeof(system_utsname) / sizeof(words); i; i--) {
+		memcpy(words, p, sizeof(words));
+		add_entropy_words(r, words, sizeof(words)/4);
+		p += sizeof(words);
+	}
+}
+
+void __init rand_initialize(void)
+{
+	int i;
+
+	if (create_entropy_store(DEFAULT_POOL_SIZE, &random_state))
+		return;		/* Error, return */
+	if (batch_entropy_init(BATCH_ENTROPY_SIZE, random_state))
+		return;		/* Error, return */
+	if (create_entropy_store(SECONDARY_POOL_SIZE, &sec_random_state))
+		return;		/* Error, return */
+	clear_entropy_store(random_state);
+	clear_entropy_store(sec_random_state);
+	init_std_data(random_state);
+#ifdef CONFIG_SYSCTL
+	sysctl_init_random(random_state);
+#endif
+	for (i = 0; i < NR_IRQS; i++)
+		irq_timer_state[i] = NULL;
+	for (i = 0; i < MAX_BLKDEV; i++)
+		blkdev_timer_state[i] = NULL;
+	memset(&keyboard_timer_state, 0, sizeof(struct timer_rand_state));
+	memset(&mouse_timer_state, 0, sizeof(struct timer_rand_state));
+	memset(&extract_timer_state, 0, sizeof(struct timer_rand_state));
+	extract_timer_state.dont_count_entropy = 1;
+}
+
+void rand_initialize_irq(int irq)
+{
+	struct timer_rand_state *state;
+	
+	if (irq >= NR_IRQS || irq_timer_state[irq])
+		return;
+
+	/*
+	 * If kmalloc returns null, we just won't use that entropy
+	 * source.
+	 */
+	state = kmalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
+	if (state) {
+		memset(state, 0, sizeof(struct timer_rand_state));
+		irq_timer_state[irq] = state;
+	}
+}
+
+void rand_initialize_blkdev(int major, int mode)
+{
+	struct timer_rand_state *state;
+	
+	if (major >= MAX_BLKDEV || blkdev_timer_state[major])
+		return;
+
+	/*
+	 * If kmalloc returns null, we just won't use that entropy
+	 * source.
+	 */
+	state = kmalloc(sizeof(struct timer_rand_state), mode);
+	if (state) {
+		memset(state, 0, sizeof(struct timer_rand_state));
+		blkdev_timer_state[major] = state;
+	}
 }
 
+
 static ssize_t
 random_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
 {
@@ -1309,11 +1442,13 @@
 
 	add_wait_queue(&random_read_wait, &wait);
 	while (nbytes > 0) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		
 		n = nbytes;
-		if (n > random_state.entropy_count / 8)
-			n = random_state.entropy_count / 8;
+		if (n > SEC_XFER_SIZE)
+			n = SEC_XFER_SIZE;
+		if (n > random_state->entropy_count / 8)
+			n = random_state->entropy_count / 8;
 		if (n == 0) {
 			if (file->f_flags & O_NONBLOCK) {
 				retval = -EAGAIN;
@@ -1326,7 +1461,9 @@
 			schedule();
 			continue;
 		}
-		n = extract_entropy(&random_state, buf, n, 1);
+		n = extract_entropy(sec_random_state, buf, n,
+				    EXTRACT_ENTROPY_USER |
+				    EXTRACT_ENTROPY_SECONDARY);
 		if (n < 0) {
 			retval = n;
 			break;
@@ -1351,10 +1488,12 @@
 }
 
 static ssize_t
-random_read_unlimited(struct file * file, char * buf,
+urandom_read(struct file * file, char * buf,
 		      size_t nbytes, loff_t *ppos)
 {
-	return extract_entropy(&random_state, buf, nbytes, 1);
+	return extract_entropy(sec_random_state, buf, nbytes,
+			       EXTRACT_ENTROPY_USER |
+			       EXTRACT_ENTROPY_SECONDARY);
 }
 
 static unsigned int
@@ -1365,9 +1504,9 @@
 	poll_wait(file, &random_read_wait, wait);
 	poll_wait(file, &random_write_wait, wait);
 	mask = 0;
-	if (random_state.entropy_count >= WAIT_INPUT_BITS)
+	if (random_state->entropy_count >= random_read_wakeup_thresh)
 		mask |= POLLIN | POLLRDNORM;
-	if (random_state.entropy_count < WAIT_OUTPUT_BITS)
+	if (random_state->entropy_count < random_write_wakeup_thresh)
 		mask |= POLLOUT | POLLWRNORM;
 	return mask;
 }
@@ -1378,7 +1517,6 @@
 {
 	int		ret = 0;
 	size_t		bytes;
-	unsigned	i;
 	__u32 		buf[16];
 	const char 	*p = buffer;
 	size_t		c = count;
@@ -1393,11 +1531,10 @@
 		}
 		c -= bytes;
 		p += bytes;
-		
-		i = (unsigned)((bytes-1) / (2 * sizeof(__u32)));
-		do {
-			add_entropy_words(&random_state, buf[2*i], buf[2*i+1]);
-		} while (i--);
+
+		/* Convert bytes to words */
+		bytes = (bytes + 3) / sizeof(__u32);
+		add_entropy_words(random_state, buf, bytes);
 	}
 	if (p == buffer) {
 		return (ssize_t)ret;
@@ -1417,7 +1554,7 @@
 	
 	switch (cmd) {
 	case RNDGETENTCNT:
-		ent_count = random_state.entropy_count;
+		ent_count = random_state->entropy_count;
 		if (put_user(ent_count, (int *) arg))
 			return -EFAULT;
 		return 0;
@@ -1426,45 +1563,31 @@
 			return -EPERM;
 		if (get_user(ent_count, (int *) arg))
 			return -EFAULT;
-		/*
-		 * Add i to entropy_count, limiting the result to be
-		 * between 0 and POOLBITS.
-		 */
-		if (ent_count < -random_state.entropy_count)
-			random_state.entropy_count = 0;
-		else if (ent_count > POOLBITS)
-			random_state.entropy_count = POOLBITS;
-		else {
-			random_state.entropy_count += ent_count;
-			if (random_state.entropy_count > POOLBITS)
-				random_state.entropy_count = POOLBITS;
-			if (random_state.entropy_count < 0)
-				random_state.entropy_count = 0;
-		}
+		credit_entropy_store(random_state, ent_count);
 		/*
 		 * Wake up waiting processes if we have enough
 		 * entropy.
 		 */
-		if (random_state.entropy_count >= WAIT_INPUT_BITS)
+		if (random_state->entropy_count >= random_read_wakeup_thresh)
 			wake_up_interruptible(&random_read_wait);
 		return 0;
 	case RNDGETPOOL:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		p = (int *) arg;
-		ent_count = random_state.entropy_count;
+		ent_count = random_state->entropy_count;
 		if (put_user(ent_count, p++))
 			return -EFAULT;
 			
 		if (get_user(size, p))
 			return -EFAULT;
-		if (put_user(POOLWORDS, p++))
+		if (put_user(random_state->poolinfo.poolwords, p++))
 			return -EFAULT;
 		if (size < 0)
 			return -EINVAL;
-		if (size > POOLWORDS)
-			size = POOLWORDS;
-		if (copy_to_user(p, random_state.pool, size*sizeof(__u32)))
+		if (size > random_state->poolinfo.poolwords)
+			size = random_state->poolinfo.poolwords;
+		if (copy_to_user(p, random_state->pool, size*sizeof(__u32)))
 			return -EFAULT;
 		return 0;
 	case RNDADDENTROPY:
@@ -1481,36 +1604,25 @@
 				      size, &file->f_pos);
 		if (retval < 0)
 			return retval;
-		/*
-		 * Add ent_count to entropy_count, limiting the result to be
-		 * between 0 and POOLBITS.
-		 */
-		if (ent_count > POOLBITS)
-			random_state.entropy_count = POOLBITS;
-		else {
-			random_state.entropy_count += ent_count;
-			if (random_state.entropy_count > POOLBITS)
-				random_state.entropy_count = POOLBITS;
-			if (random_state.entropy_count < 0)
-				random_state.entropy_count = 0;
-		}
+		credit_entropy_store(random_state, ent_count);
 		/*
 		 * Wake up waiting processes if we have enough
 		 * entropy.
 		 */
-		if (random_state.entropy_count >= WAIT_INPUT_BITS)
+		if (random_state->entropy_count >= random_read_wakeup_thresh)
 			wake_up_interruptible(&random_read_wait);
 		return 0;
 	case RNDZAPENTCNT:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		random_state.entropy_count = 0;
+		random_state->entropy_count = 0;
 		return 0;
 	case RNDCLEARPOOL:
 		/* Clear the entropy pool and associated counters. */
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		rand_clear_pool();
+		clear_entropy_store(random_state);
+		init_std_data(random_state);
 		return 0;
 	default:
 		return -EINVAL;
@@ -1532,7 +1644,7 @@
 
 struct file_operations urandom_fops = {
 	NULL,		/* unrandom_lseek */
-	random_read_unlimited,
+	urandom_read,
 	random_write,
 	NULL,		/* urandom_readdir */
 	NULL,		/* urandom_poll */
@@ -1543,6 +1655,210 @@
 	NULL		/* no special release code */
 };
 
+/***************************************************************
+ * Random UUID interface
+ * 
+ * Used here for a Boot ID, but can be useful for other kernel 
+ * drivers.
+ ***************************************************************/
+
+/*
+ * Generate random UUID
+ */
+void generate_random_uuid(unsigned char uuid_out[16])
+{
+	get_random_bytes(uuid_out, 16);
+	/* Set UUID version to 4 --- truely random generation */
+	uuid_out[6] = (uuid_out[6] & 0x0F) | 0x40;
+	/* Set the UUID variant to DCE */
+	uuid_out[8] = (uuid_out[8] & 0x3F) | 0x80;
+}
+
+/********************************************************************
+ *
+ * Sysctl interface
+ *
+ ********************************************************************/
+
+#ifdef CONFIG_SYSCTL
+
+#include <linux/sysctl.h>
+
+static int sysctl_poolsize;
+static int min_read_thresh, max_read_thresh;
+static int min_write_thresh, max_write_thresh;
+static char sysctl_bootid[16];
+
+/*
+ * This function handles a request from the user to change the pool size 
+ * of the primary entropy store.
+ */
+static int change_poolsize(int poolsize)
+{
+	struct entropy_store	*new_store, *old_store;
+	int			ret;
+	
+	if ((ret = create_entropy_store(poolsize, &new_store)))
+		return ret;
+
+	add_entropy_words(new_store, random_state->pool,
+			  random_state->poolinfo.poolwords);
+	credit_entropy_store(new_store, random_state->entropy_count);
+
+	sysctl_init_random(new_store);
+	old_store = random_state;
+	random_state = batch_tqueue.data = new_store;
+	free_entropy_store(old_store);
+	return 0;
+}
+
+static int proc_do_poolsize(ctl_table *table, int write, struct file *filp,
+			    void *buffer, size_t *lenp)
+{
+	int	ret;
+
+	sysctl_poolsize = random_state->poolinfo.poolwords * 4;
+
+	ret = proc_dointvec(table, write, filp, buffer, lenp);
+	if (ret || !write ||
+	    (sysctl_poolsize == random_state->poolinfo.poolwords * 4))
+		return ret;
+
+	return change_poolsize(sysctl_poolsize);
+}
+
+static int poolsize_strategy(ctl_table *table, int *name, int nlen,
+			     void *oldval, size_t *oldlenp,
+			     void *newval, size_t newlen, void **context)
+{
+	int	len;
+	
+	sysctl_poolsize = random_state->poolinfo.poolwords * 4;
+
+	/*
+	 * We only handle the write case, since the read case gets
+	 * handled by the default handler (and we don't care if the
+	 * write case happens twice; it's harmless).
+	 */
+	if (newval && newlen) {
+		len = newlen;
+		if (len > table->maxlen)
+			len = table->maxlen;
+		if (copy_from_user(table->data, newval, len))
+			return -EFAULT;
+	}
+
+	if (sysctl_poolsize != random_state->poolinfo.poolwords * 4)
+		return change_poolsize(sysctl_poolsize);
+
+	return 0;
+}
+
+/*
+ * These functions is used to return both the bootid UUID, and random
+ * UUID.  The difference is in whether table->data is NULL; if it is,
+ * then a new UUID is generated and returned to the user.
+ * 
+ * If the user accesses this via the proc interface, it will be returned
+ * as an ASCII string in the standard UUID format.  If accesses via the 
+ * sysctl system call, it is returned as 16 bytes of binary data.
+ */
+static int proc_do_uuid(ctl_table *table, int write, struct file *filp,
+			void *buffer, size_t *lenp)
+{
+	ctl_table	fake_table;
+	unsigned char	buf[64], tmp_uuid[16], *uuid;
+
+	uuid = table->data;
+	if (!uuid) {
+		uuid = tmp_uuid;
+		uuid[8] = 0;
+	}
+	if (uuid[8] == 0)
+		generate_random_uuid(uuid);
+
+	sprintf(buf, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
+		"%02x%02x%02x%02x%02x%02x",
+		uuid[0],  uuid[1],  uuid[2],  uuid[3],
+		uuid[4],  uuid[5],  uuid[6],  uuid[7],
+		uuid[8],  uuid[9],  uuid[10], uuid[11],
+		uuid[12], uuid[13], uuid[14], uuid[15]);
+	fake_table.data = buf;
+	fake_table.maxlen = sizeof(buf);
+
+	return proc_dostring(&fake_table, write, filp, buffer, lenp);
+}
+
+static int uuid_strategy(ctl_table *table, int *name, int nlen,
+			 void *oldval, size_t *oldlenp,
+			 void *newval, size_t newlen, void **context)
+{
+	unsigned char	tmp_uuid[16], *uuid;
+	int	len;
+
+	if (!oldval || !oldlenp)
+		return 1;
+
+	uuid = table->data;
+	if (!uuid) {
+		uuid = tmp_uuid;
+		uuid[8] = 0;
+	}
+	if (uuid[8] == 0)
+		generate_random_uuid(uuid);
+
+	get_user(len, oldlenp);
+	if (len) {
+		if (len > 16)
+			len = 16;
+		if (copy_to_user(oldval, table->data, len))
+			return -EFAULT;
+		if (put_user(len, oldlenp))
+			return -EFAULT;
+	}
+	return 1;
+}
+
+ctl_table random_table[] = {
+	{RANDOM_POOLSIZE, "poolsize",
+	 &sysctl_poolsize, sizeof(int), 0644, NULL,
+	 &proc_do_poolsize, &poolsize_strategy},
+	{RANDOM_ENTROPY_COUNT, "entropy_avail",
+	 NULL, sizeof(int), 0444, NULL,
+	 &proc_dointvec},
+	{RANDOM_READ_THRESH, "read_wakeup_threshold",
+	 &random_read_wakeup_thresh, sizeof(int), 0644, NULL,
+	 &proc_dointvec_minmax, &sysctl_intvec, 0,
+	 &min_read_thresh, &max_read_thresh},
+	{RANDOM_WRITE_THRESH, "write_wakeup_threshold",
+	 &random_write_wakeup_thresh, sizeof(int), 0644, NULL,
+	 &proc_dointvec_minmax, &sysctl_intvec, 0,
+	 &min_write_thresh, &max_write_thresh},
+	{RANDOM_BOOT_ID, "boot_id",
+	 &sysctl_bootid, 16, 0444, NULL,
+	 &proc_do_uuid, &uuid_strategy},
+	{RANDOM_UUID, "uuid",
+	 NULL, 16, 0444, NULL,
+	 &proc_do_uuid, &uuid_strategy},
+	{0}
+};
+
+static void sysctl_init_random(struct entropy_store *random_state)
+{
+	min_read_thresh = 8;
+	min_write_thresh = 0;
+	max_read_thresh = max_write_thresh =
+		random_state->poolinfo.poolwords * 32;
+	random_table[1].data = &random_state->entropy_count;
+}
+#endif 	/* CONFIG_SYSCTL */
+
+/********************************************************************
+ *
+ * Random funtions for networking
+ *
+ ********************************************************************/
+
 /*
  * TCP initial sequence number picking.  This uses the random number
  * generator to pick an initial secret value.  This value is hashed
@@ -1831,71 +2147,3 @@
 	return (cookie - tmp[17]) & COOKIEMASK;	/* Leaving the data behind */
 }
 #endif
-
-
-#ifdef RANDOM_BENCHMARK
-/*
- * This is so we can do some benchmarking of the random driver, to see
- * how much overhead add_timer_randomness really takes.  This only
- * works on a Pentium, since it depends on the timer clock...
- *
- * Note: the results of this benchmark as of this writing (5/27/96)
- *
- * On a Pentium, add_timer_randomness() takes between 150 and 1000
- * clock cycles, with an average of around 600 clock cycles.  On a 75
- * MHz Pentium, this translates to 2 to 13 microseconds, with an
- * average time of 8 microseconds.  This should be fast enough so we
- * can use add_timer_randomness() even with the fastest of interrupts...
- */
-static inline unsigned long long get_clock_cnt(void)
-{
-	unsigned long low, high;
-	__asm__(".byte 0x0f,0x31" :"=a" (low), "=d" (high));
-	return (((unsigned long long) high << 32) | low); 
-}
-
-static void __init 
-initialize_benchmark(struct random_benchmark *bench,
-	             const char *descr, int unit)
-{
-	bench->times = 0;
-	bench->accum = 0;
-	bench->max = 0;
-	bench->min = 1 << 31;
-	bench->descr = descr;
-	bench->unit = unit;
-}
-
-static void begin_benchmark(struct random_benchmark *bench)
-{
-#ifdef BENCHMARK_NOINT
-	save_flags(bench->flags); cli();
-#endif
-	bench->start_time = get_clock_cnt();
-}
-
-static void end_benchmark(struct random_benchmark *bench)
-{
-	unsigned long ticks;
-	
-	ticks = (unsigned long) (get_clock_cnt() - bench->start_time);
-#ifdef BENCHMARK_NOINT
-	restore_flags(bench->flags);
-#endif
-	if (ticks < bench->min)
-		bench->min = ticks;
-	if (ticks > bench->max)
-		bench->max = ticks;
-	bench->accum += ticks;
-	bench->times++;
-	if (bench->times == BENCHMARK_INTERVAL) {
-		printk("Random benchmark: %s %d: %lu min, %lu avg, "
-		       "%lu max\n", bench->descr, bench->unit, bench->min,
-		       bench->accum / BENCHMARK_INTERVAL, bench->max);
-		bench->times = 0;
-		bench->accum = 0;
-		bench->max = 0;
-		bench->min = 1 << 31;
-	}
-}	
-#endif /* RANDOM_BENCHMARK */
diff -u --recursive --new-file v2.3.15/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c
--- v2.3.15/linux/drivers/char/riscom8.c	Thu Aug  5 14:34:01 1999
+++ linux/drivers/char/riscom8.c	Tue Aug 31 11:30:48 1999
@@ -1027,7 +1027,7 @@
 			rc_out(bp, RC_DTR, bp->DTR);
 		}
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(port->flags & ASYNC_INITIALIZED)) {
 			if (port->flags & ASYNC_HUP_NOTIFY)
diff -u --recursive --new-file v2.3.15/linux/drivers/char/rocket.c linux/drivers/char/rocket.c
--- v2.3.15/linux/drivers/char/rocket.c	Thu Aug  5 15:04:52 1999
+++ linux/drivers/char/rocket.c	Tue Aug 31 11:30:48 1999
@@ -88,8 +88,6 @@
 #endif
 #if (LINUX_VERSION_CODE >= 131343) /* 2.1.15 -- XX get correct version */
 #include <linux/init.h>
-#else
-#define __initfunc(x)	x
 #endif
 	
 #include "rocket_int.h"
@@ -890,7 +888,7 @@
 			sSetDTR(&info->channel);
 			sSetRTS(&info->channel);
 		}
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ROCKET_INITIALIZED)) {
 			if (info->flags & ROCKET_HUP_NOTIFY)
diff -u --recursive --new-file v2.3.15/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.3.15/linux/drivers/char/rtc.c	Thu Aug  5 14:34:02 1999
+++ linux/drivers/char/rtc.c	Tue Aug 31 11:25:33 1999
@@ -551,7 +551,7 @@
 	return -EIO;
 
 found:
-	rtc_port = edev->base_address[0];
+	rtc_port = edev->resource[0].start;
 	rtc_irq = edev->irqs[0];
 	/*
 	 * XXX Interrupt pin #7 in Espresso is shared between RTC and
diff -u --recursive --new-file v2.3.15/linux/drivers/char/selection.c linux/drivers/char/selection.c
--- v2.3.15/linux/drivers/char/selection.c	Tue May 11 14:37:40 1999
+++ linux/drivers/char/selection.c	Tue Aug 31 11:30:48 1999
@@ -301,7 +301,7 @@
 	poke_blanked_console();
 	add_wait_queue(&vt->paste_wait, &wait);
 	while (sel_buffer && sel_buffer_lth > pasted) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (test_bit(TTY_THROTTLED, &tty->flags)) {
 			schedule();
 			continue;
diff -u --recursive --new-file v2.3.15/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.3.15/linux/drivers/char/serial.c	Thu Jul  1 15:09:01 1999
+++ linux/drivers/char/serial.c	Tue Aug 31 12:59:27 1999
@@ -2,6 +2,8 @@
  *  linux/drivers/char/serial.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 
+ * 		1998, 1999  Theodore Ts'o
  *
  *  Extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92.  Now
  *  much more extensible to support other serial cards based on the
@@ -32,6 +34,11 @@
  *  4/98: Added changes to support the ARM architecture proposed by
  * 	  Russell King
  *
+ *  5/99: Updated to include support for the XR16C850 and ST16C654
+ *        uarts.  Stuart MacDonald <stuartm@connecttech.com>
+ *
+ *  8/99: Generalized PCI support added.  Theodore Ts'o
+ * 
  * This module exports the following rs232 io functions:
  *
  *	int rs_init(void);
@@ -62,13 +69,16 @@
  * 		ever possible.
  */
 
+#include <linux/config.h>
+#include <linux/version.h>
+
 #undef SERIAL_PARANOIA_CHECK
 #define CONFIG_SERIAL_NOPAUSE_IO
 #define SERIAL_DO_RESTART
+#define CONFIG_SERIAL_PCI_MEMMAPPED
 
 #if 0
-/* Normally these defines are controlled by the autoconf.h */
-
+/* These defines are normally controlled by the autoconf.h */
 #define CONFIG_SERIAL_MANY_PORTS
 #define CONFIG_SERIAL_SHARE_IRQ
 #define CONFIG_SERIAL_DETECT_IRQ
@@ -76,6 +86,19 @@
 #define CONFIG_HUB6
 #endif
 
+#if (defined(CONFIG_PCI) && (LINUX_VERSION_CODE >= 131072))
+#define ENABLE_SERIAL_PCI
+#define CONFIG_SERIAL_SHARE_IRQ
+#endif
+
+/* Set of debugging defines */
+
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+#undef SERIAL_DEBUG_PCI
+
 /* Sanity checks */
 
 #ifdef CONFIG_SERIAL_MULTIPORT
@@ -93,18 +116,11 @@
 #endif
 #endif
 
-/* Set of debugging defines */
-
-#undef SERIAL_DEBUG_INTR
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-
 #define RS_STROBE_TIME (10*HZ)
 #define RS_ISR_PASS_LIMIT 256
 
 #define IRQ_T(state) \
- ((state->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
+	((state->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
 
 #define SERIAL_INLINE
   
@@ -119,8 +135,34 @@
  * End of serial driver configuration section.
  */
 
-#include <linux/config.h>
+#if (LINUX_VERSION_CODE > 66304)
+#define NEW_MODULES
+#ifdef LOCAL_HEADERS		/* We're building standalone */
+#define MODULE
+#endif
+#endif
+
+#ifdef NEW_MODULES
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#else /* !NEW_MODULES */
+#ifdef MODVERSIONS
+#define MODULE
+#endif
 #include <linux/module.h>
+#endif /* NEW_MODULES */
+
+#ifdef LOCAL_HEADERS
+#include "serial_local.h"
+#else
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <asm/serial.h>
+static char *serial_version = "4.30";
+#endif
+
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -128,8 +170,6 @@
 #include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
@@ -137,31 +177,47 @@
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
+#if (LINUX_VERSION_CODE >= 131343) /* 2.1.15 -- XX get correct version */
 #include <linux/init.h>
+#else
+#define __initfunc(x)	x
+#endif
 #include <linux/delay.h>
 #ifdef CONFIG_SERIAL_CONSOLE
 #include <linux/console.h>
 #endif
+#ifdef ENABLE_SERIAL_PCI
+#include <linux/pci.h>
+#endif
 
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
 #include <asm/bitops.h>
-#include <asm/serial.h>
+
+#ifdef CONFIG_MAC_SERIAL
+#define SERIAL_DEV_OFFSET	2
+#else
+#define SERIAL_DEV_OFFSET	0
+#endif
 
 #ifdef SERIAL_INLINE
 #define _INLINE_ inline
 #endif
 	
 static char *serial_name = "Serial driver";
-static char *serial_version = "4.27";
 
 static DECLARE_TASK_QUEUE(tq_serial);
 
 static struct tty_driver serial_driver, callout_driver;
 static int serial_refcount;
 
+/* serial subtype definitions */
+#ifndef SERIAL_TYPE_NORMAL
+#define SERIAL_TYPE_NORMAL	1
+#define SERIAL_TYPE_CALLOUT	2
+#endif
+
 /* number of characters left in xmit buffer before we ask for more */
 #define WAKEUP_CHARS 256
 
@@ -194,20 +250,33 @@
 	{ "16450", 1, 0 }, 
 	{ "16550", 1, 0 }, 
 	{ "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, 
-	{ "cirrus", 1, 0 }, 
-	{ "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, 
+	{ "cirrus", 1, 0 }, 	/* usurped by cyclades.c */
+	{ "ST16650", 1, UART_CLEAR_FIFO |UART_STARTECH }, 
 	{ "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO |
 		  UART_STARTECH }, 
 	{ "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO},
+	{ "Startech", 1, 0},	/* usurped by cyclades.c */
+	{ "16C950", 128, UART_CLEAR_FIFO | UART_USE_FIFO},
+	{ "ST16654", 64, UART_CLEAR_FIFO | UART_USE_FIFO |
+		  UART_STARTECH }, 
+	{ "XR16850", 128, UART_CLEAR_FIFO | UART_USE_FIFO |
+		  UART_STARTECH },
 	{ 0, 0}
 };
 
-static struct serial_state rs_table[] = {
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
 	SERIAL_PORT_DFNS	/* Defined in serial.h */
 };
 
 #define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
 
+#ifdef ENABLE_SERIAL_PCI
+#define NR_PCI_BOARDS	8
+static struct pci_board_inst	serial_pci_board[NR_PCI_BOARDS];
+static int serial_pci_board_idx = 0;
+#define PCI_BASE_ADDRESS(dev, r) ((dev)->resource[r].start)
+#endif	/* ENABLE_SERIAL_PCI  */
+
 static struct tty_struct *serial_table[NR_PORTS];
 static struct termios *serial_termios[NR_PORTS];
 static struct termios *serial_termios_locked[NR_PORTS];
@@ -226,7 +295,93 @@
  * memory if large numbers of serial ports are open.
  */
 static unsigned char *tmp_buf;
+#ifdef DECLARE_MUTEX
 static DECLARE_MUTEX(tmp_buf_sem);
+#else
+static struct semaphore tmp_buf_sem = MUTEX;
+#endif
+
+/*
+ * Provide backwards compatibility for kernels prior to 2.1.XX.
+ */
+#if (LINUX_VERSION_CODE < 0x20000)
+typedef dev_t kdev_t;
+#endif
+
+#if (LINUX_VERSION_CODE < 0x02017E)
+static signed long schedule_timeout(signed long timeout)
+{
+	unsigned long expire;
+
+	expire = timeout + jiffies;
+
+	current->timeout = jiffies + timeout;
+	schedule();
+
+	timeout = expire - jiffies;
+	return timeout < 0 ? 0 : timeout;
+}
+#endif
+
+#ifndef time_after
+#define time_after(a,b)		((long)(b) - (long)(a) < 0)
+#endif
+
+#if (LINUX_VERSION_CODE < 0x020100)
+static inline int irq_cannonicalize(int irq)
+{
+	return ((irq == 2) ? 9 : irq);
+}
+#endif
+
+#if (LINUX_VERSION_CODE < 131336)
+static int copy_from_user(void *to, const void *from_user, unsigned long len)
+{
+	int	error;
+
+	error = verify_area(VERIFY_READ, from_user, len);
+	if (error)
+		return len;
+	memcpy_fromfs(to, from_user, len);
+	return 0;
+}
+
+static int copy_to_user(void *to_user, const void *from, unsigned long len)
+{
+	int	error;
+	
+	error = verify_area(VERIFY_WRITE, to_user, len);
+	if (error)
+		return len;
+	memcpy_tofs(to_user, from, len);
+	return 0;
+}
+
+static inline int signal_pending(struct task_struct *p)
+{
+	return (p->signal & (~p->blocked != 0));
+}
+
+#else
+#include <asm/uaccess.h>
+#endif
+
+#ifdef CAP_SYS_ADMIN
+#define serial_isroot()	(capable(CAP_SYS_ADMIN))
+#else
+#define serial_isroot() (suser())
+#endif
+
+#if (LINUX_VERSION_CODE < 131394) /* 2.1.66 */
+#define test_and_clear_bit(x,y)		clear_bit(x,y)
+
+static inline void remove_bh(int nr)
+{
+	bh_base[nr] = NULL;
+	bh_mask &= ~(1 << nr);
+}
+#endif
+
 
 static inline int serial_paranoia_check(struct async_struct *info,
 					kdev_t device, const char *routine)
@@ -257,6 +412,11 @@
 	return inb(info->port+1);
     } else
 #endif
+#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
+    if (info->iomem_base)
+	return readb(info->iomem_base + (offset<<info->iomem_reg_shift));
+    else
+#endif
 	return inb(info->port + offset);
 }
 
@@ -268,6 +428,11 @@
 	return inb_p(info->port+1);
     } else
 #endif
+#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
+    if (info->iomem_base)
+	return readb(info->iomem_base + (offset<<info->iomem_reg_shift));
+    else
+#endif
 #ifdef CONFIG_SERIAL_NOPAUSE_IO
 	return inb(info->port + offset);
 #else
@@ -283,6 +448,11 @@
 	outb(value, info->port+1);
     } else
 #endif
+#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
+    if (info->iomem_base)
+	writeb(value, info->iomem_base + (offset<<info->iomem_reg_shift));
+    else
+#endif
 	outb(value, info->port+offset);
 }
 
@@ -295,6 +465,11 @@
 	outb_p(value, info->port+1);
     } else
 #endif
+#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
+    if (info->iomem_base)
+	writeb(value, info->iomem_base + (offset<<info->iomem_reg_shift));
+    else
+#endif
 #ifdef CONFIG_SERIAL_NOPAUSE_IO
 	outb(value, info->port+offset);
 #else
@@ -303,6 +478,26 @@
 }
 
 /*
+ * For the 16C950
+ */
+void serial_icr_write(struct async_struct *info, int offset, int  value)
+{
+	serial_out(info, UART_SCR, offset);
+	serial_out(info, UART_ICR, value);
+}
+
+unsigned int serial_icr_read(struct async_struct *info, int offset)
+{
+	int	value;
+
+	serial_icr_write(info, UART_ACR, info->ACR | UART_ACR_ICRRD);
+	serial_out(info, UART_SCR, offset);
+	value = serial_in(info, UART_ICR);
+	serial_icr_write(info, UART_ACR, info->ACR);
+	return value;
+}
+
+/*
  * ------------------------------------------------------------
  * rs_stop() and rs_start()
  *
@@ -323,6 +518,10 @@
 		info->IER &= ~UART_IER_THRI;
 		serial_out(info, UART_IER, info->IER);
 	}
+	if (info->state->type == PORT_16C950) {
+		info->ACR |= UART_ACR_TXDIS;
+		serial_icr_write(info, UART_ACR, info->ACR);
+	}
 	restore_flags(flags);
 }
 
@@ -339,6 +538,10 @@
 		info->IER |= UART_IER_THRI;
 		serial_out(info, UART_IER, info->IER);
 	}
+	if (info->state->type == PORT_16C950) {
+		info->ACR &= ~UART_ACR_TXDIS;
+		serial_icr_write(info, UART_ACR, info->ACR);
+	}
 	restore_flags(flags);
 }
 
@@ -453,7 +656,11 @@
 	ignore_char:
 		*status = serial_inp(info, UART_LSR);
 	} while (*status & UART_LSR_DR);
+#if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */
 	tty_flip_buffer_push(tty);
+#else
+	queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
+#endif	
 }
 
 static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
@@ -932,7 +1139,7 @@
 		goto errout;
 	}
 
-	if (!state->port || !state->type) {
+	if (!CONFIGURED_SERIAL_PORT(state) || !state->type) {
 		if (info->tty)
 			set_bit(TTY_IO_ERROR, &info->tty->flags);
 		free_page(page);
@@ -951,8 +1158,28 @@
 		/* Wake up UART */
 		serial_outp(info, UART_LCR, 0xBF);
 		serial_outp(info, UART_EFR, UART_EFR_ECB);
+		/*
+		 * Turn off LCR == 0xBF so we actually set the IER
+		 * register on the XR16C850
+		 */
+		serial_outp(info, UART_LCR, 0);
 		serial_outp(info, UART_IER, 0);
+		/*
+		 * Now reset LCR so we can turn off the ECB bit
+		 */
+		serial_outp(info, UART_LCR, 0xBF);
 		serial_outp(info, UART_EFR, 0);
+		/*
+		 * For a XR16C850, we need to set the trigger levels
+		 */
+		if (info->state->type == PORT_16850) {
+			serial_outp(info, UART_FCTR, UART_FCTR_TRGD |
+					UART_FCTR_RX);
+			serial_outp(info, UART_TRG, UART_TRG_96);
+			serial_outp(info, UART_FCTR, UART_FCTR_TRGD |
+					UART_FCTR_TX);
+			serial_outp(info, UART_TRG, UART_TRG_96);
+		}
 		serial_outp(info, UART_LCR, 0);
 	}
 
@@ -961,13 +1188,38 @@
 		serial_outp(info, UART_IER, 0);
 	}
 
+	if (info->state->type == PORT_16C950) {
+		/* Wake up and initialize UART */
+		info->ACR = 0;
+		serial_outp(info, UART_LCR, 0xBF);
+		serial_outp(info, UART_EFR, UART_EFR_ECB);
+		serial_outp(info, UART_IER, 0);
+		serial_outp(info, UART_LCR, 0);
+		serial_icr_write(info, UART_CSR, 0); /* Reset the UART */
+		serial_outp(info, UART_LCR, 0xBF);
+		serial_outp(info, UART_EFR, UART_EFR_ECB);
+		serial_outp(info, UART_LCR, 0);
+	}
+
 	/*
 	 * Clear the FIFO buffers and disable them
 	 * (they will be reenabled in change_speed())
 	 */
-	if (uart_config[state->type].flags & UART_CLEAR_FIFO)
-		serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR |
+	if (uart_config[state->type].flags & UART_CLEAR_FIFO) {
+		serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+		serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO |
+					     UART_FCR_CLEAR_RCVR |
 					     UART_FCR_CLEAR_XMIT));
+		serial_outp(info, UART_FCR, 0);
+	}
+
+	/*
+	 * Clear the interrupt registers.
+	 */
+	(void) serial_inp(info, UART_LSR);
+	(void) serial_inp(info, UART_RX);
+	(void) serial_inp(info, UART_IIR);
+	(void) serial_inp(info, UART_MSR);
 
 	/*
 	 * At this point there's no way the LSR could still be 0xFF;
@@ -975,7 +1227,8 @@
 	 * here.
 	 */
 	if (serial_inp(info, UART_LSR) == 0xff) {
-		if (capable(CAP_SYS_ADMIN)) {
+		printk("LSR safety check engaged!\n");
+		if (serial_isroot()) {
 			if (info->tty)
 				set_bit(TTY_IO_ERROR, &info->tty->flags);
 		} else
@@ -1007,7 +1260,7 @@
 		retval = request_irq(state->irq, handler, IRQ_T(state),
 				     "serial", NULL);
 		if (retval) {
-			if (capable(CAP_SYS_ADMIN)) {
+			if (serial_isroot()) {
 				if (info->tty)
 					set_bit(TTY_IO_ERROR,
 						&info->tty->flags);
@@ -1028,14 +1281,6 @@
 	figure_IRQ_timeout(state->irq);
 
 	/*
-	 * Clear the interrupt registers.
-	 */
-     /* (void) serial_inp(info, UART_LSR); */   /* (see above) */
-	(void) serial_inp(info, UART_RX);
-	(void) serial_inp(info, UART_IIR);
-	(void) serial_inp(info, UART_MSR);
-
-	/*
 	 * Now, initialize the UART 
 	 */
 	serial_outp(info, UART_LCR, UART_LCR_WLEN8);	/* reset DLAB */
@@ -1053,12 +1298,7 @@
 		if (state->irq != 0)
 			info->MCR |= UART_MCR_OUT2;
 	}
-#if defined(__alpha__) && !defined(CONFIG_PCI)
-	/*
-	 * DEC did something gratutiously wrong....
-	 */
-	info->MCR |= UART_MCR_OUT1 | UART_MCR_OUT2;
-#endif
+	info->MCR |= ALPHA_KLUDGE_MCR; 		/* Don't ask */
 	serial_outp(info, UART_MCR, info->MCR);
 	
 	/*
@@ -1097,6 +1337,7 @@
 	/*
 	 * Set up the tty->alt_speed kludge
 	 */
+#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
 	if (info->tty) {
 		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
 			info->tty->alt_speed = 57600;
@@ -1107,6 +1348,7 @@
 		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
 			info->tty->alt_speed = 460800;
 	}
+#endif
 	
 	/*
 	 * and set the speed of the serial port
@@ -1193,12 +1435,7 @@
 	} else
 #endif
 		info->MCR &= ~UART_MCR_OUT2;
-#if defined(__alpha__) && !defined(CONFIG_PCI)
-	/*
-	 * DEC did something gratutiously wrong....
-	 */
-	info->MCR |= UART_MCR_OUT1 | UART_MCR_OUT2;
-#endif
+	info->MCR |= ALPHA_KLUDGE_MCR; 		/* Don't ask */
 	
 	/* disable break condition */
 	serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC);
@@ -1230,6 +1467,37 @@
 	restore_flags(flags);
 }
 
+#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
+static int baud_table[] = {
+	0, 50, 75, 110, 134, 150, 200, 300,
+	600, 1200, 1800, 2400, 4800, 9600, 19200,
+	38400, 57600, 115200, 230400, 460800, 0 };
+
+static int tty_get_baud_rate(struct tty_struct *tty)
+{
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	unsigned int cflag, i;
+
+	cflag = tty->termios->c_cflag;
+
+	i = cflag & CBAUD;
+	if (i & CBAUDEX) {
+		i &= ~CBAUDEX;
+		if (i < 1 || i > 2) 
+			tty->termios->c_cflag &= ~CBAUDEX;
+		else
+			i += 15;
+	}
+	if (i == 15) {
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			i += 1;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			i += 2;
+	}
+	return baud_table[i];
+}
+#endif
+
 /*
  * This routine is called to set the UART divisor registers to match
  * the specified baud rate for a serial port.
@@ -1237,7 +1505,6 @@
 static void change_speed(struct async_struct *info,
 			 struct termios *old_termios)
 {
-	unsigned short port;
 	int	quot = 0, baud_base, baud;
 	unsigned cflag, cval, fcr = 0;
 	int	bits;
@@ -1246,7 +1513,7 @@
 	if (!info->tty || !info->tty->termios)
 		return;
 	cflag = info->tty->termios->c_cflag;
-	if (!(port = info->port))
+	if (!CONFIGURED_SERIAL_PORT(info))
 		return;
 
 	/* byte size and parity */
@@ -1278,6 +1545,18 @@
 	if (!baud)
 		baud = 9600;	/* B0 transition handled in rs_set_termios */
 	baud_base = info->state->baud_base;
+	if (info->state->type == PORT_16C950) {
+		if (baud <= baud_base)
+			serial_icr_write(info, UART_TCR, 0);
+		else if (baud <= 2*baud_base) {
+			serial_icr_write(info, UART_TCR, 0x8);
+			baud_base = baud_base * 2;
+		} else if (baud <= 4*baud_base) {
+			serial_icr_write(info, UART_TCR, 0x4);
+			baud_base = baud_base * 4;
+		} else
+			serial_icr_write(info, UART_TCR, 0);
+	}
 	if (baud == 38400 &&
 	    ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
 		quot = info->state->custom_divisor;
@@ -1383,6 +1662,7 @@
 	if (info->state->type == PORT_16750)
 		serial_outp(info, UART_FCR, fcr); 	/* set fcr */
 	serial_outp(info, UART_LCR, cval);		/* reset DLAB */
+	info->LCR = cval;				/* Save LCR */
 	if (info->state->type != PORT_16750)
 		serial_outp(info, UART_FCR, fcr); 	/* set fcr */
 	restore_flags(flags);
@@ -1664,7 +1944,7 @@
 	change_port = (new_serial.port != state->port) ||
 		(new_serial.hub6 != state->hub6);
   
-	if (!capable(CAP_SYS_ADMIN)) {
+	if (!serial_isroot()) {
 		if (change_irq || change_port ||
 		    (new_serial.baud_base != state->baud_base) ||
 		    (new_serial.type != state->type) ||
@@ -1721,11 +2001,14 @@
 	state->type = new_serial.type;
 	state->close_delay = new_serial.close_delay * HZ/100;
 	state->closing_wait = new_serial.closing_wait * HZ/100;
+#if (LINUX_VERSION_CODE > 0x200100)
 	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+#endif
 	info->xmit_fifo_size = state->xmit_fifo_size =
 		new_serial.xmit_fifo_size;
 
-	release_region(state->port,8);
+	if (state->port)
+		release_region(state->port,8);
 	if (change_port || change_irq) {
 		/*
 		 * We need to shutdown the serial port at the old
@@ -1736,7 +2019,7 @@
 		info->port = state->port = new_serial.port;
 		info->hub6 = state->hub6 = new_serial.hub6;
 	}
-	if (state->type != PORT_UNKNOWN)
+	if ((state->type != PORT_UNKNOWN) && state->port)
 		request_region(state->port,8,"serial(set)");
 
 	
@@ -1747,6 +2030,7 @@
 		if (((old_state.flags & ASYNC_SPD_MASK) !=
 		     (state->flags & ASYNC_SPD_MASK)) ||
 		    (old_state.custom_divisor != state->custom_divisor)) {
+#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
 			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
 				info->tty->alt_speed = 57600;
 			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
@@ -1755,6 +2039,7 @@
 				info->tty->alt_speed = 230400;
 			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
 				info->tty->alt_speed = 460800;
+#endif
 			change_speed(info, 0);
 		}
 	} else
@@ -1783,7 +2068,9 @@
 	status = serial_in(info, UART_LSR);
 	restore_flags(flags);
 	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-	return put_user(result,value);
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+	return 0;
 }
 
 
@@ -1807,19 +2094,21 @@
 		| ((status  & UART_MSR_RI) ? TIOCM_RNG : 0)
 		| ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0)
 		| ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);
-	return put_user(result,value);
+
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+	return 0;
 }
 
 static int set_modem_info(struct async_struct * info, unsigned int cmd,
 			  unsigned int *value)
 {
-	int error;
 	unsigned int arg;
 	unsigned long flags;
 
-	error = get_user(arg, value);
-	if (error)
-		return error;
+	if (copy_from_user(&arg, value, sizeof(int)))
+		return -EFAULT;
+
 	switch (cmd) {
 	case TIOCMBIS: 
 		if (arg & TIOCM_RTS)
@@ -1863,6 +2152,7 @@
 		return -EINVAL;
 	}
 	save_flags(flags); cli();
+	info->MCR |= ALPHA_KLUDGE_MCR; 		/* Don't ask */
 	serial_out(info, UART_MCR, info->MCR);
 	restore_flags(flags);
 	return 0;
@@ -1872,7 +2162,7 @@
 {
 	int			retval;
 	
-	if (!capable(CAP_SYS_ADMIN))
+	if (!serial_isroot())
 		return -EPERM;
 	
 	if (info->state->count > 1)
@@ -1895,6 +2185,22 @@
 /*
  * rs_break() --- routine which turns the break handling on or off
  */
+#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
+static void send_break(	struct async_struct * info, int duration)
+{
+	if (!CONFIGURED_SERIAL_PORT(info))
+		return;
+	current->state = TASK_INTERRUPTIBLE;
+	current->timeout = jiffies + duration;
+	cli();
+	info->LCR |= UART_LCR_SBC;
+	serial_out(info, UART_LCR, info->LCR);
+	schedule();
+	info->LCR &= ~UART_LCR_SBC;
+	serial_out(info, UART_LCR, info->LCR);
+	sti();
+}
+#else
 static void rs_break(struct tty_struct *tty, int break_state)
 {
 	struct async_struct * info = (struct async_struct *)tty->driver_data;
@@ -1903,17 +2209,17 @@
 	if (serial_paranoia_check(info, tty->device, "rs_break"))
 		return;
 
-	if (!info->port)
+	if (!CONFIGURED_SERIAL_PORT(info))
 		return;
 	save_flags(flags); cli();
 	if (break_state == -1)
-		serial_out(info, UART_LCR,
-			   serial_inp(info, UART_LCR) | UART_LCR_SBC);
+		info->LCR |= UART_LCR_SBC;
 	else
-		serial_out(info, UART_LCR,
-			   serial_inp(info, UART_LCR) & ~UART_LCR_SBC);
+		info->LCR &= ~UART_LCR_SBC;
+	serial_out(info, UART_LCR, info->LCR);
 	restore_flags(flags);
 }
+#endif
 
 #ifdef CONFIG_SERIAL_MULTIPORT
 static int get_multiport_struct(struct async_struct * info,
@@ -1959,7 +2265,7 @@
 	int	retval;
 	void (*handler)(int, void *, struct pt_regs *);
 
-	if (!capable(CAP_SYS_ADMIN))
+	if (!serial_isroot())
 		return -EPERM;
 	state = info->state;
 	
@@ -2032,11 +2338,13 @@
 static int rs_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 {
-	int error;
 	struct async_struct * info = (struct async_struct *)tty->driver_data;
 	struct async_icount cprev, cnow;	/* kernel counter temps */
-	struct serial_icounter_struct *p_cuser;	/* user space */
+	struct serial_icounter_struct icount;
 	unsigned long flags;
+#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
+	int retval, tmp;
+#endif
 	
 	if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
 		return -ENODEV;
@@ -2049,6 +2357,45 @@
 	}
 	
 	switch (cmd) {
+#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
+		case TCSBRK:	/* SVID version: non-zero arg --> no break */
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			if (signal_pending(current))
+				return -EINTR;
+			if (!arg) {
+				send_break(info, HZ/4);	/* 1/4 second */
+				if (signal_pending(current))
+					return -EINTR;
+			}
+			return 0;
+		case TCSBRKP:	/* support for POSIX tcsendbreak() */
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			if (signal_pending(current))
+				return -EINTR;
+			send_break(info, arg ? arg*(HZ/10) : HZ/4);
+			if (signal_pending(current))
+				return -EINTR;
+			return 0;
+		case TIOCGSOFTCAR:
+			tmp = C_CLOCAL(tty) ? 1 : 0;
+			if (copy_to_user((void *)arg, &tmp, sizeof(int)))
+				return -EFAULT;
+			return 0;
+		case TIOCSSOFTCAR:
+			if (copy_from_user(&tmp, (void *)arg, sizeof(int)))
+				return -EFAULT;
+
+			tty->termios->c_cflag =
+				((tty->termios->c_cflag & ~CLOCAL) |
+				 (tmp ? CLOCAL : 0));
+			return 0;
+#endif
 		case TIOCMGET:
 			return get_modem_info(info, (unsigned int *) arg);
 		case TIOCMBIS:
@@ -2124,31 +2471,21 @@
 			save_flags(flags); cli();
 			cnow = info->state->icount;
 			restore_flags(flags);
-			p_cuser = (struct serial_icounter_struct *) arg;
-			error = put_user(cnow.cts, &p_cuser->cts);
-			if (error) return error;
-			error = put_user(cnow.dsr, &p_cuser->dsr);
-			if (error) return error;
-			error = put_user(cnow.rng, &p_cuser->rng);
-			if (error) return error;
-			error = put_user(cnow.dcd, &p_cuser->dcd);
-			if (error) return error;
-			error = put_user(cnow.rx, &p_cuser->rx);
-			if (error) return error;
-			error = put_user(cnow.tx, &p_cuser->tx);
-			if (error) return error;
-			error = put_user(cnow.frame, &p_cuser->frame);
-			if (error) return error;
-			error = put_user(cnow.overrun, &p_cuser->overrun);
-			if (error) return error;
-			error = put_user(cnow.parity, &p_cuser->parity);
-			if (error) return error;
-			error = put_user(cnow.brk, &p_cuser->brk);
-			if (error) return error;
-			error = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
-			if (error) return error;			
+			icount.cts = cnow.cts;
+			icount.dsr = cnow.dsr;
+			icount.rng = cnow.rng;
+			icount.dcd = cnow.dcd;
+			icount.rx = cnow.rx;
+			icount.tx = cnow.tx;
+			icount.frame = cnow.frame;
+			icount.overrun = cnow.overrun;
+			icount.parity = cnow.parity;
+			icount.brk = cnow.brk;
+			icount.buf_overrun = cnow.buf_overrun;
+			
+			if (copy_to_user((void *)arg, &icount, sizeof(icount)))
+				return -EFAULT;
 			return 0;
-
 		case TIOCSERGWILD:
 		case TIOCSERSWILD:
 			/* "setserial -W" is called in Debian boot */
@@ -2422,7 +2759,11 @@
 static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			   struct async_struct *info)
 {
+#ifdef DECLARE_WAITQUEUE
 	DECLARE_WAITQUEUE(wait, current);
+#else
+	struct wait_queue wait = { current, NULL };
+#endif
 	struct serial_state *state = info->state;
 	int		retval;
 	int		do_clocal = 0, extra_count = 0;
@@ -2511,7 +2852,7 @@
 				   serial_inp(info, UART_MCR) |
 				   (UART_MCR_DTR | UART_MCR_RTS));
 		restore_flags(flags);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ASYNC_INITIALIZED)) {
 #ifdef SERIAL_DO_RESTART
@@ -2571,12 +2912,18 @@
 		return -ENOMEM;
 	}
 	memset(info, 0, sizeof(struct async_struct));
+#ifdef DECLARE_WAITQUEUE
 	init_waitqueue_head(&info->open_wait);
 	init_waitqueue_head(&info->close_wait);
 	init_waitqueue_head(&info->delta_msr_wait);
+#endif
 	info->magic = SERIAL_MAGIC;
 	info->port = sstate->port;
 	info->flags = sstate->flags;
+#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
+	info->iomem_base = sstate->iomem_base;
+	info->iomem_reg_shift = sstate->iomem_reg_shift;
+#endif
 	info->xmit_fifo_size = sstate->xmit_fifo_size;
 	info->line = line;
 	info->tqueue.routine = do_softint;
@@ -2616,21 +2963,20 @@
 	}
 	tty->driver_data = info;
 	info->tty = tty;
-	if (serial_paranoia_check(info, tty->device, "rs_open")) {
-		/* MOD_DEC_USE_COUNT; "info->tty" will cause this */
+	if (serial_paranoia_check(info, tty->device, "rs_open"))
 		return -ENODEV;
-	}
 
 #ifdef SERIAL_DEBUG_OPEN
 	printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
 	       info->state->count);
 #endif
+#if (LINUX_VERSION_CODE > 0x20100)
 	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+#endif
 
 	if (!tmp_buf) {
 		page = get_free_page(GFP_KERNEL);
 		if (!page) {
-			/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
 			return -ENOMEM;
 		}
 		if (tmp_buf)
@@ -2646,7 +2992,6 @@
 	    (info->flags & ASYNC_CLOSING)) {
 		if (info->flags & ASYNC_CLOSING)
 			interruptible_sleep_on(&info->close_wait);
-		/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
 #ifdef SERIAL_DO_RESTART
 		return ((info->flags & ASYNC_HUP_NOTIFY) ?
 			-EAGAIN : -ERESTARTSYS);
@@ -2660,13 +3005,11 @@
 	 */
 	retval = startup(info);
 	if (retval) {
-		/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
 		return retval;
 	}
 
 	retval = block_til_ready(tty, filp, info);
 	if (retval) {
-		/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
 #ifdef SERIAL_DEBUG_OPEN
 		printk("rs_open returning after block_til_ready with %d\n",
 		       retval);
@@ -2838,6 +3181,13 @@
 	printk(" DETECT_IRQ");
 #define SERIAL_OPT
 #endif
+#ifdef ENABLE_SERIAL_PCI
+	printk(" SERIAL_PCI");
+#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
+	printk(" PCI_IOMEM");
+#endif
+#define SERIAL_OPT
+#endif
 #ifdef SERIAL_OPT
 	printk(" enabled\n");
 #else
@@ -2913,51 +3263,155 @@
 }
 
 /*
+ * This is a quickie test to see how big the FIFO is.
+ * It doesn't work at all the time, more's the pity.
+ */
+static int size_fifo(struct async_struct *info)
+{
+	unsigned char old_fcr, old_mcr, old_dll, old_dlm;
+	int count;
+
+	old_fcr = serial_inp(info, UART_FCR);
+	old_mcr = serial_inp(info, UART_MCR);
+	serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO |
+		    UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+	serial_outp(info, UART_MCR, UART_MCR_LOOP);
+	serial_outp(info, UART_LCR, UART_LCR_DLAB);
+	old_dll = serial_inp(info, UART_DLL);
+	old_dlm = serial_inp(info, UART_DLM);
+	serial_outp(info, UART_DLL, 0x01);
+	serial_outp(info, UART_DLM, 0x00);
+	serial_outp(info, UART_LCR, 0x03);
+	for (count = 0; count < 256; count++)
+		serial_outp(info, UART_TX, count);
+	mdelay(20);
+	for (count = 0; (serial_inp(info, UART_LSR) & UART_LSR_DR) &&
+	     (count < 256); count++)
+		serial_inp(info, UART_RX);
+	serial_outp(info, UART_FCR, old_fcr);
+	serial_outp(info, UART_MCR, old_mcr);
+	serial_outp(info, UART_LCR, UART_LCR_DLAB);
+	serial_outp(info, UART_DLL, old_dll);
+	serial_outp(info, UART_DLM, old_dlm);
+
+	return count;
+}
+
+/*
+ * This is a helper routine to autodetect StarTech/Exar UART's.  When
+ * this function is called we know it is at least a StarTech 16650 V2,
+ * but it might be one of several StarTech UARTs, or one of its
+ * clones.  (We treat the broken original StarTech 16650 V1 as a
+ * 16550A, and why not?  Startech doesn't seem to even acknowledge its
+ * existence.)
+ * 
+ * What evil have men's minds wrought...
+ */
+static void autoconfig_startech_uarts(struct async_struct *info,
+				      struct serial_state *state,
+				      unsigned long flags)
+{
+	unsigned char scratch, status1, status2, old_fctr, old_emsr;
+
+	/*
+	 * Here we check for the XR16C85x family.  We do this by
+	 * checking for to see if we can replace the scratch register
+	 * with the receive FIFO count register.
+	 *
+	 * XXX  I don't have one of these chips, but it should also be
+	 * possible to check for them by setting DLL and DLM to 0, and
+	 * then reading back DLL and DLM.  If the DLM reads back as
+	 * 0x10, then the UART is a XR16C850 and the DLL contains the
+	 * chip revision.
+	 */
+	old_fctr = serial_inp(info, UART_FCTR);
+	serial_outp(info, UART_FCTR, old_fctr | UART_FCTR_SCR_SWAP);
+	old_emsr = serial_inp(info, UART_EMSR);
+	serial_outp(info, UART_EMSR, 0x00);
+	serial_outp(info, UART_LCR, 0x00);
+	scratch = serial_in(info, UART_SCR);
+	serial_outp(info, UART_SCR, 0xa5);
+	status1 = serial_in(info, UART_SCR);
+	serial_outp(info, UART_SCR, 0x5a);
+	status2 = serial_in(info, UART_SCR);
+	serial_outp(info, UART_SCR, scratch);
+	if ((status1 != 0xa5) || (status2 != 0x5a)) {
+		serial_outp(info, UART_LCR, 0xBF);
+		serial_outp(info, UART_FCTR, old_fctr | UART_FCTR_SCR_SWAP);
+		serial_outp(info, UART_EMSR, old_emsr);
+		serial_outp(info, UART_FCTR, old_fctr);
+		state->type = PORT_16850;
+		return;
+	}
+	serial_outp(info, UART_IER, old_fctr);
+
+	/*
+	 * We distinguish between the '654 and the '650 by counting
+	 * how many bytes are in the FIFO.  I'm using this for now,
+	 * since that's the technique that was sent to me in the
+	 * serial driver update, but I'm not convinced this works.
+	 * I've had problems doing this in the past.  -TYT
+	 */
+	if (size_fifo(info) == 64)
+		state->type = PORT_16654;
+	else
+		state->type = PORT_16650V2;
+}
+
+/*
  * This routine is called by rs_init() to initialize a specific serial
  * port.  It determines what type of UART chip this serial port is
  * using: 8250, 16450, 16550, 16550A.  The important question is
- * whether or not this UART is a 16550A, since this will determine
- * whether or not we can use its FIFO features.
+ * whether or not this UART is a 16550A or not, since this will
+ * determine whether or not we can use its FIFO features or not.
  */
 static void autoconfig(struct serial_state * state)
 {
-	unsigned char status1, status2, scratch, scratch2;
+	unsigned char status1, status2, scratch, scratch2, scratch3;
 	struct async_struct *info, scr_info;
 	unsigned long flags;
 
 	state->type = PORT_UNKNOWN;
 	
-	if (!state->port)
+	if (!CONFIGURED_SERIAL_PORT(state))
 		return;
 		
 	info = &scr_info;	/* This is just for serial_{in,out} */
 
 	info->magic = SERIAL_MAGIC;
+	info->state = state;
 	info->port = state->port;
 	info->flags = state->flags;
 #ifdef CONFIG_HUB6
 	info->hub6 = state->hub6;
 #endif
+#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
+	info->iomem_base = state->iomem_base;
+	info->iomem_reg_shift = state->iomem_reg_shift;
+#endif
 
 	save_flags(flags); cli();
 	
-	/*
-	 * Do a simple existence test first; if we fail this, there's
-	 * no point trying anything else.
-	 *
-	 * 0x80 is used as a nonsense port to prevent against false
-	 * positives due to ISA bus float.  The assumption is that
-	 * 0x80 is a non-existent port; which should be safe since
-	 * include/asm/io.h also makes this assumption.
-	 */
-	scratch = serial_inp(info, UART_IER);
-	serial_outp(info, UART_IER, 0);
-	outb(0xff, 0x080);
-	scratch2 = serial_inp(info, UART_IER);
-	serial_outp(info, UART_IER, scratch);
-	if (scratch2) {
-		restore_flags(flags);
-		return;		/* We failed; there's nothing here */
+	if (!state->iomem_base) {
+		/*
+		 * Do a simple existence test first; if we fail this,
+		 * there's no point trying anything else.
+		 * 
+		 * 0x80 is used as a nonsense port to prevent against
+		 * false positives due to ISA bus float.  The
+		 * assumption is that 0x80 is a non-existent port;
+		 * which should be safe since include/asm/io.h also
+		 * makes this assumption.
+		 */
+		scratch = serial_inp(info, UART_IER);
+		serial_outp(info, UART_IER, 0);
+		outb(0xff, 0x080);
+		scratch2 = serial_inp(info, UART_IER);
+		serial_outp(info, UART_IER, scratch);
+		if (scratch2) {
+			restore_flags(flags);
+			return;		/* We failed; there's nothing here */
+		}
 	}
 
 	/* 
@@ -2980,7 +3434,7 @@
 			return;
 		}
 	} 
-	
+
 	scratch2 = serial_in(info, UART_LCR);
 	serial_outp(info, UART_LCR, 0xBF); /* set up for StarTech test */
 	serial_outp(info, UART_EFR, 0);	/* EFR is the same as FCR */
@@ -3002,14 +3456,27 @@
 			break;
 	}
 	if (state->type == PORT_16550A) {
+		/* Check for Oxford Semiconductor 16C950 */
+		scratch = serial_icr_read(info, UART_ID1);
+		scratch2 = serial_icr_read(info, UART_ID2);
+		scratch3 = serial_icr_read(info, UART_ID3);
+		
+		if (scratch == 0x16 && scratch2 == 0xC9 &&
+		    (scratch3 == 0x50 || scratch3 == 0x52 ||
+		     scratch3 == 0x54)) {
+			state->type = PORT_16C950;
+			state->revision = serial_icr_read(info, UART_REV);
+		}
+	}
+	if (state->type == PORT_16550A) {
 		/* Check for Startech UART's */
-		serial_outp(info, UART_LCR, scratch2 | UART_LCR_DLAB);
+		serial_outp(info, UART_LCR, UART_LCR_DLAB);
 		if (serial_in(info, UART_EFR) == 0) {
 			state->type = PORT_16650;
 		} else {
 			serial_outp(info, UART_LCR, 0xBF);
 			if (serial_in(info, UART_EFR) == 0)
-				state->type = PORT_16650V2;
+				autoconfig_startech_uarts(info, state, flags);
 		}
 	}
 	if (state->type == PORT_16550A) {
@@ -3019,7 +3486,16 @@
 			    UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
 		scratch = serial_in(info, UART_IIR) >> 5;
 		if (scratch == 7) {
+			/*
+			 * If this is a 16750, and not a cheap UART
+			 * clone, then it should only go into 64 byte
+			 * mode if the UART_FCR7_64BYTE bit was set
+			 * while UART_LCR_DLAB was latched.
+			 */
+ 			serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
 			serial_outp(info, UART_LCR, 0);
+			serial_outp(info, UART_FCR,
+				    UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
 			scratch = serial_in(info, UART_IIR) >> 5;
 			if (scratch == 6)
 				state->type = PORT_16750;
@@ -3045,20 +3521,13 @@
 		return;
 	}
 
-	request_region(info->port,8,"serial(auto)");
+	if (info->port)
+		request_region(info->port,8,"serial(auto)");
 
 	/*
 	 * Reset the UART.
 	 */
-#if defined(__alpha__) && !defined(CONFIG_PCI)
-	/*
-	 * I wonder what DEC did to the OUT1 and OUT2 lines?
-	 * clearing them results in endless interrupts.
-	 */
-	serial_outp(info, UART_MCR, 0x0c);
-#else
-	serial_outp(info, UART_MCR, 0x00);
-#endif
+	serial_outp(info, UART_MCR, 0x00 | ALPHA_KLUDGE_MCR); /* Don't ask */
 	serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR |
 				     UART_FCR_CLEAR_XMIT));
 	(void)serial_in(info, UART_RX);
@@ -3070,13 +3539,321 @@
 int register_serial(struct serial_struct *req);
 void unregister_serial(int line);
 
+#if (LINUX_VERSION_CODE > 0x20100)
 EXPORT_SYMBOL(register_serial);
 EXPORT_SYMBOL(unregister_serial);
+#else
+static struct symbol_table serial_syms = {
+#include <linux/symtab_begin.h>
+	X(register_serial),
+	X(unregister_serial),
+#include <linux/symtab_end.h>
+};
+#endif
+
+#ifdef ENABLE_SERIAL_PCI
+/*
+ * Some PCI serial cards using the PLX 9050 PCI interface chip require
+ * that the card interrupt be explicitly enabled or disabled.  This
+ * seems to be mainly needed on card using the PLX which also use I/O
+ * mapped memory.
+ * 
+ * Note that __init is a no-op if MODULE is defined; we depend on this.
+ */
+static void __init pci_plx9050_fn(struct pci_dev *dev,
+				  struct pci_board *board,
+				  int enable)
+{
+	u8 data, *p;
+
+	pci_read_config_byte(dev, PCI_COMMAND, &data);
+
+	if (enable)
+		pci_write_config_byte(dev, PCI_COMMAND,
+				      data | PCI_COMMAND_MEMORY);
+	
+	/* enable/disable interrupts */
+	p = ioremap(PCI_BASE_ADDRESS(dev, 0), 0x80);
+	writel(enable ? 0x41 : 0x00, p + 0x4c);
+	iounmap(p);
+
+	if (!enable)
+		pci_write_config_byte(dev, PCI_COMMAND,
+				      data & ~PCI_COMMAND_MEMORY);
+}
+
+/*
+ * This is the configuration table for all of the PCI serial boards
+ * which we support.
+ */
+static struct pci_board pci_boards[] = {
+	/*
+	 * Vendor ID, 	Device ID,
+	 * Subvendor ID,	Subdevice ID,
+	 * Number of Ports, Base (Maximum) Baud Rate,
+	 * Offset of register holding Uart register offset
+	 * Mask to apply to above register's value
+	 */
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232,
+		SPCI_FL_BASE1, 8, 1382400 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232,
+		SPCI_FL_BASE1, 4, 1382400 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232,
+		SPCI_FL_BASE1, 2, 1382400 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232,
+		SPCI_FL_BASE1, 8, 1382400 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232,
+		SPCI_FL_BASE1, 4, 1382400 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232,
+		SPCI_FL_BASE1, 2, 1382400 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485,
+		SPCI_FL_BASE1, 8, 921600 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4,
+		SPCI_FL_BASE1, 8, 921600 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485,
+		SPCI_FL_BASE1, 4, 921600 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2,
+		SPCI_FL_BASE1, 4, 921600 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485,
+		SPCI_FL_BASE1, 2, 921600 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485,
+		SPCI_FL_BASE1, 8, 921600 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4,
+		SPCI_FL_BASE1, 8, 921600 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485,
+		SPCI_FL_BASE1, 4, 921600 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2,
+		SPCI_FL_BASE1, 4, 921600 },
+	{	PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960V2,
+		PCI_SUBVENDOR_ID_CONNECT_TECH,
+		PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485,
+		SPCI_FL_BASE1, 2, 921600 },
+	{	PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 },
+	{	PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 },
+	{	PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 },
+	{	PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 },
+	{	PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 },
+	{	PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 8, 115200 },
+	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 },
+	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 },
+	{	PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+		PCI_SUBVENDOR_ID_KEYSPAN,
+		PCI_SUBDEVICE_ID_KEYSPAN_SX2,
+		SPCI_FL_BASE2 | SPCI_FL_IOMEM, 2, 921600,
+		0x400, 7, pci_plx9050_fn },
+	{	PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE2 | SPCI_FL_IOMEM, 4, 921600,
+		0x400, 7, pci_plx9050_fn },
+	{	PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM,
+		PCI_ANY_ID, PCI_ANY_ID,
+		SPCI_FL_BASE2 | SPCI_FL_IOMEM, 2, 921600,
+		0x400, 7, pci_plx9050_fn },
+	{	0, }
+};
+
+/*
+ * Query PCI space for known serial boards
+ * If found, add them to the PCI device space in rs_table[]
+ *
+ * Accept a maximum of eight boards
+ *
+ */
+static void probe_serial_pci(void) 
+{
+	u16 subvendor, subdevice;
+	int k, line;
+	struct pci_dev *dev = NULL;
+	struct pci_board *board;
+	struct serial_struct fake_state;
+	int uart_offset, base_baud, base_idx;
+	unsigned long port;
+
+#ifdef SERIAL_DEBUG_PCI
+	printk(KERN_DEBUG "Entered probe_serial_pci()\n");
+#endif
+  
+	if (!pcibios_present()) {
+#ifdef SERIAL_DEBUG_PCI
+		printk(KERN_DEBUG "Leaving probe_serial_pci() (no pcibios)\n");
+#endif
+		return;
+	}
+
+	for(dev=pci_devices; dev; dev=dev->next) {
+		pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID,
+					 &subvendor);
+		pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &subdevice);
+
+		for (board = pci_boards; board->vendor; board++) {
+			if (board->vendor != (unsigned short) PCI_ANY_ID &&
+			    dev->vendor != board->vendor)
+				continue;
+			if (board->device != (unsigned short) PCI_ANY_ID &&
+			    dev->device != board->device)
+				continue;
+			if (board->subvendor != (unsigned short) PCI_ANY_ID &&
+			    subvendor != board->subvendor)
+				continue;
+			if (board->subdevice != (unsigned short) PCI_ANY_ID &&
+			    subdevice != board->subdevice)
+				continue;
+			break;
+		}
+	
+		if (board->vendor == 0) {
+#ifdef SERIAL_DEBUG_PCI
+		printk(KERN_DEBUG
+		       "Found unknown serial board: %x:%x, %x:%x, %x\n",
+		       dev->vendor, dev->device, subvendor, subdevice,
+		       dev->class);
+		printk(KERN_DEBUG
+		       "   Addresses: %lx, %lx, %lx, %lx\n",
+		       PCI_BASE_ADDRESS(dev, 0), PCI_BASE_ADDRESS(dev, 1), 
+		       PCI_BASE_ADDRESS(dev, 2), PCI_BASE_ADDRESS(dev, 3));
+#endif
+			continue; 
+		}
+
+		/*
+		 * Run the initialization function, if any
+		 */
+		if (board->init_fn)
+			(board->init_fn)(dev, board, 1);
+
+		/*
+		 * Register the serial board in the array so we can
+		 * shutdown the board later, if necessary.
+		 */
+		serial_pci_board[serial_pci_board_idx].board = board;
+		serial_pci_board[serial_pci_board_idx].dev = dev;
+		serial_pci_board_idx++;
+
+		base_idx = board->flags & SPCI_FL_BASE_MASK;
+		port = PCI_BASE_ADDRESS(dev, base_idx);
+		if (board->flags & SPCI_FL_IOMEM)
+			port &= PCI_BASE_ADDRESS_MEM_MASK;
+		else
+			port &= PCI_BASE_ADDRESS_IO_MASK;
+
+		/*
+		 * Set some defaults for the loop below, which 
+		 * actually registers each serial port belonging to
+		 * the card.
+		 */
+		uart_offset = board->uart_offset;
+		if (!uart_offset)
+			uart_offset = 8;
+		base_baud = board->base_baud;
+		if (!base_baud)
+			base_baud = BASE_BAUD;
+#ifndef CONFIG_SERIAL_PCI_MEMMAPPED
+		if (board->flags & SPCI_FL_IOMEM) {
+#ifdef SERIAL_DEBUG_PCI
+			printk(KERN_DEBUG
+		           "Can't support memory mapped PCI serial device\n");
+#endif
+			continue; 
+		}
+#endif
+		memset(&fake_state, 0, sizeof(fake_state));
+
+#ifdef SERIAL_DEBUG_PCI
+		printk(KERN_DEBUG
+		       "Found Serial PCI device: %x:%x, %x:%x, %x\n",
+		       dev->vendor, dev->device, subvendor, subdevice,
+		       dev->class);
+		printk(KERN_DEBUG
+		       "   IRQ: %d, base: %lx (%s), num_ports: %d\n",
+		       dev->irq, port, board->flags & SPCI_FL_IOMEM ?
+		       "iomem" : "port", board->num_ports);
+#endif
+		       
+		for (k=0; k < board->num_ports; k++) {
+			if (board->flags & SPCI_FL_BASE_TABLE) {
+				port = PCI_BASE_ADDRESS(dev, base_idx++);
+				if (board->flags & SPCI_FL_IOMEM)
+					port &= PCI_BASE_ADDRESS_MEM_MASK;
+				else
+					port &= PCI_BASE_ADDRESS_IO_MASK;
+			}
+			fake_state.irq = dev->irq;
+			fake_state.port = port;
+#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
+			if (board->flags & SPCI_FL_IOMEM) {
+				fake_state.iomem_base =
+					ioremap(port, board->uart_offset);
+				fake_state.iomem_reg_shift = board->reg_shift;
+				fake_state.port = 0;
+			}
+#endif
+			port += uart_offset;
+			fake_state.flags = ASYNC_SKIP_TEST | ASYNC_SHARE_IRQ;
+			line = register_serial(&fake_state);
+			if (line < 0)
+				break;
+			rs_table[line].baud_base = base_baud;
+		}
+	}
+	
+#ifdef SERIAL_DEBUG_PCI
+	printk(KERN_DEBUG "Leaving probe_serial_pci() (probe finished)\n");
+#endif
+	return;
+}
+
+#endif /* ENABLE_SERIAL_PCI */
 
 /*
  * The serial driver boot-time initialization code!
  */
-__initfunc(int rs_init(void))
+int __init rs_init(void)
 {
 	int i;
 	struct serial_state * state;
@@ -3120,10 +3897,12 @@
 	
 	memset(&serial_driver, 0, sizeof(struct tty_driver));
 	serial_driver.magic = TTY_DRIVER_MAGIC;
+#if (LINUX_VERSION_CODE > 0x20100)
 	serial_driver.driver_name = "serial";
+#endif
 	serial_driver.name = "ttyS";
 	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
+	serial_driver.minor_start = 64 + SERIAL_DEV_OFFSET;
 	serial_driver.num = NR_PORTS;
 	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
 	serial_driver.subtype = SERIAL_TYPE_NORMAL;
@@ -3147,14 +3926,18 @@
 	serial_driver.ioctl = rs_ioctl;
 	serial_driver.throttle = rs_throttle;
 	serial_driver.unthrottle = rs_unthrottle;
-	serial_driver.send_xchar = rs_send_xchar;
 	serial_driver.set_termios = rs_set_termios;
 	serial_driver.stop = rs_stop;
 	serial_driver.start = rs_start;
 	serial_driver.hangup = rs_hangup;
+#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
 	serial_driver.break_ctl = rs_break;
+#endif
+#if (LINUX_VERSION_CODE >= 131343)
+	serial_driver.send_xchar = rs_send_xchar;
 	serial_driver.wait_until_sent = rs_wait_until_sent;
 	serial_driver.read_proc = rs_read_proc;
+#endif
 	
 	/*
 	 * The callout device is just like normal device except for
@@ -3164,8 +3947,10 @@
 	callout_driver.name = "cua";
 	callout_driver.major = TTYAUX_MAJOR;
 	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+#if (LINUX_VERSION_CODE >= 131343)
 	callout_driver.read_proc = 0;
 	callout_driver.proc_entry = 0;
+#endif
 
 	if (tty_register_driver(&serial_driver))
 		panic("Couldn't register serial driver\n");
@@ -3187,15 +3972,11 @@
 		state->icount.frame = state->icount.parity = 0;
 		state->icount.overrun = state->icount.brk = 0;
 		state->irq = irq_cannonicalize(state->irq);
-		if (check_region(state->port,8))
+		if (state->port && check_region(state->port,8))
 			continue;
 		if (state->flags & ASYNC_BOOT_AUTOCONF)
 			autoconfig(state);
 	}
-	/*
-	 * Detect the IRQ only once every port is initialised,
-	 * because some 16450 do not reset to 0 the MCR register.
-	 */
 	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
 		if (state->type == PORT_UNKNOWN)
 			continue;
@@ -3204,11 +3985,14 @@
 		    && (state->port != 0))
 			state->irq = detect_uart_irq(state);
 		printk(KERN_INFO "ttyS%02d%s at 0x%04x (irq = %d) is a %s\n",
-		       state->line,
+		       state->line + SERIAL_DEV_OFFSET,
 		       (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
 		       state->port, state->irq,
 		       uart_config[state->type].name);
 	}
+#ifdef ENABLE_SERIAL_PCI
+	probe_serial_pci();
+#endif
 	return 0;
 }
 
@@ -3225,7 +4009,8 @@
 	save_flags(flags);
 	cli();
 	for (i = 0; i < NR_PORTS; i++) {
-		if (rs_table[i].port == req->port)
+		if ((rs_table[i].port == req->port) &&
+		    (rs_table[i].iomem_base == req->iomem_base))
 			break;
 	}
 	if (i == NR_PORTS) {
@@ -3248,6 +4033,10 @@
 	state->irq = req->irq;
 	state->port = req->port;
 	state->flags = req->flags;
+#ifdef CONFIG_SERIAL_PCI_MEMMAPPED
+	state->iomem_base = req->iomem_base;
+	state->iomem_reg_shift = req->iomem_reg_shift;
+#endif
 
 	autoconfig(state);
 	if (state->type == PORT_UNKNOWN) {
@@ -3257,13 +4046,16 @@
 	}
 	restore_flags(flags);
 
-	if ((state->flags & ASYNC_AUTO_IRQ) && (state->port != 0))
+	if ((state->flags & ASYNC_AUTO_IRQ) && CONFIGURED_SERIAL_PORT(state))
 		state->irq = detect_uart_irq(state);
 
-	printk(KERN_INFO "tty%02d at 0x%04x (irq = %d) is a %s\n",
-	       state->line, state->port, state->irq,
-	       uart_config[state->type].name);
-	return state->line;
+       printk(KERN_INFO "ttyS%02d at %s 0x%04lx (irq = %d) is a %s\n",
+	      state->line + SERIAL_DEV_OFFSET,
+	      state->iomem_base ? "iomem" : "port",
+	      state->iomem_base ? (unsigned long)state->iomem_base :
+	      (unsigned long)state->port,
+	      state->irq, uart_config[state->type].name);
+	return state->line + SERIAL_DEV_OFFSET;
 }
 
 void unregister_serial(int line)
@@ -3308,9 +4100,21 @@
 	restore_flags(flags);
 
 	for (i = 0; i < NR_PORTS; i++) {
-		if (rs_table[i].type != PORT_UNKNOWN)
+		if ((rs_table[i].type != PORT_UNKNOWN) && rs_table[i].port)
 			release_region(rs_table[i].port, 8);
+#if defined(ENABLE_SERIAL_PCI) && defined (CONFIG_SERIAL_PCI_MEMMAPPED)
+		if (rs_table[i].iomem_base)
+			iounmap(rs_table[i].iomem_base);
+#endif
+	}
+#ifdef ENABLE_SERIAL_PCI
+	for (i=0; i < serial_pci_board_idx; i++) {
+		struct pci_board_inst *brd = &serial_pci_board[i];
+		
+		if (brd->board->init_fn)
+			(brd->board->init_fn)(brd->dev, brd->board, 0);
 	}
+#endif	
 	if (tmp_buf) {
 		free_page((unsigned long) tmp_buf);
 		tmp_buf = NULL;
@@ -3429,7 +4233,7 @@
  *	- initialize the serial port
  *	Return non-zero if we didn't find a serial port.
  */
-__initfunc(static int serial_console_setup(struct console *co, char *options))
+static int __init serial_console_setup(struct console *co, char *options)
 {
 	struct serial_state *ser;
 	unsigned cval;
@@ -3550,9 +4354,15 @@
 /*
  *	Register console.
  */
-__initfunc (long serial_console_init(long kmem_start, long kmem_end))
+long __init serial_console_init(long kmem_start, long kmem_end)
 {
 	register_console(&sercons);
 	return kmem_start;
 }
 #endif
+
+/*
+  Local variables:
+  compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -D__SMP__ -pipe -fno-strength-reduce  -DCPU=686 -march=i686 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h   -DEXPORT_SYMTAB -c serial.c"
+  End:
+*/
diff -u --recursive --new-file v2.3.15/linux/drivers/char/serial167.c linux/drivers/char/serial167.c
--- v2.3.15/linux/drivers/char/serial167.c	Sat May 15 15:05:36 1999
+++ linux/drivers/char/serial167.c	Tue Aug 31 11:30:48 1999
@@ -1500,7 +1500,7 @@
             | ((status  & CyDCD) ? TIOCM_CAR : 0)
             | ((status  & CyDSR) ? TIOCM_DSR : 0)
             | ((status  & CyCTS) ? TIOCM_CTS : 0);
-    cy_put_user(result,(unsigned long *) value);
+    cy_put_user(result,(unsigned int *) value);
     return 0;
 } /* get_modem_info */
 
@@ -2094,7 +2094,7 @@
 #endif
 	    }
 	restore_flags(flags);
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	if (tty_hung_up_p(filp)
 	|| !(info->flags & ASYNC_INITIALIZED) ){
 	    if (info->flags & ASYNC_HUP_NOTIFY) {
diff -u --recursive --new-file v2.3.15/linux/drivers/char/specialix.c linux/drivers/char/specialix.c
--- v2.3.15/linux/drivers/char/specialix.c	Wed May 12 13:27:37 1999
+++ linux/drivers/char/specialix.c	Tue Aug 31 11:30:48 1999
@@ -1398,7 +1398,7 @@
 			} 
 		}
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(port->flags & ASYNC_INITIALIZED)) {
 			if (port->flags & ASYNC_HUP_NOTIFY)
@@ -1755,7 +1755,7 @@
 		          |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */
 		          |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
 	}
-	put_user(result,(unsigned long *) value);
+	put_user(result,(unsigned int *) value);
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.15/linux/drivers/char/synclink.c linux/drivers/char/synclink.c
--- v2.3.15/linux/drivers/char/synclink.c	Wed Jun 16 19:26:27 1999
+++ linux/drivers/char/synclink.c	Tue Aug 31 11:30:48 1999
@@ -3413,7 +3413,6 @@
 	if ( info->params.mode == MGSL_MODE_HDLC ) {
 		while (info->tx_active) {
 			current->state = TASK_INTERRUPTIBLE;
-			current->counter = 0;   /* make us low-priority */
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
@@ -3424,7 +3423,6 @@
 		while (!(usc_InReg(info,TCSR) & TXSTATUS_ALL_SENT) &&
 			info->tx_enabled) {
 			current->state = TASK_INTERRUPTIBLE;
-			current->counter = 0;   /* make us low-priority */
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
@@ -3561,7 +3559,7 @@
 			spin_unlock_irqrestore(&info->irq_spinlock,flags);
 		}
 		
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		
 		if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)){
 			retval = (info->flags & ASYNC_HUP_NOTIFY) ?
diff -u --recursive --new-file v2.3.15/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.3.15/linux/drivers/char/tty_io.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/char/tty_io.c	Tue Aug 31 11:31:35 1999
@@ -1499,10 +1499,11 @@
 	return 0;
 }
 
-static int tioccons(struct tty_struct *tty, struct tty_struct *real_tty)
+static int tioccons(struct inode *inode,
+	struct tty_struct *tty, struct tty_struct *real_tty)
 {
-	if (tty->driver.type == TTY_DRIVER_TYPE_CONSOLE ||
-	    tty->driver.type == TTY_DRIVER_TYPE_SYSCONS) {
+	if (inode->i_rdev == SYSCONS_DEV ||
+	    inode->i_rdev == CONSOLE_DEV) {
 		if (!suser())
 			return -EPERM;
 		redirect = NULL;
@@ -1631,7 +1632,7 @@
 
 static int send_break(struct tty_struct *tty, int duration)
 {
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 
 	tty->driver.break_ctl(tty, -1);
 	if (!signal_pending(current))
@@ -1712,7 +1713,7 @@
 		case TIOCSWINSZ:
 			return tiocswinsz(tty, real_tty, (struct winsize *) arg);
 		case TIOCCONS:
-			return tioccons(tty, real_tty);
+			return tioccons(inode, tty, real_tty);
 		case FIONBIO:
 			return fionbio(file, (int *) arg);
 		case TIOCEXCL:
diff -u --recursive --new-file v2.3.15/linux/drivers/char/tty_ioctl.c linux/drivers/char/tty_ioctl.c
--- v2.3.15/linux/drivers/char/tty_ioctl.c	Tue May 11 14:37:40 1999
+++ linux/drivers/char/tty_ioctl.c	Tue Aug 31 11:30:48 1999
@@ -59,7 +59,7 @@
 		printk("waiting %s...(%d)\n", tty_name(tty, buf),
 		       tty->driver.chars_in_buffer(tty));
 #endif
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (signal_pending(current))
 			goto stop_waiting;
 		if (!tty->driver.chars_in_buffer(tty))
diff -u --recursive --new-file v2.3.15/linux/drivers/char/vino.c linux/drivers/char/vino.c
--- v2.3.15/linux/drivers/char/vino.c	Wed Jun 30 11:24:54 1999
+++ linux/drivers/char/vino.c	Thu Aug 26 13:54:01 1999
@@ -240,7 +240,7 @@
 	0
 };
 
-__initfunc(int init_vino(struct video_device *dev))
+int __init init_vino(struct video_device *dev)
 {
 	int err;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v2.3.15/linux/drivers/char/vt.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/char/vt.c	Tue Aug 31 11:30:48 1999
@@ -1113,7 +1113,7 @@
 
 	add_wait_queue(&vt_activate_queue, &wait);
 	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		retval = 0;
 		if (vt == fg_console)
 			break;
diff -u --recursive --new-file v2.3.15/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
--- v2.3.15/linux/drivers/char/wdt.c	Wed Jun  2 11:29:13 1999
+++ linux/drivers/char/wdt.c	Thu Aug 26 13:53:47 1999
@@ -64,7 +64,7 @@
  *	Setup options
  */
  
-__initfunc(void wdt_setup(char *str, int *ints))
+void __init wdt_setup(char *str, int *ints)
 {
 	if(ints[0]>0)
 	{
@@ -365,7 +365,7 @@
 
 #endif
 
-__initfunc(int wdt_init(void))
+int __init wdt_init(void)
 {
 	printk("WDT500/501-P driver 0.07 at %X (Interrupt %d)\n", io,irq);
 	if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL))
diff -u --recursive --new-file v2.3.15/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c
--- v2.3.15/linux/drivers/i2o/i2o_core.c	Thu Aug  5 15:04:52 1999
+++ linux/drivers/i2o/i2o_core.c	Mon Aug 30 10:23:14 1999
@@ -310,7 +310,7 @@
 
 			*p=c->next;
 			spin_unlock(&i2o_configuration_lock);
-			if(c->page_frame);
+			if(c->page_frame)
 				kfree(c->page_frame);
 			if(c->hrt)
 				kfree(c->hrt);
diff -u --recursive --new-file v2.3.15/linux/drivers/isdn/eicon/eicon.h linux/drivers/isdn/eicon/eicon.h
--- v2.3.15/linux/drivers/isdn/eicon/eicon.h	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/eicon/eicon.h	Mon Aug 30 16:27:43 1999
@@ -1,4 +1,4 @@
-/* $Id: eicon.h,v 1.10 1999/08/22 20:26:41 calle Exp $
+/* $Id: eicon.h,v 1.11 1999/08/29 17:23:44 armin Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  *
@@ -21,6 +21,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon.h,v $
+ * Revision 1.11  1999/08/29 17:23:44  armin
+ * New setup compat.
+ * Bugfix if compile as not module.
+ *
  * Revision 1.10  1999/08/22 20:26:41  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -221,6 +225,8 @@
 #include <linux/ctype.h>
 
 #include <linux/isdnif.h>
+
+#include <linux/isdn_compat.h>
 
 typedef struct {
   __u16 length __attribute__ ((packed)); /* length of data/parameter field */
diff -u --recursive --new-file v2.3.15/linux/drivers/isdn/eicon/eicon_idi.c linux/drivers/isdn/eicon/eicon_idi.c
--- v2.3.15/linux/drivers/isdn/eicon/eicon_idi.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/eicon/eicon_idi.c	Mon Aug 30 16:27:43 1999
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.c,v 1.13 1999/08/22 20:26:44 calle Exp $
+/* $Id: eicon_idi.c,v 1.15 1999/08/28 21:32:50 armin Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  *        IDI interface 
@@ -21,6 +21,14 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_idi.c,v $
+ * Revision 1.15  1999/08/28 21:32:50  armin
+ * Prepared for fax related functions.
+ * Now compilable without errors/warnings.
+ *
+ * Revision 1.14  1999/08/28 20:24:40  armin
+ * Corrected octet 3/3a in CPN/OAD information element.
+ * Thanks to John Simpson <xfl23@dial.pipex.com>
+ *
  * Revision 1.13  1999/08/22 20:26:44  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -88,7 +96,7 @@
 
 #undef EICON_FULL_SERVICE_OKTETT
 
-char *eicon_idi_revision = "$Revision: 1.13 $";
+char *eicon_idi_revision = "$Revision: 1.15 $";
 
 eicon_manifbuf *manbuf;
 
@@ -469,14 +477,14 @@
 
 	reqbuf->XBuffer.P[l++] = CPN;
 	reqbuf->XBuffer.P[l++] = strlen(phone) + 1;
-	reqbuf->XBuffer.P[l++] = 0xc1;
+	reqbuf->XBuffer.P[l++] = 0x81;
 	for(i=0; i<strlen(phone);i++) 
 		reqbuf->XBuffer.P[l++] = phone[i];
 
 	reqbuf->XBuffer.P[l++] = OAD;
 	reqbuf->XBuffer.P[l++] = strlen(eazmsn) + 2;
 	reqbuf->XBuffer.P[l++] = 0x01;
-	reqbuf->XBuffer.P[l++] = 0x81;
+	reqbuf->XBuffer.P[l++] = 0x80;
 	for(i=0; i<strlen(eazmsn);i++) 
 		reqbuf->XBuffer.P[l++] = eazmsn[i];
 
@@ -893,6 +901,120 @@
   }
 }
 
+/********************* FAX stuff ***************************/
+
+#ifdef CONFIG_ISDN_TTY_FAX
+
+int
+idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer)
+{
+
+	/* TODO , code follows */
+
+	return(0);
+}
+
+/* send fax struct */
+int
+idi_send_edata(eicon_card *card, eicon_chan *chan)
+{
+
+	/* TODO , code follows */
+
+	return (0);
+}
+
+void
+idi_parse_edata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len)
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+idi_fax_send_header(eicon_card *card, eicon_chan *chan, int header)
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+idi_fax_cmd(eicon_card *card, eicon_chan *chan) 
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+idi_edata_rcveop(eicon_card *card, eicon_chan *chan)
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+idi_reset_fax_stat(eicon_chan *chan)
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+idi_edata_action(eicon_card *ccard, eicon_chan *chan, char *buffer, int len)
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+fax_put_rcv(eicon_card *ccard, eicon_chan *chan, u_char *Data, int len)
+{
+
+	/* TODO , code follows */
+
+}
+
+void
+idi_faxdata_rcv(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb)
+{
+
+	/* TODO , code follows */
+
+}
+
+int
+idi_fax_send_outbuf(eicon_card *ccard, eicon_chan *chan, eicon_OBJBUFFER *OutBuf)
+{
+
+	/* TODO , code follows */
+
+	return(0);
+}
+
+int
+idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb)
+{
+
+	/* TODO , code follows */
+
+	return(0);
+}
+
+void
+idi_fax_hangup(eicon_card *ccard, eicon_chan *chan)
+{
+
+	/* TODO , code follows */
+
+}
+
+#endif	/******** FAX ********/
 
 int
 idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int len)
diff -u --recursive --new-file v2.3.15/linux/drivers/isdn/eicon/eicon_mod.c linux/drivers/isdn/eicon/eicon_mod.c
--- v2.3.15/linux/drivers/isdn/eicon/eicon_mod.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/eicon/eicon_mod.c	Mon Aug 30 16:27:43 1999
@@ -1,4 +1,4 @@
-/* $Id: eicon_mod.c,v 1.9 1999/08/18 20:17:02 armin Exp $
+/* $Id: eicon_mod.c,v 1.11 1999/08/29 17:23:45 armin Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  * 
@@ -26,6 +26,14 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_mod.c,v $
+ * Revision 1.11  1999/08/29 17:23:45  armin
+ * New setup compat.
+ * Bugfix if compile as not module.
+ *
+ * Revision 1.10  1999/08/28 21:32:53  armin
+ * Prepared for fax related functions.
+ * Now compilable without errors/warnings.
+ *
  * Revision 1.9  1999/08/18 20:17:02  armin
  * Added XLOG function for all cards.
  * Bugfix of alloc_skb NULL pointer.
@@ -83,7 +91,7 @@
 static eicon_card *cards = (eicon_card *) NULL;   /* glob. var , contains
                                                      start of card-list   */
 
-static char *eicon_revision = "$Revision: 1.9 $";
+static char *eicon_revision = "$Revision: 1.11 $";
 
 extern char *eicon_pci_revision;
 extern char *eicon_isa_revision;
@@ -1006,7 +1014,7 @@
 					ISDN_FEATURE_L2_V11019 |
 					ISDN_FEATURE_L2_V11038 |
 					ISDN_FEATURE_L2_MODEM |
-					ISDN_FEATURE_L2_FAX |
+					/* ISDN_FEATURE_L2_FAX | */ 
 					ISDN_FEATURE_L3_TRANSDSP |
 					ISDN_FEATURE_L3_FAX;
                                 card->hwif.pci.card = (void *)card;
@@ -1030,7 +1038,7 @@
 					ISDN_FEATURE_L2_V11019 |
 					ISDN_FEATURE_L2_V11038 |
 					ISDN_FEATURE_L2_MODEM |
-					ISDN_FEATURE_L2_FAX |
+					/* ISDN_FEATURE_L2_FAX | */
 					ISDN_FEATURE_L3_TRANSDSP |
 					ISDN_FEATURE_L3_FAX;
                                 card->hwif.pci.card = (void *)card;
@@ -1335,7 +1343,7 @@
 #else
                 printk(KERN_INFO "Eicon: No PCI-cards found, driver not loaded !\n");
 #endif
-#endif
+#endif /* MODULE */
 		return -ENODEV;
 
 	} else
@@ -1373,13 +1381,26 @@
 }
 
 #else /* no module */
+
+#ifdef COMPAT_HAS_NEW_SETUP
+static int __init
+eicon_setup(char *line)
+{
+        int i, argc;
+	int ints[5];
+	char *str;
+
+	str = get_options(line, 4, ints);
+#else
 __initfunc(void
 eicon_setup(char *str, int *ints))
 {
         int i, argc;
+#endif
 
         argc = ints[0];
         i = 1;
+#ifdef CONFIG_ISDN_DRV_EICON_ISA
         if (argc) {
 		membase = irq = -1;
 		if (argc) {
@@ -1397,10 +1418,20 @@
 		} else {
 			strcpy(id, "eicon");
 		} 
-		/* eicon_addcard(0, membase, irq, id); */
-       		printk(KERN_INFO "eicon: membase=0x%x irq=%d id=%s\n", membase, irq, id);
+       		printk(KERN_INFO "Eicon ISDN active driver setup (id=%s membase=0x%x irq=%d)\n",
+			id, membase, irq);
 	}
+#else
+	printk(KERN_INFO "Eicon ISDN active driver setup\n");
+#endif
+#ifdef COMPAT_HAS_NEW_SETUP
+	return(1);
 }
+__setup("eicon=", eicon_setup);
+#else
+}
+#endif
+
 #endif /* MODULE */
 
 #ifdef CONFIG_ISDN_DRV_EICON_ISA
diff -u --recursive --new-file v2.3.15/linux/drivers/isdn/hisax/callc.c linux/drivers/isdn/hisax/callc.c
--- v2.3.15/linux/drivers/isdn/hisax/callc.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/hisax/callc.c	Thu Aug 26 09:48:40 1999
@@ -140,7 +140,6 @@
  *
  */
 
-#include <linux/config.h>
 #define __NO_VERSION__
 #include "hisax.h"
 #include "../avmb1/capicmd.h"  /* this should be moved in a common place */
diff -u --recursive --new-file v2.3.15/linux/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c
--- v2.3.15/linux/drivers/isdn/hisax/config.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/hisax/config.c	Mon Aug 30 16:27:43 1999
@@ -1,10 +1,16 @@
-/* $Id: config.c,v 2.31 1999/08/25 16:47:43 keil Exp $
+/* $Id: config.c,v 2.33 1999/08/30 11:57:52 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *
  *
  * $Log: config.c,v $
+ * Revision 2.33  1999/08/30 11:57:52  keil
+ * Fix broken avm pcmcia
+ *
+ * Revision 2.32  1999/08/28 22:11:10  keil
+ * __setup function should be static
+ *
  * Revision 2.31  1999/08/25 16:47:43  keil
  * Support new __setup; allow to add FEATURES after register_isdn
  *
@@ -224,6 +230,7 @@
 int avm_a1_init_pcmcia(void*, int, int*, int);
 #ifdef COMPAT_HAS_NEW_SYMTAB
 EXPORT_SYMBOL(avm_a1_init_pcmcia);
+EXPORT_SYMBOL(HiSax_closecard);
 #else
 static struct symbol_table hisax_syms_avm_a1= {
 #include <linux/symtab_begin.h>
@@ -521,9 +528,9 @@
 
 	printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
 #ifdef MODULE
-	printk(KERN_INFO "HiSax: Version 3.3 (module)\n");
+	printk(KERN_INFO "HiSax: Version 3.3a (module)\n");
 #else
-	printk(KERN_INFO "HiSax: Version 3.3 (kernel)\n");
+	printk(KERN_INFO "HiSax: Version 3.3a (kernel)\n");
 #endif
 	strcpy(tmp, l1_revision);
 	printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
@@ -555,8 +562,8 @@
 #else
 #ifdef COMPAT_HAS_NEW_SETUP
 #define MAX_ARG	(HISAX_MAX_CARDS*5)
-__initfunc(int
-HiSax_setup(char *line))
+static int __init
+HiSax_setup(char *line)
 {
 	int i, j, argc;
 	int ints[MAX_ARG + 1];
diff -u --recursive --new-file v2.3.15/linux/drivers/isdn/hisax/hfc_pci.c linux/drivers/isdn/hisax/hfc_pci.c
--- v2.3.15/linux/drivers/isdn/hisax/hfc_pci.c	Thu Aug 26 13:05:35 1999
+++ linux/drivers/isdn/hisax/hfc_pci.c	Mon Aug 30 16:27:43 1999
@@ -1,4 +1,4 @@
-/* $Id: hfc_pci.c,v 1.16 1999/08/25 17:01:27 keil Exp $
+/* $Id: hfc_pci.c,v 1.18 1999/08/29 17:05:44 werner Exp $
 
  * hfc_pci.c     low level driver for CCD´s hfc-pci based cards
  *
@@ -23,6 +23,12 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: hfc_pci.c,v $
+ * Revision 1.18  1999/08/29 17:05:44  werner
+ * corrected tx_lo line setup. Datasheet is not correct.
+ *
+ * Revision 1.17  1999/08/28 21:04:27  werner
+ * Implemented full audio support (transparent mode)
+ *
  * Revision 1.16  1999/08/25 17:01:27  keil
  * Use new LL->HL auxcmd call
  *
@@ -92,7 +98,7 @@
 
 extern const char *CardType[];
 
-static const char *hfcpci_revision = "$Revision: 1.16 $";
+static const char *hfcpci_revision = "$Revision: 1.18 $";
 
 /* table entry in the PCI devices list */
 typedef struct {
@@ -181,7 +187,7 @@
 	cs->hw.hfcpci.fifo_en = 0x30;	/* only D fifos enabled */
 	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
 
-	cs->hw.hfcpci.trm = 0; /* no echo connect */
+	cs->hw.hfcpci.trm = 0 + HFCPCI_BTRANS_THRESMASK; /* no echo connect , threshold */
 	Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
 
 	Write_hfc(cs, HFCPCI_CLKDEL, 0x0e);	/* ST-Bit delay for TE-Mode */
@@ -207,7 +213,7 @@
 	cs->hw.hfcpci.mst_m = HFCPCI_MASTER;	/* HFC Master Mode */
 
 	Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
-	cs->hw.hfcpci.sctrl = 0;
+	cs->hw.hfcpci.sctrl = 0x40; /* set tx_lo mode, error in datasheet ! */
 	Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
 	cs->hw.hfcpci.sctrl_r = 0;
 	Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
@@ -406,6 +412,59 @@
 	return (1);
 }
 
+/*******************************************************************************/
+/* check for transparent receive data and read max one threshold size if avail */
+/*******************************************************************************/
+int hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type *bz, u_char *bdata)
+{ unsigned short *z1r, *z2r;
+  int new_z2, fcnt, maxlen;
+  struct sk_buff *skb;
+  u_char *ptr, *ptr1;
+
+  z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */
+  z2r = z1r + 1; 
+
+  if (!(fcnt = *z1r - *z2r)) 
+    return(0); /* no data avail */
+
+  if (fcnt <= 0) 
+    fcnt += B_FIFO_SIZE; /* bytes actually buffered */  
+  if (fcnt > HFCPCI_BTRANS_THRESHOLD)
+    fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */
+
+  new_z2 = *z2r + fcnt;	/* new position in fifo */
+  if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
+    new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
+
+  if (!(skb = dev_alloc_skb(fcnt)))
+		printk(KERN_WARNING "HFCPCI: receive out of memory\n");
+  else {
+    SET_SKB_FREE(skb);
+    ptr = skb_put(skb, fcnt);
+    if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
+      maxlen = fcnt; /* complete transfer */
+    else
+      maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r;	/* maximum */
+
+    ptr1 = bdata + (*z2r - B_SUB_VAL);	/* start of data */
+    memcpy(ptr, ptr1, maxlen);	/* copy data */
+    fcnt -= maxlen;
+
+    if (fcnt) {	/* rest remaining */
+      ptr += maxlen;
+      ptr1 = bdata;	/* start of buffer */
+      memcpy(ptr, ptr1, fcnt);	/* rest */
+    }
+    cli();
+    skb_queue_tail(&bcs->rqueue, skb);
+    sti();
+    hfcpci_sched_event(bcs, B_RCVBUFREADY); 
+  }
+  
+  *z2r = new_z2; /* new position */
+  return(1);
+} /* hfcpci_empty_fifo_trans */ 
+
 /**********************************/
 /* B-channel main receive routine */
 /**********************************/
@@ -465,8 +524,11 @@
 			receive = 1;
 		else
 			receive = 0;
-	} else
-		receive = 0;
+	} else 
+	  if (bcs->mode == L1_MODE_TRANS)
+	    receive = hfcpci_empty_fifo_trans(bcs, bz, bdata);
+	  else
+	    receive = 0;
 	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 	if (count && receive)
 		goto Begin;
@@ -558,6 +620,7 @@
 	bzfifo_type *bz;
 	u_char *bdata;
 	u_char new_f1, *src, *dst;
+        unsigned short *z1t, *z2t;
 
 	if (!bcs->tx_skb)
 		return;
@@ -575,8 +638,60 @@
 		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b1;
 	}
 
+	if (bcs->mode == L1_MODE_TRANS) {
+	  z1t = &bz->za[MAX_B_FRAMES].z1;
+	  z2t = z1t + 1;
+	  if (cs->debug & L1_DEB_HSCX)
+	          debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)",
+		  bcs->channel, *z1t, *z2t);
+	  fcnt = *z2t - *z1t;
+	  if (fcnt <= 0)
+	          fcnt += B_FIFO_SIZE;	/* fcnt contains available bytes in fifo */
+	  fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */
+
+	  while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) {
+	    if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) { 
+	      /* data is suitable for fifo */
+	      count = bcs->tx_skb->len;
+
+	      new_z1 = *z1t + count;	/* new buffer Position */
+	      if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
+		new_z1 -= B_FIFO_SIZE;	/* buffer wrap */
+	      src = bcs->tx_skb->data;	/* source pointer */
+	      dst = bdata + (*z1t - B_SUB_VAL);
+	      maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t; /* end of fifo */
+	      if (maxlen > count)
+		maxlen = count;	/* limit size */
+	      memcpy(dst, src, maxlen);	/* first copy */
+
+	      count -= maxlen;	/* remaining bytes */
+	      if (count) {
+		dst = bdata;	/* start of buffer */
+		src += maxlen;	/* new position */
+		memcpy(dst, src, count);
+	      }
+	      bcs->tx_cnt -= bcs->tx_skb->len;
+	      fcnt += bcs->tx_skb->len;
+	      *z1t = new_z1; /* now send data */
+	    }
+            else 
+	      if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded",
+			bcs->channel, bcs->tx_skb->len);
+
+	    idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+            cli();
+            bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */
+            sti();
+	  }  
+	  test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	  restore_flags(flags);
+	  return;
+	}
+
+
 	if (cs->debug & L1_DEB_HSCX)
-		debugl1(cs, "hfcpci_fill_fifo %d f1(%d) f2(%d) z1(f1)(%x)",
+		debugl1(cs, "hfcpci_fill_fifo_hdlc %d f1(%d) f2(%d) z1(f1)(%x)",
 			bcs->channel, bz->f1, bz->f2,
 			bz->za[bz->f1].z1);
 
@@ -1125,6 +1240,7 @@
 mode_hfcpci(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
+	bzfifo_type *bzr, *bzt;
 	int flags;
 
 	if (cs->debug & L1_DEB_HSCX)
@@ -1171,6 +1287,8 @@
 				cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
 				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
 				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC);
+		                bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
+		                bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2;
 			} else {
 				cs->hw.hfcpci.ctmt |= 1;
 				cs->hw.hfcpci.conn &= ~0x03;
@@ -1178,7 +1296,17 @@
 				cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
 				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
 				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
+		                bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1;
+		                bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1;
 			}
+			bzr->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
+                        bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1; 
+			bzr->f1 = MAX_B_FRAMES;
+			bzr->f2 = bzr->f1; /* init F pointers to remain constant */
+			bzt->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
+                        bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1; 
+			bzt->f1 = MAX_B_FRAMES;
+			bzt->f2 = bzt->f1; /* init F pointers to remain constant */
 			break;
 		case (L1_MODE_HDLC):
 			if (bc) {
diff -u --recursive --new-file v2.3.15/linux/drivers/isdn/hisax/hfc_pci.h linux/drivers/isdn/hisax/hfc_pci.h
--- v2.3.15/linux/drivers/isdn/hisax/hfc_pci.h	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/hisax/hfc_pci.h	Mon Aug 30 16:27:43 1999
@@ -1,4 +1,4 @@
-/* $Id: hfc_pci.h,v 1.5 1999/08/09 19:13:34 werner Exp $
+/* $Id: hfc_pci.h,v 1.6 1999/08/28 21:04:29 werner Exp $
 
  *  specific defines for CCD's HFC 2BDS0 PCI chips
  *
@@ -21,6 +21,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: hfc_pci.h,v $
+ * Revision 1.6  1999/08/28 21:04:29  werner
+ * Implemented full audio support (transparent mode)
+ *
  * Revision 1.5  1999/08/09 19:13:34  werner
  * moved constant pci ids to pci id table
  *
@@ -36,6 +39,14 @@
  *
  *
  */
+
+/*********************************************/
+/* thresholds for transparent B-channel mode */
+/* change mask and threshold simultaneously  */
+/*********************************************/
+#define HFCPCI_BTRANS_THRESHOLD 128
+#define HFCPCI_BTRANS_THRESMASK 0x00
+
 
 
 /* defines for PCI config */
diff -u --recursive --new-file v2.3.15/linux/drivers/isdn/hisax/sedlbauer.c linux/drivers/isdn/hisax/sedlbauer.c
--- v2.3.15/linux/drivers/isdn/hisax/sedlbauer.c	Thu Aug 26 13:05:37 1999
+++ linux/drivers/isdn/hisax/sedlbauer.c	Mon Aug 30 16:27:43 1999
@@ -1,4 +1,4 @@
-/* $Id: sedlbauer.c,v 1.15 1999/08/25 17:00:00 keil Exp $
+/* $Id: sedlbauer.c,v 1.16 1999/08/29 18:23:01 niemann Exp $
 
  * sedlbauer.c  low level stuff for Sedlbauer cards
  *              includes support for the Sedlbauer speed star (speed star II),
@@ -17,6 +17,9 @@
  *            Edgar Toernig
  *
  * $Log: sedlbauer.c,v $
+ * Revision 1.16  1999/08/29 18:23:01  niemann
+ * Fixed typo in errormsg
+ *
  * Revision 1.15  1999/08/25 17:00:00  keil
  * Make ISAR V32bis modem running
  * Make LL->HL interface open for additional commands
@@ -103,7 +106,7 @@
 
 extern const char *CardType[];
 
-const char *Sedlbauer_revision = "$Revision: 1.15 $";
+const char *Sedlbauer_revision = "$Revision: 1.16 $";
 
 const char *Sedlbauer_Types[] =
 	{"None", "speed card/win", "speed star", "speed fax+", 
@@ -584,7 +587,7 @@
 #if CONFIG_PCI
 #ifdef COMPAT_HAS_NEW_PCI
 		if (!pci_present()) {
-			printk(KERN_ERR "FritzPCI: no PCI bus present\n");
+			printk(KERN_ERR "Sedlbauer: no PCI bus present\n");
 			return(0);
 		}
 		if ((dev_sedl = pci_find_device(PCI_VENDOR_SEDLBAUER,
diff -u --recursive --new-file v2.3.15/linux/drivers/isdn/hisax/teles3.c linux/drivers/isdn/hisax/teles3.c
--- v2.3.15/linux/drivers/isdn/hisax/teles3.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/hisax/teles3.c	Mon Aug 30 16:27:43 1999
@@ -1,4 +1,4 @@
-/* $Id: teles3.c,v 2.12 1999/07/12 21:05:32 keil Exp $
+/* $Id: teles3.c,v 2.13 1999/08/30 12:01:28 keil Exp $
 
  * teles3.c     low level stuff for Teles 16.3 & PNP isdn cards
  *
@@ -11,6 +11,9 @@
  *              Beat Doebeli
  *
  * $Log: teles3.c,v $
+ * Revision 2.13  1999/08/30 12:01:28  keil
+ * HW version v1.3 support
+ *
  * Revision 2.12  1999/07/12 21:05:32  keil
  * fix race in IRQ handling
  * added watchdog for lost IRQs
@@ -85,7 +88,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *teles3_revision = "$Revision: 2.12 $";
+const char *teles3_revision = "$Revision: 2.13 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -464,9 +467,10 @@
 							 * 0x1f=with AB
 							 * 0x1c 16.3 ???
 							 * 0x39 16.3 1.1
+							 * 0x38 16.3 1.3
 							 * 0x46 16.3 with AB + Video (Teles-Vision)
 							 */
-		if (val != 0x46 && val != 0x39 && val != 0x1c && val != 0x1e && val != 0x1f) {
+		if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) {
 			printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n",
 			       cs->hw.teles3.cfg_reg + 2, val);
 			release_io_teles3(cs);
diff -u --recursive --new-file v2.3.15/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c
--- v2.3.15/linux/drivers/isdn/icn/icn.c	Thu Aug 26 13:05:37 1999
+++ linux/drivers/isdn/icn/icn.c	Mon Aug 30 16:27:43 1999
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.58 1999/08/25 16:44:17 keil Exp $
+/* $Id: icn.c,v 1.59 1999/08/28 22:10:55 keil Exp $
 
  * ISDN low-level module for the ICN active ISDN-Card.
  *
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: icn.c,v $
+ * Revision 1.59  1999/08/28 22:10:55  keil
+ * __setup function should be static
+ *
  * Revision 1.58  1999/08/25 16:44:17  keil
  * Support for new __setup function
  *
@@ -235,7 +238,7 @@
 #undef MAP_DEBUG
 
 static char
-*revision = "$Revision: 1.58 $";
+*revision = "$Revision: 1.59 $";
 
 static int icn_addcard(int, char *, char *);
 
@@ -1851,7 +1854,7 @@
 #else
 #ifdef COMPAT_HAS_NEW_SETUP
 #include <linux/init.h>
-int
+static int __init
 icn_setup(char *line)
 {
 	char *p, *str;
diff -u --recursive --new-file v2.3.15/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- v2.3.15/linux/drivers/isdn/isdn_tty.c	Thu Aug 12 09:42:33 1999
+++ linux/drivers/isdn/isdn_tty.c	Tue Aug 31 11:30:48 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.72 1999/07/31 12:59:45 armin Exp $
+/* $Id: isdn_tty.c,v 1.73 1999/08/28 21:56:27 keil Exp $
 
  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
@@ -20,6 +20,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.c,v $
+ * Revision 1.73  1999/08/28 21:56:27  keil
+ * misplaced #endif caused ttyI crash in 2.3.X
+ *
  * Revision 1.72  1999/07/31 12:59:45  armin
  * Added tty fax capabilities.
  *
@@ -345,7 +348,7 @@
 static int si2bit[8] =
 {4, 1, 4, 4, 4, 4, 4, 4};
 
-char *isdn_tty_revision = "$Revision: 1.72 $";
+char *isdn_tty_revision = "$Revision: 1.73 $";
 
 
 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
@@ -1981,7 +1984,7 @@
 	restore_flags(flags);
 	info->blocked_open++;
 	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ISDN_ASYNC_INITIALIZED)) {
 #ifdef MODEM_DO_RESTART
@@ -2399,8 +2402,8 @@
 #else
 		info->open_wait = 0;
 		info->close_wait = 0;
-		info->isdn_driver = -1;
 #endif
+		info->isdn_driver = -1;
 		info->isdn_channel = -1;
 		info->drv_index = -1;
 		info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
diff -u --recursive --new-file v2.3.15/linux/drivers/isdn/pcbit/module.c linux/drivers/isdn/pcbit/module.c
--- v2.3.15/linux/drivers/isdn/pcbit/module.c	Thu Aug 26 13:05:37 1999
+++ linux/drivers/isdn/pcbit/module.c	Mon Aug 30 16:27:43 1999
@@ -105,7 +105,7 @@
 #ifdef COMPAT_HAS_NEW_SETUP
 #define MAX_PARA	(MAX_PCBIT_CARDS * 2)
 #include <linux/init.h>
-int pcbit_setup(char *line)
+static int __init pcbit_setup(char *line)
 {
 	int i, j, argc;
 	char *str;
diff -u --recursive --new-file v2.3.15/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c
--- v2.3.15/linux/drivers/macintosh/mac_keyb.c	Thu Aug 12 11:50:14 1999
+++ linux/drivers/macintosh/mac_keyb.c	Tue Aug 31 11:35:59 1999
@@ -269,8 +269,6 @@
 
 static int adb_mouse_kinds[16];
 
-__openfirmware
-
 int mackbd_setkeycode(unsigned int scancode, unsigned int keycode)
 {
 	return -EINVAL;
diff -u --recursive --new-file v2.3.15/linux/drivers/macintosh/macio-adb.c linux/drivers/macintosh/macio-adb.c
--- v2.3.15/linux/drivers/macintosh/macio-adb.c	Wed Aug  4 16:36:41 1999
+++ linux/drivers/macintosh/macio-adb.c	Tue Aug 31 11:35:59 1999
@@ -74,8 +74,6 @@
 	macio_adb_poll
 };
 
-__openfirmware
-
 void macio_adb_init(void)
 {
 	struct device_node *adbs;
diff -u --recursive --new-file v2.3.15/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c
--- v2.3.15/linux/drivers/macintosh/macserial.c	Thu Aug 12 11:50:14 1999
+++ linux/drivers/macintosh/macserial.c	Tue Aug 31 11:35:59 1999
@@ -9,6 +9,7 @@
 
 #include <linux/config.h>
 #include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
@@ -26,6 +27,7 @@
 #include <linux/console.h>
 #endif
 
+#include <asm/init.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
@@ -135,13 +137,13 @@
  * buffer across all the serial ports, since it significantly saves
  * memory if large numbers of serial ports are open.
  */
-static unsigned char tmp_buf[4096]; /* This is cheating */
-DECLARE_MUTEX(tmp_buf_sem);
+static unsigned char *tmp_buf;
+static DECLARE_MUTEX(tmp_buf_sem);
 
 
 static inline int __pmac
 serial_paranoia_check(struct mac_serial *info,
-					dev_t device, const char *routine)
+		      dev_t device, const char *routine)
 {
 #ifdef SERIAL_PARANOIA_CHECK
 	static const char *badmagic =
@@ -165,7 +167,7 @@
  * Reading and writing Z8530 registers.
  */
 static inline unsigned char __pmac read_zsreg(struct mac_zschannel *channel,
-				       unsigned char reg)
+					      unsigned char reg)
 {
 	unsigned char retval;
 	unsigned long flags;
@@ -185,7 +187,7 @@
 }
 
 static inline void __pmac write_zsreg(struct mac_zschannel *channel,
-			       unsigned char reg, unsigned char value)
+				      unsigned char reg, unsigned char value)
 {
 	unsigned long flags;
 
@@ -357,8 +359,12 @@
 
 static void transmit_chars(struct mac_serial *info)
 {
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
 	if ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0)
-		return;
+		goto out;
 	info->tx_active = 0;
 
 	if (info->x_char) {
@@ -366,12 +372,12 @@
 		write_zsdata(info->zs_channel, info->x_char);
 		info->x_char = 0;
 		info->tx_active = 1;
-		return;
+		goto out;
 	}
 
 	if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped) {
 		write_zsreg(info->zs_channel, 0, RES_Tx_P);
-		return;
+		goto out;
 	}
 
 	/* Send char */
@@ -382,6 +388,9 @@
 
 	if (info->xmit_cnt < WAKEUP_CHARS)
 		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+
+ out:
+	restore_flags(flags);
 }
 
 static _INLINE_ void status_handle(struct mac_serial *info)
@@ -764,8 +773,10 @@
 			 */
 			mdelay(250);
 		}
+#ifdef CONFIG_PMAC_PBOOK
 		if (info->is_pwbk_ir)
 			pmu_enable_irled(1);
+#endif /* CONFIG_PMAC_PBOOK */
 	} else {
 #ifdef SERIAL_DEBUG_POWER
 		printk(KERN_INFO "ttyS%02d: shutting down hardware\n", info->line);
@@ -795,8 +806,10 @@
 			feature_clear(info->dev_node, FEATURE_Modem_Reset);
 			mdelay(25);
 		}
+#ifdef CONFIG_PMAC_PBOOK
 		if (info->is_pwbk_ir)
 			pmu_enable_irled(0);
+#endif /* CONFIG_PMAC_PBOOK */
 			
 		if (info->zs_chan_a == info->zs_channel) {
 #ifdef SERIAL_DEBUG_POWER
@@ -987,7 +1000,6 @@
 static void rs_flush_chars(struct tty_struct *tty)
 {
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
-	unsigned long flags;
 
 	if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))
 		return;
@@ -997,53 +1009,76 @@
 		return;
 
 	/* Enable transmitter */
-	save_flags(flags); cli();
 	transmit_chars(info);
-	restore_flags(flags);
 }
 
 static int rs_write(struct tty_struct * tty, int from_user,
 		    const unsigned char *buf, int count)
 {
-	int	c, total = 0;
+	int	c, ret = 0;
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
 	unsigned long flags;
 
 	if (serial_paranoia_check(info, tty->device, "rs_write"))
 		return 0;
 
-	if (!tty || !info->xmit_buf)
+	if (!tty || !info->xmit_buf || !tmp_buf)
 		return 0;
 
 	save_flags(flags);
-	while (1) {
-		cli();		
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - info->xmit_head));
-		if (c <= 0)
-			break;
-
-		if (from_user) {
-			down(&tmp_buf_sem);
-			copy_from_user(tmp_buf, buf, c);
+	if (from_user) {
+		down(&tmp_buf_sem);
+		while (1) {
+			c = MIN(count,
+				MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				    SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0)
+				break;
+
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!ret)
+					ret = -EFAULT;
+				break;
+			}
+			cli();
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - info->xmit_head));
 			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
-			up(&tmp_buf_sem);
-		} else
+			info->xmit_head = ((info->xmit_head + c) &
+					   (SERIAL_XMIT_SIZE-1));
+			info->xmit_cnt += c;
+			restore_flags(flags);
+			buf += c;
+			count -= c;
+			ret += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();		
+			c = MIN(count,
+				MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				    SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
 			memcpy(info->xmit_buf + info->xmit_head, buf, c);
-		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		info->xmit_cnt += c;
-		restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
+			info->xmit_head = ((info->xmit_head + c) &
+					   (SERIAL_XMIT_SIZE-1));
+			info->xmit_cnt += c;
+			restore_flags(flags);
+			buf += c;
+			count -= c;
+			ret += c;
+		}
 	}
 	if (info->xmit_cnt && !tty->stopped && !info->tx_stopped
 	    && !info->tx_active)
 		transmit_chars(info);
 	restore_flags(flags);
-	return total;
+	return ret;
 }
 
 static int rs_write_room(struct tty_struct *tty)
@@ -1186,7 +1221,9 @@
 	tmp.close_delay = info->close_delay;
 	tmp.closing_wait = info->closing_wait;
 	tmp.custom_divisor = info->custom_divisor;
-	return copy_to_user(retinfo,&tmp,sizeof(*retinfo));
+	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
 }
 
 static int set_serial_info(struct mac_serial * info,
@@ -1196,9 +1233,8 @@
 	struct mac_serial old_info;
 	int 			retval = 0;
 
-	if (!new_info)
+	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
 		return -EFAULT;
-	copy_from_user(&new_serial,new_info,sizeof(new_serial));
 	old_info = *info;
 
 	if (!capable(CAP_SYS_ADMIN)) {
@@ -1248,29 +1284,30 @@
 static int get_lsr_info(struct mac_serial * info, unsigned int *value)
 {
 	unsigned char status;
+	unsigned long flags;
 
-	cli();
+	save_flags(flags); cli();
 	status = read_zsreg(info->zs_channel, 0);
-	sti();
-	put_user(status,value);
-	return 0;
+	restore_flags(flags);
+	status = (status & Tx_BUF_EMP)? TIOCSER_TEMT: 0;
+	return put_user(status,value);
 }
 
 static int get_modem_info(struct mac_serial *info, unsigned int *value)
 {
 	unsigned char control, status;
 	unsigned int result;
+	unsigned long flags;
 
-	cli();
+	save_flags(flags); cli();
 	control = info->curregs[5];
 	status = read_zsreg(info->zs_channel, 0);
-	sti();
+	restore_flags(flags);
 	result =  ((control & RTS) ? TIOCM_RTS: 0)
 		| ((control & DTR) ? TIOCM_DTR: 0)
 		| ((status  & DCD) ? TIOCM_CAR: 0)
 		| ((status  & CTS) ? 0: TIOCM_CTS);
-	put_user(result,value);
-	return 0;
+	return put_user(result,value);
 }
 
 static int set_modem_info(struct mac_serial *info, unsigned int cmd,
@@ -1278,13 +1315,13 @@
 {
 	int error;
 	unsigned int arg, bits;
+	unsigned long flags;
 
-	error = verify_area(VERIFY_READ, value, sizeof(int));
+	error = get_user(arg, value);
 	if (error)
 		return error;
-	get_user(arg, value);
 	bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0);
-	cli();
+	save_flags(flags); cli();
 	switch (cmd) {
 	case TIOCMBIS:
 		info->curregs[5] |= bits;
@@ -1296,12 +1333,12 @@
 		info->curregs[5] = (info->curregs[5] & ~(DTR | RTS)) | bits;
 		break;
 	default:
-		sti();
+		restore_flags(flags);
 		return -EINVAL;
 	}
 	info->pendregs[5] = info->curregs[5];
 	write_zsreg(info->zs_channel, 5, info->curregs[5]);
-	sti();
+	restore_flags(flags);
 	return 0;
 }
 
@@ -1330,7 +1367,6 @@
 static int rs_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 {
-	int error;
 	struct mac_serial * info = (struct mac_serial *)tty->driver_data;
 
 #ifdef CONFIG_KGDB
@@ -1341,48 +1377,31 @@
 		return -ENODEV;
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&
-	    (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
+	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
 	
 	switch (cmd) {
 		case TIOCMGET:
-			error = verify_area(VERIFY_WRITE, (void *) arg,
-				sizeof(unsigned int));
-			if (error)
-				return error;
 			return get_modem_info(info, (unsigned int *) arg);
 		case TIOCMBIS:
 		case TIOCMBIC:
 		case TIOCMSET:
 			return set_modem_info(info, cmd, (unsigned int *) arg);
 		case TIOCGSERIAL:
-			error = verify_area(VERIFY_WRITE, (void *) arg,
-						sizeof(struct serial_struct));
-			if (error)
-				return error;
 			return get_serial_info(info,
 					       (struct serial_struct *) arg);
 		case TIOCSSERIAL:
 			return set_serial_info(info,
 					       (struct serial_struct *) arg);
 		case TIOCSERGETLSR: /* Get line status register */
-			error = verify_area(VERIFY_WRITE, (void *) arg,
-				sizeof(unsigned int));
-			if (error)
-				return error;
-			else
-			    return get_lsr_info(info, (unsigned int *) arg);
+			return get_lsr_info(info, (unsigned int *) arg);
 
 		case TIOCSERGSTRUCT:
-			error = verify_area(VERIFY_WRITE, (void *) arg,
-						sizeof(struct mac_serial));
-			if (error)
-				return error;
-			copy_from_user((struct mac_serial *) arg,
-				       info, sizeof(struct mac_serial));
+			if (copy_to_user((struct mac_serial *) arg,
+					 info, sizeof(struct mac_serial)))
+				return -EFAULT;
 			return 0;
 			
 		default:
@@ -1674,7 +1693,7 @@
 		    (tty->termios->c_cflag & CBAUD))
 			zs_rtsdtr(info, 1);
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ZILOG_INITIALIZED)) {
 #ifdef SERIAL_DO_RESTART
@@ -1726,6 +1745,7 @@
 {
 	struct mac_serial	*info;
 	int 			retval, line;
+	unsigned long		page;
 
 	line = MINOR(tty->device) - tty->driver.minor_start;
 	if ((line < 0) || (line >= zs_channels_found))
@@ -1747,6 +1767,16 @@
 	tty->driver_data = info;
 	info->tty = tty;
 
+	if (!tmp_buf) {
+		page = get_free_page(GFP_KERNEL);
+		if (!page)
+			return -ENOMEM;
+		if (tmp_buf)
+			free_page(page);
+		else
+			tmp_buf = (unsigned char *) page;
+	}
+
 	/*
 	 * If the port is the middle of closing, bail out now
 	 */
@@ -1817,6 +1847,7 @@
 	struct device_node *dev, *ch;
 	struct mac_serial **pp;
 	int n, lenp;
+	char *conn;
 
 	n = 0;
 	pp = &zs_chain;
@@ -1842,9 +1873,11 @@
 			zs_soft[n].zs_channel->parent = &zs_soft[n];
 			zs_soft[n].is_cobalt_modem = device_is_compatible(ch, "cobalt");
 
-			/* XXX tested only with wallstreet PowerBook, should do no harm anyway */	
-			zs_soft[n].is_pwbk_ir = (strcmp(get_property(ch, "AAPL,connector",
-				&lenp), "infrared") == 0);
+			/* XXX tested only with wallstreet PowerBook,
+			   should do no harm anyway */
+			conn = get_property(ch, "AAPL,connector", &lenp);
+			zs_soft[n].is_pwbk_ir =
+				conn && (strcmp(conn, "infrared") == 0);
 
 			/* XXX this assumes the prom puts chan A before B */
 			if (n & 1)
@@ -2024,6 +2057,30 @@
 
 	return 0;
 }
+
+#ifdef MODULE
+int init_module(void)
+{
+	macserial_init();
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	int i;
+	unsigned long flags;
+	struct mac_serial *info;
+
+	for (info = zs_chain, i = 0; info; info = info->zs_next, i++)
+		set_scc_power(info, 0);
+	save_flags(flags); cli();
+	for (i = 0; i < zs_channels_found; ++i)
+		free_irq(zs_soft[i].irq, &zs_soft[i]);
+	restore_flags(flags);
+	tty_unregister_driver(&callout_driver);
+	tty_unregister_driver(&serial_driver);
+}
+#endif /* MODULE */
 
 #if 0
 /*
diff -u --recursive --new-file v2.3.15/linux/drivers/macintosh/mediabay.c linux/drivers/macintosh/mediabay.c
--- v2.3.15/linux/drivers/macintosh/mediabay.c	Wed Aug  4 16:36:41 1999
+++ linux/drivers/macintosh/mediabay.c	Tue Aug 31 11:35:59 1999
@@ -25,7 +25,7 @@
 #include <asm/io.h>
 #include <asm/feature.h>
 #include <asm/mediabay.h>
-#include <linux/init.h>
+#include <asm/init.h>
 
 
 #undef MB_USE_INTERRUPTS
@@ -64,8 +64,7 @@
 #ifdef CONFIG_BLK_DEV_IDE
 /* check the busy bit in the media-bay ide interface
    (assumes the media-bay contains an ide device) */
-#define MB_IDE_READY(i)	((in_8((volatile unsigned char *) \
-			       (media_bays[i].cd_base + 0x70)) & 0x80) == 0)
+#define MB_IDE_READY(i)	((inb(media_bays[i].cd_base + 0x70) & 0x80) == 0)
 #endif
 
 /*
diff -u --recursive --new-file v2.3.15/linux/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c
--- v2.3.15/linux/drivers/macintosh/nvram.c	Mon Aug  9 10:23:09 1999
+++ linux/drivers/macintosh/nvram.c	Tue Aug 31 11:35:59 1999
@@ -17,12 +17,6 @@
 
 #define NVRAM_SIZE	8192
 
-/* when building as a module, __openfirmware is both unavailable
- * and unnecessary. */
-#ifndef MODULE
-__openfirmware
-#endif
-
 static long long nvram_llseek(struct file *file, loff_t offset, int origin)
 {
 	switch (origin) {
diff -u --recursive --new-file v2.3.15/linux/drivers/macintosh/via-cuda.c linux/drivers/macintosh/via-cuda.c
--- v2.3.15/linux/drivers/macintosh/via-cuda.c	Wed Aug  4 16:36:41 1999
+++ linux/drivers/macintosh/via-cuda.c	Tue Aug 31 11:35:59 1999
@@ -94,8 +94,6 @@
 	cuda_poll
 };
 
-__openfirmware
-
 void
 find_via_cuda()
 {
@@ -340,10 +338,11 @@
 {
     int ie;
 
-    ie = _disable_interrupts();
+    __save_flags(ie);
+    __cli();
     if (via[IFR] & SR_INT)
 	via_interrupt(0, 0, 0);
-    _enable_interrupts(ie);
+    __restore_flags(ie);
 }
 
 static void
@@ -496,4 +495,4 @@
 cuda_present(void)
 {
 	return (adb_controller && (adb_controller->kind == ADB_VIACUDA) && via);
-}
\ No newline at end of file
+}
diff -u --recursive --new-file v2.3.15/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
--- v2.3.15/linux/drivers/macintosh/via-pmu.c	Wed Aug  4 16:36:41 1999
+++ linux/drivers/macintosh/via-pmu.c	Tue Aug 31 11:35:59 1999
@@ -28,7 +28,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
-#include <linux/init.h>
+#include <asm/init.h>
 #include <asm/irq.h>
 #include <asm/feature.h>
 #include <asm/uaccess.h>
@@ -556,10 +556,11 @@
 {
 	int ie;
 
-	ie = _disable_interrupts();
+	__save_flags(ie);
+	__cli();
 	if (via[IFR] & (SR_INT | CB1_INT))
 		via_pmu_interrupt(0, 0, 0);
-	_enable_interrupts(ie);
+	__restore_flags(ie);
 }
 
 static void __openfirmware
@@ -846,7 +847,7 @@
 {
 	struct adb_request req;
 
-	_disable_interrupts();
+	__cli();
 	
 	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
 					PMU_INT_TICK );
@@ -865,7 +866,7 @@
 {
 	struct adb_request req;
 
-	_disable_interrupts();
+	__cli();
 	
 	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
 					PMU_INT_TICK );
@@ -945,9 +946,9 @@
 			for (j = 0; j < 6; ++j)
 				pci_write_config_dword(pd,
 					PCI_BASE_ADDRESS_0 + j*4,
-					pd->base_address[j]);
+					pd->resource[j].start);
 			pci_write_config_dword(pd, PCI_ROM_ADDRESS,
-				pd->rom_address);
+			       pd->resource[PCI_ROM_RESOURCE].start);
 			pci_write_config_word(pd, PCI_CACHE_LINE_SIZE,
 				ps->cache_lat);
 			pci_write_config_word(pd, PCI_INTERRUPT_LINE,
diff -u --recursive --new-file v2.3.15/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.3.15/linux/drivers/net/8390.c	Wed Aug 18 11:36:41 1999
+++ linux/drivers/net/8390.c	Thu Aug 26 14:24:44 1999
@@ -983,7 +983,7 @@
 }	
 
 /*
- * Initialize the rest of the 8390 device structure.  Do NOT __initfunc
+ * Initialize the rest of the 8390 device structure.  Do NOT __init
  * this, as it is used by 8390 based modular drivers too.
  */
 
diff -u --recursive --new-file v2.3.15/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
--- v2.3.15/linux/drivers/net/arcnet.c	Wed Aug 18 11:36:41 1999
+++ linux/drivers/net/arcnet.c	Mon Aug 30 10:29:44 1999
@@ -472,7 +472,7 @@
 #ifdef CONFIG_ARCNET_1051
   /* Initialize the RFC1051-encap protocol driver */
   lp->sdev=(struct net_device *)kmalloc(sizeof(struct net_device)+10,GFP_KERNEL);
-  if(lp->sdev = NULL)
+  if(lp->sdev == NULL)
   {
   	if(lp->edev)
   		kfree(lp->edev);
diff -u --recursive --new-file v2.3.15/linux/drivers/net/arlan.c linux/drivers/net/arlan.c
--- v2.3.15/linux/drivers/net/arlan.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/net/arlan.c	Thu Aug 26 14:25:39 1999
@@ -72,11 +72,9 @@
 
 //        #warning kernel 2.1.110 tested
 #define myATOMIC_INIT(a,b) atomic_set(&(a),b)
-#define __initfunctio(a)                __initfunc(a)
 
 #else
 #define test_and_set_bit	set_bit
-#define __initfunctio(a)        a
 #if LINUX_VERSION_CODE != 0x20024
  //        #warning kernel  2.0.36  tested
 #endif
@@ -1034,7 +1032,7 @@
  * verifies that the correct device exists and functions.
  */
 
-__initfunctio(static int arlan_check_fingerprint(int memaddr))
+static int __init arlan_check_fingerprint(int memaddr)
 {
 	static char probeText[] = "TELESYSTEM SLW INC.    ARLAN \0";
 	char tempBuf[49];
@@ -1056,7 +1054,7 @@
 
 }
 
-__initfunctio(int arlan_probe_everywhere(struct net_device *dev))
+int __init arlan_probe_everywhere(struct net_device *dev)
 {
 	int m;
 	int probed = 0;
@@ -1094,7 +1092,7 @@
 	return ENODEV;
 }
 
-__initfunctio(int arlan_find_devices(void))
+int __init arlan_find_devices(void)
 {
 	int m;
 	int found = 0;
@@ -1153,8 +1151,8 @@
 
 
 
-__initfunctio(static int
-	      arlan_allocate_device(int num, struct net_device *devs))
+static int __init
+	      arlan_allocate_device(int num, struct net_device *devs)
 {
 
 	struct net_device *dev;
@@ -1214,7 +1212,7 @@
 }
 
 
-__initfunctio(int arlan_probe_here(struct net_device *dev, int memaddr))
+int __init arlan_probe_here(struct net_device *dev, int memaddr)
 {
 	volatile struct arlan_shmem *arlan;
 
@@ -1992,7 +1990,7 @@
 }
 
 
-__initfunctio(int arlan_probe(struct net_device *dev))
+int __init arlan_probe(struct net_device *dev)
 {
 	printk("Arlan driver %s\n", arlan_version);
 
diff -u --recursive --new-file v2.3.15/linux/drivers/net/bagetlance.c linux/drivers/net/bagetlance.c
--- v2.3.15/linux/drivers/net/bagetlance.c	Wed Aug 18 11:36:41 1999
+++ linux/drivers/net/bagetlance.c	Thu Aug 26 14:26:09 1999
@@ -469,7 +469,7 @@
 }
 
 
-__initfunc(int bagetlance_probe( struct net_device *dev ))
+int __init bagetlance_probe( struct net_device *dev )
 
 {	int i;
 	static int found = 0;
@@ -493,9 +493,9 @@
 
 /* Derived from hwreg_present() in vme/config.c: */
 
-__initfunc(static int addr_accessible( volatile void *regp, 
-									   int wordflag, 
-									   int writeflag ))
+static int __init addr_accessible( volatile void *regp, 
+				   int wordflag, 
+				   int writeflag )
 {	
 		/* We have a fine function to do it */
 		extern int try_read(unsigned long, int);
@@ -508,8 +508,8 @@
 #define IRQ_TYPE_PRIO SA_INTERRUPT
 #define IRQ_SOURCE_TO_VECTOR(x) (x)
 
-__initfunc(static unsigned long lance_probe1( struct net_device *dev,
-								   struct lance_addr *init_rec ))
+static unsigned long __init lance_probe1( struct net_device *dev,
+					   struct lance_addr *init_rec )
 
 {	volatile unsigned short *memaddr =
 		(volatile unsigned short *)init_rec->memaddr;
diff -u --recursive --new-file v2.3.15/linux/drivers/net/bmac.c linux/drivers/net/bmac.c
--- v2.3.15/linux/drivers/net/bmac.c	Wed Aug 18 11:36:41 1999
+++ linux/drivers/net/bmac.c	Tue Aug 31 11:35:59 1999
@@ -297,7 +297,6 @@
 	val = bmac_mif_readbits(dev, 17);
 	bmwrite(dev, MIFCSR, 4);
 	MIFDELAY;
-	/* printk(KERN_DEBUG "bmac_mif_read(%x) -> %x\n", addr, val); */
 	return val;
 }
 
@@ -431,18 +430,26 @@
 static int
 bmac_init_chip(struct net_device *dev)
 {
-	if (is_bmac_plus && bmac_mif_read(dev, 2) == 0x7810) {
-		if (bmac_mif_read(dev, 4) == 0xa1) {
-			bmac_mif_write(dev, 0, 0x1000);
-		} else {
-			bmac_mif_write(dev, 4, 0xa1);
+	unsigned int addr;
+
+	printk(KERN_DEBUG "phy registers:");
+	for (addr = 0; addr < 32; ++addr) {
+		if ((addr & 7) == 0)
+			printk("\n" KERN_DEBUG);
+		printk(" %.4x", bmac_mif_read(dev, addr));
+	}
+	printk("\n");
+	if (is_bmac_plus) {
+		unsigned int capable, ctrl;
+
+		ctrl = bmac_mif_read(dev, 0);
+		capable = ((bmac_mif_read(dev, 1) & 0xf800) >> 6) | 1;
+		if (bmac_mif_read(dev, 4) != capable
+		    || (ctrl & 0x1000) == 0) {
+			bmac_mif_write(dev, 4, capable);
 			bmac_mif_write(dev, 0, 0x1200);
-		}
-#if 0
-		/* XXX debugging */
-		bmac_mif_read(dev, 0);
-		bmac_mif_read(dev, 4);
-#endif
+		} else
+			bmac_mif_write(dev, 0, 0x1000);
 	}
 	bmac_init_registers(dev);
 	return 1;
@@ -1330,6 +1337,7 @@
 
 	dev->flags |= IFF_UP | IFF_RUNNING;
 
+	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -1374,6 +1382,8 @@
 	}
 	bp->reset_and_enabled = 0;
 	XXDEBUG(("bmac: all bufs freed\n"));
+
+	MOD_DEC_USE_COUNT;
 
 	return 0;
 }
diff -u --recursive --new-file v2.3.15/linux/drivers/net/cosa.c linux/drivers/net/cosa.c
--- v2.3.15/linux/drivers/net/cosa.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/net/cosa.c	Tue Aug 31 11:30:48 1999
@@ -1560,7 +1560,6 @@
 		/* sleep if not ready to read */
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(1);
-		current->state = TASK_RUNNING;
 	}
 	printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
 		cosa_getstatus(cosa));
@@ -1588,7 +1587,6 @@
 		/* sleep if not ready to read */
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(1);
-		current->state = TASK_RUNNING;
 #endif
 	}
 	printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
diff -u --recursive --new-file v2.3.15/linux/drivers/net/cycx_drv.c linux/drivers/net/cycx_drv.c
--- v2.3.15/linux/drivers/net/cycx_drv.c	Thu Aug 12 09:46:13 1999
+++ linux/drivers/net/cycx_drv.c	Tue Aug 31 11:30:48 1999
@@ -638,7 +638,6 @@
    know it all the contexts where this routine is used are interruptible... */
 
 	current->state = TASK_INTERRUPTIBLE;
-	current->counter = 0;       /* make us low-priority */
 	schedule_timeout(sec*HZ);
 }
 
diff -u --recursive --new-file v2.3.15/linux/drivers/net/cycx_main.c linux/drivers/net/cycx_main.c
--- v2.3.15/linux/drivers/net/cycx_main.c	Thu Aug 12 09:46:13 1999
+++ linux/drivers/net/cycx_main.c	Thu Aug 26 14:28:20 1999
@@ -36,7 +36,7 @@
 #include <linux/wanrouter.h>	/* WAN router definitions */
 #include <linux/cyclomx.h>	/* cyclomx common user API definitions */
 #include <asm/uaccess.h>	/* kernel <-> user copy */
-#include <linux/init.h>         /* __initfunc (when not using as a module) */
+#include <linux/init.h>         /* __init (when not using as a module) */
 
 #ifdef MODULE
 MODULE_AUTHOR("Arnaldo Carvalho de Melo");
@@ -95,7 +95,7 @@
 #ifdef MODULE
 int init_module (void)
 #else
-__initfunc(int cyclomx_init (void))
+int __init cyclomx_init (void)
 #endif
 {
 	int cnt, err = 0;
diff -u --recursive --new-file v2.3.15/linux/drivers/net/declance.c linux/drivers/net/declance.c
--- v2.3.15/linux/drivers/net/declance.c	Wed Aug 18 11:36:41 1999
+++ linux/drivers/net/declance.c	Thu Aug 26 14:28:48 1999
@@ -1000,7 +1000,7 @@
 	dev->tbusy = 0;
 }
 
-__initfunc(static int dec_lance_init(struct net_device *dev, const int type))
+static int __init dec_lance_init(struct net_device *dev, const int type)
 {
 	static unsigned version_printed = 0;
 	struct lance_private *lp;
@@ -1194,7 +1194,7 @@
 
 
 /* Find all the lance cards on the system and initialize them */
-__initfunc(int dec_lance_probe(struct net_device *dev))
+int __init dec_lance_probe(struct net_device *dev)
 {
 	static int called = 0;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/net/defxx.c linux/drivers/net/defxx.c
--- v2.3.15/linux/drivers/net/defxx.c	Wed Aug 18 11:36:41 1999
+++ linux/drivers/net/defxx.c	Mon Aug 30 10:23:14 1999
@@ -549,11 +549,12 @@
 
 				/* Get I/O base address from PCI Configuration Space */
 
-				port = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
+				port = pdev->resource[1].start
 
 				/* Verify port address range is not already being used */
 
 				port_len = PFI_K_CSR_IO_LEN;
+
 				if (check_region(port, port_len) == 0)
 					{
 					/* Allocate a new device structure for this adapter */
diff -u --recursive --new-file v2.3.15/linux/drivers/net/eepro.c linux/drivers/net/eepro.c
--- v2.3.15/linux/drivers/net/eepro.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/eepro.c	Thu Aug 26 14:26:40 1999
@@ -23,7 +23,7 @@
 	This is a compatibility hardware problem.
 
 	Versions:
-	0.11d	added __initdata, __initfunc stuff; call spin_lock_init
+	0.11d	added __initdata, __init stuff; call spin_lock_init
 	        in eepro_probe1. Replaced "eepro" by dev->name. Augmented 
 		the code protected by spin_lock in interrupt routine 
 		(PdP, 12/12/1998)
@@ -157,7 +157,6 @@
 /* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
 #define SLOW_DOWN inb(0x80)
 /* udelay(2) */
-#define compat_init_func(X)  __initfunc(X)
 #define compat_init_data     __initdata
 
 #else 
@@ -166,7 +165,6 @@
 #define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb), (mode) )
 #define test_and_set_bit(a,b) set_bit((a),(b))
 #define SLOW_DOWN SLOW_DOWN_IO
-#define compat_init_func(X) X
 #define compat_init_data
 
 #endif
@@ -461,7 +459,7 @@
 struct netdev_entry netcard_drv =
 {"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};
 #else
-compat_init_func(int eepro_probe(struct net_device *dev))
+int __init eepro_probe(struct net_device *dev)
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
diff -u --recursive --new-file v2.3.15/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c
--- v2.3.15/linux/drivers/net/eth16i.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/eth16i.c	Thu Aug 26 14:28:58 1999
@@ -171,7 +171,6 @@
 #else
 #define __init
 #define __initdata
-#define __initfunc(x) x
 #endif
 
 #if LINUX_VERSION_CODE < 0x20138
diff -u --recursive --new-file v2.3.15/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c
--- v2.3.15/linux/drivers/net/ewrk3.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/ewrk3.c	Mon Aug 30 10:23:14 1999
@@ -1414,7 +1414,7 @@
    ** If at end of eth device list and can't use current entry, malloc
    ** one up. If memory could not be allocated, print an error message.
  */
-static __init struct net_device *
+static struct net_device * __init
 insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *))
 {
 	struct net_device *new;
diff -u --recursive --new-file v2.3.15/linux/drivers/net/fc/iph5526.c linux/drivers/net/fc/iph5526.c
--- v2.3.15/linux/drivers/net/fc/iph5526.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/net/fc/iph5526.c	Tue Aug 31 11:23:03 1999
@@ -224,7 +224,7 @@
 #endif
 
 
-__initfunc(int iph5526_probe(struct net_device *dev))
+int __init iph5526_probe(struct net_device *dev)
 {
 #ifdef CONFIG_PCI
 	if (pci_present() && (iph5526_probe_pci(dev) == 0))
@@ -234,7 +234,7 @@
 }
 
 #ifdef CONFIG_PCI
-__initfunc(static int iph5526_probe_pci(struct net_device *dev))
+static int __init iph5526_probe_pci(struct net_device *dev)
 {
 #ifndef MODULE
 struct fc_info *fi;
@@ -278,7 +278,7 @@
 }
 #endif  /* CONFIG_PCI */
 
-__initfunc(static int fcdev_init(struct net_device *dev))
+static int __init fcdev_init(struct net_device *dev)
 {
 	dev->open = iph5526_open;
 	dev->stop = iph5526_close;
diff -u --recursive --new-file v2.3.15/linux/drivers/net/hp100.c linux/drivers/net/hp100.c
--- v2.3.15/linux/drivers/net/hp100.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/hp100.c	Thu Aug 26 14:27:43 1999
@@ -119,10 +119,6 @@
 typedef struct enet_statistics hp100_stats_t;
 #endif
 
-#ifndef __initfunc
-#define __initfunc(__initarg) __initarg
-#endif
-
 #include "hp100.h"
 
 /*
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/Config.in linux/drivers/net/irda/Config.in
--- v2.3.15/linux/drivers/net/irda/Config.in	Mon Jun  7 16:18:58 1999
+++ linux/drivers/net/irda/Config.in	Mon Aug 30 10:23:14 1999
@@ -20,6 +20,7 @@
   dep_tristate '   Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRDA
   dep_tristate '   Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA
   dep_tristate '   Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA
+  dep_tristate '   Adaptec Airport 1000/2000 dongle' CONFIG_AIRPORT_DONGLE $CONFIG_IRDA
 fi
 
 endmenu
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile
--- v2.3.15/linux/drivers/net/irda/Makefile	Mon Jun  7 16:18:58 1999
+++ linux/drivers/net/irda/Makefile	Mon Aug 30 10:23:14 1999
@@ -156,6 +156,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_AIRPORT_DONGLE),y)
+L_OBJS += airport.o
+else
+  ifeq ($(CONFIG_AIRPORT_DONGLE),m)
+  M_OBJS += airport.o
+  endif
+endif
+
 include $(TOPDIR)/Rules.make
 
 clean:
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c
--- v2.3.15/linux/drivers/net/irda/actisys.c	Tue Jul  6 19:05:49 1999
+++ linux/drivers/net/irda/actisys.c	Mon Aug 30 10:23:14 1999
@@ -7,7 +7,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Sun May 16 14:35:11 1999
+ * Modified at:   Sat Jun 26 16:57:57 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -37,11 +37,11 @@
 static void actisys_reset(struct irda_device *dev);
 static void actisys_open(struct irda_device *idev, int type);
 static void actisys_close(struct irda_device *dev);
-static void actisys_change_speed( struct irda_device *dev, int baudrate);
+static void actisys_change_speed( struct irda_device *dev, __u32 speed);
 static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos);
 
 /* These are the baudrates supported */
-static int baud_rates[] = { 9600, 19200, 57600, 115200, 38400};
+static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400};
 
 static struct dongle dongle = {
 	ACTISYS_DONGLE,
@@ -107,9 +107,9 @@
  *    To cycle through the available baud rates, pulse RTS low for a few
  *    ms.  
  */
-static void actisys_change_speed(struct irda_device *idev, int baudrate)
+static void actisys_change_speed(struct irda_device *idev, __u32 speed)
 {
-        int current_baudrate;
+        __u32 current_baudrate;
         int index = 0;
 	
 	DEBUG(4, __FUNCTION__ "()\n");
@@ -126,7 +126,7 @@
         DEBUG( 4, __FUNCTION__ "(), index=%d\n", index);
 
 	/* Cycle through avaiable baudrates until we reach the correct one */
-        while (current_baudrate != baudrate) {	
+        while (current_baudrate != speed) {	
                 DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",
 		      baud_rates[index]);
 		
@@ -152,7 +152,7 @@
 
                 current_baudrate = baud_rates[index];
         }
-	DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",baud_rates[index]);
+	DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", baud_rates[index]);
 }
 
 /*
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/airport.c linux/drivers/net/irda/airport.c
--- v2.3.15/linux/drivers/net/irda/airport.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/airport.c	Tue Aug 31 11:23:03 1999
@@ -0,0 +1,374 @@
+/*********************************************************************
+ *                
+ * Filename:      airport.c
+ * Version:       0.2
+ * Description:   Implementation for the Adaptec Airport 1000 and 2000 
+ *                dongles
+ * Status:        Experimental.
+ * Author:        Fons Botman <budely@tref.nl>
+ * Created at:    Wed May 19 23:14:34 CEST 1999
+ * Based on:      actisys.c
+ * By:            Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998-1999 Fons Botman, All Rights Reserved.
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither Fons Botman nor anyone else admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/dongle.h>
+
+
+static void airport_reset(struct irda_device *dev);
+static void airport_open(struct irda_device *idev, int type);
+static void airport_close(struct irda_device *dev);
+static void airport_change_speed( struct irda_device *dev, __u32 speed);
+static void airport_init_qos(struct irda_device *idev, struct qos_info *qos);
+
+
+static struct dongle dongle = {
+	AIRPORT_DONGLE,
+	airport_open,
+	airport_close,
+	airport_reset,
+	airport_change_speed,
+	airport_init_qos,
+};
+
+
+int __init airport_init(void)
+{
+	int ret;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+	ret = irda_device_register_dongle(&dongle);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+void airport_cleanup(void)
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+	irda_device_unregister_dongle(&dongle);
+}
+
+static void airport_open(struct irda_device *idev, int type)
+{
+	DEBUG(2, __FUNCTION__ "(,%d)\n", type);
+	if (strlen(idev->description) < sizeof(idev->description) - 13)
+	  strcat(idev->description, " <-> airport");
+	else
+	  DEBUG(0, __FUNCTION__ " description too long: %s\n", 
+		idev->description);
+
+        idev->io.dongle_id = type;
+	idev->flags |= IFF_DONGLE;
+
+	MOD_INC_USE_COUNT;
+}
+
+static void airport_close(struct irda_device *idev)
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+	/* Power off dongle */
+	irda_device_set_dtr_rts(idev, FALSE, FALSE);
+
+	MOD_DEC_USE_COUNT;
+}
+
+static void airport_set_command_mode(struct irda_device *idev)
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+	irda_device_set_dtr_rts(idev, FALSE, TRUE);
+}
+
+static void airport_set_normal_mode(struct irda_device *idev)
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+    	irda_device_set_dtr_rts(idev, TRUE, TRUE);
+}
+
+
+void airport_write_char(struct irda_device *idev, unsigned char c)
+{
+	int actual;
+	DEBUG(2, __FUNCTION__ "(,0x%x)\n", c & 0xff);
+	actual = idev->raw_write(idev, &c, 1);
+	ASSERT(actual == 1, return;);
+}
+
+#define JIFFIES_TO_MSECS(j) ((j)*1000/HZ)
+
+static int airport_waitfor_char(struct irda_device *idev, unsigned char c)
+{
+	int i, found = FALSE;
+	int before;
+	DEBUG(2, __FUNCTION__ "(,0x%x)\n", c);
+
+	/* Sleep approx. 10 ms */
+	before = jiffies;
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(MSECS_TO_JIFFIES(20));
+	DEBUG(4, __FUNCTION__ " waited %ldms\n", 
+	      JIFFIES_TO_MSECS(jiffies - before));
+
+	for ( i = 0 ; !found && i < idev->rx_buff.len ; i++ ) {
+		/* DEBUG(6, __FUNCTION__ " 0x02x\n", idev->rx_buff.data[i]); */
+		found = c == idev->rx_buff.data[i];
+	}
+	idev->rx_buff.len = 0;
+
+	DEBUG(2, __FUNCTION__ " returns %s\n", (found ? "true" : "false"));
+	return found;
+}
+
+static int airport_check_command_mode(struct irda_device *idev)
+{
+	int i;
+	int found = FALSE;
+  
+	DEBUG(2, __FUNCTION__ "()\n");
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(MSECS_TO_JIFFIES(20));
+	airport_set_command_mode(idev);
+
+	/* Loop until the time expires (200ms) or we get the magic char. */
+
+	for ( i = 0 ; i < 25 ; i++ ) {
+	  	airport_write_char(idev, 0xff);
+		if (airport_waitfor_char(idev, 0xc3)) {
+			found = TRUE;
+			break;
+		}
+	}
+
+	if (found) {
+		DEBUG(2, __FUNCTION__ " OK. (%d)\n", i);
+	} else {
+		DEBUG(0, __FUNCTION__ " FAILED!\n");
+	}
+	return found;
+}
+
+
+static int airport_write_register(struct irda_device *idev, unsigned char reg)
+{
+	int ok = FALSE;
+	int i;
+
+	DEBUG(4, __FUNCTION__ "(,0x%x)\n", reg);
+	airport_check_command_mode(idev);
+
+	for ( i = 0 ; i < 6 ; i++ ) {
+		airport_write_char(idev, reg);
+		if (!airport_waitfor_char(idev, reg)) 
+			continue;
+
+		/* Now read it back */
+		airport_write_char(idev, (reg << 4) | 0x0f);
+		if (airport_waitfor_char(idev, reg)) {
+			ok = TRUE;
+			break;
+		}
+	}
+
+	airport_set_normal_mode(idev);
+	if (ok) {
+		DEBUG(4, __FUNCTION__ "(,0x%x) returns OK\n", reg);
+	} else {
+		DEBUG(0, __FUNCTION__ "(,0x%x) returns False!\n", reg);
+	}
+	return ok;
+}
+
+
+/*
+ * Function airport_change_speed (tty, baud)
+ *
+ *    Change speed of the Airport type IrDA dongles.
+ */
+static void airport_change_speed(struct irda_device *idev, __u32 speed)
+{
+        __u32 current_baudrate;
+        int baudcode;
+	
+	DEBUG(4, __FUNCTION__ "(,%d)\n", speed);
+
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	
+	/* Find the correct baudrate code for the required baudrate */
+	switch (speed) {
+	case 2400:	baudcode = 0x10;	break;
+	case 4800:	baudcode = 0x20;	break;
+	case 9600:	baudcode = 0x30;	break;
+	case 19200:	baudcode = 0x40;	break;
+	case 38400:	baudcode = 0x50;	break;
+	case 57600:	baudcode = 0x60;	break;
+	case 115200:	baudcode = 0x70;	break;
+	default:
+		DEBUG(0, __FUNCTION__ " bad baud rate: %d\n", speed);
+		return;
+	}
+
+	current_baudrate = idev->qos.baud_rate.value;
+	DEBUG(4, __FUNCTION__ " current baudrate: %d\n", current_baudrate);
+
+	/* The dongle falls back to 9600 baud */
+	if (current_baudrate != 9600) {
+		DEBUG(4, __FUNCTION__ " resetting speed to 9600 baud\n");
+		ASSERT(idev->change_speed , return;);
+		idev->change_speed(idev, 9600);
+		idev->qos.baud_rate.value = 9600;
+	}
+
+	if (idev->set_raw_mode)
+		idev->set_raw_mode(idev, TRUE);
+
+	/* Set the new speed in both registers */
+	if (airport_write_register(idev, baudcode)) {
+		if (airport_write_register(idev, baudcode|0x01)) {
+			/* ok */
+		} else {
+			DEBUG(0, __FUNCTION__ 
+			      " Cannot set new speed in second register\n");
+		}
+	} else {
+		DEBUG(0, __FUNCTION__ 
+		      " Cannot set new speed in first register\n");
+	}
+	
+	if (idev->set_raw_mode)
+		idev->set_raw_mode(idev, FALSE);
+
+	/* How do I signal an error in these functions? */
+
+	DEBUG(4, __FUNCTION__ " returning\n");
+}
+
+
+/*
+ * Function airport_reset (idev)
+ *
+ *      Reset the Airport type dongle. Warning, this function must only be
+ *      called with a process context!
+ *
+ */
+static void airport_reset(struct irda_device *idev)
+{
+	int ok;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	ASSERT(idev->set_raw_mode /* The airport needs this */, return;);
+
+	if (idev->set_raw_mode)
+		idev->set_raw_mode(idev, TRUE);
+
+	airport_set_normal_mode(idev);
+
+	/* Sleep 2000 ms */
+	DEBUG(2, __FUNCTION__ " waiting for powerup\n");
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(MSECS_TO_JIFFIES(2000));
+	DEBUG(2, __FUNCTION__ " finished waiting for powerup\n");
+	
+	/* set dongle speed to 9600 */
+	ok = TRUE;
+
+	if (ok)
+		ok = airport_write_register(idev, 0x30);
+	if (!ok)
+		MESSAGE(__FUNCTION__ "() dongle not connected?\n");
+	if (ok)
+		ok = airport_write_register(idev, 0x31);
+
+	if (ok)
+		ok = airport_write_register(idev, 0x02);
+	if (ok)
+		ok = airport_write_register(idev, 0x03);
+
+	if (ok) {
+		ok = airport_check_command_mode(idev);
+
+		if (ok) {
+			airport_write_char(idev, 0x04);
+			ok = airport_waitfor_char(idev, 0x04);
+		}
+		airport_set_normal_mode(idev);
+	}
+		
+	if (idev->set_raw_mode)
+		idev->set_raw_mode(idev, FALSE);
+	
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(MSECS_TO_JIFFIES(20));
+	DEBUG(4, __FUNCTION__ " waited 20ms\n");
+
+	idev->qos.baud_rate.value = 9600;
+	if (!ok)
+		MESSAGE(__FUNCTION__ "() failed.\n");
+	DEBUG(2, __FUNCTION__ " returning.\n");
+}
+
+/*
+ * Function airport_init_qos (qos)
+ *
+ *    Initialize QoS capabilities
+ *
+ */
+static void airport_init_qos(struct irda_device *idev, struct qos_info *qos)
+{
+	qos->baud_rate.bits &= 
+		IR_2400|IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	/* May need 1ms */
+	qos->min_turn_time.bits &= 0x07;
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Fons Botman <budely@tref.nl>");
+MODULE_DESCRIPTION("Adaptec Airport 1000 and 2000 dongle driver");	
+		
+/*
+ * Function init_module (void)
+ *
+ *    Initialize Airport module
+ *
+ */
+int init_module(void)
+{
+	return airport_init();
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup Airport module
+ *
+ */
+void cleanup_module(void)
+{
+	airport_cleanup();
+}
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c
--- v2.3.15/linux/drivers/net/irda/esi.c	Tue Jul  6 19:05:49 1999
+++ linux/drivers/net/irda/esi.c	Mon Aug 30 10:23:14 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Thomas Davis, <ratbert@radiks.net>
  * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Sun May 16 14:35:21 1999
+ * Modified at:   Sat Jun 26 16:50:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:	  esi.c
  *
@@ -39,7 +39,7 @@
 
 static void esi_open(struct irda_device *idev, int type);
 static void esi_close(struct irda_device *driver);
-static void esi_change_speed(struct irda_device *idev, int baud);
+static void esi_change_speed(struct irda_device *idev, __u32 speed);
 static void esi_reset(struct irda_device *idev);
 static void esi_qos_init(struct irda_device *idev, struct qos_info *qos);
 
@@ -81,19 +81,19 @@
 }
 
 /*
- * Function esi_change_speed (tty, baud)
+ * Function esi_change_speed (idev, speed)
  *
  *    Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle
  *
  */
-static void esi_change_speed(struct irda_device *idev, int baud)
+static void esi_change_speed(struct irda_device *idev, __u32 speed)
 {
 	int dtr, rts;
 	
 	ASSERT(idev != NULL, return;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
 	
-	switch (baud) {
+	switch (speed) {
 	case 19200:
 		dtr = TRUE;
 		rts = FALSE;
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/girbil.c linux/drivers/net/irda/girbil.c
--- v2.3.15/linux/drivers/net/irda/girbil.c	Tue Jul  6 19:05:49 1999
+++ linux/drivers/net/irda/girbil.c	Mon Aug 30 10:23:14 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Feb  6 21:02:33 1999
- * Modified at:   Tue Jun  1 08:47:41 1999
+ * Modified at:   Sun Jul 18 12:09:26 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -37,7 +37,7 @@
 static void girbil_reset(struct irda_device *dev);
 static void girbil_open(struct irda_device *dev, int type);
 static void girbil_close(struct irda_device *dev);
-static void girbil_change_speed(struct irda_device *dev, int baud);
+static void girbil_change_speed(struct irda_device *dev, __u32 speed);
 static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos);
 
 /* Control register 1 */
@@ -111,7 +111,7 @@
  *    function must be called with a process context!
  *
  */
-static void girbil_change_speed(struct irda_device *idev, int speed)
+static void girbil_change_speed(struct irda_device *idev, __u32 speed)
 {
 	__u8 control[2];
 	
@@ -138,6 +138,9 @@
 	}
 	control[1] = GIRBIL_LOAD;
 
+	/* Need to reset the dongle and go to 9600 bps before programming */
+	girbil_reset(idev);
+
 	/* Set DTR and Clear RTS to enter command mode */
 	irda_device_set_dtr_rts(idev, FALSE, TRUE);
 
@@ -145,7 +148,7 @@
 	irda_device_raw_write(idev, control, 2);
 
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(2);
+	schedule_timeout(MSECS_TO_JIFFIES(100));
 	
 	/* Go back to normal mode */
 	irda_device_set_dtr_rts(idev, TRUE, TRUE);
@@ -168,18 +171,22 @@
 	ASSERT(idev != NULL, return;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
 	
+	/* Make sure the IrDA chip also goes to defalt speed */
+	if (idev->change_speed)
+		idev->change_speed(idev, 9600);
+
 	/* Reset dongle */
 	irda_device_set_dtr_rts(idev, TRUE, FALSE);
 
 	/* Sleep at least 5 ms */
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(20));
+	schedule_timeout(MSECS_TO_JIFFIES(10));
 	
 	/* Set DTR and clear RTS to enter command mode */
 	irda_device_set_dtr_rts(idev, FALSE, TRUE);
 
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(20));
+	schedule_timeout(MSECS_TO_JIFFIES(10));
 
 	/* Write control byte */
 	irda_device_raw_write(idev, &control, 1);
@@ -189,10 +196,6 @@
 
 	/* Go back to normal mode */
 	irda_device_set_dtr_rts(idev, TRUE, TRUE);
-
-       	/* Make sure the IrDA chip also goes to defalt speed */
-	if (idev->change_speed)
-		idev->change_speed(idev, 9600);
 }
 
 /*
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.3.15/linux/drivers/net/irda/irport.c	Wed Aug 18 11:38:51 1999
+++ linux/drivers/net/irda/irport.c	Mon Aug 30 10:23:14 1999
@@ -6,7 +6,7 @@
  * Status:	  Experimental.
  * Author:	  Dag Brattli <dagb@cs.uit.no>
  * Created at:	  Sun Aug  3 13:49:59 1997
- * Modified at:   Tue Jun  1 10:02:42 1999
+ * Modified at:   Wed Aug 11 09:24:46 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:	  serial.c by Linus Torvalds 
  * 
@@ -272,7 +272,7 @@
  *    Set speed of IrDA port to specified baudrate
  *
  */
-void irport_change_speed(struct irda_device *idev, int speed)
+void irport_change_speed(struct irda_device *idev, __u32 speed)
 {
 	unsigned long flags;
 	int iobase; 
@@ -319,7 +319,7 @@
 	outb(fcr,		  iobase+UART_FCR); /* Enable FIFO's */
 
 	/* Turn on interrups */
-	outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, iobase+UART_IER);
+	outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
 
 	spin_unlock_irqrestore(&idev->lock, flags);
 }
@@ -375,7 +375,7 @@
 		outb(fcr, iobase+UART_FCR);
 
 		/* Turn on receive interrupts */
-		outb(UART_IER_RLSI|UART_IER_RDI, iobase+UART_IER); 
+		outb(/* UART_IER_RLSI| */UART_IER_RDI, iobase+UART_IER);
 	}
 }
 
@@ -432,7 +432,7 @@
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE) {
 		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < 5)
+		if ((tickssofar < 5) || !dev->start)
 			return -EBUSY;
 
 		WARNING("%s: transmit timed out\n", dev->name);
@@ -443,7 +443,7 @@
 	}
 
 	spin_lock_irqsave(&idev->lock, flags);
-	
+
 	/* Init tx buffer */
 	idev->tx_buff.data = idev->tx_buff.head;
 
@@ -465,7 +465,7 @@
 }
         
 /*
- * Function irport_receive (void)
+ * Function irport_receive (idev)
  *
  *    Receive one frame from the infrared port
  *
@@ -527,10 +527,10 @@
 
 		switch (iir) {
 		case UART_IIR_RLSI:
-			DEBUG(0, __FUNCTION__ "(), RLSI\n");
+			DEBUG(2, __FUNCTION__ "(), RLSI\n");
 			break;
 		case UART_IIR_RDI:
-			if (lsr & UART_LSR_DR)
+			//if (lsr & UART_LSR_DR)
 				/* Receive interrupt */
 				irport_receive(idev);
 			break;
@@ -545,7 +545,7 @@
 		} 
 		
 		/* Make sure we don't stay here to long */
-		if (boguscount++ > 32)
+		if (boguscount++ > 100)
 			break;
 
  	        iir = inb(iobase + UART_IIR) & UART_IIR_ID;
@@ -586,18 +586,14 @@
 		return -EAGAIN;
 
 	irport_start(idev, iobase);
-
-	MOD_INC_USE_COUNT;
-
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	irda_device_net_open(dev);
 
 	/* Change speed to make sure dongles follow us again */
 	if (idev->change_speed)
 		idev->change_speed(idev, 9600);
 
+	MOD_INC_USE_COUNT;
+
 	return 0;
 }
 
@@ -612,17 +608,17 @@
 	struct irda_device *idev;
 	int iobase;
 
+	DEBUG(4, __FUNCTION__ "()\n");
+
 	ASSERT(dev != NULL, return -1;);
 	idev = (struct irda_device *) dev->priv;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	ASSERT(idev != NULL, return -1;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;)
 
 	iobase = idev->io.iobase2;
 
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
+	irda_device_net_close(dev);
 	irport_stop(idev, iobase);
 
 	free_irq(idev->io.irq2, idev);
@@ -664,7 +660,7 @@
 }
 
 /*
- * Function irtty_set_dtr_rts (tty, dtr, rts)
+ * Function irport_set_dtr_rts (tty, dtr, rts)
  *
  *    This function can be used by dongles etc. to set or reset the status
  *    of the dtr and rts lines
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- v2.3.15/linux/drivers/net/irda/irtty.c	Wed Aug 18 11:38:51 1999
+++ linux/drivers/net/irda/irtty.c	Mon Aug 30 10:23:14 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:18:38 1997
- * Modified at:   Mon May 10 15:45:50 1999
+ * Modified at:   Tue Aug 24 13:32:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
  *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
@@ -49,6 +49,9 @@
 static int  irtty_is_receiving(struct irda_device *idev);
 static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
 static int  irtty_raw_write(struct irda_device *idev, __u8 *buf, int len);
+static int  irtty_raw_read(struct irda_device *idev, __u8 *buf, int len, 
+			   int timeout);
+static void irtty_set_raw_mode(struct irda_device *dev, int mode);
 static int  irtty_net_init(struct net_device *dev);
 static int  irtty_net_open(struct net_device *dev);
 static int  irtty_net_close(struct net_device *dev);
@@ -57,7 +60,7 @@
 static void irtty_close(struct tty_struct *tty);
 static int  irtty_ioctl(struct tty_struct *, void *, int, void *);
 static int  irtty_receive_room(struct tty_struct *tty);
-static void irtty_change_speed(struct irda_device *dev, int baud);
+static void irtty_change_speed(struct irda_device *dev, __u32 speed);
 static void irtty_write_wakeup(struct tty_struct *tty);
 
 static void irtty_receive_buf(struct tty_struct *, const unsigned char *, 
@@ -91,10 +94,9 @@
 	irda_ldisc.receive_room = irtty_receive_room;
 	irda_ldisc.write_wakeup = irtty_write_wakeup;
 	
-	if (( status = tty_register_ldisc(N_IRDA, &irda_ldisc)) != 0)  {
-		printk(KERN_ERR 
-		       "IrDA: can't register line discipline (err = %d)\n", 
-		       status);
+	if ((status = tty_register_ldisc(N_IRDA, &irda_ldisc)) != 0) {
+		ERROR("IrDA: can't register line discipline (err = %d)\n", 
+		      status);
 	}
 	
 	return status;
@@ -111,9 +113,7 @@
 {
 	int ret;
 	
-	/*
-	 *  Unregister tty line-discipline
-	 */
+	/* Unregister tty line-discipline */
 	if ((ret = tty_register_ldisc(N_IRDA, NULL))) {
 		ERROR(__FUNCTION__ 
 		      "(), can't unregister line discipline (err = %d)\n",
@@ -209,9 +209,11 @@
 	/* Initialize callbacks */
 	self->idev.change_speed    = irtty_change_speed;
  	self->idev.is_receiving    = irtty_is_receiving;
+	self->idev.wait_until_sent = irtty_wait_until_sent;
 	self->idev.set_dtr_rts     = irtty_set_dtr_rts;
+	self->idev.set_raw_mode    = irtty_set_raw_mode;
 	self->idev.raw_write       = irtty_raw_write;
-	self->idev.wait_until_sent = irtty_wait_until_sent;
+	self->idev.raw_read        = irtty_raw_read;
 
 	/* Override the network functions we need to use */
 	self->idev.netdev.init            = irtty_net_init;
@@ -287,19 +289,19 @@
 }
 
 /* 
- *  Function irtty_change_speed (self, baud)
+ *  Function irtty_change_speed (self, speed)
  *
  *    Change the speed of the serial port. The driver layer must check that
  *    all transmission has finished using the irtty_wait_until_sent() 
  *    function.
  */
-static void irtty_change_speed(struct irda_device *idev, int baud) 
+static void irtty_change_speed(struct irda_device *idev, __u32 speed)
 {
         struct termios old_termios;
 	struct irtty_cb *self;
 	int cflag;
 
-	DEBUG(4,__FUNCTION__ "(), <%ld>\n", jiffies); 
+	DEBUG(4, __FUNCTION__ "(), <%ld>\n", jiffies); 
 
 	ASSERT(idev != NULL, return;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -314,9 +316,9 @@
 
 	cflag &= ~CBAUD;
 
-	DEBUG(4, __FUNCTION__ "(), Setting speed to %d\n", baud);
+	DEBUG(4, __FUNCTION__ "(), Setting speed to %d\n", speed);
 
-	switch (baud) {
+	switch (speed) {
 	case 1200:
 		cflag |= B1200;
 		break;
@@ -401,9 +403,7 @@
 {
 	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRTTY_MAGIC, return;);
-	
+	DEBUG(5, __FUNCTION__ "(,,,count=%d)\n", count);
 	/* Read the characters out of the buffer */
  	while (count--) {
 		/* 
@@ -411,13 +411,25 @@
 		 */
  		if (fp && *fp++) { 
 			DEBUG( 0, "Framing or parity error!\n");
-			irda_device_set_media_busy( &self->idev, TRUE);
+			irda_device_set_media_busy(&self->idev, TRUE);
 
  			cp++;
  			continue;
  		}
-		/* Unwrap and destuff one byte */
-		async_unwrap_char(&self->idev, *cp++);
+
+		DEBUG(6, __FUNCTION__ " char=0x%02x\n", *cp);
+ 		if (self->idev.raw_mode) {
+			struct irda_device *idev = &self->idev;
+
+			/* What should we do when the buffer is full? */
+			if (idev->rx_buff.len == idev->rx_buff.truesize)
+				idev->rx_buff.len = 0;
+
+			idev->rx_buff.data[idev->rx_buff.len++] = *cp++;
+		} else {
+			/* Unwrap and destuff one byte */
+			async_unwrap_char(&self->idev, *cp++);
+ 		}
 	}
 }
 
@@ -615,6 +627,72 @@
 	set_fs(fs);
 }
 
+/*
+ * Function irtty_set_raw_mode (idev, status)
+ *
+ *    For the airport dongle, we need support for reading raw characters
+ *    from the IrDA device. This function switches between those modes. 
+ *    FALSE is the default mode, and will then treat incoming data as IrDA 
+ *    packets.
+ */
+void irtty_set_raw_mode(struct irda_device *idev, int status)
+{
+	struct irtty_cb *self;
+
+	DEBUG(2, __FUNCTION__ "(), status=%s\n", status ? "TRUE" : "FALSE");
+
+	ASSERT(idev != NULL, return;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+	
+	self = (struct irtty_cb *) idev->priv;
+
+	/* save status for driver */
+	self->idev.raw_mode = status;
+	
+	/* reset the buffer state */
+	idev->rx_buff.data = idev->rx_buff.head;
+	idev->rx_buff.len = 0;
+	idev->rx_buff.state = OUTSIDE_FRAME;
+}
+
+/*
+ * Function irtty_raw_read (idev, buf, len)
+ *
+ *    Receive incomming data. This function sleeps, so it must only be
+ *    called with a process context. Timeout is currently defined to be
+ *    a multiple of 10 ms.
+ */
+static int irtty_raw_read(struct irda_device *idev, __u8 *buf, int len, 
+			  int timeout)
+{
+	int count;
+
+	buf = idev->rx_buff.data;
+
+	/* Wait for the requested amount of data to arrive */
+	while (len < idev->rx_buff.len) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(MSECS_TO_JIFFIES(10));
+
+		if (!timeout--)
+			break;
+	}
+	
+	count = idev->rx_buff.len < len ? idev->rx_buff.len : len;
+
+	/* 
+	 * Reset the state, this mean that a raw read is sort of a 
+	 * datagram read, and _not_ a stream style read. Be aware of the
+	 * difference. Implementing it the other way will just be painful ;-)
+	 */
+	idev->rx_buff.data = idev->rx_buff.head;
+	idev->rx_buff.len = 0;
+	idev->rx_buff.state = OUTSIDE_FRAME;
+
+	/* Return the amount we were able to get */
+	return count;
+}
+
 static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len)
 {
 	struct irtty_cb *self;
@@ -634,6 +712,8 @@
 	return actual;
 }
 
+
+
 static int irtty_net_init(struct net_device *dev)
 {
 	/* Set up to be a normal IrDA network device driver */
@@ -646,12 +726,7 @@
 
 static int irtty_net_open(struct net_device *dev)
 {
-	ASSERT(dev != NULL, return -1;);
-
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	irda_device_net_open(dev);
 
 	MOD_INC_USE_COUNT;
 
@@ -660,11 +735,7 @@
 
 static int irtty_net_close(struct net_device *dev)
 {
-	ASSERT(dev != NULL, return -1;);
-	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
+	irda_device_net_close(dev);
 
 	MOD_DEC_USE_COUNT;
 
@@ -701,10 +772,3 @@
 }
 
 #endif /* MODULE */
-
-
-
-
-
-
-
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/litelink.c linux/drivers/net/irda/litelink.c
--- v2.3.15/linux/drivers/net/irda/litelink.c	Tue Jul  6 19:05:49 1999
+++ linux/drivers/net/irda/litelink.c	Mon Aug 30 10:23:14 1999
@@ -6,7 +6,7 @@
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri May  7 12:50:33 1999
- * Modified at:   Wed May 19 07:25:15 1999
+ * Modified at:   Sat Jun 26 17:01:05 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -44,12 +44,12 @@
 
 static void litelink_open(struct irda_device *idev, int type);
 static void litelink_close(struct irda_device *dev);
-static void litelink_change_speed(struct irda_device *dev, int baudrate);
+static void litelink_change_speed(struct irda_device *dev, __u32);
 static void litelink_reset(struct irda_device *dev);
 static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos);
 
 /* These are the baudrates supported */
-static int baud_rates[] = { 115200, 57600, 38400, 19200, 9600 };
+static __u32 baud_rates[] = { 115200, 57600, 38400, 19200, 9600 };
 
 static struct dongle dongle = {
 	LITELINK_DONGLE,
@@ -89,12 +89,12 @@
 }
 
 /*
- * Function litelink_change_speed (tty, baud)
+ * Function litelink_change_speed (idev, speed)
  *
  *    Change speed of the Litelink dongle. To cycle through the available 
  *    baud rates, pulse RTS low for a few ms.  
  */
-static void litelink_change_speed(struct irda_device *idev, int baudrate)
+static void litelink_change_speed(struct irda_device *idev, __u32 speed)
 {
         int i;
 	
@@ -114,7 +114,7 @@
 	udelay(MIN_DELAY);
 	
 	/* Cycle through avaiable baudrates until we reach the correct one */
-	for (i=0; i<5 && baud_rates[i] != baudrate; i++) {
+	for (i=0; i<5 && baud_rates[i] != speed; i++) {
 
 		/* Set DTR, clear RTS */
 		irda_device_set_dtr_rts(idev, FALSE, TRUE);
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c
--- v2.3.15/linux/drivers/net/irda/pc87108.c	Wed Aug 18 11:38:51 1999
+++ linux/drivers/net/irda/pc87108.c	Mon Aug 30 10:23:14 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Nov  7 21:43:15 1998
- * Modified at:   Mon May 24 15:19:21 1999
+ * Modified at:   Wed Aug 11 09:26:26 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -110,7 +110,7 @@
 static int  pc87108_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static int  pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
 static void pc87108_dma_write(struct irda_device *idev, int iobase);
-static void pc87108_change_speed(struct irda_device *idev, int baud);
+static void pc87108_change_speed(struct irda_device *idev, __u32 baud);
 static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void pc87108_wait_until_sent(struct irda_device *idev);
 static int  pc87108_is_receiving(struct irda_device *idev);
@@ -615,7 +615,7 @@
  *    Change the speed of the device
  *
  */
-static void pc87108_change_speed( struct irda_device *idev, int speed)
+static void pc87108_change_speed(struct irda_device *idev, __u32 speed)
 {
 	__u8 mcr = MCR_SIR;
 	__u8 bank;
@@ -1391,12 +1391,7 @@
 		free_irq( idev->io.irq, idev);
 		return -EAGAIN;
 	}
-		
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
+	
 	/* Save current bank */
 	bank = inb( iobase+BSR);
 	
@@ -1407,6 +1402,8 @@
 	/* Restore bank register */
 	outb( bank, iobase+BSR);
 
+	irda_device_net_open(dev);
+
 	MOD_INC_USE_COUNT;
 
 	return 0;
@@ -1424,34 +1421,32 @@
 	int iobase;
 	__u8 bank;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
+	irda_device_net_close(dev);
 
-	ASSERT( dev != NULL, return -1;);
+	ASSERT(dev != NULL, return -1;);
 	idev = (struct irda_device *) dev->priv;
 	
-	ASSERT( idev != NULL, return 0;);
-	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	ASSERT(idev != NULL, return 0;);
+	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
 	
 	iobase = idev->io.iobase;
 
-	disable_dma( idev->io.dma);
+	disable_dma(idev->io.dma);
 
 	/* Save current bank */
-	bank = inb( iobase+BSR);
+	bank = inb(iobase+BSR);
 
 	/* Disable interrupts */
-	switch_bank( iobase, BANK0);
-	outb( 0, iobase+IER); 
+	switch_bank(iobase, BANK0);
+	outb(0, iobase+IER); 
        
-	free_irq( idev->io.irq, idev);
-	free_dma( idev->io.dma);
+	free_irq(idev->io.irq, idev);
+	free_dma(idev->io.dma);
 
 	/* Restore bank register */
-	outb( bank, iobase+BSR);
+	outb(bank, iobase+BSR);
 
 	MOD_DEC_USE_COUNT;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c
--- v2.3.15/linux/drivers/net/irda/smc-ircc.c	Wed Aug 18 11:38:52 1999
+++ linux/drivers/net/irda/smc-ircc.c	Mon Aug 30 10:23:14 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Thomas Davis (tadavis@jps.net)
  * Created at:    
- * Modified at:   Wed May 19 15:30:08 1999
+ * Modified at:   Tue Aug 24 13:33:22 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Thomas Davis, All Rights Reserved.
@@ -65,7 +65,7 @@
 static int  ircc_dma_receive_complete(struct irda_device *idev, int iobase);
 static int  ircc_hard_xmit( struct sk_buff *skb, struct net_device *dev);
 static void ircc_dma_write( struct irda_device *idev, int iobase);
-static void ircc_change_speed( struct irda_device *idev, int baud);
+static void ircc_change_speed( struct irda_device *idev, __u32 speed);
 static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void ircc_wait_until_sent( struct irda_device *idev);
 static int  ircc_is_receiving( struct irda_device *idev);
@@ -348,7 +348,7 @@
  *    Change the speed of the device
  *
  */
-static void ircc_change_speed( struct irda_device *idev, int speed)
+static void ircc_change_speed( struct irda_device *idev, __u32 speed)
 {
 	struct ircc_cb *self;
 	int iobase, ir_mode, select, fast; 
@@ -884,9 +884,7 @@
 	}
 		
 	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	irda_device_net_open(dev);
 
 	/* turn on interrupts */
 	
@@ -909,10 +907,6 @@
 
 	DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
 	ASSERT( dev != NULL, return -1;);
 	idev = (struct irda_device *) dev->priv;
 	
@@ -920,6 +914,8 @@
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
 	
 	iobase = idev->io.iobase;
+
+	irda_device_net_close(dev);
 
 	disable_dma( idev->io.dma);
 
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c
--- v2.3.15/linux/drivers/net/irda/tekram.c	Tue Jul  6 19:05:49 1999
+++ linux/drivers/net/irda/tekram.c	Mon Aug 30 10:23:14 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Sun May 16 14:33:42 1999
+ * Modified at:   Thu Jul 15 01:17:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -36,7 +36,7 @@
 static void tekram_reset(struct irda_device *dev);
 static void tekram_open(struct irda_device *dev, int type);
 static void tekram_close(struct irda_device *dev);
-static void tekram_change_speed(struct irda_device *dev, int baud);
+static void tekram_change_speed(struct irda_device *dev, __u32 speed);
 static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos);
 
 #define TEKRAM_115200 0x00
@@ -85,7 +85,7 @@
 }
 
 /*
- * Function tekram_change_speed (tty, baud)
+ * Function tekram_change_speed (tty, speed)
  *
  *    Set the speed for the Tekram IRMate 210 type dongle. Warning, this 
  *    function must be called with a process context!
@@ -100,7 +100,7 @@
  *    6. wait at least 50 us, new setting (baud rate, etc) takes effect here 
  *       after
  */
-static void tekram_change_speed(struct irda_device *idev, int baud)
+static void tekram_change_speed(struct irda_device *idev, __u32 speed)
 {
 	__u8 byte;
 	
@@ -109,7 +109,7 @@
 	ASSERT(idev != NULL, return;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
 
-	switch (baud) {
+	switch (speed) {
 	default:
 	case 9600:
 		byte = TEKRAM_PW|TEKRAM_9600;
@@ -135,7 +135,7 @@
 	irda_device_set_dtr_rts(idev, TRUE, FALSE);
 	
 	/* Wait at least 7us */
-	udelay(7);
+	udelay(10);
 
 	/* Write control byte */
 	irda_device_raw_write(idev, &byte, 1);
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c
--- v2.3.15/linux/drivers/net/irda/toshoboe.c	Wed Aug 18 11:38:51 1999
+++ linux/drivers/net/irda/toshoboe.c	Mon Aug 30 10:23:14 1999
@@ -460,7 +460,7 @@
 
 /* Change the baud rate */
 static void 
-toshoboe_change_speed (struct irda_device *idev, int speed)
+toshoboe_change_speed (struct irda_device *idev, __u32 speed)
 {
   struct toshoboe_cb *self;
   DEBUG (4, __FUNCTION__ "()\n");
@@ -582,10 +582,7 @@
 
   sti ();
 
-
-  dev->tbusy = 0;
-  dev->interrupt = 0;
-  dev->start = 1;
+  irda_device_net_open(dev);
 
   MOD_INC_USE_COUNT;
 
@@ -607,9 +604,7 @@
   ASSERT (idev != NULL, return 0;);
   ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;);
 
-  dev->tbusy = 1;
-  dev->start = 0;
-
+  irda_device_net_close(dev);
 
   self = idev->priv;
 
@@ -849,7 +844,7 @@
                                  PCI_DEVICE_ID_FIR701, pci_dev);
       if (pci_dev)
         {
-          printk (KERN_WARNING "ToshOboe: Found 701 chip at 0x%0lx irq %d\n",
+          printk (KERN_WARNING "ToshOboe: Found 701 chip at 0x%0lx irq %ld\n",
                   pci_dev->resource[0],
                   pci_dev->irq);
 
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/uircc.c linux/drivers/net/irda/uircc.c
--- v2.3.15/linux/drivers/net/irda/uircc.c	Wed Aug 18 11:38:51 1999
+++ linux/drivers/net/irda/uircc.c	Mon Aug 30 10:23:14 1999
@@ -7,7 +7,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Dec 26 10:59:03 1998
- * Modified at:   Wed May 19 15:29:56 1999
+ * Modified at:   Tue Aug 24 13:33:57 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -73,11 +73,11 @@
 static int  uircc_dma_receive_complete(struct irda_device *idev, int iobase);
 static int  uircc_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static void uircc_dma_write(struct irda_device *idev, int iobase);
-static void uircc_change_speed(struct irda_device *idev, int baud);
+static void uircc_change_speed(struct irda_device *idev, __u32 baud);
 static void uircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void uircc_wait_until_sent(struct irda_device *idev);
 static int  uircc_is_receiving(struct irda_device *idev);
-static int uircc_toshiba_cmd(int *retval, int arg0, int arg1, int arg2);
+static int  uircc_toshiba_cmd(int *retval, int arg0, int arg1, int arg2);
 static int  uircc_net_init(struct net_device *dev);
 static int  uircc_net_open(struct net_device *dev);
 static int  uircc_net_close(struct net_device *dev);
@@ -318,7 +318,7 @@
  *    Change the speed of the device
  *
  */
-static void uircc_change_speed(struct irda_device *idev, int speed)
+static void uircc_change_speed(struct irda_device *idev, __u32 speed)
 {
 	struct uircc_cb *self;
 	int iobase; 
@@ -846,9 +846,7 @@
 	}
 		
 	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	irda_device_net_open(dev);
 
 	/* turn on interrupts */
 	
@@ -870,10 +868,6 @@
 
 	DEBUG(4, __FUNCTION__ "()\n");
 	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
 	ASSERT(dev != NULL, return -1;);
 	idev = (struct irda_device *) dev->priv;
 	
@@ -881,6 +875,8 @@
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
 	
 	iobase = idev->io.iobase;
+
+	irda_device_net_close(dev);
 
 	disable_dma(idev->io.dma);
 
diff -u --recursive --new-file v2.3.15/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c
--- v2.3.15/linux/drivers/net/irda/w83977af_ir.c	Wed Aug 18 11:38:51 1999
+++ linux/drivers/net/irda/w83977af_ir.c	Mon Aug 30 10:23:14 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Wed Nov  4 11:46:16 1998
- * Modified at:   Fri May 21 22:18:19 1999
+ * Modified at:   Wed Aug 11 09:27:54 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -90,7 +90,7 @@
 static int  w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static int  w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
 static void w83977af_dma_write(struct irda_device *idev, int iobase);
-static void w83977af_change_speed(struct irda_device *idev, int baud);
+static void w83977af_change_speed(struct irda_device *idev, __u32 speed);
 static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void w83977af_wait_until_sent(struct irda_device *idev);
 static int  w83977af_is_receiving(struct irda_device *idev);
@@ -376,7 +376,7 @@
  *    Change the speed of the device
  *
  */
-void w83977af_change_speed(struct irda_device *idev, int speed)
+void w83977af_change_speed(struct irda_device *idev, __u32 speed)
 {
 	int ir_mode = HCR_SIR;
 	int iobase; 
@@ -1203,11 +1203,6 @@
 		return -EAGAIN;
 	}
 		
-	/* Ready to play! */
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
 	/* Save current set */
 	set = inb(iobase+SSR);
 
@@ -1222,6 +1217,9 @@
 	/* Restore bank register */
 	outb(set, iobase+SSR);
 
+	/* Ready to play! */
+	irda_device_net_open(dev);
+
 	MOD_INC_USE_COUNT;
 
 	return 0;
@@ -1240,18 +1238,18 @@
 	__u8 set;
 
 	DEBUG(0, __FUNCTION__ "()\n");
-	
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
 
 	ASSERT(dev != NULL, return -1;);
+	
 	idev = (struct irda_device *) dev->priv;
 	
 	ASSERT(idev != NULL, return 0;);
 	ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
 	
 	iobase = idev->io.iobase;
+
+	/* Stop device */
+	irda_device_net_close(dev);
 
 	disable_dma(idev->io.dma);
 
diff -u --recursive --new-file v2.3.15/linux/drivers/net/jazzsonic.c linux/drivers/net/jazzsonic.c
--- v2.3.15/linux/drivers/net/jazzsonic.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/jazzsonic.c	Thu Aug 26 14:28:05 1999
@@ -90,7 +90,7 @@
  * Probe for a SONIC ethernet controller on a Mips Jazz board.
  * Actually probing is superfluous but we're paranoid.
  */
-__initfunc(int sonic_probe(struct net_device *dev))
+int __init sonic_probe(struct net_device *dev)
 {
     unsigned int base_addr = dev ? dev->base_addr : 0;
     int i;
@@ -115,8 +115,8 @@
     return -ENODEV;
 }
 
-__initfunc(static int sonic_probe1(struct net_device *dev,
-                                   unsigned int base_addr, unsigned int irq))
+static int __init sonic_probe1(struct net_device *dev,
+                               unsigned int base_addr, unsigned int irq)
 {
     static unsigned version_printed = 0;
     unsigned int silicon_revision;
diff -u --recursive --new-file v2.3.15/linux/drivers/net/macsonic.c linux/drivers/net/macsonic.c
--- v2.3.15/linux/drivers/net/macsonic.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/macsonic.c	Thu Aug 26 14:29:08 1999
@@ -174,7 +174,7 @@
 static unsigned char nibbletab[] = {0, 8, 4, 12, 2, 10, 6, 14,
 				    1, 9, 5, 13, 3, 11, 7, 15};
 
-__initfunc(int mac_onboard_sonic_probe(void))
+int __init mac_onboard_sonic_probe(void)
 {
 	struct net_device *dev;
 	unsigned int silicon_revision;
diff -u --recursive --new-file v2.3.15/linux/drivers/net/mvme147.c linux/drivers/net/mvme147.c
--- v2.3.15/linux/drivers/net/mvme147.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/mvme147.c	Thu Aug 26 14:28:33 1999
@@ -70,7 +70,7 @@
 #endif
 
 /* Initialise the one and only on-board 7990 */
-__initfunc(int mvme147lance_probe(struct net_device *dev))
+int __init mvme147lance_probe(struct net_device *dev)
 {
 	static int called = 0;
 	static const char name[] = "MVME147 LANCE";
diff -u --recursive --new-file v2.3.15/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c
--- v2.3.15/linux/drivers/net/ne2k-pci.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/ne2k-pci.c	Mon Aug 30 18:09:00 1999
@@ -86,7 +86,7 @@
 	{0x4a14, 0x5000, "NetVin NV5000SC", 0},
 	{0x1106, 0x0926, "Via 86C926", ONLY_16BIT_IO},
 	{0x10bd, 0x0e34, "SureCom NE34", 0},
-	{0x1050, 0x5a5a, "Winbond", 0},
+	{0x1050, 0x5a5a, "Winbond W89C940F", 0},
 	{0x12c3, 0x0058, "Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX},
 	{0x12c3, 0x5598, "Holtek HT80229",
 	 ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 },
diff -u --recursive --new-file v2.3.15/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v2.3.15/linux/drivers/net/net_init.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/net/net_init.c	Tue Aug 31 11:23:03 1999
@@ -135,9 +135,11 @@
 
 	ether_setup(dev); 	/* Hmmm, should this be called here? */
 	
-	if (new_device)
+	if (new_device) {
+		rtnl_lock();
 		register_netdevice(dev);
-
+		rtnl_unlock();
+	}
 	return dev;
 }
 
@@ -259,9 +261,11 @@
 
 	hippi_setup(dev);
 	
-	if (new_device)
+	if (new_device) {
+		rtnl_lock();
 		register_netdevice(dev);
-
+		rtnl_unlock();
+	}
 	return dev;
 }
 
@@ -601,9 +605,11 @@
 	/* New-style flags. */
 	dev->flags		= IFF_BROADCAST;
 
-	if (new_device)
+	if (new_device) {
+		rtnl_lock();
 		register_netdevice(dev);
-
+		rtnl_unlock();
+	}
 	return dev;
 }
 
@@ -744,9 +750,11 @@
                 }
                                                 
         fc_setup(dev);                                 
-        if (new_device)                 
+        if (new_device) {
+		rtnl_lock();
                 register_netdevice(dev);  
-                
+		rtnl_unlock();
+	}                
         return dev;
 }
 
@@ -775,7 +783,7 @@
 void unregister_fcdev(struct net_device *dev)
 {
         rtnl_lock();
-		unregister_netdevice(dev);
+	unregister_netdevice(dev);
         rtnl_unlock();
         fc_freedev(dev);
 }
diff -u --recursive --new-file v2.3.15/linux/drivers/net/olympic.c linux/drivers/net/olympic.c
--- v2.3.15/linux/drivers/net/olympic.c	Wed Aug 18 16:24:11 1999
+++ linux/drivers/net/olympic.c	Thu Aug 26 14:27:11 1999
@@ -150,7 +150,7 @@
 #endif
 #endif
 
-__initfunc(int olympic_probe(struct net_device *dev)) 
+int __init olympic_probe(struct net_device *dev)
 {
 	int cards_found;
 
@@ -158,7 +158,7 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-__initfunc(static int olympic_scan(struct net_device *dev)) 
+static int __init olympic_scan(struct net_device *dev)
 {
 	struct pci_dev *pci_device = NULL ;
 	struct olympic_private *olympic_priv;
@@ -226,7 +226,7 @@
 }
 
 
-__initfunc(static int olympic_init(struct net_device *dev)) 
+static int __init olympic_init(struct net_device *dev)
 {
     	struct olympic_private *olympic_priv;
 	__u8 *olympic_mmio, *init_srb,*adapter_addr;
diff -u --recursive --new-file v2.3.15/linux/drivers/net/ptifddi.c linux/drivers/net/ptifddi.c
--- v2.3.15/linux/drivers/net/ptifddi.c	Wed Aug 18 11:36:42 1999
+++ linux/drivers/net/ptifddi.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: ptifddi.c,v 1.8 1999/08/08 01:35:56 davem Exp $
+/* $Id: ptifddi.c,v 1.9 1999/08/20 00:31:07 davem Exp $
  * ptifddi.c: Network driver for Performance Technologies single-attach
  *            and dual-attach FDDI sbus cards.
  *
diff -u --recursive --new-file v2.3.15/linux/drivers/net/ptifddi.h linux/drivers/net/ptifddi.h
--- v2.3.15/linux/drivers/net/ptifddi.h	Wed Aug 18 11:36:45 1999
+++ linux/drivers/net/ptifddi.h	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: ptifddi.h,v 1.2 1996/12/16 06:15:15 davem Exp $
+/* $Id: ptifddi.h,v 1.3 1999/08/20 00:31:08 davem Exp $
  * ptifddi.c: Defines for Performance Technologies FDDI sbus cards.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.15/linux/drivers/net/sdlamain.c linux/drivers/net/sdlamain.c
--- v2.3.15/linux/drivers/net/sdlamain.c	Wed Jun  2 14:40:22 1999
+++ linux/drivers/net/sdlamain.c	Thu Aug 26 14:27:28 1999
@@ -11,7 +11,7 @@
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 * ============================================================================
-* May 19, 1999  Arnaldo Melo    __initfunc for wanpipe_init
+* May 19, 1999  Arnaldo Melo    __init for wanpipe_init
 * Nov 28, 1997	Jaspreet Singh	Changed DRV_RELEASE to 1
 * Nov 10, 1997	Jaspreet Singh	Changed sti() to restore_flags();
 * Nov 06, 1997 	Jaspreet Singh	Changed DRV_VERSION to 4 and DRV_RELEASE to 0
@@ -43,7 +43,7 @@
 #include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
 #include <asm/uaccess.h>	/* kernel <-> user copy */
 #include <asm/io.h>		/* phys_to_virt() */
-#include <linux/init.h>         /* __initfunc (when not using as a module) */
+#include <linux/init.h>         /* __init (when not using as a module) */
 
 
 /****** Defines & Macros ****************************************************/
@@ -124,7 +124,7 @@
 #ifdef MODULE
 int init_module (void)
 #else
-__initfunc(int wanpipe_init(void))
+int __init wanpipe_init(void)
 #endif
 {
 	int cnt, err = 0;
diff -u --recursive --new-file v2.3.15/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.3.15/linux/drivers/net/sunhme.c	Wed Aug 18 11:36:43 1999
+++ linux/drivers/net/sunhme.c	Tue Aug 31 11:25:33 1999
@@ -3325,7 +3325,7 @@
 	}		
 
 	hpreg_base = pdev->resource[0].start;
-	if ((pdev->resource[0].flags & IORESOURCE_IOPORT) != 0) {
+	if ((pdev->resource[0].flags & IORESOURCE_IO) != 0) {
 		printk("happymeal(PCI): Cannot find proper PCI device base address.\n");
 		return ENODEV;
 	}
diff -u --recursive --new-file v2.3.15/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c
--- v2.3.15/linux/drivers/net/sunlance.c	Wed Aug 18 11:36:43 1999
+++ linux/drivers/net/sunlance.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.87 1999/08/08 01:36:14 davem Exp $
+/* $Id: sunlance.c,v 1.88 1999/08/20 00:31:45 davem Exp $
  * lance.c: Linux/Sparc/Lance driver
  *
  *	Written 1995, 1996 by Miguel de Icaza
diff -u --recursive --new-file v2.3.15/linux/drivers/parport/Config.in linux/drivers/parport/Config.in
--- v2.3.15/linux/drivers/parport/Config.in	Tue Aug  3 15:30:44 1999
+++ linux/drivers/parport/Config.in	Tue Aug 31 11:25:33 1999
@@ -33,6 +33,11 @@
   else
     define_bool CONFIG_PARPORT_ATARI n
   fi
+  if [ "$CONFIG_SBUS" = "y" ]; then
+    dep_tristate '   Sparc hardware (EXPERIMENTAL)' CONFIG_PARPORT_SUNBPP $CONFIG_PARPORT
+  else
+    define_bool CONFIG_PARPORT_SUNBPP n
+  fi
 
   # If exactly one hardware type is selected then parport will optimise away
   # support for loading any others.  Defeat this if the user is keen.
diff -u --recursive --new-file v2.3.15/linux/drivers/parport/Makefile linux/drivers/parport/Makefile
--- v2.3.15/linux/drivers/parport/Makefile	Mon Aug  2 11:16:02 1999
+++ linux/drivers/parport/Makefile	Tue Aug 31 11:25:33 1999
@@ -57,6 +57,13 @@
       M_OBJS += parport_atari.o
     endif
   endif
+  ifeq ($(CONFIG_PARPORT_SUNBPP),y)
+    LX_OBJS += parport_sunbpp.o
+  else
+    ifeq ($(CONFIG_PARPORT_SUNBPP),m)
+      MX_OBJS += parport_sunbpp.o
+    endif
+  endif
   LX_OBJS += init.o
 else
   ifeq ($(CONFIG_PARPORT),m)
@@ -81,6 +88,9 @@
   endif
   ifeq ($(CONFIG_PARPORT_ATARI),m)
     M_OBJS += parport_atari.o
+  endif
+  ifeq ($(CONFIG_PARPORT_SUNBPP),m)
+    M_OBJS += parport_sunbpp.o
   endif
 endif
 
diff -u --recursive --new-file v2.3.15/linux/drivers/parport/parport_amiga.c linux/drivers/parport/parport_amiga.c
--- v2.3.15/linux/drivers/parport/parport_amiga.c	Mon Aug  9 12:32:28 1999
+++ linux/drivers/parport/parport_amiga.c	Thu Aug 26 14:29:50 1999
@@ -221,7 +221,7 @@
 
 /* ----------- Initialisation code --------------------------------- */
 
-__initfunc(int parport_amiga_init(void))
+int __init parport_amiga_init(void)
 {
 	struct parport *p;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/parport/parport_mfc3.c linux/drivers/parport/parport_mfc3.c
--- v2.3.15/linux/drivers/parport/parport_mfc3.c	Sun Aug 15 11:48:32 1999
+++ linux/drivers/parport/parport_mfc3.c	Thu Aug 26 12:42:33 1999
@@ -313,7 +313,7 @@
 
 /* ----------- Initialisation code --------------------------------- */
 
-__initfunc(int parport_mfc3_init(void))
+int __init parport_mfc3_init(void)
 {
 	struct parport *p;
 	int pias = 0;
diff -u --recursive --new-file v2.3.15/linux/drivers/parport/parport_sunbpp.c linux/drivers/parport/parport_sunbpp.c
--- v2.3.15/linux/drivers/parport/parport_sunbpp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/parport/parport_sunbpp.c	Tue Aug 31 11:25:33 1999
@@ -0,0 +1,398 @@
+/* $Id: parport_sunbpp.c,v 1.6 1999/08/31 06:57:22 davem Exp $
+ * Parallel-port routines for Sun architecture
+ * 
+ * Author: Derrick J. Brashear <shadow@dementia.org>
+ *
+ * based on work by:
+ *          Phil Blundell <Philip.Blundell@pobox.com>
+ *          Tim Waugh <tim@cyberelk.demon.co.uk>
+ *	    Jose Renau <renau@acm.org>
+ *          David Campbell <campbell@tirian.che.curtin.edu.au>
+ *          Grant Guenther <grant@torque.net>
+ *          Eddie C. Dost <ecd@skynet.be>
+ *          Stephen Williams (steve@icarus.com)
+ *          Gus Baldauf (gbaldauf@ix.netcom.com)
+ *          Peter Zaitcev
+ *          Tom Dyas
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+
+#include <linux/parport.h>
+
+#include <asm/ptrace.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/oplib.h>           /* OpenProm Library */
+#include <asm/sbus.h>            /* struct linux_sbus *SBus_chain */
+#include <asm/dma.h>             /* BPP uses LSI 64854 for DMA */
+#include <asm/irq.h>
+#include <asm/sunbpp.h>
+
+#undef __SUNBPP_DEBUG
+#ifdef __SUNBPP_DEBUG
+#define dprintk(x) printk x
+#else
+#define dprintk(x)
+#endif
+
+static void parport_sunbpp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	parport_generic_irq(irq, (struct parport *) dev_id, regs);
+}
+
+void
+parport_sunbpp_disable_irq(struct parport *p)
+{
+	struct bpp_regs *regs = (struct bpp_regs *)p->base;
+
+	regs->p_csr &= ~(DMA_INT_ENAB);
+}
+
+void
+parport_sunbpp_enable_irq(struct parport *p)
+{
+	struct bpp_regs *regs = (struct bpp_regs *)p->base;
+
+	regs->p_csr |= DMA_INT_ENAB;
+}
+
+void
+parport_sunbpp_write_data(struct parport *p, unsigned char d)
+{
+	struct bpp_regs *regs = (struct bpp_regs *)p->base;
+
+	regs->p_dr = d;
+	dprintk(("wrote 0x%x\n", d));
+}
+
+unsigned char
+parport_sunbpp_read_data(struct parport *p)
+{
+	struct bpp_regs *regs = (struct bpp_regs *)p->base;
+
+	return regs->p_dr;
+}
+
+static void
+control_pc_to_sunbpp(struct parport *p, unsigned char status)
+{
+  struct bpp_regs *regs = (struct bpp_regs *)p->base;
+  unsigned char value_tcr = regs->p_tcr;
+  unsigned char value_or = regs->p_or;
+
+  if (status & PARPORT_CONTROL_STROBE) 
+    value_tcr |= P_TCR_DS;
+  if (status & PARPORT_CONTROL_AUTOFD) 
+    value_or |= P_OR_AFXN;
+  if (status & PARPORT_CONTROL_INIT) 
+    value_or |= P_OR_INIT;
+  if (status & PARPORT_CONTROL_SELECT) 
+    value_or |= P_OR_SLCT_IN;
+
+  regs->p_or = value_or;
+  regs->p_tcr = value_tcr;
+}
+
+static unsigned char 
+status_sunbpp_to_pc(struct parport *p)
+{
+  struct bpp_regs *regs = (struct bpp_regs *)p->base;
+  unsigned char bits = 0;
+  unsigned char value_tcr = regs->p_tcr;
+  unsigned char value_ir = regs->p_ir;
+
+  if (!(value_ir & P_IR_ERR))          bits |= PARPORT_STATUS_ERROR;
+  if (!(value_ir & P_IR_SLCT))      bits |= PARPORT_STATUS_SELECT;
+  if (!(value_ir & P_IR_PE))        bits |= PARPORT_STATUS_PAPEROUT;
+  if (value_tcr & P_TCR_ACK)        bits |= PARPORT_STATUS_ACK;
+  if (!(value_tcr & P_TCR_BUSY))       bits |= PARPORT_STATUS_BUSY;
+
+  dprintk(("tcr 0x%x ir 0x%x\n", regs->p_tcr, regs->p_ir));
+  dprintk(("read status 0x%x\n", bits));
+  return bits;
+}
+
+static unsigned char 
+control_sunbpp_to_pc(struct parport *p)
+{
+  struct bpp_regs *regs = (struct bpp_regs *)p->base;
+  unsigned char bits = 0;
+  unsigned char value_tcr = regs->p_tcr;
+  unsigned char value_or = regs->p_or;
+
+  if (!(value_tcr & P_TCR_DS))      bits |= PARPORT_CONTROL_STROBE;
+  if (!(value_or & P_OR_AFXN))      bits |= PARPORT_CONTROL_AUTOFD;
+  if (!(value_or & P_OR_INIT))      bits |= PARPORT_CONTROL_INIT;
+  if (value_or & P_OR_SLCT_IN)      bits |= PARPORT_CONTROL_SELECT;
+
+  dprintk(("tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
+  dprintk(("read control 0x%x\n", bits));
+  return bits;
+}
+
+unsigned char 
+parport_sunbpp_read_control(struct parport *p)
+{
+  return control_sunbpp_to_pc(p);
+}
+
+unsigned char 
+parport_sunbpp_frob_control(struct parport *p, unsigned char mask,
+			    unsigned char val)
+{
+  struct bpp_regs *regs = (struct bpp_regs *)p->base;
+  unsigned char value_tcr = regs->p_tcr;
+  unsigned char value_or = regs->p_or;
+
+  dprintk(("frob1: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
+  if (mask & PARPORT_CONTROL_STROBE) {
+    if (val & PARPORT_CONTROL_STROBE)
+      value_tcr &= ~P_TCR_DS;
+    else
+      value_tcr |= P_TCR_DS;
+  }
+  if (mask & PARPORT_CONTROL_AUTOFD) {
+    if (val & PARPORT_CONTROL_AUTOFD)
+      value_or &= ~P_OR_AFXN;
+    else
+      value_or |= P_OR_AFXN;
+  }
+  if (mask & PARPORT_CONTROL_INIT) {
+    if (val & PARPORT_CONTROL_INIT)
+      value_or &= ~P_OR_INIT;
+    else
+      value_or |= P_OR_INIT;
+  }
+  if (mask & PARPORT_CONTROL_SELECT) {
+    if (val & PARPORT_CONTROL_SELECT)
+      value_or |= P_OR_SLCT_IN;
+    else
+      value_or &= ~P_OR_SLCT_IN;
+  }
+  regs->p_or = value_or;
+  regs->p_tcr = value_tcr;
+  dprintk(("frob2: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
+  return parport_sunbpp_read_control(p);
+}
+
+void
+parport_sunbpp_write_control(struct parport *p, unsigned char d)
+{
+  const unsigned char wm = (PARPORT_CONTROL_STROBE |
+			    PARPORT_CONTROL_AUTOFD |
+			    PARPORT_CONTROL_INIT |
+			    PARPORT_CONTROL_SELECT);
+
+  parport_sunbpp_frob_control (p, wm, d & wm);
+  return;
+}
+
+unsigned char 
+parport_sunbpp_read_status(struct parport *p)
+{
+  return status_sunbpp_to_pc(p);
+}
+
+void parport_sunbpp_data_forward (struct parport *p)
+{
+  struct bpp_regs *regs = (struct bpp_regs *)p->base;
+  unsigned char value_tcr = regs->p_tcr;
+
+  dprintk(("forward\n"));
+  value_tcr = regs->p_tcr;
+  value_tcr &= ~P_TCR_DIR;
+  regs->p_tcr = value_tcr;
+}
+
+void parport_sunbpp_data_reverse (struct parport *p)
+{
+  struct bpp_regs *regs = (struct bpp_regs *)p->base;
+
+  dprintk(("reverse\n"));
+  regs->p_tcr |= P_TCR_DIR;
+}
+
+void
+parport_sunbpp_init_state(struct pardevice *dev, struct parport_state *s)
+{
+	s->u.pc.ctr = 0xc;
+	s->u.pc.ecr = 0x0;
+}
+
+void
+parport_sunbpp_save_state(struct parport *p, struct parport_state *s)
+{
+	s->u.pc.ctr = parport_sunbpp_read_control(p);
+}
+
+void
+parport_sunbpp_restore_state(struct parport *p, struct parport_state *s)
+{
+	parport_sunbpp_write_control(p, s->u.pc.ctr);
+}
+
+void
+parport_sunbpp_inc_use_count(void)
+{
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
+}
+
+void
+parport_sunbpp_dec_use_count(void)
+{
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
+}
+
+static struct parport_operations parport_sunbpp_ops = 
+{
+	parport_sunbpp_write_data,
+	parport_sunbpp_read_data,
+
+	parport_sunbpp_write_control,
+	parport_sunbpp_read_control,
+	parport_sunbpp_frob_control,
+
+	parport_sunbpp_read_status,
+
+	parport_sunbpp_enable_irq,
+        parport_sunbpp_disable_irq,
+
+        parport_sunbpp_data_forward,
+        parport_sunbpp_data_reverse,
+
+        parport_sunbpp_init_state,
+        parport_sunbpp_save_state,
+        parport_sunbpp_restore_state,
+
+        parport_sunbpp_inc_use_count,
+        parport_sunbpp_dec_use_count,
+
+        parport_ieee1284_epp_write_data,
+        parport_ieee1284_epp_read_data,
+        parport_ieee1284_epp_write_addr,
+        parport_ieee1284_epp_read_addr,
+
+        parport_ieee1284_ecp_write_data,
+        parport_ieee1284_ecp_read_data,
+        parport_ieee1284_ecp_write_addr,
+
+        parport_ieee1284_write_compat,
+        parport_ieee1284_read_nibble,
+        parport_ieee1284_read_byte,
+};
+
+
+int
+init_one_port(struct linux_sbus_device *sdev)
+{
+	struct parport *p;
+	/* at least in theory there may be a "we don't dma" case */
+	struct parport_operations *ops;
+	char *base;
+	int irq, dma, err, size;
+	struct bpp_regs *regs;
+	unsigned char value_tcr;
+
+	irq = sdev->irqs[0];
+	prom_apply_sbus_ranges(sdev->my_bus, sdev->reg_addrs, 1, sdev);
+	base = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
+				 sdev->reg_addrs[0].reg_size, 
+				 "sunbpp", sdev->reg_addrs[0].which_io, 0);
+	size = sdev->reg_addrs[0].reg_size;
+	dma = PARPORT_DMA_NONE;
+
+	ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
+        if (!ops) {
+	  sparc_free_io(base, size);
+	  return 0;
+        }
+        memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations));
+
+	if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) {
+	  kfree(ops);
+	  sparc_free_io(base, size);
+	  return 0;
+	}
+
+	if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
+			       0, p->name, p)) != 0) {
+	  parport_unregister_port(p);
+	  kfree(ops);
+	  sparc_free_io(base, size);
+	  return err;
+	} else
+	  parport_sunbpp_enable_irq(p);
+
+	regs = (struct bpp_regs *)p->base;
+	dprintk(("forward\n"));
+	value_tcr = regs->p_tcr;
+	value_tcr &= ~P_TCR_DIR;
+	regs->p_tcr = value_tcr;
+
+	printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base);
+	parport_proc_register(p);
+	parport_announce_port (p);
+
+	return 1;
+}
+
+EXPORT_NO_SYMBOLS;
+
+#ifdef MODULE
+int init_module(void)
+#else
+int __init parport_sunbpp_init(void)
+#endif
+{
+        struct linux_sbus *sbus;
+        struct linux_sbus_device *sdev;
+	int count = 0;
+
+	for_each_sbus(sbus) {
+		for_each_sbusdev(sdev, sbus) {
+			if (!strcmp(sdev->prom_name, "SUNW,bpp"))
+				count += init_one_port(sdev);
+		}
+	}
+	return count ? 0 : -ENODEV;
+}
+
+#ifdef MODULE
+MODULE_AUTHOR("Derrick J Brashear");
+MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port");
+MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port");
+
+void
+cleanup_module(void)
+{
+	struct parport *p = parport_enumerate(), *tmp;
+	while (p) {
+		tmp = p->next;
+		if (1/*p->modes & PARPORT_MODE_PCSPP*/) { 
+		  struct parport_operations *ops = p->ops;
+		  if (p->irq != PARPORT_IRQ_NONE) {
+		    parport_sunbpp_disable_irq(p);
+		    free_irq(p->irq, p);
+		  }
+		  sparc_free_io((char *)p->base, p->size);
+		  parport_proc_unregister(p);
+		  parport_unregister_port(p);
+		  kfree (ops);
+		}
+		p = tmp;
+	}
+}
+#endif
diff -u --recursive --new-file v2.3.15/linux/drivers/pci/devlist.h linux/drivers/pci/devlist.h
--- v2.3.15/linux/drivers/pci/devlist.h	Thu Aug  5 18:44:28 1999
+++ linux/drivers/pci/devlist.h	Tue Aug 31 10:53:32 1999
@@ -101,8 +101,9 @@
 	DEVICE( CIRRUS,		CIRRUS_5436,	"GD 5436")
 	DEVICE( CIRRUS,		CIRRUS_5446,	"GD 5446")
 	DEVICE( CIRRUS,		CIRRUS_5480,	"GD 5480")
-	DEVICE( CIRRUS,		CIRRUS_5464,	"GD 5464")
-	DEVICE( CIRRUS,		CIRRUS_5465,	"GD 5465")
+	DEVICE( CIRRUS,		CIRRUS_5462,	"Laguna")
+	DEVICE( CIRRUS,		CIRRUS_5464,	"Laguna 3D")
+	DEVICE( CIRRUS,		CIRRUS_5465,	"Laguna 3DA")
 	DEVICE( CIRRUS,		CIRRUS_6729,	"CL 6729")
 	DEVICE( CIRRUS,		CIRRUS_6832,	"PD 6832")
 	DEVICE( CIRRUS,		CIRRUS_7542,	"CL 7542")
@@ -134,11 +135,21 @@
 ENDVENDOR()
 
 VENDOR( TRIDENT, "Trident" )
+	DEVICE( TRIDENT,	TRIDENT_9320,	"Cyber9320")
+	DEVICE( TRIDENT,	TRIDENT_9388,	"Cyber9388")
 	DEVICE( TRIDENT,	TRIDENT_9397,	"Cyber9397")
-	DEVICE( TRIDENT,	TRIDENT_9420,	"TG 9420")
-	DEVICE( TRIDENT,	TRIDENT_9440,	"TG 9440")
-	DEVICE( TRIDENT,	TRIDENT_9660,	"TG 9660 / Cyber9385")
-	DEVICE( TRIDENT,	TRIDENT_9750,	"Image 975")
+	DEVICE( TRIDENT,	TRIDENT_939A,	"Cyber939a")
+	DEVICE( TRIDENT,	TRIDENT_9520,	"Cyber9520")
+	DEVICE( TRIDENT,	TRIDENT_9525,	"Cyber9525")
+	DEVICE( TRIDENT,	TRIDENT_9420,	"TGUI 9420")
+	DEVICE( TRIDENT,	TRIDENT_9440,	"TGUI 9440")
+	DEVICE( TRIDENT,	TRIDENT_9660,	"TGUI 9660 / Cyber9385")
+	DEVICE( TRIDENT,	TRIDENT_9750,	"3DImage 975")
+	DEVICE( TRIDENT,	TRIDENT_9850,	"3DImage 985")
+	DEVICE( TRIDENT,	TRIDENT_9880,	"Blade 3D")
+	DEVICE( TRIDENT,	TRIDENT_8400,	"CyberBlade/i7")
+	DEVICE( TRIDENT,	TRIDENT_8420,	"CyberBlade/i7d")
+	DEVICE( TRIDENT,	TRIDENT_8500,	"CyberBlade/i1")
 ENDVENDOR()
 
 VENDOR( AI, "Acer Incorporated" )
@@ -151,11 +162,13 @@
 	DEVICE( MATROX,		MATROX_MYS,	"Mystique")
 	DEVICE( MATROX,		MATROX_MIL_2,	"Millennium II")
 	DEVICE( MATROX,		MATROX_MIL_2_AGP,"Millennium II AGP")
-	DEVICE( MATROX,         MATROX_G200_PCI,"G200 PCI")
-	DEVICE( MATROX,         MATROX_G200_AGP,"G200 AGP")
 	DEVICE( MATROX,		MATROX_MGA_IMP,	"MGA Impression")
 	DEVICE( MATROX,         MATROX_G100_MM, "G100 multi monitor")
 	DEVICE( MATROX,         MATROX_G100_AGP,"G100 AGP")
+	DEVICE( MATROX,         MATROX_G200_PCI,"G200 PCI")
+	DEVICE( MATROX,         MATROX_G200_AGP,"G200 AGP")
+	DEVICE( MATROX,		MATROX_G400,	"G400")
+	DEVICE( MATROX,		MATROX_VIA,	"Corona / Meteor-II")
 ENDVENDOR()
 
 VENDOR( CT, "Chips & Technologies" )
@@ -185,15 +198,20 @@
 	DEVICE( SI,		SI_ACPI,	"ACPI")
 	DEVICE( SI,		SI_5597_VGA,	"5597/5598 VGA")
 	DEVICE( SI,		SI_6205,	"6205")
-	DEVICE( SI,		SI_501,		"85C501")
 	DEVICE( SI,		SI_496,		"85C496")
+	DEVICE(	SI,		SI_501,		"85C501")
+	DEVICE(	SI,		SI_530,		"530 Host")
 	DEVICE( SI,		SI_601,		"85C601")
+	DEVICE(	SI,		SI_620,		"620 Host")
 	DEVICE( SI,		SI_5107,	"5107")
 	DEVICE( SI,		SI_5511,       	"85C5511")
-	DEVICE( SI,		SI_5513,	"85C5513")
+	DEVICE( SI,		SI_5513,	"85C5513 IDE")
 	DEVICE( SI,		SI_5571,	"5571")
 	DEVICE( SI,		SI_5591,	"5591/5592 Host")
 	DEVICE( SI,		SI_5597,	"5597/5598 Host")
+	DEVICE(	SI,		SI_5600,	"5600 Host")
+	DEVICE(	SI,		SI_6306,	"3D-AGP 6306 VGA")
+	DEVICE(	SI,		SI_6326,	"3D-AGP 6326 VGA")
 	DEVICE( SI,		SI_7001,	"7001 USB")
 ENDVENDOR()
 
@@ -251,6 +269,7 @@
 
 VENDOR( WINBOND2, "Winbond" )
 	DEVICE( WINBOND2,	WINBOND2_89C940,"NE2000-PCI")
+	DEVICE( WINBOND2,	WINBOND2_89C940F, "W89C940F")
 ENDVENDOR()
 
 VENDOR( MOTOROLA, "Motorola" )
@@ -475,6 +494,12 @@
 ENDVENDOR()
 
 VENDOR( NVIDIA, "NVidia" )
+	DEVICE( NVIDIA,		NVIDIA_TNT,	"Riva TNT")
+	DEVICE( NVIDIA,		NVIDIA_TNT2,	"Riva TNT2")
+	DEVICE( NVIDIA,		NVIDIA_UTNT2,	"Riva TNT2 (Ultra)")
+	DEVICE( NVIDIA,		NVIDIA_VTNT2,	"Riva TNT2 (Vanta)")
+	DEVICE( NVIDIA,		NVIDIA_UVTNT2,	"Riva TNT2 (Ultra Vanta)")
+	DEVICE( NVIDIA,		NVIDIA_ITNT2,	"Riva TNT2 (Integrated)")
 ENDVENDOR()
 
 VENDOR( IMS, "IMS" )
@@ -499,6 +524,7 @@
 VENDOR( INTERG, "Intergraphics" )
 	DEVICE( INTERG,		INTERG_1680,	"IGA-1680")
 	DEVICE( INTERG,         INTERG_1682,    "IGA-1682")
+	DEVICE( INTERG,		INTERG_2000,	"CyberPro 2000")
 ENDVENDOR()
 
 VENDOR( REALTEK, "Realtek" )
@@ -517,7 +543,8 @@
 ENDVENDOR()
 
 VENDOR( TTI, "Triones Technologies, Inc." )
-	DEVICE(	TTI,		TTI_HPT343,	"HPT343")
+	DEVICE(	TTI,		TTI_HPT343,	"HPT343 IDE UltraDMA/33")
+	DEVICE(	TTI,		TTI_HPT366,	"HPT366 IDE UltraDMA/66")
 ENDVENDOR()
 
 VENDOR( VIA, "VIA Technologies" )
@@ -528,13 +555,21 @@
 	DEVICE( VIA,		VIA_82C585,	"VT 82C585 Apollo VP1/VPX")
 	DEVICE( VIA,		VIA_82C586_0,	"VT 82C586 Apollo ISA")
 	DEVICE( VIA,		VIA_82C595,	"VT 82C595 Apollo VP2")
+	DEVICE(	VIA,		VIA_82C596,	"VT 82C596 Apollo Mobile")
 	DEVICE( VIA,		VIA_82C597_0,	"VT 82C597 Apollo VP3")
 	DEVICE( VIA,		VIA_82C598_0,	"VT 82C598 Apollo MVP3")
+	DEVICE(	VIA,		VIA_82C680,	"VT 82C680 Apollo P6")
+	DEVICE(	VIA,		VIA_82C686,	"VT 82C686 Apollo Super")
+	DEVICE(	VIA,		VIA_82C691,	"VT 82C691 Apollo Pro")
+	DEVICE(	VIA,		VIA_82C693,	"VT 82C693 Apollo Pro Plus")
 	DEVICE( VIA,		VIA_82C926,	"VT 82C926 Amazon")
 	DEVICE( VIA,		VIA_82C416,	"VT 82C416MV")
 	DEVICE( VIA,		VIA_82C595_97,	"VT 82C595 Apollo VP2/97")
 	DEVICE( VIA,		VIA_82C586_2,	"VT 82C586 Apollo USB")
 	DEVICE( VIA,		VIA_82C586_3,	"VT 82C586B Apollo ACPI")
+	DEVICE(	VIA,		VIA_82C686_4,	"VT 82C686 Apollo Super ACPI")
+	DEVICE(	VIA,		VIA_82C686_5,	"VT 82C686 Apollo Super AC97/Audio")
+	DEVICE(	VIA,		VIA_82C686_6,	"VT 82C686 Apollo Super AC97/Modem")
 	DEVICE( VIA,		VIA_86C100A,	"VT 86C100A")
 	DEVICE( VIA,		VIA_82C597_1,	"VT 82C597 Apollo VP3 AGP")
 	DEVICE( VIA,		VIA_82C598_1,	"VT 82C598 Apollo MVP3 AGP")
@@ -764,6 +799,10 @@
 	DEVICE( OPTIBASE,	OPTIBASE_VQUEST,"VideoQuest")
 ENDVENDOR()
 
+VENDOR(	ESS, "ESS Technologies" )
+	DEVICE(	ESS,		ESS_AUDIOPCI,	"3D Audio 1969")
+ENDVENDOR()
+
 VENDOR( SATSAGEM, "SatSagem" )
 	DEVICE( SATSAGEM,	SATSAGEM_PCR2101,"PCR2101 DVB receiver")
 	DEVICE( SATSAGEM,	SATSAGEM_TELSATTURBO,"Telsat Turbo DVB")
@@ -867,6 +906,7 @@
 	DEVICE( INTEL,		INTEL_82596,	"82596")
 	DEVICE( INTEL,		INTEL_82865,	"82865")
 	DEVICE( INTEL,		INTEL_82557,	"EtherExpress Pro100")
+	DEVICE( INTEL,		INTEL_82559ER,	"82559ER")
 	DEVICE( INTEL,		INTEL_82437,	"82437")
 	DEVICE( INTEL,		INTEL_82371FB_0,"82371FB PIIX ISA")
 	DEVICE( INTEL,		INTEL_82371FB_1,"82371FB PIIX IDE")
diff -u --recursive --new-file v2.3.15/linux/drivers/pci/names.c linux/drivers/pci/names.c
--- v2.3.15/linux/drivers/pci/names.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/pci/names.c	Tue Aug 31 11:02:26 1999
@@ -79,12 +79,12 @@
 		}
 
 		/* Ok, found the vendor, but unknown device */
-		sprintf(name, " PCI device %04x:%04x (%s)", dev->vendor, dev->device, vendor_p->name);
+		sprintf(name, "PCI device %04x:%04x (%s)", dev->vendor, dev->device, vendor_p->name);
 		return;
 
 		/* Full match */
 		match_device: {
-			char *n = name + sprintf(name, " %s %s", vendor_p->name, device_p->name);
+			char *n = name + sprintf(name, "%s %s", vendor_p->name, device_p->name);
 			int nr = device_p->seen + 1;
 			device_p->seen = nr;
 			if (nr > 1)
diff -u --recursive --new-file v2.3.15/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.3.15/linux/drivers/pci/pci.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/pci/pci.c	Tue Aug 31 11:06:09 1999
@@ -9,7 +9,6 @@
  *	Copyright 1997 -- 1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -18,6 +17,7 @@
 #include <linux/malloc.h>
 #include <linux/ioport.h>
 
+#include <asm/pci.h>
 #include <asm/page.h>
 
 #undef DEBUG
@@ -89,6 +89,65 @@
 }
 
 
+int
+pci_find_capability(struct pci_dev *dev, int cap)
+{
+	u16 status;
+	u8 pos, id;
+	int ttl = 48;
+
+	pci_read_config_word(dev, PCI_STATUS, &status);
+	if (!(status & PCI_STATUS_CAP_LIST))
+		return 0;
+	pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos);
+	while (ttl-- && pos >= 0x40) {
+		pos &= ~3;
+		pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id);
+		if (id == 0xff)
+			break;
+		if (id == cap)
+			return pos;
+		pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos);
+	}
+	return 0;
+}
+
+
+/*
+ *  For given resource region of given device, return the resource
+ *  region of parent bus the given region is contained in or where
+ *  it should be allocated from.
+ */
+struct resource *
+pci_find_parent_resource(struct pci_dev *dev, struct resource *res)
+{
+	struct pci_bus *bus = dev->bus;
+	int i;
+	struct resource *best = NULL;
+
+	while (bus) {
+		for(i=0; i<4; i++) {
+			struct resource *r = bus->resource[i];
+			if (!r)
+				continue;
+			if (res->start && !(res->start >= r->start && res->end <= r->end))
+				continue;	/* Not contained */
+			if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM))
+				continue;	/* Wrong type */
+			if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH))
+				return r;	/* Exact match */
+			if ((res->flags & IORESOURCE_PREFETCH) && !(r->flags & IORESOURCE_PREFETCH))
+				best = r;	/* Approximating prefetchable by non-prefetchable */
+		}
+		if (best)
+			return best;
+		bus = bus->parent;
+	}
+	printk(KERN_ERR "PCI: Bug: Parent resource not found!\n");
+	return NULL;
+}
+
+
 /*
  * This interrupt-safe spinlock protects all accesses to PCI
  * configuration space.
@@ -152,7 +211,7 @@
 static inline unsigned int pci_resource_flags(unsigned int flags)
 {
 	if (flags & PCI_BASE_ADDRESS_SPACE_IO)
-		return IORESOURCE_IO | flags;
+		return IORESOURCE_IO;
 
 	if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH)
 		return IORESOURCE_MEM | IORESOURCE_PREFETCH;
@@ -192,7 +251,7 @@
 			res->start = l & PCI_BASE_ADDRESS_IO_MASK;
 			sz = ~(sz & PCI_BASE_ADDRESS_IO_MASK) & 0xffff;
 		}
-		res->end = res->start + sz;
+		res->end = res->start + (unsigned long) sz;
 		res->flags |= (l & 0xf) | pci_resource_flags(l);
 		if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
 		    == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
@@ -208,7 +267,7 @@
 				res->end = res->start + (((unsigned long) ~l) << 32);
 #else
 			if (l) {
-				printk("PCI: Unable to handle 64-bit address for device %s\n", dev->name);
+				printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", dev->name);
 				res->start = 0;
 				res->flags = 0;
 				continue;
@@ -228,17 +287,80 @@
 			res->flags = (l & PCI_ROM_ADDRESS_ENABLE) |
 			  IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
 			res->start = l & PCI_ROM_ADDRESS_MASK;
-			res->end = res->start + (~(sz & PCI_ROM_ADDRESS_MASK));
+			sz = ~(sz & PCI_ROM_ADDRESS_MASK);
+			res->end = res->start + (unsigned long) sz;
 		}
 		res->name = dev->name;
 	}
 	pci_write_config_word(dev, PCI_COMMAND, cmd);
 }
 
+static void __init pci_read_bridge_bases(struct pci_dev *dev, struct pci_bus *child)
+{
+	u8 io_base_lo, io_limit_lo;
+	u16 mem_base_lo, mem_limit_lo, io_base_hi, io_limit_hi;
+	u32 mem_base_hi, mem_limit_hi;
+	unsigned long base, limit;
+	struct resource *res;
+	int i;
+
+	for(i=0; i<3; i++)
+		child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
+
+	res = child->resource[0];
+	pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
+	pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
+	pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
+	pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
+	base = ((io_base_lo & PCI_IO_RANGE_MASK) << 8) | (io_base_hi << 16);
+	limit = ((io_limit_lo & PCI_IO_RANGE_MASK) << 8) | (io_limit_hi << 16);
+	if (base && base <= limit) {
+		res->flags |= (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
+		res->start = base;
+		res->end = limit + 0xfff;
+		res->name = child->name;
+	}
+
+	res = child->resource[1];
+	pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
+	pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
+	base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
+	limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
+	if (base && base <= limit) {
+		res->flags |= (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
+		res->start = base;
+		res->end = limit + 0xfffff;
+		res->name = child->name;
+	}
+
+	res = child->resource[2];
+	pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
+	pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
+	pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
+	pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
+	base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
+	limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
+#if BITS_PER_LONG == 64
+	base |= ((long) mem_base_hi) << 32;
+	limit |= ((long) mem_limit_hi) << 32;
+#else
+	if (mem_base_hi || mem_limit_hi) {
+		printk(KERN_ERR "PCI: Unable to handle 64-bit address space for %s\n", child->name);
+		return;
+	}
+#endif
+	if (base && base <= limit) {
+		res->flags |= (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
+		res->start = base;
+		res->end = limit + 0xfffff;
+		res->name = child->name;
+	}
+}
+
 static unsigned int __init pci_do_scan_bus(struct pci_bus *bus)
 {
 	unsigned int devfn, l, max, class;
-	unsigned char cmd, irq, tmp, hdr_type, is_multi = 0;
+	unsigned char irq, hdr_type, is_multi = 0;
 	struct pci_dev *dev, **bus_last;
 	struct pci_bus *child;
 	struct pci_dev *dev_cache = NULL;
@@ -274,15 +396,9 @@
 		dev_cache = NULL;
 		dev->vendor = l & 0xffff;
 		dev->device = (l >> 16) & 0xffff;
+		sprintf(dev->name, "%02x:%02x.%d", bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
 		pci_name_device(dev);
 
-		/* non-destructively determine if device can be a master: */
-		pci_read_config_byte(dev, PCI_COMMAND, &cmd);
-		pci_write_config_byte(dev, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
-		pci_read_config_byte(dev, PCI_COMMAND, &tmp);
-		dev->master = ((tmp & PCI_COMMAND_MASTER) != 0);
-		pci_write_config_byte(dev, PCI_COMMAND, cmd);
-
 		pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
 		class >>= 8;				    /* upper 3 bytes */
 		dev->class = class;
@@ -391,11 +507,13 @@
 
 			/*
 			 * Set up the primary, secondary and subordinate
-			 * bus numbers.
+			 * bus numbers.  Read resource ranges behind the bridge.
 			 */
 			child->number = child->secondary = ++max;
 			child->primary = bus->secondary;
 			child->subordinate = 0xff;
+			sprintf(child->name, "PCI Bus #%02x", child->number);
+			pci_read_bridge_bases(dev, child);
 			/*
 			 * Clear all status bits and turn off memory,
 			 * I/O and master enables.
@@ -410,7 +528,8 @@
 			 * do not modify the configuration, merely note it.
 			 */
 			pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
-			if ((buses & 0xFFFFFF) != 0)
+			if ((buses & 0xFFFFFF) != 0
+			    && ! pcibios_assign_all_busses())
 			  {
 			    unsigned int cmax;
 
@@ -459,20 +578,42 @@
 	return max;
 }
 
+static int __init pci_bus_exists(struct pci_bus *b, int nr)
+{
+	while (b) {
+		if (b->number == nr)
+			return 1;
+		if (b->children && pci_bus_exists(b->children, nr))
+			return 1;
+		b = b->next;
+	}
+	return 0;
+}
+
 struct pci_bus * __init pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata)
 {
-	struct pci_bus *b;
+	struct pci_bus *b, **r;
+
+	if (pci_bus_exists(pci_root, bus)) {
+		/* If we already got to this bus through a different bridge, ignore it */
+		DBG("PCI: Bus %02x already known\n", bus);
+		return NULL;
+	}
 
 	b = kmalloc(sizeof(*b), GFP_KERNEL);
 	memset(b, 0, sizeof(*b));
-	if (pci_root) {
-		b->next = pci_root->next;
-		pci_root->next = b;
-	} else
-		pci_root = b;
+
+	/* Put the new bus at the end of the chain of busses.  */
+	r = &pci_root;
+	while (*r)
+		r = &(*r)->next;
+	*r = b;
+
 	b->number = b->secondary = bus;
 	b->sysdata = sysdata;
 	b->ops = ops;
+	b->resource[0] = &ioport_resource;
+	b->resource[1] = &iomem_resource;
 	b->subordinate = pci_do_scan_bus(b);
 	return b;
 }
diff -u --recursive --new-file v2.3.15/linux/drivers/pci/proc.c linux/drivers/pci/proc.c
--- v2.3.15/linux/drivers/pci/proc.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/pci/proc.c	Tue Aug 31 11:08:00 1999
@@ -418,78 +418,33 @@
  */
 static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
 {
-	unsigned int class_rev, bus, devfn;
-	unsigned short vendor, device, status;
-	unsigned char bist, latency, min_gnt, max_lat;
+	unsigned int class_rev;
+	unsigned char latency, min_gnt, max_lat;
 	int reg, len = 0;
-	const char *str;
 
-	bus   = dev->bus->number;
-	devfn = dev->devfn;
-
-	pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class_rev);
-	pcibios_read_config_word (bus, devfn, PCI_VENDOR_ID, &vendor);
-	pcibios_read_config_word (bus, devfn, PCI_DEVICE_ID, &device);
-	pcibios_read_config_word (bus, devfn, PCI_STATUS, &status);
-	pcibios_read_config_byte (bus, devfn, PCI_BIST, &bist);
-	pcibios_read_config_byte (bus, devfn, PCI_LATENCY_TIMER, &latency);
-	pcibios_read_config_byte (bus, devfn, PCI_MIN_GNT, &min_gnt);
-	pcibios_read_config_byte (bus, devfn, PCI_MAX_LAT, &max_lat);
-	if (len + 80 > size) {
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
+	pci_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
+	pci_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
+	if (len + 160 > size)
 		return -1;
-	}
 	len += sprintf(buf + len, "  Bus %2d, device %3d, function %2d:\n",
-		       bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
-	if (len + 80 > size) {
-		return -1;
-	}
-	len += sprintf(buf + len, "    %s: %s (rev %d).\n      ",
+		       dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+	len += sprintf(buf + len, "    %s: %s (rev %d).\n",
 		       pci_strclass(class_rev >> 8),
 		       dev->name,
 		       class_rev & 0xff);
 
-	switch (status & PCI_STATUS_DEVSEL_MASK) {
-	      case PCI_STATUS_DEVSEL_FAST:   str = "Fast devsel.  "; break;
-	      case PCI_STATUS_DEVSEL_MEDIUM: str = "Medium devsel.  "; break;
-	      case PCI_STATUS_DEVSEL_SLOW:   str = "Slow devsel.  "; break;
-	      default:			     str = "Unknown devsel.  ";
-	}
-	if (len + strlen(str) > size) {
-		return -1;
-	}
-	len += sprintf(buf + len, str);
-
-	if (status & PCI_STATUS_FAST_BACK) {
-#		define fast_b2b_capable	"Fast back-to-back capable.  "
-		if (len + strlen(fast_b2b_capable) > size) {
-			return -1;
-		}
-		len += sprintf(buf + len, fast_b2b_capable);
-#		undef fast_b2b_capable
-	}
-
-	if (bist & PCI_BIST_CAPABLE) {
-#		define BIST_capable	"BIST capable.  "
-		if (len + strlen(BIST_capable) > size) {
-			return -1;
-		}
-		len += sprintf(buf + len, BIST_capable);
-#		undef BIST_capable
-	}
-
 	if (dev->irq) {
-		if (len + 40 > size) {
+		if (len + 40 > size)
 			return -1;
-		}
-		len += sprintf(buf + len, "IRQ %d.  ", dev->irq);
+		len += sprintf(buf + len, "      IRQ %d.\n", dev->irq);
 	}
 
-	if (dev->master) {
-		if (len + 80 > size) {
+	if (latency || min_gnt || max_lat) {
+		if (len + 80 > size)
 			return -1;
-		}
-		len += sprintf(buf + len, "Master Capable.  ");
+		len += sprintf(buf + len, "      Master Capable.  ");
 		if (latency)
 		  len += sprintf(buf + len, "Latency=%d.  ", latency);
 		else
@@ -498,15 +453,15 @@
 		  len += sprintf(buf + len, "Min Gnt=%d.", min_gnt);
 		if (max_lat)
 		  len += sprintf(buf + len, "Max Lat=%d.", max_lat);
+		len += sprintf(buf + len, "\n");
 	}
 
 	for (reg = 0; reg < 6; reg++) {
 		struct resource *res = dev->resource + reg;
 		unsigned long base, end, flags;
 
-		if (len + 40 > size) {
+		if (len + 40 > size)
 			return -1;
-		}
 		base = res->start;
 		end = res->end;
 		flags = res->flags;
@@ -515,16 +470,15 @@
 
 		if (flags & PCI_BASE_ADDRESS_SPACE_IO) {
 			len += sprintf(buf + len,
-				       "\n      I/O at 0x%lx [0x%lx].",
+				       "      I/O at 0x%lx [0x%lx].\n",
 				       base, end);
 		} else {
 			const char *pref, *type = "unknown";
 
-			if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+			if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH)
 				pref = "P";
-			} else {
+			else
 				pref = "Non-p";
-			}
 			switch (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
 			      case PCI_BASE_ADDRESS_MEM_TYPE_32:
 				type = "32 bit"; break;
@@ -534,18 +488,23 @@
 				type = "64 bit"; break;
 			}
 			len += sprintf(buf + len,
-				       "\n      %srefetchable %s memory at "
-				       "0x%lx [0x%lx].", pref, type,
+				       "      %srefetchable %s memory at "
+				       "0x%lx [0x%lx].\n", pref, type,
 				       base,
 				       end);
 		}
 	}
 
-	len += sprintf(buf + len, "\n");
 	return len;
 }
 
 
+static struct proc_dir_entry proc_old_pci = {
+	PROC_PCI, 3, "pci",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_array_inode_operations
+};
+
 /*
  * Return list of PCI devices as a character string for /proc/pci.
  * BUF is a buffer that is PAGE_SIZE bytes long.
@@ -563,18 +522,15 @@
 	for (dev = pci_devices; dev; dev = dev->next) {
 		nprinted = sprint_dev_config(dev, buf + len, size - len);
 		if (nprinted < 0) {
-			return len + sprintf(buf + len, MSG);
+			len += sprintf(buf + len, MSG);
+			proc_old_pci.size = len;
+			return len;
 		}
 		len += nprinted;
 	}
+	proc_old_pci.size = len;
 	return len;
 }
-
-static struct proc_dir_entry proc_old_pci = {
-	PROC_PCI, 3, "pci",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, &proc_array_inode_operations
-};
 
 static int __init pci_proc_init(void)
 {
diff -u --recursive --new-file v2.3.15/linux/drivers/pci/quirks.c linux/drivers/pci/quirks.c
--- v2.3.15/linux/drivers/pci/quirks.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/pci/quirks.c	Tue Aug 31 11:02:26 1999
@@ -58,6 +58,27 @@
 
 
 /*
+ *  S3 868 and 968 chips report region size equal to 32M, but they decode 64M.
+ *  If it's needed, re-allocate the region.
+ */
+
+static void __init quirk_s3_64M(struct pci_dev *dev)
+{
+	struct resource *r = &dev->resource[0];
+
+	if ((r->start & 0x3ffffff) || r->end != r->start + 0x3ffffff) {
+		printk("PCI: Re-allocating buggy S3 card at %s: ", dev->name);
+		r->start = 0;
+		r->end = 0x3ffffff;
+		if (pcibios_assign_resource(dev, 0))
+			printk("FAILED\n");
+		else
+			printk("moved to %08lx\n", r->start);
+	}
+}
+
+
+/*
  *  The main table of quirks.
  */
 
@@ -69,6 +90,8 @@
 	 * quantity.
 	 */
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_868,		quirk_s3_64M },
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_S3,	PCI_DEVICE_ID_S3_968,		quirk_s3_64M },
 	{ 0 }
 };
 
diff -u --recursive --new-file v2.3.15/linux/drivers/pnp/isapnp.c linux/drivers/pnp/isapnp.c
--- v2.3.15/linux/drivers/pnp/isapnp.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/pnp/isapnp.c	Tue Aug 31 10:50:44 1999
@@ -28,6 +28,7 @@
 #include <linux/string.h>
 #include <linux/malloc.h>
 #include <linux/proc_fs.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
diff -u --recursive --new-file v2.3.15/linux/drivers/pnp/isapnp_proc.c linux/drivers/pnp/isapnp_proc.c
--- v2.3.15/linux/drivers/pnp/isapnp_proc.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/pnp/isapnp_proc.c	Thu Aug 26 14:22:51 1999
@@ -230,7 +230,7 @@
 	NULL			/* permission */
 };
 
-__initfunc(static int isapnp_proc_init(void))
+static int __init isapnp_proc_init(void)
 {
 	struct proc_dir_entry *p;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/audio/amd7930.c linux/drivers/sbus/audio/amd7930.c
--- v2.3.15/linux/drivers/sbus/audio/amd7930.c	Thu Jan  7 09:21:53 1999
+++ linux/drivers/sbus/audio/amd7930.c	Tue Aug 31 11:25:33 1999
@@ -102,6 +102,11 @@
 #include <asm/audioio.h>
 #include "amd7930.h"
 
+static __u8  bilinear2mulaw(__u8 data);
+static __u8  mulaw2bilinear(__u8 data);
+static __u8  linear2mulaw(__u16 data);
+static __u16 mulaw2linear(__u8 data);
+
 #if defined (AMD79C30_ISDN) || defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff 
 #include "../../isdn/hisax/hisax.h"
 #include "../../isdn/hisax/isdnl1.h"
@@ -146,8 +151,12 @@
 	/* Callback routine (and argument) when input is done on */
 	void (*input_callback)();
 	void * input_callback_arg;
+
+	int input_format;
+	int output_format;
 };
 
+
 /* Private information we store for each amd7930 chip. */
 struct amd7930_info {
 	struct amd7930_channel D;
@@ -173,6 +182,9 @@
 	int irq;
 	volatile int ints_on;
 
+	/* Format type */
+	int format_type;
+
 
 	/* Someone to signal when the ISDN LIU state changes */
 	int liu_state;
@@ -489,10 +501,25 @@
 	if (channel->output_ptr && channel->output_count > 0) {
 
 		/* Send the next byte and advance buffer pointer. */
-		*io_reg = *(channel->output_ptr);
+		switch(channel->output_format) {
+		case AUDIO_ENCODING_ULAW:
+		case AUDIO_ENCODING_ALAW:
+			*io_reg = *(channel->output_ptr);
+			break;
+		case AUDIO_ENCODING_LINEAR8:
+			*io_reg = bilinear2mulaw(*(channel->output_ptr));
+			break;
+		case AUDIO_ENCODING_LINEAR:
+			if (channel->output_count >= 2) {
+				*io_reg = linear2mulaw(*((__u16*)(channel->output_ptr)));
+				channel->output_ptr++;
+				channel->output_count--;
+			};
+		};
 		channel->output_ptr++;
 		channel->output_count--;
 
+
 		/* Done with the buffer? Notify the midlevel driver. */
 		if (channel->output_count == 0) {
 			channel->output_ptr = NULL;
@@ -510,7 +537,21 @@
 	if (channel->input_ptr && channel->input_count > 0) {
 
 		/* Get the next byte and advance buffer pointer. */
-		*(channel->input_ptr) = *io_reg;
+		switch(channel->input_format) {
+		case AUDIO_ENCODING_ULAW:
+		case AUDIO_ENCODING_ALAW:
+			*(channel->input_ptr) = *io_reg;
+			break;
+		case AUDIO_ENCODING_LINEAR8:
+			*(channel->input_ptr) = mulaw2bilinear(*io_reg);
+			break;
+		case AUDIO_ENCODING_LINEAR:
+			if (channel->input_count >= 2) {
+				*((__u16*)(channel->input_ptr)) = mulaw2linear(*io_reg);
+				channel->input_ptr++;
+				channel->input_count--;
+			} else *(channel->input_ptr) = 0;
+		};
 		channel->input_ptr++;
 		channel->input_count--;
 
@@ -565,6 +606,20 @@
 static int amd7930_open(struct inode * inode, struct file * file,
 			struct sparcaudio_driver *drv)
 {
+	struct amd7930_info *info = (struct amd7930_info *)drv->private;
+
+	switch(MINOR(inode->i_rdev) & 0xf) {
+	case SPARCAUDIO_AUDIO_MINOR:
+		info->format_type = AUDIO_ENCODING_ULAW;
+		break;
+	case SPARCAUDIO_DSP_MINOR:
+		info->format_type = AUDIO_ENCODING_LINEAR8;
+		break;
+	case SPARCAUDIO_DSP16_MINOR:
+		info->format_type = AUDIO_ENCODING_LINEAR;
+		break;
+	};
+
 	MOD_INC_USE_COUNT;
 	return 0;
 }
@@ -637,8 +692,9 @@
 	if (info->Baudio) {
 		info->Baudio->output_ptr = buffer;
 		info->Baudio->output_count = count;
-        	info->Baudio->output_callback = (void *) &sparcaudio_output_done;
-	        info->Baudio->output_callback_arg = (void *) drv;
+		info->Baudio->output_format = info->format_type;
+       	info->Baudio->output_callback = (void *) &sparcaudio_output_done;
+        info->Baudio->output_callback_arg = (void *) drv;
 		info->Baudio->xmit_idle_char = 0;
 	}
 }
@@ -667,6 +723,7 @@
 	if (info->Baudio) {
 		info->Baudio->input_ptr = buffer;
 		info->Baudio->input_count = count;
+		info->Baudio->input_format = info->format_type;
 		info->Baudio->input_callback = (void *) &sparcaudio_input_done;
 		info->Baudio->input_callback_arg = (void *) drv;
 	}
@@ -700,7 +757,7 @@
 
 static int amd7930_get_formats(struct sparcaudio_driver *drv)
 {
-      return (AFMT_MU_LAW | AFMT_A_LAW);
+      return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_U8 | AFMT_S16_BE);
 }
 
 static int amd7930_get_output_ports(struct sparcaudio_driver *drv)
@@ -850,9 +907,11 @@
 static int amd7930_get_encoding(struct sparcaudio_driver *drv)
 {
   struct amd7930_info *info = (struct amd7930_info *)drv->private;
-  if (info->map.mmr1 & AM_MAP_MMR1_ALAW)
+  if ((info->map.mmr1 & AM_MAP_MMR1_ALAW) && 
+      (info->format_type == AUDIO_ENCODING_ALAW))
     return AUDIO_ENCODING_ALAW;
-  return AUDIO_ENCODING_ULAW;
+
+  return info->format_type;
 }
 
 static int 
@@ -861,15 +920,20 @@
   struct amd7930_info *info = (struct amd7930_info *)drv->private;
 
   switch (value) {
-  case AUDIO_ENCODING_ULAW:
-    info->map.mmr1 &= ~AM_MAP_MMR1_ALAW;
-    break;
   case AUDIO_ENCODING_ALAW:
     info->map.mmr1 |= AM_MAP_MMR1_ALAW;
     break;
+  case AUDIO_ENCODING_LINEAR8:
+  case AUDIO_ENCODING_LINEAR:
+  case AUDIO_ENCODING_ULAW:
+    info->map.mmr1 &= ~AM_MAP_MMR1_ALAW;
+    break;
   default:
     return -EINVAL;
-  }
+  };
+
+  info->format_type = value;
+
   amd7930_update_map(drv);
   return 0;
 }
@@ -1390,6 +1454,7 @@
 
 		Bchan->output_ptr = buffer;
 		Bchan->output_count = count;
+		Bchan->output_format = AUDIO_ENCODING_ULAW;
 	        Bchan->output_callback = (void *) callback;
         	Bchan->output_callback_arg = callback_arg;
 
@@ -1418,6 +1483,7 @@
 
 		Bchan->input_ptr = buffer;
 		Bchan->input_count = size;
+		Bchan->input_format = AUDIO_ENCODING_ULAW;
 		Bchan->input_callback = (void *) callback;
 		Bchan->input_callback_arg = callback_arg;
 
@@ -1568,6 +1634,11 @@
 	info->rgain = 128;
 	info->pgain = 200;
 	info->mgain = 0;
+	info->format_type = AUDIO_ENCODING_ULAW;
+	info->Bb.input_format = AUDIO_ENCODING_ULAW;
+	info->Bb.output_format = AUDIO_ENCODING_ULAW;
+	info->Bc.input_format = AUDIO_ENCODING_ULAW;
+	info->Bc.output_format = AUDIO_ENCODING_ULAW;
 	amd7930_update_map(drv);
 
 	/* Register the amd7930 with the midlevel audio driver. */
@@ -1608,7 +1679,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__initfunc(int amd7930_init(void))
+int __init amd7930_init(void)
 #endif
 {
 	struct linux_sbus *bus;
@@ -1651,3 +1722,178 @@
 	}
 }
 #endif
+
+
+/*************************************************************/
+/*                 Audio format conversion                   */
+/*************************************************************/
+
+/* Translation tables */
+
+static unsigned char ulaw[] = {
+    3,   7,  11,  15,  19,  23,  27,  31, 
+   35,  39,  43,  47,  51,  55,  59,  63, 
+   66,  68,  70,  72,  74,  76,  78,  80, 
+   82,  84,  86,  88,  90,  92,  94,  96, 
+   98,  99, 100, 101, 102, 103, 104, 105, 
+  106, 107, 108, 109, 110, 111, 112, 113, 
+  113, 114, 114, 115, 115, 116, 116, 117, 
+  117, 118, 118, 119, 119, 120, 120, 121, 
+  121, 121, 122, 122, 122, 122, 123, 123, 
+  123, 123, 124, 124, 124, 124, 125, 125, 
+  125, 125, 125, 125, 126, 126, 126, 126, 
+  126, 126, 126, 126, 127, 127, 127, 127, 
+  127, 127, 127, 127, 127, 127, 127, 127, 
+  128, 128, 128, 128, 128, 128, 128, 128, 
+  128, 128, 128, 128, 128, 128, 128, 128, 
+  128, 128, 128, 128, 128, 128, 128, 128, 
+  253, 249, 245, 241, 237, 233, 229, 225, 
+  221, 217, 213, 209, 205, 201, 197, 193, 
+  190, 188, 186, 184, 182, 180, 178, 176, 
+  174, 172, 170, 168, 166, 164, 162, 160, 
+  158, 157, 156, 155, 154, 153, 152, 151, 
+  150, 149, 148, 147, 146, 145, 144, 143, 
+  143, 142, 142, 141, 141, 140, 140, 139, 
+  139, 138, 138, 137, 137, 136, 136, 135, 
+  135, 135, 134, 134, 134, 134, 133, 133, 
+  133, 133, 132, 132, 132, 132, 131, 131, 
+  131, 131, 131, 131, 130, 130, 130, 130, 
+  130, 130, 130, 130, 129, 129, 129, 129, 
+  129, 129, 129, 129, 129, 129, 129, 129, 
+  128, 128, 128, 128, 128, 128, 128, 128, 
+  128, 128, 128, 128, 128, 128, 128, 128, 
+  128, 128, 128, 128, 128, 128, 128, 128
+};
+
+static __u8 mulaw2bilinear(__u8 data)
+{
+	return ulaw[data];
+}
+
+
+static unsigned char linear[] = {
+     0,    0,    0,    0,    0,    0,    0,    1,
+     0,    0,    0,    2,    0,    0,    0,    3,
+     0,    0,    0,    4,    0,    0,    0,    5,
+     0,    0,    0,    6,    0,    0,    0,    7,
+     0,    0,    0,    8,    0,    0,    0,    9,
+     0,    0,    0,   10,    0,    0,    0,   11,
+     0,    0,    0,   12,    0,    0,    0,   13,
+     0,    0,    0,   14,    0,    0,    0,   15,
+     0,    0,   16,    0,   17,    0,   18,    0,
+    19,    0,   20,    0,   21,    0,   22,    0,
+    23,    0,   24,    0,   25,    0,   26,    0,
+    27,    0,   28,    0,   29,    0,   30,    0,
+    31,    0,   32,   33,   34,   35,   36,   37,
+    38,   39,   40,   41,   42,   43,   44,   45,
+    46,   48,   50,   52,   54,   56,   58,   60,
+    62,   65,   69,   73,   77,   83,   91,  103,
+   255,  231,  219,  211,  205,  201,  197,  193,
+   190,  188,  186,  184,  182,  180,  178,  176,
+   174,  173,  172,  171,  170,  169,  168,  167,
+   166,  165,  164,  163,  162,  161,  160,    0,
+   159,    0,  158,    0,  157,    0,  156,    0,
+   155,    0,  154,    0,  153,    0,  152,    0,
+   151,    0,  150,    0,  149,    0,  148,    0,
+   147,    0,  146,    0,  145,    0,  144,    0,
+     0,  143,    0,    0,    0,  142,    0,    0,
+     0,  141,    0,    0,    0,  140,    0,    0,
+     0,  139,    0,    0,    0,  138,    0,    0,
+     0,  137,    0,    0,    0,  136,    0,    0,
+     0,  135,    0,    0,    0,  134,    0,    0,
+     0,  133,    0,    0,    0,  132,    0,    0,
+     0,  131,    0,    0,    0,  130,    0,    0,
+     0,  129,    0,    0,    0,  128,    0,    0
+};
+
+static __u8 bilinear2mulaw(__u8 data)
+{
+	return linear[data];
+}
+
+static int exp_lut[256] = {
+	0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+	5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+	6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+	6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+	7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+};
+
+#define BIAS 0x84
+#define CLIP 32635
+
+#define SWAP_ENDIAN(x) ((x >> 8) | ((x & 0xff) << 8))
+
+static __u8  linear2mulaw(__u16 data)
+{
+	static int sign, exponent, mantissa;
+
+	/* not really sure, if swapping is ok - comment next line to disable it */
+	data = SWAP_ENDIAN(data);
+	
+	sign = (data >> 8) & 0x80;
+	if (sign != 0) data = -data;
+
+	if (data > CLIP) data = CLIP;
+	data += BIAS;
+	exponent = exp_lut[(data >> 7) & 0xFF];
+	mantissa = (data >> (exponent + 3)) & 0x0F;
+
+	return (~(sign | (exponent << 4) | mantissa));
+}
+
+static __u16 mulaw2linear(__u8 data)
+{
+	/* this conversion is not working */
+	return data;
+}
+
+#if 0
+#define INOUT(x,y) (((x) << 16) | (y))
+static int convert_audio(int in_format, int out_format, __u8* buffer, int count)
+{
+	static int i,sign,exponent;
+	static __u16 data;
+
+	if (in_format == out_format) return count;
+
+	switch(INOUT(in_format, out_format)) {
+	case INOUT(AUDIO_ENCODING_ULAW, AUDIO_ENCODING_LINEAR8):
+		for (i = 0;i < count; i++) {
+			buffer[i] = ulaw[buffer[i]];
+		};
+		break;
+	case INOUT(AUDIO_ENCODING_ULAW, AUDIO_ENCODING_LINEAR):
+		break;
+	case INOUT(AUDIO_ENCODING_LINEAR, AUDIO_ENCODING_ULAW):
+		/* buffer is two-byte => convert to first */
+		for (i = 0; i < count/2; i++) {
+			data = ((__u16*)buffer)[i];
+			sign = (data >> 8) & 0x80;
+			if (data > CLIP) data = CLIP;
+			data += BIAS;
+			exponent = exp_lut[(data >> 7) & 0xFF];
+			buffer[i] = ~(sign | (exponent << 4) | 
+						  ((data >> (exponent + 3)) & 0x0F));
+		};
+		break;
+	case INOUT(AUDIO_ENCODING_LINEAR8, AUDIO_ENCODING_ULAW):
+		for (i = 0; i < count; i++) {
+			buffer[i] = linear[buffer[i]];
+		};
+		break;
+	default:
+		return 0;
+	};
+
+	return count;
+}
+#undef INOUT
+#endif
+
+#undef BIAS
+#undef CLIP
+#undef SWAP_ENDIAN
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c
--- v2.3.15/linux/drivers/sbus/audio/audio.c	Fri Aug  6 11:58:00 1999
+++ linux/drivers/sbus/audio/audio.c	Tue Aug 31 11:25:33 1999
@@ -1,12 +1,12 @@
 /*
  * drivers/sbus/audio/audio.c
  *
- * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
- * Copyright (C) 1997,1998 Derrick J. Brashear (shadow@dementia.org)
- * Copyright (C) 1997 Brent Baccala (baccala@freesoft.org)
+ * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
+ * Copyright 1997,1998,1999 Derrick J. Brashear (shadow@dementia.org)
+ * Copyright 1997 Brent Baccala (baccala@freesoft.org)
  * 
  * Mixer code adapted from code contributed by and
- * Copyright (C) 1998 Michael Mraka (michael@fi.muni.cz)
+ * Copyright 1998 Michael Mraka (michael@fi.muni.cz)
  * and with fixes from Michael Shuey (shuey@ecn.purdue.edu)
  * The mixer code cheats; Sparc hardware doesn't generally allow independent
  * line control, and this fakes it badly.
@@ -40,11 +40,17 @@
 #undef __AUDIO_DEBUG
 #define __AUDIO_ERROR
 #undef __AUDIO_TRACE
+#undef __AUDIO_OSSDEBUG
 #ifdef __AUDIO_DEBUG
 #define dprintk(x) printk x
 #else
 #define dprintk(x)
 #endif
+#ifdef __AUDIO_OSSDEBUG
+#define oprintk(x) printk x
+#else
+#define oprintk(x)
+#endif
 #ifdef __AUDIO_ERROR
 #define eprintk(x) printk x
 #else
@@ -117,10 +123,12 @@
          * TODO: Make number of input/output buffers tunable parameters
          */
 
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x202ff
         init_waitqueue_head(&drv->open_wait);
         init_waitqueue_head(&drv->output_write_wait);
         init_waitqueue_head(&drv->output_drain_wait);
         init_waitqueue_head(&drv->input_read_wait);
+#endif
 
         drv->num_output_buffers = 8;
 	drv->output_buffer_size = (4096 * 2);
@@ -269,6 +277,7 @@
    * If status & 2, a buffer was claimed for DMA and is still in use.
    *
    * The playing_count for non-DMA hardware should never be non-zero.
+   * Value of status for non-DMA hardware should always be 1.
    */
   if (status & 1) {
     if (drv->playing_count) 
@@ -305,15 +314,16 @@
 
   /* If we got back a buffer, see if anyone wants to write to it */
   if ((status & 1) || ((drv->output_count + drv->playing_count) 
-		  < drv->num_output_buffers)) 
+                       < drv->num_output_buffers)) {
     wake_up_interruptible(&drv->output_write_wait);
+  }
 
   /* If the output queue is empty, shut down the driver. */
   if ((drv->output_count < 1) && (drv->playing_count < 1)) {
     kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
 
     /* Stop the lowlevel driver from outputing. */
-    drv->ops->stop_output(drv); 
+    /* drv->ops->stop_output(drv); Should not be necessary  -- DJB 5/25/98 */
     drv->output_active = 0;
 		  
     /* Wake up any waiting writers or syncers and return. */
@@ -638,8 +648,11 @@
 {
   struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
 					   SPARCAUDIO_DEVICE_SHIFT)];
-  unsigned long i = 0, j = 0;
-  unsigned int k;
+  unsigned long i = 0, j = 0, l = 0, m = 0;
+  unsigned int k = 0;
+
+  if (_SIOC_DIR(cmd) & _SIOC_WRITE)
+    drv->mixer_modify_counter++;
 
   if(cmd == SOUND_MIXER_INFO) {
           audio_device_t tmp;
@@ -651,9 +664,7 @@
                   memset(&info, 0, sizeof(info));
                   strncpy(info.id, tmp.name, sizeof(info.id));
                   strncpy(info.name, "Sparc Audio", sizeof(info.name));
-
-                  /* XXX do this right... */
-                  info.modify_counter = 0;
+                  info.modify_counter = drv->mixer_modify_counter;
 
                   if(copy_to_user((char *)arg, &info, sizeof(info)))
                           retval = -EFAULT;
@@ -665,74 +676,130 @@
 
   switch (cmd) {
   case SOUND_MIXER_WRITE_RECLEV:
-  case SOUND_MIXER_WRITE_MIC:
-  case SOUND_MIXER_WRITE_CD:
-  case SOUND_MIXER_WRITE_LINE:
-  case SOUND_MIXER_WRITE_IMIX:
     if(COPY_IN(arg, k))
       return -EFAULT;
-    tprintk(("setting input volume (0x%x)", k));
+  iretry:
+    oprintk(("setting input volume (0x%x)", k));
     if (drv->ops->get_input_channels)
       j = drv->ops->get_input_channels(drv);
-    if (j == 1) {
-      i = s_to_m(k);
-      tprintk((" for mono to %d\n", i));
-      if (drv->ops->set_input_volume)
-	drv->ops->set_input_volume(drv, i);
-      if (drv->ops->get_input_volume)
-	i = drv->ops->get_input_volume(drv);
-      i = m_to_s(i);
-    } else {
-      i = s_to_g(k);
-      j = s_to_b(k);
-      tprintk((" for stereo to to %d (bal %d)\n", i, j));
-      if (drv->ops->set_input_volume)
-	drv->ops->set_input_volume(drv, i);
-      if (drv->ops->get_input_volume)
-	i = drv->ops->get_input_volume(drv);
-      if (drv->ops->set_input_balance)
-	drv->ops->set_input_balance(drv, j);
-      if (drv->ops->get_input_balance)
-	j = drv->ops->get_input_balance(drv);
-      i = b_to_s(i,j);
-    }
+    if (drv->ops->get_input_volume)
+      l = drv->ops->get_input_volume(drv);
+    if (drv->ops->get_input_balance)
+      m = drv->ops->get_input_balance(drv);
+    i = OSS_TO_GAIN(k);
+    j = OSS_TO_BAL(k);
+    oprintk((" for stereo to to %d (bal %d):", i, j));
+    if (drv->ops->set_input_volume)
+      drv->ops->set_input_volume(drv, i);
+    if (drv->ops->set_input_balance)
+      drv->ops->set_input_balance(drv, j);
+  case SOUND_MIXER_READ_RECLEV:
+    if (drv->ops->get_input_volume)
+      i = drv->ops->get_input_volume(drv);
+    if (drv->ops->get_input_balance)
+      j = drv->ops->get_input_balance(drv);
+    oprintk((" got (0x%x)\n", BAL_TO_OSS(i,j)));
+    i = BAL_TO_OSS(i,j);
+    /* Try to be reasonable about volume changes */
+    if ((cmd == SOUND_MIXER_WRITE_RECLEV) && (i != k) && 
+        (i == BAL_TO_OSS(l,m))) 
+      {
+        k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256;
+        k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1;
+        oprintk((" try 0x%x\n", k));
+        goto iretry;
+      }
     return COPY_OUT(arg, i);
-  case SOUND_MIXER_WRITE_PCM:
   case SOUND_MIXER_WRITE_VOLUME:
-  case SOUND_MIXER_WRITE_SPEAKER:
     if(COPY_IN(arg, k))
 	return -EFAULT;
-    tprintk(("setting output volume (0x%x)", k));
+    if (drv->ops->get_output_muted && drv->ops->set_output_muted) {
+      i = drv->ops->get_output_muted(drv);
+      if ((k == 0) || ((i == 0) && (OSS_LEFT(k) < 100)))
+        drv->ops->set_output_muted(drv, 1);
+      else
+        drv->ops->set_output_muted(drv, 0);
+    }
+  case SOUND_MIXER_READ_VOLUME:
+    if (drv->ops->get_output_muted) 
+      i = drv->ops->get_output_muted(drv);
+    k = 0x6464 * (1 - i);
+    return COPY_OUT(arg, k);
+  case SOUND_MIXER_WRITE_PCM:
+    if(COPY_IN(arg, k))
+	return -EFAULT;
+  oretry:
+    oprintk(("setting output volume (0x%x)\n", k));
     if (drv->ops->get_output_channels)
       j = drv->ops->get_output_channels(drv);
-    if (j == 1) {
-      i = s_to_m(k);
-      tprintk((" for mono to %d\n", i));
-      if (drv->ops->set_output_volume)
-	drv->ops->set_output_volume(drv, i);
-      if (drv->ops->get_output_volume)
-	i = drv->ops->get_output_volume(drv);
-      i = m_to_s(i);
-    } else {
-      i = s_to_g(k);
-      j = s_to_b(k);
-      tprintk((" for stereo to to %d (bal %d)\n", i, j));
-      if (drv->ops->set_output_volume)
-	drv->ops->set_output_volume(drv, i);
-      if (drv->ops->get_output_volume)
-	i = drv->ops->get_output_volume(drv);
-      if (drv->ops->set_output_balance)
-	drv->ops->set_output_balance(drv, j);
-      if (drv->ops->get_output_balance)
-	j = drv->ops->get_output_balance(drv);
-      i = b_to_s(i,j);
-    }
+    if (drv->ops->get_output_volume)
+      l = drv->ops->get_output_volume(drv);
+    if (drv->ops->get_output_balance)
+      m = drv->ops->get_output_balance(drv);
+    oprintk((" started as (0x%x)\n", BAL_TO_OSS(l,m)));
+    i = OSS_TO_GAIN(k);
+    j = OSS_TO_BAL(k);
+    oprintk((" for stereo to %d (bal %d)\n", i, j));
+    if (drv->ops->set_output_volume)
+      drv->ops->set_output_volume(drv, i);
+    if (drv->ops->set_output_balance)
+      drv->ops->set_output_balance(drv, j);
+  case SOUND_MIXER_READ_PCM:
+    if (drv->ops->get_output_volume)
+      i = drv->ops->get_output_volume(drv);
+    if (drv->ops->get_output_balance)
+      j = drv->ops->get_output_balance(drv);
+    oprintk((" got 0x%x\n", BAL_TO_OSS(i,j)));
+    i = BAL_TO_OSS(i,j);
+    /* Try to be reasonable about volume changes */
+    if ((cmd == SOUND_MIXER_WRITE_PCM) && (i != k) && 
+        (i == BAL_TO_OSS(l,m))) 
+      {
+        k += (OSS_LEFT(k) > OSS_LEFT(i)) ? 256 : -256;
+        k += (OSS_RIGHT(k) > OSS_RIGHT(i)) ? 1 : -1;
+        oprintk((" try 0x%x\n", k));
+        goto oretry;
+      }
     return COPY_OUT(arg, i);
+  case SOUND_MIXER_READ_SPEAKER:
+    k = OSS_PORT_AUDIO(drv, AUDIO_SPEAKER);
+    return COPY_OUT(arg, k);
+  case SOUND_MIXER_READ_MIC:
+    k = OSS_IPORT_AUDIO(drv, AUDIO_MICROPHONE);
+    return COPY_OUT(arg, k);
+  case SOUND_MIXER_READ_CD:
+    k = OSS_IPORT_AUDIO(drv, AUDIO_CD);
+    return COPY_OUT(arg, k);
+  case SOUND_MIXER_READ_LINE:
+    k = OSS_IPORT_AUDIO(drv, AUDIO_LINE_IN);
+    return COPY_OUT(arg, k);
+  case SOUND_MIXER_READ_LINE1:
+    k = OSS_PORT_AUDIO(drv, AUDIO_HEADPHONE);
+    return COPY_OUT(arg, k);
+  case SOUND_MIXER_READ_LINE2:
+    k = OSS_PORT_AUDIO(drv, AUDIO_LINE_OUT);
+    return COPY_OUT(arg, k);
+
+  case SOUND_MIXER_WRITE_MIC:
+  case SOUND_MIXER_WRITE_CD:
+  case SOUND_MIXER_WRITE_LINE:
+  case SOUND_MIXER_WRITE_LINE1:
+  case SOUND_MIXER_WRITE_LINE2:
+  case SOUND_MIXER_WRITE_SPEAKER:
+    if(COPY_IN(arg, k))
+	return -EFAULT;
+    OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_LINE, AUDIO_LINE_IN, k);
+    OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_MIC, AUDIO_MICROPHONE, k);
+    OSS_TWIDDLE_IPORT(drv, cmd, SOUND_MIXER_WRITE_CD, AUDIO_CD, k);
+
+    OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_SPEAKER, AUDIO_SPEAKER, k);
+    OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE1, AUDIO_HEADPHONE, k);
+    OSS_TWIDDLE_PORT(drv, cmd, SOUND_MIXER_WRITE_LINE2, AUDIO_LINE_OUT, k);
+    return COPY_OUT(arg, k);
   case SOUND_MIXER_READ_RECSRC: 
     if (drv->ops->get_input_port)
       i = drv->ops->get_input_port(drv);
     /* 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;
@@ -744,11 +811,10 @@
     if(COPY_IN(arg, k))
       return -EFAULT;
     /* only one should ever be selected */
-    if (k & SOUND_MASK_IMIX) j = AUDIO_ANALOG_LOOPBACK;
     if (k & SOUND_MASK_CD) j = AUDIO_CD;
     if (k & SOUND_MASK_LINE) j = AUDIO_LINE_IN;
     if (k & SOUND_MASK_MIC) j = AUDIO_MICROPHONE;
-    tprintk(("setting inport to %d\n", j));
+    oprintk(("setting inport to %d\n", j));
     i = drv->ops->set_input_port(drv, j);
     
     return COPY_OUT(arg, i);
@@ -759,7 +825,6 @@
     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_READ_CAPS: /* mixer capabilities */
@@ -767,62 +832,27 @@
     return COPY_OUT(arg, i);
 
   case SOUND_MIXER_READ_DEVMASK: /* all supported devices */
-  case SOUND_MIXER_READ_STEREODEVS: /* what supports stereo */
     if (drv->ops->get_input_ports)
       i = drv->ops->get_input_ports(drv);
     /* 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 (drv->ops->get_output_ports)
       i = drv->ops->get_output_ports(drv);
     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;
-    
+    if (i & AUDIO_HEADPHONE) j |= SOUND_MASK_LINE1;
+    if (i & AUDIO_LINE_OUT) j |= SOUND_MASK_LINE2;
+
     j |= SOUND_MASK_VOLUME;
-    
+
+  case SOUND_MIXER_READ_STEREODEVS: /* what supports stereo */
+    j |= SOUND_MASK_PCM|SOUND_MASK_RECLEV;
+
     if (cmd == SOUND_MIXER_READ_STEREODEVS)
       j &= ~(MONO_DEVICES);
     return COPY_OUT(arg, j);
-  case SOUND_MIXER_READ_PCM:
-  case SOUND_MIXER_READ_SPEAKER:
-  case SOUND_MIXER_READ_VOLUME:
-    if (drv->ops->get_output_channels)
-      j = drv->ops->get_output_channels(drv);
-    if (j == 1) {
-      if (drv->ops->get_output_volume)
-	i = drv->ops->get_output_volume(drv);
-      i = m_to_s(i);
-    } else {
-      if (drv->ops->get_output_volume)
-	i = drv->ops->get_output_volume(drv);
-      if (drv->ops->get_output_balance)
-	j = drv->ops->get_output_balance(drv);
-      i = b_to_s(i,j);
-    }
-    return COPY_OUT(arg, i);
-  case SOUND_MIXER_READ_RECLEV:
-  case SOUND_MIXER_READ_MIC:
-  case SOUND_MIXER_READ_CD:
-  case SOUND_MIXER_READ_LINE:
-  case SOUND_MIXER_READ_IMIX:
-    if (drv->ops->get_input_channels)
-      j = drv->ops->get_input_channels(drv);
-    if (j == 1) {
-      if (drv->ops->get_input_volume)
-	i = drv->ops->get_input_volume(drv);
-      i = m_to_s(i);
-    } else {
-      if (drv->ops->get_input_volume)
-	i = drv->ops->get_input_volume(drv);
-      if (drv->ops->get_input_balance)
-	j = drv->ops->get_input_balance(drv);
-      i = b_to_s(i,j);
-    }
-    return COPY_OUT(arg, i);
   default:
     return -EINVAL;
   }
@@ -881,6 +911,10 @@
         case SPARCAUDIO_DSP_MINOR:
 	case SPARCAUDIO_AUDIO_MINOR:
 	case SPARCAUDIO_AUDIOCTL_MINOR:
+          /* According to the OSS prog int, you can mixer ioctl /dev/dsp */
+          if (_IOC_TYPE(cmd) == 'M')
+            return sparcaudio_mixer_ioctl(inode, 
+                                          file, cmd, (unsigned int *)arg);
 	  switch (cmd) {
 	  case I_GETSIG:
 	  case I_GETSIG_SOLARIS:
@@ -1997,6 +2031,36 @@
 	  return -ENXIO;
 	}
 
+        /* From the dbri driver:
+         * SunOS 5.5.1 audio(7I) man page says:
+         * "Upon the initial open() of the audio device, the driver
+         *  will reset the data format of the device to the default
+         *  state of 8-bit, 8KHz, mono u-law data."
+         *
+         * Of course, we only do this for /dev/audio, and assume
+         * OSS semantics on /dev/dsp
+         */
+
+	if ((minor & 0xf) == SPARCAUDIO_AUDIO_MINOR) {
+	  if (file->f_mode & FMODE_WRITE) {
+            if (drv->ops->set_output_channels)
+              drv->ops->set_output_channels(drv, 1);
+            if (drv->ops->set_output_encoding)
+              drv->ops->set_output_encoding(drv, AUDIO_ENCODING_ULAW);
+            if (drv->ops->set_output_rate)
+              drv->ops->set_output_rate(drv, 8000);
+          }          
+
+	  if (file->f_mode & FMODE_READ) {
+            if (drv->ops->set_input_channels)
+              drv->ops->set_input_channels(drv, 1);
+            if (drv->ops->set_input_encoding)
+              drv->ops->set_input_encoding(drv, AUDIO_ENCODING_ULAW);
+            if (drv->ops->set_input_rate)
+              drv->ops->set_input_rate(drv, 8000);
+          }          
+        }
+
 	MOD_INC_USE_COUNT;
 
 	/* Success! */
@@ -2098,7 +2162,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__initfunc(int sparcaudio_init(void))
+int __init sparcaudio_init(void)
 #endif
 {
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c
--- v2.3.15/linux/drivers/sbus/audio/cs4231.c	Fri Aug  6 11:58:00 1999
+++ linux/drivers/sbus/audio/cs4231.c	Tue Aug 31 11:25:33 1999
@@ -1,7 +1,9 @@
 /*
  * drivers/sbus/audio/cs4231.c
  *
- * Copyright 1996, 1997, 1998 Derrick J Brashear (shadow@andrew.cmu.edu)
+ * Copyright 1996, 1997, 1998, 1999 Derrick J Brashear (shadow@andrew.cmu.edu)
+ * The 4231/ebus support was written by David Miller, who didn't bother
+ * crediting himself here, so I will.
  *
  * Based on the AMD7930 driver:
  * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
@@ -11,7 +13,7 @@
  * 
  * 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
+ * The APC DMA controller support unfortunately is not documented. Thanks, Sun.
  */
 
 #include <linux/config.h>
@@ -36,6 +38,7 @@
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff && defined(CONFIG_PCI)
 #define EB4231_SUPPORT
 #include <asm/ebus.h>
+#include <asm/pbm.h>
 #endif
 
 #include <asm/audioio.h>
@@ -69,15 +72,17 @@
 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 void cs4231_playintr(struct sparcaudio_driver *drv, int);
 static int cs4231_recintr(struct sparcaudio_driver *drv);
 static int cs4231_output_muted(struct sparcaudio_driver *drv, int value);
 static void cs4231_pollinput(struct sparcaudio_driver *drv);
-static void eb4231_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);
+#ifdef EB4231_SUPPORT
+static void eb4231_pollinput(struct sparcaudio_driver *drv);
+#endif
 
 #define CHIP_READY udelay(100); cs4231_ready(drv); udelay(1000);
 
@@ -416,8 +421,8 @@
   int tmp_bits;
 
   tprintk(("input channels %d\n", value));
-  cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c;
-  tmp_bits = cs4231_chip->regs->idr;
+  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), (IAR_AUTOCAL_BEGIN | 0x1c));
+  tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
   switch (value) {
   case 1:
       CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), CS4231_MONO_ON(tmp_bits));
@@ -1228,11 +1233,20 @@
   MOD_DEC_USE_COUNT;
 }
 
-static void cs4231_playintr(struct sparcaudio_driver *drv)
+static void cs4231_playintr(struct sparcaudio_driver *drv, int push)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
   int status = 0;
 
+  if (!push) {
+    if (!cs4231_chip->perchip_info.play.active) {
+      cs4231_chip->regs->dmapnva = cs4231_chip->output_next_dma_handle;
+      cs4231_chip->regs->dmapnc = cs4231_chip->output_next_dma_size;
+    }
+    sparcaudio_output_done(drv, 0);
+    return;
+  }
+
   if (cs4231_chip->playlen == 0 && cs4231_chip->output_size > 0) 
     cs4231_chip->playlen = cs4231_chip->output_size;
 
@@ -1484,14 +1498,16 @@
   cs4231_chip->perchip_info.play.active = 1;
   cs4231_chip->playing_count = 0;
 
-  cs4231_playintr(drv);
   if ((cs4231_chip->regs->dmacsr & APC_PPAUSE) || 
       !(cs4231_chip->regs->dmacsr & APC_PDMA_READY)) {
-    cs4231_chip->regs->dmacsr &= ~(APC_XINT_PLAY | APC_PPAUSE);
-    cs4231_chip->regs->dmacsr |= APC_GENL_INT | APC_XINT_ENA | APC_XINT_PLAY
-      | APC_XINT_GENL | APC_XINT_PENA | APC_PDMA_READY;
+    cs4231_chip->regs->dmacsr &= ~APC_XINT_PLAY;
+    cs4231_chip->regs->dmacsr &= ~APC_PPAUSE;
+    
+    cs4231_playintr(drv, cs4231_chip->regs->dmapnva == 0 ? 1 : 0);
+
+    cs4231_chip->regs->dmacsr |= APC_PLAY_SETUP;
     cs4231_enable_play(drv);
-  
+
     cs4231_ready(drv);
   }
 }
@@ -1522,7 +1538,6 @@
 
   /* Else subsequent speed setting changes are ignored by the chip. */
   cs4231_disable_play(drv);
-  cs4231_chip->perchip_info.play.active = 0;
 }
 #endif
 
@@ -1545,14 +1560,9 @@
     cs4231_chip->output_next_dma_handle = 0;
     cs4231_chip->output_next_dma_size = 0;
   }
-#if 1 /* Not safe without shutting off the DMA controller as well. -DaveM */
+#if 0 /* Not safe without shutting off the DMA controller as well. -DaveM */
   /* Else subsequent speed setting changes are ignored by the chip. */
-  cs4231_chip->regs->dmacsr &= ~(APC_GENL_INT | APC_XINT_ENA | APC_XINT_PLAY 
-                                 | APC_XINT_GENL | APC_PDMA_READY 
-                                 | APC_XINT_PENA | APC_PPAUSE );
-  printk("in cs4231_stop_output: 0x%x\n", cs4231_chip->regs->dmacsr);
   cs4231_disable_play(drv);
-  cs4231_chip->perchip_info.play.active = 0;
 #endif
 }
 
@@ -1874,6 +1884,7 @@
   }
 
   if((dummy & EBUS_DCSR_A_LOADED) == 0) {
+    cs4231_chip->perchip_info.play.active = 0;
     eb4231_playintr(drv);
 
     eb4231_getsamplecount(drv, cs4231_chip->playlen, 0);
@@ -1898,11 +1909,14 @@
    * if anything since we may be doing shared interrupts 
    */
 
-  if (dummy & (APC_PLAY_INT|APC_XINT_PNVA|APC_XINT_PLAY|APC_XINT_EMPT|APC_XINT_PEMP)) {
+  if (dummy & APC_PLAY_INT) {
+    if (dummy & APC_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 & APC_XINT_EMPT))
+        cs4231_playintr(drv, 1);
+    } 
     /* Any other conditions we need worry about? */
   }
 
@@ -1927,15 +1941,13 @@
   }
 
   if (dummy & APC_XINT_EMPT) {
-#if 0 /* Call to stop_output from midlevel will get this */
     if (!cs4231_chip->output_next_dma_handle) {
       cs4231_chip->regs->dmacsr |= (APC_PPAUSE);
       cs4231_disable_play(drv);
       cs4231_chip->perchip_info.play.error = 1;
     }
     cs4231_chip->perchip_info.play.active = 0;
-    cs4231_playintr(drv);
-#endif
+    cs4231_playintr(drv, 0);
 
     cs4231_getsamplecount(drv, cs4231_chip->playlen, 0);
   }
@@ -2213,16 +2225,9 @@
 
   nregs = len / sizeof(regs[0]);
 
-  cs4231_chip->regs = (struct cs4231_regs *)edev->base_address[0];
-  cs4231_chip->eb2p = (struct linux_ebus_dma *)edev->base_address[1];
-  cs4231_chip->eb2c = (struct linux_ebus_dma *)edev->base_address[2];
-
-  request_region((unsigned long)cs4231_chip->regs, 
-                 sizeof(struct cs4231_regs), "cs4231 regs");
-  request_region((unsigned long)cs4231_chip->eb2c, 
-                 sizeof(struct linux_ebus_dma), "4231 capture DMA");
-  request_region((unsigned long)cs4231_chip->eb2p, 
-                 sizeof(struct linux_ebus_dma), "4231 playback DMA");
+  cs4231_chip->regs = (struct cs4231_regs *)edev->resource[0].start;
+  cs4231_chip->eb2p = (struct linux_ebus_dma *)edev->resource[1].start;
+  cs4231_chip->eb2c = (struct linux_ebus_dma *)edev->resource[2].start;
 
   cs4231_chip->status |= CS_STATUS_IS_EBUS;
 
@@ -2252,13 +2257,6 @@
     free_irq(cs4231_chip->irq, drv);
     disable_irq(cs4231_chip->irq2);
     free_irq(cs4231_chip->irq2, drv);
-
-    release_region((unsigned long)cs4231_chip->regs, 
-                   sizeof(struct cs4231_regs));
-    release_region((unsigned long)cs4231_chip->eb2c, 
-                   sizeof(struct linux_ebus_dma));
-    release_region((unsigned long)cs4231_chip->eb2p, 
-                   sizeof(struct linux_ebus_dma));
     kfree(drv->private);
     return -EIO;
   }
@@ -2292,7 +2290,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__initfunc(int cs4231_init(void))
+int __init cs4231_init(void)
 #endif
 {
   struct linux_sbus *sbus;
@@ -2351,9 +2349,6 @@
 #ifdef EB4231_SUPPORT
           disable_irq(cs4231_chip->irq2);
           free_irq(cs4231_chip->irq2, drv);
-          release_region((unsigned long)cs4231_chip->regs, sizeof(struct cs4231_regs));
-          release_region((unsigned long)cs4231_chip->eb2c, sizeof(struct linux_ebus_dma));
-          release_region((unsigned long)cs4231_chip->eb2p, sizeof(struct linux_ebus_dma));
 #endif
         }
         kfree(drv->private);
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/audio/cs4231.h linux/drivers/sbus/audio/cs4231.h
--- v2.3.15/linux/drivers/sbus/audio/cs4231.h	Thu Apr 22 19:24:51 1999
+++ linux/drivers/sbus/audio/cs4231.h	Tue Aug 31 11:25:33 1999
@@ -255,19 +255,19 @@
 #define APC_XINT_PLAY   0x40000  /* Playback ext intr */
 #define APC_XINT_CAPT   0x20000  /* Capture ext intr */
 #define APC_XINT_GENL   0x10000  /* Error ext intr */
-#define APC_XINT_EMPT   0x8000   /* Pipe empty interrupt */
-#define APC_XINT_PEMP   0x4000   /* Play pipe empty */
+#define APC_XINT_EMPT   0x8000   /* Pipe empty interrupt (0 write to pva) */
+#define APC_XINT_PEMP   0x4000   /* Play pipe empty (pva and pnva not set) */
 #define APC_XINT_PNVA   0x2000   /* Playback NVA dirty */
 #define APC_XINT_PENA   0x1000   /* play pipe empty Int enable */
 #define APC_XINT_COVF   0x800    /* Cap data dropped on floor */
 #define APC_XINT_CNVA   0x400    /* Capture NVA dirty */
-#define APC_XINT_CEMP   0x200    /* Capture pipe empty interrupt */
+#define APC_XINT_CEMP   0x200    /* Capture pipe empty (cva and cnva not set) */
 #define APC_XINT_CENA   0x100    /* Cap. pipe empty int enable */
 #define APC_PPAUSE      0x80     /* Pause the play DMA */
 #define APC_CPAUSE      0x40     /* Pause the capture DMA */
 #define APC_CDC_RESET   0x20     /* CODEC RESET */
-#define APC_PDMA_READY     0x08     /* Play DMA Go */
-#define APC_CDMA_READY     0x04     /* Capture DMA Go */
+#define APC_PDMA_READY  0x08     /* Play DMA Go */
+#define APC_CDMA_READY  0x04     /* Capture DMA Go */
 #define APC_CHIP_RESET  0x01     /* Reset the chip */
 
 #define APC_INIT_SETUP  (APC_CDMA_READY | APC_PDMA_READY | APC_XINT_ENA | APC_XINT_PLAY | APC_XINT_GENL | APC_INT_PENDING | APC_PLAY_INT | APC_CAPT_INT | APC_GENL_INT) 
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/audio/dbri.c linux/drivers/sbus/audio/dbri.c
--- v2.3.15/linux/drivers/sbus/audio/dbri.c	Thu Jun 17 01:08:50 1999
+++ linux/drivers/sbus/audio/dbri.c	Tue Aug 31 11:25:33 1999
@@ -1907,19 +1907,11 @@
 {
 	MOD_INC_USE_COUNT;
 
-	/* SunOS 5.5.1 audio(7I) man page says:
-	 * "Upon the initial open() of the audio device, the driver
-	 *  will reset the data format of the device to the default
-	 *  state of 8-bit, 8KHz, mono u-law data."
-	 *
-	 * I've also taken the liberty of setting half gain and
+        /*
+	 * I've taken the liberty of setting half gain and
 	 * mid balance, to put the codec in a known state.
 	 */
 
-	dbri_set_output_channels(drv, 1);
-	dbri_set_output_encoding(drv, AUDIO_ENCODING_ULAW);
-	dbri_set_output_rate(drv, 8000);
-
 	dbri_set_output_balance(drv, AUDIO_MID_BALANCE);
 	dbri_set_output_volume(drv, AUDIO_MAX_GAIN/2);
 
@@ -2162,7 +2154,6 @@
                int hdlcmode, u_char xmit_idle_char)
 {
        struct dbri *dbri;
-       int val;
 
        if (dev >= num_drivers || chan > 1) {
                return -1;
@@ -2356,7 +2347,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__initfunc(int dbri_init(void))
+int __init dbri_init(void)
 #endif
 {
 	struct linux_sbus *bus;
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/audio/dmy.c linux/drivers/sbus/audio/dmy.c
--- v2.3.15/linux/drivers/sbus/audio/dmy.c	Fri Apr 16 08:20:23 1999
+++ linux/drivers/sbus/audio/dmy.c	Tue Aug 31 11:25:33 1999
@@ -643,7 +643,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__initfunc(int dummy_init(void))
+int __init dummy_init(void)
 #endif
 {
   num_drivers = 0;
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/Config.in linux/drivers/sbus/char/Config.in
--- v2.3.15/linux/drivers/sbus/char/Config.in	Wed Jun  9 14:44:25 1999
+++ linux/drivers/sbus/char/Config.in	Tue Aug 31 11:25:33 1999
@@ -9,7 +9,7 @@
 fi
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  tristate 'Bidirectional parallel port support (EXPERIMENTAL)' CONFIG_SUN_BPP
+  tristate 'Bidirectional parallel port support (obsolete)' CONFIG_SUN_BPP
   tristate 'Videopix Frame Grabber (EXPERIMENTAL)' CONFIG_SUN_VIDEOPIX
   tristate 'Aurora Multiboard 1600se (EXPERIMENTAL)' CONFIG_SUN_AURORA
 
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c
--- v2.3.15/linux/drivers/sbus/char/aurora.c	Wed Jun 30 11:24:54 1999
+++ linux/drivers/sbus/char/aurora.c	Tue Aug 31 11:30:48 1999
@@ -1327,7 +1327,7 @@
 			bp->r[chip]->r[CD180_MSVR]=port->MSVR;/* auto drops DTR */
 		}
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(port->flags & ASYNC_INITIALIZED)) {
 			if (port->flags & ASYNC_HUP_NOTIFY)
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c
--- v2.3.15/linux/drivers/sbus/char/bpp.c	Fri Aug  6 11:58:00 1999
+++ linux/drivers/sbus/char/bpp.c	Tue Aug 31 11:25:33 1999
@@ -1050,7 +1050,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__initfunc(int bpp_init(void))
+int __init bpp_init(void)
 #endif
 {
 	int rc;
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/envctrl.c linux/drivers/sbus/char/envctrl.c
--- v2.3.15/linux/drivers/sbus/char/envctrl.c	Mon Nov 16 10:37:28 1998
+++ linux/drivers/sbus/char/envctrl.c	Tue Aug 31 11:25:33 1999
@@ -1,17 +1,23 @@
-/* $Id: envctrl.c,v 1.9 1998/11/06 07:38:20 ecd Exp $
+/* $Id: envctrl.c,v 1.12 1999/08/31 06:58:04 davem Exp $
  * envctrl.c: Temperature and Fan monitoring on Machines providing it.
  *
  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
  */
 
+#include <linux/version.h>
 #include <linux/config.h>
 #include <linux/module.h>
+
+#define __KERNEL_SYSCALLS__
 #include <linux/sched.h>
+#include <linux/unistd.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
+#include <linux/malloc.h>
 #include <linux/miscdevice.h>
+#include <linux/smp_lock.h>
 
 #include <asm/ebus.h>
 #include <asm/uaccess.h>
@@ -20,8 +26,16 @@
 #define ENVCTRL_MINOR	162
 
 
-#undef DEBUG_BUS_SCAN
+#undef U450_SUPPORT		/* might fry you machine, careful here !!! */
+
 
+#define DEBUG		1
+#define DEBUG_BUS_SCAN	1
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0)
+#define schedule_timeout(a) { current->timeout = jiffies + (a); schedule(); }
+#endif
 
 #define PCF8584_ADDRESS	0x55
 
@@ -61,13 +75,196 @@
 #define I2C_WRITE	0x00
 #define I2C_READ	0x01
 
-struct pcf8584_reg
+/* PCF8584 register offsets */
+#define I2C_DATA	0x00UL
+#define I2C_CSR		0x01UL
+
+struct i2c_device {
+	unsigned char		addr;
+	struct i2c_device	*next;
+};
+
+static unsigned long i2c_regs;
+static struct i2c_device  *i2c_devices;
+
+static int errno;
+
+#define MAX_TEMPERATURE		111
+#define MAX_FAN_SPEED		63
+
+
+/*
+ * UltraAXi constants.
+ */
+#define AXI_THERM_ADDR		0x9e
+#define AXI_THERM_PORT_CPU	0
+#define AXI_THERM_PORT_MOD	1
+#define AXI_THERM_PORT_PCI	2
+#define AXI_THERM_PORT_DISK	3
+
+#define AXI_FAN_ADDR		0x4e
+#define AXI_FAN_PORT_FRONT	0
+#define AXI_FAN_PORT_BACK	1
+
+#define AXI_PIO_ADDR		0x70
+
+/*
+ * Ultra 450 constants.
+ */
+#define U450_FAN_ADDR		0x4e
+#define U450_FAN_PORT_CPU	0
+#define U450_FAN_PORT_PS	1
+
+#define U450_PIO_ADDR		0x70
+#define U450_TIMER_ADDR		0xa0
+
+static unsigned char
+axi_cpu_temp_table[256] =
 {
-	__volatile__ unsigned char data;
-	__volatile__ unsigned char csr;
+	0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x67,
+	0x66, 0x65, 0x64, 0x63, 0x61, 0x60, 0x5f, 0x5e,
+	0x5d, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x55, 0x54,
+	0x53, 0x52, 0x50, 0x4f, 0x4e, 0x4d, 0x4c, 0x4a,
+	0x49, 0x48, 0x47, 0x46, 0x44, 0x43, 0x42, 0x41,
+	0x40, 0x3e, 0x3d, 0x3c, 0x3c, 0x3b, 0x3b, 0x3a,
+	0x3a, 0x39, 0x39, 0x38, 0x38, 0x37, 0x37, 0x36,
+	0x36, 0x35, 0x35, 0x34, 0x34, 0x33, 0x33, 0x32,
+	0x32, 0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2e,
+	0x2d, 0x2d, 0x2c, 0x2c, 0x2b, 0x2b, 0x2a, 0x2a,
+	0x29, 0x29, 0x28, 0x28, 0x27, 0x27, 0x26, 0x26,
+	0x25, 0x25, 0x24, 0x24, 0x23, 0x23, 0x22, 0x22,
+	0x21, 0x21, 0x20, 0x20, 0x1f, 0x1f, 0x1e, 0x1e,
+	0x1e, 0x1e, 0x1d, 0x1d, 0x1d, 0x1d, 0x1c, 0x1c,
+	0x1c, 0x1c, 0x1b, 0x1b, 0x1b, 0x1b, 0x1a, 0x1a,
+	0x1a, 0x1a, 0x1a, 0x19, 0x19, 0x19, 0x19, 0x18,
+	0x18, 0x18, 0x18, 0x17, 0x17, 0x17, 0x17, 0x16,
+	0x16, 0x16, 0x16, 0x16, 0x16, 0x15, 0x15, 0x15,
+	0x15, 0x14, 0x14, 0x14, 0x14, 0x13, 0x13, 0x13,
+	0x13, 0x12, 0x12, 0x12, 0x12, 0x12, 0x11, 0x11,
+	0x11, 0x11, 0x10, 0x10, 0x10, 0x10, 0x0f, 0x0f,
+	0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,
+	0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b,
+	0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08,
+	0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06,
+	0x06, 0x05, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04,
+	0x04, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02,
+	0x01, 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
+};
+
+static unsigned char
+axi_mod_temp_table[256] =
+{
+	0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e,
+	0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56,
+	0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e,
+	0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46,
+	0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3f, 0x3e,
+	0x3d, 0x3c, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x39,
+	0x39, 0x38, 0x38, 0x37, 0x37, 0x36, 0x36, 0x35,
+	0x35, 0x35, 0x34, 0x34, 0x33, 0x33, 0x32, 0x32,
+	0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2e, 0x2e,
+	0x2e, 0x2d, 0x2d, 0x2c, 0x2c, 0x2b, 0x2b, 0x2a,
+	0x2a, 0x29, 0x29, 0x29, 0x28, 0x28, 0x27, 0x27,
+	0x26, 0x26, 0x25, 0x25, 0x24, 0x24, 0x23, 0x23,
+	0x23, 0x22, 0x22, 0x21, 0x21, 0x20, 0x20, 0x1f,
+	0x1f, 0x1e, 0x1e, 0x1e, 0x1d, 0x1d, 0x1d, 0x1d,
+	0x1d, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1b, 0x1b,
+	0x1b, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x19, 0x19,
+	0x19, 0x19, 0x18, 0x18, 0x18, 0x18, 0x17, 0x17,
+	0x17, 0x17, 0x17, 0x16, 0x16, 0x16, 0x16, 0x15,
+	0x15, 0x15, 0x15, 0x14, 0x14, 0x14, 0x14, 0x13,
+	0x13, 0x13, 0x13, 0x13, 0x12, 0x12, 0x12, 0x12,
+	0x11, 0x11, 0x11, 0x11, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e,
+	0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c,
+	0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,
+	0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08,
+	0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
+	0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05,
+	0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
+	0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char
+axi_fan_speeds[112] =
+{
+	0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+	0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+	0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+	0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x20,
+	0x22, 0x23, 0x25, 0x27, 0x28, 0x2a, 0x2b, 0x2d,
+	0x2f, 0x30, 0x32, 0x33, 0x35, 0x37, 0x38, 0x3a,
+	0x3b, 0x3d, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f
 };
 
-static struct pcf8584_reg *i2c;
+
+struct therm_regs {
+	u32	addr;
+	u32	port;
+	u32	min_temp;
+	u32	warning;
+	u32	shutdown;
+	u32	num;
+	u32	den;
+};
+
+struct thermistor {
+	char			name[8];
+	struct therm_regs	regs;
+	unsigned char		(*temperature) (struct thermistor *);
+	unsigned char		(*fan_speed) (struct thermistor *);
+	struct thermistor	*next;		/* all thermistors */
+	struct thermistor	*chain;		/* thermistors for one fan */
+};
+
+struct fan_regs {
+	u32	addr;
+	u32	port;
+};
+
+struct fan {
+	char			name[8];
+	struct fan_regs		regs;
+	int			(*set_speed)(struct fan *, unsigned char value);
+	int			(*check_failure)(struct fan *);
+	unsigned char		value;
+	struct thermistor	*monitor;
+	struct fan		*next;
+};
+
+
+struct environment {
+	struct thermistor	*thermistors;
+	struct fan		*fans;
+	unsigned char		*cpu_temp_table;
+	unsigned char		*cpu_fan_speeds;
+	unsigned char		*ps_temp_table;
+	unsigned char		*ps_fan_speeds;
+	void			(*enable) (struct environment *);
+	void			(*disable) (struct environment *);
+	void			(*keep_alive) (struct environment *);
+	int			interval;
+	pid_t			kenvd_pid;
+	wait_queue_head_t	kenvd_wait;
+	int			terminate;
+};
+
+
+static struct environment	envctrl;
 
 
 #ifdef DEBUG_BUS_SCAN
@@ -78,37 +275,42 @@
 };
 
 static struct i2c_addr_map devmap[] = {
-	{ 0x38, 0x78, "PCF8574A" },
-	{ 0x20, 0x78, "TDA8444" },
-	{ 0x48, 0x78, "PCF8591" },
+	{ 0x70, 0xf0, "PCF8574A" },
+	{ 0x40, 0xf0, "TDA8444" },
+	{ 0x90, 0xf0, "PCF8591" },
+	{ 0xa0, 0xf0, "PCF8583" },
 };
 #define NR_DEVMAP (sizeof(devmap) / sizeof(devmap[0]))
 #endif
 
 static __inline__ int
-PUT_DATA(__volatile__ unsigned char *data, char *buffer, int user)
+PUT_DATA(unsigned long data, char *buffer, int user)
 {
 	if (user) {
-		if (put_user(*data, buffer))
+		u8 tmp = readb(data);
+		if (put_user(tmp, buffer))
 			return -EFAULT;
 	} else {
-		*buffer = *data;
+		*buffer = readb(data);
 	}
 	return 0;
 }
 
 static __inline__ int
-GET_DATA(__volatile__ unsigned char *data, const char *buffer, int user)
+GET_DATA(unsigned long data, const char *buffer, int user)
 {
 	if (user) {
-		if (get_user(*data, buffer))
+		u8 tmp;
+		if (get_user(tmp, buffer))
 			return -EFAULT;
+		writeb(tmp, data);
 	} else {
-		*data = *buffer;
+		writeb(*buffer, data);
 	}
 	return 0;
 }
 
+
 static int
 i2c_read(unsigned char dev, char *buffer, int len, int user)
 {
@@ -117,16 +319,17 @@
 	int error = -ENODEV;
 	int count = 0;
 
-	i2c->data = (dev << 1) | I2C_READ;
+	writeb((dev & 0xfe) | I2C_READ, i2c_regs + I2C_DATA);
 
-	while (!(i2c->csr & STATUS_BB))
+	while (!(readb(i2c_regs + I2C_CSR) & STATUS_BB))
 		udelay(1);
 
-	i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK;
+	writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK,
+	       i2c_regs + I2C_CSR);
 
 	do {
 		udelay(1);
-		while ((stat = i2c->csr) & STATUS_PIN)
+		while ((stat = readb(i2c_regs + I2C_CSR)) & STATUS_PIN)
 			udelay(1);
 
 		if (stat & STATUS_LRB)
@@ -142,29 +345,30 @@
 			break;
 
 		if (count++ > 0) {
-			error = PUT_DATA(&i2c->data, buffer++, user);
+			error = PUT_DATA(i2c_regs + I2C_DATA, buffer++, user);
 			if (error)
 				break;
 		} else
-			dummy = i2c->data;
+			dummy = readb(i2c_regs + I2C_DATA);
 	} while (1);
 
-	i2c->csr = CONTROL_ES0;
+	writeb(CONTROL_ES0, i2c_regs + I2C_CSR);
 	if (!error && (count++ > 0))
-		error = PUT_DATA(&i2c->data, buffer++, user);
+		error = PUT_DATA(i2c_regs + I2C_DATA, buffer++, user);
 	else
-		dummy = i2c->data;
+		dummy = readb(i2c_regs + I2C_DATA);
 
 	udelay(1);
-	while ((stat = i2c->csr) & STATUS_PIN)
+	while ((stat = readb(i2c_regs + I2C_CSR)) & STATUS_PIN)
 		udelay(1);
 
 stop:
-	i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK;
+	writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK,
+	       i2c_regs + I2C_CSR);
 	if (!error && (count++ > 0))
-		error = PUT_DATA(&i2c->data, buffer++, user);
+		error = PUT_DATA(i2c_regs + I2C_DATA, buffer++, user);
 	else
-		dummy = i2c->data;
+		dummy = readb(i2c_regs + I2C_DATA);
 
 	if (error)
 		return error;
@@ -176,20 +380,33 @@
 {
 	int error = -ENODEV;
 	int count = 0;
+	int timeout;
 
-	while (!(i2c->csr & STATUS_BB))
+	timeout = 1000000;
+	while (!(readb(i2c_regs + I2C_CSR) & STATUS_BB) && --timeout)
 		udelay(1);
+	if (!timeout) {
+		printk("%s [%d]: TIMEOUT\n", __FUNCTION__, __LINE__);
+		return -ENODEV;
+	}
 
-	i2c->data = (dev << 1) | I2C_WRITE;
-	i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK;
+	writeb((dev & 0xfe) | I2C_WRITE, i2c_regs + I2C_DATA);
+	writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK,
+	       i2c_regs + I2C_CSR);
 
 	do {
 		unsigned char stat;
 
 		udelay(1);
-		while ((stat = i2c->csr) & STATUS_PIN)
+		timeout = 1000000;
+		while (((stat = readb(i2c_regs + I2C_CSR)) & STATUS_PIN) && --timeout)
 			udelay(1);
 
+		if (!timeout) {
+			printk("%s [%d]: TIMEOUT\n", __FUNCTION__, __LINE__);
+			break;
+		}
+
 		if (stat & STATUS_LRB)
 			break;
 
@@ -197,32 +414,172 @@
 		if (count == len)
 			break;
 
-		error = GET_DATA(&i2c->data, buffer++, user);
+		error = GET_DATA(i2c_regs + I2C_DATA, buffer++, user);
 		if (error)
 			break;
 
 		count++;
 	} while (1);
 
-	i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK;
+	writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK, 
+	       i2c_regs + I2C_CSR);
 	return error;
 }
 
-__initfunc(static int i2c_scan_bus(void))
+#ifdef U450_SUPPORT
+static int
+i2c_write_read(unsigned char dev, char *outbuf, int outlen,
+				  char *inbuf, int inlen, int user)
+{
+	unsigned char dummy;
+	unsigned char stat;
+	int error = -ENODEV;
+	int count = 0;
+
+	while (!(readb(i2c_regs + I2C_CSR) & STATUS_BB))
+		udelay(1);
+
+	writeb((dev & 0xfe) | I2C_WRITE, i2c_regs + I2C_DATA);
+	writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_STA | CONTROL_ACK, 
+	       i2c_regs + I2C_CSR);
+
+	do {
+		unsigned char stat;
+
+		udelay(1);
+		while ((stat = readb(i2c_regs + I2C_CSR)) & STATUS_PIN)
+			udelay(1);
+
+		if (stat & STATUS_LRB)
+			break;
+
+		error = count;
+		if (count == outlen)
+			break;
+
+		error = GET_DATA(i2c_regs + I2C_DATA, outbuf++, user);
+		if (error)
+			break;
+
+		count++;
+	} while (1);
+
+	if (error < 0) {
+		writeb(CONTROL_PIN | CONTROL_ES0 |
+		       CONTROL_STO | CONTROL_ACK, i2c_regs + I2C_CSR);
+		return error;
+	}
+
+	writeb(CONTROL_ES0 | CONTROL_STA | CONTROL_ACK, i2c_regs + I2C_CSR);
+	udelay(1);
+	writeb((dev & 0xfe) | I2C_READ, i2c_regs + I2C_DATA);
+
+	count = 0;
+	do {
+		udelay(1);
+		while ((stat = readb(i2c_regs + I2C_CSR)) & STATUS_PIN)
+			udelay(1);
+
+		if (stat & STATUS_LRB)
+			goto stop;
+
+		error = 0;
+		if (inlen == 0) {
+			count--;
+			break;
+		}
+
+		if (count == (inlen - 1))
+			break;
+
+		if (count++ > 0) {
+			error = PUT_DATA(i2c_regs + I2C_DATA, inbuf++, user);
+			if (error)
+				break;
+		} else
+			dummy = readb(i2c_regs + I2C_DATA);
+	} while (1);
+
+	writeb(CONTROL_ES0, i2c_regs + I2C_CSR);
+	if (!error && (count++ > 0))
+		error = PUT_DATA(i2c_regs + I2C_DATA, inbuf++, user);
+	else
+		dummy = readb(i2c_regs + I2C_DATA);
+
+	udelay(1);
+	while ((stat = readb(i2c_regs + I2C_CSR)) & STATUS_PIN)
+		udelay(1);
+
+stop:
+	writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_STO | CONTROL_ACK,
+	       i2c_regs + I2C_CSR);
+	if (!error && (count++ > 0))
+		error = PUT_DATA(i2c_regs + I2C_DATA, inbuf++, user);
+	else
+		dummy = readb(i2c_regs + I2C_DATA);
+
+	if (error)
+		return error;
+	return count - 1;
+}
+#endif /* U450_SUPPORT */
+
+static struct i2c_device *
+i2c_find_device(unsigned char addr)
+{
+	struct i2c_device *dev;
+
+	for (dev = i2c_devices; dev; dev = dev->next) {
+		if (dev->addr == addr)
+			return dev;
+	}
+	return 0;
+}
+
+static void
+i2c_free_devices(void)
 {
-	unsigned char dev;
+	struct i2c_device *dev;
+
+	dev = i2c_devices;
+	while (dev) {
+		i2c_devices = dev->next;
+		kfree(dev);
+		dev = i2c_devices;
+	}
+}
+
+static __init int i2c_scan_bus(void)
+{
+	struct i2c_device *dev, **last;
+	unsigned int addr;
 	int count = 0;
 
-	for (dev = 1; dev < 128; dev++) {
-		if (i2c_read(dev, 0, 0, 0) == 0) {
+	last = &i2c_devices;
+	for (addr = 0; addr < 256; addr += 2) {
+		if (i2c_write(addr, 0, 0, 0) == 0) {
 #ifdef DEBUG_BUS_SCAN
 			int i;
 			for (i = 0; i < NR_DEVMAP; i++)
-				if ((dev & devmap[i].mask) == devmap[i].addr)
+				if ((addr & devmap[i].mask) == devmap[i].addr)
 					break;
-			printk("envctrl: i2c device at %02x: %s\n", dev,
+			printk("envctrl: i2c device at %02x: %s\n", addr,
 			       i < NR_DEVMAP ? devmap[i].name : "unknown");
 #endif
+
+			dev = kmalloc(sizeof(struct i2c_device), GFP_KERNEL);
+			if (!dev) {
+				printk("i2c: can't alloc i2c_device\n");
+				i2c_free_devices();
+				return -ENOMEM;
+			}
+			memset(dev, 0, sizeof(struct i2c_device));
+
+			dev->addr = addr;
+
+			*last = dev;
+			last = &dev->next;
+
 			count++;
 		}
 	}
@@ -233,6 +590,872 @@
 	return 0;
 }
 
+
+static int
+read_8591(unsigned char dev, unsigned char offset, unsigned char *value)
+{
+	unsigned char data[2];
+
+	data[0] = 0x40 | offset;
+	if (i2c_write(dev, data, 1, 0) != 1)
+		return -1;
+	if (i2c_read(dev, data, 2, 0) != 2)
+		return -1;
+	*value = data[1];
+	return 0;
+}
+
+static int
+write_8444(unsigned char dev, unsigned char offset, unsigned char value)
+{
+	unsigned char data[2];
+
+	data[0] = offset;
+	data[1] = value;
+	if (i2c_write(dev, data, 2, 0) != 2)
+		return -1;
+	return 0;
+}
+
+#ifdef U450_SUPPORT
+static int
+read_8583(unsigned char dev, unsigned char offset, unsigned char *value)
+{
+	unsigned char data;
+
+	data = offset;
+	if (i2c_write_read(dev, &data, 1, &data, 1, 0) != 1)
+		return -1;
+	*value = data;
+	return 0;
+}
+
+static int
+write_8583(unsigned char dev, unsigned char offset, unsigned char value)
+{
+	unsigned char data[2];
+
+	data[0] = offset;
+	data[1] = value;
+	if (i2c_write(dev, data, 2, 0) != 2)
+		return -1;
+	return 0;
+}
+#endif /* U450_SUPPORT */
+
+struct thermistor *
+find_thermistor(const char *name, struct thermistor *from)
+{
+	int n;
+
+	if (!from)
+		from = envctrl.thermistors;
+	else
+		from = from->next;
+
+	n = strlen(name);
+	while (from && strncmp(from->name, name, n))
+		from = from->next;
+
+	return from;
+}
+
+void
+check_temperatures(struct environment *env)
+{
+	struct thermistor *t;
+
+	for (t = env->thermistors; t; t = t->next) {
+#ifdef DEBUG
+		printk("Thermistor `%s' [%02x:%d]: "
+		       "%d C (%d C, %d C)\n",
+		       t->name, t->regs.addr, t->regs.port,
+		       t->temperature(t), t->regs.warning, t->regs.shutdown);
+#endif
+
+		/*
+		 * Implement slow-down or shutdown here...
+		 */
+	}
+}
+
+void
+check_fan_speeds(struct environment *env)
+{
+	unsigned char speed, max;
+	struct thermistor *t;
+	struct fan *f;
+
+	for (f = env->fans; f; f = f->next) {
+#ifdef DEBUG
+		printk("Fan `%s' [%02x:%d]:", f->name,
+		       f->regs.addr, f->regs.port);
+#endif
+		max = 0;
+		for (t = f->monitor; t; t = t->chain) {
+			speed = t->fan_speed(t);
+			if (speed > max)
+				max = speed;
+#ifdef DEBUG
+			printk(" %s:%02x", t->name, speed);
+#endif
+		}
+
+		f->set_speed(f, max);
+#ifdef DEBUG
+		printk(" -> %02x\n", f->value);
+#endif
+	}
+}
+
+void
+envctrl_fans_blast(struct environment *env)
+{
+	struct fan *f;
+
+	for (f = env->fans; f; f = f->next)
+		f->set_speed(f, MAX_FAN_SPEED);
+}
+
+int
+kenvd(void *data)
+{
+	struct environment *env = data;
+
+	MOD_INC_USE_COUNT;
+	lock_kernel();
+
+	env->kenvd_pid = current->pid;
+
+	exit_files(current);
+	exit_mm(current);
+
+	spin_lock_irq(&current->sigmask_lock);
+	siginitsetinv(&current->blocked, sigmask(SIGKILL));
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	current->session = 1;
+	current->pgrp = 1;
+	strcpy(current->comm, "kenvd");
+
+	if (env->enable)
+		env->enable(env);
+
+	while (!env->terminate) {
+
+		check_temperatures(env);
+		check_fan_speeds(env);
+		if (env->keep_alive)
+			env->keep_alive(env);
+
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(env->interval * HZ);
+
+		if (signal_pending(current)) {
+			spin_lock_irq(&current->sigmask_lock);
+			flush_signals(current);
+			spin_unlock_irq(&current->sigmask_lock);
+			break;
+		}
+	}
+
+	if (env->disable)
+		env->disable(env);
+
+	env->kenvd_pid = 0;
+	wake_up(&envctrl.kenvd_wait);
+
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+void
+envctrl_stop(void)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct thermistor *t;
+	struct fan *f;
+	pid_t pid;
+
+	if (envctrl.kenvd_pid) {
+		pid = envctrl.kenvd_pid;
+
+		current->state = TASK_INTERRUPTIBLE;
+		add_wait_queue(&envctrl.kenvd_wait, &wait);
+
+		envctrl.terminate = 1;
+		kill_proc(pid, SIGKILL, 1);
+
+		schedule();
+
+		remove_wait_queue(&envctrl.kenvd_wait, &wait);
+		current->state = TASK_RUNNING;
+	}
+
+	t = envctrl.thermistors;
+	while (t) {
+		envctrl.thermistors = t->next;
+		kfree(t);
+		t = envctrl.thermistors;
+	}
+
+	f = envctrl.fans;
+	while (f) {
+		envctrl.fans = f->next;
+		kfree(f);
+		f = envctrl.fans;
+	}
+
+	if (envctrl.cpu_temp_table)
+		kfree(envctrl.cpu_temp_table);
+
+	if (envctrl.cpu_fan_speeds)
+		kfree(envctrl.cpu_fan_speeds);
+
+	if (envctrl.ps_temp_table)
+		kfree(envctrl.ps_temp_table);
+
+	if (envctrl.ps_fan_speeds)
+		kfree(envctrl.ps_fan_speeds);
+}
+
+
+static unsigned char
+axi_get_temperature(struct thermistor *t)
+{
+	unsigned char value;
+
+	if (read_8591(t->regs.addr, t->regs.port, &value) < 0)
+		return MAX_TEMPERATURE;
+	if (t->regs.port == AXI_THERM_PORT_CPU)
+		return axi_cpu_temp_table[value];
+	else
+		return axi_mod_temp_table[value];
+}
+
+static unsigned char
+axi_get_fan_speed(struct thermistor *t)
+{
+	unsigned char temp;
+
+	temp = t->temperature(t);
+	if (temp >= MAX_TEMPERATURE)
+		return MAX_FAN_SPEED;
+
+	return axi_fan_speeds[temp];
+}
+
+static int
+axi_set_fan_speed(struct fan *f, unsigned char value)
+{
+	if (value != f->value) {
+		if (write_8444(f->regs.addr, f->regs.port, value))
+			return -1;
+		f->value = value;
+	}
+	return 0;
+}
+
+static void
+axi_toggle_i2c_int(struct environment *env)
+{
+	unsigned char data;
+
+	if (i2c_read(AXI_PIO_ADDR, &data, 1, 0) != 1)
+		return;
+
+	data &= ~(0x08);
+	if (i2c_write(AXI_PIO_ADDR, &data, 1, 0) != 1)
+		return;
+	mdelay(1);
+
+	data |= 0x08;
+	if (i2c_write(AXI_PIO_ADDR, &data, 1, 0) != 1)
+		return;
+	mdelay(1);
+}
+
+
+static int
+rasctrl_setup(int node)
+{
+	struct thermistor *t, **tlast;
+	struct fan *f, **flast;
+	char tmp[32];
+	int monitor;
+	int shutdown;
+	int warning;
+	int i;
+
+	prom_getstring(prom_root_node, "name", tmp, sizeof(tmp));
+	if (strcmp(tmp, "SUNW,UltraSPARC-IIi-Engine")) {
+		printk("SUNW,rasctrl will work only on Ultra AXi\n");
+		return -ENODEV;
+	}
+
+	monitor = prom_getintdefault(node, "env-monitor", 0);
+	if (monitor == 0)
+		return -ENODEV;
+
+	envctrl.interval = prom_getintdefault(node, "env-mon-interval", 60);
+	warning = prom_getintdefault(node, "warning-temp", 55);
+	shutdown = prom_getintdefault(node, "shutdown-temp", 58);
+
+	tlast = &envctrl.thermistors;
+	for (i = 0; i < 4; i++) {
+		t = kmalloc(sizeof(struct thermistor), GFP_KERNEL);
+		if (!t)
+			goto out;
+		memset(t, 0, sizeof(struct thermistor));
+
+		t->regs.addr = AXI_THERM_ADDR;
+		t->regs.port = i;
+		t->regs.warning = warning;
+		t->regs.shutdown = shutdown;
+
+		switch (i) {
+		case AXI_THERM_PORT_CPU:
+			sprintf(t->name, "%.7s", "CPU");
+			break;
+		case AXI_THERM_PORT_MOD:
+			sprintf(t->name, "%.7s", "MOD");
+			break;
+		case AXI_THERM_PORT_PCI:
+			sprintf(t->name, "%.7s", "PCI");
+			break;
+		case AXI_THERM_PORT_DISK:
+			sprintf(t->name, "%.7s", "DISK");
+			break;
+		}
+
+		t->temperature = axi_get_temperature;
+		t->fan_speed = axi_get_fan_speed;
+
+		if (!i2c_find_device(t->regs.addr)) {
+			printk("envctrl: `%s': i2c device %02x not found\n",
+			       t->name, t->regs.addr);
+			kfree(t);
+			continue;
+		}
+
+		*tlast = t;
+		tlast = &t->next;
+	}
+
+	flast = &envctrl.fans;
+	for (i = 0; i < 2; i++) {
+		f = kmalloc(sizeof(struct fan), GFP_KERNEL);
+		if (!f)
+			goto out;
+		memset(f, 0, sizeof(struct fan));
+
+		f->regs.addr = AXI_FAN_ADDR;
+		f->regs.port = i;
+
+		switch (i) {
+		case AXI_FAN_PORT_FRONT:
+			sprintf(f->name, "%.7s", "FRONT");
+			t = NULL;
+			while ((t = find_thermistor("CPU", t))) {
+				t->chain = f->monitor;
+				f->monitor = t;
+			}
+			break;
+		case AXI_FAN_PORT_BACK:
+			sprintf(f->name, "%.7s", "BACK");
+			t = NULL;
+			while ((t = find_thermistor("PCI", t))) {
+				t->chain = f->monitor;
+				f->monitor = t;
+			}
+			break;
+		}
+
+		if (!f->monitor) {
+			kfree(f);
+			continue;
+		}
+
+		if (!i2c_find_device(f->regs.addr)) {
+			printk("envctrl: `%s': i2c device %02x not found\n",
+			       f->name, f->regs.addr);
+			kfree(f);
+			continue;
+		}
+
+		*flast = f;
+		flast = &f->next;
+
+		f->check_failure = NULL;
+		f->set_speed = axi_set_fan_speed;
+	}
+
+	envctrl.enable = axi_toggle_i2c_int;
+	envctrl.disable = envctrl_fans_blast;
+
+#ifdef DEBUG
+	printk("Warn: %d C, Shutdown %d C, Interval %d s, Monitor %d\n",
+		warning, shutdown, envctrl.interval, monitor);
+#endif
+	return 0;
+
+out:
+	envctrl_stop();
+	return -ENODEV;
+}
+
+
+#ifdef U450_SUPPORT
+
+static unsigned char
+envctrl_get_temperature(struct thermistor *t)
+{
+	unsigned char value;
+
+	if (read_8591(t->regs.addr, t->regs.port, &value) < 0)
+		return MAX_TEMPERATURE;
+	if (!strncmp(t->name, "CPU", 3))
+		return envctrl.cpu_temp_table[value];
+	else
+		return envctrl.ps_temp_table[value];
+}
+
+static unsigned char
+envctrl_get_fan_speed(struct thermistor *t)
+{
+	unsigned char temp;
+
+	temp = t->temperature(t);
+	if (temp >= MAX_TEMPERATURE)
+		return MAX_FAN_SPEED;
+
+	if (!strncmp(t->name, "CPU", 3))
+		return envctrl.cpu_fan_speeds[temp];
+	else
+		return envctrl.ps_fan_speeds[temp];
+}
+
+static int
+envctrl_set_fan_speed(struct fan *f, unsigned char value)
+{
+	if (value != f->value) {
+		if (write_8444(f->regs.addr, f->regs.port, value))
+			return -1;
+		f->value = value;
+	}
+
+	return 0;
+}
+
+static unsigned char u450_default_thermisters[] =
+{
+	/* CPU0 */
+	0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46,
+	0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x01, 0x43, 0x50, 0x55, 0x30, 0x00,
+	/* CPU1 */
+	0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46,
+	0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x01, 0x43, 0x50, 0x55, 0x31, 0x00,
+	/* CPU2 */
+	0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46,
+	0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x01, 0x43, 0x50, 0x55, 0x32, 0x00,
+	/* CPU3 */
+	0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46,
+	0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x01, 0x43, 0x50, 0x55, 0x33, 0x00,
+	/* PS0 */
+	0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5a,
+	0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x01, 0x50, 0x53, 0x30, 0x00,
+	/* PS1 */
+	0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5a,
+	0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x01, 0x50, 0x53, 0x31, 0x00,
+	/* PS2 */
+	0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5a,
+	0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x01, 0x50, 0x53, 0x32, 0x00,
+	/* AMB */
+	0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x28,
+	0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x01, 0x41, 0x4d, 0x42, 0x00
+};
+
+static unsigned char u450_default_cpu_temp_factors[] =
+{
+	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
+	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
+	0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96,
+	0x96, 0x94, 0x92, 0x90, 0x8f, 0x8e, 0x8d, 0x8c,
+	0x8a, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82,
+	0x81, 0x80, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a,
+	0x79, 0x79, 0x78, 0x78, 0x77, 0x76, 0x75, 0x74,
+	0x73, 0x72, 0x71, 0x70, 0x70, 0x6f, 0x6f, 0x6e,
+	0x6e, 0x6e, 0x6d, 0x6d, 0x6c, 0x6b, 0x6a, 0x6a,
+	0x69, 0x69, 0x68, 0x67, 0x66, 0x65, 0x65, 0x64,
+	0x64, 0x64, 0x63, 0x63, 0x62, 0x62, 0x61, 0x61,
+	0x60, 0x60, 0x5f, 0x5f, 0x5e, 0x5e, 0x5d, 0x5d,
+	0x5c, 0x5c, 0x5b, 0x5b, 0x5b, 0x5a, 0x5a, 0x5a,
+	0x59, 0x59, 0x58, 0x58, 0x57, 0x57, 0x56, 0x56,
+	0x55, 0x55, 0x54, 0x54, 0x53, 0x53, 0x52, 0x52,
+	0x52, 0x51, 0x51, 0x50, 0x50, 0x50, 0x50, 0x4f,
+	0x4f, 0x4f, 0x4e, 0x4e, 0x4e, 0x4d, 0x4d, 0x4d,
+	0x4c, 0x4c, 0x4c, 0x4b, 0x4b, 0x4b, 0x4a, 0x4a,
+	0x4a, 0x49, 0x49, 0x49, 0x48, 0x48, 0x48, 0x47,
+	0x47, 0x47, 0x46, 0x46, 0x46, 0x46, 0x45, 0x45,
+	0x45, 0x44, 0x44, 0x44, 0x44, 0x43, 0x43, 0x43,
+	0x43, 0x42, 0x42, 0x42, 0x42, 0x41, 0x41, 0x41,
+	0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e, 0x3e,
+	0x3e, 0x3d, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
+	0x3c, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
+	0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37, 0x37,
+	0x37, 0x37, 0x36, 0x36, 0x36, 0x35, 0x35, 0x35,
+	0x34, 0x34, 0x34, 0x33, 0x33, 0x33, 0x33, 0x32,
+	0x32, 0x32, 0x31, 0x31, 0x31, 0x30, 0x30, 0x30,
+	0x2f, 0x2f, 0x2f, 0x2e, 0x2e, 0x2e, 0x2d, 0x2d,
+	0x2d, 0x2c, 0x2c, 0x2c, 0x2b, 0x2b, 0x2b, 0x2a,
+	0x2a, 0x2a, 0x29, 0x29, 0x29, 0x28, 0x28, 0x28
+};
+
+static unsigned char u450_default_cpu_fan_speeds[] =
+{
+	0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+	0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+	0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+	0x1f, 0x1f, 0x1f, 0x1f, 0x20, 0x21, 0x22, 0x23,
+	0x24, 0x25, 0x26, 0x27, 0x28, 0x2a, 0x2b, 0x2d,
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f
+};
+
+static unsigned char u450_default_ps_temp_factors[] =
+{
+	0x9a, 0x96, 0x82, 0x7d, 0x78, 0x73, 0x6e, 0x6b,
+	0x69, 0x67, 0x64, 0x5f, 0x5a, 0x57, 0x55, 0x53,
+	0x51, 0x50, 0x4e, 0x4d, 0x4c, 0x4b, 0x49, 0x47,
+	0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3f,
+	0x3e, 0x3d, 0x3c, 0x3c, 0x3b, 0x3a, 0x39, 0x39,
+	0x38, 0x37, 0x37, 0x36, 0x35, 0x35, 0x34, 0x33,
+	0x32, 0x32, 0x32, 0x31, 0x31, 0x30, 0x30, 0x2f,
+	0x2f, 0x2e, 0x2e, 0x2d, 0x2d, 0x2c, 0x2c, 0x2b,
+	0x2a, 0x2a, 0x29, 0x29, 0x28, 0x28, 0x27, 0x27,
+	0x26, 0x26, 0x25, 0x25, 0x25, 0x25, 0x24, 0x24,
+	0x23, 0x23, 0x23, 0x22, 0x22, 0x22, 0x21, 0x21,
+	0x21, 0x20, 0x20, 0x20, 0x1f, 0x1f, 0x1e, 0x1e,
+	0x1e, 0x1d, 0x1d, 0x1d, 0x1d, 0x1c, 0x1c, 0x1c,
+	0x1b, 0x1b, 0x1b, 0x1a, 0x1a, 0x1a, 0x19, 0x19,
+	0x19, 0x18, 0x18, 0x18, 0x18, 0x17, 0x17, 0x17,
+	0x17, 0x16, 0x16, 0x16, 0x16, 0x15, 0x15, 0x15,
+	0x14, 0x14, 0x14, 0x13, 0x13, 0x13, 0x13, 0x13,
+	0x12, 0x12, 0x12, 0x12, 0x11, 0x11, 0x11, 0x11,
+	0x10, 0x10, 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0f,
+	0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d,
+	0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b,
+	0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08,
+	0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
+	0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
+	0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
+	0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
+	0x01, 0x01, 0x01, 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
+};
+
+static unsigned char u450_default_ps_fan_speeds[] =
+{
+	0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+	0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+	0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
+	0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x21, 0x22, 0x23,
+	0x24, 0x25, 0x26, 0x26, 0x27, 0x28, 0x29, 0x2a,
+	0x2b, 0x2d, 0x2e, 0x2f, 0x30, 0x30, 0x30, 0x30,
+	0x30, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
+	0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f
+};
+
+static void
+u450_toggle_i2c_int(struct environment *env)
+{
+	unsigned char tmp[80];
+	unsigned char data;
+	int i, n;
+
+	write_8583(U450_TIMER_ADDR, 0, 0x84);
+	write_8583(U450_TIMER_ADDR, 8, 0x0a);
+	write_8583(U450_TIMER_ADDR, 7, 0x00);
+	write_8583(U450_TIMER_ADDR, 0, 0x04);
+
+	n = sprintf(tmp, "envctrl: PCF8583:");
+	for (i = 0; i < 16; i++) {
+		if (read_8583(U450_TIMER_ADDR, i, &data) < 0) {
+			printk("envctrl: error reading PCF8583\n");
+			break;
+		}
+		n += sprintf(tmp+n, " %02x", data);
+	}
+	printk("%s\n", tmp);
+
+#if 1
+	data = 0x70;
+	if (i2c_write(U450_PIO_ADDR, &data, 1, 0) != 1)
+		return;
+	mdelay(1);
+
+	data = 0x78;
+	if (i2c_write(U450_PIO_ADDR, &data, 1, 0) != 1)
+		return;
+	mdelay(1);
+#endif
+}
+
+static void
+u450_set_egg_timer(struct environment *env)
+{
+	unsigned char value;
+
+#if 0
+	write_8583(U450_TIMER_ADDR, 0x00, 0x84);
+	read_8583(U450_TIMER_ADDR, 0x07, &value);
+	write_8583(U450_TIMER_ADDR, 0x07, 0x00);
+	write_8583(U450_TIMER_ADDR, 0x00, 0x04);
+#else
+	read_8583(U450_TIMER_ADDR, 0x07, &value);
+	printk("envctrl: TIMER [%02x:07]: %02x\n", U450_TIMER_ADDR, value);
+	read_8583(U450_TIMER_ADDR, 0x00, &value);
+	printk("envctrl: TIMER [%02x:00]: %02x\n", U450_TIMER_ADDR, value);
+#endif
+}
+
+static int
+envctrl_setup(int node)
+{
+	struct thermistor *t, **tlast;
+	struct fan *f, **flast;
+	unsigned char *tmp = NULL, *p;
+	int len, n, err;
+	int defaults = 0;
+
+	len = prom_getproplen(node, "thermisters");
+	if (len <= 0) {
+		printk("envctrl: no property `thermisters', using defaults\n");
+		defaults++;
+		len = sizeof(u450_default_thermisters);
+	}
+
+	tmp = (unsigned char *)kmalloc(len, GFP_KERNEL);
+	if (!tmp) {
+		printk("envctrl: can't allocate property buffer\n");
+		return -ENODEV;
+	}
+
+	if (defaults) {
+		memcpy(tmp, u450_default_thermisters, len);
+	} else {
+		err = prom_getproperty(node, "thermisters", tmp, len);
+		if (err < 0) {
+			printk("envctrl: error reading property `thermisters'\n");
+			kfree(tmp);
+			return -ENODEV;
+		}
+	}
+
+	p = tmp;
+	err = -ENOMEM;
+
+	tlast = &envctrl.thermistors;
+	while (len > sizeof(struct therm_regs)) {
+		t = kmalloc(sizeof(struct thermistor), GFP_KERNEL);
+		if (!t) {
+			printk("envctrl: can't allocate thermistor struct\n");
+			goto out;
+		}
+		memset(t, 0, sizeof(struct thermistor));
+
+		memcpy(&t->regs, p, sizeof(struct therm_regs));
+		p += sizeof(struct therm_regs);
+		len -= sizeof(struct therm_regs);
+
+		n = strlen(p) + 1;
+		strncpy(t->name, p, 7);
+		p += n;
+		len -= n;
+
+		if (!i2c_find_device(t->regs.addr)) {
+			printk("envctrl: `%s': i2c device %02x not found\n",
+			       t->name, t->regs.addr);
+			kfree(t);
+			continue;
+		}
+
+		t->temperature = envctrl_get_temperature;
+		t->fan_speed = envctrl_get_fan_speed;
+
+		*tlast = t;
+		tlast = &t->next;
+	}
+
+	flast = &envctrl.fans;
+	for (n = 0; n < 2; n++) {
+		f = kmalloc(sizeof(struct fan), GFP_KERNEL);
+		if (!f)
+			goto out;
+		memset(f, 0, sizeof(struct fan));
+
+		f->regs.addr = U450_FAN_ADDR;
+		f->regs.port = n;
+
+		switch (n) {
+		case U450_FAN_PORT_CPU:
+			sprintf(f->name, "%.7s", "CPU");
+			t = NULL;
+			while ((t = find_thermistor("CPU", t))) {
+				t->chain = f->monitor;
+				f->monitor = t;
+			}
+			break;
+		case U450_FAN_PORT_PS:
+			sprintf(f->name, "%.7s", "PS");
+			t = NULL;
+			while ((t = find_thermistor("PS", t))) {
+				t->chain = f->monitor;
+				f->monitor = t;
+			}
+			break;
+		}
+
+		if (!f->monitor) {
+			kfree(f);
+			continue;
+		}
+
+		if (!i2c_find_device(f->regs.addr)) {
+			printk("envctrl: `%s': i2c device %02x not found\n",
+			       f->name, f->regs.addr);
+			kfree(f);
+			continue;
+		}
+
+		*flast = f;
+		flast = &f->next;
+
+		f->check_failure = NULL;
+		f->set_speed = envctrl_set_fan_speed;
+	}
+
+	envctrl.cpu_temp_table = kmalloc(256, GFP_KERNEL);
+	if (!envctrl.cpu_temp_table) {
+		printk("envctrl: can't allocate temperature table\n");
+		goto out;
+	}
+	if (defaults) {
+		memcpy(envctrl.cpu_temp_table,
+		       u450_default_cpu_temp_factors, 256);
+	} else {
+		err = prom_getproperty(node, "cpu-temp-factors",
+				       envctrl.cpu_temp_table, 256);
+		if (err) {
+			printk("envctrl: can't read `cpu-temp-factors'\n");
+			goto out;
+		}
+	}
+
+	envctrl.cpu_fan_speeds = kmalloc(112, GFP_KERNEL);
+	if (!envctrl.cpu_fan_speeds) {
+		printk("envctrl: can't allocate fan speed table\n");
+		goto out;
+	}
+	if (defaults) {
+		memcpy(envctrl.cpu_fan_speeds,
+		       u450_default_cpu_fan_speeds, 112);
+	} else {
+		err = prom_getproperty(node, "cpu-fan-speeds",
+				       envctrl.cpu_fan_speeds, 112);
+		if (err) {
+			printk("envctrl: can't read `cpu-fan-speeds'\n");
+			goto out;
+		}
+	}
+
+	envctrl.ps_temp_table = kmalloc(256, GFP_KERNEL);
+	if (!envctrl.ps_temp_table) {
+		printk("envctrl: can't allocate temperature table\n");
+		goto out;
+	}
+	if (defaults) {
+		memcpy(envctrl.ps_temp_table,
+		       u450_default_ps_temp_factors, 256);
+	} else {
+		err = prom_getproperty(node, "ps-temp-factors",
+				       envctrl.ps_temp_table, 256);
+		if (err) {
+			printk("envctrl: can't read `ps-temp-factors'\n");
+			goto out;
+		}
+	}
+
+	envctrl.ps_fan_speeds = kmalloc(112, GFP_KERNEL);
+	if (!envctrl.ps_fan_speeds) {
+		printk("envctrl: can't allocate fan speed table\n");
+		goto out;
+	}
+	if (defaults) {
+		memcpy(envctrl.ps_fan_speeds,
+		       u450_default_ps_fan_speeds, 112);
+	} else {
+		err = prom_getproperty(node, "ps-fan-speeds",
+				       envctrl.ps_fan_speeds, 112);
+		if (err) {
+			printk("envctrl: can't read `ps-fan-speeds'\n");
+			goto out;
+		}
+	}
+
+	envctrl.enable = u450_toggle_i2c_int;
+	envctrl.keep_alive = u450_set_egg_timer;
+	envctrl.disable = envctrl_fans_blast;
+	envctrl.interval = 60;
+
+	kfree(tmp);
+	return 0;
+
+out:
+	if (tmp)
+		kfree(tmp);
+
+	envctrl_stop();
+	return err;
+}
+#endif /* U450_SUPPORT */
+
+
+
 static loff_t
 envctrl_llseek(struct file *file, loff_t offset, int type)
 {
@@ -266,7 +1489,9 @@
 		case I2CIOCSADR:
 			if (get_user(addr, (int *)arg))
 				return -EFAULT;
-			data = addr & 0x7f;
+			data = addr & 0xfe;
+			if (!i2c_find_device(addr & 0xfe))
+				return -ENODEV;
 			file->private_data = (void *)data;
 			break;
 		case I2CIOCGADR:
@@ -317,12 +1542,13 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__initfunc(int envctrl_init(void))
+int __init envctrl_init(void)
 #endif
 {
 #ifdef CONFIG_PCI
 	struct linux_ebus *ebus;
 	struct linux_ebus_device *edev = 0;
+	pid_t pid;
 	int err;
 
 	for_each_ebus(ebus) {
@@ -339,33 +1565,55 @@
 		return -ENODEV;
 	}
 
-	if (check_region(edev->base_address[0], sizeof(*i2c))) {
-		printk("%s: Can't get region %lx, %d\n",
-		       __FUNCTION__, edev->base_address[0], (int)sizeof(*i2c));
-		return -ENODEV;
-	}
-
-	i2c = (struct pcf8584_reg *)edev->base_address[0];
-
-	request_region((unsigned long)i2c, sizeof(*i2c), "i2c");
-
-	i2c->csr = CONTROL_PIN;
-	i2c->data = PCF8584_ADDRESS;
-	i2c->csr = CONTROL_PIN | CONTROL_ES1;
-	i2c->data = CLK_4_43 | BUS_CLK_90;
-	i2c->csr = CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK;
+	i2c_regs = edev->resource[0].start;
+	writeb(CONTROL_PIN, i2c_regs + I2C_CSR);
+	writeb(PCF8584_ADDRESS >> 1, i2c_regs + I2C_DATA);
+	writeb(CONTROL_PIN | CONTROL_ES1, i2c_regs + I2C_CSR);
+	writeb(CLK_4_43 | BUS_CLK_90, i2c_regs + I2C_DATA);
+	writeb(CONTROL_PIN | CONTROL_ES0 | CONTROL_ACK, i2c_regs + I2C_CSR);
 	mdelay(10);
 
 	if (misc_register(&envctrl_dev)) {
 		printk("%s: unable to get misc minor %d\n",
 		       __FUNCTION__, envctrl_dev.minor);
-		release_region((unsigned long)i2c, sizeof(*i2c));
+		return -ENODEV;
 	}
 
 	err = i2c_scan_bus();
-	if (err)
-		release_region((unsigned long)i2c, sizeof(*i2c));
-	return err;
+	if (err) {
+		i2c_free_devices();
+		misc_deregister(&envctrl_dev);
+		return err;
+	}
+
+	memset(&envctrl, 0, sizeof(struct environment));
+
+	err = -ENODEV;
+	if (!strcmp(edev->prom_name, "SUNW,rasctrl"))
+		err = rasctrl_setup(edev->prom_node);
+#ifdef U450_SUPPORT
+	else if (!strcmp(edev->prom_name, "SUNW,envctrl"))
+		err = envctrl_setup(edev->prom_node);
+#endif
+
+	if (err) {
+		envctrl_stop();
+		i2c_free_devices();
+		misc_deregister(&envctrl_dev);
+		return err;
+	}
+
+	init_waitqueue_head(&envctrl.kenvd_wait);
+
+	pid = kernel_thread(kenvd, (void *)&envctrl, CLONE_FS);
+	if (pid < 0) {
+		envctrl_stop();
+		i2c_free_devices();
+		misc_deregister(&envctrl_dev);
+		return -ENODEV;
+	}
+
+	return 0;
 #else
 	return -ENODEV;
 #endif
@@ -375,7 +1623,8 @@
 #ifdef MODULE
 void cleanup_module(void)
 {
+	envctrl_stop();
+	i2c_free_devices();
 	misc_deregister(&envctrl_dev);
-	release_region((unsigned long)i2c, sizeof(*i2c));
 }
 #endif
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c
--- v2.3.15/linux/drivers/sbus/char/flash.c	Mon Mar 15 16:11:30 1999
+++ linux/drivers/sbus/char/flash.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: flash.c,v 1.11 1999/03/09 14:06:45 davem Exp $
+/* $Id: flash.c,v 1.13 1999/08/31 06:58:06 davem Exp $
  * flash.c: Allow mmap access to the OBP Flash, for OBP updates.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -22,11 +22,11 @@
 #include <asm/ebus.h>
 
 static struct {
-	unsigned long read_base;
-	unsigned long write_base;
-	unsigned long read_size;
-	unsigned long write_size;
-	unsigned long busy;
+	unsigned long read_base;	/* Physical read address */
+	unsigned long write_base;	/* Physical write address */
+	unsigned long read_size;	/* Size of read area */
+	unsigned long write_size;	/* Size of write area */
+	unsigned long busy;		/* In use? */
 } flash;
 
 #define FLASH_MINOR	152
@@ -41,7 +41,7 @@
 		return -ENXIO;
 
 	if (flash.read_base == flash.write_base) {
-		addr = __pa(flash.read_base);
+		addr = flash.read_base;
 		size = flash.read_size;
 	} else {
 		if ((vma->vm_flags & VM_READ) &&
@@ -49,10 +49,10 @@
 			return -EINVAL;
 
 		if (vma->vm_flags & VM_READ) {
-			addr = __pa(flash.read_base);
+			addr = flash.read_base;
 			size = flash.read_size;
 		} else if (vma->vm_flags & VM_WRITE) {
-			addr = __pa(flash.write_base);
+			addr = flash.write_base;
 			size = flash.write_size;
 		} else
 			return -ENXIO;
@@ -152,7 +152,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__initfunc(int flash_init(void))
+int __init flash_init(void)
 #endif
 {
 	struct linux_sbus *sbus;
@@ -167,20 +167,17 @@
 			prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0],
 					       sdev->num_registers, sdev);
 			if (sdev->reg_addrs[0].phys_addr == sdev->reg_addrs[1].phys_addr) {
-				flash.read_base = (unsigned long)sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
-								 sdev->reg_addrs[0].reg_size, "flashprom",
-								 sdev->reg_addrs[0].which_io, 0);
+				flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) |
+					(((unsigned long)sdev->reg_addrs[0].which_io)<<32UL);
 				flash.read_size = sdev->reg_addrs[0].reg_size;
 				flash.write_base = flash.read_base;
 				flash.write_size = flash.read_size;
 			} else {
-				flash.read_base = (unsigned long)sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
-								 sdev->reg_addrs[0].reg_size, "flashprom",
-								 sdev->reg_addrs[0].which_io, 0);
+				flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) |
+					(((unsigned long)sdev->reg_addrs[0].which_io)<<32UL);
 				flash.read_size = sdev->reg_addrs[0].reg_size;
-				flash.write_base = (unsigned long)sparc_alloc_io(sdev->reg_addrs[1].phys_addr, 0,
-								 sdev->reg_addrs[1].reg_size, "flashprom",
-								 sdev->reg_addrs[1].which_io, 0);
+				flash.write_base = ((unsigned long)sdev->reg_addrs[1].phys_addr) |
+					(((unsigned long)sdev->reg_addrs[1].which_io)<<32UL);
 				flash.write_size = sdev->reg_addrs[1].reg_size;
 			}
 			flash.busy = 0;
@@ -207,14 +204,14 @@
 
 		nregs = len / sizeof(regs[0]);
 
-		flash.read_base = edev->base_address[0];
+		flash.read_base = edev->resource[0].start;
 		flash.read_size = regs[0].reg_size;
 
 		if (nregs == 1) {
-			flash.write_base = edev->base_address[0];
+			flash.write_base = edev->resource[0].start;
 			flash.write_size = regs[0].reg_size;
 		} else if (nregs == 2) {
-			flash.write_base = edev->base_address[1];
+			flash.write_base = edev->resource[1].start;
 			flash.write_size = regs[1].reg_size;
 		} else {
 			printk("flash: Strange number of regs %d\n", nregs);
@@ -229,8 +226,8 @@
 	}
 
 	printk("OBP Flash: RD %lx[%lx] WR %lx[%lx]\n",
-	       __pa(flash.read_base), flash.read_size,
-	       __pa(flash.write_base), flash.write_size);
+	       flash.read_base, flash.read_size,
+	       flash.write_base, flash.write_size);
 
 	err = misc_register(&flash_dev);
 	if (err) {
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/openprom.c linux/drivers/sbus/char/openprom.c
--- v2.3.15/linux/drivers/sbus/char/openprom.c	Mon Aug 24 13:14:09 1998
+++ linux/drivers/sbus/char/openprom.c	Tue Aug 31 11:25:33 1999
@@ -577,7 +577,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__initfunc(int openprom_init(void))
+int __init openprom_init(void)
 #endif
 {
 	unsigned long flags;
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.3.15/linux/drivers/sbus/char/pcikbd.c	Wed Jun  9 14:44:25 1999
+++ linux/drivers/sbus/char/pcikbd.c	Tue Aug 31 11:30:48 1999
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.30 1999/06/03 15:02:36 davem Exp $
+/* $Id: pcikbd.c,v 1.32 1999/08/31 06:58:11 davem Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -367,7 +367,7 @@
 		
 }
 
-__initfunc(static int pcikbd_wait_for_input(void))
+static int __init pcikbd_wait_for_input(void)
 {
 	int status, data;
 	unsigned long start = jiffies;
@@ -384,7 +384,7 @@
 	return -1;
 }
 
-__initfunc(static void pcikbd_write(int address, int data))
+static void __init pcikbd_write(int address, int data)
 {
 	int status;
 
@@ -436,7 +436,7 @@
 
 extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);
 
-__initfunc(static char *do_pcikbd_init_hw(void))
+static char * __init do_pcikbd_init_hw(void)
 {
 
 	while(pcikbd_wait_for_input() != -1)
@@ -479,7 +479,7 @@
 	return NULL; /* success */
 }
 
-__initfunc(void pcikbd_init_hw(void))
+void __init pcikbd_init_hw(void)
 {
 	struct linux_ebus *ebus;
 	struct linux_ebus_device *edev;
@@ -516,16 +516,7 @@
 		return;
 
 found:
-		pcikbd_iobase = child->base_address[0];
-#ifdef __sparc_v9__
-		if (check_region(pcikbd_iobase, sizeof(unsigned long))) {
-			printk("8042: can't get region %lx, %d\n",
-			       pcikbd_iobase, (int)sizeof(unsigned long));
-			return;
-		}
-		request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller");
-#endif
-
+		pcikbd_iobase = child->resource[0].start;
 		pcikbd_irq = child->irqs[0];
 		if (request_irq(pcikbd_irq, &pcikbd_interrupt,
 				SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) {
@@ -559,17 +550,11 @@
 	if (!edev)
 		pcibeep_iobase = (pcikbd_iobase & ~(0xffffff)) | 0x722000;
 	else
-		pcibeep_iobase = edev->base_address[0];
+		pcibeep_iobase = edev->resource[0].start;
 
-	if (check_region(pcibeep_iobase, sizeof(unsigned int))) {
-		printk("8042: can't get region %lx, %d\n",
-		       pcibeep_iobase, (int)sizeof(unsigned int));
-	} else {
-		request_region(pcibeep_iobase, sizeof(unsigned int), "speaker");
-		kd_mksound = pcikbd_kd_mksound;
-		printk("8042(speaker): iobase[%016lx]%s\n", pcibeep_iobase,
-		       edev ? "" : " (forced)");
-	}
+	kd_mksound = pcikbd_kd_mksound;
+	printk("8042(speaker): iobase[%016lx]%s\n", pcibeep_iobase,
+	       edev ? "" : " (forced)");
 #endif
 
 	disable_irq(pcikbd_irq);
@@ -711,7 +696,7 @@
  * Write to device & handle returned ack
  */
 
-__initfunc(static int aux_write_ack(int val))
+static int __init aux_write_ack(int val)
 {
 	aux_write_dev(val);
 	poll_aux_status();
@@ -893,7 +878,7 @@
 			return -EAGAIN;
 		add_wait_queue(&queue->proc_list, &wait);
 repeat:
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (queue_empty() && !signal_pending(current)) {
 			schedule();
 			goto repeat;
@@ -943,7 +928,7 @@
 	PSMOUSE_MINOR, "ps2aux", &psaux_fops
 };
 
-__initfunc(int pcimouse_init(void))
+int __init pcimouse_init(void)
 {
 	struct linux_ebus *ebus;
 	struct linux_ebus_device *edev;
@@ -971,14 +956,7 @@
 		return -ENODEV;
 
 found:
-		pcimouse_iobase = child->base_address[0];
-		/*
-		 * Just in case the iobases for kbd/mouse ever differ...
-		 */
-		if (!check_region(pcimouse_iobase, sizeof(unsigned long)))
-			request_region(pcimouse_iobase, sizeof(unsigned long),
-				       "8042 controller");
-
+		pcimouse_iobase = child->resource[0].start;
 		pcimouse_irq = child->irqs[0];
 	}
 
@@ -1027,7 +1005,7 @@
 }
 
 
-__initfunc(int ps2kbd_probe(unsigned long *memory_start))
+int __init ps2kbd_probe(unsigned long *memory_start)
 {
 	int pnode, enode, node, dnode, xnode;
 	int kbnode = 0, msnode = 0, bnode = 0;
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/rtc.c linux/drivers/sbus/char/rtc.c
--- v2.3.15/linux/drivers/sbus/char/rtc.c	Wed Jun  9 14:44:25 1999
+++ linux/drivers/sbus/char/rtc.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: rtc.c,v 1.14 1999/06/03 15:02:38 davem Exp $
+/* $Id: rtc.c,v 1.17 1999/08/31 13:32:01 anton Exp $
  *
  * Linux/SPARC Real Time Clock Driver
  * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
@@ -29,12 +29,16 @@
 /* Retrieve the current date and time from the real time clock. */
 void get_rtc_time(struct rtc_time *t)
 {
-	register struct mostek48t02 *regs = mstk48t02_regs;
+	struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
 	unsigned long flags;
+	u8 tmp;
 
 	save_flags(flags);
 	cli();
-	regs->creg |= MSTK_CREG_READ;
+
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp |= MSTK_CREG_READ;
+	mostek_write(regs + MOSTEK_CREG, tmp);
 
 	t->sec = MSTK_REG_SEC(regs);
 	t->min = MSTK_REG_MIN(regs);
@@ -44,19 +48,24 @@
 	t->month = MSTK_REG_MONTH(regs);
 	t->year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) );
 
-	regs->creg &= ~MSTK_CREG_READ;
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp &= ~MSTK_CREG_READ;
+	mostek_write(regs + MOSTEK_CREG, tmp);
 	restore_flags(flags);
 }
 
 /* Set the current date and time inthe real time clock. */
 void set_rtc_time(struct rtc_time *t)
 {
-	register struct mostek48t02 *regs = mstk48t02_regs;
+	struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
 	unsigned long flags;
+	u8 tmp;
 
 	save_flags(flags);
 	cli();
-	regs->creg |= MSTK_CREG_WRITE;
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp |= MSTK_CREG_WRITE;
+	mostek_write(regs + MOSTEK_CREG, tmp);
 
 	MSTK_SET_REG_SEC(regs,t->sec);
 	MSTK_SET_REG_MIN(regs,t->min);
@@ -66,7 +75,9 @@
 	MSTK_SET_REG_MONTH(regs,t->month);
 	MSTK_SET_REG_YEAR(regs,t->year - MSTK_YEAR_ZERO);
 
-	regs->creg &= ~MSTK_CREG_WRITE;
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp &= ~MSTK_CREG_WRITE;
+	mostek_write(regs + MOSTEK_CREG, tmp);
 	restore_flags(flags);
 }
 
@@ -145,7 +156,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__initfunc(int rtc_sun_init(void))
+int __init rtc_sun_init(void)
 #endif
 {
 	int error;
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c
--- v2.3.15/linux/drivers/sbus/char/sab82532.c	Sun Jul  4 09:53:12 1999
+++ linux/drivers/sbus/char/sab82532.c	Tue Aug 31 11:30:48 1999
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.32 1999/07/03 08:57:41 davem Exp $
+/* $Id: sab82532.c,v 1.34 1999/08/31 06:58:16 davem Exp $
  * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -174,7 +174,7 @@
 static __inline__ void sab82532_tec_wait(struct sab82532 *info)
 {
 	int count = SAB82532_MAX_TEC_DELAY;
-	while ((info->regs->r.star & SAB82532_STAR_TEC) && --count)
+	while ((readb(&info->regs->r.star) & SAB82532_STAR_TEC) && --count)
 		udelay(1);
 }
 
@@ -188,12 +188,13 @@
 	if (info->xmit_cnt <= 0)
 		goto out;
 
-	if (!(info->regs->r.star & SAB82532_STAR_XFW))
+	if (!(readb(&info->regs->r.star) & SAB82532_STAR_XFW))
 		goto out;
 
 	info->all_sent = 0;
 	for (i = 0; i < info->xmit_fifo_size; i++) {
-		info->regs->w.xfifo[i] = info->xmit_buf[info->xmit_tail++];
+		u8 val = info->xmit_buf[info->xmit_tail++];
+		writeb(val, &info->regs->w.xfifo[i]);
 		info->xmit_tail &= (SERIAL_XMIT_SIZE - 1);
 		info->icount.tx++;
 		if (--info->xmit_cnt <= 0)
@@ -201,9 +202,9 @@
 	}
 
 	/* Issue a Transmit Frame command. */
-	if (info->regs->r.star & SAB82532_STAR_CEC)
+	if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
 		udelay(1);
-	info->regs->w.cmdr = SAB82532_CMDR_XF;
+	writeb(SAB82532_CMDR_XF, &info->regs->w.cmdr);
 
 out:
 	restore_flags(flags);
@@ -228,7 +229,7 @@
 
 	save_flags(flags); cli();
 	info->interrupt_mask1 |= SAB82532_IMR1_XPR;
-	info->regs->w.imr1 = info->interrupt_mask1;
+	writeb(info->interrupt_mask1, &info->regs->w.imr1);
 	restore_flags(flags);
 }
 
@@ -242,14 +243,14 @@
 
 	save_flags(flags); cli();
 	info->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);
-	info->regs->w.imr1 = info->interrupt_mask1;
+	writeb(info->interrupt_mask1, &info->regs->w.imr1);
 	sab82532_start_tx(info);
 	restore_flags(flags);
 }
 
 static void batten_down_hatches(struct sab82532 *info)
 {
-	unsigned char saved_rfc;
+	unsigned char saved_rfc, tmp;
 
 	/* If we are doing kadb, we call the debugger
 	 * else we just drop into the boot monitor.
@@ -262,11 +263,13 @@
 	/*
 	 * Set FIFO to single character mode.
 	 */
-	saved_rfc = info->regs->r.rfc;
-	info->regs->rw.rfc &= ~(SAB82532_RFC_RFDF);
-	if (info->regs->r.star & SAB82532_STAR_CEC)
+	saved_rfc = readb(&info->regs->r.rfc);
+	tmp = readb(&info->regs->rw.rfc);
+	tmp &= ~(SAB82532_RFC_RFDF);
+	writeb(tmp, &info->regs->rw.rfc);
+	if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
 		udelay(1);
-	info->regs->w.cmdr = SAB82532_CMDR_RRES;
+	writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
 
 #ifndef __sparc_v9__
 	if ((((unsigned long)linux_dbvec) >= DEBUG_FIRSTVADDR) &&
@@ -279,10 +282,10 @@
 	/*
 	 * Reset FIFO to character + status mode.
 	 */
-	info->regs->w.rfc = saved_rfc;
-	if (info->regs->r.star & SAB82532_STAR_CEC)
+	writeb(saved_rfc, &info->regs->w.rfc);
+	if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
 		udelay(1);
-	info->regs->w.cmdr = SAB82532_CMDR_RRES;
+	writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
 }
 
 /*
@@ -333,15 +336,15 @@
 	}
 
 	if (stat->sreg.isr0 & SAB82532_ISR0_TCD) {
-		count = info->regs->r.rbcl & (info->recv_fifo_size - 1);
+		count = readb(&info->regs->r.rbcl) & (info->recv_fifo_size - 1);
 		free_fifo++;
 	}
 
 	/* Issue a FIFO read command in case we where idle. */
 	if (stat->sreg.isr0 & SAB82532_ISR0_TIME) {
-		if (info->regs->r.star & SAB82532_STAR_CEC)
+		if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
 			udelay(1);
-		info->regs->w.cmdr = SAB82532_CMDR_RFRD;
+		writeb(SAB82532_CMDR_RFRD, &info->regs->w.cmdr);
 	}
 
 	if (stat->sreg.isr0 & SAB82532_ISR0_RFO) {
@@ -353,13 +356,13 @@
 
 	/* Read the FIFO. */
 	for (i = 0; i < count; i++)
-		buf[i] = info->regs->r.rfifo[i];
+		buf[i] = readb(&info->regs->r.rfifo[i]);
 
 	/* Issue Receive Message Complete command. */
 	if (free_fifo) {
-		if (info->regs->r.star & SAB82532_STAR_CEC)
+		if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
 			udelay(1);
-		info->regs->w.cmdr = SAB82532_CMDR_RMC;
+		writeb(SAB82532_CMDR_RMC, &info->regs->w.cmdr);
 	}
 
 	if (info->is_console)
@@ -410,26 +413,27 @@
 
 	if (stat->sreg.isr1 & SAB82532_ISR1_ALLS)
 		info->all_sent = 1;
-	if (!(info->regs->r.star & SAB82532_STAR_XFW))
+	if (!(readb(&info->regs->r.star) & SAB82532_STAR_XFW))
 		return;
 
 	if (!info->tty) {
 		info->interrupt_mask1 |= SAB82532_IMR1_XPR;
-		info->regs->w.imr1 = info->interrupt_mask1;
+		writeb(info->interrupt_mask1, &info->regs->w.imr1);
 		return;
 	}
 
 	if ((info->xmit_cnt <= 0) || info->tty->stopped ||
 	    info->tty->hw_stopped) {
 		info->interrupt_mask1 |= SAB82532_IMR1_XPR;
-		info->regs->w.imr1 = info->interrupt_mask1;
+		writeb(info->interrupt_mask1, &info->regs->w.imr1);
 		return;
 	}
 
 	/* Stuff 32 bytes into Transmit FIFO. */
 	info->all_sent = 0;
 	for (i = 0; i < info->xmit_fifo_size; i++) {
-		info->regs->w.xfifo[i] = info->xmit_buf[info->xmit_tail++];
+		u8 val = info->xmit_buf[info->xmit_tail++];
+		writeb(val, &info->regs->w.xfifo[i]);
 		info->xmit_tail &= (SERIAL_XMIT_SIZE - 1);
 		info->icount.tx++;
 		if (--info->xmit_cnt <= 0)
@@ -437,9 +441,9 @@
 	}
 
 	/* Issue a Transmit Frame command. */
-	if (info->regs->r.star & SAB82532_STAR_CEC)
+	if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
 		udelay(1);
-	info->regs->w.cmdr = SAB82532_CMDR_XF;
+	writeb(SAB82532_CMDR_XF, &info->regs->w.cmdr);
 
 	if (info->xmit_cnt < WAKEUP_CHARS)
 		sab82532_sched_event(info, RS_EVENT_WRITE_WAKEUP);
@@ -449,7 +453,7 @@
 #endif
 	if (info->xmit_cnt <= 0) {
 		info->interrupt_mask1 |= SAB82532_IMR1_XPR;
-		info->regs->w.imr1 = info->interrupt_mask1;
+		writeb(info->interrupt_mask1, &info->regs->w.imr1);
 	}
 }
 
@@ -490,7 +494,7 @@
 
 check_modem:
 	if (stat->sreg.isr0 & SAB82532_ISR0_CDSC) {
-		info->dcd = (info->regs->r.vstr & SAB82532_VSTR_CD) ? 0 : 1;
+		info->dcd = (readb(&info->regs->r.vstr) & SAB82532_VSTR_CD) ? 0 : 1;
 		info->icount.dcd++;
 		modem_change++;
 #if 0
@@ -498,15 +502,15 @@
 #endif
 	}
 	if (stat->sreg.isr1 & SAB82532_ISR1_CSC) {
-		info->cts = info->regs->r.star & SAB82532_STAR_CTS;
+		info->cts = readb(&info->regs->r.star) & SAB82532_STAR_CTS;
 		info->icount.cts++;
 		modem_change++;
 #if 0
 		printk("CTS change: %d, CTS %s\n", info->icount.cts, info->cts ? "on" : "off");
 #endif
 	}
-	if ((info->regs->r.pvr & info->pvr_dsr_bit) ^ info->dsr) {
-		info->dsr = (info->regs->r.pvr & info->pvr_dsr_bit) ? 0 : 1;
+	if ((readb(&info->regs->r.pvr) & info->pvr_dsr_bit) ^ info->dsr) {
+		info->dsr = (readb(&info->regs->r.pvr) & info->pvr_dsr_bit) ? 0 : 1;
 		info->icount.dsr++;
 		modem_change++;
 #if 0
@@ -548,7 +552,7 @@
 				sab82532_sched_event(info,
 						     RS_EVENT_WRITE_WAKEUP);
 				info->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);
-				info->regs->w.imr1 = info->interrupt_mask1;
+				writeb(info->interrupt_mask1, &info->regs->w.imr1);
 				sab82532_start_tx(info);
 			}
 		} else {
@@ -576,10 +580,10 @@
 #endif
 
 	status.stat = 0;
-	if (info->regs->r.gis & SAB82532_GIS_ISA0)
-		status.sreg.isr0 = info->regs->r.isr0;
-	if (info->regs->r.gis & SAB82532_GIS_ISA1)
-		status.sreg.isr1 = info->regs->r.isr1;
+	if (readb(&info->regs->r.gis) & SAB82532_GIS_ISA0)
+		status.sreg.isr0 = readb(&info->regs->r.isr0);
+	if (readb(&info->regs->r.gis) & SAB82532_GIS_ISA1)
+		status.sreg.isr1 = readb(&info->regs->r.isr1);
 
 #ifdef SERIAL_DEBUG_INTR
 	printk("%d<%02x.%02x>", info->line,
@@ -601,10 +605,10 @@
 next:
 	info = info->next;
 	status.stat = 0;
-	if (info->regs->r.gis & SAB82532_GIS_ISB0)
-		status.sreg.isr0 = info->regs->r.isr0;
-	if (info->regs->r.gis & SAB82532_GIS_ISB1)
-		status.sreg.isr1 = info->regs->r.isr1;
+	if (readb(&info->regs->r.gis) & SAB82532_GIS_ISB0)
+		status.sreg.isr0 = readb(&info->regs->r.isr0);
+	if (readb(&info->regs->r.gis) & SAB82532_GIS_ISB1)
+		status.sreg.isr1 = readb(&info->regs->r.isr1);
 
 #ifdef SERIAL_DEBUG_INTR
 	printk("%d<%02x.%02x>", info->line,
@@ -690,63 +694,73 @@
 static void
 sab82532_init_line(struct sab82532 *info)
 {
-	unsigned char stat;
+	unsigned char stat, tmp;
 
 	/*
 	 * Wait for any commands or immediate characters
 	 */
-	if (info->regs->r.star & SAB82532_STAR_CEC)
+	if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
 		udelay(1);
 	sab82532_tec_wait(info);
 
 	/*
 	 * Clear the FIFO buffers.
 	 */
-	if (info->regs->r.star & SAB82532_STAR_CEC)
+	if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
 		udelay(1);
-	info->regs->w.cmdr = SAB82532_CMDR_RRES;
-	if (info->regs->r.star & SAB82532_STAR_CEC)
+	writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
+	if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
 		udelay(1);
-	info->regs->w.cmdr = SAB82532_CMDR_XRES;
+	writeb(SAB82532_CMDR_XRES, &info->regs->w.cmdr);
 
 	/*
 	 * Clear the interrupt registers.
 	 */
-	stat = info->regs->r.isr0;
-	stat = info->regs->r.isr1;
+	stat = readb(&info->regs->r.isr0);
+	stat = readb(&info->regs->r.isr1);
 
 	/*
 	 * Now, initialize the UART 
 	 */
-	info->regs->w.ccr0 = 0;				/* power-down */
-	info->regs->w.ccr0 = SAB82532_CCR0_MCE | SAB82532_CCR0_SC_NRZ |
-			     SAB82532_CCR0_SM_ASYNC;
-	info->regs->w.ccr1 = SAB82532_CCR1_ODS | SAB82532_CCR1_BCR | 7;
-	info->regs->w.ccr2 = SAB82532_CCR2_BDF | SAB82532_CCR2_SSEL |
-			     SAB82532_CCR2_TOE;
-	info->regs->w.ccr3 = 0;
-	info->regs->w.ccr4 = SAB82532_CCR4_MCK4 | SAB82532_CCR4_EBRG;
-	info->regs->w.mode = SAB82532_MODE_RTS | SAB82532_MODE_FCTS |
-			     SAB82532_MODE_RAC;
-	info->regs->w.rfc = SAB82532_RFC_DPS | SAB82532_RFC_RFDF;
+	writeb(0, &info->regs->w.ccr0);				/* power-down */
+	writeb(SAB82532_CCR0_MCE | SAB82532_CCR0_SC_NRZ |
+	       SAB82532_CCR0_SM_ASYNC, &info->regs->w.ccr0);
+	writeb(SAB82532_CCR1_ODS | SAB82532_CCR1_BCR | 7, &info->regs->w.ccr1);
+	writeb(SAB82532_CCR2_BDF | SAB82532_CCR2_SSEL |
+	       SAB82532_CCR2_TOE, &info->regs->w.ccr2);
+	writeb(0, &info->regs->w.ccr3);
+	writeb(SAB82532_CCR4_MCK4 | SAB82532_CCR4_EBRG, &info->regs->w.ccr4);
+	writeb(SAB82532_MODE_RTS | SAB82532_MODE_FCTS |
+	       SAB82532_MODE_RAC, &info->regs->w.mode);
+	writeb(SAB82532_RFC_DPS | SAB82532_RFC_RFDF, &info->regs->w.rfc);
 	switch (info->recv_fifo_size) {
 		case 1:
-			info->regs->w.rfc |= SAB82532_RFC_RFTH_1;
+			tmp = readb(&info->regs->w.rfc);
+			tmp |= SAB82532_RFC_RFTH_1;
+			writeb(tmp, &info->regs->w.rfc);
 			break;
 		case 4:
-			info->regs->w.rfc |= SAB82532_RFC_RFTH_4;
+			tmp = readb(&info->regs->w.rfc);
+			tmp |= SAB82532_RFC_RFTH_4;
+			writeb(tmp, &info->regs->w.rfc);
 			break;
 		case 16:
-			info->regs->w.rfc |= SAB82532_RFC_RFTH_16;
+			tmp = readb(&info->regs->w.rfc);
+			tmp |= SAB82532_RFC_RFTH_16;
+			writeb(tmp, &info->regs->w.rfc);
 			break;
 		default:
 			info->recv_fifo_size = 32;
 			/* fall through */
 		case 32:
-			info->regs->w.rfc |= SAB82532_RFC_RFTH_32;
+			tmp = readb(&info->regs->w.rfc);
+			tmp |= SAB82532_RFC_RFTH_32;
+			writeb(tmp, &info->regs->w.rfc);
 			break;
 	}
-	info->regs->rw.ccr0 |= SAB82532_CCR0_PU;	/* power-up */
+	tmp = readb(&info->regs->rw.ccr0);
+	tmp |= SAB82532_CCR0_PU;	/* power-up */
+	writeb(tmp, &info->regs->rw.ccr0);
 }
 
 static int startup(struct sab82532 *info)
@@ -788,9 +802,16 @@
 	sab82532_init_line(info);
 
 	if (info->tty->termios->c_cflag & CBAUD) {
-		info->regs->rw.mode &= ~(SAB82532_MODE_FRTS);
-		info->regs->rw.mode |= SAB82532_MODE_RTS;
-		info->regs->rw.pvr &= ~(info->pvr_dtr_bit);
+		u8 tmp;
+
+		tmp = readb(&info->regs->rw.mode);
+		tmp &= ~(SAB82532_MODE_FRTS);
+		tmp |= SAB82532_MODE_RTS;
+		writeb(tmp, &info->regs->rw.mode);
+
+		tmp = readb(&info->regs->rw.pvr);
+		tmp &= ~(info->pvr_dtr_bit);
+		writeb(tmp, &info->regs->rw.pvr);
 	}
 
 	/*
@@ -798,11 +819,11 @@
 	 */
 	info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
 				SAB82532_IMR0_PLLA;
-	info->regs->w.imr0 = info->interrupt_mask0;
+	writeb(info->interrupt_mask0, &info->regs->w.imr0);
 	info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_XOFF |
 				SAB82532_IMR1_TIN | SAB82532_IMR1_XON |
 				SAB82532_IMR1_XPR;
-	info->regs->w.imr1 = info->interrupt_mask1;
+	writeb(info->interrupt_mask1, &info->regs->w.imr1);
 
 	if (info->tty)
 		clear_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -829,6 +850,7 @@
 static void shutdown(struct sab82532 *info)
 {
 	unsigned long flags;
+	u8 tmp;
 
 	if (!(info->flags & ASYNC_INITIALIZED))
 		return;
@@ -853,12 +875,12 @@
 	if (info->is_console) {
 		info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
 					SAB82532_IMR0_PLLA | SAB82532_IMR0_CDSC;
-		info->regs->w.imr0 = info->interrupt_mask0;
+		writeb(info->interrupt_mask0, &info->regs->w.imr0);
 		info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS |
 					SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN |
 					SAB82532_IMR1_CSC | SAB82532_IMR1_XON |
 					SAB82532_IMR1_XPR;
-		info->regs->w.imr1 = info->interrupt_mask1;
+		writeb(info->interrupt_mask1, &info->regs->w.imr1);
 		if (info->tty)
 			set_bit(TTY_IO_ERROR, &info->tty->flags);
 		info->flags &= ~ASYNC_INITIALIZED;
@@ -868,24 +890,30 @@
 
 	/* Disable Interrupts */
 	info->interrupt_mask0 = 0xff;
-	info->regs->w.imr0 = info->interrupt_mask0;
+	writeb(info->interrupt_mask0, &info->regs->w.imr0);
 	info->interrupt_mask1 = 0xff;
-	info->regs->w.imr1 = info->interrupt_mask1;
+	writeb(info->interrupt_mask1, &info->regs->w.imr1);
 
 	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
-		info->regs->rw.mode |= SAB82532_MODE_FRTS;
-		info->regs->rw.mode |= SAB82532_MODE_RTS;
-		info->regs->rw.pvr |= info->pvr_dtr_bit;
+		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);
+		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
+		writeb(readb(&info->regs->rw.pvr) | info->pvr_dtr_bit, &info->regs->rw.pvr);
 	}
 
 	/* Disable break condition */
-	info->regs->rw.dafo &= ~(SAB82532_DAFO_XBRK);
+	tmp = readb(&info->regs->rw.dafo);
+	tmp &= ~(SAB82532_DAFO_XBRK);
+	writeb(tmp, &info->regs->rw.dafo);
 
 	/* Disable Receiver */	
-	info->regs->rw.mode &= ~(SAB82532_MODE_RAC);
+	tmp = readb(&info->regs->rw.mode);
+	tmp &= ~(SAB82532_MODE_RAC);
+	writeb(tmp, &info->regs->rw.mode);
 
 	/* Power Down */	
-	info->regs->rw.ccr0 &= ~(SAB82532_CCR0_PU);
+	tmp = readb(&info->regs->rw.ccr0);
+	tmp &= ~(SAB82532_CCR0_PU);
+	writeb(tmp, &info->regs->rw.ccr0);
 
 	if (info->tty)
 		set_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -999,23 +1027,23 @@
 					    SAB82532_ISR0_TIME;
 
 	save_flags(flags); cli();
-	if (info->regs->r.star & SAB82532_STAR_CEC)
+	if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
 		udelay(1);
 	sab82532_tec_wait(info);
-	info->regs->w.dafo = dafo;
-	info->regs->w.bgr = ebrg & 0xff;
-	info->regs->rw.ccr2 &= ~(0xc0);
-	info->regs->rw.ccr2 |= (ebrg >> 2) & 0xc0;
+	writeb(dafo, &info->regs->w.dafo);
+	writeb(ebrg & 0xff, &info->regs->w.bgr);
+	writeb(readb(&info->regs->rw.ccr2) & ~(0xc0), &info->regs->rw.ccr2);
+	writeb(readb(&info->regs->rw.ccr2) | ((ebrg >> 2) & 0xc0), &info->regs->rw.ccr2);
 	if (info->flags & ASYNC_CTS_FLOW) {
-		info->regs->rw.mode &= ~(SAB82532_MODE_RTS);
-		info->regs->rw.mode |= SAB82532_MODE_FRTS;
-		info->regs->rw.mode &= ~(SAB82532_MODE_FCTS);
+		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode);
+		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);
+		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FCTS), &info->regs->rw.mode);
 	} else {
-		info->regs->rw.mode |= SAB82532_MODE_RTS;
-		info->regs->rw.mode &= ~(SAB82532_MODE_FRTS);
-		info->regs->rw.mode |= SAB82532_MODE_FCTS;
+		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
+		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode);
+		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FCTS, &info->regs->rw.mode);
 	}
-	info->regs->rw.mode |= SAB82532_MODE_RAC;
+	writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RAC, &info->regs->rw.mode);
 	restore_flags(flags);
 }
 
@@ -1056,7 +1084,7 @@
 
 	save_flags(flags); cli();
 	info->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);
-	info->regs->w.imr1 = info->interrupt_mask1;
+	writeb(info->interrupt_mask1, &info->regs->w.imr1);
 	sab82532_start_tx(info);
 	restore_flags(flags);
 }
@@ -1108,7 +1136,7 @@
 
 	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
 		info->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);
-		info->regs->w.imr1 = info->interrupt_mask1;
+		writeb(info->interrupt_mask1, &info->regs->w.imr1);
 		sab82532_start_tx(info);
 	}
 
@@ -1167,7 +1195,7 @@
 
 	save_flags(flags); cli();
 	sab82532_tec_wait(info);
-	info->regs->w.tic = ch;
+	writeb(ch, &info->regs->w.tic);
 	restore_flags(flags);
 }
 
@@ -1196,7 +1224,7 @@
 		sab82532_send_xchar(tty, STOP_CHAR(tty));
 #if 0
 	if (tty->termios->c_cflag & CRTSCTS)
-		info->regs->rw.mode |= SAB82532_MODE_RTS;
+		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
 #endif
 }
 
@@ -1222,7 +1250,7 @@
 
 #if 0
 	if (tty->termios->c_cflag & CRTSCTS)
-		info->regs->rw.mode &= ~(SAB82532_MODE_RTS);
+		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode);
 #endif
 }
 
@@ -1286,13 +1314,13 @@
 {
 	unsigned int result;
 
-	result =  ((info->regs->r.mode & SAB82532_MODE_RTS) ? 
-		    ((info->regs->r.mode & SAB82532_MODE_FRTS) ? 0 : TIOCM_RTS)
+	result =  ((readb(&info->regs->r.mode) & SAB82532_MODE_RTS) ? 
+		    ((readb(&info->regs->r.mode) & SAB82532_MODE_FRTS) ? 0 : TIOCM_RTS)
 							    : TIOCM_RTS)
-		| ((info->regs->r.pvr & info->pvr_dtr_bit) ? 0 : TIOCM_DTR)
-		| ((info->regs->r.vstr & SAB82532_VSTR_CD) ? 0 : TIOCM_CAR)
-		| ((info->regs->r.pvr & info->pvr_dsr_bit) ? 0 : TIOCM_DSR)
-		| ((info->regs->r.star & SAB82532_STAR_CTS) ? TIOCM_CTS : 0);
+		| ((readb(&info->regs->r.pvr) & info->pvr_dtr_bit) ? 0 : TIOCM_DTR)
+		| ((readb(&info->regs->r.vstr) & SAB82532_VSTR_CD) ? 0 : TIOCM_CAR)
+		| ((readb(&info->regs->r.pvr) & info->pvr_dsr_bit) ? 0 : TIOCM_DSR)
+		| ((readb(&info->regs->r.star) & SAB82532_STAR_CTS) ? TIOCM_CTS : 0);
 	return put_user(result,value);
 }
 
@@ -1308,34 +1336,34 @@
 	switch (cmd) {
 	case TIOCMBIS: 
 		if (arg & TIOCM_RTS) {
-			info->regs->rw.mode &= ~(SAB82532_MODE_FRTS);
-			info->regs->rw.mode |= SAB82532_MODE_RTS;
+			writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode);
+			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
 		}
 		if (arg & TIOCM_DTR) {
-			info->regs->rw.pvr &= ~(info->pvr_dtr_bit);
+			writeb(readb(&info->regs->rw.pvr) & ~(info->pvr_dtr_bit), &info->regs->rw.pvr);
 		}
 		break;
 	case TIOCMBIC:
 		if (arg & TIOCM_RTS) {
-			info->regs->rw.mode |= SAB82532_MODE_FRTS;
-			info->regs->rw.mode |= SAB82532_MODE_RTS;
+			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);
+			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
 		}
 		if (arg & TIOCM_DTR) {
-			info->regs->rw.pvr |= info->pvr_dtr_bit;
+			writeb(readb(&info->regs->rw.pvr) | info->pvr_dtr_bit, &info->regs->rw.pvr);
 		}
 		break;
 	case TIOCMSET:
 		if (arg & TIOCM_RTS) {
-			info->regs->rw.mode &= ~(SAB82532_MODE_FRTS);
-			info->regs->rw.mode |= SAB82532_MODE_RTS;
+			writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode);
+			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
 		} else {
-			info->regs->rw.mode |= SAB82532_MODE_FRTS;
-			info->regs->rw.mode |= SAB82532_MODE_RTS;
+			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);
+			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
 		}
 		if (arg & TIOCM_DTR) {
-			info->regs->rw.pvr &= ~(info->pvr_dtr_bit);
+			writeb(readb(&info->regs->rw.pvr) & ~(info->pvr_dtr_bit), &info->regs->rw.pvr);
 		} else {
-			info->regs->rw.pvr |= info->pvr_dtr_bit;
+			writeb(readb(&info->regs->rw.pvr) | info->pvr_dtr_bit, &info->regs->rw.pvr);
 		}
 		break;
 	default:
@@ -1363,9 +1391,9 @@
 #endif
 	save_flags(flags); cli();
 	if (break_state == -1)
-		info->regs->rw.dafo |= SAB82532_DAFO_XBRK;
+		writeb(readb(&info->regs->rw.dafo) | SAB82532_DAFO_XBRK, &info->regs->rw.dafo);
 	else
-		info->regs->rw.dafo &= ~(SAB82532_DAFO_XBRK);
+		writeb(readb(&info->regs->rw.dafo) & ~(SAB82532_DAFO_XBRK), &info->regs->rw.dafo);
 	restore_flags(flags);
 }
 
@@ -1496,19 +1524,19 @@
 	/* Handle transition to B0 status */
 	if ((old_termios->c_cflag & CBAUD) &&
 	    !(tty->termios->c_cflag & CBAUD)) {
-		info->regs->w.mode |= SAB82532_MODE_FRTS;
-		info->regs->w.mode |= SAB82532_MODE_RTS;
-		info->regs->w.pvr |= info->pvr_dtr_bit;
+		writeb(readb(&info->regs->w.mode) | SAB82532_MODE_FRTS, &info->regs->w.mode);
+		writeb(readb(&info->regs->w.mode) | SAB82532_MODE_RTS, &info->regs->w.mode);
+		writeb(readb(&info->regs->w.pvr) | info->pvr_dtr_bit, &info->regs->w.pvr);
 	}
 	
 	/* Handle transition away from B0 status */
 	if (!(old_termios->c_cflag & CBAUD) &&
 	    (tty->termios->c_cflag & CBAUD)) {
-		info->regs->w.pvr &= ~(info->pvr_dtr_bit);
+		writeb(readb(&info->regs->w.pvr) & ~(info->pvr_dtr_bit), &info->regs->w.pvr);
 		if (!tty->hw_stopped ||
 		    !(tty->termios->c_cflag & CRTSCTS)) {
-			info->regs->w.mode &= ~(SAB82532_MODE_FRTS);
-			info->regs->w.mode |= SAB82532_MODE_RTS;
+			writeb(readb(&info->regs->w.mode) & ~(SAB82532_MODE_FRTS), &info->regs->w.mode);
+			writeb(readb(&info->regs->w.mode) | SAB82532_MODE_RTS, &info->regs->w.mode);
 		}
 	}
 	
@@ -1606,9 +1634,9 @@
 	 * the receiver.
 	 */
 	info->interrupt_mask0 |= SAB82532_IMR0_TCD;
-	info->regs->w.imr0 = info->interrupt_mask0;
+	writeb(info->interrupt_mask0, &info->regs->w.imr0);
 #if 0
-	info->regs->rw.mode &= ~(SAB82532_MODE_RAC);
+	writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RAC), &info->regs->rw.mode);
 #endif
 	if (info->flags & ASYNC_INITIALIZED) {
 		/*
@@ -1797,12 +1825,12 @@
 		cli();
 		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
 		    (tty->termios->c_cflag & CBAUD)) {
-			info->regs->rw.pvr &= ~(info->pvr_dtr_bit);
-			info->regs->rw.mode |= SAB82532_MODE_FRTS;
-			info->regs->rw.mode &= ~(SAB82532_MODE_RTS);
+			writeb(readb(&info->regs->rw.pvr) & ~(info->pvr_dtr_bit), &info->regs->rw.pvr);
+			writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);
+			writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode);
 		}
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ASYNC_INITIALIZED)) {
 #ifdef SERIAL_DO_RESTART
@@ -1817,7 +1845,7 @@
 		}
 		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
 		    !(info->flags & ASYNC_CLOSING) &&
-		    (do_clocal || !(info->regs->r.vstr & SAB82532_VSTR_CD)))
+		    (do_clocal || !(readb(&info->regs->r.vstr) & SAB82532_VSTR_CD)))
 			break;
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
@@ -1825,7 +1853,7 @@
 		}
 #ifdef SERIAL_DEBUG_OPEN
 		printk("block_til_ready blocking: ttyS%d, count = %d, flags = %x, clocal = %d, vstr = %02x\n",
-		       info->line, info->count, info->flags, do_clocal, info->regs->r.vstr);
+		       info->line, info->count, info->flags, do_clocal, readb(&info->regs->r.vstr));
 #endif
 		schedule();
 	}
@@ -1995,19 +2023,19 @@
 	stat_buf[0] = 0;
 	stat_buf[1] = 0;
 	save_flags(flags); cli();
-	if (info->regs->r.mode & SAB82532_MODE_RTS) {
-		if (!(info->regs->r.mode & SAB82532_MODE_FRTS))
+	if (readb(&info->regs->r.mode) & SAB82532_MODE_RTS) {
+		if (!(readb(&info->regs->r.mode) & SAB82532_MODE_FRTS))
 			strcat(stat_buf, "|RTS");
 	} else {
 		strcat(stat_buf, "|RTS");
 	}
-	if (info->regs->r.star & SAB82532_STAR_CTS)
+	if (readb(&info->regs->r.star) & SAB82532_STAR_CTS)
 		strcat(stat_buf, "|CTS");
-	if (!(info->regs->r.pvr & info->pvr_dtr_bit))
+	if (!(readb(&info->regs->r.pvr) & info->pvr_dtr_bit))
 		strcat(stat_buf, "|DTR");
-	if (!(info->regs->r.pvr & info->pvr_dsr_bit))
+	if (!(readb(&info->regs->r.pvr) & info->pvr_dsr_bit))
 		strcat(stat_buf, "|DSR");
-	if (!(info->regs->r.vstr & SAB82532_VSTR_CD))
+	if (!(readb(&info->regs->r.vstr) & SAB82532_VSTR_CD))
 		strcat(stat_buf, "|CD");
 	restore_flags(flags);
 
@@ -2065,7 +2093,7 @@
  * sab82532_init() is called at boot-time to initialize the serial driver.
  * ---------------------------------------------------------------------
  */
-__initfunc(static int get_sab82532(unsigned long *memory_start))
+static int __init get_sab82532(unsigned long *memory_start)
 {
 	struct linux_ebus *ebus;
 	struct linux_ebus_device *edev = 0;
@@ -2083,7 +2111,7 @@
 	if (!edev)
 		return -ENODEV;
 
-	regs = edev->base_address[0];
+	regs = edev->resource[0].start;
 	offset = sizeof(union sab82532_async_regs);
 
 	for (i = 0; i < 2; i++) {
@@ -2107,16 +2135,7 @@
 		sab->xmit_fifo_size = 32;
 		sab->recv_fifo_size = 32;
 
-		if (check_region((unsigned long)sab->regs,
-				 sizeof(union sab82532_async_regs))) {
-			kfree(sab);
-			continue;
-		}
-		request_region((unsigned long)sab->regs,
-			       sizeof(union sab82532_async_regs),
-			       "serial(sab82532)");
-
-		sab->regs->w.ipc = SAB82532_IPC_IC_ACT_LOW;
+		writeb(SAB82532_IPC_IC_ACT_LOW, &sab->regs->w.ipc);
 
 		sab->next = sab82532_chain;
 		sab82532_chain = sab;
@@ -2126,16 +2145,15 @@
 	return 0;
 }
 
-__initfunc(static void
-sab82532_kgdb_hook(int line))
+static void __init sab82532_kgdb_hook(int line)
 {
 	prom_printf("sab82532: kgdb support is not implemented, yet\n");
 	prom_halt();
 }
 
-__initfunc(static inline void show_serial_version(void))
+static inline void __init show_serial_version(void)
 {
-	char *revision = "$Revision: 1.32 $";
+	char *revision = "$Revision: 1.34 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2148,7 +2166,7 @@
 /*
  * The serial driver boot-time initialization code!
  */
-__initfunc(int sab82532_init(void))
+int __init sab82532_init(void)
 {
 	struct sab82532 *info;
 	int i;
@@ -2220,9 +2238,9 @@
 	for (info = sab82532_chain, i = 0; info; info = info->next, i++) {
 		info->magic = SERIAL_MAGIC;
 
-		info->type = info->regs->r.vstr & 0x0f;
-		info->regs->w.pcr = ~((1 << 1) | (1 << 2) | (1 << 4));
-		info->regs->w.pim = 0xff;
+		info->type = readb(&info->regs->r.vstr) & 0x0f;
+		writeb(~((1 << 1) | (1 << 2) | (1 << 4)), &info->regs->w.pcr);
+		writeb(0xff, &info->regs->w.pim);
 		if (info->line == 0) {
 			info->pvr_dsr_bit = (1 << 0);
 			info->pvr_dtr_bit = (1 << 1);
@@ -2230,9 +2248,9 @@
 			info->pvr_dsr_bit = (1 << 3);
 			info->pvr_dtr_bit = (1 << 2);
 		}
-		info->regs->w.pvr = (1 << 1) | (1 << 2) | (1 << 4);
-		info->regs->rw.mode |= SAB82532_MODE_FRTS;
-		info->regs->rw.mode |= SAB82532_MODE_RTS;
+		writeb((1 << 1) | (1 << 2) | (1 << 4), &info->regs->w.pvr);
+		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);
+		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
 
 		info->custom_divisor = 16;
 		info->close_delay = 5*HZ/10;
@@ -2276,7 +2294,7 @@
 	return 0;
 }
 
-__initfunc(int sab82532_probe(unsigned long *memory_start))
+int __init sab82532_probe(unsigned long *memory_start)
 {
 	int node, enode, snode;
 	char model[32];
@@ -2340,7 +2358,6 @@
 {
 	unsigned long flags;
 	int e1, e2;
-	int i;
 
 	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
 	save_flags(flags);
@@ -2357,12 +2374,6 @@
 		       e2);
 	restore_flags(flags);
 
-	for (i = 0; i < NR_PORTS; i++) {
-		struct sab82532 *info = (struct sab82532 *)sab82532_table[i]->driver_data;
-		if (info->type != PORT_UNKNOWN)
-			release_region((unsigned long)info->regs,
-				       sizeof(union sab82532_async_regs));
-	}
 	if (tmp_buf) {
 		free_page((unsigned long) tmp_buf);
 		tmp_buf = NULL;
@@ -2379,7 +2390,7 @@
 
 	save_flags(flags); cli();
 	sab82532_tec_wait(info);
-	info->regs->w.tic = c;
+	writeb(c, &info->regs->w.tic);
 	restore_flags(flags);
 }
 
@@ -2445,12 +2456,12 @@
 	 */
 	info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
 				SAB82532_IMR0_PLLA | SAB82532_IMR0_CDSC;
-	info->regs->w.imr0 = info->interrupt_mask0;
+	writeb(info->interrupt_mask0, &info->regs->w.imr0);
 	info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS |
 				SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN |
 				SAB82532_IMR1_CSC | SAB82532_IMR1_XON |
 				SAB82532_IMR1_XPR;
-	info->regs->w.imr1 = info->interrupt_mask1;
+	writeb(info->interrupt_mask1, &info->regs->w.imr1);
 
 	printk("Console: ttyS%d (SAB82532)\n", info->line);
 
@@ -2524,24 +2535,24 @@
 		info->flags |= ASYNC_CHECK_CD;
 
 	save_flags(flags); cli();
-	if (info->regs->r.star & SAB82532_STAR_CEC)
+	if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
 		udelay(1);
 	sab82532_tec_wait(info);
-	info->regs->w.dafo = dafo;
-	info->regs->w.bgr = ebrg & 0xff;
-	info->regs->rw.ccr2 &= ~(0xc0);
-	info->regs->rw.ccr2 |= (ebrg >> 2) & 0xc0;
+	writeb(dafo, &info->regs->w.dafo);
+	writeb(ebrg & 0xff, &info->regs->w.bgr);
+	writeb(readb(&info->regs->rw.ccr2) & ~(0xc0), &info->regs->rw.ccr2);
+	writeb(readb(&info->regs->rw.ccr2) | ((ebrg >> 2) & 0xc0), &info->regs->rw.ccr2);
 	if (info->flags & ASYNC_CTS_FLOW) {
-		info->regs->rw.mode &= ~(SAB82532_MODE_RTS);
-		info->regs->rw.mode |= SAB82532_MODE_FRTS;
-		info->regs->rw.mode &= ~(SAB82532_MODE_FCTS);
+		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode);
+		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FRTS, &info->regs->rw.mode);
+		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FCTS), &info->regs->rw.mode);
 	} else {
-		info->regs->rw.mode |= SAB82532_MODE_RTS;
-		info->regs->rw.mode &= ~(SAB82532_MODE_FRTS);
-		info->regs->rw.mode |= SAB82532_MODE_FCTS;
+		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
+		writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_FRTS), &info->regs->rw.mode);
+		writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_FCTS, &info->regs->rw.mode);
 	}
-	info->regs->rw.pvr &= ~(info->pvr_dtr_bit);
-	info->regs->rw.mode |= SAB82532_MODE_RAC;
+	writeb(~(info->pvr_dtr_bit), &info->regs->rw.pvr);
+	writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RAC, &info->regs->rw.mode);
 	restore_flags(flags);
 
 	return 0;
@@ -2561,7 +2572,7 @@
 	NULL
 };
 
-__initfunc(int sab82532_console_init(void))
+int __init sab82532_console_init(void)
 {
 	extern int con_is_present(void);
 
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c
--- v2.3.15/linux/drivers/sbus/char/su.c	Sun Jul  4 09:53:12 1999
+++ linux/drivers/sbus/char/su.c	Tue Aug 31 11:30:48 1999
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.22 1999/07/03 08:57:43 davem Exp $
+/* $Id: su.c,v 1.25 1999/08/31 06:58:20 davem Exp $
  * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -1965,7 +1965,7 @@
 				   serial_inp(info, UART_MCR) |
 				   (UART_MCR_DTR | UART_MCR_RTS));
 		restore_flags(flags);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ASYNC_INITIALIZED)) {
 #ifdef SERIAL_DO_RESTART
@@ -2212,9 +2212,9 @@
  * number, and identifies which options were configured into this
  * driver.
  */
-__initfunc(static __inline__ void show_su_version(void))
+static __inline__ void __init show_su_version(void)
 {
-	char *revision = "$Revision: 1.22 $";
+	char *revision = "$Revision: 1.25 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2251,11 +2251,7 @@
 	for_each_ebus(ebus) {
 		for_each_ebusdev(dev, ebus) {
 			if (dev->prom_node == info->port_node) {
-				info->port = dev->base_address[0];
-#ifdef __sparc_v9__
-				if (check_region(info->port, 8))
-					return;
-#endif
+				info->port = dev->resource[0].start;
 				info->irq = dev->irqs[0];
 				goto ebus_done;
 			}
@@ -2400,10 +2396,6 @@
 
 	sprintf(info->name, "su(%s)", su_typev[info->port_type]);
 
-#ifdef __sparc_v9__
-	request_region(info->port, 8, info->name);
-#endif
-
 	/*
 	 * Reset the UART.
 	 */
@@ -2418,7 +2410,7 @@
 /*
  * The serial driver boot-time initialization code!
  */
-__initfunc(int su_serial_init(void))
+int __init su_serial_init(void)
 {
 	int i;
 	struct su_struct *info;
@@ -2516,7 +2508,7 @@
 	return 0;
 }
 
-__initfunc(int su_kbd_ms_init(void))
+int __init su_kbd_ms_init(void)
 {
 	int i;
 	struct su_struct *info;
@@ -2541,7 +2533,7 @@
 		if (info->type == PORT_UNKNOWN)
 			continue;
 
-		printk(KERN_INFO "%s at %16lx (irq = %s) is a %s\n",
+		printk(KERN_INFO "%s at 0x%lx (irq = %s) is a %s\n",
 		       info->name, info->port, __irq_itoa(info->irq),
 		       uart_config[info->type].name);
 
@@ -2559,7 +2551,7 @@
  * of device tree. 'su' may be found under obio, ebus, isa and pci.
  * We walk over the tree and find them wherever PROM hides them.
  */
-__initfunc(void su_probe_any(struct su_probe_scan *t, int sunode))
+void __init su_probe_any(struct su_probe_scan *t, int sunode)
 {
 	struct su_struct *info;
 	int len;
@@ -2590,7 +2582,7 @@
 	}
 }
 
-__initfunc(int su_probe (unsigned long *memory_start))
+int __init su_probe (unsigned long *memory_start)
 {
 	int node;
 	int len;
@@ -2792,7 +2784,7 @@
  *	- initialize the serial port
  *	Return non-zero if we didn't find a serial port.
  */
-__initfunc(static int serial_console_setup(struct console *co, char *options))
+static int __init serial_console_setup(struct console *co, char *options)
 {
 	struct su_struct *info;
 	unsigned cval;
@@ -2915,7 +2907,7 @@
 /*
  *	Register console.
  */
-__initfunc(int su_serial_console_init(void))
+int __init su_serial_console_init(void)
 {
 	extern int con_is_present(void);
 
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c
--- v2.3.15/linux/drivers/sbus/char/sunkbd.c	Mon Aug  2 22:07:16 1999
+++ linux/drivers/sbus/char/sunkbd.c	Tue Aug 31 11:25:33 1999
@@ -1212,7 +1212,7 @@
 
 extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);
 
-__initfunc(int sun_kbd_init(void))
+int __init sun_kbd_init(void)
 {
 	int i, opt_node;
 	struct kbd_struct kbd0;
@@ -1502,7 +1502,7 @@
 	NULL,			/* revalidate */
 };
 
-__initfunc(void keyboard_zsinit(void (*put_char)(unsigned char)))
+void __init keyboard_zsinit(void (*put_char)(unsigned char))
 {
 	int timeout = 0;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/sunmouse.c linux/drivers/sbus/char/sunmouse.c
--- v2.3.15/linux/drivers/sbus/char/sunmouse.c	Mon Aug  2 22:07:16 1999
+++ linux/drivers/sbus/char/sunmouse.c	Tue Aug 31 11:25:33 1999
@@ -69,7 +69,7 @@
 	unsigned char prev_state;      /* Previous button state */
 	int delta_x;                   /* Current delta-x */
 	int delta_y;                   /* Current delta-y */
-	int present;
+	int present;                   
 	int ready;		       /* set if there if data is available */
 	int active;		       /* set if device is open */
         int vuid_mode;	               /* VUID_NATIVE or VUID_FIRM_EVENT */
@@ -170,11 +170,16 @@
 	static int ctr = 0;
 
 	if(wait_for_synchron) {
-		if((c < 0x80) || (c > 0x87))
+		if((c & ~0x0f) != 0x80)
 			mouse_bogon_bytes++;
 		else {
-			ctr = 0;
-			wait_for_synchron = 0;
+		        if (c & 8) {
+				ctr = 2;
+				wait_for_synchron = 0;
+			} else {
+				ctr = 0;
+				wait_for_synchron = 0;
+			}
 		}
 	} else {
 		ctr++;
@@ -212,6 +217,11 @@
 	mouse_baud_detection(byte);
 
 	if (!gen_events){
+		if (((byte & ~0x0f) == 0x80) && (byte & 0x8)) {
+			/* Push dummy 4th and 5th byte for last txn */
+			push_char(0x0);
+			push_char(0x0);
+		}
 		push_char (byte);
 		return;
 	}
@@ -220,7 +230,7 @@
 	 * we are starting at byte zero in the transaction
 	 * protocol.
 	 */
-	if(byte >= 0x80 && byte <= 0x87)
+	if((byte & ~0x0f) == 0x80) 
 		sunmouse.byte = 0;
 
 	mvalue = (signed char) byte;
@@ -234,6 +244,12 @@
 		       ((sunmouse.button_state & 0x2) ? "DOWN" : "UP"),
 		       ((sunmouse.button_state & 0x1) ? "DOWN" : "UP"));
 #endif
+		/* To deal with the Sparcbook 3 */
+		if (byte & 0x8) {
+			sunmouse.byte += 2;
+			sunmouse.delta_y = 0;
+			sunmouse.delta_x = 0;
+		}
 		sunmouse.byte++;
 		return;
 	case 1:
@@ -492,7 +508,7 @@
 	SUN_MOUSE_MINOR, "sunmouse", &sun_mouse_fops
 };
 
-__initfunc(int sun_mouse_init(void))
+int __init sun_mouse_init(void)
 {
 	if (!sunmouse.present)
 		return -ENODEV;
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c
--- v2.3.15/linux/drivers/sbus/char/sunserial.c	Mon Mar 15 16:11:30 1999
+++ linux/drivers/sbus/char/sunserial.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: sunserial.c,v 1.68 1998/12/09 18:53:51 davem Exp $
+/* $Id: sunserial.c,v 1.69 1999/08/31 06:58:29 davem Exp $
  * serial.c: Serial port driver infrastructure for the Sparc.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -20,13 +20,12 @@
 
 int serial_console;
 
-__initfunc(int con_is_present(void))
+int __init con_is_present(void)
 {
 	return serial_console ? 0 : 1;
 }
 
-__initfunc(static void
-nop_rs_kgdb_hook(int channel))
+static void __init nop_rs_kgdb_hook(int channel)
 {
 	printk("Oops: %s called\n", __FUNCTION__);
 }
@@ -63,13 +62,12 @@
 	return err;
 }
 
-__initfunc(void
-rs_kgdb_hook(int channel))
+void __init rs_kgdb_hook(int channel)
 {
 	rs_ops.rs_kgdb_hook(channel);
 }
 
-__initfunc(long serial_console_init(long kmem_start, long kmem_end))
+long __init serial_console_init(long kmem_start, long kmem_end)
 {
 	return kmem_start;
 }
@@ -352,8 +350,7 @@
 extern int ps2kbd_probe(unsigned long *);
 #endif
 
-__initfunc(unsigned long
-sun_serial_setup(unsigned long memory_start))
+unsigned long __init sun_serial_setup(unsigned long memory_start)
 {
 	int ret = 1;
 	
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c
--- v2.3.15/linux/drivers/sbus/char/zs.c	Mon Aug  2 22:07:16 1999
+++ linux/drivers/sbus/char/zs.c	Tue Aug 31 11:30:48 1999
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.43 1999/07/17 06:03:58 zaitcev Exp $
+/* $Id: zs.c,v 1.44 1999/08/31 06:58:32 davem Exp $
  * zs.c: Zilog serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1711,7 +1711,7 @@
 		if (!(info->flags & ZILOG_CALLOUT_ACTIVE))
 			zs_rtsdtr(info, 1);
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ZILOG_INITIALIZED)) {
 #ifdef SERIAL_DEBUG_OPEN
@@ -1844,7 +1844,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.43 $";
+	char *revision = "$Revision: 1.44 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -1862,8 +1862,7 @@
  *       we have a special version for sun4u.
  */
 #ifdef __sparc_v9__
-__initfunc(static struct sun_zslayout *
-get_zs(int chip))
+static struct sun_zslayout * __init get_zs(int chip)
 {
 	unsigned int vaddr[2] = { 0, 0 };
 	unsigned long mapped_addr = 0;
@@ -1971,8 +1970,7 @@
 		return (struct sun_zslayout *) (unsigned long) vaddr[0];
 }
 #else /* !(__sparc_v9__) */
-__initfunc(static struct sun_zslayout *
-get_zs(int chip))
+static struct sun_zslayout * __init get_zs(int chip)
 {
 	struct linux_prom_irqs tmp_irq[2];
 	unsigned int paddr = 0;
@@ -2112,7 +2110,7 @@
 	write_zsreg(zs_soft[channel].zs_channel, R13, ((brg >> 8) & 0xff));
 }
 
-__initfunc(int zs_probe (unsigned long *memory_start))
+int __init zs_probe (unsigned long *memory_start)
 {
 	char *p;
 	int node;
@@ -2265,7 +2263,7 @@
 	restore_flags(flags);
 }
 
-__initfunc(int zs_init(void))
+int __init zs_init(void)
 {
 	int channel, brg, i;
 	unsigned long flags;
@@ -2534,8 +2532,7 @@
  * for /dev/ttyb which is determined in setup_arch() from the
  * boot command line flags.
  */
-__initfunc(static void
-zs_kgdb_hook(int tty_num))
+static void __init zs_kgdb_hook(int tty_num)
 {
 	int chip = 0;
 
@@ -2647,8 +2644,7 @@
 	return MKDEV(TTY_MAJOR, 64 + con->index);
 }
 
-__initfunc(static int
-zs_console_setup(struct console *con, char *options))
+static int __init zs_console_setup(struct console *con, char *options)
 {
 	struct sun_serial *info;
 	int i, brg, baud;
@@ -2729,8 +2725,7 @@
 	NULL
 };
 
-__initfunc(static int
-zs_console_init(void))
+static int __init zs_console_init(void)
 {
 	extern int con_is_present(void);
 
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/dvma.c linux/drivers/sbus/dvma.c
--- v2.3.15/linux/drivers/sbus/dvma.c	Tue Jun  1 23:25:48 1999
+++ linux/drivers/sbus/dvma.c	Tue Aug 31 11:25:33 1999
@@ -29,8 +29,7 @@
 	return;
 }
 
-__initfunc(void
-init_one_dvma(struct Linux_SBus_DMA *dma, int num_dma))
+void __init init_one_dvma(struct Linux_SBus_DMA *dma, int num_dma)
 {
 	printk("dma%d: ", num_dma);
 	
@@ -75,8 +74,7 @@
 }
 
 /* Probe this SBus DMA module(s) */
-__initfunc(void
-dvma_init(struct linux_sbus *sbus))
+void __init dvma_init(struct linux_sbus *sbus)
 {
 	struct linux_sbus_device *this_dev;
 	struct Linux_SBus_DMA *dma;
@@ -133,7 +131,7 @@
 
 #include <asm/sun4paddr.h>
 
-__initfunc(void sun4_dvma_init(void))
+void __init sun4_dvma_init(void)
 {
 	struct Linux_SBus_DMA *dma;
 	struct Linux_SBus_DMA *dchain;
diff -u --recursive --new-file v2.3.15/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c
--- v2.3.15/linux/drivers/sbus/sbus.c	Mon Aug  2 22:07:16 1999
+++ linux/drivers/sbus/sbus.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.78 1999/07/23 02:00:27 davem Exp $
+/* $Id: sbus.c,v 1.79 1999/08/31 06:57:40 davem Exp $
  * sbus.c:  SBus support routines.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -40,8 +40,7 @@
 
 /* #define DEBUG_FILL */
 
-__initfunc(static void
-fill_sbus_device(int nd, struct linux_sbus_device *sbus_dev))
+static void __init fill_sbus_device(int nd, struct linux_sbus_device *sbus_dev)
 {
 	int grrr, len;
 	unsigned long dev_base_addr, base;
@@ -210,9 +209,9 @@
 extern int aurora_init(void);
 #endif
 
-__initfunc(static void
-sbus_do_child_siblings(int start_node, struct linux_sbus_device *child,
-		       struct linux_sbus *sbus))
+static void __init sbus_do_child_siblings(int start_node,
+					  struct linux_sbus_device *child,
+					  struct linux_sbus *sbus)
 {
 	struct linux_sbus_device *this_dev = child;
 	int this_node = start_node;
@@ -240,7 +239,7 @@
 	}
 }
 
-__initfunc(void sbus_init(void))
+void __init sbus_init(void)
 {
 	register int nd, this_sbus, sbus_devs, topnd, iommund;
 	unsigned int sbus_clock;
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/ChangeLog.serverraid linux/drivers/scsi/ChangeLog.serverraid
--- v2.3.15/linux/drivers/scsi/ChangeLog.serverraid	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/ChangeLog.serverraid	Mon Aug 30 10:43:25 1999
@@ -0,0 +1,25 @@
+Change Log
+~~~~~~~~~~
+
+	1.00.00 - Initial Public Release
+		- Functionally equivalent to 0.99.05
+
+        0.99.05 - Fix an oops on certain passthru commands
+
+	0.99.04 - Fix race condition in the passthru mechanism
+                  -- this required the interface to the utilities to change
+		- Fix error recovery code
+
+	0.99.03 - Make interrupt routine handle all completed request on the
+		  adapter not just the first one
+		- Make sure passthru commands get woken up if we run out of
+		  SCBs
+		- Send all of the commands on the queue at once rather than
+		  one at a time since the card will support it.
+
+	0.99.02 - Added some additional debug statements to print out
+                  errors if an error occurs while trying to read/write
+                  to a logical drive (IPS_DEBUG).
+
+                  Fixed read/write errors when the adapter is using an
+                  8K stripe size.
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v2.3.15/linux/drivers/scsi/Config.in	Thu Aug 26 13:05:38 1999
+++ linux/drivers/scsi/Config.in	Mon Aug 30 10:43:25 1999
@@ -30,6 +30,7 @@
     bool '   Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS N
     int  '   Delay in seconds after SCSI bus reset' CONFIG_AIC7XXX_RESET_DELAY 5
 fi
+dep_tristate 'IBM ServeRAID support' CONFIG_SCSI_IPS $CONFIG_SCSI
 dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
 dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI
 dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.3.15/linux/drivers/scsi/Makefile	Wed Aug 18 10:00:52 1999
+++ linux/drivers/scsi/Makefile	Mon Aug 30 10:43:25 1999
@@ -370,6 +370,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_IPS),y)
+L_OBJS += ips.o
+else
+  ifeq ($(CONFIG_SCSI_IPS),m)
+  M_OBJS += ips.o
+  endif
+endif
+
 ifeq ($(CONFIG_SCSI_DC390T),y)
 L_OBJS += tmscsim.o
 else
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c
--- v2.3.15/linux/drivers/scsi/advansys.c	Thu Aug  5 15:07:42 1999
+++ linux/drivers/scsi/advansys.c	Thu Aug 26 14:02:45 1999
@@ -3203,11 +3203,9 @@
  * are not used when the driver is built as a module, cf. linux/init.h.
  */
 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,23)
-#define ASC_INITFUNC(func)      func
 #define ASC_INITDATA
 #define ASC_INIT
 #else /* version >= v2.1.23 */
-#define ASC_INITFUNC(func)      __initfunc(func)
 #define ASC_INITDATA            __initdata
 #define ASC_INIT                __init
 #endif /* version >= v2.1.23 */
@@ -4168,10 +4166,8 @@
  * it must not call SCSI mid-level functions including scsi_malloc()
  * and scsi_free().
  */
-ASC_INITFUNC(
-int
+int ASC_INIT
 advansys_detect(Scsi_Host_Template *tpnt)
-)
 {
     static int          detect_called = ASC_FALSE;
     int                 iop;
@@ -6192,10 +6188,8 @@
  * ints[2] - second argument
  * ...
  */
-ASC_INITFUNC(
-void
+void ASC_INIT
 advansys_setup(char *str, int *ints)
-)
 {
     int    i;
 
@@ -7454,10 +7448,8 @@
 /*
  * Search for an AdvanSys PCI device in the PCI configuration space.
  */
-ASC_INITFUNC(
-STATIC int
+STATIC int ASC_INIT
 asc_srch_pci_dev(PCI_DEVICE *pciDevice)
-)
 {
     int                        ret = PCI_DEVICE_NOT_FOUND;
 
@@ -7494,10 +7486,8 @@
 /*
  * Determine the access method to be used for 'pciDevice'.
  */
-ASC_INITFUNC(
-STATIC uchar
+STATIC uchar ASC_INIT
 asc_scan_method(void)
-)
 {
     ushort      data;
     PCI_DATA    pciData;
@@ -7526,10 +7516,8 @@
  *
  * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND.
  */
-ASC_INITFUNC(
-STATIC int
+STATIC int ASC_INIT
 asc_pci_find_dev(PCI_DEVICE *pciDevice)
-)
 {
     PCI_DATA    pciData;
     ushort      vendorid, deviceid;
@@ -7578,10 +7566,8 @@
 /*
  * Read PCI configuration data into 'pciConfig'.
  */
-ASC_INITFUNC(
-STATIC void
+STATIC void ASC_INIT
 asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig)
-)
 {
     PCI_DATA    pciData;
     uchar       counter;
@@ -7610,10 +7596,8 @@
  *
  * The configuration mechanism is checked for the correct access method.
  */
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 asc_get_cfg_word(PCI_DATA *pciData)
-)
 {
     ushort   tmp;
     ulong    address;
@@ -7693,10 +7677,8 @@
  *
  * The configuration mechanism is checked for the correct access method.
  */
-ASC_INITFUNC(
-STATIC uchar
+STATIC uchar ASC_INIT
 asc_get_cfg_byte(PCI_DATA *pciData)
-)
 {
     uchar tmp;
     ulong address;
@@ -7773,10 +7755,8 @@
 /*
  * Write a byte to the PCI configuration space.
  */
-ASC_INITFUNC(
-STATIC void
+STATIC void ASC_INIT
 asc_put_cfg_byte(PCI_DATA *pciData, uchar byte_data)
-)
 {
     ulong tmpl;
     ulong address;
@@ -9366,12 +9346,10 @@
 /*
  * Read a PCI configuration byte.
  */
-ASC_INITFUNC(
-STATIC uchar
+STATIC uchar ASC_INIT
 DvcReadPCIConfigByte(
         ASC_DVC_VAR asc_ptr_type *asc_dvc, 
         ushort offset)
-)
 {
 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
 #ifdef ASC_CONFIG_PCI
@@ -9403,13 +9381,11 @@
 /*
  * Write a PCI configuration byte.
  */
-ASC_INITFUNC(
-STATIC void
+STATIC void ASC_INIT
 DvcWritePCIConfigByte(
         ASC_DVC_VAR asc_ptr_type *asc_dvc, 
         ushort offset, 
         uchar  byte_data)
-)
 {
 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
 #ifdef ASC_CONFIG_PCI
@@ -9436,13 +9412,11 @@
  * Return the BIOS address of the adapter at the specified
  * I/O port and with the specified bus type.
  */
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscGetChipBiosAddress(
         PortAddr iop_base,
         ushort bus_type
 )
-)
 {
     ushort  cfg_lsw ;
     ushort  bios_addr ;
@@ -9519,12 +9493,10 @@
 /*
  * Read a PCI configuration byte.
  */
-ASC_INITFUNC(
-STATIC uchar
+STATIC uchar ASC_INIT
 DvcAdvReadPCIConfigByte(
         ADV_DVC_VAR *asc_dvc, 
         ushort offset)
-)
 {
 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
 #ifdef ASC_CONFIG_PCI
@@ -9556,13 +9528,11 @@
 /*
  * Write a PCI configuration byte.
  */
-ASC_INITFUNC(
-STATIC void
+STATIC void ASC_INIT
 DvcAdvWritePCIConfigByte(
         ADV_DVC_VAR *asc_dvc, 
         ushort offset, 
         uchar  byte_data)
-)
 {
 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
 #ifdef ASC_CONFIG_PCI
@@ -10206,12 +10176,10 @@
  * --- Asc Library Functions
  */
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscGetEisaChipCfg(
                      PortAddr iop_base
 )
-)
 {
     PortAddr            eisa_cfg_iop;
 
@@ -10220,13 +10188,11 @@
     return (inpw(eisa_cfg_iop));
 }
 
-ASC_INITFUNC(
-STATIC uchar
+STATIC uchar ASC_INIT
 AscSetChipScsiID(
                     PortAddr iop_base,
                     uchar new_host_id
 )
-)
 {
     ushort              cfg_lsw;
 
@@ -10240,12 +10206,10 @@
     return (AscGetChipScsiID(iop_base));
 }
 
-ASC_INITFUNC(
-STATIC uchar
+STATIC uchar ASC_INIT
 AscGetChipScsiCtrl(
                       PortAddr iop_base
 )
-)
 {
     uchar               sc;
 
@@ -10255,13 +10219,11 @@
     return (sc);
 }
 
-ASC_INITFUNC(
-STATIC uchar
+STATIC uchar ASC_INIT
 AscGetChipVersion(
                      PortAddr iop_base,
                      ushort bus_type
 )
-)
 {
     if ((bus_type & ASC_IS_EISA) != 0) {
         PortAddr            eisa_iop;
@@ -10274,12 +10236,10 @@
     return (AscGetChipVerNo(iop_base));
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscGetChipBusType(
                      PortAddr iop_base
 )
-)
 {
     ushort              chip_ver;
 
@@ -10309,15 +10269,13 @@
     return (0);
 }
 
-ASC_INITFUNC(
-STATIC ulong
+STATIC ulong ASC_INIT
 AscLoadMicroCode(
                     PortAddr iop_base,
                     ushort s_addr,
                     ushort *mcode_buf,
                     ushort mcode_size
 )
-)
 {
     ulong               chksum;
     ushort              mcode_word_size;
@@ -10335,12 +10293,10 @@
     return (chksum);
 }
 
-ASC_INITFUNC(
-STATIC int
+STATIC int ASC_INIT
 AscFindSignature(
                     PortAddr iop_base
 )
-)
 {
     ushort              sig_word;
 
@@ -10361,13 +10317,11 @@
     ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
 };
 
-ASC_INITFUNC(
-STATIC PortAddr
+STATIC PortAddr ASC_INIT
 AscSearchIOPortAddr(
                        PortAddr iop_beg,
                        ushort bus_type
 )
-)
 {
     if (bus_type & ASC_IS_VL) {
         while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
@@ -10398,12 +10352,10 @@
     return (0);
 }
 
-ASC_INITFUNC(
-STATIC PortAddr
+STATIC PortAddr ASC_INIT
 AscSearchIOPortAddr11(
                          PortAddr s_addr
 )
-)
 {
     int                 i;
     PortAddr            iop_base;
@@ -10429,36 +10381,30 @@
     return (0);
 }
 
-ASC_INITFUNC(
-STATIC void
+STATIC void ASC_INIT
 AscToggleIRQAct(
                    PortAddr iop_base
 )
-)
 {
     AscSetChipStatus(iop_base, CIW_IRQ_ACT);
     AscSetChipStatus(iop_base, 0);
     return;
 }
 
-ASC_INITFUNC(
-STATIC void
+STATIC void ASC_INIT
 AscSetISAPNPWaitForKey(
     void)
-)
 {
     outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
     outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
     return;
 }
 
-ASC_INITFUNC(
-STATIC uchar
+STATIC uchar ASC_INIT
 AscGetChipIRQ(
                  PortAddr iop_base,
                  ushort bus_type
 )
-)
 {
     ushort              cfg_lsw;
     uchar               chip_irq;
@@ -10488,14 +10434,12 @@
     return ((uchar) (chip_irq + ASC_MIN_IRQ_NO));
 }
 
-ASC_INITFUNC(
-STATIC uchar
+STATIC uchar ASC_INIT
 AscSetChipIRQ(
                  PortAddr iop_base,
                  uchar irq_no,
                  ushort bus_type
 )
-)
 {
     ushort              cfg_lsw;
 
@@ -10529,12 +10473,10 @@
     return (0);
 }
 
-ASC_INITFUNC(
-STATIC void
+STATIC void ASC_INIT
 AscEnableIsaDma(
                    uchar dma_channel
 )
-)
 {
     if (dma_channel < 4) {
         outp(0x000B, (ushort) (0xC0 | dma_channel));
@@ -12396,12 +12338,10 @@
     udelay((nano_sec + 999)/1000);
 }
 
-ASC_INITFUNC(
-STATIC ulong
+STATIC ulong ASC_INIT
 AscGetEisaProductID(
                        PortAddr iop_base
 )
-)
 {
     PortAddr            eisa_iop;
     ushort              product_id_high, product_id_low;
@@ -12414,12 +12354,10 @@
     return (product_id);
 }
 
-ASC_INITFUNC(
-STATIC PortAddr
+STATIC PortAddr ASC_INIT
 AscSearchIOPortAddrEISA(
                            PortAddr iop_base
 )
-)
 {
     ulong               eisa_product_id;
 
@@ -12608,12 +12546,10 @@
     return (AscIsChipHalted(iop_base));
 }
 
-ASC_INITFUNC(
-STATIC ulong
+STATIC ulong ASC_INIT
 AscGetMaxDmaCount(
                      ushort bus_type
 )
-)
 {
     if (bus_type & ASC_IS_ISA)
         return (ASC_MAX_ISA_DMA_COUNT);
@@ -12622,12 +12558,10 @@
     return (ASC_MAX_PCI_DMA_COUNT);
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscGetIsaDmaChannel(
                        PortAddr iop_base
 )
-)
 {
     ushort              channel;
 
@@ -12639,13 +12573,11 @@
     return (channel + 4);
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscSetIsaDmaChannel(
                        PortAddr iop_base,
                        ushort dma_channel
 )
-)
 {
     ushort              cfg_lsw;
     uchar               value;
@@ -12663,13 +12595,11 @@
     return (0);
 }
 
-ASC_INITFUNC(
-STATIC uchar
+STATIC uchar ASC_INIT
 AscSetIsaDmaSpeed(
                      PortAddr iop_base,
                      uchar speed_value
 )
-)
 {
     speed_value &= 0x07;
     AscSetBank(iop_base, 1);
@@ -12678,12 +12608,10 @@
     return (AscGetIsaDmaSpeed(iop_base));
 }
 
-ASC_INITFUNC(
-STATIC uchar
+STATIC uchar ASC_INIT
 AscGetIsaDmaSpeed(
                      PortAddr iop_base
 )
-)
 {
     uchar               speed_value;
 
@@ -12694,12 +12622,10 @@
     return (speed_value);
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscReadPCIConfigWord(
     ASC_DVC_VAR asc_ptr_type *asc_dvc,
     ushort pci_config_offset)
-)
 {
     uchar       lsb, msb;
 
@@ -12708,12 +12634,10 @@
     return ((ushort) ((msb << 8) | lsb));
 }
 
-ASC_INITFUNC(
-STATIC ushort 
+STATIC ushort ASC_INIT
 AscInitGetConfig(
         ASC_DVC_VAR asc_ptr_type * asc_dvc
 )
-)
 {
     ushort              warn_code;
     PortAddr            iop_base;
@@ -12793,12 +12717,10 @@
     return(warn_code);
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscInitSetConfig(
                     ASC_DVC_VAR asc_ptr_type * asc_dvc
 )
-)
 {
     ushort              warn_code = 0;
 
@@ -12814,12 +12736,10 @@
     return (warn_code);
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscInitFromAscDvcVar(
                         ASC_DVC_VAR asc_ptr_type * asc_dvc
 )
-)
 {
     PortAddr            iop_base;
     ushort              cfg_msw;
@@ -12877,12 +12797,10 @@
     return (warn_code);
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscInitAsc1000Driver(
                         ASC_DVC_VAR asc_ptr_type * asc_dvc
 )
-)
 {
     ushort              warn_code;
     PortAddr            iop_base;
@@ -12919,12 +12837,10 @@
     return (warn_code);
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscInitAscDvcVar(
                     ASC_DVC_VAR asc_ptr_type * asc_dvc
 )
-)
 {
     int                 i;
     PortAddr            iop_base;
@@ -13034,12 +12950,10 @@
     return (warn_code);
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscInitFromEEP(
                   ASC_DVC_VAR asc_ptr_type * asc_dvc
 )
-)
 {
     ASCEEP_CONFIG       eep_config_buf;
     ASCEEP_CONFIG       *eep_config;
@@ -13189,12 +13103,10 @@
     return (warn_code);
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscInitMicroCodeVar(
                        ASC_DVC_VAR asc_ptr_type * asc_dvc
 )
-)
 {
     int                 i;
     ushort              warn_code;
@@ -13239,12 +13151,10 @@
     return (warn_code);
 }
 
-ASC_INITFUNC(
-STATIC int
+STATIC int ASC_INIT
 AscTestExternalLram(
                        ASC_DVC_VAR asc_ptr_type * asc_dvc
 )
-)
 {
     PortAddr            iop_base;
     ushort              q_addr;
@@ -13266,13 +13176,11 @@
     return (sta);
 }
 
-ASC_INITFUNC(
-STATIC int
+STATIC int ASC_INIT
 AscWriteEEPCmdReg(
                      PortAddr iop_base,
                      uchar cmd_reg
 )
-)
 {
     uchar               read_back;
     int                 retry;
@@ -13291,13 +13199,11 @@
     }
 }
 
-ASC_INITFUNC(
-STATIC int
+STATIC int ASC_INIT
 AscWriteEEPDataReg(
                       PortAddr iop_base,
                       ushort data_reg
 )
-)
 {
     ushort              read_back;
     int                 retry;
@@ -13316,35 +13222,29 @@
     }
 }
 
-ASC_INITFUNC(
-STATIC void
+STATIC void ASC_INIT
 AscWaitEEPRead(
                   void
 )
-)
 {
     DvcSleepMilliSecond(1);
     return;
 }
 
-ASC_INITFUNC(
-STATIC void
+STATIC void ASC_INIT
 AscWaitEEPWrite(
                    void
 )
-)
 {
     DvcSleepMilliSecond(20);
     return;
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscReadEEPWord(
                   PortAddr iop_base,
                   uchar addr
 )
-)
 {
     ushort              read_wval;
     uchar               cmd_reg;
@@ -13359,14 +13259,12 @@
     return (read_wval);
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscWriteEEPWord(
                    PortAddr iop_base,
                    uchar addr,
                    ushort word_val
 )
-)
 {
     ushort              read_wval;
 
@@ -13386,13 +13284,11 @@
     return (read_wval);
 }
 
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AscGetEEPConfig(
                    PortAddr iop_base,
                    ASCEEP_CONFIG * cfg_buf, ushort bus_type
 )
-)
 {
     ushort              wval;
     ushort              sum;
@@ -13427,13 +13323,11 @@
     return (sum);
 }
 
-ASC_INITFUNC(
-STATIC int
+STATIC int ASC_INIT
 AscSetEEPConfigOnce(
                        PortAddr iop_base,
                        ASCEEP_CONFIG * cfg_buf, ushort bus_type
 )
-)
 {
     int                 n_error;
     ushort      *wbuf;
@@ -13484,13 +13378,11 @@
     return (n_error);
 }
 
-ASC_INITFUNC(
-STATIC int
+STATIC int ASC_INIT
 AscSetEEPConfig(
                    PortAddr iop_base,
                    ASCEEP_CONFIG * cfg_buf, ushort bus_type
 )
-)
 {
     int            retry;
     int            n_error;
@@ -14175,10 +14067,8 @@
  * For a non-fatal error return a warning code. If there are no warnings
  * then 0 is returned.
  */
-ASC_INITFUNC(
-int
+int ASC_INIT
 AdvInitGetConfig(ADV_DVC_VAR *asc_dvc)
-)
 {
     ushort      warn_code;
     AdvPortAddr iop_base;
@@ -14285,10 +14175,8 @@
  * For a non-fatal error return a warning code. If there are no warnings
  * then 0 is returned.
  */
-ASC_INITFUNC(
-int
+int ASC_INIT
 AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
-)
 {
     AdvPortAddr iop_base;
     ushort      warn_code;
@@ -14620,10 +14508,8 @@
  *
  * Note: Chip is stopped on entry.
  */
-ASC_INITFUNC(
-STATIC int
+STATIC int ASC_INIT
 AdvInitFromEEP(ADV_DVC_VAR *asc_dvc)
-)
 {
     AdvPortAddr         iop_base;
     ushort              warn_code;
@@ -14786,10 +14672,8 @@
  *
  * Return a checksum based on the EEPROM configuration read.
  */
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AdvGetEEPConfig(AdvPortAddr iop_base, ADVEEP_CONFIG *cfg_buf)
-)
 {
     ushort              wval, chksum;
     ushort              *wbuf;
@@ -14820,10 +14704,8 @@
 /*
  * Read the EEPROM from specified location
  */
-ASC_INITFUNC(
-STATIC ushort
+STATIC ushort ASC_INIT
 AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr)
-)
 {
     AdvWriteWordRegister(iop_base, IOPW_EE_CMD,
         ASC_EEP_CMD_READ | eep_word_addr);
@@ -14834,10 +14716,8 @@
 /*
  * Wait for EEPROM command to complete
  */
-ASC_INITFUNC(
-STATIC void
+STATIC void ASC_INIT
 AdvWaitEEPCmd(AdvPortAddr iop_base)
-)
 {
     int eep_delay_ms;
 
@@ -14859,10 +14739,8 @@
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-ASC_INITFUNC(
-STATIC void
+STATIC void ASC_INIT
 AdvSetEEPConfig(AdvPortAddr iop_base, ADVEEP_CONFIG *cfg_buf)
-)
 {
     ushort       *wbuf;
     ushort       addr, chksum;
@@ -14923,10 +14801,8 @@
  * configuration is read to determine whether SCSI Bus Resets
  * should be performed.
  */
-ASC_INITFUNC(
-STATIC void
+STATIC void ASC_INIT
 AdvResetChip(ADV_DVC_VAR *asc_dvc)
-)
 {
     AdvPortAddr    iop_base;
     ushort         word;
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/atari_NCR5380.c linux/drivers/scsi/atari_NCR5380.c
--- v2.3.15/linux/drivers/scsi/atari_NCR5380.c	Wed Aug 18 10:00:52 1999
+++ linux/drivers/scsi/atari_NCR5380.c	Tue Aug 31 11:23:03 1999
@@ -323,7 +323,7 @@
 static TAG_ALLOC TagAlloc[8][8]; /* 8 targets and 8 LUNs */
 
 
-__initfunc(static void init_tags( void ))
+static void __init init_tags( void )
 {
     int target, lun;
     TAG_ALLOC *ta;
@@ -684,7 +684,7 @@
  * Inputs : instance, pointer to this instance.  Unused.
  */
 
-__initfunc(static void NCR5380_print_options (struct Scsi_Host *instance))
+static void __init NCR5380_print_options (struct Scsi_Host *instance)
 {
     printk(" generic options"
 #ifdef AUTOSENSE 
@@ -848,7 +848,7 @@
  * 
  */
 
-__initfunc(static void NCR5380_init (struct Scsi_Host *instance, int flags))
+static void __init NCR5380_init (struct Scsi_Host *instance, int flags)
 {
     int i;
     SETUP_HOSTDATA(instance);
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c
--- v2.3.15/linux/drivers/scsi/esp.c	Mon Mar 15 16:11:31 1999
+++ linux/drivers/scsi/esp.c	Thu Aug 26 14:30:19 1999
@@ -671,9 +671,9 @@
 	trash = eregs->esp_intrpt;
 }
 
-__initfunc(int detect_one_esp
+int __init 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))
+ struct linux_sbus *sbus, int id, int hme)
 {
 	struct Sparc_ESP *esp, *elink;
 	struct Scsi_Host *esp_host;
@@ -1022,7 +1022,7 @@
 
 #include <asm/sun4paddr.h>
 
-__initfunc(int esp_detect(Scsi_Host_Template *tpnt))
+int __init esp_detect(Scsi_Host_Template *tpnt)
 {
 	static struct linux_sbus_device esp_dev;
 	int esps_in_use = 0;
@@ -1044,7 +1044,7 @@
 
 #else /* !CONFIG_SUN4 */
 
-__initfunc(int esp_detect(Scsi_Host_Template *tpnt))
+int __init esp_detect(Scsi_Host_Template *tpnt)
 {
 	struct linux_sbus *sbus;
 	struct linux_sbus_device *esp_dev, *sbdev_iter;
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/fcal.c linux/drivers/scsi/fcal.c
--- v2.3.15/linux/drivers/scsi/fcal.c	Mon Mar 15 16:11:31 1999
+++ linux/drivers/scsi/fcal.c	Tue Aug 31 11:23:03 1999
@@ -90,7 +90,7 @@
 
 /* Detect all FC Arbitrated Loops attached to the machine.
    fc4 module has done all the work for us... */
-__initfunc(int fcal_detect(Scsi_Host_Template *tpnt))
+int __init fcal_detect(Scsi_Host_Template *tpnt)
 {
 	int nfcals = 0;
 	fc_channel *fc;
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.3.15/linux/drivers/scsi/hosts.c	Thu Aug 26 13:05:39 1999
+++ linux/drivers/scsi/hosts.c	Mon Aug 30 10:43:25 1999
@@ -135,6 +135,10 @@
 #include "aic7xxx.h"
 #endif
 
+#ifdef CONFIG_SCSI_IPS
+#include "ips.h"
+#endif
+
 #ifdef CONFIG_SCSI_BUSLOGIC
 #include "BusLogic.h"
 #endif
@@ -478,6 +482,9 @@
 #endif
 #ifdef CONFIG_SCSI_AIC7XXX
     AIC7XXX,
+#endif
+#ifdef CONFIG_SCSI_IPS
+    IPS,
 #endif
 #ifdef CONFIG_SCSI_FD_MCS
    FD_MCS,
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
--- v2.3.15/linux/drivers/scsi/ide-scsi.c	Tue Jul  6 19:08:33 1999
+++ linux/drivers/scsi/ide-scsi.c	Thu Aug 26 13:44:03 1999
@@ -429,7 +429,8 @@
 	if (drive->using_dma && rq->bh)
 		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 
-	OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE (dma_ok,IDE_FEATURE_REG);
 	OUT_BYTE (bcount >> 8,IDE_BCOUNTH_REG);
 	OUT_BYTE (bcount & 0xff,IDE_BCOUNTL_REG);
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/ips.c linux/drivers/scsi/ips.c
--- v2.3.15/linux/drivers/scsi/ips.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/ips.c	Tue Aug 31 09:33:09 1999
@@ -0,0 +1,3936 @@
+/*****************************************************************************/
+/* ips.c -- driver for the IBM ServeRAID controller                          */
+/*                                                                           */
+/* Written By: Keith Mitchell, IBM Corporation                               */
+/*                                                                           */
+/* Copyright (C) 1999 IBM Corporation                                        */
+/*                                                                           */
+/* This program is free software; you can redistribute it and/or modify      */
+/* it under the terms of the GNU General Public License as published by      */
+/* the Free Software Foundation; either version 2 of the License, or         */
+/* (at your option) any later version.                                       */
+/*                                                                           */
+/* This program is distributed in the hope that it will be useful,           */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
+/* GNU General Public License for more details.                              */
+/*                                                                           */
+/* NO WARRANTY                                                               */
+/* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR        */
+/* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT      */
+/* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,      */
+/* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is    */
+/* solely responsible for determining the appropriateness of using and       */
+/* distributing the Program and assumes all risks associated with its        */
+/* exercise of rights under this Agreement, including but not limited to     */
+/* the risks and costs of program errors, damage to or loss of data,         */
+/* programs or equipment, and unavailability or interruption of operations.  */
+/*                                                                           */
+/* DISCLAIMER OF LIABILITY                                                   */
+/* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY   */
+/* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL        */
+/* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND   */
+/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
+/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
+/* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED  */
+/* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES             */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License         */
+/* along with this program; if not, write to the Free Software               */
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+/*                                                                           */
+/* Bugs/Comments/Suggestions should be mailed to:                            */
+/*      ipslinux@us.ibm.com                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* Change Log                                                                */
+/*                                                                           */
+/* 0.99.02  - Breakup commands that are bigger than 8 * the stripe size      */
+/* 0.99.03  - Make interrupt routine handle all completed request on the     */
+/*            adapter not just the first one                                 */
+/*          - Make sure passthru commands get woken up if we run out of      */
+/*            SCBs                                                           */
+/*          - Send all of the commands on the queue at once rather than      */
+/*            one at a time since the card will support it.                  */
+/* 0.99.04  - Fix race condition in the passthru mechanism -- this required  */
+/*            the interface to the utilities to change                       */
+/*          - Fix error recovery code                                        */
+/* 0.99.05  - Fix an oops when we get certain passthru commands              */
+/* 1.00.00  - Initial Public Release                                         */
+/*            Functionally equivalent to 0.99.05                             */
+/*                                                                           */
+/*****************************************************************************/
+
+/*
+ * Conditional Compilation directives for this driver:
+ *
+ * NO_IPS_RESET         - Don't reset the controller (no matter what)
+ * IPS_DEBUG            - More verbose error messages
+ * IPS_PCI_PROBE_DEBUG  - Print out more detail on the PCI probe
+ *
+ */
+
+#if defined (MODULE)
+   #include <linux/module.h>
+#endif /* MODULE */
+
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <linux/stddef.h>
+#include <linux/version.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+
+#include <linux/blk.h>
+#include <linux/types.h>
+
+#ifndef NO_IPS_CMDLINE
+#include <scsi/sg.h>
+#endif
+
+#include "sd.h"
+#include "scsi.h"
+#include "hosts.h"
+#include "ips.h"
+
+#include <linux/stat.h>
+#include <linux/config.h>
+#include <asm/spinlock.h>
+#include <linux/smp.h>
+
+/*
+ * DRIVER_VER
+ */
+#define IPS_VERSION_HIGH        "1.00"  /* MUST be 4 chars */
+#define IPS_VERSION_LOW         ".00 "  /* MUST be 4 chars */
+
+struct proc_dir_entry proc_scsi_ips = {
+#if !defined(PROC_SCSI_IPS)
+   0,                                /* Use dynamic inode allocation */
+#else
+   PROC_SCSI_IPS,
+#endif
+   3, "ips",
+   S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,93)
+   #include <linux/bios32.h>
+#endif
+
+#if !defined(__i386__)
+   #error "This driver has only been tested on the x86 platform"
+#endif
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,2,0)
+   #error "This driver only works with kernel 2.2.0 and later"
+#endif
+
+#if !defined(NO_IPS_CMDLINE) && ((SG_BIG_BUFF < 8192) || !defined(SG_BIG_BUFF))
+   #error "To use the command-line interface you need to define SG_BIG_BUFF"
+#endif
+
+#if IPS_DEBUG >= 12
+   #define DBG(s)       printk(KERN_NOTICE s "\n"); MDELAY(2*ONE_SEC)
+#elif IPS_DEBUG >= 11
+   #define DBG(s)       printk(KERN_NOTICE s "\n")
+#else
+   #define DBG(s)
+#endif
+
+/*
+ * global variables
+ */
+static const char * ips_name = "ips";
+static struct Scsi_Host * ips_sh[IPS_MAX_ADAPTERS];  /* Array of host controller structures */
+static ips_ha_t * ips_ha[IPS_MAX_ADAPTERS];          /* Array of HA structures */
+static unsigned int ips_num_controllers = 0;
+static int          ips_cmd_timeout = 60;
+static int          ips_reset_timeout = 60 * 5;
+
+#define MAX_ADAPTER_NAME 6
+
+static char ips_adapter_name[][30] = {
+   "ServeRAID",
+   "ServeRAID II",
+   "ServeRAID on motherboard",
+   "ServeRAID on motherboard",
+   "ServeRAID 3H",
+   "ServeRAID 3L"
+};
+
+/*
+ * Function prototypes
+ */
+int ips_detect(Scsi_Host_Template *);
+int ips_release(struct Scsi_Host *);
+int ips_abort(Scsi_Cmnd *);
+int ips_reset(Scsi_Cmnd *, unsigned int);
+int ips_eh_abort(Scsi_Cmnd *);
+int ips_eh_reset(Scsi_Cmnd *);
+int ips_queue(Scsi_Cmnd *, void (*) (Scsi_Cmnd *));
+int ips_biosparam(Disk *, kdev_t, int *);
+const char * ips_info(struct Scsi_Host *);
+void do_ipsintr(int, void *, struct pt_regs *);
+static int ips_hainit(ips_ha_t *);
+static int ips_map_status(ips_scb_t *, ips_stat_t *);
+static int ips_send(ips_ha_t *, ips_scb_t *, scb_callback);
+static int ips_send_wait(ips_ha_t *, ips_scb_t *, int);
+static int ips_send_cmd(ips_ha_t *, ips_scb_t *);
+static int ips_chkstatus(ips_ha_t *);
+static int ips_online(ips_ha_t *, ips_scb_t *);
+static int ips_inquiry(ips_ha_t *, ips_scb_t *);
+static int ips_rdcap(ips_ha_t *, ips_scb_t *);
+static int ips_msense(ips_ha_t *, ips_scb_t *);
+static int ips_reqsen(ips_ha_t *, ips_scb_t *);
+static int ips_allocatescbs(ips_ha_t *);
+static int ips_reset_adapter(ips_ha_t *);
+static int ips_statupd(ips_ha_t *);
+static int ips_issue(ips_ha_t *, ips_scb_t *);
+static int ips_isintr(ips_ha_t *);
+static int ips_wait(ips_ha_t *, int, int);
+static int ips_write_driver_status(ips_ha_t *);
+static int ips_read_adapter_status(ips_ha_t *);
+static int ips_read_subsystem_parameters(ips_ha_t *);
+static int ips_read_config(ips_ha_t *);
+static int ips_clear_adapter(ips_ha_t *);
+static int ips_readwrite_page5(ips_ha_t *, int);
+static void ips_intr(ips_ha_t *);
+static void ips_next(ips_ha_t *);
+static void ipsintr_blocking(ips_ha_t *, struct ips_scb *);
+static void ipsintr_done(ips_ha_t *, struct ips_scb *);
+static void ips_done(ips_ha_t *, ips_scb_t *);
+static void ips_free(ips_ha_t *);
+static void ips_init_scb(ips_ha_t *, ips_scb_t *);
+static void ips_freescb(ips_ha_t *, ips_scb_t *);
+static void ips_statinit(ips_ha_t *);
+static ips_scb_t * ips_getscb(ips_ha_t *);
+static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
+static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *);
+static inline ips_scb_t * ips_removeq_scb_head(ips_scb_queue_t *);
+static inline ips_scb_t * ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
+static inline void ips_putq_wait_head(ips_wait_queue_t *, Scsi_Cmnd *);
+static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
+static inline Scsi_Cmnd * ips_removeq_wait_head(ips_wait_queue_t *);
+static inline Scsi_Cmnd * ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
+
+#ifndef NO_IPS_CMDLINE
+static int ips_is_passthru(Scsi_Cmnd *);
+static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *);
+static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);
+#endif
+
+int  ips_proc_info(char *, char **, off_t, int, int, int);
+static int ips_host_info(ips_ha_t *, char *, off_t, int);
+static void copy_mem_info(INFOSTR *, char *, int);
+static int copy_info(INFOSTR *, char *, ...);
+
+/*--------------------------------------------------------------------------*/
+/* Exported Functions                                                       */
+/*--------------------------------------------------------------------------*/
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_detect                                                 */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Detect and initialize the driver                                       */
+/*                                                                          */
+/****************************************************************************/
+int
+ips_detect(Scsi_Host_Template *SHT) {
+   struct Scsi_Host *sh;
+   ips_ha_t         *ha;
+   u32               io_addr;
+   u16               planer;
+   u8                bus;
+   u8                func;
+   u8                irq;
+   int               index;
+   struct pci_dev   *dev = NULL;
+
+   DBG("ips_detect");
+
+   SHT->proc_info = ips_proc_info;
+   SHT->proc_dir = &proc_scsi_ips;
+
+#if defined(CONFIG_PCI)
+
+   /* initalize number of controllers */
+   ips_num_controllers = 0;
+
+   if (!pci_present())
+      return (0);
+
+   for (index = 0; index < IPS_MAX_ADAPTERS; index++) {
+
+      if (!(dev = pci_find_device(IPS_VENDORID, IPS_DEVICEID, dev)))
+         break;
+
+      /* stuff that we get in dev */
+      irq = dev->irq;
+      bus = dev->bus->number;
+      func = dev->devfn;
+      io_addr = dev->resource[0].start;
+
+      /* get planer status */
+      if (pci_read_config_word(dev, 0x04, &planer)) {
+         printk(KERN_WARNING "(%s%d) can't get planer status.\n",
+                ips_name, index);
+
+         continue;
+      }
+
+      /* check I/O address */
+      if ((dev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
+         continue;
+
+      /* check to see if an onboard planer controller is disabled */
+      if (!(planer & 0x000C)) {
+
+   #ifdef IPS_PCI_PROBE_DEBUG
+         printk(KERN_NOTICE "(%s%d) detect, Onboard ServeRAID disabled by BIOS\n",
+                ips_name, index);
+   #endif
+
+         continue;
+      }
+
+   #ifdef IPS_PCI_PROBE_DEBUG
+      printk(KERN_NOTICE "(%s%d) detect bus %d, func %x, irq %d, io %x\n",
+             ips_name, index, bus, func, irq, io_addr);
+   #endif
+
+      /* found a controller */
+      sh = scsi_register(SHT, sizeof(ips_ha_t));
+
+      if (sh == NULL) {
+         printk(KERN_WARNING "(%s%d) Unable to register controller with SCSI subsystem - skipping controller\n",
+                ips_name, index);
+
+         continue;
+      }
+
+      ha = HA(sh);
+      memset(ha, 0, sizeof(ips_ha_t));
+
+      /* Initialize spin lock */
+      spin_lock_init(&ha->scb_lock);
+      spin_lock_init(&ha->copp_lock);
+
+      ips_sh[ips_num_controllers] = sh;
+      ips_ha[ips_num_controllers] = ha;
+      ips_num_controllers++;
+      ha->active = 1;
+
+      ha->enq = kmalloc(sizeof(ENQCMD), GFP_KERNEL|GFP_DMA);
+
+      if (!ha->enq) {
+         printk(KERN_WARNING "(%s%d) Unable to allocate host inquiry structure - skipping contoller\n",
+                ips_name, index);
+
+         ha->active = 0;
+
+         continue;
+      }
+
+      ha->adapt = kmalloc(sizeof(ADAPTER_AREA), GFP_KERNEL|GFP_DMA);
+
+      if (!ha->adapt) {
+         printk(KERN_WARNING "(%s%d) Unable to allocate host adapt structure - skipping controller\n",
+                ips_name, index);
+
+         ha->active = 0;
+
+         continue;
+      }
+
+      ha->conf = kmalloc(sizeof(CONFCMD), GFP_KERNEL|GFP_DMA);
+
+      if (!ha->conf) {
+         printk(KERN_WARNING "(%s%d) Unable to allocate host conf structure - skipping controller\n",
+                ips_name, index);
+
+         ha->active = 0;
+
+         continue;
+      }
+
+      ha->nvram = kmalloc(sizeof(NVRAM_PAGE5), GFP_KERNEL|GFP_DMA);
+
+      if (!ha->nvram) {
+         printk(KERN_WARNING "(%s%d) Unable to allocate host nvram structure - skipping controller\n",
+                ips_name, index);
+
+         ha->active = 0;
+
+         continue;
+      }
+
+      ha->subsys = kmalloc(sizeof(SUBSYS_PARAM), GFP_KERNEL|GFP_DMA);
+
+      if (!ha->subsys) {
+         printk(KERN_WARNING "(%s%d) Unable to allocate host subsystem structure - skipping controller\n",
+                ips_name, index);
+
+         ha->active = 0;
+
+         continue;
+      }
+
+      ha->dummy = kmalloc(sizeof(BASIC_IO_CMD), GFP_KERNEL|GFP_DMA);
+
+      if (!ha->dummy) {
+         printk(KERN_WARNING "(%s%d) Unable to allocate host dummy structure - skipping controller\n",
+                ips_name, index);
+
+         ha->active = 0;
+
+         continue;
+      }
+
+      /* Store away needed values for later use */
+      sh->io_port = io_addr;
+      sh->n_io_port = 255;
+      sh->unique_id = io_addr;
+      sh->irq = irq;
+      sh->select_queue_depths = NULL;
+      sh->sg_tablesize = sh->hostt->sg_tablesize;
+      sh->can_queue = sh->hostt->can_queue;
+      sh->cmd_per_lun = sh->hostt->cmd_per_lun;
+      sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
+      sh->use_clustering = sh->hostt->use_clustering;
+      sh->wish_block = FALSE;
+
+      /* Store info in HA structure */
+      ha->io_addr = io_addr;
+      ha->irq = irq;
+      ha->host_num = index;
+
+      /* install the interrupt handler */
+      if (request_irq(irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) {
+         printk(KERN_WARNING "(%s%d) unable to install interrupt handler - skipping controller\n",
+                ips_name, index);
+
+         ha->active = 0;
+
+         continue;
+      }
+
+      /*
+       * Allocate a temporary SCB for initialization
+       */
+      ha->scbs = (ips_scb_t *) kmalloc(sizeof(ips_scb_t), GFP_KERNEL|GFP_DMA);
+      if (!ha->scbs) {
+         /* couldn't allocate a temp SCB */
+         printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
+                ips_name, index);
+
+         ha->active = 0;
+
+         continue;
+      }
+
+      memset(ha->scbs, 0, sizeof(ips_scb_t));
+      ha->scbs->sg_list = (SG_LIST *) kmalloc(sizeof(SG_LIST) * MAX_SG_ELEMENTS, GFP_KERNEL|GFP_DMA);
+      if (!ha->scbs->sg_list) {
+         /* couldn't allocate a temp SCB S/G list */
+         printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
+                ips_name, index);
+
+         ha->active = 0;
+
+         continue;
+      }
+
+      ha->max_cmds = 1;
+
+      if (!ips_hainit(ha)) {
+         printk(KERN_WARNING "(%s%d) unable to initialize controller - skipping\n",
+                ips_name, index);
+
+         ha->active = 0;
+
+         continue;
+      }
+
+      /*
+       * Free the temporary SCB
+       */
+      kfree(ha->scbs->sg_list);
+      kfree(ha->scbs);
+      ha->scbs = NULL;
+
+      /* allocate CCBs */
+      if (!ips_allocatescbs(ha)) {
+         printk(KERN_WARNING "(%s%d) unable to allocate CCBs - skipping contoller\n",
+                ips_name, index);
+
+         ha->active = 0;
+
+         continue;
+      }
+
+      /* finish setting values */
+      sh->max_id = ha->ntargets;
+      sh->max_lun = ha->nlun;
+      sh->max_channel = ha->nbus;
+      sh->can_queue = ha->max_cmds-1;
+   } /* end for */
+
+   return (ips_num_controllers);
+
+#else
+
+   /* No PCI -- No ServeRAID */
+   return (0);
+#endif /* CONFIG_PCI */
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_release                                                */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Remove a driver                                                        */
+/*                                                                          */
+/****************************************************************************/
+int
+ips_release(struct Scsi_Host *sh) {
+   ips_scb_t *scb;
+   ips_ha_t  *ha;
+   int        i;
+
+   DBG("ips_release");
+
+   for (i = 0; i < IPS_MAX_ADAPTERS && ips_sh[i] != sh; i++);
+
+   if (i == IPS_MAX_ADAPTERS)
+      panic("(%s) release, invalid Scsi_Host pointer.\n",
+            ips_name);
+
+   ha = HA(sh);
+
+   if (!ha)
+      return (FALSE);
+
+   /* flush the cache on the controller */
+   scb = &ha->scbs[ha->max_cmds-1];
+
+   ips_init_scb(ha, scb);
+
+   scb->timeout = ips_cmd_timeout;
+   scb->cdb[0] = FLUSH_CACHE;
+
+   scb->cmd.flush_cache.op_code = FLUSH_CACHE;
+   scb->cmd.flush_cache.command_id = IPS_COMMAND_ID(ha, scb);
+   scb->cmd.flush_cache.state = NORM_STATE;
+   scb->cmd.flush_cache.reserved = 0;
+   scb->cmd.flush_cache.reserved2 = 0;
+   scb->cmd.flush_cache.reserved3 = 0;
+   scb->cmd.flush_cache.reserved4 = 0;
+
+   printk("(%s%d) Flushing Cache.\n", ips_name, ha->host_num);
+
+   /* send command */
+   if (ips_send_wait(ha, scb, ips_cmd_timeout) == IPS_FAILURE)
+      printk("(%s%d) Incomplete Flush.\n", ips_name, ha->host_num);
+
+   printk("(%s%d) Flushing Complete.\n", ips_name, ha->host_num);
+
+   ips_sh[i] = NULL;
+   ips_ha[i] = NULL;
+
+   /* free extra memory */
+   ips_free(ha);
+
+   /* free IRQ */
+   free_irq(ha->irq, ha);
+
+   /* unregister with SCSI sub system */
+   scsi_unregister(sh);
+
+   return (FALSE);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_eh_abort                                               */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Abort a command (using the new error code stuff)                       */
+/*                                                                          */
+/****************************************************************************/
+int
+ips_eh_abort(Scsi_Cmnd *SC) {
+   ips_ha_t         *ha;
+
+   DBG("ips_eh_abort");
+
+   if (!SC)
+      return (FAILED);
+
+   ha = (ips_ha_t *) SC->host->hostdata;
+
+   if (!ha)
+      return (FAILED);
+
+   if (!ha->active)
+      return (FAILED);
+
+   if (SC->serial_number != SC->serial_number_at_timeout) {
+      /* HMM, looks like a bogus command */
+#if IPS_DEBUG >= 1
+      printk(KERN_NOTICE "Abort called with bogus scsi command\n");
+#endif
+
+      return (FAILED);
+   }
+
+   if (test_and_set_bit(IPS_IN_ABORT, &ha->flags))
+      return (FAILED);
+
+   /* See if the command is on the wait queue */
+   if (ips_removeq_wait(&ha->scb_waitlist, SC) ||
+       ips_removeq_wait(&ha->copp_waitlist, SC)) {
+      /* command not sent yet */
+      clear_bit(IPS_IN_ABORT, &ha->flags);
+
+      return (SUCCESS);
+   } else {
+      /* command must have already been sent */
+      clear_bit(IPS_IN_ABORT, &ha->flags);
+
+      return (FAILED);
+   }
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_abort                                                  */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Abort a command                                                        */
+/*                                                                          */
+/****************************************************************************/
+int
+ips_abort(Scsi_Cmnd *SC) {
+   ips_ha_t         *ha;
+
+   DBG("ips_abort");
+
+   if (!SC)
+      return (SCSI_ABORT_SNOOZE);
+
+   ha = (ips_ha_t *) SC->host->hostdata;
+
+   if (!ha)
+      return (SCSI_ABORT_SNOOZE);
+
+   if (!ha->active)
+      return (SCSI_ABORT_SNOOZE);
+
+   if (SC->serial_number != SC->serial_number_at_timeout) {
+      /* HMM, looks like a bogus command */
+#if IPS_DEBUG >= 1
+      printk(KERN_NOTICE "Abort called with bogus scsi command\n");
+#endif
+
+      return (SCSI_ABORT_NOT_RUNNING);
+   }
+
+   if (test_and_set_bit(IPS_IN_ABORT, &ha->flags))
+      return (SCSI_ABORT_SNOOZE);
+
+   /* See if the command is on the wait queue */
+   if (ips_removeq_wait(&ha->scb_waitlist, SC) ||
+       ips_removeq_wait(&ha->copp_waitlist, SC)) {
+      /* command not sent yet */
+      clear_bit(IPS_IN_ABORT, &ha->flags);
+
+      return (SCSI_ABORT_PENDING);
+   } else {
+      /* command must have already been sent */
+      clear_bit(IPS_IN_ABORT, &ha->flags);
+
+      return (SCSI_ABORT_SNOOZE);
+   }
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_eh_reset                                               */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Reset the controller (with new eh error code)                          */
+/*                                                                          */
+/****************************************************************************/
+int
+ips_eh_reset(Scsi_Cmnd *SC) {
+   ips_ha_t         *ha;
+   ips_scb_t        *scb;
+
+   DBG("ips_eh_reset");
+
+#ifdef NO_IPS_RESET
+   return (FAILED);
+#else
+
+   if (!SC) {
+
+#if IPS_DEBUG >= 1
+      printk(KERN_NOTICE "Reset called with NULL scsi command\n");
+#endif
+
+      return (FAILED);
+   }
+
+   ha = (ips_ha_t *) SC->host->hostdata;
+
+   if (!ha) {
+
+#if IPS_DEBUG >= 1
+      printk(KERN_NOTICE "Reset called with NULL ha struct\n");
+#endif
+
+      return (FAILED);
+   }
+
+   if (!ha->active)
+      return (FAILED);
+
+   if (test_and_set_bit(IPS_IN_RESET, &ha->flags))
+      return (FAILED);
+
+   /* See if the command is on the waiting queue */
+   if (ips_removeq_wait(&ha->scb_waitlist, SC) ||
+       ips_removeq_wait(&ha->copp_waitlist, SC)) {
+      /* command not sent yet */
+      clear_bit(IPS_IN_ABORT, &ha->flags);
+
+      return (SUCCESS);
+   }
+
+   /*
+    * command must have already been sent
+    * reset the controller
+    */
+   if (!ips_reset_adapter(ha)) {
+      clear_bit(IPS_IN_RESET, &ha->flags);
+
+      return (FAILED);
+   }
+
+   if (!ips_clear_adapter(ha)) {
+      clear_bit(IPS_IN_RESET, &ha->flags);
+
+      return (FAILED);
+   }
+
+   /* Now fail all of the active commands */
+#if IPS_DEBUG >= 1
+   printk(KERN_WARNING "(%s%d) Failing active commands\n",
+          ips_name, ha->host_num);
+#endif
+   while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
+      scb->scsi_cmd->result = DID_RESET << 16;
+      scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+      ips_freescb(ha, scb);
+   }
+
+   /* Reset the number of active IOCTLs */
+   ha->num_ioctl = 0;
+
+   clear_bit(IPS_IN_RESET, &ha->flags);
+
+   if (!test_bit(IPS_IN_INTR, &ha->flags)) {
+      /*
+       * Only execute the next command when
+       * we are not being called from the
+       * interrupt handler.  The interrupt
+       * handler wants to do this and since
+       * interrupts are turned off here....
+       */
+      ips_next(ha);
+   }
+
+   return (SUCCESS);
+
+#endif /* NO_IPS_RESET */
+
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_reset                                                  */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Reset the controller                                                   */
+/*                                                                          */
+/****************************************************************************/
+int
+ips_reset(Scsi_Cmnd *SC, unsigned int flags) {
+   ips_ha_t         *ha;
+   ips_scb_t        *scb;
+
+   DBG("ips_reset");
+
+#ifdef NO_IPS_RESET
+   return (SCSI_RESET_SNOOZE);
+#else
+
+   if (!SC) {
+
+#if IPS_DEBUG >= 1
+      printk(KERN_NOTICE "Reset called with NULL scsi command\n");
+#endif
+
+      return (SCSI_RESET_SNOOZE);
+   }
+
+   ha = (ips_ha_t *) SC->host->hostdata;
+
+   if (!ha) {
+
+#if IPS_DEBUG >= 1
+      printk(KERN_NOTICE "Reset called with NULL ha struct\n");
+#endif
+
+      return (SCSI_RESET_SNOOZE);
+   }
+
+   if (!ha->active)
+      return (SCSI_RESET_SNOOZE);
+
+   if (test_and_set_bit(IPS_IN_RESET, &ha->flags))
+      return (SCSI_RESET_SNOOZE);
+
+   /* See if the command is on the waiting queue */
+   if (ips_removeq_wait(&ha->scb_waitlist, SC) ||
+       ips_removeq_wait(&ha->copp_waitlist, SC)) {
+      /* command not sent yet */
+      clear_bit(IPS_IN_ABORT, &ha->flags);
+
+      return (SCSI_RESET_SNOOZE);
+   }
+
+   /* reset the controller */
+   if (!ips_reset_adapter(ha)) {
+      clear_bit(IPS_IN_RESET, &ha->flags);
+
+      return (SCSI_RESET_ERROR);
+   }
+
+   if (!ips_clear_adapter(ha)) {
+      clear_bit(IPS_IN_RESET, &ha->flags);
+
+      return (SCSI_RESET_ERROR);
+   }
+
+   /* Now fail all of the active commands */
+#if IPS_DEBUG >= 1
+   printk(KERN_WARNING "(%s%d) Failing active commands\n",
+          ips_name, ha->host_num);
+#endif
+   while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
+      scb->scsi_cmd->result = DID_RESET << 16;
+      scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+      ips_freescb(ha, scb);
+   }
+
+   /* Reset the number of active IOCTLs */
+   ha->num_ioctl = 0;
+
+   clear_bit(IPS_IN_RESET, &ha->flags);
+
+   if (!test_bit(IPS_IN_INTR, &ha->flags)) {
+      /*
+       * Only execute the next command when
+       * we are not being called from the
+       * interrupt handler.  The interrupt
+       * handler wants to do this and since
+       * interrupts are turned off here....
+       */
+      ips_next(ha);
+   }
+
+   return (SCSI_RESET_SUCCESS);
+
+#endif /* NO_IPS_RESET */
+
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_queue                                                  */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Send a command to the controller                                       */
+/*                                                                          */
+/****************************************************************************/
+int
+ips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) {
+   ips_ha_t         *ha;
+
+   DBG("ips_queue");
+
+   ha = (ips_ha_t *) SC->host->hostdata;
+
+   if (!ha)
+      return (1);
+
+   if (!ha->active)
+      return (1);
+
+#ifndef NO_IPS_CMDLINE
+   if (ips_is_passthru(SC)) {
+      if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) {
+         SC->result = DID_BUS_BUSY << 16;
+         done(SC);
+
+         return (0);
+      }
+   } else {
+#endif
+      if (ha->scb_waitlist.count == IPS_MAX_QUEUE) {
+         SC->result = DID_BUS_BUSY << 16;
+         done(SC);
+
+         return (0);
+      }
+
+#ifndef NO_IPS_CMDLINE
+   }
+#endif
+
+   SC->scsi_done = done;
+
+#if IPS_DEBUG >= 10
+   printk(KERN_NOTICE "%s: ips_queue: cmd 0x%X (%d %d %d)\n",
+          ips_name,
+          SC->cmnd[0],
+          SC->channel,
+          SC->target,
+          SC->lun);
+#if IPS_DEBUG >= 11
+        MDELAY(2*ONE_SEC);
+#endif
+#endif
+
+#ifndef NO_IPS_CMDLINE
+   if (ips_is_passthru(SC))
+      ips_putq_wait_tail(&ha->copp_waitlist, SC);
+   else
+#endif
+      ips_putq_wait_tail(&ha->scb_waitlist, SC);
+
+   if ((!test_bit(IPS_IN_INTR, &ha->flags)) &&
+       (!test_bit(IPS_IN_ABORT, &ha->flags)) &&
+       (!test_bit(IPS_IN_RESET, &ha->flags)))
+      ips_next(ha);
+
+   return (0);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_biosparam                                              */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Set bios geometry for the controller                                   */
+/*                                                                          */
+/****************************************************************************/
+int
+ips_biosparam(Disk *disk, kdev_t dev, int geom[]) {
+   ips_ha_t         *ha;
+   int               heads;
+   int               sectors;
+   int               cylinders;
+
+   DBG("ips_biosparam");
+
+   ha = (ips_ha_t *) disk->device->host->hostdata;
+
+   if (!ha)
+      /* ?!?! host adater info invalid */
+      return (0);
+
+   if (!ha->active)
+      return (0);
+
+   if (!ips_read_adapter_status(ha))
+      /* ?!?! Enquiry command failed */
+      return (0);
+
+   if ((disk->capacity > 0x400000) &&
+       ((ha->enq->ucMiscFlag & 0x8) == 0)) {
+      heads = NORM_MODE_HEADS;
+      sectors = NORM_MODE_SECTORS;
+   } else {
+      heads = COMP_MODE_HEADS;
+      sectors = COMP_MODE_SECTORS;
+   }
+
+   cylinders = disk->capacity / (heads * sectors);
+
+#if IPS_DEBUG >= 2
+   printk(KERN_NOTICE "Geometry: heads: %d, sectors: %d, cylinders: %d\n",
+          heads, sectors, cylinders);
+#endif
+
+   geom[0] = heads;
+   geom[1] = sectors;
+   geom[2] = cylinders;
+
+   return (0);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: do_ipsintr                                                 */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Wrapper for the interrupt handler                                      */
+/*                                                                          */
+/****************************************************************************/
+void
+do_ipsintr(int irq, void *dev_id, struct pt_regs *regs) {
+   ips_ha_t         *ha;
+   unsigned int      cpu_flags;
+
+   DBG("do_ipsintr");
+
+   ha = (ips_ha_t *) dev_id;
+
+   spin_lock_irqsave(&io_request_lock, cpu_flags);
+
+   if (test_and_set_bit(IPS_IN_INTR, &ha->flags)) {
+      spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+
+      return ;
+   }
+
+   if (!ha) {
+      clear_bit(IPS_IN_INTR, &ha->flags);
+      spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+
+      return;
+   }
+
+   if (!ha->active) {
+      clear_bit(IPS_IN_INTR, &ha->flags);
+      spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+
+      return;
+   }
+
+   ips_intr(ha);
+
+   clear_bit(IPS_IN_INTR, &ha->flags);
+
+   spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_intr                                                   */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Polling interrupt handler                                              */
+/*                                                                          */
+/*   ASSUMES interrupts are disabled                                        */
+/*                                                                          */
+/****************************************************************************/
+void
+ips_intr(ips_ha_t *ha) {
+   ips_stat_t       *sp;
+   ips_scb_t        *scb;
+   int               status;
+
+   DBG("ips_intr");
+
+   if (!ha)
+      return;
+
+   if (!ha->active)
+      return;
+
+   while (ips_isintr(ha)) {
+      sp = &ha->sp;
+
+      if ((status = ips_chkstatus(ha)) < 0) {
+         /* unexpected interrupt - no ccb */
+         printk(KERN_WARNING "(%s%d) Spurious interrupt; no ccb.\n",
+                ips_name, ha->host_num);
+         continue ;
+      }
+
+      scb = (ips_scb_t *) sp->scb_addr;
+
+      /*
+       * use the callback function to finish things up
+       * NOTE: interrupts are OFF for this
+       */
+      (*scb->callback) (ha, scb);
+   }
+
+   clear_bit(IPS_IN_INTR, &ha->flags);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_info                                                   */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Return info about the driver                                           */
+/*                                                                          */
+/****************************************************************************/
+const char *
+ips_info(struct Scsi_Host *SH) {
+   static char  buffer[256];
+   char        *bp;
+   ips_ha_t    *ha;
+
+   DBG("ips_info");
+
+   ha = HA(SH);
+
+   if (!ha)
+      return (NULL);
+
+   bp = &buffer[0];
+   memset(bp, 0, sizeof(buffer));
+
+   strcpy(bp, "IBM PCI ServeRAID ");
+   strcat(bp, IPS_VERSION_HIGH);
+   strcat(bp, IPS_VERSION_LOW);
+
+   if (ha->ad_type > 0 &&
+       ha->ad_type <= MAX_ADAPTER_NAME) {
+      strcat(bp, " <");
+      strcat(bp, ips_adapter_name[ha->ad_type-1]);
+      strcat(bp, ">");
+   }
+
+   return (bp);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_proc_info                                              */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   The passthru interface for the driver                                  */
+/*                                                                          */
+/****************************************************************************/
+int
+ips_proc_info(char *buffer, char **start, off_t offset,
+              int length, int hostno, int func) {
+   int           i;
+   int           ret;
+   ips_ha_t     *ha = NULL;
+
+   DBG("ips_proc_info");
+
+   /* Find our host structure */
+   for (i = 0; i < ips_num_controllers; i++) {
+      if (ips_sh[i] && ips_sh[i]->host_no == hostno) {
+         ha = (ips_ha_t *) ips_sh[i]->hostdata;
+
+         break;
+      }
+   }
+
+   if (!ha)
+      return (-EINVAL);
+
+   if (func) {
+      /* write */
+      return (0);
+   } else {
+      /* read */
+      if (start)
+         *start = buffer;
+
+      ret = ips_host_info(ha, buffer, offset, length);
+
+      return (ret);
+   }
+}
+
+/*--------------------------------------------------------------------------*/
+/* Helper Functions                                                         */
+/*--------------------------------------------------------------------------*/
+
+#ifndef NO_IPS_CMDLINE
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_is_passthru                                            */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Determine if the specified SCSI command is really a passthru command   */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_is_passthru(Scsi_Cmnd *SC) {
+   DBG("ips_is_passthru");
+
+   if (!SC)
+      return (0);
+
+   if ((SC->channel == 0) &&
+       (SC->target == IPS_ADAPTER_ID) &&
+       (SC->lun == 0) &&
+       (SC->cmnd[0] == 0x0d) &&
+       (SC->request_bufflen) &&
+       (!SC->use_sg) &&
+       (((char *) SC->request_buffer)[0] == 'C') &&
+       (((char *) SC->request_buffer)[1] == 'O') &&
+       (((char *) SC->request_buffer)[2] == 'P') &&
+       (((char *) SC->request_buffer)[3] == 'P')) {
+      return (1);
+   } else {
+      return (0);
+   }
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_is_passthru                                            */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Make a passthru command out of the info in the Scsi block              */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_make_passthru(ips_ha_t *ha, Scsi_Cmnd *SC, ips_scb_t *scb) {
+   ips_passthru_t *pt;
+
+   DBG("ips_make_passthru");
+
+   if (!SC->request_bufflen || !SC->request_buffer) {
+      /* no data */
+#if IPS_DEBUG_PT >= 1
+      printk(KERN_NOTICE "(%s%d) No passthru structure\n",
+             ips_name, ha->host_num);
+#endif
+
+      return (IPS_FAILURE);
+   }
+
+   if (SC->request_bufflen < sizeof(ips_passthru_t)) {
+      /* wrong size */
+#if IPS_DEBUG_PT >= 1
+      printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n",
+             ips_name, ha->host_num);
+#endif
+
+      return (IPS_FAILURE);
+   }
+
+   if ((((char *) SC->request_buffer)[0] != 'C') ||
+       (((char *) SC->request_buffer)[1] != 'O') ||
+       (((char *) SC->request_buffer)[2] != 'P') ||
+       (((char *) SC->request_buffer)[3] != 'P')) {
+      /* signature doesn't match */
+#if IPS_DEBUG_PT >= 1
+      printk(KERN_NOTICE "(%s%d) Wrong signature on passthru structure.\n",
+             ips_name, ha->host_num);
+#endif
+
+      return (IPS_FAILURE);
+   }
+
+   pt = (ips_passthru_t *) SC->request_buffer;
+   scb->scsi_cmd = SC;
+
+   if (SC->request_bufflen < (sizeof(ips_passthru_t) + pt->CmdBSize)) {
+      /* wrong size */
+#if IPS_DEBUG_PT >= 1
+      printk(KERN_NOTICE "(%s%d) Passthru structure wrong size\n",
+             ips_name, ha->host_num);
+#endif
+
+      return (IPS_FAILURE);
+   }
+
+   switch (pt->CoppCmd) {
+   case IPS_NUMCTRLS:
+      memcpy(SC->request_buffer + sizeof(ips_passthru_t),
+             &ips_num_controllers, sizeof(int));
+      SC->result = DID_OK << 16;
+
+      return (IPS_SUCCESS_IMM);
+   case IPS_CTRLINFO:
+      memcpy(SC->request_buffer + sizeof(ips_passthru_t),
+             ha, sizeof(ips_ha_t));
+      SC->result = DID_OK << 16;
+
+      return (IPS_SUCCESS_IMM);
+   case COPPUSRCMD:
+      if (ips_usrcmd(ha, pt, scb))
+         return (IPS_SUCCESS);
+      else
+         return (IPS_FAILURE);
+      break;
+   }
+
+   return (IPS_FAILURE);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_usrcmd                                                 */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Process a user command and make it ready to send                       */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_usrcmd(ips_ha_t *ha, ips_passthru_t *pt, ips_scb_t *scb) {
+   SG_LIST        *sg_list;
+
+   DBG("ips_usrcmd");
+
+   if ((!scb) || (!pt) || (!ha))
+      return (0);
+
+   /* Save the S/G list pointer so it doesn't get clobbered */
+   sg_list = scb->sg_list;
+
+   /* copy in the CP */
+   memcpy(&scb->cmd, &pt->CoppCP.cmd, sizeof(IOCTL_INFO));
+   memcpy(&scb->dcdb, &pt->CoppCP.dcdb, sizeof(DCDB_TABLE));
+
+   /* FIX stuff that might be wrong */
+   scb->sg_list = sg_list;
+   scb->scb_busaddr = VIRT_TO_BUS(scb);
+   scb->bus = 0;
+   scb->target_id = 0;
+   scb->lun = 0;
+   scb->sg_len = 0;
+   scb->data_len = 0;
+   scb->flags = 0;
+   scb->op_code = 0;
+   scb->callback = ipsintr_done;
+   scb->timeout = ips_cmd_timeout;
+   scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
+
+   /* we don't support DCDB/READ/WRITE Scatter Gather */
+   if ((scb->cmd.basic_io.op_code == READ_SCATTER_GATHER) ||
+       (scb->cmd.basic_io.op_code == WRITE_SCATTER_GATHER) ||
+       (scb->cmd.basic_io.op_code == DIRECT_CDB_SCATTER_GATHER))
+      return (0);
+
+   if (pt->CmdBSize && pt->CmdBuffer) {
+      scb->data_busaddr = VIRT_TO_BUS(scb->scsi_cmd->request_buffer + sizeof(ips_passthru_t));
+   } else {
+      scb->data_busaddr = 0L;
+   }
+
+   if (pt->CmdBSize) {
+      if (scb->cmd.dcdb.op_code == DIRECT_CDB) {
+         scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
+         scb->dcdb.buffer_pointer = scb->data_busaddr;
+      } else {
+         scb->cmd.basic_io.sg_addr = scb->data_busaddr;
+      }
+   }
+
+   /* set timeouts */
+   if (pt->TimeOut) {
+      scb->timeout = pt->TimeOut;
+
+      if (pt->TimeOut <= 10)
+         scb->dcdb.cmd_attribute |= TIMEOUT_10;
+      else if (pt->TimeOut <= 60)
+         scb->dcdb.cmd_attribute |= TIMEOUT_60;
+      else
+         scb->dcdb.cmd_attribute |= TIMEOUT_20M;
+   }
+
+   /* assume error */
+   scb->scsi_cmd->result = DID_ERROR << 16;
+
+   /* success */
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_cleanup_passthru                                       */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Cleanup after a passthru command                                       */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_cleanup_passthru(ips_scb_t *scb) {
+   ips_passthru_t *pt;
+
+   DBG("ips_cleanup_passthru");
+
+   if ((!scb) || (!scb->scsi_cmd) || (!scb->scsi_cmd->request_buffer)) {
+#if IPS_DEBUG_PT >= 1
+      printk(KERN_NOTICE "IPS couldn't cleanup\n");
+#endif
+
+      return ;
+   }
+
+   pt = (ips_passthru_t *) scb->scsi_cmd->request_buffer;
+
+   /* Copy data back to the user */
+   pt->BasicStatus = scb->basic_status;
+   pt->ExtendedStatus = scb->extended_status;
+
+   scb->scsi_cmd->result = DID_OK << 16;
+}
+
+#endif
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_host_info                                              */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   The passthru interface for the driver                                  */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_host_info(ips_ha_t *ha, char *ptr, off_t offset, int len) {
+   INFOSTR info;
+
+   DBG("ips_host_info");
+
+   info.buffer = ptr;
+   info.length = len;
+   info.offset = offset;
+   info.pos = 0;
+
+   copy_info(&info, "\nIBM ServeRAID General Information:\n\n");
+
+   if ((ha->nvram->signature == NVRAM_PAGE5_SIGNATURE) &&
+       (ha->nvram->adapter_type != 0))
+      copy_info(&info, "\tController Type                   : %s\n", ips_adapter_name[ha->ad_type-1]);
+   else
+      copy_info(&info, "\tController Type                   : Unknown\n");
+
+   copy_info(&info, "\tIO port address                   : 0x%lx\n", ha->io_addr);
+   copy_info(&info, "\tIRQ number                        : %d\n", ha->irq);
+
+   if (ha->nvram->signature == NVRAM_PAGE5_SIGNATURE)
+      copy_info(&info, "\tBIOS Version                      : %c%c%c%c%c%c%c%c\n",
+                ha->nvram->bios_high[0], ha->nvram->bios_high[1],
+                ha->nvram->bios_high[2], ha->nvram->bios_high[3],
+                ha->nvram->bios_low[0], ha->nvram->bios_low[1],
+                ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
+
+   copy_info(&info, "\tFirmware Version                  : %c%c%c%c%c%c%c%c\n",
+             ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
+             ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
+             ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
+             ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
+
+   copy_info(&info, "\tBoot Block Version                : %c%c%c%c%c%c%c%c\n",
+             ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
+             ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
+             ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
+             ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
+
+   copy_info(&info, "\tDriver Version                    : %s%s\n",
+             IPS_VERSION_HIGH, IPS_VERSION_LOW);
+
+   copy_info(&info, "\tMax Physical Devices              : %d\n",
+             ha->enq->ucMaxPhysicalDevices);
+   copy_info(&info, "\tMax Active Commands               : %d\n",
+             ha->max_cmds);
+   copy_info(&info, "\tCurrent Queued Commands           : %d\n",
+             ha->scb_waitlist.count);
+   copy_info(&info, "\tCurrent Active Commands           : %d\n",
+             ha->scb_activelist.count - ha->num_ioctl);
+   copy_info(&info, "\tCurrent Queued PT Commands        : %d\n",
+             ha->copp_waitlist.count);
+   copy_info(&info, "\tCurrent Active PT Commands        : %d\n",
+             ha->num_ioctl);
+
+   copy_info(&info, "\n");
+
+   return (info.pos > info.offset ? info.pos - info.offset : 0);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: copy_mem_info                                              */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Copy data into an INFOSTR structure                                    */
+/*                                                                          */
+/****************************************************************************/
+static void
+copy_mem_info(INFOSTR *info, char *data, int len) {
+   DBG("copy_mem_info");
+
+   if (info->pos + len > info->length)
+      len = info->length - info->pos;
+
+   if (info->pos + len < info->offset) {
+      info->pos += len;
+      return;
+   }
+
+   if (info->pos < info->offset) {
+      data += (info->offset - info->pos);
+      len  -= (info->offset - info->pos);
+   }
+
+   if (len > 0) {
+      memcpy(info->buffer + info->pos, data, len);
+      info->pos += len;
+   }
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: copy_info                                                  */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   printf style wrapper for an info structure                             */
+/*                                                                          */
+/****************************************************************************/
+static int
+copy_info(INFOSTR *info, char *fmt, ...) {
+   va_list args;
+   char buf[81];
+   int len;
+
+   DBG("copy_info");
+
+   va_start(args, fmt);
+   len = vsprintf(buf, fmt, args);
+   va_end(args);
+
+   copy_mem_info(info, buf, len);
+
+   return (len);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_hainit                                                 */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Initialize the controller                                              */
+/*                                                                          */
+/* NOTE: Assumes to be called from with a lock                              */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_hainit(ips_ha_t *ha) {
+   int       i;
+
+   DBG("ips_hainit");
+
+   if (!ha)
+      return (0);
+
+   /* initialize status queue */
+   ips_statinit(ha);
+
+   /* Setup HBA ID's */
+   if (!ips_read_config(ha)) {
+
+#ifndef NO_IPS_RESET
+
+      /* Try to reset the controller and try again */
+      if (!ips_reset_adapter(ha)) {
+         printk(KERN_WARNING "(%s%d) unable to reset controller.\n",
+                ips_name, ha->host_num);
+
+         return (0);
+      }
+
+      if (!ips_clear_adapter(ha)) {
+         printk(KERN_WARNING "(%s%d) unable to initialize controller.\n",
+                ips_name, ha->host_num);
+
+         return (0);
+      }
+
+#endif
+
+      if (!ips_read_config(ha)) {
+         printk(KERN_WARNING "(%s%d) unable to read config from controller.\n",
+                ips_name, ha->host_num);
+
+         return (0);
+      }
+   } /* end if */
+
+   /* write driver version */
+   if (!ips_write_driver_status(ha)) {
+      printk(KERN_WARNING "(%s%d) unable to write driver info to controller.\n",
+             ips_name, ha->host_num);
+
+      return (0);
+   }
+
+   if (!ips_read_adapter_status(ha)) {
+      printk(KERN_WARNING "(%s%d) unable to read controller status.\n",
+             ips_name, ha->host_num);
+
+      return (0);
+   }
+
+   if (!ips_read_subsystem_parameters(ha)) {
+      printk(KERN_WARNING "(%s%d) unable to read subsystem parameters.\n",
+             ips_name, ha->host_num);
+
+      return (0);
+   }
+
+   /* set limits on SID, LUN, BUS */
+   ha->ntargets = MAX_TARGETS + 1;
+   ha->nlun = 1;
+   ha->nbus = (ha->enq->ucMaxPhysicalDevices / MAX_TARGETS);
+
+   switch (ha->conf->logical_drive[0].ucStripeSize) {
+   case 4:
+      ha->max_xfer = 0x10000;
+      break;
+
+   case 5:
+      ha->max_xfer = 0x20000;
+      break;
+
+   case 6:
+      ha->max_xfer = 0x40000;
+      break;
+
+   case 7:
+   default:
+      ha->max_xfer = 0x80000;
+      break;
+   }
+
+   /* setup max concurrent commands */
+   if (ha->subsys->param[4] & 0x1) {
+      /* Use the new method */
+      ha->max_cmds = ha->enq->ucConcurrentCmdCount;
+   } else {
+      /* use the old method */
+      switch (ha->conf->logical_drive[0].ucStripeSize) {
+      case 4:
+         ha->max_cmds = 32;
+         break;
+
+      case 5:
+         ha->max_cmds = 16;
+         break;
+
+      case 6:
+         ha->max_cmds = 8;
+         break;
+
+      case 7:
+      default:
+         ha->max_cmds = 4;
+         break;
+      }
+   }
+
+   /* set controller IDs */
+   ha->ha_id[0] = IPS_ADAPTER_ID;
+   for (i = 1; i < ha->nbus; i++)
+      ha->ha_id[i] = ha->conf->init_id[i-1] & 0x1f;
+
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_next                                                   */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Take the next command off the queue and send it to the controller      */
+/*                                                                          */
+/* ASSUMED to be called from within a lock                                  */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_next(ips_ha_t *ha) {
+   ips_scb_t    *scb;
+   Scsi_Cmnd    *SC;
+   int           ret;
+
+   DBG("ips_next");
+
+   if (!ha)
+      return ;
+
+#ifndef NO_IPS_CMDLINE
+   /*
+    * Send passthru commands
+    * These have priority over normal I/O
+    * but shouldn't affect performance too much
+    * since we limit the number that can be active
+    * on the card at any one time
+    */
+   while ((ha->num_ioctl < IPS_MAX_IOCTL) &&
+          (ha->copp_waitlist.head) &&
+          (scb = ips_getscb(ha))) {
+      SC = ips_removeq_wait_head(&ha->copp_waitlist);
+
+      ret = ips_make_passthru(ha, SC, scb);
+
+      switch (ret) {
+      case IPS_FAILURE:
+         if (scb->scsi_cmd) {
+            scb->scsi_cmd->result = DID_ERROR << 16;
+            scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+         }
+         ips_freescb(ha, scb);
+         break;
+      case IPS_SUCCESS_IMM:
+         if (scb->scsi_cmd)
+            scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+         ips_freescb(ha, scb);
+         break;
+      default:
+         break;
+      } /* end case */
+
+      if (ret != IPS_SUCCESS)
+         continue;
+
+      ret = ips_send_cmd(ha, scb);
+
+      if (ret == IPS_SUCCESS) {
+         ips_putq_scb_head(&ha->scb_activelist, scb);
+         ha->num_ioctl++;
+      }
+
+      switch(ret) {
+      case IPS_FAILURE:
+         if (scb->scsi_cmd) {
+            scb->scsi_cmd->result = DID_ERROR << 16;
+            scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+         }
+
+         ips_freescb(ha, scb);
+         break;
+      case IPS_SUCCESS_IMM:
+         if (scb->scsi_cmd)
+            scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+         ips_freescb(ha, scb);
+         break;
+      default:
+         break;
+      } /* end case */
+   }
+#endif
+
+   /*
+    * Send "Normal" I/O commands
+    */
+   while ((ha->scb_waitlist.head) &&
+          (scb = ips_getscb(ha))) {
+      SC = ips_removeq_wait_head(&ha->scb_waitlist);
+
+      SC->result = DID_OK;
+      SC->host_scribble = NULL;
+
+      memset(SC->sense_buffer, 0, sizeof(SC->sense_buffer));
+
+      scb->target_id = SC->target;
+      scb->lun = SC->lun;
+      scb->bus = SC->channel;
+      scb->scsi_cmd = SC;
+      scb->breakup = 0;
+      scb->data_len = 0;
+      scb->callback = ipsintr_done;
+      scb->timeout = ips_cmd_timeout;
+      memset(&scb->cmd, 0, 4);
+
+      /* copy in the CDB */
+      memcpy(scb->cdb, SC->cmnd, SC->cmd_len);
+
+      /* Now handle the data buffer */
+      if (SC->use_sg) {
+         struct scatterlist *sg;
+         int                 i;
+
+         sg = SC->request_buffer;
+
+         for (i = 0; i < SC->use_sg; i++) {
+            scb->sg_list[i].address = VIRT_TO_BUS(sg[i].address);
+            scb->sg_list[i].length = sg[i].length;
+
+            if (scb->data_len + sg[i].length > ha->max_xfer) {
+               /*
+                * Data Breakup required
+                */
+               scb->breakup = i;
+               break;
+            }
+
+            scb->data_len += sg[i].length;
+         }
+
+         if (!scb->breakup)
+            scb->sg_len = SC->use_sg;
+         else
+            scb->sg_len = scb->breakup;
+
+         scb->dcdb.transfer_length = scb->data_len;
+         scb->data_busaddr = VIRT_TO_BUS(scb->sg_list);
+      } else {
+         if (SC->request_bufflen) {
+            if (SC->request_bufflen > ha->max_xfer) {
+               /*
+                * Data breakup required
+                */
+               scb->breakup = 1;
+               scb->data_len = ha->max_xfer;
+            } else {
+               scb->data_len = SC->request_bufflen;
+            }
+
+            scb->dcdb.transfer_length = scb->data_len;
+            scb->data_busaddr = VIRT_TO_BUS(SC->request_buffer);
+            scb->sg_len = 0;
+         } else {
+            scb->data_busaddr = 0L;
+            scb->sg_len = 0;
+            scb->data_len = 0;
+            scb->dcdb.transfer_length = 0;
+         }
+
+      }
+
+      if ((scb->scsi_cmd->request.cmd == READ) && (SC->request_bufflen))
+         scb->dcdb.cmd_attribute |= DATA_IN;
+
+      if ((scb->scsi_cmd->request.cmd == WRITE) && (SC->request_bufflen))
+         scb->dcdb.cmd_attribute |= DATA_OUT;
+
+      if (scb->data_len >= IPS_MAX_XFER) {
+         scb->dcdb.cmd_attribute |= TRANSFER_64K;
+         scb->dcdb.transfer_length = 0;
+      }
+
+      ret = ips_send_cmd(ha, scb);
+
+      if (ret == IPS_SUCCESS)
+         ips_putq_scb_head(&ha->scb_activelist, scb);
+
+      switch(ret) {
+      case IPS_FAILURE:
+         if (scb->scsi_cmd) {
+            scb->scsi_cmd->result = DID_ERROR << 16;
+            scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+         }
+
+         ips_freescb(ha, scb);
+         break;
+      case IPS_SUCCESS_IMM:
+         if (scb->scsi_cmd)
+            scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+         ips_freescb(ha, scb);
+         break;
+      default:
+         break;
+      } /* end case */
+   } /* end while */
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_putq_scb_head                                          */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Add an item to the head of the queue                                   */
+/*                                                                          */
+/* ASSUMED to be called from within a lock                                  */
+/*                                                                          */
+/****************************************************************************/
+static inline void
+ips_putq_scb_head(ips_scb_queue_t *queue, ips_scb_t *item) {
+   DBG("ips_putq_scb_head");
+
+   if (!item)
+      return ;
+
+   item->q_next = queue->head;
+   queue->head = item;
+
+   if (!queue->tail)
+      queue->tail = item;
+
+   queue->count++;
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_putq_scb_tail                                          */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Add an item to the tail of the queue                                   */
+/*                                                                          */
+/* ASSUMED to be called from within a lock                                  */
+/*                                                                          */
+/****************************************************************************/
+static inline void
+ips_putq_scb_tail(ips_scb_queue_t *queue, ips_scb_t *item) {
+   DBG("ips_putq_scb_tail");
+
+   if (!item)
+      return ;
+
+   item->q_next = NULL;
+
+   if (queue->tail)
+      queue->tail->q_next = item;
+
+   queue->tail = item;
+
+   if (!queue->head)
+      queue->head = item;
+
+   queue->count++;
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_removeq_scb_head                                       */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Remove the head of the queue                                           */
+/*                                                                          */
+/* ASSUMED to be called from within a lock                                  */
+/*                                                                          */
+/****************************************************************************/
+static inline ips_scb_t *
+ips_removeq_scb_head(ips_scb_queue_t *queue) {
+   ips_scb_t  *item;
+
+   DBG("ips_removeq_scb_head");
+
+   item = queue->head;
+
+   if (!item)
+      return (NULL);
+
+   queue->head = item->q_next;
+   item->q_next = NULL;
+
+   if (queue->tail == item)
+      queue->tail = NULL;
+
+   queue->count--;
+
+   return (item);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_removeq_scb                                            */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Remove an item from a queue                                            */
+/*                                                                          */
+/* ASSUMED to be called from within a lock                                  */
+/*                                                                          */
+/****************************************************************************/
+static inline ips_scb_t *
+ips_removeq_scb(ips_scb_queue_t *queue, ips_scb_t *item) {
+   ips_scb_t  *p;
+
+   DBG("ips_removeq_scb");
+
+   if (!item)
+      return (NULL);
+
+   if (item == queue->head)
+      return (ips_removeq_scb_head(queue));
+
+   p = queue->head;
+
+   while ((p) && (item != p->q_next))
+      p = p->q_next;
+
+   if (p) {
+      /* found a match */
+      p->q_next = item->q_next;
+
+      if (!item->q_next)
+         queue->tail = p;
+
+      item->q_next = NULL;
+      queue->count--;
+
+      return (item);
+   }
+
+   return (NULL);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_putq_wait_head                                         */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Add an item to the head of the queue                                   */
+/*                                                                          */
+/* ASSUMED to be called from within a lock                                  */
+/*                                                                          */
+/****************************************************************************/
+static inline void
+ips_putq_wait_head(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
+   DBG("ips_putq_wait_head");
+
+   if (!item)
+      return ;
+
+   item->host_scribble = (char *) queue->head;
+   queue->head = item;
+
+   if (!queue->tail)
+      queue->tail = item;
+
+   queue->count++;
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_putq_wait_tail                                         */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Add an item to the tail of the queue                                   */
+/*                                                                          */
+/* ASSUMED to be called from within a lock                                  */
+/*                                                                          */
+/****************************************************************************/
+static inline void
+ips_putq_wait_tail(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
+   DBG("ips_putq_wait_tail");
+
+   if (!item)
+      return ;
+
+   item->host_scribble = NULL;
+
+   if (queue->tail)
+      queue->tail->host_scribble = (char *)item;
+
+   queue->tail = item;
+
+   if (!queue->head)
+      queue->head = item;
+
+   queue->count++;
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_removeq_wait_head                                      */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Remove the head of the queue                                           */
+/*                                                                          */
+/* ASSUMED to be called from within a lock                                  */
+/*                                                                          */
+/****************************************************************************/
+static inline Scsi_Cmnd *
+ips_removeq_wait_head(ips_wait_queue_t *queue) {
+   Scsi_Cmnd  *item;
+
+   DBG("ips_removeq_wait_head");
+
+   item = queue->head;
+
+   if (!item)
+      return (NULL);
+
+   queue->head = (Scsi_Cmnd *) item->host_scribble;
+   item->host_scribble = NULL;
+
+   if (queue->tail == item)
+      queue->tail = NULL;
+
+   queue->count--;
+
+   return (item);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_removeq_wait                                           */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Remove an item from a queue                                            */
+/*                                                                          */
+/* ASSUMED to be called from within a lock                                  */
+/*                                                                          */
+/****************************************************************************/
+static inline Scsi_Cmnd *
+ips_removeq_wait(ips_wait_queue_t *queue, Scsi_Cmnd *item) {
+   Scsi_Cmnd  *p;
+
+   DBG("ips_removeq_wait");
+
+   if (!item)
+      return (NULL);
+
+   if (item == queue->head)
+      return (ips_removeq_wait_head(queue));
+
+   p = queue->head;
+
+   while ((p) && (item != (Scsi_Cmnd *) p->host_scribble))
+      p = (Scsi_Cmnd *) p->host_scribble;
+
+   if (p) {
+      /* found a match */
+      p->host_scribble = item->host_scribble;
+
+      if (!item->host_scribble)
+         queue->tail = p;
+
+      item->host_scribble = NULL;
+      queue->count--;
+
+      return (item);
+   }
+
+   return (NULL);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ipsintr_blocking                                           */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Finalize an interrupt for internal commands                            */
+/*                                                                          */
+/****************************************************************************/
+static void
+ipsintr_blocking(ips_ha_t *ha, ips_scb_t *scb) {
+   DBG("ipsintr_blocking");
+
+   if ((ha->waitflag == TRUE) &&
+       (ha->cmd_in_progress == scb->cdb[0])) {
+      ha->waitflag = FALSE;
+
+      return ;
+   }
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ipsintr_done                                               */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Finalize an interrupt for non-internal commands                        */
+/*                                                                          */
+/****************************************************************************/
+static void
+ipsintr_done(ips_ha_t *ha, ips_scb_t *scb) {
+   DBG("ipsintr_done");
+
+   if (scb->scsi_cmd == NULL) {
+      /* unexpected interrupt */
+      printk(KERN_WARNING "(%s%d) Spurious interrupt; scsi_cmd not set.\n",
+             ips_name, ha->host_num);
+
+      return;
+   }
+
+   ips_done(ha, scb);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_done                                                   */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Do housekeeping on completed commands                                  */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_done(ips_ha_t *ha, ips_scb_t *scb) {
+   int ret;
+
+   DBG("ips_done");
+
+   if (!scb)
+      return ;
+
+#ifndef NO_IPS_CMDLINE
+   if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd))) {
+      ips_cleanup_passthru(scb);
+      ha->num_ioctl--;
+   } else {
+#endif
+      /*
+       * Check to see if this command had too much
+       * data and had to be broke up.  If so, queue
+       * the rest of the data and continue.
+       */
+      if (scb->breakup) {
+         /* we had a data breakup */
+         u16 bk_save;
+
+         bk_save = scb->breakup;
+         scb->breakup = 0;
+
+         if (scb->scsi_cmd->use_sg) {
+            /* S/G request */
+            struct scatterlist *sg;
+            int                 i;
+
+            sg = scb->scsi_cmd->request_buffer;
+
+            scb->data_len = 0;
+
+            for (i = bk_save; i < scb->scsi_cmd->use_sg; i++) {
+               scb->sg_list[i - bk_save].address = VIRT_TO_BUS(sg[i].address);
+               scb->sg_list[i - bk_save].length = sg[i].length;
+
+               if (scb->data_len + sg[i].length > ha->max_xfer) {
+                  /*
+                   * Data Breakup required
+                   */
+                  scb->breakup = i;
+                  break;
+               }
+
+               scb->data_len += sg[i].length;
+            }
+
+            if (!scb->breakup)
+               scb->sg_len = scb->scsi_cmd->use_sg - bk_save;
+            else
+               scb->sg_len = scb->breakup - bk_save;
+
+            scb->dcdb.transfer_length = scb->data_len;
+            scb->data_busaddr = VIRT_TO_BUS(scb->sg_list);
+         } else {
+            /* Non S/G Request */
+            if (scb->scsi_cmd->request_bufflen - (bk_save * ha->max_xfer)) {
+               /* Further breakup required */
+               scb->data_len = ha->max_xfer;
+               scb->data_busaddr = VIRT_TO_BUS(scb->scsi_cmd->request_buffer + (bk_save * ha->max_xfer));
+               scb->breakup = bk_save + 1;
+            } else {
+               scb->data_len = scb->scsi_cmd->request_bufflen - (bk_save * ha->max_xfer);
+               scb->data_busaddr = VIRT_TO_BUS(scb->scsi_cmd->request_buffer + (bk_save * ha->max_xfer));
+            }
+
+            scb->dcdb.transfer_length = scb->data_len;
+            scb->sg_len = 0;
+         }
+
+         if ((scb->scsi_cmd->request.cmd == READ) && (scb->data_len))
+            scb->dcdb.cmd_attribute |= DATA_IN;
+
+         if ((scb->scsi_cmd->request.cmd == WRITE) && (scb->data_len))
+            scb->dcdb.cmd_attribute |= DATA_OUT;
+
+         if (scb->data_len >= IPS_MAX_XFER) {
+            scb->dcdb.cmd_attribute |= TRANSFER_64K;
+            scb->dcdb.transfer_length = 0;
+         }
+
+         ret = ips_send_cmd(ha, scb);
+
+         switch(ret) {
+         case IPS_FAILURE:
+            if (scb->scsi_cmd) {
+               scb->scsi_cmd->result = DID_ERROR << 16;
+               scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+            }
+
+            ips_freescb(ha, scb);
+            break;
+         case IPS_SUCCESS_IMM:
+            if (scb->scsi_cmd) {
+               scb->scsi_cmd->result = DID_ERROR << 16;
+               scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+            }
+
+            ips_freescb(ha, scb);
+            break;
+         default:
+            break;
+         } /* end case */
+
+         return ;
+      }
+#ifndef NO_IPS_CMDLINE
+   } /* end if passthru */
+#endif
+
+   /* call back to SCSI layer */
+   scb->scsi_cmd->scsi_done(scb->scsi_cmd);
+   ips_freescb(ha, scb);
+
+   /* do the next command */
+   ips_next(ha);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_map_status                                             */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Map ServeRAID error codes to Linux Error Codes                         */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_map_status(ips_scb_t *scb, ips_stat_t *sp) {
+   int       errcode;
+
+   DBG("ips_map_status");
+
+   if (scb->bus) {
+      /* copy SCSI status and sense data for DCDB commands */
+      memcpy(scb->scsi_cmd->sense_buffer, scb->dcdb.sense_info,
+             sizeof(scb->scsi_cmd->sense_buffer));
+      scb->scsi_cmd->result = scb->dcdb.scsi_status;
+   } else
+      scb->scsi_cmd->result = 0;
+
+   /* default driver error */
+   errcode = DID_ERROR;
+
+   switch (scb->basic_status & GSC_STATUS_MASK) {
+   case CMD_TIMEOUT:
+      errcode = DID_TIME_OUT;
+      break;
+
+   case INVAL_OPCO:
+   case INVAL_CMD_BLK:
+   case INVAL_PARM_BLK:
+   case LOG_DRV_ERROR:
+   case CMD_CMPLT_WERROR:
+      break;
+
+   case PHYS_DRV_ERROR:
+      /*
+       * For physical drive errors that
+       * are not on a logical drive should
+       * be DID_OK.  The SCSI errcode will
+       * show what the real error is.
+       */
+      if (scb->bus)
+         errcode = DID_OK;
+
+      switch (scb->extended_status) {
+      case SELECTION_TIMEOUT:
+         if (scb->bus) {
+            scb->scsi_cmd->result |= DID_TIME_OUT << 16;
+
+            return (0);
+         }
+         break;
+      case DATA_OVER_UNDER_RUN:
+         if ((scb->bus) && (scb->dcdb.transfer_length < scb->data_len)) {
+            if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
+                ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) == TYPE_DISK)) {
+               /* underflow -- no error               */
+               /* restrict access to physical DASD    */
+               errcode = DID_TIME_OUT;
+               break;
+            }
+
+            /* normal underflow Occured */
+            if (scb->dcdb.transfer_length >= scb->scsi_cmd->underflow) {
+               scb->scsi_cmd->result |= DID_OK << 16;
+
+               return (0);
+            }
+         }
+
+         break;
+      case EXT_RECOVERY:
+         /* don't fail recovered errors */
+         if (scb->bus) {
+            scb->scsi_cmd->result |= DID_OK << 16;
+
+            return (0);
+         }
+         break;
+
+      case EXT_HOST_RESET:
+      case EXT_DEVICE_RESET:
+         errcode = DID_RESET;
+         break;
+
+      case EXT_CHECK_CONDITION:
+         break;
+      } /* end switch */
+   } /* end switch */
+
+   scb->scsi_cmd->result |= (errcode << 16);
+
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_send                                                   */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Wrapper for ips_send_cmd                                               */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_send(ips_ha_t *ha, ips_scb_t *scb, scb_callback callback) {
+   int ret;
+
+   DBG("ips_send");
+
+   scb->callback = callback;
+
+   ret = ips_send_cmd(ha, scb);
+
+   return (ret);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_send_wait                                              */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Send a command to the controller and wait for it to return             */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_send_wait(ips_ha_t *ha, ips_scb_t *scb, int timeout) {
+   int       ret;
+
+   DBG("ips_send_wait");
+
+   ha->waitflag = TRUE;
+   ha->cmd_in_progress = scb->cdb[0];
+
+   ret = ips_send(ha, scb, ipsintr_blocking);
+
+   if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
+      return (ret);
+
+   ret = ips_wait(ha, timeout, IPS_INTR_OFF);
+
+   return (ret);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_send_cmd                                               */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Map SCSI commands to ServeRAID commands for logical drives             */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_send_cmd(ips_ha_t *ha, ips_scb_t *scb) {
+   int       ret;
+
+   DBG("ips_send_cmd");
+
+   ret = IPS_SUCCESS;
+
+   if (!scb->scsi_cmd) {
+      /* internal command */
+
+      if (scb->bus > 0) {
+         /* ServeRAID commands can't be issued */
+         /* to real devices -- fail them       */
+         if ((ha->waitflag == TRUE) &&
+             (ha->cmd_in_progress == scb->cdb[0])) {
+            ha->waitflag = FALSE;
+         }
+
+         return (1);
+      }
+#ifndef NO_IPS_CMDLINE
+   } else if ((scb->bus == 0) && (!ips_is_passthru(scb->scsi_cmd))) {
+#else
+   } else if (scb->bus == 0) {
+#endif
+      /* command to logical bus -- interpret */
+      ret = IPS_SUCCESS_IMM;
+
+      switch (scb->scsi_cmd->cmnd[0]) {
+      case ALLOW_MEDIUM_REMOVAL:
+      case REZERO_UNIT:
+      case ERASE:
+      case WRITE_FILEMARKS:
+      case SPACE:
+         scb->scsi_cmd->result = DID_ERROR << 16;
+         break;
+
+      case START_STOP:
+         scb->scsi_cmd->result = DID_OK << 16;
+
+      case TEST_UNIT_READY:
+      case INQUIRY:
+         if (scb->target_id == IPS_ADAPTER_ID) {
+            /*
+             * Either we have a TUR
+             * or we have a SCSI inquiry
+             */
+            if (scb->scsi_cmd->cmnd[0] == TEST_UNIT_READY)
+               scb->scsi_cmd->result = DID_OK << 16;
+
+            if (scb->scsi_cmd->cmnd[0] == INQUIRY) {
+               INQUIRYDATA inq;
+
+               memset(&inq, 0, sizeof(INQUIRYDATA));
+
+               inq.DeviceType = TYPE_PROCESSOR;
+               inq.DeviceTypeQualifier = 0;
+               inq.RemoveableMedia = 0;
+               inq.Versions = 0x1;  /* SCSI I */
+               inq.AdditionalLength = 31;
+               strncpy(inq.VendorId, "IBM     ", 8);
+               strncpy(inq.ProductId, "SERVERAID       ", 16);
+               strncpy(inq.ProductRevisionLevel, "1.00", 4);
+
+               memcpy(scb->scsi_cmd->request_buffer, &inq, scb->scsi_cmd->request_bufflen);
+
+               scb->scsi_cmd->result = DID_OK << 16;
+            }
+         } else {
+            scb->cmd.logical_info.op_code = GET_LOGICAL_DRIVE_INFO;
+            scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb);
+            scb->cmd.logical_info.buffer_addr = VIRT_TO_BUS(&ha->adapt->logical_drive_info);
+            scb->cmd.logical_info.reserved = 0;
+            scb->cmd.logical_info.reserved2 = 0;
+            ret = IPS_SUCCESS;
+         }
+
+         break;
+
+      case REQUEST_SENSE:
+         ips_reqsen(ha, scb);
+         scb->scsi_cmd->result = DID_OK << 16;
+         break;
+
+      case READ_6:
+      case WRITE_6:
+         if (!scb->sg_len) {
+            scb->cmd.basic_io.op_code =
+            (scb->scsi_cmd->cmnd[0] == READ_6) ? IPS_READ : IPS_WRITE;
+         } else {
+            scb->cmd.basic_io.op_code =
+            (scb->scsi_cmd->cmnd[0] == READ_6) ? READ_SCATTER_GATHER : WRITE_SCATTER_GATHER;
+         }
+
+         scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
+         scb->cmd.basic_io.log_drv = scb->target_id;
+         scb->cmd.basic_io.sg_count = scb->sg_len;
+         scb->cmd.basic_io.sg_addr = scb->data_busaddr;
+
+         if (scb->cmd.basic_io.lba)
+            scb->cmd.basic_io.lba += scb->cmd.basic_io.sector_count;
+         else
+            scb->cmd.basic_io.lba = (((scb->scsi_cmd->cmnd[1] & 0x1f) << 16) |
+                                     (scb->scsi_cmd->cmnd[2] << 8) |
+                                     (scb->scsi_cmd->cmnd[3]));
+
+         scb->cmd.basic_io.sector_count = scb->data_len / IPS_BLKSIZE;
+
+         if (scb->cmd.basic_io.sector_count == 0)
+            scb->cmd.basic_io.sector_count = 256;
+
+         scb->cmd.basic_io.reserved = 0;
+         ret = IPS_SUCCESS;
+         break;
+
+      case READ_10:
+      case WRITE_10:
+         if (!scb->sg_len) {
+            scb->cmd.basic_io.op_code =
+            (scb->scsi_cmd->cmnd[0] == READ_10) ? IPS_READ : IPS_WRITE;
+         } else {
+            scb->cmd.basic_io.op_code =
+            (scb->scsi_cmd->cmnd[0] == READ_10) ? READ_SCATTER_GATHER : WRITE_SCATTER_GATHER;
+         }
+
+         scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
+         scb->cmd.basic_io.log_drv = scb->target_id;
+         scb->cmd.basic_io.sg_count = scb->sg_len;
+         scb->cmd.basic_io.sg_addr = scb->data_busaddr;
+
+         if (scb->cmd.basic_io.lba)
+            scb->cmd.basic_io.lba += scb->cmd.basic_io.sector_count;
+         else
+            scb->cmd.basic_io.lba = ((scb->scsi_cmd->cmnd[2] << 24) |
+                                     (scb->scsi_cmd->cmnd[3] << 16) |
+                                     (scb->scsi_cmd->cmnd[4] << 8) |
+                                     scb->scsi_cmd->cmnd[5]);
+
+         scb->cmd.basic_io.sector_count = scb->data_len / IPS_BLKSIZE;
+
+         scb->cmd.basic_io.reserved = 0;
+
+         if (scb->cmd.basic_io.sector_count == 0) {
+            /*
+             * This is a null condition
+             * we don't have to do anything
+             * so just return
+             */
+            scb->scsi_cmd->result = DID_OK << 16;
+         } else
+            ret = IPS_SUCCESS;
+
+         break;
+
+      case RESERVE:
+      case RELEASE:
+         scb->scsi_cmd->result = DID_OK << 16;
+         break;
+
+      case MODE_SENSE:
+         scb->cmd.basic_io.op_code = ENQUIRY;
+         scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
+         scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->enq);
+         ret = IPS_SUCCESS;
+         break;
+
+      case READ_CAPACITY:
+         scb->cmd.logical_info.op_code = GET_LOGICAL_DRIVE_INFO;
+         scb->cmd.logical_info.command_id = IPS_COMMAND_ID(ha, scb);
+         scb->cmd.logical_info.buffer_addr = VIRT_TO_BUS(&ha->adapt->logical_drive_info);
+         scb->cmd.logical_info.reserved = 0;
+         scb->cmd.logical_info.reserved2 = 0;
+         scb->cmd.logical_info.reserved3 = 0;
+         ret = IPS_SUCCESS;
+         break;
+
+      case SEND_DIAGNOSTIC:
+      case REASSIGN_BLOCKS:
+      case FORMAT_UNIT:
+      case SEEK_10:
+      case VERIFY:
+      case READ_DEFECT_DATA:
+      case READ_BUFFER:
+      case WRITE_BUFFER:
+         scb->scsi_cmd->result = DID_OK << 16;
+         break;
+
+      default:
+         scb->scsi_cmd->result = DID_ERROR << 16;
+         break;
+      } /* end switch */
+   } /* end if */
+
+   if (ret == IPS_SUCCESS_IMM)
+      return (ret);
+
+   /* setup DCDB */
+   if (scb->bus > 0) {
+      if (!scb->sg_len)
+         scb->cmd.dcdb.op_code = DIRECT_CDB;
+      else
+         scb->cmd.dcdb.op_code = DIRECT_CDB_SCATTER_GATHER;
+
+      scb->cmd.dcdb.command_id = IPS_COMMAND_ID(ha, scb);
+      scb->cmd.dcdb.dcdb_address = VIRT_TO_BUS(&scb->dcdb);
+      scb->cmd.dcdb.reserved = 0;
+      scb->cmd.dcdb.reserved2 = 0;
+      scb->cmd.dcdb.reserved3 = 0;
+
+      scb->dcdb.device_address = ((scb->bus - 1) << 4) | scb->target_id;
+      scb->dcdb.cmd_attribute |= DISCONNECT_ALLOWED;
+
+      if (scb->timeout) {
+         if (scb->timeout <= 10)
+            scb->dcdb.cmd_attribute |= TIMEOUT_10;
+         else if (scb->timeout <= 60)
+            scb->dcdb.cmd_attribute |= TIMEOUT_60;
+         else
+            scb->dcdb.cmd_attribute |= TIMEOUT_20M;
+      }
+
+      if (!(scb->dcdb.cmd_attribute & TIMEOUT_20M))
+         scb->dcdb.cmd_attribute |= TIMEOUT_20M;
+
+      scb->dcdb.sense_length = sizeof(scb->scsi_cmd->sense_buffer);
+      scb->dcdb.buffer_pointer = scb->data_busaddr;
+      scb->dcdb.sg_count = scb->sg_len;
+      scb->dcdb.cdb_length = scb->scsi_cmd->cmd_len;
+      memcpy(scb->dcdb.scsi_cdb, scb->scsi_cmd->cmnd, scb->scsi_cmd->cmd_len);
+   }
+
+   return (ips_issue(ha, scb));
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_chk_status                                             */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Check the status of commands to logical drives                         */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_chkstatus(ips_ha_t *ha) {
+   ips_scb_t  *scb;
+   ips_stat_t *sp = &ha->sp;
+   u8          basic_status;
+   u8          ext_status;
+   int         command_id;
+   int         errcode;
+   int         ret;
+
+   DBG("ips_chkstatus");
+
+   command_id = ips_statupd(ha);
+
+   if (command_id > (MAX_CMDS-1)) {
+      printk(KERN_NOTICE "(%s%d) invalid command id received: %d\n",
+             ips_name, ha->host_num, command_id);
+
+      return (-1);
+   }
+
+   scb = &ha->scbs[command_id];
+   sp->scb_addr = (u32) scb;
+   sp->residue_len = 0;
+   scb->basic_status = basic_status = ha->adapt->p_status_tail->basic_status & BASIC_STATUS_MASK;
+   scb->extended_status = ext_status = ha->adapt->p_status_tail->extended_status;
+
+   /* Remove the item from the active queue */
+   ips_removeq_scb(&ha->scb_activelist, scb);
+
+   if (!scb->scsi_cmd)
+      /* internal commands are handled in do_ipsintr */
+      return (0);
+
+#ifndef NO_IPS_CMDLINE
+   if ((scb->scsi_cmd) && (ips_is_passthru(scb->scsi_cmd)))
+      /* passthru - just returns the raw result */
+      return (0);
+#endif
+
+   errcode = DID_OK;
+   ret = 0;
+
+   if (((basic_status & GSC_STATUS_MASK) == SSUCCESS) ||
+       ((basic_status & GSC_STATUS_MASK) == RECOVERED_ERROR)) {
+
+      if (scb->bus == 0) {
+#if IPS_DEBUG >= 1
+         if ((basic_status & GSC_STATUS_MASK) == RECOVERED_ERROR) {
+            printk(KERN_NOTICE "(%s%d) Recovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x\n",
+                   ips_name, ha->host_num,
+                   scb->cmd.basic_io.op_code, basic_status, ext_status);
+         }
+#endif
+
+         switch (scb->scsi_cmd->cmnd[0]) {
+         case ALLOW_MEDIUM_REMOVAL:
+         case REZERO_UNIT:
+         case ERASE:
+         case WRITE_FILEMARKS:
+         case SPACE:
+            errcode = DID_ERROR;
+            ret = 1;
+            break;
+
+         case START_STOP:
+            break;
+
+         case TEST_UNIT_READY:
+            if (!ips_online(ha, scb)) {
+               errcode = DID_TIME_OUT;
+               ret = 1;
+            }
+            break;
+
+         case INQUIRY:
+            if (ips_online(ha, scb)) {
+               ips_inquiry(ha, scb);
+            } else {
+               errcode = DID_TIME_OUT;
+               ret = 1;
+            }
+            break;
+
+         case REQUEST_SENSE:
+            ips_reqsen(ha, scb);
+            break;
+
+         case READ_6:
+         case WRITE_6:
+         case READ_10:
+         case WRITE_10:
+         case RESERVE:
+         case RELEASE:
+            break;
+
+         case MODE_SENSE:
+            if (!ips_online(ha, scb) || !ips_msense(ha, scb)) {
+               errcode = DID_ERROR;
+               ret = 1;
+            }
+            break;
+
+         case READ_CAPACITY:
+            if (ips_online(ha, scb))
+               ips_rdcap(ha, scb);
+            else {
+               errcode = DID_TIME_OUT;
+               ret = 1;
+            }
+            break;
+
+         case SEND_DIAGNOSTIC:
+         case REASSIGN_BLOCKS:
+            break;
+
+         case FORMAT_UNIT:
+            errcode = DID_ERROR;
+            ret = 1;
+            break;
+
+         case SEEK_10:
+         case VERIFY:
+         case READ_DEFECT_DATA:
+         case READ_BUFFER:
+         case WRITE_BUFFER:
+            break;
+
+         default:
+            errcode = DID_ERROR;
+            ret = 1;
+         } /* end switch */
+
+         scb->scsi_cmd->result = errcode << 16;
+      } else { /* bus == 0 */
+         /* restrict access to physical drives */
+         if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
+             ((((char *) scb->scsi_cmd->buffer)[0] & 0x1f) == TYPE_DISK)) {
+
+            scb->scsi_cmd->result = DID_TIME_OUT << 16;
+
+            ret = 1;
+         }
+      } /* else */
+   } else { /* recovered error / success */
+#if IPS_DEBUG >= 1
+      if (scb->bus == 0) {
+         printk(KERN_NOTICE "(%s%d) Unrecovered Logical Drive Error OpCode: %x, BSB: %x, ESB: %x\n",
+                ips_name, ha->host_num,
+                scb->cmd.basic_io.op_code, basic_status, ext_status);
+      }
+#endif
+
+      ret = ips_map_status(scb, sp);
+   } /* else */
+
+   return (ret);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_online                                                 */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Determine if a logical drive is online                                 */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_online(ips_ha_t *ha, ips_scb_t *scb) {
+   DBG("ips_online");
+
+   if (scb->target_id >= MAX_LOGICAL_DRIVES)
+      return (0);
+
+   if ((scb->basic_status & GSC_STATUS_MASK) > 1) {
+      memset(&ha->adapt->logical_drive_info, 0, sizeof(ha->adapt->logical_drive_info));
+
+      return (0);
+   }
+
+   if (scb->target_id < ha->adapt->logical_drive_info.no_of_log_drive &&
+       ha->adapt->logical_drive_info.drive_info[scb->target_id].state != OFF_LINE &&
+       ha->adapt->logical_drive_info.drive_info[scb->target_id].state != FREE &&
+       ha->adapt->logical_drive_info.drive_info[scb->target_id].state != CRS &&
+       ha->adapt->logical_drive_info.drive_info[scb->target_id].state != SYS)
+      return (1);
+   else
+      return (0);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_inquiry                                                */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Simulate an inquiry command to a logical drive                         */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_inquiry(ips_ha_t *ha, ips_scb_t *scb) {
+   INQUIRYDATA inq;
+
+   DBG("ips_inquiry");
+
+   memset(&inq, 0, sizeof(INQUIRYDATA));
+
+   inq.DeviceType = TYPE_DISK;
+   inq.DeviceTypeQualifier = 0;
+   inq.RemoveableMedia = 0;
+   inq.Versions = 0x1;  /* SCSI I */
+   inq.AdditionalLength = 31;
+   strncpy(inq.VendorId, "IBM     ", 8);
+   strncpy(inq.ProductId, "SERVERAID       ", 16);
+   strncpy(inq.ProductRevisionLevel, "1.00", 4);
+
+   memcpy(scb->scsi_cmd->request_buffer, &inq, scb->scsi_cmd->request_bufflen);
+
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_rdcap                                                  */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Simulate a read capacity command to a logical drive                    */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_rdcap(ips_ha_t *ha, ips_scb_t *scb) {
+   CAPACITY_T *cap;
+
+   DBG("ips_rdcap");
+
+   if (scb->scsi_cmd->bufflen < 8)
+      return (0);
+
+   cap = (CAPACITY_T *) scb->scsi_cmd->request_buffer;
+
+   cap->lba = htonl(ha->adapt->logical_drive_info.drive_info[scb->target_id].sector_count - 1);
+   cap->len = htonl((u32) IPS_BLKSIZE);
+
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_msense                                                 */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Simulate a mode sense command to a logical drive                       */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_msense(ips_ha_t *ha, ips_scb_t *scb) {
+   u16          heads;
+   u16          sectors;
+   u32          cylinders;
+   ips_mdata_t  mdata;
+
+   DBG("ips_msense");
+
+   if (ha->enq->ulDriveSize[scb->target_id] > 0x400000 &&
+       (ha->enq->ucMiscFlag & 0x8) == 0) {
+      heads = NORM_MODE_HEADS;
+      sectors = NORM_MODE_SECTORS;
+   } else {
+      heads = COMP_MODE_HEADS;
+      sectors = COMP_MODE_SECTORS;
+   }
+
+   cylinders = ha->enq->ulDriveSize[scb->target_id] / (heads * sectors);
+
+   mdata.plh.plh_type = 0;
+   mdata.plh.plh_wp = 0;
+   mdata.plh.plh_bdl = 8;
+
+   switch (scb->scsi_cmd->cmnd[2] & 0x3f) {
+   case 0x03: /* page 3 */
+      mdata.pdata.pg3.pg_pc = 0x3;
+      mdata.pdata.pg3.pg_res1 = 0;
+      mdata.pdata.pg3.pg_len = sizeof(DADF_T);
+      mdata.plh.plh_len = 3 + mdata.plh.plh_bdl + mdata.pdata.pg3.pg_len;
+      mdata.pdata.pg3.pg_trk_z = 0;
+      mdata.pdata.pg3.pg_asec_z = 0;
+      mdata.pdata.pg3.pg_atrk_z = 0;
+      mdata.pdata.pg3.pg_atrk_v = 0;
+      mdata.pdata.pg3.pg_sec_t = htons(sectors);
+      mdata.pdata.pg3.pg_bytes_s = htons(IPS_BLKSIZE);
+      mdata.pdata.pg3.pg_intl = htons(1);
+      mdata.pdata.pg3.pg_trkskew = 0;
+      mdata.pdata.pg3.pg_cylskew = 0;
+      mdata.pdata.pg3.pg_res2 = 0;
+      mdata.pdata.pg3.pg_ins = 0;
+      mdata.pdata.pg3.pg_surf = 0;
+      mdata.pdata.pg3.pg_rmb = 0;
+      mdata.pdata.pg3.pg_hsec = 0;
+      mdata.pdata.pg3.pg_ssec = 1;
+      break;
+
+   case 0x4:
+      mdata.pdata.pg4.pg_pc = 0x4;
+      mdata.pdata.pg4.pg_res1 = 0;
+      mdata.pdata.pg4.pg_len = sizeof(RDDG_T);
+      mdata.plh.plh_len = 3 + mdata.plh.plh_bdl + mdata.pdata.pg4.pg_len;
+      mdata.pdata.pg4.pg_cylu = (cylinders >> 8) & 0xffff;
+      mdata.pdata.pg4.pg_cyll = cylinders & 0xff;
+      mdata.pdata.pg4.pg_head = heads;
+      mdata.pdata.pg4.pg_wrpcompu = 0;
+      mdata.pdata.pg4.pg_wrpcompl = 0;
+      mdata.pdata.pg4.pg_redwrcur = 0;
+      mdata.pdata.pg4.pg_drstep = htons(1);
+      mdata.pdata.pg4.pg_landu = 0;
+      mdata.pdata.pg4.pg_landl = 0;
+      mdata.pdata.pg4.pg_res2 = 0;
+      break;
+   default:
+      return (0);
+   } /* end switch */
+
+   memcpy(scb->scsi_cmd->request_buffer, &mdata, scb->scsi_cmd->request_bufflen);
+
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_reqsen                                                 */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Simulate a request sense command to a logical drive                    */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_reqsen(ips_ha_t *ha, ips_scb_t *scb) {
+   char *sp;
+
+   DBG("ips_reqsen");
+
+   sp = (char *) scb->scsi_cmd->sense_buffer;
+   memset(sp, 0, sizeof(scb->scsi_cmd->sense_buffer));
+
+   sp[0] = 0x70;
+   sp[3] = NO_SENSE;
+   sp[7] = 0xe;
+   sp[12] = NO_SENSE;
+
+   return (0);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_free                                                   */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Free any allocated space for this controller                           */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_free(ips_ha_t *ha) {
+   int i;
+
+   DBG("ips_free");
+
+   if (ha) {
+      if (ha->enq) {
+         kfree(ha->enq);
+         ha->enq = NULL;
+      }
+
+      if (ha->conf) {
+         kfree(ha->conf);
+         ha->conf = NULL;
+      }
+
+      if (ha->adapt) {
+         kfree(ha->adapt);
+         ha->adapt = NULL;
+      }
+
+      if (ha->nvram) {
+         kfree(ha->nvram);
+         ha->nvram = NULL;
+      }
+
+      if (ha->subsys) {
+         kfree(ha->subsys);
+         ha->subsys = NULL;
+      }
+
+      if (ha->dummy) {
+         kfree(ha->dummy);
+         ha->dummy = NULL;
+      }
+
+      if (ha->scbs) {
+         for (i = 0; i < ha->max_cmds; i++) {
+            if (ha->scbs[i].sg_list)
+               kfree(ha->scbs[i].sg_list);
+         }
+
+         kfree(ha->scbs);
+         ha->scbs = NULL;
+      } /* end if */
+   }
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_allocatescbs                                           */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Allocate the command blocks                                            */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_allocatescbs(ips_ha_t *ha) {
+   ips_scb_t *scb_p;
+   int        i;
+
+   DBG("ips_allocatescbs");
+
+   /* Allocate memory for the CCBs */
+   ha->scbs = (ips_scb_t *) kmalloc(ha->max_cmds * sizeof(ips_scb_t), GFP_KERNEL|GFP_DMA);
+
+   memset(ha->scbs, 0, ha->max_cmds * sizeof(ips_scb_t));
+
+   for (i = 0; i < ha->max_cmds; i++) {
+      scb_p = &ha->scbs[i];
+
+      /* allocate S/G list */
+      scb_p->sg_list = (SG_LIST *) kmalloc(sizeof(SG_LIST) * MAX_SG_ELEMENTS, GFP_KERNEL|GFP_DMA);
+
+      if (! scb_p->sg_list)
+         return (0);
+
+      /* add to the free list */
+      if (i < ha->max_cmds - 1) {
+         scb_p->q_next = ha->scb_freelist;
+         ha->scb_freelist = scb_p;
+      }
+   }
+
+   /* success */
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_init_scb                                               */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Initialize a CCB to default values                                     */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_init_scb(ips_ha_t *ha, ips_scb_t *scb) {
+   SG_LIST *sg_list;
+
+   DBG("ips_init_scb");
+
+   if (scb == NULL)
+      return ;
+
+   sg_list = scb->sg_list;
+
+   /* zero fill */
+   memset(scb, 0, sizeof(ips_scb_t));
+   memset(ha->dummy, 0, sizeof(BASIC_IO_CMD));
+
+   /* Initialize dummy command bucket */
+   ha->dummy->op_code = 0xFF;
+   ha->dummy->ccsar = VIRT_TO_BUS(ha->dummy);
+   ha->dummy->command_id = MAX_CMDS;
+
+   /* set bus address of scb */
+   scb->scb_busaddr = VIRT_TO_BUS(scb);
+   scb->sg_list = sg_list;
+
+   /* Neptune Fix */
+   scb->cmd.basic_io.cccr = ILE;
+   scb->cmd.basic_io.ccsar = VIRT_TO_BUS(ha->dummy);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_get_scb                                                */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Initialize a CCB to default values                                     */
+/*                                                                          */
+/* ASSUMED to be callled from within a lock                                 */
+/*                                                                          */
+/****************************************************************************/
+static ips_scb_t *
+ips_getscb(ips_ha_t *ha) {
+   ips_scb_t     *scb;
+   unsigned int   cpu_flags;
+
+   DBG("ips_getscb");
+
+   spin_lock_irqsave(&ha->scb_lock, cpu_flags);
+   if ((scb = ha->scb_freelist) == NULL) {
+      spin_unlock_irqrestore(&ha->scb_lock, cpu_flags);
+
+      return (NULL);
+   }
+
+   ha->scb_freelist = scb->q_next;
+   scb->q_next = NULL;
+
+   spin_unlock_irqrestore(&ha->scb_lock, cpu_flags);
+
+   ips_init_scb(ha, scb);
+
+   return (scb);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_free_scb                                               */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Return an unused CCB back to the free list                             */
+/*                                                                          */
+/* ASSUMED to be called from within a lock                                  */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_freescb(ips_ha_t *ha, ips_scb_t *scb) {
+   unsigned int cpu_flags;
+
+   DBG("ips_freescb");
+
+   /* check to make sure this is not our "special" scb */
+   if (IPS_COMMAND_ID(ha, scb) < (ha->max_cmds - 1)) {
+      spin_lock_irqsave(&ha->scb_lock, cpu_flags);
+      scb->q_next = ha->scb_freelist;
+      ha->scb_freelist = scb;
+      spin_unlock_irqrestore(&ha->scb_lock, cpu_flags);
+   }
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_reset_adapter                                          */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Reset the controller                                                   */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_reset_adapter(ips_ha_t *ha) {
+   u8  Isr;
+   u8  Cbsp;
+   u8  PostByte[MAX_POST_BYTES];
+   u8  ConfigByte[MAX_CONFIG_BYTES];
+   int i, j;
+   int reset_counter;
+
+   DBG("ips_reset_adapter");
+
+#if IPS_DEBUG >= 1
+   printk(KERN_WARNING "ips_reset_adapter: io addr: %x, irq: %d\n",
+          ha->io_addr, ha->irq);
+#endif
+
+   reset_counter = 0;
+
+   while (reset_counter < 2) {
+      reset_counter++;
+
+      outb(RST, ha->io_addr + SCPR);
+      MDELAY(ONE_SEC);
+      outb(0, ha->io_addr + SCPR);
+      MDELAY(ONE_SEC);
+
+      for (i = 0; i < MAX_POST_BYTES; i++) {
+         for (j = 0; j < 45; j++) {
+            Isr = inb(ha->io_addr + HISR);
+            if (Isr & GHI)
+               break;
+
+            MDELAY(ONE_SEC);
+         }
+
+         if (j >= 45) {
+            /* error occured */
+            if (reset_counter < 2)
+               continue;
+            else
+               /* reset failed */
+               return (0);
+         }
+
+         PostByte[i] = inb(ha->io_addr + ISPR);
+         outb(Isr, ha->io_addr + HISR);
+      }
+
+      if (PostByte[0] < GOOD_POST_BASIC_STATUS) {
+         printk("(%s%d) reset controller fails (post status %x %x).\n",
+                ips_name, ha->host_num, PostByte[0], PostByte[1]);
+
+         return (0);
+      }
+
+      for (i = 0; i < MAX_CONFIG_BYTES; i++) {
+         for (j = 0; j < 240; j++) {
+            Isr = inb(ha->io_addr + HISR);
+            if (Isr & GHI)
+               break;
+
+            MDELAY(ONE_SEC); /* 100 msec */
+         }
+
+         if (j >= 240) {
+            /* error occured */
+            if (reset_counter < 2)
+               continue;
+            else
+               /* reset failed */
+               return (0);
+         }
+
+         ConfigByte[i] = inb(ha->io_addr + ISPR);
+         outb(Isr, ha->io_addr + HISR);
+      }
+
+      if (ConfigByte[0] == 0 && ConfigByte[1] == 2) {
+         printk("(%s%d) reset controller fails (status %x %x).\n",
+                ips_name, ha->host_num, ConfigByte[0], ConfigByte[1]);
+
+         return (0);
+      }
+
+      for (i = 0; i < 240; i++) {
+         Cbsp = inb(ha->io_addr + CBSP);
+
+         if ((Cbsp & OP) == 0)
+            break;
+
+         MDELAY(ONE_SEC);
+      }
+
+      if (i >= 240) {
+         /* error occured */
+         if (reset_counter < 2)
+            continue;
+         else
+            /* reset failed */
+            return (0);
+      }
+
+      /* setup CCCR */
+      outw(0x1010, ha->io_addr + CCCR);
+
+      /* Enable busmastering */
+      outb(EBM, ha->io_addr + SCPR);
+
+      /* setup status queues */
+      ips_statinit(ha);
+
+      /* Enable interrupts */
+      outb(EI, ha->io_addr + HISR);
+
+      /* if we get here then everything went OK */
+      break;
+   }
+
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_statinit                                               */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Initialize the status queues on the controller                         */
+/*                                                                          */
+/****************************************************************************/
+static void
+ips_statinit(ips_ha_t *ha) {
+   u32        phys_status_start;
+
+   DBG("ips_statinit");
+
+   ha->adapt->p_status_start = ha->adapt->status;
+   ha->adapt->p_status_end = ha->adapt->status + MAX_CMDS;
+   ha->adapt->p_status_tail = ha->adapt->status;
+
+   phys_status_start = VIRT_TO_BUS(ha->adapt->status);
+   outl(phys_status_start, ha->io_addr + SQSR);
+   outl(phys_status_start + STATUS_Q_SIZE, ha->io_addr + SQER);
+   outl(phys_status_start + STATUS_SIZE, ha->io_addr + SQHR);
+   outl(phys_status_start, ha->io_addr + SQTR);
+
+   ha->adapt->hw_status_start = phys_status_start;
+   ha->adapt->hw_status_tail = phys_status_start;
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_statupd                                                */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Remove an element from the status queue                                */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_statupd(ips_ha_t *ha) {
+   int       command_id;
+
+   DBG("ips_statupd");
+
+   if (ha->adapt->p_status_tail != ha->adapt->p_status_end) {
+      ha->adapt->p_status_tail++;
+      ha->adapt->hw_status_tail += sizeof(STATUS);
+   } else {
+      ha->adapt->p_status_tail = ha->adapt->p_status_start;
+      ha->adapt->hw_status_tail = ha->adapt->hw_status_start;
+   }
+
+   outl(ha->adapt->hw_status_tail, ha->io_addr + SQTR);
+
+   command_id = ha->adapt->p_status_tail->command_id;
+
+   return (command_id);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_issue                                                  */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Send a command down to the controller                                  */
+/*                                                                          */
+/* ASSUMED to be called from within a lock                                  */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_issue(ips_ha_t *ha, ips_scb_t *scb) {
+   u32       TimeOut;
+   u16       val;
+
+   DBG("ips_issue");
+
+#if IPS_DEBUG >= 10
+   if (scb->scsi_cmd)
+      printk(KERN_NOTICE "%s: ips_issue: cmd 0x%X id %d (%d %d %d)\n",
+             ips_name,
+             scb->cdb[0],
+             scb->cmd.basic_io.command_id,
+             scb->bus,
+             scb->target_id,
+             scb->lun);
+   else
+      printk(KERN_NOTICE "%s: ips_issue: logical cmd id %d\n",
+             ips_name,
+             scb->cmd.basic_io.command_id);
+#if IPS_DEBUG >= 11
+      MDELAY(ONE_SEC);
+#endif
+#endif
+
+   TimeOut = 0;
+
+   while ((val = inw(ha->io_addr + CCCR)) & SEMAPHORE) {
+      UDELAY(1000);
+
+      if (++TimeOut >= SEMAPHORE_TIMEOUT) {
+         if (!(val & START_STOP_BIT))
+            break;
+
+         printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].\n",
+                ips_name, ha->host_num, val);
+         printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n",
+                ips_name, ha->host_num);
+
+         return (IPS_FAILURE);
+      } /* end if */
+   } /* end while */
+
+   outl(scb->scb_busaddr, ha->io_addr + CCSAR);
+   outw(START_COMMAND, ha->io_addr + CCCR);
+
+   return (IPS_SUCCESS);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_isintr                                                 */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Test to see if an interrupt is for us                                  */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_isintr(ips_ha_t *ha) {
+   u8 Isr;
+
+   DBG("ips_isintr");
+
+   Isr = inb(ha->io_addr + HISR);
+
+   if (Isr == 0xFF)
+      /* ?!?! Nothing really there */
+      return (0);
+
+   if (Isr & SCE)
+      return (1);
+   else if (Isr & (SQO | GHI)) {
+      /* status queue overflow or GHI */
+      /* just clear the interrupt */
+      outb(Isr, ha->io_addr + HISR);
+   }
+
+   return (0);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_wait                                                   */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Wait for a command to complete                                         */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_wait(ips_ha_t *ha, int time, int intr) {
+   int        ret;
+
+   DBG("ips_wait");
+
+   ret = IPS_FAILURE;
+
+   time *= ONE_SEC; /* convert seconds to milliseconds */
+
+   while (time > 0) {
+      if (intr == IPS_INTR_OFF) {
+         if (ha->waitflag == FALSE) {
+            /*
+             * controller generated an interupt to
+             * acknowledge completion of the command
+             * and ips_intr() has serviced the interrupt.
+             */
+            ret = IPS_SUCCESS;
+            break;
+         }
+
+         /*
+          * NOTE: Interrupts are disabled here
+          * On an SMP system interrupts will only
+          * be disabled on one processor.
+          * So, ultimately we still need to set the
+          * "I'm in the interrupt handler flag"
+          */
+         while (test_and_set_bit(IPS_IN_INTR, &ha->flags))
+            UDELAY(1000);
+
+         ips_intr(ha);
+
+         clear_bit(IPS_IN_INTR, &ha->flags);
+
+      } else {
+         if (ha->waitflag == FALSE) {
+            ret = IPS_SUCCESS;
+            break;
+         }
+      }
+
+      UDELAY(1000); /* 1 milisecond */
+      time--;
+   }
+
+   return (ret);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_write_driver_status                                    */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Write OS/Driver version to Page 5 of the nvram on the controller       */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_write_driver_status(ips_ha_t *ha) {
+   DBG("ips_write_driver_status");
+
+   if (!ips_readwrite_page5(ha, FALSE)) {
+      printk(KERN_WARNING "(%s%d) unable to read NVRAM page 5.\n",
+             ips_name, ha->host_num);
+
+      return (0);
+   }
+
+   /* check to make sure the page has a valid */
+   /* signature */
+   if (ha->nvram->signature != NVRAM_PAGE5_SIGNATURE) {
+#if IPS_DEBUG >= 1
+      printk("(%s%d) NVRAM page 5 has an invalid signature: %X.\n",
+             ips_name, ha->host_num, ha->nvram->signature);
+#endif
+      return (1);
+   }
+
+#if IPS_DEBUG >= 2
+   printk("(%s%d) Ad Type: %d, Ad Slot: %d, BIOS: %c%c%c%c %c%c%c%c.\n",
+          ips_name, ha->host_num, ha->nvram->adapter_type, ha->nvram->adapter_slot,
+          ha->nvram->bios_high[0], ha->nvram->bios_high[1],
+          ha->nvram->bios_high[2], ha->nvram->bios_high[3],
+          ha->nvram->bios_low[0], ha->nvram->bios_low[1],
+          ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
+#endif
+
+   /* save controller type */
+   ha->ad_type = ha->nvram->adapter_type;
+
+   /* change values (as needed) */
+   ha->nvram->operating_system = OS_LINUX;
+   strncpy((char *) ha->nvram->driver_high, IPS_VERSION_HIGH, 4);
+   strncpy((char *) ha->nvram->driver_low, IPS_VERSION_LOW, 4);
+
+   /* now update the page */
+   if (!ips_readwrite_page5(ha, TRUE)) {
+      printk(KERN_WARNING "(%s%d) unable to write NVRAM page 5.\n",
+             ips_name, ha->host_num);
+
+      return (0);
+   }
+
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_read_adapter_status                                    */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Do an Inquiry command to the adapter                                   */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_read_adapter_status(ips_ha_t *ha) {
+   ips_scb_t *scb;
+   int        ret;
+
+   DBG("ips_read_adapter_status");
+
+   scb = &ha->scbs[ha->max_cmds-1];
+
+   ips_init_scb(ha, scb);
+
+   scb->timeout = ips_cmd_timeout;
+   scb->cdb[0] = ENQUIRY;
+
+   scb->cmd.basic_io.op_code = ENQUIRY;
+   scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
+   scb->cmd.basic_io.sg_count = 0;
+   scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->enq);
+   scb->cmd.basic_io.lba = 0;
+   scb->cmd.basic_io.sector_count = 0;
+   scb->cmd.basic_io.log_drv = 0;
+   scb->cmd.basic_io.reserved = 0;
+
+   /* send command */
+   ret = ips_send_wait(ha, scb, ips_cmd_timeout);
+   if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
+      return (0);
+
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_read_subsystem_parameters                              */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Read subsystem parameters from the adapter                             */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_read_subsystem_parameters(ips_ha_t *ha) {
+   ips_scb_t *scb;
+   int        ret;
+
+   DBG("ips_read_subsystem_parameters");
+
+   scb = &ha->scbs[ha->max_cmds-1];
+
+   ips_init_scb(ha, scb);
+
+   scb->timeout = ips_cmd_timeout;
+   scb->cdb[0] = GET_SUBSYS_PARAM;
+
+   scb->cmd.basic_io.op_code = GET_SUBSYS_PARAM;
+   scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
+   scb->cmd.basic_io.sg_count = 0;
+   scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->subsys);
+   scb->cmd.basic_io.lba = 0;
+   scb->cmd.basic_io.sector_count = 0;
+   scb->cmd.basic_io.log_drv = 0;
+   scb->cmd.basic_io.reserved = 0;
+
+   /* send command */
+   ret = ips_send_wait(ha, scb, ips_cmd_timeout);
+   if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
+      return (0);
+
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_read_config                                            */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Read the configuration on the adapter                                  */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_read_config(ips_ha_t *ha) {
+   ips_scb_t *scb;
+   int        i;
+   int        ret;
+
+   DBG("ips_read_config");
+
+   /* set defaults for initiator IDs */
+   ha->conf->init_id[0] = IPS_ADAPTER_ID;
+   for (i = 1; i < 4; i++)
+      ha->conf->init_id[i] = 7;
+
+   scb = &ha->scbs[ha->max_cmds-1];
+
+   ips_init_scb(ha, scb);
+
+   scb->timeout = ips_cmd_timeout;
+   scb->cdb[0] = READ_NVRAM_CONFIGURATION;
+
+   scb->cmd.basic_io.op_code = READ_NVRAM_CONFIGURATION;
+   scb->cmd.basic_io.command_id = IPS_COMMAND_ID(ha, scb);
+   scb->cmd.basic_io.sg_addr = VIRT_TO_BUS(ha->conf);
+
+   /* send command */
+   if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout)) == IPS_FAILURE) ||
+       (ret == IPS_SUCCESS_IMM) ||
+       ((scb->basic_status & GSC_STATUS_MASK) > 1)) {
+
+      memset(ha->conf, 0, sizeof(CONFCMD));
+
+      /* reset initiator IDs */
+      ha->conf->init_id[0] = IPS_ADAPTER_ID;
+      for (i = 1; i < 4; i++)
+         ha->conf->init_id[i] = 7;
+
+      return (0);
+   }
+
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_readwrite_page5                                        */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Read the configuration on the adapter                                  */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_readwrite_page5(ips_ha_t *ha, int write) {
+   ips_scb_t *scb;
+   int        ret;
+
+   DBG("ips_readwrite_page5");
+
+   scb = &ha->scbs[ha->max_cmds-1];
+
+   ips_init_scb(ha, scb);
+
+   scb->timeout = ips_cmd_timeout;
+   scb->cdb[0] = RW_NVRAM_PAGE;
+
+   scb->cmd.nvram.op_code = RW_NVRAM_PAGE;
+   scb->cmd.nvram.command_id = IPS_COMMAND_ID(ha, scb);
+   scb->cmd.nvram.page = 5;
+   scb->cmd.nvram.write = write;
+   scb->cmd.nvram.buffer_addr = VIRT_TO_BUS(ha->nvram);
+   scb->cmd.nvram.reserved = 0;
+   scb->cmd.nvram.reserved2 = 0;
+
+   /* issue the command */
+   if (((ret = ips_send_wait(ha, scb, ips_cmd_timeout)) == IPS_FAILURE) ||
+       (ret == IPS_SUCCESS_IMM) ||
+       ((scb->basic_status & GSC_STATUS_MASK) > 1)) {
+
+      memset(ha->nvram, 0, sizeof(NVRAM_PAGE5));
+
+      return (0);
+   }
+
+   return (1);
+}
+
+/****************************************************************************/
+/*                                                                          */
+/* Routine Name: ips_clear_adapter                                          */
+/*                                                                          */
+/* Routine Description:                                                     */
+/*                                                                          */
+/*   Clear the stripe lock tables                                           */
+/*                                                                          */
+/****************************************************************************/
+static int
+ips_clear_adapter(ips_ha_t *ha) {
+   ips_scb_t *scb;
+   int        ret;
+
+   DBG("ips_clear_adapter");
+
+   scb = &ha->scbs[ha->max_cmds-1];
+
+   ips_init_scb(ha, scb);
+
+   scb->timeout = ips_reset_timeout;
+   scb->cdb[0] = CONFIG_SYNC;
+
+   scb->cmd.config_sync.op_code = CONFIG_SYNC;
+   scb->cmd.config_sync.command_id = IPS_COMMAND_ID(ha, scb);
+   scb->cmd.config_sync.channel = 0;
+   scb->cmd.config_sync.source_target = POCL;
+   scb->cmd.config_sync.reserved = 0;
+   scb->cmd.config_sync.reserved2 = 0;
+   scb->cmd.config_sync.reserved3 = 0;
+
+   /* issue command */
+   ret = ips_send_wait(ha, scb, ips_reset_timeout);
+   if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
+      return (0);
+
+   /* send unlock stripe command */
+   ips_init_scb(ha, scb);
+
+   scb->cdb[0] = GET_ERASE_ERROR_TABLE;
+   scb->timeout = ips_reset_timeout;
+
+   scb->cmd.unlock_stripe.op_code = GET_ERASE_ERROR_TABLE;
+   scb->cmd.unlock_stripe.command_id = IPS_COMMAND_ID(ha, scb);
+   scb->cmd.unlock_stripe.log_drv = 0;
+   scb->cmd.unlock_stripe.control = CSL;
+   scb->cmd.unlock_stripe.reserved = 0;
+   scb->cmd.unlock_stripe.reserved2 = 0;
+   scb->cmd.unlock_stripe.reserved3 = 0;
+
+   /* issue command */
+   ret = ips_send_wait(ha, scb, ips_reset_timeout);
+   if ((ret == IPS_FAILURE) || (ret == IPS_SUCCESS_IMM))
+      return (0);
+
+   return (1);
+}
+
+#if defined (MODULE)
+
+Scsi_Host_Template driver_template = IPS;
+
+   #include "scsi_module.c"
+
+#endif
+
+
+/*
+ * Overrides for Emacs so that we almost 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: 2
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -2
+ * c-argdecl-indent: 2
+ * c-label-offset: -2
+ * c-continued-statement-offset: 2
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/ips.h linux/drivers/scsi/ips.h
--- v2.3.15/linux/drivers/scsi/ips.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/ips.h	Tue Aug 31 16:12:42 1999
@@ -0,0 +1,838 @@
+/*****************************************************************************/
+/* ips.h -- driver for the IBM ServeRAID adapter                             */
+/*                                                                           */
+/* Written By: Keith Mitchell, IBM Corporation                               */
+/*                                                                           */
+/* Copyright (C) 1999 IBM Corporation                                        */
+/*                                                                           */
+/* This program is free software; you can redistribute it and/or modify      */
+/* it under the terms of the GNU General Public License as published by      */
+/* the Free Software Foundation; either version 2 of the License, or         */
+/* (at your option) any later version.                                       */
+/*                                                                           */
+/* This program is distributed in the hope that it will be useful,           */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
+/* GNU General Public License for more details.                              */
+/*                                                                           */
+/* NO WARRANTY                                                               */
+/* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR        */
+/* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT      */
+/* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,      */
+/* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is    */
+/* solely responsible for determining the appropriateness of using and       */
+/* distributing the Program and assumes all risks associated with its        */
+/* exercise of rights under this Agreement, including but not limited to     */
+/* the risks and costs of program errors, damage to or loss of data,         */
+/* programs or equipment, and unavailability or interruption of operations.  */
+/*                                                                           */
+/* DISCLAIMER OF LIABILITY                                                   */
+/* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY   */
+/* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL        */
+/* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND   */
+/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     */
+/* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE    */
+/* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED  */
+/* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES             */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License         */
+/* along with this program; if not, write to the Free Software               */
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+/*                                                                           */
+/* Bugs/Comments/Suggestions should be mailed to:                            */
+/*      ipslinux@us.ibm.com                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef _IPS_H_
+   #define _IPS_H_
+
+   #include <linux/config.h>
+   #include <asm/uaccess.h>
+   #include <asm/io.h>
+
+   /* Prototypes */
+   extern int ips_detect(Scsi_Host_Template *);
+   extern int ips_release(struct Scsi_Host *);
+   extern int ips_abort(Scsi_Cmnd *);
+   extern int ips_reset(Scsi_Cmnd *, unsigned int);
+   extern int ips_eh_abort(Scsi_Cmnd *);
+   extern int ips_eh_reset(Scsi_Cmnd *);
+   extern int ips_queue(Scsi_Cmnd *, void (*) (Scsi_Cmnd *));
+   extern int ips_biosparam(Disk *, kdev_t, int *);
+   extern const char * ips_info(struct Scsi_Host *);
+   extern void do_ipsintr(int, void *, struct pt_regs *);
+
+   /*
+    * Some handy macros
+    */
+   #ifndef LinuxVersionCode
+      #define LinuxVersionCode(x,y,z)   (((x)<<16)+((y)<<8)+(z))
+   #endif
+
+   #define HA(x)                       ((ips_ha_t *) x->hostdata)
+   #define IPS_COMMAND_ID(ha, scb)     (int) (scb - ha->scbs)
+   #define VIRT_TO_BUS(x)              (unsigned int)virt_to_bus((void *) x)
+
+   #define UDELAY udelay
+   #define MDELAY mdelay
+
+   #define verify_area_20(t,a,sz)               (0) /* success */
+   #define PUT_USER                             put_user
+   #define __PUT_USER                           __put_user
+   #define PUT_USER_RET                         put_user_ret
+   #define GET_USER                             get_user
+   #define __GET_USER                           __get_user
+   #define GET_USER_RET                         get_user_ret
+
+/*
+ * Adapter address map equates
+ */
+   #define HISR                 0x08    /* Host Interrupt Status Reg   */
+   #define CCSAR                0x10    /* Cmd Channel System Addr Reg */
+   #define CCCR                 0x14    /* Cmd Channel Control Reg     */
+   #define SQHR                 0x20    /* Status Q Head Reg           */
+   #define SQTR                 0x24    /* Status Q Tail Reg           */
+   #define SQER                 0x28    /* Status Q End Reg            */
+   #define SQSR                 0x2C    /* Status Q Start Reg          */
+   #define SCPR                 0x05    /* Subsystem control port reg  */
+   #define ISPR                 0x06    /* interrupt status port reg   */
+   #define CBSP                 0x07    /* CBSP register               */
+
+/*
+ * Adapter register bit equates
+ */
+   #define GHI                  0x04    /* HISR General Host Interrupt */
+   #define SQO                  0x02    /* HISR Status Q Overflow      */
+   #define SCE                  0x01    /* HISR Status Channel Enqueue */
+   #define SEMAPHORE            0x08    /* CCCR Semaphore Bit          */
+   #define ILE                  0x10    /* CCCR ILE Bit                */
+   #define START_COMMAND        0x101A  /* CCCR Start Command Channel  */
+   #define START_STOP_BIT       0x0002  /* CCCR Start/Stop Bit         */
+   #define RST                  0x80    /* SCPR Reset Bit              */
+   #define EBM                  0x02    /* SCPR Enable Bus Master      */
+   #define EI                   0x80    /* HISR Enable Interrupts      */
+   #define OP                   0x01    /* OP bit in CBSP              */
+
+/*
+ * Adapter Command ID Equates
+ */
+   #define GET_LOGICAL_DRIVE_INFO               0x19
+   #define GET_SUBSYS_PARAM                     0x40
+   #define READ_NVRAM_CONFIGURATION             0x38
+   #define RW_NVRAM_PAGE                        0xBC
+   #define IPS_READ                             0x02
+   #define IPS_WRITE                            0x03
+   #define ENQUIRY                              0x05
+   #define FLUSH_CACHE                          0x0A
+   #define NORM_STATE                           0x00
+   #define READ_SCATTER_GATHER                  0x82
+   #define WRITE_SCATTER_GATHER                 0x83
+   #define DIRECT_CDB                           0x04
+   #define DIRECT_CDB_SCATTER_GATHER            0x84
+   #define CONFIG_SYNC                          0x58
+   #define POCL                                 0x30
+   #define GET_ERASE_ERROR_TABLE                0x17
+   #define RESET_CHANNEL                        0x1A
+   #define CSL                                  0xFF
+   #define ADAPT_RESET                          0xFF
+
+/*
+ * Adapter Equates
+ */
+   #define IPS_MAX_ADAPTERS                     16
+   #define IPS_MAX_IOCTL                        1
+   #define IPS_MAX_IOCTL_QUEUE                  8
+   #define IPS_MAX_QUEUE                        128
+   #define IPS_BLKSIZE                          512
+   #define MAX_SG_ELEMENTS                      17
+   #define MAX_LOGICAL_DRIVES                   8
+   #define MAX_CHANNELS                         3
+   #define MAX_TARGETS                          15
+   #define MAX_CHUNKS                           16
+   #define MAX_CMDS                             64
+   #define IPS_MAX_XFER                         0x10000
+   #define COMP_MODE_HEADS                      128
+   #define COMP_MODE_SECTORS                    32
+   #define NORM_MODE_HEADS                      254
+   #define NORM_MODE_SECTORS                    63
+   #define NVRAM_PAGE5_SIGNATURE                0xFFDDBB99
+   #define MAX_POST_BYTES                       0x02
+   #define MAX_CONFIG_BYTES                     0x02
+   #define GOOD_POST_BASIC_STATUS               0x80
+   #define SEMAPHORE_TIMEOUT                    2000
+   #define IPS_INTR_OFF                         0
+   #define IPS_INTR_ON                          1
+   #define IPS_ADAPTER_ID                       0xF
+   #define IPS_VENDORID                         0x1014
+   #define IPS_DEVICEID                         0x002E
+   #define TIMEOUT_10                           0x10
+   #define TIMEOUT_60                           0x20
+   #define TIMEOUT_20M                          0x30
+   #define STATUS_SIZE                          4
+   #define STATUS_Q_SIZE                        (MAX_CMDS+1) * STATUS_SIZE
+   #define ONE_MSEC                             1
+   #define ONE_SEC                              1000
+
+/*
+ * Adapter Basic Status Codes
+ */
+   #define BASIC_STATUS_MASK            0xFF
+   #define GSC_STATUS_MASK              0x0F
+   #define SSUCCESS                     0x00
+   #define RECOVERED_ERROR              0x01
+   #define IPS_CHECK_CONDITION          0x02
+   #define INVAL_OPCO                   0x03
+   #define INVAL_CMD_BLK                0x04
+   #define INVAL_PARM_BLK               0x05
+   #define IPS_BUSY                     0x08
+   #define ADAPT_HARDWARE_ERROR         0x09
+   #define ADAPT_FIRMWARE_ERROR         0x0A
+   #define CMD_CMPLT_WERROR             0x0C
+   #define LOG_DRV_ERROR                0x0D
+   #define CMD_TIMEOUT                  0x0E
+   #define PHYS_DRV_ERROR               0x0F
+
+/*
+ * Adapter Extended Status Equates
+ */
+   #define SELECTION_TIMEOUT                    0xF0
+   #define DATA_OVER_UNDER_RUN                  0xF2
+   #define EXT_HOST_RESET                       0xF7
+   #define EXT_DEVICE_RESET                     0xF8
+   #define EXT_RECOVERY                         0xFC
+   #define EXT_CHECK_CONDITION                  0xFF
+
+/*
+ * Operating System Defines
+ */
+   #define OS_WINDOWS_NT                        0x01
+   #define OS_NETWARE                           0x02
+   #define OS_OPENSERVER                        0x03
+   #define OS_UNIXWARE                          0x04
+   #define OS_SOLARIS                           0x05
+   #define OS_OS2                               0x06
+   #define OS_LINUX                             0x07
+   #define OS_FREEBSD                           0x08
+
+/*
+ * Adapter Command/Status Packet Definitions
+ */
+   #define IPS_SUCCESS                  0x01 /* Successfully completed       */
+   #define IPS_SUCCESS_IMM              0x02 /* Success - Immediately        */
+   #define IPS_FAILURE                  0x04 /* Completed with Error         */
+
+/*
+ * Logical Drive Equates
+ */
+   #define OFF_LINE             0x02
+   #define OKAY                 0x03
+   #define FREE                 0x00
+   #define SYS                  0x06
+   #define CRS                  0x24
+
+/*
+ * DCDB Table Equates
+ */
+   #define NO_DISCONNECT                0x00
+   #define DISCONNECT_ALLOWED           0x80
+   #define NO_AUTO_REQUEST_SENSE        0x40
+   #define DATA_IN                      0x01
+   #define DATA_OUT                     0x02
+   #define TRANSFER_64K                 0x08
+   #define NOTIMEOUT                    0x00
+   #define TIMEOUT10                    0x10
+   #define TIMEOUT60                    0x20
+   #define TIMEOUT20M                   0x30
+
+/*
+ * Host adapter Flags (bit numbers)
+ */
+   #define IPS_IN_INTR                  0
+   #define IPS_IN_ABORT                 1
+   #define IPS_IN_RESET                 2
+
+/*
+ * SCB Flags
+ */
+   #define SCB_ACTIVE                   0x00001
+   #define SCB_WAITING                  0x00002
+
+/*
+ * Passthru stuff
+ */
+   #define COPPUSRCMD                  (('C'<<8) | 65)
+   #define IPS_NUMCTRLS                (('C'<<8) | 68)
+   #define IPS_CTRLINFO                (('C'<<8) | 69)
+
+/*
+ * Scsi_Host Template
+ */
+ #define IPS {                            \
+    next : NULL,                          \
+    module : NULL,                        \
+    proc_dir : NULL,                      \
+    proc_info : NULL,                     \
+    name : NULL,                          \
+    detect : ips_detect,                  \
+    release : ips_release,                \
+    info : ips_info,                      \
+    command : NULL,                       \
+    queuecommand : ips_queue,             \
+    eh_strategy_handler : NULL,           \
+    eh_abort_handler : ips_eh_abort,      \
+    eh_device_reset_handler : NULL,       \
+    eh_bus_reset_handler : NULL,          \
+    eh_host_reset_handler : ips_eh_reset, \
+    abort : ips_abort,                    \
+    reset : ips_reset,                    \
+    slave_attach : NULL,                  \
+    bios_param : ips_biosparam,           \
+    can_queue : 0,                        \
+    this_id: -1,                          \
+    sg_tablesize : MAX_SG_ELEMENTS,       \
+    cmd_per_lun: 16,                      \
+    present : 0,                          \
+    unchecked_isa_dma : 0,                \
+    use_clustering : ENABLE_CLUSTERING,   \
+    use_new_eh_code : 1                   \
+ }
+
+/*
+ * IBM PCI Raid Command Formats
+ */
+typedef struct {
+   u8        op_code;
+   u8        command_id;
+   u8        log_drv;
+   u8        sg_count;
+   u32       lba;
+   u32       sg_addr;
+   u16       sector_count;
+   u16       reserved;
+   u32       ccsar;
+   u32       cccr;
+} BASIC_IO_CMD, *PBASIC_IO_CMD;
+
+typedef struct {
+   u8        op_code;
+   u8        command_id;
+   u16       reserved;
+   u32       reserved2;
+   u32       buffer_addr;
+   u32       reserved3;
+   u32       ccsar;
+   u32       cccr;
+} LOGICAL_INFO, *PLOGICAL_INFO;
+
+typedef struct {
+   u8        op_code;
+   u8        command_id;
+   u8        reserved;
+   u8        reserved2;
+   u32       reserved3;
+   u32       buffer_addr;
+   u32       reserved4;
+} IOCTL_INFO, *PIOCTL_INFO;
+
+typedef struct {
+   u8        op_code;
+   u8        command_id;
+   u16       reserved;
+   u32       reserved2;
+   u32       dcdb_address;
+   u32       reserved3;
+   u32       ccsar;
+   u32       cccr;
+} DCDB_CMD, *PDCDB_CMD;
+
+typedef struct {
+   u8        op_code;
+   u8        command_id;
+   u8        channel;
+   u8        source_target;
+   u32       reserved;
+   u32       reserved2;
+   u32       reserved3;
+   u32       ccsar;
+   u32       cccr;
+} CONFIG_SYNC_CMD, *PCONFIG_SYNC_CMD;
+
+typedef struct {
+   u8        op_code;
+   u8        command_id;
+   u8        log_drv;
+   u8        control;
+   u32       reserved;
+   u32       reserved2;
+   u32       reserved3;
+   u32       ccsar;
+   u32       cccr;
+} UNLOCK_STRIPE_CMD, *PUNLOCK_STRIPE_CMD;
+
+typedef struct {
+   u8        op_code;
+   u8        command_id;
+   u8        reserved;
+   u8        state;
+   u32       reserved2;
+   u32       reserved3;
+   u32       reserved4;
+   u32       ccsar;
+   u32       cccr;
+} FLUSH_CACHE_CMD, *PFLUSH_CACHE_CMD;
+
+typedef struct {
+   u8        op_code;
+   u8        command_id;
+   u8        reserved;
+   u8        desc;
+   u32       reserved2;
+   u32       buffer_addr;
+   u32       reserved3;
+   u32       ccsar;
+   u32       cccr;
+} STATUS_CMD, *PSTATUS_CMD;
+
+typedef struct {
+   u8        op_code;
+   u8        command_id;
+   u8        page;
+   u8        write;
+   u32       reserved;
+   u32       buffer_addr;
+   u32       reserved2;
+   u32       ccsar;
+   u32       cccr;
+} NVRAM_CMD, *PNVRAM_CMD;
+
+typedef union {
+   BASIC_IO_CMD      basic_io;
+   LOGICAL_INFO      logical_info;
+   IOCTL_INFO        ioctl_info;
+   DCDB_CMD          dcdb;
+   CONFIG_SYNC_CMD   config_sync;
+   UNLOCK_STRIPE_CMD unlock_stripe;
+   FLUSH_CACHE_CMD   flush_cache;
+   STATUS_CMD        status;
+   NVRAM_CMD         nvram;
+} HOST_COMMAND, *PHOST_COMMAND;
+
+typedef struct {
+   u8         logical_id;
+   u8         reserved;
+   u8         raid_level;
+   u8         state;
+   u32        sector_count;
+} DRIVE_INFO, *PDRIVE_INFO;
+
+typedef struct {
+   u8         no_of_log_drive;
+   u8         reserved[3];
+   DRIVE_INFO drive_info[MAX_LOGICAL_DRIVES];
+} LOGICAL_DRIVE_INFO, *PLOGICAL_DRIVE_INFO;
+
+typedef struct {
+   u8        ha_num;
+   u8        bus_num;
+   u8        id;
+   u8        device_type;
+   u32       data_len;
+   u32       data_ptr;
+   u8        scsi_cdb[12];
+   u32       data_counter;
+   u32       block_size;
+} NON_DISK_DEVICE_INFO, *PNON_DISK_DEVICE_INFO;
+
+typedef struct {
+   u8         device_address;
+   u8         cmd_attribute;
+   u16        transfer_length;
+   u32        buffer_pointer;
+   u8         cdb_length;
+   u8         sense_length;
+   u8         sg_count;
+   u8         reserved;
+   u8         scsi_cdb[12];
+   u8         sense_info[64];
+   u8         scsi_status;
+   u8         reserved2[3];
+} DCDB_TABLE, *PDCDB_TABLE;
+
+typedef struct {
+   volatile u8      reserved;
+   volatile u8      command_id;
+   volatile u8      basic_status;
+   volatile u8      extended_status;
+} STATUS, *PSTATUS;
+
+typedef struct {
+   STATUS               status[MAX_CMDS + 1];
+   volatile PSTATUS     p_status_start;
+   volatile PSTATUS     p_status_end;
+   volatile PSTATUS     p_status_tail;
+   volatile u32         hw_status_start;
+   volatile u32         hw_status_tail;
+   LOGICAL_DRIVE_INFO   logical_drive_info;
+} ADAPTER_AREA, *PADAPTER_AREA;
+
+typedef struct {
+   u8        ucLogDriveCount;
+   u8        ucMiscFlag;
+   u8        ucSLTFlag;
+   u8        ucBSTFlag;
+   u8        ucPwrChgCnt;
+   u8        ucWrongAdrCnt;
+   u8        ucUnidentCnt;
+   u8        ucNVramDevChgCnt;
+   u8        CodeBlkVersion[8];
+   u8        BootBlkVersion[8];
+   u32       ulDriveSize[MAX_LOGICAL_DRIVES];
+   u8        ucConcurrentCmdCount;
+   u8        ucMaxPhysicalDevices;
+   u16       usFlashRepgmCount;
+   u8        ucDefunctDiskCount;
+   u8        ucRebuildFlag;
+   u8        ucOfflineLogDrvCount;
+   u8        ucCriticalDrvCount;
+   u16       usConfigUpdateCount;
+   u8        ucBlkFlag;
+   u8        reserved;
+   u16       usAddrDeadDisk[MAX_CHANNELS * MAX_TARGETS];
+} ENQCMD, *PENQCMD;
+
+typedef struct {
+   u8        ucInitiator;
+   u8        ucParameters;
+   u8        ucMiscFlag;
+   u8        ucState;
+   u32       ulBlockCount;
+   u8        ucDeviceId[28];
+} DEVSTATE, *PDEVSTATE;
+
+typedef struct {
+   u8        ucChn;
+   u8        ucTgt;
+   u16       ucReserved;
+   u32       ulStartSect;
+   u32       ulNoOfSects;
+} CHUNK, *PCHUNK;
+
+typedef struct {
+   u16       ucUserField;
+   u8        ucState;
+   u8        ucRaidCacheParam;
+   u8        ucNoOfChunkUnits;
+   u8        ucStripeSize;
+   u8        ucParams;
+   u8        ucReserved;
+   u32       ulLogDrvSize;
+   CHUNK     chunk[MAX_CHUNKS];
+} LOGICAL_DRIVE, *PLOGICAL_DRIVE;
+
+typedef struct {
+   u8        board_disc[8];
+   u8        processor[8];
+   u8        ucNoChanType;
+   u8        ucNoHostIntType;
+   u8        ucCompression;
+   u8        ucNvramType;
+   u32       ulNvramSize;
+} HARDWARE_DISC, *PHARDWARE_DISC;
+
+typedef struct {
+   u8             ucLogDriveCount;
+   u8             ucDateD;
+   u8             ucDateM;
+   u8             ucDateY;
+   u8             init_id[4];
+   u8             host_id[12];
+   u8             time_sign[8];
+
+   struct {
+      u32         usCfgDrvUpdateCnt:16;
+      u32         ConcurDrvStartCnt:4;
+      u32         StartupDelay:4;
+      u32         auto_rearrange:1;
+      u32         cd_boot:1;
+      u32         cluster:1;
+      u32         reserved:5;
+   } UserOpt;
+
+   u16            user_field;
+   u8             ucRebuildRate;
+   u8             ucReserve;
+   HARDWARE_DISC  hardware_disc;
+   LOGICAL_DRIVE  logical_drive[MAX_LOGICAL_DRIVES];
+   DEVSTATE       dev[MAX_CHANNELS][MAX_TARGETS+1];
+   u8             reserved[512];
+
+} CONFCMD, *PCONFCMD;
+
+typedef struct {
+   u32        signature;
+   u8         reserved;
+   u8         adapter_slot;
+   u16        adapter_type;
+   u8         bios_high[4];
+   u8         bios_low[4];
+   u16        reserved2;
+   u8         reserved3;
+   u8         operating_system;
+   u8         driver_high[4];
+   u8         driver_low[4];
+   u8         reserved4[100];
+} NVRAM_PAGE5, *PNVRAM_PAGE5;
+
+typedef struct _SUBSYS_PARAM {
+   u32        param[128];
+} SUBSYS_PARAM, *PSUBSYS_PARAM;
+
+/*
+ * Inquiry Data Format
+ */
+typedef struct {
+   u8        DeviceType:5;
+   u8        DeviceTypeQualifier:3;
+   u8        DeviceTypeModifier:7;
+   u8        RemoveableMedia:1;
+   u8        Versions;
+   u8        ResponseDataFormat;
+   u8        AdditionalLength;
+   u16       Reserved;
+   u8        SoftReset:1;
+   u8        CommandQueue:1;
+   u8        Reserved2:1;
+   u8        LinkedCommands:1;
+   u8        Synchronous:1;
+   u8        Wide16Bit:1;
+   u8        Wide32Bit:1;
+   u8        RelativeAddressing:1;
+   u8        VendorId[8];
+   u8        ProductId[16];
+   u8        ProductRevisionLevel[4];
+   u8        VendorSpecific[20];
+   u8        Reserved3[40];
+} INQUIRYDATA, *PINQUIRYDATA;
+
+/*
+ * Read Capacity Data Format
+ */
+typedef struct {
+   u32       lba;
+   u32       len;
+} CAPACITY_T;
+
+/*
+ * Sense Data Format
+ */
+typedef struct {
+   u8        pg_pc:6;       /* Page Code                    */
+   u8        pg_res1:2;     /* Reserved                     */
+   u8        pg_len;        /* Page Length                  */
+   u16       pg_trk_z;      /* Tracks per zone              */
+   u16       pg_asec_z;     /* Alternate sectors per zone   */
+   u16       pg_atrk_z;     /* Alternate tracks per zone    */
+   u16       pg_atrk_v;     /* Alternate tracks per volume  */
+   u16       pg_sec_t;      /* Sectors per track            */
+   u16       pg_bytes_s;    /* Bytes per physical sectors   */
+   u16       pg_intl;       /* Interleave                   */
+   u16       pg_trkskew;    /* Track skew factor            */
+   u16       pg_cylskew;    /* Cylinder Skew Factor         */
+   u32       pg_res2:27;    /* Reserved                     */
+   u32       pg_ins:1;      /* Inhibit Slave                */
+   u32       pg_surf:1;     /* Allocate Surface Sectors     */
+   u32       pg_rmb:1;      /* Removeable                   */
+   u32       pg_hsec:1;     /* Hard sector formatting       */
+   u32       pg_ssec:1;     /* Soft sector formatting       */
+} DADF_T;
+
+typedef struct {
+   u8        pg_pc:6;        /* Page Code                     */
+   u8        pg_res1:2;      /* Reserved                      */
+   u8        pg_len;         /* Page Length                   */
+   u16       pg_cylu;        /* Number of cylinders (upper)   */
+   u8        pg_cyll;        /* Number of cylinders (lower)   */
+   u8        pg_head;        /* Number of heads               */
+   u16       pg_wrpcompu;    /* Write precomp (upper)         */
+   u32       pg_wrpcompl:8;  /* Write precomp (lower)         */
+   u32       pg_redwrcur:24; /* Reduced write current         */
+   u32       pg_drstep:16;   /* Drive step rate               */
+   u32       pg_landu:16;    /* Landing zone cylinder (upper) */
+   u32       pg_landl:8;     /* Landing zone cylinder (lower) */
+   u32       pg_res2:24;     /* Reserved                      */
+} RDDG_T;
+
+struct blk_desc {
+   u8       bd_dencode;
+   u8       bd_nblks1;
+   u8       bd_nblks2;
+   u8       bd_nblks3;
+   u8       bd_res;
+   u8       bd_blen1;
+   u8       bd_blen2;
+   u8       bd_blen3;
+};
+
+typedef struct {
+   u8       plh_len;   /* Data length             */
+   u8       plh_type;  /* Medium type             */
+   u8       plh_res:7; /* Reserved                */
+   u8       plh_wp:1;  /* Write protect           */
+   u8       plh_bdl;   /* Block descriptor length */
+} SENSE_PLH_T;
+
+typedef struct {
+   SENSE_PLH_T     plh;
+   struct blk_desc blk_desc;
+
+   union {
+      DADF_T        pg3;
+      RDDG_T        pg4;
+   } pdata;
+} ips_mdata_t;
+
+/*
+ * Scatter Gather list format
+ */
+typedef struct ips_sglist {
+   u32       address;
+   u32       length;
+} SG_LIST, *PSG_LIST;
+
+typedef struct _INFOSTR {
+   char *buffer;
+   int   length;
+   int   offset;
+   int   pos;
+} INFOSTR;
+
+/*
+ * Status Info
+ */
+typedef struct ips_stat {
+   u32       residue_len;
+   u32       scb_addr;
+} ips_stat_t;
+
+/*
+ * SCB Queue Format
+ */
+typedef struct ips_scb_queue {
+   struct ips_scb *head;
+   struct ips_scb *tail;
+   unsigned int    count;
+} ips_scb_queue_t;
+
+/*
+ * Wait queue_format
+ */
+typedef struct ips_wait_queue {
+   Scsi_Cmnd      *head;
+   Scsi_Cmnd      *tail;
+   unsigned int    count;
+} ips_wait_queue_t;
+
+typedef struct ips_ha {
+   u8                 ha_id[MAX_CHANNELS+1];
+   u32                io_addr;            /* Base I/O address           */
+   u8                 irq;                /* IRQ for adapter            */
+   u8                 ntargets;           /* Number of targets          */
+   u8                 nbus;               /* Number of buses            */
+   u8                 nlun;               /* Number of Luns             */
+   u16                ad_type;            /* Adapter type               */
+   u16                host_num;           /* Adapter number             */
+   u32                max_xfer;           /* Maximum Xfer size          */
+   u32                max_cmds;           /* Max concurrent commands    */
+   u32                num_ioctl;          /* Number of Ioctls           */
+   ips_stat_t         sp;                 /* Status packer pointer      */
+   struct ips_scb    *scbs;               /* Array of all CCBS          */
+   struct ips_scb    *scb_freelist;       /* SCB free list              */
+   ips_wait_queue_t   scb_waitlist;       /* Pending SCB list           */
+   ips_wait_queue_t   copp_waitlist;      /* Pending PT list            */
+   ips_scb_queue_t    scb_activelist;     /* Active SCB list            */
+   BASIC_IO_CMD      *dummy;              /* dummy command              */
+   ADAPTER_AREA      *adapt;              /* Adapter status area        */
+   ENQCMD            *enq;                /* Adapter Enquiry data       */
+   CONFCMD           *conf;               /* Adapter config data        */
+   NVRAM_PAGE5       *nvram;              /* NVRAM page 5 data          */
+   SUBSYS_PARAM      *subsys;             /* Subsystem parameters       */
+   u32                cmd_in_progress;    /* Current command in progress*/
+   u32                flags;              /* HA flags                   */
+   u8                 waitflag;           /* are we waiting for cmd     */
+   u8                 active;
+   u32                reserved:16;        /* reserved space             */
+   wait_queue_head_t  copp_queue;         /* passthru sync queue        */
+
+   #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0)
+   spinlock_t         scb_lock;
+   spinlock_t         copp_lock;
+   #endif
+} ips_ha_t;
+
+typedef void (*scb_callback) (ips_ha_t *, struct ips_scb *);
+
+/*
+ * SCB Format
+ */
+typedef struct ips_scb {
+   HOST_COMMAND      cmd;
+   DCDB_TABLE        dcdb;
+   u8                target_id;
+   u8                bus;
+   u8                lun;
+   u8                cdb[12];
+   u32               scb_busaddr;
+   u32               data_busaddr;
+   u32               timeout;
+   u8                basic_status;
+   u8                extended_status;
+   u16               breakup;
+   u32               data_len;
+   u32               sg_len;
+   u32               flags;
+   u32               op_code;
+   SG_LIST          *sg_list;
+   Scsi_Cmnd        *scsi_cmd;
+   struct ips_scb   *q_next;
+   scb_callback      callback;
+} ips_scb_t;
+
+/*
+ * Passthru Command Format
+ */
+typedef struct {
+   u8         CoppID[4];
+   u32        CoppCmd;
+   u32        PtBuffer;
+   u8        *CmdBuffer;
+   u32        CmdBSize;
+   ips_scb_t  CoppCP;
+   u32        TimeOut;
+   u8         BasicStatus;
+   u8         ExtendedStatus;
+   u16        reserved;
+} ips_passthru_t;
+
+#endif
+
+
+
+/*
+ * Overrides for Emacs so that we almost 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: 2
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -2
+ * c-argdecl-indent: 2
+ * c-label-offset: -2
+ * c-continued-statement-offset: 2
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/mesh.c linux/drivers/scsi/mesh.c
--- v2.3.15/linux/drivers/scsi/mesh.c	Wed Dec 30 10:55:07 1998
+++ linux/drivers/scsi/mesh.c	Tue Aug 31 11:35:59 1999
@@ -40,6 +40,8 @@
  * - retry arbitration if lost (unless higher levels do this for us)
  */
 
+#define MESH_NEW_STYLE_EH
+
 #if 1
 #undef KERN_DEBUG
 #define KERN_DEBUG KERN_WARNING
@@ -151,10 +153,12 @@
 	u8	msgout[16];
 	struct dbdma_cmd *dma_cmds;	/* space for dbdma commands, aligned */
 	int	clk_freq;
+	struct mesh_target tgts[8];
+#ifndef MESH_NEW_STYLE_EH
 	Scsi_Cmnd *completed_q;
 	Scsi_Cmnd *completed_qtail;
-	struct mesh_target tgts[8];
 	struct tq_struct tqueue;
+#endif
 #ifdef MESH_DBG
 	int	log_ix;
 	int	n_log;
@@ -186,7 +190,9 @@
 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 *);
+#ifndef MESH_NEW_STYLE_EH
 static void finish_cmds(void *);
+#endif
 static void add_sdtr_msg(struct mesh_state *);
 static void set_sdtr(struct mesh_state *, int, int);
 static void start_phase(struct mesh_state *);
@@ -252,8 +258,10 @@
 			continue;
 		}
 		mesh_host->unique_id = nmeshes;
+#ifndef MODULE
 		note_scsi_host(mesh, mesh_host);
-		
+#endif
+
 		ms = (struct mesh_state *) mesh_host->hostdata;
 		if (ms == 0)
 			panic("no mesh state");
@@ -282,10 +290,10 @@
 			ms->tgts[tgt].sync_params = ASYNC_PARAMS;
 			ms->tgts[tgt].current_req = 0;
 		}
-
+#ifndef MESH_NEW_STYLE_EH
 		ms->tqueue.routine = finish_cmds;
 		ms->tqueue.data = ms;
-
+#endif
 		*prev_statep = ms;
 		prev_statep = &ms->next;
 
@@ -428,7 +436,9 @@
 	{
 		handle_reset(ms);
 		restore_flags(flags);
+#ifndef MESH_NEW_STYLE_EH
 		finish_cmds(ms);
+#endif
 		ret |= SCSI_RESET_SUCCESS;
 	}
 	return ret;
@@ -677,6 +687,7 @@
 	}
 }
 
+#ifndef MESH_NEW_STYLE_EH
 static void
 finish_cmds(void *data)
 {
@@ -685,18 +696,18 @@
 	unsigned long flags;
 
 	for (;;) {
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&io_request_lock, flags);
 		cmd = ms->completed_q;
 		if (cmd == NULL) {
-			restore_flags(flags);
+			spin_unlock_irqrestore(&io_request_lock, flags);
 			break;
 		}
 		ms->completed_q = (Scsi_Cmnd *) cmd->host_scribble;
-		restore_flags(flags);
 		(*cmd->scsi_done)(cmd);
+		spin_unlock_irqrestore(&io_request_lock, flags);
 	}
 }
+#endif /* MESH_NEW_STYLE_EH */
 
 static inline void
 add_sdtr_msg(struct mesh_state *ms)
@@ -762,8 +773,8 @@
 	Scsi_Cmnd *cmd = ms->current_req;
 	struct mesh_target *tp = &ms->tgts[ms->conn_tgt];
 
-	dlog(ms, "start_phase err/exc/fc/seq = %.8x",
-	     MKWORD(mr->error, mr->exception, mr->fifo_count, mr->sequence));
+	dlog(ms, "start_phase nmo/exc/fc/seq = %.8x",
+	     MKWORD(ms->n_msgout, mr->exception, mr->fifo_count, mr->sequence));
 	out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE);
 	seq = use_active_neg + (ms->n_msgout? SEQ_ATN: 0);
 	switch (ms->msgphase) {
@@ -1057,6 +1068,7 @@
 			t = 230;		/* wait up to 230us */
 			while ((mr->bus_status0 & BS0_REQ) == 0) {
 				if (--t < 0) {
+					dlog(ms, "impatient for req", ms->n_msgout);
 					ms->msgphase = msg_none;
 					break;
 				}
@@ -1643,7 +1655,9 @@
 static void
 mesh_completed(struct mesh_state *ms, Scsi_Cmnd *cmd)
 {
-#if 0
+#ifdef MESH_NEW_STYLE_EH
+	(*cmd->scsi_done)(cmd);
+#else
 	if (ms->completed_q == NULL)
 		ms->completed_q = cmd;
 	else
@@ -1652,9 +1666,7 @@
 	cmd->host_scribble = NULL;
 	queue_task(&ms->tqueue, &tq_immediate);
 	mark_bh(IMMEDIATE_BH);
-#else
-	(*cmd->scsi_done)(cmd);
-#endif
+#endif /* MESH_NEW_STYLE_EH */
 }
 
 /*
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/mesh.h linux/drivers/scsi/mesh.h
--- v2.3.15/linux/drivers/scsi/mesh.h	Sun Dec 21 17:04:49 1997
+++ linux/drivers/scsi/mesh.h	Tue Aug 31 11:35:59 1999
@@ -28,6 +28,7 @@
 	sg_tablesize:	SG_ALL,				\
 	cmd_per_lun:	2,				\
 	use_clustering:	DISABLE_CLUSTERING,		\
+	use_new_eh_code: 1,				\
 }
 
 /*
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.3.15/linux/drivers/scsi/ncr53c8xx.c	Mon Aug 16 10:33:58 1999
+++ linux/drivers/scsi/ncr53c8xx.c	Tue Aug 31 11:25:33 1999
@@ -146,9 +146,6 @@
 #ifndef	__initdata
 #define	__initdata
 #endif
-#ifndef	__initfunc
-#define	__initfunc(__arginit) __arginit
-#endif
 #endif
 
 #if LINUX_VERSION_CODE <= LinuxVersionCode(2,1,92)
@@ -9578,8 +9575,10 @@
 static int __init 
 pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
 {
-	*base = pdev->resource[++index].start;
-	return index;
+	*base = pdev->resource[index].start;
+	if ((pdev->resource[index].flags & 0x7) == 0x4)
+		++index;
+	return ++index;
 }
 
 /*
@@ -9764,9 +9763,6 @@
 	 *	each and every PCI card, if they don't use Fcode?
 	 */
 
-	base = __pa(base);
-	base_2 = __pa(base_2);
-
 	if (!(command & PCI_COMMAND_MASTER)) {
 		if (initverbose >= 2)
 			printk("ncr53c8xx: setting PCI_COMMAND_MASTER bit (fixup)\n");
@@ -9807,28 +9803,16 @@
 
 	/*
 	 * Check availability of IO space, memory space and master capability.
+	 * No need to test BARs flags since they are hardwired to the
+	 * expected value.
 	 */
-	if (command & PCI_COMMAND_IO) { 
-		if ((io_port & 3) != 1) {
-			printk("ncr53c8xx: disabling I/O mapping since base address 0 (0x%x)\n"
-				"           bits 0..1 indicate a non-IO mapping\n", (int) io_port);
-			io_port = 0;
-		}
-		else
-			io_port &= PCI_BASE_ADDRESS_IO_MASK;
-	}
+	if (command & PCI_COMMAND_IO)
+		io_port &= PCI_BASE_ADDRESS_IO_MASK;
 	else
 		io_port = 0;
 
-	if (command & PCI_COMMAND_MEMORY) {
-		if ((base & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
-			printk("ncr53c8xx: disabling memory mapping since base address 1\n"
-				"            contains a non-memory mapping\n");
-			base = 0;
-		}
-		else 
-			base &= PCI_BASE_ADDRESS_MEM_MASK;
-	}
+	if (command & PCI_COMMAND_MEMORY)
+		base &= PCI_BASE_ADDRESS_MEM_MASK;
 	else
 		base = 0;
 	
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/pluto.c linux/drivers/scsi/pluto.c
--- v2.3.15/linux/drivers/scsi/pluto.c	Wed May 12 08:41:15 1999
+++ linux/drivers/scsi/pluto.c	Tue Aug 31 11:23:03 1999
@@ -58,18 +58,18 @@
 
 static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
 
-__initfunc(static void pluto_detect_timeout(unsigned long data))
+static void __init pluto_detect_timeout(unsigned long data)
 {
 	PLND(("Timeout\n"))
 	up(&fc_sem);
 }
 
-__initfunc(static void pluto_detect_done(Scsi_Cmnd *SCpnt))
+static void __init pluto_detect_done(Scsi_Cmnd *SCpnt)
 {
 	/* Do nothing */
 }
 
-__initfunc(static void pluto_detect_scsi_done(Scsi_Cmnd *SCpnt))
+static void __init pluto_detect_scsi_done(Scsi_Cmnd *SCpnt)
 {
 	SCpnt->request.rq_status = RQ_SCSI_DONE;
 	PLND(("Detect done %08lx\n", (long)SCpnt))
@@ -92,7 +92,7 @@
 
 /* Detect all SSAs attached to the machine.
    To be fast, do it on all online FC channels at the same time. */
-__initfunc(int pluto_detect(Scsi_Host_Template *tpnt))
+int __init pluto_detect(Scsi_Host_Template *tpnt)
 {
 	int i, retry, nplutos;
 	fc_channel *fc;
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/qlogicfc.c linux/drivers/scsi/qlogicfc.c
--- v2.3.15/linux/drivers/scsi/qlogicfc.c	Thu Aug 26 13:05:39 1999
+++ linux/drivers/scsi/qlogicfc.c	Mon Aug 30 10:25:30 1999
@@ -635,7 +635,8 @@
 #define AS_FIRMWARE_DEAD      -1
 #define AS_LOOP_DOWN           0
 #define AS_LOOP_GOOD           1
-#define AS_REDO_PORTDB         2
+#define AS_REDO_FABRIC_PORTDB  2
+#define AS_REDO_LOOP_PORTDB    4
 
 struct isp2x00_hostdata {
 	u_char revision;
@@ -965,30 +966,31 @@
 	}
 	printk("qlogicfc%d : Fabric found.\n", hostdata->host_id);
 
-
-	memset(&req, 0, sizeof(req));
-	
-	req.len = 8;
-	req.response_low = virt_to_bus_low32(sns_response);
-	req.response_high = virt_to_bus_high32(sns_response);
-	req.sub_len = 22;
-	req.data[0] = 0x17;
-	req.data[1] = 0x02;
-	req.data[8] = (u_char) (hostdata->port_id & 0xff);
-	req.data[9] = (u_char) (hostdata->port_id >> 8 & 0xff);
-	req.data[10] = (u_char) (hostdata->port_id >> 16 & 0xff);
-	req.data[13] = 0x01;
-	param[0] = MBOX_SEND_SNS;
-	param[1] = 30;
-	param[2] = virt_to_bus_low32(&req) >> 16;
-	param[3] = virt_to_bus_low32(&req);
-	param[6] = virt_to_bus_high32(&req) >> 16;
-	param[7] = virt_to_bus_high32(&req);
+	if (hostdata->adapter_state & AS_REDO_LOOP_PORTDB){
+	        memset(&req, 0, sizeof(req));
 	
-	isp2x00_mbox_command(host, param);
+		req.len = 8;
+		req.response_low = virt_to_bus_low32(sns_response);
+		req.response_high = virt_to_bus_high32(sns_response);
+		req.sub_len = 22;
+		req.data[0] = 0x17;
+		req.data[1] = 0x02;
+		req.data[8] = (u_char) (hostdata->port_id & 0xff);
+		req.data[9] = (u_char) (hostdata->port_id >> 8 & 0xff);
+		req.data[10] = (u_char) (hostdata->port_id >> 16 & 0xff);
+		req.data[13] = 0x01;
+		param[0] = MBOX_SEND_SNS;
+		param[1] = 30;
+		param[2] = virt_to_bus_low32(&req) >> 16;
+		param[3] = virt_to_bus_low32(&req);
+		param[6] = virt_to_bus_high32(&req) >> 16;
+		param[7] = virt_to_bus_high32(&req);
+		
+		isp2x00_mbox_command(host, param);
 	
-	if (param[0] != MBOX_COMMAND_COMPLETE)
-	        printk("qlogicfc%d : error sending RFC-4\n", hostdata->host_id);	       
+		if (param[0] != MBOX_COMMAND_COMPLETE)
+		        printk("qlogicfc%d : error sending RFC-4\n", hostdata->host_id);	       
+	}
 
 	port_id = hostdata->port_id;
 	while (!done) {
@@ -1131,9 +1133,9 @@
 
 	DEBUG(isp2x00_print_scsi_cmd(Cmnd));
 
-	if (hostdata->adapter_state == AS_REDO_PORTDB) {
-		hostdata->adapter_state = AS_LOOP_GOOD;
+	if (hostdata->adapter_state & AS_REDO_FABRIC_PORTDB || hostdata->adapter_state & AS_REDO_LOOP_PORTDB) {
 		isp2x00_make_portdb(host);
+		hostdata->adapter_state = AS_LOOP_GOOD;
 		printk("qlogicfc%d : Port Database\n", hostdata->host_id);
 		for (i = 0; hostdata->port_db[i].wwn != 0; i++) {
 			printk("wwn: %08x%08x  scsi_id: %x  loop_id: %x\n", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i, hostdata->port_db[i].loop_id);
@@ -1270,6 +1272,9 @@
 	}
 
 	switch (Cmnd->cmnd[0]) {
+	case TEST_UNIT_READY:
+	case START_STOP:
+	        break;
 	case WRITE_10:
 	case WRITE_6:
 	case WRITE_BUFFER:
@@ -1378,7 +1383,7 @@
 		case LOOP_UP:
 		case POINT_TO_POINT_UP:
 		        printk("qlogicfc%d : link is up\n", hostdata->host_id);
-			hostdata->adapter_state = AS_REDO_PORTDB;
+			hostdata->adapter_state = AS_REDO_FABRIC_PORTDB | AS_REDO_LOOP_PORTDB;
 			break;
 		case LOOP_DOWN:
 		        printk("qlogicfc%d : link is down\n", hostdata->host_id);
@@ -1387,12 +1392,15 @@
 		case CONNECTION_MODE:
 		        printk("received CONNECTION_MODE irq %x\n", inw(host->io_port + MBOX1));
 			break;
-		case LIP_OCCURED:
 		case CHANGE_NOTIFICATION:
+			if (hostdata->adapter_state == AS_LOOP_GOOD)
+				hostdata->adapter_state = AS_REDO_FABRIC_PORTDB;
+			break;		        
+		case LIP_OCCURED:
 		case PORT_DB_CHANGED:
 		case LIP_RECEIVED:
 			if (hostdata->adapter_state == AS_LOOP_GOOD)
-				hostdata->adapter_state = AS_REDO_PORTDB;
+				hostdata->adapter_state = AS_REDO_LOOP_PORTDB;
 			break;
 		case SYSTEM_ERROR:
 			printk("qlogicfc%d : The firmware just choked.\n", hostdata->host_id);
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c
--- v2.3.15/linux/drivers/scsi/qlogicisp.c	Thu Aug  5 15:11:52 1999
+++ linux/drivers/scsi/qlogicisp.c	Tue Aug 31 10:50:45 1999
@@ -1170,7 +1170,7 @@
 
 static int isp1020_init(struct Scsi_Host *sh)
 {
-	u_long io_base;
+	u_long io_base, io_flags;
 	struct isp1020_hostdata *hostdata;
 	u_char revision;
 	u_int irq;
@@ -1188,7 +1188,9 @@
 		printk("qlogicisp : error reading PCI configuration\n");
 		return 1;
 	}
+
 	io_base = pdev->resource[0].start;
+	io_flags = pdev->resource[0].flags;
 	irq = pdev->irq;
 
 	if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) {
@@ -1212,9 +1214,9 @@
 	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
 #endif
 
-	if (command & PCI_COMMAND_IO && (io_base & 3) == 1)
-		io_base &= PCI_BASE_ADDRESS_IO_MASK;
-	else {
+	if (! ((command & PCI_COMMAND_IO)
+	       && ((io_flags & PCI_BASE_ADDRESS_SPACE)
+		   == PCI_BASE_ADDRESS_SPACE_IO))) {
 		printk("qlogicisp : i/o mapping is disabled\n");
 		return 1;
 	}
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c
--- v2.3.15/linux/drivers/scsi/qlogicpti.c	Mon Mar 15 16:11:31 1999
+++ linux/drivers/scsi/qlogicpti.c	Tue Aug 31 11:23:03 1999
@@ -353,7 +353,7 @@
 
 #define PTI_RESET_LIMIT 400
 
-__initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
+static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
 {
 	struct qlogicpti_regs *qregs = qpti->qregs;
 	unsigned short csum = 0;
@@ -583,7 +583,7 @@
 #endif
 
 /* Detect all PTI Qlogic ISP's in the machine. */
-__initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
+int __init qlogicpti_detect(Scsi_Host_Template *tpnt)
 {
 	struct qlogicpti *qpti, *qlink;
 	struct Scsi_Host *qpti_host;
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v2.3.15/linux/drivers/scsi/scsi.h	Wed Aug 18 16:44:19 1999
+++ linux/drivers/scsi/scsi.h	Tue Aug 31 16:12:41 1999
@@ -715,7 +715,7 @@
 	DECLARE_WAITQUEUE(wait, current);	    \
 	add_wait_queue(QUEUE, &wait);		    \
 	for(;;) {			            \
-	current->state = TASK_UNINTERRUPTIBLE;	    \
+	set_current_state(TASK_UNINTERRUPTIBLE);    \
 	if (CONDITION) {		            \
             if (in_interrupt())	                    \
 	        panic("scsi: trying to call schedule() in interrupt" \
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/sgiwd93.c linux/drivers/scsi/sgiwd93.c
--- v2.3.15/linux/drivers/scsi/sgiwd93.c	Fri May  8 00:22:12 1998
+++ linux/drivers/scsi/sgiwd93.c	Tue Aug 31 11:23:03 1999
@@ -217,7 +217,7 @@
 	hcp->desc.pnext = PHYSADDR(buf);
 }
 
-__initfunc(int sgiwd93_detect(Scsi_Host_Template *HPsUX))
+int __init sgiwd93_detect(Scsi_Host_Template *HPsUX)
 {
 	static unsigned char called = 0;
 	struct hpc3_scsiregs *hregs = &hpc3c0->scsi_chan0;
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v2.3.15/linux/drivers/scsi/sr.c	Mon Aug  9 12:34:22 1999
+++ linux/drivers/scsi/sr.c	Tue Aug 31 16:03:17 1999
@@ -20,6 +20,9 @@
  *          Modified by Gerd Knorr <kraxel@cs.tu-berlin.de> to support the
  *          generic cdrom interface
  *
+ *	 Modified by Jens Axboe <axboe@image.dk> - Uniform sr_packet()
+ *	 interface, capabilities probe additions, ioctl cleanups, etc.
+ *
  */
 
 #include <linux/module.h>
@@ -925,10 +928,13 @@
 	scsi_CDs[i].sector_size = 2048;  /* A guess, just in case */
 	scsi_CDs[i].needs_sector_size = 1;
     } else {
-	scsi_CDs[i].capacity = 1 + ((buffer[0] << 24) |
-				    (buffer[1] << 16) |
-				    (buffer[2] << 8) |
-				    buffer[3]);
+	if (cdrom_get_last_written(MKDEV(MAJOR_NR, i),
+	   (long*)&scsi_CDs[i].capacity)) {
+		scsi_CDs[i].capacity = 1 + ((buffer[0] << 24) |
+					    (buffer[1] << 16) |
+					    (buffer[2] << 8) |
+					     buffer[3]);
+	}
 	scsi_CDs[i].sector_size = (buffer[4] << 24) |
 	    (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
 	switch (scsi_CDs[i].sector_size) {
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v2.3.15/linux/drivers/scsi/sr_ioctl.c	Thu Aug  5 16:24:15 1999
+++ linux/drivers/scsi/sr_ioctl.c	Tue Aug 31 16:03:17 1999
@@ -19,9 +19,6 @@
 # define DEBUG
 #endif
 
-/* for now we borrow the "operation not supported" from the network folks */
-#define EDRIVE_CANT_DO_THIS  EOPNOTSUPP
-
 /* The sr_is_xa() seems to trigger firmware bugs with some drives :-(
  * It is off by default and can be turned on with this module parameter */
 static int xa_test = 0;
@@ -160,7 +157,7 @@
 {
 	u_char  sr_cmd[10];
 
-        sr_cmd[0] = TEST_UNIT_READY;
+        sr_cmd[0] = GPCMD_TEST_UNIT_READY;
         sr_cmd[1] = ((scsi_CDs[minor].device -> lun) << 5);
         sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
         return sr_do_ioctl(minor, sr_cmd, NULL, 255, 1);
@@ -170,7 +167,7 @@
 {
         u_char  sr_cmd[10];
 
-        sr_cmd[0] = START_STOP;
+        sr_cmd[0] = GPCMD_START_STOP_UNIT;
         sr_cmd[1] = ((scsi_CDs[MINOR(cdi->dev)].device -> lun) << 5);
         sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
         sr_cmd[4] = (pos == 0) ? 0x03 /* close */ : 0x02 /* eject */;
@@ -243,7 +240,7 @@
 	char buffer[32];
         int result;
         	
-	sr_cmd[0] = SCMD_READ_SUBCHANNEL;
+	sr_cmd[0] = GPCMD_READ_SUBCHANNEL;
 	sr_cmd[1] = ((scsi_CDs[MINOR(cdi->dev)].device->lun) << 5);
 	sr_cmd[2] = 0x40;    /* I do want the subchannel info */
 	sr_cmd[3] = 0x02;    /* Give me medium catalog number info */
@@ -277,7 +274,7 @@
             speed *= 177;   /* Nx to kbyte/s */
         
 	memset(sr_cmd,0,12);
-	sr_cmd[0] = 0xbb; /* SET CD SPEED */
+	sr_cmd[0] = GPCMD_SET_SPEED; /* SET CD SPEED */
 	sr_cmd[1] = (scsi_CDs[MINOR(cdi->dev)].device->lun) << 5;
 	sr_cmd[2] = (speed >> 8) & 0xff; /* MSB for speed (in kbytes/sec) */
 	sr_cmd[3] =  speed       & 0xff; /* LSB */
@@ -290,6 +287,8 @@
 /* ----------------------------------------------------------------------- */
 /* this is called by the generic cdrom driver. arg is a _kernel_ pointer,  */
 /* becauce the generic cdrom driver does the user access stuff for us.     */
+/* only cdromreadtochdr and cdromreadtocentry are left - for use with the  */
+/* sr_disk_status interface for the generic cdrom driver.                  */
 
 int sr_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void* arg)
 {
@@ -300,94 +299,12 @@
     
     switch (cmd) 
     {
-	/* Sun-compatible */
-    case CDROMPAUSE:
-	
-	sr_cmd[0] = SCMD_PAUSE_RESUME;
-	sr_cmd[1] = scsi_CDs[target].device->lun << 5;
-	sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;
-	sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;
-	sr_cmd[8] = 0;
-	sr_cmd[9] = 0;
-	
-	result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0);
-        break;
-	
-    case CDROMRESUME:
-	
-	sr_cmd[0] = SCMD_PAUSE_RESUME;
-	sr_cmd[1] = scsi_CDs[target].device->lun << 5;
-	sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;
-	sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;
-	sr_cmd[8] = 1;
-	sr_cmd[9] = 0;
-	
-	result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0);
-        break;
-	
-    case CDROMPLAYMSF:
-    {
-	struct cdrom_msf* msf = (struct cdrom_msf*)arg;
-
-	sr_cmd[0] = SCMD_PLAYAUDIO_MSF;
-	sr_cmd[1] = scsi_CDs[target].device->lun << 5;
-	sr_cmd[2] = 0;
-	sr_cmd[3] = msf->cdmsf_min0;
-	sr_cmd[4] = msf->cdmsf_sec0;
-	sr_cmd[5] = msf->cdmsf_frame0;
-	sr_cmd[6] = msf->cdmsf_min1;
-	sr_cmd[7] = msf->cdmsf_sec1;
-	sr_cmd[8] = msf->cdmsf_frame1;
-	sr_cmd[9] = 0;
-	
-	result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0);
-        break;
-    }
-
-    case CDROMPLAYBLK:
-    {
-	struct cdrom_blk* blk = (struct cdrom_blk*)arg;
-
-	sr_cmd[0] = SCMD_PLAYAUDIO10;
-	sr_cmd[1] = scsi_CDs[target].device->lun << 5;
-	sr_cmd[2] = blk->from >> 24;
-	sr_cmd[3] = blk->from >> 16;
-	sr_cmd[4] = blk->from >> 8;
-	sr_cmd[5] = blk->from;
-	sr_cmd[6] = 0;
-	sr_cmd[7] = blk->len >> 8;
-	sr_cmd[8] = blk->len;
-	sr_cmd[9] = 0;
-	
-	result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0);
-        break;
-    }
-		
-    case CDROMPLAYTRKIND:
-    {
-	struct cdrom_ti* ti = (struct cdrom_ti*)arg;
-
-	sr_cmd[0] = SCMD_PLAYAUDIO_TI;
-	sr_cmd[1] = scsi_CDs[target].device->lun << 5;
-	sr_cmd[2] = 0;
-	sr_cmd[3] = 0;
-	sr_cmd[4] = ti->cdti_trk0;
-	sr_cmd[5] = ti->cdti_ind0;
-	sr_cmd[6] = 0;
-	sr_cmd[7] = ti->cdti_trk1;
-	sr_cmd[8] = ti->cdti_ind1;
-	sr_cmd[9] = 0;
-	
-	result = sr_do_ioctl(target, sr_cmd, NULL, 255, 0);
-        break;
-    }
-	
     case CDROMREADTOCHDR:
     {
 	struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg;
 	char buffer[32];
 	
-	sr_cmd[0] = SCMD_READ_TOC;
+	sr_cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
 	sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5);
 	sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
 	sr_cmd[6] = 0;
@@ -408,7 +325,7 @@
 	struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg;
 	unsigned char buffer[32];
 	
-	sr_cmd[0] = SCMD_READ_TOC;
+	sr_cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
 	sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) |
           (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
 	sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
@@ -432,39 +349,7 @@
 	
         break;
     }
-	
-    case CDROMSUBCHNL:
-    {
-	struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg;
-	char buffer[32];
-	
-	sr_cmd[0] = SCMD_READ_SUBCHANNEL;
-	sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 0x02;    /* MSF format */
-	sr_cmd[2] = 0x40;    /* I do want the subchannel info */
-	sr_cmd[3] = 0x01;    /* Give me current position info */
-	sr_cmd[4] = sr_cmd[5] = 0;
-	sr_cmd[6] = 0;
-	sr_cmd[7] = 0;
-	sr_cmd[8] = 16;
-	sr_cmd[9] = 0;
-	
-	result = sr_do_ioctl(target, sr_cmd, buffer, 16, 0);
-	
-	subchnl->cdsc_audiostatus = buffer[1];
-	subchnl->cdsc_format = CDROM_MSF;
-	subchnl->cdsc_ctrl = buffer[5] & 0xf;
-	subchnl->cdsc_trk = buffer[6];
-	subchnl->cdsc_ind = buffer[7];
-	
-	subchnl->cdsc_reladdr.msf.minute = buffer[13];
-	subchnl->cdsc_reladdr.msf.second = buffer[14];
-	subchnl->cdsc_reladdr.msf.frame = buffer[15];
-	subchnl->cdsc_absaddr.msf.minute = buffer[9];
-	subchnl->cdsc_absaddr.msf.second = buffer[10];
-	subchnl->cdsc_absaddr.msf.frame = buffer[11];
-	
-        break;
-    }
+
     default:
         return -EINVAL;
     }
@@ -502,7 +387,7 @@
 #endif
 
     memset(cmd,0,12);
-    cmd[0] = 0xbe /* READ_CD */;
+    cmd[0] = GPCMD_READ_CD; /* READ_CD */
     cmd[1] = (scsi_CDs[minor].device->lun << 5) | ((format & 7) << 2);
     cmd[2] = (unsigned char)(lba >> 24) & 0xff;
     cmd[3] = (unsigned char)(lba >> 16) & 0xff;
@@ -548,7 +433,7 @@
 #endif
     
     memset(cmd,0,12);
-    cmd[0] = READ_10;
+    cmd[0] = GPCMD_READ_10;
     cmd[1] = (scsi_CDs[minor].device->lun << 5);
     cmd[2] = (unsigned char)(lba >> 24) & 0xff;
     cmd[3] = (unsigned char)(lba >> 16) & 0xff;
@@ -603,89 +488,6 @@
     target = MINOR(cdi->dev);
     
     switch (cmd) {
-    case CDROMREADMODE1:
-    case CDROMREADMODE2:
-    case CDROMREADRAW:
-    {
-	unsigned char      *raw;
-        struct cdrom_msf   msf;
-        int                lba, rc;
-	int                blocksize = 2048;
-        unsigned long flags;
-
-        switch (cmd) {
-        case CDROMREADMODE2: blocksize = CD_FRAMESIZE_RAW0; break; /* 2336 */
-        case CDROMREADRAW:   blocksize = CD_FRAMESIZE_RAW;  break; /* 2352 */
-        }
-
-	if (copy_from_user(&msf,(void*)arg,sizeof(msf)))
-		return -EFAULT;
-        spin_lock_irqsave(&io_request_lock, flags);
-        raw = scsi_malloc(2048+512);
-        spin_unlock_irqrestore(&io_request_lock, flags);
-	if (!(raw))
-                return -ENOMEM;
-
-	lba = (((msf.cdmsf_min0 * CD_SECS) + msf.cdmsf_sec0)
-			* CD_FRAMES + msf.cdmsf_frame0) - CD_MSF_OFFSET;
-        if (lba < 0 || lba >= scsi_CDs[target].capacity)
-            return -EINVAL;
-
-        rc = sr_read_sector(target, lba, blocksize, raw);
-	if (!rc)
-		if (copy_to_user((void*)arg, raw, blocksize))
-			rc = -EFAULT;
-
-        spin_lock_irqsave(&io_request_lock, flags);
-	scsi_free(raw,2048+512);
-        spin_unlock_irqrestore(&io_request_lock, flags);
-	return rc;
-    }
-    case CDROMREADAUDIO:
-    {
-	unsigned char      *raw;
-        int                lba, rc=0;
-        struct cdrom_read_audio ra;
-        unsigned long flags;
-
-        if (!scsi_CDs[target].readcd_known || !scsi_CDs[target].readcd_cdda)
-            return -EINVAL;  /* -EDRIVE_DOES_NOT_SUPPORT_THIS ? */
-        
-	if (copy_from_user(&ra,(void*)arg,sizeof(ra)))
-            return -EFAULT;
-        
-        if (ra.addr_format == CDROM_LBA)
-            lba = ra.addr.lba;
-        else
-            lba = (((ra.addr.msf.minute * CD_SECS) + ra.addr.msf.second)
-                   * CD_FRAMES + ra.addr.msf.frame) - CD_MSF_OFFSET;
-
-        if (lba < 0 || lba >= scsi_CDs[target].capacity)
-            return -EINVAL;
-        spin_lock_irqsave(&io_request_lock, flags);
-        raw = scsi_malloc(2048+512);
-        spin_unlock_irqrestore(&io_request_lock, flags);
-	if (!(raw))
-            return -ENOMEM;
-
-        while (ra.nframes > 0) {
-            rc = sr_read_cd(target, raw, lba, 1, CD_FRAMESIZE_RAW);
-            if (!rc)
-		if (copy_to_user(ra.buf, raw, CD_FRAMESIZE_RAW))
-                    rc = -EFAULT;
-            if (rc)
-                break;
-
-            ra.buf     += CD_FRAMESIZE_RAW;
-            ra.nframes -= 1;
-            lba++;
-        }
-        spin_lock_irqsave(&io_request_lock, flags);
-	scsi_free(raw,2048+512);
-        spin_unlock_irqrestore(&io_request_lock, flags);
-        return rc;
-    }
-
     case BLKROSET:
     case BLKROGET:
     case BLKRASET:
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v2.3.15/linux/drivers/scsi/st.c	Mon Aug  9 10:25:01 1999
+++ linux/drivers/scsi/st.c	Tue Aug 31 11:23:03 1999
@@ -3499,7 +3499,7 @@
 
 static int st_registered = 0;
 
-/* Driver initialization (not __initfunc because may be called later) */
+/* Driver initialization (not __init because may be called later) */
 static int st_init()
 {
   int i;
diff -u --recursive --new-file v2.3.15/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c
--- v2.3.15/linux/drivers/scsi/sym53c8xx.c	Wed Aug  4 10:54:13 1999
+++ linux/drivers/scsi/sym53c8xx.c	Tue Aug 31 11:25:33 1999
@@ -134,8 +134,8 @@
 #ifndef	__initdata
 #define	__initdata
 #endif
-#ifndef	__initfunc
-#define	__initfunc(__arginit) __arginit
+#ifndef	__init
+#define	__init
 #endif
 #endif
 
@@ -569,16 +569,13 @@
 #endif
 
 #ifdef __sparc__
-#define remap_pci_mem(base, size)	((u_long) __va(base))
-#define unmap_pci_mem(vaddr, size)
 #define pcivtobus(p)			((p) & pci_dvma_mask)
 #else	/* __sparc__ */
 #define pcivtobus(p)			(p)
+#endif
 
 #if !defined(NCR_IOMAPPED) || defined(__i386__)
-__initfunc(
-static u_long remap_pci_mem(u_long base, u_long size)
-)
+static u_long __init remap_pci_mem(u_long base, u_long size)
 {
 	u_long page_base	= ((u_long) base) & PAGE_MASK;
 	u_long page_offs	= ((u_long) base) - page_base;
@@ -587,15 +584,12 @@
 	return page_remapped? (page_remapped + page_offs) : 0UL;
 }
 
-__initfunc(
-static void unmap_pci_mem(u_long vaddr, u_long size)
-)
+static void __init unmap_pci_mem(u_long vaddr, u_long size)
 {
 	if (vaddr)
 		iounmap((void *) (vaddr & PAGE_MASK));
 }
 #endif	/* !NCR_IOMAPPED || __i386__ */
-#endif	/* __sparc__ */
 
 /*
 **	Insert a delay in micro-seconds and milli-seconds.
@@ -3802,9 +3796,7 @@
 **==========================================================
 */
 
-__initfunc(
-void ncr_script_fill (struct script * scr, struct scripth * scrh)
-)
+void __init ncr_script_fill (struct script * scr, struct scripth * scrh)
 {
 	int	i;
 	ncrcmd	*p;
@@ -3868,9 +3860,7 @@
 **==========================================================
 */
 
-__initfunc(
-static void ncr_script_copy_and_bind (ncb_p np,ncrcmd *src,ncrcmd *dst,int len)
-)
+static void __init ncr_script_copy_and_bind (ncb_p np,ncrcmd *src,ncrcmd *dst,int len)
 {
 	ncrcmd  opcode, new, old, tmp1, tmp2;
 	ncrcmd	*start, *end;
@@ -4138,10 +4128,8 @@
 **	Get target set-up from Symbios format NVRAM.
 */
 
-__initfunc(
-static void
+static void __init
 	ncr_Symbios_setup_target(ncb_p np, int target, Symbios_nvram *nvram)
-)
 {
 	tcb_p tp = &np->target[target];
 	Symbios_target *tn = &nvram->target[target];
@@ -4161,10 +4149,8 @@
 **	Get target set-up from Tekram format NVRAM.
 */
 
-__initfunc(
-static void
+static void __init
 	ncr_Tekram_setup_target(ncb_p np, int target, Tekram_nvram *nvram)
-)
 {
 	tcb_p tp = &np->target[target];
 	struct Tekram_target *tn = &nvram->target[target];
@@ -4190,9 +4176,7 @@
 }
 #endif /* SCSI_NCR_NVRAM_SUPPORT */
 
-__initfunc(
-static int ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
-)
+static int __init ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
 {
 	u_char	burst_max;
 	u_long	period;
@@ -4514,9 +4498,7 @@
 
 #ifdef SCSI_NCR_DEBUG_NVRAM
 
-__initfunc(
-void ncr_display_Symbios_nvram(ncb_p np, Symbios_nvram *nvram)
-)
+void __init ncr_display_Symbios_nvram(ncb_p np, Symbios_nvram *nvram)
 {
 	int i;
 
@@ -4546,9 +4528,7 @@
 
 static u_char Tekram_boot_delay[7] __initdata = {3, 5, 10, 20, 30, 60, 120};
 
-__initfunc(
-void ncr_display_Tekram_nvram(ncb_p np, Tekram_nvram *nvram)
-)
+void __init ncr_display_Tekram_nvram(ncb_p np, Tekram_nvram *nvram)
 {
 	int i, tags, boot_delay;
 	char *rem;
@@ -4607,9 +4587,7 @@
 **	start the timer daemon.
 */
 
-__initfunc(
-static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
-)
+static int __init ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device)
 {
         struct host_data *host_data;
 	ncb_p np = 0;
@@ -9202,9 +9180,7 @@
 */
 
 #ifndef NCR_IOMAPPED
-__initfunc(
-static int ncr_regtest (struct ncb* np)
-)
+static int __init ncr_regtest (struct ncb* np)
 {
 	register volatile u_int32 data;
 	/*
@@ -9228,9 +9204,7 @@
 }
 #endif
 
-__initfunc(
-static int ncr_snooptest (struct ncb* np)
-)
+static int __init ncr_snooptest (struct ncb* np)
 {
 	u_int32	ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc;
 	int	i, err=0;
@@ -9460,9 +9434,7 @@
 /*
  *	calculate NCR SCSI clock frequency (in KHz)
  */
-__initfunc(
-static unsigned ncrgetfreq (ncb_p np, int gen)
-)
+static unsigned __init ncrgetfreq (ncb_p np, int gen)
 {
 	unsigned ms = 0;
 
@@ -9510,9 +9482,7 @@
 /*
  *	Get/probe NCR SCSI clock frequency
  */
-__initfunc(
-static void ncr_getclock (ncb_p np, int mult)
-)
+static void __init ncr_getclock (ncb_p np, int mult)
 {
 	unsigned char scntl3 = INB(nc_scntl3);
 	unsigned char stest1 = INB(nc_stest1);
@@ -9644,9 +9614,7 @@
 #define	ARG_SEP	','
 #endif
 
-__initfunc(
-static int get_setup_token(char *p)
-)
+static int __init get_setup_token(char *p)
 {
 	char *cur = setup_token;
 	char *pc;
@@ -9663,9 +9631,7 @@
 }
 
 
-__initfunc(
-void sym53c8xx_setup(char *str, int *ints)
-)
+void __init sym53c8xx_setup(char *str, int *ints)
 {
 #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
 	char *cur = str;
@@ -9799,9 +9765,7 @@
 **   Returns the number of boards successfully attached.
 */
 
-__initfunc(
-static void ncr_print_driver_setup(void)
-)
+static void __init ncr_print_driver_setup(void)
 {
 #define YesNo(y)	y ? 'y' : 'n'
 	printk (NAME53C8XX ": setup=disc:%c,specf:%d,ultra:%d,tags:%d,sync:%d,"
@@ -9860,9 +9824,7 @@
 #define	SCSI_NCR_MAX_PQS_BUS	16
 static int pqs_bus[SCSI_NCR_MAX_PQS_BUS] __initdata = { 0 };
 
-__initfunc(
-static void ncr_detect_pqs_pds(void)
-)
+static void __init ncr_detect_pqs_pds(void)
 {
 	short index;
 
@@ -9900,9 +9862,7 @@
 **    the the order they are detected.
 **===================================================================
 */
-__initfunc(
-int sym53c8xx_detect(Scsi_Host_Template *tpnt)
-)
+int __init sym53c8xx_detect(Scsi_Host_Template *tpnt)
 {
 	int i, j, chips, hosts, count;
 	u_char bus, device_fn;
@@ -10090,10 +10050,8 @@
 **===================================================================
 */
 #if LINUX_VERSION_CODE <= LinuxVersionCode(2,1,92)
-__initfunc(
-static int 
+static int  __init
 pci_read_base_address(u_char bus, u_char device_fn, int offset, u_long *base)
-)
 {
 	u_int32 tmp;
 
@@ -10110,10 +10068,8 @@
 	return offset;
 }
 #else	/* LINUX_VERSION_CODE > LinuxVersionCode(2,1,92) */
-__initfunc(
-static int 
+static int __init
 pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
-)
 {
 	/* FIXME! This is just unbelieably horrible backwards compatibility code */
 	struct resource *res = pdev->resource + index;
@@ -10132,10 +10088,8 @@
 **   been detected.
 **===================================================================
 */
-__initfunc(
-static int sym53c8xx_pci_init(Scsi_Host_Template *tpnt,
+static int __init sym53c8xx_pci_init(Scsi_Host_Template *tpnt,
 			      uchar bus, uchar device_fn, ncr_device *device)
-)
 {
 	u_short vendor_id, device_id, command;
 	u_char cache_line_size, latency_timer;
@@ -10313,9 +10267,6 @@
 	**    coherent with hardware and software resource identifications.
 	**    This is fairly simple, but seems still too complex for Sparc.
 	*/
-	base = __pa(base);
-	base_2 = __pa(base_2);
-
 	if (!cache_line_size)
 		suggested_cache_line_size = 16;
 
@@ -10470,7 +10421,7 @@
 *===================================================================
 */
 #ifdef SCSI_NCR_NVRAM_SUPPORT
-__initfunc(static void ncr_get_nvram(ncr_device *devp, ncr_nvram *nvp))
+static void __init ncr_get_nvram(ncr_device *devp, ncr_nvram *nvp)
 {
 	devp->nvram = nvp;
 	if (!nvp)
@@ -11335,9 +11286,7 @@
 static void nvram_stop(ncr_slot *np, u_char *gpreg);
 static void nvram_setBit(ncr_slot *np, u_char write_bit, u_char *gpreg, int bit_mode);
 
-__initfunc(
-static int ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram)
-)
+static int __init ncr_get_Symbios_nvram (ncr_slot *np, Symbios_nvram *nvram)
 {
 	static u_char Symbios_trailer[6] = {0xfe, 0xfe, 0, 0, 0, 0};
 	u_char	gpcntl, gpreg;
@@ -11426,9 +11375,7 @@
 /*
  * Read Symbios NvRAM data and compute checksum.
  */
-__initfunc(
-static u_short nvram_read_data(ncr_slot *np, u_char *data, int len, u_char *gpreg, u_char *gpcntl)
-)
+static u_short __init nvram_read_data(ncr_slot *np, u_char *data, int len, u_char *gpreg, u_char *gpcntl)
 {
 	int	x;
 	u_short	csum;
@@ -11445,9 +11392,7 @@
 /*
  * Send START condition to NVRAM to wake it up.
  */
-__initfunc(
-static void nvram_start(ncr_slot *np, u_char *gpreg)
-)
+static void __init nvram_start(ncr_slot *np, u_char *gpreg)
 {
 	nvram_setBit(np, 1, gpreg, SET_BIT);
 	nvram_setBit(np, 0, gpreg, SET_CLK);
@@ -11459,9 +11404,7 @@
  * WRITE a byte to the NVRAM and then get an ACK to see it was accepted OK,
  * GPIO0 must already be set as an output
  */
-__initfunc(
-static void nvram_write_byte(ncr_slot *np, u_char *ack_data, u_char write_data, u_char *gpreg, u_char *gpcntl)
-)
+static void __init nvram_write_byte(ncr_slot *np, u_char *ack_data, u_char write_data, u_char *gpreg, u_char *gpcntl)
 {
 	int x;
 	
@@ -11475,9 +11418,7 @@
  * READ a byte from the NVRAM and then send an ACK to say we have got it,
  * GPIO0 must already be set as an input
  */
-__initfunc(
-static void nvram_read_byte(ncr_slot *np, u_char *read_data, u_char ack_data, u_char *gpreg, u_char *gpcntl)
-)
+static void __init nvram_read_byte(ncr_slot *np, u_char *read_data, u_char ack_data, u_char *gpreg, u_char *gpcntl)
 {
 	int x;
 	u_char read_bit;
@@ -11495,9 +11436,7 @@
  * Output an ACK to the NVRAM after reading,
  * change GPIO0 to output and when done back to an input
  */
-__initfunc(
-static void nvram_writeAck(ncr_slot *np, u_char write_bit, u_char *gpreg, u_char *gpcntl)
-)
+static void __init nvram_writeAck(ncr_slot *np, u_char write_bit, u_char *gpreg, u_char *gpcntl)
 {
 	OUTB (nc_gpcntl, *gpcntl & 0xfe);
 	nvram_doBit(np, 0, write_bit, gpreg);
@@ -11508,9 +11447,7 @@
  * Input an ACK from NVRAM after writing,
  * change GPIO0 to input and when done back to an output
  */
-__initfunc(
-static void nvram_readAck(ncr_slot *np, u_char *read_bit, u_char *gpreg, u_char *gpcntl)
-)
+static void __init nvram_readAck(ncr_slot *np, u_char *read_bit, u_char *gpreg, u_char *gpcntl)
 {
 	OUTB (nc_gpcntl, *gpcntl | 0x01);
 	nvram_doBit(np, read_bit, 1, gpreg);
@@ -11521,9 +11458,7 @@
  * Read or write a bit to the NVRAM,
  * read if GPIO0 input else write if GPIO0 output
  */
-__initfunc(
-static void nvram_doBit(ncr_slot *np, u_char *read_bit, u_char write_bit, u_char *gpreg)
-)
+static void __init nvram_doBit(ncr_slot *np, u_char *read_bit, u_char write_bit, u_char *gpreg)
 {
 	nvram_setBit(np, write_bit, gpreg, SET_BIT);
 	nvram_setBit(np, 0, gpreg, SET_CLK);
@@ -11536,9 +11471,7 @@
 /*
  * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZzzzz!!
  */
-__initfunc(
-static void nvram_stop(ncr_slot *np, u_char *gpreg)
-)
+static void __init nvram_stop(ncr_slot *np, u_char *gpreg)
 {
 	nvram_setBit(np, 0, gpreg, SET_CLK);
 	nvram_setBit(np, 1, gpreg, SET_BIT);
@@ -11547,9 +11480,7 @@
 /*
  * Set/clear data/clock bit in GPIO0
  */
-__initfunc(
-static void nvram_setBit(ncr_slot *np, u_char write_bit, u_char *gpreg, int bit_mode)
-)
+static void __init nvram_setBit(ncr_slot *np, u_char write_bit, u_char *gpreg, int bit_mode)
 {
 	UDELAY (5);
 	switch (bit_mode){
@@ -11600,9 +11531,7 @@
 static void Tnvram_Stop(ncr_slot *np, u_char *gpreg);
 static void Tnvram_Clk(ncr_slot *np, u_char *gpreg);
 
-__initfunc(
-static int ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram *nvram)
-)
+static int __init ncr_get_Tekram_nvram (ncr_slot *np, Tekram_nvram *nvram)
 {
 	u_char gpcntl, gpreg;
 	u_char old_gpcntl, old_gpreg;
@@ -11637,9 +11566,7 @@
 /*
  * Read Tekram NvRAM data and compute checksum.
  */
-__initfunc(
-static u_short Tnvram_read_data(ncr_slot *np, u_short *data, int len, u_char *gpreg)
-)
+static u_short __init Tnvram_read_data(ncr_slot *np, u_short *data, int len, u_char *gpreg)
 {
 	u_char	read_bit;
 	u_short	csum;
@@ -11664,9 +11591,7 @@
 /*
  * Send read command and address to NVRAM
  */
-__initfunc(
-static void Tnvram_Send_Command(ncr_slot *np, u_short write_data, u_char *read_bit, u_char *gpreg)
-)
+static void __init Tnvram_Send_Command(ncr_slot *np, u_short write_data, u_char *read_bit, u_char *gpreg)
 {
 	int x;
 
@@ -11680,9 +11605,7 @@
 /*
  * READ a byte from the NVRAM
  */
-__initfunc(
-static void Tnvram_Read_Word(ncr_slot *np, u_short *nvram_data, u_char *gpreg)
-)
+static void __init Tnvram_Read_Word(ncr_slot *np, u_short *nvram_data, u_char *gpreg)
 {
 	int x;
 	u_char read_bit;
@@ -11701,9 +11624,7 @@
 /* 
  * Read bit from NVRAM
  */
-__initfunc(
-static void Tnvram_Read_Bit(ncr_slot *np, u_char *read_bit, u_char *gpreg)
-)
+static void __init Tnvram_Read_Bit(ncr_slot *np, u_char *read_bit, u_char *gpreg)
 {
 	UDELAY (2);
 	Tnvram_Clk(np, gpreg);
@@ -11713,9 +11634,7 @@
 /*
  * Write bit to GPIO0
  */
-__initfunc(
-static void Tnvram_Write_Bit(ncr_slot *np, u_char write_bit, u_char *gpreg)
-)
+static void __init Tnvram_Write_Bit(ncr_slot *np, u_char write_bit, u_char *gpreg)
 {
 	if (write_bit & 0x01)
 		*gpreg |= 0x02;
@@ -11733,9 +11652,7 @@
 /*
  * Send STOP condition to NVRAM - puts NVRAM to sleep... ZZZzzz!!
  */
-__initfunc(
-static void Tnvram_Stop(ncr_slot *np, u_char *gpreg)
-)
+static void __init Tnvram_Stop(ncr_slot *np, u_char *gpreg)
 {
 	*gpreg &= 0xef;
 	OUTB (nc_gpreg, *gpreg);
@@ -11747,9 +11664,7 @@
 /*
  * Pulse clock bit in GPIO0
  */
-__initfunc(
-static void Tnvram_Clk(ncr_slot *np, u_char *gpreg)
-)
+static void __init Tnvram_Clk(ncr_slot *np, u_char *gpreg)
 {
 	OUTB (nc_gpreg, *gpreg | 0x04);
 	UDELAY (2);
diff -u --recursive --new-file v2.3.15/linux/drivers/sgi/char/ds1286.c linux/drivers/sgi/char/ds1286.c
--- v2.3.15/linux/drivers/sgi/char/ds1286.c	Fri Jun 25 17:39:34 1999
+++ linux/drivers/sgi/char/ds1286.c	Tue Aug 31 11:23:03 1999
@@ -392,7 +392,7 @@
 	&ds1286_fops
 };
 
-__initfunc(int ds1286_init(void))
+int __init ds1286_init(void)
 {
 	printk(KERN_INFO "DS1286 Real Time Clock Driver v%s\n", DS1286_VERSION);
 	misc_register(&ds1286_dev);
diff -u --recursive --new-file v2.3.15/linux/drivers/sgi/char/graphics.c linux/drivers/sgi/char/graphics.c
--- v2.3.15/linux/drivers/sgi/char/graphics.c	Fri Jul  2 15:15:51 1999
+++ linux/drivers/sgi/char/graphics.c	Tue Aug 31 11:23:03 1999
@@ -324,13 +324,13 @@
 };
 
 /* This is called later from the misc-init routine */
-__initfunc(void gfx_register (void))
+void __init gfx_register (void)
 {
 	misc_register (&dev_graphics);
 	misc_register (&dev_opengl);
 }
 
-__initfunc(void gfx_init (const char **name))
+void __init gfx_init (const char **name)
 {
 #if 0
 	struct console_ops *console;
diff -u --recursive --new-file v2.3.15/linux/drivers/sgi/char/sgiserial.c linux/drivers/sgi/char/sgiserial.c
--- v2.3.15/linux/drivers/sgi/char/sgiserial.c	Tue Jun 29 09:22:08 1999
+++ linux/drivers/sgi/char/sgiserial.c	Tue Aug 31 11:30:48 1999
@@ -1591,7 +1591,7 @@
 		if (!(info->flags & ZILOG_CALLOUT_ACTIVE))
 			zs_rtsdtr(info, 1);
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ZILOG_INITIALIZED)) {
 #ifdef SERIAL_DO_RESTART
@@ -2045,7 +2045,7 @@
 }
 
 
-__initfunc(static int zs_console_setup(struct console *con, char *options))
+static int __init zs_console_setup(struct console *con, char *options)
 {
 	struct sgi_serial *info;
 	int	baud = 9600;
@@ -2185,7 +2185,7 @@
 /*
  *	Register console.
  */
-__initfunc (long serial_console_init(long kmem_start, long kmem_end))
+long __init serial_console_init(long kmem_start, long kmem_end)
 {
 	register_console(&sgi_console_driver);
 	return kmem_start;
diff -u --recursive --new-file v2.3.15/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v2.3.15/linux/drivers/sound/Config.in	Thu Aug 26 13:05:39 1999
+++ linux/drivers/sound/Config.in	Mon Aug 30 18:15:21 1999
@@ -274,7 +274,7 @@
     dep_tristate 'Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS
     if [ "$CONFIG_SOUND_WAVEARTIST" != "n" ]; then
       hex '  WaveArtist I/O base' CONFIG_WAVEARTIST_BASE 250
-      int '  WaveArtist IRQ' CONFIG_WAVEARTIST_IRQ 28
+      int '  WaveArtist IRQ' CONFIG_WAVEARTIST_IRQ 12
       int '  WaveArtist DMA' CONFIG_WAVEARTIST_DMA 3
       int '  WaveArtist second DMA' CONFIG_WAVEARTIST_DMA2 7
     fi
diff -u --recursive --new-file v2.3.15/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v2.3.15/linux/drivers/sound/Makefile	Thu Aug 26 13:05:39 1999
+++ linux/drivers/sound/Makefile	Mon Aug 30 10:23:14 1999
@@ -81,6 +81,7 @@
 obj-$(CONFIG_SOUND_ES1370)	+= es1370.o
 obj-$(CONFIG_SOUND_ES1371)	+= es1371.o
 obj-$(CONFIG_SOUND_ESSSOLO1)	+= esssolo1.o
+obj-$(CONFIG_SOUND_MAESTRO)	+= maestro.o
 
 # Declare multi-part drivers.
 
diff -u --recursive --new-file v2.3.15/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c
--- v2.3.15/linux/drivers/sound/cmpci.c	Thu Aug  5 15:11:52 1999
+++ linux/drivers/sound/cmpci.c	Thu Aug 26 14:23:32 1999
@@ -2176,9 +2176,9 @@
 };
 
 #ifdef MODULE
-__initfunc(int init_module(void))
+int __init init_module(void)
 #else
-__initfunc(int init_cmpci(void))
+int __init init_cmpci(void)
 #endif
 {
 	struct cm_state *s;
diff -u --recursive --new-file v2.3.15/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h
--- v2.3.15/linux/drivers/sound/dev_table.h	Mon Jul  5 19:58:24 1999
+++ linux/drivers/sound/dev_table.h	Mon Aug 30 18:15:21 1999
@@ -33,7 +33,7 @@
 #define SNDCARD_WAVEFRONT               41
 #define SNDCARD_OPL3SA2                 42
 #define SNDCARD_OPL3SA2_MPU             43
-#define SNDCARD_WAVEARTIST		44
+#define SNDCARD_WAVEARTIST              44	/* Rebel Waveartist */
 #define SNDCARD_OPL3SA2_MSS             45	/* Originally missed */
 #define SNDCARD_AD1816                  88
 
diff -u --recursive --new-file v2.3.15/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c
--- v2.3.15/linux/drivers/sound/maestro.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/maestro.c	Tue Aug 31 11:23:03 1999
@@ -0,0 +1,2918 @@
+/*****************************************************************************
+ *
+ *      ESS Maestro/Maestro-2/Maestro-2E driver for Linux 2.2.x
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *	(c) Copyright 1999	 Alan Cox <alan.cox@linux.org>
+ *
+ *	Based heavily on SonicVibes.c:
+ *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *	Heavily modified by Zach Brown <zab@redhat.com> based on lunch
+ *	with ESS engineers.  Many thanks to Howard Kim for providing 
+ *	contacts and hardware.  Honorable mention goes to Eric 
+ *	Brombaugh for the BOB routines and nice hacking in general.
+ *
+ *  Supported devices:
+ *  /dev/dsp0-7    standard /dev/dsp device, (mostly) OSS compatible
+ *  /dev/mixer  standard /dev/mixer device, (mostly) OSS compatible
+ *
+ *  Hardware Description
+ *
+ *	A working Maestro setup contains the Maestro chip wired to a 
+ *	codec or 2.  In the Maestro we have the APUs, the ASP, and the
+ *	Wavecache.  The APUs can be though of as virtual audio routing
+ *	channels.  They can take data from a number of sources and perform
+ *	basic encodings of the data.  The wavecache is a storehouse for
+ *	PCM data.  Typically it deals with PCI and interracts with the
+ *	APUs.  The ASP is a wacky DSP like device that ESS is loathe
+ *	to release docs on.  Thankfully it isn't required on the Maestro
+ *	until you start doing insane things like FM emulation and surround
+ *	encoding.  The codecs are almost always AC-97 compliant codecs, 
+ *	but it appears that early Maestros may have had PT101 (an ESS
+ *	part?) wired to them.  The only real difference in the Maestro
+ *	families is external goop like docking capability, memory for
+ *	the ASP, and trivial initialization differences.
+ *
+ *  Driver Operation
+ *
+ *	We only drive the APU/Wavecache as typical DACs and drive the
+ *	mixers in the codecs.  There are 64 APUs.  We assign 4 to each
+ *	/dev/dsp? device.  2 channels for both in and out.
+ *
+ *	For output we maintain a ring buffer of data that we are dmaing
+ *	to the card.  In mono operation this is nice and easy.  When
+ *	we receive data we tack it onto the ring buffer and make sure
+ *	the APU assigned to it is playing over the data.  When we fill
+ *	the ring buffer we put the client to sleep until there is
+ *	room again.  Easy.
+ *
+ *	However, this starts to stink when we use stereo.  The APUs
+ *	supposedly can decode LRLR packed stereo data, but it
+ *	doesn't work.  So we're forced to use dual mono APUs walking over
+ *	mono encoded data.  This requires us to split the input from
+ *	the client and complicates the buffer maths tremendously.  Ick.
+ *
+ *	Once input is actually written, it will be worth pointing out
+ *	that only 44/16 input actually works.
+ *
+ * TODO
+ *	Leaks memory?
+ *	recording is horribly broken
+ *	apus or dmas get out sync
+ *	bob can be started twice
+ *	anyone have a pt101 codec?
+ *	ess's ac97 codec (es1921) doesn't work
+ *	generally test across codecs..
+ *	mmap(), but beware stereo encoding nastiness.
+ */
+
+/*****************************************************************************/
+
+      
+#ifdef MODULE
+#include <linux/module.h>
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#endif
+
+#include <linux/version.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/sound.h>
+#include <linux/malloc.h>
+#include <linux/soundcard.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <asm/spinlock.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+
+#include "maestro.h"
+#include "maestro_tables.h"
+
+/* --------------------------------------------------------------------- */
+
+#define M_DEBUG 1
+
+#ifdef M_DEBUG
+static int debug=0;
+#define M_printk(args...) {if (debug) printk(args);}
+#else
+#define M_printk(x)
+#endif
+
+/* --------------------------------------------------------------------- */
+
+#define DRIVER_VERSION "0.03"
+
+#ifndef PCI_VENDOR_ESS
+#define PCI_VENDOR_ESS			0x125D
+#define PCI_DEVICE_ID_ESS_ESS1968	0x1968		/* Maestro 2	*/
+#define PCI_DEVICE_ID_ESS_ESS1978      	0x1978		/* Maestro 2E	*/
+
+#define PCI_VENDOR_ESS_OLD		0x1285		/* vendor id for maestro 1 */
+#define PCI_DEVICE_ID_ESS_ESS0100	0x0100		/* maestro 1 */
+#endif /* PCI_VENDOR_ESS */
+
+#define ESS_CHAN_HARD		0x100
+
+#define ESS_CFMT_STEREO     0x01
+#define ESS_CFMT_16BIT      0x02
+#define ESS_CFMT_MASK       0x03
+#define ESS_CFMT_ASHIFT     0   
+#define ESS_CFMT_CSHIFT     4
+
+#define ESS_ENABLE_PE		1
+#define ESS_ENABLE_RE		2
+
+#define ESS_STATE_MAGIC		0x125D1968
+#define ESS_CARD_MAGIC		0x19283746
+
+#define DAC_RUNNING		1
+#define ADC_RUNNING		2
+
+static const unsigned sample_size[] = { 1, 2, 2, 4 };
+static const unsigned sample_shift[] = { 0, 1, 1, 2 };
+
+enum card_types_t {
+	TYPE_MAESTRO,
+	TYPE_MAESTRO2,
+	TYPE_MAESTRO2E
+};
+
+static const char *card_names[]={
+	[TYPE_MAESTRO] = "ESS Maestro",
+	[TYPE_MAESTRO2] = "ESS Maestro 2",
+	[TYPE_MAESTRO2E] = "ESS Maestro 2E"
+};
+
+#define SND_DEV_DSP16   5 
+
+/* --------------------------------------------------------------------- */
+
+struct ess_state {
+	unsigned int magic;
+	/* FIXME: we probably want submixers in here, but only one record pair */
+	u8 apu[4];		/* Left, Right, Left In, Right In */
+	u8 apu_mode[4];		/* Running mode for this APU */
+	u8 apu_pan[4];		/* Panning setup for this APU */
+	struct ess_card *card;	/* Card info */
+	/* wave stuff */
+	unsigned int rateadc, ratedac;
+	unsigned char fmt, enable;
+
+	spinlock_t lock;
+	struct semaphore open_sem;
+	mode_t open_mode;
+	wait_queue_head_t open_wait;
+
+	/* soundcore stuff */
+	int dev_audio;
+
+	struct dmabuf {
+		void *rawbuf;
+		unsigned buforder;
+		unsigned numfrag;
+		unsigned fragshift;
+		unsigned hwptr, swptr;
+		unsigned total_bytes;
+		int count;
+		unsigned error; /* over/underrun */
+		wait_queue_head_t wait;
+		/* redundant, but makes calculations easier */
+		unsigned fragsize;
+		unsigned dmasize;
+		unsigned fragsamples;
+		/* OSS stuff */
+		unsigned mapped:1;
+		unsigned ready:1;
+		unsigned endcleared:1;
+		unsigned ossfragshift;
+		int ossmaxfrags;
+		unsigned subdivision;
+		u16 base;		/* Offset for ptr */
+	} dma_dac, dma_adc;
+};
+	
+struct ess_card {
+	unsigned int magic;
+
+	/* We keep maestro cards in a linked list */
+	struct ess_card *next;
+
+	int dev_mixer;
+
+	int card_type;
+
+	/* as most of this is static,
+		perhaps it should be a pointer to a global struct */
+	struct mixer_goo {
+		int modcnt;
+		int supported_mixers;
+		int stereo_mixers;
+		int record_sources;
+		/* the caller must guarantee arg sanity before calling these */
+		int (*read_mixer)(struct ess_card *card, int index);
+		void (*write_mixer)(struct ess_card *card,int mixer, int vol);
+		int (*recmask_io)(struct ess_card *card,int rw,int mask);
+	} mix;
+	
+	struct ess_state channels[8];
+	u16 maestro_map[32];	/* Register map */
+
+	/* hardware resources */
+	u32 iobase;
+	u32 irq;
+
+};
+
+extern __inline__ unsigned ld2(unsigned int x)
+{
+	unsigned r = 0;
+	
+	if (x >= 0x10000) {
+		x >>= 16;
+		r += 16;
+	}
+	if (x >= 0x100) {
+		x >>= 8;
+		r += 8;
+	}
+	if (x >= 0x10) {
+		x >>= 4;
+		r += 4;
+	}
+	if (x >= 4) {
+		x >>= 2;
+		r += 2;
+	}
+	if (x >= 2)
+		r++;
+	return r;
+}
+
+
+/* --------------------------------------------------------------------- */
+
+static struct ess_card *devs = NULL;
+
+/* --------------------------------------------------------------------- */
+
+
+/*
+ *	ESS Maestro AC97 codec programming interface.
+ */
+	 
+static void maestro_ac97_set(int io, u8 cmd, u16 val)
+{
+	int i;
+	/*
+	 *	Wait for the codec bus to be free 
+	 */
+	 
+	for(i=0;i<10000;i++)
+	{
+		if(!(inb(io+ESS_AC97_INDEX)&1))
+			break;
+	}
+	/*
+	 *	Write the bus
+	 */ 
+	outw(val, io+ESS_AC97_DATA);
+	udelay(1);
+	/* should actually be delaying 10 milliseconds? */
+	outb(cmd, io+ESS_AC97_INDEX);
+	udelay(1);
+}
+
+static u16 maestro_ac97_get(int io, u8 cmd)
+{
+	int sanity=100000;
+	u16 data;
+	int i;
+	
+	/*
+	 *	Wait for the codec bus to be free 
+	 */
+	 
+	for(i=0;i<10000;i++)
+	{
+		if(!(inb(io+ESS_AC97_INDEX)&1))
+			break;
+	}
+
+	outb(cmd|0x80, io+ESS_AC97_INDEX);
+	udelay(1);
+	
+	while(inb(io+ESS_AC97_INDEX)&1)
+	{
+		sanity--;
+		if(!sanity)
+		{
+			printk(KERN_ERR "maestro: ac97 codec read timeout.\n");
+			return 0;
+		}
+	}
+	data=inw(io+ESS_AC97_DATA);
+	udelay(1);
+	return data;
+}
+
+/*
+ *	The Maestro can be wired to a standard AC97 compliant codec
+ *	(see www.intel.com for the pdf's on this), or to a PT101 codec
+ *	which appears to be the ES1918 (data sheet on the esstech.com.tw site)
+ *
+ *	The PT101 setup is untested.
+ */
+ 
+static u16 maestro_ac97_init(int iobase)
+{
+
+	int val, seid, caps;
+	u16 vend1, vend2;
+
+#if 0 /* an experiment for another time */
+		/* aim at the second codec */
+		outw(0x21, iobase+0x38);
+		outw(0x5555, iobase+0x3a);
+		outw(0x5555, iobase+0x3c);
+		udelay(1);
+		vend1 = maestro_ac97_get(iobase, 0x7c);
+		vend2 = maestro_ac97_get(iobase, 0x7e);
+		if(vend1 != 0xffff || vend2 != 0xffff) {
+			printk("maestro: It seems you have a second codec: %x %x, please report this.\n",
+				vend1,vend2);
+		}
+		/* back to the first */
+		outw(0x0, iobase+0x38);
+		outw(0x0, iobase+0x3a);
+		outw(0x0, iobase+0x3c);
+#endif
+
+	/* should make sure we're ac97 2.1? */
+	vend1 = maestro_ac97_get(iobase, 0x7c);
+	vend2 = maestro_ac97_get(iobase, 0x7e);
+
+	val = maestro_ac97_get(iobase, 0x00);
+	seid = val >> 8;
+	caps = val & 255;
+
+	printk(KERN_INFO "maestro: AC97 Codec detected: v: 0x%2x%2x 3d: 0x%x caps: 0x%x\n",
+		vend1,vend2,seid, caps);
+
+	switch ((long)(vend1 << 16) | vend2) {
+		/* magic vendor specifc init code, _no_ idea what these do */
+#if 0
+	case 0x83847609:	/* ESS 1921 */
+		maestro_ac97_set(iobase,0x76,0xABBA); /* o/~ Take a chance on me o/~ */
+		udelay(20);
+		maestro_ac97_set(iobase,0x78,0x3002);
+		udelay(20);
+		maestro_ac97_set(iobase,0x78,0x3802);
+		udelay(20);
+		break;
+#endif
+	default: break;
+	}
+
+	/* set master, headphone, master mono */
+        maestro_ac97_set(iobase, 0x02, 0x0000);
+	/* always set headphones to max unmuted, OSS won't 
+		let us change it :( */
+        maestro_ac97_set(iobase, 0x04, 0x0000);
+        maestro_ac97_set(iobase, 0x06, 0x0000);
+        maestro_ac97_set(iobase, 0x08, 0x0606);
+	/* beep, phone, mic, line, cd video, aux */
+	maestro_ac97_set(iobase, 0x0A, 0x1F1F);
+	maestro_ac97_set(iobase, 0x0C, 0x1F1F);
+	maestro_ac97_set(iobase, 0x0E, 0x1F1F);
+	maestro_ac97_set(iobase, 0x10, 0x1F1F);
+	maestro_ac97_set(iobase, 0x12, 0x1F1F);
+	maestro_ac97_set(iobase, 0x14, 0x1F1F);
+	maestro_ac97_set(iobase, 0x16, 0x1F1F);
+	/* unmute, but set pcm out to 1/2 */
+	maestro_ac97_set(iobase, 0x18, 0x0808);
+	/* null record select */
+	maestro_ac97_set(iobase, 0x1A, 0x0000);
+	/* record gain, record gain mic.. */
+	maestro_ac97_set(iobase, 0x1C, 0x0404);
+	maestro_ac97_set(iobase, 0x1E, 0x0404);
+	/* null misc stuff */
+	maestro_ac97_set(iobase, 0x20, 0x0000);
+	/* power up various units? */
+	maestro_ac97_set(iobase, 0x26, 0x000F);
+
+	return 0;
+}
+
+static u16 maestro_pt101_init(int iobase)
+{
+	printk(KERN_INFO "maestro: PT101 Codec detected, initializing but _not_ installing mixer device.\n");
+	/* who knows.. */
+	maestro_ac97_set(iobase, 0x2A, 0x0001);
+	maestro_ac97_set(iobase, 0x2C, 0x0000);
+	maestro_ac97_set(iobase, 0x2C, 0xFFFF);
+	maestro_ac97_set(iobase, 0x10, 0x9F1F);
+	maestro_ac97_set(iobase, 0x12, 0x0808);
+	maestro_ac97_set(iobase, 0x14, 0x9F1F);
+	maestro_ac97_set(iobase, 0x16, 0x9F1F);
+	maestro_ac97_set(iobase, 0x18, 0x0404);
+	maestro_ac97_set(iobase, 0x1A, 0x0000);
+	maestro_ac97_set(iobase, 0x1C, 0x0000);
+	maestro_ac97_set(iobase, 0x02, 0x0404);
+	maestro_ac97_set(iobase, 0x04, 0x0808);
+	maestro_ac97_set(iobase, 0x0C, 0x801F);
+	maestro_ac97_set(iobase, 0x0E, 0x801F);
+	return 0;
+}
+
+static void maestro_ac97_reset(int ioaddr)
+{
+	outw(0x2000,  ioaddr+0x36);
+	udelay(20);
+	outw(0x0000,  ioaddr+0x36);
+	udelay(200);
+}
+
+/*
+ *	Indirect register access. Not all registers are readable so we
+ *	need to keep register state ourselves
+ */
+ 
+#define WRITEABLE_MAP	0xEFFFFF
+#define READABLE_MAP	0x64003F
+
+/*
+ *	The Maestro engineers were a little indirection happy. These indirected
+ *	registers themselves include indirect registers at another layer
+ */
+ 
+static void maestro_write(struct ess_state *ess, u16 reg, u16 data)
+{
+	long ioaddr = ess->card->iobase;
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	outw(reg, ioaddr+0x02);
+	outw(data, ioaddr+0x00);
+	ess->card->maestro_map[reg]=data;
+	restore_flags(flags);
+}
+
+static u16 maestro_read(struct ess_state *ess, u16 reg)
+{
+	long ioaddr = ess->card->iobase;
+	if(READABLE_MAP & (1<<reg))
+	{
+		unsigned long flags;
+		save_flags(flags);
+		cli();
+		outw(reg, ioaddr+0x02);
+		ess->card->maestro_map[reg]=inw(ioaddr+0x00);
+		restore_flags(flags);
+	}
+	return ess->card->maestro_map[reg];
+}
+
+/*
+ *	These routines handle accessing the second level indirections to the
+ *	wave ram.
+ */
+
+/*
+ *	The register names are the ones ESS uses (see 104T31.ZIP)
+ */
+ 
+#define IDR0_DATA_PORT		0x00
+#define IDR1_CRAM_POINTER	0x01
+#define IDR2_CRAM_DATA		0x02
+#define IDR3_WAVE_DATA		0x03
+#define IDR4_WAVE_PTR_LOW	0x04
+#define IDR5_WAVE_PTR_HI	0x05
+#define IDR6_TIMER_CTRL		0x06
+#define IDR7_WAVE_ROMRAM	0x07
+
+static void apu_index_set(struct ess_state *ess, u16 index)
+{
+	int i;
+	maestro_write(ess, IDR1_CRAM_POINTER, index);
+	for(i=0;i<1000;i++)
+		if(maestro_read(ess, IDR1_CRAM_POINTER)==index)
+			return;
+	printk(KERN_WARNING "maestro: APU register select failed.\n");
+}
+
+static void apu_data_set(struct ess_state *ess, u16 data)
+{
+	int i;
+	for(i=0;i<1000;i++)
+	{
+		if(maestro_read(ess, IDR0_DATA_PORT)==data)
+			return;
+		maestro_write(ess, IDR0_DATA_PORT, data);
+	}
+}
+
+/*
+ *	This is the public interface for APU manipulation. It handles the
+ *	interlock to avoid two APU writes in parallel etc. Don't diddle
+ *	directly with the stuff above.
+ */
+
+static void apu_set_register(struct ess_state *ess, u16 channel, u8 reg, u16 data)
+{
+	unsigned long flags;
+	
+	if(channel&ESS_CHAN_HARD)
+		channel&=~ESS_CHAN_HARD;
+	else
+	{
+		if(channel>3)
+			printk("BAD CHANNEL %d.\n",channel);
+		else
+			channel = ess->apu[channel];
+	}
+	
+	reg|=(channel<<4);
+	
+	save_flags(flags);
+	cli();
+	apu_index_set(ess, reg);
+	apu_data_set(ess, data);
+	restore_flags(flags);
+}
+
+static u16 apu_get_register(struct ess_state *ess, u16 channel, u8 reg)
+{
+	unsigned long flags;
+	u16 v;
+	
+	if(channel&ESS_CHAN_HARD)
+		channel&=~ESS_CHAN_HARD;
+	else
+		channel = ess->apu[channel];
+
+	reg|=(channel<<4);
+	
+	save_flags(flags);
+	cli();
+	apu_index_set(ess, reg);
+	v=maestro_read(ess, IDR0_DATA_PORT);
+	restore_flags(flags);
+	return v;
+}
+
+
+/*
+ *	The wavecache does pci fetches for us and feeds
+ *	them to the APUs..  
+ *	XXX describe interface
+ */
+ 
+static void wave_set_register(struct ess_state *ess, u16 reg, u16 value)
+{
+	long ioaddr = ess->card->iobase;
+	unsigned long flags;
+	
+	save_flags(flags);
+	cli();
+	outw(reg, ioaddr+0x10);
+	outw(value, ioaddr+0x12);
+	restore_flags(flags);
+}
+
+static u16 wave_get_register(struct ess_state *ess, u16 reg)
+{
+	long ioaddr = ess->card->iobase;
+	unsigned long flags;
+	u16 value;
+	
+	save_flags(flags);
+	cli();
+	outw(reg, ioaddr+0x10);
+	value=inw(ioaddr+0x12);
+	restore_flags(flags);
+	
+	return value;
+}
+
+static void sound_reset(int ioaddr)
+{
+	outw(0x2000, 0x18+ioaddr);
+	udelay(10);
+	outw(0x0000, 0x18+ioaddr);
+	udelay(10);
+}
+
+static void set_apu_fmt(struct ess_state *s, int apu, int mode)
+{
+	if(mode&ESS_CFMT_16BIT) { 
+		s->apu_mode[apu] = 0x10;
+		s->apu_mode[apu+1] = 0x10;
+	} else {
+		s->apu_mode[apu] = 0x30;
+		s->apu_mode[apu+1] = 0x30;
+	}
+}
+
+static void set_fmt(struct ess_state *s, unsigned char mask, unsigned char data)
+{
+	s->fmt = (s->fmt & mask) | data;
+	set_apu_fmt(s, 0, s->fmt & ESS_CFMT_MASK);
+	set_apu_fmt(s, 2, (s->fmt >> ESS_CFMT_CSHIFT) & ESS_CFMT_MASK);
+}
+
+static u16 compute_rate(u32 freq)
+{
+	if(freq==48000)
+		return 0xFFFF;
+	freq<<=16;
+	freq/=48000;
+	return freq;
+}
+
+static void set_dac_rate(struct ess_state *s, unsigned rate)
+{
+	u32 freq;
+
+	if (rate > 48000)
+		rate = 48000;
+	if (rate < 4000)
+		rate = 4000;
+
+	s->ratedac = rate;
+
+	if(!(s->fmt & ESS_CFMT_16BIT))
+		rate >>= 1; /* who knows */
+
+/*	M_printk("computing dac rate %d with mode %d\n",rate,s->fmt);*/
+
+	freq = compute_rate(rate);
+	
+	/* Load the frequency, turn on 6dB, turn off the effects */
+	apu_set_register(s, 0, 2, (freq&0xFF)<<8|0x10);
+	apu_set_register(s, 0, 3, freq>>8);
+	apu_set_register(s, 1, 2, (freq&0xFF)<<8|0x10);
+	apu_set_register(s, 1, 3, freq>>8);
+}
+
+static void set_adc_rate(struct ess_state *s, unsigned rate)
+{
+	u32 freq;
+
+	if (rate > 48000)
+		rate = 48000;
+	if (rate < 4000)
+		rate = 4000;
+
+	s->rateadc = rate;
+
+	freq = compute_rate(rate);
+	
+	/* Load the frequency, turn on 6dB, turn off the effects */
+	apu_set_register(s, 2, 2, (freq&0xFF)<<8|0x10);
+	apu_set_register(s, 2, 3, freq>>8);
+	apu_set_register(s, 3, 2, (freq&0xFF)<<8|0x10);
+	apu_set_register(s, 3, 3, freq>>8);
+}
+
+
+/*
+ *	Native play back driver 
+ */
+
+static void ess_play_setup(struct ess_state *ess, int mode, u32 rate, void *buffer, int size)
+{
+	u32 pa;
+	u32 tmpval;
+	int high_apu = 0;
+	int channel;
+
+	M_printk("mode=%d rate=%d buf=%p len=%d.\n",
+		mode, rate, buffer, size);
+		
+	/* all maestro sizes are in 16bit words */
+	size >>=1;
+
+	/* we're given the full size of the buffer, but
+	in stereo each channel will only play its half */
+	if(mode&ESS_CFMT_STEREO) {
+		size >>=1; 
+		high_apu++;
+	}
+	
+	for(channel=0; channel <= high_apu; channel++)
+	{
+		int i;
+		
+		/*
+		 *	To understand this it helps to know how the
+		 *	wave cache works. There are 4 DSP wavecache 
+		 *	blocks which are 0x1FC->0x1FF. They are selected
+		 *	by setting bits  22,21,20 of the address to
+		 *	1 X Y   where X Y select the block.
+		 *
+		 *	In addition stereo pairing is supported. This is
+		 *	set in the wave cache control for the channel as is
+		 *	8bit unsigned.
+		 *
+		 *	Note that this causes a problem. With our limit of
+		 *	about 12 full duplex pairs (48 channels active) we
+		 *	will need to do a lot of juggling to get all the
+		 *	memory we want sufficiently close together.
+		 *	
+		 *	Even with 64K blocks that means
+		 *		24 channel pairs
+		 *		6 pairs/block
+		 *	
+		 *	10K per channel pair = 5000 samples.
+		 */
+		
+		if(!channel) 
+			pa = virt_to_bus(buffer);
+		else
+		/* right channel plays its split half.
+			*2 accomodates for rampant shifting earlier */
+			pa = virt_to_bus(buffer + size*2);
+
+		M_printk("sending pa %x to %d\n",pa,channel);
+		
+		wave_set_register(ess, 0x01FC, (pa&0xFFE00000)>>12);
+
+		/* set the wavecache control reg */
+		tmpval = (pa - 0x10) & 0xFFF8;
+#if 0
+		if(mode & 1) tmpval |= 2; /* stereo */
+#endif
+		if(!(mode & 2)) tmpval |= 4; /* 8bit */ 
+		wave_set_register(ess, ess->apu[channel]<<3, tmpval);
+		
+		pa&=0x1FFFFF;			/* Low 21 bits */	
+		pa>>=1; /* words */
+		
+		/* base offset of dma calcs when reading the pointer
+			on this left one */
+		if(!channel) ess->dma_dac.base = pa&0xFFFF;
+		
+#if 0
+		if(mode&ESS_CFMT_STEREO)			/* Enable stereo */
+			pa|=0x00800000;
+#endif
+		pa|=0x00400000;			/* System RAM */
+		
+		/* Begin loading the APU */		
+		for(i=0;i<15;i++)		/* clear all PBRs */
+			apu_set_register(ess, channel, i, 0x0000);
+			
+		/* Load the frequency, turn on 6dB, turn off the effects */
+/*		apu_set_register(ess, channel, 2, (rate&0xFF)<<8|0x10);
+		apu_set_register(ess, channel, 3, rate>>8);*/
+		
+		/* Load the buffer into the wave engine */
+		apu_set_register(ess, channel, 4, ((pa>>16)&0xFF)<<8);
+		/* XXX reg is little endian.. */
+		apu_set_register(ess, channel, 5, pa&0xFFFF);
+		apu_set_register(ess, channel, 6, (pa+size)&0xFFFF);
+		/* setting loop == sample len */
+		apu_set_register(ess, channel, 7, size);
+		
+		/* clear effects/env.. */
+		apu_set_register(ess, channel, 8, 0x0000);
+		/* aplitudeNow to 0xd0? */
+		apu_set_register(ess, channel, 9, 0xD000);
+
+		/* set the panning reg of the apu to left/right/mid.. */
+
+		/* clear routing stuff */
+		apu_set_register(ess, channel, 11, 0x0000);
+		/* mark dma and turn on filter stuff? */
+		apu_set_register(ess, channel, 0, 0x400F);
+		
+		if(mode&ESS_CFMT_STEREO)
+			/* set panning: left or right */
+			apu_set_register(ess, channel, 10, 0x8F00 | (channel ? 0x10 : 0));
+		else
+			apu_set_register(ess, channel, 10, 0x8F08);
+
+	}
+	
+	/* clear WP interupts */
+	outw(1, ess->card->iobase+0x04);
+	/* enable WP ints */
+	outw(inw(ess->card->iobase+0x18)|4, ess->card->iobase+0x18);
+
+	set_dac_rate(ess,rate);
+
+	for(channel=0; channel<=high_apu; channel++)
+	{
+		/* Turn on the DMA */
+		if(mode&ESS_CFMT_16BIT)
+		{
+			apu_set_register(ess, channel, 0,
+				(apu_get_register(ess, channel, 0)&0xFF0F)|0x10);
+			ess->apu_mode[channel]=0x10;
+		}
+		else
+		{
+			apu_set_register(ess, channel, 0,
+				(apu_get_register(ess, channel, 0)&0xFF0F)|0x30);
+			ess->apu_mode[channel]=0x30;
+		}
+	}
+}
+
+/* --------------------------------------------------------------------- */
+
+static void set_dmaa(struct ess_state *s, unsigned int addr, unsigned int count)
+{
+}
+
+static void set_dmac(struct ess_state *s, unsigned int addr, unsigned int count)
+{
+}
+
+/* Playback pointer */
+extern __inline__ unsigned get_dmaa(struct ess_state *s)
+{
+	long ioport = s->card->iobase;
+	int offset;
+	
+	outw(1, ioport+2);
+	outw(s->apu[0]<<4|5, ioport);
+	outw(0, ioport+2);
+	offset=inw(ioport);
+
+/*	M_printk("dmaa: offset: %d, base: %d\n",offset,s->dma_dac.base);*/
+	
+	offset-=s->dma_dac.base;
+
+	return (offset&0xFFFE)/*<<1*/; /* XXX printk didn't have it */
+}
+
+/* Record pointer */
+extern __inline__ unsigned get_dmac(struct ess_state *s)
+{
+	long ioport = s->card->iobase;
+	int offset;
+	
+	outw(1, ioport+2);
+	outw(s->apu[2]<<4|5, ioport);
+	outw(0, ioport+2);
+	offset=inw(ioport);
+	
+	/* The offset is an address not a position relative to base */
+	
+	return (offset&0xFFFE)<<1; /* hardware is in words */
+}
+
+/*
+ *	Meet Bob, the timer...
+ */
+
+static void ess_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+#define ESS_HW_TIMER
+
+#ifndef ESS_HW_TIMER
+
+/* old kernel timer based timer ints, should BOB prove flakey */
+
+static struct timer_list tmp_timer;
+
+static int bob_stopped;
+
+static void ess_interrupt_fake(unsigned long v)
+{
+	ess_interrupt(5, (void *)v, NULL);
+	del_timer(&tmp_timer);
+	if(!bob_stopped)
+	{
+		tmp_timer.expires=jiffies+1;
+		add_timer(&tmp_timer);
+	}
+	else
+		M_printk("Stopping bob (SW)\n");
+}
+
+static void stop_bob(struct ess_state *s)
+{
+	bob_stopped=1;
+}
+
+static void kill_bob(struct ess_state *s)
+{
+	del_timer(&tmp_timer);
+	M_printk("Killing bob (SW)\n");
+}
+
+static void start_bob(struct ess_state *s)
+{
+	static int init=1;
+	if(init)
+	{
+		init=0;
+		init_timer(&tmp_timer);
+		tmp_timer.function = ess_interrupt_fake;
+	}
+	bob_stopped = 0;
+	if(!timer_pending(&tmp_timer))
+	{
+		del_timer(&tmp_timer);
+		tmp_timer.expires = jiffies+1;
+		tmp_timer.data = (unsigned long)s->card;
+		add_timer(&tmp_timer);
+		M_printk("Starting bob (SW)\n");
+	}
+}
+
+#else
+
+/* nice HW BOB implementation.  cheers, eric. */
+
+static void stop_bob(struct ess_state *s)
+{
+	/* Mask IDR 11,17 */
+	maestro_write(s,  0x11, maestro_read(s, 0x11)&~1);
+	maestro_write(s,  0x17, maestro_read(s, 0x17)&~1);
+}
+
+/* eventually we could be clever and limit bob ints
+	to the frequency at which our smallest duration
+	chunks may expire */
+static void start_bob(struct ess_state *s)
+{
+	stop_bob(s);	// make sure bob's not already running
+	
+	maestro_write(s, 6, 0x8000 |(1<<12) | (5<<5) | 11);		// (50MHz/2^14)/12 = 254 Hz = 40 mS
+	
+	/* Now set IDR 11/17 */
+	maestro_write(s, 0x11, maestro_read(s, 0x11)|1);
+	maestro_write(s, 0x17, maestro_read(s, 0x17)|1);
+}
+#endif // ESS_HW_TIMER
+/* --------------------------------------------------------------------- */
+
+static int adc_active = 0;
+
+extern inline void stop_adc(struct ess_state *s)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+	/* Stop left and right recording APU */
+	s->enable &= ~ADC_RUNNING;
+	apu_set_register(s, 2, 0, apu_get_register(s, 2, 0)&0xFF0F);
+	apu_set_register(s, 3, 0, apu_get_register(s, 3, 0)&0xFF0F);
+	adc_active&=~1;
+//	if(!adc_active)
+//		stop_bob(s);
+	spin_unlock_irqrestore(&s->lock, flags);
+}	
+
+extern inline void stop_dac(struct ess_state *s)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+	s->enable &= ~DAC_RUNNING;
+	apu_set_register(s, 0, 0, apu_get_register(s, 0, 0)&0xFF0F);
+	apu_set_register(s, 1, 0, apu_get_register(s, 1, 0)&0xFF0F);
+	adc_active&=~2;
+//	if(!adc_active)
+//		stop_bob(s);
+	spin_unlock_irqrestore(&s->lock, flags);
+}	
+
+static void start_dac(struct ess_state *s)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+	if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) {
+		s->enable |= DAC_RUNNING;
+
+		apu_set_register(s, 0, 0, 
+			(apu_get_register(s, 0, 0)&0xFF0F)|s->apu_mode[0]);
+
+		if(s->fmt & ESS_CFMT_STEREO) 
+			apu_set_register(s, 1, 0, 
+				(apu_get_register(s, 1, 0)&0xFF0F)|s->apu_mode[1]);
+	}
+//	if(!adc_active)
+//		start_bob(s);
+	adc_active|=2;
+	spin_unlock_irqrestore(&s->lock, flags);
+}	
+
+static void start_adc(struct ess_state *s)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+	if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) 
+	    && s->dma_adc.ready) {
+		s->enable |= ADC_RUNNING;
+		apu_set_register(s, 2, 0, 
+			(apu_get_register(s, 2, 0)&0xFF0F)|s->apu_mode[2]);
+		apu_set_register(s, 3, 0, 
+			(apu_get_register(s, 3, 0)&0xFF0F)|s->apu_mode[3]);
+	}
+//	if(!adc_active)
+//		start_bob(s);
+	adc_active|=1;
+	spin_unlock_irqrestore(&s->lock, flags);
+}	
+
+/* --------------------------------------------------------------------- */
+
+#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
+#define DMABUF_MINORDER 1
+
+static void dealloc_dmabuf(struct dmabuf *db)
+{
+	unsigned long map, mapend;
+
+	if (db->rawbuf) {
+		/* undo marking the pages as reserved */
+		mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
+		for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
+			clear_bit(PG_reserved, &mem_map[map].flags);	
+		free_pages((unsigned long)db->rawbuf, db->buforder);
+	}
+	db->rawbuf = NULL;
+	db->mapped = db->ready = 0;
+}
+
+
+static int prog_dmabuf(struct ess_state *s, unsigned rec)
+{
+	struct dmabuf *db = rec ? &s->dma_adc : &s->dma_dac;
+	unsigned rate = rec ? s->rateadc : s->ratedac;
+	int order;
+	unsigned bytepersec;
+	unsigned bufs;
+	unsigned long map, mapend;
+	unsigned char fmt;
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+	fmt = s->fmt;
+	if (rec) {
+		s->enable &= ~ESS_ENABLE_RE;
+		fmt >>= ESS_CFMT_CSHIFT;
+	} else {
+		s->enable &= ~ESS_ENABLE_PE;
+		fmt >>= ESS_CFMT_ASHIFT;
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+
+	db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
+
+	if (!db->rawbuf) {
+		db->ready = db->mapped = 0;
+
+		/* alloc as big a chunk as we can */
+		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER && !db->rawbuf; order--)
+			db->rawbuf = (void *)__get_free_pages(GFP_KERNEL|GFP_DMA, order);
+
+		if (!db->rawbuf)
+			return -ENOMEM;
+
+		db->buforder = order;
+
+		if ((virt_to_bus(db->rawbuf) ^ (virt_to_bus(db->rawbuf) + (PAGE_SIZE << db->buforder) - 1)) & ~0xffff)
+			printk(KERN_DEBUG "maestro: DMA buffer crosses 64k boundary: busaddr 0x%lx  size %ld\n", 
+			       virt_to_bus(db->rawbuf), PAGE_SIZE << db->buforder);
+
+		if ((virt_to_bus(db->rawbuf) + (PAGE_SIZE << db->buforder) - 1) & ~0xffffff)
+			printk(KERN_DEBUG "maestro: DMA buffer beyond 16MB: busaddr 0x%lx  size %ld\n", 
+			       virt_to_bus(db->rawbuf), PAGE_SIZE << db->buforder);
+
+		/* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
+		mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
+		for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
+			set_bit(PG_reserved, &mem_map[map].flags);
+	}
+	bytepersec = rate << sample_shift[fmt];
+	bufs = PAGE_SIZE << db->buforder;
+	if (db->ossfragshift) {
+		if ((1000 << db->ossfragshift) < bytepersec)
+			db->fragshift = ld2(bytepersec/1000);
+		else
+			db->fragshift = db->ossfragshift;
+	} else {
+		db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1));
+		if (db->fragshift < 3)
+			db->fragshift = 3;
+	}
+	db->numfrag = bufs >> db->fragshift;
+	while (db->numfrag < 4 && db->fragshift > 3) {
+		db->fragshift--;
+		db->numfrag = bufs >> db->fragshift;
+	}
+	db->fragsize = 1 << db->fragshift;
+	if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)
+		db->numfrag = db->ossmaxfrags;
+	db->fragsamples = db->fragsize >> sample_shift[fmt];
+	db->dmasize = db->numfrag << db->fragshift;
+	memset(db->rawbuf, (fmt & ESS_CFMT_16BIT) ? 0 : 0x80, db->dmasize);
+	spin_lock_irqsave(&s->lock, flags);
+	if (rec) {
+		set_dmac(s, virt_to_bus(db->rawbuf), db->numfrag << db->fragshift);
+		/* program enhanced mode registers */
+		/* FILL */
+	} else {
+		//set_dmaa(s, virt_to_bus(db->rawbuf), db->numfrag << db->fragshift);
+		/* program enhanced mode registers */
+		/* FILL */
+		//set_dac_rate(s, s->ratedac);	// redundant
+		ess_play_setup(s, fmt, s->ratedac, 
+			db->rawbuf, db->numfrag << db->fragshift);
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	db->ready = 1;
+	return 0;
+}
+
+extern __inline__ void clear_advance(struct ess_state *s)
+{
+	unsigned char c = (s->fmt & (ESS_CFMT_16BIT << ESS_CFMT_ASHIFT)) ? 0 : 0x80;
+	unsigned char *buf = s->dma_dac.rawbuf;
+	unsigned bsize = s->dma_dac.dmasize;
+	unsigned bptr = s->dma_dac.swptr;
+	unsigned len = s->dma_dac.fragsize;
+
+	if (bptr + len > bsize) {
+		unsigned x = bsize - bptr;
+		memset(buf + bptr, c, x);
+		/* account for wrapping? */
+		bptr = 0;
+		len -= x;
+	}
+	memset(buf + bptr, c, len);
+}
+
+/* call with spinlock held! */
+static void ess_update_ptr(struct ess_state *s)
+{
+	unsigned hwptr;
+	int diff;
+
+	/* update ADC pointer */
+	if (s->dma_adc.ready) {
+		M_printk("adc ready.. \n");
+		hwptr = (/*s->dma_adc.dmasize - */get_dmac(s)) % s->dma_adc.dmasize;
+		diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize;
+		s->dma_adc.hwptr = hwptr;
+		s->dma_adc.total_bytes += diff;
+		s->dma_adc.count += diff;
+		if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) 
+			wake_up(&s->dma_adc.wait);
+		if (!s->dma_adc.mapped) {
+			if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
+				s->enable &= ~ESS_ENABLE_RE;
+				/* FILL ME */
+//				wrindir(s, SV_CIENABLE, s->enable);
+				stop_adc(s);
+				s->dma_adc.error++;
+			}
+		}
+	}
+	/* update DAC pointer */
+	if (s->dma_dac.ready) {
+		hwptr = (/*s->dma_dac.dmasize -*/ get_dmaa(s)) % s->dma_dac.dmasize;
+		diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize;
+/*		M_printk("updating dac: hwptr: %d diff: %d\n",hwptr,diff);*/
+		s->dma_dac.hwptr = hwptr;
+		s->dma_dac.total_bytes += diff;
+		if (s->dma_dac.mapped) {
+			s->dma_dac.count += diff;
+			if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)
+				wake_up(&s->dma_dac.wait);
+		} else {
+			s->dma_dac.count -= diff;
+			if (s->dma_dac.count <= 0) {
+				s->enable &= ~ESS_ENABLE_PE;
+/* FILL ME */
+//				wrindir(s, SV_CIENABLE, s->enable);
+
+				stop_dac(s);
+				s->dma_dac.error++;
+			} else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) {
+				clear_advance(s);
+				s->dma_dac.endcleared = 1;
+			}
+			if (s->dma_dac.count + (signed)s->dma_dac.fragsize <= (signed)s->dma_dac.dmasize)
+				wake_up(&s->dma_dac.wait);
+		}
+	}
+}
+
+static void ess_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+        struct ess_state *s;
+        struct ess_card *c = (struct ess_card *)dev_id;
+	int i;
+	u32 event;
+
+	event = inb(c->iobase+0x1A);
+	
+	outw(inw(c->iobase+4)&1, c->iobase+4);
+
+/*	M_printk("maestro int: %x\n",event);*/
+
+	if(event&(1<<6))
+	{
+		/* XXX if we have a hw volume control int enable
+			all the ints?  doesn't make sense.. */
+		event = inw(c->iobase+0x18);
+		outb(0xFF, c->iobase+0x1A);
+	}
+	else
+	{
+		/* else ack 'em all, i imagine */
+		outb(0xFF, c->iobase+0x1A);
+	}
+		
+	/*
+	 *	Update the pointers for all APU's we are running.
+	 */
+	for(i=0;i<8;i++)
+	{
+		s=&c->channels[i];
+		if(s->dev_audio == -1)
+			break;
+		spin_lock(&s->lock);
+		ess_update_ptr(s);
+		spin_unlock(&s->lock);
+	}
+}
+
+
+/* --------------------------------------------------------------------- */
+
+static const char invalid_magic[] = KERN_CRIT "maestro: invalid magic value in %s\n";
+
+#define VALIDATE_MAGIC(FOO,MAG)                         \
+({                                                \
+	if (!(FOO) || (FOO)->magic != MAG) { \
+		printk(invalid_magic,__FUNCTION__);            \
+		return -ENXIO;                    \
+	}                                         \
+})
+
+#define VALIDATE_STATE(a) VALIDATE_MAGIC(a,ESS_STATE_MAGIC)
+#define VALIDATE_CARD(a) VALIDATE_MAGIC(a,ESS_CARD_MAGIC)
+
+/* --------------------------------------------------------------------- */
+
+/* ac97 mixer routines.  */
+
+#define AC97_STEREO_MASK (SOUND_MASK_VOLUME|\
+	SOUND_MASK_PCM|SOUND_MASK_LINE|SOUND_MASK_CD|\
+	SOUND_MASK_VIDEO|SOUND_MASK_LINE1|SOUND_MASK_IGAIN)
+
+#define AC97_SUPPORTED_MASK (AC97_STEREO_MASK | \
+	SOUND_MASK_BASS|SOUND_MASK_TREBLE|SOUND_MASK_MIC|\
+	SOUND_MASK_SPEAKER)
+
+#define AC97_RECORD_MASK (SOUND_MASK_MIC|\
+	SOUND_MASK_CD| SOUND_MASK_VIDEO| SOUND_MASK_LINE1| SOUND_MASK_LINE|\
+	SOUND_MASK_PHONEIN)
+
+#define supported_mixer(CARD,FOO) ( CARD->mix.supported_mixers & (1<<FOO) )
+
+static struct ac97_mixer_hw {
+	unsigned char offset;
+	int scale;
+} ac97_hw[SOUND_MIXER_NRDEVICES]= {
+	[SOUND_MIXER_VOLUME]	=	{0x02,63},
+	[SOUND_MIXER_BASS]	=	{0x08,15},
+	[SOUND_MIXER_TREBLE]	=	{0x08,15},
+	[SOUND_MIXER_SPEAKER]	=	{0x0a,15},
+	[SOUND_MIXER_MIC]	=	{0x0e,31},
+	[SOUND_MIXER_LINE]	=	{0x10,31},
+	[SOUND_MIXER_CD]	=	{0x12,31},
+	[SOUND_MIXER_VIDEO]	=	{0x14,31},
+	[SOUND_MIXER_LINE1]	=	{0x16,31},
+	[SOUND_MIXER_PCM]	=	{0x18,31},
+	[SOUND_MIXER_IGAIN]	=	{0x1c,31}
+};
+
+/* reads the given OSS mixer from the ac97
+	the caller must have insured that the ac97 knows
+	about that given mixer, and should be holding a
+	spinlock for the card */
+static int ac97_read_mixer(struct ess_card *card, int mixer) 
+{
+	u16 val;
+	int ret=0;
+	struct ac97_mixer_hw *mh = &ac97_hw[mixer];
+
+	val = maestro_ac97_get(card->iobase , mh->offset);
+
+	if(AC97_STEREO_MASK & (1<<mixer)) {
+		/* nice stereo mixers .. */
+		int left,right;
+
+		left = (val >> 8)  & 0x7f;
+		right = val  & 0x7f;
+
+		right = 100 - ((right * 100) / mh->scale);
+		left = 100 - ((left * 100) / mh->scale);
+		ret = left | (right << 8);
+	} else if (mixer == SOUND_MIXER_SPEAKER) {
+		ret = 100 - ((((val & 0x1e)>>1) * 100) / mh->scale);
+	} else if (mixer == SOUND_MIXER_MIC) {
+		ret = 100 - (((val & 0x1f) * 100) / mh->scale);
+	/*  the low bit is optional in the tone sliders and masking
+		it lets is avoid the 0xf 'bypass'.. */
+	} else if (mixer == SOUND_MIXER_BASS) {
+		ret = 100 - ((((val >> 8) & 0xe) * 100) / mh->scale);
+	} else if (mixer == SOUND_MIXER_TREBLE) {
+		ret = 100 - (((val & 0xe) * 100) / mh->scale);
+	}
+
+	M_printk("read mixer %d (0x%x) %x -> %x\n",mixer,mh->offset,val,ret);
+
+	return ret;
+}
+
+/* write the OSS encoded volume to the given OSS encoded mixer,
+	again caller's job to make sure all is well in arg land,
+	call with spinlock held */
+static void ac97_write_mixer(struct ess_card *card,int mixer, int vol) 
+{
+	u16 val=0;
+	unsigned left, right;
+	struct ac97_mixer_hw *mh = &ac97_hw[mixer];
+
+	/* cleanse input a little */
+	right = ((vol >> 8)  & 0x7f) ;
+	left = (vol  & 0x7f) ;
+
+	if(right > 100) right = 100;
+	if(left > 100) left = 100;
+
+	M_printk("wrote mixer %d (0x%x) %d,%d",mixer,mh->offset,left,right);
+
+	if(AC97_STEREO_MASK & (1<<mixer)) {
+		/* stereo mixers */
+
+		right = ((100 - right) * mh->scale) / 100;
+		left = ((100 - left) * mh->scale) / 100;
+
+		val = (left << 8) | right;
+	} else if (mixer == SOUND_MIXER_SPEAKER) {
+		val = (((100 - left) * mh->scale) / 100) << 1;
+	} else if (mixer == SOUND_MIXER_MIC) {
+		val = maestro_ac97_get(card->iobase , mh->offset) & ~0x001f;
+		val |= (((100 - left) * mh->scale) / 100);
+	/*  the low bit is optional in the tone sliders and masking
+		it lets is avoid the 0xf 'bypass'.. */
+	} else if (mixer == SOUND_MIXER_BASS) {
+		val = maestro_ac97_get(card->iobase , mh->offset) & ~0x0f00;
+		val |= ((((100 - left) * mh->scale) / 100) << 8) & 0xe0;
+	} else if (mixer == SOUND_MIXER_TREBLE)  {
+		val = maestro_ac97_get(card->iobase , mh->offset) & ~0x000f;
+		val |= (((100 - left) * mh->scale) / 100) & 0xe;
+	}
+
+	maestro_ac97_set(card->iobase , mh->offset, val);
+	
+	M_printk(" -> %x\n",val);
+}
+
+enum ac97_recsettings {
+	AC97_REC_MIC=0,
+	AC97_REC_CD,
+	AC97_REC_VIDEO,
+	AC97_REC_AUX,
+	AC97_REC_LINE,
+	AC97_REC_STEREO, /* combination of all enabled outputs..  */
+	AC97_REC_MONO,        /*.. or the mono equivalent */
+	AC97_REC_PHONE        
+};
+static unsigned int ac97_rm2oss[] = {
+	[AC97_REC_MIC] = SOUND_MASK_MIC, 
+	[AC97_REC_CD] = SOUND_MASK_CD, 
+	[AC97_REC_VIDEO] = SOUND_MASK_VIDEO, 
+	[AC97_REC_AUX] = SOUND_MASK_LINE1, 
+	[AC97_REC_LINE] = SOUND_MASK_LINE, 
+	[AC97_REC_PHONE] = SOUND_MASK_PHONEIN
+};
+
+/* indexed by bit position, XXX dependant on OSS header internals */
+static unsigned int ac97_oss_rm[] = {
+	[SOUND_MIXER_MIC] = AC97_REC_MIC,
+	[SOUND_MIXER_CD] = AC97_REC_CD,
+	[SOUND_MIXER_VIDEO] = AC97_REC_VIDEO,
+	[SOUND_MIXER_LINE1] = AC97_REC_AUX,
+	[SOUND_MIXER_LINE] = AC97_REC_LINE,
+	[SOUND_MIXER_PHONEIN] = AC97_REC_PHONE
+};
+	
+/* read or write the recmask 
+	the ac97 can really have left and right recording
+	inputs independantly set, but OSS doesn't seem to 
+	want us to express that to the user. 
+	the caller guarantees that we have a supported bit set,
+	and they must be holding the card's spinlock */
+static int ac97_recmask_io(struct ess_card *card, int rw, int mask) 
+{
+	unsigned int val;
+
+	if (rw) {
+		/* read it from the card */
+		val = maestro_ac97_get(card->iobase, 0x1a) & 0x7;
+		return ac97_rm2oss[val];
+	}
+
+	/* else, write the first set in the mask as the
+		output */	
+
+	val = ffs(mask); 
+	val = ac97_oss_rm[val-1];
+	val |= val << 8;  /* set both channels */
+
+	maestro_ac97_set(card->iobase,0x1a,val);
+
+	return 0;
+};
+
+static int ac97_mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long arg)
+{
+	unsigned long flags;
+	int i, val=0;
+	struct ess_state *s = &card->channels[0];
+
+	VALIDATE_CARD(card);
+        if (cmd == SOUND_MIXER_INFO) {
+		mixer_info info;
+		strncpy(info.id, card_names[card->card_type], sizeof(info.id));
+		strncpy(info.name,card_names[card->card_type],sizeof(info.name));
+		info.modify_counter = card->mix.modcnt;
+		if (copy_to_user((void *)arg, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	if (cmd == SOUND_OLD_MIXER_INFO) {
+		_old_mixer_info info;
+		strncpy(info.id, card_names[card->card_type], sizeof(info.id));
+		strncpy(info.name,card_names[card->card_type],sizeof(info.name));
+		if (copy_to_user((void *)arg, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	if (cmd == OSS_GETVERSION)
+		return put_user(SOUND_VERSION, (int *)arg);
+
+	if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
+                return -EINVAL;
+
+        if (_IOC_DIR(cmd) == _IOC_READ) {
+                switch (_IOC_NR(cmd)) {
+                case SOUND_MIXER_RECSRC: /* give them the current record source */
+			spin_lock_irqsave(&s->lock, flags);
+			val = card->mix.recmask_io(card,1,0);
+			spin_unlock_irqrestore(&s->lock, flags);
+			break;
+			
+                case SOUND_MIXER_DEVMASK: /* give them the supported mixers */
+			val = card->mix.supported_mixers;
+			break;
+
+                case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
+			val = card->mix.record_sources;
+			break;
+			
+                case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
+			val = card->mix.stereo_mixers;
+			break;
+			
+                case SOUND_MIXER_CAPS:
+			val = SOUND_CAP_EXCL_INPUT;
+			break;
+
+		default: /* read a specific mixer */
+			i = _IOC_NR(cmd);
+
+			if ( ! supported_mixer(card,i)) 
+				return -EINVAL;
+
+			spin_lock_irqsave(&s->lock, flags);
+			val = card->mix.read_mixer(card,i);
+			spin_unlock_irqrestore(&s->lock, flags);
+
+			break;
+		}
+		return put_user(val,(int *)arg);
+	}
+	
+        if (_IOC_DIR(cmd) != (_IOC_WRITE|_IOC_READ))
+		return -EINVAL;
+	
+	card->mix.modcnt++;
+
+	get_user_ret(val, (int *)arg, -EFAULT);
+
+	switch (_IOC_NR(cmd)) {
+	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
+
+		if(! (val &= card->mix.record_sources)) return -EINVAL;
+
+		spin_lock_irqsave(&s->lock, flags);
+		card->mix.recmask_io(card,0,val);
+		spin_unlock_irqrestore(&s->lock, flags);
+		return 0;
+
+	default:
+		i = _IOC_NR(cmd);
+
+		if ( ! supported_mixer(card,i)) 
+			return -EINVAL;
+
+		spin_lock_irqsave(&s->lock, flags);
+		card->mix.write_mixer(card,i,val);
+		spin_unlock_irqrestore(&s->lock, flags);
+
+		return 0;
+	}
+}
+
+/* --------------------------------------------------------------------- */
+
+static loff_t ess_llseek(struct file *file, loff_t offset, int origin)
+{
+	return -ESPIPE;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int ess_open_mixdev(struct inode *inode, struct file *file)
+{
+	int minor = MINOR(inode->i_rdev);
+	struct ess_card *card = devs;
+
+	while (card && card->dev_mixer != minor)
+		card = card->next;
+	if (!card)
+		return -ENODEV;
+
+	file->private_data = card;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int ess_release_mixdev(struct inode *inode, struct file *file)
+{
+	struct ess_card *card = (struct ess_card *)file->private_data;
+
+	VALIDATE_CARD(card);
+	
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int ess_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct ess_card *card = (struct ess_card *)file->private_data;
+
+	VALIDATE_CARD(card);
+
+	return ac97_mixer_ioctl(card, cmd, arg);
+}
+
+static /*const*/ struct file_operations ess_mixer_fops = {
+	&ess_llseek,
+	NULL,  /* read */
+	NULL,  /* write */
+	NULL,  /* readdir */
+	NULL,  /* poll */
+	&ess_ioctl_mixdev,
+	NULL,  /* mmap */
+	&ess_open_mixdev,
+	NULL,	/* flush */
+	&ess_release_mixdev,
+	NULL,  /* fsync */
+	NULL,  /* fasync */
+	NULL,  /* check_media_change */
+	NULL,  /* revalidate */
+	NULL,  /* lock */
+};
+
+/* --------------------------------------------------------------------- */
+
+static int drain_dac(struct ess_state *s, int nonblock)
+{
+        DECLARE_WAITQUEUE(wait,current);
+	unsigned long flags;
+	int count, tmo;
+
+	if (s->dma_dac.mapped || !s->dma_dac.ready)
+		return 0;
+        current->state = TASK_INTERRUPTIBLE;
+        add_wait_queue(&s->dma_dac.wait, &wait);
+        for (;;) {
+                spin_lock_irqsave(&s->lock, flags);
+		count = s->dma_dac.count;
+                spin_unlock_irqrestore(&s->lock, flags);
+		if (count <= 0)
+			break;
+		if (signal_pending(current))
+                        break;
+                if (nonblock) {
+                        remove_wait_queue(&s->dma_dac.wait, &wait);
+                        current->state = TASK_RUNNING;
+                        return -EBUSY;
+                }
+		tmo = (count * HZ) / s->ratedac;
+		tmo >>= sample_shift[(s->fmt >> ESS_CFMT_ASHIFT) & ESS_CFMT_MASK];
+		if (!schedule_timeout(tmo ? : 1) && tmo)
+			printk(KERN_DEBUG "maestro: dma timed out??\n");
+        }
+        remove_wait_queue(&s->dma_dac.wait, &wait);
+        current->state = TASK_RUNNING;
+        if (signal_pending(current))
+                return -ERESTARTSYS;
+        return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static ssize_t ess_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct ess_state *s = (struct ess_state *)file->private_data;
+	ssize_t ret;
+	unsigned long flags;
+	unsigned swptr;
+	/* for damned dual players */
+	int cnt;
+
+	VALIDATE_STATE(s);
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (s->dma_adc.mapped)
+		return -ENXIO;
+	if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
+		return ret;
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return -EFAULT;
+	ret = 0;
+#if 0
+   spin_lock_irqsave(&s->lock, flags);
+   ess_update_ptr(s);
+   spin_unlock_irqrestore(&s->lock, flags);
+#endif
+	while (count > 0) {
+		spin_lock_irqsave(&s->lock, flags);
+		swptr = s->dma_adc.swptr;
+		cnt = s->dma_adc.dmasize-swptr;
+		if (s->dma_adc.count < cnt)
+			cnt = s->dma_adc.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		if (cnt > count)
+			cnt = count;
+		if (cnt <= 0) {
+			start_adc(s);
+			if (file->f_flags & O_NONBLOCK) 
+				return ret ? ret : -EAGAIN;
+			if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) {
+				printk(KERN_DEBUG "maestro: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+				       s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count, 
+				       s->dma_adc.hwptr, s->dma_adc.swptr);
+				stop_adc(s);
+				spin_lock_irqsave(&s->lock, flags);
+				set_dmac(s, virt_to_bus(s->dma_adc.rawbuf), s->dma_adc.numfrag << s->dma_adc.fragshift);
+				/* program enhanced mode registers */
+				/* FILL ME */
+//				wrindir(s, SV_CIDMACBASECOUNT1, (s->dma_adc.fragsamples-1) >> 8);
+//				wrindir(s, SV_CIDMACBASECOUNT0, s->dma_adc.fragsamples-1);
+				s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;
+				spin_unlock_irqrestore(&s->lock, flags);
+			}
+			if (signal_pending(current)) 
+				return ret ? ret : -ERESTARTSYS;
+			continue;
+		}
+		if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) 
+			return ret ? ret : -EFAULT;
+		swptr = (swptr + cnt) % s->dma_adc.dmasize;
+		spin_lock_irqsave(&s->lock, flags);
+		s->dma_adc.swptr = swptr;
+		s->dma_adc.count -= cnt;
+		spin_unlock_irqrestore(&s->lock, flags);
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+		start_adc(s);
+	}
+
+	return ret;
+}
+
+/* god this is gross..*/
+int split_stereo(unsigned char *real_buffer,unsigned char  *tmp_buffer, int offset, 
+	int count, int bufsize, int mode)
+{  
+	/* oh, bother.	stereo decoding APU's don't work in 16bit so we
+	use dual linear decoders.  which means we have to hack up stereo
+	buffer's we're given.  yuck. 
+
+	and we have to be able to work a byte at a time..*/
+
+	unsigned char *so,*left,*right;
+	int i;
+
+	so = tmp_buffer;
+	left = real_buffer + offset;
+	right = real_buffer + bufsize/2 + offset;
+
+	M_printk("writing %d to %p and %p from %p:%d bufs: %d\n",count/2, left,right,real_buffer,offset,bufsize);
+
+	if(mode & ESS_CFMT_16BIT) {
+		for(i=count/4; i ; i--) {
+			*(right++) = (*(so+2));
+			*(right++) = (*(so+3));
+			*(left++) = (*so);
+			*(left++) = (*(so+1));
+			so+=4;
+		}
+	} else {
+		for(i=count/2; i ; i--) {
+			*(right++) = (*(so+1));
+			*(left++) = (*so);
+			so+=2;
+		}
+	}
+
+	return 0;
+}
+
+static ssize_t ess_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+	struct ess_state *s = (struct ess_state *)file->private_data;
+	ssize_t ret;
+	unsigned long flags;
+	unsigned swptr;
+	unsigned char *splitbuf = NULL;
+	int cnt;
+
+	VALIDATE_STATE(s);
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (s->dma_dac.mapped)
+		return -ENXIO;
+	if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+		return ret;
+	if (!access_ok(VERIFY_READ, buffer, count))
+		return -EFAULT;
+	/* I wish we could be more clever than this */
+	if (!(splitbuf = kmalloc(count,GFP_KERNEL)))
+		return -ENOMEM; 
+	ret = 0;
+#if 0
+   spin_lock_irqsave(&s->lock, flags);
+   ess_update_ptr(s);
+   spin_unlock_irqrestore(&s->lock, flags);
+#endif
+	while (count > 0) {
+		spin_lock_irqsave(&s->lock, flags);
+
+		if (s->dma_dac.count < 0) {
+			s->dma_dac.count = 0;
+			s->dma_dac.swptr = s->dma_dac.hwptr;
+		}
+		swptr = s->dma_dac.swptr;
+
+		if(s->fmt & ESS_CFMT_STEREO) {
+			/* in stereo we have the 'dual' buffers.. */
+			cnt = ((s->dma_dac.dmasize/2)-swptr)*2;
+		} else {
+			cnt = s->dma_dac.dmasize-swptr;
+		}
+		if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
+			cnt = s->dma_dac.dmasize - s->dma_dac.count;
+
+		spin_unlock_irqrestore(&s->lock, flags);
+
+		if (cnt > count)
+			cnt = count;
+
+		/* our goofball stereo splitter can only deal in mults of 4 */
+		if (cnt > 0) 
+			cnt &= ~3;
+
+		if (cnt <= 0) {
+			/* buffer is full, wait for it to be played */
+			start_dac(s);
+			if (file->f_flags & O_NONBLOCK) {
+				if(!ret) ret = -EAGAIN;
+				goto return_free;
+			}
+			if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) {
+				printk(KERN_DEBUG "maestro: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+				       s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count, 
+				       s->dma_dac.hwptr, s->dma_dac.swptr);
+				stop_dac(s);
+				spin_lock_irqsave(&s->lock, flags);
+				set_dmaa(s, virt_to_bus(s->dma_dac.rawbuf), s->dma_dac.numfrag << s->dma_dac.fragshift);
+				/* program enhanced mode registers */
+//				wrindir(s, SV_CIDMAABASECOUNT1, (s->dma_dac.fragsamples-1) >> 8);
+//				wrindir(s, SV_CIDMAABASECOUNT0, s->dma_dac.fragsamples-1);
+				/* FILL ME */
+				s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;
+				spin_unlock_irqrestore(&s->lock, flags);
+			}
+			if (signal_pending(current)) {
+				if (!ret) ret = -ERESTARTSYS;
+				goto return_free;
+			}
+			continue;
+		}
+		if(s->fmt & ESS_CFMT_STEREO) {
+			if (copy_from_user(splitbuf, buffer, cnt)) {
+				if (!ret) ret = -EFAULT;
+				goto return_free;
+			}
+			split_stereo(s->dma_dac.rawbuf,splitbuf,swptr,cnt,s->dma_dac.dmasize,s->fmt);
+		} else {
+			if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
+				if (!ret) ret = -EFAULT;
+				goto return_free;
+			}
+		}
+
+		if(s->fmt & ESS_CFMT_STEREO) {
+			/* again with the weird pointer magic*/
+			swptr = (swptr + (cnt/2)) % (s->dma_dac.dmasize/2);
+		} else {
+			swptr = (swptr + cnt) % s->dma_dac.dmasize;
+		}
+		spin_lock_irqsave(&s->lock, flags);
+		s->dma_dac.swptr = swptr;
+		s->dma_dac.count += cnt;
+		s->dma_dac.endcleared = 0;
+		spin_unlock_irqrestore(&s->lock, flags);
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+		start_dac(s);
+	}
+return_free:
+	if (splitbuf) kfree(splitbuf);
+	return ret;
+}
+
+static unsigned int ess_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct ess_state *s = (struct ess_state *)file->private_data;
+	unsigned long flags;
+	unsigned int mask = 0;
+
+	VALIDATE_STATE(s);
+	if (file->f_mode & FMODE_WRITE)
+		poll_wait(file, &s->dma_dac.wait, wait);
+	if (file->f_mode & FMODE_READ)
+		poll_wait(file, &s->dma_adc.wait, wait);
+	spin_lock_irqsave(&s->lock, flags);
+	ess_update_ptr(s);
+	if (file->f_mode & FMODE_READ) {
+		if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
+			mask |= POLLIN | POLLRDNORM;
+	}
+	if (file->f_mode & FMODE_WRITE) {
+		if (s->dma_dac.mapped) {
+			if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) 
+				mask |= POLLOUT | POLLWRNORM;
+		} else {
+			if ((signed)s->dma_dac.dmasize >= s->dma_dac.count + (signed)s->dma_dac.fragsize)
+				mask |= POLLOUT | POLLWRNORM;
+		}
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	return mask;
+}
+
+/* this needs to be fixed to deal with the dualing apus/buffers */
+#if 0
+static int ess_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct ess_state *s = (struct ess_state *)file->private_data;
+	struct dmabuf *db;
+	int ret;
+	unsigned long size;
+
+	VALIDATE_STATE(s);
+	if (vma->vm_flags & VM_WRITE) {
+		if ((ret = prog_dmabuf(s, 1)) != 0)
+			return ret;
+		db = &s->dma_dac;
+	} else if (vma->vm_flags & VM_READ) {
+		if ((ret = prog_dmabuf(s, 0)) != 0)
+			return ret;
+		db = &s->dma_adc;
+	} else 
+		return -EINVAL;
+	if (vma->vm_offset != 0)
+		return -EINVAL;
+	size = vma->vm_end - vma->vm_start;
+	if (size > (PAGE_SIZE << db->buforder))
+		return -EINVAL;
+	if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
+		return -EAGAIN;
+	db->mapped = 1;
+	return 0;
+}
+#endif
+
+static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct ess_state *s = (struct ess_state *)file->private_data;
+	unsigned long flags;
+        audio_buf_info abinfo;
+        count_info cinfo;
+	int val, mapped, ret;
+	unsigned char fmtm, fmtd;
+
+	VALIDATE_STATE(s);
+        mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||
+		((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
+	switch (cmd) {
+	case OSS_GETVERSION:
+		return put_user(SOUND_VERSION, (int *)arg);
+
+	case SNDCTL_DSP_SYNC:
+		if (file->f_mode & FMODE_WRITE)
+			return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/);
+		return 0;
+		
+	case SNDCTL_DSP_SETDUPLEX:
+		return 0;
+
+	case SNDCTL_DSP_GETCAPS:
+		return put_user(0/*DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP*/, (int *)arg);
+		
+        case SNDCTL_DSP_RESET:
+		if (file->f_mode & FMODE_WRITE) {
+			stop_dac(s);
+			synchronize_irq();
+			s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = s->dma_dac.total_bytes = 0;
+		}
+		if (file->f_mode & FMODE_READ) {
+			stop_adc(s);
+			synchronize_irq();
+			s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0;
+		}
+		return 0;
+
+        case SNDCTL_DSP_SPEED:
+                get_user_ret(val, (int *)arg, -EFAULT);
+		if (val >= 0) {
+			if (file->f_mode & FMODE_READ) {
+				stop_adc(s);
+				s->dma_adc.ready = 0;
+				set_adc_rate(s, val);
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				stop_dac(s);
+				s->dma_dac.ready = 0;
+				set_dac_rate(s, val);
+			}
+		}
+		return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
+		
+        case SNDCTL_DSP_STEREO:
+		get_user_ret(val, (int *)arg, -EFAULT);
+		fmtd = 0;
+		fmtm = ~0;
+		if (file->f_mode & FMODE_READ) {
+			stop_adc(s);
+			s->dma_adc.ready = 0;
+			if (val)
+				fmtd |= ESS_CFMT_STEREO << ESS_CFMT_CSHIFT;
+			else
+				fmtm &= ~(ESS_CFMT_STEREO << ESS_CFMT_CSHIFT);
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			stop_dac(s);
+			s->dma_dac.ready = 0;
+			if (val)
+				fmtd |= ESS_CFMT_STEREO << ESS_CFMT_ASHIFT;
+			else
+				fmtm &= ~(ESS_CFMT_STEREO << ESS_CFMT_ASHIFT);
+		}
+		set_fmt(s, fmtm, fmtd);
+		return 0;
+
+        case SNDCTL_DSP_CHANNELS:
+                get_user_ret(val, (int *)arg, -EFAULT);
+		if (val != 0) {
+			fmtd = 0;
+			fmtm = ~0;
+			if (file->f_mode & FMODE_READ) {
+				stop_adc(s);
+				s->dma_adc.ready = 0;
+				if (val >= 2)
+					fmtd |= ESS_CFMT_STEREO << ESS_CFMT_CSHIFT;
+				else
+					fmtm &= ~(ESS_CFMT_STEREO << ESS_CFMT_CSHIFT);
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				stop_dac(s);
+				s->dma_dac.ready = 0;
+				if (val >= 2)
+					fmtd |= ESS_CFMT_STEREO << ESS_CFMT_ASHIFT;
+				else
+					fmtm &= ~(ESS_CFMT_STEREO << ESS_CFMT_ASHIFT);
+			}
+			set_fmt(s, fmtm, fmtd);
+		}
+		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (ESS_CFMT_STEREO << ESS_CFMT_CSHIFT) 
+					   : (ESS_CFMT_STEREO << ESS_CFMT_ASHIFT))) ? 2 : 1, (int *)arg);
+		
+	case SNDCTL_DSP_GETFMTS: /* Returns a mask */
+                return put_user(AFMT_S8|AFMT_S16_LE, (int *)arg);
+		
+	case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
+		get_user_ret(val, (int *)arg, -EFAULT);
+		if (val != AFMT_QUERY) {
+			fmtd = 0;
+			fmtm = ~0;
+			if (file->f_mode & FMODE_READ) {
+				stop_adc(s);
+				s->dma_adc.ready = 0;
+				if (val == AFMT_S16_LE)
+					fmtd |= ESS_CFMT_16BIT << ESS_CFMT_CSHIFT;
+				else
+					fmtm &= ~(ESS_CFMT_16BIT << ESS_CFMT_CSHIFT);
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				stop_dac(s);
+				s->dma_dac.ready = 0;
+				if (val == AFMT_S16_LE)
+					fmtd |= ESS_CFMT_16BIT << ESS_CFMT_ASHIFT;
+				else
+					fmtm &= ~(ESS_CFMT_16BIT << ESS_CFMT_ASHIFT);
+			}
+			set_fmt(s, fmtm, fmtd);
+		}
+ 		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? 
+			(ESS_CFMT_16BIT << ESS_CFMT_CSHIFT) 
+			: (ESS_CFMT_16BIT << ESS_CFMT_ASHIFT))) ? 
+				AFMT_S16_LE : 
+				AFMT_S8, 
+			(int *)arg);
+		
+	case SNDCTL_DSP_POST:
+                return 0;
+
+        case SNDCTL_DSP_GETTRIGGER:
+		val = 0;
+		if (file->f_mode & FMODE_READ && s->enable & ESS_ENABLE_RE) 
+			val |= PCM_ENABLE_INPUT;
+		if (file->f_mode & FMODE_WRITE && s->enable & ESS_ENABLE_PE) 
+			val |= PCM_ENABLE_OUTPUT;
+		return put_user(val, (int *)arg);
+		
+	case SNDCTL_DSP_SETTRIGGER:
+		get_user_ret(val, (int *)arg, -EFAULT);
+		if (file->f_mode & FMODE_READ) {
+			if (val & PCM_ENABLE_INPUT) {
+				if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))
+					return ret;
+				start_adc(s);
+			} else
+				stop_adc(s);
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			if (val & PCM_ENABLE_OUTPUT) {
+				if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+					return ret;
+				start_dac(s);
+			} else
+				stop_dac(s);
+		}
+		return 0;
+
+	case SNDCTL_DSP_GETOSPACE:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		if (!(s->enable & ESS_ENABLE_PE) && (val = prog_dmabuf(s, 0)) != 0)
+			return val;
+		spin_lock_irqsave(&s->lock, flags);
+		ess_update_ptr(s);
+		abinfo.fragsize = s->dma_dac.fragsize;
+                abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count;
+                abinfo.fragstotal = s->dma_dac.numfrag;
+                abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;      
+		spin_unlock_irqrestore(&s->lock, flags);
+		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+
+	case SNDCTL_DSP_GETISPACE:
+		if (!(file->f_mode & FMODE_READ))
+			return -EINVAL;
+		if (!(s->enable & ESS_ENABLE_RE) && (val = prog_dmabuf(s, 1)) != 0)
+			return val;
+		spin_lock_irqsave(&s->lock, flags);
+		ess_update_ptr(s);
+		abinfo.fragsize = s->dma_adc.fragsize;
+                abinfo.bytes = s->dma_adc.count;
+                abinfo.fragstotal = s->dma_adc.numfrag;
+                abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
+		spin_unlock_irqrestore(&s->lock, flags);
+		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+		
+        case SNDCTL_DSP_NONBLOCK:
+                file->f_flags |= O_NONBLOCK;
+                return 0;
+
+        case SNDCTL_DSP_GETODELAY:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		spin_lock_irqsave(&s->lock, flags);
+		ess_update_ptr(s);
+                val = s->dma_dac.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		return put_user(val, (int *)arg);
+
+        case SNDCTL_DSP_GETIPTR:
+		if (!(file->f_mode & FMODE_READ))
+			return -EINVAL;
+		spin_lock_irqsave(&s->lock, flags);
+		ess_update_ptr(s);
+                cinfo.bytes = s->dma_adc.total_bytes;
+                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+                cinfo.ptr = s->dma_adc.hwptr;
+		if (s->dma_adc.mapped)
+			s->dma_adc.count &= s->dma_adc.fragsize-1;
+		spin_unlock_irqrestore(&s->lock, flags);
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+        case SNDCTL_DSP_GETOPTR:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		spin_lock_irqsave(&s->lock, flags);
+		ess_update_ptr(s);
+                cinfo.bytes = s->dma_dac.total_bytes;
+                cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
+                cinfo.ptr = s->dma_dac.hwptr;
+		if (s->dma_dac.mapped)
+			s->dma_dac.count &= s->dma_dac.fragsize-1;
+		spin_unlock_irqrestore(&s->lock, flags);
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+        case SNDCTL_DSP_GETBLKSIZE:
+		if (file->f_mode & FMODE_WRITE) {
+			if ((val = prog_dmabuf(s, 0)))
+				return val;
+			return put_user(s->dma_dac.fragsize, (int *)arg);
+		}
+		if ((val = prog_dmabuf(s, 1)))
+			return val;
+		return put_user(s->dma_adc.fragsize, (int *)arg);
+
+        case SNDCTL_DSP_SETFRAGMENT:
+                get_user_ret(val, (int *)arg, -EFAULT);
+		if (file->f_mode & FMODE_READ) {
+			s->dma_adc.ossfragshift = val & 0xffff;
+			s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
+			if (s->dma_adc.ossfragshift < 4)
+				s->dma_adc.ossfragshift = 4;
+			if (s->dma_adc.ossfragshift > 15)
+				s->dma_adc.ossfragshift = 15;
+			if (s->dma_adc.ossmaxfrags < 4)
+				s->dma_adc.ossmaxfrags = 4;
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			s->dma_dac.ossfragshift = val & 0xffff;
+			s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff;
+			if (s->dma_dac.ossfragshift < 4)
+				s->dma_dac.ossfragshift = 4;
+			if (s->dma_dac.ossfragshift > 15)
+				s->dma_dac.ossfragshift = 15;
+			if (s->dma_dac.ossmaxfrags < 4)
+				s->dma_dac.ossmaxfrags = 4;
+		}
+		return 0;
+
+        case SNDCTL_DSP_SUBDIVIDE:
+		if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
+		    (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
+			return -EINVAL;
+                get_user_ret(val, (int *)arg, -EFAULT);
+		if (val != 1 && val != 2 && val != 4)
+			return -EINVAL;
+		if (file->f_mode & FMODE_READ)
+			s->dma_adc.subdivision = val;
+		if (file->f_mode & FMODE_WRITE)
+			s->dma_dac.subdivision = val;
+		return 0;
+
+        case SOUND_PCM_READ_RATE:
+		return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
+
+        case SOUND_PCM_READ_CHANNELS:
+		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (ESS_CFMT_STEREO << ESS_CFMT_CSHIFT) 
+					   : (ESS_CFMT_STEREO << ESS_CFMT_ASHIFT))) ? 2 : 1, (int *)arg);
+
+        case SOUND_PCM_READ_BITS:
+		return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (ESS_CFMT_16BIT << ESS_CFMT_CSHIFT) 
+					   : (ESS_CFMT_16BIT << ESS_CFMT_ASHIFT))) ? 16 : 8, (int *)arg);
+
+        case SOUND_PCM_WRITE_FILTER:
+        case SNDCTL_DSP_SETSYNCRO:
+        case SOUND_PCM_READ_FILTER:
+                return -EINVAL;
+		
+	}
+//	return mixer_ioctl(s, cmd, arg);
+	return -EINVAL;
+}
+
+static int ess_open(struct inode *inode, struct file *file)
+{
+	int minor = MINOR(inode->i_rdev);
+	struct ess_card *c = devs;
+	struct ess_state *s = NULL, *sp;
+	int i;
+	unsigned char fmtm = ~0, fmts = 0;
+
+	/*
+	 *	Scan the cards and find the channel. We only
+	 *	do this at open time so it is ok
+	 */
+	 
+	while (c!=NULL)
+	{
+		for(i=0;i<8;i++)
+		{
+			sp=&c->channels[i];
+			if(sp->dev_audio < 0)
+				continue;
+			if((sp->dev_audio ^ minor) & ~0xf)
+				continue;
+			s=sp;
+		}
+		c=c->next;
+	}
+		
+	if (!s)
+		return -ENODEV;
+		
+       	VALIDATE_STATE(s);
+	file->private_data = s;
+	/* wait for device to become free */
+	down(&s->open_sem);
+	while (s->open_mode & file->f_mode) {
+		if (file->f_flags & O_NONBLOCK) {
+			up(&s->open_sem);
+			return -EWOULDBLOCK;
+		}
+		up(&s->open_sem);
+		interruptible_sleep_on(&s->open_wait);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+		down(&s->open_sem);
+	}
+	if (file->f_mode & FMODE_READ) {
+		fmtm &= ~((ESS_CFMT_STEREO | ESS_CFMT_16BIT) << ESS_CFMT_CSHIFT);
+		if ((minor & 0xf) == SND_DEV_DSP16)
+			fmts |= ESS_CFMT_16BIT << ESS_CFMT_CSHIFT;
+		s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0;
+		set_adc_rate(s, 8000);
+	}
+	if (file->f_mode & FMODE_WRITE) {
+		fmtm &= ~((ESS_CFMT_STEREO | ESS_CFMT_16BIT) << ESS_CFMT_ASHIFT);
+		if ((minor & 0xf) == SND_DEV_DSP16)
+			fmts |= ESS_CFMT_16BIT << ESS_CFMT_ASHIFT;
+		s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0;
+		set_dac_rate(s, 8000);
+	}
+	set_fmt(s, fmtm, fmts);
+	s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
+	start_bob(s);
+	up(&s->open_sem);
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int ess_release(struct inode *inode, struct file *file)
+{
+	struct ess_state *s = (struct ess_state *)file->private_data;
+
+	VALIDATE_STATE(s);
+	if (file->f_mode & FMODE_WRITE)
+		drain_dac(s, file->f_flags & O_NONBLOCK);
+	down(&s->open_sem);
+	if (file->f_mode & FMODE_WRITE) {
+		stop_dac(s);
+		dealloc_dmabuf(&s->dma_dac);
+	}
+	if (file->f_mode & FMODE_READ) {
+		stop_adc(s);
+		dealloc_dmabuf(&s->dma_adc);
+	}
+	s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
+	stop_bob(s);
+	up(&s->open_sem);
+	wake_up(&s->open_wait);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static /*const*/ struct file_operations ess_audio_fops = {
+	&ess_llseek,
+	&ess_read,
+	&ess_write,
+	NULL,  /* readdir */
+	&ess_poll,
+	&ess_ioctl,
+	NULL,	/* XXX &ess_mmap, */
+	&ess_open,
+	NULL,	/* flush */
+	&ess_release,
+	NULL,  /* fsync */
+	NULL,  /* fasync */
+	NULL,  /* check_media_change */
+	NULL,  /* revalidate */
+	NULL,  /* lock */
+};
+
+
+/* --------------------------------------------------------------------- */
+
+/*	XXX get rid of this
+ *	maximum number of devices 
+ */
+#define NR_DEVICE 4
+
+/* --------------------------------------------------------------------- */
+
+static int maestro_install(struct pci_dev *pcidev, int card_type, int index)
+{
+	u16 w;
+	u32 n;
+	int iobase;
+	int i;
+	struct ess_card *card;
+	struct ess_state *ess;
+	int apu;
+	int num = 0;
+			
+	iobase = pcidev->resource[0].start;
+
+	card = kmalloc(sizeof(struct ess_card), GFP_KERNEL);
+	if(card == NULL)
+	{
+		printk(KERN_WARNING "maestro: out of memory\n");
+		return 0;
+	}
+	
+	memset(card, 0, sizeof(*card));
+
+	card->iobase = iobase;
+	card->card_type = card_type;
+	card->irq = pcidev->irq;
+	card->next = devs;
+	card->magic = ESS_CARD_MAGIC;
+	devs = card;
+	
+	/* init our 8 groups of 4 apus */
+	for(i=0;i<8;i++)
+	{
+		struct ess_state *s=&card->channels[i];
+		
+		s->card = card;
+		init_waitqueue_head(&s->dma_adc.wait);
+		init_waitqueue_head(&s->dma_dac.wait);
+		init_waitqueue_head(&s->open_wait);
+		init_MUTEX(&s->open_sem);
+		s->magic = ESS_STATE_MAGIC;
+		
+		s->apu[0] = 4*i;
+		s->apu[1] = (4*i)+1;
+		s->apu[2] = (4*i)+2;
+		s->apu[3] = (4*i)+3;
+		
+		if(s->dma_adc.ready || s->dma_dac.ready || s->dma_adc.rawbuf)
+			printk("BOTCH!\n");
+		/* register devices */
+		if ((s->dev_audio = register_sound_dsp(&ess_audio_fops, -1)) < 0)
+			break;
+	}
+	
+	num = i;
+	
+	/* clear the rest if we ran out of slots to register */
+	for(;i<8;i++)
+	{
+		struct ess_state *s=&card->channels[i];
+		s->dev_audio = -1;
+	}
+	
+	ess = &card->channels[0];
+	
+	/*
+	 *	Ok card ready. Begin setup proper
+	 */
+	 
+	printk(KERN_INFO "maestro: Configuring %s at 0x%04X\n", card_names[card_type], iobase);
+
+	/*
+	 *	Disable ACPI
+	 */
+	 
+	pci_write_config_dword(pcidev, 0x54, 0x00000000);
+	pci_write_config_dword(pcidev, 0x56, 0x00000000);
+	
+	/*
+	 *	Use TDMA for now. TDMA works on all boards, so while its
+	 *	not the most efficient its the simplest.
+	 */ 
+	 
+	pci_read_config_word(pcidev, 0x50, &w);
+
+	/* Clear DMA bits */
+	w&=~(1<<10|1<<9|1<<8);
+
+	/* TDMA on */
+	w|=(1<<8);
+
+/* XXX do we care about these two ? */
+	/*
+	 *	MPU at 330
+	 */
+	
+	w&=~((1<<4)|(1<<3));
+	
+	/*
+	 *	SB at 0x220
+	 */
+
+	w&=~(1<<2);
+	
+#if 0 /* huh?  its sub decode.. */
+
+	/*
+	 *	Reserved write as 0
+	 */
+	 
+	w&=~(1<<1);
+#endif
+	
+	/*
+	 *	Some of these are undocumented bits
+	 */
+	 
+	w&=~(1<<13)|(1<<14);		/* PIC Snoop mode bits */
+	w&=~(1<<11);			/* Safeguard off */
+	w|= (1<<7);			/* Posted write */
+	w|= (1<<6);			/* ISA timing on */
+	w&=~(1<<1);			/* Subtractive decode off */
+	/* XXX huh?  claims to be reserved.. */
+	w&=~(1<<5);			/* Don't swap left/right */
+	
+	pci_write_config_word(pcidev, 0x50, w);
+	
+	pci_read_config_word(pcidev, 0x52, &w);
+	w&=~(1<<15);		/* Turn off internal clock multiplier */
+	/* XXX how do we know which to use? */
+	w&=~(1<<14);		/* External clock */
+	
+	w&=~(1<<7);		/* HWV off */
+	w&=~(1<<6);		/* Debounce off */
+	w&=~(1<<5);		/* GPIO 4:5 */
+	w&=~(1<<4);		/* Disconnect from the CHI */
+	w&=~(1<<3);		/* IDMA off (undocumented) */
+	w&=~(1<<2);		/* MIDI fix off (undoc) */
+	w&=~(1<<1);		/* reserved, always write 0 */
+	w&=~(1<<0);		/* IRQ to ISA off (undoc) */
+	pci_write_config_word(pcidev, 0x52, w);
+
+	/*
+	 *	DDMA off
+	 */
+
+	pci_read_config_word(pcidev, 0x60, &w);
+	w&=~(1<<0);
+	pci_write_config_word(pcidev, 0x60, w);
+	
+	/*
+	 *	Legacy mode
+	 */
+
+	pci_read_config_word(pcidev, 0x40, &w);
+	w|=(1<<15);	/* legacy decode off */
+	w&=~(1<<14);	/* Disable SIRQ */
+	w&=~(0x1f);	/* disable mpu irq/io, game port, fm, SB */
+	 
+	pci_write_config_word(pcidev, 0x40, w);
+
+	sound_reset(iobase);
+
+	/*
+	 *	Reset the CODEC
+	 */
+	 
+	maestro_ac97_reset(iobase);
+		
+	/*
+	 *	Ring Bus Setup
+	 */
+	 	 
+	n=inl(iobase+0x34);
+	n&=~0xF000;
+	n|=12<<12;		/* Direct Sound, Stereo */
+
+	n=inl(iobase+0x34);
+	n&=~0x0F00;		/* Modem off */
+	outl(n, iobase+0x34);
+
+	n=inl(iobase+0x34);
+	n&=~0x00F0;
+	n|=9<<4;		/* DAC, Stereo */
+	outl(n, iobase+0x34);
+	
+	n=inl(iobase+0x34);
+	n&=~0x000F;		/* ASSP off */
+	outl(n, iobase+0x34);
+	
+	
+	n=inl(iobase+0x34);
+	n|=(1<<29);		/* Enable ring bus */
+	outl(n, iobase+0x34);
+	
+	
+	n=inl(iobase+0x34);
+	n|=(1<<28);		/* Enable serial bus */
+	outl(n, iobase+0x34);
+	
+	n=inl(iobase+0x34);
+	n&=~0x00F00000;		/* MIC off */
+	outl(n, iobase+0x34);
+	
+	n=inl(iobase+0x34);
+	n&=~0x000F0000;		/* I2S off */
+	outl(n, iobase+0x34);
+	
+	w=inw(iobase+0x18);
+	w&=~(1<<7);		/* ClkRun off */
+	outw(w, iobase+0x18);
+
+	w=inw(iobase+0x18);
+	w&=~(1<<6);		/* Harpo off */
+	outw(w, iobase+0x18);
+	
+	w=inw(iobase+0x18);
+	w&=~(1<<4);		/* ASSP irq off */
+	outw(w, iobase+0x18);
+	
+	w=inw(iobase+0x18);
+	w&=~(1<<3);		/* ISDN irq off */
+	outw(w, iobase+0x18);
+	
+	w=inw(iobase+0x18);
+	w|=(1<<2);		/* Direct Sound IRQ on */
+	outw(w, iobase+0x18);
+
+	w=inw(iobase+0x18);
+	w&=~(1<<1);		/* MPU401 IRQ off */
+	outw(w, iobase+0x18);
+
+	w=inw(iobase+0x18);
+	w|=(1<<0);		/* SB IRQ on */
+	outw(w, iobase+0x18);
+
+
+	outb(0, iobase+0xA4);
+	outb(3, iobase+0xA2);
+	outb(0, iobase+0xA6);
+	
+	for(apu=0;apu<16;apu++)
+	{
+		/* Write 0 into the buffer area 0x1E0->1EF */
+		outw(0x01E0+apu, 0x10+iobase);
+		outw(0x0000, 0x12+iobase);
+	
+		/*
+		 * The 1.10 test program seem to write 0 into the buffer area
+		 * 0x1D0-0x1DF too.
+		 */
+		outw(0x01D0+apu, 0x10+iobase);
+		outw(0x0000, 0x12+iobase);
+	}
+
+#if 1
+	wave_set_register(ess, IDR7_WAVE_ROMRAM, 
+		(wave_get_register(ess, IDR7_WAVE_ROMRAM)&0xFF00));
+	wave_set_register(ess, IDR7_WAVE_ROMRAM,
+		wave_get_register(ess, IDR7_WAVE_ROMRAM)|0x100);
+	wave_set_register(ess, IDR7_WAVE_ROMRAM,
+		wave_get_register(ess, IDR7_WAVE_ROMRAM)&~0x200);
+	wave_set_register(ess, IDR7_WAVE_ROMRAM,
+		wave_get_register(ess, IDR7_WAVE_ROMRAM)|~0x400);
+#else		
+	maestro_write(ess, IDR7_WAVE_ROMRAM, 
+		(maestro_read(ess, IDR7_WAVE_ROMRAM)&0xFF00));
+	maestro_write(ess, IDR7_WAVE_ROMRAM,
+		maestro_read(ess, IDR7_WAVE_ROMRAM)|0x100);
+	maestro_write(ess, IDR7_WAVE_ROMRAM,
+		maestro_read(ess, IDR7_WAVE_ROMRAM)&~0x200);
+	maestro_write(ess, IDR7_WAVE_ROMRAM,
+		maestro_read(ess, IDR7_WAVE_ROMRAM)|0x400);
+#endif
+	
+	maestro_write(ess, IDR2_CRAM_DATA, 0x0000);
+	maestro_write(ess, 0x08, 0xB004);
+	/* Now back to the DirectSound stuff */
+	maestro_write(ess, 0x09, 0x001B);
+	maestro_write(ess, 0x0A, 0x8000);
+	maestro_write(ess, 0x0B, 0x3F37);
+	maestro_write(ess, 0x0C, 0x0098);
+	
+	maestro_write(ess, 0x0C, 
+		(maestro_read(ess, 0x0C)&~0xF000)|0x8000);
+	maestro_write(ess, 0x0C, 
+		(maestro_read(ess, 0x0C)&~0x0F00)|0x0500);
+
+	maestro_write(ess, 0x0D, 0x7632);
+			
+	/* Wave cache control on - test off, sg off, 
+		enable, enable extra chans 1Mb */
+		
+	outw(inw(0x14+iobase)|(1<<8),0x14+iobase);
+	outw(inw(0x14+iobase)&0xFE03,0x14+iobase);
+	outw((inw(0x14+iobase)&0xFFFC), 0x14+iobase);
+	outw(inw(0x14+iobase)|(1<<7),0x14+iobase);
+
+	outw(0xA1A0, 0x14+iobase);	/* 0300 ? */
+
+	if(maestro_ac97_get(iobase, 0x00)==0x0080)
+	{
+		maestro_pt101_init(iobase);
+	}
+	else
+	{
+		maestro_ac97_init(iobase);
+		card->mix.supported_mixers = AC97_SUPPORTED_MASK;
+		card->mix.stereo_mixers = AC97_STEREO_MASK;
+		card->mix.record_sources = AC97_RECORD_MASK;
+		card->mix.read_mixer = ac97_read_mixer;
+		card->mix.write_mixer = ac97_write_mixer;
+		card->mix.recmask_io = ac97_recmask_io;
+
+		if ((card->dev_mixer = register_sound_mixer(&ess_mixer_fops, -1)) < 0)
+			printk("maestro: couldn't register mixer!\n");
+	}
+	
+	/* Now clear the channel data */	
+	for(apu=0;apu<64;apu++)
+	{
+		for(w=0;w<0x0E;w++)
+			apu_set_register(ess, apu|ESS_CHAN_HARD, w, 0);
+	}
+	
+	if(request_irq(card->irq, ess_interrupt, SA_SHIRQ, card_names[card_type], card))
+	{
+		printk(KERN_ERR "maestro: unable to allocate irq %d,\n", card->irq);
+		return 0;
+	}
+
+//	ess_play_test(ess);
+	printk("maestro: %d channels configured.\n", num);
+	return 1; 
+}
+
+#ifdef MODULE
+
+int __init init_module(void)
+#else
+int __init init_maestro(void)
+#endif
+{
+	struct pci_dev *pcidev = NULL;
+	int index = 0;
+
+	if (!pci_present())   /* No PCI bus in this machine! */
+		return -ENODEV;
+	printk(KERN_INFO "maestro: version " DRIVER_VERSION " time " __TIME__ " " __DATE__ "\n");
+
+	pcidev = NULL;
+
+	/*
+	 *	Find the ESS Maestro 2.
+	 */
+
+	while((pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1968, pcidev))!=NULL)
+	{
+		index+=maestro_install(pcidev, TYPE_MAESTRO2, index);
+		if(index == NR_DEVICE)
+			return index;
+	}
+
+	/*
+	 *	Find the ESS Maestro 2E
+	 */
+
+	while((pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1978, pcidev))!=NULL)
+	{
+		index+=maestro_install(pcidev, TYPE_MAESTRO2E, index);
+		if(index == NR_DEVICE)
+			return index;
+	}
+
+	/*
+	 *	ESS Maestro 1
+	 */
+
+	while((pcidev = pci_find_device(PCI_VENDOR_ESS_OLD, PCI_DEVICE_ID_ESS_ESS0100, pcidev))!=NULL)
+	{
+		index+=maestro_install(pcidev, TYPE_MAESTRO, index);
+		if(index == NR_DEVICE)
+			return index;
+	}
+	if(index==0)
+		return -ENODEV;
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Alan Cox <alan@redhat.com>");
+MODULE_DESCRIPTION("ESS Maestro Driver");
+#ifdef M_DEBUG
+MODULE_PARM(debug,"i");
+#endif
+
+void cleanup_module(void)
+{
+	struct ess_card *s;
+
+	while ((s = devs)) {
+		int i;
+		devs = devs->next;
+//		ess_play_test(&s->channels[0]);
+#ifndef ESS_HW_TIMER
+		kill_bob(&s->channels[0]);
+#else
+		stop_bob(&s->channels[0]);
+#endif
+//		outb(~0, s->ioenh + SV_CODEC_INTMASK);  /* disable ints */
+//		synchronize_irq();
+//		inb(s->ioenh + SV_CODEC_STATUS); /* ack interrupts */
+//		wrindir(s, SV_CIENABLE, 0);     /* disable DMAA and DMAC */
+		//outb(0, s->iodmaa + SV_DMA_RESET);
+		//outb(0, s->iodmac + SV_DMA_RESET);
+		free_irq(s->irq, s);
+		unregister_sound_mixer(s->dev_mixer);
+		for(i=0;i<8;i++)
+		{
+			struct ess_state *ess = &s->channels[i];
+			if(ess->dev_audio != -1)
+				unregister_sound_dsp(ess->dev_audio);
+		}
+		kfree(s);
+	}
+	M_printk("maestro: unloading\n");
+}
+
+#endif /* MODULE */
+
+#if 0
+/*============================================================================
+ *  ex-code that we're not using anymore..
+ *============================================================================
+ */
+/*
+ *	The ASSP is fortunately not double indexed
+ */
+ 
+static void assp_set_register(int ioaddr, u32 reg, u32 value)
+{
+	unsigned long flags;
+	
+	save_flags(flags);
+	cli();
+	outl(reg, ioaddr+0x80);
+	outl(value, ioaddr+0x84);
+	restore_flags(flags);
+}
+
+static u32 assp_get_register(int ioaddr, u32 reg)
+{
+	unsigned long flags;
+	u32 value;
+	
+	save_flags(flags);
+	cli();
+	outl(reg, ioaddr+0x80);
+	value=inl(ioaddr+0x84);
+	restore_flags(flags);
+	
+	return value;
+}
+
+/* the ASP is basically a DSP that one can dma instructions
+	into.  it can do things like surround encoding or
+	fm synth in sb emul mode.  It is highly proprietary
+	and the ESS dudes are none too excited about telling
+	us about it.  so screw it, we'll just turn it off and
+	not bother with it.  Its not needed for apu/dac work. */
+
+
+static void asp_load(int ioaddr, u16 l, u16 h, u16 *data, int len)
+{
+	int i;
+	outw(l, ioaddr+0x80);
+	outw(h, ioaddr+0x82);
+	for(i=0;i<len;i++)
+		outw(*data++, ioaddr+0x84);
+}
+
+static void asp_memset(int ioaddr, u16 l, u16 h, u16 v, int len)
+{
+	int i;
+	outw(l, ioaddr+0x80);
+	outw(h, ioaddr+0x82);
+	for(i=0;i<len;i++)
+		outw(v, ioaddr+0x84);
+}
+
+/*
+ *	Load a code table into the ASP.
+ */
+
+#define ASSP_LOAD_PROGRAM 0x02 
+#define ASSP_LOAD_DATA 0x03 
+
+static void load_tables(int iobase)
+{
+	outb(0x00, ESS_SETUP_A4+iobase); /* start ASSP programming */
+
+	asp_load(iobase, 0x0, ASSP_LOAD_PROGRAM, asp_block_0,
+		sizeof(asp_block_0)/2);
+
+	asp_load(iobase, 0x0800, ASSP_LOAD_PROGRAM,
+		asp_block_1, sizeof(asp_block_1)/2);
+
+	asp_memset(iobase, 0x1000, ASSP_LOAD_DATA, 0, 1024);
+
+/*
+ * At page 25 of the Maestro-2E data sheet, Table 7, there is a layout of the
+ * ASSP memory mapping that describe the 0x2000-0x23FF as a data area.
+ * The 1.10 version of the test code load 0x3B4 words of data into this area.
+ * I have grabbed the data with hexdump and inserted them into this code.
+ */ 
+	asp_load(iobase, 0x2000, ASSP_LOAD_DATA, asp_block_4,
+		sizeof(asp_block_4)/2);
+
+	asp_memset(iobase, 0x11BC, ASSP_LOAD_DATA, 0x18, 36);
+
+	asp_load(iobase, 0x13DC, ASSP_LOAD_DATA, asp_block_2,
+		sizeof(asp_block_2)/2);
+
+	asp_load(iobase, 0x1300, ASSP_LOAD_DATA, asp_block_3,
+		sizeof(asp_block_3)/2);
+
+	outb(0x41, ESS_SETUP_A4+iobase); /* stop programming and run ASSP */
+}
+/*
+ *	Do not use the main maestro_reset.  it is known
+ *	to leave certain chips in an unstable state.
+ *	best to just reset the direct sound (apus) and
+ *	assp pieces seperately.
+ */
+
+static void maestro_reset(int ioaddr)
+{
+	outw(0x8000, 0x18+ioaddr);
+	udelay(10);
+	outw(0x0000, 0x18+ioaddr);
+	udelay(10);
+}
+#endif
diff -u --recursive --new-file v2.3.15/linux/drivers/sound/maestro.h linux/drivers/sound/maestro.h
--- v2.3.15/linux/drivers/sound/maestro.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/maestro.h	Mon Aug 30 10:23:14 1999
@@ -0,0 +1,60 @@
+/*
+ *	Registers for the ESS PCI cards
+ */
+ 
+/*
+ *	Memory access
+ */
+ 
+#define ESS_MEM_DATA		0x00
+#define	ESS_MEM_INDEX		0x02
+
+/*
+ *	AC-97 Codec port. Delay 1uS after each write. This is used to
+ *	talk AC-97 (see intel.com). Write data then register.
+ */
+ 
+#define ESS_AC97_INDEX		0x30		/* byte wide */
+#define ESS_AC97_DATA		0x32
+
+/* 
+ *	Reading is a bit different. You write register|0x80 to ubdex
+ *	delay 1uS poll the low bit of index, when it clears read the
+ *	data value.
+ */
+
+/*
+ *	Control port. Not yet fully understood
+ *	The value 0xC090 gets loaded to it then 0x0000 and 0x2800
+ *	to the data port. Then after 4uS the value 0x300 is written
+ */
+ 
+#define RING_BUS_CTRL_L		0x34
+#define RING_BUS_CTRL_H		0x36
+
+/*
+ *	This is also used during setup. The value 0x17 is written to it
+ */
+ 
+#define ESS_SETUP_18		0x18
+
+/*
+ *	And this one gets 0x000b
+ */
+ 
+#define ESS_SETUP_A2		0xA2
+
+/*
+ *	And this 0x0000
+ */
+ 
+#define ESS_SETUP_A4		0xA4
+#define ESS_SETUP_A6		0xA6
+
+/*
+ *	Stuff to do with Harpo - the wave stuff
+ */
+ 
+#define ESS_WAVETABLE_SIZE	0x14
+#define 	ESS_WAVETABLE_2M	0xA180
+
diff -u --recursive --new-file v2.3.15/linux/drivers/sound/maestro_tables.h linux/drivers/sound/maestro_tables.h
--- v2.3.15/linux/drivers/sound/maestro_tables.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/maestro_tables.h	Mon Aug 30 10:23:14 1999
@@ -0,0 +1,333 @@
+/* 
+ *	Set up data block for the ESS soundblaster emulation. This is like
+ *	the example code from ftp.esstech.com.tw  (104T31.ZIP)
+ */
+
+u16 asp_block_0[]= {
+	0x7980, 0x003a, 0x7980, 0x007d, 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, 
+	0xbe3a, 0x8b00, 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, 0xbe3a, 0x8b00, 
+	0x7980, 0x0be6, 0x7980, 0x0069, 0xbe3a, 0x8b00, 0x8048, 0x6945, 
+	0xb801, 0x9045, 0x6941, 0xe388, 0x0031, 0x6944, 0xba50, 0xe38c, 
+	0x0031, 0x8b88, 0x6942, 0x304a, 0xe308, 0x0028, 0x6949, 0x9042, 
+	0x0042, 0xafa0, 0x8000, 0xafa0, 0x8000, 0x8042, 0x6944, 0xb801, 
+	0x9044, 0x0048, 0xbe3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0xbe41, 0xbf80, 0x0101, 0x8806, 0x8804, 0xb912, 
+	0x8807, 0xbc26, 0xbe40, 0xb92f, 0x9001, 0x9002, 0x003b, 0x0122, 
+	0x7a88, 0x0055, 0x003a, 0x013c, 0x7a88, 0x0055, 0x4902, 0xe100, 
+	0x0800, 0x0c02, 0xa000, 0x7980, 0x004e, 0xb908, 0x8809, 0xbec6, 
+	0x0067, 0x4a80, 0xe200, 0x0065, 0x4880, 0xe200, 0x0063, 0xb97f, 
+	0x6e80, 0x7980, 0x0066, 0x1089, 0x9088, 0xb900, 0x90a9, 0x8ba8, 
+	0xef00, 0x803d, 0x0003, 0x1007, 0x881f, 0x8b88, 0xbb0f, 0xada0, 
+	0x0810, 0x9003, 0x4903, 0xe200, 0x007b, 0x9002, 0x6a05, 0x6d04, 
+	0x9803, 0x9804, 0x9005, 0x003d, 0xbe3a, 0xaf06, 0x0000, 0x803d, 
+	0x8b88, 0x6906, 0x8810, 0xaf06, 0x0001, 0xbfb0, 0x00ff, 0xbaf5, 
+	0xe3cc, 0x009a, 0x5e06, 0x003f, 0xbf80, 0x0080, 0x4a06, 0xe200, 
+	0x0095, 0x6e80, 0x6d06, 0x7980, 0x009b, 0x9080, 0x0810, 0xba46, 
+	0x8810, 0x8b00, 0x1006, 0x9080, 0x003d, 0xbe3a, 0x1024, 0x2009, 
+	0x8810, 0x8b88, 0x8b00, 0x1089, 0xbfb0, 0x000e, 0xbe0a, 0x880d, 
+	0x903e, 0x1038, 0x2008, 0x8810, 0x1037, 0x2008, 0x8811, 0x5f3e, 
+	0x0000, 0x8b00, 0xf500, 0x5e80, 0xfffe, 0x1039, 0x2008, 0x8815, 
+	0x8b8d, 0x0231, 0x0333, 0x108a, 0x90ad, 0x1025, 0x200a, 0x8815, 
+	0x0605, 0xb91f, 0x8809, 0x4f16, 0x1080, 0xf600, 0xbfb0, 
+	0x0003, 0xbfb0, 0x0007, 0x9089, 0xbe47, 0xbe43, 0xbec6, 
+	0x00f6, 0x4f8b, 0x14a8, 0xe500, 0x6380, 0x8b89, 0x4e8a, 
+	0xbfe3, 0xe500, 0x2480, 0xbe46, 0x8b9d, 0xbfe7, 0xbfb0, 
+	0x00ff, 0x288c, 0x2026, 0x8814, 0xbe47, 0x8b00, 0x738f, 
+	0x54aa, 0xbe03, 0xbe0a, 0x2fa8, 0x988a, 0x8da9, 0xbe03, 
+	0x4d8e, 0xbfe1, 0xf500, 0x6180, 0x9880, 0x8ba9, 0xbe03, 
+	0x4c8e, 0xbfe1, 0xf500, 0x6180, 0x9880, 0x8ba9, 0xbe42, 
+	0x1039, 0x2008, 0x8815, 0x8b8d, 0x8b00, 0x8d8a, 0x7980, 
+	0x0bcf};
+
+u16 asp_block_1[]={
+	0x0005, 0xb900, 0x9008, 0x9009, 0x900a, 0xbb3f, 0x90a0,
+	0x001a, 0x011b, 0x021c, 0x0323, 0x1089, 0x9015, 0x108a,
+	0x9016, 0x108b, 0x9017, 0x1088, 0x9018, 0x0137, 0x0524, 
+	0x8b8d, 0x4f16, 0xe200, 0x0827, 0x4f15, 0xe200, 0x0827, 
+	0x7a80, 0x08e6, 0x102c, 0xb802, 0x8813, 0x8b8b, 0xb900, 
+	0x90a0, 0x908d, 0x7980, 0x0833, 0x7a80, 0x0913, 0x7803, 
+	0x7a80, 0x0913, 0x102c, 0xb802, 0x8813, 0x8b8b, 0xb903, 
+	0x90a0, 0x908d, 0x7c02, 0x4f16, 0xe200, 0x0845, 0x4e15, 
+	0xe200, 0x0845, 0x7a80, 0x08e6, 0x102c, 0xb806, 0x8813, 
+	0x8b8b, 0xb901, 0x90a0, 0x908d, 0x7980, 0x0851, 0x7a80, 
+	0x0913, 0x7803, 0x7a80, 0x0913, 0x102c, 0xb806, 0x8813, 
+	0x8b8b, 0xb904, 0x90a0, 0x908d, 0x7c02, 0x4f16, 0xe200, 
+	0x0863, 0x4d15, 0xe200, 0x0863, 0x7a80, 0x08e6, 0x102c, 
+	0xb80a, 0x8813, 0x8b8b, 0xb902, 0x90a0, 0x908d, 0x7980, 
+	0x086f, 0x7a80, 0x0913, 0x7803, 0x7a80, 0x0913, 0x102c, 
+	0xb80a, 0x8813, 0x8b8b, 0xb905, 0x90a0, 0x908d, 0x7801, 
+	0x7a80, 0x0913, 0x7801, 0x7a80, 0x0913, 0x7801, 0x7a80, 
+	0x0913, 0x1024, 0xbf90, 0x0100, 0x8815, 0x4f16, 0xe200, 
+	0x088e, 0x4c15, 0xe200, 0x088e, 0x7a80, 0x08e6, 0x102c, 
+	0xb814, 0x8813, 0x8b8b, 0xbf80, 0x0100, 0x90a0, 0x908d, 
+	0x7980, 0x089b, 0x7a80, 0x0913, 0x7803, 0x7a80, 0x0913, 
+	0x102c, 0xb814, 0x8813, 0x8b8b, 0xbf80, 0x0103, 0x90a0, 
+	0x908d, 0x7c02, 0x4f16, 0xe200, 0x08ae, 0x4b15, 0xe200, 
+	0x08ae, 0x7a80, 0x08e6, 0x102c, 0xb818, 0x8813, 0x8b8b, 
+	0xbf80, 0x0101, 0x90a0, 0x908d, 0x7980, 0x08bb, 0x7a80, 
+	0x0913, 0x7803, 0x7a80, 0x0913, 0x102c, 0xb818, 0x8813, 
+	0x8b8b, 0xbf80, 0x0104, 0x90a0, 0x908d, 0x7c02, 0x4f16, 
+	0xe200, 0x08ce, 0x4a15, 0xe200, 0x08ce, 0x7a80, 0x08e6, 
+	0x102c, 0xb81c, 0x8813, 0x8b8b, 0xbf80, 0x0102, 0x90a0, 
+	0x908d, 0x7980, 0x08db, 0x7a80, 0x0913, 0x7803, 0x7a80, 
+	0x0913, 0x102c, 0xb81c, 0x8813, 0x8b8b, 0xbf80, 0x0105, 
+	0x90a0, 0x908d, 0x7801, 0x7a80, 0x0913, 0x7801, 0x7a80, 
+	0x0913, 0x7801, 0x7a80, 0x0913, 0x7980, 0x0920, 0x4f80, 
+	0x7803, 0xe100, 0x08fe, 0x4f89, 0xe100, 0x08f5, 0xb901, 
+	0x90a0, 0xb902, 0x90a0, 0x90a0, 0xb906, 0x90ad, 0xef00, 
+	0xb901, 0x90a0, 0xb906, 0x90a0, 0xb900, 0x90a0, 0xb906, 
+	0x90ad, 0xef00, 0x4f89, 0xe100, 0x090a, 0xb905, 0x90a0, 
+	0xb900, 0x90a0, 0xb902, 0x90a0, 0xb906, 0x90ad, 0xef00, 
+	0xb905, 0x90a0, 0xb900, 0x90a0, 0xb906, 0x90a0, 0xb904, 
+	0x90ad, 0xef00, 0x4f89, 0xe100, 0x091b, 0xb901, 0x90a0, 
+	0xb906, 0x90ad, 0xef00, 0xb905, 0x90a0, 0xb904, 0x90ad, 
+	0xef00, 0xb91f, 0x8809, 0x0034, 0x8b88, 0xbec6, 0x0932, 
+	0x1313, 0xbe1e, 0x1014, 0xbe1a, 0xbe01, 0xbfe8, 0xbe17, 
+	0x6a13, 0x6214, 0xbe14, 0x9813, 0x9014, 0x98a0, 0xbe47, 
+	0x5f0f, 0x002e, 0xe200, 0x093d, 0xbf80, 0xffd2, 0x900f, 
+	0x7980, 0x0940, 0x100f, 0xb801, 0x900f, 0x400f, 0x8b00, 
+	0xe500, 0xbe01, 0xbe09, 0x9010, 0xbe46, 0x5f11, 0x003f, 
+	0xe200, 0x094f, 0xb900, 0x9011, 0x7980, 0x0952, 0x1011, 
+	0xb801, 0x9011, 0x1001, 0xe388, 0x0bcf, 0x1021, 0x2009, 
+	0x8813, 0x8b8b, 0x8b00, 0x1080, 0xbfe6, 0x7810, 0x8b00, 
+	0x8b00, 0x2180, 0xbfb0, 0x0007, 0x4c11, 0x8b00, 0xe100, 
+	0x096c, 0x4b11, 0x8b00, 0xe600, 0xb900, 0x7980, 0x096d, 
+	0xbe0a, 0x4a11, 0x8b00, 0xe500, 0xbe01, 0x9012, 0x1037, 
+	0x2008, 0x8811, 0x102e, 0x2008, 0x8812, 0x4a89, 0xb901, 
+	0xe500, 0x9019, 0xe100, 0x09c9, 0xb900, 0x9019, 0x4a18, 
+	0xe200, 0x09c9, 0x5f0a, 0x0010, 0xe200, 0x098d, 0x4b18, 
+	0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 0x5f0a, 0x0013, 
+	0xe200, 0x0997, 0x4b18, 0xb901, 0xe500, 0x9019, 0x7980, 
+	0x09c9, 0x5f0a, 0x0011, 0xe200, 0x09a4, 0x4f18, 0xb905, 
+	0xe500, 0x9080, 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 
+	0x5f0a, 0x0014, 0xe200, 0x09b1, 0x4c18, 0xb904, 0xe500, 
+	0x9080, 0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 0x5f0a, 
+	0x0012, 0xe200, 0x09be, 0x4d18, 0xb905, 0xe500, 0x9080, 
+	0xb901, 0xe500, 0x9019, 0x7980, 0x09c9, 0x5f0a, 0x0015, 
+	0xe200, 0x09c9, 0x4e18, 0xb904, 0xe500, 0x9080, 0xb901, 
+	0xe500, 0x9019, 0x8b8a, 0x4f19, 0xe200, 0x09d4, 0x4b80, 
+	0xe200, 0x09d6, 0x5d80, 0x0020, 0x7980, 0x09d9, 0x5d80, 
+	0x0010, 0x4a80, 0xe200, 0x0bca, 0x1001, 0xba01, 0x9001, 
+	0x1024, 0x2009, 0x8815, 0x8b89, 0x4d8d, 0xe200, 0x09f8, 
+	0x4f16, 0xe100, 0x09ed, 0x8b89, 0x1080, 0xbfc0, 0x000c, 
+	0x908c, 0x7980, 0x09f8, 0x4b89, 0x108d, 0xf600, 0xbfb0, 
+	0x0003, 0x4a89, 0x8b00, 0xf500, 0xbfc0, 0x0008, 0x908c, 
+	0x1022, 0x2009, 0x8811, 0x102e, 0x2008, 0x8812, 0x102f, 
+	0x2008, 0x8813, 0x1020, 0x200a, 0x8814, 0x101d, 0x200a, 
+	0x8815, 0x8b8a, 0x4f19, 0xe100, 0x0a11, 0x5e80, 0x0020, 
+	0x5d80, 0x0018, 0x7980, 0x0a3e, 0x4f80, 0xe200, 0x0a1e, 
+	0x8b8b, 0x108a, 0xbfa0, 0x7fc0, 0x8b00, 0xf704, 0x5c80, 
+	0x0003, 0x7980, 0x0a3e, 0x4e80, 0xe200, 0x0a36, 0x8b8c, 
+	0x178b, 0xbe01, 0xbfb7, 0x00f0, 0x308a, 0xe344, 0x0a3e, 
+	0x8b8d, 0x4a8a, 0x8b00, 0xe200, 0x0a32, 0x5c80, 0x0006, 
+	0x7980, 0x0a3e, 0x5c80, 0x000a, 0x7980, 0x0a3e, 0x4c80,
+	0xe200, 0x0a3e, 0x4b80, 0x8b00, 0xf500, 0x5c80, 0x0019, 
+	0x4f80, 0xe200, 0x0a4d, 0x101f, 0x200a, 0x8816, 0x8b00, 
+	0x8b00, 0x8b8e, 0x1780, 0xbfb7, 0x00f0, 0x900b, 0x7980, 
+	0x0a64, 0x4e80, 0xe200, 0x0a5c, 0x101f, 0x200a, 0x8816, 
+	0x8b00, 0x8b00, 0x8b8e, 0x1b80, 0xbfbb, 0x000f, 0x900b, 
+	0x7980, 0x0a64, 0x4c80, 0xe200, 0x0a64, 0x8b8c, 0x1b80, 
+	0xbfbb, 0x000f, 0x900b, 0x8b89, 0x1880, 0xbfb8, 0x001c, 
+	0x4917, 0xe100, 0x0a6e, 0x4f80, 0x7980, 0x0a70, 0x4e80, 
+	0x8b00, 0xf500, 0xbf98, 0x0002, 0x8b8d, 0x4b89, 0x8b00, 
+	0xe600, 0xbfe1, 0x903e, 0xbe43, 0x6a0b, 0x613e, 0xbfe8, 
+	0x980c, 0xbe42, 0x7c10, 0x1080, 0xbfe5, 0xbe1e, 0x7810, 
+	0x1280, 0xbfb2, 0x001f, 0xbe11, 0x2027, 0x8811, 0x101e, 
+	0x200a, 0x8816, 0x8b00, 0x128e, 0x4980, 0xe100, 0x0a9b, 
+	0x4880, 0xe100, 0x0a98, 0xb900, 0x7980, 0x0a9f, 0xbe0a, 
+	0x7980, 0x0a9f, 0x4880, 0xe200, 0x0a9f, 0xbe09, 0xbe1e, 
+	0x158d, 0xbfb5, 0x003f, 0xbe11, 0x4889, 0xe200, 0x0aae, 
+	0xbe1e, 0x1010, 0x4818, 0x8b00, 0xe600, 0xbfe1, 0xbe11, 
+	0xbfe1, 0x8811, 0xbe1e, 0xb9ff, 0x8819, 0x8b00, 0x8b00, 
+	0xbf46, 0x8b00, 0xe600, 0xbe1f, 0xbe01, 0xbfb0, 0x00ff, 
+	0x202a, 0x8811, 0x8b00, 0x8b00, 0x108a, 0x900d, 0xb91f, 
+	0x8809, 0x0732, 0x730d, 0x4f80, 0xe200, 0x0ad8, 0x1028, 
+	0x200c, 0x8815, 0xbe43, 0x8b8b, 0x6a8d, 0xbec6, 0x0ad4, 
+	0x618b, 0x9880, 0x548f, 0x8dad, 0xbe42, 0x7980, 0x0b24, 
+	0x4e80, 0xe200, 0x0af9, 0x8b8c, 0x178b, 0xbe01, 0xbfb7, 
+	0x00f0, 0x903e, 0x1029, 0x200c, 0x8815, 0x108d, 0xbec6, 
+	0x0af6, 0x308b, 0xbe1e, 0x303e, 0x903f, 0x403f, 0xbe1f, 
+	0xe500, 0x103e, 0x9080, 0xbfe6, 0x202a, 0x8811, 0x8b00, 
+	0x1089, 0x548f, 0x8dad, 0x7980, 0x0b24, 0x4c8b, 0xe200, 
+	0x0b1b, 0x1029, 0x200c, 0x8815, 0xbf80, 0x007f, 0x903e, 
+	0x108d, 0xbec6, 0x0b14, 0x308b, 0xbe1e, 0x303e, 0x903f, 
+	0x403f, 0xbe1f, 0xe500, 0xb900, 0x9080, 0xbfe6, 0x202a, 
+	0x8811, 0x8b00, 0x1089, 0x548f, 0x8dad, 0x8b8a, 0xf500, 
+	0x5e80, 0xffdf, 0x7980, 0x0b24, 0x1089, 0xbfe6, 0x202a, 
+	0x8811, 0x8b00, 0x8b00, 0x548f, 0xbb1f, 0x8da0, 0x8b8f, 
+	0x0732, 0x1021, 0x2009, 0x8811, 0x8b89, 0x101d, 0x200a, 
+	0x8812, 0x1080, 0x7810, 0x8b00, 0xbe47, 0x288a, 0xbfb0, 
+	0x03ff, 0x4989, 0xe200, 0x0b3e, 0xbe1e, 0x1012, 0x4918, 
+	0x8b00, 0xe600, 0xbe0a, 0xbe11, 0x900e, 0xbe46, 0x108a, 
+	0xbfb0, 0x001c, 0xbfe1, 0x880d, 0x8b00, 0x6b0e, 0xbe0a, 
+	0x880c, 0x108c, 0xbfb0, 0x000f, 0x202d, 0x8814, 0x8b00, 
+	0x8b00, 0x5589, 0xbf03, 0x8c0e, 0xbf00, 0x1030, 0x2008, 
+	0x8811, 0xb91f, 0x8809, 0x108b, 0x0333, 0xbec6, 0x0b5f, 
+	0x200e, 0x90a0, 0x8b00, 0x8b89, 0x9080, 0x4a18, 0xe200, 
+	0x0b7a, 0x5f0a, 0x0011, 0xe200, 0x0b6c, 0x4f18, 0xe900, 
+	0x0b7c, 0x5f0a, 0x0014, 0xe200, 0x0b73, 0x4c18, 0xe900, 
+	0x0b9b, 0x5f0a, 0x0015, 0xe200, 0x0b7a, 0x4e18, 0xe900, 
+	0x0bb2, 0x7980, 0x009e, 0x0034, 0xb91f, 0x8809, 0x0333, 
+	0x8b8b, 0xbec6, 0x0b99, 0x1280, 0x6c80, 0xbfea, 0xbe1e, 
+	0x1580, 0x6c88, 0xbfec, 0xbe13, 0x903e, 0x6cab, 0x903f, 
+	0x4f3e, 0xb900, 0xf500, 0xbf80, 0x8000, 0x4f3f, 0xbf90, 
+	0x0d00, 0xf500, 0xbf90, 0x2700, 0x90a0, 0xef00, 0x0034, 
+	0xb91f, 0x8809, 0x0333, 0x8b88, 0xbec6, 0x0bb0, 0x1eab, 
+	0x6c80, 0xbfed, 0x903e, 0x4180, 0xb900, 0xf500, 0xbf80, 
+	0x8000, 0x4f3e, 0x8b00, 0xf500, 0xbf90, 0x4000, 0x90a8, 
+	0xef00, 0x0034, 0xb91f, 0x8809, 0x0333, 0x8b8b, 0xbec6, 
+	0x0bc8, 0x1280, 0x6c8b, 0xbfea, 0xbe1e, 0x1580, 0x6c80, 
+	0xbfec, 0xbe13, 0x903e, 0x4f3e, 0xbf80, 0x4000, 0xf500, 
+	0xbf90, 0x8000, 0x90a0, 0xef00, 0x0231, 0x8b8a, 0xb900, 
+	0xbb20, 0x90a0, 0x5f08, 0x0023, 0xe100, 0x0043, 0x1008, 
+	0xb801, 0x9008, 0x102b, 0x2008, 0x8812, 0x8b00, 0x8b00, 
+	0x1080, 0x900a, 0x102c, 0x2008, 0x8812, 0x8b00, 0x8b00, 
+	0x1080, 0x9009, 0x7980, 0x0952, 0x8148, 0x6946, 0xb801, 
+	0x9046, 0xb901, 0x9041, 0x6944, 0xba08, 0xe344, 0x0bfe, 
+	0x9044, 0x8b89, 0x0143, 0x694b, 0x881f, 0xbb0f, 0xada0, 
+	0x8143, 0x0811, 0x304a, 0xe308, 0x0bfe, 0x6949, 0x9043,
+	0x0148, 0xbe3a 
+}; 
+	
+u16 asp_block_2[]={ 
+	0x0000, 0x0000, 0x0003, 0x0003, 0x0001, 0x0001, 
+	0x0004, 0x0004, 0x0002, 0x0002, 0x0005, 0x0005, 
+	0x0006, 0x0006, 0x0007, 0x0007, 0x0008, 0x0008, 
+	0x0100, 0x0100, 0x0103, 0x0103, 0x0101, 0x0101, 
+	0x0104, 0x0104, 0x0102, 0x0102, 0x0105, 0x0105, 
+	0x0106, 0x0106, 0x0107, 0x0107, 0x0108, 0x0108
+};
+
+u16 asp_block_3[]={ 
+	0x0000, 0x0000, 0x0000, 0x1200, 0x1200, 0x1280, 0x0000, 0x05d0, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x1104, 0x1105, 0x1008, 0x1020, 0x1040, 0x1060, 
+	0x1080, 0x10a0, 0x10b0, 0x100d, 0x1010, 0x10e0, 0x2000, 0x2980, 
+	0x2b00, 0x2b40, 0x2a00, 0x2b90, 0x13dc, 0x2b80, 0x11bc, 0x134c, 
+	0x1370, 0x12e0, 0x1240, 0x1260, 0x12c0, 0x009e, 0x0045, 0x10bc, 
+	0x1394, 0x13b8, 0x11f6, 0x10f6, 0x11b0, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0815, 0x0956, 0x09df, 0x0be5, 0x0a19, 0x0a48, 0x0b37,
+	0x0b5d, 0x0a8b, 0x0aae, 0x0ad2 }; 
+
+
+u16 asp_block_4[] = {
+	0x0192, 0x04b6, 0x07d9, 0x0afb, 0x0e1c, 0x113a, 0x1455, 0x176e,
+	0x1a83, 0x1d93, 0x209f, 0x23a7, 0x26a8, 0x29a4, 0x2c99, 0x2f87,
+	0x326e, 0x354e, 0x3825, 0x3af3, 0x3db8, 0x4074, 0x4326, 0x45cd,
+	0x486a, 0x4afb, 0x4d81, 0x4ffb, 0x5269, 0x54ca, 0x571e, 0x5964,
+	0x5b9d, 0x5dc8, 0x5fe4, 0x61f1, 0x63ef, 0x65de, 0x67bd, 0x698c,
+	0x6b4b, 0x6cf9, 0x6e97, 0x7023, 0x719e, 0x7308, 0x7460, 0x75a6,
+	0x76d9, 0x77fb, 0x790a, 0x7a06, 0x7aef, 0x7bc6, 0x7c89, 0x7d3a,
+	0x7dd6, 0x7e60, 0x7ed6, 0x7f38, 0x7f87, 0x7fc2, 0x7fea, 0x7ffe,
+	0x7ffe, 0x7fea, 0x7fc2, 0x7f87, 0x7f38, 0x7ed6, 0x7e60, 0x7dd6,
+	0x7d3a, 0x7c89, 0x7bc6, 0x7aef, 0x7a06, 0x790a, 0x77fb, 0x76d9,
+	0x75a6, 0x7460, 0x7308, 0x719e, 0x7023, 0x6e97, 0x6cf9, 0x6b4b,
+	0x698c, 0x67bd, 0x65de, 0x63ef, 0x61f1, 0x5fe4, 0x5dc8, 0x5b9d,
+	0x5964, 0x571e, 0x54ca, 0x5269, 0x4ffb, 0x4d81, 0x4afb, 0x486a,
+	0x45cd, 0x4326, 0x4074, 0x3db8, 0x3af3, 0x3825, 0x354e, 0x326e,
+	0x2f87, 0x2c99, 0x29a4, 0x26a8, 0x23a7, 0x209f, 0x1d93, 0x1a83,
+	0x176e, 0x1455, 0x113a, 0x0e1c, 0x0afb, 0x07d9, 0x04b6, 0x0192,
+	0xfe6f, 0xfb4b, 0xf828, 0xf506, 0xf1e5, 0xeec7, 0xebac, 0xe893,
+	0xe57e, 0xe26e, 0xdf62, 0xdc5a, 0xd959, 0xd65d, 0xd368, 0xd07a,
+	0xcd93, 0xcab3, 0xc7dc, 0xc50e, 0xc249, 0xbf8d, 0xbcdb, 0xba34,
+	0xb797, 0xb506, 0xb280, 0xb006, 0xad98, 0xab37, 0xa8e3, 0xa69d,
+	0xa464, 0xa239, 0xa01d, 0x9e10, 0x9c12, 0x9a23, 0x9844, 0x9675,
+	0x94b6, 0x9308, 0x916a, 0x8fde, 0x8e63, 0x8cf9, 0x8ba1, 0x8a5b,
+	0x8928, 0x8806, 0x86f7, 0x85fb, 0x8512, 0x843b, 0x8378, 0x82c7,
+	0x822b, 0x81a1, 0x812b, 0x80c9, 0x807a, 0x803f, 0x8017, 0x8003,
+	0x8003, 0x8017, 0x803f, 0x807a, 0x80c9, 0x812b, 0x81a1, 0x822b,
+	0x82c7, 0x8378, 0x843b, 0x8512, 0x85fb, 0x86f7, 0x8806, 0x8928,
+	0x8a5b, 0x8ba1, 0x8cf9, 0x8e63, 0x8fde, 0x916a, 0x9308, 0x94b6,
+	0x9675, 0x9844, 0x9a23, 0x9c12, 0x9e10, 0xa01d, 0xa239, 0xa464,
+	0xa69d, 0xa8e3, 0xab37, 0xad98, 0xb006, 0xb280, 0xb506, 0xb797,
+	0xba34, 0xbcdb, 0xbf8d, 0xc249, 0xc50e, 0xc7dc, 0xcab3, 0xcd93,
+	0xd07a, 0xd368, 0xd65d, 0xd959, 0xdc5a, 0xdf62, 0xe26e, 0xe57e,
+	0xe893, 0xebac, 0xeec7, 0xf1e5, 0xf506, 0xf828, 0xfb4b, 0xfe6f,
+	0x7cc3, 0x725e, 0x68d5, 0x6017, 0x5813, 0x50b9, 0x49fb, 0x43cd,
+	0x3e22, 0x38ef, 0x342b, 0x2fcc, 0x2bc9, 0x281c, 0x24be, 0x21a6,
+	0x1ed1, 0x1c37, 0x19d5, 0x17a6, 0x15a5, 0x13ce, 0x121f, 0x1093,
+	0x0f28, 0x0ddc, 0x0cab, 0x0b93, 0x0a92, 0x09a7, 0x08cf, 0x080a,
+	0x0754, 0x06ae, 0x0615, 0x0589, 0x0509, 0x0494, 0x0428, 0x03c5,
+	0x036a, 0x0317, 0x02cb, 0x0285, 0x0245, 0x020a, 0x01d4, 0x01a2,
+	0x0175, 0x014b, 0x0125, 0x0102, 0x00e2, 0x00c5, 0x00aa, 0x0091,
+	0x007b, 0x0066, 0x0053, 0x0041, 0x0031, 0x0022, 0x0015, 0x0009,
+	0xfffe, 0xfff2, 0xffe5, 0xffd7, 0xffc8, 0xffb7, 0xffa5, 0xff91,
+	0xff7b, 0xff64, 0xff4a, 0xff2e, 0xff0f, 0xfeee, 0xfec9, 0xfea1,
+	0xfe76, 0xfe46, 0xfe13, 0xfdda, 0xfd9d, 0xfd5a, 0xfd11, 0xfcc1,
+	0xfc6b, 0xfc0c, 0xfba5, 0xfb34, 0xfab9, 0xfa33, 0xf9a1, 0xf902,
+	0xf854, 0xf797, 0xf6c8, 0xf5e7, 0xf4f1, 0xf3e5, 0xf2c1, 0xf183,
+	0xf027, 0xeeac, 0xed0f, 0xeb4d, 0xe961, 0xe74a, 0xe501, 0xe284,
+	0xdfcd, 0xdcd8, 0xd99d, 0xd618, 0xd242, 0xce12, 0xc982, 0xc487,
+	0xbf1a, 0xb92e, 0xb2ba, 0xabaf, 0xa402, 0x9ba3, 0x9282, 0x888d,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e, 0x0010,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0006, 0x000a, 0x000e,
+	0x0010, 0x0014, 0x0016, 0x0018, 0x001a, 0x001c, 0x001e, 0x0020,
+	0x0000, 0x0000, 0x0000, 0x000a, 0x0010, 0x0016, 0x001a, 0x001e,
+	0x0020, 0x0024, 0x0026, 0x0028, 0x002a, 0x002c, 0x002e, 0x0030,
+	0x0000, 0x0000, 0x0010, 0x001a, 0x0020, 0x0026, 0x002a, 0x002e,
+	0x0030, 0x0034, 0x0036, 0x0038, 0x003a, 0x003c, 0x003e, 0x0040,
+	0x0000, 0x0010, 0x0020, 0x002a, 0x0030, 0x0036, 0x003a, 0x003e,
+	0x0040, 0x0044, 0x0046, 0x0048, 0x004a, 0x004c, 0x004e, 0x0050,
+	0x0000, 0x0020, 0x0030, 0x003a, 0x0040, 0x0046, 0x004a, 0x004e,
+	0x0050, 0x0054, 0x0056, 0x0058, 0x005a, 0x005c, 0x005e, 0x0060,
+	0x0000, 0x0030, 0x0040, 0x004a, 0x0050, 0x0056, 0x005a, 0x005e,
+	0x0060, 0x0064, 0x0066, 0x0068, 0x006a, 0x006c, 0x006e, 0x0070,
+	0x0008, 0x0021, 0x0042, 0x0064, 0x0086, 0x00a8, 0x00cb, 0x00ee,
+	0x0111, 0x0135, 0x0158, 0x017d, 0x01a1, 0x01c6, 0x01eb, 0x0211,
+	0x0236, 0x025d, 0x0283, 0x02aa, 0x02d1, 0x02f9, 0x0321, 0x0349,
+	0x0372, 0x039b, 0x03c4, 0x03ee, 0x0418, 0x0442, 0x046d, 0x0499,
+	0x04c4, 0x04f0, 0x051d, 0x054a, 0x0577, 0x05a5, 0x05d3, 0x0601,
+	0x0630, 0x0660, 0x0690, 0x06c0, 0x06f1, 0x0722, 0x0753, 0x0785,
+	0x07b8, 0x07eb, 0x081e, 0x0852, 0x0886, 0x08bb, 0x08f0, 0x0926,
+	0x095c, 0x0993, 0x09ca, 0x0a02, 0x0a3a, 0x0a73, 0x0aac, 0x0ae6,
+	0x0b20, 0x0b5b, 0x0b96, 0x0bd2, 0x0c0e, 0x0c4b, 0x0c89, 0x0cc7,
+	0x0d05, 0x0d44, 0x0d84, 0x0dc5, 0x0e05, 0x0e47, 0x0e89, 0x0ecc,
+	0x0f0f, 0x0f53, 0x0f97, 0x0fdd, 0x1022, 0x1069, 0x10b0, 0x10f7,
+	0x1140, 0x1189, 0x11d2, 0x121c, 0x1267, 0x12b3, 0x12ff, 0x134c,
+	0x139a, 0x13e8, 0x1438, 0x1487, 0x14d8, 0x1529, 0x157b, 0x15ce,
+	0x1621, 0x1676, 0x16cb, 0x1720, 0x1777, 0x17ce, 0x1826, 0x187f,
+	0x18d9, 0x1934, 0x198f, 0x19eb, 0x1a48, 0x1aa6, 0x1b05, 0x1b64,
+	0x1bc5, 0x1c26, 0x1c88, 0x1ceb, 0x1d4f, 0x1db4, 0x1e1a, 0x1e80,
+	0x1ee8, 0x1f51, 0x1fba, 0x2025, 0x2090, 0x20fc, 0x216a, 0x21d8,
+	0x2247, 0x22b8, 0x2329, 0x239b, 0x240f, 0x2483, 0x24f9, 0x256f,
+	0x25e7, 0x2660, 0x26da, 0x2755, 0x27d1, 0x284e, 0x28cc, 0x294b,
+	0x29cc, 0x2a4e, 0x2ad1, 0x2b55, 0x2bda, 0x2c61, 0x2ce8, 0x2d71,
+	0x2dfb, 0x2e87, 0x2f13, 0x2fa1, 0x3031, 0x30c1, 0x3153, 0x31e6,
+	0x327b, 0x3310, 0x33a8, 0x3440, 0x34da, 0x3575, 0x3612, 0x36b0,
+	0x3750, 0x37f1, 0x3893, 0x3937, 0x39dc, 0x3a83, 0x3b2c, 0x3bd6,
+	0x3c81, 0x3d2e, 0x3ddd, 0x3e8d, 0x3f3f, 0x3ff2, 0x40a7, 0x415d,
+	0x4216, 0x42d0, 0x438b, 0x4448, 0x4507, 0x45c8, 0x468b, 0x474f,
+	0x4815, 0x48dd, 0x49a6, 0x4a72, 0x4b3f, 0x4c0e, 0x4cdf, 0x4db2,
+	0x4e87, 0x4f5d, 0x5036, 0x5111, 0x51ed, 0x52cc, 0x53ac, 0x548f,
+	0x5573, 0x565a, 0x5743, 0x582e, 0x591b, 0x5a0a, 0x5afb, 0x5bef,
+	0x5ce4, 0x5ddc, 0x5ed7, 0x5fd3, 0x60d2, 0x61d3, 0x62d6, 0x63dc,
+	0x64e4, 0x65ee, 0x66fb, 0x680a, 0x691c, 0x6a30, 0x6b47, 0x6c60,
+	0x6d7c, 0x6e9a, 0x6fbb, 0x70de, 0x7204, 0x732d, 0x7459, 0x7587,
+	0x76b8, 0x77eb, 0x7922, 0x7a5b, 0x7b97, 0x7cd6, 0x7e18, 0x7f5d,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0002, 0x0002, 0x0003,
+	0x0003, 0x0004, 0x0004, 0x0005, 0x0006, 0x0008, 0x0009, 0x000a,
+	0x000c, 0x0010, 0x0012, 0x0015, 0x0019, 0x0022, 0x0024, 0x002a,
+	0x0031, 0x003e, 0x0049, 0x0055, 0x0062, 0x007c, 0x0092, 0x00a9,
+	0x00c4, 0x00fc, 0x0125, 0x0152, 0x0187, 0x01f2, 0x024a, 0x02a4,
+	0x030d, 0x03e3, 0x0492, 0x0547, 0x061b, 0x07c7, 0x0923, 0x0a8d,
+	0x0c19, 0x0eb3, 0x1228, 0x14c1, 0x17fb, 0x1d17, 0x22f2, 0x2835,
+	0x2dd4, 0x3cd0, 0x4cf5, 0x51cc, 0x7fff, 0x7fff, 0x7fff, 0x7fff,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0002,
+	0x0002, 0x0003, 0x0004, 0x0005, 0x0005, 0x0007, 0x0008, 0x000a,
+	0x000b, 0x000e, 0x0011, 0x0014, 0x0017, 0x001c, 0x0022, 0x0028,
+	0x002e, 0x0039, 0x0045, 0x0050, 0x005c, 0x0073, 0x008a, 0x00a0,
+	0x00b9, 0x00e7, 0x0114, 0x0141, 0x0172, 0x01ce, 0x0228, 0x0283,
+	0x02e3, 0x039b, 0x0454, 0x0501, 0x05bf, 0x072a, 0x0899, 0x0a18,
+	0x0b7e, 0x0e55, 0x10d3, 0x1404, 0x16c3, 0x16c3, 0x16c3, 0x16c3,
+	0x0012, 0x0024, 0x0048, 0x006c, 0x0090, 0x00b4, 0x00d8, 0x00fc,
+	0x0120, 0x0144, 0x0168, 0x0168, 0x01b0, 0x01b0, 0x021c, 0x021c,
+	0x0000, 0x0003, 0x0008, 0x000b, 0x0001, 0x0004, 0x0009, 0x000c,
+	0x0002, 0x0005, 0x000a, 0x000d, 0x0010, 0x0013, 0x0011, 0x0014,
+	0x0012, 0x0015, 0x0100, 0x0103, 0x0108, 0x010b, 0x0101, 0x0104,
+	0x0109, 0x010c, 0x0102, 0x0105, 0x010a, 0x010d, 0x0110, 0x0113,
+	0x0111, 0x0114, 0x0112, 0x0115 };
diff -u --recursive --new-file v2.3.15/linux/drivers/tc/tc.c linux/drivers/tc/tc.c
--- v2.3.15/linux/drivers/tc/tc.c	Wed Aug  4 16:36:45 1999
+++ linux/drivers/tc/tc.c	Thu Aug 26 12:42:33 1999
@@ -92,12 +92,12 @@
 /*
  * Probing for TURBOchannel modules
  */
-__initfunc(static void my_dbe_handler(struct pt_regs *regs))
+static void __init my_dbe_handler(struct pt_regs *regs)
 {
 	regs->cp0_epc += 4;
 }
 
-__initfunc(static void tc_probe(unsigned long startaddr, unsigned long size, int max_slot))
+static void __init tc_probe(unsigned long startaddr, unsigned long size, int max_slot)
 {
 	int i, slot;
 	long offset;
@@ -164,7 +164,7 @@
 /*
  * the main entry
  */
-__initfunc(void tc_init(void))
+void __init tc_init(void)
 {
 	int tc_clock;
 	int i;
diff -u --recursive --new-file v2.3.15/linux/drivers/tc/zs.c linux/drivers/tc/zs.c
--- v2.3.15/linux/drivers/tc/zs.c	Fri Jun 25 17:38:40 1999
+++ linux/drivers/tc/zs.c	Tue Aug 31 11:30:48 1999
@@ -1315,7 +1315,6 @@
 		char_time = MIN(char_time, timeout);
 	while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
 		current->state = TASK_INTERRUPTIBLE;
-		current->counter = 0;	/* make us low-priority */
 		schedule_timeout(char_time);
 		if (signal_pending(current))
 			break;
@@ -1433,7 +1432,7 @@
 		    (tty->termios->c_cflag & CBAUD))
 			zs_rtsdtr(info, 1);
 		sti();
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ZILOG_INITIALIZED)) {
 #ifdef SERIAL_DO_RESTART
@@ -1564,7 +1563,7 @@
 
 /* Finally, routines used to initialize the serial driver. */
 
-__initfunc(static void show_serial_version(void))
+static void __init show_serial_version(void)
 {
 	printk("DECstation Z8530 serial driver version 0.03\n");
 }
@@ -1572,7 +1571,7 @@
 /*  Initialize Z8530s zs_channels
  */
 
-__initfunc(static void probe_sccs(void))
+static void __init probe_sccs(void)
 {
 	struct dec_serial **pp;
 	int i, n, n_chips = 0, n_channels, chip, channel;
@@ -1654,7 +1653,7 @@
 }
 
 /* zs_init inits the driver */
-__initfunc(int zs_init(void))
+int __init zs_init(void)
 {
 	int channel, i;
 	unsigned long flags;
@@ -1886,7 +1885,7 @@
  *	- initialize the serial port
  *	Return non-zero if we didn't find a serial port.
  */
-__initfunc(static int serial_console_setup(struct console *co, char *options))
+static int __init serial_console_setup(struct console *co, char *options)
 {
 	struct dec_serial *info;
 	int	baud = 9600;
@@ -2022,7 +2021,7 @@
 /*
  *	Register console.
  */
-__initfunc (long zs_serial_console_init(long kmem_start, long kmem_end))
+long __init zs_serial_console_init(long kmem_start, long kmem_end)
 {
 	register_console(&sercons);
 	return kmem_start;
@@ -2087,7 +2086,7 @@
  * for /dev/ttyb which is determined in setup_arch() from the
  * boot command line flags.
  */
-__initfunc(void zs_kgdb_hook(int tty_num))
+void __init zs_kgdb_hook(int tty_num)
 {
 	/* Find out how many Z8530 SCCs we have */
 	if (zs_chain == 0)
diff -u --recursive --new-file v2.3.15/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
--- v2.3.15/linux/drivers/usb/acm.c	Thu Aug 26 13:05:39 1999
+++ linux/drivers/usb/acm.c	Tue Aug 31 12:38:12 1999
@@ -23,10 +23,7 @@
  * uhci.c. Should have the correct interface now. 
  * (6/6/99)
  *
- * version 0.5 driver now generates a tty instead of a simple character
- * device
- *
- * version 0.3: Mayor changes. Changed Bulk transfer to interrupt based
+ * version 0.3: Major changes. Changed Bulk transfer to interrupt based
  * transfer. Using FIFO Buffers now. Consistent handling of open/close
  * file state and detected/nondetected device. File operations behave
  * according to this. Driver is able to send+receive now! Heureka!
@@ -485,6 +482,7 @@
 	struct usb_interface_descriptor *interface;
 	struct usb_endpoint_descriptor *endpoint;
 	int cfgnum,acmno;
+	int swapped=0;
 	
 	info("acm_probe\n");
 	
@@ -500,14 +498,13 @@
             dev->descriptor.bDeviceProtocol != 0)
 		return -1;
 
-	/* Now scan all configs for a ACM configuration */
+#define IFCLASS(if) ((if->bInterfaceClass << 24) | (if->bInterfaceSubClass << 16) | (if->bInterfaceProtocol << 8) | (if->bNumEndpoints))
+
+	/* Now scan all configs for a ACM configuration*/
 	for (cfgnum=0;cfgnum<dev->descriptor.bNumConfigurations;cfgnum++) {
 		/* The first one should be Communications interface? */
 		interface = &dev->config[cfgnum].interface[0].altsetting[0];
-		if (interface->bInterfaceClass != 2 ||
-		    interface->bInterfaceSubClass != 2 ||
-		    interface->bInterfaceProtocol != 1 ||
-	    	    interface->bNumEndpoints != 1)
+		if (IFCLASS(interface) != 0x02020101)
 			continue;
 
 		/*Which uses an interrupt input */
@@ -519,19 +516,20 @@
 		/* The second one should be a Data interface? */
 		interface = &dev->config[cfgnum].interface[1].altsetting[0];
 		if (interface->bInterfaceClass != 10 ||
-		    interface->bInterfaceSubClass != 0 ||
-		    interface->bInterfaceProtocol != 0 ||
-	    	    interface->bNumEndpoints != 2)
+		    interface->bNumEndpoints != 2)
 			continue;
 
+		if ((endpoint->bEndpointAddress & 0x80) == 0x80)
+			swapped = 1;
+
 		/*With a bulk input */
-		endpoint = &interface->endpoint[0];
+		endpoint = &interface->endpoint[0^swapped];
 		if ((endpoint->bEndpointAddress & 0x80) != 0x80 ||
 		    (endpoint->bmAttributes & 3) != 2)
 			continue;
 			
 		/*And a bulk output */
-		endpoint = &interface->endpoint[1];
+		endpoint = &interface->endpoint[1^swapped];
 		if ((endpoint->bEndpointAddress & 0x80) == 0x80 ||
 		    (endpoint->bmAttributes & 3) != 2)
 			continue;
@@ -542,30 +540,30 @@
 		acm->dev=dev;
 		dev->private=acm;
 
-		acm->readendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[0].bEndpointAddress;
+		acm->readendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[0^swapped].bEndpointAddress;
 		acm->readpipe=usb_rcvbulkpipe(dev,acm->readendp);
-		acm->readbuffer=kmalloc(acm->readsize=dev->config[cfgnum].interface[1].altsetting[0].endpoint[0].wMaxPacketSize,GFP_KERNEL);
+		acm->readbuffer=kmalloc(acm->readsize=dev->config[cfgnum].interface[1].altsetting[0].endpoint[0^swapped].wMaxPacketSize,GFP_KERNEL);
 		acm->reading=0;
 		if (!acm->readbuffer) {
 			printk("ACM: Couldn't allocate readbuffer\n");
 			return -1;
 		}
-		
-		acm->writeendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[1].bEndpointAddress;
+
+		acm->writeendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[1^swapped].bEndpointAddress;
 		acm->writepipe=usb_sndbulkpipe(dev,acm->writeendp);
-		acm->writebuffer=kmalloc(acm->writesize=dev->config[cfgnum].interface[1].altsetting[0].endpoint[1].wMaxPacketSize, GFP_KERNEL);
+		acm->writebuffer=kmalloc(acm->writesize=dev->config[cfgnum].interface[1].altsetting[0].endpoint[1^swapped].wMaxPacketSize, GFP_KERNEL);
 		acm->writing=0;
 		if (!acm->writebuffer) {
 			printk("ACM: Couldn't allocate writebuffer\n");
 			kfree(acm->readbuffer);
 			return -1;
 		}
-		
+
 		acm->ctrlendp=dev->config[cfgnum].interface[0].altsetting[0].endpoint[0].bEndpointAddress;
 		acm->ctrlpipe=usb_rcvctrlpipe(acm->dev,acm->ctrlendp);
 		acm->ctrlinterval=dev->config[cfgnum].interface[0].altsetting[0].endpoint[0].bInterval;
 
-		acm->present=1;
+		acm->present=1;				
 		MOD_INC_USE_COUNT;
 		return 0;
 	}
@@ -660,7 +658,10 @@
 	acm_tty_driver.read_proc = NULL; //rs_read_proc;
 	acm_tty_driver.chars_in_buffer = rs_chars_in_buffer;
 	acm_tty_driver.flush_buffer = NULL; //rs_flush_buffer;
-	tty_register_driver(&acm_tty_driver);
+	if (tty_register_driver(&acm_tty_driver)) {
+		printk( "acm: failed to register tty driver\n" );
+		return -EPERM;
+	}
 	
 	//REGISTER USB DRIVER
 	usb_register(&acm_driver);
diff -u --recursive --new-file v2.3.15/linux/drivers/usb/printer.c linux/drivers/usb/printer.c
--- v2.3.15/linux/drivers/usb/printer.c	Thu Aug 26 13:05:39 1999
+++ linux/drivers/usb/printer.c	Fri Aug 27 12:35:57 1999
@@ -163,6 +163,11 @@
 	unsigned long partial;
 	int result = USB_ST_NOERROR;
 	int maxretry;
+	int endpoint_num;
+	struct usb_interface_descriptor *interface;
+	
+	interface = p->pusb_dev->config->interface->altsetting;
+	endpoint_num = (interface->endpoint[1].bEndpointAddress & 0x0f);
 
 	do {
 		char *obuf = p->obuf;
@@ -179,7 +184,8 @@
 				return bytes_written ? bytes_written : -EINTR;
 			}
 			result = p->pusb_dev->bus->op->bulk_msg(p->pusb_dev,
-					 usb_sndbulkpipe(p->pusb_dev, 1), obuf, thistime, &partial);
+					 usb_sndbulkpipe(p->pusb_dev, endpoint_num),
+					 obuf, thistime, &partial);
 			if (partial) {
 				obuf += partial;
 				thistime -= partial;
@@ -218,6 +224,11 @@
 	char buf[64];
 	unsigned long partial;
 	int result;
+	int endpoint_num;
+	struct usb_interface_descriptor *interface;
+	
+	interface = p->pusb_dev->config->interface->altsetting;
+	endpoint_num = (interface->endpoint[0].bEndpointAddress & 0x0f);
 
 	if (p->noinput)
 		return -EINVAL;
@@ -232,7 +243,8 @@
 		this_read = (count > sizeof(buf)) ? sizeof(buf) : count;
 
 		result = p->pusb_dev->bus->op->bulk_msg(p->pusb_dev,
-			  usb_rcvbulkpipe(p->pusb_dev, 2), buf, this_read, &partial);
+			  usb_rcvbulkpipe(p->pusb_dev, endpoint_num),
+			  buf, this_read, &partial);
 
 		/* unlike writes, we don't retry a NAK, just stop now */
 		if (!result & partial)
@@ -276,10 +288,10 @@
 		return -1;
 	}
 
-	if (interface->endpoint[0].bEndpointAddress != 0x01 ||
+	if ((interface->endpoint[0].bEndpointAddress & 0xf0) != 0x00 ||
 	    interface->endpoint[0].bmAttributes != 0x02 ||
 	    (interface->bNumEndpoints > 1 && (
-		    interface->endpoint[1].bEndpointAddress != 0x82 ||
+		    (interface->endpoint[1].bEndpointAddress & 0xf0) != 0x80 ||
 		    interface->endpoint[1].bmAttributes != 0x02))) {
 		return -1;
 	}
diff -u --recursive --new-file v2.3.15/linux/drivers/usb/proc_usb.c linux/drivers/usb/proc_usb.c
--- v2.3.15/linux/drivers/usb/proc_usb.c	Thu Aug 26 13:05:39 1999
+++ linux/drivers/usb/proc_usb.c	Fri Aug 27 11:46:35 1999
@@ -1,6 +1,7 @@
 /*
  * drivers/usb/proc_usb.c
  * (C) Copyright 1999 Randy Dunlap.
+ * (C) Copyright 1999 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -48,6 +49,9 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/list.h>
+#include <linux/bitops.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
 
 #include "usb.h"
 
@@ -191,7 +195,7 @@
  *    which ones are active, if any)
  * 2. Add proc_usb_init() call from usb-core.c.
  * 3. proc_usb as a MODULE ?
- * 4. use __initfunc() ?
+ * 4. use __init ?
  * 5. add <halted> status to each endpoint line
  */
 
@@ -435,12 +439,7 @@
 
 /*
  * proc entry for every device
- * sailer@ife.ee.ethz.ch
  */
-#include <linux/bitops.h>
-#include <asm/uaccess.h>
-#include <linux/mm.h>
-#include "ezusb.h"
 
 static long long usbdev_lseek(struct file * file, long long offset, int orig)
 {
@@ -484,8 +483,12 @@
 	return ret;
 }
 
-static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+/* note: this is a compatibility kludge that will vanish soon. */
+#include "ezusb.h"
+
+static int usbdev_ioctl_ezusbcompat(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
+	static unsigned obsolete_warn = 0;
 	struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
 	struct usb_device *dev = (struct usb_device *)dp->data;
 	struct ezusb_ctrltransfer ctrl;
@@ -498,6 +501,11 @@
 
 	switch (cmd) {
 	case EZUSB_CONTROL:
+		if (obsolete_warn < 20) {
+			printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_CONTROL ioctl\n",
+			       current->pid, current->comm);
+			obsolete_warn++;
+		}
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 		copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
@@ -529,6 +537,11 @@
 		return 0;
 
 	case EZUSB_BULK:
+		if (obsolete_warn < 20) {
+			printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_BULK ioctl\n",
+			       current->pid, current->comm);
+			obsolete_warn++;
+		}
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 		copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
@@ -567,6 +580,11 @@
 		return len2;
 
 	case EZUSB_RESETEP:
+		if (obsolete_warn < 20) {
+			printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_RESETEP ioctl\n",
+			       current->pid, current->comm);
+			obsolete_warn++;
+		}
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 		get_user_ret(ep, (unsigned int *)arg, -EFAULT);
@@ -576,12 +594,131 @@
 		return 0;
 
 	case EZUSB_SETINTERFACE:
+		if (obsolete_warn < 20) {
+			printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_SETINTERFACE ioctl\n",
+			       current->pid, current->comm);
+			obsolete_warn++;
+		}
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 		copy_from_user_ret(&setintf, (void *)arg, sizeof(setintf), -EFAULT);
 		if (usb_set_interface(dev, setintf.interface, setintf.altsetting))
 			return -EINVAL;
 		return 0;
+	}
+	return -ENOIOCTLCMD;
+}
+
+
+
+static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
+	struct usb_device *dev = (struct usb_device *)dp->data;
+	struct usb_proc_ctrltransfer ctrl;
+	struct usb_proc_bulktransfer bulk;
+	struct usb_proc_setinterface setintf;
+	unsigned int len1, ep, pipe;
+	unsigned long len2;
+	unsigned char *tbuf;
+	int i;
+
+	switch (cmd) {
+	case USB_PROC_CONTROL:
+		if (!capable(CAP_SYS_RAWIO))
+			return -EPERM;
+		copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
+		if (ctrl.length > PAGE_SIZE)
+			return -EINVAL;
+		if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+			return -ENOMEM;
+		if (ctrl.requesttype & 0x80) {
+			if (ctrl.length && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.length)) {
+				free_page((unsigned long)tbuf);
+				return -EINVAL;
+			}
+			i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request, 
+					    ctrl.requesttype, ctrl.value, ctrl.index, tbuf, 
+					    ctrl.length);
+			if (!i && ctrl.length) {
+				copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT);
+			}
+		} else {
+			if (ctrl.length) {
+				copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT);
+			}
+			i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request, 
+					    ctrl.requesttype, ctrl.value, ctrl.index, tbuf, 
+					    ctrl.length);
+		}
+		free_page((unsigned long)tbuf);
+		if (i) {
+			printk(KERN_WARNING "/proc/bus/usb: USB_PROC_CONTROL failed rqt %u rq %u len %u ret %d\n", 
+			       ctrl.requesttype, ctrl.request, ctrl.length, i);
+			return -ENXIO;
+		}
+		return 0;
+
+	case USB_PROC_BULK:
+		if (!capable(CAP_SYS_RAWIO))
+			return -EPERM;
+		copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
+		if (bulk.ep & 0x80)
+			pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
+		else
+			pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
+		if (!usb_maxpacket(dev, pipe, !(bulk.ep & 0x80)))
+			return -EINVAL;
+		len1 = bulk.len;
+		if (len1 > PAGE_SIZE)
+			len1 = PAGE_SIZE;
+		if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+			return -ENOMEM;
+		if (bulk.ep & 0x80) {
+			if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
+				free_page((unsigned long)tbuf);
+				return -EINVAL;
+			}
+			i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2);
+			if (!i && len2) {
+				copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
+			}
+		} else {
+			if (len1) {
+				copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
+			}
+			i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2);
+		}
+		free_page((unsigned long)tbuf);
+		if (i) {
+			printk(KERN_WARNING "/proc/bus/usb: USB_PROC_BULK failed ep 0x%x len %u ret %d\n", 
+			       bulk.ep, bulk.len, i);
+			return -ENXIO;
+		}
+		return len2;
+
+	case USB_PROC_RESETEP:
+		if (!capable(CAP_SYS_RAWIO))
+			return -EPERM;
+		get_user_ret(ep, (unsigned int *)arg, -EFAULT);
+		if ((ep & ~0x80) >= 16)
+			return -EINVAL;
+		usb_settoggle(dev, ep & 0xf, !(ep & 0x80), 0);
+		return 0;
+
+	case USB_PROC_SETINTERFACE:
+		if (!capable(CAP_SYS_RAWIO))
+			return -EPERM;
+		copy_from_user_ret(&setintf, (void *)arg, sizeof(setintf), -EFAULT);
+		if (usb_set_interface(dev, setintf.interface, setintf.altsetting))
+			return -EINVAL;
+		return 0;
+
+	case EZUSB_CONTROL:
+	case EZUSB_BULK:
+	case EZUSB_RESETEP:
+	case EZUSB_SETINTERFACE:
+		return usbdev_ioctl_ezusbcompat(inode, file, cmd, arg);
 	}
 	return -ENOIOCTLCMD;
 }
diff -u --recursive --new-file v2.3.15/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.3.15/linux/drivers/usb/uhci.c	Thu Aug 26 13:05:39 1999
+++ linux/drivers/usb/uhci.c	Fri Aug 27 15:03:07 1999
@@ -192,7 +192,7 @@
 	if ((status == TD_CTRL_ACTIVE) && (!rval))
 		return USB_ST_DATAUNDERRUN;
 
-	return uhci_map_status(status, usb_pipeout(tmp->info) ^ 1);
+	return uhci_map_status(status, uhci_packetout(tmp->info));
 }
 
 /*
@@ -593,7 +593,7 @@
  */
 static int uhci_get_current_frame_number(struct usb_device *usb_dev)
 {
-       return inw (usb_to_uhci(usb_dev)->uhci->io_addr + USBFRNUM) & 0x3ff;
+       return inw (usb_to_uhci(usb_dev)->uhci->io_addr + USBFRNUM);
 }
 
 
@@ -747,26 +747,52 @@
 		return -EINVAL;
 	}
 
+	/*
+	 * Check start_frame for inside a valid range.
+	 * Only allow transfer requests to be made 1.000 second
+	 * into the future.
+	 */
+	cur_frame = uhci_get_current_frame_number (isocdesc->usb_dev);
+
 	/* if not START_ASAP (i.e., RELATIVE or ABSOLUTE): */
-	if (!pr_isocdesc && (isocdesc->start_type != START_ASAP))
-		if ((isocdesc->start_frame < 0) || (isocdesc->start_frame > 1000)) {
+	if (!pr_isocdesc)
+		if (isocdesc->start_type == START_RELATIVE) {
+			if ((isocdesc->start_frame < 0) || (isocdesc->start_frame > CAN_SCHEDULE_FRAMES)) {
 #ifdef CONFIG_USB_DEBUG_ISOC
-			printk (KERN_DEBUG "uhci_init_isoc: bad start_frame value (%d)\n",
-				isocdesc->start_frame);
+				printk (KERN_DEBUG "uhci_init_isoc: bad start_frame value (%d)\n",
+					isocdesc->start_frame);
 #endif
-			return -EINVAL;
-		}
+				return -EINVAL;
+			}
+		} /* end START_RELATIVE */
+		else
+		if (isocdesc->start_type == START_ABSOLUTE) {
+			if (isocdesc->start_frame > cur_frame) {
+				if ((isocdesc->start_frame - cur_frame) > CAN_SCHEDULE_FRAMES) {
+#ifdef CONFIG_USB_DEBUG_ISOC
+					printk (KERN_DEBUG "uhci_init_isoc: bad start_frame value (%d)\n",
+						isocdesc->start_frame);
+#endif
+					return -EINVAL;
+				}
+			}
+			else /* start_frame <= cur_frame */ {
+				if ((isocdesc->start_frame + UHCI_MAX_SOF_NUMBER + 1
+				    - cur_frame) > CAN_SCHEDULE_FRAMES) {
+#ifdef CONFIG_USB_DEBUG_ISOC
+					printk (KERN_DEBUG "uhci_init_isoc: bad start_frame value (%d)\n",
+						isocdesc->start_frame);
+#endif
+					return -EINVAL;
+				}
+			}
+		} /* end START_ABSOLUTE */
 
 	/*
 	 * Set the start/end frame numbers.
 	 */
-	if (!pr_isocdesc)
-		cur_frame = uhci_get_current_frame_number (isocdesc->usb_dev);
-
 	if (pr_isocdesc) {
 		isocdesc->start_frame = pr_isocdesc->end_frame + 1;
-	} else if (isocdesc->start_type == START_ABSOLUTE) {
-		/* Use start_frame as is. */
 	} else if (isocdesc->start_type == START_RELATIVE) {
 		if (isocdesc->start_frame < START_FRAME_FUDGE)
 			isocdesc->start_frame = START_FRAME_FUDGE;
@@ -774,15 +800,16 @@
 	} else if (isocdesc->start_type == START_ASAP) {
 		isocdesc->start_frame = cur_frame + START_FRAME_FUDGE;
 	}
+	/* else for start_type == START_ABSOLUTE, use start_frame as is. */
 
 	/* and see if start_frame needs any correction */
-	if (isocdesc->start_frame >= 1000)
-		isocdesc->start_frame -= 1000;
+	if (isocdesc->start_frame >= UHCI_NUMFRAMES)
+		isocdesc->start_frame -= UHCI_NUMFRAMES;
 
 	/* and fix the end_frame value */
 	isocdesc->end_frame = isocdesc->start_frame + isocdesc->frame_count - 1;
-	if (isocdesc->end_frame >= 1000)
-	isocdesc->end_frame -= 1000;
+	if (isocdesc->end_frame >= UHCI_NUMFRAMES)
+		isocdesc->end_frame -= UHCI_NUMFRAMES;
 
 	isocdesc->prev_completed_frame = -1;
 	isocdesc->cur_completed_frame  = -1;
@@ -807,7 +834,7 @@
 		isocdesc->frame_spacing = 1;
 
 	for (ix = 0, td = isocdesc->td, fd = isocdesc->frames;
-	     ix < isocdesc->frame_count; ix++, td++, fd++, cur_frame++) {
+	     ix < isocdesc->frame_count; ix++, td++, fd++) {
 		frlen = fd->frame_length;
 		if (frlen > isocdesc->frame_size)
 			frlen = isocdesc->frame_size;
@@ -823,7 +850,7 @@
 		td->info   = destination | ((frlen - 1) << 21);
 		td->buffer = virt_to_bus (bufptr);
 		td->dev    = dev;
-		td->isoc_td_number = ix;        /* 0-based; does not wrap 999 -> 0 */
+		td->isoc_td_number = ix;        /* 0-based; does not wrap/overflow back to 0 */
 
 		if (isocdesc->callback_frames &&
 		    (++cb_frames >= isocdesc->callback_frames)) {
@@ -841,8 +868,8 @@
 		td->link    = uhci->fl->frame [cur_frame];
 		uhci->fl->frame [cur_frame] = virt_to_bus (td);
 
-		if (cur_frame >= 999)
-			cur_frame = -1;
+		if (++cur_frame >= UHCI_NUMFRAMES)
+			cur_frame = 0;
 	} /* end for ix */
 
 	/*
@@ -872,7 +899,7 @@
 	struct uhci_td  *td;
 	int             ix, cur_frame;
 
-	if ((isocdesc->start_frame < 0) || (isocdesc->start_frame >= 1000)) {
+	if ((isocdesc->start_frame < 0) || (isocdesc->start_frame >= UHCI_NUMFRAMES)) {
 #ifdef CONFIG_USB_DEBUG_ISOC
 		printk (KERN_DEBUG "uhci_kill_isoc: invalid start_frame (%d)\n",
 			isocdesc->start_frame);
@@ -885,7 +912,7 @@
 		td->status &= ~(TD_CTRL_ACTIVE | TD_CTRL_IOC);
 		uhci->fl->frame [cur_frame] = td->link;
 
-		if (++cur_frame >= 1000)
+		if (++cur_frame >= UHCI_NUMFRAMES)
 			cur_frame = 0;
 	} /* end for ix */
 
@@ -1551,7 +1578,7 @@
 			usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info) ^ 1);
 			td->info &= ~(1 << 19); /* clear data toggle */
 			td->info |= usb_gettoggle(usb_dev, usb_pipeendpoint(td->info),
-				usb_pipeout(td->info) ^ 1) << 19; /* toggle between data0 and data1 */
+				uhci_packetout(td->info)) << 19; /* toggle between data0 and data1 */
 			td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
 			/* The HC only removes it when it completed */
 			/* successfully, so force remove and readd it */
@@ -1562,7 +1589,7 @@
 
 			/* marked for removal */
 			td->flags &= ~UHCI_TD_REMOVE;
-			usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info) ^ 1);
+			usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), uhci_packetout(td->info));
 			uhci_remove_qh(td->qh->skel, td->qh);
 			uhci_qh_free(td->qh);
 			uhci_td_free(td);
diff -u --recursive --new-file v2.3.15/linux/drivers/usb/uhci.h linux/drivers/usb/uhci.h
--- v2.3.15/linux/drivers/usb/uhci.h	Thu Aug 26 13:05:39 1999
+++ linux/drivers/usb/uhci.h	Fri Aug 27 15:03:07 1999
@@ -60,7 +60,9 @@
 #define UHCI_PTR_QH		0x0002
 #define UHCI_PTR_DEPTH		0x0004
 
-#define UHCI_NUMFRAMES		1024
+#define UHCI_NUMFRAMES		1024	/* in the frame list [array] */
+#define UHCI_MAX_SOF_NUMBER	2047	/* in an SOF packet */
+#define CAN_SCHEDULE_FRAMES	1000	/* how far future frames can be scheduled */
 
 struct uhci_td;
 
@@ -80,7 +82,7 @@
 } __attribute__((aligned(16)));
 
 struct uhci_framelist {
-	__u32 frame[1024];
+	__u32 frame[UHCI_NUMFRAMES];
 } __attribute__((aligned(4096)));
 
 /*
@@ -127,20 +129,6 @@
 #define uhci_packetout(token)	(uhci_packetid(token) != USB_PID_IN)
 #define uhci_packetin(token)	(uhci_packetid(token) == USB_PID_IN)
 
-/*
- * for TD <info>: (a.k.a. Token)
- */
-#define TD_TOKEN_TOGGLE		19
-
-#define uhci_maxlen(token)	((token) >> 21)
-#define uhci_toggle(token)	(((token) >> TD_TOKEN_TOGGLE) & 1)
-#define uhci_endpoint(token)	(((token) >> 15) & 0xf)
-#define uhci_devaddr(token)	(((token) >> 8) & 0x7f)
-#define uhci_devep(token)	(((token) >> 8) & 0x7ff)
-#define uhci_packetid(token)	((token) & 0xff)
-#define uhci_packetout(token)	(uhci_packetid(token) != USB_PID_IN)
-#define uhci_packetin(token)	(uhci_packetid(token) == USB_PID_IN)
-
 
 /*
  * The documentation says "4 words for hardware, 4 words for software".
@@ -176,16 +164,6 @@
 	int isoc_td_number;		/* 0-relative number within a usb_isoc_desc. */
 } __attribute__((aligned(16)));
 
-struct uhci_iso_td {
-	int num;			/* Total number of TD's */
-	char *data;			/* Beginning of buffer */
-	int maxsze;			/* Maximum size of each data block */
-
-	struct uhci_td *td;		/* Pointer to first TD */
-
-	int frame;			/* Beginning frame */
-	int endframe;			/* End frame */
-};
 
 /*
  * Note the alignment requirements of the entries
diff -u --recursive --new-file v2.3.15/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.3.15/linux/drivers/usb/usb.c	Thu Aug 26 13:05:39 1999
+++ linux/drivers/usb/usb.c	Fri Aug 27 11:46:35 1999
@@ -1044,8 +1044,7 @@
         dr.index = cpu_to_le16p(&index);
         dr.length = cpu_to_le16p(&size);
 
-        return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr,
-                data, size);
+        return dev->bus->op->control_msg(dev, pipe, &dr, data, size);
 }
 
 void *usb_request_irq(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
diff -u --recursive --new-file v2.3.15/linux/drivers/usb/usb.h linux/drivers/usb/usb.h
--- v2.3.15/linux/drivers/usb/usb.h	Thu Aug 26 13:05:39 1999
+++ linux/drivers/usb/usb.h	Fri Aug 27 11:46:35 1999
@@ -1,33 +1,10 @@
 #ifndef __LINUX_USB_H
 #define __LINUX_USB_H
 
-#include <linux/config.h>
 #include <linux/types.h>
-#include <linux/list.h>
-#include <linux/sched.h>
+#include <linux/ioctl.h>
 
-extern int usb_hub_init(void);
-extern int usb_kbd_init(void);
-extern int usb_cpia_init(void);
-extern int usb_mouse_init(void);
-extern int usb_printer_init(void);
-
-extern void usb_hub_cleanup(void);
-extern void usb_mouse_cleanup(void);
-
-static __inline__ void wait_ms(unsigned int ms)
-{
-        current->state = TASK_UNINTERRUPTIBLE;
-        schedule_timeout(1 + ms * HZ / 1000);
-}
-
-typedef struct {
-	__u8 requesttype;
-	__u8 request;
-	__u16 value;
-	__u16 index;
-	__u16 length;
-} devrequest __attribute__ ((packed));
+/* USB constants */
 
 /*
  * Device and/or Interface Class codes
@@ -132,6 +109,69 @@
 
 #define USB_RT_HIDD			(USB_TYPE_CLASS | USB_RECIP_INTERFACE)
 
+/* /proc/bus/usb/xxx/yyy ioctl codes */
+
+struct usb_proc_ctrltransfer {
+	__u8 requesttype;
+	__u8 request;
+	__u16 value;
+	__u16 index;
+	__u16 length;
+        /* pointer to data */
+        void *data;
+};
+
+#define USB_PROC_CONTROL        _IOWR('U', 0, struct usb_proc_ctrltransfer)
+
+struct usb_proc_bulktransfer {
+        unsigned int ep;
+        unsigned int len;
+        void *data;
+};
+
+#define USB_PROC_BULK           _IOWR('U', 2, struct usb_proc_bulktransfer)
+
+#define USB_PROC_RESETEP        _IOR('U', 3, unsigned int)
+
+struct usb_proc_setinterface {
+        unsigned int interface;
+        unsigned int altsetting;
+};
+
+#define USB_PROC_SETINTERFACE   _IOR('U', 4, struct usb_proc_setinterface)
+
+
+
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+
+extern int usb_hub_init(void);
+extern int usb_kbd_init(void);
+extern int usb_cpia_init(void);
+extern int usb_mouse_init(void);
+extern int usb_printer_init(void);
+
+extern void usb_hub_cleanup(void);
+extern void usb_mouse_cleanup(void);
+
+static __inline__ void wait_ms(unsigned int ms)
+{
+        current->state = TASK_UNINTERRUPTIBLE;
+        schedule_timeout(1 + ms * HZ / 1000);
+}
+
+typedef struct {
+	__u8 requesttype;
+	__u8 request;
+	__u16 value;
+	__u16 index;
+	__u16 length;
+} devrequest __attribute__ ((packed));
+
 /* 
  * Status codes (these follow OHCI controllers condition codes)
  */
@@ -639,6 +679,8 @@
 extern inline void proc_usb_add_device(struct usb_device *dev) {}
 extern inline void proc_usb_remove_device(struct usb_device *dev) {}
 #endif
+
+#endif  /* __KERNEL */
 
 #endif
 
diff -u --recursive --new-file v2.3.15/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c
--- v2.3.15/linux/drivers/video/acornfb.c	Thu Aug 26 13:05:40 1999
+++ linux/drivers/video/acornfb.c	Mon Aug 30 18:15:21 1999
@@ -34,6 +34,7 @@
 #include <video/fbcon-cfb4.h>
 #include <video/fbcon-cfb8.h>
 #include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb32.h>
 
 /*
  * Default resolution.
@@ -58,7 +59,7 @@
 #endif
 
 #define EXTEND8(x) ((x)|(x)<<8)
-#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<16)
+#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<12)
 
 struct vidc20_palette {
 	u_int red:8;
@@ -554,14 +555,14 @@
 	bandwidth = var->pixclock * 8 / var->bits_per_pixel;
 
 	/* Encode bandwidth as VIDC20 setting */
-	if (bandwidth > 16667*2)
-		vidc->control |= VIDC20_CTRL_FIFO_16;
-	else if (bandwidth > 13333*2)
-		vidc->control |= VIDC20_CTRL_FIFO_20;
-	else if (bandwidth > 11111*2)
-		vidc->control |= VIDC20_CTRL_FIFO_24;
+	if (bandwidth > 33334)
+		vidc->control |= VIDC20_CTRL_FIFO_16;	/* < 30.0MB/s */
+	else if (bandwidth > 26666)
+		vidc->control |= VIDC20_CTRL_FIFO_20;	/* < 37.5MB/s */
+	else if (bandwidth > 22222)
+		vidc->control |= VIDC20_CTRL_FIFO_24;	/* < 45.0MB/s */
 	else
-		vidc->control |= VIDC20_CTRL_FIFO_28;
+		vidc->control |= VIDC20_CTRL_FIFO_28;	/* > 45.0MB/s */
 
 	/* Find the PLL values */
 	vidc->pll_ctl  = acornfb_vidc20_find_pll(var->pixclock / div);
@@ -742,7 +743,7 @@
  * Before selecting the timing parameters, adjust
  * the resolution to fit the rules.
  */
-static void
+static int
 acornfb_pre_adjust_timing(struct fb_var_screeninfo *var, int con)
 {
 	u_int font_line_len;
@@ -785,6 +786,13 @@
 	font_line_len = var->xres * var->bits_per_pixel * fontht / 8;
 	min_size = var->xres * var->yres * var->bits_per_pixel / 8;
 
+	/*
+	 * If minimum screen size is greater than that we have
+	 * available, reject it.
+	 */
+	if (min_size > current_par.screen_size)
+		return -EINVAL;
+
 	/* Find int 'y', such that y * fll == s * sam < maxsize
 	 * y = s * sam / fll; s = maxsize / sam
 	 */
@@ -820,6 +828,7 @@
 		if (var->yoffset + var->yres > var->yres_virtual)
 			var->yoffset = var->yres_virtual - var->yres;
 	}
+	return 0;
 }
 
 /*
@@ -897,32 +906,75 @@
 	return 0;
 }
 
+/*
+ * We have to take note of the VIDC20's 16-bit palette here.
+ * The VIDC20 looks up a 16 bit pixel as follows:
+ *
+ *   bits   111111
+ *          5432109876543210
+ *   red            ++++++++  (8 bits,  7 to 0)
+ *  green       ++++++++      (8 bits, 11 to 4)
+ *   blue   ++++++++          (8 bits, 15 to 8)
+ *
+ * We use a pixel which looks like:
+ *
+ *   bits   111111
+ *          5432109876543210
+ *   red               +++++  (5 bits,  4 to  0)
+ *  green         +++++       (5 bits,  9 to  5)
+ *   blue    +++++            (5 bits, 14 to 10)
+ */
 static int
 acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 		  u_int trans, struct fb_info *info)
 {
 	union palette pal;
+	int bpp = fb_display[current_par.currcon].var.bits_per_pixel;
 
 	if (regno >= current_par.palette_size)
 		return 1;
 
 	pal = acornfb_palette_encode(regno, red, green, blue, trans);
-	acornfb_palette_write(regno, pal);
 	current_par.palette[regno] = pal;
 
+#ifdef HAS_VIDC20
 	if (regno < 16) {
-		switch (info->disp->var.bits_per_pixel) {
+		switch (bpp) {
 #ifdef FBCON_HAS_CFB16
-		case 16:	/* RGB555 */
-			current_par.cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno;
+		case 16:
+			current_par.cmap.cfb16[regno] =
+				regno | regno << 5 | regno << 10;
+			break;
+#endif
+#ifdef FBCON_HAS_CFB32
+		case 32:
+			current_par.cmap.cfb32[regno] =
+				regno | regno << 8 | regno << 16;
 			break;
 #endif
-
 		default:
 			break;
 		}
 	}
 
+#ifdef FBCON_HAS_CFB16
+	if (bpp == 16) {
+		int i;
+
+		pal.p = 0;
+		outl(0x10000000, IO_VIDC_BASE);
+		for (i = 0; i < 256; i += 1) {
+			pal.vidc20.red   = current_par.palette[ i       & 31].vidc20.red;
+			pal.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
+			pal.vidc20.blue  = current_par.palette[(i >> 2) & 31].vidc20.blue;
+			outl(pal.p, IO_VIDC_BASE);
+			/* Palette register pointer auto-increments */
+		}
+	} else
+#endif
+#endif
+		acornfb_palette_write(regno, pal);
+
 	return 0;
 }
 
@@ -965,6 +1017,8 @@
 static int
 acornfb_decode_var(struct fb_var_screeninfo *var, int con, int *visual)
 {
+	int err;
+
 	switch (var->bits_per_pixel) {
 #ifdef FBCON_HAS_MFB
 	case 1:
@@ -990,10 +1044,18 @@
 		*visual = FB_VISUAL_PSEUDOCOLOR;
 		break;
 #endif
+#ifdef HAS_VIDC20
+#ifdef FBCON_HAS_CFB16
 	case 16:
-	case 24:
+		*visual = FB_VISUAL_DIRECTCOLOR;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB32
 	case 32:
 		*visual = FB_VISUAL_TRUECOLOR;
+		break;
+#endif
+#endif
 	default:
 		return -EINVAL;
 	}
@@ -1002,20 +1064,52 @@
 		return -EINVAL;
 
 	/*
-	 * Adjust the resolution before using it.
+	 * Validate and adjust the resolution
+	 * before using it.
 	 */
-	acornfb_pre_adjust_timing(var, con);
+	err = acornfb_pre_adjust_timing(var, con);
+	if (err)
+		return err;
 
 #if defined(HAS_VIDC20)
-	var->red.length	   = 8;
-	var->transp.length = 4;
+	switch (var->bits_per_pixel) {
+	case 1: case 2: case 4: case 8:
+		var->red.offset    = 0;
+		var->red.length    = 8;
+		var->green         = var->red;
+		var->blue          = var->red;
+		var->transp.offset = 0;
+		var->transp.length = 4;
+		break;
+
+	case 16:
+		var->red.offset    = 0;
+		var->red.length    = 5;
+		var->green.offset  = 5;
+		var->green.length  = 5;
+		var->blue.offset   = 10;
+		var->blue.length   = 5;
+		var->transp.offset = 15;
+		var->transp.length = 1;
+		break;
+
+	case 32:
+		var->red.offset    = 0;
+		var->red.length    = 8;
+		var->green.offset  = 8;
+		var->green.length  = 8;
+		var->blue.offset   = 16;
+		var->blue.length   = 8;
+		var->transp.offset = 24;
+		var->transp.length = 4;
+		break;
+	}
 #elif defined(HAS_VIDC)
 	var->red.length	   = 4;
+	var->green         = var->red;
+	var->blue          = var->red;
 	var->transp.length = 1;
 #endif
-	var->green = var->red;
-	var->blue  = var->red;
-
 	/*
 	 * Now adjust the timing parameters
 	 */
@@ -1153,11 +1247,18 @@
 #endif
 #ifdef FBCON_HAS_CFB16
 	case 16:
-		current_par.palette_size = VIDC_PALETTE_SIZE;
+		current_par.palette_size = 32;
 		display->dispsw = &fbcon_cfb16;
 		display->dispsw_data = current_par.cmap.cfb16;
 		break;
 #endif
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		current_par.palette_size = VIDC_PALETTE_SIZE;
+		display->dispsw = &fbcon_cfb32;
+		display->dispsw_data = current_par.cmap.cfb32;
+		break;
+#endif
 	default:
 		display->dispsw = &fbcon_dummy;
 		break;
@@ -1290,19 +1391,32 @@
 static void
 acornfb_blank(int blank, struct fb_info *info)
 {
-	int i;
+	union palette p;
+	int i, bpp = fb_display[current_par.currcon].var.bits_per_pixel;
 
-	if (blank)
+	if (bpp != 16) {
 		for (i = 0; i < current_par.palette_size; i++) {
-			union palette p;
-
-			p = acornfb_palette_encode(i, 0, 0, 0, 0);
+			if (blank)
+				p = acornfb_palette_encode(i, 0, 0, 0, 0);
+			else
+				p = current_par.palette[i];
 
 			acornfb_palette_write(i, p);
 		}
-	else
-		for (i = 0; i < current_par.palette_size; i++)
+	} else {
+		p.p = 0;
+
+		for (i = 0; i < 256; i++) {
+			if (blank)
+				p = acornfb_palette_encode(i, 0, 0, 0, 0);
+			else {
+				p.vidc20.red   = current_par.palette[ i       & 31].vidc20.red;
+				p.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
+				p.vidc20.blue  = current_par.palette[(i >> 2) & 31].vidc20.blue;
+			}
 			acornfb_palette_write(i, current_par.palette[i]);
+		}
+	}
 }
 
 /*
@@ -1842,7 +1956,7 @@
 
 	size = PAGE_ALIGN(size);
 
-#ifdef CONFIG_ARCH_RPC
+#if defined(HAS_VIDC20)
 	if (!current_par.using_vram) {
 		/*
 		 * RiscPC needs to allocate the DRAM memory
@@ -1850,17 +1964,30 @@
 		 * VRAM.  Archimedes/A5000 machines use a
 		 * fixed address for their framebuffers.
 		 */
-		current_par.screen_base = (unsigned long)kmalloc(size, GFP_KERNEL);
+		int order = 0;
+		unsigned long page, top;
+		while (size > (PAGE_SIZE * (1 << order)))
+			order++;
+		current_par.screen_base = __get_free_pages(GFP_KERNEL, order);
 		if (current_par.screen_base == 0) {
 			printk(KERN_ERR "acornfb: unable to allocate screen "
 			       "memory\n");
 			return;
 		}
+		top = current_par.screen_base + (PAGE_SIZE * (1 << order));
+		/* Mark the framebuffer pages as reserved so mmap will work. */
+		for (page = current_par.screen_base; 
+		     page < PAGE_ALIGN(current_par.screen_base + size);
+		     page += PAGE_SIZE)
+			mem_map[MAP_NR(page)].flags |= (1 << PG_reserved);
+		/* Hand back any excess pages that we allocated. */
+		for (page = current_par.screen_base + size; page < top; page += PAGE_SIZE)
+			free_page(page);
 		current_par.screen_base_p =
 			virt_to_phys(current_par.screen_base);
 	}
 #endif
-#if defined(CONFIG_ARCH_A5K) || defined(CONFIG_ARCH_ARC)
+#if defined(HAS_VIDC)
 #define MAX_SIZE	480*1024
 	/*
 	 * Limit maximum screen size.
diff -u --recursive --new-file v2.3.15/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.3.15/linux/drivers/video/atyfb.c	Thu Aug 26 13:05:40 1999
+++ linux/drivers/video/atyfb.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.109 1999/08/08 01:38:05 davem Exp $
+/*  $Id: atyfb.c,v 1.120 1999/08/30 10:12:18 davem Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *	Copyright (C) 1997-1998  Geert Uytterhoeven
@@ -262,6 +262,7 @@
 static int atyfb_mmap(struct fb_info *info, struct file *file,
 		      struct vm_area_struct *vma);
 #endif
+static int atyfb_rasterimg(struct fb_info *info, int start);
 
 
     /*
@@ -400,10 +401,11 @@
     atyfb_open, atyfb_release, atyfb_get_fix, atyfb_get_var, atyfb_set_var,
     atyfb_get_cmap, atyfb_set_cmap, atyfb_pan_display, atyfb_ioctl,
 #ifdef __sparc__
-    atyfb_mmap
+    atyfb_mmap,
 #else
-    NULL
+    NULL,
 #endif
+    atyfb_rasterimg
 };
 
 static char atyfb_name[16] = "ATY Mach64";
@@ -488,7 +490,7 @@
     asm volatile("lwbrx %0,%1,%2" : "=r"(val) : "b" (regindex), "r" (temp));
 #elif defined(__sparc_v9__)
     temp = info->ati_regbase + regindex;
-    asm volatile("lduwa [%1] %2, %0" : "=r" (val) : "r" (temp), "i" (ASI_PL));
+    val = readl(temp);
 #else
     temp = info->ati_regbase+regindex;
     val = le32_to_cpu(*((volatile u32 *)(temp)));
@@ -507,7 +509,7 @@
 	"memory");
 #elif defined(__sparc_v9__)
     temp = info->ati_regbase + regindex;
-    asm volatile("stwa %0, [%1] %2" : : "r" (val), "r" (temp), "i" (ASI_PL) : "memory");
+    writel(val, temp);
 #else
     temp = info->ati_regbase+regindex;
     *((volatile u32 *)(temp)) = cpu_to_le32(val);
@@ -517,13 +519,21 @@
 static inline u8 aty_ld_8(unsigned int regindex,
 			  const struct fb_info_aty *info)
 {
+#ifdef __sparc_v9__
+    return readb(info->ati_regbase + regindex);
+#else
     return *(volatile u8 *)(info->ati_regbase+regindex);
+#endif
 }
 
 static inline void aty_st_8(unsigned int regindex, u8 val,
 			    const struct fb_info_aty *info)
 {
+#ifdef __sparc_v9__
+    writeb(val, info->ati_regbase + regindex);
+#else
     *(volatile u8 *)(info->ati_regbase+regindex) = val;
+#endif
 }
 
 
@@ -2224,6 +2234,7 @@
 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
 		       u_long arg, int con, struct fb_info *info2)
 {
+    struct fb_info_aty *info = (struct fb_info_aty *)info2;
 #ifdef __sparc__
     struct fbtype fbtyp;
     struct display *disp;
@@ -2298,6 +2309,15 @@
     return 0;
 }
 
+static int atyfb_rasterimg(struct fb_info *info, int start)
+{
+    struct fb_info_aty *fb = (struct fb_info_aty *)info;
+
+    if (fb->blitter_may_be_busy)
+	wait_for_idle(fb);
+    return 0;
+}
+
 #ifdef __sparc__
 static int atyfb_mmap(struct fb_info *info, struct file *file,
 		      struct vm_area_struct *vma)
@@ -2511,6 +2531,9 @@
     u8 pll_ref_div;
 
     info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0);
+#ifdef __sparc_v9__
+    info->aty_cmap_regs = __va(info->aty_cmap_regs);
+#endif
     chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
     Gx = chip_id & CFG_CHIP_TYPE;
     Rev = (chip_id & CFG_CHIP_REV)>>24;
@@ -2755,6 +2778,7 @@
 #ifdef MODULE
     var = default_var;
 #else /* !MODULE */
+    memset(&var, 0, sizeof(var));
 #if defined(CONFIG_PPC)
     if (mode_option) {
 	if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
@@ -2784,8 +2808,16 @@
 	    var = default_var;
     }
 #else /* !CONFIG_PPC */
+#ifdef __sparc__
+    if (mode_option) {
+    	if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
+	    var = default_var;
+    } else
+	var = default_var;
+#else
     if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
 	var = default_var;
+#endif /* !__sparc__ */
 #endif /* !CONFIG_PPC */
 #endif /* !MODULE */
     if (noaccel)
@@ -2884,14 +2916,14 @@
 	    /*
 	     * Map memory-mapped registers.
 	     */
-	    info->ati_regbase = addr + 0x7ffc00;
-	    info->ati_regbase_phys = __pa(addr + 0x7ffc00);
+	    info->ati_regbase = addr + 0x7ffc00UL;
+	    info->ati_regbase_phys = addr + 0x7ffc00UL;
 
 	    /*
 	     * Map in big-endian aperture.
 	     */
-	    info->frame_buffer = (unsigned long)(addr + 0x800000);
-	    info->frame_buffer_phys = __pa(addr + 0x800000);
+	    info->frame_buffer = (unsigned long) __va(addr + 0x800000UL);
+	    info->frame_buffer_phys = addr + 0x800000UL;
 
 	    /*
 	     * Figure mmap addresses from PCI config space.
@@ -2934,7 +2966,7 @@
 		 */
 		if (base == addr) {
 		    info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
-		    info->mmap_map[j].poff = __pa(base & PAGE_MASK);
+		    info->mmap_map[j].poff = base & PAGE_MASK;
 		    info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
 		    info->mmap_map[j].prot_mask = _PAGE_CACHE;
 		    info->mmap_map[j].prot_flag = _PAGE_E;
@@ -2947,7 +2979,7 @@
 		 */
 		if (base == addr) {
 		    info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
-		    info->mmap_map[j].poff = __pa((base+0x800000) & PAGE_MASK);
+		    info->mmap_map[j].poff = (base+0x800000) & PAGE_MASK;
 		    info->mmap_map[j].size = 0x800000;
 		    info->mmap_map[j].prot_mask = _PAGE_CACHE;
 		    info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE;
@@ -2956,7 +2988,7 @@
 		}
 
 		info->mmap_map[j].voff = pbase & PAGE_MASK;
-		info->mmap_map[j].poff = __pa(base & PAGE_MASK);
+		info->mmap_map[j].poff = base & PAGE_MASK;
 		info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
 		info->mmap_map[j].prot_mask = _PAGE_CACHE;
 		info->mmap_map[j].prot_flag = _PAGE_E;
@@ -3136,7 +3168,7 @@
 	    info->mmap_map[0].prot_mask = _PAGE_CACHE;
 	    info->mmap_map[0].prot_flag = _PAGE_E;
 	    info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram;
-	    info->mmap_map[1].poff = __pa(info->ati_regbase & PAGE_MASK);
+	    info->mmap_map[1].poff = info->ati_regbase & PAGE_MASK;
 	    info->mmap_map[1].size = PAGE_SIZE;
 	    info->mmap_map[1].prot_mask = _PAGE_CACHE;
 	    info->mmap_map[1].prot_flag = _PAGE_E;
@@ -3334,8 +3366,8 @@
 	    }
 	}
 #endif
-       else
-           mode_option = this_opt;
+	else
+	    mode_option = this_opt;
     }
     return 0;
 }
diff -u --recursive --new-file v2.3.15/linux/drivers/video/bwtwofb.c linux/drivers/video/bwtwofb.c
--- v2.3.15/linux/drivers/video/bwtwofb.c	Thu Feb 25 10:02:12 1999
+++ linux/drivers/video/bwtwofb.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: bwtwofb.c,v 1.7 1999/01/26 10:55:02 jj Exp $
+/* $Id: bwtwofb.c,v 1.8 1999/08/26 05:13:09 shadow Exp $
  * bwtwofb.c: BWtwo frame buffer driver
  *
  * Copyright (C) 1998 Jakub Jelinek   (jj@ultra.linux.cz)
@@ -216,7 +216,7 @@
 #endif
 	fb->margins = bw2_margins;
 	
-	fb->physbase = phys;
+	fb->physbase = __get_phys(fb->sbdp->sbus_vaddrs[0]);
 	fb->mmap_map = bw2_mmap_map;
 
 #ifdef __sparc_v9__
diff -u --recursive --new-file v2.3.15/linux/drivers/video/cgfourteenfb.c linux/drivers/video/cgfourteenfb.c
--- v2.3.15/linux/drivers/video/cgfourteenfb.c	Mon Aug  9 10:25:01 1999
+++ linux/drivers/video/cgfourteenfb.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: cgfourteenfb.c,v 1.4 1999/01/26 10:55:03 jj Exp $
+/* $Id: cgfourteenfb.c,v 1.5 1999/08/10 15:56:02 davem Exp $
  * cgfourteenfb.c: CGfourteen frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
diff -u --recursive --new-file v2.3.15/linux/drivers/video/cgsixfb.c linux/drivers/video/cgsixfb.c
--- v2.3.15/linux/drivers/video/cgsixfb.c	Mon Aug  9 10:25:01 1999
+++ linux/drivers/video/cgsixfb.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.17 1999/05/25 01:00:31 davem Exp $
+/* $Id: cgsixfb.c,v 1.19 1999/08/10 15:56:03 davem Exp $
  * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -588,6 +588,18 @@
 	p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin);
 }
 
+static int __init cg6_rasterimg (struct fb_info *info, int start)
+{
+	struct fb_info_sbusfb *fb = sbusfbinfo(info);
+	register struct cg6_fbc *fbc = fb->s.cg6.fbc;
+	int i;
+	
+	do {
+		i = fbc->s;
+	} while (i & 0x10000000);
+	return 0;
+}
+
 static char idstring[70] __initdata = { 0 };
 
 char __init *cgsixfb_init(struct fb_info_sbusfb *fb)
@@ -601,10 +613,20 @@
 	char *p;
 	char *cardtype;
 	struct bt_regs *bt;
+	struct fb_ops *fbops;
+
+	fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
+	if (!fbops) return NULL;
+	
+	*fbops = *fb->info.fbops;
+	fbops->fb_rasterimg = cg6_rasterimg;
+	fb->info.fbops = fbops;
+	
+	if (prom_getbool (fb->prom_node, "dblbuf")) {
+		type->fb_size *= 4;
+		fix->smem_len *= 4;
+	}
 
-	strcpy(fb->info.modename, "CGsix");
-		
-	strcpy(fix->id, "CGsix");
 	fix->line_length = fb->var.xres_virtual;
 	fix->accel = FB_ACCEL_SUN_CGSIX;
 	
@@ -660,9 +682,9 @@
 
 	if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) {
 		if (fix->smem_len <= 0x100000) {
-			cardtype = "TurboGX";
+			cardtype = "TGX";
 		} else {
-			cardtype = "TurboGX+";
+			cardtype = "TGX+";
 		}
 	} else {
 		if (fix->smem_len <= 0x100000) {
@@ -680,6 +702,9 @@
 #endif
 		    (fb->s.cg6.thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK,
 		    p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK, cardtype);
+
+	sprintf(fb->info.modename, "CGsix [%s]", cardtype);
+	sprintf(fix->id, "CGsix [%s]", cardtype);
 		    
 	cg6_reset(fb);
 		    
diff -u --recursive --new-file v2.3.15/linux/drivers/video/cgthreefb.c linux/drivers/video/cgthreefb.c
--- v2.3.15/linux/drivers/video/cgthreefb.c	Mon Aug  9 10:25:01 1999
+++ linux/drivers/video/cgthreefb.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: cgthreefb.c,v 1.4 1999/01/26 10:55:01 jj Exp $
+/* $Id: cgthreefb.c,v 1.5 1999/08/10 15:56:04 davem Exp $
  * cgthreefb.c: CGthree frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
diff -u --recursive --new-file v2.3.15/linux/drivers/video/chipsfb.c linux/drivers/video/chipsfb.c
--- v2.3.15/linux/drivers/video/chipsfb.c	Thu Aug 26 13:05:40 1999
+++ linux/drivers/video/chipsfb.c	Thu Aug 26 12:34:55 1999
@@ -559,7 +559,7 @@
 // * 3400 has 1MB (I think).  Don't know if it's expandable.
 // -- Tim Seufert
 	p->fix.smem_len = 0x100000;	// 1MB
-	p->fix.mmio_start = (char *) p->io_base_phys;
+	p->fix.mmio_start = p->io_base_phys;
 	p->fix.type = FB_TYPE_PACKED_PIXELS;
 	p->fix.visual = FB_VISUAL_PSEUDOCOLOR;
 	p->fix.line_length = 800;
diff -u --recursive --new-file v2.3.15/linux/drivers/video/controlfb.c linux/drivers/video/controlfb.c
--- v2.3.15/linux/drivers/video/controlfb.c	Thu Aug 26 13:05:40 1999
+++ linux/drivers/video/controlfb.c	Thu Aug 26 09:48:40 1999
@@ -149,7 +149,7 @@
 /*
  * Exported functions
  */
-void control_init(void);
+int control_init(void);
 #ifdef CONFIG_FB_OF
 void control_of_init(struct device_node *dp);
 #endif
@@ -185,13 +185,9 @@
 
 /********************  The functions for controlfb_ops ********************/
 
-#ifndef MODULE
-__openfirmware
-#endif
-
 /**********  Dummies for loading control as a module  **********/
 
-static int control_open(struct fb_info *info, int user)
+int control_open(struct fb_info *info, int user)
 {
 	MOD_INC_USE_COUNT;
 	return 0;
@@ -660,7 +656,7 @@
 #endif /* CONFIG_FB_COMPAT_XPMAC */
 }
 
-void __init control_init(void)
+int __init control_init(void)
 {
 #ifndef CONFIG_FB_OF
 	struct device_node *dp;
@@ -669,6 +665,7 @@
 	if (dp != 0)
 		control_of_init(dp);
 #endif /* CONFIG_FB_OF */
+	return 0;
 }
 
 void __init control_of_init(struct device_node *dp)
@@ -720,9 +717,11 @@
 	p->total_vram = (bank1 + bank2) * 0x200000;
 	/* If we don't have bank 1 installed, we hope we have bank 2 :-) */
 	p->control_use_bank2 = !bank1;
-	if (p->control_use_bank2)
+	if (p->control_use_bank2) {
 		p->frame_buffer += 0x600000;
-
+		p->frame_buffer_phys += 0x600000;
+	}
+	
 	init_control(p);
 }
 
diff -u --recursive --new-file v2.3.15/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c
--- v2.3.15/linux/drivers/video/creatorfb.c	Mon Aug  9 10:25:01 1999
+++ linux/drivers/video/creatorfb.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: creatorfb.c,v 1.27 1999/03/28 12:37:12 jj Exp $
+/* $Id: creatorfb.c,v 1.29 1999/08/10 15:56:07 davem Exp $
  * creatorfb.c: Creator/Creator3D frame buffer driver
  *
  * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
@@ -633,7 +633,13 @@
 	fbc->fg = fb->s.ffb.fg_cache;
 	fbc->bg = fb->s.ffb.bg_cache;
 	FFBWait(fbc);
-}                                
+}
+
+static int __init ffb_rasterimg (struct fb_info *info, int start)
+{
+	ffb_switch_from_graph (sbusfbinfo(info));
+	return 0;
+}
 
 static char idstring[60] __initdata = { 0 };
 
@@ -647,6 +653,7 @@
 	int i, afb = 0;
 	unsigned int btype;
 	char name[64];
+	struct fb_ops *fbops;
 
 	if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0)
 		return NULL;
@@ -655,6 +662,13 @@
 	if (!disp->dispsw_data)
 		return NULL;
 	memset(disp->dispsw_data, 0, 16 * sizeof(u32));
+
+	fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
+	if (!fbops) return NULL;
+	
+	*fbops = *fb->info.fbops;
+	fbops->fb_rasterimg = ffb_rasterimg;
+	fb->info.fbops = fbops;
 
 	prom_getstring(fb->prom_node, "name", name, sizeof(name));
 	if (!strcmp(name, "SUNW,afb"))
diff -u --recursive --new-file v2.3.15/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c
--- v2.3.15/linux/drivers/video/cyber2000fb.c	Thu Aug 26 13:05:40 1999
+++ linux/drivers/video/cyber2000fb.c	Mon Aug 30 18:15:21 1999
@@ -631,13 +631,15 @@
 	cyber2000_outw(width, 0xbf218);
 	cyber2000_outb(b,     0xbf01c);
 
-{ int j;
+#if 0
+{ int j; i = 0;
  printk(KERN_DEBUG);
  for (j = 0; j < 19; j++) printk("%2d ", j); printk("\n"KERN_DEBUG);
  for (j = 0; j < 19; j++) printk("%02X ", crtc[j]); printk("\n"KERN_DEBUG);
  for (j = 0; j < 18; j++) printk("%02X ", cyber2000_res[i].crtc_regs[j]);
  printk("%02X\n", cyber2000_res[i].crtc_ofl);
 }
+#endif
 }
 
 static inline void
@@ -1143,12 +1145,24 @@
 {
 	struct pci_dev *dev;
 	u_int h_sync, v_sync;
+	u_long base_p, base_v;
 
 	dev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, NULL);
 	if (!dev)
 		return -ENXIO;
 
-	CyberRegs = bus_to_virt(dev->base_address[0]) + 0x00800000;/*FIXME*/
+	/* this should be done by PCI generic code */
+	base_p = 0x80000000 + dev->resource[0].start;
+
+	/*
+	 * This should be ioremap'd, thus:
+	 *
+	 * base_v = ioremap(dev->resource[0].start, dev->resource[0].end - dev->resource[0].start + 1);
+	 */
+	base_v = (u_long)bus_to_virt(dev->resource[0].start);
+
+	/*FIXME*/
+	CyberRegs = base_v + 0x00800000;
 
 	cyber2000_outb(0x18, 0x46e8);
 	cyber2000_outb(0x01, 0x102);
@@ -1157,13 +1171,10 @@
 	cyber2000fb_init_fbinfo();
 
 	current_par.currcon		= -1;
-	/* this should be done by PCI generic code */
-	current_par.screen_base_p	= 0x80000000 + dev->resource[0].start;
-	/* and this by ioremap... But I have no such device here to test */
-	/* current_par.screen_base = ioremap(dev->resource[0].start, dev->resource[0].end - dev->resource[0].start + 1); */
-	current_par.screen_base		= (u_int)bus_to_virt(dev->resource[0].start);
+	current_par.screen_base_p	= base_p;
+	current_par.screen_base		= base_v;
 	current_par.screen_size		= 0x00200000;
-	current_par.regs_base_p		= 0x80800000 + dev->resource[0].start;
+	current_par.regs_base_p		= base_p + 0x00800000;
 
 	cyber2000fb_set_var(&init_var, -1, &fb_info);
 
diff -u --recursive --new-file v2.3.15/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- v2.3.15/linux/drivers/video/fbcon.c	Mon Aug  9 11:38:10 1999
+++ linux/drivers/video/fbcon.c	Thu Aug 26 14:24:11 1999
@@ -246,7 +246,7 @@
 
 struct display_switch fbcon_dummy;
 
-/* NOTE: fbcon cannot be __initfunc: it may be called from take_over_console later */
+/* NOTE: fbcon cannot be __init: it may be called from take_over_console later */
 
 static const char *fbcon_startup(void)
 {
diff -u --recursive --new-file v2.3.15/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.3.15/linux/drivers/video/fbmem.c	Thu Aug 26 13:05:40 1999
+++ linux/drivers/video/fbmem.c	Thu Aug 26 09:48:40 1999
@@ -92,6 +92,8 @@
 extern int sbusfb_setup(char*);
 extern int valkyriefb_init(void);
 extern int valkyriefb_setup(char*);
+extern int control_init(void);
+extern int control_setup(char*);
 extern int g364fb_init(void);
 extern int fm2fb_init(void);
 extern int fm2fb_setup(char*);
@@ -176,6 +178,9 @@
 #ifdef CONFIG_FB_HP300
 	{ "hpfb", hpfb_init, hpfb_setup },
 #endif 
+#ifdef CONFIG_FB_CONTROL
+	{ "controlfb", control_init, control_setup },
+#endif
 #ifdef CONFIG_FB_VALKYRIE
 	{ "valkyriefb", valkyriefb_init, valkyriefb_setup },
 #endif
diff -u --recursive --new-file v2.3.15/linux/drivers/video/leofb.c linux/drivers/video/leofb.c
--- v2.3.15/linux/drivers/video/leofb.c	Thu Apr 22 19:30:08 1999
+++ linux/drivers/video/leofb.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: leofb.c,v 1.6 1999/04/01 13:03:25 jj Exp $
+/* $Id: leofb.c,v 1.7 1999/08/09 11:06:52 jj Exp $
  * leofb.c: Leo (ZX) 24/8bit frame buffer driver
  *
  * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
@@ -505,8 +505,9 @@
 	us->fontt = 0;
 }
 
-static void __init leo_rasterimg (struct fb_info_sbusfb *fb, int start)
+static int __init leo_rasterimg (struct fb_info *info, int start)
 {
+	struct fb_info_sbusfb *fb = sbusfbinfo(info);
 	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
 	register struct leo_ld *ss = fb->s.leo.ld_ss0;
 
@@ -521,6 +522,7 @@
 		ss->rop = 0x310850;
 		us->addrspace = 4;
 	}
+	return 0;
 }
 
 static char idstring[40] __initdata = { 0 };
diff -u --recursive --new-file v2.3.15/linux/drivers/video/matroxfb.c linux/drivers/video/matroxfb.c
--- v2.3.15/linux/drivers/video/matroxfb.c	Thu Aug 26 13:05:40 1999
+++ linux/drivers/video/matroxfb.c	Mon Aug 30 18:17:51 1999
@@ -5635,6 +5635,16 @@
 		NULL,
 		NULL}};
 	
+#ifndef MODULE
+		/* it cannot be static const struct due to __initdata
+		marker */
+		static struct fb_videomode defaultmode __initdata = {
+			/* 640x480 @ 60Hz, 31.5 kHz */
+			NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
+			0, FB_VMODE_NONINTERLACED
+		};
+#endif /* !MODULE */
+
 static int __init initMatrox2(WPMINFO struct display* d, struct board* b){
 	unsigned long ctrlptr_phys = 0;
 	unsigned long video_base_phys = 0;
@@ -5876,14 +5886,6 @@
 #ifndef MODULE
 	/* mode database is marked __init ... */
 	{
-		/* it cannot be static const struct due to __initdata
-		marker */
-		static struct fb_videomode defaultmode __initdata = {
-			/* 640x480 @ 60Hz, 31.5 kHz */
-			NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
-			0, FB_VMODE_NONINTERLACED
-		};
-
 		fb_find_mode(&vesafb_defined, &ACCESS_FBINFO(fbcon), videomode[0]?videomode:NULL,
 		NULL, 0, &defaultmode, vesafb_defined.bits_per_pixel);
 	}
diff -u --recursive --new-file v2.3.15/linux/drivers/video/newport_con.c linux/drivers/video/newport_con.c
--- v2.3.15/linux/drivers/video/newport_con.c	Fri Jun 25 17:37:52 1999
+++ linux/drivers/video/newport_con.c	Thu Aug 26 14:24:11 1999
@@ -267,7 +267,7 @@
 #ifdef MODULE
 static const char *newport_startup(void)
 #else
-__initfunc(static const char *newport_startup(void))
+static const char * __init newport_startup(void)
 #endif
 {
     struct newport_regs *p;
diff -u --recursive --new-file v2.3.15/linux/drivers/video/p9100.h linux/drivers/video/p9100.h
--- v2.3.15/linux/drivers/video/p9100.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/p9100.h	Tue Aug 31 11:25:33 1999
@@ -0,0 +1,87 @@
+/*
+ * Register information for the Weitek P9100 as found
+ * on the Tadpole Sparcbook 3 laptops.
+ * 
+ * From the technical specification document provided by Tadpole.
+ *
+ * Derrick J Brashear (shadow@dementia.org)
+ */
+
+#ifndef _P9100_H_
+#define _P9100_H_
+
+/* P9100 control registers */
+#define P9100_SYSCTL_OFF 0x0
+#define P9100_VIDEOCTL_OFF 0x100
+#define P9100_VRAMCTL_OFF 0x180
+#define P9100_RAMDAC_OFF 0x200
+#define P9100_VIDEOCOPROC_OFF 0x400
+
+/* P9100 command registers */
+#define P9100_CMD_OFF 0x0
+
+/* P9100 framebuffer memory */
+#define P9100_FB_OFF 0x0
+
+
+/* 3 bits: 2=8bpp 3=16bpp 5=32bpp 7=24bpp */
+#define SYS_CONFIG_PIXELSIZE_SHIFT 26 
+
+#define SCREENPAINT_TIMECTL1_ENABLE_VIDEO 0x20 /* 0 = off, 1 = on */
+
+struct p9100_ctrl {
+  /* Registers for the system control */
+  __volatile__ __u32 sys_base;
+  __volatile__ __u32 sys_config;
+  __volatile__ __u32 sys_intr;
+  __volatile__ __u32 sys_int_ena;
+  __volatile__ __u32 sys_alt_rd;
+  __volatile__ __u32 sys_alt_wr;
+  __volatile__ __u32 sys_xxx[58];
+  /* Registers for the video control */
+  __volatile__ __u32 vid_base;
+  __volatile__ __u32 vid_hcnt;
+  __volatile__ __u32 vid_htotal;
+  __volatile__ __u32 vid_hsync_rise;
+  __volatile__ __u32 vid_hblank_rise;
+  __volatile__ __u32 vid_hblank_fall;
+  __volatile__ __u32 vid_hcnt_preload;
+  __volatile__ __u32 vid_vcnt;
+  __volatile__ __u32 vid_vlen;
+  __volatile__ __u32 vid_vsync_rise;
+  __volatile__ __u32 vid_vblank_rise;
+  __volatile__ __u32 vid_vblank_fall;
+  __volatile__ __u32 vid_vcnt_preload;
+  __volatile__ __u32 vid_screenpaint_addr;
+  __volatile__ __u32 vid_screenpaint_timectl1;
+  __volatile__ __u32 vid_screenpaint_qsfcnt;
+  __volatile__ __u32 vid_screenpaint_timectl2;
+  __volatile__ __u32 vid_xxx[15];
+  /* Registers for the video control */
+  __volatile__ __u32 vram_base;
+  __volatile__ __u32 vram_memcfg;
+  __volatile__ __u32 vram_refresh_pd;
+  __volatile__ __u32 vram_refresh_cnt;
+  __volatile__ __u32 vram_raslo_max;
+  __volatile__ __u32 vram_raslo_cur;
+  __volatile__ __u32 pwrup_cfg;
+  __volatile__ __u32 vram_xxx[25];
+  /* Registers for IBM RGB528 Palette */
+  __volatile__ __u32 ramdac_cmap_wridx; 
+  __volatile__ __u32 ramdac_palette_data;
+  __volatile__ __u32 ramdac_pixel_mask;
+  __volatile__ __u32 ramdac_palette_rdaddr;
+  __volatile__ __u32 ramdac_idx_lo;
+  __volatile__ __u32 ramdac_idx_hi;
+  __volatile__ __u32 ramdac_idx_data;
+  __volatile__ __u32 ramdac_idx_ctl;
+  __volatile__ __u32 ramdac_xxx[1784];
+};
+
+struct p9100_cmd_parameng {
+  __volatile__ __u32 parameng_status;
+  __volatile__ __u32 parameng_bltcmd;
+  __volatile__ __u32 parameng_quadcmd;
+};
+
+#endif /* _P9100_H_ */
diff -u --recursive --new-file v2.3.15/linux/drivers/video/p9100fb.c linux/drivers/video/p9100fb.c
--- v2.3.15/linux/drivers/video/p9100fb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/p9100fb.c	Tue Aug 31 11:25:33 1999
@@ -0,0 +1,192 @@
+/* $id: p9100fb.c,v 1.4 1999/08/18 10:55:01 shadow Exp $
+ * p9100fb.c: P9100 frame buffer driver
+ *
+ * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/selection.h>
+
+#include <video/sbusfb.h>
+#include <asm/io.h>
+
+#include <video/fbcon-cfb8.h>
+
+#include "p9100.h"
+
+static struct sbus_mmap_map p9100_mmap_map[] = {
+#if 0 /* For now, play we're a dumb color fb */
+  { P9100_CTL_OFF, 0x38000000, 0x2000 },
+  { P9100_CMD_OFF, 0x38002000, 0x2000 },
+  { P9100_FB_OFF, 0x38800000, 0x200000 },
+#else
+  { CG3_MMAP_OFFSET, 0x38800000, SBUS_MMAP_FBSIZE(1) },
+#endif
+  { 0, 0, 0 }
+};
+
+#define _READCTL(member, out) \
+{ \
+  struct p9100_ctrl *actual; \
+  actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \
+  out = actual-> ## member ; \
+}
+
+#define READCTL(member, out) \
+{ \
+  struct p9100_ctrl *enab, *actual; \
+  actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \
+  enab = (struct p9100_ctrl *)fb->s.p9100.fbmem; \
+  out = enab-> ## member ; \
+  out = actual-> ## member ; \
+}
+
+#define WRITECTL(member, val) \
+{ \
+  u32 __writetmp; \
+  struct p9100_ctrl *enab, *actual; \
+  actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \
+  enab = (struct p9100_ctrl *)fb->s.p9100.fbmem; \
+  __writetmp = enab-> ## member ; \
+  actual-> ## member = val; \
+}
+
+static void p9100_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
+{
+	int i;
+	u32 tmp;
+
+	_READCTL(pwrup_cfg, tmp);
+	WRITECTL(ramdac_cmap_wridx, (index << 16));
+
+	for (i = index; count--; i++){
+		_READCTL(pwrup_cfg, tmp);
+		WRITECTL(ramdac_palette_data, (fb->color_map CM(i,0) << 16));
+		_READCTL(pwrup_cfg, tmp);
+		WRITECTL(ramdac_palette_data, (fb->color_map CM(i,1) << 16));
+		_READCTL(pwrup_cfg, tmp);
+		WRITECTL(ramdac_palette_data, (fb->color_map CM(i,2) << 16));
+	}
+#if 0
+	printk("updating %d colors starting at %d\n", count, index);
+
+	WRITECTL(ramdac_palette_rdaddr, index);
+	for (i = index; count--; i++){
+		_READCTL(pwrup_cfg, tmp);
+		READCTL(ramdac_palette_data, tmp);
+		printk("%d: red %x ", i, tmp);
+		_READCTL(pwrup_cfg, tmp);
+		READCTL(ramdac_palette_data, tmp);
+		printk("green %x ", tmp);
+		_READCTL(pwrup_cfg, tmp);
+		READCTL(ramdac_palette_data, tmp);
+		printk("blue %x\n", tmp);
+	}
+#endif
+}
+
+static void p9100_blank (struct fb_info_sbusfb *fb)
+{
+  u32 val;
+  READCTL(vid_screenpaint_timectl1, val);
+  val &= ~ SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
+  WRITECTL(vid_screenpaint_timectl1, val);
+}
+
+static void p9100_unblank (struct fb_info_sbusfb *fb)
+{
+  u32 val;
+  READCTL(vid_screenpaint_timectl1, val);
+  val |= SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
+  WRITECTL(vid_screenpaint_timectl1, val);
+}
+
+static void p9100_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
+{
+  p->screen_base += (y_margin - fb->y_margin) * p->line_length + 
+    (x_margin - fb->x_margin);
+}
+
+static char idstring[60] __initdata = { 0 };
+
+char * __init p9100fb_init(struct fb_info_sbusfb *fb)
+{
+	struct fb_fix_screeninfo *fix = &fb->fix;
+	struct display *disp = &fb->disp;
+	struct fbtype *type = &fb->type;
+	unsigned long phys = fb->sbdp->reg_addrs[2].phys_addr;
+	int tmp;
+
+#ifndef FBCON_HAS_CFB8
+	return NULL;
+#endif
+
+	/* Control regs: fb->sbdp->reg_addrs[0].phys_addr 
+	 * Command regs: fb->sbdp->reg_addrs[1].phys_addr 
+	 * Frame buffer: fb->sbdp->reg_addrs[2].phys_addr 
+         */
+
+	if (!fb->s.p9100.ctrl) {
+	  fb->s.p9100.ctrl = (struct p9100_ctrl *)
+	    sparc_alloc_io(fb->sbdp->reg_addrs[0].phys_addr, 0, fb->sbdp->reg_addrs[1].reg_size, "p9100_ctrl", fb->iospace, 0);
+	}
+
+	strcpy(fb->info.modename, "p9100");
+	strcpy(fix->id, "p9100");
+	fix->accel = FB_ACCEL_SUN_CGTHREE;
+	fix->line_length = fb->var.xres_virtual;
+
+	disp->scrollmode = SCROLL_YREDRAW;
+	if (!disp->screen_base)
+		disp->screen_base = 
+		  (char *)sparc_alloc_io(phys, 0, type->fb_size, "p9100_ram", 
+					 fb->iospace, 0);
+	fb->s.p9100.fbmem = disp->screen_base;
+	disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
+
+	READCTL(sys_config, tmp);
+        switch ((tmp >> SYS_CONFIG_PIXELSIZE_SHIFT) & 7) {
+	case 7: 
+	  type->fb_depth = 24; 
+	  break;
+	case 5: 
+	  type->fb_depth = 32;
+	  break;
+	case 3: 
+	  type->fb_depth = 16; 
+	  break;
+	case 2: 
+	  type->fb_depth = 8; 
+	  break;
+	default: 
+	  printk("p9100: screen depth unknown: 0x%x", tmp);
+	  return NULL;
+        }
+
+	fb->dispsw = fbcon_cfb8;
+
+	fb->margins = p9100_margins;
+	fb->loadcmap = p9100_loadcmap;
+	fb->blank = p9100_blank;
+	fb->unblank = p9100_unblank;
+	
+	fb->physbase = phys;
+	fb->mmap_map = p9100_mmap_map;
+	
+	sprintf(idstring, "%s at 0x%x", "p9100", disp->screen_base);
+
+	return idstring;
+}
+
diff -u --recursive --new-file v2.3.15/linux/drivers/video/promcon.c linux/drivers/video/promcon.c
--- v2.3.15/linux/drivers/video/promcon.c	Mon Aug  9 10:25:01 1999
+++ linux/drivers/video/promcon.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: promcon.c,v 1.15 1999/04/22 06:35:32 davem Exp $
+/* $Id: promcon.c,v 1.16 1999/08/10 15:56:22 davem Exp $
  * Console driver utilizing PROM sun terminal emulation
  *
  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
diff -u --recursive --new-file v2.3.15/linux/drivers/video/sbusfb.c linux/drivers/video/sbusfb.c
--- v2.3.15/linux/drivers/video/sbusfb.c	Thu Aug 12 10:22:33 1999
+++ linux/drivers/video/sbusfb.c	Tue Aug 31 11:25:33 1999
@@ -1086,6 +1086,10 @@
 	case FBTYPE_MDICOLOR:
 		p = cgfourteenfb_init(fb); break;
 #endif
+#ifdef CONFIG_FB_P9100
+	case FBTYPE_P9100COLOR:
+		p = p9100fb_init(fb); break;
+#endif
 	}
 	
 	if (!p) {
@@ -1149,6 +1153,8 @@
 		return FBTYPE_SUN2BW;
 	if (!strcmp(name, "tcx"))
 		return FBTYPE_TCXCOLOR;
+	if (!strcmp(name, "p9100"))
+		return FBTYPE_P9100COLOR;
 	return FBTYPE_NOTYPE;
 }
 
@@ -1188,7 +1194,7 @@
 		}
 	}
 #endif
-	if (!SBus_chain) return;
+	if (!SBus_chain) return 0;
 	for_all_sbusdev(sbdp, sbus) {
 		type = known_card(sbdp->prom_name);
 		if (type == FBTYPE_NOTYPE) continue;
diff -u --recursive --new-file v2.3.15/linux/drivers/video/tcxfb.c linux/drivers/video/tcxfb.c
--- v2.3.15/linux/drivers/video/tcxfb.c	Mon Aug  9 10:25:01 1999
+++ linux/drivers/video/tcxfb.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: tcxfb.c,v 1.7 1999/01/26 10:55:03 jj Exp $
+/* $Id: tcxfb.c,v 1.8 1999/08/10 15:56:26 davem Exp $
  * tcxfb.c: TCX 24/8bit frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
diff -u --recursive --new-file v2.3.15/linux/drivers/video/tgafb.c linux/drivers/video/tgafb.c
--- v2.3.15/linux/drivers/video/tgafb.c	Thu Aug 26 13:05:40 1999
+++ linux/drivers/video/tgafb.c	Thu Aug 26 14:24:11 1999
@@ -1027,7 +1027,7 @@
      *  Initialisation
      */
 
-__initfunc(int tgafb_init(void))
+int __init tgafb_init(void)
 {
     struct pci_dev *pdev;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/video/valkyriefb.c linux/drivers/video/valkyriefb.c
--- v2.3.15/linux/drivers/video/valkyriefb.c	Thu Aug 26 13:05:40 1999
+++ linux/drivers/video/valkyriefb.c	Thu Aug 26 12:34:55 1999
@@ -767,7 +767,7 @@
 {
 	memset(fix, 0, sizeof(*fix));
 	strcpy(fix->id, "valkyrie");
-	fix->mmio_start = (char *)p->valkyrie_regs_phys;
+	fix->mmio_start = p->valkyrie_regs_phys;
 	fix->mmio_len = sizeof(struct valkyrie_regs);
 	fix->type = FB_TYPE_PACKED_PIXELS;
 	
diff -u --recursive --new-file v2.3.15/linux/drivers/zorro/proc.c linux/drivers/zorro/proc.c
--- v2.3.15/linux/drivers/zorro/proc.c	Sun Jun 27 10:10:41 1999
+++ linux/drivers/zorro/proc.c	Thu Aug 26 12:42:33 1999
@@ -143,7 +143,7 @@
 
 static struct proc_dir_entry *proc_bus_zorro_dir;
 
-__initfunc(static int zorro_proc_attach_device(u_int slot))
+static int __init zorro_proc_attach_device(u_int slot)
 {
 	struct proc_dir_entry *entry;
 	char name[4];
@@ -158,7 +158,7 @@
 	return 0;
 }
 
-__initfunc(void zorro_proc_init(void))
+void __init zorro_proc_init(void)
 {
 	u_int slot;
 
diff -u --recursive --new-file v2.3.15/linux/drivers/zorro/zorro.c linux/drivers/zorro/zorro.c
--- v2.3.15/linux/drivers/zorro/zorro.c	Mon Oct  5 13:48:05 1998
+++ linux/drivers/zorro/zorro.c	Thu Aug 26 12:42:33 1999
@@ -153,7 +153,7 @@
 u32 zorro_unused_z2ram[4] = { 0, 0, 0, 0 };
 
 
-__initfunc(static void mark_region(u32 addr, u_int size, int flag))
+static void __init mark_region(u32 addr, u_int size, int flag)
 {
     u32 start, end;
 
@@ -183,7 +183,7 @@
      *  Initialization
      */
 
-__initfunc(void zorro_init(void))
+void __init zorro_init(void)
 {
     u_int i;
 
diff -u --recursive --new-file v2.3.15/linux/fs/adfs/super.c linux/fs/adfs/super.c
--- v2.3.15/linux/fs/adfs/super.c	Tue Jun  8 10:47:58 1999
+++ linux/fs/adfs/super.c	Thu Aug 26 14:18:06 1999
@@ -385,7 +385,7 @@
 	"adfs", FS_REQUIRES_DEV, adfs_read_super, NULL
 };
 
-__initfunc(int init_adfs_fs(void))
+int __init init_adfs_fs(void)
 {
 	return register_filesystem(&adfs_fs_type);
 }
diff -u --recursive --new-file v2.3.15/linux/fs/affs/super.c linux/fs/affs/super.c
--- v2.3.15/linux/fs/affs/super.c	Tue Jun  8 10:47:58 1999
+++ linux/fs/affs/super.c	Thu Aug 26 14:18:06 1999
@@ -688,7 +688,7 @@
 	NULL
 };
 
-__initfunc(int init_affs_fs(void))
+int __init init_affs_fs(void)
 {
 	return register_filesystem(&affs_fs_type);
 }
diff -u --recursive --new-file v2.3.15/linux/fs/autofs/init.c linux/fs/autofs/init.c
--- v2.3.15/linux/fs/autofs/init.c	Tue Oct 27 14:13:53 1998
+++ linux/fs/autofs/init.c	Thu Aug 26 14:18:06 1999
@@ -34,7 +34,7 @@
 
 #else /* MODULE */
 
-__initfunc(int init_autofs_fs(void))
+int __init init_autofs_fs(void)
 {
 	return register_filesystem(&autofs_fs_type);
 }
diff -u --recursive --new-file v2.3.15/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- v2.3.15/linux/fs/binfmt_aout.c	Tue Aug  3 10:18:39 1999
+++ linux/fs/binfmt_aout.c	Tue Aug 31 11:25:33 1999
@@ -315,7 +315,7 @@
 	current->personality = PER_LINUX;
 
 #if defined(__sparc__) && !defined(__sparc_v9__)
-	memcpy(&current->tss.core_exec, &ex, sizeof(struct exec));
+	memcpy(&current->thread.core_exec, &ex, sizeof(struct exec));
 #endif
 
 	current->mm->end_code = ex.a_text +
diff -u --recursive --new-file v2.3.15/linux/fs/buffer.c linux/fs/buffer.c
--- v2.3.15/linux/fs/buffer.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/buffer.c	Tue Aug 31 11:30:48 1999
@@ -146,8 +146,8 @@
 	atomic_inc(&bh->b_count);
 	add_wait_queue(&bh->b_wait, &wait);
 repeat:
-	tsk->state = TASK_UNINTERRUPTIBLE;
 	run_task_queue(&tq_disk);
+	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 	if (buffer_locked(bh)) {
 		schedule();
 		goto repeat;
@@ -698,7 +698,6 @@
 	unsigned long flags;
 	struct buffer_head *tmp;
 	struct page *page;
-	int free;
 
 	mark_buffer_uptodate(bh, uptodate);
 
@@ -718,7 +717,7 @@
 	 * deemed complete once all buffers have been visited
 	 * (b_count==0) and are now unlocked. We must make sure that
 	 * only the _last_ buffer that decrements its count is the one
-	 * that free's the page..
+	 * that unlock the page..
 	 */
 	spin_lock_irqsave(&page_uptodate_lock, flags);
 	unlock_buffer(bh);
@@ -743,26 +742,15 @@
 
 	/*
 	 * Run the hooks that have to be done when a page I/O has completed.
-	 *
-	 * Note - we need to test the flags before we unlock the page, but
-	 * we must not actually free the page until after the unlock!
 	 */
 	if (test_and_clear_bit(PG_decr_after, &page->flags))
 		atomic_dec(&nr_async_pages);
 
-	if (test_and_clear_bit(PG_free_swap_after, &page->flags))
-		swap_free(page->offset);
-
-	free = test_and_clear_bit(PG_free_after, &page->flags);
-
 	if (page->owner != (void *)-1)
 		PAGE_BUG(page);
 	page->owner = current;
 	UnlockPage(page);
 
-	if (free)
-		__free_page(page);
-
 	return;
 
 still_busy:
@@ -1100,7 +1088,6 @@
  */
 static struct buffer_head * create_buffers(unsigned long page, unsigned long size, int async)
 {
-	DECLARE_WAITQUEUE(wait, current);
 	struct buffer_head *bh, *head;
 	long offset;
 
@@ -1165,14 +1152,7 @@
 	 * Set our state for sleeping, then check again for buffer heads.
 	 * This ensures we won't miss a wake_up from an interrupt.
 	 */
-	add_wait_queue(&buffer_wait, &wait);
-	current->state = TASK_UNINTERRUPTIBLE;
-	if (nr_unused_buffer_heads < MAX_BUF_PER_PAGE) {
-		current->policy |= SCHED_YIELD;
-		schedule();
-	}
-	remove_wait_queue(&buffer_wait, &wait);
-	current->state = TASK_RUNNING;
+	wait_event(buffer_wait, nr_unused_buffer_heads >= MAX_BUF_PER_PAGE);
 	goto try_again;
 }
 
@@ -1238,7 +1218,7 @@
 	if (!PageLocked(page))
 		BUG();
 	if (!page->buffers)
-		return 0;
+		return 1;
 
 	head = page->buffers;
 	bh = head;
@@ -1279,10 +1259,13 @@
 	 */
 	if (!offset) {
 		if (!try_to_free_buffers(page))
+		{
 			atomic_add(PAGE_CACHE_SIZE, &buffermem);
+			return 0;
+		}
 	}
 
-	return 0;
+	return 1;
 }
 
 static void create_empty_buffers(struct page *page, struct inode *inode, unsigned long blocksize)
@@ -1822,6 +1805,10 @@
 		for (pageind = 0; pageind < iobuf->nr_pages; pageind++) {
 			page = iobuf->pagelist[pageind];
 			map  = iobuf->maplist[pageind];
+			if (map && PageBIGMEM(map)) {
+				err = -EIO;
+				goto error;
+			}
 
 			while (length > 0) {
 				blocknr = b[bufind++];
@@ -2060,6 +2047,7 @@
 static int grow_buffers(int size)
 {
 	unsigned long page;
+	struct page * page_map;
 	struct buffer_head *bh, *tmp;
 	struct buffer_head * insert_point;
 	int isize;
@@ -2100,7 +2088,9 @@
 	free_list[isize].list = bh;
 	spin_unlock(&free_list[isize].lock);
 
-	mem_map[MAP_NR(page)].buffers = bh;
+	page_map = mem_map + MAP_NR(page);
+	page_map->buffers = bh;
+	lru_cache_add(page_map);
 	atomic_add(PAGE_SIZE, &buffermem);
 	return 1;
 
diff -u --recursive --new-file v2.3.15/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.3.15/linux/fs/coda/psdev.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/coda/psdev.c	Thu Aug 26 14:18:06 1999
@@ -334,7 +334,7 @@
 
 
 
-__initfunc(int init_coda(void)) 
+int __init init_coda(void)
 {
 	int status;
 	printk(KERN_INFO "Coda Kernel/Venus communications, v4.6.0, braam@cs.cmu.edu\n");
diff -u --recursive --new-file v2.3.15/linux/fs/coda/upcall.c linux/fs/coda/upcall.c
--- v2.3.15/linux/fs/coda/upcall.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/coda/upcall.c	Tue Aug 31 11:30:48 1999
@@ -625,9 +625,9 @@
 	add_wait_queue(&vmp->uc_sleep, &wait);
 	for (;;) {
 		if ( coda_hard == 0 ) 
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 		else
-			current->state = TASK_UNINTERRUPTIBLE;
+			set_current_state(TASK_UNINTERRUPTIBLE);
 
 		/* got a reply */
 		if ( vmp->uc_flags & REQ_WRITE )
diff -u --recursive --new-file v2.3.15/linux/fs/dcache.c linux/fs/dcache.c
--- v2.3.15/linux/fs/dcache.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/dcache.c	Mon Aug 30 13:47:18 1999
@@ -20,6 +20,7 @@
 #include <linux/malloc.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 
@@ -473,9 +474,11 @@
 {
 	if (gfp_mask & __GFP_IO) {
 		int count = 0;
+		lock_kernel();
 		if (priority)
 			count = dentry_stat.nr_unused / priority;
 		prune_dcache(count);
+		unlock_kernel();
 	}
 }
 
diff -u --recursive --new-file v2.3.15/linux/fs/devpts/inode.c linux/fs/devpts/inode.c
--- v2.3.15/linux/fs/devpts/inode.c	Tue Jun  8 10:47:58 1999
+++ linux/fs/devpts/inode.c	Thu Aug 26 14:18:06 1999
@@ -348,7 +348,7 @@
 	}
 }
 
-__initfunc(int init_devpts_fs(void))
+int __init init_devpts_fs(void)
 {
 	return register_filesystem(&devpts_fs_type);
 
diff -u --recursive --new-file v2.3.15/linux/fs/devpts/root.c linux/fs/devpts/root.c
--- v2.3.15/linux/fs/devpts/root.c	Sun Jun 27 10:10:41 1999
+++ linux/fs/devpts/root.c	Fri Aug 27 12:02:04 1999
@@ -152,10 +152,9 @@
 			unsigned int nentry = *p++ - '0';
 			if ( nentry > 9 )
 				return NULL;
-			nentry += entry * 10;
-			if (nentry < entry)
+			if ( entry >= ~0U/10 )
 				return NULL;
-			entry = nentry;
+			entry = nentry + entry * 10;
 		}
 	}
 
diff -u --recursive --new-file v2.3.15/linux/fs/dquot.c linux/fs/dquot.c
--- v2.3.15/linux/fs/dquot.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/dquot.c	Tue Aug 31 11:30:48 1999
@@ -199,7 +199,7 @@
 
 	add_wait_queue(&dquot->dq_wait, &wait);
 repeat:
-	current->state = TASK_UNINTERRUPTIBLE;
+	set_current_state(TASK_UNINTERRUPTIBLE);
 	if (dquot->dq_flags & DQ_LOCKED) {
 		schedule();
 		goto repeat;
diff -u --recursive --new-file v2.3.15/linux/fs/efs/super.c linux/fs/efs/super.c
--- v2.3.15/linux/fs/efs/super.c	Tue Jun  8 10:47:58 1999
+++ linux/fs/efs/super.c	Thu Aug 26 14:18:06 1999
@@ -32,7 +32,7 @@
 	NULL		/* remount */
 };
 
-__initfunc(int init_efs_fs(void)) {
+int __init init_efs_fs(void) {
 	return register_filesystem(&efs_fs_type);
 }
 
diff -u --recursive --new-file v2.3.15/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.3.15/linux/fs/ext2/super.c	Tue Jun  8 10:47:58 1999
+++ linux/fs/ext2/super.c	Thu Aug 26 14:18:06 1999
@@ -739,7 +739,7 @@
 	NULL
 };
 
-__initfunc(int init_ext2_fs(void))
+int __init init_ext2_fs(void)
 {
         return register_filesystem(&ext2_fs_type);
 }
diff -u --recursive --new-file v2.3.15/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.3.15/linux/fs/fat/inode.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/fat/inode.c	Mon Aug 30 10:23:14 1999
@@ -622,7 +622,7 @@
 	sb->s_magic = MSDOS_SUPER_MAGIC;
 	/* set up enough so that it can read an inode */
 	init_waitqueue_head(&MSDOS_SB(sb)->fat_wait);
-	MSDOS_SB(sb)->fat_lock = 0;
+	init_MUTEX(&MSDOS_SB(sb)->fat_lock);
 	MSDOS_SB(sb)->prev_free = 0;
 
 	cp = opts.codepage ? opts.codepage : 437;
diff -u --recursive --new-file v2.3.15/linux/fs/fat/misc.c linux/fs/fat/misc.c
--- v2.3.15/linux/fs/fat/misc.c	Mon Aug  9 11:43:49 1999
+++ linux/fs/fat/misc.c	Mon Aug 30 10:23:14 1999
@@ -79,35 +79,29 @@
 /* File creation lock. This is system-wide to avoid deadlocks in rename. */
 /* (rename might deadlock before detecting cross-FS moves.) */
 
-static DECLARE_WAIT_QUEUE_HEAD(creation_wait);
-static int creation_lock = 0;
-
+static DECLARE_MUTEX(creation_lock);
 
 void fat_lock_creation(void)
 {
-	while (creation_lock) sleep_on(&creation_wait);
-	creation_lock = 1;
+	down(&creation_lock);
 }
 
 
 void fat_unlock_creation(void)
 {
-	creation_lock = 0;
-	wake_up(&creation_wait);
+	up(&creation_lock);
 }
 
 
 void lock_fat(struct super_block *sb)
 {
-	while (MSDOS_SB(sb)->fat_lock) sleep_on(&MSDOS_SB(sb)->fat_wait);
-	MSDOS_SB(sb)->fat_lock = 1;
+	down(&(MSDOS_SB(sb)->fat_lock));
 }
 
 
 void unlock_fat(struct super_block *sb)
 {
-	MSDOS_SB(sb)->fat_lock = 0;
-	wake_up(&MSDOS_SB(sb)->fat_wait);
+	up(&(MSDOS_SB(sb)->fat_lock));
 }
 
 /* Flushes the number of free clusters on FAT32 */
diff -u --recursive --new-file v2.3.15/linux/fs/fcntl.c linux/fs/fcntl.c
--- v2.3.15/linux/fs/fcntl.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/fcntl.c	Fri Aug 27 12:03:01 1999
@@ -234,7 +234,8 @@
 			err = filp->f_owner.signum;
 			break;
 		case F_SETSIG:
-			if (arg <= 0 || arg > _NSIG) {
+			/* arg == 0 restores default behaviour. */
+			if (arg < 0 || arg > _NSIG) {
 				err = -EINVAL;
 				break;
 			}
diff -u --recursive --new-file v2.3.15/linux/fs/hfs/super.c linux/fs/hfs/super.c
--- v2.3.15/linux/fs/hfs/super.c	Tue Jun  8 10:47:58 1999
+++ linux/fs/hfs/super.c	Thu Aug 26 14:18:06 1999
@@ -493,7 +493,7 @@
 	return NULL;	
 }
 
-__initfunc(int init_hfs_fs(void))
+int __init init_hfs_fs(void)
 {
         hfs_cat_init();
 	return register_filesystem(&hfs_fs);
diff -u --recursive --new-file v2.3.15/linux/fs/inode.c linux/fs/inode.c
--- v2.3.15/linux/fs/inode.c	Mon Jul  5 20:34:31 1999
+++ linux/fs/inode.c	Tue Aug 31 11:30:48 1999
@@ -103,7 +103,7 @@
 
 	add_wait_queue(&inode->i_wait, &wait);
 repeat:
-	current->state = TASK_UNINTERRUPTIBLE;
+	set_current_state(TASK_UNINTERRUPTIBLE);
 	if (inode->i_state & I_LOCK) {
 		schedule();
 		goto repeat;
diff -u --recursive --new-file v2.3.15/linux/fs/iobuf.c linux/fs/iobuf.c
--- v2.3.15/linux/fs/iobuf.c	Mon Jul 26 22:50:35 1999
+++ linux/fs/iobuf.c	Tue Aug 31 11:30:48 1999
@@ -122,8 +122,8 @@
 
 	add_wait_queue(&kiobuf->wait_queue, &wait);
 repeat:
-	tsk->state = TASK_UNINTERRUPTIBLE;
 	run_task_queue(&tq_disk);
+	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 	if (atomic_read(&kiobuf->io_count) != 0) {
 		schedule();
 		goto repeat;
diff -u --recursive --new-file v2.3.15/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.3.15/linux/fs/isofs/inode.c	Sun Jun 27 10:10:41 1999
+++ linux/fs/isofs/inode.c	Thu Aug 26 14:18:06 1999
@@ -1469,7 +1469,7 @@
 	NULL
 };
 
-__initfunc(int init_iso9660_fs(void))
+int __init init_iso9660_fs(void)
 {
         return register_filesystem(&iso9660_fs_type);
 }
diff -u --recursive --new-file v2.3.15/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.3.15/linux/fs/minix/inode.c	Sun Jun 27 10:10:41 1999
+++ linux/fs/minix/inode.c	Tue Aug 31 11:23:03 1999
@@ -518,7 +518,7 @@
 		}
 	}
 
-	tmp = minix_new_block(inode->i_sb);
+	tmp = minix_new_block(inode);
 	if (!tmp) {
 		*err = -ENOSPC;
 		return NULL;
@@ -526,7 +526,7 @@
 	if (metadata) {
 		result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
 		if (*p) {
-			minix_free_block(inode->i_sb, tmp);
+			minix_free_block(inode, tmp);
 			brelse(result);
 			goto repeat;
 		}
@@ -540,7 +540,7 @@
 			 * state from under us:
 			 */
 			BUG();
-			minix_free_block(inode->i_sb, tmp);
+			minix_free_block(inode, tmp);
 			goto repeat;
 		}
 		*phys = tmp;
@@ -599,13 +599,13 @@
 		}
 	}
 
-	tmp = minix_new_block(inode->i_sb);
+	tmp = minix_new_block(inode);
 	if (!tmp)
 		goto out;
 	if (metadata) {
 		result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
 		if (*p) {
-			minix_free_block(inode->i_sb, tmp);
+			minix_free_block(inode, tmp);
 			brelse(result);
 			goto repeat;
 		}
@@ -617,7 +617,7 @@
 		*new = 1;
 	}
 	if (*p) {
-		minix_free_block(inode->i_sb, tmp);
+		minix_free_block(inode, tmp);
 		brelse(result);
 		goto repeat;
 	}
@@ -754,7 +754,7 @@
 		}
 	}
 
-	tmp = minix_new_block(inode->i_sb);
+	tmp = minix_new_block(inode);
 	if (!tmp) {
 		*err = -ENOSPC;
 		return NULL;
@@ -762,7 +762,7 @@
 	if (metadata) {
 		result = getblk(inode->i_dev, tmp, BLOCK_SIZE);
 		if (*p) {
-			minix_free_block(inode->i_sb, tmp);
+			minix_free_block(inode, tmp);
 			brelse(result);
 			goto repeat;
 		}
@@ -776,7 +776,7 @@
 			 * state from under us:
 			 */
 			BUG();
-			minix_free_block(inode->i_sb, tmp);
+			minix_free_block(inode, tmp);
 			goto repeat;
 		}
 		*phys = tmp;
@@ -835,13 +835,13 @@
 		}
 	}
 
-	tmp = minix_new_block(inode->i_sb);
+	tmp = minix_new_block(inode);
 	if (!tmp)
 		goto out;
 	if (metadata) {
 		result = getblk(bh->b_dev, tmp, BLOCK_SIZE);
 		if (*p) {
-			minix_free_block(inode->i_sb, tmp);
+			minix_free_block(inode, tmp);
 			brelse(result);
 			goto repeat;
 		}
@@ -853,7 +853,7 @@
 		*new = 1;
 	}
 	if (*p) {
-		minix_free_block(inode->i_sb, tmp);
+		minix_free_block(inode, tmp);
 		brelse(result);
 		goto repeat;
 	}
@@ -1238,7 +1238,7 @@
 	NULL
 };
 
-__initfunc(int init_minix_fs(void))
+int __init init_minix_fs(void)
 {
         return register_filesystem(&minix_fs_type);
 }
diff -u --recursive --new-file v2.3.15/linux/fs/msdos/msdosfs_syms.c linux/fs/msdos/msdosfs_syms.c
--- v2.3.15/linux/fs/msdos/msdosfs_syms.c	Thu May 13 23:18:20 1999
+++ linux/fs/msdos/msdosfs_syms.c	Thu Aug 26 14:18:06 1999
@@ -34,7 +34,7 @@
 	NULL
 };
 
-__initfunc(int init_msdos_fs(void))
+int __init init_msdos_fs(void)
 {
 	return register_filesystem(&msdos_fs_type);
 }
diff -u --recursive --new-file v2.3.15/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v2.3.15/linux/fs/msdos/namei.c	Wed Aug 18 10:03:52 1999
+++ linux/fs/msdos/namei.c	Tue Aug 31 11:23:03 1999
@@ -361,8 +361,6 @@
 	struct inode *inode;
 	int res,is_hid;
 	char msdos_name[MSDOS_NAME];
-	struct buffer_head *bh1;
-	struct msdos_dir_entry *de1;
 	int ino;
 
 	res = msdos_format_name(dentry->d_name.name,dentry->d_name.len,
diff -u --recursive --new-file v2.3.15/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.3.15/linux/fs/ncpfs/inode.c	Sat Aug  7 12:59:40 1999
+++ linux/fs/ncpfs/inode.c	Thu Aug 26 14:18:06 1999
@@ -720,7 +720,7 @@
 	NULL
 };
 
-__initfunc(int init_ncp_fs(void))
+int __init init_ncp_fs(void)
 {
 	return register_filesystem(&ncp_fs_type);
 }
diff -u --recursive --new-file v2.3.15/linux/fs/ncpfs/sock.c linux/fs/ncpfs/sock.c
--- v2.3.15/linux/fs/ncpfs/sock.c	Fri May 14 12:43:00 1999
+++ linux/fs/ncpfs/sock.c	Tue Aug 31 11:30:48 1999
@@ -172,7 +172,10 @@
 	      re_select:
 		wait_table.nr = 0;
 		wait_table.entry = &entry;
-		current->state = TASK_INTERRUPTIBLE;
+		/* mb() is not necessary because ->poll() will serialize
+		   instructions adding the wait_table waitqueues in the
+		   waitqueue-head before going to calculate the mask-retval. */
+		__set_current_state(TASK_INTERRUPTIBLE);
 		if (!(file->f_op->poll(file, &wait_table) & POLLIN)) {
 			int timed_out;
 			if (timeout > max_timeout) {
diff -u --recursive --new-file v2.3.15/linux/fs/nfs/nfsroot.c linux/fs/nfs/nfsroot.c
--- v2.3.15/linux/fs/nfs/nfsroot.c	Thu Apr 23 18:12:21 1998
+++ linux/fs/nfs/nfsroot.c	Tue Aug 31 11:23:03 1999
@@ -154,7 +154,7 @@
  *  need to have root_server_addr set _before_ IPConfig gets called as it
  *  can override it.
  */
-__initfunc(static void root_nfs_parse_addr(char *name))
+static void __init root_nfs_parse_addr(char *name)
 {
 	int octets = 0;
 	char *cp, *cq;
@@ -183,7 +183,7 @@
 /*
  *  Parse option string.
  */
-__initfunc(static void root_nfs_parse(char *name, char *buf))
+static void __init root_nfs_parse(char *name, char *buf)
 {
 	char *options, *val, *cp;
 
@@ -220,7 +220,7 @@
 /*
  *  Prepare the NFS data structure and parse all options.
  */
-__initfunc(static int root_nfs_name(char *name))
+static int __init root_nfs_name(char *name)
 {
 	char buf[NFS_MAXPATHLEN];
 	char *cp;
@@ -261,7 +261,7 @@
 /*
  *  Get NFS server address.
  */
-__initfunc(static int root_nfs_addr(void))
+static int __init root_nfs_addr(void)
 {
 	if ((servaddr = root_server_addr) == INADDR_NONE) {
 		printk(KERN_ERR "Root-NFS: No NFS server available, giving up.\n");
@@ -277,7 +277,7 @@
  *  Tell the user what's going on.
  */
 #ifdef NFSROOT_DEBUG
-__initfunc(static void root_nfs_print(void))
+static void __init root_nfs_print(void)
 {
 	printk(KERN_NOTICE "Root-NFS: Mounting %s on server %s as root\n",
 		nfs_path, nfs_data.hostname);
@@ -292,7 +292,7 @@
 #endif
 
 
-__initfunc(int root_nfs_init(void))
+int __init root_nfs_init(void)
 {
 #ifdef NFSROOT_DEBUG
 	nfs_debug |= NFSDBG_ROOT;
@@ -320,7 +320,7 @@
  *  Parse NFS server and directory information passed on the kernel
  *  command line.
  */
-__initfunc(void nfs_root_setup(char *line, int *ints))
+void __init nfs_root_setup(char *line, int *ints)
 {
 	ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255);
 	if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
@@ -356,7 +356,7 @@
 /*
  *  Query server portmapper for the port of a daemon program.
  */
-__initfunc(static int root_nfs_getport(int program, int version))
+static int __init root_nfs_getport(int program, int version)
 {
 	struct sockaddr_in sin;
 
@@ -372,7 +372,7 @@
  *  by the user. Use defaults if portmapper is not available.
  *  XXX: Is there any nfs server with no portmapper?
  */
-__initfunc(static int root_nfs_ports(void))
+static int __init root_nfs_ports(void)
 {
 	int port;
 
@@ -403,7 +403,7 @@
  *  Get a file handle from the server for the directory which is to be
  *  mounted.
  */
-__initfunc(static int root_nfs_get_handle(void))
+static int __init root_nfs_get_handle(void)
 {
 	struct sockaddr_in sin;
 	int status;
@@ -421,7 +421,7 @@
 /*
  *  Now actually mount the given directory.
  */
-__initfunc(static int root_nfs_do_mount(struct super_block *sb))
+static int __init root_nfs_do_mount(struct super_block *sb)
 {
 	/* Pass the server address to NFS */
 	set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, nfs_port);
@@ -437,7 +437,7 @@
  *  Get the NFS port numbers and file handle, and then read the super-
  *  block for mounting.
  */
-__initfunc(int nfs_root_mount(struct super_block *sb))
+int __init nfs_root_mount(struct super_block *sb)
 {
 	if (root_nfs_init() < 0
 	 || root_nfs_ports() < 0
diff -u --recursive --new-file v2.3.15/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.3.15/linux/fs/nfs/write.c	Sat Jul  3 10:44:05 1999
+++ linux/fs/nfs/write.c	Tue Aug 31 11:30:48 1999
@@ -392,7 +392,7 @@
 	rpc_clnt_sigmask(clnt, &oldmask);
 	add_wait_queue(&req->wb_wait, &wait);
 	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		retval = 0;
 		if (req->wb_flags & NFS_WRITE_COMPLETE)
 			break;
diff -u --recursive --new-file v2.3.15/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- v2.3.15/linux/fs/ntfs/fs.c	Sun Jun 27 10:10:41 1999
+++ linux/fs/ntfs/fs.c	Thu Aug 26 14:18:06 1999
@@ -1028,10 +1028,10 @@
 /* When this code is not compiled as a module, this is the main entry point,
  * called by do_sys_setup() in fs/filesystems.c
  *
- * NOTE : __initfunc() is a macro used to remove this function from memory
+ * NOTE : __init is a macro used to remove this function from memory
  * once initialization is done
  */
-__initfunc(int init_ntfs_fs(void))
+int __init init_ntfs_fs(void)
 {
 	/* Comment this if you trust klogd. There are reasons not to trust it
 	 */
diff -u --recursive --new-file v2.3.15/linux/fs/partitions/Config.in linux/fs/partitions/Config.in
--- v2.3.15/linux/fs/partitions/Config.in	Sun Aug 15 11:44:29 1999
+++ linux/fs/partitions/Config.in	Mon Aug 30 18:14:55 1999
@@ -2,47 +2,37 @@
 # Partition configuration
 #
 bool 'Advanced partition selection' CONFIG_PARTITION_ADVANCED
-if [ "$CONFIG_PARTITION_ADVANCED" = "n" ]; then
-  define_bool CONFIG_MSDOS_PARTITION y
+if [ "$CONFIG_PARTITION_ADVANCED" = "y" ]; then
+  bool 'Alpha OSF partition support' CONFIG_OSF_PARTITION
+  bool 'Macintosh partition map support' CONFIG_MAC_PARTITION
+  bool 'PC BIOS (MSDOS partition tables) support' CONFIG_MSDOS_PARTITION
+else
   if [ "$ARCH" = "alpha" ]; then
     define_bool CONFIG_OSF_PARTITION y
   fi
-  if [ "$CONFIG_AMIGA" = "y" ]; then
-    define_bool CONFIG_AMIGA_PARTITION y
-  fi
-  if [ "$CONFIG_ARM" = "y" ]; then
-    if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
-      define_bool CONFIG_ACORN_PARTITION y
-      define_bool CONFIG_ACORN_PARTITION_ADFS y
-#      define_bool CONFIG_ACORN_PARTITION_CUMANA y
-      define_bool CONFIG_ACORN_PARTITION_ICS y
-      define_bool CONFIG_ACORN_PARTITION_POWERTEC y
-      define_bool CONFIG_ACORN_PARTITION_RISCIX y
-    fi
-  fi
-  if [ "$CONFIG_ATARI" = "y" ]; then
-    define_bool CONFIG_ATARI_PARTITION y
-  fi
-  bool 'SMD disklabel (Sun partition tables) support' CONFIG_SMD_DISKLABEL
-  if [ "$ARCH" = "sparc" -o "$CONFIG_SMD_DISKLABEL" = "y" ]; then
-    define_bool CONFIG_SUN_PARTITION y
-  fi
-  bool 'SGI disklabel support' CONFIG_SGI_DISKLABEL
-  if [ "$CONFIG_SGI" = "y" -o "$CONFIG_SGI_DISKLABEL" = "y" ]; then
-    define_bool CONFIG_SGI_PARTITION y
+  if [ "$ARCH" = "ppc" -o "$CONFIG_MAC" = "y" ]; then
+    define_bool CONFIG_MAC_PARTITION y
   fi
-else
-  bool 'Alpha OSF partition support' CONFIG_OSF_PARTITION
-  bool 'Macintosh partition map support' CONFIG_MAC_PARTITION
-  bool 'PC BIOS (MSDOS partition tables) support' CONFIG_MSDOS_PARTITION
+  define_bool CONFIG_MSDOS_PARTITION y
+fi
+if [ "$CONFIG_MSDOS_PARTITION" = "y" ]; then
+  bool '  BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
+  bool '  Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
+  bool '  Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
+fi
+if [ "$CONFIG_SGI" != "y" ]; then
   bool 'SGI partition support' CONFIG_SGI_PARTITION
-  bool 'BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
-  bool 'SMD disklabel (Sun partition tables) support' CONFIG_SMD_DISKLABEL
-  bool 'Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
-  bool 'SGI disklabel support' CONFIG_SGI_DISKLABEL
-
-  bool 'SPARC partition support' CONFIG_SUN_PARTITION
+else
+  define_bool CONFIG_SGI_PARTITION y
+fi
+if [ "$ARCH" != "sparc" -a "$ARCH" != "sparc64" ]; then
+  bool 'Sun partition tables support' CONFIG_SUN_PARTITION
+else
+  define_bool CONFIG_SUN_PARTITION y
+fi
+if [ "$CONFIG_PARTITION_ADVANCED" = "y" ]; then
   bool 'Amiga partition table support' CONFIG_AMIGA_PARTITION
+  bool 'Atari partition table support' CONFIG_ATARI_PARTITION
   bool 'Acorn partition support' CONFIG_ACORN_PARTITION
   if [ "$CONFIG_ACORN_PARTITION" != "n" ]; then
     bool '  Native filecore partition support' CONFIG_ACORN_PARTITION_ADFS
@@ -51,4 +41,19 @@
     bool '  PowerTec partition support' CONFIG_ACORN_PARTITION_POWERTEC
     bool '  RISCiX partition support' CONFIG_ACORN_PARTITION_RISCIX
   fi
+else
+  if [ "$CONFIG_AMIGA" = "y" ]; then
+    define_bool CONFIG_AMIGA_PARTITION y
+  fi
+  if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
+    define_bool CONFIG_ACORN_PARTITION y
+    define_bool CONFIG_ACORN_PARTITION_ADFS y
+#    define_bool CONFIG_ACORN_PARTITION_CUMANA y
+    define_bool CONFIG_ACORN_PARTITION_ICS y
+    define_bool CONFIG_ACORN_PARTITION_POWERTEC y
+    define_bool CONFIG_ACORN_PARTITION_RISCIX y
+  fi
+fi
+if [ "$CONFIG_ATARI" = "y" ]; then
+  define_bool CONFIG_ATARI_PARTITION y
 fi
diff -u --recursive --new-file v2.3.15/linux/fs/partitions/check.c linux/fs/partitions/check.c
--- v2.3.15/linux/fs/partitions/check.c	Wed Aug 18 09:38:29 1999
+++ linux/fs/partitions/check.c	Mon Aug 30 10:24:14 1999
@@ -130,6 +130,16 @@
  			sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part);
  		return buf;
  	}
+	if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
+		int ctlr = hd->major - DAC960_MAJOR;
+ 		int disk = minor >> hd->minor_shift;
+ 		int part = minor & (( 1 << hd->minor_shift) - 1);
+ 		if (part == 0)
+ 			sprintf(buf, "%s/c%dd%d", maj, ctlr, disk);
+ 		else
+ 			sprintf(buf, "%s/c%dd%dp%d", maj, ctlr, disk, part);
+ 		return buf;
+ 	}
 	if (part)
 		sprintf(buf, "%s%c%d", maj, unit, part);
 	else
diff -u --recursive --new-file v2.3.15/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.3.15/linux/fs/proc/array.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/proc/array.c	Tue Aug 31 11:35:59 1999
@@ -44,6 +44,8 @@
  *
  * Al Viro           :  safe handling of mm_struct
  *
+ * Gerhard Wichert   :  added BIGMEM support
+ * Siemens AG           <Gerhard.Wichert@pdb.siemens.de>
  */
 
 #include <linux/types.h>
@@ -247,9 +249,8 @@
 	int i, len;
 	unsigned sum = 0;
 	extern unsigned long total_forks;
-	unsigned long ticks;
+	unsigned long jif = jiffies;
 
-	ticks = jiffies * smp_num_cpus;
 	for (i = 0 ; i < NR_IRQS ; i++)
 		sum += kstat_irqs(i);
 
@@ -259,14 +260,14 @@
 		kstat.cpu_user,
 		kstat.cpu_nice,
 		kstat.cpu_system,
-		jiffies*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system));
+		jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system));
 	for (i = 0 ; i < smp_num_cpus; i++)
 		len += sprintf(buffer + len, "cpu%d %u %u %u %lu\n",
 			i,
 			kstat.per_cpu_user[cpu_logical_map(i)],
 			kstat.per_cpu_nice[cpu_logical_map(i)],
 			kstat.per_cpu_system[cpu_logical_map(i)],
-			jiffies - (  kstat.per_cpu_user[cpu_logical_map(i)] \
+			jif - (  kstat.per_cpu_user[cpu_logical_map(i)] \
 			           + kstat.per_cpu_nice[cpu_logical_map(i)] \
 			           + kstat.per_cpu_system[cpu_logical_map(i)]));
 	len += sprintf(buffer + len,
@@ -292,7 +293,7 @@
 		kstat.cpu_user,
 		kstat.cpu_nice,
 		kstat.cpu_system,
-		ticks - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
+		jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
 #endif
 		kstat.dk_drive[0], kstat.dk_drive[1],
 		kstat.dk_drive[2], kstat.dk_drive[3],
@@ -316,7 +317,7 @@
 		"btime %lu\n"
 		"processes %lu\n",
 		kstat.context_swtch,
-		xtime.tv_sec - jiffies / HZ,
+		xtime.tv_sec - jif / HZ,
 		total_forks);
 	return len;
 }
@@ -376,6 +377,8 @@
 		"MemShared: %8lu kB\n"
 		"Buffers:   %8lu kB\n"
 		"Cached:    %8u kB\n"
+		"BigTotal:  %8lu kB\n"
+		"BigFree:   %8lu kB\n"
 		"SwapTotal: %8lu kB\n"
 		"SwapFree:  %8lu kB\n",
 		i.totalram >> 10,
@@ -383,6 +386,8 @@
 		i.sharedram >> 10,
 		i.bufferram >> 10,
 		atomic_read(&page_cache_size) << (PAGE_SHIFT - 10),
+		i.totalbig >> 10,
+		i.freebig >> 10,
 		i.totalswap >> 10,
 		i.freeswap >> 10);
 }
@@ -432,6 +437,8 @@
 	return pte_page(pte) + (ptr & ~PAGE_MASK);
 }
 
+#include <linux/bigmem.h>
+
 static int get_array(struct mm_struct *mm, unsigned long start, unsigned long end, char * buffer)
 {
 	unsigned long addr;
@@ -444,19 +451,25 @@
 		addr = get_phys_addr(mm, start);
 		if (!addr)
 			return result;
+		addr = kmap(addr, KM_READ);
 		do {
 			c = *(char *) addr;
 			if (!c)
 				result = size;
 			if (size < PAGE_SIZE)
 				buffer[size++] = c;
-			else
+			else {
+				kunmap(addr, KM_READ);
 				return result;
+			}
 			addr++;
 			start++;
-			if (!c && start >= end)
+			if (!c && start >= end) {
+				kunmap(addr, KM_READ);
 				return result;
+			}
 		} while (addr & ~PAGE_MASK);
+		kunmap(addr, KM_READ);
 	}
 	return result;
 }
@@ -519,12 +532,12 @@
 
 		stack_page = (unsigned long)p;
 		esp = p->thread.esp;
-		if (!stack_page || esp < stack_page || esp >= 8188+stack_page)
+		if (!stack_page || esp < stack_page || esp > 8188+stack_page)
 			return 0;
 		/* include/asm-i386/system.h:switch_to() pushes ebp last. */
 		ebp = *(unsigned long *) esp;
 		do {
-			if (ebp < stack_page || ebp >= 8188+stack_page)
+			if (ebp < stack_page || ebp > 8184+stack_page)
 				return 0;
 			eip = *(unsigned long *) (ebp+4);
 			if (eip < first_sched || eip >= last_sched)
@@ -593,7 +606,7 @@
 		unsigned long stack_page = (unsigned long) p;
 		int count = 0;
 
-		sp = p->tss.ksp;
+		sp = p->thread.ksp;
 		do {
 			sp = *(unsigned long *)sp;
 			if (sp < stack_page || sp >= stack_page + 8188)
@@ -675,8 +688,8 @@
 	eip; })
 #define	KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
 #elif defined(__powerpc__)
-#define KSTK_EIP(tsk)	((tsk)->tss.regs->nip)
-#define KSTK_ESP(tsk)	((tsk)->tss.regs->gpr[1])
+#define KSTK_EIP(tsk)	((tsk)->thread.regs->nip)
+#define KSTK_ESP(tsk)	((tsk)->thread.regs->gpr[1])
 #elif defined (__sparc_v9__)
 # define KSTK_EIP(tsk)  ((tsk)->thread.kregs->tpc)
 # define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
@@ -689,6 +702,9 @@
 #define KSTK_TOS(tsk) ((unsigned long)(tsk) + KERNEL_STACK_SIZE - 32)
 # define KSTK_EIP(tsk)	(*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(cp0_epc)))
 # define KSTK_ESP(tsk)	(*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(regs[29])))
+#elif defined(__sh__)
+# define KSTK_EIP(tsk)  ((tsk)->thread.pc)
+# define KSTK_ESP(tsk)  ((tsk)->thread.sp)
 #endif
 
 /* Gcc optimizes away "strlen(x)" for constant x */
@@ -1337,7 +1353,7 @@
 		case PROC_MEMINFO:
 			return get_meminfo(page);
 
-#ifdef CONFIG_PCI_OLD_PROC
+#ifdef CONFIG_PCI
 	        case PROC_PCI:
 			return get_pci_list(page);
 #endif
@@ -1456,8 +1472,7 @@
 	if (!p)
 		return 1;
 
-	switch(type)
-	{
+	switch(type) {
 		case PROC_PID_STATUS:
 		case PROC_PID_STATM:
 		case PROC_PID_STAT:
@@ -1524,8 +1539,7 @@
 	start = NULL;
 	dp = (struct proc_dir_entry *) inode->u.generic_ip;
 	
-	if (pid && process_unauthorized(type, pid))
-	{
+	if (pid && process_unauthorized(type, pid)) {
 		free_page(page);
 		return -EIO;
 	}
diff -u --recursive --new-file v2.3.15/linux/fs/proc/base.c linux/fs/proc/base.c
--- v2.3.15/linux/fs/proc/base.c	Sat Jun 26 12:04:39 1999
+++ linux/fs/proc/base.c	Thu Aug 26 14:18:06 1999
@@ -178,7 +178,7 @@
 };
 #endif
 
-__initfunc(void proc_base_init(void))
+void __init proc_base_init(void)
 {
 #if CONFIG_AP1000
 	proc_register(&proc_pid, &proc_pid_ringbuf);
diff -u --recursive --new-file v2.3.15/linux/fs/proc/mem.c linux/fs/proc/mem.c
--- v2.3.15/linux/fs/proc/mem.c	Sat Jul  3 12:04:12 1999
+++ linux/fs/proc/mem.c	Thu Aug 26 12:34:55 1999
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/proc_fs.h>
+#include <linux/bigmem.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
@@ -120,7 +121,9 @@
 		i = PAGE_SIZE-(addr & ~PAGE_MASK);
 		if (i > scount)
 			i = scount;
+		page = (char *) kmap((unsigned long) page, KM_READ);
 		copy_to_user(tmp, page, i);
+		kunmap((unsigned long) page, KM_READ);
 		addr += i;
 		tmp += i;
 		scount -= i;
@@ -177,7 +180,9 @@
 		i = PAGE_SIZE-(addr & ~PAGE_MASK);
 		if (i > count)
 			i = count;
+		page = (unsigned long) kmap((unsigned long) page, KM_WRITE);
 		copy_from_user(page, tmp, i);
+		kunmap((unsigned long) page, KM_WRITE);
 		addr += i;
 		tmp += i;
 		count -= i;
diff -u --recursive --new-file v2.3.15/linux/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c
--- v2.3.15/linux/fs/proc/openpromfs.c	Tue Jun 29 09:22:08 1999
+++ linux/fs/proc/openpromfs.c	Tue Aug 31 11:25:33 1999
@@ -1,4 +1,4 @@
-/* $Id: openpromfs.c,v 1.35 1999/06/27 00:37:36 davem Exp $
+/* $Id: openpromfs.c,v 1.36 1999/08/31 07:01:03 davem Exp $
  * openpromfs.c: /proc/openprom handling routines
  *
  * Copyright (C) 1996-1998 Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
@@ -990,7 +990,7 @@
 
 /* {{{ init section */
 #ifndef MODULE
-__initfunc(static int check_space (u16 n))
+static int __init check_space (u16 n)
 #else
 static int check_space (u16 n)
 #endif
@@ -1014,7 +1014,7 @@
 }
 
 #ifndef MODULE
-__initfunc(static u16 get_nodes (u16 parent, u32 node))
+static u16 __init get_nodes (u16 parent, u32 node)
 #else
 static u16 get_nodes (u16 parent, u32 node)
 #endif
@@ -1132,7 +1132,7 @@
 
 #ifndef MODULE
 #define RET(x)
-__initfunc(void openpromfs_init (void))
+void __init openpromfs_init (void)
 #else
 
 EXPORT_NO_SYMBOLS;
diff -u --recursive --new-file v2.3.15/linux/fs/proc/proc_tty.c linux/fs/proc/proc_tty.c
--- v2.3.15/linux/fs/proc/proc_tty.c	Tue Aug  4 10:57:13 1998
+++ linux/fs/proc/proc_tty.c	Thu Aug 26 14:18:06 1999
@@ -170,7 +170,7 @@
 /*
  * Called by proc_root_init() to initialize the /proc/tty subtree
  */
-__initfunc(void proc_tty_init(void))
+void __init proc_tty_init(void)
 {
 	struct proc_dir_entry *ent;
 	
diff -u --recursive --new-file v2.3.15/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.3.15/linux/fs/proc/root.c	Wed Aug  4 17:19:09 1999
+++ linux/fs/proc/root.c	Thu Aug 26 14:18:06 1999
@@ -704,7 +704,7 @@
 };
 #endif
 
-__initfunc(void proc_root_init(void))
+void __init proc_root_init(void)
 {
 	proc_base_init();
 	proc_register(&proc_root, &proc_root_loadavg);
diff -u --recursive --new-file v2.3.15/linux/fs/qnx4/inode.c linux/fs/qnx4/inode.c
--- v2.3.15/linux/fs/qnx4/inode.c	Tue Jun  8 10:47:58 1999
+++ linux/fs/qnx4/inode.c	Thu Aug 26 14:18:06 1999
@@ -430,7 +430,7 @@
 	NULL
 };
 
-__initfunc(int init_qnx4_fs(void))
+int __init init_qnx4_fs(void)
 {
 	printk("QNX4 filesystem v0.2 registered.\n");
 	return register_filesystem(&qnx4_fs_type);
diff -u --recursive --new-file v2.3.15/linux/fs/romfs/inode.c linux/fs/romfs/inode.c
--- v2.3.15/linux/fs/romfs/inode.c	Thu Aug 12 10:19:59 1999
+++ linux/fs/romfs/inode.c	Thu Aug 26 14:18:06 1999
@@ -692,7 +692,7 @@
 	NULL
 };
 
-__initfunc(int init_romfs_fs(void))
+int __init init_romfs_fs(void)
 {
 	return register_filesystem(&romfs_fs_type);
 }
diff -u --recursive --new-file v2.3.15/linux/fs/select.c linux/fs/select.c
--- v2.3.15/linux/fs/select.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/select.c	Tue Aug 31 11:30:48 1999
@@ -174,7 +174,7 @@
 	n = retval;
 	retval = 0;
 	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		for (i = 0 ; i < n; i++) {
 			unsigned long bit = BIT(i);
 			unsigned long mask;
@@ -337,7 +337,7 @@
 		unsigned int j;
 		struct pollfd * fdpnt;
 
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		for (fdpnt = fds, j = 0; j < nfds; j++, fdpnt++) {
 			int fd;
 			unsigned int mask;
diff -u --recursive --new-file v2.3.15/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.3.15/linux/fs/smbfs/inode.c	Wed Jun 30 11:24:55 1999
+++ linux/fs/smbfs/inode.c	Thu Aug 26 14:18:06 1999
@@ -575,7 +575,7 @@
 	NULL
 };
 
-__initfunc(int init_smb_fs(void))
+int __init init_smb_fs(void)
 {
 	return register_filesystem(&smb_fs_type);
 }
diff -u --recursive --new-file v2.3.15/linux/fs/super.c linux/fs/super.c
--- v2.3.15/linux/fs/super.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/super.c	Tue Aug 31 11:30:48 1999
@@ -417,7 +417,7 @@
 
 	add_wait_queue(&sb->s_wait, &wait);
 repeat:
-	current->state = TASK_UNINTERRUPTIBLE;
+	set_current_state(TASK_UNINTERRUPTIBLE);
 	if (sb->s_lock) {
 		schedule();
 		goto repeat;
diff -u --recursive --new-file v2.3.15/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v2.3.15/linux/fs/sysv/inode.c	Sun Jun 27 10:10:41 1999
+++ linux/fs/sysv/inode.c	Thu Aug 26 14:18:06 1999
@@ -1174,7 +1174,7 @@
 	{"coherent", FS_REQUIRES_DEV, sysv_read_super, NULL}
 };
 
-__initfunc(int init_sysv_fs(void))
+int __init init_sysv_fs(void)
 {
 	int i;
 	int ouch;
diff -u --recursive --new-file v2.3.15/linux/fs/ufs/super.c linux/fs/ufs/super.c
--- v2.3.15/linux/fs/ufs/super.c	Thu Jul  1 10:45:57 1999
+++ linux/fs/ufs/super.c	Thu Aug 26 14:18:06 1999
@@ -935,7 +935,7 @@
 	NULL
 };
 
-__initfunc(int init_ufs_fs(void))
+int __init init_ufs_fs(void)
 {
 	return register_filesystem(&ufs_fs_type);
 }
diff -u --recursive --new-file v2.3.15/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- v2.3.15/linux/fs/umsdos/inode.c	Mon Aug  9 11:44:49 1999
+++ linux/fs/umsdos/inode.c	Thu Aug 26 14:18:06 1999
@@ -434,7 +434,7 @@
 	NULL
 };
 
-__initfunc (int init_umsdos_fs (void))
+int __init init_umsdos_fs (void)
 {
 	return register_filesystem (&umsdos_fs_type);
 }
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/compiler.h linux/include/asm-alpha/compiler.h
--- v2.3.15/linux/include/asm-alpha/compiler.h	Mon Aug 16 10:33:58 1999
+++ linux/include/asm-alpha/compiler.h	Tue Aug 31 10:50:45 1999
@@ -18,6 +18,8 @@
   (((unsigned long)(val) & 0xfful) << ((shift) * 8))
 #define __kernel_inswl(val, shift) \
   (((unsigned long)(val) & 0xfffful) << ((shift) * 8))
+#define __kernel_insql(val, shift) \
+  ((unsigned long)(val) << ((shift) * 8))
 #else
 #define __kernel_insbl(val, shift)					\
   ({ unsigned long __kir;						\
@@ -27,6 +29,10 @@
   ({ unsigned long __kir;						\
      __asm__("inswl %2,%1,%0" : "=r"(__kir) : "rI"(shift), "r"(val));	\
      __kir; })
+#define __kernel_insql(val, shift)					\
+  ({ unsigned long __kir;						\
+     __asm__("insql %2,%1,%0" : "=r"(__kir) : "rI"(shift), "r"(val));	\
+     __kir; })
 #endif
 
 #if 0 && (__GNUC__ > 2 || __GNUC_MINOR__ >= 92)
@@ -47,11 +53,10 @@
 /* 
  * Beginning with EGCS 1.1, GCC defines __alpha_bwx__ when the BWX 
  * extension is enabled.  Previous versions did not define anything
- * we could test during compilation, so allow users to tell us when
- * the compiler will DTRT.
+ * we could test during compilation -- too bad, so sad.
  */
 
-#if defined(HAVE_BWX) || defined(__alpha_bwx__)
+#if defined(__alpha_bwx__)
 #define __kernel_ldbu(mem)	(mem)
 #define __kernel_ldwu(mem)	(mem)
 #define __kernel_stb(val,mem)	((mem) = (val))
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/core_apecs.h linux/include/asm-alpha/core_apecs.h
--- v2.3.15/linux/include/asm-alpha/core_apecs.h	Mon Aug 16 10:33:58 1999
+++ linux/include/asm-alpha/core_apecs.h	Tue Aug 31 10:50:45 1999
@@ -67,25 +67,17 @@
    make the AVANTI support pay for the limitations of the XL. It is true,
    however, that an XL kernel will run on an AVANTI without problems.
 */
-#define APECS_XL_DMA_WIN1_BASE		(64*1024*1024)
-#define APECS_XL_DMA_WIN1_SIZE		(64*1024*1024)
-#define APECS_XL_DMA_WIN1_SIZE_PARANOID	(48*1024*1024)
-#define APECS_XL_DMA_WIN2_BASE		(1024*1024*1024)
-#define APECS_XL_DMA_WIN2_SIZE		(1024*1024*1024)
+#define APECS_XL_DMA_WIN1_BASE		(64UL*1024*1024)
+#define APECS_XL_DMA_WIN1_SIZE		(64UL*1024*1024)
+#define APECS_XL_DMA_WIN1_SIZE_PARANOID	(48UL*1024*1024)
+#define APECS_XL_DMA_WIN2_BASE		(1UL*1024*1024*1024)
+#define APECS_XL_DMA_WIN2_SIZE		(1UL*1024*1024*1024)
 
 
 /* These are for normal APECS family machines, AVANTI/MUSTANG/EB64/PC64.  */
 
-#define APECS_DMA_WIN_BASE_DEFAULT	(1024*1024*1024)
-#define APECS_DMA_WIN_SIZE_DEFAULT	(1024*1024*1024)
-
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-#define APECS_DMA_WIN_BASE		alpha_mv.dma_win_base
-#define APECS_DMA_WIN_SIZE		alpha_mv.dma_win_size
-#else
-#define APECS_DMA_WIN_BASE		APECS_DMA_WIN_BASE_DEFAULT
-#define APECS_DMA_WIN_SIZE		APECS_DMA_WIN_SIZE_DEFAULT
-#endif
+#define APECS_DMA_WIN_BASE		(1UL*1024*1024*1024)
+#define APECS_DMA_WIN_SIZE		(1UL*1024*1024*1024)
 
 
 /*
@@ -400,9 +392,9 @@
 {
 	unsigned long paddr = virt_to_phys(address);
 	if (paddr < APECS_XL_DMA_WIN1_SIZE_PARANOID)
-	  return paddr + APECS_XL_DMA_WIN1_BASE;
+		return paddr + APECS_XL_DMA_WIN1_BASE;
 	else
-	  return paddr + APECS_XL_DMA_WIN2_BASE; /* win 2 xlates to 0 also */
+		return paddr + APECS_XL_DMA_WIN2_BASE;
 }
 
 __EXTERN_INLINE void * apecs_bus_to_virt(unsigned long address)
@@ -501,14 +493,6 @@
 {
 	unsigned long result, msb;
 
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += APECS_DENSE_MEM;
-	}
-#endif
-
 	addr -= APECS_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
@@ -523,14 +507,6 @@
 {
 	unsigned long result, msb;
 
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += APECS_DENSE_MEM;
-	}
-#endif
-
 	addr -= APECS_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
@@ -543,27 +519,11 @@
 
 __EXTERN_INLINE unsigned long apecs_readl(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += APECS_DENSE_MEM;
-	}
-#endif
-
 	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long apecs_readq(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += APECS_DENSE_MEM;
-	}
-#endif
-
 	return *(vulp)addr;
 }
 
@@ -571,14 +531,6 @@
 {
 	unsigned long msb;
 
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += APECS_DENSE_MEM;
-	}
-#endif
-
 	addr -= APECS_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
@@ -592,14 +544,6 @@
 {
 	unsigned long msb;
 
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += APECS_DENSE_MEM;
-	}
-#endif
-
 	addr -= APECS_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
@@ -611,38 +555,22 @@
 
 __EXTERN_INLINE void apecs_writel(unsigned int b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += APECS_DENSE_MEM;
-	}
-#endif
-
 	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void apecs_writeq(unsigned long b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "apecs: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += APECS_DENSE_MEM;
-	}
-#endif
-
 	*(vulp)addr = b;
 }
 
 __EXTERN_INLINE unsigned long apecs_ioremap(unsigned long addr)
 {
-	return APECS_DENSE_MEM + addr;
+	return addr + APECS_DENSE_MEM;
 }
 
 __EXTERN_INLINE int apecs_is_ioaddr(unsigned long addr)
 {
-	return addr >= IDENT_ADDR + 0x100000000UL;
+	return addr >= IDENT_ADDR + 0x180000000UL;
 }
 
 #undef vip
@@ -677,17 +605,14 @@
 #define __is_ioaddr	apecs_is_ioaddr
 
 #define inb(port) \
-(__builtin_constant_p((port))?__inb(port):_inb(port))
-
+  (__builtin_constant_p((port))?__inb(port):_inb(port))
 #define outb(x, port) \
-(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
+  (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
 
-#if !__DEBUG_IOREMAP
 #define __raw_readl(a)		__readl((unsigned long)(a))
 #define __raw_readq(a)		__readq((unsigned long)(a))
 #define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
 #define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
-#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/core_cia.h linux/include/asm-alpha/core_cia.h
--- v2.3.15/linux/include/asm-alpha/core_cia.h	Wed Aug 18 17:12:15 1999
+++ linux/include/asm-alpha/core_cia.h	Tue Aug 31 10:50:45 1999
@@ -1,6 +1,9 @@
 #ifndef __ALPHA_CIA__H__
 #define __ALPHA_CIA__H__
 
+/* Define to experiment with fitting everything into one 512MB HAE window.  */
+#define CIA_ONE_HAE_WINDOW 1
+
 #include <linux/config.h>
 #include <linux/types.h>
 #include <asm/compiler.h>
@@ -11,7 +14,7 @@
  *
  * This file is based on:
  *
- * DECchip 21171 Core Logic Chipset 
+ * DECchip 21171 Core Logic Chipset
  * Technical Reference Manual
  *
  * EC-QE18B-TE
@@ -39,7 +42,7 @@
 
 /* CIA ADDRESS BIT DEFINITIONS
  *
- *  3333 3333 3322 2222 2222 1111 1111 11 
+ *  3333 3333 3322 2222 2222 1111 1111 11
  *  9876 5432 1098 7654 3210 9876 5432 1098 7654 3210
  *  ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
  *  1                                             000
@@ -75,8 +78,8 @@
 #define CIA_MEM_R2_MASK 0x07ffffff  /* SPARSE Mem region 2 mask is 27 bits */
 #define CIA_MEM_R3_MASK 0x03ffffff  /* SPARSE Mem region 3 mask is 26 bits */
 
-#define CIA_DMA_WIN_BASE_DEFAULT	(1UL*1024*1024*1024)
-#define CIA_DMA_WIN_SIZE_DEFAULT	(2UL*1024*1024*1024)
+#define CIA_DMA_WIN_BASE		(1UL*1024*1024*1024)
+#define CIA_DMA_WIN_SIZE		(2UL*1024*1024*1024)
 
 /* Window 0 at 1GB size 1GB mapping to 0.  */
 #define CIA_DMA_WIN0_BASE_DEFAULT      (1UL*1024*1024*1024)
@@ -89,14 +92,6 @@
 #define CIA_DMA_WIN1_TRAN_DEFAULT      (1UL*1024*1024*1024)
 
 
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-#define CIA_DMA_WIN_BASE		alpha_mv.dma_win_base
-#define CIA_DMA_WIN_SIZE		alpha_mv.dma_win_size
-#else
-#define CIA_DMA_WIN_BASE		CIA_DMA_WIN_BASE_DEFAULT
-#define CIA_DMA_WIN_SIZE		CIA_DMA_WIN_SIZE_DEFAULT
-#endif
-
 /*
  * 21171-CA Control and Status Registers (p4-1)
  */
@@ -216,7 +211,9 @@
 #define CIA_IOC_STAT0_P_NBR_SHIFT	13
 #define CIA_IOC_STAT0_P_NBR_MASK	0x7ffff
 
+#if !CIA_ONE_HAE_WINDOW
 #define CIA_HAE_ADDRESS	                CIA_IOC_HAE_MEM
+#endif
 
 /*
  * Data structure for handling CIA machine checks.
@@ -248,47 +245,47 @@
 
 /* System-specific info.  */
 struct el_CIA_sysdata_mcheck {
-	unsigned long      coma_gcr;                       
-	unsigned long      coma_edsr;                      
-	unsigned long      coma_ter;                       
-	unsigned long      coma_elar;                      
-	unsigned long      coma_ehar;                      
-	unsigned long      coma_ldlr;                      
-	unsigned long      coma_ldhr;                      
-	unsigned long      coma_base0;                     
-	unsigned long      coma_base1;                     
-	unsigned long      coma_base2;                     
-	unsigned long      coma_cnfg0;                     
-	unsigned long      coma_cnfg1;                     
-	unsigned long      coma_cnfg2;                     
-	unsigned long      epic_dcsr;                      
-	unsigned long      epic_pear;                      
-	unsigned long      epic_sear;                      
-	unsigned long      epic_tbr1;                      
-	unsigned long      epic_tbr2;                      
-	unsigned long      epic_pbr1;                      
-	unsigned long      epic_pbr2;                      
-	unsigned long      epic_pmr1;                      
-	unsigned long      epic_pmr2;                      
-	unsigned long      epic_harx1;                     
-	unsigned long      epic_harx2;                     
-	unsigned long      epic_pmlt;                      
-	unsigned long      epic_tag0;                      
-	unsigned long      epic_tag1;                      
-	unsigned long      epic_tag2;                      
-	unsigned long      epic_tag3;                      
-	unsigned long      epic_tag4;                      
-	unsigned long      epic_tag5;                      
-	unsigned long      epic_tag6;                      
-	unsigned long      epic_tag7;                      
-	unsigned long      epic_data0;                     
-	unsigned long      epic_data1;                     
-	unsigned long      epic_data2;                     
-	unsigned long      epic_data3;                     
-	unsigned long      epic_data4;                     
-	unsigned long      epic_data5;                     
-	unsigned long      epic_data6;                     
-	unsigned long      epic_data7;                     
+	unsigned long      coma_gcr;
+	unsigned long      coma_edsr;
+	unsigned long      coma_ter;
+	unsigned long      coma_elar;
+	unsigned long      coma_ehar;
+	unsigned long      coma_ldlr;
+	unsigned long      coma_ldhr;
+	unsigned long      coma_base0;
+	unsigned long      coma_base1;
+	unsigned long      coma_base2;
+	unsigned long      coma_cnfg0;
+	unsigned long      coma_cnfg1;
+	unsigned long      coma_cnfg2;
+	unsigned long      epic_dcsr;
+	unsigned long      epic_pear;
+	unsigned long      epic_sear;
+	unsigned long      epic_tbr1;
+	unsigned long      epic_tbr2;
+	unsigned long      epic_pbr1;
+	unsigned long      epic_pbr2;
+	unsigned long      epic_pmr1;
+	unsigned long      epic_pmr2;
+	unsigned long      epic_harx1;
+	unsigned long      epic_harx2;
+	unsigned long      epic_pmlt;
+	unsigned long      epic_tag0;
+	unsigned long      epic_tag1;
+	unsigned long      epic_tag2;
+	unsigned long      epic_tag3;
+	unsigned long      epic_tag4;
+	unsigned long      epic_tag5;
+	unsigned long      epic_tag6;
+	unsigned long      epic_tag7;
+	unsigned long      epic_data0;
+	unsigned long      epic_data1;
+	unsigned long      epic_data2;
+	unsigned long      epic_data3;
+	unsigned long      epic_data4;
+	unsigned long      epic_data5;
+	unsigned long      epic_data6;
+	unsigned long      epic_data7;
 };
 
 
@@ -369,8 +366,8 @@
 /*
  * Memory functions.  64-bit and 32-bit accesses are done through
  * dense memory space, everything else through sparse space.
- * 
- * For reading and writing 8 and 16 bit quantities we need to 
+ *
+ * For reading and writing 8 and 16 bit quantities we need to
  * go through one of the three sparse address mapping regions
  * and use the HAE_MEM CSR to provide some bits of the address.
  * The following few routines use only sparse address region 1
@@ -379,10 +376,10 @@
  * See p 6-17 of the specification but it looks something like this:
  *
  * 21164 Address:
- * 
- *          3         2         1                                                               
+ *
+ *          3         2         1
  * 9876543210987654321098765432109876543210
- * 1ZZZZ0.PCI.QW.Address............BBLL                 
+ * 1ZZZZ0.PCI.QW.Address............BBLL
  *
  * ZZ = SBZ
  * BB = Byte offset
@@ -390,117 +387,26 @@
  *
  * PCI Address:
  *
- * 3         2         1                                                               
+ * 3         2         1
  * 10987654321098765432109876543210
  * HHH....PCI.QW.Address........ 00
  *
  * HHH = 31:29 HAE_MEM CSR
- * 
+ *
  */
 
-__EXTERN_INLINE unsigned long cia_srm_base(unsigned long addr)
-{
-	unsigned long mask, base;
-
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += CIA_DENSE_MEM;
-	}
-#endif
-
-	addr -= CIA_DENSE_MEM;
-	if (addr >= alpha_mv.sm_base_r1
-	    && addr <= alpha_mv.sm_base_r1 + CIA_MEM_R1_MASK) {
-		mask = CIA_MEM_R1_MASK;
-		base = CIA_SPARSE_MEM;
-	}
-	else if (addr >= alpha_mv.sm_base_r2
-		 && addr <= alpha_mv.sm_base_r2 + CIA_MEM_R2_MASK) {
-		mask = CIA_MEM_R2_MASK;
-		base = CIA_SPARSE_MEM_R2;
-	}
-	else if (addr >= alpha_mv.sm_base_r3
-		 && addr <= alpha_mv.sm_base_r3 + CIA_MEM_R3_MASK) {
-		mask = CIA_MEM_R3_MASK;
-		base = CIA_SPARSE_MEM_R3;
-	}
-	else
-	{
-#if 0
-		printk(KERN_CRIT "cia: address 0x%lx not covered by HAE\n",
-		       addr);
-#endif
-		return 0;
-	}
-
-	return ((addr & mask) << 5) + base;
-}
-
-__EXTERN_INLINE unsigned long cia_srm_readb(unsigned long addr)
-{
-	unsigned long result, work;
-
-	if ((work = cia_srm_base(addr)) == 0)
-		return 0xff;
-	work += 0x00;	/* add transfer length */
-
-	result = *(vip) work;
-	return __kernel_extbl(result, addr & 3);
-}
-
-__EXTERN_INLINE unsigned long cia_srm_readw(unsigned long addr)
-{
-	unsigned long result, work;
-
-	if ((work = cia_srm_base(addr)) == 0)
-		return 0xffff;
-	work += 0x08;	/* add transfer length */
-
-	result = *(vip) work;
-	return __kernel_extwl(result, addr & 3);
-}
-
-__EXTERN_INLINE void cia_srm_writeb(unsigned char b, unsigned long addr)
-{
-	unsigned long work, w;
-
-	if ((work = cia_srm_base(addr)) != 0) {
-		work += 0x00;	/* add transfer length */
-		w = __kernel_insbl(b, addr & 3);
-		*(vuip) work = w;
-	}
-}
-
-__EXTERN_INLINE void cia_srm_writew(unsigned short b, unsigned long addr)
-{
-	unsigned long work, w;
-
-	addr -= CIA_DENSE_MEM;
-	if ((work = cia_srm_base(addr)) != 0) {
-		work += 0x08;	/* add transfer length */
-		w = __kernel_inswl(b, addr & 3);
-		*(vuip) work = w;
-	}
-}
-
 __EXTERN_INLINE unsigned long cia_readb(unsigned long addr)
 {
-	unsigned long result, msb;
-
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
+	unsigned long result;
 
-	/* Note that CIA_DENSE_MEM has no bits not masked in these 
+#if !CIA_ONE_HAE_WINDOW
+	unsigned long msb;
+	/* Note that CIA_DENSE_MEM has no bits not masked in these
 	   operations, so we don't have to subtract it back out.  */
 	msb = addr & 0xE0000000;
-	addr &= CIA_MEM_R1_MASK;
 	set_hae(msb);
+#endif
+	addr &= CIA_MEM_R1_MASK;
 
 	result = *(vip) ((addr << 5) + CIA_SPARSE_MEM + 0x00);
 	return __kernel_extbl(result, addr & 3);
@@ -508,20 +414,16 @@
 
 __EXTERN_INLINE unsigned long cia_readw(unsigned long addr)
 {
-	unsigned long result, msb;
-
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
+	unsigned long result;
 
-	/* Note that CIA_DENSE_MEM has no bits not masked in these 
+#if !CIA_ONE_HAE_WINDOW
+	unsigned long msb;
+	/* Note that CIA_DENSE_MEM has no bits not masked in these
 	   operations, so we don't have to subtract it back out.  */
 	msb = addr & 0xE0000000;
-	addr &= CIA_MEM_R1_MASK;
 	set_hae(msb);
+#endif
+	addr &= CIA_MEM_R1_MASK;
 
 	result = *(vip) ((addr << 5) + CIA_SPARSE_MEM + 0x08);
 	return __kernel_extwl(result, addr & 3);
@@ -529,20 +431,16 @@
 
 __EXTERN_INLINE void cia_writeb(unsigned char b, unsigned long addr)
 {
-	unsigned long msb, w; 
-
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
+	unsigned long w;
 
-	/* Note that CIA_DENSE_MEM has no bits not masked in these 
+#if !CIA_ONE_HAE_WINDOW
+	unsigned long msb;
+	/* Note that CIA_DENSE_MEM has no bits not masked in these
 	   operations, so we don't have to subtract it back out.  */
 	msb = addr & 0xE0000000;
-	addr &= CIA_MEM_R1_MASK;
 	set_hae(msb);
+#endif
+	addr &= CIA_MEM_R1_MASK;
 
 	w = __kernel_insbl(b, addr & 3);
 	*(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x00) = w;
@@ -550,20 +448,16 @@
 
 __EXTERN_INLINE void cia_writew(unsigned short b, unsigned long addr)
 {
-	unsigned long msb, w; 
-
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
+	unsigned long w;
 
-	/* Note that CIA_DENSE_MEM has no bits not masked in these 
+#if !CIA_ONE_HAE_WINDOW
+	unsigned long msb;
+	/* Note that CIA_DENSE_MEM has no bits not masked in these
 	   operations, so we don't have to subtract it back out.  */
 	msb = addr & 0xE0000000;
-	addr &= CIA_MEM_R1_MASK;
 	set_hae(msb);
+#endif
+	addr &= CIA_MEM_R1_MASK;
 
 	w = __kernel_inswl(b, addr & 3);
 	*(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x08) = w;
@@ -571,55 +465,27 @@
 
 __EXTERN_INLINE unsigned long cia_readl(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
-
 	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long cia_readq(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
-
 	return *(vulp)addr;
 }
 
 __EXTERN_INLINE void cia_writel(unsigned int b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
-
 	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void cia_writeq(unsigned long b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "cia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
-
 	*(vulp)addr = b;
 }
 
 __EXTERN_INLINE unsigned long cia_ioremap(unsigned long addr)
 {
-	return CIA_DENSE_MEM + addr;
+	return addr + CIA_DENSE_MEM;
 }
 
 __EXTERN_INLINE int cia_is_ioaddr(unsigned long addr)
@@ -642,18 +508,10 @@
 #define __outw		cia_outw
 #define __outl		cia_outl
 
-#ifdef CONFIG_ALPHA_SRM_SETUP
-#define __readb		cia_srm_readb
-#define __readw		cia_srm_readw
-#define __writeb	cia_srm_writeb
-#define __writew	cia_srm_writew
-#else
 #define __readb		cia_readb
 #define __readw		cia_readw
 #define __writeb	cia_writeb
 #define __writew	cia_writew
-#endif
-
 #define __readl		cia_readl
 #define __readq		cia_readq
 #define __writel	cia_writel
@@ -662,24 +520,14 @@
 #define __is_ioaddr	cia_is_ioaddr
 
 #define inb(port) \
-(__builtin_constant_p((port))?__inb(port):_inb(port))
+  (__builtin_constant_p((port))?__inb(port):_inb(port))
 #define outb(x, port) \
-(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
-
-#define inw(port) \
-(__builtin_constant_p((port))?__inw(port):_inw(port))
-#define outw(x, port) \
-(__builtin_constant_p((port))?__outw((x),(port)):_outw((x),(port)))
+  (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
 
-#define inl(port)	__inl(port)
-#define outl(x,port)	__outl((x),(port))
-
-#if !__DEBUG_IOREMAP
 #define __raw_readl(a)		__readl((unsigned long)(a))
 #define __raw_readq(a)		__readq((unsigned long)(a))
 #define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
 #define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
-#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/core_lca.h linux/include/asm-alpha/core_lca.h
--- v2.3.15/linux/include/asm-alpha/core_lca.h	Mon Aug 16 10:33:58 1999
+++ linux/include/asm-alpha/core_lca.h	Tue Aug 31 10:50:45 1999
@@ -56,16 +56,9 @@
  * ugh).
  */
 
-#define LCA_DMA_WIN_BASE_DEFAULT	(1024*1024*1024)
-#define LCA_DMA_WIN_SIZE_DEFAULT	(1024*1024*1024)
+#define LCA_DMA_WIN_BASE	(1UL*1024*1024*1024)
+#define LCA_DMA_WIN_SIZE	(1UL*1024*1024*1024)
 
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-#define LCA_DMA_WIN_BASE		alpha_mv.dma_win_base
-#define LCA_DMA_WIN_SIZE		alpha_mv.dma_win_size
-#else
-#define LCA_DMA_WIN_BASE		LCA_DMA_WIN_BASE_DEFAULT
-#define LCA_DMA_WIN_SIZE		LCA_DMA_WIN_SIZE_DEFAULT
-#endif
 
 /*
  * Memory Controller registers:
@@ -305,14 +298,6 @@
 {
 	unsigned long result, msb;
 
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += LCA_DENSE_MEM;
-	}
-#endif
-
 	addr -= LCA_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
@@ -327,14 +312,6 @@
 {
 	unsigned long result, msb;
 
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += LCA_DENSE_MEM;
-	}
-#endif
-
 	addr -= LCA_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
@@ -347,27 +324,11 @@
 
 __EXTERN_INLINE unsigned long lca_readl(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += LCA_DENSE_MEM;
-	}
-#endif
-
 	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long lca_readq(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += LCA_DENSE_MEM;
-	}
-#endif
-
 	return *(vulp)addr;
 }
 
@@ -376,14 +337,6 @@
 	unsigned long msb;
 	unsigned long w;
 
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += LCA_DENSE_MEM;
-	}
-#endif
-
 	addr -= LCA_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
@@ -399,14 +352,6 @@
 	unsigned long msb;
 	unsigned long w;
 
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += LCA_DENSE_MEM;
-	}
-#endif
-
 	addr -= LCA_DENSE_MEM;
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
@@ -419,38 +364,22 @@
 
 __EXTERN_INLINE void lca_writel(unsigned int b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += LCA_DENSE_MEM;
-	}
-#endif
-
 	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void lca_writeq(unsigned long b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "lca: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += LCA_DENSE_MEM;
-	}
-#endif
-
 	*(vulp)addr = b;
 }
 
 __EXTERN_INLINE unsigned long lca_ioremap(unsigned long addr)
 {
-	return LCA_DENSE_MEM + addr;
+	return addr + LCA_DENSE_MEM;
 }
 
 __EXTERN_INLINE int lca_is_ioaddr(unsigned long addr)
 {
-	return addr >= IDENT_ADDR + 0x100000000UL;
+	return addr >= IDENT_ADDR + 0x120000000UL;
 }
 
 #undef vip
@@ -479,17 +408,14 @@
 #define __is_ioaddr	lca_is_ioaddr
 
 #define inb(port) \
-(__builtin_constant_p((port))?__inb(port):_inb(port))
-
+  (__builtin_constant_p((port))?__inb(port):_inb(port))
 #define outb(x, port) \
-(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
+  (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
 
-#if !__DEBUG_IOREMAP
 #define __raw_readl(a)		__readl((unsigned long)(a))
 #define __raw_readq(a)		__readq((unsigned long)(a))
 #define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
 #define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
-#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/core_mcpcia.h linux/include/asm-alpha/core_mcpcia.h
--- v2.3.15/linux/include/asm-alpha/core_mcpcia.h	Mon Aug 16 10:33:58 1999
+++ linux/include/asm-alpha/core_mcpcia.h	Tue Aug 31 10:50:45 1999
@@ -1,6 +1,10 @@
 #ifndef __ALPHA_MCPCIA__H__
 #define __ALPHA_MCPCIA__H__
 
+/* Define to experiment with fitting everything into one 128MB HAE window.
+   One window per bus, that is.  */
+#define MCPCIA_ONE_HAE_WINDOW 1
+
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -71,99 +75,112 @@
 
 #define MCPCIA_MEM_MASK 0x07ffffff /* SPARSE Mem region mask is 27 bits */
 
-#define MCPCIA_DMA_WIN_BASE_DEFAULT    (2*1024*1024*1024U)
-#define MCPCIA_DMA_WIN_SIZE_DEFAULT    (2*1024*1024*1024U)
+#define MCPCIA_DMA_WIN_BASE		(2UL*1024*1024*1024)
+#define MCPCIA_DMA_WIN_SIZE		(2UL*1024*1024*1024)
 
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-#define MCPCIA_DMA_WIN_BASE		alpha_mv.dma_win_base
-#define MCPCIA_DMA_WIN_SIZE		alpha_mv.dma_win_size
-#else
-#define MCPCIA_DMA_WIN_BASE		MCPCIA_DMA_WIN_BASE_DEFAULT
-#define MCPCIA_DMA_WIN_SIZE		MCPCIA_DMA_WIN_SIZE_DEFAULT
-#endif
+#define MCPCIA_MID(m)		((unsigned long)(m) << 33)
 
-#define HOSE(h) (((unsigned long)(h)) << 33)
+/*
+ * Memory spaces:
+ */
+#define MCPCIA_SPARSE(m)	(IDENT_ADDR + 0xf000000000UL + MCPCIA_MID(m))
+#define MCPCIA_DENSE(m)		(IDENT_ADDR + 0xf100000000UL + MCPCIA_MID(m))
+#define MCPCIA_IO(m)		(IDENT_ADDR + 0xf180000000UL + MCPCIA_MID(m))
+#define MCPCIA_CONF(m)		(IDENT_ADDR + 0xf1c0000000UL + MCPCIA_MID(m))
+#define MCPCIA_CSR(m)		(IDENT_ADDR + 0xf1e0000000UL + MCPCIA_MID(m))
+#define MCPCIA_IO_IACK(m)	(IDENT_ADDR + 0xf1f0000000UL + MCPCIA_MID(m))
+#define MCPCIA_DENSE_IO(m)	(IDENT_ADDR + 0xe1fc000000UL + MCPCIA_MID(m))
+#define MCPCIA_DENSE_CONF(m)	(IDENT_ADDR + 0xe1fe000000UL + MCPCIA_MID(m))
 
 /*
  *  General Registers
  */
-#define MCPCIA_REV(h)		(IDENT_ADDR + 0xf9e0000000UL + HOSE(h))
-#define MCPCIA_WHOAMI(h)	(IDENT_ADDR + 0xf9e0000040UL + HOSE(h))
-#define MCPCIA_PCI_LAT(h)	(IDENT_ADDR + 0xf9e0000080UL + HOSE(h))
-#define MCPCIA_CAP_CTRL(h)	(IDENT_ADDR + 0xf9e0000100UL + HOSE(h))
-#define MCPCIA_HAE_MEM(h)	(IDENT_ADDR + 0xf9e0000400UL + HOSE(h))
-#define MCPCIA_HAE_IO(h)	(IDENT_ADDR + 0xf9e0000440UL + HOSE(h))
-#if 0
-#define MCPCIA_IACK_SC(h)	(IDENT_ADDR + 0xf9e0000480UL + HOSE(h))
-#endif
-#define MCPCIA_HAE_DENSE(h)	(IDENT_ADDR + 0xf9e00004c0UL + HOSE(h))
+#define MCPCIA_REV(m)		(MCPCIA_CSR(m) + 0x000)
+#define MCPCIA_WHOAMI(m)	(MCPCIA_CSR(m) + 0x040)
+#define MCPCIA_PCI_LAT(m)	(MCPCIA_CSR(m) + 0x080)
+#define MCPCIA_CAP_CTRL(m)	(MCPCIA_CSR(m) + 0x100)
+#define MCPCIA_HAE_MEM(m)	(MCPCIA_CSR(m) + 0x400)
+#define MCPCIA_HAE_IO(m)	(MCPCIA_CSR(m) + 0x440)
+#define _MCPCIA_IACK_SC(m)	(MCPCIA_CSR(m) + 0x480)
+#define MCPCIA_HAE_DENSE(m)	(MCPCIA_CSR(m) + 0x4C0)
 
 /*
  * Interrupt Control registers
  */
-#define MCPCIA_INT_CTL(h)	(IDENT_ADDR + 0xf9e0000500UL + HOSE(h))
-#define MCPCIA_INT_REQ(h)	(IDENT_ADDR + 0xf9e0000540UL + HOSE(h))
-#define MCPCIA_INT_TARG(h)	(IDENT_ADDR + 0xf9e0000580UL + HOSE(h))
-#define MCPCIA_INT_ADR(h)	(IDENT_ADDR + 0xf9e00005c0UL + HOSE(h))
-#define MCPCIA_INT_ADR_EXT(h)	(IDENT_ADDR + 0xf9e0000600UL + HOSE(h))
-#define MCPCIA_INT_MASK0(h)	(IDENT_ADDR + 0xf9e0000640UL + HOSE(h))
-#define MCPCIA_INT_MASK1(h)	(IDENT_ADDR + 0xf9e0000680UL + HOSE(h))
-#define MCPCIA_INT_ACK0(h)	(IDENT_ADDR + 0xf9f0003f00UL + HOSE(h))
-#define MCPCIA_INT_ACK1(h)	(IDENT_ADDR + 0xf9e0003f40UL + HOSE(h))
+#define MCPCIA_INT_CTL(m)	(MCPCIA_CSR(m) + 0x500)
+#define MCPCIA_INT_REQ(m)	(MCPCIA_CSR(m) + 0x540)
+#define MCPCIA_INT_TARG(m)	(MCPCIA_CSR(m) + 0x580)
+#define MCPCIA_INT_ADR(m)	(MCPCIA_CSR(m) + 0x5C0)
+#define MCPCIA_INT_ADR_EXT(m)	(MCPCIA_CSR(m) + 0x600)
+#define MCPCIA_INT_MASK0(m)	(MCPCIA_CSR(m) + 0x640)
+#define MCPCIA_INT_MASK1(m)	(MCPCIA_CSR(m) + 0x680)
+#define MCPCIA_INT_ACK0(m)	(MCPCIA_CSR(m) + 0x10003f00)
+#define MCPCIA_INT_ACK1(m)	(MCPCIA_CSR(m) + 0x10003f40)
 
 /*
  * Performance Monitor registers
  */
-#define MCPCIA_PERF_MONITOR(h)	(IDENT_ADDR + 0xf9e0000300UL + HOSE(h))
-#define MCPCIA_PERF_CONTROL(h)	(IDENT_ADDR + 0xf9e0000340UL + HOSE(h))
+#define MCPCIA_PERF_MON(m)	(MCPCIA_CSR(m) + 0x300)
+#define MCPCIA_PERF_CONT(m)	(MCPCIA_CSR(m) + 0x340)
 
 /*
  * Diagnostic Registers
  */
-#define MCPCIA_CAP_DIAG(h)	(IDENT_ADDR + 0xf9e0000700UL + HOSE(h))
-#define MCPCIA_TOP_OF_MEM(h)	(IDENT_ADDR + 0xf9e00007c0UL + HOSE(h))
+#define MCPCIA_CAP_DIAG(m)	(MCPCIA_CSR(m) + 0x700)
+#define MCPCIA_TOP_OF_MEM(m)	(MCPCIA_CSR(m) + 0x7C0)
 
 /*
  * Error registers
  */
-#define MCPCIA_MC_ERR0(h)	(IDENT_ADDR + 0xf9e0000800UL + HOSE(h))
-#define MCPCIA_MC_ERR1(h)	(IDENT_ADDR + 0xf9e0000840UL + HOSE(h))
-#define MCPCIA_CAP_ERR(h)	(IDENT_ADDR + 0xf9e0000880UL + HOSE(h))
-#define MCPCIA_PCI_ERR1(h)	(IDENT_ADDR + 0xf9e0001040UL + HOSE(h))
+#define MCPCIA_MC_ERR0(m)	(MCPCIA_CSR(m) + 0x800)
+#define MCPCIA_MC_ERR1(m)	(MCPCIA_CSR(m) + 0x840)
+#define MCPCIA_CAP_ERR(m)	(MCPCIA_CSR(m) + 0x880)
+#define MCPCIA_PCI_ERR1(m)	(MCPCIA_CSR(m) + 0x1040)
+#define MCPCIA_MDPA_STAT(m)	(MCPCIA_CSR(m) + 0x4000)
+#define MCPCIA_MDPA_SYN(m)	(MCPCIA_CSR(m) + 0x4040)
+#define MCPCIA_MDPA_DIAG(m)	(MCPCIA_CSR(m) + 0x4080)
+#define MCPCIA_MDPB_STAT(m)	(MCPCIA_CSR(m) + 0x8000)
+#define MCPCIA_MDPB_SYN(m)	(MCPCIA_CSR(m) + 0x8040)
+#define MCPCIA_MDPB_DIAG(m)	(MCPCIA_CSR(m) + 0x8080)
 
 /*
  * PCI Address Translation Registers.
  */
-#define MCPCIA_SG_TBIA(h)	(IDENT_ADDR + 0xf9e0001300UL + HOSE(h))
-#define MCPCIA_HBASE(h)		(IDENT_ADDR + 0xf9e0001340UL + HOSE(h))
+#define MCPCIA_SG_TBIA(m)	(MCPCIA_CSR(m) + 0x1300)
+#define MCPCIA_HBASE(m)		(MCPCIA_CSR(m) + 0x1340)
 
-#define MCPCIA_W0_BASE(h)	(IDENT_ADDR + 0xf9e0001400UL + HOSE(h))
-#define MCPCIA_W0_MASK(h)	(IDENT_ADDR + 0xf9e0001440UL + HOSE(h))
-#define MCPCIA_T0_BASE(h)	(IDENT_ADDR + 0xf9e0001480UL + HOSE(h))
-
-#define MCPCIA_W1_BASE(h)	(IDENT_ADDR + 0xf9e0001500UL + HOSE(h))
-#define MCPCIA_W1_MASK(h)	(IDENT_ADDR + 0xf9e0001540UL + HOSE(h))
-#define MCPCIA_T1_BASE(h)	(IDENT_ADDR + 0xf9e0001580UL + HOSE(h))
-
-#define MCPCIA_W2_BASE(h)	(IDENT_ADDR + 0xf9e0001600UL + HOSE(h))
-#define MCPCIA_W2_MASK(h)	(IDENT_ADDR + 0xf9e0001640UL + HOSE(h))
-#define MCPCIA_T2_BASE(h)	(IDENT_ADDR + 0xf9e0001680UL + HOSE(h))
-
-#define MCPCIA_W3_BASE(h)	(IDENT_ADDR + 0xf9e0001700UL + HOSE(h))
-#define MCPCIA_W3_MASK(h)	(IDENT_ADDR + 0xf9e0001740UL + HOSE(h))
-#define MCPCIA_T3_BASE(h)	(IDENT_ADDR + 0xf9e0001780UL + HOSE(h))
+#define MCPCIA_W0_BASE(m)	(MCPCIA_CSR(m) + 0x1400)
+#define MCPCIA_W0_MASK(m)	(MCPCIA_CSR(m) + 0x1440)
+#define MCPCIA_T0_BASE(m)	(MCPCIA_CSR(m) + 0x1480)
 
-/*
- * Memory spaces:
+#define MCPCIA_W1_BASE(m)	(MCPCIA_CSR(m) + 0x1500)
+#define MCPCIA_W1_MASK(m)	(MCPCIA_CSR(m) + 0x1540)
+#define MCPCIA_T1_BASE(m)	(MCPCIA_CSR(m) + 0x1580)
+
+#define MCPCIA_W2_BASE(m)	(MCPCIA_CSR(m) + 0x1600)
+#define MCPCIA_W2_MASK(m)	(MCPCIA_CSR(m) + 0x1640)
+#define MCPCIA_T2_BASE(m)	(MCPCIA_CSR(m) + 0x1680)
+
+#define MCPCIA_W3_BASE(m)	(MCPCIA_CSR(m) + 0x1700)
+#define MCPCIA_W3_MASK(m)	(MCPCIA_CSR(m) + 0x1740)
+#define MCPCIA_T3_BASE(m)	(MCPCIA_CSR(m) + 0x1780)
+
+/* Hack!  Only words for bus 0.  */
+
+#if !MCPCIA_ONE_HAE_WINDOW
+#define MCPCIA_HAE_ADDRESS	MCPCIA_HAE_MEM(4)
+#endif
+#define MCPCIA_IACK_SC		_MCPCIA_IACK_SC(4)
+
+/* 
+ * The canonical non-remaped I/O and MEM addresses have these values
+ * subtracted out.  This is arranged so that folks manipulating ISA
+ * devices can use their familiar numbers and have them map to bus 0.
  */
-#define MCPCIA_CONF(h)		(IDENT_ADDR + 0xf9c0000000UL + HOSE(h))
-#define MCPCIA_IO(h)		(IDENT_ADDR + 0xf980000000UL + HOSE(h))
-#define MCPCIA_SPARSE(h)	(IDENT_ADDR + 0xf800000000UL + HOSE(h))
-#define MCPCIA_DENSE(h)		(IDENT_ADDR + 0xf900000000UL + HOSE(h))
-#define _MCPCIA_IACK_SC(h)	(IDENT_ADDR + 0xf9f0003f00UL + HOSE(h))
 
-#define MCPCIA_HAE_ADDRESS	MCPCIA_HAE_MEM(0)
-#define MCPCIA_IACK_SC		_MCPCIA_IACK_SC(0)
+#define MCPCIA_IO_BIAS		MCPCIA_IO(4)
+#define MCPCIA_MEM_BIAS		MCPCIA_DENSE(4)
+
 
 /*
  * Data structure for handling MCPCIA machine checks:
@@ -215,54 +232,79 @@
 
 __EXTERN_INLINE unsigned int mcpcia_inb(unsigned long in_addr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	long result = *(vip) ((addr << 5) + MCPCIA_IO(hose) + 0x00);
+	unsigned long addr, hose, result;
+
+	addr = in_addr & 0xffffUL;
+	hose = in_addr & ~0xffffUL;
+
+	/* ??? I wish I could get rid of this.  But there's no ioremap
+	   equivalent for I/O space.  PCI I/O can be forced into the
+	   correct hose's I/O region, but that doesn't take care of
+	   legacy ISA crap.  */
+	hose += MCPCIA_IO_BIAS;
+
+	result = *(vip) ((addr << 5) + hose + 0x00);
 	return __kernel_extbl(result, addr & 3);
 }
 
 __EXTERN_INLINE void mcpcia_outb(unsigned char b, unsigned long in_addr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	unsigned long w;
+	unsigned long addr, hose, w;
+
+	addr = in_addr & 0xffffUL;
+	hose = in_addr & ~0xffffUL;
+	hose += MCPCIA_IO_BIAS;
 
 	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x00) = w;
+	*(vuip) ((addr << 5) + hose + 0x00) = w;
 	mb();
 }
 
 __EXTERN_INLINE unsigned int mcpcia_inw(unsigned long in_addr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	long result = *(vip) ((addr << 5) + MCPCIA_IO(hose) + 0x08);
+	unsigned long addr, hose, result;
+
+	addr = in_addr & 0xffffUL;
+	hose = in_addr & ~0xffffUL;
+	hose += MCPCIA_IO_BIAS;
+
+	result = *(vip) ((addr << 5) + hose + 0x08);
 	return __kernel_extwl(result, addr & 3);
 }
 
 __EXTERN_INLINE void mcpcia_outw(unsigned short b, unsigned long in_addr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	unsigned long w;
+	unsigned long addr, hose, w;
+
+	addr = in_addr & 0xffffUL;
+	hose = in_addr & ~0xffffUL;
+	hose += MCPCIA_IO_BIAS;
 
 	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x08) = w;
+	*(vuip) ((addr << 5) + hose + 0x08) = w;
 	mb();
 }
 
 __EXTERN_INLINE unsigned int mcpcia_inl(unsigned long in_addr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	return *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x18);
+	unsigned long addr, hose;
+
+	addr = in_addr & 0xffffUL;
+	hose = in_addr & ~0xffffUL;
+	hose += MCPCIA_IO_BIAS;
+
+	return *(vuip) ((addr << 5) + hose + 0x18);
 }
 
 __EXTERN_INLINE void mcpcia_outl(unsigned int b, unsigned long in_addr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	*(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x18) = b;
+	unsigned long addr, hose;
+
+	addr = in_addr & 0xffffUL;
+	hose = in_addr & ~0xffffUL;
+	hose += MCPCIA_IO_BIAS;
+
+	*(vuip) ((addr << 5) + hose + 0x18) = b;
 	mb();
 }
 
@@ -299,234 +341,107 @@
  *
  */
 
-__EXTERN_INLINE unsigned long mcpcia_ioremap(unsigned long in_addr)
+__EXTERN_INLINE unsigned long mcpcia_ioremap(unsigned long addr)
 {
-	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	return addr + MCPCIA_DENSE(hose);
+	return addr + MCPCIA_MEM_BIAS;
 }
 
 __EXTERN_INLINE int mcpcia_is_ioaddr(unsigned long addr)
 {
-	return addr >= IDENT_ADDR + 0x8000000000UL;
-}
-
-__EXTERN_INLINE unsigned long mcpcia_srm_base(unsigned long addr)
-{
-	unsigned long mask, base;
-	unsigned long hose = (addr >> 32) & 3;
-
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
-
-	addr &= 0xfffffffful;
-	if (addr >= alpha_mv.sm_base_r1
-	    && addr <= alpha_mv.sm_base_r1 + MCPCIA_MEM_MASK) {
-		mask = MCPCIA_MEM_MASK;
-		base = MCPCIA_SPARSE(hose);
-	}
-	else
-	{
-#if 0
-	  printk("mcpcia: address 0x%lx not covered by HAE\n", addr);
-#endif
-	  return 0;
-	}
-
-	return ((addr & mask) << 5) + base;
-}
-
-__EXTERN_INLINE unsigned long mcpcia_srm_readb(unsigned long addr)
-{
-	unsigned long result, work;
-
-	if ((work = mcpcia_srm_base(addr)) == 0)
-		return 0xff;
-	work += 0x00;	/* add transfer length */
-
-	result = *(vip)work;
-	return __kernel_extbl(result, addr & 3);
-}
-
-__EXTERN_INLINE unsigned long mcpcia_srm_readw(unsigned long addr)
-{
-	unsigned long result, work;
-
-	if ((work = mcpcia_srm_base(addr)) == 0)
-		return 0xffff;
-	work += 0x08;	/* add transfer length */
-
-	result = *(vip) work;
-	return __kernel_extwl(result, addr & 3);
-}
-
-__EXTERN_INLINE void mcpcia_srm_writeb(unsigned char b, unsigned long addr)
-{
-	unsigned long w, work = mcpcia_srm_base(addr);
-	if (work) {
-		work += 0x00;	/* add transfer length */
-		w = __kernel_insbl(b, addr & 3);
-		*(vuip)work = w;
-	}
-}
-
-__EXTERN_INLINE void mcpcia_srm_writew(unsigned short b, unsigned long addr)
-{
-	unsigned long w, work = mcpcia_srm_base(addr);
-	if (work) {
-		work += 0x08;	/* add transfer length */
-		w = __kernel_inswl(b, addr & 3);
-		*(vuip)work = w;
-	}
+	return addr >= MCPCIA_SPARSE(0);
 }
 
 __EXTERN_INLINE unsigned long mcpcia_readb(unsigned long in_addr)
 {
-	/* Note that MCPCIA_DENSE(hose) has no bits not masked here, and
-	   that the hose calculation is still correct.  */
 	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	unsigned long result, msb, work, temp;
-
-#if __DEBUG_IOREMAP
-	if (in_addr <= 0x1000000000) {
-		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
+	unsigned long hose = in_addr & ~0xffffffffUL;
+	unsigned long result, work;
 
+#if !MCPCIA_ONE_HAE_WINDOW
+	unsigned long msb;
 	msb = addr & ~MCPCIA_MEM_MASK;
-	temp = addr & MCPCIA_MEM_MASK;
 	set_hae(msb);
+#endif
+	addr = addr & MCPCIA_MEM_MASK;
 
-	work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x00);
+	hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);
+	work = ((addr << 5) + hose + 0x00);
 	result = *(vip) work;
 	return __kernel_extbl(result, addr & 3);
 }
 
 __EXTERN_INLINE unsigned long mcpcia_readw(unsigned long in_addr)
 {
-	/* Note that MCPCIA_DENSE(hose) has no bits not masked here, and
-	   that the hose calculation is still correct.  */
 	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	unsigned long result, msb, work, temp;
-
-#if __DEBUG_IOREMAP
-	if (in_addr <= 0x1000000000) {
-		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
+	unsigned long hose = in_addr & ~0xffffffffUL;
+	unsigned long result, work;
 
+#if !MCPCIA_ONE_HAE_WINDOW
+	unsigned long msb;
 	msb = addr & ~MCPCIA_MEM_MASK;
-	temp = addr & MCPCIA_MEM_MASK;
 	set_hae(msb);
+#endif
+	addr = addr & MCPCIA_MEM_MASK;
 
-	work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x08);
+	hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);
+	work = ((addr << 5) + hose + 0x08);
 	result = *(vip) work;
 	return __kernel_extwl(result, addr & 3);
 }
 
 __EXTERN_INLINE void mcpcia_writeb(unsigned char b, unsigned long in_addr)
 {
-	/* Note that MCPCIA_DENSE(hose) has no bits not masked here, and
-	   that the hose calculation is still correct.  */
 	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	unsigned long msb, w;
-
-#if __DEBUG_IOREMAP
-	if (in_addr <= 0x1000000000) {
-		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
+	unsigned long hose = in_addr & ~0xffffffffUL;
+	unsigned long w;
 
+#if !MCPCIA_ONE_HAE_WINDOW
+	unsigned long msb;
 	msb = addr & ~MCPCIA_MEM_MASK;
-	addr &= MCPCIA_MEM_MASK;
 	set_hae(msb);
+#endif
+	addr = addr & MCPCIA_MEM_MASK;
 
 	w = __kernel_insbl(b, in_addr & 3);
-	*(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x00) = w;
+	hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);
+	*(vuip) ((addr << 5) + hose + 0x00) = w;
 }
 
 __EXTERN_INLINE void mcpcia_writew(unsigned short b, unsigned long in_addr)
 {
-	/* Note that MCPCIA_DENSE(hose) has no bits not masked here, and
-	   that the hose calculation is still correct.  */
 	unsigned long addr = in_addr & 0xffffffffUL;
-	unsigned long hose = (in_addr >> 32) & 3;
-	unsigned long msb, w;
-
-#if __DEBUG_IOREMAP
-	if (in_addr <= 0x1000000000) {
-		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
+	unsigned long hose = in_addr & ~0xffffffffUL;
+	unsigned long w;
 
+#if !MCPCIA_ONE_HAE_WINDOW
+	unsigned long msb;
 	msb = addr & ~MCPCIA_MEM_MASK;
-	addr &= MCPCIA_MEM_MASK;
 	set_hae(msb);
+#endif
+	addr = addr & MCPCIA_MEM_MASK;
 
 	w = __kernel_inswl(b, in_addr & 3);
-	*(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x08) = w;
+	hose = hose - MCPCIA_DENSE(4) + MCPCIA_SPARSE(4);
+	*(vuip) ((addr << 5) + hose + 0x08) = w;
 }
 
 __EXTERN_INLINE unsigned long mcpcia_readl(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr = mcpcia_ioremap(addr);
-	}
-#endif
-
 	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long mcpcia_readq(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr = mcpcia_ioremap(addr);
-	}
-#endif
-
 	return *(vulp)addr;
 }
 
 __EXTERN_INLINE void mcpcia_writel(unsigned int b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr = mcpcia_ioremap(addr);
-	}
-#endif
-
 	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void mcpcia_writeq(unsigned long b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "mcpcia: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr = mcpcia_ioremap(addr);
-	}
-#endif
-
 	*(vulp)addr = b;
 }
 
@@ -547,22 +462,14 @@
 #define __outb		mcpcia_outb
 #define __outw		mcpcia_outw
 #define __outl		mcpcia_outl
-#ifdef CONFIG_ALPHA_SRM_SETUP
-# define __readb	mcpcia_srm_readb
-# define __readw	mcpcia_srm_readw
-# define __writeb	mcpcia_srm_writeb
-# define __writew	mcpcia_srm_writew
-#else
-# define __readb	mcpcia_readb
-# define __readw	mcpcia_readw
-# define __writeb	mcpcia_writeb
-# define __writew	mcpcia_writew
-#endif
+#define __readb		mcpcia_readb
+#define __readw		mcpcia_readw
+#define __writeb	mcpcia_writeb
+#define __writew	mcpcia_writew
 #define __readl		mcpcia_readl
 #define __readq		mcpcia_readq
 #define __writel	mcpcia_writel
 #define __writeq	mcpcia_writeq
-
 #define __ioremap	mcpcia_ioremap
 #define __is_ioaddr	mcpcia_is_ioaddr
 
@@ -571,12 +478,10 @@
 # define outb(x, port) \
   (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
 
-#if !__DEBUG_IOREMAP
 #define __raw_readl(a)		__readl((unsigned long)(a))
 #define __raw_readq(a)		__readq((unsigned long)(a))
 #define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
 #define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
-#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/core_polaris.h linux/include/asm-alpha/core_polaris.h
--- v2.3.15/linux/include/asm-alpha/core_polaris.h	Mon Aug 16 10:33:58 1999
+++ linux/include/asm-alpha/core_polaris.h	Tue Aug 31 11:32:15 1999
@@ -41,16 +41,9 @@
  * supports transfers of all sizes in dense space.
  */
 
-#define POLARIS_DMA_WIN_BASE_DEFAULT	0x80000000	/* fixed, 2G @ 2G */
-#define POLARIS_DMA_WIN_SIZE_DEFAULT	0x80000000	/* fixed, 2G @ 2G */
+#define POLARIS_DMA_WIN_BASE	0x80000000UL	/* fixed, 2G @ 2G */
+#define POLARIS_DMA_WIN_SIZE	0x80000000UL	/* fixed, 2G @ 2G */
 
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-#define POLARIS_DMA_WIN_BASE		alpha_mv.dma_win_base
-#define POLARIS_DMA_WIN_SIZE		alpha_mv.dma_win_size
-#else
-#define POLARIS_DMA_WIN_BASE		POLARIS_DMA_WIN_BASE_DEFAULT
-#define POLARIS_DMA_WIN_SIZE		POLARIS_DMA_WIN_SIZE_DEFAULT
-#endif
 
 /*
  * Data structure for handling POLARIS machine checks:
@@ -96,6 +89,11 @@
 
 __EXTERN_INLINE unsigned int polaris_inb(unsigned long addr)
 {
+	/* ??? I wish I could get rid of this.  But there's no ioremap
+	   equivalent for I/O space.  PCI I/O can be forced into the
+	   POLARIS I/O region, but that doesn't take care of legacy
+	   ISA crap.  */
+
 	return __kernel_ldbu(*(vucp)(addr + POLARIS_DENSE_IO_BASE));
 }
 
@@ -136,116 +134,52 @@
 
 __EXTERN_INLINE unsigned long polaris_readb(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += POLARIS_DENSE_MEM_BASE;
-	}
-#endif
-
 	return __kernel_ldbu(*(vucp)addr);
 }
 
 __EXTERN_INLINE unsigned long polaris_readw(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += POLARIS_DENSE_MEM_BASE;
-	}
-#endif
-
 	return __kernel_ldwu(*(vusp)addr);
 }
 
 __EXTERN_INLINE unsigned long polaris_readl(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += POLARIS_DENSE_MEM_BASE;
-	}
-#endif
-
 	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long polaris_readq(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += POLARIS_DENSE_MEM_BASE;
-	}
-#endif
-
 	return *(vulp)addr;
 }
 
 __EXTERN_INLINE void polaris_writeb(unsigned char b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += POLARIS_DENSE_MEM_BASE;
-	}
-#endif
-
 	__kernel_stb(b, *(vucp)addr);
 }
 
 __EXTERN_INLINE void polaris_writew(unsigned short b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += POLARIS_DENSE_MEM_BASE;
-	}
-#endif
-
 	__kernel_stw(b, *(vusp)addr);
 }
 
 __EXTERN_INLINE void polaris_writel(unsigned int b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += POLARIS_DENSE_MEM_BASE;
-	}
-#endif
-
 	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void polaris_writeq(unsigned long b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "polaris: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += POLARIS_DENSE_MEM_BASE;
-	}
-#endif
-
 	*(vulp)addr = b;
 }
 
 __EXTERN_INLINE unsigned long polaris_ioremap(unsigned long addr)
 {
-	return POLARIS_DENSE_MEM_BASE + addr;
+	return addr + POLARIS_DENSE_MEM_BASE;
 }
 
 __EXTERN_INLINE int polaris_is_ioaddr(unsigned long addr)
 {
-	return addr >= IDENT_ADDR + 0x8000000000UL;
+	return addr >= POLARIS_SPARSE_MEM_BASE;
 }
 
 #undef vucp
@@ -275,24 +209,21 @@
 #define __ioremap       polaris_ioremap
 #define __is_ioaddr	polaris_is_ioaddr
 
-#define inb(port) __inb((port))
-#define inw(port) __inw((port))
-#define inl(port) __inl((port))
-
-#define outb(v, port) __outb((v),(port))
-#define outw(v, port) __outw((v),(port))
-#define outl(v, port) __outl((v),(port))
+#define inb(port)	__inb((port))
+#define inw(port)	__inw((port))
+#define inl(port)	__inl((port))
+#define outb(v, port)	__outb((v),(port))
+#define outw(v, port)	__outw((v),(port))
+#define outl(v, port)	__outl((v),(port))
 
-#if !__DEBUG_IOREMAP
 #define __raw_readb(a)		__readb((unsigned long)(a))
 #define __raw_readw(a)		__readw((unsigned long)(a))
 #define __raw_readl(a)		__readl((unsigned long)(a))
 #define __raw_readq(a)		__readq((unsigned long)(a))
 #define __raw_writeb(v,a)	__writeb((v),(unsigned long)(a))
-#define __raw_writeb(v,a)	__writew((v),(unsigned long)(a))
+#define __raw_writew(v,a)	__writew((v),(unsigned long)(a))
 #define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
 #define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
-#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/core_pyxis.h linux/include/asm-alpha/core_pyxis.h
--- v2.3.15/linux/include/asm-alpha/core_pyxis.h	Mon Aug 16 10:33:58 1999
+++ linux/include/asm-alpha/core_pyxis.h	Tue Aug 31 11:32:12 1999
@@ -72,8 +72,8 @@
 #define PYXIS_MEM_R2_MASK 0x07ffffff  /* SPARSE Mem region 2 mask is 27 bits */
 #define PYXIS_MEM_R3_MASK 0x03ffffff  /* SPARSE Mem region 3 mask is 26 bits */
 
-#define PYXIS_DMA_WIN_BASE_DEFAULT	(1UL*1024*1024*1024)
-#define PYXIS_DMA_WIN_SIZE_DEFAULT	(2UL*1024*1024*1024)
+#define PYXIS_DMA_WIN_BASE		(1UL*1024*1024*1024)
+#define PYXIS_DMA_WIN_SIZE		(2UL*1024*1024*1024)
 
 /* Window 0 at 1GB size 1GB mapping 0 */
 #define PYXIS_DMA_WIN0_BASE_DEFAULT	(1UL*1024*1024*1024)
@@ -85,13 +85,6 @@
 #define PYXIS_DMA_WIN1_SIZE_DEFAULT	(1UL*1024*1024*1024)
 #define PYXIS_DMA_WIN1_TRAN_DEFAULT	(1UL*1024*1024*1024)
 
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-#define PYXIS_DMA_WIN_BASE		alpha_mv.dma_win_base
-#define PYXIS_DMA_WIN_SIZE		alpha_mv.dma_win_size
-#else
-#define PYXIS_DMA_WIN_BASE		PYXIS_DMA_WIN_BASE_DEFAULT
-#define PYXIS_DMA_WIN_SIZE		PYXIS_DMA_WIN_SIZE_DEFAULT
-#endif
 
 /*
  *  General Registers
@@ -293,77 +286,40 @@
 #define vuip	volatile unsigned int *
 #define vulp	volatile unsigned long *
 
-__EXTERN_INLINE unsigned int pyxis_bw_inb(unsigned long addr)
-{
-	return __kernel_ldbu(*(vucp)(addr+PYXIS_BW_IO));
-}
-
-__EXTERN_INLINE void pyxis_bw_outb(unsigned char b, unsigned long addr)
-{
-	__kernel_stb(b, *(vucp)(addr+PYXIS_BW_IO));
-	mb();
-}
-
-__EXTERN_INLINE unsigned int pyxis_bw_inw(unsigned long addr)
-{
-	return __kernel_ldwu(*(vusp)(addr+PYXIS_BW_IO));
-}
-
-__EXTERN_INLINE void pyxis_bw_outw(unsigned short b, unsigned long addr)
-{
-	__kernel_stw(b, *(vusp)(addr+PYXIS_BW_IO));
-	mb();
-}
-
-__EXTERN_INLINE unsigned int pyxis_bw_inl(unsigned long addr)
-{
-	return *(vuip)(addr+PYXIS_BW_IO);
-}
-
-__EXTERN_INLINE void pyxis_bw_outl(unsigned int b, unsigned long addr)
-{
-	*(vuip)(addr+PYXIS_BW_IO) = b;
-	mb();
-}
-
 __EXTERN_INLINE unsigned int pyxis_inb(unsigned long addr)
 {
-	long result = *(vip) ((addr << 5) + PYXIS_IO + 0x00);
-	return __kernel_extbl(result, addr & 3);
+	/* ??? I wish I could get rid of this.  But there's no ioremap
+	   equivalent for I/O space.  PCI I/O can be forced into the
+	   PYXIS I/O region, but that doesn't take care of legacy ISA crap.  */
+
+	return __kernel_ldbu(*(vucp)(addr+PYXIS_BW_IO));
 }
 
 __EXTERN_INLINE void pyxis_outb(unsigned char b, unsigned long addr)
 {
-	unsigned long w;
-
-	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + PYXIS_IO + 0x00) = w;
+	__kernel_stb(b, *(vucp)(addr+PYXIS_BW_IO));
 	mb();
 }
 
 __EXTERN_INLINE unsigned int pyxis_inw(unsigned long addr)
 {
-	long result = *(vip) ((addr << 5) + PYXIS_IO + 0x08);
-	return __kernel_extwl(result, addr & 3);
+	return __kernel_ldwu(*(vusp)(addr+PYXIS_BW_IO));
 }
 
 __EXTERN_INLINE void pyxis_outw(unsigned short b, unsigned long addr)
 {
-	unsigned long w;
-
-	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + PYXIS_IO + 0x08) = w;
+	__kernel_stw(b, *(vusp)(addr+PYXIS_BW_IO));
 	mb();
 }
 
 __EXTERN_INLINE unsigned int pyxis_inl(unsigned long addr)
 {
-	return *(vuip) ((addr << 5) + PYXIS_IO + 0x18);
+	return *(vuip)(addr+PYXIS_BW_IO);
 }
 
 __EXTERN_INLINE void pyxis_outl(unsigned int b, unsigned long addr)
 {
-	*(vuip) ((addr << 5) + PYXIS_IO + 0x18) = b;
+	*(vuip)(addr+PYXIS_BW_IO) = b;
 	mb();
 }
 
@@ -400,344 +356,54 @@
  *
  */
 
-__EXTERN_INLINE unsigned long pyxis_bw_readb(unsigned long addr)
+__EXTERN_INLINE unsigned long pyxis_readb(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_BW_MEM;
-	}
-#endif
-
 	return __kernel_ldbu(*(vucp)addr);
 }
 
-__EXTERN_INLINE unsigned long pyxis_bw_readw(unsigned long addr)
+__EXTERN_INLINE unsigned long pyxis_readw(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_BW_MEM;
-	}
-#endif
-
 	return __kernel_ldwu(*(vusp)addr);
 }
 
-__EXTERN_INLINE unsigned long pyxis_bw_readl(unsigned long addr)
+__EXTERN_INLINE unsigned long pyxis_readl(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_BW_MEM;
-	}
-#endif
-
 	return *(vuip)addr;
 }
 
-__EXTERN_INLINE unsigned long pyxis_bw_readq(unsigned long addr)
+__EXTERN_INLINE unsigned long pyxis_readq(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_BW_MEM;
-	}
-#endif
-
 	return *(vulp)addr;
 }
 
-__EXTERN_INLINE void pyxis_bw_writeb(unsigned char b, unsigned long addr)
-{
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_BW_MEM;
-	}
-#endif
-
-	__kernel_stb(b, *(vucp)addr);
-}
-
-__EXTERN_INLINE void pyxis_bw_writew(unsigned short b, unsigned long addr)
-{
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_BW_MEM;
-	}
-#endif
-
-	__kernel_stw(b, *(vusp)addr);
-}
-
-__EXTERN_INLINE void pyxis_bw_writel(unsigned int b, unsigned long addr)
-{
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_BW_MEM;
-	}
-#endif
-
-	*(vuip)addr = b;
-}
-
-__EXTERN_INLINE void pyxis_bw_writeq(unsigned long b, unsigned long addr)
-{
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_BW_MEM;
-	}
-#endif
-
-	*(vulp)addr = b;
-}
-
-__EXTERN_INLINE unsigned long pyxis_bw_ioremap(unsigned long addr)
-{
-	return PYXIS_BW_MEM + addr;
-}
-
-__EXTERN_INLINE unsigned long pyxis_srm_base(unsigned long addr)
-{
-	unsigned long mask, base;
-
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_BW_MEM;
-	}
-#endif
-
-	addr -= PYXIS_BW_MEM;
-	if (addr >= alpha_mv.sm_base_r1
-	    && addr <= alpha_mv.sm_base_r1 + PYXIS_MEM_R1_MASK) {
-		mask = PYXIS_MEM_R1_MASK;
-		base = PYXIS_SPARSE_MEM;
-	}
-	else if (addr >= alpha_mv.sm_base_r2
-		 && addr <= alpha_mv.sm_base_r2 + PYXIS_MEM_R2_MASK) {
-		mask = PYXIS_MEM_R2_MASK;
-		base = PYXIS_SPARSE_MEM_R2;
-	}
-	else if (addr >= alpha_mv.sm_base_r3
-		 && addr <= alpha_mv.sm_base_r3 + PYXIS_MEM_R3_MASK) {
-		mask = PYXIS_MEM_R3_MASK;
-		base = PYXIS_SPARSE_MEM_R3;
-	}
-	else
-	{
-#if 0
-	  printk("pyxis: address 0x%lx not covered by HAE\n", addr);
-#endif
-	  return 0;
-	}
-
-	return ((addr & mask) << 5) + base;
-}
-
-__EXTERN_INLINE unsigned long pyxis_srm_readb(unsigned long addr)
-{
-	unsigned long result, work;
-
-	if ((work = pyxis_srm_base(addr)) == 0)
-		return 0xff;
-	work += 0x00;	/* add transfer length */
-
-	result = *(vip) work;
-	return __kernel_extbl(result, addr & 3);
-}
-
-__EXTERN_INLINE unsigned long pyxis_srm_readw(unsigned long addr)
-{
-	unsigned long result, work;
-
-	if ((work = pyxis_srm_base(addr)) == 0)
-		return 0xffff;
-	work += 0x08;	/* add transfer length */
-
-	result = *(vip) work;
-	return __kernel_extwl(result, addr & 3);
-}
-
-__EXTERN_INLINE void pyxis_srm_writeb(unsigned char b, unsigned long addr)
-{
-	unsigned long w, work = pyxis_srm_base(addr);
-	if (work) {
-		work += 0x00;	/* add transfer length */
-		w = __kernel_insbl(b, addr & 3);
-		*(vuip)work = w;
-	}
-}
-
-__EXTERN_INLINE void pyxis_srm_writew(unsigned short b, unsigned long addr)
-{
-	unsigned long w, work = pyxis_srm_base(addr);
-	if (work) {
-		work += 0x08;	/* add transfer length */
-		w = __kernel_inswl(b, addr & 3);
-		*(vuip)work = w;
-	}
-}
-
-__EXTERN_INLINE unsigned long pyxis_readb(unsigned long addr)
-{
-	unsigned long result, msb, work, temp;
-
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
-
-	/* Note that PYXIS_DENSE_MEM has no bits not masked in these
-	   operations, so we don't have to subtract it back out.  */
-	msb = addr & 0xE0000000UL;
-	temp = addr & PYXIS_MEM_R1_MASK;
-	set_hae(msb);
-
-	work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x00);
-	result = *(vip) work;
-	return __kernel_extbl(result, addr & 3);
-}
-
-__EXTERN_INLINE unsigned long pyxis_readw(unsigned long addr)
-{
-	unsigned long result, msb, work, temp;
-
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
-
-	/* Note that PYXIS_DENSE_MEM has no bits not masked in these
-	   operations, so we don't have to subtract it back out.  */
-	msb = addr & 0xE0000000UL;
-	temp = addr & PYXIS_MEM_R1_MASK;
-	set_hae(msb);
-
-	work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x08);
-	result = *(vip) work;
-	return __kernel_extwl(result, addr & 3);
-}
-
 __EXTERN_INLINE void pyxis_writeb(unsigned char b, unsigned long addr)
 {
-	unsigned long msb, w;
-
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
-
-	/* Note that PYXIS_DENSE_MEM has no bits not masked in these
-	   operations, so we don't have to subtract it back out.  */
-	msb = addr & 0xE0000000;
-	addr &= PYXIS_MEM_R1_MASK;
-	set_hae(msb);
-
-	w = __kernel_insbl(b, addr & 3);
-	*(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x00) = w;
+	__kernel_stb(b, *(vucp)addr);
 }
 
 __EXTERN_INLINE void pyxis_writew(unsigned short b, unsigned long addr)
 {
-	unsigned long msb, w;
-
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-	}
-#endif
-
-	/* Note that PYXIS_DENSE_MEM has no bits not masked in these
-	   operations, so we don't have to subtract it back out.  */
-	msb = addr & 0xE0000000;
-	addr &= PYXIS_MEM_R1_MASK;
-	set_hae(msb);
-
-	w = __kernel_inswl(b, addr & 3);
-	*(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x08) = w;
-}
-
-__EXTERN_INLINE unsigned long pyxis_readl(unsigned long addr)
-{
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_DENSE_MEM;
-	}
-#endif
-
-	return *(vuip)addr;
-}
-
-__EXTERN_INLINE unsigned long pyxis_readq(unsigned long addr)
-{
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_DENSE_MEM;
-	}
-#endif
-
-	return *(vulp)addr;
+	__kernel_stw(b, *(vusp)addr);
 }
 
 __EXTERN_INLINE void pyxis_writel(unsigned int b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_DENSE_MEM;
-	}
-#endif
-
 	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void pyxis_writeq(unsigned long b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x100000000) {
-		printk(KERN_CRIT "pyxis: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr += PYXIS_DENSE_MEM;
-	}
-#endif
-
 	*(vulp)addr = b;
 }
 
 __EXTERN_INLINE unsigned long pyxis_ioremap(unsigned long addr)
 {
-	return PYXIS_DENSE_MEM + addr;
+	return addr + PYXIS_BW_MEM;
 }
 
 __EXTERN_INLINE int pyxis_is_ioaddr(unsigned long addr)
 {
-	return addr >= IDENT_ADDR + 0x8000000000UL;
+	return addr >= IDENT_ADDR + 0x8740000000UL;
 }
 
 #undef vucp
@@ -751,75 +417,37 @@
 #define virt_to_bus	pyxis_virt_to_bus
 #define bus_to_virt	pyxis_bus_to_virt
 
-#if defined(BWIO_ENABLED) && !defined(CONFIG_ALPHA_RUFFIAN)
-# define __inb		pyxis_bw_inb
-# define __inw		pyxis_bw_inw
-# define __inl		pyxis_bw_inl
-# define __outb		pyxis_bw_outb
-# define __outw		pyxis_bw_outw
-# define __outl		pyxis_bw_outl
-# define __readb	pyxis_bw_readb
-# define __readw	pyxis_bw_readw
-# define __writeb	pyxis_bw_writeb
-# define __writew	pyxis_bw_writew
-# define __readl	pyxis_bw_readl
-# define __readq	pyxis_bw_readq
-# define __writel	pyxis_bw_writel
-# define __writeq	pyxis_bw_writeq
-# define __ioremap	pyxis_bw_ioremap
-#else
-# define __inb		pyxis_inb
-# define __inw		pyxis_inw
-# define __inl		pyxis_inl
-# define __outb		pyxis_outb
-# define __outw		pyxis_outw
-# define __outl		pyxis_outl
-# ifdef CONFIG_ALPHA_SRM_SETUP
-#  define __readb	pyxis_srm_readb
-#  define __readw	pyxis_srm_readw
-#  define __writeb	pyxis_srm_writeb
-#  define __writew	pyxis_srm_writew
-# else
-#  define __readb	pyxis_readb
-#  define __readw	pyxis_readw
-#  define __writeb	pyxis_writeb
-#  define __writew	pyxis_writew
-# endif
-# define __readl	pyxis_readl
-# define __readq	pyxis_readq
-# define __writel	pyxis_writel
-# define __writeq	pyxis_writeq
-# define __ioremap	pyxis_ioremap
-#endif /* BWIO */
-
+#define __inb		pyxis_inb
+#define __inw		pyxis_inw
+#define __inl		pyxis_inl
+#define __outb		pyxis_outb
+#define __outw		pyxis_outw
+#define __outl		pyxis_outl
+#define __readb		pyxis_readb
+#define __readw		pyxis_readw
+#define __writeb	pyxis_writeb
+#define __writew	pyxis_writew
+#define __readl		pyxis_readl
+#define __readq		pyxis_readq
+#define __writel	pyxis_writel
+#define __writeq	pyxis_writeq
+#define __ioremap	pyxis_ioremap
 #define __is_ioaddr	pyxis_is_ioaddr
 
-#if defined(BWIO_ENABLED) && !defined(CONFIG_ALPHA_RUFFIAN)
-# define inb(port)		__inb((port))
-# define inw(port)		__inw((port))
-# define inl(port)		__inl((port))
-# define outb(x, port)		__outb((x),(port))
-# define outw(x, port)		__outw((x),(port))
-# define outl(x, port)		__outl((x),(port))
-# if !__DEBUG_IOREMAP
-#  define __raw_readb(addr)	__readb((addr))
-#  define __raw_readw(addr)	__readw((addr))
-#  define __raw_writeb(b, addr)	__writeb((b),(addr))
-#  define __raw_writeb(b, addr)	__writew((b),(addr))
-# endif
-#else
-# define inb(port) \
-  (__builtin_constant_p((port))?__inb(port):_inb(port))
-# define outb(x, port) \
-  (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
-#endif /* BWIO */
-
-#if !__DEBUG_IOREMAP
+#define inb(port)		__inb((port))
+#define inw(port)		__inw((port))
+#define inl(port)		__inl((port))
+#define outb(x, port)		__outb((x),(port))
+#define outw(x, port)		__outw((x),(port))
+#define outl(x, port)		__outl((x),(port))
+#define __raw_readb(addr)	__readb((addr))
+#define __raw_readw(addr)	__readw((addr))
+#define __raw_writeb(b, addr)	__writeb((b),(addr))
+#define __raw_writew(b, addr)	__writew((b),(addr))
 #define __raw_readl(a)		__readl((unsigned long)(a))
 #define __raw_readq(a)		__readq((unsigned long)(a))
 #define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
 #define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
-#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/core_t2.h linux/include/asm-alpha/core_t2.h
--- v2.3.15/linux/include/asm-alpha/core_t2.h	Mon Aug 16 10:33:58 1999
+++ linux/include/asm-alpha/core_t2.h	Tue Aug 31 10:50:45 1999
@@ -21,16 +21,8 @@
 
 #define T2_MEM_R1_MASK 0x03ffffff  /* Mem sparse region 1 mask is 26 bits */
 
-#define T2_DMA_WIN_BASE_DEFAULT	(1024*1024*1024)
-#define T2_DMA_WIN_SIZE_DEFAULT	(1024*1024*1024)
-
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-#define T2_DMA_WIN_BASE		alpha_mv.dma_win_base
-#define T2_DMA_WIN_SIZE		alpha_mv.dma_win_size
-#else
-#define T2_DMA_WIN_BASE		T2_DMA_WIN_BASE_DEFAULT
-#define T2_DMA_WIN_SIZE		T2_DMA_WIN_SIZE_DEFAULT
-#endif
+#define T2_DMA_WIN_BASE		(1UL*1024*1024*1024)
+#define T2_DMA_WIN_SIZE		(1UL*1024*1024*1024)
 
 /* GAMMA-SABLE is a SABLE with EV5-based CPUs */
 #define _GAMMA_BIAS		0x8000000000UL
@@ -428,112 +420,6 @@
  *
  */
 
-__EXTERN_INLINE unsigned long t2_srm_base(unsigned long addr)
-{
-	if ((addr >= alpha_mv.sm_base_r1
-	     && addr <= alpha_mv.sm_base_r1 + T2_MEM_R1_MASK)
-	    || (addr >= 512*1024 && addr < 1024*1024)) {
-		return ((addr & T2_MEM_R1_MASK) << 5) + T2_SPARSE_MEM;
-	}
-#if 0
-	printk("T2: address 0x%lx not covered by HAE\n", addr);
-#endif
-	return 0;
-}
-
-__EXTERN_INLINE unsigned long t2_srm_readb(unsigned long addr)
-{
-	unsigned long result, work;
-
-	if ((work = t2_srm_base(addr)) == 0)
-		return 0xff;
-	work += 0x00;	/* add transfer length */
-
-	result = *(vip) work;
-	return __kernel_extbl(result, addr & 3);
-}
-
-__EXTERN_INLINE unsigned long t2_srm_readw(unsigned long addr)
-{
-	unsigned long result, work;
-
-	if ((work = t2_srm_base(addr)) == 0)
-		return 0xffff;
-	work += 0x08;	/* add transfer length */
-
-	result = *(vip) work;
-	return __kernel_extwl(result, addr & 3);
-}
-
-/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */
-__EXTERN_INLINE unsigned long t2_srm_readl(unsigned long addr)
-{
-	unsigned long work;
-
-	if ((work = t2_srm_base(addr)) == 0)
-		return 0xffffffff;
-	work += 0x18;	/* add transfer length */
-
-	return *(vuip) work;
-}
-
-/* ... which makes me wonder why we advertise we have DENSE memory at all.
-   Anyway, guess that means we should emulate 64-bit access as two cycles.  */
-__EXTERN_INLINE unsigned long t2_srm_readq(unsigned long addr)
-{
-	unsigned long work, r0, r1;
-
-	if ((work = t2_srm_base(addr)) == 0)
-		return ~0UL;
-	work += 0x18;	/* add transfer length */
-
-	r0 = *(vuip) work;
-	r1 = *(vuip) (work + (4 << 5));
-	return r1 << 32 | r0;
-}
-
-__EXTERN_INLINE void t2_srm_writeb(unsigned char b, unsigned long addr)
-{
-	unsigned long w, work = t2_srm_base(addr);
-	if (work) {
-		work += 0x00;	/* add transfer length */
-		w = __kernel_insbl(b, addr & 3);
-		*(vuip) work = w;
-	}
-}
-
-__EXTERN_INLINE void t2_srm_writew(unsigned short b, unsigned long addr)
-{
-	unsigned long w, work = t2_srm_base(addr);
-	if (work) {
-		work += 0x08;	/* add transfer length */
-		w = __kernel_inswl(b, addr & 3);
-		*(vuip) work = w;
-	}
-}
-
-/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */
-__EXTERN_INLINE void t2_srm_writel(unsigned int b, unsigned long addr)
-{
-	unsigned long work = t2_srm_base(addr);
-	if (work) {
-		work += 0x18;	/* add transfer length */
-		*(vuip) work = b;
-	}
-}
-
-/* ... which makes me wonder why we advertise we have DENSE memory at all.
-   Anyway, guess that means we should emulate 64-bit access as two cycles.  */
-__EXTERN_INLINE void t2_srm_writeq(unsigned long b, unsigned long addr)
-{
-	unsigned long work = t2_srm_base(addr);
-	if (work) {
-		work += 0x18;	/* add transfer length */
-		*(vuip) work = b;
-		*(vuip) (work + (4 << 5)) = b >> 32;
-	}
-}
-
 __EXTERN_INLINE unsigned long t2_readb(unsigned long addr)
 {
 	unsigned long result, msb;
@@ -656,17 +542,6 @@
 #define __outb		t2_outb
 #define __outw		t2_outw
 #define __outl		t2_outl
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-#define __readb		t2_srm_readb
-#define __readw		t2_srm_readw
-#define __readl		t2_srm_readl
-#define __readq		t2_srm_readq
-#define __writeb	t2_srm_writeb
-#define __writew	t2_srm_writew
-#define __writel	t2_srm_writel
-#define __writeq	t2_srm_writeq
-#else
 #define __readb		t2_readb
 #define __readw		t2_readw
 #define __readl		t2_readl
@@ -675,16 +550,13 @@
 #define __writew	t2_writew
 #define __writel	t2_writel
 #define __writeq	t2_writeq
-#endif
-
 #define __ioremap	t2_ioremap
 #define __is_ioaddr	t2_is_ioaddr
 
 #define inb(port) \
-(__builtin_constant_p((port))?__inb(port):_inb(port))
-
+  (__builtin_constant_p((port))?__inb(port):_inb(port))
 #define outb(x, port) \
-(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
+  (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port)))
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/core_tsunami.h linux/include/asm-alpha/core_tsunami.h
--- v2.3.15/linux/include/asm-alpha/core_tsunami.h	Mon Aug 16 10:33:58 1999
+++ linux/include/asm-alpha/core_tsunami.h	Tue Aug 31 10:50:45 1999
@@ -24,8 +24,8 @@
  *
  * Sigh...
  */
-#define TSUNAMI_DMA_WIN_BASE_DEFAULT	(1UL*1024*1024*1024)
-#define TSUNAMI_DMA_WIN_SIZE_DEFAULT	(2UL*1024*1024*1024)
+#define TSUNAMI_DMA_WIN_BASE		(1UL*1024*1024*1024)
+#define TSUNAMI_DMA_WIN_SIZE		(2UL*1024*1024*1024)
 
 #define TSUNAMI_DMA_WIN0_BASE_DEFAULT	(1UL*1024*1024*1024)
 #define TSUNAMI_DMA_WIN0_SIZE_DEFAULT	(1UL*1024*1024*1024)
@@ -35,13 +35,6 @@
 #define TSUNAMI_DMA_WIN1_SIZE_DEFAULT	(1UL*1024*1024*1024)
 #define TSUNAMI_DMA_WIN1_TRAN_DEFAULT	(1UL*1024*1024*1024)
 
-#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
-#define TSUNAMI_DMA_WIN_BASE		alpha_mv.dma_win_base
-#define TSUNAMI_DMA_WIN_SIZE		alpha_mv.dma_win_size
-#else
-#define TSUNAMI_DMA_WIN_BASE		TSUNAMI_DMA_WIN_BASE_DEFAULT
-#define TSUNAMI_DMA_WIN_SIZE		TSUNAMI_DMA_WIN_SIZE_DEFAULT
-#endif
 
 /* XXX: Do we need to conditionalize on this?  */
 #ifdef USE_48_BIT_KSEG
@@ -279,14 +272,25 @@
 /*
  * Memory spaces:
  */
-#define HOSE(h) (((unsigned long)(h)) << 33)
+#define TSUNAMI_HOSE(h)		(((unsigned long)(h)) << 33)
+#define TSUNAMI_BASE		(IDENT_ADDR + TS_BIAS)
+
+#define TSUNAMI_MEM(h)		(TSUNAMI_BASE+TSUNAMI_HOSE(h) + 0x000000000UL)
+#define _TSUNAMI_IACK_SC(h)	(TSUNAMI_BASE+TSUNAMI_HOSE(h) + 0x1F8000000UL)
+#define TSUNAMI_IO(h)		(TSUNAMI_BASE+TSUNAMI_HOSE(h) + 0x1FC000000UL)
+#define TSUNAMI_CONF(h)		(TSUNAMI_BASE+TSUNAMI_HOSE(h) + 0x1FE000000UL)
+
+#define TSUNAMI_IACK_SC		_TSUNAMI_IACK_SC(0) /* hack! */
 
-#define TSUNAMI_MEM(h)	     (IDENT_ADDR + TS_BIAS + 0x000000000UL + HOSE(h))
-#define _TSUNAMI_IACK_SC(h)  (IDENT_ADDR + TS_BIAS + 0x1F8000000UL + HOSE(h))
-#define TSUNAMI_IO(h)	     (IDENT_ADDR + TS_BIAS + 0x1FC000000UL + HOSE(h))
-#define TSUNAMI_CONF(h)	     (IDENT_ADDR + TS_BIAS + 0x1FE000000UL + HOSE(h))
 
-#define TSUNAMI_IACK_SC	     _TSUNAMI_IACK_SC(0) /* hack! */
+/* 
+ * The canonical non-remaped I/O and MEM addresses have these values
+ * subtracted out.  This is arranged so that folks manipulating ISA
+ * devices can use their familiar numbers and have them map to bus 0.
+ */
+
+#define TSUNAMI_IO_BIAS          TSUNAMI_IO(0)
+#define TSUNAMI_MEM_BIAS         TSUNAMI_MEM(0)
 
 
 /*
@@ -329,39 +333,47 @@
 #define vuip	volatile unsigned int *
 #define vulp	volatile unsigned long *
 
-#define XADDR	((addr) & 0xffffffffUL)
-#define XHOSE	(((addr) >> 32) & 3UL)
-
 __EXTERN_INLINE unsigned int tsunami_inb(unsigned long addr)
 {
-	return __kernel_ldbu(*(vucp)(XADDR + TSUNAMI_IO(XHOSE)));
+	/* ??? I wish I could get rid of this.  But there's no ioremap
+	   equivalent for I/O space.  PCI I/O can be forced into the
+	   correct hose's I/O region, but that doesn't take care of
+	   legacy ISA crap.  */
+
+	addr += TSUNAMI_IO_BIAS;
+	return __kernel_ldbu(*(vucp)addr);
 }
 
 __EXTERN_INLINE void tsunami_outb(unsigned char b, unsigned long addr)
 {
-	__kernel_stb(b, *(vucp)(XADDR + TSUNAMI_IO(XHOSE)));
+	addr += TSUNAMI_IO_BIAS;
+	__kernel_stb(b, *(vucp)addr);
 	mb();
 }
 
 __EXTERN_INLINE unsigned int tsunami_inw(unsigned long addr)
 {
-	return __kernel_ldwu(*(vusp)(XADDR + TSUNAMI_IO(XHOSE)));
+	addr += TSUNAMI_IO_BIAS;
+	return __kernel_ldwu(*(vusp)addr);
 }
 
 __EXTERN_INLINE void tsunami_outw(unsigned short b, unsigned long addr)
 {
-	__kernel_stw(b, *(vusp)(XADDR + TSUNAMI_IO(XHOSE)));
+	addr += TSUNAMI_IO_BIAS;
+	__kernel_stw(b, *(vusp)addr);
 	mb();
 }
 
 __EXTERN_INLINE unsigned int tsunami_inl(unsigned long addr)
 {
-	return *(vuip)(XADDR + TSUNAMI_IO(XHOSE));
+	addr += TSUNAMI_IO_BIAS;
+	return *(vuip)addr;
 }
 
 __EXTERN_INLINE void tsunami_outl(unsigned int b, unsigned long addr)
 {
-	*(vuip)(XADDR + TSUNAMI_IO(XHOSE)) = b;
+	addr += TSUNAMI_IO_BIAS;
+	*(vuip)addr = b;
 	mb();
 }
 
@@ -371,115 +383,51 @@
 
 __EXTERN_INLINE unsigned long tsunami_ioremap(unsigned long addr)
 {
-	return XADDR + TSUNAMI_MEM(XHOSE);
+	return addr + TSUNAMI_MEM_BIAS;
 }
 
 __EXTERN_INLINE int tsunami_is_ioaddr(unsigned long addr)
 {
-	return addr >= IDENT_ADDR+TS_BIAS;
+	return addr >= TSUNAMI_BASE;
 }
 
 __EXTERN_INLINE unsigned long tsunami_readb(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr = tsunami_ioremap(addr);
-	}
-#endif
-
 	return __kernel_ldbu(*(vucp)addr);
 }
 
 __EXTERN_INLINE unsigned long tsunami_readw(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr = tsunami_ioremap(addr);
-	}
-#endif
-
 	return __kernel_ldwu(*(vusp)addr);
 }
 
 __EXTERN_INLINE unsigned long tsunami_readl(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr = tsunami_ioremap(addr);
-	}
-#endif
-
 	return *(vuip)addr;
 }
 
 __EXTERN_INLINE unsigned long tsunami_readq(unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr = tsunami_ioremap(addr);
-	}
-#endif
-
 	return *(vulp)addr;
 }
 
 __EXTERN_INLINE void tsunami_writeb(unsigned char b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr = tsunami_ioremap(addr);
-	}
-#endif
-
 	__kernel_stb(b, *(vucp)addr);
 }
 
 __EXTERN_INLINE void tsunami_writew(unsigned short b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr = tsunami_ioremap(addr);
-	}
-#endif
-
 	__kernel_stw(b, *(vusp)addr);
 }
 
 __EXTERN_INLINE void tsunami_writel(unsigned int b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr = tsunami_ioremap(addr);
-	}
-#endif
-
 	*(vuip)addr = b;
 }
 
 __EXTERN_INLINE void tsunami_writeq(unsigned long b, unsigned long addr)
 {
-#if __DEBUG_IOREMAP
-	if (addr <= 0x1000000000) {
-		printk(KERN_CRIT "tsunami: 0x%lx not ioremapped (%p)\n",
-		       addr, __builtin_return_address(0));
-		addr = tsunami_ioremap(addr);
-	}
-#endif
-
 	*(vulp)addr = b;
 }
 
@@ -488,9 +436,6 @@
 #undef vuip
 #undef vulp
 
-#undef XADDR
-#undef XHOSE
-
 #ifdef __WANT_IO_DEF
 
 #define virt_to_bus	tsunami_virt_to_bus
@@ -513,24 +458,21 @@
 #define __ioremap	tsunami_ioremap
 #define __is_ioaddr	tsunami_is_ioaddr
 
-#define inb(port) __inb((port))
-#define inw(port) __inw((port))
-#define inl(port) __inl((port))
-
-#define outb(v, port) __outb((v),(port))
-#define outw(v, port) __outw((v),(port))
-#define outl(v, port) __outl((v),(port))
+#define inb(port)	__inb((port))
+#define inw(port)	__inw((port))
+#define inl(port)	__inl((port))
+#define outb(v, port)	__outb((v),(port))
+#define outw(v, port)	__outw((v),(port))
+#define outl(v, port)	__outl((v),(port))
 
-#if !__DEBUG_IOREMAP
 #define __raw_readb(a)		__readb((unsigned long)(a))
 #define __raw_readw(a)		__readw((unsigned long)(a))
 #define __raw_readl(a)		__readl((unsigned long)(a))
 #define __raw_readq(a)		__readq((unsigned long)(a))
 #define __raw_writeb(v,a)	__writeb((v),(unsigned long)(a))
-#define __raw_writeb(v,a)	__writew((v),(unsigned long)(a))
+#define __raw_writew(v,a)	__writew((v),(unsigned long)(a))
 #define __raw_writel(v,a)	__writel((v),(unsigned long)(a))
 #define __raw_writeq(v,a)	__writeq((v),(unsigned long)(a))
-#endif
 
 #endif /* __WANT_IO_DEF */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/delay.h linux/include/asm-alpha/delay.h
--- v2.3.15/linux/include/asm-alpha/delay.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-alpha/delay.h	Tue Aug 31 10:50:45 1999
@@ -12,9 +12,13 @@
 extern __inline__ void
 __delay(unsigned long loops)
 {
-	__asm__ __volatile__(".align 3\n"
-		"1:\tsubq %0,1,%0\n\t"
-		"bge %0,1b": "=r" (loops) : "0" (loops));
+	register unsigned long r0 __asm__("$0") = loops;
+#ifdef MODULE
+	__asm__ __volatile__("lda $28,___delay; jsr $28,($28),0"
+			     : "=r"(r0) : "r"(r0) : "$28");
+#else
+	__asm__ __volatile__("bsr $28,___delay" : "=r"(r0) : "r"(r0) : "$28");
+#endif
 }
 
 /*
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- v2.3.15/linux/include/asm-alpha/io.h	Thu Aug 26 13:05:40 1999
+++ linux/include/asm-alpha/io.h	Tue Aug 31 10:50:45 1999
@@ -1,8 +1,6 @@
 #ifndef __ALPHA_IO_H
 #define __ALPHA_IO_H
 
-#define __DEBUG_IOREMAP 1
-
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/system.h>
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/machvec.h linux/include/asm-alpha/machvec.h
--- v2.3.15/linux/include/asm-alpha/machvec.h	Mon Aug 16 10:33:58 1999
+++ linux/include/asm-alpha/machvec.h	Tue Aug 31 10:50:45 1999
@@ -19,6 +19,8 @@
 struct pt_regs;
 struct vm_area_struct;
 struct linux_hose_info;
+struct pci_dev;
+struct pci_ops;
 
 struct alpha_machine_vector
 {
@@ -34,6 +36,8 @@
 	unsigned long max_dma_address;
 	unsigned long irq_probe_mask;
 	unsigned long iack_sc;
+	unsigned long min_io_address;
+	unsigned long min_mem_address;
 
 	unsigned long (*mv_virt_to_bus)(void *);
 	void * (*mv_bus_to_virt)(unsigned long);
@@ -59,20 +63,6 @@
 	unsigned long (*mv_ioremap)(unsigned long);
 	int (*mv_is_ioaddr)(unsigned long);
 
-	int (*hose_read_config_byte)(u8, u8, u8, u8 *value,
-				     struct linux_hose_info *);
-	int (*hose_read_config_word)(u8, u8, u8, u16 *value,
-				     struct linux_hose_info *);
-	int (*hose_read_config_dword)(u8, u8, u8, u32 *value,
-				      struct linux_hose_info *);
-
-	int (*hose_write_config_byte)(u8, u8, u8, u8 value,
-				      struct linux_hose_info *);
-	int (*hose_write_config_word)(u8, u8, u8, u16 value,
-				      struct linux_hose_info *);
-	int (*hose_write_config_dword)(u8, u8, u8, u32 value,
-				       struct linux_hose_info *);
-	
 	void (*mv_switch_mm)(struct mm_struct *, struct mm_struct *,
 			     struct task_struct *, long);
 	void (*mv_activate_mm)(struct mm_struct *, struct mm_struct *, long);
@@ -91,9 +81,13 @@
 	void (*init_arch)(unsigned long *, unsigned long *);
 	void (*init_irq)(void);
 	void (*init_pit)(void);
-	void (*pci_fixup)(void);
+	void (*init_pci)(void);
 	void (*kill_arch)(int, char *);
 
+	u8 (*pci_swizzle)(struct pci_dev *, u8 *);
+	int (*pci_map_irq)(struct pci_dev *, u8, u8);
+	struct pci_ops *pci_ops;
+
 	const char *vector_name;
 
 	/* System specific parameters.  */
@@ -105,29 +99,22 @@
 	    struct {
 		unsigned long gamma_bias;
 	    } t2;
-	} sys;
 
-	/* Runtime variables it is handy to keep close.  */
-	unsigned long dma_win_base;
-	unsigned long dma_win_size;
-	unsigned long sm_base_r1, sm_base_r2, sm_base_r3;
+	    struct {
+		unsigned int route_tab;
+	    } sio;
+	} sys;
 };
 
 extern struct alpha_machine_vector alpha_mv;
 
 #ifdef CONFIG_ALPHA_GENERIC
 extern int alpha_using_srm;
-extern int alpha_use_srm_setup;
 #else
 #ifdef CONFIG_ALPHA_SRM
 #define alpha_using_srm 1
 #else
 #define alpha_using_srm 0
-#endif
-#if defined(CONFIG_ALPHA_SRM_SETUP)
-#define alpha_use_srm_setup 1
-#else
-#define alpha_use_srm_setup 0
 #endif
 #endif /* GENERIC */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/pci.h linux/include/asm-alpha/pci.h
--- v2.3.15/linux/include/asm-alpha/pci.h	Thu Jan  7 09:25:02 1999
+++ linux/include/asm-alpha/pci.h	Tue Aug 31 11:21:39 1999
@@ -1,48 +1,31 @@
 #ifndef __ALPHA_PCI_H
 #define __ALPHA_PCI_H
 
-#include <linux/config.h>
-#include <linux/pci.h>
-
-
 /*
  * The following structure is used to manage multiple PCI busses.
- *
- * XXX: We should solve this problem in an architecture independent
- * way, rather than hacking something up here.
  */
 
-struct linux_hose_info {
-        struct pci_bus                  pci_bus;
-	struct linux_hose_info         *next;
-	unsigned long                   pci_io_space;
-	unsigned long                   pci_mem_space;
-	unsigned long                   pci_config_space;
-	unsigned long                   pci_sparse_space;
-        unsigned int                    pci_first_busno;
-        unsigned int                    pci_last_busno;
-	unsigned int                    pci_hose_index;
-};
-
-/* This is indexed by a pseudo- PCI bus number to obtain the real deal.  */
-extern struct linux_hose_info *bus2hose[256];
-
-/* Create a handle that is OR-ed into the reported I/O space address
-   for a device.  We use this later to find the bus a device lives on.  */
+struct pci_bus;
+struct resource;
 
-#if defined(CONFIG_ALPHA_GENERIC) \
-    || defined(CONFIG_ALPHA_MCPCIA) \
-    || defined(CONFIG_ALPHA_TSUNAMI)
-
-#define PCI_HANDLE(bus)   ((bus2hose[bus]->pci_hose_index & 3UL) << 32)
-#define DEV_IS_ON_PRIMARY(dev) \
-  (bus2hose[(dev)->bus->number]->pci_first_busno == (dev)->bus->number)
-
-#else
+struct pci_controler {
+	/* Mandated.  */
+	struct pci_controler *next;
+        struct pci_bus *bus;
+	struct resource *io_space;
+	struct resource *mem_space;
+
+	/* Alpha specific.  */
+	unsigned long config_space;
+	unsigned int index;
+	unsigned int first_busno;
+	unsigned int last_busno;
+};
 
-#define PCI_HANDLE(bus)         0
-#define DEV_IS_ON_PRIMARY(dev)  ((dev)->bus->number == 0)
+/* Override the logic in pci_scan_bus for skipping already-configured
+   bus numbers.  */
 
-#endif /* Multiple busses */
+#define pcibios_assign_all_busses()	1
 
 #endif /* __ALPHA_PCI_H */
+
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/smp.h linux/include/asm-alpha/smp.h
--- v2.3.15/linux/include/asm-alpha/smp.h	Mon Aug 16 10:33:58 1999
+++ linux/include/asm-alpha/smp.h	Tue Aug 31 10:50:45 1999
@@ -33,7 +33,7 @@
 	int irq_count, bh_count;
 	unsigned char mcheck_expected;
 	unsigned char mcheck_taken;
-	unsigned char mcheck_hose;
+	unsigned char mcheck_extra;
 } __attribute__((aligned(64)));
 
 extern struct cpuinfo_alpha cpu_data[NR_CPUS];
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h
--- v2.3.15/linux/include/asm-alpha/system.h	Tue Aug  3 08:01:29 1999
+++ linux/include/asm-alpha/system.h	Tue Aug 31 11:30:48 1999
@@ -108,6 +108,15 @@
 #define wmb() \
 __asm__ __volatile__("wmb": : :"memory")
 
+#define set_mb(var, value) \
+do { var = value; mb(); } while (0)
+
+#define set_rmb(var, value) \
+do { var = value; rmb(); } while (0)
+
+#define set_wmb(var, value) \
+do { var = value; wmb(); } while (0)
+
 #define imb() \
 __asm__ __volatile__ ("call_pal %0 #imb" : : "i" (PAL_imb) : "memory")
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- v2.3.15/linux/include/asm-alpha/unistd.h	Thu Aug 26 13:05:40 1999
+++ linux/include/asm-alpha/unistd.h	Tue Aug 31 10:50:48 1999
@@ -308,6 +308,8 @@
 #define __NR_capget			368
 #define __NR_capset			369
 #define __NR_sendfile			370
+#define __NR_setresgid			371
+#define __NR_getresgid			372
 
 #if defined(__LIBRARY__) && defined(__GNUC__)
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-alpha/vga.h linux/include/asm-alpha/vga.h
--- v2.3.15/linux/include/asm-alpha/vga.h	Mon Aug 16 10:33:58 1999
+++ linux/include/asm-alpha/vga.h	Tue Aug 31 10:50:48 1999
@@ -16,7 +16,7 @@
 extern inline void scr_writew(u16 val, u16 *addr)
 {
 	if (__is_ioaddr((unsigned long) addr))
-		writew(val, (unsigned long) addr);
+		__raw_writew(val, (unsigned long) addr);
 	else
 		*addr = val;
 }
@@ -24,7 +24,7 @@
 extern inline u16 scr_readw(const u16 *addr)
 {
 	if (__is_ioaddr((unsigned long) addr))
-		return readw((unsigned long) addr);
+		return __raw_readw((unsigned long) addr);
 	else
 		return *addr;
 }
@@ -47,9 +47,11 @@
 	memcpy_toio(d, s, count);
 }
 
-
-#define vga_readb readb
-#define vga_writeb writeb
+/* ??? These are currently only used for downloading character sets.  As
+   such, they don't need memory barriers.  Is this all they are intended
+   to be used for?  */
+#define vga_readb	readb
+#define vga_writeb	writeb
 
 #define VGA_MAP_MEM(x)	((unsigned long) ioremap((x), 0))
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/arch-arc/system.h linux/include/asm-arm/arch-arc/system.h
--- v2.3.15/linux/include/asm-arm/arch-arc/system.h	Thu Jan  7 15:51:33 1999
+++ linux/include/asm-arm/arch-arc/system.h	Mon Aug 30 18:15:21 1999
@@ -30,7 +30,7 @@
 	/*
 	 * Do any cleanups that the processor may require
 	 */
-	processor._proc_fin();
+	cpu_proc_fin();
 
 	/*
 	 * Reset all expansion cards.
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/arch-ebsa285/io.h linux/include/asm-arm/arch-ebsa285/io.h
--- v2.3.15/linux/include/asm-arm/arch-ebsa285/io.h	Mon Jul 19 09:52:57 1999
+++ linux/include/asm-arm/arch-ebsa285/io.h	Mon Aug 30 18:15:21 1999
@@ -62,6 +62,8 @@
  */
 #define IO_FUDGE_FACTOR		PCIMEM_BASE
 
+#define __pci_mem_addr(x)	((void *)(IO_FUDGE_FACTOR + (unsigned long)(x)))
+
 /*
  * ioremap takes a PCI memory address, as specified in
  * linux/Documentation/IO-mapping.txt
@@ -78,9 +80,7 @@
 
 #define ioremap_nocache(iomem_addr,size) ioremap((iomem_addr),(size))
 
-extern void iounmap(void *addr);
-
-#define __pci_mem_addr(x)	((void *)(IO_FUDGE_FACTOR + (unsigned long)(x)))
+#define iounmap(_addr)	do { __iounmap(__pci_mem_addr((_addr))); } while (0)
 
 #define readb(addr)	(*(volatile unsigned char *)__pci_mem_addr(addr))
 #define readw(addr)	(*(volatile unsigned short *)__pci_mem_addr(addr))
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/arch-ebsa285/irq.h linux/include/asm-arm/arch-ebsa285/irq.h
--- v2.3.15/linux/include/asm-arm/arch-ebsa285/irq.h	Mon Jul 19 09:52:57 1999
+++ linux/include/asm-arm/arch-ebsa285/irq.h	Mon Aug 30 18:15:21 1999
@@ -110,6 +110,8 @@
 }
 
 static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL };
+static struct resource pic1_resource = { "pic1", 0x20, 0x3f };
+static struct resource pic2_resource = { "pic2", 0xa0, 0xbf };
 
 static __inline__ void irq_init_irq(void)
 {
@@ -203,8 +205,8 @@
 			irq_desc[irq].unmask	= isa_unmask_pic_hi_irq;
 		}
 
-		request_region(PIC_LO, 2, "pic1");
-		request_region(PIC_HI, 2, "pic2");
+		request_resource(&ioport_resource, &pic1_resource);
+		request_resource(&ioport_resource, &pic2_resource);
 		setup_arm_irq(IRQ_ISA_CASCADE, &irq_cascade);
 		setup_arm_irq(isa_irq, &irq_cascade);
 	}
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/arch-ebsa285/time.h linux/include/asm-arm/arch-ebsa285/time.h
--- v2.3.15/linux/include/asm-arm/arch-ebsa285/time.h	Mon Jul 19 09:52:57 1999
+++ linux/include/asm-arm/arch-ebsa285/time.h	Tue Aug 31 11:23:03 1999
@@ -129,8 +129,7 @@
 	NULL
 };
 
-__initfunc(static unsigned long
-get_isa_cmos_time(void))
+static unsigned long __init get_isa_cmos_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
 	int i;
@@ -240,10 +239,8 @@
 {
 	*CSR_TIMER1_CLR = 0;
 
-	/* Do the LEDs things on non-CATS hardware.
-	 */
-	if (!machine_is_cats())
-		do_leds();
+	/* Do the LEDs things */
+	do_leds();
 
 	do_timer(regs);
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/arch-rpc/system.h linux/include/asm-arm/arch-rpc/system.h
--- v2.3.15/linux/include/asm-arm/arch-rpc/system.h	Sat May  8 11:06:57 1999
+++ linux/include/asm-arm/arch-rpc/system.h	Mon Aug 30 18:15:21 1999
@@ -17,7 +17,7 @@
 			     "mcr  p15, 0, %0, c1, c0, 0;"		\
 			     "movs pc, #0"				\
 			 : 						\
-			 : "r" (processor.u.armv3v4.reset()));		\
+			 : "r" (cpu_reset()));				\
 	}
 
 #endif
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/atomic.h linux/include/asm-arm/atomic.h
--- v2.3.15/linux/include/asm-arm/atomic.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-arm/atomic.h	Mon Aug 30 18:15:21 1999
@@ -81,6 +81,19 @@
 	return result;
 }
 
+extern __inline__ int atomic_add_negative(int i, volatile atomic_t *v)
+{
+	unsigned long flags;
+	int result;
+
+	save_flags_cli(flags);
+	v->counter += i;
+	result = (v->counter < 0);
+	restore_flags(flags);
+
+	return result;
+}
+
 static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *addr)
 {
 	unsigned long flags;
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/bugs.h linux/include/asm-arm/bugs.h
--- v2.3.15/linux/include/asm-arm/bugs.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/bugs.h	Mon Aug 30 18:15:21 1999
@@ -8,6 +8,6 @@
 
 #include <asm/proc-fns.h>
 
-#define check_bugs() processor._check_bugs()
+#define check_bugs() cpu_check_bugs()
 
 #endif
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/cache.h linux/include/asm-arm/cache.h
--- v2.3.15/linux/include/asm-arm/cache.h	Mon Mar 15 16:11:55 1999
+++ linux/include/asm-arm/cache.h	Mon Aug 30 18:15:21 1999
@@ -8,4 +8,12 @@
 #define        L1_CACHE_ALIGN(x)       (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 #define        SMP_CACHE_BYTES L1_CACHE_BYTES
 
+#ifdef MODULE
+#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
+#else
+#define __cacheline_aligned					\
+  __attribute__((__aligned__(L1_CACHE_BYTES),			\
+		 __section__(".data.cacheline_aligned")))
+#endif
+
 #endif
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/cpu-multi26.h linux/include/asm-arm/cpu-multi26.h
--- v2.3.15/linux/include/asm-arm/cpu-multi26.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/cpu-multi26.h	Mon Aug 30 18:15:21 1999
@@ -0,0 +1,68 @@
+#ifndef __ASSEMBLY__
+
+#include <asm/page.h>
+
+/* forward-declare task_struct */
+struct task_struct;
+
+/*
+ * Don't change this structure - ASM code
+ * relies on it.
+ */
+extern struct processor {
+	/* MISC
+	 * get data abort address/flags
+	 */
+	void (*_data_abort)(unsigned long pc);
+	/*
+	 * check for any bugs
+	 */
+	void (*_check_bugs)(void);
+	/*
+	 * Set up any processor specifics
+	 */
+	void (*_proc_init)(void);
+	/*
+	 * Disable any processor specifics
+	 */
+	void (*_proc_fin)(void);
+	/*
+	 * Processor architecture specific
+	 */
+	/* MEMC
+	 *
+	 * remap memc tables
+	 */
+	void (*_remap_memc)(void *tsk);
+	/*
+	 * update task's idea of mmap
+	 */
+	void (*_update_map)(void *tsk);
+	/*
+	 * update task's idea after abort
+	 */
+	void (*_update_mmu_cache)(void *vma, unsigned long addr, pte_t pte);
+	/* XCHG
+	 */
+	unsigned long (*_xchg_1)(unsigned long x, volatile void *ptr);
+	unsigned long (*_xchg_2)(unsigned long x, volatile void *ptr);
+	unsigned long (*_xchg_4)(unsigned long x, volatile void *ptr);
+} processor;
+
+extern const struct processor arm2_processor_functions;
+extern const struct processor arm250_processor_functions;
+extern const struct processor arm3_processor_functions;
+
+#define cpu_data_abort(pc)			processor._data_abort(pc)
+#define cpu_check_bugs()			processor._check_bugs()
+#define cpu_proc_init()				processor._proc_init()
+#define cpu_proc_fin()				processor._proc_fin()
+
+#define cpu_remap_memc(tsk)			processor._remap_memc(tsk)
+#define cpu_update_map(tsk)			processor._update_map(tsk)
+#define cpu_update_mmu_cache(vma,addr,pte)	processor._update_mmu_cache(vma,addr,pte)
+#define cpu_xchg_1(x,ptr)			processor._xchg_1(x,ptr)
+#define cpu_xchg_2(x,ptr)			processor._xchg_2(x,ptr)
+#define cpu_xchg_4(x,ptr)			processor._xchg_4(x,ptr)
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/cpu-multi32.h linux/include/asm-arm/cpu-multi32.h
--- v2.3.15/linux/include/asm-arm/cpu-multi32.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/cpu-multi32.h	Mon Aug 30 18:15:21 1999
@@ -0,0 +1,117 @@
+#ifndef __ASSEMBLY__
+
+#include <asm/page.h>
+
+/* forward-declare task_struct */
+struct task_struct;
+
+/*
+ * Don't change this structure - ASM code
+ * relies on it.
+ */
+extern struct processor {
+	/* MISC
+	 * get data abort address/flags
+	 */
+	void (*_data_abort)(unsigned long pc);
+	/*
+	 * check for any bugs
+	 */
+	void (*_check_bugs)(void);
+	/*
+	 * Set up any processor specifics
+	 */
+	void (*_proc_init)(void);
+	/*
+	 * Disable any processor specifics
+	 */
+	void (*_proc_fin)(void);
+	/*
+	 * Processor architecture specific
+	 */
+	/* CACHE
+	 *
+	 * flush all caches
+	 */
+	void (*_flush_cache_all)(void);
+	/*
+	 * flush a specific page or pages
+	 */
+	void (*_flush_cache_area)(unsigned long address, unsigned long end, int flags);
+	/*
+	 * flush cache entry for an address
+	 */
+	void (*_flush_cache_entry)(unsigned long address);
+	/*
+	 * clean a virtual address range from the
+	 * D-cache without flushing the cache.
+	 */
+	void (*_clean_cache_area)(unsigned long start, unsigned long size);
+	/*
+	 * flush a page to RAM
+	 */
+	void (*_flush_ram_page)(unsigned long page);
+	/* TLB
+	 *
+	 * flush all TLBs
+	 */
+	void (*_flush_tlb_all)(void);
+	/*
+	 * flush a specific TLB
+	 */
+	void (*_flush_tlb_area)(unsigned long address, unsigned long end, int flags);
+	/*
+	 * Set the page table
+	 */
+	void (*_set_pgd)(unsigned long pgd_phys);
+	/*
+	 * Set a PMD (handling IMP bit 4)
+	 */
+	void (*_set_pmd)(pmd_t *pmdp, pmd_t pmd);
+	/*
+	 * Set a PTE
+	 */
+	void (*_set_pte)(pte_t *ptep, pte_t pte);
+	/*
+	 * Special stuff for a reset
+	 */
+	unsigned long (*reset)(void);
+	/*
+	 * flush an icached page
+	 */
+	void (*_flush_icache_area)(unsigned long start, unsigned long size);
+	/*
+	 * write back dirty cached data
+	 */
+	void (*_cache_wback_area)(unsigned long start, unsigned long end);
+	/*
+	 * purge cached data without (necessarily) writing it back
+	 */
+	void (*_cache_purge_area)(unsigned long start, unsigned long end);
+} processor;
+
+extern const struct processor arm6_processor_functions;
+extern const struct processor arm7_processor_functions;
+extern const struct processor sa110_processor_functions;
+
+#define cpu_data_abort(pc)			processor._data_abort(pc)
+#define cpu_check_bugs()			processor._check_bugs()
+#define cpu_proc_init()				processor._proc_init()
+#define cpu_proc_fin()				processor._proc_fin()
+
+#define cpu_flush_cache_all()			processor._flush_cache_all()
+#define cpu_flush_cache_area(start,end,flags)	processor._flush_cache_area(start,end,flags)
+#define cpu_flush_cache_entry(addr)		processor._flush_cache_entry(addr)
+#define cpu_clean_cache_area(start,size)	processor._clean_cache_area(start,size)
+#define cpu_flush_ram_page(page)		processor._flush_ram_page(page)
+#define cpu_flush_tlb_all()			processor._flush_tlb_all()
+#define cpu_flush_tlb_area(start,end,flags)	processor._flush_tlb_area(start,end,flags)
+#define cpu_switch_mm(pgd,tsk)			processor._set_pgd(pgd)
+#define cpu_set_pmd(pmdp, pmd)			processor._set_pmd(pmdp, pmd)
+#define cpu_set_pte(ptep, pte)			processor._set_pte(ptep, pte)
+#define cpu_reset()				processor.reset()
+#define cpu_flush_icache_area(start,end)	processor._flush_icache_area(start,end)
+#define cpu_cache_wback_area(start,end)		processor._cache_wback_area(start,end)
+#define cpu_cache_purge_area(start,end)		processor._cache_purge_area(start,end)
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/cpu-single.h linux/include/asm-arm/cpu-single.h
--- v2.3.15/linux/include/asm-arm/cpu-single.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/cpu-single.h	Mon Aug 30 18:15:21 1999
@@ -0,0 +1,61 @@
+/*
+ * Single CPU
+ */
+#define __cpu_fn(name,x)	cpu_##name##x
+#define cpu_fn(name,x)		__cpu_fn(name,x)
+
+/*
+ * If we are supporting multiple CPUs, then
+ * we must use a table of function pointers
+ * for this lot.  Otherwise, we can optimise
+ * the table away.
+ */
+#define cpu_data_abort			cpu_fn(CPU_NAME,_data_abort)
+#define cpu_check_bugs			cpu_fn(CPU_NAME,_check_bugs)
+#define cpu_proc_init			cpu_fn(CPU_NAME,_proc_init)
+#define cpu_proc_fin			cpu_fn(CPU_NAME,_proc_fin)
+
+#define cpu_flush_cache_all		cpu_fn(CPU_NAME,_flush_cache_all)
+#define cpu_flush_cache_area		cpu_fn(CPU_NAME,_flush_cache_area)
+#define cpu_flush_cache_entry		cpu_fn(CPU_NAME,_flush_cache_entry)
+#define cpu_clean_cache_area		cpu_fn(CPU_NAME,_clean_cache_area)
+#define cpu_flush_ram_page		cpu_fn(CPU_NAME,_flush_ram_page)
+#define cpu_flush_tlb_all		cpu_fn(CPU_NAME,_flush_tlb_all)
+#define cpu_flush_tlb_area		cpu_fn(CPU_NAME,_flush_tlb_area)
+#define cpu_switch_mm			cpu_fn(CPU_NAME,_set_pgd)
+#define cpu_set_pmd			cpu_fn(CPU_NAME,_set_pmd)
+#define cpu_set_pte			cpu_fn(CPU_NAME,_set_pte)
+#define cpu_reset			cpu_fn(CPU_NAME,reset)
+#define cpu_flush_icache_area		cpu_fn(CPU_NAME,_flush_icache_area)
+#define cpu_cache_wback_area		cpu_fn(CPU_NAME,_cache_wback_area)
+#define cpu_cache_purge_area		cpu_fn(CPU_NAME,_cache_purge_area)
+
+#ifndef __ASSEMBLY__
+
+#include <asm/page.h>
+
+/* forward declare task_struct */
+struct task_struct;
+
+/* declare all the functions as extern */
+extern void cpu_data_abort(unsigned long pc);
+extern void cpu_check_bugs(void);
+extern void cpu_proc_init(void);
+extern void cpu_proc_fin(void);
+
+extern void cpu_flush_cache_all(void);
+extern void cpu_flush_cache_area(unsigned long address, unsigned long end, int flags);
+extern void cpu_flush_cache_entry(unsigned long address);
+extern void cpu_clean_cache_area(unsigned long start, unsigned long size);
+extern void cpu_flush_ram_page(unsigned long page);
+extern void cpu_flush_tlb_all(void);
+extern void cpu_flush_tlb_area(unsigned long address, unsigned long end, int flags);
+extern void cpu_switch_mm(unsigned long pgd_phys, struct task_struct *tsk);
+extern void cpu_set_pmd(pmd_t *pmdp, pmd_t pmd);
+extern void cpu_set_pte(pte_t *ptep, pte_t pte);
+extern unsigned long cpu_reset(void);
+extern void cpu_flush_icache_area(unsigned long start, unsigned long size);
+extern void cpu_cache_wback_area(unsigned long start, unsigned long end);
+extern void cpu_cache_purge_area(unsigned long start, unsigned long end);
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/dec21285.h linux/include/asm-arm/dec21285.h
--- v2.3.15/linux/include/asm-arm/dec21285.h	Sat May  8 11:06:57 1999
+++ linux/include/asm-arm/dec21285.h	Mon Aug 30 18:15:21 1999
@@ -28,6 +28,12 @@
 #define CSR_PCICSRIOBASE	DC21285_IO(0x0014)
 #define CSR_PCISDRAMBASE	DC21285_IO(0x0018)
 #define CSR_PCIROMBASE		DC21285_IO(0x0030)
+#define CSR_MBOX0		DC21285_IO(0x0050)
+#define CSR_MBOX1		DC21285_IO(0x0054)
+#define CSR_MBOX2		DC21285_IO(0x0058)
+#define CSR_MBOX3		DC21285_IO(0x005c)
+#define CSR_DOORBELL		DC21285_IO(0x0060)
+#define CSR_DOORBELL_SETUP	DC21285_IO(0x0064)
 #define CSR_ROMWRITEREG		DC21285_IO(0x0068)
 #define CSR_CSRBASEMASK		DC21285_IO(0x00f8)
 #define CSR_CSRBASEOFFSET	DC21285_IO(0x00fc)
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/elf.h linux/include/asm-arm/elf.h
--- v2.3.15/linux/include/asm-arm/elf.h	Thu Dec 17 09:05:43 1998
+++ linux/include/asm-arm/elf.h	Mon Aug 30 18:15:21 1999
@@ -47,7 +47,8 @@
 /* This yields a mask that user programs can use to figure out what
    instruction set this cpu supports. */
 
-#define ELF_HWCAP	(armidlist[armidindex].hwcap)
+extern unsigned int elf_hwcap;
+#define ELF_HWCAP	(elf_hwcap)
 
 /* This yields a string that ld.so will use to load implementation
    specific libraries for optimization.  This is more specific in
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/init.h linux/include/asm-arm/init.h
--- v2.3.15/linux/include/asm-arm/init.h	Sat May  8 11:06:57 1999
+++ linux/include/asm-arm/init.h	Mon Aug 30 18:15:21 1999
@@ -8,14 +8,10 @@
 #ifdef CONFIG_TEXT_SECTIONS
 
 #define __init __attribute__ ((__section__ (".text.init")))
-#define __initfunc(__arginit) \
-	__arginit __init; \
-	__arginit
 
 #else
 
 #define __init
-#define __initfunc(__arginit) __arginit
 
 #endif
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/io.h linux/include/asm-arm/io.h
--- v2.3.15/linux/include/asm-arm/io.h	Mon Jul 19 09:52:57 1999
+++ linux/include/asm-arm/io.h	Mon Aug 30 18:15:21 1999
@@ -21,6 +21,7 @@
 #endif
 
 extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+extern void __iounmap(void *addr);
 
 #endif
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/iomd.h linux/include/asm-arm/iomd.h
--- v2.3.15/linux/include/asm-arm/iomd.h	Sat May  8 11:06:57 1999
+++ linux/include/asm-arm/iomd.h	Mon Aug 30 18:15:21 1999
@@ -10,6 +10,10 @@
 #define IOMD_KARTRX	__IOMD(0x004)
 #define IOMD_KCTRL	__IOMD(0x008)
 
+#ifdef CONFIG_ARCH_CL7500
+#define IOMD_IOLINES	__IOMD(0x00C)
+#endif
+
 #define IOMD_IRQSTATA	__IOMD(0x010)
 #define IOMD_IRQREQA	__IOMD(0x014)
 #define IOMD_IRQCLRA	__IOMD(0x014)
@@ -37,9 +41,23 @@
 #define IOMD_T1GO	__IOMD(0x058)
 #define IOMD_T1LATCH	__IOMD(0x05c)
 
+#ifdef CONFIG_ARCH_CL7500
+#define IOMD_IRQSTATC	__IOMD(0x060)
+#define IOMD_IRQREQC	__IOMD(0x064)
+#define IOMD_IRQMASKC	__IOMD(0x068)
+
+#define IOMD_VIDMUX	__IOMD(0x06c)
+
+#define IOMD_IRQSTATD	__IOMD(0x070)
+#define IOMD_IRQREQD	__IOMD(0x074)
+#define IOMD_IRQMASKD	__IOMD(0x078)
+#endif
+
 #define IOMD_ROMCR0	__IOMD(0x080)
 #define IOMD_ROMCR1	__IOMD(0x084)
+#ifdef CONFIG_ARCH_RPC
 #define IOMD_DRAMCR	__IOMD(0x088)
+#endif
 #define IOMD_VREFCR	__IOMD(0x08C)
 
 #define IOMD_FSIZE	__IOMD(0x090)
@@ -47,14 +65,38 @@
 #define IOMD_ID1	__IOMD(0x098)
 #define IOMD_VERSION	__IOMD(0x09C)
 
+#ifdef CONFIG_ARCH_RPC
 #define IOMD_MOUSEX	__IOMD(0x0A0)
 #define IOMD_MOUSEY	__IOMD(0x0A4)
+#endif
+
+#ifdef CONFIG_ARCH_CL7500
+#define IOMD_MSEDAT	__IOMD(0x0A8)
+#define IOMD_MSECTL	__IOMD(0x0Ac)
+#endif
 
+#ifdef CONFIG_ARCH_RPC
 #define IOMD_DMATCR	__IOMD(0x0C0)
+#endif
 #define IOMD_IOTCR	__IOMD(0x0C4)
 #define IOMD_ECTCR	__IOMD(0x0C8)
+#ifdef CONFIG_ARCH_RPC
 #define IOMD_DMAEXT	__IOMD(0x0CC)
+#endif
+#ifdef CONFIG_ARCH_CL7500
+#define IOMD_ASTCR	__IOMD(0x0CC)
+#define IOMD_DRAMCR	__IOMD(0x0D0)
+#define IOMD_SELFREF	__IOMD(0x0D4)
+#define IOMD_ATODICR	__IOMD(0x0E0)
+#define IOMD_ATODSR	__IOMD(0x0E4)
+#define IOMD_ATODCC	__IOMD(0x0E8)
+#define IOMD_ATODCNT1	__IOMD(0x0EC)
+#define IOMD_ATODCNT2	__IOMD(0x0F0)
+#define IOMD_ATODCNT3	__IOMD(0x0F4)
+#define IOMD_ATODCNT4	__IOMD(0x0F8)
+#endif
 
+#ifdef CONFIG_ARCH_RPC
 #define DMA_EXT_IO0	1
 #define DMA_EXT_IO1	2
 #define DMA_EXT_IO2	4
@@ -87,6 +129,7 @@
 #define IOMD_IO3ENDB	__IOMD(0x16C)
 #define IOMD_IO3CR	__IOMD(0x170)
 #define IOMD_IO3ST	__IOMD(0x174)
+#endif
 
 #define IOMD_SD0CURA	__IOMD(0x180)
 #define IOMD_SD0ENDA	__IOMD(0x184)
@@ -95,12 +138,14 @@
 #define IOMD_SD0CR	__IOMD(0x190)
 #define IOMD_SD0ST	__IOMD(0x194)
 
+#ifdef CONFIG_ARCH_RPC
 #define IOMD_SD1CURA	__IOMD(0x1A0)
 #define IOMD_SD1ENDA	__IOMD(0x1A4)
 #define IOMD_SD1CURB	__IOMD(0x1A8)
 #define IOMD_SD1ENDB	__IOMD(0x1AC)
 #define IOMD_SD1CR	__IOMD(0x1B0)
 #define IOMD_SD1ST	__IOMD(0x1B4)
+#endif
 
 #define IOMD_CURSCUR	__IOMD(0x1C0)
 #define IOMD_CURSINIT	__IOMD(0x1C4)
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/mmu_context.h linux/include/asm-arm/mmu_context.h
--- v2.3.15/linux/include/asm-arm/mmu_context.h	Mon Aug  2 10:19:52 1999
+++ linux/include/asm-arm/mmu_context.h	Mon Aug 30 18:15:21 1999
@@ -12,6 +12,7 @@
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 #include <asm/arch/memory.h>
+#include <asm/proc-fns.h>
 
 #define destroy_context(mm)		do { } while(0)
 #define init_new_context(tsk,mm)	do { } while(0)
@@ -20,13 +21,18 @@
  * This is the actual mm switch as far as the scheduler
  * is concerned.  No registers are touched.
  */
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, unsigned int cpu)
+static inline void
+switch_mm(struct mm_struct *prev, struct mm_struct *next,
+	  struct task_struct *tsk, unsigned int cpu)
 {
 	if (prev != next) {
-		processor.u.armv3v4._set_pgd(__virt_to_phys((unsigned long)next->pgd));
+		cpu_switch_mm(__virt_to_phys((unsigned long)next->pgd), tsk);
 		clear_bit(cpu, &prev->cpu_vm_mask);
 	}
 	set_bit(cpu, &next->cpu_vm_mask);
 }
+
+#define activate_mm(prev, next) \
+	switch_mm((prev),(next),NULL,smp_processor_id())
 
 #endif
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/parport.h linux/include/asm-arm/parport.h
--- v2.3.15/linux/include/asm-arm/parport.h	Mon Aug  2 10:19:52 1999
+++ linux/include/asm-arm/parport.h	Mon Aug 30 18:15:21 1999
@@ -9,16 +9,25 @@
 #ifndef _ASM_I386_PARPORT_H
 #define _ASM_I386_PARPORT_H 1
 
+#include <linux/config.h>
+
 /* Maximum number of ports to support.  It is useless to set this greater
    than PARPORT_MAX (in <linux/parport.h>).  */
 #define PARPORT_PC_MAX_PORTS  8
 
-static int __init probe_one_port(unsigned long int base,
-				 unsigned long int base_hi,
-				 int irq, int dma);
-static int __init parport_pc_init_pci(int irq, int dma);
+/* If parport_cs (PCMCIA) is managing ports for us, we'll need the
+ * probing routines forever; otherwise we can lose them at boot time. */
+#ifdef CONFIG_PARPORT_PC_PCMCIA
+#define __maybe_initdata
+#define __maybe_init
+#else
+#define __maybe_initdata __initdata
+#define __maybe_init __init
+#endif
+
+static int __maybe_init parport_pc_init_pci(int irq, int dma);
 
-static int user_specified __initdata = 0;
+static int user_specified __maybe_initdata = 0;
 int __init
 parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
 {
@@ -29,14 +38,18 @@
 		user_specified = 1;
 		do {
 			if (!*io_hi) *io_hi = 0x400 + *io;
-			count += probe_one_port(*(io++), *(io_hi++),
-						*(irq++), *(dma++));
+			if (parport_pc_probe_port(*(io++), *(io_hi++),
+						  *(irq++), *(dma++)))
+				count++;
 		} while (*io && (++i < PARPORT_PC_MAX_PORTS));
 	} else {
 		/* Probe all the likely ports. */
-		count += probe_one_port(0x3bc, 0x7bc, irq[0], dma[0]);
-		count += probe_one_port(0x378, 0x778, irq[0], dma[0]);
-		count += probe_one_port(0x278, 0x678, irq[0], dma[0]);
+		if (parport_pc_probe_port(0x3bc, 0x7bc, irq[0], dma[0]))
+			count++;
+		if (parport_pc_probe_port(0x378, 0x778, irq[0], dma[0]))
+			count++;
+		if (parport_pc_probe_port(0x278, 0x678, irq[0], dma[0]))
+			count++;
 		count += parport_pc_init_pci (irq[0], dma[0]);
 	}
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/pgtable.h linux/include/asm-arm/pgtable.h
--- v2.3.15/linux/include/asm-arm/pgtable.h	Wed Mar 10 18:11:51 1999
+++ linux/include/asm-arm/pgtable.h	Mon Aug 30 18:15:21 1999
@@ -13,4 +13,6 @@
 #define PageSkip(page)			(0)
 #define kern_addr_valid(addr)		(1)
 
+#define io_remap_page_range remap_page_range
+
 #endif /* _ASMARM_PGTABLE_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/proc-armo/processor.h linux/include/asm-arm/proc-armo/processor.h
--- v2.3.15/linux/include/asm-arm/proc-armo/processor.h	Mon Aug  2 10:19:52 1999
+++ linux/include/asm-arm/proc-armo/processor.h	Mon Aug 30 18:15:21 1999
@@ -10,6 +10,7 @@
  *  28-09-1996	RMK	Moved start_thread into the processor dependencies
  *  11-01-1998	RMK	Added new uaccess_t
  *  09-09-1998	PJB	Delete redundant `wp_works_ok'
+ *  30-05-1999	PJB	Save sl across context switches
  */
 #ifndef __ASM_PROC_PROCESSOR_H
 #define __ASM_PROC_PROCESSOR_H
@@ -26,11 +27,12 @@
 	unsigned long r7;
 	unsigned long r8;
 	unsigned long r9;
+	unsigned long sl;
 	unsigned long fp;
 	unsigned long pc;
 };
 
-#define INIT_CSS (struct context_save_struct){ 0, 0, 0, 0, 0, 0, 0, SVC26_MODE }
+#define INIT_CSS (struct context_save_struct){ 0, 0, 0, 0, 0, 0, 0, 0, SVC26_MODE }
 
 typedef struct {
 	void (*put_byte)(void);			/* Special calling convention */
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/proc-armo/system.h linux/include/asm-arm/proc-armo/system.h
--- v2.3.15/linux/include/asm-arm/proc-armo/system.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-arm/proc-armo/system.h	Mon Aug 30 18:15:21 1999
@@ -14,9 +14,9 @@
 extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
 {
 	switch (size) {
-		case 1:	return processor.u.armv2._xchg_1(x, ptr);
-		case 2:	return processor.u.armv2._xchg_2(x, ptr);
-		case 4:	return processor.u.armv2._xchg_4(x, ptr);
+		case 1:	return cpu_xchg_1(x, ptr);
+		case 2:	return cpu_xchg_2(x, ptr);
+		case 4:	return cpu_xchg_4(x, ptr);
 		default: arm_invalidptr(xchg_str, size);
 	}
 	return 0;
@@ -26,7 +26,7 @@
  * We need to turn the caches off before calling the reset vector - RiscOS
  * messes up if we don't
  */
-#define proc_hard_reset()	processor._proc_fin()
+#define proc_hard_reset()	cpu_proc_fin()
 
 /*
  * This processor does not idle
@@ -105,7 +105,7 @@
 "	bic	%0, %0, #0x0c000000\n"			\
 "	orr	%0, %0, %1\n"				\
 "	teqp	%0, #0\n"				\
-	  : "=r" (temp)					\
+	  : "=&r" (temp)				\
 	  : "r" (x)					\
 	  : "memory");					\
 	} while (0)
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/proc-armv/io.h linux/include/asm-arm/proc-armv/io.h
--- v2.3.15/linux/include/asm-arm/proc-armv/io.h	Sat May  8 11:06:58 1999
+++ linux/include/asm-arm/proc-armv/io.h	Mon Aug 30 18:15:21 1999
@@ -22,14 +22,14 @@
 
 #include <asm/proc-fns.h>
 
-#define dma_cache_inv(start, size)					    \
-	do { processor.u.armv3v4._cache_purge_area((unsigned long)(start),  \
+#define dma_cache_inv(start, size)				\
+	do { cpu_cache_purge_area((unsigned long)(start),	\
 		((unsigned long)(start)+(size))); } while (0)
 
-#define dma_cache_wback(start, size)					    \
-	do { processor.u.armv3v4._cache_wback_area((unsigned long)(start),  \
+#define dma_cache_wback(start, size)				\
+	do { cpu_cache_wback_area((unsigned long)(start),	\
 		((unsigned long)(start)+(size))); } while (0)
 
-#define dma_cache_wback_inv(start, size)				    \
-	do { processor.u.armv3v4._flush_cache_area((unsigned long)(start),  \
+#define dma_cache_wback_inv(start, size)			\
+	do { cpu_flush_cache_area((unsigned long)(start),	\
 		((unsigned long)(start)+(size)), 0); } while (0)
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/proc-armv/pgtable.h linux/include/asm-arm/proc-armv/pgtable.h
--- v2.3.15/linux/include/asm-arm/proc-armv/pgtable.h	Mon Aug  2 10:19:52 1999
+++ linux/include/asm-arm/proc-armv/pgtable.h	Mon Aug 30 18:15:21 1999
@@ -19,27 +19,26 @@
  * Cache flushing...
  */
 #define flush_cache_all()						\
-	processor.u.armv3v4._flush_cache_all()
+	cpu_flush_cache_all()
 
 #define flush_cache_mm(_mm)						\
 	do {								\
 		if ((_mm) == current->mm)				\
-			processor.u.armv3v4._flush_cache_all();		\
+			cpu_flush_cache_all();				\
 	} while (0)
 
 #define flush_cache_range(_mm,_start,_end)				\
 	do {								\
 		if ((_mm) == current->mm)				\
-			processor.u.armv3v4._flush_cache_area		\
-				((_start), (_end), 1);			\
+			cpu_flush_cache_area((_start), (_end), 1);	\
 	} while (0)
 
 #define flush_cache_page(_vma,_vmaddr)					\
 	do {								\
 		if ((_vma)->vm_mm == current->mm)			\
-			processor.u.armv3v4._flush_cache_area		\
-				((_vmaddr), (_vmaddr) + PAGE_SIZE,	\
-				 ((_vma)->vm_flags & VM_EXEC) ? 1 : 0);	\
+			cpu_flush_cache_area((_vmaddr),			\
+				(_vmaddr) + PAGE_SIZE,			\
+				((_vma)->vm_flags & VM_EXEC) ? 1 : 0);	\
 	} while (0)
 
 #define clean_cache_range(_start,_end)					\
@@ -47,18 +46,18 @@
 		unsigned long _s, _sz;					\
 		_s = (unsigned long)_start;				\
 		_sz = (unsigned long)_end - _s;				\
-		processor.u.armv3v4._clean_cache_area(_s, _sz);		\
+		cpu_clean_cache_area(_s, _sz);				\
 	} while (0)
 
 #define clean_cache_area(_start,_size)					\
 	do {								\
 		unsigned long _s;					\
 		_s = (unsigned long)_start;				\
-		processor.u.armv3v4._clean_cache_area(_s, _size);	\
+		cpu_clean_cache_area(_s, _size);			\
 	} while (0)
 
 #define flush_icache_range(_start,_end)					\
-	processor.u.armv3v4._flush_icache_area((_start), (_end) - (_start))
+	cpu_flush_icache_area((_start), (_end) - (_start))
 
 /*
  * We don't have a MEMC chip...
@@ -73,7 +72,7 @@
  * in the cache for this page.  Is it necessary to invalidate the I-cache?
  */
 #define flush_page_to_ram(_page)					\
-	processor.u.armv3v4._flush_ram_page ((_page) & PAGE_MASK);
+	cpu_flush_ram_page((_page) & PAGE_MASK);
 
 /*
  * TLB flushing:
@@ -92,26 +91,24 @@
 #define flush_tlb() flush_tlb_all()
 
 #define flush_tlb_all()								\
-	processor.u.armv3v4._flush_tlb_all()
+	cpu_flush_tlb_all()
 
 #define flush_tlb_mm(_mm)							\
 	do {									\
 		if ((_mm) == current->mm)					\
-			processor.u.armv3v4._flush_tlb_all();			\
+			cpu_flush_tlb_all();					\
 	} while (0)
 
 #define flush_tlb_range(_mm,_start,_end)					\
 	do {									\
 		if ((_mm) == current->mm)					\
-			processor.u.armv3v4._flush_tlb_area			\
-				((_start), (_end), 1);				\
+			cpu_flush_tlb_area((_start), (_end), 1);		\
 	} while (0)
 
 #define flush_tlb_page(_vma,_vmaddr)						\
 	do {									\
 		if ((_vma)->vm_mm == current->mm)				\
-			processor.u.armv3v4._flush_tlb_area			\
-				((_vmaddr), (_vmaddr) + PAGE_SIZE,		\
+			cpu_flush_tlb_area((_vmaddr), (_vmaddr) + PAGE_SIZE,	\
 				 ((_vma)->vm_flags & VM_EXEC) ? 1 : 0);		\
 	} while (0)
 
@@ -268,7 +265,7 @@
 #define pmd_bad(pmd)		(pmd_val(pmd) & 2)
 #define mk_user_pmd(ptep)	__mk_pmd(ptep, _PAGE_USER_TABLE)
 #define mk_kernel_pmd(ptep)	__mk_pmd(ptep, _PAGE_KERNEL_TABLE)
-#define set_pmd(pmdp,pmd)	processor.u.armv3v4._set_pmd(pmdp,pmd)
+#define set_pmd(pmdp,pmd)	cpu_set_pmd(pmdp,pmd)
 
 /* Find an entry in the second-level page table.. */
 #define pmd_offset(dir, address) ((pmd_t *)(dir))
@@ -374,7 +371,7 @@
 	return pte;
 }
 
-#define set_pte(ptep, pte)	processor.u.armv3v4._set_pte(ptep,pte)
+#define set_pte(ptep, pte)	cpu_set_pte(ptep,pte)
 
 extern __inline__ unsigned long pte_page(pte_t pte)
 {
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/proc-armv/processor.h linux/include/asm-arm/proc-armv/processor.h
--- v2.3.15/linux/include/asm-arm/proc-armv/processor.h	Mon Aug  2 10:19:52 1999
+++ linux/include/asm-arm/proc-armv/processor.h	Mon Aug 30 18:15:21 1999
@@ -8,6 +8,7 @@
  *  26-09-1996	RMK	Added 'EXTRA_THREAD_STRUCT*'
  *  28-09-1996	RMK	Moved start_thread into the processor dependencies
  *  09-09-1998	PJB	Delete redundant `wp_works_ok'
+ *  30-05-1999	PJB	Save sl across context switches
  *  31-07-1999	RMK	Added 'domain' stuff
  */
 #ifndef __ASM_PROC_PROCESSOR_H
@@ -25,11 +26,12 @@
 	unsigned long r7;
 	unsigned long r8;
 	unsigned long r9;
+	unsigned long sl;
 	unsigned long fp;
 	unsigned long pc;
 };
 
-#define INIT_CSS (struct context_save_struct){ SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0 }
+#define INIT_CSS (struct context_save_struct){ SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 
 #define EXTRA_THREAD_STRUCT						\
 	unsigned int	domain;
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/proc-armv/system.h linux/include/asm-arm/proc-armv/system.h
--- v2.3.15/linux/include/asm-arm/proc-armv/system.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-arm/proc-armv/system.h	Mon Aug 30 18:15:21 1999
@@ -116,7 +116,7 @@
 "	bic	%0, %0, #192\n"					\
 "	orr	%0, %0, %1\n"					\
 "	msr	cpsr, %0"					\
-	  : "=r" (temp)						\
+	  : "=&r" (temp)					\
 	  : "r" (x)						\
 	  : "memory");			\
 	} while (0)
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/proc-fns.h linux/include/asm-arm/proc-fns.h
--- v2.3.15/linux/include/asm-arm/proc-fns.h	Mon Aug  2 10:19:52 1999
+++ linux/include/asm-arm/proc-fns.h	Mon Aug 30 18:15:21 1999
@@ -1,126 +1,61 @@
 /*
  * linux/include/asm-arm/proc-fns.h
  *
- * Copyright (C) 1997 Russell King
+ * Copyright (C) 1997-1999 Russell King
  */
 #ifndef __ASM_PROCFNS_H
 #define __ASM_PROCFNS_H
 
-#include <asm/page.h>
-
 #ifdef __KERNEL__
 
-/* forward-declare task_struct */
-struct task_struct;
+#include <linux/config.h>
 
 /*
- * Don't change this structure
+ * Work out if we need multiple CPU support
  */
-extern struct processor {
-	const char *name;
-	/* MISC
-	 * get data abort address/flags
-	 */
-	void (*_data_abort)(unsigned long pc);
-	/*
-	 * check for any bugs
-	 */
-	void (*_check_bugs)(void);
-	/*
-	 * Set up any processor specifics
-	 */
-	void (*_proc_init)(void);
-	/*
-	 * Disable any processor specifics
-	 */
-	void (*_proc_fin)(void);
-	/*
-	 * Processor architecture specific
-	 */
-	union {
-		struct {
-			/* CACHE
-			 *
-			 * flush all caches
-			 */
-			void (*_flush_cache_all)(void);
-			/*
-			 * flush a specific page or pages
-			 */
-			void (*_flush_cache_area)(unsigned long address, unsigned long end, int flags);
-			/*
-			 * flush cache entry for an address
-			 */
-			void (*_flush_cache_entry)(unsigned long address);
-			/*
-			 * clean a virtual address range from the
-			 * D-cache without flushing the cache.
-			 */
-			void (*_clean_cache_area)(unsigned long start, unsigned long size);
-			/*
-			 * flush a page to RAM
-			 */
-			void (*_flush_ram_page)(unsigned long page);
-			/* TLB
-			 *
-			 * flush all TLBs
-			 */
-			void (*_flush_tlb_all)(void);
-			/*
-			 * flush a specific TLB
-			 */
-			void (*_flush_tlb_area)(unsigned long address, unsigned long end, int flags);
-			/*
-			 * Set the page table
-			 */
-			void (*_set_pgd)(unsigned long pgd_phys);
-			/*
-			 * Set a PMD (handling IMP bit 4)
-			 */
-			void (*_set_pmd)(pmd_t *pmdp, pmd_t pmd);
-			/*
-			 * Set a PTE
-			 */
-			void (*_set_pte)(pte_t *ptep, pte_t pte);
-			/*
-			 * Special stuff for a reset
-			 */
-			unsigned long (*reset)(void);
-			/*
-			 * flush an icached page
-			 */
-			void (*_flush_icache_area)(unsigned long start, unsigned long size);
-			/*
-			 * write back dirty cached data
-			 */
-			void (*_cache_wback_area)(unsigned long start, unsigned long end);
-			/*
-			 * purge cached data without (necessarily) writing it back
-			 */
-			void (*_cache_purge_area)(unsigned long start, unsigned long end);
-		} armv3v4;
-		struct {
-			/* MEMC
-			 *
-			 * remap memc tables
-			 */
-			void (*_remap_memc)(void *tsk);
-			/*
-			 * update task's idea of mmap
-			 */
-			void (*_update_map)(void *tsk);
-			/*
-			 * update task's idea after abort
-			 */
-			void (*_update_mmu_cache)(void *vma, unsigned long addr, pte_t pte);
-			/* XCHG
-			 */
-			unsigned long (*_xchg_1)(unsigned long x, volatile void *ptr);
-			unsigned long (*_xchg_2)(unsigned long x, volatile void *ptr);
-			unsigned long (*_xchg_4)(unsigned long x, volatile void *ptr);
-		} armv2;
-	} u;
-} processor;
-#endif	
+#undef MULTI_CPU
+#undef CPU_NAME
+
+#ifdef CONFIG_CPU_26
+# define CPU_INCLUDE_NAME "asm/cpu-multi26.h"
+# define MULTI_CPU
+#endif
+
+#ifdef CONFIG_CPU_32
+# define CPU_INCLUDE_NAME "asm/cpu-multi32.h"
+# ifdef CONFIG_CPU_ARM6
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME arm6
+#  endif
+# endif
+# ifdef CONFIG_CPU_ARM7
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME arm7
+#  endif
+# endif
+# ifdef CONFIG_CPU_SA110
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME sa110
+#  endif
+# endif
 #endif
 
+#ifndef MULTI_CPU
+#undef CPU_INCLUDE_NAME
+#define CPU_INCLUDE_NAME "asm/cpu-single.h"
+#endif
+
+#include CPU_INCLUDE_NAME
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_PROCFNS_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/processor.h linux/include/asm-arm/processor.h
--- v2.3.15/linux/include/asm-arm/processor.h	Mon Aug  2 10:19:52 1999
+++ linux/include/asm-arm/processor.h	Mon Aug 30 18:15:21 1999
@@ -114,6 +114,11 @@
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
 
+/*
+ * Create a new kernel thread
+ */
+extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
 #endif
 
 #endif /* __ASM_ARM_PROCESSOR_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/procinfo.h linux/include/asm-arm/procinfo.h
--- v2.3.15/linux/include/asm-arm/procinfo.h	Sat Jul 18 11:55:25 1998
+++ linux/include/asm-arm/procinfo.h	Mon Aug 30 18:15:21 1999
@@ -1,34 +1,45 @@
 /*
  * linux/include/asm-arm/procinfo.h
  *
- * Copyright (C) 1996 Russell King
+ * Copyright (C) 1996-1999 Russell King
  */
-
 #ifndef __ASM_PROCINFO_H
 #define __ASM_PROCINFO_H
 
-#include <asm/proc-fns.h>
-
 #ifndef __ASSEMBLER__
 
-#define HWCAP_SWP	(1 << 0)
-#define HWCAP_HALF	(1 << 1)
+#include <asm/proc-fns.h>
 
-struct armversions {
-	const unsigned long id;		/* Processor ID			*/
-	const unsigned long mask;	/* Processor ID mask		*/
-	const char *manu;		/* Manufacturer			*/
-	const char *name;		/* Processor name		*/
-	const char *arch_vsn;		/* Architecture version		*/
-	const char *elf_vsn;		/* ELF library version		*/
-	const int hwcap;		/* ELF HWCAP			*/
-	const struct processor *proc;	/* Processor-specific ASM	*/
+struct proc_info_item {
+	const char	 *manufacturer;
+	const char	 *cpu_name;
 };
 
-extern const struct armversions armidlist[];
-extern int armidindex;
+/*
+ * Note!  struct processor is always defined if we're
+ * using MULTI_CPU, otherwise this entry is unused,
+ * but still exists.
+ */
+struct proc_info_list {
+	unsigned int	 cpu_val;
+	unsigned int	 cpu_mask;
+	const char	 *arch_name;
+	const char	 *elf_name;
+	unsigned int	 elf_hwcap;
+	struct proc_info_item *info;
+#ifdef MULTI_CPU
+	struct processor *proc;
+#else
+	void		 *unused;
+#endif
+};
 
 #endif
+
+#define HWCAP_SWP	1
+#define HWCAP_HALF	2
+#define HWCAP_THUMB	4
+#define HWCAP_26BIT	8	/* Play it safe */
 
 #endif
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/semaphore.h linux/include/asm-arm/semaphore.h
--- v2.3.15/linux/include/asm-arm/semaphore.h	Thu Jun 17 01:11:35 1999
+++ linux/include/asm-arm/semaphore.h	Mon Aug 30 18:15:21 1999
@@ -6,11 +6,12 @@
 
 #include <linux/linkage.h>
 #include <asm/atomic.h>
+#include <asm/spinlock.h>
 #include <linux/wait.h>
 
 struct semaphore {
 	atomic_t count;
-	int waking;
+	int sleepers;
 	wait_queue_head_t wait;
 };
 
@@ -30,7 +31,7 @@
 #define sema_init(sem, val)			\
 do {						\
 	atomic_set(&((sem)->count), (val));	\
-	(sem)->waking = 0;			\
+	(sem)->sleepers = 0;			\
 	init_waitqueue_head(&(sem)->wait);	\
 } while (0)
 
@@ -46,7 +47,7 @@
 
 asmlinkage void __down_failed (void /* special register calling convention */);
 asmlinkage int  __down_interruptible_failed (void /* special register calling convention */);
-asmlinkage int  __down_failed_trylock(void  /* params in registers */);
+asmlinkage int  __down_trylock_failed(void  /* params in registers */);
 asmlinkage void __up_wakeup (void /* special register calling convention */);
 
 extern void __down(struct semaphore * sem);
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/system.h linux/include/asm-arm/system.h
--- v2.3.15/linux/include/asm-arm/system.h	Tue Aug  3 08:01:29 1999
+++ linux/include/asm-arm/system.h	Mon Aug 30 18:15:21 1999
@@ -141,7 +141,7 @@
 #define wmb() mb()
 #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
 
-#define prepare_to_switch()	do { } while(0)
+#define prepare_to_switch()    do { } while(0)
 
 /*
  * switch_to(prev, next) should switch from task `prev' to `next'
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/termios.h linux/include/asm-arm/termios.h
--- v2.3.15/linux/include/asm-arm/termios.h	Wed Dec 16 13:35:49 1998
+++ linux/include/asm-arm/termios.h	Mon Aug 30 18:15:21 1999
@@ -43,6 +43,8 @@
 #define TIOCM_DSR	0x100
 #define TIOCM_CD	TIOCM_CAR
 #define TIOCM_RI	TIOCM_RNG
+#define TIOCM_OUT1	0x2000
+#define TIOCM_OUT2	0x4000
 
 /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 
@@ -60,6 +62,7 @@
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define N_HDLC		13	/* synchronous HDLC */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-arm/unistd.h linux/include/asm-arm/unistd.h
--- v2.3.15/linux/include/asm-arm/unistd.h	Thu Aug 26 13:05:40 1999
+++ linux/include/asm-arm/unistd.h	Mon Aug 30 18:15:21 1999
@@ -395,11 +395,6 @@
  */
 static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp);
 
-/*
- * Create a new kernel thread
- */
-extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 #endif
 #endif /* __ASM_ARM_UNISTD_H */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-i386/bigmem.h linux/include/asm-i386/bigmem.h
--- v2.3.15/linux/include/asm-i386/bigmem.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/bigmem.h	Tue Aug 31 16:12:02 1999
@@ -0,0 +1,69 @@
+/*
+ * bigmem.h:	virtual kernel memory mappings for big memory
+ *
+ * Used in CONFIG_BIGMEM systems for memory pages which	are not
+ * addressable by direct kernel virtual adresses.
+ *
+ * Copyright (C) 1999 Gerhard Wichert, Siemens AG
+ *		      Gerhard.Wichert@pdb.siemens.de
+ */
+
+#ifndef _ASM_BIGMEM_H
+#define _ASM_BIGMEM_H
+
+#include <linux/init.h>
+
+#define BIGMEM_DEBUG /* undef for production */
+
+/* declarations for bigmem.c */
+extern unsigned long bigmem_start, bigmem_end;
+extern int nr_free_bigpages;
+
+extern pte_t *kmap_pte;
+extern pgprot_t kmap_prot;
+
+extern void kmap_init(void) __init;
+
+/* kmap helper functions necessary to access the bigmem pages in kernel */
+#include <asm/pgtable.h>
+#include <asm/kmap_types.h>
+
+extern inline unsigned long kmap(unsigned long kaddr, enum km_type type)
+{
+	if (__pa(kaddr) < bigmem_start)
+		return kaddr;
+	{
+		enum fixed_addresses idx = type+KM_TYPE_NR*smp_processor_id();
+		unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN+idx);
+
+#ifdef BIGMEM_DEBUG
+		if (!pte_none(*(kmap_pte-idx)))
+		{
+			__label__ here;
+		here:
+			printk(KERN_ERR "not null pte on CPU %d from %p\n",
+			       smp_processor_id(), &&here);
+		}
+#endif
+		set_pte(kmap_pte-idx, mk_pte(kaddr & PAGE_MASK, kmap_prot));
+		__flush_tlb_one(vaddr);
+
+		return vaddr | (kaddr & ~PAGE_MASK);
+	}
+}
+
+extern inline void kunmap(unsigned long vaddr, enum km_type type)
+{
+#ifdef BIGMEM_DEBUG
+	enum fixed_addresses idx = type+KM_TYPE_NR*smp_processor_id();
+	if ((vaddr & PAGE_MASK) == __fix_to_virt(FIX_KMAP_BEGIN+idx))
+	{
+		/* force other mappings to Oops if they'll try to access
+		   this pte without first remap it */
+		pte_clear(kmap_pte-idx);
+		__flush_tlb_one(vaddr);
+	}
+#endif
+}
+
+#endif /* _ASM_BIGMEM_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h
--- v2.3.15/linux/include/asm-i386/bugs.h	Wed Aug 18 16:43:26 1999
+++ linux/include/asm-i386/bugs.h	Tue Aug 31 16:11:54 1999
@@ -50,7 +50,7 @@
 
 static char __initdata fpu_error = 0;
 
-__initfunc(static void copro_timeout(void))
+static void __init copro_timeout(void)
 {
 	fpu_error = 1;
 	timer_table[COPRO_TIMER].expires = jiffies+100;
@@ -64,7 +64,7 @@
 static double __initdata x = 4195835.0;
 static double __initdata y = 3145727.0;
 
-__initfunc(static void check_fpu(void))
+static void __init check_fpu(void)
 {
 	unsigned short control_word;
 
@@ -111,7 +111,7 @@
 	 * should get there first..
 	 */
 	printk(KERN_INFO "Checking 386/387 coupling... ");
-	timer_table[COPRO_TIMER].expires = jiffies+50;
+	timer_table[COPRO_TIMER].expires = jiffies+HZ/2;
 	timer_table[COPRO_TIMER].fn = copro_timeout;
 	timer_active |= 1<<COPRO_TIMER;
 	__asm__("clts ; fninit ; fnstcw %0 ; fwait":"=m" (*&control_word));
@@ -143,7 +143,7 @@
 		printk("Hmm, FPU using exception 16 error reporting with FDIV bug.\n");
 }
 
-__initfunc(static void check_hlt(void))
+static void __init check_hlt(void)
 {
 	printk(KERN_INFO "Checking 'hlt' instruction... ");
 	if (!boot_cpu_data.hlt_works_ok) {
@@ -159,7 +159,7 @@
  *	machine even from user space.
  */
  
-__initfunc(static void check_popad(void))
+static void __init check_popad(void)
 {
 #ifndef CONFIG_X86_POPAD_OK
 	int res, inp = (int) &res;
@@ -192,7 +192,7 @@
 extern void vide(void);
 __asm__(".align 4\nvide: ret");
 
-__initfunc(static void check_amd_k6(void))
+static void __init check_amd_k6(void)
 {
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
 	    boot_cpu_data.x86_model == 6 &&
@@ -238,7 +238,7 @@
 
 extern void trap_init_f00f_bug(void);
 
-__initfunc(static void check_pentium_f00f(void))
+static void __init check_pentium_f00f(void)
 {
 	/*
 	 * Pentium and Pentium MMX
@@ -280,7 +280,7 @@
 
 extern unsigned char Cx86_dir0_msb;  /* exported HACK from cyrix_model() */
 
-__initfunc(static void check_cx686_cpuid(void))
+static void __init check_cx686_cpuid(void)
 {
 	if (boot_cpu_data.cpuid_level == -1 &&
 	    ((Cx86_dir0_msb == 5) || (Cx86_dir0_msb == 3))) {
@@ -320,7 +320,7 @@
 
 extern void calibrate_delay(void) __init;
 
-__initfunc(static void check_cx686_slop(void))
+static void __init check_cx686_slop(void)
 {
 	if (Cx86_dir0_msb == 3) {
 		unsigned char ccr3, ccr5;
@@ -348,7 +348,7 @@
  * PII and PPro exhibit this behavior too, but they have cpuid available.
  */
 
-__initfunc(static void check_cyrix_cpu(void))
+static void __init check_cyrix_cpu(void)
 {
 	if ((boot_cpu_data.cpuid_level == -1) && (boot_cpu_data.x86 == 4)
 	    && test_cyrix_52div()) {
@@ -363,7 +363,7 @@
  * enable the workaround for it.
  */
 
-__initfunc(static void check_cyrix_coma(void))
+static void __init check_cyrix_coma(void)
 {
 }
  
@@ -380,7 +380,7 @@
  *   reads from the APIC.
 */
 
-__initfunc(static void check_config(void))
+static void __init check_config(void)
 {
 /*
  * We'd better not be a i386 if we're configured to use some
@@ -409,7 +409,7 @@
 #endif
 }
 
-__initfunc(static void check_bugs(void))
+static void __init check_bugs(void)
 {
 	check_cyrix_cpu();
 	identify_cpu(&boot_cpu_data);
diff -u --recursive --new-file v2.3.15/linux/include/asm-i386/e820.h linux/include/asm-i386/e820.h
--- v2.3.15/linux/include/asm-i386/e820.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/e820.h	Mon Aug 30 10:47:02 1999
@@ -0,0 +1,35 @@
+/*
+ * structures and definitions for the int 15, ax=e820 memory map
+ * scheme.
+ *
+ * In a nutshell, arch/i386/boot/setup.S populates a scratch table
+ * in the empty_zero_block that contains a list of usable address/size
+ * duples.   In arch/i386/kernel/setup.c, this information is
+ * transferred into the e820map, and in arch/i386/mm/init.c, that
+ * new information is used to mark pages reserved or not.
+ *
+ */
+#ifndef __E820_HEADER
+#define __E820_HEADER
+
+#define E820MAP	0x2d0		/* our map */
+#define E820MAX	32		/* number of entries in E820MAP */
+#define E820NR	0x1e8		/* # entries in E820MAP */
+
+#define HIGH_MEMORY	(1024*1024)
+
+#ifndef __ASSEMBLY__
+
+struct e820map {
+    int nr_map;
+    struct {
+	long long addr;		/* start of memory segment */
+	long long size;		/* size of memory segment */
+	long type;		/* type of memory segment */
+    } map[E820MAX];
+};
+
+extern struct e820map e820;
+#endif/*!__ASSEMBLY__*/
+
+#endif/*__E820_HEADER*/
diff -u --recursive --new-file v2.3.15/linux/include/asm-i386/fixmap.h linux/include/asm-i386/fixmap.h
--- v2.3.15/linux/include/asm-i386/fixmap.h	Wed Aug 18 16:43:30 1999
+++ linux/include/asm-i386/fixmap.h	Tue Aug 31 16:11:58 1999
@@ -6,6 +6,8 @@
  * for more details.
  *
  * Copyright (C) 1998 Ingo Molnar
+ *
+ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
  */
 
 #ifndef _ASM_FIXMAP_H
@@ -15,6 +17,10 @@
 #include <linux/kernel.h>
 #include <asm/apic.h>
 #include <asm/page.h>
+#ifdef CONFIG_BIGMEM
+#include <linux/tasks.h>
+#include <asm/kmap_types.h>
+#endif
 
 /*
  * Here we define all the compile-time 'special' virtual
@@ -54,6 +60,10 @@
 	FIX_CO_APIC,	/* Cobalt APIC Redirection Table */ 
 	FIX_LI_PCIA,	/* Lithium PCI Bridge A */
 	FIX_LI_PCIB,	/* Lithium PCI Bridge B */
+#endif
+#ifdef CONFIG_BIGMEM
+	FIX_KMAP_BEGIN,	/* reserved pte's for temporary kernel mappings */
+	FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
 #endif
 	__end_of_fixed_addresses
 };
diff -u --recursive --new-file v2.3.15/linux/include/asm-i386/io.h linux/include/asm-i386/io.h
--- v2.3.15/linux/include/asm-i386/io.h	Thu Aug 26 13:05:41 1999
+++ linux/include/asm-i386/io.h	Tue Aug 31 16:12:10 1999
@@ -27,6 +27,7 @@
 
  /*
   *  Bit simplified and optimized by Jan Hubicka
+  *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
   */
 
 #ifdef SLOW_IO_BY_JUMPING
@@ -98,6 +99,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/config.h>
 #include <linux/vmalloc.h>
 #include <asm/page.h>
 
@@ -109,12 +111,20 @@
  */
 extern inline unsigned long virt_to_phys(volatile void * address)
 {
+#ifdef CONFIG_BIGMEM
+	return __pa(address);
+#else
 	return __io_phys(address);
+#endif
 }
 
 extern inline void * phys_to_virt(unsigned long address)
 {
+#ifdef CONFIG_BIGMEM
+	return __va(address);
+#else
 	return __io_virt(address);
+#endif
 }
 
 extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
diff -u --recursive --new-file v2.3.15/linux/include/asm-i386/kmap_types.h linux/include/asm-i386/kmap_types.h
--- v2.3.15/linux/include/asm-i386/kmap_types.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/kmap_types.h	Thu Aug 26 12:34:55 1999
@@ -0,0 +1,10 @@
+#ifndef _ASM_KMAP_TYPES_H
+#define _ASM_KMAP_TYPES_H
+
+enum km_type {
+	KM_READ,
+	KM_WRITE,
+	KM_TYPE_NR,
+};
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/asm-i386/page.h linux/include/asm-i386/page.h
--- v2.3.15/linux/include/asm-i386/page.h	Wed Aug 18 16:43:28 1999
+++ linux/include/asm-i386/page.h	Tue Aug 31 16:11:56 1999
@@ -101,6 +101,7 @@
 #define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
 #define MAP_NR(addr)		(__pa(addr) >> PAGE_SHIFT)
+#define PHYSMAP_NR(addr)	((unsigned long)(addr) >> PAGE_SHIFT)
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-i386/pci.h linux/include/asm-i386/pci.h
--- v2.3.15/linux/include/asm-i386/pci.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/pci.h	Tue Aug 31 11:21:39 1999
@@ -0,0 +1,11 @@
+#ifndef __i386_PCI_H
+#define __i386_PCI_H
+
+/* Can be used to override the logic in pci_scan_bus for skipping
+   already-configured bus numbers - to be used for buggy BIOSes
+   or architectures with incomplete PCI setup by the loader */
+
+#define pcibios_assign_all_busses()	0
+
+#endif /* __i386_PCI_H */
+
diff -u --recursive --new-file v2.3.15/linux/include/asm-i386/serial.h linux/include/asm-i386/serial.h
--- v2.3.15/linux/include/asm-i386/serial.h	Wed Aug 18 16:43:33 1999
+++ linux/include/asm-i386/serial.h	Tue Aug 31 16:11:58 1999
@@ -27,6 +27,9 @@
 #define ACCENT_FLAGS 0
 #define BOCA_FLAGS 0
 #define HUB6_FLAGS 0
+#define RS_TABLE_SIZE	64
+#else
+#define RS_TABLE_SIZE
 #endif
 	
 /*
diff -u --recursive --new-file v2.3.15/linux/include/asm-i386/softirq.h linux/include/asm-i386/softirq.h
--- v2.3.15/linux/include/asm-i386/softirq.h	Wed Aug 18 16:43:30 1999
+++ linux/include/asm-i386/softirq.h	Tue Aug 31 16:11:57 1999
@@ -18,24 +18,7 @@
 #define get_active_bhs()	(bh_mask & bh_active)
 #define clear_active_bhs(x)	atomic_clear_mask((x),&bh_active)
 
-extern inline void init_bh(int nr, void (*routine)(void))
-{
-	bh_base[nr] = routine;
-	atomic_set(&bh_mask_count[nr], 0);
-	bh_mask |= 1 << nr;
-}
-
-extern inline void remove_bh(int nr)
-{
-	bh_mask &= ~(1 << nr);
-	mb();
-	bh_base[nr] = NULL;
-}
-
-extern inline void mark_bh(int nr)
-{
-	set_bit(nr, &bh_active);
-}
+extern spinlock_t i386_bh_lock;
 
 #ifdef __SMP__
 
@@ -101,21 +84,58 @@
 
 #endif	/* SMP */
 
+extern inline void init_bh(int nr, void (*routine)(void))
+{
+	unsigned long flags;
+
+	bh_base[nr] = routine;
+	atomic_set(&bh_mask_count[nr], 0);
+
+	spin_lock_irqsave(&i386_bh_lock, flags);
+	bh_mask |= 1 << nr;
+	spin_unlock_irqrestore(&i386_bh_lock, flags);
+}
+
+extern inline void remove_bh(int nr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&i386_bh_lock, flags);
+	bh_mask &= ~(1 << nr);
+	spin_unlock_irqrestore(&i386_bh_lock, flags);
+
+	synchronize_bh();
+	bh_base[nr] = NULL;
+}
+
+extern inline void mark_bh(int nr)
+{
+	set_bit(nr, &bh_active);
+}
+
 /*
  * These use a mask count to correctly handle
  * nested disable/enable calls
  */
 extern inline void disable_bh(int nr)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&i386_bh_lock, flags);
 	bh_mask &= ~(1 << nr);
 	atomic_inc(&bh_mask_count[nr]);
+	spin_unlock_irqrestore(&i386_bh_lock, flags);
 	synchronize_bh();
 }
 
 extern inline void enable_bh(int nr)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&i386_bh_lock, flags);
 	if (atomic_dec_and_test(&bh_mask_count[nr]))
 		bh_mask |= 1 << nr;
+	spin_unlock_irqrestore(&i386_bh_lock, flags);
 }
 
 #endif	/* __ASM_SOFTIRQ_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
--- v2.3.15/linux/include/asm-i386/system.h	Thu Aug 26 13:05:41 1999
+++ linux/include/asm-i386/system.h	Tue Aug 31 16:11:57 1999
@@ -133,7 +133,7 @@
  * Note 2: xchg has side effect, so that attribute volatile is necessary,
  *	  but generally the primitive is invalid, *ptr is output argument. --ANK
  */
-static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
 {
 	switch (size) {
 		case 1:
@@ -175,6 +175,9 @@
 #define mb() 	__asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
 #define rmb()	mb()
 #define wmb()	__asm__ __volatile__ ("": : :"memory")
+#define set_rmb(var, value) do { xchg(&var, value); } while (0)
+#define set_mb(var, value) set_rmb(var, value)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
 
 /* interrupt control.. */
 #define __save_flags(x)		__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory")
diff -u --recursive --new-file v2.3.15/linux/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h
--- v2.3.15/linux/include/asm-i386/uaccess.h	Wed Aug 18 16:43:40 1999
+++ linux/include/asm-i386/uaccess.h	Tue Aug 31 16:12:08 1999
@@ -42,7 +42,7 @@
 	unsigned long flag,sum; \
 	asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
 		:"=&r" (flag), "=r" (sum) \
-		:"1" (addr),"g" (size),"g" (current->addr_limit.seg)); \
+		:"1" (addr),"g" ((int)(size)),"g" (current->addr_limit.seg)); \
 	flag; })
 
 #ifdef CONFIG_X86_WP_WORKS_OK
diff -u --recursive --new-file v2.3.15/linux/include/asm-m68k/hwtest.h linux/include/asm-m68k/hwtest.h
--- v2.3.15/linux/include/asm-m68k/hwtest.h	Sat Jun 13 13:14:33 1998
+++ linux/include/asm-m68k/hwtest.h	Tue Aug 31 11:23:03 1999
@@ -2,7 +2,7 @@
  * see arch/m68k/mm/hwtest.c.
  *  -- PMM <pmaydell@chiark.greenend.org.uk> 05/1998
  *
- * Removed initfunc from decls.  We might want them in modules, and 
+ * Removed __init from decls.  We might want them in modules, and 
  * the code is tiny anyway.  16/5/98 pb
  */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-m68k/init.h linux/include/asm-m68k/init.h
--- v2.3.15/linux/include/asm-m68k/init.h	Tue Jan 19 10:58:34 1999
+++ linux/include/asm-m68k/init.h	Thu Aug 26 14:20:51 1999
@@ -7,9 +7,6 @@
 
 #define __init __attribute__ ((__section__ (".text.init")))
 #define __initdata __attribute__ ((__section__ (".data.init")))
-#define __initfunc(__arginit) \
-	__arginit __init; \
-	__arginit
 /* For assembly routines */
 #define __INIT		.section	".text.init",#alloc,#execinstr
 #define __FINIT		.previous
@@ -25,7 +22,6 @@
 	
 #define __init
 #define __initdata
-#define __initfunc(__arginit) __arginit
 /* For assembly routines */
 #define __INIT
 #define __FINIT
diff -u --recursive --new-file v2.3.15/linux/include/asm-mips/init.h linux/include/asm-mips/init.h
--- v2.3.15/linux/include/asm-mips/init.h	Fri Jun 25 17:37:53 1999
+++ linux/include/asm-mips/init.h	Thu Aug 26 14:20:51 1999
@@ -11,9 +11,6 @@
 
 #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
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/cache.h linux/include/asm-ppc/cache.h
--- v2.3.15/linux/include/asm-ppc/cache.h	Fri Mar 19 10:50:51 1999
+++ linux/include/asm-ppc/cache.h	Tue Aug 31 11:36:43 1999
@@ -15,6 +15,14 @@
 
 #define        SMP_CACHE_BYTES L1_CACHE_BYTES
 
+#ifdef MODULE
+#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
+#else
+#define __cacheline_aligned					\
+  __attribute__((__aligned__(L1_CACHE_BYTES),			\
+		 __section__(".data.cacheline_aligned")))
+#endif
+
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 extern void flush_dcache_range(unsigned long start, unsigned long stop);
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/gemini.h linux/include/asm-ppc/gemini.h
--- v2.3.15/linux/include/asm-ppc/gemini.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/gemini.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,165 @@
+/*
+ *  include/asm-ppc/gemini.h
+ *
+ *
+ *  Onboard registers and descriptions for Synergy Microsystems' 
+ *  "Gemini" boards.
+ *
+ */
+#ifndef __PPC_GEMINI_H
+#define __PPC_GEMINI_H
+
+/*  Registers  */
+
+#define GEMINI_SERIAL_B     (0xffeffb00)
+#define GEMINI_SERIAL_A     (0xffeffb08)
+#define GEMINI_USWITCH      (0xffeffd00)
+#define GEMINI_BREV         (0xffeffe00)
+#define GEMINI_BECO         (0xffeffe08)
+#define GEMINI_FEAT         (0xffeffe10)
+#define GEMINI_BSTAT        (0xffeffe18)
+#define GEMINI_CPUSTAT      (0xffeffe20)
+#define GEMINI_L2CFG        (0xffeffe30)
+#define GEMINI_MEMCFG       (0xffeffe38)
+#define GEMINI_FLROM        (0xffeffe40)
+#define GEMINI_P0PCI        (0xffeffe48)
+#define GEMINI_FLWIN        (0xffeffe50)
+#define GEMINI_P0INTMASK    (0xffeffe60)
+#define GEMINI_P0INTAP      (0xffeffe68)
+#define GEMINI_PCIERR       (0xffeffe70)
+#define GEMINI_LEDBASE      (0xffeffe80)
+#define GEMINI_RTC          (0xffe9fff8)
+#define GEMINI_LEDS         8
+#define GEMINI_SWITCHES     8
+
+
+/* Flash ROM bit definitions */
+#define GEMINI_FLS_WEN      (1<<0)
+#define GEMINI_FLS_JMP      (1<<6)
+#define GEMINI_FLS_BOOT     (1<<7)
+
+/* Memory bit definitions */
+#define GEMINI_MEM_TYPE_MASK 0xc0
+#define GEMINI_MEM_SIZE_MASK 0x38
+#define GEMINI_MEM_BANK_MASK 0x07
+
+/* L2 cache bit definitions */
+#define GEMINI_L2_SIZE_MASK  0xc0
+#define GEMINI_L2_RATIO_MASK 0x03
+
+/* Timebase register bit definitons */
+#define GEMINI_TIMEB0_EN     (1<<0)
+#define GEMINI_TIMEB1_EN     (1<<1)
+#define GEMINI_TIMEB2_EN     (1<<2)
+#define GEMINI_TIMEB3_EN     (1<<3)
+
+/* CPU status bit definitions */
+#define GEMINI_CPU_ID_MASK   0x03
+#define GEMINI_CPU_COUNT_MASK 0x0c
+#define GEMINI_CPU0_HALTED   (1<<4)
+#define GEMINI_CPU1_HALTED   (1<<5)
+#define GEMINI_CPU2_HALTED   (1<<6)
+#define GEMINI_CPU3_HALTED   (1<<7)
+
+/* Board status bit definitions */
+#define GEMINI_BRD_FAIL      (1<<0)   /* FAIL led is lit */
+#define GEMINI_BRD_BUS_MASK  0x0c     /* PowerPC bus speed */
+
+/* Board family/feature bit descriptions */
+#define GEMINI_FEAT_HAS_FLASH (1<<0)
+#define GEMINI_FEAT_HAS_ETH   (1<<1)
+#define GEMINI_FEAT_HAS_SCSI  (1<<2)
+#define GEMINI_FEAT_HAS_P0    (1<<3)
+#define GEMINI_FEAT_FAM_MASK  0xf0
+
+/* Mod/ECO bit definitions */
+#define GEMINI_ECO_LEVEL_MASK 0x0f
+#define GEMINI_MOD_MASK       0xf0
+
+/* Type/revision bit definitions */
+#define GEMINI_REV_MASK       0x0f
+#define GEMINI_TYPE_MASK      0xf0
+
+/* User switch definitions */
+#define GEMINI_SWITCH_VERBOSE    1     /* adds "debug" to boot cmd line */
+#define GEMINI_SWITCH_SINGLE_USER 7    /* boots into "single-user" mode */
+
+#define SGS_RTC_CONTROL  0
+#define SGS_RTC_SECONDS  1
+#define SGS_RTC_MINUTES  2
+#define SGS_RTC_HOURS    3
+#define SGS_RTC_DAY      4
+#define SGS_RTC_DAY_OF_MONTH 5
+#define SGS_RTC_MONTH    6
+#define SGS_RTC_YEAR     7
+
+#define SGS_RTC_SET  0x80
+#define SGS_RTC_IS_STOPPED 0x80
+
+#define GRACKLE_CONFIG_ADDR_ADDR  (0xfec00000)
+#define GRACKLE_CONFIG_DATA_ADDR  (0xfee00000)
+
+#define GEMINI_BOOT_INIT  (0xfff00100)
+
+#ifndef __ASSEMBLY__
+
+static inline void grackle_write( unsigned long addr, unsigned long data )
+{
+  __asm__ __volatile__(
+  " stwbrx %1, 0, %0\n \
+    sync\n \
+    stwbrx %3, 0, %2\n \
+    sync "
+  : /* no output */
+  : "r" (GRACKLE_CONFIG_ADDR_ADDR), "r" (addr),
+    "r" (GRACKLE_CONFIG_DATA_ADDR), "r" (data));
+}
+
+static inline unsigned long grackle_read( unsigned long addr )
+{
+  unsigned long val;
+
+  __asm__ __volatile__(
+  " stwbrx %1, 0, %2\n \
+    sync\n \
+    lwbrx %0, 0, %3\n \
+    sync "
+  : "=r" (val)
+  : "r" (addr), "r" (GRACKLE_CONFIG_ADDR_ADDR),
+    "r" (GRACKLE_CONFIG_DATA_ADDR));
+
+  return val;
+}
+
+static inline void gemini_led_on( int led )
+{
+  if (led >= 0 && led < GEMINI_LEDS)
+    *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 1;
+}
+
+static inline void gemini_led_off(int led)
+{
+  if (led >= 0 && led < GEMINI_LEDS)
+    *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 0;
+}
+
+static inline int gemini_led_val(int led)
+{
+  int val = 0;
+  if (led >= 0 && led < GEMINI_LEDS)
+    val = *(unsigned char *)(GEMINI_LEDBASE + (led<<3));
+  return (val & 0x1);
+}
+
+/* returns processor id from the board */
+static inline int gemini_processor(void)
+{
+  unsigned char cpu = *(unsigned char *)(GEMINI_CPUSTAT);
+  return (int) ((cpu == 0) ? 4 : (cpu & GEMINI_CPU_ID_MASK));
+}
+
+
+extern void _gemini_reboot(void);
+extern void gemini_init_l2(void);
+#endif /* __ASSEMBLY__ */
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/gemini_serial.h linux/include/asm-ppc/gemini_serial.h
--- v2.3.15/linux/include/asm-ppc/gemini_serial.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/gemini_serial.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,32 @@
+#ifndef __ASMPPC_GEMINI_SERIAL_H
+#define __ASMPPC_GEMINI_SERIAL_H
+
+#include <asm/gemini.h>
+
+/* Rate for the 24.576 Mhz clock for the onboard serial chip */
+#define BASE_BAUD  (24576000 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_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
+
+#define STD_SERIAL_PORT_DEFNS \
+        { 0, BASE_BAUD, GEMINI_SERIAL_A, 15, STD_COM_FLAGS }, /* ttyS0 */ \
+        { 0, BASE_BAUD, GEMINI_SERIAL_B, 14, STD_COM_FLAGS }, /* ttyS1 */ \
+
+#ifdef CONFIG_GEMINI_PU32
+#define PU32_SERIAL_PORT_DEFNS \
+        { 0, BASE_BAUD, NULL, 0, STD_COM_FLAGS },
+#else
+#define PU32_SERIAL_PORT_DEFNS
+#endif
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DEFNS \
+        PU32_SERIAL_PORT_DEFNS
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h
--- v2.3.15/linux/include/asm-ppc/ide.h	Fri Aug  6 11:16:54 1999
+++ linux/include/asm-ppc/ide.h	Tue Aug 31 11:36:43 1999
@@ -109,10 +109,14 @@
 #ifndef CONFIG_BLK_DEV_IDEPCI
 	hw_regs_t hw;
 	int index;
+	ide_ioreg_t base;
 
-	for(index = 0; index < MAX_HWIFS; index++) {
-		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
-		hw.irq = ide_default_irq(ide_default_io_base(index));
+	for (index = 0; index < MAX_HWIFS; index++) {
+		base = ide_default_io_base(index);
+		if (base == 0)
+			continue;
+		ide_init_hwif_ports(&hw, base, 0, NULL);
+		hw.irq = ide_default_irq(base);
 		ide_register_hw(&hw, NULL);
 	}
 #endif /* CONFIG_BLK_DEV_IDEPCI */
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/init.h linux/include/asm-ppc/init.h
--- v2.3.15/linux/include/asm-ppc/init.h	Wed Dec 30 10:56:58 1998
+++ linux/include/asm-ppc/init.h	Tue Aug 31 11:36:43 1999
@@ -1,25 +1,26 @@
 #ifndef _PPC_INIT_H
 #define _PPC_INIT_H
 
-#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
+#include <linux/init.h>
 
-#define __pmac __attribute__ ((__section__ (".text.pmac")))
+#if 0/*__GNUC__ > 2 || __GNUC_MINOR__ >= 90*/ /* egcs */
 #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 __prepdata /* __attribute__ ((__section__ (".data.prep")))*/
 #define __prepfunc(__argprep) \
 	__argprep __prep; \
 	__argprep
 
+#define __apus __attribute__ ((__section__ (".text.apus")))
+#define __apusdata __attribute__ ((__section__ (".data.apus")))
+#define __apusfunc(__argapus) \
+	__argapus __apus; \
+	__argapus
+
 /* this is actually just common chrp/pmac code, not OF code -- Cort */
 #define __openfirmware __attribute__ ((__section__ (".text.openfirmware")))
 #define __openfirmwaredata __attribute__ ((__section__ (".data.openfirmware")))
@@ -27,23 +28,8 @@
 	__argopenfirmware __openfirmware; \
 	__argopenfirmware
 	
-#define __INIT		.section	".text.init",#alloc,#execinstr
-#define __FINIT	.previous
-#define __INITDATA	.section	".data.init",#alloc,#write
-
-#define __cacheline_aligned __attribute__ \
-			 ((__section__ (".data.cacheline_aligned")))
-
 #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
@@ -52,10 +38,14 @@
 #define __prepdata
 #define __prepfunc(x) x
 
+#define __apus
+#define __apusdata
+#define __apusfunc(x) x
+
 #define __openfirmware
 #define __openfirmwaredata
 #define __openfirmwarefunc(x) x
 
-#define __cacheline_aligned
 #endif /* egcs */
-#endif
+
+#endif /* _PPC_INIT_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/io.h linux/include/asm-ppc/io.h
--- v2.3.15/linux/include/asm-ppc/io.h	Thu May 13 11:00:09 1999
+++ linux/include/asm-ppc/io.h	Tue Aug 31 11:36:43 1999
@@ -77,7 +77,7 @@
 #define outb_p(val, port)	out_8((unsigned char *)((port)+_IO_BASE), (val))
 #define inw_p(port)		in_le16((unsigned short *)((port)+_IO_BASE))
 #define outw_p(val, port)	out_le16((unsigned short *)((port)+_IO_BASE), (val))
-#define inl_p(port)		in_le32(((unsigned *)(port)+_IO_BASE))
+#define inl_p(port)		in_le32((unsigned *)((port)+_IO_BASE))
 #define outl_p(val, port)	out_le32((unsigned *)((port)+_IO_BASE), (val))
 
 extern void _insb(volatile unsigned char *port, void *buf, int ns);
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/irq.h linux/include/asm-ppc/irq.h
--- v2.3.15/linux/include/asm-ppc/irq.h	Mon Jun 28 13:40:39 1999
+++ linux/include/asm-ppc/irq.h	Tue Aug 31 11:36:43 1999
@@ -29,11 +29,9 @@
 #endif /* CONFIG_APUS */
 
 #define NUM_8259_INTERRUPTS	16
-#define NUM_OPENPIC_INTERRUPTS	20
-#define is_8259_irq(n)		((n) < NUM_8259_INTERRUPTS)
+#define IRQ_8259_CASCADE	16
 #define openpic_to_irq(n)	((n)+NUM_8259_INTERRUPTS)
 #define irq_to_openpic(n)	((n)-NUM_8259_INTERRUPTS)
-#define IRQ_8259_CASCADE	NUM_8259_INTERRUPTS
 
 #ifndef CONFIG_APUS
 /*
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/irq_control.h linux/include/asm-ppc/irq_control.h
--- v2.3.15/linux/include/asm-ppc/irq_control.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/irq_control.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,84 @@
+/*
+ * $Id: irq_control.h,v 1.2 1999/07/17 20:23:58 cort Exp $
+ *
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
+#ifndef _PPC_IRQ_CONTROL_H
+#define _PPC_IRQ_CONTROL_H
+
+#include <linux/config.h>
+
+#include <asm/irq.h>
+#include <asm/atomic.h>
+
+extern void do_lost_interrupts(unsigned long);
+extern atomic_t ppc_n_lost_interrupts;
+
+#define __no_use_save_flags(flags) \
+	({__asm__ __volatile__ ("mfmsr %0" : "=r" ((flags)) : : "memory"); })
+
+extern __inline__ void __no_use_restore_flags(unsigned long flags)
+{
+        if ((flags & MSR_EE) && atomic_read(&ppc_n_lost_interrupts) != 0) {
+                do_lost_interrupts(flags);
+        } else {
+                __asm__ __volatile__ ("sync; mtmsr %0; isync"
+                              : : "r" (flags) : "memory");
+        }
+}
+
+extern __inline__ void __no_use_sti(void)
+{
+	unsigned long flags;
+
+	__asm__ __volatile__ ("mfmsr %0": "=r" (flags));
+	flags |= MSR_EE;
+	if ( atomic_read(&ppc_n_lost_interrupts) )
+		do_lost_interrupts(flags);
+	__asm__ __volatile__ ("sync; mtmsr %0; isync":: "r" (flags));
+}
+
+extern __inline__ void __no_use_cli(void)
+{
+	unsigned long flags;
+	__asm__ __volatile__ ("mfmsr %0": "=r" (flags));
+	flags &= ~MSR_EE;
+	__asm__ __volatile__ ("sync; mtmsr %0; isync":: "r" (flags));
+}
+
+#define __no_use_mask_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->disable) irq_desc[irq].ctl->disable(irq);})
+#define __no_use_unmask_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->enable) irq_desc[irq].ctl->enable(irq);})
+#define __no_use_mask_and_ack_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->mask_and_ack) irq_desc[irq].ctl->mask_and_ack(irq);})
+
+#ifdef CONFIG_RTL
+
+/* the rtl system provides these -- Cort */
+extern void __sti(void);
+extern void __cli(void);
+extern void __restore_flags(unsigned int);
+extern unsigned int __return_flags(void);
+#define __save_flags(flags) (flags = __return_flags())
+
+#define rtl_hard_cli __no_use_cli
+#define rtl_hard_sti __no_use_sti
+#define rtl_hard_save_flags(flags) __no_use_save_flags(flags)
+#define rtl_hard_restore_flags(flags) __no_use_restore_flags(flags)
+
+#define rtl_hard_mask_irq(irq) __no_use_mask_irq(irq)
+#define rtl_hard_unmask_irq(irq) __no_use_unmask_irq(irq)
+#define rtl_hard_mask_and_ack_irq(irq) __no_use_mask_and_ack_irq(irq)
+
+#else /* CONFIG_RTL */
+
+#define __cli __no_use_cli
+#define __sti __no_use_sti
+#define __save_flags(flags) __no_use_save_flags(flags)
+#define __restore_flags(flags) __no_use_restore_flags(flags)
+
+#define mask_irq(irq) __no_use_mask_irq(irq)
+#define unmask_irq(irq) __no_use_unmask_irq(irq)
+#define mask_and_ack_irq(irq) __no_use_mask_and_ack_irq(irq)
+
+#endif /* CONFIG_RTL */
+
+#endif /* _PPC_IRQ_CONTROL_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/m48t35.h linux/include/asm-ppc/m48t35.h
--- v2.3.15/linux/include/asm-ppc/m48t35.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/m48t35.h	Tue Aug 31 11:36:43 1999
@@ -0,0 +1,30 @@
+/*
+ *  Registers for the SGS-Thomson M48T35 Timekeeper RAM chip
+ */
+
+#ifndef __PPC_M48T35_H
+#define __PPC_M48T35_H
+
+/* RTC offsets */
+#define M48T35_RTC_CONTROL  0
+#define M48T35_RTC_SECONDS  1
+#define M48T35_RTC_MINUTES  2
+#define M48T35_RTC_HOURS    3
+#define M48T35_RTC_DAY      4
+#define M48T35_RTC_DOM      5
+#define M48T35_RTC_MONTH    6
+#define M48T35_RTC_YEAR     7
+
+#define M48T35_RTC_SET      0x80
+#define M48T35_RTC_STOPPED  0x80
+#define M48T35_RTC_READ     0x40
+
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(x)   ((x)=((x)&15) + ((x)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(x)   ((x)=(((x)/10)<<4) + (x)%10)
+#endif
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/machdep.h linux/include/asm-ppc/machdep.h
--- v2.3.15/linux/include/asm-ppc/machdep.h	Mon Jul 12 15:12:55 1999
+++ linux/include/asm-ppc/machdep.h	Tue Aug 31 11:36:43 1999
@@ -79,4 +79,19 @@
 
 extern void setup_pci_ptrs(void);
 
+#define BOOT_INFO_VER 0x1
+#define BOOT_INFO_MAGIC 0x05027800
+
+struct boot_info
+{
+	unsigned long magic_start;
+	char cmd_line[256];
+	char boot_loader[128];
+	int _machine;
+	unsigned long initrd_start, initrd_size;
+	unsigned long systemmap_start, systemmap_size;
+	char reserved[3684];	/* pad to 1 page */
+	unsigned long magic_end;
+};
+struct boot_info *binfo;
 #endif /* _PPC_MACHDEP_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h
--- v2.3.15/linux/include/asm-ppc/mmu_context.h	Sun Jul 25 13:45:25 1999
+++ linux/include/asm-ppc/mmu_context.h	Tue Aug 31 11:36:43 1999
@@ -20,15 +20,15 @@
  */
 
 #ifdef CONFIG_8xx
-#define NO_CONTEXT      16
-#define LAST_CONTEXT    15
+#define NO_CONTEXT      	16
+#define LAST_CONTEXT    	15
 #define MUNGE_CONTEXT(n)        (n)
 
 #else
 
 /* PPC 6xx, 7xx CPUs */
-#define NO_CONTEXT      0
-#define LAST_CONTEXT    0xfffff
+#define NO_CONTEXT      	0
+#define LAST_CONTEXT    	0xfffff
 
 /*
  * Allocating context numbers this way tends to spread out
@@ -41,18 +41,25 @@
 extern atomic_t next_mmu_context;
 extern void mmu_context_overflow(void);
 
-#ifndef CONFIG_8xx
+/*
+ * Set the current MMU context.
+ * On 32-bit PowerPCs (other than the 8xx embedded chips), this is done by
+ * loading up the segment registers for the user part of the address space.
+ */
 extern void set_context(int context);
-#else
-#define set_context(context)    do { } while (0)
+
+#ifdef CONFIG_8xx
+extern inline void mmu_context_overflow(void)
+{
+	atomic_set(&next_mmu_context, -1);
+}
 #endif
 
 /*
  * Get a new mmu context for task tsk if necessary.
  */
-#define get_mmu_context(tsk)					\
+#define get_mmu_context(mm)					\
 do { 								\
-	struct mm_struct *mm = (tsk)->mm;			\
 	if (mm->context == NO_CONTEXT) {			\
 		if (atomic_read(&next_mmu_context) == LAST_CONTEXT)		\
 			mmu_context_overflow();			\
@@ -63,21 +70,30 @@
 /*
  * Set up the context for a new address space.
  */
-#define init_new_context(mm)	((mm)->context = NO_CONTEXT)
+#define init_new_context(tsk,mm)	((mm)->context = NO_CONTEXT)
 
 /*
  * We're finished using the context for an address space.
  */
 #define destroy_context(mm)     do { } while (0)
 
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+			     struct task_struct *tsk, int cpu)
+{
+	tsk->thread.pgdir = next->pgd;
+	get_mmu_context(next);
+	set_context(next->context);
+}
+
 /*
  * After we have set current->mm to a new value, this activates
  * the context for the new mm so we see the new mappings.
  */
-extern inline void activate_context(struct task_struct *tsk)
+static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm)
 {
-	get_mmu_context(tsk);
-	set_context(tsk->mm->context);
+	current->thread.pgdir = mm->pgd;
+	get_mmu_context(mm);
+	set_context(mm->context);
 }
 
 /*
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/page.h linux/include/asm-ppc/page.h
--- v2.3.15/linux/include/asm-ppc/page.h	Mon Jun 28 13:40:39 1999
+++ linux/include/asm-ppc/page.h	Tue Aug 31 11:36:43 1999
@@ -23,7 +23,7 @@
 #define BUG() do { \
 	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
 	__asm__ __volatile__(".long 0x0"); \
-}
+} while (0)
 #endif
 #define PAGE_BUG(page) do { BUG(); } while (0)
 
@@ -80,15 +80,34 @@
 #define copy_page(to,from)	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
 
 /* map phys->virtual and virtual->phys for RAM pages */
-#ifdef CONFIG_APUS
-#include <asm/amigappc.h>
-/* Word at CYBERBASEp has the value (-KERNELBASE+CYBERBASE). */
-#define __pa(x)			((unsigned long)(x)+(*(unsigned long*)CYBERBASEp))
-#define __va(x)			((void *)((unsigned long)(x)-(*(unsigned long*)CYBERBASEp)))
-#else
-#define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
-#define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
-#endif
+static inline unsigned long ___pa(unsigned long v)
+{ 
+	unsigned long p;
+	asm volatile ("1: addis %0, %1, %2;" 
+		      ".section \".vtop_fixup\",\"aw\";"
+		      ".align  1;"
+		      ".long   1b;"
+		      ".previous;"
+		      : "=r" (p) 
+		      : "b" (v), "K" (((-PAGE_OFFSET) >> 16) & 0xffff));
+
+	return p;
+}
+static inline void* ___va(unsigned long p)
+{ 
+	unsigned long v;
+	asm volatile ("1: addis %0, %1, %2;" 
+		      ".section \".ptov_fixup\",\"aw\";"
+		      ".align  1;"
+		      ".long   1b;"
+		      ".previous;"
+		      : "=r" (v) 
+		      : "b" (p), "K" (((PAGE_OFFSET) >> 16) & 0xffff));
+
+	return (void*) v;
+}
+#define __pa(x) ___pa ((unsigned long)(x))
+#define __va(x) ___va ((unsigned long)(x))
 
 #define MAP_NR(addr)		(((unsigned long)addr-PAGE_OFFSET) >> PAGE_SHIFT)
 #define MAP_PAGE_RESERVED	(1<<15)
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h
--- v2.3.15/linux/include/asm-ppc/pgtable.h	Thu Aug 26 13:05:41 1999
+++ linux/include/asm-ppc/pgtable.h	Tue Aug 31 11:36:43 1999
@@ -20,11 +20,6 @@
 #define flush_tlb_page local_flush_tlb_page
 #define flush_tlb_range local_flush_tlb_range
 
-extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end)
-{
-	/* PPC has hw page tables. */
-}
-
 /*
  * No cache flushing is required when address mappings are
  * changed, because the caches on PowerPCs are physically
@@ -44,6 +39,7 @@
 extern pte_t *va_to_pte(struct task_struct *tsk, unsigned long address);
 extern unsigned long ioremap_bot, ioremap_base;
 #endif /* __ASSEMBLY__ */
+
 /*
  * The PowerPC MMU uses a hash table containing PTEs, together with
  * a set of 16 segment registers (on 32-bit implementations), to define
@@ -56,7 +52,9 @@
  * for extracting ptes from the tree and putting them into the hash table
  * when necessary, and updating the accessed and modified bits in the
  * page table tree.
- *
+ */
+
+/*
  * The PowerPC MPC8xx uses a TLB with hardware assisted, software tablewalk.
  * We also use the two level tables, but we can put the real bits in them
  * needed for the TLB and tablewalk.  These definitions require Mx_CTR.PPM = 0,
@@ -94,7 +92,8 @@
 #define PTRS_PER_PGD	1024
 #define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
 
-/* Just any arbitrary offset to the start of the vmalloc VM area: the
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 64MB value just means that there will be a 64MB "hole" after the
  * physical memory until the kernel virtual memory starts.  That means that
  * any out-of-bounds memory accesses will hopefully be caught.
@@ -120,6 +119,7 @@
  * (hardware-defined) PowerPC PTE as closely as possible.
  */
 #ifndef CONFIG_8xx
+/* Definitions for 60x, 740/750, etc. */
 #define _PAGE_PRESENT	0x001	/* software: pte contains a translation */
 #define _PAGE_USER	0x002	/* matches one of the PP bits */
 #define _PAGE_RW	0x004	/* software: user write access allowed */
@@ -133,6 +133,7 @@
 #define _PAGE_SHARED	0
 
 #else
+/* Definitions for 8xx embedded chips. */
 #define _PAGE_PRESENT	0x0001	/* Page is valid */
 #define _PAGE_NO_CACHE	0x0002	/* I: cache inhibit */
 #define _PAGE_SHARED	0x0004	/* No ASID (context) compare */
@@ -225,20 +226,6 @@
 /* 64-bit machines, beware!  SRB. */
 #define SIZEOF_PTR_LOG2	2
 
-/* to set the page-dir */
-/* tsk is a task_struct and pgdir is a pte_t */
-#ifndef CONFIG_8xx
-#define SET_PAGE_DIR(tsk,pgdir)  \
-	((tsk)->tss.pg_tables = (unsigned long *)(pgdir))
-#else /* CONFIG_8xx */     
-#define SET_PAGE_DIR(tsk,pgdir)  \
- do { \
-	unsigned long __pgdir = (unsigned long)pgdir; \
-	((tsk)->tss.pg_tables = (unsigned long *)(__pgdir)); \
-	asm("mtspr %0,%1 \n\t" : : "i"(M_TWB), "r"(__pa(__pgdir))); \
- } while (0)
-#endif /* CONFIG_8xx */
-     
 #ifndef __ASSEMBLY__
 extern inline int pte_none(pte_t pte)		{ return !pte_val(pte); }
 extern inline int pte_present(pte_t pte)	{ return pte_val(pte) & _PAGE_PRESENT; }
@@ -648,6 +635,23 @@
 #define kern_addr_valid(addr)	(1)
 
 #define io_remap_page_range remap_page_range 
+
+#ifdef CONFIG_8xx
+#define __tlbia()	asm volatile ("tlbia" : : )
+
+extern inline void local_flush_tlb_all(void)
+	{ __tlbia(); }
+extern inline void local_flush_tlb_mm(struct mm_struct *mm)
+	{ __tlbia(); }
+extern inline void local_flush_tlb_page(struct vm_area_struct *vma,
+				unsigned long vmaddr)
+	{ __tlbia(); }
+extern inline void local_flush_tlb_range(struct mm_struct *mm,
+				unsigned long start, unsigned long end)
+	{ __tlbia(); }
+extern inline void flush_hash_page(unsigned context, unsigned long va)
+	{ }
+#endif
 
 #endif __ASSEMBLY__
 #endif /* _PPC_PGTABLE_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/pmu.h linux/include/asm-ppc/pmu.h
--- v2.3.15/linux/include/asm-ppc/pmu.h	Thu Apr 29 12:39:01 1999
+++ linux/include/asm-ppc/pmu.h	Tue Aug 31 11:36:43 1999
@@ -6,6 +6,7 @@
  * Copyright (C) 1998 Paul Mackerras.
  */
 
+#include <linux/config.h>
 /*
  * PMU commands
  */
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- v2.3.15/linux/include/asm-ppc/processor.h	Mon Jun 28 13:40:39 1999
+++ linux/include/asm-ppc/processor.h	Tue Aug 31 11:36:43 1999
@@ -66,8 +66,33 @@
 #define HID0_BTCD	(1<<1)		/* Branch target cache disable */
 
 /* fpscr settings */
-#define FPSCR_FX        (1<<31)
-#define FPSCR_FEX       (1<<30)
+#define FPSCR_FX	0x80000000	/* FPU exception summary */
+#define FPSCR_FEX	0x40000000	/* FPU enabled exception summary */
+#define FPSCR_VX	0x20000000	/* Invalid operation summary */
+#define FPSCR_OX	0x10000000	/* Overflow exception summary */
+#define FPSCR_UX	0x08000000	/* Underflow exception summary */
+#define FPSCR_ZX	0x04000000	/* Zero-devide exception summary */
+#define FPSCR_XX	0x02000000	/* Inexact exception summary */
+#define FPSCR_VXSNAN	0x01000000	/* Invalid op for SNaN */
+#define FPSCR_VXISI	0x00800000	/* Invalid op for Inv - Inv */
+#define FPSCR_VXIDI	0x00400000	/* Invalid op for Inv / Inv */
+#define FPSCR_VXZDZ	0x00200000	/* Invalid op for Zero / Zero */
+#define FPSCR_VXIMZ	0x00100000	/* Invalid op for Inv * Zero */
+#define FPSCR_VXVC	0x00080000	/* Invalid op for Compare */
+#define FPSCR_FR	0x00040000	/* Fraction rounded */
+#define FPSCR_FI	0x00020000	/* Fraction inexact */
+#define FPSCR_FPRF	0x0001f000	/* FPU Result Flags */
+#define FPSCR_FPCC	0x0000f000	/* FPU Condition Codes */
+#define FPSCR_VXSOFT	0x00000400	/* Invalid op for software request */
+#define FPSCR_VXSQRT	0x00000200	/* Invalid op for square root */
+#define FPSCR_VXCVI	0x00000100	/* Invalid op for integer convert */
+#define FPSCR_VE	0x00000080	/* Invalid op exception enable */
+#define FPSCR_OE	0x00000040	/* IEEE overflow exception enable */
+#define FPSCR_UE	0x00000020	/* IEEE underflow exception enable */
+#define FPSCR_ZE	0x00000010	/* IEEE zero divide exception enable */
+#define FPSCR_XE	0x00000008	/* FP inexact exception enable */
+#define FPSCR_NI	0x00000004	/* FPU non IEEE-Mode */
+#define FPSCR_RN	0x00000003	/* FPU rounding control */
 
 #define _MACH_prep     1
 #define _MACH_Pmac     2  /* pmac or pmac clone (non-chrp) */
@@ -78,6 +103,7 @@
 #define _MACH_rpxlite 64  /* RPCG RPX-Lite 8xx board */
 #define _MACH_bseip   128 /* Bright Star Engineering ip-Engine */
 #define _MACH_yk      256 /* Motorola Yellowknife */
+#define _MACH_gemini  512 /* Synergy Microsystems gemini board */
 
 /* see residual.h for these */
 #define _PREP_Motorola 0x01  /* motorola prep */
@@ -154,6 +180,7 @@
 #define DEC	22	/* Decrementer */
 #define EAR	282	/* External Address Register */
 #define L2CR	1017    /* PPC 750 L2 control register */
+#define IMMR	638	/* PPC 860/821 Internal Memory Map Register */
 
 #define THRM1	1020
 #define THRM2	1021
@@ -242,10 +269,10 @@
 
 struct thread_struct {
 	unsigned long	ksp;		/* Kernel stack pointer */
-	unsigned long	*pg_tables;	/* Base of page-table tree */
 	unsigned long	wchan;		/* Event task is sleeping on */
 	struct pt_regs	*regs;		/* Pointer to saved register state */
 	mm_segment_t	fs;		/* for get_fs() validation */
+	void		*pgdir;		/* root of page-table tree */
 	signed long     last_syscall;
 	double		fpr[32];	/* Complete floating point set */
 	unsigned long	fpscr_pad;	/* fpr ... fpscr must be contiguous */
@@ -254,12 +281,12 @@
 
 #define INIT_SP		(sizeof(init_stack) + (unsigned long) &init_stack)
 
-#define INIT_TSS  { \
+#define INIT_THREAD  { \
 	INIT_SP, /* ksp */ \
-	(unsigned long *) swapper_pg_dir, /* pg_tables */ \
 	0, /* wchan */ \
 	(struct pt_regs *)INIT_SP - 1, /* regs */ \
 	KERNEL_DS, /*fs*/ \
+	swapper_pg_dir, /* pgdir */ \
 	0, /* last_syscall */ \
 	{0}, 0, 0 \
 }
@@ -280,13 +307,14 @@
 	return (t->regs) ? t->regs->nip : 0;
 }
 
-#define copy_segments(nr, tsk, mm)	do { } while (0)
+#define copy_segments(tsk, mm)		do { } while (0)
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
 /*
  * NOTE! The task struct and the stack go together
  */
+#define THREAD_SIZE (2*PAGE_SIZE)
 #define alloc_task_struct() \
 	((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
 #define free_task_struct(p)	free_pages((unsigned long)(p),1)
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/ptrace.h linux/include/asm-ppc/ptrace.h
--- v2.3.15/linux/include/asm-ppc/ptrace.h	Wed Jun 30 11:24:55 1999
+++ linux/include/asm-ppc/ptrace.h	Tue Aug 31 11:36:43 1999
@@ -6,7 +6,7 @@
  * kernel stack during a system call or other kernel entry.
  *
  * this should only contain volatile regs
- * since we can keep non-volatile in the tss
+ * since we can keep non-volatile in the thread_struct
  * should set this up when only volatiles are saved
  * by intr code.
  *
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/resource.h linux/include/asm-ppc/resource.h
--- v2.3.15/linux/include/asm-ppc/resource.h	Mon Jul 26 22:41:09 1999
+++ linux/include/asm-ppc/resource.h	Tue Aug 31 11:36:43 1999
@@ -24,7 +24,7 @@
     {_STK_LIM, LONG_MAX},			/* RLIMIT_STACK */	\
     {       0, LONG_MAX},			/* RLIMIT_CORE */	\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_RSS */	\
-    {MAX_TASKS_PER_USER, MAX_TASKS_PER_USER},	/* RLIMIT_NPROC */	\
+    {0, 0},								\
     {INR_OPEN, INR_OPEN},			/* RLIMIT_NOFILE */	\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_MEMLOCK */	\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_AS */		\
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/serial.h linux/include/asm-ppc/serial.h
--- v2.3.15/linux/include/asm-ppc/serial.h	Tue Aug  4 16:06:36 1998
+++ linux/include/asm-ppc/serial.h	Tue Aug 31 12:50:24 1999
@@ -8,116 +8,14 @@
 #include <asm-m68k/serial.h>
 #else
 
-/*
- * 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 */
-
-
+  
+#define SERIAL_PORT_DFNS
+  
 #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 */
+#define RS_TABLE_SIZE  64
 #else
-#define HUB6_SERIAL_PORT_DFNS
+#define RS_TABLE_SIZE  4
 #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
-
+  
 #endif /* CONFIG_APUS */
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/smp.h linux/include/asm-ppc/smp.h
--- v2.3.15/linux/include/asm-ppc/smp.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-ppc/smp.h	Tue Aug 31 11:36:43 1999
@@ -7,7 +7,6 @@
 #define _PPC_SMP_H
 
 #include <linux/kernel.h>
-#include <linux/tasks.h>
 
 #ifdef __SMP__
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/spinlock.h linux/include/asm-ppc/spinlock.h
--- v2.3.15/linux/include/asm-ppc/spinlock.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-ppc/spinlock.h	Tue Aug 31 11:36:43 1999
@@ -16,7 +16,7 @@
 #endif
 
 #define spin_lock_init(lock)	do { } while(0)
-#define spin_lock(lock)		do { } while(0)
+#define spin_lock(lock)		(void)(lock)	/* Avoid warnings about unused variable */
 #define spin_trylock(lock)	(1)
 #define spin_unlock_wait(lock)	do { } while(0)
 #define spin_unlock(lock)	do { } while(0)
@@ -50,9 +50,9 @@
   #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
 #endif
 
-#define read_lock(lock)		do { } while(0)
+#define read_lock(lock)		(void)(lock)	/* Avoid warnings about unused variable */
 #define read_unlock(lock)	do { } while(0)
-#define write_lock(lock)	do { } while(0)
+#define write_lock(lock)	(void)(lock)	/* Likewise */
 #define write_unlock(lock)	do { } while(0)
 #define read_lock_irq(lock)	cli()
 #define read_unlock_irq(lock)	sti()
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/system.h linux/include/asm-ppc/system.h
--- v2.3.15/linux/include/asm-ppc/system.h	Tue Aug  3 08:01:29 1999
+++ linux/include/asm-ppc/system.h	Tue Aug 31 11:36:43 1999
@@ -1,9 +1,16 @@
+/*
+ * $Id: system.h,v 1.47 1999/08/22 12:31:08 paulus Exp $
+ *
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
 #ifndef __PPC_SYSTEM_H
 #define __PPC_SYSTEM_H
 
 #include <linux/kdev_t.h>
+
 #include <asm/processor.h>
 #include <asm/atomic.h>
+#include <asm/irq_control.h>
 
 /*
  * Memory barrier.
@@ -28,9 +35,6 @@
 extern void xmon_irq(int, void *, struct pt_regs *);
 extern void xmon(struct pt_regs *excp);
 
-#define __save_flags(flags)	({\
-	__asm__ __volatile__ ("mfmsr %0" : "=r" ((flags)) : : "memory"); })
-#define __save_and_cli(flags)	({__save_flags(flags);__cli();})
 
 /* Data cache block flush - write out the cache line containing the
    specified address and then invalidate it in the cache. */
@@ -39,25 +43,6 @@
 	asm("dcbf %0,%1; sync" : : "r" (line), "r" (0));
 }
 
-extern __inline__ void __restore_flags(unsigned long flags)
-{
-        extern atomic_t ppc_n_lost_interrupts;
-	extern void do_lost_interrupts(unsigned long);
-
-        if ((flags & MSR_EE) && atomic_read(&ppc_n_lost_interrupts) != 0) {
-                do_lost_interrupts(flags);
-        } else {
-                __asm__ __volatile__ ("sync; mtmsr %0; isync"
-                              : : "r" (flags) : "memory");
-        }
-}
-
-
-extern void __sti(void);
-extern void __cli(void);
-extern int _disable_interrupts(void);
-extern void _enable_interrupts(int);
-
 extern void print_backtrace(unsigned long *);
 extern void show_regs(struct pt_regs * regs);
 extern void flush_instruction_cache(void);
@@ -87,8 +72,7 @@
 
 struct thread_struct;
 extern struct task_struct *_switch(struct thread_struct *prev,
-				     struct thread_struct *next,
-				     unsigned long context);
+				   struct thread_struct *next);
 
 extern unsigned int rtas_data;
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/uaccess.h linux/include/asm-ppc/uaccess.h
--- v2.3.15/linux/include/asm-ppc/uaccess.h	Fri Mar 19 10:50:09 1999
+++ linux/include/asm-ppc/uaccess.h	Tue Aug 31 11:36:43 1999
@@ -21,8 +21,8 @@
 #define USER_DS		((mm_segment_t) { 1 })
 
 #define get_ds()	(KERNEL_DS)
-#define get_fs()	(current->tss.fs)
-#define set_fs(val)	(current->tss.fs = (val))
+#define get_fs()	(current->thread.fs)
+#define set_fs(val)	(current->thread.fs = (val))
 
 #define segment_eq(a,b)	((a).seg == (b).seg)
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-ppc/unistd.h linux/include/asm-ppc/unistd.h
--- v2.3.15/linux/include/asm-ppc/unistd.h	Wed Jul 28 10:30:10 1999
+++ linux/include/asm-ppc/unistd.h	Tue Aug 31 11:36:43 1999
@@ -381,7 +381,6 @@
  * System call prototypes.
  */
 #define __NR__exit __NR_exit
-static inline _syscall0(int,idle)
 static inline _syscall0(int,pause)
 static inline _syscall0(int,sync)
 static inline _syscall0(pid_t,setsid)
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/a.out.h linux/include/asm-sh/a.out.h
--- v2.3.15/linux/include/asm-sh/a.out.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/a.out.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,26 @@
+#ifndef __ASM_SH_A_OUT_H
+#define __ASM_SH_A_OUT_H
+
+struct exec
+{
+  unsigned long a_info;		/* Use macros N_MAGIC, etc for access */
+  unsigned a_text;		/* length of text, in bytes */
+  unsigned a_data;		/* length of data, in bytes */
+  unsigned a_bss;		/* length of uninitialized data area for file, in bytes */
+  unsigned a_syms;		/* length of symbol table data in file, in bytes */
+  unsigned a_entry;		/* start address */
+  unsigned a_trsize;		/* length of relocation info for text, in bytes */
+  unsigned a_drsize;		/* length of relocation info for data, in bytes */
+};
+
+#define N_TRSIZE(a)	((a).a_trsize)
+#define N_DRSIZE(a)	((a).a_drsize)
+#define N_SYMSIZE(a)	((a).a_syms)
+
+#ifdef __KERNEL__
+
+#define STACK_TOP	TASK_SIZE
+
+#endif
+
+#endif /* __ASM_SH_A_OUT_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/addrspace.h linux/include/asm-sh/addrspace.h
--- v2.3.15/linux/include/asm-sh/addrspace.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/addrspace.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,41 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996 by Ralf Baechle
+ * Copyright (C) 1999 by Niibe Yutaka
+ *
+ * Defitions for the address spaces of the SH CPUs.
+ */
+#ifndef __ASM_SH_ADDRSPACE_H
+#define __ASM_SH_ADDRSPACE_H
+
+/*
+ * Memory segments (32bit kernel mode addresses)
+ */
+#define KUSEG                   0x00000000
+#define KSEG0                   0x80000000
+#define KSEG1                   0xa0000000
+#define KSEG2                   0xc0000000
+#define KSEG3                   0xe0000000
+
+/*
+ * Returns the kernel segment base of a given address
+ */
+#define KSEGX(a)                (((unsigned long)(a)) & 0xe0000000)
+
+/*
+ * Returns the physical address of a KSEG0/KSEG1 address
+ */
+#define PHYSADDR(a)		(((unsigned long)(a)) & 0x1fffffff)
+
+/*
+ * Map an address to a certain kernel segment
+ */
+#define KSEG0ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG0))
+#define KSEG1ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG1))
+#define KSEG2ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG2))
+#define KSEG3ADDR(a)		((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | KSEG3))
+
+#endif /* __ASM_SH_ADDRSPACE_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/atomic.h linux/include/asm-sh/atomic.h
--- v2.3.15/linux/include/asm-sh/atomic.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/atomic.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,113 @@
+#ifndef __ASM_SH_ATOMIC_H
+#define __ASM_SH_ATOMIC_H
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ *
+ */
+
+#ifdef __SMP__
+typedef struct { volatile int counter; } atomic_t;
+#else
+typedef struct { int counter; } atomic_t;
+#endif
+
+#define ATOMIC_INIT(i)	( (atomic_t) { (i) } )
+
+#define atomic_read(v)		((v)->counter)
+#define atomic_set(v,i)		((v)->counter = (i))
+
+#include <asm/system.h>
+
+/*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+#define __atomic_fool_gcc(x) (*(struct { int a[100]; } *)x)
+
+/*
+ * To get proper branch prediction for the main line, we must branch
+ * forward to code at the end of this object's .text section, then
+ * branch back to restart the operation.
+ */
+
+extern __inline__ void atomic_add(int i, atomic_t * v)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	*(long *)v += i;
+	restore_flags(flags);
+}
+
+extern __inline__ void atomic_sub(int i, atomic_t *v)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	*(long *)v -= i;
+	restore_flags(flags);
+}
+
+extern __inline__ int atomic_add_return(int i, atomic_t * v)
+{
+	unsigned long temp, flags;
+
+	save_flags(flags);
+	cli();
+	temp = *(long *)v;
+	temp += i;
+	*(long *)v = temp;
+	restore_flags(flags);
+
+	return temp;
+}
+
+extern __inline__ int atomic_sub_return(int i, atomic_t * v)
+{
+	unsigned long temp, flags;
+
+	save_flags(flags);
+	cli();
+	temp = *(long *)v;
+	temp -= i;
+	*(long *)v = temp;
+	restore_flags(flags);
+
+	return temp;
+}
+
+#define atomic_dec_return(v) atomic_sub_return(1,(v))
+#define atomic_inc_return(v) atomic_add_return(1,(v))
+
+#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
+#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
+
+#define atomic_inc(v) atomic_add(1,(v))
+#define atomic_dec(v) atomic_sub(1,(v))
+
+extern __inline__ void atomic_clear_mask(int mask, atomic_t *v)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	*(long *)v &= ~mask;
+	restore_flags(flags);
+}
+
+extern __inline__ void atomic_set_mask(int mask, atomic_t *v)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	*(long *)v |= mask;
+	restore_flags(flags);
+}
+
+#endif /* __ASM_SH_ATOMIC_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/bitops.h linux/include/asm-sh/bitops.h
--- v2.3.15/linux/include/asm-sh/bitops.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/bitops.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,261 @@
+#ifndef __ASM_SH_BITOPS_H
+#define __ASM_SH_BITOPS_H
+
+#ifdef __KERNEL__
+#include <asm/system.h>
+/* For __swab32 */
+#include <asm/byteorder.h>
+
+extern __inline__ void set_bit(int nr, void * addr)
+{
+	int	mask;
+	unsigned int *a = addr;
+	unsigned long flags;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	save_flags(flags);
+	cli();
+	*a |= mask;
+	restore_flags(flags);
+}
+
+extern __inline__ void clear_bit(int nr, void * addr)
+{
+	int	mask;
+	unsigned int *a = addr;
+	unsigned long flags;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	save_flags(flags);
+	cli();
+	*a &= ~mask;
+	restore_flags(flags);
+}
+
+extern __inline__ void change_bit(int nr, void * addr)
+{
+	int	mask;
+	unsigned int *a = addr;
+	unsigned long flags;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	save_flags(flags);
+	cli();
+	*a ^= mask;
+	restore_flags(flags);
+}
+
+extern __inline__ int test_and_set_bit(int nr, void * addr)
+{
+	int	mask, retval;
+	unsigned int *a = addr;
+	unsigned long flags;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	save_flags(flags);
+	cli();
+	retval = (mask & *a) != 0;
+	*a |= mask;
+	restore_flags(flags);
+
+	return retval;
+}
+
+extern __inline__ int test_and_clear_bit(int nr, void * addr)
+{
+	int	mask, retval;
+	unsigned int *a = addr;
+	unsigned long flags;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	save_flags(flags);
+	cli();
+	retval = (mask & *a) != 0;
+	*a &= ~mask;
+	restore_flags(flags);
+
+	return retval;
+}
+
+extern __inline__ int test_and_change_bit(int nr, void * addr)
+{
+	int	mask, retval;
+	unsigned int *a = addr;
+	unsigned long flags;
+
+	a += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	save_flags(flags);
+	cli();
+	retval = (mask & *a) != 0;
+	*a ^= mask;
+	restore_flags(flags);
+
+	return retval;
+}
+
+
+extern __inline__ int test_bit(int nr, const void *addr)
+{
+	return 1UL & (((const int *) addr)[nr >> 5] >> (nr & 31));
+}
+
+extern __inline__ unsigned long ffz(unsigned long word)
+{
+	unsigned long result;
+
+	__asm__("1:\n"
+		"shlr	%1\n\t"
+		"bt/s	1b\n\t"
+		"add	#1, %0"
+		: "=r" (result)
+		: "r" (word), "0" (~0L));
+	return result;
+}
+
+extern __inline__ int find_next_zero_bit(void *addr, int size, int offset)
+{
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+	unsigned long result = offset & ~31UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if (offset) {
+		tmp = *(p++);
+		tmp |= ~0UL >> (32-offset);
+		if (size < 32)
+			goto found_first;
+		if (~tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while (size & ~31UL) {
+		if (~(tmp = *(p++)))
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	tmp |= ~0UL << size;
+found_middle:
+	return result + ffz(tmp);
+}
+
+#define find_first_zero_bit(addr, size) \
+        find_next_zero_bit((addr), (size), 0)
+
+extern __inline__ int ext2_set_bit(int nr,void * addr)
+{
+	int		mask, retval;
+	unsigned long flags;
+	unsigned char	*ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	save_flags(flags); cli();
+	retval = (mask & *ADDR) != 0;
+	*ADDR |= mask;
+	restore_flags(flags);
+	return retval;
+}
+
+extern __inline__ int ext2_clear_bit(int nr, void * addr)
+{
+	int		mask, retval;
+	unsigned long flags;
+	unsigned char	*ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	save_flags(flags); cli();
+	retval = (mask & *ADDR) != 0;
+	*ADDR &= ~mask;
+	restore_flags(flags);
+	return retval;
+}
+
+extern __inline__ int ext2_test_bit(int nr, const void * addr)
+{
+	int			mask;
+	const unsigned char	*ADDR = (const unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	return ((mask & *ADDR) != 0);
+}
+
+#define ext2_find_first_zero_bit(addr, size) \
+        ext2_find_next_zero_bit((addr), (size), 0)
+
+extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+{
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+	unsigned long result = offset & ~31UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if(offset) {
+		/* We hold the little endian value in tmp, but then the
+		 * shift is illegal. So we could keep a big endian value
+		 * in tmp, like this:
+		 *
+		 * tmp = __swab32(*(p++));
+		 * tmp |= ~0UL >> (32-offset);
+		 *
+		 * but this would decrease preformance, so we change the
+		 * shift:
+		 */
+		tmp = *(p++);
+		tmp |= __swab32(~0UL >> (32-offset));
+		if(size < 32)
+			goto found_first;
+		if(~tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while(size & ~31UL) {
+		if(~(tmp = *(p++)))
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if(!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	/* tmp is little endian, so we would have to swab the shift,
+	 * see above. But then we have to swab tmp below for ffz, so
+	 * we might as well do this here.
+	 */
+	return result + ffz(__swab32(tmp) | (~0UL << size));
+found_middle:
+	return result + ffz(__swab32(tmp));
+}
+
+/* Bitmap functions for the minix filesystem.  */
+#define minix_set_bit(nr,addr) test_and_set_bit(nr,addr)
+#define minix_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH_BITOPS_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/bugs.h linux/include/asm-sh/bugs.h
--- v2.3.15/linux/include/asm-sh/bugs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/bugs.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,21 @@
+#ifndef __ASM_SH_BUGS_H
+#define __ASM_SH_BUGS_H
+
+/*
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Needs:
+ *	void check_bugs(void);
+ */
+
+/*
+ * I don't know of any Super-H bugs yet.
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+
+__initfunc(static void check_bugs(void))
+{
+}
+#endif /* __ASM_SH_BUGS_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/byteorder.h linux/include/asm-sh/byteorder.h
--- v2.3.15/linux/include/asm-sh/byteorder.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/byteorder.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,43 @@
+#ifndef __ASM_SH_BYTEORDER_H
+#define __ASM_SH_BYTEORDER_H
+
+/*
+ * Copyright (C) 1999  Niibe Yutaka
+ */
+
+#include <linux/config.h>
+#include <asm/types.h>
+
+static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
+{
+	__asm__("swap.b	%0, %0\n\t"
+		"swap.w %0, %0\n\t"
+		"swap.b %0, %0"
+		: "=r" (x)
+		: "0" (x));
+	return x;
+}
+
+static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
+{
+	__asm__("swap.b %0,%0"
+		: "=r" (x)
+		:  "0" (x));
+	return x;
+}
+
+#define __arch__swab32(x) ___arch__swab32(x)
+#define __arch__swab16(x) ___arch__swab16(x)
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#  define __SWAB_64_THRU_32__
+#endif
+
+#ifdef CONFIG_LITTLE_ENDIAN
+#include <linux/byteorder/little_endian.h>
+#else
+#include <linux/byteorder/big_endian.h>
+#endif
+
+#endif /* __ASM_SH_BYTEORDER_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/cache.h linux/include/asm-sh/cache.h
--- v2.3.15/linux/include/asm-sh/cache.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/cache.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,23 @@
+/*
+ * include/asm-sh/cache.h
+ * Copyright 1999 (C) Niibe Yutaka
+ */
+#ifndef __ASM_SH_CACHE_H
+#define __ASM_SH_CACHE_H
+
+/* bytes per L1 cache line */
+#define        L1_CACHE_BYTES  16
+
+#define        L1_CACHE_ALIGN(x)       (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
+
+#define        SMP_CACHE_BYTES L1_CACHE_BYTES
+
+#ifdef MODULE
+#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
+#else
+#define __cacheline_aligned					\
+  __attribute__((__aligned__(L1_CACHE_BYTES),			\
+		 __section__(".data.cacheline_aligned")))
+#endif
+
+#endif /* __ASM_SH_CACHE_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/checksum.h linux/include/asm-sh/checksum.h
--- v2.3.15/linux/include/asm-sh/checksum.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/checksum.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,84 @@
+#ifndef __ASM_SH_CHECKSUM_H
+#define __ASM_SH_CHECKSUM_H
+
+
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ */
+extern unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl);
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+extern unsigned short int csum_tcpudp_magic(unsigned long saddr,
+					   unsigned long daddr,
+					   unsigned short len,
+					   unsigned short proto,
+					   unsigned int sum);
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from user space (but on the alpha
+ * we have just one address space, so this is identical to the above)
+ *
+ * this is obsolete and will go away.
+ */
+#define csum_partial_copy_fromuser csum_partial_copy
+
+/*
+ * this is a new version of the above that records errors it finds in *errp,
+ * but continues and zeros the rest of the buffer.
+ */
+unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len, unsigned int sum, int *errp);
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+extern unsigned short ip_compute_csum(unsigned char * buff, int len);
+
+/*
+ *	Fold a partial checksum without adding pseudo headers
+ */
+
+static inline unsigned short csum_fold(unsigned int sum)
+{
+	sum = (sum & 0xffff) + (sum >> 16);
+	sum = (sum & 0xffff) + (sum >> 16);
+	return ~sum;
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+/*
+extern unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+                                          struct in6_addr *daddr,
+                                          __u16 len,
+                                          unsigned short proto,
+                                          unsigned int sum);
+*/
+#endif /* __ASM_SH_CHECKSUM_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/current.h linux/include/asm-sh/current.h
--- v2.3.15/linux/include/asm-sh/current.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/current.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,24 @@
+#ifndef __ASM_SH_CURRENT_H
+#define __ASM_SH_CURRENT_H
+
+/*
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ */
+
+struct task_struct;
+
+static __inline__ struct task_struct * get_current(void)
+{
+	struct task_struct *current;
+
+	__asm__("stc	r4_bank,%0\n\t"
+		"add	%1,%0"
+		:"=&r" (current)
+		:"r" (-8192));
+	return current;
+}
+
+#define current get_current()
+
+#endif /* __ASM_SH_CURRENT_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/delay.h linux/include/asm-sh/delay.h
--- v2.3.15/linux/include/asm-sh/delay.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/delay.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,44 @@
+#ifndef __ASM_SH_DELAY_H
+#define __ASM_SH_DELAY_H
+
+/*
+ * Copyright (C) 1999  Niibe Yutaka
+ */
+
+extern __inline__ void __delay(unsigned long loops)
+{
+	unsigned long __dummy;
+	__asm__ __volatile__(
+ 		"1:\t"
+		"dt	%0\n\t"
+		"bf	1b"
+		:"=r" (__dummy)
+		:"0" (loops));
+}
+
+extern __inline__ void __udelay(unsigned long usecs, unsigned long lps)
+{
+	usecs *= 0x000010c6;		/* 2**32 / 1000000 */
+	__asm__("mul.l	%0,%2\n\t"
+		"sts	macl,%0"
+		: "=&r" (usecs)
+		: "0" (usecs), "r" (lps)
+		: "macl", "mach");
+        __delay(usecs);
+}
+
+
+#ifdef __SMP__
+#define __udelay_val cpu_data[smp_processor_id()].udelay_val
+#else
+#define __udelay_val loops_per_sec
+#endif
+
+#define udelay(usecs) __udelay((usecs),__udelay_val)
+
+extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c)
+{
+	return (a*b)/c;
+}
+
+#endif /* __ASM_SH_DELAY_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/dma.h linux/include/asm-sh/dma.h
--- v2.3.15/linux/include/asm-sh/dma.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/dma.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,12 @@
+#ifndef __ASM_SH_DMA_H
+#define __ASM_SH_DMA_H
+
+/* Don't define MAX_DMA_ADDRESS; it's useless on the SuperH and any
+   occurrence should be flagged as an error.  */
+
+#define MAX_DMA_CHANNELS 8
+
+extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */
+extern void free_dma(unsigned int dmanr);	/* release it again */
+
+#endif /* __ASM_SH_DMA_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/elf.h linux/include/asm-sh/elf.h
--- v2.3.15/linux/include/asm-sh/elf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/elf.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,75 @@
+#ifndef __ASM_SH_ELF_H
+#define __ASM_SH_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <asm/user.h>
+#include <asm/byteorder.h>
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+#ifdef CONFIG_CPU_SH4
+typedef double elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+#else /* SH 3 has no floating point regs */
+typedef struct { void *null; } elf_fpregset_t;
+#endif
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ( (x) == EM_SH )
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#ifdef __LITTLE_ENDIAN
+#define ELF_DATA	ELFDATA2LSB
+#else
+#define ELF_DATA	ELFDATA2MSB
+#endif
+#define ELF_ARCH	EM_SH
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE	4096
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   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         (2 * TASK_SIZE / 3)
+
+
+#define ELF_CORE_COPY_REGS(_dest,_regs)				\
+	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 user space,
+   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)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex, ibcs2) \
+	current->personality = PER_LINUX_32BIT
+#endif
+
+#endif /* __ASM_SH_ELF_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/errno.h linux/include/asm-sh/errno.h
--- v2.3.15/linux/include/asm-sh/errno.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/errno.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,132 @@
+#ifndef __ASM_SH_ERRNO_H
+#define __ASM_SH_ERRNO_H
+
+#define	EPERM		 1	/* Operation not permitted */
+#define	ENOENT		 2	/* No such file or directory */
+#define	ESRCH		 3	/* No such process */
+#define	EINTR		 4	/* Interrupted system call */
+#define	EIO		 5	/* I/O error */
+#define	ENXIO		 6	/* No such device or address */
+#define	E2BIG		 7	/* Arg list too long */
+#define	ENOEXEC		 8	/* Exec format error */
+#define	EBADF		 9	/* Bad file number */
+#define	ECHILD		10	/* No child processes */
+#define	EAGAIN		11	/* Try again */
+#define	ENOMEM		12	/* Out of memory */
+#define	EACCES		13	/* Permission denied */
+#define	EFAULT		14	/* Bad address */
+#define	ENOTBLK		15	/* Block device required */
+#define	EBUSY		16	/* Device or resource busy */
+#define	EEXIST		17	/* File exists */
+#define	EXDEV		18	/* Cross-device link */
+#define	ENODEV		19	/* No such device */
+#define	ENOTDIR		20	/* Not a directory */
+#define	EISDIR		21	/* Is a directory */
+#define	EINVAL		22	/* Invalid argument */
+#define	ENFILE		23	/* File table overflow */
+#define	EMFILE		24	/* Too many open files */
+#define	ENOTTY		25	/* Not a typewriter */
+#define	ETXTBSY		26	/* Text file busy */
+#define	EFBIG		27	/* File too large */
+#define	ENOSPC		28	/* No space left on device */
+#define	ESPIPE		29	/* Illegal seek */
+#define	EROFS		30	/* Read-only file system */
+#define	EMLINK		31	/* Too many links */
+#define	EPIPE		32	/* Broken pipe */
+#define	EDOM		33	/* Math argument out of domain of func */
+#define	ERANGE		34	/* Math result not representable */
+#define	EDEADLK		35	/* Resource deadlock would occur */
+#define	ENAMETOOLONG	36	/* File name too long */
+#define	ENOLCK		37	/* No record locks available */
+#define	ENOSYS		38	/* Function not implemented */
+#define	ENOTEMPTY	39	/* Directory not empty */
+#define	ELOOP		40	/* Too many symbolic links encountered */
+#define	EWOULDBLOCK	EAGAIN	/* Operation would block */
+#define	ENOMSG		42	/* No message of desired type */
+#define	EIDRM		43	/* Identifier removed */
+#define	ECHRNG		44	/* Channel number out of range */
+#define	EL2NSYNC	45	/* Level 2 not synchronized */
+#define	EL3HLT		46	/* Level 3 halted */
+#define	EL3RST		47	/* Level 3 reset */
+#define	ELNRNG		48	/* Link number out of range */
+#define	EUNATCH		49	/* Protocol driver not attached */
+#define	ENOCSI		50	/* No CSI structure available */
+#define	EL2HLT		51	/* Level 2 halted */
+#define	EBADE		52	/* Invalid exchange */
+#define	EBADR		53	/* Invalid request descriptor */
+#define	EXFULL		54	/* Exchange full */
+#define	ENOANO		55	/* No anode */
+#define	EBADRQC		56	/* Invalid request code */
+#define	EBADSLT		57	/* Invalid slot */
+
+#define	EDEADLOCK	EDEADLK
+
+#define	EBFONT		59	/* Bad font file format */
+#define	ENOSTR		60	/* Device not a stream */
+#define	ENODATA		61	/* No data available */
+#define	ETIME		62	/* Timer expired */
+#define	ENOSR		63	/* Out of streams resources */
+#define	ENONET		64	/* Machine is not on the network */
+#define	ENOPKG		65	/* Package not installed */
+#define	EREMOTE		66	/* Object is remote */
+#define	ENOLINK		67	/* Link has been severed */
+#define	EADV		68	/* Advertise error */
+#define	ESRMNT		69	/* Srmount error */
+#define	ECOMM		70	/* Communication error on send */
+#define	EPROTO		71	/* Protocol error */
+#define	EMULTIHOP	72	/* Multihop attempted */
+#define	EDOTDOT		73	/* RFS specific error */
+#define	EBADMSG		74	/* Not a data message */
+#define	EOVERFLOW	75	/* Value too large for defined data type */
+#define	ENOTUNIQ	76	/* Name not unique on network */
+#define	EBADFD		77	/* File descriptor in bad state */
+#define	EREMCHG		78	/* Remote address changed */
+#define	ELIBACC		79	/* Can not access a needed shared library */
+#define	ELIBBAD		80	/* Accessing a corrupted shared library */
+#define	ELIBSCN		81	/* .lib section in a.out corrupted */
+#define	ELIBMAX		82	/* Attempting to link in too many shared libraries */
+#define	ELIBEXEC	83	/* Cannot exec a shared library directly */
+#define	EILSEQ		84	/* Illegal byte sequence */
+#define	ERESTART	85	/* Interrupted system call should be restarted */
+#define	ESTRPIPE	86	/* Streams pipe error */
+#define	EUSERS		87	/* Too many users */
+#define	ENOTSOCK	88	/* Socket operation on non-socket */
+#define	EDESTADDRREQ	89	/* Destination address required */
+#define	EMSGSIZE	90	/* Message too long */
+#define	EPROTOTYPE	91	/* Protocol wrong type for socket */
+#define	ENOPROTOOPT	92	/* Protocol not available */
+#define	EPROTONOSUPPORT	93	/* Protocol not supported */
+#define	ESOCKTNOSUPPORT	94	/* Socket type not supported */
+#define	EOPNOTSUPP	95	/* Operation not supported on transport endpoint */
+#define	EPFNOSUPPORT	96	/* Protocol family not supported */
+#define	EAFNOSUPPORT	97	/* Address family not supported by protocol */
+#define	EADDRINUSE	98	/* Address already in use */
+#define	EADDRNOTAVAIL	99	/* Cannot assign requested address */
+#define	ENETDOWN	100	/* Network is down */
+#define	ENETUNREACH	101	/* Network is unreachable */
+#define	ENETRESET	102	/* Network dropped connection because of reset */
+#define	ECONNABORTED	103	/* Software caused connection abort */
+#define	ECONNRESET	104	/* Connection reset by peer */
+#define	ENOBUFS		105	/* No buffer space available */
+#define	EISCONN		106	/* Transport endpoint is already connected */
+#define	ENOTCONN	107	/* Transport endpoint is not connected */
+#define	ESHUTDOWN	108	/* Cannot send after transport endpoint shutdown */
+#define	ETOOMANYREFS	109	/* Too many references: cannot splice */
+#define	ETIMEDOUT	110	/* Connection timed out */
+#define	ECONNREFUSED	111	/* Connection refused */
+#define	EHOSTDOWN	112	/* Host is down */
+#define	EHOSTUNREACH	113	/* No route to host */
+#define	EALREADY	114	/* Operation already in progress */
+#define	EINPROGRESS	115	/* Operation now in progress */
+#define	ESTALE		116	/* Stale NFS file handle */
+#define	EUCLEAN		117	/* Structure needs cleaning */
+#define	ENOTNAM		118	/* Not a XENIX named type file */
+#define	ENAVAIL		119	/* No XENIX semaphores available */
+#define	EISNAM		120	/* Is a named type file */
+#define	EREMOTEIO	121	/* Remote I/O error */
+#define	EDQUOT		122	/* Quota exceeded */
+
+#define	ENOMEDIUM	123	/* No medium found */
+#define	EMEDIUMTYPE	124	/* Wrong medium type */
+
+#endif /* __ASM_SH_ERRNO_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/fcntl.h linux/include/asm-sh/fcntl.h
--- v2.3.15/linux/include/asm-sh/fcntl.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/fcntl.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,66 @@
+#ifndef __ASM_SH_FCNTL_H
+#define __ASM_SH_FCNTL_H
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE	   0003
+#define O_RDONLY	     00
+#define O_WRONLY	     01
+#define O_RDWR		     02
+#define O_CREAT		   0100	/* not fcntl */
+#define O_EXCL		   0200	/* not fcntl */
+#define O_NOCTTY	   0400	/* not fcntl */
+#define O_TRUNC		  01000	/* not fcntl */
+#define O_APPEND	  02000
+#define O_NONBLOCK	  04000
+#define O_NDELAY	O_NONBLOCK
+#define O_SYNC		 010000
+#define FASYNC		 020000	/* fcntl, for BSD compatibility */
+#define O_DIRECT	 040000	/* direct disk access hint - currently ignored */
+#define O_LARGEFILE	0100000
+#define O_DIRECTORY	0200000	/* must be a directory */
+#define O_NOFOLLOW	0400000 /* don't follow links */
+
+#define F_DUPFD		0	/* dup */
+#define F_GETFD		1	/* get f_flags */
+#define F_SETFD		2	/* set f_flags */
+#define F_GETFL		3	/* more flags (cloexec) */
+#define F_SETFL		4
+#define F_GETLK		5
+#define F_SETLK		6
+#define F_SETLKW	7
+
+#define F_SETOWN	8	/*  for sockets. */
+#define F_GETOWN	9	/*  for sockets. */
+#define F_SETSIG	10	/*  for sockets. */
+#define F_GETSIG	11	/*  for sockets. */
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK		0
+#define F_WRLCK		1
+#define F_UNLCK		2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK		4	/* or 3 */
+#define F_SHLCK		8	/* or 4 */
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH		1	/* shared lock */
+#define LOCK_EX		2	/* exclusive lock */
+#define LOCK_NB		4	/* or'd with one of the above to prevent
+				   blocking */
+#define LOCK_UN		8	/* remove lock */
+
+struct flock {
+	short l_type;
+	short l_whence;
+	off_t l_start;
+	off_t l_len;
+	pid_t l_pid;
+};
+
+#endif /* __ASM_SH_FCNTL_H */
+
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/hardirq.h linux/include/asm-sh/hardirq.h
--- v2.3.15/linux/include/asm-sh/hardirq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/hardirq.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,24 @@
+#ifndef __ASM_SH_HARDIRQ_H
+#define __ASM_SH_HARDIRQ_H
+
+#include <linux/threads.h>
+
+extern unsigned int local_irq_count[NR_CPUS];
+#define in_interrupt()	(local_irq_count[smp_processor_id()] != 0)
+
+#ifndef __SMP__
+
+#define hardirq_trylock(cpu)	(local_irq_count[cpu] == 0)
+#define hardirq_endlock(cpu)	do { } while (0)
+
+#define hardirq_enter(cpu)	(local_irq_count[cpu]++)
+#define hardirq_exit(cpu)	(local_irq_count[cpu]--)
+
+#define synchronize_irq()	do { } while (0)
+
+#else
+
+#error Super-H SMP is not available
+
+#endif /* __SMP__ */
+#endif /* __ASM_SH_HARDIRQ_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/hw_irq.h linux/include/asm-sh/hw_irq.h
--- v2.3.15/linux/include/asm-sh/hw_irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/hw_irq.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH_HW_IRQ_H
+#define __ASM_SH_HW_IRQ_H
+static __inline__ void sh_do_profile (unsigned long pc) {/*Not implemented yet*/}
+
+static __inline__ void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { /* Nothing to do */ }
+#endif /* __ASM_SH_HW_IRQ_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/init.h linux/include/asm-sh/init.h
--- v2.3.15/linux/include/asm-sh/init.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/init.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1 @@
+#error "<asm/init.h> should never be used - use <linux/init.h> instead"
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/io.h linux/include/asm-sh/io.h
--- v2.3.15/linux/include/asm-sh/io.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/io.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,158 @@
+#ifndef __ASM_SH_IO_H
+#define __ASM_SH_IO_H
+/* XXXXXXXXXXXXXXXXX */
+
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
+
+extern __inline__ unsigned long readb(unsigned long addr)
+{
+       return *(volatile unsigned char*)addr;
+}
+
+extern __inline__ unsigned long readw(unsigned long addr)
+{
+       return *(volatile unsigned short*)addr;
+}
+
+extern __inline__ unsigned long readl(unsigned long addr)
+{
+       return *(volatile unsigned long*)addr;
+}
+
+extern __inline__ void writeb(unsigned short b, unsigned long addr)
+{
+       *(volatile unsigned char*)addr = b;
+}
+
+extern __inline__ void writew(unsigned short b, unsigned long addr)
+{
+       *(volatile unsigned short*)addr = b;
+}
+
+extern __inline__ void writel(unsigned int b, unsigned long addr)
+{
+        *(volatile unsigned long*)addr = b;
+}
+
+extern __inline__ unsigned long inb_local(unsigned long addr)
+{
+       return readb(addr);
+}
+
+extern __inline__ void outb_local(unsigned char b, unsigned long addr)
+{
+       return writeb(b,addr);
+}
+
+extern __inline__ unsigned long inb(unsigned long addr)
+{
+       return readb(addr);
+}
+
+extern __inline__ unsigned long inw(unsigned long addr)
+{
+       return readw(addr);
+}
+
+extern __inline__ unsigned long inl(unsigned long addr)
+{
+       return readl(addr);
+}
+
+extern __inline__ void outb(unsigned char b, unsigned long addr)
+{
+       return writeb(b,addr);
+}
+
+extern __inline__ void outw(unsigned short b, unsigned long addr)
+{
+       return writew(b,addr);
+}
+
+extern __inline__ void outl(unsigned int b, unsigned long addr)
+{
+       return writel(b,addr);
+}
+
+#define inb_p inb
+#define outb_p outb
+
+#ifdef __KERNEL__
+
+#include <asm/addrspace.h>
+
+/*
+ * Change virtual addresses to physical addresses and vv.
+ * These are trivial on the 1:1 Linux/SuperH mapping
+ */
+extern __inline__ unsigned long virt_to_phys(volatile void * address)
+{
+	return PHYSADDR(address);
+}
+
+extern __inline__ void * phys_to_virt(unsigned long address)
+{
+	return (void *)KSEG0ADDR(address);
+}
+
+extern void * ioremap(unsigned long phys_addr, unsigned long size);
+extern void iounmap(void *addr);
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the x86 architecture, we just read/write the
+ * memory location directly.
+ *
+ * On SH, we have the whole physical address space mapped at all times
+ * (as MIPS does), so "ioremap()" and "iounmap()" do not need to do
+ * anything.  (This isn't true for all machines but we still handle
+ * these cases with wired TLB entries anyway ...)
+ *
+ * We cheat a bit and always return uncachable areas until we've fixed
+ * the drivers to handle caching properly.  
+ */
+extern __inline__ void * ioremap(unsigned long offset, unsigned long size)
+{
+	return (void *) KSEG1ADDR(offset);
+}
+
+/*
+ * This one maps high address device memory and turns off caching for that area.
+ * it's useful if some control registers are in such an area and write combining
+ * or read caching is not desirable:
+ */
+extern __inline__ void * ioremap_nocache (unsigned long offset, unsigned long size)
+{
+	return (void *) KSEG1ADDR(offset);
+}
+
+extern __inline__ void iounmap(void *addr)
+{
+}
+
+static __inline__ int check_signature(unsigned long io_addr,
+			const unsigned char *signature, int length)
+{
+	int retval = 0;
+	do {
+		if (readb(io_addr) != *signature)
+			goto out;
+		io_addr++;
+		signature++;
+		length--;
+	} while (length);
+	retval = 1;
+out:
+	return retval;
+}
+
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_IO_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/ioctl.h linux/include/asm-sh/ioctl.h
--- v2.3.15/linux/include/asm-sh/ioctl.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/ioctl.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,75 @@
+/* $Id: ioctl.h,v 1.5 1993/07/19 21:53:50 root Exp root $
+ *
+ * linux/ioctl.h for Linux by H.H. Bergman.
+ */
+
+#ifndef __ASM_SH_IOCTL_H
+#define __ASM_SH_IOCTL_H
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms.  The i386 ioctl numbering scheme doesn't really enforce
+ * a type field.  De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here.  Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS	8
+#define _IOC_TYPEBITS	8
+#define _IOC_SIZEBITS	14
+#define _IOC_DIRBITS	2
+
+#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT	0
+#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE	0U
+#define _IOC_WRITE	1U
+#define _IOC_READ	2U
+
+#define _IOC(dir,type,nr,size) \
+	(((dir)  << _IOC_DIRSHIFT) | \
+	 ((type) << _IOC_TYPESHIFT) | \
+	 ((nr)   << _IOC_NRSHIFT) | \
+	 ((size) << _IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
+
+#endif /* __ASM_SH_IOCTL_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/ioctls.h linux/include/asm-sh/ioctls.h
--- v2.3.15/linux/include/asm-sh/ioctls.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/ioctls.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,99 @@
+#ifndef __ASM_SH_IOCTLS_H
+#define __ASM_SH_IOCTLS_H
+
+#include <asm/ioctl.h>
+
+#define FIOCLEX		_IO('f', 1)
+#define FIONCLEX	_IO('f', 2)
+#define FIOASYNC	_IOW('f', 125, int)
+#define FIONBIO		_IOW('f', 126, int)
+#define FIONREAD	_IOR('f', 127, int)
+#define TIOCINQ		FIONREAD
+
+#define TCGETS		_IOR('t', 19, struct termios)
+#define TCSETS		_IOW('t', 20, struct termios)
+#define TCSETSW		_IOW('t', 21, struct termios)
+#define TCSETSF		_IOW('t', 22, struct termios)
+
+#define TCGETA		_IOR('t', 23, struct termio)
+#define TCSETA		_IOW('t', 24, struct termio)
+#define TCSETAW		_IOW('t', 25, struct termio)
+#define TCSETAF		_IOW('t', 28, struct termio)
+
+#define TCSBRK		_IO('t', 29)
+#define TCXONC		_IO('t', 30)
+#define TCFLSH		_IO('t', 31)
+
+#define TIOCSWINSZ	_IOW('t', 103, struct winsize)
+#define TIOCGWINSZ	_IOR('t', 104, struct winsize)
+#define	TIOCSTART	_IO('t', 110)		/* start output, like ^Q */
+#define	TIOCSTOP	_IO('t', 111)		/* stop output, like ^S */
+#define TIOCOUTQ        _IOR('t', 115, int)     /* output queue size */
+
+#define TIOCSPGRP	_IOW('t', 118, int)
+#define TIOCGPGRP	_IOR('t', 119, int)
+
+#define TIOCEXCL	_IO('T', 12) /* 0x540C */
+#define TIOCNXCL	_IO('T', 13) /* 0x540D */
+#define TIOCSCTTY	_IO('T', 14) /* 0x540E */
+
+#define TIOCSTI		_IOW('T', 18, char) /* 0x5412 */
+#define TIOCMGET	_IOR('T', 21, unsigned int) /* 0x5415 */
+#define TIOCMBIS	_IOW('T', 22, unsigne int) /* 0x5416 */
+#define TIOCMBIC	_IOW('T', 23, unsigne int) /* 0x5417 */
+#define TIOCMSET	_IOW('T', 24, unsigne int) /* 0x5418 */
+# define TIOCM_LE	0x001
+# define TIOCM_DTR	0x002
+# define TIOCM_RTS	0x004
+# define TIOCM_ST	0x008
+# define TIOCM_SR	0x010
+# define TIOCM_CTS	0x020
+# define TIOCM_CAR	0x040
+# define TIOCM_RNG	0x080
+# define TIOCM_DSR	0x100
+# define TIOCM_CD	TIOCM_CAR
+# define TIOCM_RI	TIOCM_RNG
+
+#define TIOCGSOFTCAR	_IOR('T', 25, unsigned int) /* 0x5419 */
+#define TIOCSSOFTCAR	_IOW('T', 26, unsigned int) /* 0x541A */
+#define TIOCLINUX	_IOW('T', 28, char) /* 0x541C */
+#define TIOCCONS	_IO('T', 29) /* 0x541D */
+#define TIOCGSERIAL	_IOR('T', 30, struct serial_struct) /* 0x541E */
+#define TIOCSSERIAL	_IOW('T', 31, struct serial_struct) /* 0x541F */
+#define TIOCPKT		_IOW('T', 32, int) /* 0x5420 */
+# define TIOCPKT_DATA		 0
+# define TIOCPKT_FLUSHREAD	 1
+# define TIOCPKT_FLUSHWRITE	 2
+# define TIOCPKT_STOP		 4
+# define TIOCPKT_START		 8
+# define TIOCPKT_NOSTOP		16
+# define TIOCPKT_DOSTOP		32
+
+
+#define TIOCNOTTY	_IO('T', 34) /* 0x5422 */
+#define TIOCSETD	_IOW('T', 35, int) /* 0x5423 */
+#define TIOCGETD	_IOR('T', 36, int) /* 0x5424 */
+#define TCSBRKP		_IOW('T', 37, int) /* 0x5425 */	/* Needed for POSIX tcsendbreak() */
+#define TIOCTTYGSTRUCT	_IOR('T', 38, struct tty_struct) /* 0x5426 */ /* For debugging only */
+#define TIOCSBRK	_IO('T', 39) /* 0x5427 */ /* BSD compatibility */
+#define TIOCCBRK	_IO('T', 40) /* 0x5428 */ /* BSD compatibility */
+#define TIOCGSID	_IOR('T', 41, pid_t) /* 0x5429 */ /* 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 */
+
+#define TIOCSERCONFIG	_IO('T', 83) /* 0x5453 */
+#define TIOCSERGWILD	_IOR('T', 84,  int) /* 0x5454 */
+#define TIOCSERSWILD	_IOW('T', 85,  int) /* 0x5455 */
+#define TIOCGLCKTRMIOS	_IOR('T', 86, struct termios) /* 0x5456 */
+#define TIOCSLCKTRMIOS	_IOW('T', 87, struct termios) /* 0x5457 */
+#define TIOCSERGSTRUCT	_IOR('T', 88, struct async_struct) /* 0x5458 */ /* For debugging only */
+#define TIOCSERGETLSR   _IOR('T', 89, unsigned int) /* 0x5459 */ /* Get line status register */
+  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+# define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* 0x545A */ /* Get multiport config  */
+#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* 0x545B */ /* Set multiport config */
+
+#define TIOCMIWAIT	_IO('T', 92) /* 0x545C */	/* wait for a change on serial input line(s) */
+#define TIOCGICOUNT	_IOR('T', 93, struct async_icount) /* 0x545D */	/* read serial port inline interrupt counts */
+
+#endif /* __ASM_SH_IOCTLS_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/ipc.h linux/include/asm-sh/ipc.h
--- v2.3.15/linux/include/asm-sh/ipc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/ipc.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,31 @@
+#ifndef __ASM_SH_IPC_H
+#define __ASM_SH_IPC_H
+
+/* 
+ * These are used to wrap system calls on x86.
+ *
+ * See arch/i386/kernel/sys_i386.c for ugly details..
+ */
+struct ipc_kludge {
+	struct msgbuf *msgp;
+	long msgtyp;
+};
+
+#define SEMOP		 1
+#define SEMGET		 2
+#define SEMCTL		 3
+#define MSGSND		11
+#define MSGRCV		12
+#define MSGGET		13
+#define MSGCTL		14
+#define SHMAT		21
+#define SHMDT		22
+#define SHMGET		23
+#define SHMCTL		24
+
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC            25
+
+#define IPCCALL(version,op)	((version)<<16 | (op))
+
+#endif /* __ASM_SH_IPC_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/irq.h linux/include/asm-sh/irq.h
--- v2.3.15/linux/include/asm-sh/irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/irq.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,35 @@
+#ifndef __ASM_SH_IRQ_H
+#define __ASM_SH_IRQ_H
+
+/*
+ *
+ * linux/include/asm-sh/irq.h
+ *
+ * Copyright (C) 1999  Niibe Yutaka
+ *
+ */
+
+#define TIMER_IRQ		16	/* Hard-wired */
+#define TIMER_IRP_OFFSET	12
+#define TIMER_PRIORITY		 1
+
+/*
+ * 40 = 24+16
+ *
+ * 24 for on chip support modules.
+ * 16 for external interrupts.
+ *
+ */
+#define NR_IRQS	40
+
+extern void disable_irq(unsigned int);
+extern void disable_irq_nosync(unsigned int);
+extern void enable_irq(unsigned int);
+
+/*
+ * Function for "on chip support modules".
+ */
+extern void set_ipr_data(unsigned int irq, int offset, int priority);
+extern void make_onChip_irq(unsigned int irq);
+
+#endif /* __ASM_SH_IRQ_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/mman.h linux/include/asm-sh/mman.h
--- v2.3.15/linux/include/asm-sh/mman.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/mman.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,32 @@
+#ifndef __ASM_SH_MMAN_H
+#define __ASM_SH_MMAN_H
+
+#define PROT_READ	0x1		/* page can be read */
+#define PROT_WRITE	0x2		/* page can be written */
+#define PROT_EXEC	0x4		/* page can be executed */
+#define PROT_NONE	0x0		/* page can not be accessed */
+
+#define MAP_SHARED	0x01		/* Share changes */
+#define MAP_PRIVATE	0x02		/* Changes are private */
+#define MAP_TYPE	0x0f		/* Mask for type of mapping */
+#define MAP_FIXED	0x10		/* Interpret addr exactly */
+#define MAP_ANONYMOUS	0x20		/* don't use a file */
+
+#define MAP_GROWSDOWN	0x0100		/* stack-like segment */
+#define MAP_DENYWRITE	0x0800		/* ETXTBSY */
+#define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
+#define MAP_LOCKED	0x2000		/* pages are locked */
+#define MAP_NORESERVE	0x4000		/* don't check for reservations */
+
+#define MS_ASYNC	1		/* sync memory asynchronously */
+#define MS_INVALIDATE	2		/* invalidate the caches */
+#define MS_SYNC		4		/* synchronous memory sync */
+
+#define MCL_CURRENT	1		/* lock all current mappings */
+#define MCL_FUTURE	2		/* lock all future mappings */
+
+/* compatibility flags */
+#define MAP_ANON	MAP_ANONYMOUS
+#define MAP_FILE	0
+
+#endif /* __ASM_SH_MMAN_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/mmu_context.h linux/include/asm-sh/mmu_context.h
--- v2.3.15/linux/include/asm-sh/mmu_context.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/mmu_context.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ * ASID handling idea taken from MIPS implementation.
+ */
+#ifndef __ASM_SH_MMU_CONTEXT_H
+#define __ASM_SH_MMU_CONTEXT_H
+
+/* The MMU "context" consists of two things:
+     (a) TLB cache version (or round, cycle whatever expression you like)
+     (b) ASID (Address Space IDentifier)
+ */
+
+/*
+ * Cache of MMU context last used.
+ */
+extern unsigned long mmu_context_cache;
+
+#define MMU_CONTEXT_ASID_MASK 0xff
+#define MMU_CONTEXT_VERSION_MASK 0xffffff00
+#define MMU_CONTEXT_FIRST_VERSION 0x100
+#define NO_CONTEXT 0
+
+extern __inline__ void
+get_new_mmu_context(struct mm_struct *mm)
+{
+	unsigned long mc = ++mmu_context_cache;
+
+	if (!(mc & MMU_CONTEXT_ASID_MASK)) {
+		/* We exhaust ASID of this version.
+		   Flush all TLB and start new cycle. */
+		flush_tlb_all();
+		/* Fix version if needed.
+		   Note that we avoid version #0 to distingush NO_CONTEXT. */
+		if (!mc) 
+			mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION;
+	}
+	mm->context = mc;
+}
+
+/*P
+ * Get MMU context if needed.
+ */
+extern __inline__ void
+get_mmu_context(struct mm_struct *mm)
+{
+	if (mm) {
+		unsigned long mc = mmu_context_cache;
+		/* Check if we have old version of context.
+		   If it's old, we need to get new context with new version. */
+		if ((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK)
+			get_new_mmu_context(mm);
+	}
+}
+
+/*P
+ * Initialize the context related info for a new mm_struct
+ * instance.
+ */
+extern __inline__ void init_new_context(struct task_struct *tsk,
+					struct mm_struct *mm)
+{
+	mm->context = NO_CONTEXT;
+}
+
+/*P
+ * Destroy context related info for an mm_struct that is about
+ * to be put to rest.
+ */
+extern __inline__ void destroy_context(struct mm_struct *mm)
+{
+	mm->context = NO_CONTEXT;
+}
+
+/* Other MMU related constants. */
+
+#define MMU_PTEH	0xFFFFFFF0	/* Page table entry register HIGH */
+#define MMU_PTEL	0xFFFFFFF4	/* Page table entry register LOW */
+#define MMUCR		0xFFFFFFE0	/* MMU Control Register */
+
+#define MMU_TLB_ADDRESS_ARRAY 0xF2000000
+#define MMU_PAGE_ASSOC_BIT 0x80
+
+#define MMU_NTLB_ENTRIES       128	/* for 7708 */
+
+#define MMU_CONTROL_INIT 0x007	/* SV=0, TF=1, IX=1, AT=1 */
+
+#include <asm/uaccess.h> /* to get the definition of  __m */
+
+extern __inline__ void set_asid (unsigned long asid)
+{
+	__asm__ __volatile__ ("mov.l	%0,%1"
+			      : /* no output */
+			      : "r" (asid), "m" (__m(MMU_PTEH)));
+}
+
+extern __inline__ unsigned long get_asid (void)
+{
+	unsigned long asid;
+
+	__asm__ __volatile__ ("mov.l %1,%0"
+			      : "=r" (asid)
+			      : "m" (__m(MMU_PTEH)));
+	asid &= MMU_CONTEXT_ASID_MASK;
+	return asid;
+}
+
+/*P
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+extern __inline__ void activate_context(struct mm_struct *mm)
+{
+	get_mmu_context(mm);
+	set_asid(mm->context & MMU_CONTEXT_ASID_MASK);
+}
+
+/* MMU_TTB can be used for optimizing the fault handling.
+   (Currently not used) */
+#define MMU_TTB   0xFFFFFFF8	/* Translation table base register */
+extern __inline__ void switch_mm(struct mm_struct *prev,
+				 struct mm_struct *next,
+				 struct task_struct *tsk, unsigned int cpu)
+{
+	if (prev != next) {
+		unsigned long __pgdir = __pa(next->pgd);
+
+		__asm__ __volatile__("mov.l	%0,%1": \
+				     :"r" (__pgdir), "m" (__m(MMU_TTB)));
+		activate_context(next);
+		clear_bit(cpu, &prev->cpu_vm_mask);
+	}
+	set_bit(cpu, &next->cpu_vm_mask);
+}
+
+#define activate_mm(prev, next) \
+	switch_mm((prev),(next),NULL,smp_processor_id())
+
+#endif /* __ASM_SH_MMU_CONTEXT_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/namei.h linux/include/asm-sh/namei.h
--- v2.3.15/linux/include/asm-sh/namei.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/namei.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,18 @@
+/* $Id: namei.h,v 1.1 1996/12/13 14:48:21 jj Exp $
+ * linux/include/asm-sh/namei.h
+ *
+ * Included from linux/fs/namei.c
+ */
+
+#ifndef __ASM_SH_NAMEI_H
+#define __ASM_SH_NAMEI_H
+
+/* This dummy routine maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+
+#define __prefix_lookup_dentry(name, lookup_flags) \
+        do {} while (0)
+
+#endif /* __ASM_SH_NAMEI_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/page.h linux/include/asm-sh/page.h
--- v2.3.15/linux/include/asm-sh/page.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/page.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,104 @@
+#ifndef __ASM_SH_PAGE_H
+#define __ASM_SH_PAGE_H
+
+/*
+ * Copyright (C) 1999  Niibe Yutaka
+ */
+
+/* XXX 
+   [ P0 (virtual) ]               0x00000000     <------ User space
+   [ P1 (fixed)  write-through]   0x80000000     <------ Kernel space
+   [ P2 (fixed)  non-cachable]    0xA0000000     <------ Physical access
+   [ P3 (virtual) write-back]     0xC0000000     <------ not used
+   [ P4 control   ]               0xE0000000
+ */
+
+#include <linux/config.h>
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT	12
+#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_MASK	(~(PAGE_SIZE-1))
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#define STRICT_MM_TYPECHECKS
+
+#define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(to,from)	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+
+#ifdef STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)	((x).pte)
+#define pmd_val(x)	((x).pmd)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)	((x).pgprot)
+
+#define __pte(x)	((pte_t) { (x) } )
+#define __pmd(x)	((pmd_t) { (x) } )
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __pgprot(x)	((pgprot_t) { (x) } )
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x)	(x)
+#define pmd_val(x)	(x)
+#define pgd_val(x)	(x)
+#define pgprot_val(x)	(x)
+
+#define __pte(x)	(x)
+#define __pmd(x)	(x)
+#define __pgd(x)	(x)
+#define __pgprot(x)	(x)
+
+#endif
+#endif /* !__ASSEMBLY__ */
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+/*
+ * IF YOU CHANGE THIS, PLEASE ALSO CHANGE
+ *
+ *	arch/sh/vmlinux.lds
+ *
+ * which has the same constant encoded..
+ */
+#define __PAGE_OFFSET		(0x80000000)
+
+#define __MEMORY_START		CONFIG_MEMORY_START
+
+#define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET+__MEMORY_START)
+#define __pa(x)			((unsigned long)(x)-__PAGE_OFFSET)
+#define __va(x)			((void *)((unsigned long)(x)+__PAGE_OFFSET))
+#define MAP_NR(addr)		((__pa(addr)-__MEMORY_START) >> PAGE_SHIFT)
+
+#ifndef __ASSEMBLY__
+#define BUG() do { \
+	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+	asm volatile("nop"); \
+} while (0)
+
+#define PAGE_BUG(page) do { \
+	BUG(); \
+} while (0)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH_PAGE_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/param.h linux/include/asm-sh/param.h
--- v2.3.15/linux/include/asm-sh/param.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/param.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,20 @@
+#ifndef __ASM_SH_PARAM_H
+#define __ASM_SH_PARAM_H
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#define EXEC_PAGESIZE	4096
+
+#ifndef NGROUPS
+#define NGROUPS		32
+#endif
+
+#ifndef NOGROUP
+#define NOGROUP		(-1)
+#endif
+
+#define MAXHOSTNAMELEN	64	/* max length of hostname */
+
+#endif /* __ASM_SH_PARAM_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/pgtable.h linux/include/asm-sh/pgtable.h
--- v2.3.15/linux/include/asm-sh/pgtable.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/pgtable.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,494 @@
+#ifndef __ASM_SH_PGTABLE_H
+#define __ASM_SH_PGTABLE_H
+
+/* Copyright (C) 1999 Niibe Yutaka */
+
+#include <linux/config.h>
+
+/*
+ * This file contains the functions and defines necessary to modify and use
+ * the SuperH page table tree.
+ */
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#include <linux/threads.h>
+
+extern pgd_t swapper_pg_dir[1024];
+
+#ifdef CONFIG_CPU_SH3
+/* Cache flushing:
+ *
+ *  - flush_cache_all() flushes entire cache
+ *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
+ *  - flush_cache_page(mm, vmaddr) flushes a single page
+ *  - flush_cache_range(mm, start, end) flushes a range of pages
+ *  - flush_page_to_ram(page) write back kernel page to ram
+ *
+ *  Caches are indexed (effectively) by physical address on SH-3, so
+ *  we don't need them.
+ */
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(mm, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_page_to_ram(page)			do { } while (0)
+#define flush_icache_range(start, end)		do { } while (0)
+#elif CONFIG_CPU_SH4
+/*
+ *  Caches are broken on SH-4, so we need them.
+ *  You do bad job!
+ */
+flush_cache_all()
+flush_cache_mm(mm)
+flush_cache_range(mm, start, end)
+flush_cache_page(vma, vmaddr)
+flush_page_to_ram(page)
+flush_icache_range(start, end)
+#endif
+
+/* TLB flushing:
+ *
+ *  - flush_tlb_all() flushes all processes TLB entries
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB entries
+ *  - flush_tlb_page(mm, vmaddr) flushes a single page
+ *  - flush_tlb_range(mm, start, end) flushes a range of pages
+ */
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_range(struct mm_struct *mm, unsigned long start,
+			    unsigned long end);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
+
+/*
+ * Basically we have the same two-level (which is the logical three level
+ * Linux page table layout folded) page tables as the i386.
+ */
+
+#endif /* !__ASSEMBLY__ */
+
+/* PMD_SHIFT determines the size of the area a second-level page table can map */
+#define PMD_SHIFT	22
+#define PMD_SIZE	(1UL << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define PGDIR_SHIFT	22
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+
+/*
+ * Entries per page directory level: we use two-level, so
+ * we don't really have any PMD directory physically.
+ */
+#define PTRS_PER_PTE	1024
+#define PTRS_PER_PMD	1
+#define PTRS_PER_PGD	1024
+#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
+
+#ifndef __ASSEMBLY__
+#define VMALLOC_START	0xc0000000
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END	0xe0000000
+
+#define _PAGE_READ 	0x001  /* software: read access alowed */
+#define _PAGE_ACCESSED	0x002  /* software: page referenced */
+#define _PAGE_DIRTY	0x004  /* D-bit   : page changed */
+/*		 	0x008  */
+/*		 	0x010  */
+#define _PAGE_RW	0x020  /* PR0-bit : write access allowed */
+#define _PAGE_USER	0x040  /* PR1-bit : user space access allowed */
+/*		 	0x080  */
+#define _PAGE_PRESENT	0x100  /* V-bit   : page is valid */
+
+/* Mask which drop software flags */
+#define _PAGE_FLAGS_HARDWARE_MASK	0xfffff164
+/* Flags defalult: SZ=1 (4k-byte), C=1 (cachable), SH=0 (not shared) */
+#define _PAGE_FLAGS_HARDWARE_DEFAULT	0x00000018
+
+
+#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+#define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
+#define PAGE_KERNEL_RO	__pgprot(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED)
+
+/*
+ * As i386 and MIPS, SuperH can't do page protection for execute, and
+ * considers that the same are read.  Also, write permissions imply
+ * read permissions. This is the closest we can get..  
+ */
+
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY
+#define __P010	PAGE_COPY
+#define __P011	PAGE_COPY
+#define __P100	PAGE_READONLY
+#define __P101	PAGE_READONLY
+#define __P110	PAGE_COPY
+#define __P111	PAGE_COPY
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY
+#define __S010	PAGE_SHARED
+#define __S011	PAGE_SHARED
+#define __S100	PAGE_READONLY
+#define __S101	PAGE_READONLY
+#define __S110	PAGE_SHARED
+#define __S111	PAGE_SHARED
+
+/*
+ * BAD_PAGETABLE is used when we need a bogus page-table, while
+ * BAD_PAGE is used for a bogus page.
+ *
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern pte_t __bad_page(void);
+extern pte_t * __bad_pagetable(void);
+
+extern unsigned long empty_zero_page[1024];
+
+#define BAD_PAGETABLE __bad_pagetable()
+#define BAD_PAGE __bad_page()
+#define ZERO_PAGE(vaddr) ((unsigned long) empty_zero_page)
+
+/* number of bits that fit into a memory pointer */
+#define BITS_PER_PTR			(8*sizeof(unsigned long))
+
+/* to align the pointer to a pointer address */
+#define PTR_MASK			(~(sizeof(void*)-1))
+
+/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
+/* 64-bit machines, beware!  SRB. */
+#define SIZEOF_PTR_LOG2			2
+
+/* to find an entry in a page-table */
+#define PAGE_PTR(address) \
+((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+extern __inline__ void set_pte(pte_t *ptep, pte_t pteval)
+{
+	*ptep = pteval;
+}
+
+extern __inline__ int pte_none(pte_t pte)
+{
+	return !pte_val(pte);
+}
+
+extern __inline__ int pte_present(pte_t pte)
+{
+	return pte_val(pte) & _PAGE_PRESENT;
+}
+
+extern __inline__ void pte_clear(pte_t *ptep)
+{
+	pte_val(*ptep) = 0;
+}
+
+extern __inline__ int pmd_none(pmd_t pmd)
+{
+	return !pmd_val(pmd);
+}
+
+#define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
+
+extern __inline__ int pmd_present(pmd_t pmd)
+{
+	return pmd_val(pmd) & _PAGE_PRESENT;
+}
+
+extern __inline__ void pmd_clear(pmd_t *pmdp)
+{
+	pmd_val(*pmdp) = 0;
+}
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+extern __inline__ int pgd_none(pgd_t pgd)	{ return 0; }
+extern __inline__ int pgd_bad(pgd_t pgd)	{ return 0; }
+extern __inline__ int pgd_present(pgd_t pgd)	{ return 1; }
+extern __inline__ void pgd_clear(pgd_t * pgdp)	{ }
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+extern __inline__ int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
+extern __inline__ int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
+extern __inline__ int pte_dirty(pte_t pte){ return pte_val(pte) & _PAGE_DIRTY; }
+extern __inline__ int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; }
+extern __inline__ int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_RW; }
+
+extern __inline__ pte_t pte_rdprotect(pte_t pte){ pte_val(pte) &= ~_PAGE_USER; return pte; }
+extern __inline__ pte_t pte_exprotect(pte_t pte){ pte_val(pte) &= ~_PAGE_USER; return pte; }
+extern __inline__ pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+extern __inline__ pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+extern __inline__ pte_t pte_wrprotect(pte_t pte){ pte_val(pte) &= ~_PAGE_RW; return pte; }
+extern __inline__ pte_t pte_mkread(pte_t pte)	{ pte_val(pte) |= _PAGE_USER; return pte; }
+extern __inline__ pte_t pte_mkexec(pte_t pte)	{ pte_val(pte) |= _PAGE_USER; return pte; }
+extern __inline__ pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
+extern __inline__ pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+extern __inline__ pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= _PAGE_RW; return pte; }
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
+{
+	return __pte(__pa(page) | pgprot_val(pgprot));
+}
+
+/* This takes a physical page address that is used by the remapping functions */
+extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
+{
+	return __pte(physpage | pgprot_val(pgprot));
+}
+
+extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
+}
+
+extern __inline__ unsigned long pte_page(pte_t pte)
+{
+	return (unsigned long)__va(pte_val(pte) & PAGE_MASK);
+}
+
+extern __inline__ unsigned long pmd_page(pmd_t pmd)
+{
+	return (unsigned long)__va(pmd_val(pmd) & PAGE_MASK);
+}
+
+extern __inline__ void pmd_set(pmd_t * pmdp, pte_t * ptep)
+{
+	pmd_val(*pmdp) = __pa(((unsigned long) ptep) & PAGE_MASK) | _PAGE_TABLE;
+}
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/* to find an entry in a page-table-directory */
+extern __inline__ pgd_t *pgd_offset(struct mm_struct *mm, unsigned long addr)
+{
+	return mm->pgd + (addr >> PGDIR_SHIFT);
+}
+
+/* Find an entry in the second-level page table.. */
+extern __inline__ pmd_t * pmd_offset(pgd_t * dir, unsigned long addr)
+{
+	return (pmd_t *) dir;
+}
+
+/* Find an entry in the third-level page table.. */ 
+extern __inline__ pte_t *pte_offset(pmd_t * dir, unsigned long addr)
+{
+	return (pte_t *) (pmd_page(*dir)) +
+	       ((addr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+}
+
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any.
+ */
+
+#define pgd_quicklist (current_cpu_data.pgd_quick)
+#define pmd_quicklist ((unsigned long *)0)
+#define pte_quicklist (current_cpu_data.pte_quick)
+#define pgtable_cache_size (current_cpu_data.pgtable_cache_sz)
+
+extern __inline__ pgd_t *get_pgd_slow(void)
+{
+	pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL);
+
+	if (ret) {
+		memset(ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+		memcpy(ret + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+	}
+	return ret;
+}
+
+extern __inline__ pgd_t *get_pgd_fast(void)
+{
+	unsigned long *ret;
+
+	if ((ret = pgd_quicklist) != NULL) {
+		pgd_quicklist = (unsigned long *)(*ret);
+		ret[0] = 0;
+		pgtable_cache_size--;
+	} else
+		ret = (unsigned long *)get_pgd_slow();
+	return (pgd_t *)ret;
+}
+
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
+{
+	*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
+	pgd_quicklist = (unsigned long *) pgd;
+	pgtable_cache_size++;
+}
+
+extern __inline__ void free_pgd_slow(pgd_t *pgd)
+{
+	free_page((unsigned long)pgd);
+}
+
+extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
+extern pte_t *get_pte_kernel_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)
+{
+	free_page((unsigned long)pte);
+}
+
+/* We don't use pmd cache, so these are dummy routines */
+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 void __bad_pte(pmd_t *pmd);
+extern void __bad_pte_kernel(pmd_t *pmd);
+
+#define pte_free_kernel(pte)    free_pte_slow(pte)
+#define pte_free(pte)           free_pte_slow(pte)
+#define pgd_free(pgd)           free_pgd_slow(pgd)
+#define pgd_alloc()             get_pgd_fast()
+
+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 = get_pte_fast();
+		
+		if (!page)
+			return get_pte_kernel_slow(pmd, address);
+		pmd_set(pmd, page);
+		return page + address;
+	}
+	if (pmd_bad(*pmd)) {
+		__bad_pte_kernel(pmd);
+		return NULL;
+	}
+	return (pte_t *) pmd_page(*pmd) + address;
+}
+
+extern __inline__ pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+{
+	address = (address >> (PAGE_SHIFT-2)) & 4*(PTRS_PER_PTE - 1);
+
+	if (pmd_none(*pmd))
+		goto getnew;
+	if (pmd_bad(*pmd))
+		goto fix;
+	return (pte_t *) (pmd_page(*pmd) + address);
+getnew:
+{
+	unsigned long page = (unsigned long) get_pte_fast();
+	
+	if (!page)
+		return get_pte_slow(pmd, address);
+	pmd_val(*pmd) = _PAGE_TABLE + __pa(page);
+	return (pte_t *) (page + address);
+}
+fix:
+	__bad_pte(pmd);
+	return NULL;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+extern inline void pmd_free(pmd_t * pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
+{
+	return (pmd_t *) pgd;
+}
+
+#define pmd_free_kernel		pmd_free
+#define pmd_alloc_kernel	pmd_alloc
+
+extern int do_check_pgt_cache(int, int);
+
+extern inline void set_pgdir(unsigned long address, pgd_t entry)
+{
+	struct task_struct * p;
+	pgd_t *pgd;
+        
+	read_lock(&tasklist_lock);
+	for_each_task(p) {
+		if (!p->mm)
+			continue;
+		*pgd_offset(p->mm,address) = entry;
+	}
+	read_unlock(&tasklist_lock);
+	for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
+		pgd[address >> PGDIR_SHIFT] = entry;
+}
+
+extern pgd_t swapper_pg_dir[1024];
+
+extern void update_mmu_cache(struct vm_area_struct * vma,
+			     unsigned long address, pte_t pte);
+
+#define SWP_TYPE(entry) (((entry) >> 1) & 0x3f)
+#define SWP_OFFSET(entry) ((entry) >> 8)
+#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
+
+#define module_map      vmalloc
+#define module_unmap    vfree
+
+#endif /* !__ASSEMBLY__ */
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define PageSkip(page)		(0)
+#define kern_addr_valid(addr)	(1)
+
+#define io_remap_page_range remap_page_range
+
+#endif /* __ASM_SH_PAGE_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/poll.h linux/include/asm-sh/poll.h
--- v2.3.15/linux/include/asm-sh/poll.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/poll.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,25 @@
+#ifndef __ASM_SH_POLL_H
+#define __ASM_SH_POLL_H
+
+/* These are specified by iBCS2 */
+#define POLLIN		0x0001
+#define POLLPRI		0x0002
+#define POLLOUT		0x0004
+#define POLLERR		0x0008
+#define POLLHUP		0x0010
+#define POLLNVAL	0x0020
+
+/* The rest seem to be more-or-less nonstandard. Check them! */
+#define POLLRDNORM	0x0040
+#define POLLRDBAND	0x0080
+#define POLLWRNORM	0x0100
+#define POLLWRBAND	0x0200
+#define POLLMSG		0x0400
+
+struct pollfd {
+	int fd;
+	short events;
+	short revents;
+};
+
+#endif /* __ASM_SH_POLL_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/posix_types.h linux/include/asm-sh/posix_types.h
--- v2.3.15/linux/include/asm-sh/posix_types.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/posix_types.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,112 @@
+#ifndef __ASM_SH_POSIX_TYPES_H
+#define __ASM_SH_POSIX_TYPES_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;
+
+#ifdef __GNUC__
+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;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+#undef	__FD_SET
+static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
+{
+	unsigned long __tmp = __fd / __NFDBITS;
+	unsigned long __rem = __fd % __NFDBITS;
+	__fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
+}
+
+#undef	__FD_CLR
+static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
+{
+	unsigned long __tmp = __fd / __NFDBITS;
+	unsigned long __rem = __fd % __NFDBITS;
+	__fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
+}
+
+
+#undef	__FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
+{ 
+	unsigned long __tmp = __fd / __NFDBITS;
+	unsigned long __rem = __fd % __NFDBITS;
+	return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
+ */
+#undef	__FD_ZERO
+static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
+{
+	unsigned long *__tmp = __p->fds_bits;
+	int __i;
+
+	if (__builtin_constant_p(__FDSET_LONGS)) {
+		switch (__FDSET_LONGS) {
+		case 16:
+			__tmp[ 0] = 0; __tmp[ 1] = 0;
+			__tmp[ 2] = 0; __tmp[ 3] = 0;
+			__tmp[ 4] = 0; __tmp[ 5] = 0;
+			__tmp[ 6] = 0; __tmp[ 7] = 0;
+			__tmp[ 8] = 0; __tmp[ 9] = 0;
+			__tmp[10] = 0; __tmp[11] = 0;
+			__tmp[12] = 0; __tmp[13] = 0;
+			__tmp[14] = 0; __tmp[15] = 0;
+			return;
+
+		case 8:
+			__tmp[ 0] = 0; __tmp[ 1] = 0;
+			__tmp[ 2] = 0; __tmp[ 3] = 0;
+			__tmp[ 4] = 0; __tmp[ 5] = 0;
+			__tmp[ 6] = 0; __tmp[ 7] = 0;
+			return;
+
+		case 4:
+			__tmp[ 0] = 0; __tmp[ 1] = 0;
+			__tmp[ 2] = 0; __tmp[ 3] = 0;
+			return;
+		}
+	}
+	__i = __FDSET_LONGS;
+	while (__i) {
+		__i--;
+		*__tmp = 0;
+		__tmp++;
+	}
+}
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif /* __ASM_SH_POSIX_TYPES_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/processor.h linux/include/asm-sh/processor.h
--- v2.3.15/linux/include/asm-sh/processor.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/processor.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,114 @@
+/*
+ * include/asm-sh/processor.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ */
+
+#ifndef __ASM_SH_PROCESSOR_H
+#define __ASM_SH_PROCESSOR_H
+
+#include <asm/page.h>
+#include <asm/types.h>
+#include <linux/threads.h>
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ void *pc; __asm__("mova	1f,%0\n1:":"=z" (pc)); pc; })
+
+/*
+ *  CPU type and hardware bug flags. Kept separately for each CPU.
+ */
+
+struct sh_cpuinfo {
+	unsigned long loops_per_sec;
+	unsigned long *pgd_quick;
+	unsigned long *pte_quick;
+	unsigned long pgtable_cache_sz;
+};
+
+extern struct sh_cpuinfo boot_cpu_data;
+
+#define cpu_data &boot_cpu_data
+#define current_cpu_data boot_cpu_data
+
+/*
+ * User space process size: 2GB.
+ */
+#define TASK_SIZE	0x80000000
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
+
+struct thread_struct {
+	unsigned long sp;
+	unsigned long pc;
+
+	unsigned long trap_no, error_code;
+	unsigned long address;
+	/* Hardware debugging registers may come here */
+};
+
+#define INIT_MMAP \
+{ &init_mm, 0x80000000, 0xa0000000, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
+
+#define INIT_THREAD  {						\
+	sizeof(init_stack) + (long) &init_stack, /* sp */	\
+	0,					 /* pc */	\
+	0, 0, \
+}
+
+/*
+ * Do necessary setup to start up a newly executed thread.
+ */
+#define start_thread(regs, new_pc, new_sp)	 \
+	set_fs(USER_DS);			 \
+	regs->pr = 0;   		 	 \
+	regs->sr = 0;		/* User mode. */ \
+	regs->pc = new_pc;			 \
+	regs->u_regs[UREG_SP] = new_sp
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+struct mm_struct;
+
+/* Free all resources held by a thread. */
+extern void release_thread(struct task_struct *);
+/*
+ * create a kernel thread without removing it from tasklists
+ */
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+/*
+ * 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 */
+
+
+/* Copy and release all segment info associated with a VM */
+#define copy_segments(p, mm)	do { } while(0)
+#define release_segments(mm)	do { } while(0)
+#define forget_segments()	do { } while (0)
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+extern __inline__ unsigned long thread_saved_pc(struct thread_struct *t)
+{
+	return t->pc;
+}
+
+#define THREAD_SIZE (2*PAGE_SIZE)
+extern struct task_struct * alloc_task_struct(void);
+extern void free_task_struct(struct task_struct *);
+
+#define init_task	(init_task_union.task)
+#define init_stack	(init_task_union.stack)
+
+#endif /* __ASM_SH_PROCESSOR_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/ptrace.h linux/include/asm-sh/ptrace.h
--- v2.3.15/linux/include/asm-sh/ptrace.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/ptrace.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,31 @@
+#ifndef __ASM_SH_PTRACE_H
+#define __ASM_SH_PTRACE_H
+
+/*
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ */
+
+/*
+ * This struct defines the way the registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_regs {
+	long syscall_nr;
+	unsigned long u_regs[16];
+	unsigned long gbr;
+	unsigned long mach;
+	unsigned long macl;
+	unsigned long pr;
+	unsigned long sr;
+	unsigned long pc;
+};
+
+#ifdef __KERNEL__
+#define user_mode(regs) (((regs)->sr & 0x40000000)==0)
+#define instruction_pointer(regs) ((regs)->pc)
+extern void show_regs(struct pt_regs *);
+#endif
+
+#define UREG_SP 15
+#endif /* __ASM_SH_PTRACE_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/resource.h linux/include/asm-sh/resource.h
--- v2.3.15/linux/include/asm-sh/resource.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/resource.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,39 @@
+#ifndef __ASM_SH_RESOURCE_H
+#define __ASM_SH_RESOURCE_H
+
+/*
+ * Resource limits
+ */
+
+#define RLIMIT_CPU	0		/* CPU time in ms */
+#define RLIMIT_FSIZE	1		/* Maximum filesize */
+#define RLIMIT_DATA	2		/* max data size */
+#define RLIMIT_STACK	3		/* max stack size */
+#define RLIMIT_CORE	4		/* max core file size */
+#define RLIMIT_RSS	5		/* max resident set size */
+#define RLIMIT_NPROC	6		/* max number of processes */
+#define RLIMIT_NOFILE	7		/* max number of open files */
+#define RLIMIT_MEMLOCK	8		/* max locked-in-memory address space */
+#define RLIMIT_AS	9		/* address space limit */
+
+#define RLIM_NLIMITS	10
+
+#ifdef __KERNEL__
+
+#define INIT_RLIMITS					\
+{							\
+	{ LONG_MAX, LONG_MAX },				\
+	{ LONG_MAX, LONG_MAX },				\
+	{ LONG_MAX, LONG_MAX },				\
+	{ _STK_LIM, LONG_MAX },				\
+	{        0, LONG_MAX },				\
+	{ LONG_MAX, LONG_MAX },				\
+	{ 0, 0 },					\
+	{ INR_OPEN, INR_OPEN },				\
+	{ LONG_MAX, LONG_MAX },				\
+	{ LONG_MAX, LONG_MAX },				\
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH_RESOURCE_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/semaphore-helper.h linux/include/asm-sh/semaphore-helper.h
--- v2.3.15/linux/include/asm-sh/semaphore-helper.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/semaphore-helper.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,89 @@
+#ifndef __ASM_SH_SEMAPHORE_HELPER_H
+#define __ASM_SH_SEMAPHORE_HELPER_H
+
+/*
+ * SMP- and interrupt-safe semaphores helper functions.
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ * (C) Copyright 1999 Andrea Arcangeli
+ */
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ *
+ * This is trivially done with load_locked/store_cond,
+ * which we have.  Let the rest of the losers suck eggs.
+ */
+static __inline__ void wake_one_more(struct semaphore * sem)
+{
+	atomic_inc((atomic_t *)&sem->waking);
+}
+
+static __inline__ int waking_non_zero(struct semaphore *sem)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&semaphore_wake_lock, flags);
+	if (sem->waking > 0) {
+		sem->waking--;
+		ret = 1;
+	}
+	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+	return ret;
+}
+
+/*
+ * waking_non_zero_interruptible:
+ *	1	got the lock
+ *	0	go to sleep
+ *	-EINTR	interrupted
+ *
+ * We must undo the sem->count down_interruptible() increment while we are
+ * protected by the spinlock in order to make atomic this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
+						struct task_struct *tsk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&semaphore_wake_lock, flags);
+	if (sem->waking > 0) {
+		sem->waking--;
+		ret = 1;
+	} else if (signal_pending(tsk)) {
+		atomic_inc(&sem->count);
+		ret = -EINTR;
+	}
+	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+	return ret;
+}
+
+/*
+ * waking_non_zero_trylock:
+ *	1	failed to lock
+ *	0	got the lock
+ *
+ * We must undo the sem->count down_trylock() increment while we are
+ * protected by the spinlock in order to make atomic this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
+{
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&semaphore_wake_lock, flags);
+	if (sem->waking <= 0)
+		atomic_inc(&sem->count);
+	else {
+		sem->waking--;
+		ret = 0;
+	}
+	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+	return ret;
+}
+
+#endif /* __ASM_SH_SEMAPHORE_HELPER_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/semaphore.h linux/include/asm-sh/semaphore.h
--- v2.3.15/linux/include/asm-sh/semaphore.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/semaphore.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,133 @@
+#ifndef __ASM_SH_SEMAPHORE_H
+#define __ASM_SH_SEMAPHORE_H
+
+#include <linux/linkage.h>
+
+/*
+ * SMP- and interrupt-safe semaphores.
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ *
+ * SuperH verison by Niibe Yutaka
+ *
+ */
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/spinlock.h>
+
+struct semaphore {
+	atomic_t count;
+	int waking;
+	wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+	long __magic;
+#endif
+};
+
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name) \
+		, (int)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+	__SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+	__SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+extern inline void sema_init (struct semaphore *sem, int val)
+{
+/*
+ *	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+ *
+ * i'd rather use the more flexible initialization above, but sadly
+ * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
+ */
+	atomic_set(&sem->count, val);
+	sem->waking = 0;
+	init_waitqueue_head(&sem->wait);
+#if WAITQUEUE_DEBUG
+	sem->__magic = (int)&sem->__magic;
+#endif
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+	sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+	sema_init(sem, 0);
+}
+
+asmlinkage void __down_failed(void /* special register calling convention */);
+asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
+asmlinkage int  __down_failed_trylock(void  /* params in registers */);
+asmlinkage void __up_wakeup(void /* special register calling convention */);
+
+asmlinkage void __down(struct semaphore * sem);
+asmlinkage int  __down_interruptible(struct semaphore * sem);
+asmlinkage int  __down_trylock(struct semaphore * sem);
+asmlinkage void __up(struct semaphore * sem);
+
+extern spinlock_t semaphore_wake_lock;
+
+extern __inline__ void down(struct semaphore * sem)
+{
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	if (atomic_dec_return(&sem->count) < 0)
+		__down(sem);
+}
+
+extern __inline__ int down_interruptible(struct semaphore * sem)
+{
+	int ret = 0;
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	if (atomic_dec_return(&sem->count) < 0)
+		ret = __down_interruptible(sem);
+	return ret;
+}
+
+extern __inline__ int down_trylock(struct semaphore * sem)
+{
+	int ret = 0;
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	if (atomic_dec_return(&sem->count) < 0)
+		ret = __down_trylock(sem);
+	return ret;
+}
+
+/*
+ * Note! This is subtle. We jump to wake people up only if
+ * the semaphore was negative (== somebody was waiting on it).
+ */
+extern __inline__ void up(struct semaphore * sem)
+{
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+	if (atomic_inc_return(&sem->count) <= 0)
+		__up(sem);
+}
+
+#endif /* __ASM_SH_SEMAPHORE_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/shmparam.h linux/include/asm-sh/shmparam.h
--- v2.3.15/linux/include/asm-sh/shmparam.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/shmparam.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,46 @@
+#ifndef __ASM_SH_SHMPARAM_H
+#define __ASM_SH_SHMPARAM_H
+
+/* address range for shared memory attaches if no address passed to shmat() */
+#define SHM_RANGE_START	0x50000000
+#define SHM_RANGE_END	0x60000000
+
+/*
+ * Format of a swap-entry for shared memory pages currently out in
+ * swap space (see also mm/swap.c).
+ *
+ * SWP_TYPE = SHM_SWP_TYPE
+ * SWP_OFFSET is used as follows:
+ *
+ *  bits 0..6 : id of shared memory segment page belongs to (SHM_ID)
+ *  bits 7..21: index of page within shared memory segment (SHM_IDX)
+ *		(actually fewer bits get used since SHMMAX is so low)
+ */
+
+/*
+ * Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and
+ * there is a static array of size SHMMNI.
+ */
+#define _SHM_ID_BITS	7
+#define SHM_ID_MASK	((1<<_SHM_ID_BITS)-1)
+
+#define SHM_IDX_SHIFT	(_SHM_ID_BITS)
+#define _SHM_IDX_BITS	15
+#define SHM_IDX_MASK	((1<<_SHM_IDX_BITS)-1)
+
+/*
+ * _SHM_ID_BITS + _SHM_IDX_BITS must be <= 24 on the i386 and
+ * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
+ */
+
+#define SHMMAX 0x2000000		/* max shared seg size (bytes) */
+/* Try not to change the default shipped SHMMAX - people rely on it */
+
+#define SHMMIN 1 /* really PAGE_SIZE */	/* min shared seg size (bytes) */
+#define SHMMNI (1<<_SHM_ID_BITS)	/* max num of segs system wide */
+#define SHMALL				/* max shm system wide (pages) */ \
+	(1<<(_SHM_IDX_BITS+_SHM_ID_BITS))
+#define	SHMLBA PAGE_SIZE		/* attach addr a multiple of this */
+#define SHMSEG SHMMNI			/* max shared segs per process */
+
+#endif /* __ASM_SH_SHMPARAM_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/sigcontext.h linux/include/asm-sh/sigcontext.h
--- v2.3.15/linux/include/asm-sh/sigcontext.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/sigcontext.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,17 @@
+#ifndef __ASM_SH_SIGCONTEXT_H
+#define __ASM_SH_SIGCONTEXT_H
+
+struct sigcontext {
+	unsigned long	oldmask;
+
+	/* CPU registers */
+	unsigned long   u_regs[16];
+	unsigned long gbr;
+	unsigned long mach;
+	unsigned long macl;
+	unsigned long pr;
+	unsigned long sr;
+	unsigned long pc;
+};
+
+#endif /* __ASM_SH_SIGCONTEXT_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/siginfo.h linux/include/asm-sh/siginfo.h
--- v2.3.15/linux/include/asm-sh/siginfo.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/siginfo.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,197 @@
+#ifndef __ASM_SH_SIGINFO_H
+#define __ASM_SH_SIGINFO_H
+
+#include <linux/types.h>
+
+/* XXX: This structure was copied from the Alpha; is there an iBCS version?  */
+
+typedef union sigval {
+	int sival_int;
+	void *sival_ptr;
+} sigval_t;
+
+#define SI_MAX_SIZE	128
+#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct siginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		int _pad[SI_PAD_SIZE];
+
+		/* kill() */
+		struct {
+			pid_t _pid;		/* sender's pid */
+			uid_t _uid;		/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			unsigned int _timer1;
+			unsigned int _timer2;
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			pid_t _pid;		/* sender's pid */
+			uid_t _uid;		/* sender's uid */
+			sigval_t _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			pid_t _pid;		/* which child */
+			uid_t _uid;		/* sender's uid */
+			int _status;		/* exit code */
+			clock_t _utime;
+			clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			void *_addr; /* faulting insn/memory ref. */
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+	} _sifields;
+} siginfo_t;
+
+/*
+ * How these fields are to be accessed.
+ */
+#define si_pid		_sifields._kill._pid
+#define si_uid		_sifields._kill._uid
+#define si_status	_sifields._sigchld._status
+#define si_utime	_sifields._sigchld._utime
+#define si_stime	_sifields._sigchld._stime
+#define si_value	_sifields._rt._sigval
+#define si_int		_sifields._rt._sigval.sival_int
+#define si_ptr		_sifields._rt._sigval.sival_ptr
+#define si_addr		_sifields._sigfault._addr
+#define si_band		_sifields._sigpoll._band
+#define si_fd		_sifields._sigpoll._fd
+
+/*
+ * si_code values
+ * Digital reserves positive values for kernel-generated signals.
+ */
+#define SI_USER		0	/* sent by kill, sigsend, raise */
+#define SI_KERNEL	0x80	/* sent by the kernel from somewhere */
+#define SI_QUEUE	-1	/* sent by sigqueue */
+#define SI_TIMER	-2	/* sent by timer expiration */
+#define SI_MESGQ	-3	/* sent by real time mesq state change */
+#define SI_ASYNCIO	-4	/* sent by AIO completion */
+#define SI_SIGIO	-5	/* sent by queued SIGIO */
+
+#define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
+#define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
+
+/*
+ * SIGILL si_codes
+ */
+#define ILL_ILLOPC	1	/* illegal opcode */
+#define ILL_ILLOPN	2	/* illegal operand */
+#define ILL_ILLADR	3	/* illegal addressing mode */
+#define ILL_ILLTRP	4	/* illegal trap */
+#define ILL_PRVOPC	5	/* privileged opcode */
+#define ILL_PRVREG	6	/* privileged register */
+#define ILL_COPROC	7	/* coprocessor error */
+#define ILL_BADSTK	8	/* internal stack error */
+#define NSIGILL		8
+
+/*
+ * SIGFPE si_codes
+ */
+#define FPE_INTDIV	1	/* integer divide by zero */
+#define FPE_INTOVF	2	/* integer overflow */
+#define FPE_FLTDIV	3	/* floating point divide by zero */
+#define FPE_FLTOVF	4	/* floating point overflow */
+#define FPE_FLTUND	5	/* floating point underflow */
+#define FPE_FLTRES	6	/* floating point inexact result */
+#define FPE_FLTINV	7	/* floating point invalid operation */
+#define FPE_FLTSUB	8	/* subscript out of range */
+#define NSIGFPE		8
+
+/*
+ * SIGSEGV si_codes
+ */
+#define SEGV_MAPERR	1	/* address not mapped to object */
+#define SEGV_ACCERR	2	/* invalid permissions for mapped object */
+#define NSIGSEGV	2
+
+/*
+ * SIGBUS si_codes
+ */
+#define BUS_ADRALN	1	/* invalid address alignment */
+#define BUS_ADRERR	2	/* non-existant physical address */
+#define BUS_OBJERR	3	/* object specific hardware error */
+#define NSIGBUS		3
+
+/*
+ * SIGTRAP si_codes
+ */
+#define TRAP_BRKPT	1	/* process breakpoint */
+#define TRAP_TRACE	2	/* process trace trap */
+#define NSIGTRAP	2
+
+/*
+ * SIGCHLD si_codes
+ */
+#define CLD_EXITED	1	/* child has exited */
+#define CLD_KILLED	2	/* child was killed */
+#define CLD_DUMPED	3	/* child terminated abnormally */
+#define CLD_TRAPPED	4	/* traced child has trapped */
+#define CLD_STOPPED	5	/* child has stopped */
+#define CLD_CONTINUED	6	/* stopped child has continued */
+#define NSIGCHLD
+
+/*
+ * SIGPOLL si_codes
+ */
+#define POLL_IN		1	/* data input available */
+#define POLL_OUT	2	/* output buffers available */
+#define POLL_MSG	3	/* input message available */
+#define POLL_ERR	4	/* i/o error */
+#define POLL_PRI	5	/* high priority input available */
+#define POLL_HUP	6	/* device disconnected */
+#define NSIGPOLL	6
+
+/*
+ * sigevent definitions
+ * 
+ * It seems likely that SIGEV_THREAD will have to be handled from 
+ * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the
+ * thread manager then catches and does the appropriate nonsense.
+ * However, everything is written out here so as to not get lost.
+ */
+#define SIGEV_SIGNAL	0	/* notify via signal */
+#define SIGEV_NONE	1	/* other notification: meaningless */
+#define SIGEV_THREAD	2	/* deliver via thread creation */
+
+#define SIGEV_MAX_SIZE	64
+#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct sigevent {
+	sigval_t sigev_value;
+	int sigev_signo;
+	int sigev_notify;
+	union {
+		int _pad[SIGEV_PAD_SIZE];
+
+		struct {
+			void (*_function)(sigval_t);
+			void *_attribute;	/* really pthread_attr_t */
+		} _sigev_thread;
+	} _sigev_un;
+} sigevent_t;
+
+#define sigev_notify_function	_sigev_un._sigev_thread._function
+#define sigev_notify_attributes	_sigev_un._sigev_thread._attribute
+
+#endif /* __ASM_SH_SIGINFO_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/signal.h linux/include/asm-sh/signal.h
--- v2.3.15/linux/include/asm-sh/signal.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/signal.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,183 @@
+#ifndef __ASM_SH_SIGNAL_H
+#define __ASM_SH_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifdef __KERNEL__
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+#define _NSIG		64
+#define _NSIG_BPW	32
+#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
+
+typedef unsigned long old_sigset_t;		/* at least 32 bits */
+
+typedef struct {
+	unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG		32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP		 1
+#define SIGINT		 2
+#define SIGQUIT		 3
+#define SIGILL		 4
+#define SIGTRAP		 5
+#define SIGABRT		 6
+#define SIGIOT		 6
+#define SIGBUS		 7
+#define SIGFPE		 8
+#define SIGKILL		 9
+#define SIGUSR1		10
+#define SIGSEGV		11
+#define SIGUSR2		12
+#define SIGPIPE		13
+#define SIGALRM		14
+#define SIGTERM		15
+#define SIGSTKFLT	16
+#define SIGCHLD		17
+#define SIGCONT		18
+#define SIGSTOP		19
+#define SIGTSTP		20
+#define SIGTTIN		21
+#define SIGTTOU		22
+#define SIGURG		23
+#define SIGXCPU		24
+#define SIGXFSZ		25
+#define SIGVTALRM	26
+#define SIGPROF		27
+#define SIGWINCH	28
+#define SIGIO		29
+#define SIGPOLL		SIGIO
+/*
+#define SIGLOST		29
+*/
+#define SIGPWR		30
+#define	SIGUNUSED	31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN	32
+#define SIGRTMAX	(_NSIG-1)
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * 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_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_NOCLDSTOP	0x00000001
+#define SA_NOCLDWAIT	0x00000002 /* not supported yet */
+#define SA_SIGINFO	0x00000004
+#define SA_ONSTACK	0x08000000
+#define SA_RESTART	0x10000000
+#define SA_NODEFER	0x40000000
+#define SA_RESETHAND	0x80000000
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+#define SA_INTERRUPT	0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER	0x04000000
+
+/* 
+ * sigaltstack controls
+ */
+#define SS_ONSTACK	1
+#define SS_DISABLE	2
+
+#define MINSIGSTKSZ	2048
+#define SIGSTKSZ	8192
+
+#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_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE		SA_ONESHOT
+#define SA_SAMPLE_RANDOM	SA_RESTART
+#define SA_SHIRQ		0x04000000
+#endif
+
+#define SIG_BLOCK          0	/* for blocking signals */
+#define SIG_UNBLOCK        1	/* for unblocking signals */
+#define SIG_SETMASK        2	/* for setting the signal mask */
+
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int);
+
+#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
+#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
+#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+
+#ifdef __KERNEL__
+struct old_sigaction {
+	__sighandler_t sa_handler;
+	old_sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+struct sigaction {
+	__sighandler_t sa_handler;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+	sigset_t sa_mask;		/* mask last for extensibility */
+};
+
+struct k_sigaction {
+	struct sigaction sa;
+};
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+	union {
+	  __sighandler_t _sa_handler;
+	  void (*_sa_sigaction)(int, struct siginfo *, void *);
+	} _u;
+	sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+#define sa_handler	_u._sa_handler
+#define sa_sigaction	_u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+	void *ss_sp;
+	int ss_flags;
+	size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+
+#define sigmask(sig)	(1UL << ((sig) - 1))
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH_SIGNAL_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/smp.h linux/include/asm-sh/smp.h
--- v2.3.15/linux/include/asm-sh/smp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/smp.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,4 @@
+#ifndef __ASM_SH_SMP_H
+#define __ASM_SH_SMP_H
+
+#endif /* __ASM_SH_SMP_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/smp_lock.h linux/include/asm-sh/smp_lock.h
--- v2.3.15/linux/include/asm-sh/smp_lock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/smp_lock.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,17 @@
+#ifndef __ASM_SH_SMPLOCK_H
+#define __ASM_SH_SMPLOCK_H
+
+#ifndef __SMP__
+
+#define lock_kernel()				do { } while(0)
+#define unlock_kernel()				do { } while(0)
+#define release_kernel_lock(task, cpu, depth)	((depth) = 1)
+#define reacquire_kernel_lock(task, cpu, depth)	do { } while(0)
+
+#else
+
+#error "We do not support SMP on SH yet"
+
+#endif /* __SMP__ */
+
+#endif /* __ASM_SH_SMPLOCK_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/socket.h linux/include/asm-sh/socket.h
--- v2.3.15/linux/include/asm-sh/socket.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/socket.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,51 @@
+#ifndef __ASM_SH_SOCKET_H
+#define __ASM_SH_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockoptions(2) */
+#define SOL_SOCKET	1
+
+#define SO_DEBUG	1
+#define SO_REUSEADDR	2
+#define SO_TYPE		3
+#define SO_ERROR	4
+#define SO_DONTROUTE	5
+#define SO_BROADCAST	6
+#define SO_SNDBUF	7
+#define SO_RCVBUF	8
+#define SO_KEEPALIVE	9
+#define SO_OOBINLINE	10
+#define SO_NO_CHECK	11
+#define SO_PRIORITY	12
+#define SO_LINGER	13
+#define SO_BSDCOMPAT	14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED	16
+#define SO_PEERCRED	17
+#define SO_RCVLOWAT	18
+#define SO_SNDLOWAT	19
+#define SO_RCVTIMEO	20
+#define SO_SNDTIMEO	21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION		22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
+#define SO_SECURITY_ENCRYPTION_NETWORK		24
+
+/* Nasty libc5 fixup - bletch */
+#if defined(__KERNEL__)
+/* Socket types. */
+#define SOCK_STREAM	1		/* stream (connection) socket	*/
+#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
+#define SOCK_RAW	3		/* raw socket			*/
+#define SOCK_RDM	4		/* reliably-delivered message	*/
+#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
+#define SOCK_PACKET	10		/* linux specific way of	*/
+					/* getting packets at the dev	*/
+					/* level.  For writing rarp and	*/
+					/* other similar things on the	*/
+					/* user level.			*/
+#endif					
+
+#endif /* __ASM_SH_SOCKET_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/sockios.h linux/include/asm-sh/sockios.h
--- v2.3.15/linux/include/asm-sh/sockios.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/sockios.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,13 @@
+#ifndef __ASM_SH_SOCKIOS_H
+#define __ASM_SH_SOCKIOS_H
+
+/* Socket-level I/O control calls. */
+#define FIOGETOWN	_IOR('f', 123, int)
+#define FIOSETOWN 	_IOW('f', 124, int)
+
+#define SIOCATMARK	_IOR('s', 7, int)
+#define SIOCSPGRP	_IOW('s', 8, pid_t)
+#define SIOCGPGRP	_IOR('s', 9, pid_t)
+
+#define SIOCGSTAMP	_IOR('s', 100, struct timeval) /* Get stamp - linux-specific */
+#endif /* __ASM_SH_SOCKIOS_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/softirq.h linux/include/asm-sh/softirq.h
--- v2.3.15/linux/include/asm-sh/softirq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/softirq.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,72 @@
+#ifndef __ASM_SH_SOFTIRQ_H
+#define __ASM_SH_SOFTIRQ_H
+
+extern unsigned int local_bh_count[NR_CPUS];
+
+#define cpu_bh_disable(cpu)	do { local_bh_count[(cpu)]++; barrier(); } while (0)
+#define cpu_bh_enable(cpu)	do { barrier(); local_bh_count[(cpu)]--; } while (0)
+
+#define cpu_bh_trylock(cpu)	(local_bh_count[(cpu)] ? 0 : (local_bh_count[(cpu)] = 1))
+#define cpu_bh_endlock(cpu)	(local_bh_count[(cpu)] = 0)
+
+#define local_bh_disable()	cpu_bh_disable(smp_processor_id())
+#define local_bh_enable()	cpu_bh_enable(smp_processor_id())
+
+#define get_active_bhs()	(bh_mask & bh_active)
+/* XXX */
+#define clear_active_bhs(x)	atomic_clear_mask((x),&bh_active)
+
+extern inline void init_bh(int nr, void (*routine)(void))
+{
+	bh_base[nr] = routine;
+	atomic_set(&bh_mask_count[nr], 0);
+	bh_mask |= 1 << nr;
+}
+
+extern inline void remove_bh(int nr)
+{
+	bh_mask &= ~(1 << nr);
+	mb();
+	bh_base[nr] = NULL;
+}
+
+extern inline void mark_bh(int nr)
+{
+	set_bit(nr, &bh_active);
+}
+
+extern inline void start_bh_atomic(void)
+{
+	local_bh_disable();
+	barrier();
+}
+
+extern inline void end_bh_atomic(void)
+{
+	barrier();
+	local_bh_enable();
+}
+
+/* These are for the irq's testing the lock */
+#define softirq_trylock(cpu)	(cpu_bh_trylock(cpu))
+#define softirq_endlock(cpu)	(cpu_bh_endlock(cpu))
+#define synchronize_bh()	barrier()
+
+/*
+ * These use a mask count to correctly handle
+ * nested disable/enable calls
+ */
+extern inline void disable_bh(int nr)
+{
+	bh_mask &= ~(1 << nr);
+	atomic_inc(&bh_mask_count[nr]);
+	synchronize_bh();
+}
+
+extern inline void enable_bh(int nr)
+{
+	if (atomic_dec_and_test(&bh_mask_count[nr]))
+		bh_mask |= 1 << nr;
+}
+
+#endif /* __ASM_SH_SOFTIRQ_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/spinlock.h linux/include/asm-sh/spinlock.h
--- v2.3.15/linux/include/asm-sh/spinlock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/spinlock.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,108 @@
+#ifndef __ASM_SH_SPINLOCK_H
+#define __ASM_SH_SPINLOCK_H
+
+/*
+ * These are the generic versions of the spinlocks
+ * and read-write locks.. We should actually do a
+ * <linux/spinlock.h> with all of this. Oh, well.
+ */
+#define spin_lock_irqsave(lock, flags)		do { local_irq_save(flags);       spin_lock(lock); } while (0)
+#define spin_lock_irq(lock)			do { local_irq_disable();         spin_lock(lock); } while (0)
+#define spin_lock_bh(lock)			do { local_bh_disable();          spin_lock(lock); } while (0)
+
+#define read_lock_irqsave(lock, flags)		do { local_irq_save(flags);       read_lock(lock); } while (0)
+#define read_lock_irq(lock)			do { local_irq_disable();         read_lock(lock); } while (0)
+#define read_lock_bh(lock)			do { local_bh_disable();          read_lock(lock); } while (0)
+
+#define write_lock_irqsave(lock, flags)		do { local_irq_save(flags);      write_lock(lock); } while (0)
+#define write_lock_irq(lock)			do { local_irq_disable();        write_lock(lock); } while (0)
+#define write_lock_bh(lock)			do { local_bh_disable();         write_lock(lock); } while (0)
+
+#define spin_unlock_irqrestore(lock, flags)	do { spin_unlock(lock);  local_irq_restore(flags); } while (0)
+#define spin_unlock_irq(lock)			do { spin_unlock(lock);  local_irq_enable();       } while (0)
+#define spin_unlock_bh(lock)			do { spin_unlock(lock);  local_bh_enable();        } while (0)
+
+#define read_unlock_irqrestore(lock, flags)	do { read_unlock(lock);  local_irq_restore(flags); } while (0)
+#define read_unlock_irq(lock)			do { read_unlock(lock);  local_irq_enable();       } while (0)
+#define read_unlock_bh(lock)			do { read_unlock(lock);  local_bh_enable();        } while (0)
+
+#define write_unlock_irqrestore(lock, flags)	do { write_unlock(lock); local_irq_restore(flags); } while (0)
+#define write_unlock_irq(lock)			do { write_unlock(lock); local_irq_enable();       } while (0)
+#define write_unlock_bh(lock)			do { write_unlock(lock); local_bh_enable();        } while (0)
+
+#ifndef __SMP__
+
+#define DEBUG_SPINLOCKS	0	/* 0 == no debugging, 1 == maintain lock state, 2 == full debug */
+
+#if (DEBUG_SPINLOCKS < 1)
+
+/*
+ * Your basic spinlocks, allowing only a single CPU anywhere
+ */
+typedef struct { } spinlock_t;
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { }
+
+#define spin_lock_init(lock)	do { } while(0)
+#define spin_lock(lock)		(void)(lock) /* Not "unused variable". */
+#define spin_trylock(lock)	(1)
+#define spin_unlock_wait(lock)	do { } while(0)
+#define spin_unlock(lock)	do { } while(0)
+
+#elif (DEBUG_SPINLOCKS < 2)
+
+typedef struct {
+	volatile unsigned int lock;
+} spinlock_t;
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
+
+#define spin_lock_init(x)	do { (x)->lock = 0; } while (0)
+#define spin_trylock(lock)	(!test_and_set_bit(0,(lock)))
+
+#define spin_lock(x)		do { (x)->lock = 1; } while (0)
+#define spin_unlock_wait(x)	do { } while (0)
+#define spin_unlock(x)		do { (x)->lock = 0; } while (0)
+
+#else /* (DEBUG_SPINLOCKS >= 2) */
+
+typedef struct {
+	volatile unsigned int lock;
+	volatile unsigned int babble;
+	const char *module;
+} spinlock_t;
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 25, __BASE_FILE__ }
+
+#include <linux/kernel.h>
+
+#define spin_lock_init(x)	do { (x)->lock = 0; } while (0)
+#define spin_trylock(lock)	(!test_and_set_bit(0,(lock)))
+
+#define spin_lock(x)		do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; restore_flags(__spinflags);} while (0)
+#define spin_unlock_wait(x)	do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_wait(%s:%p) deadlock\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} restore_flags(__spinflags);} while (0)
+#define spin_unlock(x)		do {unsigned long __spinflags; save_flags(__spinflags); cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(__spinflags);} while (0)
+
+#endif	/* DEBUG_SPINLOCKS */
+
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+typedef struct { } rwlock_t;
+#define RW_LOCK_UNLOCKED (rwlock_t) { }
+
+#define read_lock(lock)		(void)(lock) /* Not "unused variable". */
+#define read_unlock(lock)	do { } while(0)
+#define write_lock(lock)	(void)(lock) /* Not "unused variable". */
+#define write_unlock(lock)	do { } while(0)
+
+#else
+
+#error "No SMP on SH"
+
+#endif /* SMP */
+#endif /* __ASM_SH_SPINLOCK_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/stat.h linux/include/asm-sh/stat.h
--- v2.3.15/linux/include/asm-sh/stat.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/stat.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,41 @@
+#ifndef __ASM_SH_STAT_H
+#define __ASM_SH_STAT_H
+
+struct __old_kernel_stat {
+	unsigned short st_dev;
+	unsigned short st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned long  st_size;
+	unsigned long  st_atime;
+	unsigned long  st_mtime;
+	unsigned long  st_ctime;
+};
+
+struct stat {
+	unsigned short st_dev;
+	unsigned short __pad1;
+	unsigned long st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned short __pad2;
+	unsigned long  st_size;
+	unsigned long  st_blksize;
+	unsigned long  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  __unused4;
+	unsigned long  __unused5;
+};
+
+#endif /* __ASM_SH_STAT_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/statfs.h linux/include/asm-sh/statfs.h
--- v2.3.15/linux/include/asm-sh/statfs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/statfs.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,25 @@
+#ifndef __ASM_SH_STATFS_H
+#define __ASM_SH_STATFS_H
+
+#ifndef __KERNEL_STRICT_NAMES
+
+#include <linux/types.h>
+
+typedef __kernel_fsid_t	fsid_t;
+
+#endif
+
+struct statfs {
+	long f_type;
+	long f_bsize;
+	long f_blocks;
+	long f_bfree;
+	long f_bavail;
+	long f_files;
+	long f_ffree;
+	__kernel_fsid_t f_fsid;
+	long f_namelen;
+	long f_spare[6];
+};
+
+#endif /* __ASM_SH_STATFS_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/string.h linux/include/asm-sh/string.h
--- v2.3.15/linux/include/asm-sh/string.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/string.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,140 @@
+#ifndef __ASM_SH_STRING_H
+#define __ASM_SH_STRING_H
+
+/*
+ * Copyright (C) 1999 Niibe Yutaka
+ * But consider these trivial functions to be public domain.
+ */
+
+#define __HAVE_ARCH_STRCPY
+extern __inline__ char *strcpy(char *__dest, const char *__src)
+{
+	register char *__xdest = __dest;
+	unsigned long __dummy;
+
+	__asm__ __volatile__("1:\n\t"
+			     "mov.b	@%1+,%2\n\t"
+			     "mov.b	%2,@%0\n\t"
+			     "cmp/eq	#0,%2\n\t"
+			     "bf/s	1b\n\t"
+			     " add	#1,%0\n\t"
+			     :"=&r" (__dest), "=&r" (__src), "=&z" (__dummy)
+			     :"0" (__dest), "1" (__src)
+			     :"memory");
+
+	return __xdest;
+}
+
+#define __HAVE_ARCH_STRNCPY
+extern __inline__ char *strncpy(char *__dest, const char *__src, size_t __n)
+{
+	register char *__xdest = __dest;
+	unsigned long __dummy;
+
+	if (__n == 0)
+		return __xdest;
+
+	__asm__ __volatile__(
+		"1:\n"
+		"mov.b	@%1+,%2\n\t"
+		"mov.b  %2,@%0\n\t"
+		"cmp/eq #0,%2\n\t"
+		"bt/s   2f\n\t"
+		" cmp/eq %5,%1\n\t"
+		"bf/s   1b\n\t"
+		" add    #1,%0\n"
+		"2:"
+		: "=r" (__dest), "=r" (__src), "=&z" (__dummy)
+		: "0" (__dest), "1" (__src), "r" (__src+__n)
+		: "memory");
+
+	return __xdest;
+}
+
+#define __HAVE_ARCH_STRCMP
+extern __inline__ int strcmp(const char *__cs, const char *__ct)
+{
+	register int __res;
+	unsigned long __dummy;
+
+	__asm__ __volatile__(
+		"mov.b	@%1+,%3\n"
+		"1:\n\t"
+		"mov.b	@%0+,%2\n\t"
+		"cmp/eq #0,%3\n\t"
+		"bt	2f\n\t"
+		"cmp/eq %2,%3\n\t"
+		"bt/s	1b\n\t"
+		" mov.b	@%1+,%3\n\t"
+		"add	#-2,%1\n\t"
+		"mov.b	@%1,%3\n\t"
+		"sub	%3,%2\n"
+		"2:"
+		: "=r" (__cs), "=r" (__ct), "=&r" (__res), "=&z" (__dummy)
+		: "0" (__cs), "1" (__ct));
+
+	return __res;
+}
+
+#define __HAVE_ARCH_STRNCMP
+extern __inline__ int strncmp(const char *__cs, const char *__ct, size_t __n)
+{
+	register int __res;
+	unsigned long __dummy;
+
+	__asm__ __volatile__(
+		"mov.b	@%1+,%3\n"
+		"1:\n\t"
+		"mov.b	@%0+,%2\n\t"
+		"cmp/eq %6,%0\n\t"
+		"bt/s	2f\n\t"
+		" cmp/eq #0,%3\n\t"
+		"bt/s	3f\n\t"
+		" cmp/eq %3,%2\n\t"
+		"bt/s	1b\n\t"
+		" mov.b	@%1+,%3\n\t"
+		"add	#-2,%1\n\t"
+		"mov.b	@%1,%3\n"
+		"2:\n\t"
+		"sub	%3,%2\n"
+		"3:"
+		:"=r" (__cs), "=r" (__ct), "=&r" (__res), "=&z" (__dummy)
+		: "0" (__cs), "1" (__ct), "r" (__cs+__n));
+
+	return __res;
+}
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *__s, int __c, size_t __count);
+
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
+
+#define __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
+
+/* Don't build bcopy at all ...  */
+#define __HAVE_ARCH_BCOPY
+
+#define __HAVE_ARCH_MEMSCAN
+extern __inline__ void *memscan(void *__addr, int __c, size_t __size)
+{
+	register char *__end;
+	unsigned long __dummy;
+
+	__asm__("mov	#0,%2\n"
+		"1:\n\t"
+		"cmp/eq	%0,%1\n\t"
+		"bt	2f\n\t"
+		"cmp/eq	%5,%2\n\t"
+		"bf/s	1b\n\t"
+		" mov.b	@%0+,%2\n\t"
+		"add	#-1,%0\n\t"
+		"2:"
+		: "=r" (__addr), "=r" (__end), "=&z" (__dummy)
+		: "0" (__addr), "1" ((char *)__addr + __size), "r" (__c));
+
+	return __addr;
+}
+
+#endif /* __ASM_SH_STRING_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/system.h linux/include/asm-sh/system.h
--- v2.3.15/linux/include/asm-sh/system.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/system.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,185 @@
+#ifndef __ASM_SH_SYSTEM_H
+#define __ASM_SH_SYSTEM_H
+
+/*
+ * Copyright (C) 1999  Niibe Yutaka
+ */
+
+/*
+ *	switch_to() should switch tasks to task nr n, first
+ */
+
+typedef struct {
+	unsigned long seg;
+} mm_segment_t;
+
+#ifdef __SMP__
+#error no SMP SuperH
+#else
+#define prepare_to_switch()	do { } while(0)
+#define switch_to(prev,next,last) do { \
+ register struct task_struct *__last; \
+ register unsigned long *__ts1 __asm__ ("r1") = &prev->thread.sp; \
+ register unsigned long *__ts2 __asm__ ("r2") = &prev->thread.pc; \
+ register unsigned long *__ts4 __asm__ ("r4") = (unsigned long *)prev; \
+ register unsigned long *__ts5 __asm__ ("r5") = (unsigned long *)next; \
+ register unsigned long *__ts6 __asm__ ("r6") = &next->thread.sp; \
+ register unsigned long __ts7 __asm__ ("r7") = next->thread.pc; \
+ __asm__ __volatile__ (".balign 4\n\t" \
+		       "sts.l	pr,@-r15\n\t" \
+		       "mov.l	r8,@-r15\n\t" \
+		       "mov.l	r9,@-r15\n\t" \
+		       "mov.l	r10,@-r15\n\t" \
+		       "mov.l	r11,@-r15\n\t" \
+		       "mov.l	r12,@-r15\n\t" \
+		       "mov.l	r13,@-r15\n\t" \
+		       "mov.l	r14,@-r15\n\t" \
+		       "mov.l	r15,@r1		! save SP\n\t" \
+		       "mov.l	@r6,r15		! change to new stack\n\t" \
+		       "mov.l	%0,@-r15	! push R0 onto new stack\n\t" \
+		       "mova	1f,%0\n\t" \
+		       "mov.l	%0,@r2		! save PC\n\t" \
+		       "mov.l	2f,%0\n\t" \
+		       "jmp	@%0		! call __switch_to\n\t" \
+		       " lds	r7,pr		!  with return to new PC\n" \
+		       "2:\n" \
+		       ".long	" "_" "__switch_to\n\t" \
+		       ".balign	4\n"	\
+		       "1:\n" \
+		       "mov.l	@r15+,%0	! pop R0 from new stack\n\t" \
+		       "mov.l	@r15+,r14\n\t" \
+		       "mov.l	@r15+,r13\n\t" \
+		       "mov.l	@r15+,r12\n\t" \
+		       "mov.l	@r15+,r11\n\t" \
+		       "mov.l	@r15+,r10\n\t" \
+		       "mov.l	@r15+,r9\n\t" \
+		       "mov.l	@r15+,r8\n\t" \
+		       "lds.l	@r15+,pr\n\t" \
+		       :"=&z" (__last) \
+		       :"0" (prev), \
+			"r" (__ts1), "r" (__ts2), \
+			"r" (__ts4), "r" (__ts5), "r" (__ts6), "r" (__ts7) \
+		       :"r3"); \
+  last = __last; \
+} while (0)
+#endif
+
+#define nop() __asm__ __volatile__ ("nop")
+
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+static __inline__ unsigned long tas(volatile int *m)
+{ /* #define tas(ptr) (xchg((ptr),1)) */
+	unsigned long retval;
+
+	__asm__ __volatile__ ("tas.b	@%1\n\t"
+			      "movt	%0"
+			      : "=r" (retval): "r" (m): "t", "memory");
+	return retval;
+}
+
+extern void __xchg_called_with_bad_pointer(void);
+
+#define mb()	__asm__ __volatile__ ("": : :"memory")
+#define rmb()	mb()
+#define wmb()	__asm__ __volatile__ ("": : :"memory")
+
+/* Interrupt Control */
+extern __inline__ void __sti(void)
+{
+	unsigned long __dummy;
+
+	__asm__ __volatile__("stc	sr,%0\n\t"
+			     "and	%1,%0\n\t"
+			     "ldc	%0,sr"
+			     : "=&z" (__dummy)
+			     : "r" (0xefffffff)
+			     : "memory");
+}
+
+extern __inline__ void __cli(void)
+{
+	unsigned long __dummy;
+	__asm__ __volatile__("stc	sr,%0\n\t"
+			     "or	%1,%0\n\t"
+			     "ldc	%0,sr"
+			     : "=&z" (__dummy)
+			     : "r" (0x10000000)
+			     : "memory");
+}
+
+#define __save_flags(x) \
+__asm__ __volatile__("stc	sr,%0\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop":"=r" (x): /* no inputs */ :"memory")
+
+#define __save_and_cli(x)               \
+({	unsigned long __dummy;		\
+__asm__ __volatile__(                   \
+	"stc	sr,%0\n\t" \
+	"mov	%0,%1\n\t" \
+	"or	%2,%1\n\t" \
+	"ldc	%1,sr"     \
+	: "=&r" (x), "=&z" (__dummy) \
+	: "r" (0x10000000) \
+	: "memory"); })
+
+#define __restore_flags(x) \
+__asm__ __volatile__("ldc	%0,sr": /* no output */: "r" (x):"memory")
+
+/* For spinlocks etc */
+#define local_irq_save(x)	__save_and_cli(x)
+#define local_irq_restore(x)	__restore_flags(x)
+#define local_irq_disable()	__cli()
+#define local_irq_enable()	__sti()
+
+#ifdef __SMP__
+
+extern void __global_cli(void);
+extern void __global_sti(void);
+extern unsigned long __global_save_flags(void);
+extern void __global_restore_flags(unsigned long);
+#define cli() __global_cli()
+#define sti() __global_sti()
+#define save_flags(x) ((x)=__global_save_flags())
+#define restore_flags(x) __global_restore_flags(x)
+
+#else
+
+#define cli() __cli()
+#define sti() __sti()
+#define save_flags(x) __save_flags(x)
+#define save_and_cli(x) __save_and_cli(x)
+#define restore_flags(x) __restore_flags(x)
+
+#endif
+
+extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
+{
+	unsigned long flags, retval;
+
+	save_and_cli(flags);
+	retval = *m;
+	*m = val;
+	restore_flags(flags);
+	return retval;
+}
+
+static __inline__ unsigned long __xchg(unsigned long x, void * ptr, int size)
+{
+	switch (size) {
+	case 4:
+		return xchg_u32(ptr, x);
+		break;
+	}
+	__xchg_called_with_bad_pointer();
+	return x;
+}
+
+/* XXX
+ * disable hlt during certain critical i/o operations
+ */
+#define HAVE_DISABLE_HLT
+void disable_hlt(void);
+void enable_hlt(void);
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/termbits.h linux/include/asm-sh/termbits.h
--- v2.3.15/linux/include/asm-sh/termbits.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/termbits.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,161 @@
+#ifndef __ASM_SH_TERMBITS_H
+#define __ASM_SH_TERMBITS_H
+
+#include <linux/posix_types.h>
+
+typedef unsigned char	cc_t;
+typedef unsigned int	speed_t;
+typedef unsigned int	tcflag_t;
+
+#define NCCS 19
+struct termios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+#define IGNBRK	0000001
+#define BRKINT	0000002
+#define IGNPAR	0000004
+#define PARMRK	0000010
+#define INPCK	0000020
+#define ISTRIP	0000040
+#define INLCR	0000100
+#define IGNCR	0000200
+#define ICRNL	0000400
+#define IUCLC	0001000
+#define IXON	0002000
+#define IXANY	0004000
+#define IXOFF	0010000
+#define IMAXBEL	0020000
+
+/* c_oflag bits */
+#define OPOST	0000001
+#define OLCUC	0000002
+#define ONLCR	0000004
+#define OCRNL	0000010
+#define ONOCR	0000020
+#define ONLRET	0000040
+#define OFILL	0000100
+#define OFDEL	0000200
+#define NLDLY	0000400
+#define   NL0	0000000
+#define   NL1	0000400
+#define CRDLY	0003000
+#define   CR0	0000000
+#define   CR1	0001000
+#define   CR2	0002000
+#define   CR3	0003000
+#define TABDLY	0014000
+#define   TAB0	0000000
+#define   TAB1	0004000
+#define   TAB2	0010000
+#define   TAB3	0014000
+#define   XTABS	0014000
+#define BSDLY	0020000
+#define   BS0	0000000
+#define   BS1	0020000
+#define VTDLY	0040000
+#define   VT0	0000000
+#define   VT1	0040000
+#define FFDLY	0100000
+#define   FF0	0000000
+#define   FF1	0100000
+
+/* c_cflag bit meaning */
+#define CBAUD	0010017
+#define  B0	0000000		/* hang up */
+#define  B50	0000001
+#define  B75	0000002
+#define  B110	0000003
+#define  B134	0000004
+#define  B150	0000005
+#define  B200	0000006
+#define  B300	0000007
+#define  B600	0000010
+#define  B1200	0000011
+#define  B1800	0000012
+#define  B2400	0000013
+#define  B4800	0000014
+#define  B9600	0000015
+#define  B19200	0000016
+#define  B38400	0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE	0000060
+#define   CS5	0000000
+#define   CS6	0000020
+#define   CS7	0000040
+#define   CS8	0000060
+#define CSTOPB	0000100
+#define CREAD	0000200
+#define PARENB	0000400
+#define PARODD	0001000
+#define HUPCL	0002000
+#define CLOCAL	0004000
+#define CBAUDEX 0010000
+#define  B57600  0010001
+#define  B115200 0010002
+#define  B230400 0010003
+#define  B460800 0010004
+#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CMSPAR	  010000000000		/* mark or space (stick) parity */
+#define CRTSCTS	  020000000000		/* flow control */
+
+/* c_lflag bits */
+#define ISIG	0000001
+#define ICANON	0000002
+#define XCASE	0000004
+#define ECHO	0000010
+#define ECHOE	0000020
+#define ECHOK	0000040
+#define ECHONL	0000100
+#define NOFLSH	0000200
+#define TOSTOP	0000400
+#define ECHOCTL	0001000
+#define ECHOPRT	0002000
+#define ECHOKE	0004000
+#define FLUSHO	0010000
+#define PENDIN	0040000
+#define IEXTEN	0100000
+
+/* tcflow() and TCXONC use these */
+#define	TCOOFF		0
+#define	TCOON		1
+#define	TCIOFF		2
+#define	TCION		3
+
+/* tcflush() and TCFLSH use these */
+#define	TCIFLUSH	0
+#define	TCOFLUSH	1
+#define	TCIOFLUSH	2
+
+/* tcsetattr uses these */
+#define	TCSANOW		0
+#define	TCSADRAIN	1
+#define	TCSAFLUSH	2
+
+#endif /* __ASM_SH_TERMBITS_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/termios.h linux/include/asm-sh/termios.h
--- v2.3.15/linux/include/asm-sh/termios.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/termios.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,98 @@
+#ifndef __ASM_SH_TERMIOS_H
+#define __ASM_SH_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+	unsigned short ws_row;
+	unsigned short ws_col;
+	unsigned short ws_xpixel;
+	unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+	unsigned short c_iflag;		/* input mode flags */
+	unsigned short c_oflag;		/* output mode flags */
+	unsigned short c_cflag;		/* control mode flags */
+	unsigned short c_lflag;		/* local mode flags */
+	unsigned char c_line;		/* line discipline */
+	unsigned char c_cc[NCC];	/* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE	0x001
+#define TIOCM_DTR	0x002
+#define TIOCM_RTS	0x004
+#define TIOCM_ST	0x008
+#define TIOCM_SR	0x010
+#define TIOCM_CTS	0x020
+#define TIOCM_CAR	0x040
+#define TIOCM_RNG	0x080
+#define TIOCM_DSR	0x100
+#define TIOCM_CD	TIOCM_CAR
+#define TIOCM_RI	TIOCM_RNG
+#define TIOCM_OUT1	0x2000
+#define TIOCM_OUT2	0x4000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+/* line disciplines */
+#define N_TTY		0
+#define N_SLIP		1
+#define N_MOUSE		2
+#define N_PPP		3
+#define N_STRIP		4
+#define N_AX25		5
+#define N_X25		6	/* X.25 async */
+#define N_6PACK		7
+#define N_MASC		8	/* Reserved fo Mobitex module <kaz@cafe.net> */
+
+#ifdef __KERNEL__
+
+/*	intr=^C		quit=^\		erase=del	kill=^U
+	eof=^D		vtime=\0	vmin=\1		sxtc=\0
+	start=^Q	stop=^S		susp=^Z		eol=\0
+	reprint=^R	discard=^U	werase=^W	lnext=^V
+	eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
+	unsigned short __tmp; \
+	get_user(__tmp,&(termio)->x); \
+	*(unsigned short *) &(termios)->x = __tmp; \
+}
+
+#define user_termio_to_kernel_termios(termios, termio) \
+({ \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
+	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+})
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+#define kernel_termios_to_user_termio(termio, termios) \
+({ \
+	put_user((termios)->c_iflag, &(termio)->c_iflag); \
+	put_user((termios)->c_oflag, &(termio)->c_oflag); \
+	put_user((termios)->c_cflag, &(termio)->c_cflag); \
+	put_user((termios)->c_lflag, &(termio)->c_lflag); \
+	put_user((termios)->c_line,  &(termio)->c_line); \
+	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+})
+
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+
+#endif	/* __KERNEL__ */
+
+#endif	/* __ASM_SH_TERMIOS_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/timex.h linux/include/asm-sh/timex.h
--- v2.3.15/linux/include/asm-sh/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/timex.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-sh/timex.h
+ *
+ * sh architecture timex specifications
+ */
+#ifndef __ASM_SH_TIMEX_H
+#define __ASM_SH_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)
+
+typedef unsigned long cycles_t;
+
+extern cycles_t cacheflush_time;
+
+static __inline__ cycles_t get_cycles (void)
+{
+	return 0;
+}
+
+#endif /* __ASM_SH_TIMEX_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/types.h linux/include/asm-sh/types.h
--- v2.3.15/linux/include/asm-sh/types.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/types.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,46 @@
+#ifndef __ASM_SH_TYPES_H
+#define __ASM_SH_TYPES_H
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH_TYPES_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/uaccess.h linux/include/asm-sh/uaccess.h
--- v2.3.15/linux/include/asm-sh/uaccess.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/uaccess.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,439 @@
+/*
+ * User space memory access functions
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ *
+ *  Based on:
+ *     MIPS implementation version 1.15 by
+ *              Copyright (C) 1996, 1997, 1998 by Ralf Baechle
+ *     and i386 version.
+ */
+#ifndef __ASM_SH_UACCESS_H
+#define __ASM_SH_UACCESS_H
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+
+#define VERIFY_READ    0
+#define VERIFY_WRITE   1
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons (Data Segment Register?), these macros are misnamed.
+ */
+
+#define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
+
+#define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
+#define USER_DS		MAKE_MM_SEG(0x80000000)
+
+#define get_ds()	(KERNEL_DS)
+#define get_fs()        (current->addr_limit)
+#define set_fs(x)       (current->addr_limit=(x))
+
+#define segment_eq(a,b)	((a).seg == (b).seg)
+
+#define __addr_ok(addr) ((unsigned long)(addr) < (current->addr_limit.seg))
+
+/*
+ * Uhhuh, this needs 33-bit arithmetic. We have a carry..
+ *
+ * sum := addr + size;  carry? --> flag = true;
+ * if (sum >= addr_limit) flag = true;
+ */
+#define __range_ok(addr,size) ({ \
+	unsigned long flag,sum; \
+	__asm__("clrt; addc %3,%1; movt %0; cmp/hi %4,%1; rotcl %0" \
+		:"=&r" (flag), "=r" (sum) \
+		:"1" (addr), "r" (size), "r" (current->addr_limit.seg)); \
+	flag; })
+
+#define access_ok(type,addr,size) (__range_ok(addr,size) == 0)
+#define __access_ok(addr,size) (__range_ok(addr,size) == 0)
+
+extern inline int verify_area(int type, const void * addr, unsigned long size)
+{
+	return access_ok(type,addr,size) ? 0 : -EFAULT;
+}
+
+/*
+ * Uh, these should become the main single-value transfer routines ...
+ * They automatically use the right size if we just have the right
+ * pointer type ...
+ *
+ * As MIPS uses the same address space for kernel and user data, we
+ * can just do these as direct assignments.
+ *
+ * Careful to not
+ * (a) re-use the arguments for side effects (sizeof is ok)
+ * (b) require any knowledge of processes at this stage
+ */
+#define put_user(x,ptr)	__put_user_check((x),(ptr),sizeof(*(ptr)))
+#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)))
+
+/*
+ * The "__xxx" versions do not do address space checking, useful when
+ * doing multiple accesses to the same area (the user has to do the
+ * checks by hand with "access_ok()")
+ */
+#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+
+/*
+ * The "xxx_ret" versions return constant specified in third argument, if
+ * something bad happens. These macros can be optimized for the
+ * case of just returning from the function xxx_ret is used.
+ */
+
+#define put_user_ret(x,ptr,ret) ({ \
+if (put_user(x,ptr)) return ret; })
+
+#define get_user_ret(x,ptr,ret) ({ \
+if (get_user(x,ptr)) return ret; })
+
+#define __put_user_ret(x,ptr,ret) ({ \
+if (__put_user(x,ptr)) return ret; })
+
+#define __get_user_ret(x,ptr,ret) ({ \
+if (__get_user(x,ptr)) return ret; })
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct *)(x))
+
+#define __get_user_nocheck(x,ptr,size) ({ \
+long __gu_err; \
+__typeof(*(ptr)) __gu_val; \
+long __gu_addr; \
+__asm__("":"=r" (__gu_val)); \
+__gu_addr = (long) (ptr); \
+__asm__("":"=r" (__gu_err)); \
+switch (size) { \
+case 1: __get_user_asm("b"); break; \
+case 2: __get_user_asm("w"); break; \
+case 4: __get_user_asm("l"); break; \
+default: __get_user_unknown(); break; \
+} x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
+
+#define __get_user_check(x,ptr,size) ({ \
+long __gu_err; \
+__typeof__(*(ptr)) __gu_val; \
+long __gu_addr; \
+__asm__("":"=r" (__gu_val)); \
+__gu_addr = (long) (ptr); \
+__asm__("":"=r" (__gu_err)); \
+if (__access_ok(__gu_addr,size)) { \
+switch (size) { \
+case 1: __get_user_asm("b"); break; \
+case 2: __get_user_asm("w"); break; \
+case 4: __get_user_asm("l"); break; \
+default: __get_user_unknown(); break; \
+} } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
+
+#define __get_user_asm(insn) \
+({ \
+__asm__ __volatile__( \
+	"1:\n\t" \
+	"mov." insn "	%2,%1\n\t" \
+	"mov	#0,%0\n" \
+	"2:\n\t" \
+	".section	.fixup,\"ax\"\n" \
+	"3:\n\t" \
+	"mov	#0,%1\n\t" \
+	"mov.l	4f,%0\n\t" \
+	"jmp	@%0\n\t" \
+	" mov	%3,%0\n" \
+	"4:	.long	2b\n\t" \
+	".previous\n\t" \
+	".section	__ex_table,\"a\"\n\t" \
+	".long	1b, 3b\n\t" \
+	".previous" \
+	:"=&r" (__gu_err), "=&r" (__gu_val) \
+	:"m" (__m(__gu_addr)), "i" (-EFAULT)); })
+
+extern void __get_user_unknown(void);
+
+#define __put_user_nocheck(x,ptr,size) ({ \
+long __pu_err; \
+__typeof__(*(ptr)) __pu_val; \
+long __pu_addr; \
+__pu_val = (x); \
+__pu_addr = (long) (ptr); \
+__asm__("":"=r" (__pu_err)); \
+switch (size) { \
+case 1: __put_user_asm("b"); break; \
+case 2: __put_user_asm("w"); break; \
+case 4: __put_user_asm("l"); break; \
+default: __put_user_unknown(); break; \
+} __pu_err; })
+
+#define __put_user_check(x,ptr,size) ({ \
+long __pu_err; \
+__typeof__(*(ptr)) __pu_val; \
+long __pu_addr; \
+__pu_val = (x); \
+__pu_addr = (long) (ptr); \
+__asm__("":"=r" (__pu_err)); \
+if (__access_ok(__pu_addr,size)) { \
+switch (size) { \
+case 1: __put_user_asm("b"); break; \
+case 2: __put_user_asm("w"); break; \
+case 4: __put_user_asm("l"); break; \
+default: __put_user_unknown(); break; \
+} } __pu_err; })
+
+#define __put_user_asm(insn) \
+({ \
+__asm__ __volatile__( \
+	"1:\n\t" \
+	"mov." insn "	%1,%2\n\t" \
+	"mov	#0,%0\n" \
+	"2:\n\t" \
+	".section	.fixup,\"ax\"\n" \
+	"3:\n\t" \
+	"nop\n\t" \
+	"mov.l	4f,%0\n\t" \
+	"jmp	@%0\n\t" \
+	"mov	%3,%0\n" \
+	"4:	.long	2b\n\t" \
+	".previous\n\t" \
+	".section	__ex_table,\"a\"\n\t" \
+	".long	1b, 3b\n\t" \
+	".previous" \
+	:"=&r" (__pu_err) \
+	:"r" (__pu_val), "m" (__m(__pu_addr)), "i" (-EFAULT)); })
+
+extern void __put_user_unknown(void);
+
+/* Generic arbitrary sized copy.  */
+/* XXX: should be such that: 4byte and the rest. */
+extern __inline__ __kernel_size_t
+__copy_user(void *__to, const void *__from, __kernel_size_t __n)
+{
+	unsigned long __dummy, _f, _t;
+	__kernel_size_t res;
+
+	__asm__ __volatile__(
+		"9:\n\t"
+		"mov.b	@%2+,%1\n\t"
+		"dt	%0\n"
+		"1:\n\t"
+		"mov.b	%1,@%3\n\t"
+		"bf/s	9b\n\t"
+		" add	#1,%3\n"
+		"2:"
+		".section .fixup,\"ax\"\n"
+		"3:\n\t"
+		"mov.l	5f,%1\n\t"
+		"jmp	@%1\n\t"
+		" mov	%7,%0\n\t"
+		".align 4\n"
+		"5:	.long 2b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.align 4\n"
+		"	.long 9b,3b\n"
+		"	.long 1b,2b\n"
+		".previous"
+		: "=&r" (res), "=&z" (__dummy), "=&r" (_f), "=&r" (_t)
+		: "2" (__from), "3" (__to), "0" (__n), "i" (-EFAULT)
+		: "memory");
+
+	return res;
+}
+
+#define copy_to_user(to,from,n) ({ \
+void *__copy_to = (void *) (to); \
+__kernel_size_t __copy_size = (__kernel_size_t) (n); \
+__kernel_size_t __copy_res; \
+if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { \
+__copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \
+} else __copy_res = __copy_size; \
+__copy_res; })
+
+#define copy_to_user_ret(to,from,n,retval) ({ \
+if (copy_to_user(to,from,n)) \
+	return retval; \
+})
+
+#define __copy_to_user(to,from,n)		\
+	__copy_user((void *)(to),		\
+		    (void *)(from), n)
+
+#define __copy_to_user_ret(to,from,n,retval) ({ \
+if (__copy_to_user(to,from,n)) \
+	return retval; \
+})
+
+#define copy_from_user(to,from,n) ({ \
+void *__copy_to = (void *) (to); \
+void *__copy_from = (void *) (from); \
+__kernel_size_t __copy_size = (__kernel_size_t) (n); \
+__kernel_size_t __copy_res; \
+if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \
+__copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \
+} else __copy_res = __copy_size; \
+__copy_res; })
+
+#define copy_from_user_ret(to,from,n,retval) ({ \
+if (copy_from_user(to,from,n)) \
+	return retval; \
+})
+
+#define __copy_from_user(to,from,n)		\
+	__copy_user((void *)(to),		\
+		    (void *)(from), n)
+
+#define __copy_from_user_ret(to,from,n,retval) ({ \
+if (__copy_from_user(to,from,n)) \
+	return retval; \
+})
+
+/* XXX: Not sure it works well..
+   should be such that: 4byte clear and the rest. */
+extern __inline__ __kernel_size_t
+__clear_user(void *addr, __kernel_size_t size)
+{
+	__kernel_size_t res;
+	unsigned long __a, __s;
+
+	__asm__ __volatile__(
+		"9:\n\t"
+		"dt	%2\n"
+		"1:\n\t"
+		"mov.b	%5,@%1\n\t"
+		"bf/s	9b\n\t"
+		" add	#1,%1\n\t"
+		"sub	%2,%0\n"
+		"2:\n"
+		".section .fixup,\"ax\"\n"
+		"3:\n\t"
+		"mov.l	4f,%0\n\t"
+		"jmp	@%0\n\t"
+		" mov	%7,%0\n"
+		".align 4\n"
+		"4:	.long 2b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.align 4\n"
+		"	.long 1b,3b\n"
+		".previous"
+		: "=&r" (res), "=&r" (__a), "=&r" (__s)
+		: "1" (addr), "2" (size), "r" (0), "0" (size), "i" (-EFAULT));
+
+	return res;
+}
+
+#define clear_user(addr,n) ({ \
+void * __cl_addr = (addr); \
+unsigned long __cl_size = (n); \
+if (__cl_size && __access_ok(((unsigned long)(__cl_addr)), __cl_size)) \
+__cl_size = __clear_user(__cl_addr, __cl_size); \
+__cl_size; })
+
+extern __inline__ int
+__strncpy_from_user(unsigned long __dest, unsigned long __src, int __count)
+{
+	__kernel_size_t res;
+	unsigned long __dummy, _d, _s;
+
+	__asm__ __volatile__(
+		"9:\n"
+		"mov.b	@%2+,%1\n\t"
+		"cmp/eq	#0,%1\n\t"
+		"bt/s	2f\n"
+		"1:\n"
+		"mov.b	%1,@%3\n\t"
+		"dt	%0\n\t"
+		"bf/s	9b\n\t"
+		" add	#1,%3\n\t"
+		"sub	%6,%0\n"
+		"2:\n"
+		".section .fixup,\"ax\"\n"
+		"3:\n\t"
+		"mov.l	4f,%1\n\t"
+		"jmp	@%1\n\t"
+		" mov	%8,%0\n\t"
+		".align 4\n"
+		"4:	.long 2b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.align 4\n"
+		"	.long 9b,3b\n"
+		"	.long 1b,2b\n"
+		".previous"
+		: "=&r" (res), "=&z" (__dummy), "=&r" (_s), "=&r" (_d)
+		: "2" (__src), "3" (__dest), "r" (__count), "0" (__count),
+		  "i" (-EFAULT)
+		: "memory");
+
+	return res;
+}
+
+#define strncpy_from_user(dest,src,count) ({ \
+unsigned long __sfu_src = (unsigned long) (src); \
+int __sfu_count = (int) (count); \
+long __sfu_res = -EFAULT; \
+if(__access_ok(__sfu_src, __sfu_count)) { \
+__sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \
+} __sfu_res; })
+
+/*
+ * Return the size of a string (including the ending 0!)
+ */
+extern __inline__ long __strlen_user(const char *__s)
+{
+	unsigned long res;
+	unsigned long __dummy;
+
+	__asm__ __volatile__(
+		"mov	#-1,%1\n"
+		"9:\n"
+		"cmp/eq	#0,%1\n\t"
+		"bf/s	9b\n\t"
+		"1:\t"
+		" mov.b	@%0+,%1\n\t"
+		"sub	%3,%0\n"
+		"2:\n"
+		".section .fixup,\"ax\"\n"
+		"3:\n\t"
+		"mov.l	4f,%1\n\t"
+		"jmp	@%1\n\t"
+		" mov	%4,%0\n"
+		".align 4\n"
+		"4:	.long 2b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		"	.align 4\n"
+		"	.long 1b,3b\n"
+		".previous"
+		: "=&r" (res), "=&z" (__dummy)
+		: "0" (__s), "r" (__s), "i" (-EFAULT));
+	return res;
+}
+
+extern __inline__ long strlen_user(const char *s)
+{
+	if(!access_ok(VERIFY_READ, s, 0))
+		return 0;
+	else
+		return __strlen_user(s);
+}
+
+struct exception_table_entry
+{
+	unsigned long insn, fixup;
+};
+
+/* Returns 0 if exception not found and fixup.unit otherwise.  */
+extern unsigned long search_exception_table(unsigned long addr);
+
+/* Returns the new pc */
+#define fixup_exception(map_reg, fixup_unit, pc)                \
+({                                                              \
+	fixup_unit;                                             \
+})
+
+#endif /* __ASM_SH_UACCESS_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/ucontext.h linux/include/asm-sh/ucontext.h
--- v2.3.15/linux/include/asm-sh/ucontext.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/ucontext.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,12 @@
+#ifndef __ASM_SH_UCONTEXT_H
+#define __ASM_SH_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_SH_UCONTEXT_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/unaligned.h linux/include/asm-sh/unaligned.h
--- v2.3.15/linux/include/asm-sh/unaligned.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/unaligned.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,19 @@
+#ifndef __ASM_SH_UNALIGNED_H
+#define __ASM_SH_UNALIGNED_H
+
+/* SH can't handle unaligned accesses. */
+
+#include <linux/string.h>
+
+
+/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
+
+#define get_unaligned(ptr) \
+  ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+
+#define put_unaligned(val, ptr)				\
+  ({ __typeof__(*(ptr)) __tmp = (val);			\
+     memmove((ptr), &__tmp, sizeof(*(ptr)));		\
+     (void)0; })
+
+#endif /* __ASM_SH_UNALIGNED_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/unistd.h linux/include/asm-sh/unistd.h
--- v2.3.15/linux/include/asm-sh/unistd.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/unistd.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,316 @@
+#ifndef __ASM_SH_UNISTD_H
+#define __ASM_SH_UNISTD_H
+
+/*
+ * Copyright (C) 1999  Niibe Yutaka
+ */
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_setup		  0	/* used only by init, to get system going */
+#define __NR_exit		  1
+#define __NR_fork		  2
+#define __NR_read		  3
+#define __NR_write		  4
+#define __NR_open		  5
+#define __NR_close		  6
+#define __NR_waitpid		  7
+#define __NR_creat		  8
+#define __NR_link		  9
+#define __NR_unlink		 10
+#define __NR_execve		 11
+#define __NR_chdir		 12
+#define __NR_time		 13
+#define __NR_mknod		 14
+#define __NR_chmod		 15
+#define __NR_lchown		 16
+#define __NR_break		 17
+#define __NR_oldstat		 18
+#define __NR_lseek		 19
+#define __NR_getpid		 20
+#define __NR_mount		 21
+#define __NR_oldumount		 22
+#define __NR_setuid		 23
+#define __NR_getuid		 24
+#define __NR_stime		 25
+#define __NR_ptrace		 26
+#define __NR_alarm		 27
+#define __NR_oldfstat		 28
+#define __NR_pause		 29
+#define __NR_utime		 30
+#define __NR_stty		 31
+#define __NR_gtty		 32
+#define __NR_access		 33
+#define __NR_nice		 34
+#define __NR_ftime		 35
+#define __NR_sync		 36
+#define __NR_kill		 37
+#define __NR_rename		 38
+#define __NR_mkdir		 39
+#define __NR_rmdir		 40
+#define __NR_dup		 41
+#define __NR_pipe		 42
+#define __NR_times		 43
+#define __NR_prof		 44
+#define __NR_brk		 45
+#define __NR_setgid		 46
+#define __NR_getgid		 47
+#define __NR_signal		 48
+#define __NR_geteuid		 49
+#define __NR_getegid		 50
+#define __NR_acct		 51
+#define __NR_umount		 52
+#define __NR_lock		 53
+#define __NR_ioctl		 54
+#define __NR_fcntl		 55
+#define __NR_mpx		 56
+#define __NR_setpgid		 57
+#define __NR_ulimit		 58
+#define __NR_oldolduname	 59
+#define __NR_umask		 60
+#define __NR_chroot		 61
+#define __NR_ustat		 62
+#define __NR_dup2		 63
+#define __NR_getppid		 64
+#define __NR_getpgrp		 65
+#define __NR_setsid		 66
+#define __NR_sigaction		 67
+#define __NR_sgetmask		 68
+#define __NR_ssetmask		 69
+#define __NR_setreuid		 70
+#define __NR_setregid		 71
+#define __NR_sigsuspend		 72
+#define __NR_sigpending		 73
+#define __NR_sethostname	 74
+#define __NR_setrlimit		 75
+#define __NR_getrlimit		 76
+#define __NR_getrusage		 77
+#define __NR_gettimeofday	 78
+#define __NR_settimeofday	 79
+#define __NR_getgroups		 80
+#define __NR_setgroups		 81
+#define __NR_select		 82
+#define __NR_symlink		 83
+#define __NR_oldlstat		 84
+#define __NR_readlink		 85
+#define __NR_uselib		 86
+#define __NR_swapon		 87
+#define __NR_reboot		 88
+#define __NR_readdir		 89
+#define __NR_mmap		 90
+#define __NR_munmap		 91
+#define __NR_truncate		 92
+#define __NR_ftruncate		 93
+#define __NR_fchmod		 94
+#define __NR_fchown		 95
+#define __NR_getpriority	 96
+#define __NR_setpriority	 97
+#define __NR_profil		 98
+#define __NR_statfs		 99
+#define __NR_fstatfs		100
+#define __NR_ioperm		101
+#define __NR_socketcall		102
+#define __NR_syslog		103
+#define __NR_setitimer		104
+#define __NR_getitimer		105
+#define __NR_stat		106
+#define __NR_lstat		107
+#define __NR_fstat		108
+#define __NR_olduname		109
+#define __NR_iopl		110
+#define __NR_vhangup		111
+#define __NR_idle		112
+#define __NR_vm86old		113
+#define __NR_wait4		114
+#define __NR_swapoff		115
+#define __NR_sysinfo		116
+#define __NR_ipc		117
+#define __NR_fsync		118
+#define __NR_sigreturn		119
+#define __NR_clone		120
+#define __NR_setdomainname	121
+#define __NR_uname		122
+#define __NR_modify_ldt		123
+#define __NR_adjtimex		124
+#define __NR_mprotect		125
+#define __NR_sigprocmask	126
+#define __NR_create_module	127
+#define __NR_init_module	128
+#define __NR_delete_module	129
+#define __NR_get_kernel_syms	130
+#define __NR_quotactl		131
+#define __NR_getpgid		132
+#define __NR_fchdir		133
+#define __NR_bdflush		134
+#define __NR_sysfs		135
+#define __NR_personality	136
+#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
+#define __NR_setfsuid		138
+#define __NR_setfsgid		139
+#define __NR__llseek		140
+#define __NR_getdents		141
+#define __NR__newselect		142
+#define __NR_flock		143
+#define __NR_msync		144
+#define __NR_readv		145
+#define __NR_writev		146
+#define __NR_getsid		147
+#define __NR_fdatasync		148
+#define __NR__sysctl		149
+#define __NR_mlock		150
+#define __NR_munlock		151
+#define __NR_mlockall		152
+#define __NR_munlockall		153
+#define __NR_sched_setparam		154
+#define __NR_sched_getparam		155
+#define __NR_sched_setscheduler		156
+#define __NR_sched_getscheduler		157
+#define __NR_sched_yield		158
+#define __NR_sched_get_priority_max	159
+#define __NR_sched_get_priority_min	160
+#define __NR_sched_rr_get_interval	161
+#define __NR_nanosleep		162
+#define __NR_mremap		163
+#define __NR_setresuid		164
+#define __NR_getresuid		165
+#define __NR_vm86		166
+#define __NR_query_module	167
+#define __NR_poll		168
+#define __NR_nfsservctl		169
+#define __NR_setresgid		170
+#define __NR_getresgid		171
+#define __NR_prctl              172
+#define __NR_rt_sigreturn	173
+#define __NR_rt_sigaction	174
+#define __NR_rt_sigprocmask	175
+#define __NR_rt_sigpending	176
+#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_capget		184
+#define __NR_capset		185
+#define __NR_sigaltstack	186
+#define __NR_sendfile		187
+#define __NR_streams1		188	/* some people actually want it */
+#define __NR_streams2		189	/* some people actually want it */
+#define __NR_vfork		190
+
+/* user-visible error numbers are in the range -1 - -125: see <asm-sh/errno.h> */
+
+#define __syscall_return(type, res) \
+do { \
+	if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+	/* Avoid using "res" which is declared to be in register r0; \
+	   errno might expand to a function call and clobber it.  */ \
+		int __err = -(res); \
+		errno = __err; \
+		res = -1; \
+	} \
+	return (type) (res); \
+} while (0)
+
+/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
+#define _syscall0(type,name) \
+type name(void) \
+{ \
+register long __sc0 __asm__ ("r0") = __NR_##name; \
+__asm__ __volatile__ ("trapa	#0" \
+	: "=z" (__sc0) \
+	: "0" (__sc0)); \
+__syscall_return(type,__sc0); \
+}
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) \
+{ \
+register long __sc0 __asm__ ("r0") = __NR_##name; \
+register long __sc4 __asm__ ("r4") = (long) arg1; \
+__asm__ __volatile__ ("trapa	#0" \
+	: "=z" (__sc0) \
+	: "0" (__sc0), "r" (__sc4)); \
+__syscall_return(type,__sc0); \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1,type2 arg2) \
+{ \
+register long __sc0 __asm__ ("r0") = __NR_##name; \
+register long __sc4 __asm__ ("r4") = (long) arg1; \
+register long __sc5 __asm__ ("r5") = (long) arg2; \
+__asm__ __volatile__ ("trapa	#0" \
+	: "=z" (__sc0) \
+	: "0" (__sc0), "r" (__sc4), "r" (__sc5)); \
+__syscall_return(type,__sc0); \
+}
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1,type2 arg2,type3 arg3) \
+{ \
+register long __sc0 __asm__ ("r0") = __NR_##name; \
+register long __sc4 __asm__ ("r4") = (long) arg1; \
+register long __sc5 __asm__ ("r5") = (long) arg2; \
+register long __sc6 __asm__ ("r6") = (long) arg3; \
+__asm__ __volatile__ ("trapa	#0" \
+	: "=z" (__sc0) \
+	: "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6)); \
+__syscall_return(type,__sc0); \
+}
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+{ \
+register long __sc0 __asm__ ("r0") = __NR_##name; \
+register long __sc4 __asm__ ("r4") = (long) arg1; \
+register long __sc5 __asm__ ("r5") = (long) arg2; \
+register long __sc6 __asm__ ("r6") = (long) arg3; \
+register long __sc6 __asm__ ("r7") = (long) arg4; \
+__asm__ __volatile__ ("trapa	#0" \
+	: "=z" (__sc0) \
+	: "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6),  \
+	  "r" (__sc7)); \
+__syscall_return(type,__sc0); \
+}
+
+#ifdef __KERNEL_SYSCALLS__
+
+/*
+ * we need this inline - forking from kernel space will result
+ * in NO COPY ON WRITE (!!!), until an execve is executed. This
+ * is no problem, but for the stack. This is handled by not letting
+ * main() use the stack at all after fork(). Thus, no function
+ * calls - which means inline code for fork too, as otherwise we
+ * would use the stack upon exit from 'fork()'.
+ *
+ * Actually only pause and fork are needed inline, so that there
+ * won't be any messing with the stack from main(), but we define
+ * some others too.
+ */
+#define __NR__exit __NR_exit
+static __inline__ _syscall0(int,pause)
+static __inline__ _syscall1(int,setup,int,magic)
+static __inline__ _syscall0(int,sync)
+static __inline__ _syscall0(pid_t,setsid)
+static __inline__ _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+static __inline__ _syscall3(int,read,int,fd,char *,buf,off_t,count)
+static __inline__ _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
+static __inline__ _syscall1(int,dup,int,fd)
+static __inline__ _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+static __inline__ _syscall3(int,open,const char *,file,int,flag,int,mode)
+static __inline__ _syscall1(int,close,int,fd)
+static __inline__ _syscall1(int,_exit,int,exitcode)
+static __inline__ _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
+static __inline__ _syscall1(int,delete_module,const char *,name)
+
+static __inline__ pid_t wait(int * wait_stat)
+{
+	return waitpid(-1,wait_stat,0);
+}
+#endif
+
+#endif /* __ASM_SH_UNISTD_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sh/user.h linux/include/asm-sh/user.h
--- v2.3.15/linux/include/asm-sh/user.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/user.h	Mon Aug 30 18:12:59 1999
@@ -0,0 +1,50 @@
+#ifndef __ASM_SH_USER_H
+#define __ASM_SH_USER_H
+
+#include <linux/types.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+
+/*
+ * Core file format: The core file is written in such a way that gdb
+ * can understand it and provide useful information to the user (under
+ * linux we use the `trad-core' bfd).  The file contents are as follows:
+ *
+ *  upage: 1 page consisting of a user struct that tells gdb
+ *	what is present in the file.  Directly after this is a
+ *	copy of the task_struct, which is currently not used by gdb,
+ *	but it may come in handy at some point.  All of the registers
+ *	are stored as part of the upage.  The upage should always be
+ *	only one page long.
+ *  data: The data segment follows next.  We use current->end_text to
+ *	current->brk to pick up all of the user variables, plus any memory
+ *	that may have been sbrk'ed.  No attempt is made to determine if a
+ *	page is demand-zero or if a page is totally unused, we just cover
+ *	the entire range.  All of the addresses are rounded in such a way
+ *	that an integral number of pages is written.
+ *  stack: We need the stack information in order to get a meaningful
+ *	backtrace.  We need to write the data from usp to
+ *	current->start_stack, so we round each of these in order to be able
+ *	to write an integer number of pages.
+ */
+struct user {
+	struct pt_regs	regs;			/* entire machine state */
+	size_t		u_tsize;		/* text size (pages) */
+	size_t		u_dsize;		/* data size (pages) */
+	size_t		u_ssize;		/* stack size (pages) */
+	unsigned long	start_code;		/* text starting address */
+	unsigned long	start_data;		/* data starting address */
+	unsigned long	start_stack;		/* stack starting address */
+	long int	signal;			/* signal causing core dump */
+	struct regs *	u_ar0;			/* help gdb find registers */
+	unsigned long	magic;			/* identifies a core file */
+	char		u_comm[32];		/* user command name */
+};
+
+#define NBPG			PAGE_SIZE
+#define UPAGES			1
+#define HOST_TEXT_START_ADDR	(u.start_code)
+#define HOST_DATA_START_ADDR	(u.start_data)
+#define HOST_STACK_END_ADDR	(u.start_stack + u.u_ssize * NBPG)
+
+#endif /* __ASM_SH_USER_H */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/asm_offsets.h linux/include/asm-sparc/asm_offsets.h
--- v2.3.15/linux/include/asm-sparc/asm_offsets.h	Sun Jul  4 09:53:12 1999
+++ linux/include/asm-sparc/asm_offsets.h	Tue Aug 31 11:23:30 1999
@@ -36,10 +36,8 @@
 #define ASIZ_task_next_task	0x00000004
 #define AOFF_task_prev_task	0x00000038
 #define ASIZ_task_prev_task	0x00000004
-#define AOFF_task_next_run	0x0000003c
-#define ASIZ_task_next_run	0x00000004
-#define AOFF_task_prev_run	0x00000040
-#define ASIZ_task_prev_run	0x00000004
+#define AOFF_task_run_list	0x0000003c
+#define ASIZ_task_run_list	0x00000008
 #define AOFF_task_binfmt	0x00000044
 #define ASIZ_task_binfmt	0x00000004
 #define AOFF_task_exit_code	0x00000048
@@ -74,113 +72,113 @@
 #define ASIZ_task_pidhash_next	0x00000004
 #define AOFF_task_pidhash_pprev	0x00000088
 #define ASIZ_task_pidhash_pprev	0x00000004
-#define AOFF_task_tarray_ptr	0x0000008c
-#define ASIZ_task_tarray_ptr	0x00000004
-#define AOFF_task_wait_chldexit	0x00000090
+#define AOFF_task_wait_chldexit	0x0000008c
 #define ASIZ_task_wait_chldexit	0x00000014
-#define AOFF_task_vfork_sem	0x000000a4
+#define AOFF_task_vfork_sem	0x000000a0
 #define ASIZ_task_vfork_sem	0x00000004
-#define AOFF_task_policy	0x000000a8
+#define AOFF_task_policy	0x000000a4
 #define ASIZ_task_policy	0x00000004
-#define AOFF_task_rt_priority	0x000000ac
+#define AOFF_task_rt_priority	0x000000a8
 #define ASIZ_task_rt_priority	0x00000004
-#define AOFF_task_it_real_value	0x000000b0
+#define AOFF_task_it_real_value	0x000000ac
 #define ASIZ_task_it_real_value	0x00000004
-#define AOFF_task_it_prof_value	0x000000b4
+#define AOFF_task_it_prof_value	0x000000b0
 #define ASIZ_task_it_prof_value	0x00000004
-#define AOFF_task_it_virt_value	0x000000b8
+#define AOFF_task_it_virt_value	0x000000b4
 #define ASIZ_task_it_virt_value	0x00000004
-#define AOFF_task_it_real_incr	0x000000bc
+#define AOFF_task_it_real_incr	0x000000b8
 #define ASIZ_task_it_real_incr	0x00000004
-#define AOFF_task_it_prof_incr	0x000000c0
+#define AOFF_task_it_prof_incr	0x000000bc
 #define ASIZ_task_it_prof_incr	0x00000004
-#define AOFF_task_it_virt_incr	0x000000c4
+#define AOFF_task_it_virt_incr	0x000000c0
 #define ASIZ_task_it_virt_incr	0x00000004
-#define AOFF_task_real_timer	0x000000c8
+#define AOFF_task_real_timer	0x000000c4
 #define ASIZ_task_real_timer	0x00000014
-#define AOFF_task_times	0x000000dc
+#define AOFF_task_times	0x000000d8
 #define ASIZ_task_times	0x00000010
-#define AOFF_task_start_time	0x000000ec
+#define AOFF_task_start_time	0x000000e8
 #define ASIZ_task_start_time	0x00000004
-#define AOFF_task_per_cpu_utime	0x000000f0
+#define AOFF_task_per_cpu_utime	0x000000ec
 #define ASIZ_task_per_cpu_utime	0x00000004
-#define AOFF_task_min_flt	0x000000f8
+#define AOFF_task_min_flt	0x000000f4
 #define ASIZ_task_min_flt	0x00000004
-#define AOFF_task_maj_flt	0x000000fc
+#define AOFF_task_maj_flt	0x000000f8
 #define ASIZ_task_maj_flt	0x00000004
-#define AOFF_task_nswap	0x00000100
+#define AOFF_task_nswap	0x000000fc
 #define ASIZ_task_nswap	0x00000004
-#define AOFF_task_cmin_flt	0x00000104
+#define AOFF_task_cmin_flt	0x00000100
 #define ASIZ_task_cmin_flt	0x00000004
-#define AOFF_task_cmaj_flt	0x00000108
+#define AOFF_task_cmaj_flt	0x00000104
 #define ASIZ_task_cmaj_flt	0x00000004
-#define AOFF_task_cnswap	0x0000010c
+#define AOFF_task_cnswap	0x00000108
 #define ASIZ_task_cnswap	0x00000004
-#define AOFF_task_uid	0x00000112
+#define AOFF_task_uid	0x0000010e
 #define ASIZ_task_uid	0x00000002
-#define AOFF_task_euid	0x00000114
+#define AOFF_task_euid	0x00000110
 #define ASIZ_task_euid	0x00000002
-#define AOFF_task_suid	0x00000116
+#define AOFF_task_suid	0x00000112
 #define ASIZ_task_suid	0x00000002
-#define AOFF_task_fsuid	0x00000118
+#define AOFF_task_fsuid	0x00000114
 #define ASIZ_task_fsuid	0x00000002
-#define AOFF_task_gid	0x0000011a
+#define AOFF_task_gid	0x00000116
 #define ASIZ_task_gid	0x00000002
-#define AOFF_task_egid	0x0000011c
+#define AOFF_task_egid	0x00000118
 #define ASIZ_task_egid	0x00000002
-#define AOFF_task_sgid	0x0000011e
+#define AOFF_task_sgid	0x0000011a
 #define ASIZ_task_sgid	0x00000002
-#define AOFF_task_fsgid	0x00000120
+#define AOFF_task_fsgid	0x0000011c
 #define ASIZ_task_fsgid	0x00000002
-#define AOFF_task_ngroups	0x00000124
+#define AOFF_task_ngroups	0x00000120
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x00000128
+#define AOFF_task_groups	0x00000124
 #define ASIZ_task_groups	0x00000040
-#define AOFF_task_cap_effective	0x00000168
+#define AOFF_task_cap_effective	0x00000164
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x0000016c
+#define AOFF_task_cap_inheritable	0x00000168
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000170
+#define AOFF_task_cap_permitted	0x0000016c
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x00000174
+#define AOFF_task_user	0x00000170
 #define ASIZ_task_user	0x00000004
-#define AOFF_task_rlim	0x00000178
+#define AOFF_task_rlim	0x00000174
 #define ASIZ_task_rlim	0x00000050
-#define AOFF_task_used_math	0x000001c8
+#define AOFF_task_used_math	0x000001c4
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x000001ca
+#define AOFF_task_comm	0x000001c6
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x000001dc
+#define AOFF_task_link_count	0x000001d8
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x000001e0
+#define AOFF_task_tty	0x000001dc
 #define ASIZ_task_tty	0x00000004
-#define AOFF_task_semundo	0x000001e4
+#define AOFF_task_semundo	0x000001e0
 #define ASIZ_task_semundo	0x00000004
-#define AOFF_task_semsleeping	0x000001e8
+#define AOFF_task_semsleeping	0x000001e4
 #define ASIZ_task_semsleeping	0x00000004
-#define AOFF_task_tss	0x000001f0
-#define ASIZ_task_tss	0x00000388
-#define AOFF_task_fs	0x00000578
+#define AOFF_task_thread	0x000001e8
+#define ASIZ_task_thread	0x00000388
+#define AOFF_task_fs	0x00000570
 #define ASIZ_task_fs	0x00000004
-#define AOFF_task_files	0x0000057c
+#define AOFF_task_files	0x00000574
 #define ASIZ_task_files	0x00000004
-#define AOFF_task_mm	0x00000580
+#define AOFF_task_mm	0x00000578
 #define ASIZ_task_mm	0x00000004
-#define AOFF_task_sigmask_lock	0x00000584
+#define AOFF_task_active_mm	0x0000057c
+#define ASIZ_task_active_mm	0x00000004
+#define AOFF_task_sigmask_lock	0x00000580
 #define ASIZ_task_sigmask_lock	0x00000001
-#define AOFF_task_sig	0x00000588
+#define AOFF_task_sig	0x00000584
 #define ASIZ_task_sig	0x00000004
-#define AOFF_task_signal	0x0000058c
+#define AOFF_task_signal	0x00000588
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000594
+#define AOFF_task_blocked	0x00000590
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x0000059c
+#define AOFF_task_sigqueue	0x00000598
 #define ASIZ_task_sigqueue	0x00000004
-#define AOFF_task_sigqueue_tail	0x000005a0
+#define AOFF_task_sigqueue_tail	0x0000059c
 #define ASIZ_task_sigqueue_tail	0x00000004
-#define AOFF_task_sas_ss_sp	0x000005a4
+#define AOFF_task_sas_ss_sp	0x000005a0
 #define ASIZ_task_sas_ss_sp	0x00000004
-#define AOFF_task_sas_ss_size	0x000005a8
+#define AOFF_task_sas_ss_size	0x000005a4
 #define ASIZ_task_sas_ss_size	0x00000004
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000004
@@ -190,53 +188,55 @@
 #define ASIZ_mm_mmap_cache	0x00000004
 #define AOFF_mm_pgd	0x0000000c
 #define ASIZ_mm_pgd	0x00000004
-#define AOFF_mm_count	0x00000010
-#define ASIZ_mm_count	0x00000004
-#define AOFF_mm_map_count	0x00000014
+#define AOFF_mm_mm_users	0x00000010
+#define ASIZ_mm_mm_users	0x00000004
+#define AOFF_mm_mm_count	0x00000014
+#define ASIZ_mm_mm_count	0x00000004
+#define AOFF_mm_map_count	0x00000018
 #define ASIZ_mm_map_count	0x00000004
-#define AOFF_mm_mmap_sem	0x00000018
+#define AOFF_mm_mmap_sem	0x0000001c
 #define ASIZ_mm_mmap_sem	0x00000020
-#define AOFF_mm_page_table_lock	0x00000038
+#define AOFF_mm_page_table_lock	0x0000003c
 #define ASIZ_mm_page_table_lock	0x00000001
-#define AOFF_mm_context	0x0000003c
+#define AOFF_mm_context	0x00000040
 #define ASIZ_mm_context	0x00000004
-#define AOFF_mm_start_code	0x00000040
+#define AOFF_mm_start_code	0x00000044
 #define ASIZ_mm_start_code	0x00000004
-#define AOFF_mm_end_code	0x00000044
+#define AOFF_mm_end_code	0x00000048
 #define ASIZ_mm_end_code	0x00000004
-#define AOFF_mm_start_data	0x00000048
+#define AOFF_mm_start_data	0x0000004c
 #define ASIZ_mm_start_data	0x00000004
-#define AOFF_mm_end_data	0x0000004c
+#define AOFF_mm_end_data	0x00000050
 #define ASIZ_mm_end_data	0x00000004
-#define AOFF_mm_start_brk	0x00000050
+#define AOFF_mm_start_brk	0x00000054
 #define ASIZ_mm_start_brk	0x00000004
-#define AOFF_mm_brk	0x00000054
+#define AOFF_mm_brk	0x00000058
 #define ASIZ_mm_brk	0x00000004
-#define AOFF_mm_start_stack	0x00000058
+#define AOFF_mm_start_stack	0x0000005c
 #define ASIZ_mm_start_stack	0x00000004
-#define AOFF_mm_arg_start	0x0000005c
+#define AOFF_mm_arg_start	0x00000060
 #define ASIZ_mm_arg_start	0x00000004
-#define AOFF_mm_arg_end	0x00000060
+#define AOFF_mm_arg_end	0x00000064
 #define ASIZ_mm_arg_end	0x00000004
-#define AOFF_mm_env_start	0x00000064
+#define AOFF_mm_env_start	0x00000068
 #define ASIZ_mm_env_start	0x00000004
-#define AOFF_mm_env_end	0x00000068
+#define AOFF_mm_env_end	0x0000006c
 #define ASIZ_mm_env_end	0x00000004
-#define AOFF_mm_rss	0x0000006c
+#define AOFF_mm_rss	0x00000070
 #define ASIZ_mm_rss	0x00000004
-#define AOFF_mm_total_vm	0x00000070
+#define AOFF_mm_total_vm	0x00000074
 #define ASIZ_mm_total_vm	0x00000004
-#define AOFF_mm_locked_vm	0x00000074
+#define AOFF_mm_locked_vm	0x00000078
 #define ASIZ_mm_locked_vm	0x00000004
-#define AOFF_mm_def_flags	0x00000078
+#define AOFF_mm_def_flags	0x0000007c
 #define ASIZ_mm_def_flags	0x00000004
-#define AOFF_mm_cpu_vm_mask	0x0000007c
+#define AOFF_mm_cpu_vm_mask	0x00000080
 #define ASIZ_mm_cpu_vm_mask	0x00000004
-#define AOFF_mm_swap_cnt	0x00000080
+#define AOFF_mm_swap_cnt	0x00000084
 #define ASIZ_mm_swap_cnt	0x00000004
-#define AOFF_mm_swap_address	0x00000084
+#define AOFF_mm_swap_address	0x00000088
 #define ASIZ_mm_swap_address	0x00000004
-#define AOFF_mm_segments	0x00000088
+#define AOFF_mm_segments	0x0000008c
 #define ASIZ_mm_segments	0x00000004
 #define AOFF_thread_uwinmask	0x00000000
 #define ASIZ_thread_uwinmask	0x00000004
@@ -313,10 +313,8 @@
 #define ASIZ_task_next_task	0x00000004
 #define AOFF_task_prev_task	0x00000038
 #define ASIZ_task_prev_task	0x00000004
-#define AOFF_task_next_run	0x0000003c
-#define ASIZ_task_next_run	0x00000004
-#define AOFF_task_prev_run	0x00000040
-#define ASIZ_task_prev_run	0x00000004
+#define AOFF_task_run_list	0x0000003c
+#define ASIZ_task_run_list	0x00000008
 #define AOFF_task_binfmt	0x00000044
 #define ASIZ_task_binfmt	0x00000004
 #define AOFF_task_exit_code	0x00000048
@@ -351,113 +349,113 @@
 #define ASIZ_task_pidhash_next	0x00000004
 #define AOFF_task_pidhash_pprev	0x00000088
 #define ASIZ_task_pidhash_pprev	0x00000004
-#define AOFF_task_tarray_ptr	0x0000008c
-#define ASIZ_task_tarray_ptr	0x00000004
-#define AOFF_task_wait_chldexit	0x00000090
+#define AOFF_task_wait_chldexit	0x0000008c
 #define ASIZ_task_wait_chldexit	0x00000018
-#define AOFF_task_vfork_sem	0x000000a8
+#define AOFF_task_vfork_sem	0x000000a4
 #define ASIZ_task_vfork_sem	0x00000004
-#define AOFF_task_policy	0x000000ac
+#define AOFF_task_policy	0x000000a8
 #define ASIZ_task_policy	0x00000004
-#define AOFF_task_rt_priority	0x000000b0
+#define AOFF_task_rt_priority	0x000000ac
 #define ASIZ_task_rt_priority	0x00000004
-#define AOFF_task_it_real_value	0x000000b4
+#define AOFF_task_it_real_value	0x000000b0
 #define ASIZ_task_it_real_value	0x00000004
-#define AOFF_task_it_prof_value	0x000000b8
+#define AOFF_task_it_prof_value	0x000000b4
 #define ASIZ_task_it_prof_value	0x00000004
-#define AOFF_task_it_virt_value	0x000000bc
+#define AOFF_task_it_virt_value	0x000000b8
 #define ASIZ_task_it_virt_value	0x00000004
-#define AOFF_task_it_real_incr	0x000000c0
+#define AOFF_task_it_real_incr	0x000000bc
 #define ASIZ_task_it_real_incr	0x00000004
-#define AOFF_task_it_prof_incr	0x000000c4
+#define AOFF_task_it_prof_incr	0x000000c0
 #define ASIZ_task_it_prof_incr	0x00000004
-#define AOFF_task_it_virt_incr	0x000000c8
+#define AOFF_task_it_virt_incr	0x000000c4
 #define ASIZ_task_it_virt_incr	0x00000004
-#define AOFF_task_real_timer	0x000000cc
+#define AOFF_task_real_timer	0x000000c8
 #define ASIZ_task_real_timer	0x00000014
-#define AOFF_task_times	0x000000e0
+#define AOFF_task_times	0x000000dc
 #define ASIZ_task_times	0x00000010
-#define AOFF_task_start_time	0x000000f0
+#define AOFF_task_start_time	0x000000ec
 #define ASIZ_task_start_time	0x00000004
-#define AOFF_task_per_cpu_utime	0x000000f4
+#define AOFF_task_per_cpu_utime	0x000000f0
 #define ASIZ_task_per_cpu_utime	0x00000080
-#define AOFF_task_min_flt	0x000001f4
+#define AOFF_task_min_flt	0x000001f0
 #define ASIZ_task_min_flt	0x00000004
-#define AOFF_task_maj_flt	0x000001f8
+#define AOFF_task_maj_flt	0x000001f4
 #define ASIZ_task_maj_flt	0x00000004
-#define AOFF_task_nswap	0x000001fc
+#define AOFF_task_nswap	0x000001f8
 #define ASIZ_task_nswap	0x00000004
-#define AOFF_task_cmin_flt	0x00000200
+#define AOFF_task_cmin_flt	0x000001fc
 #define ASIZ_task_cmin_flt	0x00000004
-#define AOFF_task_cmaj_flt	0x00000204
+#define AOFF_task_cmaj_flt	0x00000200
 #define ASIZ_task_cmaj_flt	0x00000004
-#define AOFF_task_cnswap	0x00000208
+#define AOFF_task_cnswap	0x00000204
 #define ASIZ_task_cnswap	0x00000004
-#define AOFF_task_uid	0x0000020e
+#define AOFF_task_uid	0x0000020a
 #define ASIZ_task_uid	0x00000002
-#define AOFF_task_euid	0x00000210
+#define AOFF_task_euid	0x0000020c
 #define ASIZ_task_euid	0x00000002
-#define AOFF_task_suid	0x00000212
+#define AOFF_task_suid	0x0000020e
 #define ASIZ_task_suid	0x00000002
-#define AOFF_task_fsuid	0x00000214
+#define AOFF_task_fsuid	0x00000210
 #define ASIZ_task_fsuid	0x00000002
-#define AOFF_task_gid	0x00000216
+#define AOFF_task_gid	0x00000212
 #define ASIZ_task_gid	0x00000002
-#define AOFF_task_egid	0x00000218
+#define AOFF_task_egid	0x00000214
 #define ASIZ_task_egid	0x00000002
-#define AOFF_task_sgid	0x0000021a
+#define AOFF_task_sgid	0x00000216
 #define ASIZ_task_sgid	0x00000002
-#define AOFF_task_fsgid	0x0000021c
+#define AOFF_task_fsgid	0x00000218
 #define ASIZ_task_fsgid	0x00000002
-#define AOFF_task_ngroups	0x00000220
+#define AOFF_task_ngroups	0x0000021c
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x00000224
+#define AOFF_task_groups	0x00000220
 #define ASIZ_task_groups	0x00000040
-#define AOFF_task_cap_effective	0x00000264
+#define AOFF_task_cap_effective	0x00000260
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x00000268
+#define AOFF_task_cap_inheritable	0x00000264
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x0000026c
+#define AOFF_task_cap_permitted	0x00000268
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x00000270
+#define AOFF_task_user	0x0000026c
 #define ASIZ_task_user	0x00000004
-#define AOFF_task_rlim	0x00000274
+#define AOFF_task_rlim	0x00000270
 #define ASIZ_task_rlim	0x00000050
-#define AOFF_task_used_math	0x000002c4
+#define AOFF_task_used_math	0x000002c0
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x000002c6
+#define AOFF_task_comm	0x000002c2
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x000002d8
+#define AOFF_task_link_count	0x000002d4
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x000002dc
+#define AOFF_task_tty	0x000002d8
 #define ASIZ_task_tty	0x00000004
-#define AOFF_task_semundo	0x000002e0
+#define AOFF_task_semundo	0x000002dc
 #define ASIZ_task_semundo	0x00000004
-#define AOFF_task_semsleeping	0x000002e4
+#define AOFF_task_semsleeping	0x000002e0
 #define ASIZ_task_semsleeping	0x00000004
-#define AOFF_task_tss	0x000002e8
-#define ASIZ_task_tss	0x00000388
+#define AOFF_task_thread	0x000002e8
+#define ASIZ_task_thread	0x00000388
 #define AOFF_task_fs	0x00000670
 #define ASIZ_task_fs	0x00000004
 #define AOFF_task_files	0x00000674
 #define ASIZ_task_files	0x00000004
 #define AOFF_task_mm	0x00000678
 #define ASIZ_task_mm	0x00000004
-#define AOFF_task_sigmask_lock	0x0000067c
+#define AOFF_task_active_mm	0x0000067c
+#define ASIZ_task_active_mm	0x00000004
+#define AOFF_task_sigmask_lock	0x00000680
 #define ASIZ_task_sigmask_lock	0x00000008
-#define AOFF_task_sig	0x00000684
+#define AOFF_task_sig	0x00000688
 #define ASIZ_task_sig	0x00000004
-#define AOFF_task_signal	0x00000688
+#define AOFF_task_signal	0x0000068c
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000690
+#define AOFF_task_blocked	0x00000694
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000698
+#define AOFF_task_sigqueue	0x0000069c
 #define ASIZ_task_sigqueue	0x00000004
-#define AOFF_task_sigqueue_tail	0x0000069c
+#define AOFF_task_sigqueue_tail	0x000006a0
 #define ASIZ_task_sigqueue_tail	0x00000004
-#define AOFF_task_sas_ss_sp	0x000006a0
+#define AOFF_task_sas_ss_sp	0x000006a4
 #define ASIZ_task_sas_ss_sp	0x00000004
-#define AOFF_task_sas_ss_size	0x000006a4
+#define AOFF_task_sas_ss_size	0x000006a8
 #define ASIZ_task_sas_ss_size	0x00000004
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000004
@@ -467,53 +465,55 @@
 #define ASIZ_mm_mmap_cache	0x00000004
 #define AOFF_mm_pgd	0x0000000c
 #define ASIZ_mm_pgd	0x00000004
-#define AOFF_mm_count	0x00000010
-#define ASIZ_mm_count	0x00000004
-#define AOFF_mm_map_count	0x00000014
+#define AOFF_mm_mm_users	0x00000010
+#define ASIZ_mm_mm_users	0x00000004
+#define AOFF_mm_mm_count	0x00000014
+#define ASIZ_mm_mm_count	0x00000004
+#define AOFF_mm_map_count	0x00000018
 #define ASIZ_mm_map_count	0x00000004
-#define AOFF_mm_mmap_sem	0x00000018
+#define AOFF_mm_mmap_sem	0x0000001c
 #define ASIZ_mm_mmap_sem	0x00000024
-#define AOFF_mm_page_table_lock	0x0000003c
+#define AOFF_mm_page_table_lock	0x00000040
 #define ASIZ_mm_page_table_lock	0x00000008
-#define AOFF_mm_context	0x00000044
+#define AOFF_mm_context	0x00000048
 #define ASIZ_mm_context	0x00000004
-#define AOFF_mm_start_code	0x00000048
+#define AOFF_mm_start_code	0x0000004c
 #define ASIZ_mm_start_code	0x00000004
-#define AOFF_mm_end_code	0x0000004c
+#define AOFF_mm_end_code	0x00000050
 #define ASIZ_mm_end_code	0x00000004
-#define AOFF_mm_start_data	0x00000050
+#define AOFF_mm_start_data	0x00000054
 #define ASIZ_mm_start_data	0x00000004
-#define AOFF_mm_end_data	0x00000054
+#define AOFF_mm_end_data	0x00000058
 #define ASIZ_mm_end_data	0x00000004
-#define AOFF_mm_start_brk	0x00000058
+#define AOFF_mm_start_brk	0x0000005c
 #define ASIZ_mm_start_brk	0x00000004
-#define AOFF_mm_brk	0x0000005c
+#define AOFF_mm_brk	0x00000060
 #define ASIZ_mm_brk	0x00000004
-#define AOFF_mm_start_stack	0x00000060
+#define AOFF_mm_start_stack	0x00000064
 #define ASIZ_mm_start_stack	0x00000004
-#define AOFF_mm_arg_start	0x00000064
+#define AOFF_mm_arg_start	0x00000068
 #define ASIZ_mm_arg_start	0x00000004
-#define AOFF_mm_arg_end	0x00000068
+#define AOFF_mm_arg_end	0x0000006c
 #define ASIZ_mm_arg_end	0x00000004
-#define AOFF_mm_env_start	0x0000006c
+#define AOFF_mm_env_start	0x00000070
 #define ASIZ_mm_env_start	0x00000004
-#define AOFF_mm_env_end	0x00000070
+#define AOFF_mm_env_end	0x00000074
 #define ASIZ_mm_env_end	0x00000004
-#define AOFF_mm_rss	0x00000074
+#define AOFF_mm_rss	0x00000078
 #define ASIZ_mm_rss	0x00000004
-#define AOFF_mm_total_vm	0x00000078
+#define AOFF_mm_total_vm	0x0000007c
 #define ASIZ_mm_total_vm	0x00000004
-#define AOFF_mm_locked_vm	0x0000007c
+#define AOFF_mm_locked_vm	0x00000080
 #define ASIZ_mm_locked_vm	0x00000004
-#define AOFF_mm_def_flags	0x00000080
+#define AOFF_mm_def_flags	0x00000084
 #define ASIZ_mm_def_flags	0x00000004
-#define AOFF_mm_cpu_vm_mask	0x00000084
+#define AOFF_mm_cpu_vm_mask	0x00000088
 #define ASIZ_mm_cpu_vm_mask	0x00000004
-#define AOFF_mm_swap_cnt	0x00000088
+#define AOFF_mm_swap_cnt	0x0000008c
 #define ASIZ_mm_swap_cnt	0x00000004
-#define AOFF_mm_swap_address	0x0000008c
+#define AOFF_mm_swap_address	0x00000090
 #define ASIZ_mm_swap_address	0x00000004
-#define AOFF_mm_segments	0x00000090
+#define AOFF_mm_segments	0x00000094
 #define ASIZ_mm_segments	0x00000004
 #define AOFF_thread_uwinmask	0x00000000
 #define ASIZ_thread_uwinmask	0x00000004
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/audioio.h linux/include/asm-sparc/audioio.h
--- v2.3.15/linux/include/asm-sparc/audioio.h	Mon Jul  5 20:35:18 1999
+++ linux/include/asm-sparc/audioio.h	Tue Aug 31 11:23:30 1999
@@ -237,6 +237,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/tqueue.h>
 #include <linux/wait.h>
@@ -299,6 +300,8 @@
 
         /* Hack to make it look like we support variable size buffers. */
         int buffer_size;
+
+        int mixer_modify_counter;
 };
 
 struct sparcaudio_operations
@@ -432,23 +435,6 @@
 
 #endif
 
-/* Mixer helper ioctls */
-#define right(a) (((a >> 8) & 0xff) % 101)
-#define left(a) ((a & 0xff) % 101)
-
-/* Macros to convert between mixer stereo volumes and gain (mono) */
-#define s_to_m(a) ((((left(a) + right(a)) * 255) / 200) % 256)
-#define m_to_s(a) ((a * 100 / 255) + ((a * 100 / 255) << 8))
-
-/* convert mixer stereo volume to balance */
-#define s_to_b(a) (s_to_g(a) == 0) ? 32 : ((left(a) * AUDIO_RIGHT_BALANCE / (left(a) + right(a))))
-
-/* convert mixer stereo volume to audio gain */
-#define s_to_g(a) ((((right(a) + left(a)) * 255) / 200) % 256)
-
-/* convert gain a and balance b to mixer volume */
-#define b_to_s(a,b) (((((b * a * 200) / (AUDIO_RIGHT_BALANCE * 255)) % 100) << 8) + ((((AUDIO_RIGHT_BALANCE - b) * a * 200) / (AUDIO_RIGHT_BALANCE * 255)) % 100))
-
 /* Device minor numbers */
 
 #define SPARCAUDIO_MIXER_MINOR 0
@@ -514,4 +500,147 @@
 
 #define I_GETSIG _IOR('S',012,int)
 #define I_GETSIG_SOLARIS (('S'<<8)|12)
-#endif
+
+/* Conversion between Sun and OSS volume settings */
+static __inline__ 
+int OSS_LEFT(int value)
+{
+  return ((value & 0xff) % 101);
+}
+
+static __inline__ 
+int OSS_RIGHT(int value)
+{
+  return  (((value >> 8) & 0xff) % 101);
+}
+
+static __inline__ 
+int O_TO_S(int value)
+{
+  return value * 255 / 100;
+}
+
+static __inline__ 
+int S_TO_O(int value)
+{
+  return value * 100 / 255;
+}
+
+static __inline__ 
+int OSS_TO_GAIN(int value)
+{
+  int l = O_TO_S(OSS_LEFT(value));
+  int r = O_TO_S(OSS_RIGHT(value));
+  return ((l > r) ? l : r);
+}
+
+static __inline__ 
+int OSS_TO_LGAIN(int value)
+{
+  int l = O_TO_S(OSS_LEFT(value));
+  int r = O_TO_S(OSS_RIGHT(value));
+  return ((l < r) ? l : r);
+}
+
+static __inline__ 
+int OSS_TO_BAL(int value) 
+{
+  if (!OSS_TO_GAIN(value))
+    return AUDIO_MID_BALANCE;
+  if (!OSS_TO_LGAIN(value)) {
+    if (OSS_TO_GAIN(value) == OSS_TO_GAIN(OSS_RIGHT(value)))
+      return AUDIO_RIGHT_BALANCE;
+    else
+      return AUDIO_LEFT_BALANCE;
+  }
+  if (OSS_TO_GAIN(value) == OSS_TO_GAIN(OSS_RIGHT(value)))
+    return ((OSS_TO_GAIN(value) - OSS_TO_LGAIN(value)) >> AUDIO_BALANCE_SHIFT)
+      + AUDIO_MID_BALANCE;
+  else
+    return AUDIO_MID_BALANCE - ((OSS_TO_GAIN(value) - OSS_TO_LGAIN(value)) 
+				>> AUDIO_BALANCE_SHIFT);
+}
+
+static __inline__ 
+int BAL_TO_OSS(int value, unsigned char balance)
+{
+  int l, r, adj;
+  if (balance > 63) balance = 63;
+  if (balance < AUDIO_MID_BALANCE) {
+    l = (int)value * 100 / 255 + ((value * 100 % 255) > 0);
+    adj = ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT);
+    if (adj < value)
+      r = (int)(value - adj)
+	* 100 / 255;
+    else r = 0;
+  } else if (balance > AUDIO_MID_BALANCE) {
+    r = (int)value * 100 / 255 + ((value * 100 % 255) > 0);
+    adj = ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT);
+    if (adj < value)
+      l = (int)(value - adj)
+	* 100 / 255;
+    else l = 0;
+  } else {
+    l = r = (int)value * 100 / 255 + ((value * 100 % 255) > 0);
+  }
+
+  return ((r << 8) + l);
+}
+
+/* OSS mixer ioctl port handling */
+static __inline__
+int OSS_PORT_AUDIO(struct sparcaudio_driver *drv, unsigned int set) 
+{
+  int p;
+  if (drv->ops->get_output_port) {
+    p = drv->ops->get_output_port(drv);
+    if (p & set)
+      return 0x6464;
+  }  
+  return 0;
+}
+
+static __inline__
+int OSS_IPORT_AUDIO(struct sparcaudio_driver *drv, unsigned int set) 
+{
+  int p;
+  if (drv->ops->get_input_port) {
+    p = drv->ops->get_input_port(drv);
+    if (p & set)
+      return 0x6464;
+  }  
+  return 0;
+}
+
+static __inline__ 
+void OSS_TWIDDLE_PORT(struct sparcaudio_driver *drv, unsigned int ioctl, 
+		      unsigned int port, unsigned int set, unsigned int value) 
+{
+  if (ioctl == port) {
+    int p;
+    if (drv->ops->get_output_port && drv->ops->set_output_port) {
+      p = drv->ops->get_output_port(drv);
+      if ((value == 0) || ((p & set) && (OSS_LEFT(value) < 100)))
+	drv->ops->set_output_port(drv, p & ~(set));
+      else
+	drv->ops->set_output_port(drv, p | set);
+    }
+  }
+}
+
+static __inline__ 
+void OSS_TWIDDLE_IPORT(struct sparcaudio_driver *drv, unsigned int ioctl, 
+		      unsigned int port, unsigned int set, unsigned int value) 
+{
+  if (ioctl == port) {
+    int p;
+    if (drv->ops->get_input_port && drv->ops->set_input_port) {
+      p = drv->ops->get_input_port(drv);
+      if ((value == 0) || ((p & set) && (OSS_LEFT(value) < 100)))
+	drv->ops->set_input_port(drv, p & ~(set));
+      else
+	drv->ops->set_input_port(drv, p | set);
+    }
+  }
+}
+#endif /* _AUDIOIO_H_ */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/cache.h linux/include/asm-sparc/cache.h
--- v2.3.15/linux/include/asm-sparc/cache.h	Wed Mar 10 16:53:37 1999
+++ linux/include/asm-sparc/cache.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: cache.h,v 1.8 1999/03/11 00:14:45 davem Exp $
+/* $Id: cache.h,v 1.9 1999/08/14 03:51:58 anton Exp $
  * cache.h:  Cache specific code for the Sparc.  These include flushing
  *           and direct tag/data line access.
  *
@@ -14,6 +14,14 @@
 #define L1_CACHE_ALIGN(x) ((((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)))
 
 #define SMP_CACHE_BYTES 32
+
+#ifdef MODULE
+#define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
+#else
+#define __cacheline_aligned					\
+  __attribute__((__aligned__(SMP_CACHE_BYTES),			\
+		 __section__(".data.cacheline_aligned")))
+#endif
 
 /* Direct access to the instruction cache is provided through and
  * alternate address space.  The IDC bit must be off in the ICCR on
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/dma.h linux/include/asm-sparc/dma.h
--- v2.3.15/linux/include/asm-sparc/dma.h	Wed Mar 10 16:53:37 1999
+++ linux/include/asm-sparc/dma.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: dma.h,v 1.29 1998/11/29 15:49:44 davem Exp $
+/* $Id: dma.h,v 1.30 1999/08/08 14:03:37 shadow Exp $
  * include/asm-sparc/dma.h
  *
  * Copyright 1995 (C) David S. Miller (davem@caip.rutgers.edu)
@@ -119,6 +119,7 @@
 #define DMA_FIFO_STDRAIN 0x00000040        /* DMA_VERS1 Drain the FIFO */
 #define DMA_RST_SCSI     0x00000080        /* Reset the SCSI controller */
 #define DMA_RST_ENET     DMA_RST_SCSI      /* Reset the ENET controller */
+#define DMA_RST_BPP      DMA_RST_SCSI      /* Reset the BPP controller */
 #define DMA_ST_WRITE     0x00000100        /* write from device to memory */
 #define DMA_ENABLE       0x00000200        /* Fire up DMA, handle requests */
 #define DMA_PEND_READ    0x00000400        /* DMA_VERS1/0/PLUS Pending Read */
@@ -135,8 +136,8 @@
 #define DMA_E_BURST8	 0x00040000	   /* ENET: SBUS r/w burst size */
 #define DMA_BRST_SZ      0x000c0000        /* SCSI: SBUS r/w burst size */
 #define DMA_BRST64       0x00080000        /* SCSI: 64byte bursts (HME on UltraSparc only) */
-#define DMA_BRST32       0x00040000        /* SCSI: 32byte bursts */
-#define DMA_BRST16       0x00000000        /* SCSI: 16byte bursts */
+#define DMA_BRST32       0x00040000        /* SCSI/BPP: 32byte bursts */
+#define DMA_BRST16       0x00000000        /* SCSI/BPP: 16byte bursts */
 #define DMA_BRST0        0x00080000        /* SCSI: no bursts (non-HME gate arrays) */
 #define DMA_ADDR_DISAB   0x00100000        /* No FIFO drains during addr */
 #define DMA_2CLKS        0x00200000        /* Each transfer = 2 clock ticks */
@@ -145,6 +146,7 @@
 #define DMA_CNTR_DISAB   0x00800000        /* No IRQ when DMA_TERM_CNTR set */
 #define DMA_AUTO_NADDR   0x01000000        /* Use "auto nxt addr" feature */
 #define DMA_SCSI_ON      0x02000000        /* Enable SCSI dma */
+#define DMA_BPP_ON       DMA_SCSI_ON       /* Enable BPP dma */
 #define DMA_PARITY_OFF   0x02000000        /* HME: disable parity checking */
 #define DMA_LOADED_ADDR  0x04000000        /* Address has been loaded */
 #define DMA_LOADED_NADDR 0x08000000        /* Next address has been loaded */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/fbio.h linux/include/asm-sparc/fbio.h
--- v2.3.15/linux/include/asm-sparc/fbio.h	Sun Oct  4 10:22:44 1998
+++ linux/include/asm-sparc/fbio.h	Tue Aug 31 11:23:30 1999
@@ -36,6 +36,7 @@
 /* Does not seem to be listed in the Sun file either */
 #define FBTYPE_CREATOR          22
 #define FBTYPE_PCI_IGA1682	23
+#define FBTYPE_P9100COLOR	24
 
 /* fbio ioctls */
 /* Returned by FBIOGTYPE */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/hardirq.h linux/include/asm-sparc/hardirq.h
--- v2.3.15/linux/include/asm-sparc/hardirq.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-sparc/hardirq.h	Tue Aug 31 11:23:30 1999
@@ -7,7 +7,7 @@
 #ifndef __SPARC_HARDIRQ_H
 #define __SPARC_HARDIRQ_H
 
-#include <linux/tasks.h>
+#include <linux/threads.h>
 
 #ifndef __SMP__
 extern unsigned int local_irq_count;
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/init.h linux/include/asm-sparc/init.h
--- v2.3.15/linux/include/asm-sparc/init.h	Wed Mar 10 16:53:37 1999
+++ linux/include/asm-sparc/init.h	Tue Aug 31 11:23:30 1999
@@ -1,27 +1 @@
-#ifndef _SPARC_INIT_H
-#define _SPARC_INIT_H
-
-#if (defined (__svr4__) || defined (__ELF__))
-#define __init __attribute__ ((__section__ (".text.init")))
-#define __initdata __attribute__ ((__section__ (".data.init")))
-#define __initfunc(__arginit) \
-	__arginit __init; \
-	__arginit
-#define __cacheline_aligned __attribute__ \
-			((__section__ (".data.cacheline_aligned")))
-/* For assembly routines */
-#define __INIT		.section	".text.init",#alloc,#execinstr
-#define __FINIT	.previous
-#define __INITDATA	.section	".data.init",#alloc,#write
-#else
-#define	__init
-#define __initdata
-#define __initfunc(__arginit) __arginit
-#define __cacheline_aligned
-/* For assembly routines */
-#define __INIT
-#define __FINIT
-#define __INITDATA
-#endif
-
-#endif
+#error "<asm/init.h> should never be used - use <linux/init.h> instead"
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/irq.h linux/include/asm-sparc/irq.h
--- v2.3.15/linux/include/asm-sparc/irq.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-sparc/irq.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: irq.h,v 1.26 1999/04/20 13:22:44 anton Exp $
+/* $Id: irq.h,v 1.27 1999/08/14 03:52:02 anton Exp $
  * irq.h: IRQ registers on the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -8,7 +8,7 @@
 #define _SPARC_IRQ_H
 
 #include <linux/linkage.h>
-#include <linux/tasks.h>     /* For NR_CPUS */
+#include <linux/threads.h>     /* For NR_CPUS */
 
 #include <asm/system.h>     /* For SUN4M_NCPUS */
 #include <asm/btfixup.h>
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/mostek.h linux/include/asm-sparc/mostek.h
--- v2.3.15/linux/include/asm-sparc/mostek.h	Sun Oct  4 10:22:44 1998
+++ linux/include/asm-sparc/mostek.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: mostek.h,v 1.10 1998/08/18 15:03:11 davem Exp $
+/* $Id: mostek.h,v 1.11 1999/08/30 10:14:32 davem Exp $
  * mostek.h:  Describes the various Mostek time of day clock registers.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -38,6 +38,18 @@
  * other than the control register are in binary coded decimal. Some
  * control bits also live outside the control register.
  */
+#define mostek_read(_addr)		(*((volatile u8 *)(_addr)))
+#define mostek_write(_addr,_val)	((*((volatile u8 *)(_addr))) = (_val))
+#define MOSTEK_EEPROM		0x0000UL
+#define MOSTEK_IDPROM		0x07d8UL
+#define MOSTEK_CREG		0x07f8UL
+#define MOSTEK_SEC		0x07f9UL
+#define MOSTEK_MIN		0x07faUL
+#define MOSTEK_HOUR		0x07fbUL
+#define MOSTEK_DOW		0x07fcUL
+#define MOSTEK_DOM		0x07fdUL
+#define MOSTEK_MONTH		0x07feUL
+#define MOSTEK_YEAR		0x07ffUL
 
 struct mostek48t02 {
 	volatile char eeprom[2008];	/* This is the eeprom, don't touch! */
@@ -52,7 +64,7 @@
 	volatile unsigned char year;	/* Year (0-99) */
 };
 
-extern struct mostek48t02 *mstk48t02_regs;
+extern unsigned long mstk48t02_regs;
 
 /* Control register values. */
 #define	MSTK_CREG_WRITE	0x80	/* Must set this before placing values. */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h
--- v2.3.15/linux/include/asm-sparc/processor.h	Sun Jul 25 13:45:25 1999
+++ linux/include/asm-sparc/processor.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.71 1999/05/27 04:52:43 davem Exp $
+/* $Id: processor.h,v 1.72 1999/08/14 03:52:04 anton Exp $
  * include/asm-sparc/processor.h
  *
  * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
@@ -96,7 +96,7 @@
 #define INIT_MMAP { &init_mm, (0), (0), \
 		    NULL, __pgprot(0x0) , VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
 
-#define INIT_TSS  { \
+#define INIT_THREAD  { \
 /* uwinmask, kregs, sig_address, sig_desc, ksp, kpc, kpsr, kwim */ \
    0,        0,     0,           0,        0,   0,   0,    0, \
 /* fork_kpsr, fork_kwim */ \
@@ -154,7 +154,7 @@
 extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 
-#define copy_segments(__nr, __tsk, __mm)	\
+#define copy_segments(__tsk, __mm)		\
 	if((__tsk) == current &&		\
 	   (__mm) != NULL)			\
 		flush_user_windows()
@@ -162,6 +162,7 @@
 #define forget_segments()		do { } while (0)
 
 #ifdef __KERNEL__
+#define THREAD_SIZE (2*PAGE_SIZE)
 
 extern struct task_struct *last_task_used_math;
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/resource.h linux/include/asm-sparc/resource.h
--- v2.3.15/linux/include/asm-sparc/resource.h	Mon Aug  2 22:07:16 1999
+++ linux/include/asm-sparc/resource.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: resource.h,v 1.8 1999/07/30 09:37:56 davem Exp $
+/* $Id: resource.h,v 1.9 1999/08/14 03:52:05 anton Exp $
  * resource.h: Resource definitions.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -25,14 +25,13 @@
 #define RLIM_NLIMITS	10
 
 #ifdef __KERNEL__
-
-#define INIT_RLIMITS							\
-{									\
-    {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX},				\
-    {LONG_MAX, LONG_MAX}, {_STK_LIM, LONG_MAX},				\
-    {       0, LONG_MAX}, {LONG_MAX, LONG_MAX},				\
-    {INR_OPEN, INR_OPEN}, {MAX_TASKS_PER_USER, MAX_TASKS_PER_USER},	\
-    {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX}                          \
+#define INIT_RLIMITS				\
+{						\
+    {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX},	\
+    {LONG_MAX, LONG_MAX}, {_STK_LIM, LONG_MAX},	\
+    {       0, LONG_MAX}, {LONG_MAX, LONG_MAX},	\
+    {INR_OPEN, INR_OPEN}, {0, 0},		\
+    {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX}  \
 }
 
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/smp.h linux/include/asm-sparc/smp.h
--- v2.3.15/linux/include/asm-sparc/smp.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-sparc/smp.h	Tue Aug 31 11:23:30 1999
@@ -6,7 +6,7 @@
 #ifndef _SPARC_SMP_H
 #define _SPARC_SMP_H
 
-#include <linux/tasks.h>
+#include <linux/threads.h>
 #include <asm/head.h>
 #include <asm/btfixup.h>
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/softirq.h linux/include/asm-sparc/softirq.h
--- v2.3.15/linux/include/asm-sparc/softirq.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-sparc/softirq.h	Tue Aug 31 11:23:30 1999
@@ -7,7 +7,7 @@
 #ifndef __SPARC_SOFTIRQ_H
 #define __SPARC_SOFTIRQ_H
 
-#include <linux/tasks.h>	/* For NR_CPUS */
+#include <linux/threads.h>	/* For NR_CPUS */
 
 #include <asm/atomic.h>
 #include <asm/smp.h>
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/spinlock.h linux/include/asm-sparc/spinlock.h
--- v2.3.15/linux/include/asm-sparc/spinlock.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-sparc/spinlock.h	Tue Aug 31 11:23:30 1999
@@ -6,7 +6,7 @@
 #ifndef __SPARC_SPINLOCK_H
 #define __SPARC_SPINLOCK_H
 
-#include <linux/tasks.h>	/* For NR_CPUS */
+#include <linux/threads.h>	/* For NR_CPUS */
 
 #ifndef __ASSEMBLY__
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/sunbpp.h linux/include/asm-sparc/sunbpp.h
--- v2.3.15/linux/include/asm-sparc/sunbpp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/sunbpp.h	Tue Aug 31 11:23:30 1999
@@ -0,0 +1,80 @@
+/* $Id: sunbpp.h,v 1.1 1999/08/08 14:09:49 shadow Exp $
+ * include/asm-sparc/sunbpp.h
+ */
+
+#ifndef _ASM_SPARC_SUNBPP_H
+#define _ASM_SPARC_SUNBPP_H
+
+struct bpp_regs {
+  /* DMA registers */
+  __volatile__ __u32 p_csr;		/* DMA Control/Status Register */
+  __volatile__ __u32 p_addr;		/* Address Register */
+  __volatile__ __u32 p_bcnt;		/* Byte Count Register */
+  __volatile__ __u32 p_tst_csr;		/* Test Control/Status (DMA2 only) */
+  /* Parallel Port registers */
+  __volatile__ __u16 p_hcr;		/* Hardware Configuration Register */
+  __volatile__ __u16 p_ocr;		/* Operation Configuration Register */
+  __volatile__ __u8 p_dr;		/* Parallel Data Register */
+  __volatile__ __u8 p_tcr;		/* Transfer Control Register */
+  __volatile__ __u8 p_or;		/* Output Register */
+  __volatile__ __u8 p_ir;		/* Input Register */
+  __volatile__ __u16 p_icr;		/* Interrupt Control Register */
+};
+
+/* P_HCR. Time is in increments of SBus clock. */
+#define P_HCR_TEST      0x8000      /* Allows buried counters to be read */
+#define P_HCR_DSW       0x7f00      /* Data strobe width (in ticks) */
+#define P_HCR_DDS       0x007f      /* Data setup before strobe (in ticks) */
+
+/* P_OCR. */
+#define P_OCR_MEM_CLR   0x8000
+#define P_OCR_DATA_SRC  0x4000      /* )                  */
+#define P_OCR_DS_DSEL   0x2000      /* )  Bidirectional      */
+#define P_OCR_BUSY_DSEL 0x1000      /* )    selects            */
+#define P_OCR_ACK_DSEL  0x0800      /* )                  */
+#define P_OCR_EN_DIAG   0x0400
+#define P_OCR_BUSY_OP   0x0200      /* Busy operation */
+#define P_OCR_ACK_OP    0x0100      /* Ack operation */
+#define P_OCR_SRST      0x0080      /* Reset state machines. Not selfcleaning. */
+#define P_OCR_IDLE      0x0008      /* PP data transfer state machine is idle */
+#define P_OCR_V_ILCK    0x0002      /* Versatec faded. Zebra only. */
+#define P_OCR_EN_VER    0x0001      /* Enable Versatec (0 - enable). Zebra only. */
+
+/* P_TCR */
+#define P_TCR_DIR       0x08
+#define P_TCR_BUSY      0x04
+#define P_TCR_ACK       0x02
+#define P_TCR_DS        0x01        /* Strobe */
+
+/* P_OR */
+#define P_OR_V3         0x20        /* )                 */
+#define P_OR_V2         0x10        /* ) on Zebra only   */
+#define P_OR_V1         0x08        /* )                 */
+#define P_OR_INIT       0x04
+#define P_OR_AFXN       0x02        /* Auto Feed */
+#define P_OR_SLCT_IN    0x01
+
+/* P_IR */
+#define P_IR_PE         0x04
+#define P_IR_SLCT       0x02
+#define P_IR_ERR        0x01
+
+/* P_ICR */
+#define P_DS_IRQ        0x8000      /* RW1  */
+#define P_ACK_IRQ       0x4000      /* RW1  */
+#define P_BUSY_IRQ      0x2000      /* RW1  */
+#define P_PE_IRQ        0x1000      /* RW1  */
+#define P_SLCT_IRQ      0x0800      /* RW1  */
+#define P_ERR_IRQ       0x0400      /* RW1  */
+#define P_DS_IRQ_EN     0x0200      /* RW   Always on rising edge */
+#define P_ACK_IRQ_EN    0x0100      /* RW   Always on rising edge */
+#define P_BUSY_IRP      0x0080      /* RW   1= rising edge */
+#define P_BUSY_IRQ_EN   0x0040      /* RW   */
+#define P_PE_IRP        0x0020      /* RW   1= rising edge */
+#define P_PE_IRQ_EN     0x0010      /* RW   */
+#define P_SLCT_IRP      0x0008      /* RW   1= rising edge */
+#define P_SLCT_IRQ_EN   0x0004      /* RW   */
+#define P_ERR_IRP       0x0002      /* RW1  1= rising edge */
+#define P_ERR_IRQ_EN    0x0001      /* RW   */
+
+#endif /* !(_ASM_SPARC_SUNBPP_H) */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/uaccess.h linux/include/asm-sparc/uaccess.h
--- v2.3.15/linux/include/asm-sparc/uaccess.h	Thu Apr 22 19:24:52 1999
+++ linux/include/asm-sparc/uaccess.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.18 1999/03/30 06:38:38 jj Exp $
+/* $Id: uaccess.h,v 1.19 1999/08/14 03:52:11 anton Exp $
  * uaccess.h: User space memore access functions.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -29,8 +29,8 @@
 #define VERIFY_WRITE	1
 
 #define get_ds()	(KERNEL_DS)
-#define get_fs()	(current->tss.current_ds)
-#define set_fs(val)	((current->tss.current_ds) = (val))
+#define get_fs()	(current->thread.current_ds)
+#define set_fs(val)	((current->thread.current_ds) = (val))
 
 #define segment_eq(a,b)	((a).seg == (b).seg)
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc/winmacro.h linux/include/asm-sparc/winmacro.h
--- v2.3.15/linux/include/asm-sparc/winmacro.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-sparc/winmacro.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: winmacro.h,v 1.20 1998/03/09 14:04:54 jj Exp $
+/* $Id: winmacro.h,v 1.21 1999/08/14 03:52:13 anton Exp $
  * winmacro.h: Window loading-unloading macros.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -98,18 +98,18 @@
         STORE_PT_INS(base_reg)
 
 #define SAVE_BOLIXED_USER_STACK(cur_reg, scratch) \
-        ld       [%cur_reg + AOFF_task_tss + AOFF_thread_w_saved], %scratch; \
+        ld       [%cur_reg + AOFF_task_thread + AOFF_thread_w_saved], %scratch; \
         sll      %scratch, 2, %scratch; \
         add      %scratch, %cur_reg, %scratch; \
-        st       %sp, [%scratch + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]; \
+        st       %sp, [%scratch + AOFF_task_thread + AOFF_thread_rwbuf_stkptrs]; \
         sub      %scratch, %cur_reg, %scratch; \
         sll      %scratch, 4, %scratch; \
         add      %scratch, %cur_reg, %scratch; \
-        STORE_WINDOW(scratch + AOFF_task_tss + AOFF_thread_reg_window); \
+        STORE_WINDOW(scratch + AOFF_task_thread + AOFF_thread_reg_window); \
         sub      %scratch, %cur_reg, %scratch; \
         srl      %scratch, 6, %scratch; \
         add      %scratch, 1, %scratch; \
-        st       %scratch, [%cur_reg + AOFF_task_tss + AOFF_thread_w_saved];
+        st       %scratch, [%cur_reg + AOFF_task_thread + AOFF_thread_w_saved];
 
 #ifdef __SMP__
 #define LOAD_CURRENT4M(dest_reg, idreg) \
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/audioio.h linux/include/asm-sparc64/audioio.h
--- v2.3.15/linux/include/asm-sparc64/audioio.h	Mon Jul  5 20:35:18 1999
+++ linux/include/asm-sparc64/audioio.h	Tue Aug 31 11:23:30 1999
@@ -237,6 +237,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/tqueue.h>
 #include <linux/wait.h>
@@ -299,6 +300,8 @@
 
         /* Hack to make it look like we support variable size buffers. */
         int buffer_size;
+
+        int mixer_modify_counter;
 };
 
 struct sparcaudio_operations
@@ -432,23 +435,6 @@
 
 #endif
 
-/* Mixer helper ioctls */
-#define right(a) (((a >> 8) & 0xff) % 101)
-#define left(a) ((a & 0xff) % 101)
-
-/* Macros to convert between mixer stereo volumes and gain (mono) */
-#define s_to_m(a) ((((left(a) + right(a)) * 255) / 200) % 256)
-#define m_to_s(a) ((a * 100 / 255) + ((a * 100 / 255) << 8))
-
-/* convert mixer stereo volume to balance */
-#define s_to_b(a) (s_to_g(a) == 0) ? 32 : ((left(a) * AUDIO_RIGHT_BALANCE / (left(a) + right(a))))
-
-/* convert mixer stereo volume to audio gain */
-#define s_to_g(a) ((((right(a) + left(a)) * 255) / 200) % 256)
-
-/* convert gain a and balance b to mixer volume */
-#define b_to_s(a,b) (((((b * a * 200) / (AUDIO_RIGHT_BALANCE * 255)) % 100) << 8) + ((((AUDIO_RIGHT_BALANCE - b) * a * 200) / (AUDIO_RIGHT_BALANCE * 255)) % 100))
-
 /* Device minor numbers */
 
 #define SPARCAUDIO_MIXER_MINOR 0
@@ -514,4 +500,147 @@
 
 #define I_GETSIG _IOR('S',012,int)
 #define I_GETSIG_SOLARIS (('S'<<8)|12)
-#endif
+
+/* Conversion between Sun and OSS volume settings */
+static __inline__ 
+int OSS_LEFT(int value)
+{
+  return ((value & 0xff) % 101);
+}
+
+static __inline__ 
+int OSS_RIGHT(int value)
+{
+  return  (((value >> 8) & 0xff) % 101);
+}
+
+static __inline__ 
+int O_TO_S(int value)
+{
+  return value * 255 / 100;
+}
+
+static __inline__ 
+int S_TO_O(int value)
+{
+  return value * 100 / 255;
+}
+
+static __inline__ 
+int OSS_TO_GAIN(int value)
+{
+  int l = O_TO_S(OSS_LEFT(value));
+  int r = O_TO_S(OSS_RIGHT(value));
+  return ((l > r) ? l : r);
+}
+
+static __inline__ 
+int OSS_TO_LGAIN(int value)
+{
+  int l = O_TO_S(OSS_LEFT(value));
+  int r = O_TO_S(OSS_RIGHT(value));
+  return ((l < r) ? l : r);
+}
+
+static __inline__ 
+int OSS_TO_BAL(int value) 
+{
+  if (!OSS_TO_GAIN(value))
+    return AUDIO_MID_BALANCE;
+  if (!OSS_TO_LGAIN(value)) {
+    if (OSS_TO_GAIN(value) == OSS_TO_GAIN(OSS_RIGHT(value)))
+      return AUDIO_RIGHT_BALANCE;
+    else
+      return AUDIO_LEFT_BALANCE;
+  }
+  if (OSS_TO_GAIN(value) == OSS_TO_GAIN(OSS_RIGHT(value)))
+    return ((OSS_TO_GAIN(value) - OSS_TO_LGAIN(value)) >> AUDIO_BALANCE_SHIFT)
+      + AUDIO_MID_BALANCE;
+  else
+    return AUDIO_MID_BALANCE - ((OSS_TO_GAIN(value) - OSS_TO_LGAIN(value)) 
+				>> AUDIO_BALANCE_SHIFT);
+}
+
+static __inline__ 
+int BAL_TO_OSS(int value, unsigned char balance)
+{
+  int l, r, adj;
+  if (balance > 63) balance = 63;
+  if (balance < AUDIO_MID_BALANCE) {
+    l = (int)value * 100 / 255 + ((value * 100 % 255) > 0);
+    adj = ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT);
+    if (adj < value)
+      r = (int)(value - adj)
+	* 100 / 255;
+    else r = 0;
+  } else if (balance > AUDIO_MID_BALANCE) {
+    r = (int)value * 100 / 255 + ((value * 100 % 255) > 0);
+    adj = ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT);
+    if (adj < value)
+      l = (int)(value - adj)
+	* 100 / 255;
+    else l = 0;
+  } else {
+    l = r = (int)value * 100 / 255 + ((value * 100 % 255) > 0);
+  }
+
+  return ((r << 8) + l);
+}
+
+/* OSS mixer ioctl port handling */
+static __inline__
+int OSS_PORT_AUDIO(struct sparcaudio_driver *drv, unsigned int set) 
+{
+  int p;
+  if (drv->ops->get_output_port) {
+    p = drv->ops->get_output_port(drv);
+    if (p & set)
+      return 0x6464;
+  }  
+  return 0;
+}
+
+static __inline__
+int OSS_IPORT_AUDIO(struct sparcaudio_driver *drv, unsigned int set) 
+{
+  int p;
+  if (drv->ops->get_input_port) {
+    p = drv->ops->get_input_port(drv);
+    if (p & set)
+      return 0x6464;
+  }  
+  return 0;
+}
+
+static __inline__ 
+void OSS_TWIDDLE_PORT(struct sparcaudio_driver *drv, unsigned int ioctl, 
+		      unsigned int port, unsigned int set, unsigned int value) 
+{
+  if (ioctl == port) {
+    int p;
+    if (drv->ops->get_output_port && drv->ops->set_output_port) {
+      p = drv->ops->get_output_port(drv);
+      if ((value == 0) || ((p & set) && (OSS_LEFT(value) < 100)))
+	drv->ops->set_output_port(drv, p & ~(set));
+      else
+	drv->ops->set_output_port(drv, p | set);
+    }
+  }
+}
+
+static __inline__ 
+void OSS_TWIDDLE_IPORT(struct sparcaudio_driver *drv, unsigned int ioctl, 
+		      unsigned int port, unsigned int set, unsigned int value) 
+{
+  if (ioctl == port) {
+    int p;
+    if (drv->ops->get_input_port && drv->ops->set_input_port) {
+      p = drv->ops->get_input_port(drv);
+      if ((value == 0) || ((p & set) && (OSS_LEFT(value) < 100)))
+	drv->ops->set_input_port(drv, p & ~(set));
+      else
+	drv->ops->set_input_port(drv, p | set);
+    }
+  }
+}
+#endif /* _AUDIOIO_H_ */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/dma.h linux/include/asm-sparc64/dma.h
--- v2.3.15/linux/include/asm-sparc64/dma.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/dma.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: dma.h,v 1.13 1998/12/16 04:33:55 davem Exp $
+/* $Id: dma.h,v 1.14 1999/08/30 10:14:36 davem Exp $
  * include/asm-sparc64/dma.h
  *
  * Copyright 1996 (C) David S. Miller (davem@caip.rutgers.edu)
@@ -187,5 +187,13 @@
 extern int get_dma_list(char *);
 extern int request_dma(unsigned int, __const__ char *);
 extern void free_dma(unsigned int);
+
+/* From PCI */
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy 	(0)
+#endif
 
 #endif /* !(_ASM_SPARC64_DMA_H) */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/ebus.h linux/include/asm-sparc64/ebus.h
--- v2.3.15/linux/include/asm-sparc64/ebus.h	Tue Aug  4 16:03:35 1998
+++ linux/include/asm-sparc64/ebus.h	Tue Aug 31 11:23:30 1999
@@ -1,12 +1,14 @@
-/* $Id: ebus.h,v 1.8 1998/05/07 21:00:27 ecd Exp $
+/* $Id: ebus.h,v 1.9 1999/08/30 10:14:37 davem Exp $
  * ebus.h: PCI to Ebus pseudo driver software state.
  *
  * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
  */
 
 #ifndef __SPARC64_EBUS_H
 #define __SPARC64_EBUS_H
 
+#include <asm/pbm.h>
 #include <asm/oplib.h>
 
 struct linux_ebus_child {
@@ -15,7 +17,7 @@
 	struct linux_ebus		*bus;
 	int				 prom_node;
 	char				 prom_name[64];
-	unsigned long			 base_address[PROMREG_MAX];
+	struct resource			 resource[PROMREG_MAX];
 	int				 num_addrs;
 	unsigned int			 irqs[PROMINTR_MAX];
 	int				 num_irqs;
@@ -27,7 +29,7 @@
 	struct linux_ebus		*bus;
 	int				 prom_node;
 	char				 prom_name[64];
-	unsigned long			 base_address[PROMREG_MAX];
+	struct resource			 resource[PROMREG_MAX];
 	int				 num_addrs;
 	unsigned int			 irqs[PROMINTR_MAX];
 	int				 num_irqs;
@@ -36,8 +38,9 @@
 struct linux_ebus {
 	struct linux_ebus		*next;
 	struct linux_ebus_device	*devices;
-	struct linux_pbm_info		*parent;
+	struct pci_pbm_info		*parent;
 	struct pci_dev			*self;
+	int				 index;
 	int				 prom_node;
 	char				 prom_name[64];
 	struct linux_prom_ebus_ranges	 ebus_ranges[PROMREG_MAX];
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/fbio.h linux/include/asm-sparc64/fbio.h
--- v2.3.15/linux/include/asm-sparc64/fbio.h	Fri Jul 10 15:18:32 1998
+++ linux/include/asm-sparc64/fbio.h	Tue Aug 31 11:23:30 1999
@@ -35,6 +35,8 @@
 
 /* Does not seem to be listed in the Sun file either */
 #define FBTYPE_CREATOR          22
+#define FBTYPE_PCI_IGA1682	23
+#define FBTYPE_P9100COLOR	24
 
 #define FBTYPE_PCI_GENERIC	1000
 #define FBTYPE_PCI_MACH64	1001
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/floppy.h linux/include/asm-sparc64/floppy.h
--- v2.3.15/linux/include/asm-sparc64/floppy.h	Wed Aug  4 15:39:46 1999
+++ linux/include/asm-sparc64/floppy.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.19 1999/08/03 08:01:15 davem Exp $
+/* $Id: floppy.h,v 1.22 1999/08/31 07:02:12 davem Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -276,16 +276,19 @@
 
 static unsigned char sun_pci_fd_inb(unsigned long port)
 {
+	udelay(5);
 	return inb(port);
 }
 
 static void sun_pci_fd_outb(unsigned char val, unsigned long port)
 {
+	udelay(5);
 	outb(val, port);
 }
 
 static void sun_pci_fd_broken_outb(unsigned char val, unsigned long port)
 {
+	udelay(5);
 	/*
 	 * XXX: Due to SUN's broken floppy connector on AX and AXi
 	 *      we need to turn on MOTOR_0 also, if the floppy is
@@ -304,6 +307,7 @@
 #ifdef PCI_FDC_SWAP_DRIVES
 static void sun_pci_fd_lde_broken_outb(unsigned char val, unsigned long port)
 {
+	udelay(5);
 	/*
 	 * XXX: Due to SUN's broken floppy connector on AX and AXi
 	 *      we need to turn on MOTOR_0 also, if the floppy is
@@ -326,9 +330,9 @@
 	unsigned int dcsr;
 
 	writel(EBUS_DCSR_RESET, &sun_pci_fd_ebus_dma->dcsr);
-
+	udelay(1);
 	dcsr = EBUS_DCSR_BURST_SZ_16 | EBUS_DCSR_TCI_DIS |
-	       EBUS_DCSR_EN_CNT | EBUS_DCSR_INT_EN;
+	       EBUS_DCSR_EN_CNT;
 	writel(dcsr, (unsigned long)&sun_pci_fd_ebus_dma->dcsr);
 }
 
@@ -346,12 +350,19 @@
 	unsigned int dcsr;
 
 	dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
-	while (dcsr & EBUS_DCSR_DRAIN)
-		dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
-	dcsr &= ~(EBUS_DCSR_EN_DMA);
-	if (dcsr & EBUS_DCSR_ERR_PEND)
-		sun_pci_fd_reset_dma();
-	writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
+	if (dcsr & EBUS_DCSR_EN_DMA) {
+		while (dcsr & EBUS_DCSR_DRAIN) {
+			udelay(1);
+			dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
+		}
+		dcsr &= ~(EBUS_DCSR_EN_DMA);
+		writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
+		if (dcsr & EBUS_DCSR_ERR_PEND) {
+			sun_pci_fd_reset_dma();
+			dcsr &= ~(EBUS_DCSR_ERR_PEND);
+			writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
+		}
+	}
 }
 
 static void sun_pci_fd_set_dma_mode(int mode)
@@ -359,6 +370,11 @@
 	unsigned int dcsr;
 
 	dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
+	if (readl(&sun_pci_fd_ebus_dma->dbcr)) {
+		sun_pci_fd_reset_dma();
+		writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
+	}
+
 	dcsr |= EBUS_DCSR_EN_CNT | EBUS_DCSR_TC;
 	/*
 	 * For EBus WRITE means to system memory, which is
@@ -384,7 +400,15 @@
 
 static unsigned int sun_pci_get_dma_residue(void)
 {
-	return readl(&sun_pci_fd_ebus_dma->dbcr);
+	unsigned int dcsr, res;
+
+	res = readl(&sun_pci_fd_ebus_dma->dbcr);
+	if (res != 0) {
+		dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
+		sun_pci_fd_reset_dma();
+		writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
+	}
+	return res;
 }
 
 static void sun_pci_fd_enable_irq(void)
@@ -525,7 +549,7 @@
 
 static struct linux_prom_registers fd_regs[2];
 
-__initfunc(static unsigned long sun_floppy_init(void))
+static unsigned long __init sun_floppy_init(void)
 {
 	char state[128];
 	int fd_node, num_regs;
@@ -548,7 +572,9 @@
 #ifdef CONFIG_PCI
 		struct linux_ebus *ebus;
 		struct linux_ebus_device *edev = 0;
+		unsigned long config = 0;
 		unsigned long auxio_reg;
+		unsigned char cfg;
 
 		for_each_ebus(ebus) {
 			for_each_ebusdev(edev, ebus) {
@@ -565,26 +591,17 @@
 		if(!strncmp(state, "disabled", 8))
 			return 0;
 			
-		if (check_region(edev->base_address[1],
-				 sizeof(struct linux_ebus_dma))) {
-			printk("sun_floppy_init: can't get region at %016lx\n",
-			       edev->base_address[1]);
-			return 0;
-		}
-		request_region(edev->base_address[1],
-			       sizeof(struct linux_ebus_dma), "floppy DMA");
-
-		sun_fdc = (struct sun_flpy_controller *)edev->base_address[0];
+		sun_fdc = (struct sun_flpy_controller *)edev->resource[0].start;
 		FLOPPY_IRQ = edev->irqs[0];
 
 		/* Make sure the high density bit is set, some systems
 		 * (most notably Ultra5/Ultra10) come up with it clear.
 		 */
-		auxio_reg = edev->base_address[2];
+		auxio_reg = edev->resource[2].start;
 		writel(readl(auxio_reg)|0x2, auxio_reg);
 
 		sun_pci_fd_ebus_dma = (struct linux_ebus_dma *)
-							edev->base_address[1];
+			edev->resource[1].start;
 		sun_pci_fd_reset_dma();
 
 		sun_fdops.fd_inb = sun_pci_fd_inb;
@@ -622,57 +639,62 @@
 		if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 1))
 			sun_floppy_types[1] = 4;
 
-#ifdef PCI_FDC_SWAP_DRIVES
 		/*
-		 * If only Floppy 1 is present, swap drives.
+		 * Find NS87303 SuperIO config registers (through ecpp).
 		 */
-		if (!sun_floppy_types[0] && sun_floppy_types[1]) {
-			unsigned long config = 0;
-			unsigned char tmp;
-
-			for_each_ebus(ebus) {
-				for_each_ebusdev(edev, ebus) {
-					if (!strcmp(edev->prom_name, "ecpp")) {
-						config = edev->base_address[1];
-						goto config_done;
-					}
+		for_each_ebus(ebus) {
+			for_each_ebusdev(edev, ebus) {
+				if (!strcmp(edev->prom_name, "ecpp")) {
+					config = edev->resource[1].start;
+					goto config_done;
 				}
 			}
-		config_done:
+		}
+	config_done:
 
-			/*
-			 * Sanity check, is this really the NS87303?
-			 */
-			switch (config & 0x3ff) {
-			case 0x02e:
-			case 0x15c:
-			case 0x26e:
-			case 0x398:
-				break;
-			default:
-				config = 0;
-			}
+		/*
+		 * Sanity check, is this really the NS87303?
+		 */
+		switch (config & 0x3ff) {
+		case 0x02e:
+		case 0x15c:
+		case 0x26e:
+		case 0x398:
+			break;
+		default:
+			config = 0;
+		}
+
+		if (!config)
+			return sun_floppy_types[0];
 
-			if (!config)
-				return sun_floppy_types[0];
+		/* Enable PC-AT mode. */
+		cfg = ns87303_readb(config, ASC);
+		cfg |= 0xc0;
+		ns87303_writeb(config, ASC, cfg);
 
+#ifdef PCI_FDC_SWAP_DRIVES
+		/*
+		 * If only Floppy 1 is present, swap drives.
+		 */
+		if (!sun_floppy_types[0] && sun_floppy_types[1]) {
 			/*
 			 * Set the drive exchange bit in FCR on NS87303,
 			 * make shure other bits are sane before doing so.
 			 */
-			tmp = ns87303_readb(config, FER);
-			tmp &= ~(FER_EDM);
-			ns87303_writeb(config, FER, tmp);
-			tmp = ns87303_readb(config, ASC);
-			tmp &= ~(ASC_DRV2_SEL);
-			ns87303_writeb(config, ASC, tmp);
-			tmp = ns87303_readb(config, FCR);
-			tmp |= FCR_LDE;
-			ns87303_writeb(config, FCR, tmp);
+			cfg = ns87303_readb(config, FER);
+			cfg &= ~(FER_EDM);
+			ns87303_writeb(config, FER, cfg);
+			cfg = ns87303_readb(config, ASC);
+			cfg &= ~(ASC_DRV2_SEL);
+			ns87303_writeb(config, ASC, cfg);
+			cfg = ns87303_readb(config, FCR);
+			cfg |= FCR_LDE;
+			ns87303_writeb(config, FCR, cfg);
 
-			tmp = sun_floppy_types[0];
+			cfg = sun_floppy_types[0];
 			sun_floppy_types[0] = sun_floppy_types[1];
-			sun_floppy_types[1] = tmp;
+			sun_floppy_types[1] = cfg;
 
 			if (sun_pci_broken_drive != -1) {
 				sun_pci_broken_drive = 1 - sun_pci_broken_drive;
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/ide.h linux/include/asm-sparc64/ide.h
--- v2.3.15/linux/include/asm-sparc64/ide.h	Mon Aug  9 11:29:37 1999
+++ linux/include/asm-sparc64/ide.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: ide.h,v 1.15 1999/08/08 01:38:18 davem Exp $
+/* $Id: ide.h,v 1.16 1999/08/30 10:14:42 davem Exp $
  * ide.h: Ultra/PCI specific IDE glue.
  *
  * Copyright (C) 1997  David S. Miller (davem@caip.rutgers.edu)
@@ -135,50 +135,62 @@
 #define insw(port, buf, nr) ide_insw((port), (buf), (nr))
 #define outsw(port, buf, nr) ide_outsw((port), (buf), (nr))
 
+static __inline__ unsigned int inw_be(unsigned long addr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduha [%1] %2, %0"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
 static __inline__ void ide_insw(unsigned long port,
 				void *dst,
 				unsigned long count)
 {
-	volatile unsigned short *data_port;
 	unsigned long end = (unsigned long)dst + (count << 1);
 	u16 *ps = dst;
 	u32 *pi;
 
-	data_port = (volatile unsigned short *)port;
-
 	if(((u64)ps) & 0x2) {
-		*ps++ = *data_port;
+		*ps++ = inw_be(port);
 		count--;
 	}
 	pi = (u32 *)ps;
 	while(count >= 2) {
 		u32 w;
 
-		w  = (*data_port) << 16;
-		w |= (*data_port);
+		w  = inw_be(port) << 16;
+		w |= inw_be(port);
 		*pi++ = w;
 		count -= 2;
 	}
 	ps = (u16 *)pi;
 	if(count)
-		*ps++ = *data_port;
+		*ps++ = inw_be(port);
 
 	__flush_dcache_range((unsigned long)dst, end);
 }
 
+static __inline__ void outw_be(unsigned short w, unsigned long addr)
+{
+	__asm__ __volatile__("stha %0, [%1] %2"
+			     : /* no outputs */
+			     : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
 static __inline__ void ide_outsw(unsigned long port,
 				 const void *src,
 				 unsigned long count)
 {
-	volatile unsigned short *data_port;
 	unsigned long end = (unsigned long)src + (count << 1);
 	const u16 *ps = src;
 	const u32 *pi;
 
-	data_port = (volatile unsigned short *)port;
-
 	if(((u64)src) & 0x2) {
-		*data_port = *ps++;
+		outw_be(*ps++, port);
 		count--;
 	}
 	pi = (const u32 *)ps;
@@ -186,13 +198,13 @@
 		u32 w;
 
 		w = *pi++;
-		*data_port = (w >> 16);
-		*data_port = w;
+		outw_be((w >> 16), port);
+		outw_be(w, port);
 		count -= 2;
 	}
 	ps = (const u16 *)pi;
 	if(count)
-		*data_port = *ps;
+		outw_be(*ps, port);
 
 	__flush_dcache_range((unsigned long)src, end);
 }
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/io.h linux/include/asm-sparc64/io.h
--- v2.3.15/linux/include/asm-sparc64/io.h	Sat May 15 11:12:10 1999
+++ linux/include/asm-sparc64/io.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.20 1999/05/14 07:23:18 davem Exp $ */
+/* $Id: io.h,v 1.21 1999/08/30 10:14:44 davem Exp $ */
 #ifndef __SPARC64_IO_H
 #define __SPARC64_IO_H
 
@@ -61,7 +61,7 @@
 
 	__asm__ __volatile__("lduba [%1] %2, %0"
 			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PL));
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 
 	return ret;
 }
@@ -72,7 +72,7 @@
 
 	__asm__ __volatile__("lduha [%1] %2, %0"
 			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PL));
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 
 	return ret;
 }
@@ -83,7 +83,7 @@
 
 	__asm__ __volatile__("lduwa [%1] %2, %0"
 			     : "=r" (ret)
-			     : "r" (addr), "i" (ASI_PL));
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 
 	return ret;
 }
@@ -92,21 +92,21 @@
 {
 	__asm__ __volatile__("stba %0, [%1] %2"
 			     : /* no outputs */
-			     : "r" (b), "r" (addr), "i" (ASI_PL));
+			     : "r" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
 extern __inline__ void outw(unsigned short w, unsigned long addr)
 {
 	__asm__ __volatile__("stha %0, [%1] %2"
 			     : /* no outputs */
-			     : "r" (w), "r" (addr), "i" (ASI_PL));
+			     : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
 extern __inline__ void outl(unsigned int l, unsigned long addr)
 {
 	__asm__ __volatile__("stwa %0, [%1] %2"
 			     : /* no outputs */
-			     : "r" (l), "r" (addr), "i" (ASI_PL));
+			     : "r" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
 #define inb_p inb
@@ -190,19 +190,11 @@
 	return retval;
 }
 
-/*
- * On the sparc we have the whole physical IO address space mapped at all
- * times, so ioremap() and iounmap() do not need to do anything.
+/* On sparc64 we have the whole physical IO address space accessible
+ * using physically addressed loads and stores, so this does nothing.
  */
-extern __inline__ void *ioremap(unsigned long offset, unsigned long size)
-{
-	return __va(offset);
-}
-
-extern __inline__ void iounmap(void *addr)
-{
-}
-
+#define ioremap(__offset, __size)	((void *)(__offset))
+#define iounmap(__addr)			do { } while(0)
 
 extern void sparc_ultra_mapioaddr(unsigned long physaddr,
 				  unsigned long virt_addr,
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/iommu.h linux/include/asm-sparc64/iommu.h
--- v2.3.15/linux/include/asm-sparc64/iommu.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/iommu.h	Tue Aug 31 11:23:30 1999
@@ -39,7 +39,8 @@
 #define IOPTE_64K           0x2000000000000000 /* IOPTE is for 64k page            */
 #define IOPTE_STBUF         0x1000000000000000 /* DVMA can use streaming buffer    */
 #define IOPTE_INTRA         0x0800000000000000 /* SBUS slot-->slot direct transfer */
-#define IOPTE_PAGE          0x000001ffffffe000 /* Physical page number (PA[40:13]) */
+#define IOPTE_CONTEXT	    0x07ff800000000000 /* Context number		   */
+#define IOPTE_PAGE          0x00007fffffffe000 /* Physical page number (PA[40:13]) */
 #define IOPTE_CACHE         0x0000000000000010 /* Cached (in UPA E-cache)          */
 #define IOPTE_WRITE         0x0000000000000002 /* Writeable                        */
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/irq.h linux/include/asm-sparc64/irq.h
--- v2.3.15/linux/include/asm-sparc64/irq.h	Mon Jul 19 13:12:47 1999
+++ linux/include/asm-sparc64/irq.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: irq.h,v 1.14 1998/12/19 11:05:41 davem Exp $
+/* $Id: irq.h,v 1.15 1999/08/30 10:14:48 davem Exp $
  * irq.h: IRQ registers on the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -61,19 +61,27 @@
 /*0x08*/void *irq_info;
 
 	/* Sun5 Interrupt Clear Register. */
-/*0x10*/unsigned int *iclr;
+/*0x10*/volatile unsigned int *iclr;
 
 	/* Sun5 Interrupt Mapping Register. */
-/*0x18*/unsigned int *imap;
+/*0x18*/volatile unsigned int *imap;
 
 };
 
+/* Only 8-bits are available, be careful.  -DaveM */
+#define IBF_DMA_SYNC	0x01	/* DMA synchronization behind PCI bridge needed. */
+#define IBF_PCI		0x02	/* Indicates PSYCHO/SABRE/SCHIZO PCI interrupt.	 */
+#define IBF_ACTIVE	0x04	/* This interrupt is active and has a handler.	 */
+#define IBF_MULTI	0x08	/* On PCI, indicates shared bucket.		 */
+
 #define NUM_IVECS	8192
 extern struct ino_bucket ivector_table[NUM_IVECS];
 
 #define __irq_ino(irq) \
         (((struct ino_bucket *)(unsigned long)(irq)) - &ivector_table[0])
 #define __irq_pil(irq) ((struct ino_bucket *)(unsigned long)(irq))->pil
+#define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq))
+#define __irq(bucket) ((unsigned int)(unsigned long)(bucket))
 
 static __inline__ char *__irq_itoa(unsigned int irq)
 {
@@ -89,7 +97,7 @@
 extern void enable_irq(unsigned int);
 extern void init_timers(void (*lvl10_irq)(int, void *, struct pt_regs *),
 			unsigned long *);
-extern unsigned int build_irq(int pil, int inofixup, unsigned int *iclr, unsigned int *imap);
+extern unsigned int build_irq(int pil, int inofixup, volatile unsigned int *iclr, volatile unsigned int *imap);
 extern unsigned int sbus_build_irq(void *sbus, unsigned int ino);
 extern unsigned int psycho_build_irq(void *psycho, int imap_off, int ino, int need_dma_sync);
 
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/mostek.h linux/include/asm-sparc64/mostek.h
--- v2.3.15/linux/include/asm-sparc64/mostek.h	Mon Apr 14 16:28:23 1997
+++ linux/include/asm-sparc64/mostek.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: mostek.h,v 1.2 1997/03/25 03:58:30 davem Exp $
+/* $Id: mostek.h,v 1.3 1999/08/30 10:14:50 davem Exp $
  * mostek.h:  Describes the various Mostek time of day clock registers.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -35,22 +35,38 @@
 /* The Mostek 48t02 real time clock and NVRAM chip. The registers
  * other than the control register are in binary coded decimal. Some
  * control bits also live outside the control register.
+ *
+ * We now deal with physical addresses for I/O to the chip. -DaveM
  */
+static __inline__ u8 mostek_read(unsigned long addr)
+{
+	u8 ret;
+
+	__asm__ __volatile__("lduba	[%1] %2, %0"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+	return ret;
+}
+
+static __inline__ void mostek_write(unsigned long addr, u8 val)
+{
+	__asm__ __volatile__("stba	%0, [%1] %2"
+			     : /* no outputs */
+			     : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+#define MOSTEK_EEPROM		0x0000UL
+#define MOSTEK_IDPROM		0x07d8UL
+#define MOSTEK_CREG		0x07f8UL
+#define MOSTEK_SEC		0x07f9UL
+#define MOSTEK_MIN		0x07faUL
+#define MOSTEK_HOUR		0x07fbUL
+#define MOSTEK_DOW		0x07fcUL
+#define MOSTEK_DOM		0x07fdUL
+#define MOSTEK_MONTH		0x07feUL
+#define MOSTEK_YEAR		0x07ffUL
 
-struct mostek48t02 {
-	volatile char eeprom[2008];	/* This is the eeprom, don't touch! */
-	struct idprom idprom;		/* The idprom lives here. */
-	volatile unsigned char creg;	/* Control register */
-	volatile unsigned char sec;	/* Seconds (0-59) */
-	volatile unsigned char min;	/* Minutes (0-59) */
-	volatile unsigned char hour;	/* Hour (0-23) */
-	volatile unsigned char dow;	/* Day of the week (1-7) */
-	volatile unsigned char dom;	/* Day of the month (1-31) */
-	volatile unsigned char month;	/* Month of year (1-12) */
-	volatile unsigned char year;	/* Year (0-99) */
-};
-
-extern struct mostek48t02 *mstk48t02_regs;
+extern unsigned long mstk48t02_regs;
 
 /* Control register values. */
 #define	MSTK_CREG_WRITE	0x80	/* Must set this before placing values. */
@@ -79,48 +95,51 @@
 #define MSTK_DECIMAL_TO_REGVAL(x)  ((((x) / 0x0A) << 0x04) + ((x) % 0x0A))
 
 /* Generic register set and get macros for internal use. */
-#define MSTK_GET(regs,var,mask) (MSTK_REGVAL_TO_DECIMAL(regs->var & MSTK_ ## mask ## _MASK))
-#define MSTK_SET(regs,var,value,mask) do { regs->var &= ~(MSTK_ ## mask ## _MASK); regs->var |= MSTK_DECIMAL_TO_REGVAL(value) & (MSTK_ ## mask ## _MASK); } while (0)
+#define MSTK_GET(regs,name)	\
+	(MSTK_REGVAL_TO_DECIMAL(mostek_read(regs + MOSTEK_ ## name) & MSTK_ ## name ## _MASK))
+#define MSTK_SET(regs,name,value) \
+do {	u8 __val = mostek_read(regs + MOSTEK_ ## name); \
+	__val &= ~(MSTK_ ## name ## _MASK); \
+	__val |= (MSTK_DECIMAL_TO_REGVAL(value) & \
+		  (MSTK_ ## name ## _MASK)); \
+	mostek_write(regs + MOSTEK_ ## name, __val); \
+} while(0)
 
 /* Macros to make register access easier on our fingers. These give you
  * the decimal value of the register requested if applicable. You pass
  * the a pointer to a 'struct mostek48t02'.
  */
-#define	MSTK_REG_CREG(regs)	(regs->creg)
-#define	MSTK_REG_SEC(regs)	MSTK_GET(regs,sec,SEC)
-#define	MSTK_REG_MIN(regs)	MSTK_GET(regs,min,MIN)
-#define	MSTK_REG_HOUR(regs)	MSTK_GET(regs,hour,HOUR)
-#define	MSTK_REG_DOW(regs)	MSTK_GET(regs,dow,DOW)
-#define	MSTK_REG_DOM(regs)	MSTK_GET(regs,dom,DOM)
-#define	MSTK_REG_MONTH(regs)	MSTK_GET(regs,month,MONTH)
-#define	MSTK_REG_YEAR(regs)	MSTK_GET(regs,year,YEAR)
-
-#define	MSTK_SET_REG_SEC(regs,value)	MSTK_SET(regs,sec,value,SEC)
-#define	MSTK_SET_REG_MIN(regs,value)	MSTK_SET(regs,min,value,MIN)
-#define	MSTK_SET_REG_HOUR(regs,value)	MSTK_SET(regs,hour,value,HOUR)
-#define	MSTK_SET_REG_DOW(regs,value)	MSTK_SET(regs,dow,value,DOW)
-#define	MSTK_SET_REG_DOM(regs,value)	MSTK_SET(regs,dom,value,DOM)
-#define	MSTK_SET_REG_MONTH(regs,value)	MSTK_SET(regs,month,value,MONTH)
-#define	MSTK_SET_REG_YEAR(regs,value)	MSTK_SET(regs,year,value,YEAR)
+#define	MSTK_REG_CREG(regs)	(mostek_read((regs) + MOSTEK_CREG))
+#define	MSTK_REG_SEC(regs)	MSTK_GET(regs,SEC)
+#define	MSTK_REG_MIN(regs)	MSTK_GET(regs,MIN)
+#define	MSTK_REG_HOUR(regs)	MSTK_GET(regs,HOUR)
+#define	MSTK_REG_DOW(regs)	MSTK_GET(regs,DOW)
+#define	MSTK_REG_DOM(regs)	MSTK_GET(regs,DOM)
+#define	MSTK_REG_MONTH(regs)	MSTK_GET(regs,MONTH)
+#define	MSTK_REG_YEAR(regs)	MSTK_GET(regs,YEAR)
+
+#define	MSTK_SET_REG_SEC(regs,value)	MSTK_SET(regs,SEC,value)
+#define	MSTK_SET_REG_MIN(regs,value)	MSTK_SET(regs,MIN,value)
+#define	MSTK_SET_REG_HOUR(regs,value)	MSTK_SET(regs,HOUR,value)
+#define	MSTK_SET_REG_DOW(regs,value)	MSTK_SET(regs,DOW,value)
+#define	MSTK_SET_REG_DOM(regs,value)	MSTK_SET(regs,DOM,value)
+#define	MSTK_SET_REG_MONTH(regs,value)	MSTK_SET(regs,MONTH,value)
+#define	MSTK_SET_REG_YEAR(regs,value)	MSTK_SET(regs,YEAR,value)
 
 
 /* The Mostek 48t08 clock chip. Found on Sun4m's I think. It has the
  * same (basically) layout of the 48t02 chip except for the extra
  * NVRAM on board (8 KB against the 48t02's 2 KB).
  */
-struct mostek48t08 {
-	char offset[6*1024];         /* Magic things may be here, who knows? */
-	struct mostek48t02 regs;     /* Here is what we are interested in.   */
-};
-extern struct mostek48t08 *mstk48t08_regs;
+#define MOSTEK_48T08_OFFSET	0x0000UL	/* Lower NVRAM portions */
+#define MOSTEK_48T08_48T02	0x1800UL	/* Offset to 48T02 chip */
+extern unsigned long mstk48t08_regs;
 
 /* SUN5 systems usually have 48t59 model clock chipsets.  But we keep the older
  * clock chip definitions around just in case.
  */
-struct mostek48t59 {
-	char offset[6*1024];
-	struct mostek48t02 regs;
-};
-extern struct mostek48t59 *mstk48t59_regs;
+#define MOSTEK_48T59_OFFSET	0x0000UL	/* Lower NVRAM portions */
+#define MOSTEK_48T59_48T02	0x1800UL	/* Offset to 48T02 chip */
+extern unsigned long mstk48t59_regs;
 
 #endif /* !(_SPARC64_MOSTEK_H) */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/parport.h linux/include/asm-sparc64/parport.h
--- v2.3.15/linux/include/asm-sparc64/parport.h	Mon Aug  9 11:29:37 1999
+++ linux/include/asm-sparc64/parport.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: parport.h,v 1.4 1999/08/08 01:38:18 davem Exp $
+/* $Id: parport.h,v 1.5 1999/08/30 10:14:52 davem Exp $
  * parport.h: sparc64 specific parport initialization and dma.
  *
  * Copyright (C) 1999  Eddie C. Dost  (ecd@skynet.be)
@@ -134,13 +134,13 @@
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
 			if (!strcmp(edev->prom_name, "ecpp")) {
-				unsigned long base = edev->base_address[0];
-				unsigned long config = edev->base_address[1];
+				unsigned long base = edev->resource[0].start;
+				unsigned long config = edev->resource[1].start;
 				unsigned char cfg;
 
 				sparc_ebus_dmas[count] =
 						(struct linux_ebus_dma *)
-							edev->base_address[2];
+							edev->resource[2].start;
 				reset_dma(count);
 
 				/* Enable ECP, set bit 2 of the CTR first */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/pbm.h linux/include/asm-sparc64/pbm.h
--- v2.3.15/linux/include/asm-sparc64/pbm.h	Mon Mar 15 16:10:44 1999
+++ linux/include/asm-sparc64/pbm.h	Tue Aug 31 11:23:30 1999
@@ -1,34 +1,92 @@
-/* $Id: pbm.h,v 1.16 1999/03/14 18:13:03 davem Exp $
- * pbm.h: U2P PCI bus module pseudo driver software state.
+/* $Id: pbm.h,v 1.17 1999/08/30 10:14:54 davem Exp $
+ * pbm.h: UltraSparc PCI controller software state.
  *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
  */
 
 #ifndef __SPARC64_PBM_H
 #define __SPARC64_PBM_H
 
+#include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/ioport.h>
 
-#include <asm/psycho.h>
+#include <asm/io.h>
+#include <asm/page.h>
 #include <asm/oplib.h>
+#include <asm/spinlock.h>
 
-struct linux_pbm_info;
+/* The abstraction used here is that there are PCI controllers,
+ * each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules
+ * underneath.  Each PCI controller has a single IOMMU shared
+ * by the PCI bus modules underneath, and if a streaming buffer
+ * is present, each PCI bus module has it's own. (ie. the IOMMU
+ * is shared between PBMs, the STC is not)  Furthermore, each
+ * PCI bus module controls it's own autonomous PCI bus.
+ */
+
+struct pci_controller_info;
+
+/* This contains the software state necessary to drive a PCI
+ * controller's IOMMU.
+ */
+struct pci_iommu {
+	/* This protects the controller's IOMMU and all
+	 * streaming buffers underneath.
+	 */
+	spinlock_t	lock;
+
+	/* Context allocator. */
+	unsigned int	iommu_cur_ctx;
+
+	/* IOMMU page table, a linear array of ioptes. */
+	iopte_t		*page_table;	/* The page table itself. */
+	int		page_table_sz;	/* How many pages does it map? */
+
+	/* Base PCI memory space address where IOMMU mappings
+	 * begin.
+	 */
+	u32		page_table_map_base;
+
+	/* IOMMU Controller Registers */
+	int		iommu_has_ctx_flush;	/* Feature test. */
+	unsigned long	iommu_control;		/* IOMMU control register */
+	unsigned long	iommu_tsbbase;		/* IOMMU page table base register */
+	unsigned long	iommu_flush;		/* IOMMU page flush register */
+	unsigned long	iommu_ctxflush;		/* IOMMU context flush register */
+
+	/* This is a register in the PCI controller, which if
+	 * read will have no side-effects but will guarentee
+	 * completion of all previous writes into IOMMU/STC.
+	 */
+	unsigned long	write_complete_reg;
+};
 
-/* This is what we use to determine what the PROM has assigned so
- * far, so that we can perform assignments for addresses which
- * were not taken care of by OBP.  See psycho.c for details.
- * Per-PBM these are ordered by start address.
- */
-struct pci_vma {
-	struct pci_vma			*next;
-	struct linux_pbm_info		*pbm;
-	unsigned int			start;
-	unsigned int			end;
-	unsigned int			offset;
-	unsigned int			_pad;
+/* This describes a PCI bus module's streaming buffer. */
+struct pci_strbuf {
+	int		strbuf_enabled;		/* Present and using it? */
+	int		strbuf_has_ctx_flush;	/* Supports context flushing? */
+
+	/* Streaming Buffer Control Registers */
+	unsigned long	strbuf_control;		/* STC control register */
+	unsigned long	strbuf_pflush;		/* STC page flush register */
+	unsigned long	strbuf_fsync;		/* STC flush synchronization reg */
+	unsigned long	strbuf_ctxflush;	/* STC context flush register */
+	unsigned long	strbuf_ctxmatch_base;	/* STC context flush match reg */
+	unsigned long	strbuf_flushflag_pa;	/* Physical address of flush flag */
+	volatile unsigned long *strbuf_flushflag; /* The flush flag itself */
+
+	/* And this is the actual flush flag area.
+	 * We allocate extra because the chips require
+	 * a 64-byte aligned area.
+	 */
+	volatile unsigned long	__flushflag_buf[(64 + (64 - 1)) / sizeof(long)];
 };
 
-struct linux_psycho;
+#define PCI_STC_FLUSHFLAG_INIT(STC) \
+	(*((STC)->strbuf_flushflag) = 0UL)
+#define PCI_STC_FLUSHFLAG_SET(STC) \
+	(*((STC)->strbuf_flushflag) != 0UL)
 
 /* There can be quite a few ranges and interrupt maps on a PCI
  * segment.  Thus...
@@ -36,10 +94,14 @@
 #define PROM_PCIRNG_MAX		64
 #define PROM_PCIIMAP_MAX	64
 
-struct linux_pbm_info {
-	struct linux_psycho		*parent;
-	struct pci_vma			*IO_assignments;
-	struct pci_vma			*MEM_assignments;
+struct pci_pbm_info {
+	/* PCI controller we sit under. */
+	struct pci_controller_info	*parent;
+
+	/* Name used for top-level resources. */
+	char				name[64];
+
+	/* OBP specific information. */
 	int				prom_node;
 	char				prom_name[64];
 	struct linux_prom_pci_ranges	pbm_ranges[PROM_PCIRNG_MAX];
@@ -48,27 +110,54 @@
 	int				num_pbm_intmap;
 	struct linux_prom_pci_intmask	pbm_intmask;
 
+	/* PBM I/O and Memory space resources. */
+	struct resource			io_space;
+	struct resource			mem_space;
+
+	/* This PBM's streaming buffer. */
+	struct pci_strbuf		stc;
+
 	/* Now things for the actual PCI bus probes. */
 	unsigned int			pci_first_busno;
 	unsigned int			pci_last_busno;
-	struct pci_bus			pci_bus;
+	struct pci_bus			*pci_bus;
 };
 
-struct linux_psycho {
-	struct linux_psycho		*next;
-	struct psycho_regs		*psycho_regs;
-	unsigned long			*pci_config_space;
-	unsigned long			*pci_IO_space;
-	unsigned long			*pci_mem_space;
-	u32				upa_portid;
+struct pci_controller_info {
+	/* List of all PCI controllers. */
+	struct pci_controller_info	*next;
+
+	/* Physical address base of controller registers
+	 * and PCI config space.
+	 */
+	unsigned long			controller_regs;
+	unsigned long			config_space;
+
+	/* Opaque 32-bit system bus Port ID. */
+	u32				portid;
+
+	/* Each controller gets a unique index, used mostly for
+	 * error logging purposes.
+	 */
 	int				index;
-	struct linux_pbm_info		pbm_A;
-	struct linux_pbm_info		pbm_B;
+
+	/* The PCI bus modules controlled by us. */
+	struct pci_pbm_info		pbm_A;
+	struct pci_pbm_info		pbm_B;
+
+	/* Operations which are controller specific. */
+	void (*scan_bus)(struct pci_controller_info *);
+	unsigned int (*irq_build)(struct pci_controller_info *, struct pci_dev *, unsigned int);
+	void (*base_address_update)(struct pci_dev *, int);
+	void (*resource_adjust)(struct pci_dev *, struct resource *, struct resource *);
 
 	/* Now things for the actual PCI bus probes. */
+	struct pci_ops			*pci_ops;
 	unsigned int			pci_first_busno;
 	unsigned int			pci_last_busno;
-	struct pci_bus			*pci_bus;
+
+	/* IOMMU state shared by both PBM segments. */
+	struct pci_iommu		iommu;
 
 	void				*starfire_cookie;
 };
@@ -78,17 +167,19 @@
  * code.
  */
 struct pcidev_cookie {
-	struct linux_pbm_info		*pbm;
+	struct pci_pbm_info		*pbm;
+	char				prom_name[64];
 	int				prom_node;
+	struct linux_prom_pci_registers	prom_regs[PROMREG_MAX];
+	int num_prom_regs;
+	struct linux_prom_pci_registers prom_assignments[PROMREG_MAX];
+	int num_prom_assignments;
 };
 
-
-#define PCI_IRQ_IGN	0x000007c0	/* PSYCHO "Int Group Number". */
-#define PCI_IRQ_INO	0x0000003f	/* PSYCHO INO.                */
-
-/* Used by EBus */
-extern unsigned int psycho_irq_build(struct linux_pbm_info *pbm,
-				     struct pci_dev *pdev,
-				     unsigned int full_ino);
+/* Currently these are the same across all PCI controllers
+ * we support.  Someday they may not be...
+ */
+#define PCI_IRQ_IGN	0x000007c0	/* Interrupt Group Number */
+#define PCI_IRQ_INO	0x0000003f	/* Interrupt Number */
 
 #endif /* !(__SPARC64_PBM_H) */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h
--- v2.3.15/linux/include/asm-sparc64/pgtable.h	Mon Aug  2 22:07:16 1999
+++ linux/include/asm-sparc64/pgtable.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.109 1999/08/02 08:57:46 jj Exp $
+/* $Id: pgtable.h,v 1.110 1999/08/30 10:14:57 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -529,6 +529,7 @@
 	char *__dont_touch;
 	unsigned int len;
 	__u32 dvma_addr;
+	__u32 dvma_len;
 };
 
 extern __u32 mmu_get_scsi_one(char *, unsigned long, struct linux_sbus *sbus);
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/psycho.h linux/include/asm-sparc64/psycho.h
--- v2.3.15/linux/include/asm-sparc64/psycho.h	Thu Apr 22 19:24:52 1999
+++ linux/include/asm-sparc64/psycho.h	Wed Dec 31 16:00:00 1969
@@ -1,400 +0,0 @@
-/* $Id: psycho.h,v 1.5 1999/04/01 12:27:28 davem Exp $
- * psycho.h: UltraSparc AX specific PCI definitions.
- *
- * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
- */
-
-#ifndef __SPARC64_PSYCHO_H
-#define __SPARC64_PSYCHO_H
-
-#include <linux/types.h>
-
-/* Ultra AX PSYCHO Register Set, one per controller probed. */
-struct psycho_regs {
-/*0x0000*/	u64	upa_id;		/* PSYCHO UPA Port ID Register	*/
-/*0x0008*/	u64	upa_cfg;	/* PSYCHO UPA Config Register	*/
-/*0x0010*/	u64	control;	/* PSYCHO Control Register	*/
-/*0x0018*/	u64	__pad0;
-/*0x0020*/	u64	ecc_control;	/* ECC Control Register		*/
-/*0x0028*/	u64	__pad1;
-
-		/* Uncorrectable Error Fault Registers */
-/*0x0030*/	u64	ue_afsr;	/* UE Async Fault Status	*/
-/*0x0038*/	u64	ue_afar;	/* UE Async Fault Address	*/
-
-		/* Correctable Error Fault Registers */
-/*0x0040*/	u64	ce_afsr;	/* CE Async Fault Status	*/
-/*0x0048*/	u64	ce_afar;	/* CE Async Fault Address	*/
-
-		u64	__pad2[0x16];
-
-		/* Performance Monitoring Registers */
-/*0x0100*/	u64	pmon_control;
-/*0x0108*/	u64	pmon_counter;
-
-		u64	__pad3[0x1e];
-
-		/* PCI Bus IOMMU lives here */
-/*0x0200*/	u64	iommu_control;	/* IOMMU Control		*/
-/*0x0208*/	u64	iommu_tsbbase;	/* IOMMU TSB Base		*/
-/*0x0210*/	u64	iommu_flush;	/* IOMMU Flush Register		*/
-
-		u64	__pad4[0x13d];
-
-		/* Interrupt mapping/control registers */
-/*0x0c00*/	u64	imap_a_slot0;	/* PCI A Slot 0 Int Mapping	*/
-/*0x0c08*/	u64	imap_a_slot1;	/* PCI A Slot 1 Int Mapping	*/
-/*0x0c10*/	u64	imap_a_slot2;	/* PCI A Slot 2 Int Mapping (IIi only)*/
-/*0x0c18*/	u64	imap_a_slot3;	/* PCI A Slot 3 Int Mapping (IIi only)*/
-
-/*0x0c20*/	u64	imap_b_slot0;	/* PCI B Slot 0 Int Mapping	*/
-/*0x0c28*/	u64	imap_b_slot1;	/* PCI B Slot 1 Int Mapping	*/
-/*0x0c30*/	u64	imap_b_slot2;	/* PCI B Slot 2 Int Mapping	*/
-/*0x0c38*/	u64	imap_b_slot3;	/* PCI B Slot 3 Int Mapping	*/
-
-		u64	__pad6[0x78];
-
-/*0x1000*/	u64	imap_scsi;	/* SCSI Int Mapping		*/
-/*0x1008*/	u64	imap_eth;	/* Ethernet Int Mapping		*/
-/*0x1010*/	u64	imap_bpp;	/* Parallel Port Int Mapping	*/
-/*0x1018*/	u64	imap_au_rec;	/* Audio Record Int Mapping	*/
-/*0x1020*/	u64	imap_au_play;	/* Audio Playback Int Mapping	*/
-/*0x1028*/	u64	imap_pfail;	/* Power Fail Int Mapping	*/
-/*0x1030*/	u64	imap_kms;	/* Kbd/Mouse/Ser Int Mapping	*/
-/*0x1038*/	u64	imap_flpy;	/* Floppy Int Mapping		*/
-/*0x1040*/	u64	imap_shw;	/* Spare HW Int Mapping		*/
-/*0x1048*/	u64	imap_kbd;	/* Kbd Only Int Mapping		*/
-/*0x1050*/	u64	imap_ms;	/* Mouse Only Int Mapping	*/
-/*0x1058*/	u64	imap_ser;	/* Serial Only Int Mapping	*/
-/*0x1060*/	u64	imap_tim0;	/* Timer 0 Int Mapping		*/
-/*0x1068*/	u64	imap_tim1;	/* Timer 1 Int Mapping		*/
-/*0x1070*/	u64	imap_ue;	/* UE Int Mapping		*/
-/*0x1078*/	u64	imap_ce;	/* CE Int Mapping		*/
-/*0x1080*/	u64	imap_a_err;	/* PCI A Err Int Mapping	*/
-/*0x1088*/	u64	imap_b_err;	/* PCI B Err Int Mapping	*/
-/*0x1090*/	u64	imap_pmgmt;	/* Power Mgmt Int Mapping	*/
-/*0x1098*/	u64	imap_gfx;	/* OB Graphics Int Mapping	*/
-/*0x10a0*/	u64	imap_eupa;	/* UPA Expansion Int Mapping	*/
-
-		u64	__pad7[0x6b];
-
-		/* Interrupt Clear Registers */
-/*0x1400*/	u64	iclr_a_slot0[4];	/* PCI A Slot 0 Clear Int Reg */
-/*0x1420*/	u64	iclr_a_slot1[4];	/* PCI A Slot 1 Clear Int Reg */
-/*0x1440*/	u64	iclr_a_slot2[4];	/* PCI A Slot 2 Clear Int Reg */
-/*0x1460*/	u64	iclr_a_slot3[4];	/* PCI A Slot 3 Clear Int Reg */
-
-/*0x1480*/	u64	iclr_b_slot0[4];	/* PCI B Slot 0 Clear Int Reg */
-/*0x14a0*/	u64	iclr_b_slot1[4];	/* PCI B Slot 1 Clear Int Reg */
-/*0x14c0*/	u64	iclr_b_slot2[4];	/* PCI B Slot 2 Clear Int Reg */
-/*0x14e0*/	u64	iclr_b_slot3[4];	/* PCI B Slot 3 Clear Int Reg */
-
-		u64	__pad9[0x60];
-
-/*0x1800*/	u64	iclr_scsi;
-/*0x1808*/	u64	iclr_eth;
-/*0x1810*/	u64	iclr_bpp;
-/*0x1818*/	u64	iclr_au_rec;
-/*0x1820*/	u64	iclr_au_play;
-/*0x1828*/	u64	iclr_pfail;
-/*0x1830*/	u64	iclr_kms;
-/*0x1838*/	u64	iclr_flpy;
-/*0x1840*/	u64	iclr_shw;
-/*0x1848*/	u64	iclr_kbd;
-/*0x1850*/	u64	iclr_ms;
-/*0x1858*/	u64	iclr_ser;
-/*0x1860*/	u64	iclr_tim0;
-/*0x1868*/	u64	iclr_tim1;
-/*0x1870*/	u64	iclr_ue;
-/*0x1878*/	u64	iclr_ce;
-/*0x1880*/	u64	iclr_a_err;
-/*0x1888*/	u64	iclr_b_err;
-/*0x1890*/	u64	iclr_pmgmt;
-
-		u64	__pad10[0x2d];
-
-		/* Interrupt Retry Timer. */
-/*0x1a00*/	u64	irq_retry;
-
-		u64	__pad11[0x3f];
-
-		/* Counters/Timers */
-/*0x1c00*/	u64	tim0_cnt;
-/*0x1c08*/	u64	tim0_lim;
-/*0x1c10*/	u64	tim1_cnt;
-/*0x1c18*/	u64	tim1_lim;
-/*0x1c20*/	u64	pci_dma_wsync;	/* PCI DMA Write Sync Register (IIi) */
-
-		u64	__pad12[0x7b];
-
-		/* PCI Bus A Registers */
-/*0x2000*/	u64	pci_a_control;	/* PCI Bus A Control Register	*/
-/*0x2008*/	u64	__pad13;
-/*0x2010*/	u64	pci_a_afsr;	/* PCI Bus A Async Fault Status	*/
-/*0x2018*/	u64	pci_a_afar;	/* PCI Bus A Async Fault Address*/
-/*0x2020*/	u64	pci_a_diag;	/* PCI Bus A Diag Register	*/
-/*0x2028*/	u64	pci_tasr;	/* PCI Target Address Space Reg (IIi) */
-
-		u64	__pad14[0xfa];
-
-		/* PCI Bus A/IOMMU Streaming Buffer Registers */
-/*0x2800*/	u64	sbuf_a_control;	/* StrBuffer Control		*/
-/*0x2808*/	u64	sbuf_a_pflush;	/* StrBuffer Page Flush		*/
-/*0x2810*/	u64	sbuf_a_fsync;	/* StrBuffer Flush Sync Reg	*/
-
-		u64	__pad15[0x2fd];
-
-		/* PCI Bus B Registers */
-/*0x4000*/	u64	pci_b_control;	/* PCI Bus B Control Register	*/
-/*0x4008*/	u64	__pad16;
-/*0x4010*/	u64	pci_b_afsr;	/* PCI Bus B Async Fault Status	*/
-/*0x4018*/	u64	pci_b_afar;	/* PCI Bus B Async Fault Address*/
-/*0x4020*/	u64	pci_b_diag;	/* PCI Bus B Diag Register	*/
-
-		u64	__pad17[0x7b];
-
-		/* IOMMU diagnostic things */
-/*0x4400*/	u64	iommu_vdiag;	/* VADDR Diagnostic Register	*/
-/*0x4408*/	u64	iommu_tcompare;	/* IOMMU TLB Tag Compare	*/
-
-		u64	__pad18[0x7e];
-
-		/* PCI Bus B/IOMMU Streaming Buffer Registers */
-/*0x4800*/	u64	sbuf_b_control;	/* StrBuffer Control		*/
-/*0x4808*/	u64	sbuf_b_pflush;	/* StrBuffer Page Flush		*/
-/*0x4810*/	u64	sbuf_b_fsync;	/* StrBuffer Flush Sync Reg	*/
-
-		u64	__pad19[0xafd];
-
-		/* DMA Scoreboard Diagnostic Registers */
-/*0xa000*/	u64	dscore_reg0;	/* DMA Scoreboard Diag Reg 0	*/
-/*0xa008*/	u64	dscore_reg1;	/* DMA Scoreboard Diag Reg 1	*/
-
-		u64	__pad20[0x9e];
-
-		/* More IOMMU diagnostic things */
-/*0xa500*/	u64	iommu_lru[16];	/* IOMMU LRU Queue Diag		*/
-/*0xa580*/	u64	iommu_tag[16];	/* IOMMU TLB Tag Diag		*/
-/*0xa600*/	u64	iommu_data[16];	/* IOMMU TLB Data RAM Diag	*/
-
-		u64	__pad21[0x30];
-
-		/* Interrupt State Diagnostics */
-/*0xa800*/	u64	pci_istate;
-/*0xa808*/	u64	obio_istate;
-
-		u64	__pad22[0xfe];
-
-		/* Streaming Buffer A Diagnostic Area */
-/*0xb000*/	u64	sbuf_a_data[128]; /* StrBuffer Data Ram Diag	*/
-/*0xb400*/	u64	sbuf_a_errs[128]; /* StrBuffer Error Status Diag*/
-/*0xb800*/	u64	sbuf_a_ptag[16]; /* StrBuffer Page Tag Diag	*/
-/*0xb880*/	u64	__pad23[16];
-/*0xb900*/	u64	sbuf_a_ltag[16]; /* StrBuffer Line Tag Diag	*/
-
-		u64	__pad24[0xd0];
-
-		/* Streaming Buffer B Diagnostic Area */
-/*0xc000*/	u64	sbuf_b_data[128]; /* StrBuffer Data Ram Diag	*/
-/*0xc400*/	u64	sbuf_b_errs[128]; /* StrBuffer Error Status Diag*/
-/*0xc800*/	u64	sbuf_b_ptag[16]; /* StrBuffer Page Tag Diag	*/
-/*0xc880*/	u64	__pad25[16];
-/*0xc900*/	u64	sbuf_b_ltag[16]; /* StrBuffer Line Tag Diag	*/
-};
-
-/* PSYCHO UPA Port ID */
-#define PSYCHO_UPPID_FESC	0xff00000000000000 /* FCode escape, 0xfc           */
-#define PSYCHO_UPPID_RESV1	0x00fffff800000000 /* Reserved                     */
-#define PSYCHO_UPPID_ENV	0x0000000400000000 /* Cannot generate ECC          */
-#define PSYCHO_UPPID_ORD	0x0000000200000000 /* One Outstanding Read         */
-#define PSYCHO_UPPID_RESV2	0x0000000180000000 /* Reserved                     */
-#define PSYCHO_UPPID_PDQ	0x000000007e000000 /* Data Queue size              */
-#define PSYCHO_UPPID_PRQ	0x0000000001e00000 /* Request Queue size           */
-#define PSYCHO_UPPID_UCAP	0x00000000001f0000 /* UPA Capabilities             */
-#define PSYCHO_UPPID_JEDEC	0x000000000000ffff /* JEDEC ID for PSYCHO          */
-
-/* PSYCHO UPA Configuration Register */
-#define PSYCHO_UPCFG_RESV	0xffffffffffffff00 /* Reserved                     */
-#define PSYCHO_UPCFG_SCIQ1	0x00000000000000f0 /* Unused, always zero          */
-#define PSYCHO_UPCFG_SCIQ2	0x000000000000000f /* Requests Queue size 0x2 	   */
-
-/* PSYCHO Control Register */
-#define PSYCHO_CONTROL_IMPL	0xf000000000000000 /* Implementation of this PSYCHO*/
-#define PSYCHO_CONTROL_VER	0x0f00000000000000 /* Version of this PSYCHO       */
-#define PSYCHO_CONTROL_MID	0x00f8000000000000 /* UPA Module ID of PSYCHO      */
-#define PSYCHO_CONTROL_IGN	0x0007c00000000000 /* Interrupt Group Number       */
-#define PSYCHO_CONTROL_RESV     0x00003ffffffffff0 /* Reserved                     */
-#define PSYCHO_CONTROL_APCKEN	0x0000000000000008 /* Address Parity Check Enable  */
-#define PSYCHO_CONTROL_APERR	0x0000000000000004 /* Incoming System Addr Parerr  */
-#define PSYCHO_CONTROL_IAP	0x0000000000000002 /* Invert UPA Parity            */
-#define PSYCHO_CONTROL_MODE	0x0000000000000001 /* PSYCHO clock mode            */
-
-/* PSYCHO ECC Control Register */
-#define PSYCHO_ECNTRL_ECCEN	0x8000000000000000 /* Enable ECC Checking	   */
-#define PSYCHO_ECNTRL_UEEN	0x4000000000000000 /* Enable UE Interrupts         */
-#define PSYCHO_ECNTRL_CEEN	0x2000000000000000 /* Enable CE Interrupts         */
-
-/* Uncorrectable Error AFSR, AFAR holds low 40bits of faulting physical address. */
-#define PSYCHO_UEAFSR_PPIO	0x8000000000000000 /* Primary PIO is cause         */
-#define PSYCHO_UEAFSR_PDRD	0x4000000000000000 /* Primary DVMA read is cause   */
-#define PSYCHO_UEAFSR_PDWR	0x2000000000000000 /* Primary DVMA write is cause  */
-#define PSYCHO_UEAFSR_SPIO	0x1000000000000000 /* Secondary PIO is cause       */
-#define PSYCHO_UEAFSR_SDRD	0x0800000000000000 /* Secondary DVMA read is cause */
-#define PSYCHO_UEAFSR_SDWR	0x0400000000000000 /* Secondary DVMA write is cause*/
-#define PSYCHO_UEAFSR_RESV1	0x03ff000000000000 /* Reserved                     */
-#define PSYCHO_UEAFSR_BMSK	0x0000ffff00000000 /* Bytemask of failed transfer  */
-#define PSYCHO_UEAFSR_DOFF	0x00000000e0000000 /* Doubleword Offset            */
-#define PSYCHO_UEAFSR_MID	0x000000001f000000 /* UPA MID causing the fault    */
-#define PSYCHO_UEAFSR_BLK	0x0000000000800000 /* Trans was block operation    */
-#define PSYCHO_UEAFSR_RESV2	0x00000000007fffff /* Reserved                     */
-
-/* Correctable Error AFSR, AFAR holds low 40bits of faulting physical address. */
-#define PSYCHO_CEAFSR_PPIO	0x8000000000000000 /* Primary PIO is cause         */
-#define PSYCHO_CEAFSR_PDRD	0x4000000000000000 /* Primary DVMA read is cause   */
-#define PSYCHO_CEAFSR_PDWR	0x2000000000000000 /* Primary DVMA write is cause  */
-#define PSYCHO_CEAFSR_SPIO	0x1000000000000000 /* Secondary PIO is cause       */
-#define PSYCHO_CEAFSR_SDRD	0x0800000000000000 /* Secondary DVMA read is cause */
-#define PSYCHO_CEAFSR_SDWR	0x0400000000000000 /* Secondary DVMA write is cause*/
-#define PSYCHO_CEAFSR_RESV1	0x0300000000000000 /* Reserved                     */
-#define PSYCHO_CEAFSR_ESYND	0x00ff000000000000 /* Syndrome Bits                */
-#define PSYCHO_CEAFSR_SIZE	0x0000ffff00000000 /* Bytemask of failed transfer  */
-#define PSYCHO_CEAFSR_DOFF	0x00000000e0000000 /* Double Offset                */
-#define PSYCHO_CEAFSR_MID	0x000000001f000000 /* UPA MID causing the fault    */
-#define PSYCHO_CEAFSR_BLK	0x0000000000800000 /* Trans was block operation    */
-#define PSYCHO_CEAFSR_RESV2	0x00000000007fffff /* Reserved                     */
-
-/* PSYCHO Performance Monitor Register, the counter holds 2 32-bit event counters. */
-#define PSYCHO_PMCTRL_RESV3	0xffffffffffff0000 /* Reserved                     */
-#define PSYCHO_PMCTRL_CLR1	0x0000000000008000 /* Clear SEL1 counter           */
-#define PSYCHO_PMCTRL_RESV2	0x0000000000006000 /* Reserved                     */
-#define PSYCHO_PMCTRL_SEL1	0x0000000000001f00 /* Event source 1               */
-#define PSYCHO_PMCTRL_CLR0	0x0000000000000080 /* Clear SEL0 counter           */
-#define PSYCHO_PMCTRL_RESV1	0x0000000000000060 /* Reserved                     */
-#define PSYCHO_PMCTRL_SEL0	0x000000000000001f /* Event source 0               */
-
-/* SEL0/SEL1 each can take any one of the following values. */
-#define PMCTRL_SEL_NSDRA	0x00  /* # of streaming dvma reads for PCI A       */
-#define PMCTRL_SEL_NSDWA	0x01  /* # of streaming dvma writes for PCI A      */
-#define PMCTRL_SEL_NCDRA	0x02  /* # of consistent dvma reads for PCI A      */
-#define PMCTRL_SEL_NCDWA	0x03  /* # of consistent dvma writes for PCI A     */
-#define PMCTRL_SEL_SBMA		0x04  /* # of streaming buffer misses on PCI A     */
-#define PMCTRL_SEL_DCGA		0x05  /* # of DVMA granted cycles on PCI A         */
-#define PMCTRL_SEL_DWTA		0x06  /* # of DVMA words transferred on PCI A      */
-#define PMCTRL_SEL_CPIOA	0x07  /* # of PIO cycles used by PSYCHO on PCI A   */
-#define PMCTRL_SEL_NSDRB	0x08  /* # of streaming dvma reads for PCI B       */
-#define PMCTRL_SEL_NSDWB	0x09  /* # of streaming dvma writes for PCI B      */
-#define PMCTRL_SEL_NCDRB	0x0a  /* # of consistent dvma reads for PCI B      */
-#define PMCTRL_SEL_NCDWB	0x0b  /* # of consistent dvma writes for PCI B     */
-#define PMCTRL_SEL_SBMB		0x0c  /* # of streaming buffer misses on PCI B     */
-#define PMCTRL_SEL_DCGB		0x0d  /* # of DVMA granted cycles on PCI B         */
-#define PMCTRL_SEL_DWTB		0x0e  /* # of DVMA words transferred on PCI B      */
-#define PMCTRL_SEL_CPIOB	0x0f  /* # of PIO cycles used by PSYCHO on PCI B   */
-#define PMCTRL_SEL_TMISS	0x10  /* # of IOMMU TLB misses                     */
-#define PMCTRL_SEL_IRQ		0x11  /* # of interrupts                           */
-#define PMCTRL_SEL_INACK	0x12  /* # of interrupt NACKs on UPA               */
-#define PMCTRL_SEL_PRD		0x13  /* # of PIO reads                            */
-#define PMCTRL_SEL_PWR		0x14  /* # of PIO writes                           */
-#define PMCTRL_SEL_MBT		0x15  /* # of Merge Buffer transactions            */
-#define PMCTRL_SEL_PDRTA	0x16  /* # of PCI A DVMA tablewalk induced retries */
-#define PMCTRL_SEL_PDRSA	0x17  /* # of PCI A DVMA str buf induced retries   */
-#define PMCTRL_SEL_PDRTB	0x18  /* # of PCI B DVMA tablewalk induced retries */
-#define PMCTRL_SEL_PDRSB	0x19  /* # of PCI B DVMA str buf induced retries   */
-/* Values 0x1a --> 0x1f are reserved. */
-
-/* PSYCHO PCI Control Register */
-#define PSYCHO_PCICTRL_RESV1	0xfffffff000000000 /* Reserved                     */
-#define PSYCHO_PCICTRL_SBH_ERR	0x0000000800000000 /* Streaming byte hole error    */
-#define PSYCHO_PCICTRL_SERR	0x0000000400000000 /* SERR signal asserted         */
-#define PSYCHO_PCICTRL_SPEED	0x0000000200000000 /* PCI speed (1 is U2P clock)   */
-#define PSYCHO_PCICTRL_RESV2	0x00000001ffc00000 /* Reserved                     */
-#define PSYCHO_PCICTRL_ARB_PARK	0x0000000000200000 /* PCI arbitration parking      */
-#define PSYCHO_PCICTRL_RESV3	0x00000000001ff800 /* Reserved                     */
-#define PSYCHO_PCICTRL_SBH_INT	0x0000000000000400 /* Streaming byte hole int enab */
-#define PSYCHO_PCICTRL_WEN	0x0000000000000200 /* Power Mgmt Wake Enable       */
-#define PSYCHO_PCICTRL_EEN	0x0000000000000100 /* PCI Error Interrupt Enable   */
-#define PSYCHO_PCICTRL_RESV4	0x00000000000000c0 /* Reserved                     */
-#define PSYCHO_PCICTRL_AEN	0x000000000000003f /* PCI DVMA Arbitration Enable  */
-
-/* PSYCHO PCI AFSR, AFAR holds low 40 bits of physical address causing the fault. */
-#define PSYCHO_PCIAFSR_PMA	0x8000000000000000 /* Primary Master Abort Error   */
-#define PSYCHO_PCIAFSR_PTA	0x4000000000000000 /* Primary Target Abort Error   */
-#define PSYCHO_PCIAFSR_PRTRY	0x2000000000000000 /* Primary Excessive Retries    */
-#define PSYCHO_PCIAFSR_PPERR	0x1000000000000000 /* Primary Parity Error         */
-#define PSYCHO_PCIAFSR_SMA	0x0800000000000000 /* Secondary Master Abort Error */
-#define PSYCHO_PCIAFSR_STA	0x0400000000000000 /* Secondary Target Abort Error */
-#define PSYCHO_PCIAFSR_SRTRY	0x0200000000000000 /* Secondary Excessive Retries  */
-#define PSYCHO_PCIAFSR_SPERR	0x0100000000000000 /* Secondary Parity Error       */
-#define PSYCHO_PCIAFSR_RESV1	0x00ff000000000000 /* Reserved                     */
-#define PSYCHO_PCIAFSR_SIZE	0x0000ffff00000000 /* Bytemask of failed transfer  */
-#define PSYCHO_PCIAFSR_BLK	0x0000000080000000 /* Trans was block operation    */
-#define PSYCHO_PCIAFSR_RESV2	0x0000000040000000 /* Reserved                     */
-#define PSYCHO_PCIAFSR_MID	0x000000003e000000 /* MID causing the error        */
-#define PSYCHO_PCIAFSR_RESV3	0x0000000001ffffff /* Reserved                     */
-
-/* PSYCHO Diagnostic Register. */
-#define PSYCHO_PSYDIAG_RESV	0xffffffffffffff80 /* Reserved                     */
-#define PSYCHO_PCIDIAG_DRETRY	0x0000000000000040 /* Disable retry limit          */
-#define PSYCHO_PCIDIAG_DISYNC	0x0000000000000020 /* Disable DMA wr / irq sync    */
-#define PSYCHO_PCIDIAG_DDWSYNC	0x0000000000000010 /* Disable DMA wr / PIO rd sync */
-#define PSYCHO_PCIDIAG_IDDPAR	0x0000000000000008 /* Invert DMA data parity       */
-#define PSYCHO_PCIDIAG_IPDPAR	0x0000000000000004 /* Invert PIO data parity       */
-#define PSYCHO_PCIDIAG_IPAPAR	0x0000000000000002 /* Invert PIO address parity    */
-#define PSYCHO_PCIDIAG_LPBACK	0x0000000000000001 /* Enable loopback mode         */
-
-/* IOMMU things defined fully in asm-sparc64/iommu.h */
-
-/* Streaming Buffer Control Register */
-#define PSYCHO_SBUFCTRL_RESV	0xffffffffffffff80 /* Reserved                     */
-#define PSYCHO_SBUFCTRL_LRU_LP	0x0000000000000070 /* LRU Lock Pointer             */
-#define PSYCHO_SBUFCTRL_LRU_LE	0x0000000000000008 /* LRU Lock Enable              */
-#define PSYCHO_SBUFCTRL_RR_DIS	0x0000000000000004 /* Rerun Disable                */
-#define PSYCHO_SBUFCTRL_DE	0x0000000000000002 /* Diag Mode Enable             */
-#define PSYCHO_SBUFCTRL_SB_EN	0x0000000000000001 /* Streaming Buffer Enable      */
-
-/* Streaming Buffer Page Invalidate/Flush Register */
-#define PSYCHO_SBUFFLUSH_ADDR	0x00000000ffffe000 /* DVMA Page to be flushed      */
-#define PSYCHO_SBUFFLUSH_RESV	0x0000000000001fff /* Ignored bits                 */
-
-/* Streaming Buffer Flush Synchronization Register */
-#define PSYCHO_SBUFSYNC_ADDR	0x000001ffffffffc0 /* Physical address to update   */
-#define PSYCHO_SBUFSYNC_RESV	0x000000000000003f /* Ignored bits                 */
-
-/* DMA Scoreboard Diagnostic Register(s) */
-#define PSYCHO_DSCORE_VALID	0x8000000000000000 /* Entry is valid               */
-#define PSYCHO_DSCORE_C		0x4000000000000000 /* Transaction cacheable        */
-#define PSYCHO_DSCORE_READ	0x2000000000000000 /* Transaction was a read       */
-#define PSYCHO_DSCORE_TAG	0x1f00000000000000 /* Transaction ID               */
-#define PSYCHO_DSCORE_ADDR	0x00fffffffff80000 /* Transaction PADDR            */
-#define PSYCHO_DSCORE_BMSK	0x000000000007fff8 /* Bytemask of pending transfer */
-#define PSYCHO_DSCORE_SRC	0x0000000000000007 /* Transaction source           */
-
-/* PSYCHO Interrupt mapping register(s). */
-#define PSYCHO_IMAP_RESV1	0xffffffff00000000 /* Reserved                     */
-#define PSYCHO_IMAP_VALID	0x0000000080000000 /* This enables delivery.	   */
-#define PSYCHO_IMAP_TID		0x000000007c000000 /* Target ID (MID to send it to)*/
-#define PSYCHO_IMAP_RESV2	0x0000000003fff800 /* Reserved 			   */
-#define PSYCHO_IMAP_IGN		0x00000000000007c0 /* Interrupt Group Number.	   */
-#define PSYCHO_IMAP_INO		0x000000000000003f /* Interrupt Number Offset.	   */
-#define PSYCHO_IMAP_INR		0x00000000000007ff /* Interrupt # (Gfx/UPA_slave)  */
-
-/* PSYCHO Interrupt clear pseudo register(s). */
-#define PSYCHO_ICLR_RESV1 	0xfffffffffffffff0 /* Reserved			   */
-#define PSYCHO_ICLR_IDLE	0x0000000000000000 /* Transition to idle state.	   */
-#define PSYCHO_ICLR_TRANSMIT	0x0000000000000001 /* Transition to transmit state */
-#define PSYCHO_ICLR_RESV2	0x0000000000000002 /* Reserved.			   */
-#define PSYCHO_ICLR_PENDING	0x0000000000000003 /* Transition to pending state. */
-
-/* PSYCHO Interrupt Retry Timer register. */
-#define PSYCHO_IRETRY_LIMIT	0x00000000000fffff /* The retry interval.	   */
-
-/* PSYCHO Interrupt State registers. XXX fields to be documented later */
-
-/* PSYCHO Counter register. XXX fields to be documented later */
-
-/* PSYCHO Limit register. XXX fields to be documented later */
-
-/* PSYCHO Performance Monitor Control register. XXX fields to be documented later */
-
-/* PSYCHO Performance Monitor Counter register. XXX fields to be documented later */
-
-#endif /* !(__SPARC64_PSYCHO_H) */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/reg.h linux/include/asm-sparc64/reg.h
--- v2.3.15/linux/include/asm-sparc64/reg.h	Mon Jan 12 15:15:58 1998
+++ linux/include/asm-sparc64/reg.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: reg.h,v 1.4 1997/09/14 08:40:29 davem Exp $
+/* $Id: reg.h,v 1.5 1999/08/17 17:52:32 jj Exp $
  * linux/asm-sparc64/reg.h
  * Layout of the registers as expected by gdb on the Sparc
  * we should replace the user.h definitions with those in
@@ -37,6 +37,9 @@
         unsigned int  r_y;
         unsigned int  r_fprs;
 };
+
+#define FPU_REGS_TYPE unsigned int
+#define FPU_FSR_TYPE unsigned long
 
 struct fp_status {
         unsigned long fpu_fr[32];
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/scatterlist.h linux/include/asm-sparc64/scatterlist.h
--- v2.3.15/linux/include/asm-sparc64/scatterlist.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/scatterlist.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: scatterlist.h,v 1.6 1998/12/16 04:33:57 davem Exp $ */
+/* $Id: scatterlist.h,v 1.7 1999/08/30 10:15:01 davem Exp $ */
 #ifndef _SPARC64_SCATTERLIST_H
 #define _SPARC64_SCATTERLIST_H
 
@@ -11,6 +11,7 @@
     unsigned int length;
 
     __u32 dvma_address; /* A place to hang host-specific addresses at. */
+    __u32 dvma_length;
 };
 
 extern unsigned long phys_base;
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/spinlock.h linux/include/asm-sparc64/spinlock.h
--- v2.3.15/linux/include/asm-sparc64/spinlock.h	Mon Aug  2 22:07:16 1999
+++ linux/include/asm-sparc64/spinlock.h	Tue Aug 31 11:23:30 1999
@@ -152,6 +152,7 @@
 {
 	__asm__ __volatile__("membar	#StoreStore | #LoadStore\n\t"
 			     "stb	%%g0, [%0]\n\t"
+			     "membar	#StoreStore | #StoreLoad"
 			     : /* No outputs */
 			     : "r" (lock)
 			     : "memory");
@@ -177,13 +178,13 @@
 
 extern __inline__ void spin_unlock_irq(spinlock_t *lock)
 {
-	__asm__ __volatile__("
-	membar		#StoreStore | #LoadStore
-	stb		%%g0, [%0]
-	wrpr		%%g0, 0x0, %%pil
-"	: /* no outputs */
-	: "r" (lock)
-	: "memory");
+	__asm__ __volatile__("membar	#StoreStore | #LoadStore\n\t"
+			     "stb	%%g0, [%0]\n\t"
+			     "membar	#StoreStore | #StoreLoad\n\t"
+			     "wrpr	%%g0, 0x0, %%pil"
+			     : /* no outputs */
+			     : "r" (lock)
+			     : "memory");
 }
 
 #define spin_lock_bh(__lock)	\
@@ -218,13 +219,13 @@
 
 extern __inline__ void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
 {
-	__asm__ __volatile__("
-	membar		#StoreStore | #LoadStore
-	stb		%%g0, [%0]
-	wrpr		%1, 0x0, %%pil
-"	: /* no outputs */
-	: "r" (lock), "r" (flags)
-	: "memory");
+	__asm__ __volatile__("membar	#StoreStore | #LoadStore\n\t"
+			     "stb	%%g0, [%0]\n\t"
+			     "membar	#StoreStore | #StoreLoad\n\t"
+			     "wrpr	%1, 0x0, %%pil"
+			     : /* no outputs */
+			     : "r" (lock), "r" (flags)
+			     : "memory");
 }
 
 #else /* !(SPIN_LOCK_DEBUG) */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/sunbpp.h linux/include/asm-sparc64/sunbpp.h
--- v2.3.15/linux/include/asm-sparc64/sunbpp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/sunbpp.h	Tue Aug 31 11:23:30 1999
@@ -0,0 +1,80 @@
+/* $Id: sunbpp.h,v 1.1 1999/08/13 06:21:44 shadow Exp $
+ * include/asm-sparc64/sunbpp.h
+ */
+
+#ifndef _ASM_SPARC64_SUNBPP_H
+#define _ASM_SPARC64_SUNBPP_H
+
+struct bpp_regs {
+  /* DMA registers */
+  __volatile__ __u32 p_csr;		/* DMA Control/Status Register */
+  __volatile__ __u32 p_addr;		/* Address Register */
+  __volatile__ __u32 p_bcnt;		/* Byte Count Register */
+  __volatile__ __u32 p_tst_csr;		/* Test Control/Status (DMA2 only) */
+  /* Parallel Port registers */
+  __volatile__ __u16 p_hcr;		/* Hardware Configuration Register */
+  __volatile__ __u16 p_ocr;		/* Operation Configuration Register */
+  __volatile__ __u8 p_dr;		/* Parallel Data Register */
+  __volatile__ __u8 p_tcr;		/* Transfer Control Register */
+  __volatile__ __u8 p_or;		/* Output Register */
+  __volatile__ __u8 p_ir;		/* Input Register */
+  __volatile__ __u16 p_icr;		/* Interrupt Control Register */
+};
+
+/* P_HCR. Time is in increments of SBus clock. */
+#define P_HCR_TEST      0x8000      /* Allows buried counters to be read */
+#define P_HCR_DSW       0x7f00      /* Data strobe width (in ticks) */
+#define P_HCR_DDS       0x007f      /* Data setup before strobe (in ticks) */
+
+/* P_OCR. */
+#define P_OCR_MEM_CLR   0x8000
+#define P_OCR_DATA_SRC  0x4000      /* )                  */
+#define P_OCR_DS_DSEL   0x2000      /* )  Bidirectional      */
+#define P_OCR_BUSY_DSEL 0x1000      /* )    selects            */
+#define P_OCR_ACK_DSEL  0x0800      /* )                  */
+#define P_OCR_EN_DIAG   0x0400
+#define P_OCR_BUSY_OP   0x0200      /* Busy operation */
+#define P_OCR_ACK_OP    0x0100      /* Ack operation */
+#define P_OCR_SRST      0x0080      /* Reset state machines. Not selfcleaning. */
+#define P_OCR_IDLE      0x0008      /* PP data transfer state machine is idle */
+#define P_OCR_V_ILCK    0x0002      /* Versatec faded. Zebra only. */
+#define P_OCR_EN_VER    0x0001      /* Enable Versatec (0 - enable). Zebra only. */
+
+/* P_TCR */
+#define P_TCR_DIR       0x08
+#define P_TCR_BUSY      0x04
+#define P_TCR_ACK       0x02
+#define P_TCR_DS        0x01        /* Strobe */
+
+/* P_OR */
+#define P_OR_V3         0x20        /* )                 */
+#define P_OR_V2         0x10        /* ) on Zebra only   */
+#define P_OR_V1         0x08        /* )                 */
+#define P_OR_INIT       0x04
+#define P_OR_AFXN       0x02        /* Auto Feed */
+#define P_OR_SLCT_IN    0x01
+
+/* P_IR */
+#define P_IR_PE         0x04
+#define P_IR_SLCT       0x02
+#define P_IR_ERR        0x01
+
+/* P_ICR */
+#define P_DS_IRQ        0x8000      /* RW1  */
+#define P_ACK_IRQ       0x4000      /* RW1  */
+#define P_BUSY_IRQ      0x2000      /* RW1  */
+#define P_PE_IRQ        0x1000      /* RW1  */
+#define P_SLCT_IRQ      0x0800      /* RW1  */
+#define P_ERR_IRQ       0x0400      /* RW1  */
+#define P_DS_IRQ_EN     0x0200      /* RW   Always on rising edge */
+#define P_ACK_IRQ_EN    0x0100      /* RW   Always on rising edge */
+#define P_BUSY_IRP      0x0080      /* RW   1= rising edge */
+#define P_BUSY_IRQ_EN   0x0040      /* RW   */
+#define P_PE_IRP        0x0020      /* RW   1= rising edge */
+#define P_PE_IRQ_EN     0x0010      /* RW   */
+#define P_SLCT_IRP      0x0008      /* RW   1= rising edge */
+#define P_SLCT_IRQ_EN   0x0004      /* RW   */
+#define P_ERR_IRP       0x0002      /* RW1  1= rising edge */
+#define P_ERR_IRQ_EN    0x0001      /* RW   */
+
+#endif /* !(_ASM_SPARC64_SUNBPP_H) */
diff -u --recursive --new-file v2.3.15/linux/include/asm-sparc64/sysio.h linux/include/asm-sparc64/sysio.h
--- v2.3.15/linux/include/asm-sparc64/sysio.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/sysio.h	Tue Aug 31 11:23:30 1999
@@ -1,4 +1,4 @@
-/* $Id: sysio.h,v 1.8 1998/11/29 15:49:54 davem Exp $
+/* $Id: sysio.h,v 1.9 1999/08/30 10:15:03 davem Exp $
  * sysio.h: UltraSparc sun5 specific SBUS definitions.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -11,34 +11,34 @@
 
 /* SUN5 SYSIO Register Set, one per controller probed. */
 struct sysio_regs {
-/*0x0000*/	u64	upa_id;		/* SYSIO UPA Port ID Register		*/
-/*0x0008*/	u64	upa_cfg;	/* SYSIO UPA Config Register		*/
-/*0x0010*/	u64	control;	/* SYSIO Control Register		*/
-/*0x0018*/	u64	_unused1;
-/*0x0020*/	u64	ecc_control;	/* ECC Control Register			*/
-/*0x0028*/	u64	_unused2;
+/*0x0000*/	volatile u64	upa_id;		/* SYSIO UPA Port ID Register	*/
+/*0x0008*/	volatile u64	upa_cfg;	/* SYSIO UPA Config Register	*/
+/*0x0010*/	volatile u64	control;	/* SYSIO Control Register	*/
+/*0x0018*/	volatile u64	_unused1;
+/*0x0020*/	volatile u64	ecc_control;	/* ECC Control Register		*/
+/*0x0028*/	volatile u64	_unused2;
 
 		/* Uncorrectable Error Fault Registers */
-/*0x0030*/	u64	ue_afsr;	/* UE Async Fault Status		*/
-/*0x0038*/	u64	ue_afar;	/* UE Async Fault Address		*/
+/*0x0030*/	volatile u64	ue_afsr;	/* UE Async Fault Status	*/
+/*0x0038*/	volatile u64	ue_afar;	/* UE Async Fault Address	*/
 
 		/* Correctable Error Fault Registers */
-/*0x0040*/	u64	ce_afsr;	/* CE Async Fault Status		*/
-/*0x0048*/	u64	ce_afar;	/* CE Async Fault Address		*/
+/*0x0040*/	volatile u64	ce_afsr;	/* CE Async Fault Status	*/
+/*0x0048*/	volatile u64	ce_afar;	/* CE Async Fault Address	*/
 
-		u64	__pad0[0x16];
+		volatile u64	__pad0[0x16];
 
 		/* Performance Monitoring Registers */
-/*0x0100*/	u64	pmon_control;
-/*0x0108*/	u64	pmon_counter;
+/*0x0100*/	volatile u64	pmon_control;
+/*0x0108*/	volatile u64	pmon_counter;
 
-		u64	__pad1[0x3de];
+		volatile u64	__pad1[0x3de];
 
 		/* SBUS Module Registers */
-/*0x2000*/	u64	sbus_control;	/* SBUS Control Register		*/
-/*0x2008*/	u64	_unused3;
-/*0x2010*/	u64	sbus_afsr;	/* SBUS Async Fault Status		*/
-/*0x2018*/	u64	sbus_afar;	/* SBUS Async Fault Address		*/
+/*0x2000*/	volatile u64	sbus_control;	/* SBUS Control Register	*/
+/*0x2008*/	volatile u64	_unused3;
+/*0x2010*/	volatile u64	sbus_afsr;	/* SBUS Async Fault Status	*/
+/*0x2018*/	volatile u64	sbus_afar;	/* SBUS Async Fault Address	*/
 
 		/* SBUS Slot Configuration Registers.
 		 * On Fusion/Electron/Pulsar desktops/servers slots 4-->6
@@ -52,137 +52,137 @@
 		 * On Sunfire/Starfire/Wildfire enterprise boxen these upper slots
 		 * are unused.
 		 */
-/*0x2020*/	u64	sbus_s0cfg;	/* SBUS Slot 0 Config			*/
-/*0x2028*/	u64	sbus_s1cfg;	/* SBUS Slot 1 Config			*/
-/*0x2030*/	u64	sbus_s2cfg;	/* SBUS Slot 2 Config			*/
-/*0x2038*/	u64	sbus_s3cfg;	/* SBUS Slot 3 Config			*/
-/*0x2040*/	u64	sbus_s4cfg;	/* SBUS Slot 4 Config			*/
-/*0x2048*/	u64	sbus_s5cfg;	/* SBUS Slot 5 Config			*/
-/*0x2050*/	u64	sbus_s6cfg;	/* SBUS Slot 6 Config			*/
+/*0x2020*/	volatile u64	sbus_s0cfg;	/* SBUS Slot 0 Config		*/
+/*0x2028*/	volatile u64	sbus_s1cfg;	/* SBUS Slot 1 Config		*/
+/*0x2030*/	volatile u64	sbus_s2cfg;	/* SBUS Slot 2 Config		*/
+/*0x2038*/	volatile u64	sbus_s3cfg;	/* SBUS Slot 3 Config		*/
+/*0x2040*/	volatile u64	sbus_s4cfg;	/* SBUS Slot 4 Config		*/
+/*0x2048*/	volatile u64	sbus_s5cfg;	/* SBUS Slot 5 Config		*/
+/*0x2050*/	volatile u64	sbus_s6cfg;	/* SBUS Slot 6 Config		*/
 
-		u64	__pad2[0x75];
+		volatile u64	__pad2[0x75];
 
 		/* SBUS IOMMU lives here */
-/*0x2400*/	u64	iommu_control;	/* IOMMU Control			*/
-/*0x2408*/	u64	iommu_tsbbase;	/* IOMMU TSB Base			*/
-/*0x2410*/	u64	iommu_flush;	/* IOMMU Flush Register			*/
+/*0x2400*/	volatile u64	iommu_control;	/* IOMMU Control		*/
+/*0x2408*/	volatile u64	iommu_tsbbase;	/* IOMMU TSB Base		*/
+/*0x2410*/	volatile u64	iommu_flush;	/* IOMMU Flush Register		*/
 
-		u64	__pad3[0x7d];
+		volatile u64	__pad3[0x7d];
 
 		/* SBUS/IOMMU Streaming Buffer Registers */
-/*0x2800*/	u64	sbuf_control;	/* StrBuffer Control			*/
-/*0x2808*/	u64	sbuf_pflush;	/* StrBuffer Page Flush			*/
-/*0x2810*/	u64	sbuf_fsync;	/* StrBuffer Flush Synchronization Reg	*/
+/*0x2800*/	volatile u64	sbuf_control;	/* StrBuffer Control		*/
+/*0x2808*/	volatile u64	sbuf_pflush;	/* StrBuffer Page Flush		*/
+/*0x2810*/	volatile u64	sbuf_fsync;	/* StrBuffer Flush Synchronization Reg */
 
-		u64	__pad4[0x7d];
+		volatile u64	__pad4[0x7d];
 
 		/* Interrupt mapping/control registers */
-/*0x2c00*/	u32	_uim0, imap_slot0;	/* SBUS Slot 0 Int Mapping	*/
-/*0x2c08*/	u32	_uim1, imap_slot1;	/* SBUS Slot 1 Int Mapping	*/
-/*0x2c10*/	u32	_uim2, imap_slot2;	/* SBUS Slot 2 Int Mapping	*/
-/*0x2c18*/	u32	_uim3, imap_slot3;	/* SBUS Slot 3 Int Mapping	*/
+/*0x2c00*/	volatile u32	_uim0, imap_slot0;	/* SBUS Slot 0 Int Mapping */
+/*0x2c08*/	volatile u32	_uim1, imap_slot1;	/* SBUS Slot 1 Int Mapping */
+/*0x2c10*/	volatile u32	_uim2, imap_slot2;	/* SBUS Slot 2 Int Mapping */
+/*0x2c18*/	volatile u32	_uim3, imap_slot3;	/* SBUS Slot 3 Int Mapping */
 
 		/* Interrupt Retry Timer. */
-/*0x2c20*/	u32	_irpad, irq_retry;
+/*0x2c20*/	volatile u32	_irpad, irq_retry;
 
-		u64	__pad5[0x7b];
+		volatile u64	__pad5[0x7b];
 
 		/* The following are only used on Fusion/Electron/Pulsar
 		 * desktop systems, they mean nothing on Sunfire/Starfire/Wildfire
 		 */
-/*0x3000*/	u32	_uis, imap_scsi;	/* SCSI Int Mapping		*/
-/*0x3008*/	u32	_uie, imap_eth;		/* Ethernet Int Mapping		*/
-/*0x3010*/	u32	_uip, imap_bpp;		/* Parallel Port Int Mapping	*/
-/*0x3018*/	u32	_uia, imap_audio;	/* Audio Int Mapping		*/
-/*0x3020*/	u32	_uipf, imap_pfail;	/* Power Fail Int Mapping	*/
-/*0x3028*/	u32	_uik, imap_kms;		/* Kbd/Mouse/Serial Int Mapping	*/
-/*0x3030*/	u32	_uif, imap_flpy;	/* Floppy Int Mapping		*/
-/*0x3038*/	u32	_uishw, imap_shw;	/* Spare HW Int Mapping		*/
-/*0x3040*/	u32	_uikbd, imap_kbd;	/* Kbd Only Int Mapping		*/
-/*0x3048*/	u32	_uims, imap_ms;		/* Mouse Only Int Mapping	*/
-/*0x3050*/	u32	_uiser, imap_ser;	/* Serial Only Int Mapping	*/
-/*0x3058*/	u64	_imap_unused;
-/*0x3060*/	u32	_uit0, imap_tim0;	/* Timer 0 Int Mapping		*/
-/*0x3068*/	u32	_uit1, imap_tim1;	/* Timer 1 Int Mapping		*/
-/*0x3070*/	u32	_uiue, imap_ue;		/* UE Int Mapping		*/
-/*0x3078*/	u32	_uice, imap_ce;		/* CE Int Mapping		*/
-/*0x3080*/	u32	_uisbe, imap_sberr;	/* SBUS Err Int Mapping		*/
-/*0x3088*/	u32	_uipm, imap_pmgmt;	/* Power Mgmt Int Mapping	*/
-/*0x3090*/	u32	_uigfx, imap_gfx;	/* OB Graphics Int Mapping	*/
-/*0x3098*/	u32	_uieupa, imap_eupa;	/* UPA Expansion Int Mapping	*/
+/*0x3000*/	volatile u32	_uis, imap_scsi;	/* SCSI Int Mapping	*/
+/*0x3008*/	volatile u32	_uie, imap_eth;		/* Ethernet Int Mapping	*/
+/*0x3010*/	volatile u32	_uip, imap_bpp;		/* Parallel Port Int Mapping */
+/*0x3018*/	volatile u32	_uia, imap_audio;	/* Audio Int Mapping	*/
+/*0x3020*/	volatile u32	_uipf, imap_pfail;	/* Power Fail Int Mapping */
+/*0x3028*/	volatile u32	_uik, imap_kms;		/* Kbd/Ms/Serial Int Mapping */
+/*0x3030*/	volatile u32	_uif, imap_flpy;	/* Floppy Int Mapping	*/
+/*0x3038*/	volatile u32	_uishw, imap_shw;	/* Spare HW Int Mapping	*/
+/*0x3040*/	volatile u32	_uikbd, imap_kbd;	/* Kbd Only Int Mapping	*/
+/*0x3048*/	volatile u32	_uims, imap_ms;		/* Mouse Only Int Mapping */
+/*0x3050*/	volatile u32	_uiser, imap_ser;	/* Serial Only Int Mapping */
+/*0x3058*/	volatile u64	_imap_unused;
+/*0x3060*/	volatile u32	_uit0, imap_tim0;	/* Timer 0 Int Mapping	*/
+/*0x3068*/	volatile u32	_uit1, imap_tim1;	/* Timer 1 Int Mapping	*/
+/*0x3070*/	volatile u32	_uiue, imap_ue;		/* UE Int Mapping	*/
+/*0x3078*/	volatile u32	_uice, imap_ce;		/* CE Int Mapping	*/
+/*0x3080*/	volatile u32	_uisbe, imap_sberr;	/* SBUS Err Int Mapping	*/
+/*0x3088*/	volatile u32	_uipm, imap_pmgmt;	/* Power Mgmt Int Mapping */
+/*0x3090*/	volatile u32	_uigfx, imap_gfx;	/* OB Graphics Int Mapping */
+/*0x3098*/	volatile u32	_uieupa, imap_eupa;	/* UPA Expansion Int Mapping */
 
-		u64	__pad6[0x6c];
+		volatile u64	__pad6[0x6c];
 
 		/* Interrupt Clear Registers */
-/*0x3400*/	u32	__ucu0, iclr_unused0;
-/*0x3408*/	u32	_ucs0, iclr_slot0;
-		u64	__pad7[0x7];
-/*0x3448*/	u32	_ucs1, iclr_slot1;
-		u64	__pad8[0x7];
-/*0x3488*/	u32	_ucs2, iclr_slot2;
-		u64	__pad9[0x7];
-/*0x34c8*/	u32	_ucs3, iclr_slot3;
-		u64	__pad10[0x66];
-/*0x3800*/	u32	_ucscsi, iclr_scsi;
-/*0x3808*/	u32	_uceth, iclr_eth;
-/*0x3810*/	u32	_ucbpp, iclr_bpp;
-/*0x3818*/	u32	_ucaudio, iclr_audio;
-/*0x3820*/	u32	_ucpfail, iclr_pfail;
-/*0x3828*/	u32	_uckms, iclr_kms;
-/*0x3830*/	u32	_ucflpy, iclr_flpt;
-/*0x3838*/	u32	_ucshw, iclr_shw;
-/*0x3840*/	u32	_uckbd, iclr_kbd;
-/*0x3848*/	u32	_ucms, iclr_ms;
-/*0x3850*/	u32	_ucser, iclr_ser;
-/*0x3858*/	u64	iclr_unused1;
-/*0x3860*/	u32	_uctim0, iclr_tim0;
-/*0x3868*/	u32	_uctim1, iclr_tim1;
-/*0x3870*/	u32	_ucue, iclr_ue;
-/*0x3878*/	u32	_ucce, iclr_ce;
-/*0x3880*/	u32	_ucserr, iclr_serr;
-/*0x3888*/	u32	_ucpmgmt, iclr_pmgmt;
+/*0x3400*/	volatile u32	__ucu0, iclr_unused0;
+/*0x3408*/	volatile u32	_ucs0, iclr_slot0;
+		volatile u64	__pad7[0x7];
+/*0x3448*/	volatile u32	_ucs1, iclr_slot1;
+		volatile u64	__pad8[0x7];
+/*0x3488*/	volatile u32	_ucs2, iclr_slot2;
+		volatile u64	__pad9[0x7];
+/*0x34c8*/	volatile u32	_ucs3, iclr_slot3;
+		volatile u64	__pad10[0x66];
+/*0x3800*/	volatile u32	_ucscsi, iclr_scsi;
+/*0x3808*/	volatile u32	_uceth, iclr_eth;
+/*0x3810*/	volatile u32	_ucbpp, iclr_bpp;
+/*0x3818*/	volatile u32	_ucaudio, iclr_audio;
+/*0x3820*/	volatile u32	_ucpfail, iclr_pfail;
+/*0x3828*/	volatile u32	_uckms, iclr_kms;
+/*0x3830*/	volatile u32	_ucflpy, iclr_flpt;
+/*0x3838*/	volatile u32	_ucshw, iclr_shw;
+/*0x3840*/	volatile u32	_uckbd, iclr_kbd;
+/*0x3848*/	volatile u32	_ucms, iclr_ms;
+/*0x3850*/	volatile u32	_ucser, iclr_ser;
+/*0x3858*/	volatile u64	iclr_unused1;
+/*0x3860*/	volatile u32	_uctim0, iclr_tim0;
+/*0x3868*/	volatile u32	_uctim1, iclr_tim1;
+/*0x3870*/	volatile u32	_ucue, iclr_ue;
+/*0x3878*/	volatile u32	_ucce, iclr_ce;
+/*0x3880*/	volatile u32	_ucserr, iclr_serr;
+/*0x3888*/	volatile u32	_ucpmgmt, iclr_pmgmt;
 
-		u64	__pad11[0x6e];
+		volatile u64	__pad11[0x6e];
 
 		/* Counters/Timers */
-/*0x3c00*/	u64	tim0_cnt;
-/*0x3c08*/	u64	tim0_lim;
-/*0x3c10*/	u64	tim1_cnt;
-/*0x3c18*/	u64	tim1_lim;
+/*0x3c00*/	volatile u64	tim0_cnt;
+/*0x3c08*/	volatile u64	tim0_lim;
+/*0x3c10*/	volatile u64	tim1_cnt;
+/*0x3c18*/	volatile u64	tim1_lim;
 
-		u64	__pad12[0x7c];
+		volatile u64	__pad12[0x7c];
 
 		/* DMA Scoreboard Diagnostic Registers */
-/*0x4000*/	u64	dscore_reg0;	/* DMA Scoreboard Diag Reg 0		*/
-/*0x4008*/	u64	dscore_reg1;	/* DMA Scoreboard Diag Reg 1		*/
+/*0x4000*/	volatile u64	dscore_reg0;	/* DMA Scoreboard Diag Reg 0	*/
+/*0x4008*/	volatile u64	dscore_reg1;	/* DMA Scoreboard Diag Reg 1	*/
 
-		u64	__pad13[0x7e];
+		volatile u64	__pad13[0x7e];
 
 		/* SBUS IOMMU Diagnostic Registers */
-/*0x4400*/	u64	sbus_vdiag;	/* SBUS VADDR Diagnostic Register	*/
-/*0x4408*/	u64	sbus_tcompare;	/* SBUS IOMMU TLB Tag Compare		*/
+/*0x4400*/	volatile u64	sbus_vdiag;	/* SBUS VADDR Diagnostic Register */
+/*0x4408*/	volatile u64	sbus_tcompare;	/* SBUS IOMMU TLB Tag Compare	  */
 
-		u64	__pad14[0x1e];
+		volatile u64	__pad14[0x1e];
 
 		/* More IOMMU diagnostic things */
-/*0x4500*/	u64	iommu_lru[16];	/* IOMMU LRU Queue Diagnostic Access	*/
-/*0x4580*/	u64	iommu_tag[16];	/* IOMMU TLB Tag Diagnostic Access	*/
-/*0x4600*/	u64	iommu_data[32];	/* IOMMU TLB Data RAM Diagnostic Access	*/
+/*0x4500*/	volatile u64	iommu_lru[16];	/* IOMMU LRU Queue Diagnostic Access */
+/*0x4580*/	volatile u64	iommu_tag[16];	/* IOMMU TLB Tag Diagnostic Access   */
+/*0x4600*/	volatile u64	iommu_data[32];	/* IOMMU TLB Data RAM Diag Access    */
 
-		u64	__pad15[0x20];
+		volatile u64	__pad15[0x20];
 
 		/* Interrupt State Diagnostics */
-/*0x4800*/	u64	sbus_istate;
-/*0x4808*/	u64	obio_istate;
+/*0x4800*/	volatile u64	sbus_istate;
+/*0x4808*/	volatile u64	obio_istate;
 
-		u64	__pad16[0xfe];
+		volatile u64	__pad16[0xfe];
 
 		/* Streaming Buffer Diagnostic Area */
-/*0x5000*/	u64	sbuf_data[128];	/* StrBuffer Data Ram Diagnostic	*/
-/*0x5400*/	u64	sbuf_errs[128];	/* StrBuffer Error Status Diagnostics	*/
-/*0x5800*/	u64	sbuf_ptag[16];	/* StrBuffer Page Tag Diagnostics	*/
-/*0x5880*/	u64	_unusedXXX[16];
-/*0x5900*/	u64	sbuf_ltag[16];	/* StrBuffer Line Tag Diagnostics	*/
+/*0x5000*/	volatile u64	sbuf_data[128];	/* StrBuffer Data Ram Diagnostic */
+/*0x5400*/	volatile u64	sbuf_errs[128];	/* StrBuffer Error Status Diagnostics */
+/*0x5800*/	volatile u64	sbuf_ptag[16];	/* StrBuffer Page Tag Diagnostics */
+/*0x5880*/	volatile u64	_unusedXXX[16];
+/*0x5900*/	volatile u64	sbuf_ltag[16];	/* StrBuffer Line Tag Diagnostics */
 };
 
 /* SYSIO UPA Port ID */
diff -u --recursive --new-file v2.3.15/linux/include/linux/bigmem.h linux/include/linux/bigmem.h
--- v2.3.15/linux/include/linux/bigmem.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/bigmem.h	Tue Aug 31 16:12:02 1999
@@ -0,0 +1,48 @@
+#ifndef _LINUX_BIGMEM_H
+#define _LINUX_BIGMEM_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_BIGMEM
+
+#include <asm/bigmem.h>
+
+/* declarations for linux/mm/bigmem.c */
+extern unsigned long bigmem_mapnr;
+extern int nr_free_bigpages;
+
+extern struct page * prepare_bigmem_swapout(struct page *);
+extern struct page * replace_with_bigmem(struct page *);
+
+#else /* CONFIG_BIGMEM */
+
+#define prepare_bigmem_swapout(page) page
+#define replace_with_bigmem(page) page
+#define kmap(kaddr, type) kaddr
+#define kunmap(vaddr, type) do { } while (0)
+#define nr_free_bigpages 0
+
+#endif /* CONFIG_BIGMEM */
+
+/* when CONFIG_BIGMEM is not set these will be plain clear/copy_page */
+extern inline void clear_bigpage(unsigned long kaddr)
+{
+	unsigned long vaddr;
+
+	vaddr = kmap(kaddr, KM_WRITE);
+	clear_page(vaddr);
+	kunmap(vaddr, KM_WRITE);
+}
+
+extern inline void copy_bigpage(unsigned long to, unsigned long from)
+{
+	unsigned long vfrom, vto;
+
+	vfrom = kmap(from, KM_READ);
+	vto = kmap(to, KM_WRITE);
+	copy_page(vto, vfrom);
+	kunmap(vfrom, KM_READ);
+	kunmap(vto, KM_WRITE);
+}
+
+#endif /* _LINUX_BIGMEM_H */
diff -u --recursive --new-file v2.3.15/linux/include/linux/blk.h linux/include/linux/blk.h
--- v2.3.15/linux/include/linux/blk.h	Wed Aug 18 16:44:16 1999
+++ linux/include/linux/blk.h	Tue Aug 31 16:13:53 1999
@@ -19,7 +19,7 @@
  * NOTE that writes may use only the low 2/3 of these: reads
  * take precedence.
  */
-#define NR_REQUEST	64
+#define NR_REQUEST	128
 
 /*
  * This is used in the elevator algorithm.  We don't prioritise reads
@@ -86,6 +86,19 @@
 #endif
 
 		 
+/*
+ * end_request() and friends. Must be called with the request queue spinlock
+ * acquired. All functions called within end_request() _must_be_ atomic.
+ *
+ * Several drivers define their own end_request and call
+ * end_that_request_first() and end_that_request_last()
+ * for parts of the original function. This prevents
+ * code duplication in drivers.
+ */
+
+int end_that_request_first(struct request *req, int uptodate, char *name);
+void end_that_request_last(struct request *req);
+
 #if defined(MAJOR_NR) || defined(IDE_DRIVER)
 
 /*
@@ -359,6 +372,15 @@
 #define DEVICE_ON(device)
 #define DEVICE_OFF(device)
 
+#elif (MAJOR_NR == COMPAQ_SMART2_MAJOR)
+
+#define DEVICE_NAME "ida"
+#define TIMEOUT_VALUE (25*HZ)
+#define DEVICE_REQUEST do_ida_request0
+#define DEVICE_NR(device) (MINOR(device) >> 4)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
 #endif /* MAJOR_NR == whatever */
 
 #if (MAJOR_NR != SCSI_TAPE_MAJOR)
@@ -421,17 +443,6 @@
 
 #endif /* !defined(IDE_DRIVER) */
 
-/*
- * end_request() and friends. Must be called with the request queue spinlock
- * acquired. All functions called within end_request() _must_be_ atomic.
- *
- * Several drivers define their own end_request and call end_that_request_first()
- * and end_that_request_last() for parts of the original function. This prevents
- * code duplication in drivers.
- */
-
-int end_that_request_first(struct request *req, int uptodate, char *name);
-void end_that_request_last(struct request *req);
 
 #ifndef LOCAL_END_REQUEST	/* If we have our own end_request, we do not want to include this mess */
 
diff -u --recursive --new-file v2.3.15/linux/include/linux/blkdev.h linux/include/linux/blkdev.h
--- v2.3.15/linux/include/linux/blkdev.h	Wed Aug 18 16:43:56 1999
+++ linux/include/linux/blkdev.h	Tue Aug 31 16:12:08 1999
@@ -25,6 +25,7 @@
 	int errors;
 	unsigned long sector;
 	unsigned long nr_sectors;
+	unsigned long nr_segments;
 	unsigned long current_nr_sectors;
 	char * buffer;
 	struct semaphore * sem;
@@ -75,14 +76,18 @@
 
 extern int * max_sectors[MAX_BLKDEV];
 
-#define MAX_SECTORS 244 /* 254 ? */
+extern int * max_segments[MAX_BLKDEV];
+
+#define MAX_SECTORS 128
+
+#define MAX_SEGMENTS MAX_SECTORS
 
 #define PageAlignSize(size) (((size) + PAGE_SIZE -1) & PAGE_MASK)
 #if 0  /* small readahead */
 #define MAX_READAHEAD PageAlignSize(4096*7)
 #define MIN_READAHEAD PageAlignSize(4096*2)
 #else /* large readahead */
-#define MAX_READAHEAD PageAlignSize(4096*18)
+#define MAX_READAHEAD PageAlignSize(4096*31)
 #define MIN_READAHEAD PageAlignSize(4096*3)
 #endif
 
diff -u --recursive --new-file v2.3.15/linux/include/linux/capability.h linux/include/linux/capability.h
--- v2.3.15/linux/include/linux/capability.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/capability.h	Tue Aug 31 16:12:04 1999
@@ -175,6 +175,7 @@
 #define CAP_SYS_MODULE       16
 
 /* Allow ioperm/iopl access */
+/* Allow sending USB messages to any device via /proc/bus/usb */
 
 #define CAP_SYS_RAWIO        17
 
diff -u --recursive --new-file v2.3.15/linux/include/linux/cdrom.h linux/include/linux/cdrom.h
--- v2.3.15/linux/include/linux/cdrom.h	Thu Aug  5 16:24:15 1999
+++ linux/include/linux/cdrom.h	Tue Aug 31 16:03:17 1999
@@ -11,6 +11,8 @@
 #ifndef	_LINUX_CDROM_H
 #define	_LINUX_CDROM_H
 
+#include <linux/types.h>
+
 /*******************************************************
  * As of Linux 2.1.x, all Linux CD-ROM application programs will use this 
  * (and only this) include file.  It is my hope to provide Linux with
@@ -94,16 +96,26 @@
 #define CDROMPLAYBLK		0x5317	/* (struct cdrom_blk) */
 
 /* 
- * These ioctls are used only used in optcd.c
+ * These ioctls are only used in optcd.c
  */
 #define CDROMREADALL		0x5318	/* read all 2646 bytes */
-#define CDROMCLOSETRAY		0x5319	/* pendant of CDROMEJECT */
+
+/* 
+ * These ioctls are (now) only in ide-cd.c for controlling 
+ * drive spindown time.  They should be implemented in the
+ * Uniform driver, via generic packet commands, GPCMD_MODE_SELECT_10,
+ * GPCMD_MODE_SENSE_10 and the GPMODE_POWER_PAGE...
+ *  -Erik
+ */
+#define CDROMGETSPINDOWN        0x531d
+#define CDROMSETSPINDOWN        0x531e
 
 /* 
  * These ioctls are implemented through the uniform CD-ROM driver
  * They _will_ be adopted by all CD-ROM drivers, when all the CD-ROM
  * drivers are eventually ported to the uniform CD-ROM driver interface.
  */
+#define CDROMCLOSETRAY		0x5319	/* pendant of CDROMEJECT */
 #define CDROM_SET_OPTIONS	0x5320  /* Set behavior options */
 #define CDROM_CLEAR_OPTIONS	0x5321  /* Clear behavior options */
 #define CDROM_SELECT_SPEED	0x5322  /* Set the CD-ROM speed */
@@ -125,7 +137,8 @@
 #define DVD_AUTH		0x5392  /* Authentication */
 
 #define CDROM_SEND_PACKET	0x5393	/* send a packet to the drive */
-#define CDROM_BLANK		0x5394	/* blank */
+#define CDROM_NEXT_WRITABLE	0x5394	/* get next writable block */
+#define CDROM_LAST_WRITTEN	0x5395	/* get last block written on disc */
 
 /*******************************************************
  * CDROM IOCTL structures
@@ -340,14 +353,6 @@
 #define	CDROM_AUDIO_ERROR	0x14	/* audio play stopped due to error */
 #define	CDROM_AUDIO_NO_STATUS	0x15	/* no current audio status to return */
 
-/* CD-ROM-specific SCSI command opcodes */
-#define SCMD_READ_TOC		0x43	/* read table of contents */
-#define SCMD_PLAYAUDIO_MSF	0x47	/* play data at time offset */
-#define SCMD_PLAYAUDIO_TI	0x48	/* play data at track/index */
-#define SCMD_PAUSE_RESUME	0x4B	/* pause/resume audio */
-#define SCMD_READ_SUBCHANNEL	0x42	/* read SC info on playing disc */
-#define SCMD_PLAYAUDIO10	0x45	/* play data at logical block */
-
 /* capability flags used with the uniform CD-ROM driver */ 
 #define CDC_CLOSE_TRAY		0x1     /* caddy systems _can't_ close */
 #define CDC_OPEN_TRAY		0x2     /* but _can_ eject.  */
@@ -396,13 +401,93 @@
 #define CDSL_CURRENT    	((int) (~0U>>1))
 
 /*********************************************************************
- * MMC commands and such
+ * Generic Packet commands, MMC commands, and such
  *********************************************************************/
 
-#define DVD_SEND_KEY		0xa3
-#define DVD_REPORT_KEY		0xa4
-#define DVD_READ_STRUCTURE	0xad
+ /* The generic packet command opcodes for CD/DVD Logical Units,
+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+#define GPCMD_BLANK			    0xa1
+#define GPCMD_CLOSE_TRACK		    0x5b
+#define GPCMD_FLUSH_CACHE		    0x35
+#define GPCMD_FORMAT_UNIT		    0x04
+#define GPCMD_GET_CONFIGURATION		    0x46
+#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
+#define GPCMD_GET_PERFORMANCE		    0xac
+#define GPCMD_INQUIRY			    0x12
+#define GPCMD_LOAD_UNLOAD		    0xa6
+#define GPCMD_MECHANISM_STATUS		    0xbd
+#define GPCMD_MODE_SELECT_10		    0x55
+#define GPCMD_MODE_SENSE_10		    0x5a
+#define GPCMD_PAUSE_RESUME		    0x4b
+#define GPCMD_PLAY_AUDIO_10		    0x45
+#define GPCMD_PLAY_AUDIO_MSF		    0x47
+#define GPCMD_PLAY_CD			    0xbc
+#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL  0x1e
+#define GPCMD_READ_10			    0x28
+#define GPCMD_READ_12			    0xa8
+#define GPCMD_READ_CDVD_CAPACITY	    0x25
+#define GPCMD_READ_CD			    0xbe
+#define GPCMD_READ_CD_MSF		    0xb9
+#define GPCMD_READ_DISC_INFO		    0x51
+#define GPCMD_READ_DVD_STRUCTURE	    0xad
+#define GPCMD_READ_FORMAT_CAPACITIES	    0x23
+#define GPCMD_READ_HEADER		    0x44
+#define GPCMD_READ_TRACK_RZONE_INFO	    0x52
+#define GPCMD_READ_SUBCHANNEL		    0x42
+#define GPCMD_READ_TOC_PMA_ATIP		    0x43
+#define GPCMD_REPAIR_RZONE_TRACK	    0x58
+#define GPCMD_REPORT_KEY		    0xa4
+#define GPCMD_REQUEST_SENSE		    0x03
+#define GPCMD_RESERVE_RZONE_TRACK	    0x53
+#define GPCMD_SCAN			    0xba
+#define GPCMD_SEEK			    0x2b
+#define GPCMD_SEND_DVD_STRUCTURE	    0xad
+#define GPCMD_SEND_EVENT		    0xa2
+#define GPCMD_SEND_KEY			    0xa3
+#define GPCMD_SEND_OPC			    0x54
+#define GPCMD_SET_READ_AHEAD		    0xa7
+#define GPCMD_SET_STREAMING		    0xb6
+#define GPCMD_START_STOP_UNIT		    0x1b
+#define GPCMD_STOP_PLAY_SCAN		    0x4e
+#define GPCMD_TEST_UNIT_READY		    0x00
+#define GPCMD_VERIFY_10			    0x2f
+#define GPCMD_WRITE_10			    0x2a
+#define GPCMD_WRITE_AND_VERIFY_10	    0x2e
+/* This is listed as optional in ATAPI 2.6, but is (curiously) 
+ * missing from Mt. Fuji, Table 57.  It _is_ mentioned in Mt. Fuji
+ * Table 377 as an MMC command for SCSi devices though...  Most ATAPI
+ * drives support it. */
+#define GPCMD_SET_SPEED			    0xbb
+/* This seems to be a SCSI specific CD-ROM opcode 
+ * to play data at track/index */
+#define GPCMD_PLAYAUDIO_TI		    0x48
+
+/* Is this really used by anything?  I couldn't find these...*/
+#if 0
+/* MMC2/MTFuji Opcodes */
+#define ERASE			0x2c
+#define READ_BUFFER		0x3c
+#endif
+
+
+
+
+/* Mode page codes for mode sense/set */
+#define GPMODE_R_W_ERROR_PAGE	    0x1
+#define GPMODE_WRITE_PARMS_PAGE	    0x5
+#define GPMODE_AUDIO_CTL_PAGE	    0xe
+#define GPMODE_POWER_PAGE	    0x1a
+#define GPMODE_FAULT_FAIL_PAGE	    0x1c
+#define GPMODE_TO_PROTECT_PAGE	    0x1d
+#define GPMODE_CAPABILITIES_PAGE    0x2a
+#define GPMODE_ALL_PAGES	    0x3f
+/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor
+ * of MODE_SENSE_POWER_PAGE */
+#define GPMODE_CDROM_PAGE              0x0d
 
+
+
+/* DVD struct types */
 #define DVD_STRUCT_PHYSICAL	0x00
 #define DVD_STRUCT_COPYRIGHT	0x01
 #define DVD_STRUCT_DISCKEY	0x02
@@ -622,6 +707,95 @@
     long error;
 } tracktype;
 extern void cdrom_count_tracks(struct cdrom_device_info *cdi,tracktype* tracks);
+extern int cdrom_get_next_writable(kdev_t dev, long *next_writable);
+extern int cdrom_get_last_written(kdev_t dev, long *last_written);
+
+typedef struct {
+	__u16 disc_information_length;
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved1			: 3;
+        __u8 erasable			: 1;
+        __u8 border_status		: 2;
+        __u8 disc_border		: 2;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+        __u8 disc_border		: 2;
+        __u8 border_status		: 2;
+        __u8 erasable			: 1;
+	__u8 reserved1			: 3;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+	__u8 n_first_track;
+	__u8 n_sessions_lsb;
+	__u8 first_track_lsb;
+	__u8 last_track_lsb;
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 did_v			: 1;
+        __u8 dbc_v			: 1;
+        __u8 uru			: 1;
+        __u8 reserved2			: 5;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+        __u8 reserved2			: 5;
+        __u8 uru			: 1;
+        __u8 dbc_v			: 1;
+	__u8 did_v			: 1;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+	__u8 disc_type;
+	__u8 n_sessions_msb;
+	__u8 first_track_msb;
+	__u8 last_track_msb;
+	__u32 disc_id;
+	__u32 lead_in;
+	__u32 lead_out;
+	__u8 disc_bar_code[8];
+	__u8 reserved3;
+	__u8 n_opc;
+} disc_information;
+
+typedef struct {
+	__u16 track_information_length;
+	__u8 track_lsb;
+	__u8 session_lsb;
+	__u8 reserved1;
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved2			: 2;
+        __u8 damage			: 1;
+        __u8 copy			: 1;
+        __u8 track_mode			: 4;
+	__u8 rt				: 1;
+	__u8 blank			: 1;
+	__u8 packet			: 1;
+	__u8 fp				: 1;
+	__u8 data_mode			: 4;
+	__u8 reserved3			: 6;
+	__u8 lra_v			: 1;
+	__u8 nwa_v			: 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+        __u8 track_mode			: 4;
+        __u8 copy			: 1;
+        __u8 damage			: 1;
+	__u8 reserved2			: 2;
+	__u8 data_mode			: 4;
+	__u8 fp				: 1;
+	__u8 packet			: 1;
+	__u8 blank			: 1;
+	__u8 rt				: 1;
+	__u8 nwa_v			: 1;
+	__u8 lra_v			: 1;
+	__u8 reserved3			: 6;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+	__u32 track_start;
+	__u32 next_writable;
+	__u32 free_blocks;
+	__u32 fixed_packet_size;
+	__u32 track_size;
+	__u32 last_rec_address;
+} track_information;
+
 #endif  /* End of kernel only stuff */ 
 
 #endif  /* _LINUX_CDROM_H */
diff -u --recursive --new-file v2.3.15/linux/include/linux/elf.h linux/include/linux/elf.h
--- v2.3.15/linux/include/linux/elf.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/elf.h	Tue Aug 31 16:13:58 1999
@@ -59,6 +59,8 @@
 
 #define EM_PPC	       20	/* PowerPC */
 
+#define EM_SH	       42	/* SuperH */
+
 #define EM_SPARCV9     43	/* SPARC v9 64-bit */
 
 #define EM_IA_64	50	/* HP/Intel IA-64 */
diff -u --recursive --new-file v2.3.15/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.3.15/linux/include/linux/fs.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/fs.h	Tue Aug 31 16:12:04 1999
@@ -851,6 +851,25 @@
 #define LOOKUP_SLASHOK		(4)
 #define LOOKUP_CONTINUE		(8)
 
+/*
+ * "descriptor" for what we're up to with a read for sendfile().
+ * This allows us to use the same read code yet
+ * have multiple different users of the data that
+ * we read from a file.
+ *
+ * The simplest case just copies the data to user
+ * mode.
+ */
+typedef struct {
+	size_t written;
+	size_t count;
+	char * buf;
+	int error;
+} read_descriptor_t;
+
+typedef int (*read_actor_t)(read_descriptor_t *, const char *, unsigned long);
+
+
 extern struct dentry * lookup_dentry(const char *, struct dentry *, unsigned int);
 extern struct dentry * __namei(const char *, unsigned int);
 
@@ -904,6 +923,7 @@
 extern int generic_file_mmap(struct file *, struct vm_area_struct *);
 extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
 extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *, writepage_t);
+extern void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc, read_actor_t actor);
 
 
 extern struct super_block *get_super(kdev_t);
diff -u --recursive --new-file v2.3.15/linux/include/linux/init.h linux/include/linux/init.h
--- v2.3.15/linux/include/linux/init.h	Fri Aug  6 11:56:54 1999
+++ linux/include/linux/init.h	Thu Aug 26 12:43:58 1999
@@ -17,14 +17,6 @@
  *    extern int z; z = x * y;
  * }
  *
- * Depricated: you can surround the whole function declaration 
- * just before function body into __initfunc() macro, like:
- *
- * __initfunc (static void initme(int x, int y))
- * {
- *    extern int z; z = x * y;
- * }
- *
  * If the function has a prototype somewhere, you can also add
  * __init between closing brace of the prototype and semicolon:
  *
@@ -41,12 +33,6 @@
  * you should use __initlocaldata instead, due to a bug in GCC 2.7.
  */
 
-/*
- * Disable the __initfunc macros if a file that is a part of a
- * module attempts to use them. We do not want to interfere
- * with module linking.
- */
-
 #ifndef MODULE
 
 #ifndef __ASSEMBLY__
@@ -88,10 +74,6 @@
 #define __initsetup	__attribute__ ((unused,__section__ (".setup.init")))
 #define __init_call	__attribute__ ((unused,__section__ (".initcall.init")))
 
-#define __initfunc(__arginit) \
-	__arginit __init; \
-	__arginit
-
 /* For assembly routines */
 #define __INIT		.section	".text.init","ax"
 #define __FINIT		.previous
@@ -106,7 +88,6 @@
 #define __exit
 #define __initdata
 #define __exitdata
-#define __initfunc(__arginit) __arginit
 #define __initcall
 /* For assembly routines */
 #define __INIT
diff -u --recursive --new-file v2.3.15/linux/include/linux/kernel.h linux/include/linux/kernel.h
--- v2.3.15/linux/include/linux/kernel.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/kernel.h	Tue Aug 31 11:17:19 1999
@@ -91,10 +91,11 @@
 	unsigned long freeram;		/* Available memory size */
 	unsigned long sharedram;	/* Amount of shared memory */
 	unsigned long bufferram;	/* Memory used by buffers */
+	unsigned long totalbig;		/* Total big memory size */
+	unsigned long freebig;		/* Available big memory size */
 	unsigned long totalswap;	/* Total swap space size */
 	unsigned long freeswap;		/* swap space still available */
 	unsigned short procs;		/* Number of current processes */
-	char _f[22];			/* Pads structure to 64 bytes */
 };
 
 #endif
diff -u --recursive --new-file v2.3.15/linux/include/linux/linkage.h linux/include/linux/linkage.h
--- v2.3.15/linux/include/linux/linkage.h	Tue Dec  1 11:28:24 1998
+++ linux/include/linux/linkage.h	Mon Aug 30 18:12:12 1999
@@ -13,6 +13,17 @@
 #define asmlinkage CPP_ASMLINKAGE
 #endif
 
+#ifdef __sh__
+#define STRINGIFY(X) #X
+#define SYMBOL_NAME_STR(X) STRINGIFY(SYMBOL_NAME(X))
+#ifdef __STDC__
+#define SYMBOL_NAME(X) _##X
+#define SYMBOL_NAME_LABEL(X) _##X##:
+#else
+#define SYMBOL_NAME(X) _/**/X
+#define SYMBOL_NAME_LABEL(X) _/**/X/**/:
+#endif
+#else
 #define SYMBOL_NAME_STR(X) #X
 #define SYMBOL_NAME(X) X
 #ifdef __STDC__
@@ -20,6 +31,7 @@
 #else
 #define SYMBOL_NAME_LABEL(X) X/**/:
 #endif
+#endif
 
 #ifdef __arm__
 #define __ALIGN .align 0
@@ -29,6 +41,10 @@
 #define __ALIGN .align 4
 #define __ALIGN_STR ".align 4"
 #else
+#ifdef __sh__
+#define __ALIGN .balign 4
+#define __ALIGN_STR ".balign 4"
+#else
 #if !defined(__i486__) && !defined(__i586__)
 #define __ALIGN .align 4,0x90
 #define __ALIGN_STR ".align 4,0x90"
@@ -36,6 +52,7 @@
 #define __ALIGN .align 16,0x90
 #define __ALIGN_STR ".align 16,0x90"
 #endif /* __i486__/__i586__ */
+#endif /* __sh__ */
 #endif /* __mc68000__ */
 #endif /* __arm__ */
 
diff -u --recursive --new-file v2.3.15/linux/include/linux/mca.h linux/include/linux/mca.h
--- v2.3.15/linux/include/linux/mca.h	Thu Apr 15 05:42:40 1999
+++ linux/include/linux/mca.h	Thu Aug 26 14:54:23 1999
@@ -10,7 +10,9 @@
  * The information is exported to the protected code, where this 
  * variable is set to one in case MCA bus was detected.
 */
+#ifndef MCA_bus__is_a_macro
 extern int  MCA_bus;
+#endif
 
 /* maximal number of MCA slots - actually, some machines have less, but
 they all have sufficient number of POS registers to cover 8. */
diff -u --recursive --new-file v2.3.15/linux/include/linux/miscdevice.h linux/include/linux/miscdevice.h
--- v2.3.15/linux/include/linux/miscdevice.h	Fri Jun 25 17:37:52 1999
+++ linux/include/linux/miscdevice.h	Tue Aug 31 11:35:59 1999
@@ -10,7 +10,7 @@
 #define SUN_MOUSE_MINOR 6
 #define APOLLO_MOUSE_MINOR 7
 #define PC110PAD_MINOR 9
-#define MAC_MOUSE_MINOR 10
+#define ADB_MOUSE_MINOR 10
 #define WATCHDOG_MINOR		130	/* Watchdog timer     */
 #define TEMP_MINOR		131	/* Temperature Sensor */
 #define RTC_MINOR 135
diff -u --recursive --new-file v2.3.15/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.3.15/linux/include/linux/mm.h	Wed Aug 18 16:43:40 1999
+++ linux/include/linux/mm.h	Tue Aug 31 16:12:06 1999
@@ -6,6 +6,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/config.h>
 #include <linux/string.h>
 
 extern unsigned long max_mapnr;
@@ -125,6 +126,7 @@
 	struct page *next_hash;
 	atomic_t count;
 	unsigned long flags;	/* atomic flags, some possibly updated asynchronously */
+	struct list_head lru;
 	wait_queue_head_t wait;
 	struct page **pprev_hash;
 	struct buffer_head * buffers;
@@ -145,14 +147,13 @@
 #define PG_error		 1
 #define PG_referenced		 2
 #define PG_uptodate		 3
-#define PG_free_after		 4
 #define PG_decr_after		 5
-#define PG_free_swap_after	 6
 #define PG_DMA			 7
 #define PG_Slab			 8
 #define PG_swap_cache		 9
 #define PG_skip			10
 #define PG_swap_entry		11
+#define PG_BIGMEM		12
 				/* bits 21-30 unused */
 #define PG_reserved		31
 
@@ -180,9 +181,7 @@
 #define SetPageError(page)	({ int _ret = test_and_set_bit(PG_error, &(page)->flags); _ret; })
 #define ClearPageError(page)	do { if (!test_and_clear_bit(PG_error, &(page)->flags)) BUG(); } while (0)
 #define PageReferenced(page)	(test_bit(PG_referenced, &(page)->flags))
-#define PageFreeAfter(page)	(test_bit(PG_free_after, &(page)->flags))
 #define PageDecrAfter(page)	(test_bit(PG_decr_after, &(page)->flags))
-#define PageSwapUnlockAfter(page) (test_bit(PG_free_swap_after, &(page)->flags))
 #define PageDMA(page)		(test_bit(PG_DMA, &(page)->flags))
 #define PageSlab(page)		(test_bit(PG_Slab, &(page)->flags))
 #define PageSwapCache(page)	(test_bit(PG_swap_cache, &(page)->flags))
@@ -199,6 +198,11 @@
 
 #define PageTestandClearSwapCache(page)	\
 			(test_and_clear_bit(PG_swap_cache, &(page)->flags))
+#ifdef CONFIG_BIGMEM
+#define PageBIGMEM(page)	(test_bit(PG_BIGMEM, &(page)->flags))
+#else
+#define PageBIGMEM(page) 0 /* needed to optimize away at compile time */
+#endif
 
 /*
  * Various page->flags bits:
@@ -259,8 +263,6 @@
  * PG_uptodate tells whether the page's contents is valid.
  * When a read completes, the page becomes uptodate, unless a disk I/O
  * error happened.
- * When a write completes, and PG_free_after is set, the page is
- * freed without any further delay.
  *
  * For choosing which pages to swap out, inode pages carry a
  * PG_referenced bit, which is set any time the system accesses
@@ -357,11 +359,17 @@
 #define __GFP_HIGH	0x08
 #define __GFP_IO	0x10
 #define __GFP_SWAP	0x20
+#ifdef CONFIG_BIGMEM
+#define __GFP_BIGMEM	0x40
+#else
+#define __GFP_BIGMEM	0x0 /* noop */
+#endif
 
 #define __GFP_DMA	0x80
 
 #define GFP_BUFFER	(__GFP_LOW | __GFP_WAIT)
 #define GFP_ATOMIC	(__GFP_HIGH)
+#define GFP_BIGUSER	(__GFP_LOW | __GFP_WAIT | __GFP_IO | __GFP_BIGMEM)
 #define GFP_USER	(__GFP_LOW | __GFP_WAIT | __GFP_IO)
 #define GFP_KERNEL	(__GFP_MED | __GFP_WAIT | __GFP_IO)
 #define GFP_NFS		(__GFP_HIGH | __GFP_WAIT | __GFP_IO)
@@ -371,6 +379,11 @@
    platforms, used as appropriate on others */
 
 #define GFP_DMA		__GFP_DMA
+
+/* Flag - indicates that the buffer can be taken from big memory which is not
+   directly addressable by the kernel */
+
+#define GFP_BIGMEM	__GFP_BIGMEM
 
 /* vma is the first one with  address < vma->vm_end,
  * and even  address < vma->vm_start. Have to extend vma. */
diff -u --recursive --new-file v2.3.15/linux/include/linux/msdos_fs_sb.h linux/include/linux/msdos_fs_sb.h
--- v2.3.15/linux/include/linux/msdos_fs_sb.h	Mon Aug  9 12:41:57 1999
+++ linux/include/linux/msdos_fs_sb.h	Mon Aug 30 10:23:14 1999
@@ -44,7 +44,7 @@
 	unsigned long root_cluster;  /* first cluster of the root directory */
 	unsigned long fsinfo_offset; /* FAT32 fsinfo offset from start of disk */
 	wait_queue_head_t fat_wait;
-	int fat_lock;
+	struct semaphore fat_lock;
 	int prev_free;               /* previously returned free cluster number */
 	int free_clusters;           /* -1 if undefined */
 	struct fat_mount_options options;
diff -u --recursive --new-file v2.3.15/linux/include/linux/msg.h linux/include/linux/msg.h
--- v2.3.15/linux/include/linux/msg.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/msg.h	Mon Aug 30 10:23:14 1999
@@ -39,11 +39,11 @@
 	__kernel_time_t msg_stime;	/* last msgsnd time */
 	__kernel_time_t msg_rtime;	/* last msgrcv time */
 	__kernel_time_t msg_ctime;	/* last change time */
-	unsigned long  msg_cbytes;	/* Reuse junk fields for 32 bit */
-	unsigned long  msg_qbytes;	/* ditto */
-	unsigned short msg_cbytes_old;	/* current number of bytes on queue */
+	unsigned long  msg_lcbytes;	/* Reuse junk fields for 32 bit */
+	unsigned long  msg_lqbytes;	/* ditto */
+	unsigned short msg_cbytes;	/* current number of bytes on queue */
 	unsigned short msg_qnum;	/* number of messages in queue */
-	unsigned short msg_qbytes_old;	/* max number of bytes on queue */
+	unsigned short msg_qbytes;	/* max number of bytes on queue */
 	__kernel_ipc_pid_t msg_lspid;	/* pid of last msgsnd */
 	__kernel_ipc_pid_t msg_lrpid;	/* last receive pid */
 };
diff -u --recursive --new-file v2.3.15/linux/include/linux/n_r3964.h linux/include/linux/n_r3964.h
--- v2.3.15/linux/include/linux/n_r3964.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/n_r3964.h	Mon Aug 30 18:05:19 1999
@@ -0,0 +1,221 @@
+/* r3964 linediscipline for linux
+ *
+ * -----------------------------------------------------------
+ * Copyright by
+ * Philips Automation Projects
+ * Kassel (Germany)
+ * http://www.pap-philips.de
+ * -----------------------------------------------------------
+ * This software may be used and distributed according to the terms of
+ * the GNU Public License, incorporated herein by reference.
+ *
+ * Author:
+ * L. Haag
+ *
+ * $Log: r3964.h,v $
+ * Revision 1.1.1.1  1998/10/13 16:43:14  dwmw2
+ * This'll screw the version control
+ *
+ * Revision 1.6  1998/09/30 00:40:38  dwmw2
+ * Updated to use kernel's N_R3964 if available
+ *
+ * Revision 1.4  1998/04/02 20:29:44  lhaag
+ * select, blocking, ...
+ *
+ * Revision 1.3  1998/02/12 18:58:43  root
+ * fixed some memory leaks
+ * calculation of checksum characters
+ *
+ * Revision 1.2  1998/02/07 13:03:17  root
+ * ioctl read_telegram
+ *
+ * Revision 1.1  1998/02/06 19:19:43  root
+ * Initial revision
+ *
+ *
+ */
+
+#ifndef __LINUX_N_R3964_H__
+#define __LINUX_N_R3964_H__
+
+/* line disciplines for r3964 protocol */
+#include <asm/termios.h>
+
+#ifdef __KERNEL__
+/*
+ * Common ascii handshake characters:
+ */
+
+#define STX 0x02
+#define ETX 0x03
+#define DLE 0x10
+#define NAK 0x15
+
+/*
+ * Timeouts (msecs/10 msecs per timer interrupt):
+ */
+
+#define R3964_TO_QVZ 550/10
+#define R3964_TO_ZVZ 220/10
+#define R3964_TO_NO_BUF 400/10
+#define R3964_NO_TX_ROOM 100/10
+#define R3964_TO_RX_PANIC 4000/10
+#define R3964_MAX_RETRIES 5
+
+#endif
+
+/*
+ * Ioctl-commands
+ */
+
+#define R3964_ENABLE_SIGNALS      0x5301
+#define R3964_SETPRIORITY         0x5302
+#define R3964_USE_BCC             0x5303
+#define R3964_READ_TELEGRAM       0x5304
+
+/* Options for R3964_SETPRIORITY */
+#define R3964_MASTER   0
+#define R3964_SLAVE    1
+
+/* Options for R3964_ENABLE_SIGNALS */
+#define R3964_SIG_ACK   0x0001
+#define R3964_SIG_DATA  0x0002
+#define R3964_SIG_ALL   0x000f
+#define R3964_SIG_NONE  0x0000
+#define R3964_USE_SIGIO 0x1000
+
+/*
+ * r3964 operation states:
+ */
+#ifdef __KERNEL__
+
+enum { R3964_IDLE, 
+	   R3964_TX_REQUEST, R3964_TRANSMITTING, 
+	   R3964_WAIT_ZVZ_BEFORE_TX_RETRY, R3964_WAIT_FOR_TX_ACK,
+	   R3964_WAIT_FOR_RX_BUF,
+	   R3964_RECEIVING, R3964_WAIT_FOR_BCC, R3964_WAIT_FOR_RX_REPEAT
+	   };
+
+/*
+ * All open file-handles are 'clients' and are stored in a linked list:
+ */
+
+struct r3964_message;
+
+struct r3964_client_info {
+	pid_t          pid;
+    unsigned int   sig_flags;
+
+	struct r3964_client_info *next;
+
+	struct r3964_message *first_msg;
+	struct r3964_message *last_msg;
+	struct r3964_block_header *next_block_to_read;
+	int            msg_count;
+};
+
+
+#endif
+
+/* types for msg_id: */
+enum {R3964_MSG_ACK=1, R3964_MSG_DATA };
+
+#define R3964_MAX_MSG_COUNT 32
+
+/* error codes for client messages */
+#define R3964_OK 0        /* no error. */
+#define R3964_TX_FAIL -1  /* transmission error, block NOT sent */
+#define R3964_OVERFLOW -2 /* msg queue overflow */
+
+/* the client gets this struct when calling read(fd,...): */
+struct r3964_client_message {
+	  int     msg_id;
+	  int     arg;
+	  int     error_code;
+};
+
+#define R3964_MTU      256
+
+
+#ifdef __KERNEL__
+
+struct r3964_block_header;
+
+/* internal version of client_message: */
+struct r3964_message {
+	  int     msg_id;
+	  int     arg;
+	  int     error_code;
+	  struct r3964_block_header *block;
+	  struct r3964_message *next;
+};
+
+/*
+ * Header of received block in rx_buf/tx_buf:
+ */
+
+struct r3964_block_header 
+{
+	unsigned int length;             /* length in chars without header */
+	unsigned char *data;             /* usually data is located 
+                                        immediatly behind this struct */
+	unsigned int locks;              /* only used in rx_buffer */
+	  
+    struct r3964_block_header *next;
+	struct r3964_client_info *owner;  /* =NULL in rx_buffer */
+};
+
+/*
+ * If rx_buf hasn't enough space to store R3964_MTU chars,
+ * we will reject all incoming STX-requests by sending NAK.
+ */
+
+#define RX_BUF_SIZE    4000
+#define TX_BUF_SIZE    4000
+#define R3964_MAX_BLOCKS_IN_RX_QUEUE 100
+
+#define R3964_PARITY 0x0001
+#define R3964_FRAME  0x0002
+#define R3964_OVERRUN 0x0004
+#define R3964_UNKNOWN 0x0008
+#define R3964_BREAK   0x0010
+#define R3964_CHECKSUM 0x0020
+#define R3964_ERROR  0x003f
+#define R3964_BCC   0x4000
+#define R3964_DEBUG 0x8000
+
+
+struct r3964_info {
+	struct tty_struct *tty;
+	unsigned char priority;
+	unsigned char *rx_buf;            /* ring buffer */
+	unsigned char *tx_buf;
+
+	wait_queue_head_t read_wait;
+	//struct wait_queue *read_wait;
+
+	struct r3964_block_header *rx_first;
+	struct r3964_block_header *rx_last;
+	struct r3964_block_header *tx_first;
+	struct r3964_block_header *tx_last;
+	unsigned int tx_position;
+        unsigned int rx_position;
+	unsigned char last_rx;
+	unsigned char bcc;
+        unsigned int  blocks_in_rx_queue;
+	  
+	
+	struct r3964_client_info *firstClient;
+	unsigned int state;
+	unsigned int flags;
+
+	int count_down;
+    int nRetry;
+
+    struct tq_struct bh_1;
+    struct tq_struct bh_2;
+};
+
+#endif	
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/linux/netfilter_ipv4.h linux/include/linux/netfilter_ipv4.h
--- v2.3.15/linux/include/linux/netfilter_ipv4.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/netfilter_ipv4.h	Tue Aug 31 16:13:14 1999
@@ -50,10 +50,12 @@
 #define NF_IP_NUMHOOKS		5
 
 #ifdef CONFIG_NETFILTER_DEBUG
+#ifdef __KERNEL__
 void debug_print_hooks_ip(unsigned int nf_debug);
 void nf_debug_ip_local_deliver(struct sk_buff *skb);
 void nf_debug_ip_loopback_xmit(struct sk_buff *newskb);
 void nf_debug_ip_finish_output2(struct sk_buff *skb);
-#endif
+#endif /*__KERNEL__*/
+#endif /*CONFIG_NETFILTER_DEBUG*/
 
 #endif /*__LINUX_IP_NETFILTER_H*/
diff -u --recursive --new-file v2.3.15/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.3.15/linux/include/linux/pci.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/pci.h	Tue Aug 31 16:11:57 1999
@@ -455,6 +455,7 @@
 #define PCI_DEVICE_ID_CIRRUS_5436	0x00ac
 #define PCI_DEVICE_ID_CIRRUS_5446	0x00b8
 #define PCI_DEVICE_ID_CIRRUS_5480	0x00bc
+#define PCI_DEVICE_ID_CIRRUS_5462	0x00d0
 #define PCI_DEVICE_ID_CIRRUS_5464	0x00d4
 #define PCI_DEVICE_ID_CIRRUS_5465	0x00d6
 #define PCI_DEVICE_ID_CIRRUS_6729	0x1100
@@ -485,11 +486,21 @@
 #define PCI_DEVICE_ID_AMD_SCSI		0x2020
 
 #define PCI_VENDOR_ID_TRIDENT		0x1023
+#define PCI_DEVICE_ID_TRIDENT_9320	0x9320
+#define PCI_DEVICE_ID_TRIDENT_9388	0x9388
 #define PCI_DEVICE_ID_TRIDENT_9397	0x9397
+#define PCI_DEVICE_ID_TRIDENT_939A	0x939A
+#define PCI_DEVICE_ID_TRIDENT_9520	0x9520
+#define PCI_DEVICE_ID_TRIDENT_9525	0x9525
 #define PCI_DEVICE_ID_TRIDENT_9420	0x9420
 #define PCI_DEVICE_ID_TRIDENT_9440	0x9440
 #define PCI_DEVICE_ID_TRIDENT_9660	0x9660
 #define PCI_DEVICE_ID_TRIDENT_9750	0x9750
+#define PCI_DEVICE_ID_TRIDENT_9850	0x9850
+#define PCI_DEVICE_ID_TRIDENT_9880	0x9880
+#define PCI_DEVICE_ID_TRIDENT_8400	0x8400
+#define PCI_DEVICE_ID_TRIDENT_8420	0x8420
+#define PCI_DEVICE_ID_TRIDENT_8500	0x8500
 
 #define PCI_VENDOR_ID_AI		0x1025
 #define PCI_DEVICE_ID_AI_M1435		0x1435
@@ -500,11 +511,13 @@
 #define PCI_DEVICE_ID_MATROX_MYS	0x051A
 #define PCI_DEVICE_ID_MATROX_MIL_2	0x051b
 #define PCI_DEVICE_ID_MATROX_MIL_2_AGP	0x051f
-#define PCI_DEVICE_ID_MATROX_G200_PCI   0x0520
-#define PCI_DEVICE_ID_MATROX_G200_AGP   0x0521
 #define PCI_DEVICE_ID_MATROX_MGA_IMP	0x0d10
 #define PCI_DEVICE_ID_MATROX_G100_MM    0x1000
 #define PCI_DEVICE_ID_MATROX_G100_AGP   0x1001
+#define PCI_DEVICE_ID_MATROX_G200_PCI   0x0520
+#define PCI_DEVICE_ID_MATROX_G200_AGP   0x0521
+#define	PCI_DEVICE_ID_MATROX_G400	0x0525
+#define PCI_DEVICE_ID_MATROX_VIA	0x4536
 
 #define PCI_VENDOR_ID_CT		0x102c
 #define PCI_DEVICE_ID_CT_65545		0x00d8
@@ -542,6 +555,7 @@
 #define PCI_DEVICE_ID_SI_5597		0x5597
 #define PCI_DEVICE_ID_SI_5600		0x5600
 #define PCI_DEVICE_ID_SI_6306		0x6306
+#define PCI_DEVICE_ID_SI_6326		0x6326
 #define PCI_DEVICE_ID_SI_7001		0x7001
 
 #define PCI_VENDOR_ID_HP		0x103c
@@ -594,6 +608,7 @@
 /* Winbond have two vendor IDs! See 0x10ad as well */
 #define PCI_VENDOR_ID_WINBOND2		0x1050
 #define PCI_DEVICE_ID_WINBOND2_89C940	0x0940
+#define PCI_DEVICE_ID_WINBOND2_89C940F	0x5a5a
 
 #define PCI_VENDOR_ID_MOTOROLA		0x1057
 #define PCI_VENDOR_ID_MOTOROLA_OOPS	0x1507
@@ -633,6 +648,12 @@
 #define PCI_DEVICE_ID_MYLEX_DAC960P_V4	0x0010
 #define PCI_DEVICE_ID_MYLEX_DAC960P_V5	0x0020
 
+#define PCI_VENDOR_ID_MYLEX		0x1069
+#define PCI_DEVICE_ID_MYLEX_DAC960P_V2	0x0001
+#define PCI_DEVICE_ID_MYLEX_DAC960P_V3	0x0002
+#define PCI_DEVICE_ID_MYLEX_DAC960P_V4	0x0010
+#define PCI_DEVICE_ID_MYLEX_DAC960P_V5	0x0020
+
 #define PCI_VENDOR_ID_PICOP		0x1066
 #define PCI_DEVICE_ID_PICOP_PT86C52X	0x0001
 #define PCI_DEVICE_ID_PICOP_PT80C524	0x8002
@@ -721,11 +742,13 @@
 #define PCI_DEVICE_ID_DATABOOK_87144	0xb106
 
 #define PCI_VENDOR_ID_PLX		0x10b5
+#define PCI_DEVICE_ID_PLX_SPCOM200	0x1103
 #define PCI_DEVICE_ID_PLX_9050		0x9050
 #define PCI_DEVICE_ID_PLX_9060		0x9060
 #define PCI_DEVICE_ID_PLX_9060ES	0x906E
 #define PCI_DEVICE_ID_PLX_9060SD	0x906D
 #define PCI_DEVICE_ID_PLX_9080		0x9080
+#define PCI_DEVICE_ID_PLX_GTEK_SERIAL2	0xa001
 
 #define PCI_VENDOR_ID_MADGE		0x10b6
 #define PCI_DEVICE_ID_MADGE_MK2		0x0002
@@ -798,6 +821,12 @@
 #define PCI_DEVICE_ID_CERN_HIPPI_SRC	0x0022
 
 #define PCI_VENDOR_ID_NVIDIA		0x10de
+#define PCI_DEVICE_ID_NVIDIA_TNT	0x0020
+#define PCI_DEVICE_ID_NVIDIA_TNT2	0x0028
+#define PCI_DEVICE_ID_NVIDIA_UTNT2	0x0029
+#define PCI_DEVICE_ID_NVIDIA_VTNT2	0x002C
+#define PCI_DEVICE_ID_NVIDIA_UVTNT2	0x002D
+#define PCI_DEVICE_ID_NVIDIA_ITNT2	0x00A0
 
 #define PCI_VENDOR_ID_IMS		0x10e0
 #define PCI_DEVICE_ID_IMS_8849		0x8849
@@ -817,6 +846,7 @@
 #define PCI_VENDOR_ID_INTERG		0x10ea
 #define PCI_DEVICE_ID_INTERG_1680	0x1680
 #define PCI_DEVICE_ID_INTERG_1682	0x1682
+#define PCI_DEVICE_ID_INTERG_2000	0x2000
 
 #define PCI_VENDOR_ID_REALTEK		0x10ec
 #define PCI_DEVICE_ID_REALTEK_8029	0x8029
@@ -969,8 +999,8 @@
 #define PCI_VENDOR_ID_OMEGA		0x119b
 #define PCI_DEVICE_ID_OMEGA_82C092G	0x1221
 
-#define PCI_VENDOR_ID_GALILEO		0x11ab
-#define PCI_DEVICE_ID_GALILEO_GT64011	0x4146
+#define PCI_SUBVENDOR_ID_KEYSPAN	0x11a9
+#define PCI_SUBDEVICE_ID_KEYSPAN_SX2	0x5334
 
 #define PCI_VENDOR_ID_GALILEO		0x11ab
 #define PCI_DEVICE_ID_GALILEO_GT64011	0x4146
@@ -978,6 +1008,12 @@
 #define PCI_VENDOR_ID_LITEON		0x11ad
 #define PCI_DEVICE_ID_LITEON_LNE100TX	0x0002
 
+#define PCI_VENDOR_ID_V3		0x11b0
+#define PCI_DEVICE_ID_V3_V960		0x0001
+#define PCI_DEVICE_ID_V3_V350		0x0001
+#define PCI_DEVICE_ID_V3_V960V2		0x0002
+#define PCI_DEVICE_ID_V3_V350V2		0x0002
+
 #define PCI_VENDOR_ID_NP		0x11bc
 #define PCI_DEVICE_ID_NP_PCI_FDDI	0x0001
 
@@ -1082,6 +1118,16 @@
 #define PCI_VENDOR_ID_ALTEON		0x12ae
 #define PCI_DEVICE_ID_ALTEON_ACENIC	0x0001
 
+#define PCI_SUBVENDOR_ID_CONNECT_TECH			0x12c4
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232		0x0001
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232		0x0002
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232		0x0003
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485		0x0004
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4	0x0005
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485		0x0006
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2	0x0007
+#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485		0x0008
+
 #define PCI_VENDOR_ID_PICTUREL		0x12c5
 #define PCI_DEVICE_ID_PICTUREL_PCIVST	0x0081
 
@@ -1112,6 +1158,14 @@
 #define PCI_DEVICE_ID_SIIG_2S1P_20x_650	0x2061
 #define PCI_DEVICE_ID_SIIG_2S1P_20x_850	0x2062
 
+#define PCI_VENDOR_ID_SEALEVEL		0x135e
+#define PCI_DEVICE_ID_SEALEVEL_U530	0x7101
+#define PCI_DEVICE_ID_SEALEVEL_UCOMM2	0x7201
+#define PCI_DEVICE_ID_SEALEVEL_UCOMM422	0x7402
+#define PCI_DEVICE_ID_SEALEVEL_UCOMM232	0x7202
+#define PCI_DEVICE_ID_SEALEVEL_COMM4	0x7401
+#define PCI_DEVICE_ID_SEALEVEL_COMM8	0x7801
+
 #define PCI_VENDOR_ID_NETGEAR		0x1385
 #define PCI_DEVICE_ID_NETGEAR_GA620	0x620a
 
@@ -1120,6 +1174,10 @@
 #define PCI_DEVICE_ID_LAVA_DUAL_PAR_A	0x8001 /* The Lava Dual Parallel is */
 #define PCI_DEVICE_ID_LAVA_DUAL_PAR_B	0x8002 /* two PCI devices on a card */
 
+#define PCI_VENDOR_ID_PANACOM		0x14d4
+#define PCI_DEVICE_ID_PANACOM_QUADMODEM	0x0400
+#define PCI_DEVICE_ID_PANACOM_DUALMODEM	0x0402
+
 #define PCI_VENDOR_ID_SYMPHONY		0x1c1c
 #define PCI_DEVICE_ID_SYMPHONY_101	0x0001
 
@@ -1177,6 +1235,7 @@
 #define PCI_DEVICE_ID_INTEL_82430	0x0486
 #define PCI_DEVICE_ID_INTEL_82434	0x04a3
 #define PCI_DEVICE_ID_INTEL_I960	0x0960
+#define PCI_DEVICE_ID_INTEL_82559ER	0x1209
 #define PCI_DEVICE_ID_INTEL_82092AA_0	0x1221
 #define PCI_DEVICE_ID_INTEL_82092AA_1	0x1222
 #define PCI_DEVICE_ID_INTEL_7116	0x1223
@@ -1278,6 +1337,10 @@
 #define PCI_DEVICE_ID_INTERPHASE_5526	0x0004
 #define PCI_DEVICE_ID_INTERPHASE_55x6	0x0005
 
+#define PCI_VENDOR_ID_INTERPHASE		0x107e
+#define PCI_DEVICE_ID_INTERPHASE_5526	0x0004
+#define PCI_DEVICE_ID_INTERPHASE_55x6	0x0005
+
 /*
  * The PCI interface treats multi-function devices as independent
  * devices.  The slot/function address of each device is encoded
@@ -1322,7 +1385,6 @@
 	unsigned short	subsystem_device;
 	unsigned int	class;		/* 3 bytes: (base,sub,prog-if) */
 	unsigned int	hdr_type;	/* PCI header type */
-	unsigned int	master : 1;	/* set if device is master capable */
 
 	unsigned short	regs;
 
@@ -1346,12 +1408,18 @@
 	int (*deactivate)(struct pci_dev *dev);
 };
 
-#define PCI_ROM_RESOURCE 6
-#define PCI_NUM_RESOURCES 7
+/*
+ *  For PCI devices, the region numbers are assigned this way:
+ *
+ *	0-5	standard PCI regions
+ *	6	expansion ROM
+ *	7-10	bridges: address space assigned to buses behind the bridge
+ */
 
-#define PCI_REGION_EXISTS(dev, r) (dev)->resource[r].start
-#define PCI_REGION_IS_IO(dev, r) (PCI_REGION_EXISTS(dev,r) && ((dev)->resource[r].flags & PCI_BASE_ADDRESS_SPACE_IO))
-#define PCI_REGION_IS_MEM(dev, r) (PCI_REGION_EXISTS(dev,r) && !((dev)->resource[r].flags & PCI_BASE_ADDRESS_SPACE_IO))
+#define PCI_ROM_RESOURCE 6
+#define PCI_BRIDGE_RESOURCES 7
+#define PCI_NUM_RESOURCES 11
+  
 #define PCI_REGION_FLAG_MASK 0x0f	/* These bits of resource flags tell us the PCI region flags */
 
 struct pci_bus {
@@ -1362,6 +1430,7 @@
 
 	struct pci_dev	*self;		/* bridge device as seen by parent */
 	struct pci_dev	*devices;	/* devices behind this bridge */
+	struct resource	*resource[4];	/* address space routed to this bus */
 
 	void		*sysdata;	/* hook for sys-specific extension */
 	struct proc_dir_entry *procdir;	/* directory entry in /proc/bus/pci */
@@ -1409,6 +1478,7 @@
 void pcibios_init(void);
 void pcibios_fixup_bus(struct pci_bus *);
 char *pcibios_setup (char *str);
+int pcibios_assign_resource(struct pci_dev *, int i);
 
 
 /* Backward compatibility, don't use in new code! */
@@ -1440,6 +1510,7 @@
 int pci_proc_attach_device(struct pci_dev *dev);
 int pci_proc_detach_device(struct pci_dev *dev);
 void pci_name_device(struct pci_dev *dev);
+struct resource *pci_find_parent_resource(struct pci_dev *dev, struct resource *res);
 
 struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
 struct pci_dev *pci_find_subsys (unsigned int vendor, unsigned int device,
@@ -1447,6 +1518,7 @@
 				 struct pci_dev *from);
 struct pci_dev *pci_find_class (unsigned int class, struct pci_dev *from);
 struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
+int pci_find_capability (struct pci_dev *dev, int cap);
 
 #define PCI_ANY_ID (~0)
 
diff -u --recursive --new-file v2.3.15/linux/include/linux/random.h linux/include/linux/random.h
--- v2.3.15/linux/include/linux/random.h	Sun Jul 19 20:48:55 1998
+++ linux/include/linux/random.h	Tue Aug 31 12:37:39 1999
@@ -52,6 +52,7 @@
 extern void add_blkdev_randomness(int major);
 
 extern void get_random_bytes(void *buf, int nbytes);
+void generate_random_uuid(unsigned char uuid_out[16]);
 
 extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
 					__u16 sport, __u16 dport);
diff -u --recursive --new-file v2.3.15/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.3.15/linux/include/linux/sched.h	Wed Aug 18 16:43:38 1999
+++ linux/include/linux/sched.h	Tue Aug 31 16:12:06 1999
@@ -83,6 +83,26 @@
 #define TASK_SWAPPING		16
 #define TASK_EXCLUSIVE		32
 
+#define __set_task_state(tsk, state_value)		\
+	do { tsk->state = state_value; } while (0)
+#ifdef __SMP__
+#define set_task_state(tsk, state_value)		\
+	set_mb(tsk->state, state_value)
+#else
+#define set_task_state(tsk, state_value)		\
+	__set_task_state(tsk, state_value)
+#endif
+
+#define __set_current_state(state_value)			\
+	do { current->state = state_value; } while (0)
+#ifdef __SMP__
+#define set_current_state(state_value)		\
+	set_mb(current->state, state_value)
+#else
+#define set_current_state(state_value)		\
+	__set_current_state(state_value)
+#endif
+
 /*
  * Scheduling policies
  */
@@ -715,8 +735,7 @@
 									\
 	add_wait_queue(&wq, &__wait);					\
 	for (;;) {							\
-		current->state = TASK_UNINTERRUPTIBLE;			\
-		mb();							\
+		set_current_state(TASK_UNINTERRUPTIBLE);		\
 		if (condition)						\
 			break;						\
 		schedule();						\
@@ -739,8 +758,7 @@
 									\
 	add_wait_queue(&wq, &__wait);					\
 	for (;;) {							\
-		current->state = TASK_INTERRUPTIBLE;			\
-		mb();							\
+		set_current_state(TASK_INTERRUPTIBLE);			\
 		if (condition)						\
 			break;						\
 		if (!signal_pending(current)) {				\
diff -u --recursive --new-file v2.3.15/linux/include/linux/serial.h linux/include/linux/serial.h
--- v2.3.15/linux/include/linux/serial.h	Tue Nov  3 22:05:25 1998
+++ linux/include/linux/serial.h	Tue Aug 31 12:47:56 1999
@@ -24,7 +24,9 @@
 	int	hub6;
 	unsigned short	closing_wait; /* time to wait before closing */
 	unsigned short	closing_wait2; /* no longer used... */
-	int	reserved[4];
+	unsigned char	*iomem_base;
+	unsigned short	iomem_reg_shift;
+	int	reserved[2];
 };
 
 /*
@@ -47,7 +49,10 @@
 #define PORT_16650V2	7
 #define PORT_16750	8
 #define PORT_STARTECH	9	/* usurped by cyclades.c */
-#define PORT_MAX	9
+#define PORT_16C950	10	/* Oxford Semiconductor */
+#define PORT_16654	11
+#define PORT_16850	12
+#define PORT_MAX	12
 
 struct serial_uart_config {
 	char	*name;
diff -u --recursive --new-file v2.3.15/linux/include/linux/serialP.h linux/include/linux/serialP.h
--- v2.3.15/linux/include/linux/serialP.h	Wed Aug 18 16:43:29 1999
+++ linux/include/linux/serialP.h	Tue Aug 31 16:11:59 1999
@@ -21,6 +21,10 @@
 
 #include <linux/termios.h>
 #include <linux/tqueue.h>
+#include <linux/wait.h>
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
 
 /*
  * Counters of the input lines (CTS, DSR, RI, CD) interrupts
@@ -40,9 +44,12 @@
 	int	hub6;
 	int	type;
 	int	line;
+	int	revision;	/* Chip revision (950) */
 	int	xmit_fifo_size;
 	int	custom_divisor;
 	int	count;
+	u8	*iomem_base;
+	u16	iomem_reg_shift;
 	unsigned short	close_delay;
 	unsigned short	closing_wait; /* time to wait before closing */
 	struct async_icount	icount;	
@@ -69,6 +76,8 @@
 	unsigned short		closing_wait2;
 	int			IER; 	/* Interrupt Enable Register */
 	int			MCR; 	/* Modem control register */
+	int			LCR; 	/* Line control register */
+	int			ACR;	 /* 16950 Additional Control Reg. */
 	unsigned long		event;
 	unsigned long		last_active;
 	int			line;
@@ -79,14 +88,24 @@
 	int			xmit_head;
 	int			xmit_tail;
 	int			xmit_cnt;
+	u8			*iomem_base;
+	u16			iomem_reg_shift;
 	struct tq_struct	tqueue;
+#ifdef DECLARE_WAITQUEUE
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 	wait_queue_head_t	delta_msr_wait;
+#else	
+	struct wait_queue	*open_wait;
+	struct wait_queue	*close_wait;
+	struct wait_queue	*delta_msr_wait;
+#endif	
 	struct async_struct	*next_port; /* For the linked list */
 	struct async_struct	*prev_port;
 };
 
+#define CONFIGURED_SERIAL_PORT(info) ((info)->port || ((info)->iomem_base))
+
 #define SERIAL_MAGIC 0x5301
 #define SSTATE_MAGIC 0x5302
 
@@ -115,5 +134,51 @@
 	unsigned char	mask4, match4;
 	int		port_monitor;
 };
+
+#if defined(__alpha__) && !defined(CONFIG_PCI)
+/*
+ * Digital did something really horribly wrong with the OUT1 and OUT2
+ * lines on at least some ALPHA's.  The failure mode is that if either
+ * is cleared, the machine locks up with endless interrupts.
+ */
+#define ALPHA_KLUDGE_MCR  (UART_MCR_OUT2 | UART_MCR_OUT1)
+#else
+#define ALPHA_KLUDGE_MCR 0
+#endif
+
+/*
+ * Structures and definitions for PCI support
+ */
+struct pci_board {
+	unsigned short vendor;
+	unsigned short device;
+	unsigned short subvendor;
+	unsigned short subdevice;
+	int flags;
+	int num_ports;
+	int base_baud;
+	int uart_offset;
+	int reg_shift;
+	void (*init_fn)(struct pci_dev *dev, struct pci_board *board,
+			int enable);
+};
+
+struct pci_board_inst {
+	struct pci_board	*board;
+	struct pci_dev		*dev;
+};
+
+#ifndef PCI_ANY_ID
+#define PCI_ANY_ID (~0)
+#endif
+
+#define SPCI_FL_BASE_MASK	0x0007
+#define SPCI_FL_BASE0	0x0000
+#define SPCI_FL_BASE1	0x0001
+#define SPCI_FL_BASE2	0x0002
+#define SPCI_FL_BASE3	0x0003
+#define SPCI_FL_BASE4	0x0004
+#define SPCI_FL_IOMEM		0x0008 /* Use I/O mapped memory */
+#define SPCI_FL_BASE_TABLE	0x0010 /* Use base address table for UART */
 
 #endif /* _LINUX_SERIAL_H */
diff -u --recursive --new-file v2.3.15/linux/include/linux/serial_reg.h linux/include/linux/serial_reg.h
--- v2.3.15/linux/include/linux/serial_reg.h	Mon May 25 10:32:52 1998
+++ linux/include/linux/serial_reg.h	Tue Aug 31 12:47:56 1999
@@ -17,17 +17,29 @@
 #define UART_RX		0	/* In:  Receive buffer (DLAB=0) */
 #define UART_TX		0	/* Out: Transmit buffer (DLAB=0) */
 #define UART_DLL	0	/* Out: Divisor Latch Low (DLAB=1) */
+#define UART_TRG	0	/* (LCR=BF) FCTR bit 7 selects Rx or Tx
+				 * In: Fifo count
+				 * Out: Fifo custom trigger levels
+				 * XR16C85x only */
+
 #define UART_DLM	1	/* Out: Divisor Latch High (DLAB=1) */
 #define UART_IER	1	/* Out: Interrupt Enable Register */
+#define UART_FCTR	1	/* (LCR=BF) Feature Control Register
+				 * XR16C85x only */
+
 #define UART_IIR	2	/* In:  Interrupt ID Register */
 #define UART_FCR	2	/* Out: FIFO Control Register */
 #define UART_EFR	2	/* I/O: Extended Features Register */
 				/* (DLAB=1, 16C660 only) */
+
 #define UART_LCR	3	/* Out: Line Control Register */
 #define UART_MCR	4	/* Out: Modem Control Register */
 #define UART_LSR	5	/* In:  Line Status Register */
 #define UART_MSR	6	/* In:  Modem Status Register */
 #define UART_SCR	7	/* I/O: Scratch Register */
+#define UART_EMSR	7	/* (LCR=BF) Extended Mode Select Register 
+				 * FCTR bit 6 selects SCR or EMSR
+				 * XR16c85x only */
 
 /*
  * These are the definitions for the FIFO Control Register
@@ -139,6 +151,83 @@
 /*
  * the low four bits control software flow control
  */
+
+/*
+ * These register definitions are for the 16C950
+ */
+#define UART_ASR	0x01	/* Additional Status Register */
+#define UART_RFL	0x03	/* Transmitter FIFO level */
+#define UART_TFL 	0x04	/* Receiver FIFO level */
+#define UART_ICR	0x05	/* Index Control Register */
+
+/* The 16950 ICR registers */
+#define UART_ACR	0x00	/* Additional Control Register */
+#define UART_CPR	0x01	/* Clock Prescalar Register */
+#define UART_TCR	0x02	/* Times Clock Register */
+#define UART_CKS	0x03	/* Clock Select Register */
+#define UART_TTL	0x04	/* Transmitter Interrupt Trigger Level */
+#define UART_RTL	0x05	/* Receiver Interrupt Trigger Level */
+#define UART_FCL	0x06	/* Flow Control Level Lower */
+#define UART_FCH	0x07	/* Flow Control Level Higher */
+#define UART_ID1	0x08	/* ID #1 */
+#define UART_ID2	0x09	/* ID #2 */
+#define UART_ID3	0x0A	/* ID #3 */
+#define UART_REV	0x0B	/* Revision */
+#define UART_CSR	0x0C	/* Channel Software Reset */
+#define UART_NMR	0x0D	/* Nine-bit Mode Register */
+#define UART_CTR	0xFF
+
+/*
+ * The 16C950 Additional Control Reigster
+ */
+#define UART_ACR_RXDIS	0x01	/* Receiver disable */
+#define UART_ACR_TXDIS	0x02	/* Receiver disable */
+#define UART_ACR_DSRFC	0x04	/* DSR Flow Control */
+#define UART_ACR_TLENB	0x20	/* 950 trigger levels enable */
+#define UART_ACR_ICRRD	0x40	/* ICR Read enable */
+#define UART_ACR_ASREN	0x80	/* Additional status enable */
+
+/*
+ * These are the definitions for the Feature Control Register
+ * (XR16C85x only, when LCR=bf; doubles with the Interrupt Enable
+ * Register, UART register #1)
+ */
+#define UART_FCTR_RTS_NODELAY	0x00  /* RTS flow control delay */
+#define UART_FCTR_RTS_4DELAY	0x01
+#define UART_FCTR_RTS_6DELAY	0x02
+#define UART_FCTR_RTS_8DELAY	0x03
+#define UART_FCTR_IRDA	0x04  /* IrDa data encode select */
+#define UART_FCTR_TX_INT	0x08  /* Tx interrupt type select */
+#define UART_FCTR_TRGA	0x00  /* Tx/Rx 550 trigger table select */
+#define UART_FCTR_TRGB	0x10  /* Tx/Rx 650 trigger table select */
+#define UART_FCTR_TRGC	0x20  /* Tx/Rx 654 trigger table select */
+#define UART_FCTR_TRGD	0x30  /* Tx/Rx 850 programmable trigger select */
+#define UART_FCTR_SCR_SWAP	0x40  /* Scratch pad register swap */
+#define UART_FCTR_RX	0x00  /* Programmable trigger mode select */
+#define UART_FCTR_TX	0x80  /* Programmable trigger mode select */
+
+/*
+ * These are the definitions for the Enhanced Mode Select Register
+ * (XR16C85x only, when LCR=bf and FCTR bit 6=1; doubles with the
+ * Scratch register, UART register #7)
+ */
+#define UART_EMSR_FIFO_COUNT	0x01  /* Rx/Tx select */
+#define UART_EMSR_ALT_COUNT	0x02  /* Alternating count select */
+
+/*
+ * These are the definitions for the Programmable Trigger
+ * Register (XR16C85x only, when LCR=bf; doubles with the UART RX/TX
+ * register, UART register #0)
+ */
+#define UART_TRG_1	0x01
+#define UART_TRG_4	0x04
+#define UART_TRG_8	0x08
+#define UART_TRG_16	0x10
+#define UART_TRG_32	0x20
+#define UART_TRG_64	0x40
+#define UART_TRG_96	0x60
+#define UART_TRG_120	0x78
+#define UART_TRG_128	0x80
 
 #endif /* _LINUX_SERIAL_REG_H */
 
diff -u --recursive --new-file v2.3.15/linux/include/linux/swap.h linux/include/linux/swap.h
--- v2.3.15/linux/include/linux/swap.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/swap.h	Tue Aug 31 16:11:57 1999
@@ -64,6 +64,8 @@
 
 extern int nr_swap_pages;
 extern int nr_free_pages;
+extern int nr_lru_pages;
+extern struct list_head lru_cache;
 extern atomic_t nr_async_pages;
 extern struct inode swapper_inode;
 extern atomic_t page_cache_size;
@@ -157,10 +159,29 @@
 	count = page_count(page);
 	if (PageSwapCache(page))
 		count += swap_count(page->offset) - 2;
-	if (PageFreeAfter(page))
-		count--;
 	return  count > 1;
 }
+
+extern spinlock_t pagemap_lru_lock;
+
+/*
+ * Helper macros for lru_pages handling.
+ */
+#define	lru_cache_add(page)			\
+do {						\
+	spin_lock(&pagemap_lru_lock);		\
+	list_add(&(page)->lru, &lru_cache);	\
+	nr_lru_pages++;				\
+	spin_unlock(&pagemap_lru_lock);		\
+} while (0)
+
+#define	lru_cache_del(page)			\
+do {						\
+	spin_lock(&pagemap_lru_lock);		\
+	list_del(&(page)->lru);			\
+	nr_lru_pages--;				\
+	spin_unlock(&pagemap_lru_lock);		\
+} while (0)
 
 #endif /* __KERNEL__*/
 
diff -u --recursive --new-file v2.3.15/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.3.15/linux/include/linux/sysctl.h	Thu Aug 26 13:05:41 1999
+++ linux/include/linux/sysctl.h	Tue Aug 31 12:37:39 1999
@@ -100,9 +100,10 @@
 	KERN_SHMMAX=34,         /* int: Maximum shared memory segment */
 	KERN_MSGMAX=35,         /* int: Maximum size of a messege */
 	KERN_MSGMNB=36,         /* int: Maximum message queue size */
-	KERN_MSGPOOL=37,         /* int: Maximum system message pool size */
+	KERN_MSGPOOL=37,        /* int: Maximum system message pool size */
 	KERN_SYSRQ=38,		/* int: Sysreq enable */
-	KERN_MAX_THREADS=39     /* int: Maximum nr of threads in the system */
+	KERN_MAX_THREADS=39,    /* int: Maximum nr of threads in the system */
+ 	KERN_RANDOM=40		/* Random driver */
 };
 
 
@@ -142,6 +143,17 @@
 	NET_DECNET=15,
 	NET_ECONET=16,
 	NET_KHTTPD=17
+};
+
+/* /proc/sys/kernel/random */
+enum
+{
+	RANDOM_POOLSIZE=1,
+	RANDOM_ENTROPY_COUNT=2,
+	RANDOM_READ_THRESH=3,
+	RANDOM_WRITE_THRESH=4,
+	RANDOM_BOOT_ID=5,
+	RANDOM_UUID=6
 };
 
 /* /proc/sys/bus/isa */
diff -u --recursive --new-file v2.3.15/linux/include/math-emu/double.h linux/include/math-emu/double.h
--- v2.3.15/linux/include/math-emu/double.h	Wed Dec 31 16:00:00 1969
+++ linux/include/math-emu/double.h	Tue Aug 31 11:24:24 1999
@@ -0,0 +1,197 @@
+/* Software floating-point emulation.
+   Definitions for IEEE Double Precision
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+		  Jakub Jelinek (jj@ultra.linux.cz),
+		  David S. Miller (davem@redhat.com) and
+		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel kid.  Go buy yourself a real computer."
+#endif
+
+#if _FP_W_TYPE_SIZE < 64
+#define _FP_FRACTBITS_D		(2 * _FP_W_TYPE_SIZE)
+#else
+#define _FP_FRACTBITS_D		_FP_W_TYPE_SIZE
+#endif
+
+#define _FP_FRACBITS_D		53
+#define _FP_FRACXBITS_D		(_FP_FRACTBITS_D - _FP_FRACBITS_D)
+#define _FP_WFRACBITS_D		(_FP_WORKBITS + _FP_FRACBITS_D)
+#define _FP_WFRACXBITS_D	(_FP_FRACTBITS_D - _FP_WFRACBITS_D)
+#define _FP_EXPBITS_D		11
+#define _FP_EXPBIAS_D		1023
+#define _FP_EXPMAX_D		2047
+
+#define _FP_QNANBIT_D		\
+	((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE)
+#define _FP_IMPLBIT_D		\
+	((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE)
+#define _FP_OVERFLOW_D		\
+	((_FP_W_TYPE)1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE)
+
+#if _FP_W_TYPE_SIZE < 64
+
+union _FP_UNION_D
+{
+  double flt;
+  struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned sign  : 1;
+    unsigned exp   : _FP_EXPBITS_D;
+    unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
+    unsigned frac0 : _FP_W_TYPE_SIZE;
+#else
+    unsigned frac0 : _FP_W_TYPE_SIZE;
+    unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
+    unsigned exp   : _FP_EXPBITS_D;
+    unsigned sign  : 1;
+#endif
+  } bits __attribute__((packed));
+};
+
+#define FP_DECL_D(X)		_FP_DECL(2,X)
+#define FP_UNPACK_RAW_D(X,val)	_FP_UNPACK_RAW_2(D,X,val)
+#define FP_UNPACK_RAW_DP(X,val)	_FP_UNPACK_RAW_2_P(D,X,val)
+#define FP_PACK_RAW_D(val,X)	_FP_PACK_RAW_2(D,val,X)
+#define FP_PACK_RAW_DP(val,X)		\
+  do {					\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_2_P(D,val,X);	\
+  } while (0)
+
+#define FP_UNPACK_D(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_2(D,X,val);		\
+    _FP_UNPACK_CANONICAL(D,2,X);	\
+  } while (0)
+
+#define FP_UNPACK_DP(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_2_P(D,X,val);	\
+    _FP_UNPACK_CANONICAL(D,2,X);	\
+  } while (0)
+
+#define FP_PACK_D(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(D,2,X);		\
+    _FP_PACK_RAW_2(D,val,X);		\
+  } while (0)
+
+#define FP_PACK_DP(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(D,2,X);		\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_2_P(D,val,X);	\
+  } while (0)
+
+#define FP_ISSIGNAN_D(X)		_FP_ISSIGNAN(D,2,X)
+#define FP_NEG_D(R,X)			_FP_NEG(D,2,R,X)
+#define FP_ADD_D(R,X,Y)			_FP_ADD(D,2,R,X,Y)
+#define FP_SUB_D(R,X,Y)			_FP_SUB(D,2,R,X,Y)
+#define FP_MUL_D(R,X,Y)			_FP_MUL(D,2,R,X,Y)
+#define FP_DIV_D(R,X,Y)			_FP_DIV(D,2,R,X,Y)
+#define FP_SQRT_D(R,X)			_FP_SQRT(D,2,R,X)
+#define _FP_SQRT_MEAT_D(R,S,T,X,Q)	_FP_SQRT_MEAT_2(R,S,T,X,Q)
+
+#define FP_CMP_D(r,X,Y,un)	_FP_CMP(D,2,r,X,Y,un)
+#define FP_CMP_EQ_D(r,X,Y)	_FP_CMP_EQ(D,2,r,X,Y)
+
+#define FP_TO_INT_D(r,X,rsz,rsg)	_FP_TO_INT(D,2,r,X,rsz,rsg)
+#define FP_FROM_INT_D(X,r,rs,rt)	_FP_FROM_INT(D,2,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_D(X)	_FP_FRAC_HIGH_2(X)
+#define _FP_FRAC_HIGH_RAW_D(X)	_FP_FRAC_HIGH_2(X)
+
+#else
+
+union _FP_UNION_D
+{
+  double flt;
+  struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned sign : 1;
+    unsigned exp  : _FP_EXPBITS_D;
+    unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
+#else
+    unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
+    unsigned exp  : _FP_EXPBITS_D;
+    unsigned sign : 1;
+#endif
+  } bits __attribute__((packed));
+};
+
+#define FP_DECL_D(X)		_FP_DECL(1,X)
+#define FP_UNPACK_RAW_D(X,val)	_FP_UNPACK_RAW_1(D,X,val)
+#define FP_UNPACK_RAW_DP(X,val)	_FP_UNPACK_RAW_1_P(D,X,val)
+#define FP_PACK_RAW_D(val,X)	_FP_PACK_RAW_1(D,val,X)
+#define FP_PACK_RAW_DP(val,X)		\
+  do {					\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_1_P(D,val,X);	\
+  } while (0)
+
+#define FP_UNPACK_D(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_1(D,X,val);		\
+    _FP_UNPACK_CANONICAL(D,1,X);	\
+  } while (0)
+
+#define FP_UNPACK_DP(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_1_P(D,X,val);	\
+    _FP_UNPACK_CANONICAL(D,1,X);	\
+  } while (0)
+
+#define FP_PACK_D(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(D,1,X);		\
+    _FP_PACK_RAW_1(D,val,X);		\
+  } while (0)
+
+#define FP_PACK_DP(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(D,1,X);		\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_1_P(D,val,X);	\
+  } while (0)
+
+#define FP_ISSIGNAN_D(X)		_FP_ISSIGNAN(D,1,X)
+#define FP_NEG_D(R,X)			_FP_NEG(D,1,R,X)
+#define FP_ADD_D(R,X,Y)			_FP_ADD(D,1,R,X,Y)
+#define FP_SUB_D(R,X,Y)			_FP_SUB(D,1,R,X,Y)
+#define FP_MUL_D(R,X,Y)			_FP_MUL(D,1,R,X,Y)
+#define FP_DIV_D(R,X,Y)			_FP_DIV(D,1,R,X,Y)
+#define FP_SQRT_D(R,X)			_FP_SQRT(D,1,R,X)
+#define _FP_SQRT_MEAT_D(R,S,T,X,Q)	_FP_SQRT_MEAT_1(R,S,T,X,Q)
+
+/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
+   the target machine.  */
+
+#define FP_CMP_D(r,X,Y,un)	_FP_CMP(D,1,r,X,Y,un)
+#define FP_CMP_EQ_D(r,X,Y)	_FP_CMP_EQ(D,1,r,X,Y)
+
+#define FP_TO_INT_D(r,X,rsz,rsg)	_FP_TO_INT(D,1,r,X,rsz,rsg)
+#define FP_FROM_INT_D(X,r,rs,rt)	_FP_FROM_INT(D,1,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_D(X)	_FP_FRAC_HIGH_1(X)
+#define _FP_FRAC_HIGH_RAW_D(X)	_FP_FRAC_HIGH_1(X)
+
+#endif /* W_TYPE_SIZE < 64 */
diff -u --recursive --new-file v2.3.15/linux/include/math-emu/extended.h linux/include/math-emu/extended.h
--- v2.3.15/linux/include/math-emu/extended.h	Wed Dec 31 16:00:00 1969
+++ linux/include/math-emu/extended.h	Tue Aug 31 11:24:24 1999
@@ -0,0 +1,388 @@
+/* Software floating-point emulation.
+   Definitions for IEEE Extended Precision.
+   Copyright (C) 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek (jj@ultra.linux.cz).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel, kid. Go buy yourself a real computer."
+#endif
+
+#if _FP_W_TYPE_SIZE < 64
+#define _FP_FRACTBITS_E         (4*_FP_W_TYPE_SIZE)
+#else
+#define _FP_FRACTBITS_E		(2*_FP_W_TYPE_SIZE)
+#endif
+
+#define _FP_FRACBITS_E		64
+#define _FP_FRACXBITS_E		(_FP_FRACTBITS_E - _FP_FRACBITS_E)
+#define _FP_WFRACBITS_E		(_FP_WORKBITS + _FP_FRACBITS_E)
+#define _FP_WFRACXBITS_E	(_FP_FRACTBITS_E - _FP_WFRACBITS_E)
+#define _FP_EXPBITS_E		15
+#define _FP_EXPBIAS_E		16383
+#define _FP_EXPMAX_E		32767
+
+#define _FP_QNANBIT_E		\
+	((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2) % _FP_W_TYPE_SIZE)
+#define _FP_IMPLBIT_E		\
+	((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1) % _FP_W_TYPE_SIZE)
+#define _FP_OVERFLOW_E		\
+	((_FP_W_TYPE)1 << (_FP_WFRACBITS_E % _FP_W_TYPE_SIZE))
+
+#if _FP_W_TYPE_SIZE < 64
+
+union _FP_UNION_E
+{
+   long double flt;
+   struct 
+   {
+#if __BYTE_ORDER == __BIG_ENDIAN
+      unsigned long pad1 : _FP_W_TYPE_SIZE;
+      unsigned long pad2 : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
+      unsigned long sign : 1;
+      unsigned long exp : _FP_EXPBITS_E;
+      unsigned long frac1 : _FP_W_TYPE_SIZE;
+      unsigned long frac0 : _FP_W_TYPE_SIZE;
+#else
+      unsigned long frac0 : _FP_W_TYPE_SIZE;
+      unsigned long frac1 : _FP_W_TYPE_SIZE;
+      unsigned exp : _FP_EXPBITS_E;
+      unsigned sign : 1;
+#endif /* not bigendian */
+   } bits __attribute__((packed));
+};
+
+
+#define FP_DECL_E(X)		_FP_DECL(4,X)
+
+#define FP_UNPACK_RAW_E(X, val)				\
+  do {							\
+    union _FP_UNION_E _flo; _flo.flt = (val);		\
+							\
+    X##_f[2] = 0; X##_f[3] = 0;				\
+    X##_f[0] = _flo.bits.frac0;				\
+    X##_f[1] = _flo.bits.frac1;				\
+    X##_e  = _flo.bits.exp;				\
+    X##_s  = _flo.bits.sign;				\
+    if (!X##_e && (X##_f[1] || X##_f[0])		\
+        && !(X##_f[1] & _FP_IMPLBIT_E))			\
+      {							\
+        X##_e++;					\
+        FP_SET_EXCEPTION(FP_EX_DENORM);			\
+      }							\
+  } while (0)
+
+#define FP_UNPACK_RAW_EP(X, val)			\
+  do {							\
+    union _FP_UNION_E *_flo =				\
+    (union _FP_UNION_E *)(val);				\
+							\
+    X##_f[2] = 0; X##_f[3] = 0;				\
+    X##_f[0] = _flo->bits.frac0;			\
+    X##_f[1] = _flo->bits.frac1;			\
+    X##_e  = _flo->bits.exp;				\
+    X##_s  = _flo->bits.sign;				\
+    if (!X##_e && (X##_f[1] || X##_f[0])		\
+        && !(X##_f[1] & _FP_IMPLBIT_E))			\
+      {							\
+        X##_e++;					\
+        FP_SET_EXCEPTION(FP_EX_DENORM);			\
+      }							\
+  } while (0)
+
+#define FP_PACK_RAW_E(val, X)				\
+  do {							\
+    union _FP_UNION_E _flo;				\
+							\
+    if (X##_e) X##_f[1] |= _FP_IMPLBIT_E;		\
+    else X##_f[1] &= ~(_FP_IMPLBIT_E);			\
+    _flo.bits.frac0 = X##_f[0];				\
+    _flo.bits.frac1 = X##_f[1];				\
+    _flo.bits.exp   = X##_e;				\
+    _flo.bits.sign  = X##_s;				\
+							\
+    (val) = _flo.flt;					\
+  } while (0)
+
+#define FP_PACK_RAW_EP(val, X)				\
+  do {							\
+    if (!FP_INHIBIT_RESULTS)				\
+      {							\
+	union _FP_UNION_E *_flo =			\
+	  (union _FP_UNION_E *)(val);			\
+							\
+	if (X##_e) X##_f[1] |= _FP_IMPLBIT_E;		\
+	else X##_f[1] &= ~(_FP_IMPLBIT_E);		\
+	_flo->bits.frac0 = X##_f[0];			\
+	_flo->bits.frac1 = X##_f[1];			\
+	_flo->bits.exp   = X##_e;			\
+	_flo->bits.sign  = X##_s;			\
+      }							\
+  } while (0)
+
+#define FP_UNPACK_E(X,val)		\
+  do {					\
+    FP_UNPACK_RAW_E(X,val);		\
+    _FP_UNPACK_CANONICAL(E,4,X);	\
+  } while (0)
+
+#define FP_UNPACK_EP(X,val)		\
+  do {					\
+    FP_UNPACK_RAW_2_P(X,val);		\
+    _FP_UNPACK_CANONICAL(E,4,X);	\
+  } while (0)
+
+#define FP_PACK_E(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(E,4,X);		\
+    FP_PACK_RAW_E(val,X);		\
+  } while (0)
+
+#define FP_PACK_EP(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(E,4,X);		\
+    FP_PACK_RAW_EP(val,X);		\
+  } while (0)
+
+#define FP_ISSIGNAN_E(X)	_FP_ISSIGNAN(E,4,X)
+#define FP_NEG_E(R,X)		_FP_NEG(E,4,R,X)
+#define FP_ADD_E(R,X,Y)		_FP_ADD(E,4,R,X,Y)
+#define FP_SUB_E(R,X,Y)		_FP_SUB(E,4,R,X,Y)
+#define FP_MUL_E(R,X,Y)		_FP_MUL(E,4,R,X,Y)
+#define FP_DIV_E(R,X,Y)		_FP_DIV(E,4,R,X,Y)
+#define FP_SQRT_E(R,X)		_FP_SQRT(E,4,R,X)
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ * This has special _E version because standard _4 square
+ * root would not work (it has to start normally with the
+ * second word and not the first), but as we have to do it
+ * anyway, we optimize it by doing most of the calculations
+ * in two UWtype registers instead of four.
+ */
+ 
+#define _FP_SQRT_MEAT_E(R, S, T, X, q)			\
+  do {							\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
+    _FP_FRAC_SRL_4(X, (_FP_WORKBITS));			\
+    while (q)						\
+      {							\
+	T##_f[1] = S##_f[1] + q;			\
+	if (T##_f[1] <= X##_f[1])			\
+	  {						\
+	    S##_f[1] = T##_f[1] + q;			\
+	    X##_f[1] -= T##_f[1];			\
+	    R##_f[1] += q;				\
+	  }						\
+	_FP_FRAC_SLL_2(X, 1);				\
+	q >>= 1;					\
+      }							\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
+    while (q)						\
+      {							\
+	T##_f[0] = S##_f[0] + q;			\
+	T##_f[1] = S##_f[1];				\
+	if (T##_f[1] < X##_f[1] || 			\
+	    (T##_f[1] == X##_f[1] &&			\
+	     T##_f[0] <= X##_f[0]))			\
+	  {						\
+	    S##_f[0] = T##_f[0] + q;			\
+	    S##_f[1] += (T##_f[0] > S##_f[0]);		\
+	    _FP_FRAC_DEC_2(X, T);			\
+	    R##_f[0] += q;				\
+	  }						\
+	_FP_FRAC_SLL_2(X, 1);				\
+	q >>= 1;					\
+      }							\
+    _FP_FRAC_SLL_4(R, (_FP_WORKBITS));			\
+    if (X##_f[0] | X##_f[1])				\
+      {							\
+	if (S##_f[1] < X##_f[1] || 			\
+	    (S##_f[1] == X##_f[1] &&			\
+	     S##_f[0] < X##_f[0]))			\
+	  R##_f[0] |= _FP_WORK_ROUND;			\
+	R##_f[0] |= _FP_WORK_STICKY;			\
+      }							\
+  } while (0)
+
+#define FP_CMP_E(r,X,Y,un)	_FP_CMP(E,4,r,X,Y,un)
+#define FP_CMP_EQ_E(r,X,Y)	_FP_CMP_EQ(E,4,r,X,Y)
+
+#define FP_TO_INT_E(r,X,rsz,rsg)	_FP_TO_INT(E,4,r,X,rsz,rsg)
+#define FP_FROM_INT_E(X,r,rs,rt)	_FP_FROM_INT(E,4,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_E(X)	(X##_f[2])
+#define _FP_FRAC_HIGH_RAW_E(X)	(X##_f[1])
+
+#else   /* not _FP_W_TYPE_SIZE < 64 */
+union _FP_UNION_E
+{
+  long double flt /* __attribute__((mode(TF))) */ ;
+  struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned long pad : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
+    unsigned sign  : 1;
+    unsigned exp   : _FP_EXPBITS_E;
+    unsigned long frac : _FP_W_TYPE_SIZE;
+#else
+    unsigned long frac : _FP_W_TYPE_SIZE;
+    unsigned exp   : _FP_EXPBITS_E;
+    unsigned sign  : 1;
+#endif
+  } bits;
+};
+
+#define FP_DECL_E(X)		_FP_DECL(2,X)
+
+#define FP_UNPACK_RAW_E(X, val)					\
+  do {								\
+    union _FP_UNION_E _flo; _flo.flt = (val);			\
+								\
+    X##_f0 = _flo.bits.frac;					\
+    X##_f1 = 0;							\
+    X##_e = _flo.bits.exp;					\
+    X##_s = _flo.bits.sign;					\
+    if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E))		\
+      {								\
+        X##_e++;						\
+        FP_SET_EXCEPTION(FP_EX_DENORM);				\
+      }								\
+  } while (0)
+
+#define FP_UNPACK_RAW_EP(X, val)				\
+  do {								\
+    union _FP_UNION_E *_flo =					\
+      (union _FP_UNION_E *)(val);				\
+								\
+    X##_f0 = _flo->bits.frac;					\
+    X##_f1 = 0;							\
+    X##_e = _flo->bits.exp;					\
+    X##_s = _flo->bits.sign;					\
+    if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E))		\
+      {								\
+        X##_e++;						\
+        FP_SET_EXCEPTION(FP_EX_DENORM);				\
+      }								\
+  } while (0)
+
+#define FP_PACK_RAW_E(val, X)					\
+  do {								\
+    union _FP_UNION_E _flo;					\
+								\
+    if (X##_e) X##_f0 |= _FP_IMPLBIT_E;				\
+    else X##_f0 &= ~(_FP_IMPLBIT_E);				\
+    _flo.bits.frac = X##_f0;					\
+    _flo.bits.exp  = X##_e;					\
+    _flo.bits.sign = X##_s;					\
+								\
+    (val) = _flo.flt;						\
+  } while (0)
+
+#define FP_PACK_RAW_EP(fs, val, X)				\
+  do {								\
+    if (!FP_INHIBIT_RESULTS)					\
+      {								\
+	union _FP_UNION_E *_flo =				\
+	  (union _FP_UNION_E *)(val);				\
+								\
+	if (X##_e) X##_f0 |= _FP_IMPLBIT_E;			\
+	else X##_f0 &= ~(_FP_IMPLBIT_E);			\
+	_flo->bits.frac = X##_f0;				\
+	_flo->bits.exp  = X##_e;				\
+	_flo->bits.sign = X##_s;				\
+      }								\
+  } while (0)
+
+
+#define FP_UNPACK_E(X,val)		\
+  do {					\
+    FP_UNPACK_RAW_E(X,val);		\
+    _FP_UNPACK_CANONICAL(E,2,X);	\
+  } while (0)
+
+#define FP_UNPACK_EP(X,val)		\
+  do {					\
+    FP_UNPACK_RAW_EP(X,val);		\
+    _FP_UNPACK_CANONICAL(E,2,X);	\
+  } while (0)
+
+#define FP_PACK_E(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(E,2,X);		\
+    FP_PACK_RAW_E(val,X);		\
+  } while (0)
+
+#define FP_PACK_EP(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(E,2,X);		\
+    FP_PACK_RAW_EP(val,X);		\
+  } while (0)
+
+#define FP_ISSIGNAN_E(X)	_FP_ISSIGNAN(E,2,X)
+#define FP_NEG_E(R,X)		_FP_NEG(E,2,R,X)
+#define FP_ADD_E(R,X,Y)		_FP_ADD(E,2,R,X,Y)
+#define FP_SUB_E(R,X,Y)		_FP_SUB(E,2,R,X,Y)
+#define FP_MUL_E(R,X,Y)		_FP_MUL(E,2,R,X,Y)
+#define FP_DIV_E(R,X,Y)		_FP_DIV(E,2,R,X,Y)
+#define FP_SQRT_E(R,X)		_FP_SQRT(E,2,R,X)
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ * We optimize it by doing most of the calculations
+ * in one UWtype registers instead of two, although we don't
+ * have to.
+ */
+#define _FP_SQRT_MEAT_E(R, S, T, X, q)			\
+  do {							\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
+    _FP_FRAC_SRL_2(X, (_FP_WORKBITS));			\
+    while (q)						\
+      {							\
+        T##_f0 = S##_f0 + q;				\
+        if (T##_f0 <= X##_f0)				\
+          {						\
+            S##_f0 = T##_f0 + q;			\
+            X##_f0 -= T##_f0;				\
+            R##_f0 += q;				\
+          }						\
+        _FP_FRAC_SLL_1(X, 1);				\
+        q >>= 1;					\
+      }							\
+    _FP_FRAC_SLL_2(R, (_FP_WORKBITS));			\
+    if (X##_f0)						\
+      {							\
+	if (S##_f0 < X##_f0)				\
+	  R##_f0 |= _FP_WORK_ROUND;			\
+	R##_f0 |= _FP_WORK_STICKY;			\
+      }							\
+  } while (0)
+ 
+#define FP_CMP_E(r,X,Y,un)	_FP_CMP(E,2,r,X,Y,un)
+#define FP_CMP_EQ_E(r,X,Y)	_FP_CMP_EQ(E,2,r,X,Y)
+
+#define FP_TO_INT_E(r,X,rsz,rsg)	_FP_TO_INT(E,2,r,X,rsz,rsg)
+#define FP_FROM_INT_E(X,r,rs,rt)	_FP_FROM_INT(E,2,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_E(X)	(X##_f1)
+#define _FP_FRAC_HIGH_RAW_E(X)	(X##_f0)
+
+#endif /* not _FP_W_TYPE_SIZE < 64 */
diff -u --recursive --new-file v2.3.15/linux/include/math-emu/op-1.h linux/include/math-emu/op-1.h
--- v2.3.15/linux/include/math-emu/op-1.h	Wed Dec 31 16:00:00 1969
+++ linux/include/math-emu/op-1.h	Tue Aug 31 11:24:24 1999
@@ -0,0 +1,297 @@
+/* Software floating-point emulation.
+   Basic one-word fraction declaration and manipulation.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+		  Jakub Jelinek (jj@ultra.linux.cz),
+		  David S. Miller (davem@redhat.com) and
+		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#define _FP_FRAC_DECL_1(X)	_FP_W_TYPE X##_f
+#define _FP_FRAC_COPY_1(D,S)	(D##_f = S##_f)
+#define _FP_FRAC_SET_1(X,I)	(X##_f = I)
+#define _FP_FRAC_HIGH_1(X)	(X##_f)
+#define _FP_FRAC_LOW_1(X)	(X##_f)
+#define _FP_FRAC_WORD_1(X,w)	(X##_f)
+
+#define _FP_FRAC_ADDI_1(X,I)	(X##_f += I)
+#define _FP_FRAC_SLL_1(X,N)			\
+  do {						\
+    if (__builtin_constant_p(N) && (N) == 1)	\
+      X##_f += X##_f;				\
+    else					\
+      X##_f <<= (N);				\
+  } while (0)
+#define _FP_FRAC_SRL_1(X,N)	(X##_f >>= N)
+
+/* Right shift with sticky-lsb.  */
+#define _FP_FRAC_SRS_1(X,N,sz)	__FP_FRAC_SRS_1(X##_f, N, sz)
+
+#define __FP_FRAC_SRS_1(X,N,sz)						\
+   (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1		\
+		     ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
+
+#define _FP_FRAC_ADD_1(R,X,Y)	(R##_f = X##_f + Y##_f)
+#define _FP_FRAC_SUB_1(R,X,Y)	(R##_f = X##_f - Y##_f)
+#define _FP_FRAC_DEC_1(X,Y)	(X##_f -= Y##_f)
+#define _FP_FRAC_CLZ_1(z, X)	__FP_CLZ(z, X##_f)
+
+/* Predicates */
+#define _FP_FRAC_NEGP_1(X)	((_FP_WS_TYPE)X##_f < 0)
+#define _FP_FRAC_ZEROP_1(X)	(X##_f == 0)
+#define _FP_FRAC_OVERP_1(fs,X)	(X##_f & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_EQ_1(X, Y)	(X##_f == Y##_f)
+#define _FP_FRAC_GE_1(X, Y)	(X##_f >= Y##_f)
+#define _FP_FRAC_GT_1(X, Y)	(X##_f > Y##_f)
+
+#define _FP_ZEROFRAC_1		0
+#define _FP_MINFRAC_1		1
+#define _FP_MAXFRAC_1		(~(_FP_WS_TYPE)0)
+
+/*
+ * Unpack the raw bits of a native fp value.  Do not classify or
+ * normalize the data.
+ */
+
+#define _FP_UNPACK_RAW_1(fs, X, val)				\
+  do {								\
+    union _FP_UNION_##fs _flo; _flo.flt = (val);		\
+								\
+    X##_f = _flo.bits.frac;					\
+    X##_e = _flo.bits.exp;					\
+    X##_s = _flo.bits.sign;					\
+  } while (0)
+
+#define _FP_UNPACK_RAW_1_P(fs, X, val)				\
+  do {								\
+    union _FP_UNION_##fs *_flo =				\
+      (union _FP_UNION_##fs *)(val);				\
+								\
+    X##_f = _flo->bits.frac;					\
+    X##_e = _flo->bits.exp;					\
+    X##_s = _flo->bits.sign;					\
+  } while (0)
+
+/*
+ * Repack the raw bits of a native fp value.
+ */
+
+#define _FP_PACK_RAW_1(fs, val, X)				\
+  do {								\
+    union _FP_UNION_##fs _flo;					\
+								\
+    _flo.bits.frac = X##_f;					\
+    _flo.bits.exp  = X##_e;					\
+    _flo.bits.sign = X##_s;					\
+								\
+    (val) = _flo.flt;						\
+  } while (0)
+
+#define _FP_PACK_RAW_1_P(fs, val, X)				\
+  do {								\
+    union _FP_UNION_##fs *_flo =				\
+      (union _FP_UNION_##fs *)(val);				\
+								\
+    _flo->bits.frac = X##_f;					\
+    _flo->bits.exp  = X##_e;					\
+    _flo->bits.sign = X##_s;					\
+  } while (0)
+
+
+/*
+ * Multiplication algorithms:
+ */
+
+/* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
+   multiplication immediately.  */
+
+#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y)				\
+  do {									\
+    R##_f = X##_f * Y##_f;						\
+    /* Normalize since we know where the msb of the multiplicands	\
+       were (bit B), we know that the msb of the of the product is	\
+       at either 2B or 2B-1.  */					\
+    _FP_FRAC_SRS_1(R, wfracbits-1, 2*wfracbits);			\
+  } while (0)
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
+
+#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit)			\
+  do {									\
+    _FP_W_TYPE _Z_f0, _Z_f1;						\
+    doit(_Z_f1, _Z_f0, X##_f, Y##_f);					\
+    /* Normalize since we know where the msb of the multiplicands	\
+       were (bit B), we know that the msb of the of the product is	\
+       at either 2B or 2B-1.  */					\
+    _FP_FRAC_SRS_2(_Z, wfracbits-1, 2*wfracbits);			\
+    R##_f = _Z_f0;							\
+  } while (0)
+
+/* Finally, a simple widening multiply algorithm.  What fun!  */
+
+#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y)				\
+  do {									\
+    _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1;		\
+									\
+    /* split the words in half */					\
+    _xh = X##_f >> (_FP_W_TYPE_SIZE/2);					\
+    _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1);		\
+    _yh = Y##_f >> (_FP_W_TYPE_SIZE/2);					\
+    _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1);		\
+									\
+    /* multiply the pieces */						\
+    _z_f0 = _xl * _yl;							\
+    _a_f0 = _xh * _yl;							\
+    _a_f1 = _xl * _yh;							\
+    _z_f1 = _xh * _yh;							\
+									\
+    /* reassemble into two full words */				\
+    if ((_a_f0 += _a_f1) < _a_f1)					\
+      _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2);			\
+    _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2);				\
+    _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2);				\
+    _FP_FRAC_ADD_2(_z, _z, _a);						\
+									\
+    /* normalize */							\
+    _FP_FRAC_SRS_2(_z, wfracbits - 1, 2*wfracbits);			\
+    R##_f = _z_f0;							\
+  } while (0)
+
+
+/*
+ * Division algorithms:
+ */
+
+/* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
+   division immediately.  Give this macro either _FP_DIV_HELP_imm for
+   C primitives or _FP_DIV_HELP_ldiv for the ISO function.  Which you
+   choose will depend on what the compiler does with divrem4.  */
+
+#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit)		\
+  do {							\
+    _FP_W_TYPE _q, _r;					\
+    X##_f <<= (X##_f < Y##_f				\
+	       ? R##_e--, _FP_WFRACBITS_##fs		\
+	       : _FP_WFRACBITS_##fs - 1);		\
+    doit(_q, _r, X##_f, Y##_f);				\
+    R##_f = _q | (_r != 0);				\
+  } while (0)
+
+/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
+   that may be useful in this situation.  This first is for a primitive
+   that requires normalization, the second for one that does not.  Look
+   for UDIV_NEEDS_NORMALIZATION to tell which your machine needs.  */
+
+#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y)				\
+  do {									\
+    _FP_W_TYPE _nh, _nl, _q, _r;					\
+									\
+    /* Normalize Y -- i.e. make the most significant bit set.  */	\
+    Y##_f <<= _FP_WFRACXBITS_##fs - 1;					\
+									\
+    /* Shift X op correspondingly high, that is, up one full word.  */	\
+    if (X##_f <= Y##_f)							\
+      {									\
+	_nl = 0;							\
+	_nh = X##_f;							\
+      }									\
+    else								\
+      {									\
+	R##_e++;							\
+	_nl = X##_f << (_FP_W_TYPE_SIZE-1);				\
+	_nh = X##_f >> 1;						\
+      }									\
+    									\
+    udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);				\
+    R##_f = _q | (_r != 0);						\
+  } while (0)
+
+#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y)		\
+  do {							\
+    _FP_W_TYPE _nh, _nl, _q, _r;			\
+    if (X##_f < Y##_f)					\
+      {							\
+	R##_e--;					\
+	_nl = X##_f << _FP_WFRACBITS_##fs;		\
+	_nh = X##_f >> _FP_WFRACXBITS_##fs;		\
+      }							\
+    else						\
+      {							\
+	_nl = X##_f << (_FP_WFRACBITS_##fs - 1);	\
+	_nh = X##_f >> (_FP_WFRACXBITS_##fs + 1);	\
+      }							\
+    udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);		\
+    R##_f = _q | (_r != 0);				\
+  } while (0)
+  
+  
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ */
+ 
+#define _FP_SQRT_MEAT_1(R, S, T, X, q)			\
+  do {							\
+    while (q != _FP_WORK_ROUND)				\
+      {							\
+        T##_f = S##_f + q;				\
+        if (T##_f <= X##_f)				\
+          {						\
+            S##_f = T##_f + q;				\
+            X##_f -= T##_f;				\
+            R##_f += q;					\
+          }						\
+        _FP_FRAC_SLL_1(X, 1);				\
+        q >>= 1;					\
+      }							\
+    if (X##_f)						\
+      {							\
+	if (S##_f < X##_f)				\
+	  R##_f |= _FP_WORK_ROUND;			\
+	R##_f |= _FP_WORK_STICKY;			\
+      }							\
+  } while (0)
+
+/*
+ * Assembly/disassembly for converting to/from integral types.  
+ * No shifting or overflow handled here.
+ */
+
+#define _FP_FRAC_ASSEMBLE_1(r, X, rsize)	(r = X##_f)
+#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize)	(X##_f = r)
+
+
+/*
+ * Convert FP values between word sizes
+ */
+
+#define _FP_FRAC_CONV_1_1(dfs, sfs, D, S)				\
+  do {									\
+    D##_f = S##_f;							\
+    if (_FP_WFRACBITS_##sfs > _FP_WFRACBITS_##dfs)			\
+      {									\
+	if (S##_c != FP_CLS_NAN)					\
+	  _FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs),	\
+			 _FP_WFRACBITS_##sfs);				\
+	else								\
+	  _FP_FRAC_SRL_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs));	\
+      }									\
+    else								\
+      D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs;		\
+  } while (0)
diff -u --recursive --new-file v2.3.15/linux/include/math-emu/op-2.h linux/include/math-emu/op-2.h
--- v2.3.15/linux/include/math-emu/op-2.h	Wed Dec 31 16:00:00 1969
+++ linux/include/math-emu/op-2.h	Tue Aug 31 11:24:24 1999
@@ -0,0 +1,608 @@
+/* Software floating-point emulation.
+   Basic two-word fraction declaration and manipulation.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+		  Jakub Jelinek (jj@ultra.linux.cz),
+		  David S. Miller (davem@redhat.com) and
+		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#define _FP_FRAC_DECL_2(X)	_FP_W_TYPE X##_f0, X##_f1
+#define _FP_FRAC_COPY_2(D,S)	(D##_f0 = S##_f0, D##_f1 = S##_f1)
+#define _FP_FRAC_SET_2(X,I)	__FP_FRAC_SET_2(X, I)
+#define _FP_FRAC_HIGH_2(X)	(X##_f1)
+#define _FP_FRAC_LOW_2(X)	(X##_f0)
+#define _FP_FRAC_WORD_2(X,w)	(X##_f##w)
+
+#define _FP_FRAC_SLL_2(X,N)						\
+  do {									\
+    if ((N) < _FP_W_TYPE_SIZE)						\
+      {									\
+	if (__builtin_constant_p(N) && (N) == 1) 			\
+	  {								\
+	    X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0);	\
+	    X##_f0 += X##_f0;						\
+	  }								\
+	else								\
+	  {								\
+	    X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N));	\
+	    X##_f0 <<= (N);						\
+	  }								\
+      }									\
+    else								\
+      {									\
+	X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE);			\
+	X##_f0 = 0;							\
+      }									\
+  } while (0)
+
+#define _FP_FRAC_SRL_2(X,N)						\
+  do {									\
+    if ((N) < _FP_W_TYPE_SIZE)						\
+      {									\
+	X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N));	\
+	X##_f1 >>= (N);							\
+      }									\
+    else								\
+      {									\
+	X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE);			\
+	X##_f1 = 0;							\
+      }									\
+  } while (0)
+
+/* Right shift with sticky-lsb.  */
+#define _FP_FRAC_SRS_2(X,N,sz)						\
+  do {									\
+    if ((N) < _FP_W_TYPE_SIZE)						\
+      {									\
+	X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) |	\
+		  (__builtin_constant_p(N) && (N) == 1			\
+		   ? X##_f0 & 1						\
+		   : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0));	\
+	X##_f1 >>= (N);							\
+      }									\
+    else								\
+      {									\
+	X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) |			\
+		  (((X##_f1 << (sz - (N))) | X##_f0) != 0));		\
+	X##_f1 = 0;							\
+      }									\
+  } while (0)
+
+#define _FP_FRAC_ADDI_2(X,I)	\
+  __FP_FRAC_ADDI_2(X##_f1, X##_f0, I)
+
+#define _FP_FRAC_ADD_2(R,X,Y)	\
+  __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_SUB_2(R,X,Y)	\
+  __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_DEC_2(X,Y)	\
+  __FP_FRAC_DEC_2(X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_CLZ_2(R,X)	\
+  do {				\
+    if (X##_f1)			\
+      __FP_CLZ(R,X##_f1);	\
+    else 			\
+    {				\
+      __FP_CLZ(R,X##_f0);	\
+      R += _FP_W_TYPE_SIZE;	\
+    }				\
+  } while(0)
+
+/* Predicates */
+#define _FP_FRAC_NEGP_2(X)	((_FP_WS_TYPE)X##_f1 < 0)
+#define _FP_FRAC_ZEROP_2(X)	((X##_f1 | X##_f0) == 0)
+#define _FP_FRAC_OVERP_2(fs,X)	(_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_EQ_2(X, Y)	(X##_f1 == Y##_f1 && X##_f0 == Y##_f0)
+#define _FP_FRAC_GT_2(X, Y)	\
+  (X##_f1 > Y##_f1 || X##_f1 == Y##_f1 && X##_f0 > Y##_f0)
+#define _FP_FRAC_GE_2(X, Y)	\
+  (X##_f1 > Y##_f1 || X##_f1 == Y##_f1 && X##_f0 >= Y##_f0)
+
+#define _FP_ZEROFRAC_2		0, 0
+#define _FP_MINFRAC_2		0, 1
+#define _FP_MAXFRAC_2		(~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
+
+/*
+ * Internals 
+ */
+
+#define __FP_FRAC_SET_2(X,I1,I0)	(X##_f0 = I0, X##_f1 = I1)
+
+#define __FP_CLZ_2(R, xh, xl)	\
+  do {				\
+    if (xh)			\
+      __FP_CLZ(R,xh);		\
+    else 			\
+    {				\
+      __FP_CLZ(R,xl);		\
+      R += _FP_W_TYPE_SIZE;	\
+    }				\
+  } while(0)
+
+#if 0
+
+#ifndef __FP_FRAC_ADDI_2
+#define __FP_FRAC_ADDI_2(xh, xl, i)	\
+  (xh += ((xl += i) < i))
+#endif
+#ifndef __FP_FRAC_ADD_2
+#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl)	\
+  (rh = xh + yh + ((rl = xl + yl) < xl))
+#endif
+#ifndef __FP_FRAC_SUB_2
+#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl)	\
+  (rh = xh - yh - ((rl = xl - yl) > xl))
+#endif
+#ifndef __FP_FRAC_DEC_2
+#define __FP_FRAC_DEC_2(xh, xl, yh, yl)	\
+  do {					\
+    UWtype _t = xl;			\
+    xh -= yh + ((xl -= yl) > _t);	\
+  } while (0)
+#endif
+
+#else
+
+#undef __FP_FRAC_ADDI_2
+#define __FP_FRAC_ADDI_2(xh, xl, i)	add_ssaaaa(xh, xl, xh, xl, 0, i)
+#undef __FP_FRAC_ADD_2
+#define __FP_FRAC_ADD_2			add_ssaaaa
+#undef __FP_FRAC_SUB_2
+#define __FP_FRAC_SUB_2			sub_ddmmss
+#undef __FP_FRAC_DEC_2
+#define __FP_FRAC_DEC_2(xh, xl, yh, yl)	sub_ddmmss(xh, xl, xh, xl, yh, yl)
+
+#endif
+
+/*
+ * Unpack the raw bits of a native fp value.  Do not classify or
+ * normalize the data.
+ */
+
+#define _FP_UNPACK_RAW_2(fs, X, val)			\
+  do {							\
+    union _FP_UNION_##fs _flo; _flo.flt = (val);	\
+							\
+    X##_f0 = _flo.bits.frac0;				\
+    X##_f1 = _flo.bits.frac1;				\
+    X##_e  = _flo.bits.exp;				\
+    X##_s  = _flo.bits.sign;				\
+  } while (0)
+
+#define _FP_UNPACK_RAW_2_P(fs, X, val)			\
+  do {							\
+    union _FP_UNION_##fs *_flo =			\
+      (union _FP_UNION_##fs *)(val);			\
+							\
+    X##_f0 = _flo->bits.frac0;				\
+    X##_f1 = _flo->bits.frac1;				\
+    X##_e  = _flo->bits.exp;				\
+    X##_s  = _flo->bits.sign;				\
+  } while (0)
+
+
+/*
+ * Repack the raw bits of a native fp value.
+ */
+
+#define _FP_PACK_RAW_2(fs, val, X)			\
+  do {							\
+    union _FP_UNION_##fs _flo;				\
+							\
+    _flo.bits.frac0 = X##_f0;				\
+    _flo.bits.frac1 = X##_f1;				\
+    _flo.bits.exp   = X##_e;				\
+    _flo.bits.sign  = X##_s;				\
+							\
+    (val) = _flo.flt;					\
+  } while (0)
+
+#define _FP_PACK_RAW_2_P(fs, val, X)			\
+  do {							\
+    union _FP_UNION_##fs *_flo =			\
+      (union _FP_UNION_##fs *)(val);			\
+							\
+    _flo->bits.frac0 = X##_f0;				\
+    _flo->bits.frac1 = X##_f1;				\
+    _flo->bits.exp   = X##_e;				\
+    _flo->bits.sign  = X##_s;				\
+  } while (0)
+
+
+/*
+ * Multiplication algorithms:
+ */
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
+
+#define _FP_MUL_MEAT_2_wide(wfracbits, R, X, Y, doit)			\
+  do {									\
+    _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	\
+									\
+    doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0);	\
+    doit(_b_f1, _b_f0, X##_f0, Y##_f1);					\
+    doit(_c_f1, _c_f0, X##_f1, Y##_f0);					\
+    doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1);	\
+									\
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1), 0, _b_f1, _b_f0,		\
+		    _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1));				\
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0,		\
+		    _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1));				\
+									\
+    /* Normalize since we know where the msb of the multiplicands	\
+       were (bit B), we know that the msb of the of the product is	\
+       at either 2B or 2B-1.  */					\
+    _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits);			\
+    R##_f0 = _FP_FRAC_WORD_4(_z,0);					\
+    R##_f1 = _FP_FRAC_WORD_4(_z,1);					\
+  } while (0)
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication.
+   Do only 3 multiplications instead of four. This one is for machines
+   where multiplication is much more expensive than subtraction.  */
+
+#define _FP_MUL_MEAT_2_wide_3mul(wfracbits, R, X, Y, doit)		\
+  do {									\
+    _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	\
+    _FP_W_TYPE _d;							\
+    int _c1, _c2;							\
+									\
+    _b_f0 = X##_f0 + X##_f1;						\
+    _c1 = _b_f0 < X##_f0;						\
+    _b_f1 = Y##_f0 + Y##_f1;						\
+    _c2 = _b_f1 < Y##_f0;						\
+    doit(_d, _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0);			\
+    doit(_FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1), _b_f0, _b_f1);	\
+    doit(_c_f1, _c_f0, X##_f1, Y##_f1);					\
+									\
+    _b_f0 &= -_c2;							\
+    _b_f1 &= -_c1;							\
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1), (_c1 & _c2), 0, _d,		\
+		    0, _FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1));	\
+    __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		     _b_f0);						\
+    __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		     _b_f1);						\
+    __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1),				\
+		    0, _d, _FP_FRAC_WORD_4(_z,0));			\
+    __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
+		    _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0);		\
+    __FP_FRAC_ADD_2(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2),	\
+		    _c_f1, _c_f0,					\
+		    _FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2));	\
+									\
+    /* Normalize since we know where the msb of the multiplicands	\
+       were (bit B), we know that the msb of the of the product is	\
+       at either 2B or 2B-1.  */					\
+    _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits);			\
+    R##_f0 = _FP_FRAC_WORD_4(_z,0);					\
+    R##_f1 = _FP_FRAC_WORD_4(_z,1);					\
+  } while (0)
+
+#define _FP_MUL_MEAT_2_gmp(wfracbits, R, X, Y)				\
+  do {									\
+    _FP_FRAC_DECL_4(_z);						\
+    _FP_W_TYPE _x[2], _y[2];						\
+    _x[0] = X##_f0; _x[1] = X##_f1;					\
+    _y[0] = Y##_f0; _y[1] = Y##_f1;					\
+									\
+    mpn_mul_n(_z_f, _x, _y, 2);						\
+									\
+    /* Normalize since we know where the msb of the multiplicands	\
+       were (bit B), we know that the msb of the of the product is	\
+       at either 2B or 2B-1.  */					\
+    _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits);			\
+    R##_f0 = _z_f[0];							\
+    R##_f1 = _z_f[1];							\
+  } while (0)
+
+/* Do at most 120x120=240 bits multiplication using double floating
+   point multiplication.  This is useful if floating point
+   multiplication has much bigger throughput than integer multiply.
+   It is supposed to work for _FP_W_TYPE_SIZE 64 and wfracbits
+   between 106 and 120 only.  
+   Caller guarantees that X and Y has (1LLL << (wfracbits - 1)) set.
+   SETFETZ is a macro which will disable all FPU exceptions and set rounding
+   towards zero,  RESETFE should optionally reset it back.  */
+
+#define _FP_MUL_MEAT_2_120_240_double(wfracbits, R, X, Y, setfetz, resetfe)	\
+  do {										\
+    static const double _const[] = {						\
+      /* 2^-24 */ 5.9604644775390625e-08,					\
+      /* 2^-48 */ 3.5527136788005009e-15,					\
+      /* 2^-72 */ 2.1175823681357508e-22,					\
+      /* 2^-96 */ 1.2621774483536189e-29,					\
+      /* 2^28 */ 2.68435456e+08,						\
+      /* 2^4 */ 1.600000e+01,							\
+      /* 2^-20 */ 9.5367431640625e-07,						\
+      /* 2^-44 */ 5.6843418860808015e-14,					\
+      /* 2^-68 */ 3.3881317890172014e-21,					\
+      /* 2^-92 */ 2.0194839173657902e-28,					\
+      /* 2^-116 */ 1.2037062152420224e-35};					\
+    double _a240, _b240, _c240, _d240, _e240, _f240, 				\
+	   _g240, _h240, _i240, _j240, _k240;					\
+    union { double d; UDItype i; } _l240, _m240, _n240, _o240,			\
+				   _p240, _q240, _r240, _s240;			\
+    UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0;			\
+										\
+    if (wfracbits < 106 || wfracbits > 120)					\
+      abort();									\
+										\
+    setfetz;									\
+										\
+    _e240 = (double)(long)(X##_f0 & 0xffffff);					\
+    _j240 = (double)(long)(Y##_f0 & 0xffffff);					\
+    _d240 = (double)(long)((X##_f0 >> 24) & 0xffffff);				\
+    _i240 = (double)(long)((Y##_f0 >> 24) & 0xffffff);				\
+    _c240 = (double)(long)(((X##_f1 << 16) & 0xffffff) | (X##_f0 >> 48));	\
+    _h240 = (double)(long)(((Y##_f1 << 16) & 0xffffff) | (Y##_f0 >> 48));	\
+    _b240 = (double)(long)((X##_f1 >> 8) & 0xffffff);				\
+    _g240 = (double)(long)((Y##_f1 >> 8) & 0xffffff);				\
+    _a240 = (double)(long)(X##_f1 >> 32);					\
+    _f240 = (double)(long)(Y##_f1 >> 32);					\
+    _e240 *= _const[3];								\
+    _j240 *= _const[3];								\
+    _d240 *= _const[2];								\
+    _i240 *= _const[2];								\
+    _c240 *= _const[1];								\
+    _h240 *= _const[1];								\
+    _b240 *= _const[0];								\
+    _g240 *= _const[0];								\
+    _s240.d =							      _e240*_j240;\
+    _r240.d =						_d240*_j240 + _e240*_i240;\
+    _q240.d =				  _c240*_j240 + _d240*_i240 + _e240*_h240;\
+    _p240.d =		    _b240*_j240 + _c240*_i240 + _d240*_h240 + _e240*_g240;\
+    _o240.d = _a240*_j240 + _b240*_i240 + _c240*_h240 + _d240*_g240 + _e240*_f240;\
+    _n240.d = _a240*_i240 + _b240*_h240 + _c240*_g240 + _d240*_f240;		\
+    _m240.d = _a240*_h240 + _b240*_g240 + _c240*_f240;				\
+    _l240.d = _a240*_g240 + _b240*_f240;					\
+    _k240 =   _a240*_f240;							\
+    _r240.d += _s240.d;								\
+    _q240.d += _r240.d;								\
+    _p240.d += _q240.d;								\
+    _o240.d += _p240.d;								\
+    _n240.d += _o240.d;								\
+    _m240.d += _n240.d;								\
+    _l240.d += _m240.d;								\
+    _k240 += _l240.d;								\
+    _s240.d -= ((_const[10]+_s240.d)-_const[10]);				\
+    _r240.d -= ((_const[9]+_r240.d)-_const[9]);					\
+    _q240.d -= ((_const[8]+_q240.d)-_const[8]);					\
+    _p240.d -= ((_const[7]+_p240.d)-_const[7]);					\
+    _o240.d += _const[7];							\
+    _n240.d += _const[6];							\
+    _m240.d += _const[5];							\
+    _l240.d += _const[4];							\
+    if (_s240.d != 0.0) _y240 = 1;						\
+    if (_r240.d != 0.0) _y240 = 1;						\
+    if (_q240.d != 0.0) _y240 = 1;						\
+    if (_p240.d != 0.0) _y240 = 1;						\
+    _t240 = (DItype)_k240;							\
+    _u240 = _l240.i;								\
+    _v240 = _m240.i;								\
+    _w240 = _n240.i;								\
+    _x240 = _o240.i;								\
+    R##_f1 = (_t240 << (128 - (wfracbits - 1)))					\
+	     | ((_u240 & 0xffffff) >> ((wfracbits - 1) - 104));			\
+    R##_f0 = ((_u240 & 0xffffff) << (168 - (wfracbits - 1)))			\
+    	     | ((_v240 & 0xffffff) << (144 - (wfracbits - 1)))			\
+    	     | ((_w240 & 0xffffff) << (120 - (wfracbits - 1)))			\
+    	     | ((_x240 & 0xffffff) >> ((wfracbits - 1) - 96))			\
+    	     | _y240;								\
+    resetfe;									\
+  } while (0)
+
+/*
+ * Division algorithms:
+ */
+
+#define _FP_DIV_MEAT_2_udiv(fs, R, X, Y)				\
+  do {									\
+    _FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0;		\
+    if (_FP_FRAC_GT_2(X, Y))						\
+      {									\
+	_n_f2 = X##_f1 >> 1;						\
+	_n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1;		\
+	_n_f0 = X##_f0 << (_FP_W_TYPE_SIZE - 1);			\
+      }									\
+    else								\
+      {									\
+	R##_e--;							\
+	_n_f2 = X##_f1;							\
+	_n_f1 = X##_f0;							\
+	_n_f0 = 0;							\
+      }									\
+									\
+    /* Normalize, i.e. make the most significant bit of the 		\
+       denominator set. */						\
+    _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs);				\
+									\
+    udiv_qrnnd(R##_f1, _r_f1, _n_f2, _n_f1, Y##_f1);			\
+    umul_ppmm(_m_f1, _m_f0, R##_f1, Y##_f0);				\
+    _r_f0 = _n_f0;							\
+    if (_FP_FRAC_GT_2(_m, _r))						\
+      {									\
+	R##_f1--;							\
+	_FP_FRAC_ADD_2(_r, Y, _r);					\
+	if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))		\
+	  {								\
+	    R##_f1--;							\
+	    _FP_FRAC_ADD_2(_r, Y, _r);					\
+	  }								\
+      }									\
+    _FP_FRAC_DEC_2(_r, _m);						\
+									\
+    if (_r_f1 == Y##_f1)						\
+      {									\
+	/* This is a special case, not an optimization			\
+	   (_r/Y##_f1 would not fit into UWtype).			\
+	   As _r is guaranteed to be < Y,  R##_f0 can be either		\
+	   (UWtype)-1 or (UWtype)-2.  But as we know what kind		\
+	   of bits it is (sticky, guard, round),  we don't care.	\
+	   We also don't care what the reminder is,  because the	\
+	   guard bit will be set anyway.  -jj */			\
+	R##_f0 = -1;							\
+      }									\
+    else								\
+      {									\
+	udiv_qrnnd(R##_f0, _r_f1, _r_f1, _r_f0, Y##_f1);		\
+	umul_ppmm(_m_f1, _m_f0, R##_f0, Y##_f0);			\
+	_r_f0 = 0;							\
+	if (_FP_FRAC_GT_2(_m, _r))					\
+	  {								\
+	    R##_f0--;							\
+	    _FP_FRAC_ADD_2(_r, Y, _r);					\
+	    if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))		\
+	      {								\
+		R##_f0--;						\
+		_FP_FRAC_ADD_2(_r, Y, _r);				\
+	      }								\
+	  }								\
+	if (!_FP_FRAC_EQ_2(_r, _m))					\
+	  R##_f0 |= _FP_WORK_STICKY;					\
+      }									\
+  } while (0)
+
+
+#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y)					\
+  do {									\
+    _FP_W_TYPE _x[4], _y[2], _z[4];					\
+    _y[0] = Y##_f0; _y[1] = Y##_f1;					\
+    _x[0] = _x[3] = 0;							\
+    if (_FP_FRAC_GT_2(X, Y))						\
+      {									\
+	R##_e++;							\
+	_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE) |	\
+		 X##_f1 >> (_FP_W_TYPE_SIZE -				\
+			    (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE)));	\
+	_x[2] = X##_f1 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE);	\
+      }									\
+    else								\
+      {									\
+	_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE) |	\
+		 X##_f1 >> (_FP_W_TYPE_SIZE -				\
+			    (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE)));	\
+	_x[2] = X##_f1 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE);	\
+      }									\
+									\
+    (void) mpn_divrem (_z, 0, _x, 4, _y, 2);				\
+    R##_f1 = _z[1];							\
+    R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0);				\
+  } while (0)
+
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ */
+ 
+#define _FP_SQRT_MEAT_2(R, S, T, X, q)			\
+  do {							\
+    while (q)						\
+      {							\
+	T##_f1 = S##_f1 + q;				\
+	if (T##_f1 <= X##_f1)				\
+	  {						\
+	    S##_f1 = T##_f1 + q;			\
+	    X##_f1 -= T##_f1;				\
+	    R##_f1 += q;				\
+	  }						\
+	_FP_FRAC_SLL_2(X, 1);				\
+	q >>= 1;					\
+      }							\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
+    while (q != _FP_WORK_ROUND)				\
+      {							\
+	T##_f0 = S##_f0 + q;				\
+	T##_f1 = S##_f1;				\
+	if (T##_f1 < X##_f1 || 				\
+	    (T##_f1 == X##_f1 && T##_f0 <= X##_f0))	\
+	  {						\
+	    S##_f0 = T##_f0 + q;			\
+	    S##_f1 += (T##_f0 > S##_f0);		\
+	    _FP_FRAC_DEC_2(X, T);			\
+	    R##_f0 += q;				\
+	  }						\
+	_FP_FRAC_SLL_2(X, 1);				\
+	q >>= 1;					\
+      }							\
+    if (X##_f0 | X##_f1)				\
+      {							\
+	if (S##_f1 < X##_f1 || 				\
+	    (S##_f1 == X##_f1 && S##_f0 < X##_f0))	\
+	  R##_f0 |= _FP_WORK_ROUND;			\
+	R##_f0 |= _FP_WORK_STICKY;			\
+      }							\
+  } while (0)
+
+
+/*
+ * Assembly/disassembly for converting to/from integral types.  
+ * No shifting or overflow handled here.
+ */
+
+#define _FP_FRAC_ASSEMBLE_2(r, X, rsize)	\
+  do {						\
+    if (rsize <= _FP_W_TYPE_SIZE)		\
+      r = X##_f0;				\
+    else					\
+      {						\
+	r = X##_f1;				\
+	r <<= _FP_W_TYPE_SIZE;			\
+	r += X##_f0;				\
+      }						\
+  } while (0)
+
+#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize)				\
+  do {									\
+    X##_f0 = r;								\
+    X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);	\
+  } while (0)
+
+/*
+ * Convert FP values between word sizes
+ */
+
+#define _FP_FRAC_CONV_1_2(dfs, sfs, D, S)				\
+  do {									\
+    if (S##_c != FP_CLS_NAN)						\
+      _FP_FRAC_SRS_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),	\
+		     _FP_WFRACBITS_##sfs);				\
+    else								\
+      _FP_FRAC_SRL_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs));	\
+    D##_f = S##_f0;							\
+  } while (0)
+
+#define _FP_FRAC_CONV_2_1(dfs, sfs, D, S)				\
+  do {									\
+    D##_f0 = S##_f;							\
+    D##_f1 = 0;								\
+    _FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));	\
+  } while (0)
+
diff -u --recursive --new-file v2.3.15/linux/include/math-emu/op-4.h linux/include/math-emu/op-4.h
--- v2.3.15/linux/include/math-emu/op-4.h	Wed Dec 31 16:00:00 1969
+++ linux/include/math-emu/op-4.h	Tue Aug 31 11:24:24 1999
@@ -0,0 +1,661 @@
+/* Software floating-point emulation.
+   Basic four-word fraction declaration and manipulation.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+		  Jakub Jelinek (jj@ultra.linux.cz),
+		  David S. Miller (davem@redhat.com) and
+		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#define _FP_FRAC_DECL_4(X)	_FP_W_TYPE X##_f[4]
+#define _FP_FRAC_COPY_4(D,S)			\
+  (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1],	\
+   D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
+#define _FP_FRAC_SET_4(X,I)	__FP_FRAC_SET_4(X, I)
+#define _FP_FRAC_HIGH_4(X)	(X##_f[3])
+#define _FP_FRAC_LOW_4(X)	(X##_f[0])
+#define _FP_FRAC_WORD_4(X,w)	(X##_f[w])
+
+#define _FP_FRAC_SLL_4(X,N)						\
+  do {									\
+    _FP_I_TYPE _up, _down, _skip, _i;					\
+    _skip = (N) / _FP_W_TYPE_SIZE;					\
+    _up = (N) % _FP_W_TYPE_SIZE;					\
+    _down = _FP_W_TYPE_SIZE - _up;					\
+    if (!_up)								\
+      for (_i = 3; _i >= _skip; --_i)					\
+	X##_f[_i] = X##_f[_i-_skip];					\
+    else								\
+      {									\
+	for (_i = 3; _i > _skip; --_i)					\
+	  X##_f[_i] = X##_f[_i-_skip] << _up				\
+		      | X##_f[_i-_skip-1] >> _down;			\
+	X##_f[_i--] = X##_f[0] << _up; 					\
+      }									\
+    for (; _i >= 0; --_i)						\
+      X##_f[_i] = 0;							\
+  } while (0)
+
+/* This one was broken too */
+#define _FP_FRAC_SRL_4(X,N)						\
+  do {									\
+    _FP_I_TYPE _up, _down, _skip, _i;					\
+    _skip = (N) / _FP_W_TYPE_SIZE;					\
+    _down = (N) % _FP_W_TYPE_SIZE;					\
+    _up = _FP_W_TYPE_SIZE - _down;					\
+    if (!_down)								\
+      for (_i = 0; _i <= 3-_skip; ++_i)					\
+	X##_f[_i] = X##_f[_i+_skip];					\
+    else								\
+      {									\
+	for (_i = 0; _i < 3-_skip; ++_i)				\
+	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
+		      | X##_f[_i+_skip+1] << _up;			\
+	X##_f[_i++] = X##_f[3] >> _down;				\
+      }									\
+    for (; _i < 4; ++_i)						\
+      X##_f[_i] = 0;							\
+  } while (0)
+
+
+/* Right shift with sticky-lsb. 
+ * What this actually means is that we do a standard right-shift,
+ * but that if any of the bits that fall off the right hand side
+ * were one then we always set the LSbit.
+ */
+#define _FP_FRAC_SRS_4(X,N,size)					\
+  do {									\
+    _FP_I_TYPE _up, _down, _skip, _i;					\
+    _FP_W_TYPE _s;							\
+    _skip = (N) / _FP_W_TYPE_SIZE;					\
+    _down = (N) % _FP_W_TYPE_SIZE;					\
+    _up = _FP_W_TYPE_SIZE - _down;					\
+    for (_s = _i = 0; _i < _skip; ++_i)					\
+      _s |= X##_f[_i];							\
+    _s |= X##_f[_i] << _up;						\
+/* s is now != 0 if we want to set the LSbit */				\
+    if (!_down)								\
+      for (_i = 0; _i <= 3-_skip; ++_i)					\
+	X##_f[_i] = X##_f[_i+_skip];					\
+    else								\
+      {									\
+	for (_i = 0; _i < 3-_skip; ++_i)				\
+	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
+		      | X##_f[_i+_skip+1] << _up;			\
+	X##_f[_i++] = X##_f[3] >> _down;				\
+      }									\
+    for (; _i < 4; ++_i)						\
+      X##_f[_i] = 0;							\
+    /* don't fix the LSB until the very end when we're sure f[0] is stable */	\
+    X##_f[0] |= (_s != 0);						\
+  } while (0)
+
+#define _FP_FRAC_ADD_4(R,X,Y)						\
+  __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0],		\
+		  X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
+		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_SUB_4(R,X,Y)						\
+  __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0],		\
+		  X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
+		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_DEC_4(X,Y)						\
+  __FP_FRAC_DEC_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
+		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_ADDI_4(X,I)						\
+  __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
+
+#define _FP_ZEROFRAC_4  0,0,0,0
+#define _FP_MINFRAC_4   0,0,0,1
+#define _FP_MAXFRAC_4	(~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
+
+#define _FP_FRAC_ZEROP_4(X)     ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
+#define _FP_FRAC_NEGP_4(X)      ((_FP_WS_TYPE)X##_f[3] < 0)
+#define _FP_FRAC_OVERP_4(fs,X)  (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
+
+#define _FP_FRAC_EQ_4(X,Y)				\
+ (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1]		\
+  && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
+
+#define _FP_FRAC_GT_4(X,Y)				\
+ (X##_f[3] > Y##_f[3] ||				\
+  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||	\
+   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||	\
+    (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0])	\
+   ))							\
+  ))							\
+ )
+
+#define _FP_FRAC_GE_4(X,Y)				\
+ (X##_f[3] > Y##_f[3] ||				\
+  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||	\
+   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||	\
+    (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0])	\
+   ))							\
+  ))							\
+ )
+
+
+#define _FP_FRAC_CLZ_4(R,X)		\
+  do {					\
+    if (X##_f[3])			\
+    {					\
+	__FP_CLZ(R,X##_f[3]);		\
+    }					\
+    else if (X##_f[2])			\
+    {					\
+	__FP_CLZ(R,X##_f[2]);		\
+	R += _FP_W_TYPE_SIZE;		\
+    }					\
+    else if (X##_f[1])			\
+    {					\
+	__FP_CLZ(R,X##_f[2]);		\
+	R += _FP_W_TYPE_SIZE*2;		\
+    }					\
+    else				\
+    {					\
+	__FP_CLZ(R,X##_f[0]);		\
+	R += _FP_W_TYPE_SIZE*3;		\
+    }					\
+  } while(0)
+
+
+#define _FP_UNPACK_RAW_4(fs, X, val)				\
+  do {								\
+    union _FP_UNION_##fs _flo; _flo.flt = (val);		\
+    X##_f[0] = _flo.bits.frac0;					\
+    X##_f[1] = _flo.bits.frac1;					\
+    X##_f[2] = _flo.bits.frac2;					\
+    X##_f[3] = _flo.bits.frac3;					\
+    X##_e  = _flo.bits.exp;					\
+    X##_s  = _flo.bits.sign;					\
+  } while (0)
+
+#define _FP_UNPACK_RAW_4_P(fs, X, val)				\
+  do {								\
+    union _FP_UNION_##fs *_flo =				\
+      (union _FP_UNION_##fs *)(val);				\
+								\
+    X##_f[0] = _flo->bits.frac0;				\
+    X##_f[1] = _flo->bits.frac1;				\
+    X##_f[2] = _flo->bits.frac2;				\
+    X##_f[3] = _flo->bits.frac3;				\
+    X##_e  = _flo->bits.exp;					\
+    X##_s  = _flo->bits.sign;					\
+  } while (0)
+
+#define _FP_PACK_RAW_4(fs, val, X)				\
+  do {								\
+    union _FP_UNION_##fs _flo;					\
+    _flo.bits.frac0 = X##_f[0];					\
+    _flo.bits.frac1 = X##_f[1];					\
+    _flo.bits.frac2 = X##_f[2];					\
+    _flo.bits.frac3 = X##_f[3];					\
+    _flo.bits.exp   = X##_e;					\
+    _flo.bits.sign  = X##_s;					\
+    (val) = _flo.flt;				   		\
+  } while (0)
+
+#define _FP_PACK_RAW_4_P(fs, val, X)				\
+  do {								\
+    union _FP_UNION_##fs *_flo =				\
+      (union _FP_UNION_##fs *)(val);				\
+								\
+    _flo->bits.frac0 = X##_f[0];				\
+    _flo->bits.frac1 = X##_f[1];				\
+    _flo->bits.frac2 = X##_f[2];				\
+    _flo->bits.frac3 = X##_f[3];				\
+    _flo->bits.exp   = X##_e;					\
+    _flo->bits.sign  = X##_s;					\
+  } while (0)
+
+/*
+ * Multiplication algorithms:
+ */
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */
+
+#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit)			    \
+  do {									    \
+    _FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	    \
+    _FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f);	    \
+									    \
+    doit(_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0), X##_f[0], Y##_f[0]); \
+    doit(_b_f1, _b_f0, X##_f[0], Y##_f[1]);				    \
+    doit(_c_f1, _c_f0, X##_f[1], Y##_f[0]);				    \
+    doit(_d_f1, _d_f0, X##_f[1], Y##_f[1]);				    \
+    doit(_e_f1, _e_f0, X##_f[0], Y##_f[2]);				    \
+    doit(_f_f1, _f_f0, X##_f[2], Y##_f[0]);				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2),	    \
+		    _FP_FRAC_WORD_8(_z,1), 0,_b_f1,_b_f0,		    \
+		    0,0,_FP_FRAC_WORD_8(_z,1));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2),	    \
+		    _FP_FRAC_WORD_8(_z,1), 0,_c_f1,_c_f0,		    \
+		    _FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2),	    \
+		    _FP_FRAC_WORD_8(_z,1));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
+		    _FP_FRAC_WORD_8(_z,2), 0,_d_f1,_d_f0,		    \
+		    0,_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2));	    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
+		    _FP_FRAC_WORD_8(_z,2), 0,_e_f1,_e_f0,		    \
+		    _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
+		    _FP_FRAC_WORD_8(_z,2));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
+		    _FP_FRAC_WORD_8(_z,2), 0,_f_f1,_f_f0,		    \
+		    _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
+		    _FP_FRAC_WORD_8(_z,2));				    \
+    doit(_b_f1, _b_f0, X##_f[0], Y##_f[3]);				    \
+    doit(_c_f1, _c_f0, X##_f[3], Y##_f[0]);				    \
+    doit(_d_f1, _d_f0, X##_f[1], Y##_f[2]);				    \
+    doit(_e_f1, _e_f0, X##_f[2], Y##_f[1]);				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3), 0,_b_f1,_b_f0,		    \
+		    0,_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3));	    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3), 0,_c_f1,_c_f0,		    \
+		    _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3), 0,_d_f1,_d_f0,		    \
+		    _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3), 0,_e_f1,_e_f0,		    \
+		    _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
+		    _FP_FRAC_WORD_8(_z,3));				    \
+    doit(_b_f1, _b_f0, X##_f[2], Y##_f[2]);				    \
+    doit(_c_f1, _c_f0, X##_f[1], Y##_f[3]);				    \
+    doit(_d_f1, _d_f0, X##_f[3], Y##_f[1]);				    \
+    doit(_e_f1, _e_f0, X##_f[2], Y##_f[3]);				    \
+    doit(_f_f1, _f_f0, X##_f[3], Y##_f[2]);				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
+		    _FP_FRAC_WORD_8(_z,4), 0,_b_f1,_b_f0,		    \
+		    0,_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4));	    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
+		    _FP_FRAC_WORD_8(_z,4), 0,_c_f1,_c_f0,		    \
+		    _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
+		    _FP_FRAC_WORD_8(_z,4));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
+		    _FP_FRAC_WORD_8(_z,4), 0,_d_f1,_d_f0,		    \
+		    _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
+		    _FP_FRAC_WORD_8(_z,4));				    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
+		    _FP_FRAC_WORD_8(_z,5), 0,_e_f1,_e_f0,		    \
+		    0,_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5));	    \
+    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
+		    _FP_FRAC_WORD_8(_z,5), 0,_f_f1,_f_f0,		    \
+		    _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
+		    _FP_FRAC_WORD_8(_z,5));				    \
+    doit(_b_f1, _b_f0, X##_f[3], Y##_f[3]);				    \
+    __FP_FRAC_ADD_2(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
+		    _b_f1,_b_f0,					    \
+		    _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6));	    \
+									    \
+    /* Normalize since we know where the msb of the multiplicands	    \
+       were (bit B), we know that the msb of the of the product is	    \
+       at either 2B or 2B-1.  */					    \
+    _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits);			    \
+    __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2),	    \
+		    _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0));	    \
+  } while (0)
+
+#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y)				    \
+  do {									    \
+    _FP_FRAC_DECL_8(_z);						    \
+									    \
+    mpn_mul_n(_z_f, _x_f, _y_f, 4);					    \
+									    \
+    /* Normalize since we know where the msb of the multiplicands	    \
+       were (bit B), we know that the msb of the of the product is	    \
+       at either 2B or 2B-1.  */					    \
+    _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits);	 		    \
+    __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2),	    \
+		    _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0));	    \
+  } while (0)
+
+/*
+ * Helper utility for _FP_DIV_MEAT_4_udiv:
+ * pppp = m * nnn
+ */
+#define umul_ppppmnnn(p3,p2,p1,p0,m,n2,n1,n0)				    \
+  do {									    \
+    UWtype _t;								    \
+    umul_ppmm(p1,p0,m,n0);						    \
+    umul_ppmm(p2,_t,m,n1);						    \
+    __FP_FRAC_ADDI_2(p2,p1,_t);						    \
+    umul_ppmm(p3,_t,m,n2);						    \
+    __FP_FRAC_ADDI_2(p3,p2,_t);						    \
+  } while (0)
+
+/*
+ * Division algorithms:
+ */
+
+#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y)				    \
+  do {									    \
+    int _i;								    \
+    _FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m);				    \
+    _FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4);					    \
+    if (_FP_FRAC_GT_4(X, Y))						    \
+      {									    \
+	_n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1);			    \
+	_FP_FRAC_SRL_4(X, 1);						    \
+      }									    \
+    else								    \
+      R##_e--;								    \
+									    \
+    /* Normalize, i.e. make the most significant bit of the 		    \
+       denominator set. */						    \
+    _FP_FRAC_SLL_4(Y, _FP_WFRACXBITS_##fs);				    \
+									    \
+    for (_i = 3; ; _i--)						    \
+      {									    \
+        if (X##_f[3] == Y##_f[3])					    \
+          {								    \
+            /* This is a special case, not an optimization		    \
+               (X##_f[3]/Y##_f[3] would not fit into UWtype).		    \
+               As X## is guaranteed to be < Y,  R##_f[_i] can be either	    \
+               (UWtype)-1 or (UWtype)-2.  */				    \
+            R##_f[_i] = -1;						    \
+            if (!_i)							    \
+	      break;							    \
+            __FP_FRAC_SUB_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0],	    \
+			    Y##_f[2], Y##_f[1], Y##_f[0], 0,		    \
+			    X##_f[2], X##_f[1], X##_f[0], _n_f[_i]);	    \
+            _FP_FRAC_SUB_4(X, Y, X);					    \
+            if (X##_f[3] > Y##_f[3])					    \
+              {								    \
+                R##_f[_i] = -2;						    \
+                _FP_FRAC_ADD_4(X, Y, X);				    \
+              }								    \
+          }								    \
+        else								    \
+          {								    \
+            udiv_qrnnd(R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]);  \
+            umul_ppppmnnn(_m_f[3], _m_f[2], _m_f[1], _m_f[0],		    \
+			  R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]);	    \
+            X##_f[2] = X##_f[1];					    \
+            X##_f[1] = X##_f[0];					    \
+            X##_f[0] = _n_f[_i];					    \
+            if (_FP_FRAC_GT_4(_m, X))					    \
+              {								    \
+                R##_f[_i]--;						    \
+                _FP_FRAC_ADD_4(X, Y, X);				    \
+                if (_FP_FRAC_GE_4(X, Y) && _FP_FRAC_GT_4(_m, X))	    \
+                  {							    \
+		    R##_f[_i]--;					    \
+		    _FP_FRAC_ADD_4(X, Y, X);				    \
+                  }							    \
+              }								    \
+            _FP_FRAC_DEC_4(X, _m);					    \
+            if (!_i)							    \
+	      {								    \
+		if (!_FP_FRAC_EQ_4(X, _m))				    \
+		  R##_f[0] |= _FP_WORK_STICKY;				    \
+		break;							    \
+	      }								    \
+          }								    \
+      }									    \
+  } while (0)
+
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ */
+ 
+#define _FP_SQRT_MEAT_4(R, S, T, X, q)				\
+  do {								\
+    while (q)							\
+      {								\
+	T##_f[3] = S##_f[3] + q;				\
+	if (T##_f[3] <= X##_f[3])				\
+	  {							\
+	    S##_f[3] = T##_f[3] + q;				\
+	    X##_f[3] -= T##_f[3];				\
+	    R##_f[3] += q;					\
+	  }							\
+	_FP_FRAC_SLL_4(X, 1);					\
+	q >>= 1;						\
+      }								\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);			\
+    while (q)							\
+      {								\
+	T##_f[2] = S##_f[2] + q;				\
+	T##_f[3] = S##_f[3];					\
+	if (T##_f[3] < X##_f[3] || 				\
+	    (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2]))	\
+	  {							\
+	    S##_f[2] = T##_f[2] + q;				\
+	    S##_f[3] += (T##_f[2] > S##_f[2]);			\
+	    __FP_FRAC_DEC_2(X##_f[3], X##_f[2],			\
+			    T##_f[3], T##_f[2]);		\
+	    R##_f[2] += q;					\
+	  }							\
+	_FP_FRAC_SLL_4(X, 1);					\
+	q >>= 1;						\
+      }								\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);			\
+    while (q)							\
+      {								\
+	T##_f[1] = S##_f[1] + q;				\
+	T##_f[2] = S##_f[2];					\
+	T##_f[3] = S##_f[3];					\
+	if (T##_f[3] < X##_f[3] || 				\
+	    (T##_f[3] == X##_f[3] && (T##_f[2] < X##_f[2] ||	\
+	     (T##_f[2] == X##_f[2] && T##_f[1] <= X##_f[1]))))	\
+	  {							\
+	    S##_f[1] = T##_f[1] + q;				\
+	    S##_f[2] += (T##_f[1] > S##_f[1]);			\
+	    S##_f[3] += (T##_f[2] > S##_f[2]);			\
+	    __FP_FRAC_DEC_3(X##_f[3], X##_f[2], X##_f[1],	\
+	    		    T##_f[3], T##_f[2], T##_f[1]);	\
+	    R##_f[1] += q;					\
+	  }							\
+	_FP_FRAC_SLL_4(X, 1);					\
+	q >>= 1;						\
+      }								\
+    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);			\
+    while (q != _FP_WORK_ROUND)					\
+      {								\
+	T##_f[0] = S##_f[0] + q;				\
+	T##_f[1] = S##_f[1];					\
+	T##_f[2] = S##_f[2];					\
+	T##_f[3] = S##_f[3];					\
+	if (_FP_FRAC_GE_4(X,T))					\
+	  {							\
+	    S##_f[0] = T##_f[0] + q;				\
+	    S##_f[1] += (T##_f[0] > S##_f[0]);			\
+	    S##_f[2] += (T##_f[1] > S##_f[1]);			\
+	    S##_f[3] += (T##_f[2] > S##_f[2]);			\
+	    _FP_FRAC_DEC_4(X, T);				\
+	    R##_f[0] += q;					\
+	  }							\
+	_FP_FRAC_SLL_4(X, 1);					\
+	q >>= 1;						\
+      }								\
+    if (!_FP_FRAC_ZEROP_4(X))					\
+      {								\
+	if (_FP_FRAC_GT_4(X,S))					\
+	  R##_f[0] |= _FP_WORK_ROUND;				\
+	R##_f[0] |= _FP_WORK_STICKY;				\
+      }								\
+  } while (0)
+
+
+/*
+ * Internals 
+ */
+
+#define __FP_FRAC_SET_4(X,I3,I2,I1,I0)					\
+  (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)
+
+#ifndef __FP_FRAC_ADD_3
+#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)			\
+  (r0 = x0 + y0,							\
+   r1 = x1 + y1 + (r0 < x0),						\
+   r2 = x2 + y2 + (r1 < x1))
+#endif
+
+#ifndef __FP_FRAC_ADD_4
+#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
+  (r0 = x0 + y0,							\
+   r1 = x1 + y1 + (r0 < x0),						\
+   r2 = x2 + y2 + (r1 < x1),						\
+   r3 = x3 + y3 + (r2 < x2))
+#endif
+
+#ifndef __FP_FRAC_SUB_3
+#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)			\
+  (r0 = x0 - y0,							\
+   r1 = x1 - y1 - (r0 > x0),						\
+   r2 = x2 - y2 - (r1 > x1))
+#endif
+
+#ifndef __FP_FRAC_SUB_4
+#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)		\
+  (r0 = x0 - y0,							\
+   r1 = x1 - y1 - (r0 > x0),						\
+   r2 = x2 - y2 - (r1 > x1),						\
+   r3 = x3 - y3 - (r2 > x2))
+#endif
+
+#ifndef __FP_FRAC_DEC_3
+#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0)				\
+  do {									\
+    UWtype _t0, _t1;							\
+    _t0 = x0;								\
+    x0 -= y0;								\
+    _t1 = x1;								\
+    x1 -= y1 + (x0 > _t0);						\
+    x2 -= y2 + (x1 > _t1);						\
+  } while (0)
+#endif
+
+#ifndef __FP_FRAC_DEC_4
+#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0)			\
+  do {									\
+    UWtype _t0, _t1;							\
+    _t0 = x0;								\
+    x0 -= y0;								\
+    _t1 = x1;								\
+    x1 -= y1 + (x0 > _t0);						\
+    _t0 = x2;								\
+    x2 -= y2 + (x1 > _t1);						\
+    x3 -= y3 + (x2 > _t0);						\
+  } while (0)
+#endif
+
+#ifndef __FP_FRAC_ADDI_4
+#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i)					\
+  do {									\
+    UWtype _t;								\
+    _t = ((x0 += i) < i);						\
+    x1 += _t; _t = (x1 < _t);						\
+    x2 += _t; _t = (x2 < _t);						\
+    x3 += _t;								\
+  } while (0)
+#endif
+
+/* Convert FP values between word sizes. This appears to be more
+ * complicated than I'd have expected it to be, so these might be
+ * wrong... These macros are in any case somewhat bogus because they
+ * use information about what various FRAC_n variables look like 
+ * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do
+ * the ones in op-2.h and op-1.h. 
+ */
+#define _FP_FRAC_CONV_1_4(dfs, sfs, D, S)				\
+   do {									\
+     if (S##_c != FP_CLS_NAN)						\
+       _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),	\
+			  _FP_WFRACBITS_##sfs);				\
+     else								\
+       _FP_FRAC_SRL_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs));	\
+     D##_f = S##_f[0];							\
+  } while (0)
+
+#define _FP_FRAC_CONV_2_4(dfs, sfs, D, S)				\
+   do {									\
+     if (S##_c != FP_CLS_NAN)						\
+       _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs),	\
+		      _FP_WFRACBITS_##sfs);				\
+     else								\
+       _FP_FRAC_SRL_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs));	\
+     D##_f0 = S##_f[0];							\
+     D##_f1 = S##_f[1];							\
+  } while (0)
+
+/* Assembly/disassembly for converting to/from integral types.  
+ * No shifting or overflow handled here.
+ */
+/* Put the FP value X into r, which is an integer of size rsize. */
+#define _FP_FRAC_ASSEMBLE_4(r, X, rsize)				\
+  do {									\
+    if (rsize <= _FP_W_TYPE_SIZE)					\
+      r = X##_f[0];							\
+    else if (rsize <= 2*_FP_W_TYPE_SIZE)				\
+    {									\
+      r = X##_f[1];							\
+      r <<= _FP_W_TYPE_SIZE;						\
+      r += X##_f[0];							\
+    }									\
+    else								\
+    {									\
+      /* I'm feeling lazy so we deal with int == 3words (implausible)*/	\
+      /* and int == 4words as a single case.			 */	\
+      r = X##_f[3];							\
+      r <<= _FP_W_TYPE_SIZE;						\
+      r += X##_f[2];							\
+      r <<= _FP_W_TYPE_SIZE;						\
+      r += X##_f[1];							\
+      r <<= _FP_W_TYPE_SIZE;						\
+      r += X##_f[0];							\
+    }									\
+  } while (0)
+
+/* "No disassemble Number Five!" */
+/* move an integer of size rsize into X's fractional part. We rely on
+ * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid
+ * having to mask the values we store into it.
+ */
+#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize)				\
+  do {									\
+    X##_f[0] = r;							\
+    X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);	\
+    X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
+    X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
+  } while (0);
+
+#define _FP_FRAC_CONV_4_1(dfs, sfs, D, S)				\
+   do {									\
+     D##_f[0] = S##_f;							\
+     D##_f[1] = D##_f[2] = D##_f[3] = 0;				\
+     _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));	\
+   } while (0)
+
+#define _FP_FRAC_CONV_4_2(dfs, sfs, D, S)				\
+   do {									\
+     D##_f[0] = S##_f0;							\
+     D##_f[1] = S##_f1;							\
+     D##_f[2] = D##_f[3] = 0;						\
+     _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));	\
+   } while (0)
+
diff -u --recursive --new-file v2.3.15/linux/include/math-emu/op-8.h linux/include/math-emu/op-8.h
--- v2.3.15/linux/include/math-emu/op-8.h	Wed Dec 31 16:00:00 1969
+++ linux/include/math-emu/op-8.h	Tue Aug 31 11:24:24 1999
@@ -0,0 +1,103 @@
+/* Software floating-point emulation.
+   Basic eight-word fraction declaration and manipulation.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+		  Jakub Jelinek (jj@ultra.linux.cz) and
+		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
+                                                         
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* We need just a few things from here for op-4, if we ever need some
+   other macros, they can be added. */
+#define _FP_FRAC_DECL_8(X)	_FP_W_TYPE X##_f[8]
+#define _FP_FRAC_HIGH_8(X)	(X##_f[7])
+#define _FP_FRAC_LOW_8(X)	(X##_f[0])
+#define _FP_FRAC_WORD_8(X,w)	(X##_f[w])
+
+#define _FP_FRAC_SLL_8(X,N)						\
+  do {									\
+    _FP_I_TYPE _up, _down, _skip, _i;					\
+    _skip = (N) / _FP_W_TYPE_SIZE;					\
+    _up = (N) % _FP_W_TYPE_SIZE;					\
+    _down = _FP_W_TYPE_SIZE - _up;					\
+    if (!_up)								\
+      for (_i = 7; _i >= _skip; --_i)					\
+	X##_f[_i] = X##_f[_i-_skip];					\
+    else								\
+      {									\
+	for (_i = 7; _i > _skip; --_i)					\
+	  X##_f[_i] = X##_f[_i-_skip] << _up				\
+		      | X##_f[_i-_skip-1] >> _down;			\
+	X##_f[_i--] = X##_f[0] << _up; 					\
+      }									\
+    for (; _i >= 0; --_i)						\
+      X##_f[_i] = 0;							\
+  } while (0)
+
+#define _FP_FRAC_SRL_8(X,N)						\
+  do {									\
+    _FP_I_TYPE _up, _down, _skip, _i;					\
+    _skip = (N) / _FP_W_TYPE_SIZE;					\
+    _down = (N) % _FP_W_TYPE_SIZE;					\
+    _up = _FP_W_TYPE_SIZE - _down;					\
+    if (!_down)								\
+      for (_i = 0; _i <= 7-_skip; ++_i)					\
+	X##_f[_i] = X##_f[_i+_skip];					\
+    else								\
+      {									\
+	for (_i = 0; _i < 7-_skip; ++_i)				\
+	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
+		      | X##_f[_i+_skip+1] << _up;			\
+	X##_f[_i++] = X##_f[7] >> _down;				\
+      }									\
+    for (; _i < 8; ++_i)						\
+      X##_f[_i] = 0;							\
+  } while (0)
+
+
+/* Right shift with sticky-lsb. 
+ * What this actually means is that we do a standard right-shift,
+ * but that if any of the bits that fall off the right hand side
+ * were one then we always set the LSbit.
+ */
+#define _FP_FRAC_SRS_8(X,N,size)					\
+  do {									\
+    _FP_I_TYPE _up, _down, _skip, _i;					\
+    _FP_W_TYPE _s;							\
+    _skip = (N) / _FP_W_TYPE_SIZE;					\
+    _down = (N) % _FP_W_TYPE_SIZE;					\
+    _up = _FP_W_TYPE_SIZE - _down;					\
+    for (_s = _i = 0; _i < _skip; ++_i)					\
+      _s |= X##_f[_i];							\
+    _s |= X##_f[_i] << _up;						\
+/* s is now != 0 if we want to set the LSbit */				\
+    if (!_down)								\
+      for (_i = 0; _i <= 7-_skip; ++_i)					\
+	X##_f[_i] = X##_f[_i+_skip];					\
+    else								\
+      {									\
+	for (_i = 0; _i < 7-_skip; ++_i)				\
+	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
+		      | X##_f[_i+_skip+1] << _up;			\
+	X##_f[_i++] = X##_f[7] >> _down;				\
+      }									\
+    for (; _i < 8; ++_i)						\
+      X##_f[_i] = 0;							\
+    /* don't fix the LSB until the very end when we're sure f[0] is stable */	\
+    X##_f[0] |= (_s != 0);						\
+  } while (0)
+
diff -u --recursive --new-file v2.3.15/linux/include/math-emu/op-common.h linux/include/math-emu/op-common.h
--- v2.3.15/linux/include/math-emu/op-common.h	Wed Dec 31 16:00:00 1969
+++ linux/include/math-emu/op-common.h	Tue Aug 31 11:24:24 1999
@@ -0,0 +1,767 @@
+/* Software floating-point emulation. Common operations.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+		  Jakub Jelinek (jj@ultra.linux.cz),
+		  David S. Miller (davem@redhat.com) and
+		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#define _FP_DECL(wc, X)			\
+  _FP_I_TYPE X##_c, X##_s, X##_e;	\
+  _FP_FRAC_DECL_##wc(X)
+
+/*
+ * Finish truely unpacking a native fp value by classifying the kind
+ * of fp value and normalizing both the exponent and the fraction.
+ */
+
+#define _FP_UNPACK_CANONICAL(fs, wc, X)					\
+do {									\
+  switch (X##_e)							\
+  {									\
+  default:								\
+    _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs;			\
+    _FP_FRAC_SLL_##wc(X, _FP_WORKBITS);					\
+    X##_e -= _FP_EXPBIAS_##fs;						\
+    X##_c = FP_CLS_NORMAL;						\
+    break;								\
+									\
+  case 0:								\
+    if (_FP_FRAC_ZEROP_##wc(X))						\
+      X##_c = FP_CLS_ZERO;						\
+    else								\
+      {									\
+	/* a denormalized number */					\
+	_FP_I_TYPE _shift;						\
+	_FP_FRAC_CLZ_##wc(_shift, X);					\
+	_shift -= _FP_FRACXBITS_##fs;					\
+	_FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS));			\
+	X##_e -= _FP_EXPBIAS_##fs - 1 + _shift;				\
+	X##_c = FP_CLS_NORMAL;						\
+	FP_SET_EXCEPTION(FP_EX_DENORM);					\
+      }									\
+    break;								\
+									\
+  case _FP_EXPMAX_##fs:							\
+    if (_FP_FRAC_ZEROP_##wc(X))						\
+      X##_c = FP_CLS_INF;						\
+    else								\
+      {									\
+	X##_c = FP_CLS_NAN;						\
+	/* Check for signaling NaN */					\
+	if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))		\
+	  FP_SET_EXCEPTION(FP_EX_INVALID);				\
+      }									\
+    break;								\
+  }									\
+} while (0)
+
+/*
+ * Before packing the bits back into the native fp result, take care
+ * of such mundane things as rounding and overflow.  Also, for some
+ * kinds of fp values, the original parts may not have been fully
+ * extracted -- but that is ok, we can regenerate them now.
+ */
+
+#define _FP_PACK_CANONICAL(fs, wc, X)				\
+do {								\
+  switch (X##_c)						\
+  {								\
+  case FP_CLS_NORMAL:						\
+    X##_e += _FP_EXPBIAS_##fs;					\
+    if (X##_e > 0)						\
+      {								\
+	_FP_ROUND(wc, X);					\
+	if (_FP_FRAC_OVERP_##wc(fs, X))				\
+	  {							\
+	    _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1));		\
+	    X##_e++;						\
+	  }							\
+	else							\
+	  _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);			\
+	if (X##_e >= _FP_EXPMAX_##fs)				\
+	  {							\
+	    /* overflow */					\
+	    switch (FP_ROUNDMODE)				\
+	      {							\
+	      case FP_RND_NEAREST:				\
+		X##_c = FP_CLS_INF;				\
+		break;						\
+	      case FP_RND_PINF:					\
+		if (!X##_s) X##_c = FP_CLS_INF;			\
+		break;						\
+	      case FP_RND_MINF:					\
+		if (X##_s) X##_c = FP_CLS_INF;			\
+		break;						\
+	      }							\
+	    if (X##_c == FP_CLS_INF)				\
+	      {							\
+		/* Overflow to infinity */			\
+		X##_e = _FP_EXPMAX_##fs;			\
+		_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);	\
+	      }							\
+	    else						\
+	      {							\
+		/* Overflow to maximum normal */		\
+		X##_e = _FP_EXPMAX_##fs - 1;			\
+		_FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc);		\
+	      }							\
+	    FP_SET_EXCEPTION(FP_EX_OVERFLOW);			\
+            FP_SET_EXCEPTION(FP_EX_INEXACT);			\
+	  }							\
+      }								\
+    else							\
+      {								\
+	/* we've got a denormalized number */			\
+	X##_e = -X##_e + 1;					\
+	if (X##_e <= _FP_WFRACBITS_##fs)			\
+	  {							\
+	    _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);	\
+	    _FP_ROUND(wc, X);					\
+	    if (_FP_FRAC_HIGH_##fs(X)				\
+		& (_FP_OVERFLOW_##fs >> 1))			\
+	      {							\
+	        X##_e = 1;					\
+	        _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);	\
+	      }							\
+	    else						\
+	      {							\
+		X##_e = 0;					\
+		_FP_FRAC_SRL_##wc(X, _FP_WORKBITS);		\
+		FP_SET_EXCEPTION(FP_EX_UNDERFLOW);		\
+	      }							\
+	  }							\
+	else							\
+	  {							\
+	    /* underflow to zero */				\
+	    X##_e = 0;						\
+	    if (!_FP_FRAC_ZEROP_##wc(X))			\
+	      {							\
+	        _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);		\
+	        _FP_ROUND(wc, X);				\
+	        _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS);	\
+	      }							\
+	    FP_SET_EXCEPTION(FP_EX_UNDERFLOW);			\
+	  }							\
+      }								\
+    break;							\
+								\
+  case FP_CLS_ZERO:						\
+    X##_e = 0;							\
+    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			\
+    break;							\
+								\
+  case FP_CLS_INF:						\
+    X##_e = _FP_EXPMAX_##fs;					\
+    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			\
+    break;							\
+								\
+  case FP_CLS_NAN:						\
+    X##_e = _FP_EXPMAX_##fs;					\
+    if (!_FP_KEEPNANFRACP)					\
+      {								\
+	_FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);			\
+	X##_s = _FP_NANSIGN_##fs;				\
+      }								\
+    else							\
+      _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;		\
+    break;							\
+  }								\
+} while (0)
+
+/* This one accepts raw argument and not cooked,  returns
+ * 1 if X is a signaling NaN.
+ */
+#define _FP_ISSIGNAN(fs, wc, X)					\
+({								\
+  int __ret = 0;						\
+  if (X##_e == _FP_EXPMAX_##fs)					\
+    {								\
+      if (!_FP_FRAC_ZEROP_##wc(X)				\
+	  && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))	\
+	__ret = 1;						\
+    }								\
+  __ret;							\
+})
+
+
+
+
+
+/*
+ * Main addition routine.  The input values should be cooked.
+ */
+
+#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP)				     \
+do {									     \
+  switch (_FP_CLS_COMBINE(X##_c, Y##_c))				     \
+  {									     \
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):			     \
+    {									     \
+      /* shift the smaller number so that its exponent matches the larger */ \
+      _FP_I_TYPE diff = X##_e - Y##_e;					     \
+									     \
+      if (diff < 0)							     \
+	{								     \
+	  diff = -diff;							     \
+	  if (diff <= _FP_WFRACBITS_##fs)				     \
+	    _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs);		     \
+	  else if (!_FP_FRAC_ZEROP_##wc(X))				     \
+	    _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);			     \
+	  R##_e = Y##_e;						     \
+	}								     \
+      else								     \
+	{								     \
+	  if (diff > 0)							     \
+	    {								     \
+	      if (diff <= _FP_WFRACBITS_##fs)				     \
+	        _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs);		     \
+	      else if (!_FP_FRAC_ZEROP_##wc(Y))				     \
+	        _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);			     \
+	    }								     \
+	  R##_e = X##_e;						     \
+	}								     \
+									     \
+      R##_c = FP_CLS_NORMAL;						     \
+									     \
+      if (X##_s == Y##_s)						     \
+	{								     \
+	  R##_s = X##_s;						     \
+	  _FP_FRAC_ADD_##wc(R, X, Y);					     \
+	  if (_FP_FRAC_OVERP_##wc(fs, R))				     \
+	    {								     \
+	      _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);		     \
+	      R##_e++;							     \
+	    }								     \
+	}								     \
+      else								     \
+	{								     \
+	  R##_s = X##_s;						     \
+	  _FP_FRAC_SUB_##wc(R, X, Y);					     \
+	  if (_FP_FRAC_ZEROP_##wc(R))					     \
+	    {								     \
+	      /* return an exact zero */				     \
+	      if (FP_ROUNDMODE == FP_RND_MINF)				     \
+		R##_s |= Y##_s;						     \
+	      else							     \
+		R##_s &= Y##_s;						     \
+	      R##_c = FP_CLS_ZERO;					     \
+	    }								     \
+	  else								     \
+	    {								     \
+	      if (_FP_FRAC_NEGP_##wc(R))				     \
+		{							     \
+		  _FP_FRAC_SUB_##wc(R, Y, X);				     \
+		  R##_s = Y##_s;					     \
+		}							     \
+									     \
+	      /* renormalize after subtraction */			     \
+	      _FP_FRAC_CLZ_##wc(diff, R);				     \
+	      diff -= _FP_WFRACXBITS_##fs;				     \
+	      if (diff)							     \
+		{							     \
+		  R##_e -= diff;					     \
+		  _FP_FRAC_SLL_##wc(R, diff);				     \
+		}							     \
+	    }								     \
+	}								     \
+      break;								     \
+    }									     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):				     \
+    _FP_CHOOSENAN(fs, wc, R, X, Y, OP);					     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):			     \
+    R##_e = X##_e;							     \
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):			     \
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):				     \
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):				     \
+    _FP_FRAC_COPY_##wc(R, X);						     \
+    R##_s = X##_s;							     \
+    R##_c = X##_c;							     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):			     \
+    R##_e = Y##_e;							     \
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):			     \
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):				     \
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):				     \
+    _FP_FRAC_COPY_##wc(R, Y);						     \
+    R##_s = Y##_s;							     \
+    R##_c = Y##_c;							     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):				     \
+    if (X##_s != Y##_s)							     \
+      {									     \
+	/* +INF + -INF => NAN */					     \
+	_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);				     \
+	R##_s = _FP_NANSIGN_##fs;					     \
+	R##_c = FP_CLS_NAN;						     \
+	FP_SET_EXCEPTION(FP_EX_INVALID);				     \
+	break;								     \
+      }									     \
+    /* FALLTHRU */							     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):			     \
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):				     \
+    R##_s = X##_s;							     \
+    R##_c = FP_CLS_INF;							     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):			     \
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):				     \
+    R##_s = Y##_s;							     \
+    R##_c = FP_CLS_INF;							     \
+    break;								     \
+									     \
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):			     \
+    /* make sure the sign is correct */					     \
+    if (FP_ROUNDMODE == FP_RND_MINF)					     \
+      R##_s = X##_s | Y##_s;						     \
+    else								     \
+      R##_s = X##_s & Y##_s;						     \
+    R##_c = FP_CLS_ZERO;						     \
+    break;								     \
+									     \
+  default:								     \
+    abort();								     \
+  }									     \
+} while (0)
+
+#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
+#define _FP_SUB(fs, wc, R, X, Y)					     \
+  do {									     \
+    if (Y##_c != FP_CLS_NAN) Y##_s ^= 1;				     \
+    _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-');				     \
+  } while (0)
+
+
+/*
+ * Main negation routine.  FIXME -- when we care about setting exception
+ * bits reliably, this will not do.  We should examine all of the fp classes.
+ */
+
+#define _FP_NEG(fs, wc, R, X)		\
+  do {					\
+    _FP_FRAC_COPY_##wc(R, X);		\
+    R##_c = X##_c;			\
+    R##_e = X##_e;			\
+    R##_s = 1 ^ X##_s;			\
+  } while (0)
+
+
+/*
+ * Main multiplication routine.  The input values should be cooked.
+ */
+
+#define _FP_MUL(fs, wc, R, X, Y)			\
+do {							\
+  R##_s = X##_s ^ Y##_s;				\
+  switch (_FP_CLS_COMBINE(X##_c, Y##_c))		\
+  {							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):	\
+    R##_c = FP_CLS_NORMAL;				\
+    R##_e = X##_e + Y##_e + 1;				\
+							\
+    _FP_MUL_MEAT_##fs(R,X,Y);				\
+							\
+    if (_FP_FRAC_OVERP_##wc(fs, R))			\
+      _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);	\
+    else						\
+      R##_e--;						\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):		\
+    _FP_CHOOSENAN(fs, wc, R, X, Y, '*');		\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):	\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):		\
+    R##_s = X##_s;					\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):	\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):	\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):	\
+    _FP_FRAC_COPY_##wc(R, X);				\
+    R##_c = X##_c;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):	\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):		\
+    R##_s = Y##_s;					\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):	\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):	\
+    _FP_FRAC_COPY_##wc(R, Y);				\
+    R##_c = Y##_c;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):		\
+    R##_s = _FP_NANSIGN_##fs;				\
+    R##_c = FP_CLS_NAN;					\
+    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
+    FP_SET_EXCEPTION(FP_EX_INVALID);			\
+    break;						\
+							\
+  default:						\
+    abort();						\
+  }							\
+} while (0)
+
+
+/*
+ * Main division routine.  The input values should be cooked.
+ */
+
+#define _FP_DIV(fs, wc, R, X, Y)			\
+do {							\
+  R##_s = X##_s ^ Y##_s;				\
+  switch (_FP_CLS_COMBINE(X##_c, Y##_c))		\
+  {							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):	\
+    R##_c = FP_CLS_NORMAL;				\
+    R##_e = X##_e - Y##_e;				\
+							\
+    _FP_DIV_MEAT_##fs(R,X,Y);				\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):		\
+    _FP_CHOOSENAN(fs, wc, R, X, Y, '/');		\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):	\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):		\
+    R##_s = X##_s;					\
+    _FP_FRAC_COPY_##wc(R, X);				\
+    R##_c = X##_c;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):	\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):		\
+    R##_s = Y##_s;					\
+    _FP_FRAC_COPY_##wc(R, Y);				\
+    R##_c = Y##_c;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):	\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):	\
+    R##_c = FP_CLS_ZERO;				\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):	\
+    FP_SET_EXCEPTION(FP_EX_DIVZERO);			\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):		\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):	\
+    R##_c = FP_CLS_INF;					\
+    break;						\
+							\
+  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):		\
+  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):	\
+    R##_s = _FP_NANSIGN_##fs;				\
+    R##_c = FP_CLS_NAN;					\
+    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
+    FP_SET_EXCEPTION(FP_EX_INVALID);			\
+    break;						\
+							\
+  default:						\
+    abort();						\
+  }							\
+} while (0)
+
+
+/*
+ * Main differential comparison routine.  The inputs should be raw not
+ * cooked.  The return is -1,0,1 for normal values, 2 otherwise.
+ */
+
+#define _FP_CMP(fs, wc, ret, X, Y, un)					\
+  do {									\
+    /* NANs are unordered */						\
+    if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))		\
+	|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))	\
+      {									\
+	ret = un;							\
+      }									\
+    else								\
+      {									\
+	int __is_zero_x;						\
+	int __is_zero_y;						\
+									\
+	__is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0;	\
+	__is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0;	\
+									\
+	if (__is_zero_x && __is_zero_y)					\
+		ret = 0;						\
+	else if (__is_zero_x)						\
+		ret = Y##_s ? 1 : -1;					\
+	else if (__is_zero_y)						\
+		ret = X##_s ? -1 : 1;					\
+	else if (X##_s != Y##_s)					\
+	  ret = X##_s ? -1 : 1;						\
+	else if (X##_e > Y##_e)						\
+	  ret = X##_s ? -1 : 1;						\
+	else if (X##_e < Y##_e)						\
+	  ret = X##_s ? 1 : -1;						\
+	else if (_FP_FRAC_GT_##wc(X, Y))				\
+	  ret = X##_s ? -1 : 1;						\
+	else if (_FP_FRAC_GT_##wc(Y, X))				\
+	  ret = X##_s ? 1 : -1;						\
+	else								\
+	  ret = 0;							\
+      }									\
+  } while (0)
+
+
+/* Simplification for strict equality.  */
+
+#define _FP_CMP_EQ(fs, wc, ret, X, Y)					  \
+  do {									  \
+    /* NANs are unordered */						  \
+    if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))		  \
+	|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))	  \
+      {									  \
+	ret = 1;							  \
+      }									  \
+    else								  \
+      {									  \
+	ret = !(X##_e == Y##_e						  \
+		&& _FP_FRAC_EQ_##wc(X, Y)				  \
+		&& (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
+      }									  \
+  } while (0)
+
+/*
+ * Main square root routine.  The input value should be cooked.
+ */
+
+#define _FP_SQRT(fs, wc, R, X)						\
+do {									\
+    _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S);			\
+    _FP_W_TYPE q;							\
+    switch (X##_c)							\
+    {									\
+    case FP_CLS_NAN:							\
+	_FP_FRAC_COPY_##wc(R, X);					\
+	R##_s = X##_s;							\
+    	R##_c = FP_CLS_NAN;						\
+    	break;								\
+    case FP_CLS_INF:							\
+    	if (X##_s)							\
+    	  {								\
+    	    R##_s = _FP_NANSIGN_##fs;					\
+	    R##_c = FP_CLS_NAN; /* NAN */				\
+	    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);			\
+	    FP_SET_EXCEPTION(FP_EX_INVALID);				\
+    	  }								\
+    	else								\
+    	  {								\
+    	    R##_s = 0;							\
+    	    R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */			\
+    	  }								\
+    	break;								\
+    case FP_CLS_ZERO:							\
+	R##_s = X##_s;							\
+	R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */			\
+	break;								\
+    case FP_CLS_NORMAL:							\
+    	R##_s = 0;							\
+        if (X##_s)							\
+          {								\
+	    R##_c = FP_CLS_NAN; /* sNAN */				\
+	    R##_s = _FP_NANSIGN_##fs;					\
+	    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);			\
+	    FP_SET_EXCEPTION(FP_EX_INVALID);				\
+	    break;							\
+          }								\
+    	R##_c = FP_CLS_NORMAL;						\
+        if (X##_e & 1)							\
+          _FP_FRAC_SLL_##wc(X, 1);					\
+        R##_e = X##_e >> 1;						\
+        _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc);			\
+        _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc);			\
+        q = _FP_OVERFLOW_##fs >> 1;					\
+        _FP_SQRT_MEAT_##wc(R, S, T, X, q);				\
+    }									\
+  } while (0)
+
+/*
+ * Convert from FP to integer
+ */
+
+/* RSIGNED can have following values:
+ * 0:  the number is required to be 0..(2^rsize)-1, if not, NV is set plus
+ *     the result is either 0 or (2^rsize)-1 depending on the sign in such case.
+ * 1:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
+ *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
+ *     on the sign in such case.
+ * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
+ *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
+ *     on the sign in such case.
+ */
+#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)				\
+  do {										\
+    switch (X##_c)								\
+      {										\
+      case FP_CLS_NORMAL:							\
+	if (X##_e < 0)								\
+	  {									\
+	    FP_SET_EXCEPTION(FP_EX_INEXACT);					\
+	  case FP_CLS_ZERO:							\
+	    r = 0;								\
+	  }									\
+	else if (X##_e >= rsize - (rsigned > 0 || X##_s)			\
+		 || (!rsigned && X##_s))					\
+	  {	/* overflow */							\
+	  case FP_CLS_NAN:                                                      \
+	  case FP_CLS_INF:							\
+	    if (rsigned)							\
+	      {									\
+		r = 1;								\
+		r <<= rsize - 1;						\
+		r -= 1 - X##_s;							\
+	      } else {								\
+		r = 0;								\
+		if (X##_s)							\
+		  r = ~r;							\
+	      }									\
+	    FP_SET_EXCEPTION(FP_EX_INVALID);					\
+	  }									\
+	else									\
+	  {									\
+	    if (_FP_W_TYPE_SIZE*wc < rsize)					\
+	      {									\
+		_FP_FRAC_ASSEMBLE_##wc(r, X, rsize);				\
+		r <<= X##_e - _FP_WFRACBITS_##fs;				\
+	      }									\
+	    else								\
+	      {									\
+		if (X##_e >= _FP_WFRACBITS_##fs)				\
+		  _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));	\
+		else if (X##_e < _FP_WFRACBITS_##fs - 1)			\
+		  {								\
+		    _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2),	\
+				      _FP_WFRACBITS_##fs);			\
+		    if (_FP_FRAC_LOW_##wc(X) & 1)				\
+		      FP_SET_EXCEPTION(FP_EX_INEXACT);				\
+		    _FP_FRAC_SRL_##wc(X, 1);					\
+		  }								\
+		_FP_FRAC_ASSEMBLE_##wc(r, X, rsize);				\
+	      }									\
+	    if (rsigned && X##_s)						\
+	      r = -r;								\
+	  }									\
+	break;									\
+      }										\
+  } while (0)
+
+#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)			\
+  do {									\
+    if (r)								\
+      {									\
+	X##_c = FP_CLS_NORMAL;						\
+									\
+	if ((X##_s = (r < 0)))						\
+	  r = -r;							\
+									\
+	if (rsize <= _FP_W_TYPE_SIZE)					\
+	  __FP_CLZ(X##_e, r);						\
+	else								\
+	  __FP_CLZ_2(X##_e, (_FP_W_TYPE)(r >> _FP_W_TYPE_SIZE), 	\
+		     (_FP_W_TYPE)r);					\
+	if (rsize < _FP_W_TYPE_SIZE)					\
+		X##_e -= (_FP_W_TYPE_SIZE - rsize);			\
+	X##_e = rsize - X##_e - 1;					\
+									\
+	if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e)	\
+	  __FP_FRAC_SRS_1(r, (X##_e - _FP_WFRACBITS_##fs), rsize);	\
+	r &= ~((rtype)1 << X##_e);					\
+	_FP_FRAC_DISASSEMBLE_##wc(X, ((unsigned rtype)r), rsize);	\
+	_FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));		\
+      }									\
+    else								\
+      {									\
+	X##_c = FP_CLS_ZERO, X##_s = 0;					\
+      }									\
+  } while (0)
+
+
+#define FP_CONV(dfs,sfs,dwc,swc,D,S)			\
+  do {							\
+    _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S);	\
+    D##_e = S##_e;					\
+    D##_c = S##_c;					\
+    D##_s = S##_s;					\
+  } while (0)
+
+/*
+ * Helper primitives.
+ */
+
+/* Count leading zeros in a word.  */
+
+#ifndef __FP_CLZ
+#if _FP_W_TYPE_SIZE < 64
+/* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
+#define __FP_CLZ(r, x)				\
+  do {						\
+    _FP_W_TYPE _t = (x);			\
+    r = _FP_W_TYPE_SIZE - 1;			\
+    if (_t > 0xffff) r -= 16;			\
+    if (_t > 0xffff) _t >>= 16;			\
+    if (_t > 0xff) r -= 8;			\
+    if (_t > 0xff) _t >>= 8;			\
+    if (_t & 0xf0) r -= 4;			\
+    if (_t & 0xf0) _t >>= 4;			\
+    if (_t & 0xc) r -= 2;			\
+    if (_t & 0xc) _t >>= 2;			\
+    if (_t & 0x2) r -= 1;			\
+  } while (0)
+#else /* not _FP_W_TYPE_SIZE < 64 */
+#define __FP_CLZ(r, x)				\
+  do {						\
+    _FP_W_TYPE _t = (x);			\
+    r = _FP_W_TYPE_SIZE - 1;			\
+    if (_t > 0xffffffff) r -= 32;		\
+    if (_t > 0xffffffff) _t >>= 32;		\
+    if (_t > 0xffff) r -= 16;			\
+    if (_t > 0xffff) _t >>= 16;			\
+    if (_t > 0xff) r -= 8;			\
+    if (_t > 0xff) _t >>= 8;			\
+    if (_t & 0xf0) r -= 4;			\
+    if (_t & 0xf0) _t >>= 4;			\
+    if (_t & 0xc) r -= 2;			\
+    if (_t & 0xc) _t >>= 2;			\
+    if (_t & 0x2) r -= 1;			\
+  } while (0)
+#endif /* not _FP_W_TYPE_SIZE < 64 */
+#endif /* ndef __FP_CLZ */
+
+#define _FP_DIV_HELP_imm(q, r, n, d)		\
+  do {						\
+    q = n / d, r = n % d;			\
+  } while (0)
+
diff -u --recursive --new-file v2.3.15/linux/include/math-emu/quad.h linux/include/math-emu/quad.h
--- v2.3.15/linux/include/math-emu/quad.h	Wed Dec 31 16:00:00 1969
+++ linux/include/math-emu/quad.h	Tue Aug 31 11:24:24 1999
@@ -0,0 +1,201 @@
+/* Software floating-point emulation.
+   Definitions for IEEE Quad Precision.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+		  Jakub Jelinek (jj@ultra.linux.cz),
+		  David S. Miller (davem@redhat.com) and
+		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel, kid. Go buy yourself a real computer."
+#endif
+
+#if _FP_W_TYPE_SIZE < 64
+#define _FP_FRACTBITS_Q         (4*_FP_W_TYPE_SIZE)
+#else
+#define _FP_FRACTBITS_Q		(2*_FP_W_TYPE_SIZE)
+#endif
+
+#define _FP_FRACBITS_Q		113
+#define _FP_FRACXBITS_Q		(_FP_FRACTBITS_Q - _FP_FRACBITS_Q)
+#define _FP_WFRACBITS_Q		(_FP_WORKBITS + _FP_FRACBITS_Q)
+#define _FP_WFRACXBITS_Q	(_FP_FRACTBITS_Q - _FP_WFRACBITS_Q)
+#define _FP_EXPBITS_Q		15
+#define _FP_EXPBIAS_Q		16383
+#define _FP_EXPMAX_Q		32767
+
+#define _FP_QNANBIT_Q		\
+	((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2) % _FP_W_TYPE_SIZE)
+#define _FP_IMPLBIT_Q		\
+	((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1) % _FP_W_TYPE_SIZE)
+#define _FP_OVERFLOW_Q		\
+	((_FP_W_TYPE)1 << (_FP_WFRACBITS_Q % _FP_W_TYPE_SIZE))
+
+#if _FP_W_TYPE_SIZE < 64
+
+union _FP_UNION_Q
+{
+   long double flt;
+   struct 
+   {
+#if __BYTE_ORDER == __BIG_ENDIAN
+      unsigned sign : 1;
+      unsigned exp : _FP_EXPBITS_Q;
+      unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
+      unsigned long frac2 : _FP_W_TYPE_SIZE;
+      unsigned long frac1 : _FP_W_TYPE_SIZE;
+      unsigned long frac0 : _FP_W_TYPE_SIZE;
+#else
+      unsigned long frac0 : _FP_W_TYPE_SIZE;
+      unsigned long frac1 : _FP_W_TYPE_SIZE;
+      unsigned long frac2 : _FP_W_TYPE_SIZE;
+      unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
+      unsigned exp : _FP_EXPBITS_Q;
+      unsigned sign : 1;
+#endif /* not bigendian */
+   } bits __attribute__((packed));
+};
+
+
+#define FP_DECL_Q(X)		_FP_DECL(4,X)
+#define FP_UNPACK_RAW_Q(X,val)	_FP_UNPACK_RAW_4(Q,X,val)
+#define FP_UNPACK_RAW_QP(X,val)	_FP_UNPACK_RAW_4_P(Q,X,val)
+#define FP_PACK_RAW_Q(val,X)	_FP_PACK_RAW_4(Q,val,X)
+#define FP_PACK_RAW_QP(val,X)		\
+  do {					\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_4_P(Q,val,X);	\
+  } while (0)
+
+#define FP_UNPACK_Q(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_4(Q,X,val);		\
+    _FP_UNPACK_CANONICAL(Q,4,X);	\
+  } while (0)
+
+#define FP_UNPACK_QP(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_4_P(Q,X,val);	\
+    _FP_UNPACK_CANONICAL(Q,4,X);	\
+  } while (0)
+
+#define FP_PACK_Q(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(Q,4,X);		\
+    _FP_PACK_RAW_4(Q,val,X);		\
+  } while (0)
+
+#define FP_PACK_QP(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(Q,4,X);		\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_4_P(Q,val,X);	\
+  } while (0)
+
+#define FP_ISSIGNAN_Q(X)		_FP_ISSIGNAN(Q,4,X)
+#define FP_NEG_Q(R,X)			_FP_NEG(Q,4,R,X)
+#define FP_ADD_Q(R,X,Y)			_FP_ADD(Q,4,R,X,Y)
+#define FP_SUB_Q(R,X,Y)			_FP_SUB(Q,4,R,X,Y)
+#define FP_MUL_Q(R,X,Y)			_FP_MUL(Q,4,R,X,Y)
+#define FP_DIV_Q(R,X,Y)			_FP_DIV(Q,4,R,X,Y)
+#define FP_SQRT_Q(R,X)			_FP_SQRT(Q,4,R,X)
+#define _FP_SQRT_MEAT_Q(R,S,T,X,Q)	_FP_SQRT_MEAT_4(R,S,T,X,Q)
+
+#define FP_CMP_Q(r,X,Y,un)	_FP_CMP(Q,4,r,X,Y,un)
+#define FP_CMP_EQ_Q(r,X,Y)	_FP_CMP_EQ(Q,4,r,X,Y)
+
+#define FP_TO_INT_Q(r,X,rsz,rsg)	_FP_TO_INT(Q,4,r,X,rsz,rsg)
+#define FP_FROM_INT_Q(X,r,rs,rt)	_FP_FROM_INT(Q,4,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_Q(X)	_FP_FRAC_HIGH_4(X)
+#define _FP_FRAC_HIGH_RAW_Q(X)	_FP_FRAC_HIGH_4(X)
+
+#else   /* not _FP_W_TYPE_SIZE < 64 */
+union _FP_UNION_Q
+{
+  long double flt /* __attribute__((mode(TF))) */ ;
+  struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned sign  : 1;
+    unsigned exp   : _FP_EXPBITS_Q;
+    unsigned long frac1 : _FP_FRACBITS_Q-(_FP_IMPLBIT_Q != 0)-_FP_W_TYPE_SIZE;
+    unsigned long frac0 : _FP_W_TYPE_SIZE;
+#else
+    unsigned long frac0 : _FP_W_TYPE_SIZE;
+    unsigned long frac1 : _FP_FRACBITS_Q-(_FP_IMPLBIT_Q != 0)-_FP_W_TYPE_SIZE;
+    unsigned exp   : _FP_EXPBITS_Q;
+    unsigned sign  : 1;
+#endif
+  } bits;
+};
+
+#define FP_DECL_Q(X)		_FP_DECL(2,X)
+#define FP_UNPACK_RAW_Q(X,val)	_FP_UNPACK_RAW_2(Q,X,val)
+#define FP_UNPACK_RAW_QP(X,val)	_FP_UNPACK_RAW_2_P(Q,X,val)
+#define FP_PACK_RAW_Q(val,X)	_FP_PACK_RAW_2(Q,val,X)
+#define FP_PACK_RAW_QP(val,X)		\
+  do {					\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_2_P(Q,val,X);	\
+  } while (0)
+
+#define FP_UNPACK_Q(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_2(Q,X,val);		\
+    _FP_UNPACK_CANONICAL(Q,2,X);	\
+  } while (0)
+
+#define FP_UNPACK_QP(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_2_P(Q,X,val);	\
+    _FP_UNPACK_CANONICAL(Q,2,X);	\
+  } while (0)
+
+#define FP_PACK_Q(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(Q,2,X);		\
+    _FP_PACK_RAW_2(Q,val,X);		\
+  } while (0)
+
+#define FP_PACK_QP(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(Q,2,X);		\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_2_P(Q,val,X);	\
+  } while (0)
+
+#define FP_ISSIGNAN_Q(X)		_FP_ISSIGNAN(Q,2,X)
+#define FP_NEG_Q(R,X)			_FP_NEG(Q,2,R,X)
+#define FP_ADD_Q(R,X,Y)			_FP_ADD(Q,2,R,X,Y)
+#define FP_SUB_Q(R,X,Y)			_FP_SUB(Q,2,R,X,Y)
+#define FP_MUL_Q(R,X,Y)			_FP_MUL(Q,2,R,X,Y)
+#define FP_DIV_Q(R,X,Y)			_FP_DIV(Q,2,R,X,Y)
+#define FP_SQRT_Q(R,X)			_FP_SQRT(Q,2,R,X)
+#define _FP_SQRT_MEAT_Q(R,S,T,X,Q)	_FP_SQRT_MEAT_2(R,S,T,X,Q)
+
+#define FP_CMP_Q(r,X,Y,un)	_FP_CMP(Q,2,r,X,Y,un)
+#define FP_CMP_EQ_Q(r,X,Y)	_FP_CMP_EQ(Q,2,r,X,Y)
+
+#define FP_TO_INT_Q(r,X,rsz,rsg)	_FP_TO_INT(Q,2,r,X,rsz,rsg)
+#define FP_FROM_INT_Q(X,r,rs,rt)	_FP_FROM_INT(Q,2,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_Q(X)	_FP_FRAC_HIGH_2(X)
+#define _FP_FRAC_HIGH_RAW_Q(X)	_FP_FRAC_HIGH_2(X)
+
+#endif /* not _FP_W_TYPE_SIZE < 64 */
diff -u --recursive --new-file v2.3.15/linux/include/math-emu/single.h linux/include/math-emu/single.h
--- v2.3.15/linux/include/math-emu/single.h	Wed Dec 31 16:00:00 1969
+++ linux/include/math-emu/single.h	Tue Aug 31 11:24:24 1999
@@ -0,0 +1,110 @@
+/* Software floating-point emulation.
+   Definitions for IEEE Single Precision.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+		  Jakub Jelinek (jj@ultra.linux.cz),
+		  David S. Miller (davem@redhat.com) and
+		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel kid.  Go buy yourself a real computer."
+#endif
+
+#define _FP_FRACBITS_S		24
+#define _FP_FRACXBITS_S		(_FP_W_TYPE_SIZE - _FP_FRACBITS_S)
+#define _FP_WFRACBITS_S		(_FP_WORKBITS + _FP_FRACBITS_S)
+#define _FP_WFRACXBITS_S	(_FP_W_TYPE_SIZE - _FP_WFRACBITS_S)
+#define _FP_EXPBITS_S		8
+#define _FP_EXPBIAS_S		127
+#define _FP_EXPMAX_S		255
+#define _FP_QNANBIT_S		((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2))
+#define _FP_IMPLBIT_S		((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1))
+#define _FP_OVERFLOW_S		((_FP_W_TYPE)1 << (_FP_WFRACBITS_S))
+
+/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be
+   chosen by the target machine.  */
+
+union _FP_UNION_S
+{
+  float flt;
+  struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned sign : 1;
+    unsigned exp  : _FP_EXPBITS_S;
+    unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
+#else
+    unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
+    unsigned exp  : _FP_EXPBITS_S;
+    unsigned sign : 1;
+#endif
+  } bits __attribute__((packed));
+};
+
+#define FP_DECL_S(X)		_FP_DECL(1,X)
+#define FP_UNPACK_RAW_S(X,val)	_FP_UNPACK_RAW_1(S,X,val)
+#define FP_UNPACK_RAW_SP(X,val)	_FP_UNPACK_RAW_1_P(S,X,val)
+#define FP_PACK_RAW_S(val,X)	_FP_PACK_RAW_1(S,val,X)
+#define FP_PACK_RAW_SP(val,X)		\
+  do {					\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_1_P(S,val,X);	\
+  } while (0)
+
+#define FP_UNPACK_S(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_1(S,X,val);		\
+    _FP_UNPACK_CANONICAL(S,1,X);	\
+  } while (0)
+
+#define FP_UNPACK_SP(X,val)		\
+  do {					\
+    _FP_UNPACK_RAW_1_P(S,X,val);	\
+    _FP_UNPACK_CANONICAL(S,1,X);	\
+  } while (0)
+
+#define FP_PACK_S(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(S,1,X);		\
+    _FP_PACK_RAW_1(S,val,X);		\
+  } while (0)
+
+#define FP_PACK_SP(val,X)		\
+  do {					\
+    _FP_PACK_CANONICAL(S,1,X);		\
+    if (!FP_INHIBIT_RESULTS)		\
+      _FP_PACK_RAW_1_P(S,val,X);	\
+  } while (0)
+
+#define FP_ISSIGNAN_S(X)		_FP_ISSIGNAN(S,1,X)
+#define FP_NEG_S(R,X)			_FP_NEG(S,1,R,X)
+#define FP_ADD_S(R,X,Y)			_FP_ADD(S,1,R,X,Y)
+#define FP_SUB_S(R,X,Y)			_FP_SUB(S,1,R,X,Y)
+#define FP_MUL_S(R,X,Y)			_FP_MUL(S,1,R,X,Y)
+#define FP_DIV_S(R,X,Y)			_FP_DIV(S,1,R,X,Y)
+#define FP_SQRT_S(R,X)			_FP_SQRT(S,1,R,X)
+#define _FP_SQRT_MEAT_S(R,S,T,X,Q)	_FP_SQRT_MEAT_1(R,S,T,X,Q)
+
+#define FP_CMP_S(r,X,Y,un)	_FP_CMP(S,1,r,X,Y,un)
+#define FP_CMP_EQ_S(r,X,Y)	_FP_CMP_EQ(S,1,r,X,Y)
+
+#define FP_TO_INT_S(r,X,rsz,rsg)	_FP_TO_INT(S,1,r,X,rsz,rsg)
+#define FP_FROM_INT_S(X,r,rs,rt)	_FP_FROM_INT(S,1,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_S(X)	_FP_FRAC_HIGH_1(X)
+#define _FP_FRAC_HIGH_RAW_S(X)	_FP_FRAC_HIGH_1(X)
diff -u --recursive --new-file v2.3.15/linux/include/math-emu/soft-fp.h linux/include/math-emu/soft-fp.h
--- v2.3.15/linux/include/math-emu/soft-fp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/math-emu/soft-fp.h	Tue Aug 31 11:24:24 1999
@@ -0,0 +1,176 @@
+/* Software floating-point emulation.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+		  Jakub Jelinek (jj@ultra.linux.cz),
+		  David S. Miller (davem@redhat.com) and
+		  Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef SOFT_FP_H
+#define SOFT_FP_H
+
+#include "sfp-machine.h"
+
+/* Allow sfp-machine to have its own byte order definitions. */
+#ifndef __BYTE_ORDER
+#include <endian.h>
+#endif
+
+#define _FP_WORKBITS		3
+#define _FP_WORK_LSB		((_FP_W_TYPE)1 << 3)
+#define _FP_WORK_ROUND		((_FP_W_TYPE)1 << 2)
+#define _FP_WORK_GUARD		((_FP_W_TYPE)1 << 1)
+#define _FP_WORK_STICKY		((_FP_W_TYPE)1 << 0)
+
+#ifndef FP_RND_NEAREST
+# define FP_RND_NEAREST		0
+# define FP_RND_ZERO		1
+# define FP_RND_PINF		2
+# define FP_RND_MINF		3
+#ifndef FP_ROUNDMODE
+# define FP_ROUNDMODE		FP_RND_NEAREST
+#endif
+#endif
+
+/* By default don't care about exceptions. */
+#ifndef FP_EX_INVALID
+#define FP_EX_INVALID		0
+#endif
+#ifndef FP_EX_OVERFLOW
+#define FP_EX_OVERFLOW		0
+#endif
+#ifndef FP_EX_UNDERFLOW
+#define FP_EX_UNDERFLOW		
+#endif
+#ifndef FP_EX_DIVZERO
+#define FP_EX_DIVZERO		0
+#endif
+#ifndef FP_EX_INEXACT
+#define FP_EX_INEXACT		0
+#endif
+#ifndef FP_EX_DENORM
+#define FP_EX_DENORM		0
+#endif
+
+#ifdef _FP_DECL_EX
+#define FP_DECL_EX					\
+  int _fex = 0;						\
+  _FP_DECL_EX
+#else
+#define FP_DECL_EX int _fex = 0
+#endif
+  
+#ifndef FP_INIT_ROUNDMODE
+#define FP_INIT_ROUNDMODE do {} while (0)
+#endif
+
+#ifndef FP_HANDLE_EXCEPTIONS
+#define FP_HANDLE_EXCEPTIONS do {} while (0)
+#endif
+
+#ifndef FP_INHIBIT_RESULTS
+/* By default we write the results always.
+ * sfp-machine may override this and e.g.
+ * check if some exceptions are unmasked
+ * and inhibit it in such a case.
+ */
+#define FP_INHIBIT_RESULTS 0
+#endif
+
+#define FP_SET_EXCEPTION(ex)				\
+  _fex |= (ex)
+  
+#define FP_UNSET_EXCEPTION(ex)				\
+  _fex &= ~(ex)
+
+#define FP_CLEAR_EXCEPTIONS				\
+  _fex = 0
+
+#define _FP_ROUND_NEAREST(wc, X)			\
+do {							\
+    if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND)	\
+      _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND);		\
+} while (0)
+
+#define _FP_ROUND_ZERO(wc, X)		0
+
+#define _FP_ROUND_PINF(wc, X)				\
+do {							\
+    if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7))		\
+      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);		\
+} while (0)
+
+#define _FP_ROUND_MINF(wc, X)				\
+do {							\
+    if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7))		\
+      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);		\
+} while (0)
+
+#define _FP_ROUND(wc, X)			\
+do {						\
+	if (_FP_FRAC_LOW_##wc(X) & 7)		\
+	  FP_SET_EXCEPTION(FP_EX_INEXACT);	\
+	switch (FP_ROUNDMODE)			\
+	{					\
+	  case FP_RND_NEAREST:			\
+	    _FP_ROUND_NEAREST(wc,X);		\
+	    break;				\
+	  case FP_RND_ZERO:			\
+	    _FP_ROUND_ZERO(wc,X);		\
+	    break;				\
+	  case FP_RND_PINF:			\
+	    _FP_ROUND_PINF(wc,X);		\
+	    break;				\
+	  case FP_RND_MINF:			\
+	    _FP_ROUND_MINF(wc,X);		\
+	    break;				\
+	}					\
+} while (0)
+
+#define FP_CLS_NORMAL		0
+#define FP_CLS_ZERO		1
+#define FP_CLS_INF		2
+#define FP_CLS_NAN		3
+
+#define _FP_CLS_COMBINE(x,y)	(((x) << 2) | (y))
+
+#include "op-1.h"
+#include "op-2.h"
+#include "op-4.h"
+#include "op-8.h"
+#include "op-common.h"
+
+/* Sigh.  Silly things longlong.h needs.  */
+#define UWtype		_FP_W_TYPE
+#define W_TYPE_SIZE	_FP_W_TYPE_SIZE
+
+typedef int SItype __attribute__((mode(SI)));
+typedef int DItype __attribute__((mode(DI)));
+typedef unsigned int USItype __attribute__((mode(SI)));
+typedef unsigned int UDItype __attribute__((mode(DI)));
+#if _FP_W_TYPE_SIZE == 32
+typedef unsigned int UHWtype __attribute__((mode(HI)));
+#elif _FP_W_TYPE_SIZE == 64
+typedef USItype UHWtype;
+#endif
+
+#ifndef umul_ppmm
+#include <stdlib/longlong.h>
+#endif
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/discovery.h linux/include/net/irda/discovery.h
--- v2.3.15/linux/include/net/irda/discovery.h	Sat Apr 24 17:50:05 1999
+++ linux/include/net/irda/discovery.h	Mon Aug 30 10:30:24 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Apr  6 16:53:53 1999
- * Modified at:   Thu Apr 22 11:04:56 1999
+ * Modified at:   Mon Aug 23 09:26:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -39,6 +39,8 @@
 #define DISCOVERY_EXPIRE_TIMEOUT 6*HZ
 #define DISCOVERY_DEFAULT_SLOTS  0
 
+#define NICKNAME_MAX_LEN 21
+
 /*
  * The DISCOVERY structure is used for both discovery requests and responses
  */
@@ -50,17 +52,17 @@
 	LAP_REASON condition;    /* More info about the discovery */
 
 	__u16_host_order hints;  /* Discovery hint bits */
-	__u8       charset;
-	char       info[32];     /* Usually the name of the device */
-	__u8       info_len;     /* Length of device info field */
+	__u8       charset;      /* Encoding of nickname */
+	char       nickname[22]; /* The name of the device (21 bytes + \0) */
+	int        name_len;     /* Lenght of nickname */
 
 	int        gen_addr_bit; /* Need to generate a new device address? */
 	int        nslots;       /* Number of slots to use when discovering */
-	int        timestamp;    /* Time discovered */
+	unsigned long timestamp; /* Time discovered */
 } discovery_t;
 
 void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *discovery);
 void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log);
-void irlmp_expire_discoveries(hashbin_t *log, int saddr, int force);
+void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force);
 
 #endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/dongle.h linux/include/net/irda/dongle.h
--- v2.3.15/linux/include/net/irda/dongle.h	Mon Jun  7 16:18:58 1999
+++ linux/include/net/irda/dongle.h	Mon Aug 30 10:30:24 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 22:47:12 1998
- * Modified at:   Sun May 16 13:40:03 1999
+ * Modified at:   Sat Jun 26 16:58:44 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -35,6 +35,7 @@
 	ACTISYS_PLUS_DONGLE,
 	GIRBIL_DONGLE,
 	LITELINK_DONGLE,
+	AIRPORT_DONGLE,
 } IRDA_DONGLE;
 
 struct irda_device;
@@ -44,7 +45,7 @@
 	void (*open)(struct irda_device *, int type);
 	void (*close)(struct irda_device *);
 	void (*reset)( struct irda_device *);
-	void (*change_speed)( struct irda_device *, int baudrate);
+	void (*change_speed)( struct irda_device *, __u32 speed);
 	void (*qos_init)( struct irda_device *, struct qos_info *);
 };
 
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/ircomm_common.h linux/include/net/irda/ircomm_common.h
--- v2.3.15/linux/include/net/irda/ircomm_common.h	Mon Jun  7 16:18:58 1999
+++ linux/include/net/irda/ircomm_common.h	Wed Dec 31 16:00:00 1969
@@ -1,270 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      ircomm_common.h
- * Version:       
- * Description:   An implementation of IrCOMM service interface and state machine 
- * Status:        Experimental.
- * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
- *
- *     Copyright (c) 1998-1999, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Takahide Higuchi, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRCOMM_H
-#define IRCOMM_H
-
-/* #define DEBUG(n, args...) printk( KERN_DEBUG args) */ /* enable all debug message */
-
-#include <linux/types.h>
-#include <net/irda/irmod.h> 
-
-typedef enum {
-        COMM_IDLE,
-
-	COMM_DISCOVERY_WAIT,
-	COMM_QUERYPARAM_WAIT,
-	COMM_QUERYLSAP_WAIT,
-
-	COMM_WAITI,
-	COMM_WAITR,
-	COMM_CONN,
-} IRCOMM_STATE;
-
-/* IrCOMM Events */
-typedef enum {
-	IRCOMM_CONNECT_REQUEST,
-	TTP_CONNECT_INDICATION,
-	LMP_CONNECT_INDICATION,
-
-	TTP_CONNECT_CONFIRM,
-	TTP_DISCONNECT_INDICATION,
-	LMP_CONNECT_CONFIRM,
-	LMP_DISCONNECT_INDICATION,
-
-	IRCOMM_CONNECT_RESPONSE,
-	IRCOMM_DISCONNECT_REQUEST,
-
-	TTP_DATA_INDICATION,
-	IRCOMM_DATA_REQUEST,
-	LMP_DATA_INDICATION,
-	IRCOMM_CONTROL_REQUEST,
-	
-	DISCOVERY_INDICATION,
-	GOT_PARAMETERS,
-	GOT_LSAPSEL,
-	QUERYIAS_ERROR,
-
-} IRCOMM_EVENT;
-
-typedef enum {
-	TX_READY,
-	TX_BUSY,
-
-	IAS_PARAM,
-	CONTROL_CHANNEL,
-} IRCOMM_CMD;
-
-
-
-#define IRCOMM_MAGIC            0x434f4d4d
-#define COMM_INIT_CTRL_PARAM    3          /* length of initial control parameters */
-#define COMM_HEADER_SIZE        1          /* length of clen field */
-#define COMM_MAX_HEADER_SIZE    (TTP_MAX_HEADER+COMM_HEADER_SIZE)
-#define COMM_DEFAULT_SDU_SIZE   (64 - COMM_HEADER_SIZE)
-#define IRCOMM_MAX_CONNECTION   1          /* Don't change for now */
-
-
-
-
-#define UNKNOWN         0x00            /* not defined yet. */
-/* we use 9wire if servicetype=DEFAULT, but is it good? */
-#define DEFAULT         0x0a            /* private number */
-#define THREE_WIRE_RAW	0x01		/* bit 0 */
-#define THREE_WIRE	0x02		/* bit 1 */
-#define NINE_WIRE	0x04		/* bit 2 */
-#define CENTRONICS	0x08		/* bit 3 */
-
-#define SERIAL		0x01		/* bit 0 */
-#define PARALLEL	0x02		/* bit 1 */
-
-
-#define SERVICETYPE 0x00
-#define PORT_TYPE 0x01
-#define PORT_NAME 0x02
-#define FIXED_PORT_NAME 0x82
-
-#define DATA_RATE 0x10
-#define DATA_FORMAT 0x11
-#define FLOW_CONTROL 0x12
-#define XON_XOFF_CHAR 0x13
-#define ENQ_ACK_CHAR 0x14
-#define LINESTATUS 0x15
-#define BREAK_SIGNAL 0x16
-
-#define DTELINE_STATE 0x20
-#define DCELINE_STATE 0x21
-#define POLL_FOR_LINE_SETTINGS 0x22
-
-#define STATUS_QUERY 0x30
-#define SET_BUSY_TIMEOUT 0x31
-#define IEEE1284_MODE_SUPPORT 0x32
-#define IEEE1284_DEVICEID 0x33
-#define IEEE1284_MODE 0x34
-#define IEEE1284_ECP_EPP_DATA_TRANSFER 0x35
-
-/*  parameters of FLOW_CONTROL  */
-
-#define USE_RTS 0x08  /* use RTS on output */
-#define USE_CTS 0x04  /* use CTS on input */
-#define USE_DTR 0x20  /* use DTR on output */
-
-/*  parameters of DTELINE_STATE  */
-
-#define DELTA_DTR 0x01
-#define DELTA_RTS 0x02
-#define MCR_DTR 0x04
-#define MCR_RTS 0x08
-
-/*  parameters of DCELINE_STATE  */
-
-#define DELTA_CTS 0x01
-#define DELTA_DSR 0x02
-#define DELTA_RI  0x04 
-#define DELTA_DCD 0x08
-#define MSR_CTS   0x10
-#define MSR_DSR   0x20
-#define MSR_RI    0x40 
-#define MSR_DCD   0x80
-
-/*  parameters of DATA_FORMAT */
-
-#define IRCOMM_WLEN5   0x00       /* word length is 5bit */
-#define IRCOMM_WLEN6   0x01       /* word length is 6bit */
-#define IRCOMM_WLEN7   0x02       /* word length is 7bit */
-#define IRCOMM_WLEN8   0x03       /* word length is 8bit */
-
-#define IRCOMM_STOP2   0x04       /* 2 stop bits mode */
-#define IRCOMM_PARENB  0x08       /* parity enable */
-#define IRCOMM_PARODD  0x00       /*  odd parity */
-#define IRCOMM_PAREVEN 0x10       /*  even parity */
-#define IRCOMM_PARMARK 0x20
-#define IRCOMM_PARSPC  0x30
-
-/*  parameters of LINE_STATUS */
-
-#define LSR_OE     0x02    /* Overrun error indicator */
-#define LSR_PE     0x04    /* Parity error indicator */
-#define LSR_FE     0x08    /* Frame error indicator */
-#define LSR_BI     0x01    /* Break interrupt indicator */
-
-
-struct ircomm_cb {
-	int magic;
-	int state;          /* Current state of IrCOMM layer: 
-			     *  DISCOVERY,COMM_IDLE, COMM_WAITR,
-			     *  COMM_WAITI, COMM_CONN
-			     */
-	int in_use;
-	int null_modem_mode;     /* switch for null modem emulation */
-	int ttp_stop;
-
-	__u32 tx_max_sdu_size;          
-	__u32 rx_max_sdu_size;
-	__u8 max_header_size;
-
- 	__u32 daddr;        /* Device address of the peer device */ 
-	__u32 saddr;
-	__u32 skey;
-	__u32 ckey;
-	int                 queryias_lock;
-	int                 ias_type;
-	int disconnect_priority; /* P_NORMAL or P_HIGH. see irttp.h */
-	struct notify_t notify;     /* container of callbacks */
-	void (*d_handler)(struct ircomm_cb *self);
-
-	int control_ch_pending;
-	struct sk_buff *ctrl_skb;   /* queue of control channel */
-
-	__u8 dlsap;          /* IrLMP dlsap */
-	__u8 lsap;           /* sap of local device */ 
-	struct tsap_cb *tsap;          /* IrTTP/LMP handle */
-	struct qos_info *qos;         /* Quality of Service */
-	int reason;          /* I don't know about reason: 
-				see Irlmp.c or somewhere :p)*/ 
-	int peer_cap;        /* capability of peer device */
-
-	wait_queue_head_t   discovery_wait;
-	wait_queue_head_t   ias_wait;
-
-	/* statistics */
-	int                 tx_packets;
-	int                 rx_packets;
-	int                 tx_controls;
-	int                 pending_control_tuples;
-	int                 ignored_control_tuples;
-
-	__u8 pi ;            /* instruction of control channel*/ 
-
-	__u8 port_type;
-	__u8 peer_port_type;
-
-	__u8 servicetype;    
-	__u8 peer_servicetype;    
-	__u8 data_format;   
-	__u8 peer_data_format;   
-	__u8 flow_ctrl;
-	__u8 peer_flow_ctrl;
-	__u8 line_status;
-	__u8 peer_line_status;
-	__u8 break_signal;
-	__u8 peer_break_signal;
-	__u8 dte;
-	__u8 peer_dte;
-	__u8 dce;
-	__u8 peer_dce;
-	__u8 xon_char;
-	__u8 xoff_char;
-	__u8 peer_xon_char;
-	__u8 peer_xoff_char;
-	__u8 enq_char;
-	__u8 ack_char;
-	__u8 peer_enq_char;
-	__u8 peer_ack_char;
-	__u8 busy_timeout;
-	__u8 peer_busy_timeout;
-	__u8 ecp_epp_mode;
-	__u8 peer_ecp_epp_mode;
-	__u8 channel_or_addr;
-	__u8 peer_channel_or_addr;
-	
-	__u32 data_rate;
-	__u32 peer_data_rate;
-	char port_name[33];
-	int port_name_critical;
-};
-
-void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype);
-void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
-			     __u32 maxsdusize);
-void ircomm_disconnect_request(struct ircomm_cb *self,
-			       struct sk_buff *userdata, int priority);
-int ircomm_data_request(struct ircomm_cb *self,
-			struct sk_buff *userdata);
-void ircomm_control_request(struct ircomm_cb *self, __u8 instruction);
-
-void ircomm_parse_tuples(struct ircomm_cb *self, struct sk_buff *skb, int type);
-
-struct ircomm_cb *ircomm_open_instance(struct notify_t notify);
-int ircomm_close_instance(struct ircomm_cb *self);
-
-
-#endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/ircomm_core.h linux/include/net/irda/ircomm_core.h
--- v2.3.15/linux/include/net/irda/ircomm_core.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/ircomm_core.h	Mon Aug 30 10:30:24 1999
@@ -0,0 +1,110 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_core.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Wed Jun  9 08:58:43 1999
+ * Modified at:   Fri Aug 13 07:24:18 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_CORE_H
+#define IRCOMM_CORE_H
+
+#include <net/irda/irda.h>
+#include <net/irda/ircomm_event.h>
+
+#define IRCOMM_MAGIC 0x98347298
+#define IRCOMM_HEADER_SIZE 1
+
+struct ircomm_cb;   /* Forward decl. */
+
+/*
+ * A small call-table, so we don't have to check the service-type whenever
+ * we want to do something
+ */
+typedef struct {
+	int (*data_request)(struct ircomm_cb *, struct sk_buff *, int clen);
+	int (*connect_request)(struct ircomm_cb *, struct sk_buff *, 
+			       struct ircomm_info *);
+	int (*connect_response)(struct ircomm_cb *, struct sk_buff *);
+	int (*disconnect_request)(struct ircomm_cb *, struct sk_buff *, 
+				  struct ircomm_info *);	
+} call_t;
+
+struct ircomm_cb {
+	QUEUE   queue;
+	magic_t magic;
+
+	notify_t notify;
+	call_t   issue;
+
+	int state;
+	int line;            /* Which TTY line we are using */
+
+	struct tsap_cb *tsap;
+	struct lsap_cb *lsap;
+	
+	__u8 dlsap_sel;      /* Destination LSAP/TSAP selector */
+	__u8 slsap_sel;      /* Source LSAP/TSAP selector */
+
+	__u32 saddr;         /* Source device address (link we are using) */
+	__u32 daddr;         /* Destination device address */
+
+	int max_header_size; /* Header space we must reserve for each frame */
+	int max_data_size;   /* The amount of data we can fill in each frame */
+
+	LOCAL_FLOW flow_status; /* Used by ircomm_lmp */
+	int pkt_count;          /* Number of frames we have sent to IrLAP */
+
+	__u8 service_type;
+};
+
+extern hashbin_t *ircomm;
+
+struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line);
+int ircomm_close(struct ircomm_cb *self);
+
+int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *skb);
+void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb);
+void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb);
+int ircomm_control_request(struct ircomm_cb *self, struct sk_buff *skb);
+int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel, 
+			   __u32 saddr, __u32 daddr, struct sk_buff *skb,
+			   __u8 service_type);
+void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+			       struct ircomm_info *info);
+void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb,
+			    struct ircomm_info *info);
+int ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata);
+int ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata);
+void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+				  struct ircomm_info *info);
+void ircomm_flow_request(struct ircomm_cb *self, LOCAL_FLOW flow);
+
+extern inline int ircomm_is_connected(struct ircomm_cb *self)
+{
+	return self->state == IRCOMM_CONN;
+}
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/ircomm_event.h linux/include/net/irda/ircomm_event.h
--- v2.3.15/linux/include/net/irda/ircomm_event.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/ircomm_event.h	Mon Aug 30 10:30:24 1999
@@ -0,0 +1,84 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_event.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 23:51:13 1999
+ * Modified at:   Thu Jun 10 08:36:25 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_EVENT_H
+#define IRCOMM_EVENT_H
+
+typedef enum {
+        IRCOMM_IDLE,
+        IRCOMM_WAITI,
+        IRCOMM_WAITR,
+        IRCOMM_CONN,
+} IRCOMM_STATE;
+
+/* IrCOMM Events */
+typedef enum {
+        IRCOMM_CONNECT_REQUEST,
+        IRCOMM_CONNECT_RESPONSE,
+        IRCOMM_TTP_CONNECT_INDICATION,
+	IRCOMM_LMP_CONNECT_INDICATION,
+        IRCOMM_TTP_CONNECT_CONFIRM,
+	IRCOMM_LMP_CONNECT_CONFIRM,
+
+        IRCOMM_LMP_DISCONNECT_INDICATION,
+	IRCOMM_TTP_DISCONNECT_INDICATION,
+        IRCOMM_DISCONNECT_REQUEST,
+
+        IRCOMM_TTP_DATA_INDICATION,
+	IRCOMM_LMP_DATA_INDICATION,
+        IRCOMM_DATA_REQUEST,
+        IRCOMM_CONTROL_REQUEST,
+        IRCOMM_CONTROL_INDICATION,
+} IRCOMM_EVENT;
+
+/*
+ * Used for passing information through the state-machine
+ */
+struct ircomm_info {
+        __u32     saddr;               /* Source device address */
+        __u32     daddr;               /* Destination device address */
+        __u8      dlsap_sel;
+        LM_REASON reason;              /* Reason for disconnect */
+	__u32     max_data_size;
+	__u32     max_header_size;
+
+	struct qos_info *qos;
+};
+
+extern char *ircomm_state[];
+extern char *ircomm_event[];
+
+struct ircomm_cb;   /* Forward decl. */
+
+int ircomm_do_event(struct ircomm_cb *self, IRCOMM_EVENT event,
+		    struct sk_buff *skb, struct ircomm_info *info);
+void ircomm_next_state(struct ircomm_cb *self, IRCOMM_STATE state);
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/ircomm_lmp.h linux/include/net/irda/ircomm_lmp.h
--- v2.3.15/linux/include/net/irda/ircomm_lmp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/ircomm_lmp.h	Mon Aug 30 10:30:24 1999
@@ -0,0 +1,65 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_lmp.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Wed Jun  9 10:06:07 1999
+ * Modified at:   Fri Aug 13 07:32:32 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_LMP_H
+#define IRCOMM_LMP_H
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_event.h>
+
+int ircomm_open_lsap(struct ircomm_cb *self);
+int  ircomm_lmp_connect_request(struct ircomm_cb *self, 
+				struct sk_buff *userdata, 
+				struct ircomm_info *info);
+int  ircomm_lmp_connect_response(struct ircomm_cb *self, struct sk_buff *skb);
+int  ircomm_lmp_disconnect_request(struct ircomm_cb *self, 
+				   struct sk_buff *userdata, 
+				   struct ircomm_info *info);
+int  ircomm_lmp_data_request(struct ircomm_cb *self, struct sk_buff *skb, 
+			     int clen);
+int  ircomm_lmp_control_request(struct ircomm_cb *self, 
+			       struct sk_buff *userdata);
+int  ircomm_lmp_data_indication(void *instance, void *sap,
+				struct sk_buff *skb);
+void ircomm_lmp_connect_confirm(void *instance, void *sap,
+				struct qos_info *qos, 
+				__u32 max_sdu_size, 
+				__u8 max_header_size,
+				struct sk_buff *skb);
+void ircomm_lmp_connect_indication(void *instance, void *sap,
+				   struct qos_info *qos,
+				   __u32 max_sdu_size,
+				   __u8 max_header_size,
+				   struct sk_buff *skb);
+void ircomm_lmp_disconnect_indication(void *instance, void *sap, 
+				      LM_REASON reason,
+				      struct sk_buff *skb);
+
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/ircomm_param.h linux/include/net/irda/ircomm_param.h
--- v2.3.15/linux/include/net/irda/ircomm_param.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/ircomm_param.h	Mon Aug 30 10:30:24 1999
@@ -0,0 +1,150 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_param.h
+ * Version:       1.0
+ * Description:   Parameter handling for the IrCOMM protocol
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Jun  7 08:47:28 1999
+ * Modified at:   Wed Aug 25 13:46:33 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_PARAMS_H
+#define IRCOMM_PARAMS_H
+
+#include <net/irda/parameters.h>
+
+/* Parameters common to all service types */
+#define IRCOMM_SERVICE_TYPE     0x00
+#define IRCOMM_PORT_TYPE        0x01 /* Only used in LM-IAS */
+#define IRCOMM_PORT_NAME        0x02 /* Only used in LM-IAS */
+
+/* Parameters for both 3 wire and 9 wire */
+#define IRCOMM_DATA_RATE        0x10
+#define IRCOMM_DATA_FORMAT      0x11
+#define IRCOMM_FLOW_CONTROL     0x12
+#define IRCOMM_XON_XOFF         0x13
+#define IRCOMM_ENQ_ACK          0x14
+#define IRCOMM_LINE_STATUS      0x15
+#define IRCOMM_BREAK            0x16
+
+/* Parameters for 9 wire */
+#define IRCOMM_DTE              0x20
+#define IRCOMM_DCE              0x21
+#define IRCOMM_POLL             0x22
+
+/* Service type (details) */
+#define IRCOMM_3_WIRE_RAW       0x01
+#define IRCOMM_3_WIRE           0x02
+#define IRCOMM_9_WIRE           0x04
+#define IRCOMM_CENTRONICS       0x08
+
+/* Port type (details) */
+#define IRCOMM_SERIAL           0x00
+#define IRCOMM_PARALLEL         0x01
+
+/* Data format (details) */
+#define IRCOMM_WSIZE_5          0x00
+#define IRCOMM_WSIZE_6          0x01
+#define IRCOMM_WSIZE_7          0x02
+#define IRCOMM_WSIZE_8          0x03
+
+#define IRCOMM_1_STOP_BIT       0x00
+#define IRCOMM_2_STOP_BIT       0x04 /* 1.5 if char len 5 */
+
+#define IRCOMM_PARITY_DISABLE   0x00
+#define IRCOMM_PARITY_ENABLE    0x08
+
+#define IRCOMM_PARITY_ODD       0x00
+#define IRCOMM_PARITY_EVEN      0x10
+#define IRCOMM_PARITY_MARK      0x20
+#define IRCOMM_PARITY_SPACE     0x30
+
+/* Flow control */
+#define IRCOMM_XON_XOFF_IN      0x01
+#define IRCOMM_XON_XOFF_OUT     0x02
+#define IRCOMM_RTS_CTS_IN       0x04
+#define IRCOMM_RTS_CTS_OUT      0x08
+#define IRCOMM_DSR_DTR_IN       0x10
+#define IRCOMM_DSR_DTR_OUT      0x20
+#define IRCOMM_ENQ_ACK_IN       0x40
+#define IRCOMM_ENQ_ACK_OUT      0x80
+
+/* Line status */
+#define IRCOMM_OVERRUN_ERROR    0x02
+#define IRCOMM_PARITY_ERROR     0x04
+#define IRCOMM_FRAMING_ERROR    0x08
+
+/* DTE (Data terminal equipment) line settings */
+#define IRCOMM_DELTA_DTR        0x01
+#define IRCOMM_DELTA_RTS        0x02
+#define IRCOMM_DTR              0x04
+#define IRCOMM_RTS              0x08
+
+/* DCE (Data communications equipment) line settings */
+#define IRCOMM_DELTA_CTS        0x01  /* Clear to send has changed */
+#define IRCOMM_DELTA_DSR        0x02  /* Data set ready has changed */
+#define IRCOMM_DELTA_RI         0x04  /* Ring indicator has changed */
+#define IRCOMM_DELTA_CD         0x08  /* Carrier detect has changed */
+#define IRCOMM_CTS              0x10  /* Clear to send is high */
+#define IRCOMM_DSR              0x20  /* Data set ready is high */
+#define IRCOMM_RI               0x40  /* Ring indicator is high */
+#define IRCOMM_CD               0x80  /* Carrier detect is high */
+#define IRCOMM_DCE_DELTA_ANY    0x0f
+
+/*
+ * Parameter state
+ */
+struct ircomm_params {
+	/* General control params */
+	__u8  service_type;
+	__u8  port_type;
+	char  port_name[32];
+
+	/* Control params for 3- and 9-wire service type */
+	__u32 data_rate;         /* Data rate in bps */
+	__u8  data_format;
+	__u8  flow_control;
+	char  xonxoff[2];
+	char  enqack[2];
+	__u8  line_status;
+	__u8  _break;
+
+	__u8  null_modem;
+
+	/* Control params for 9-wire service type */
+	__u8 dte;
+	__u8 dce;
+	__u8 poll;
+
+	/* Control params for Centronics service type */
+};
+
+struct ircomm_tty_cb; /* Forward decl. */
+
+int ircomm_param_flush(struct ircomm_tty_cb *self);
+int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush);
+
+extern pi_param_info_t ircomm_param_info;
+
+#endif /* IRCOMM_PARAMS_H */
+
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/ircomm_ttp.h linux/include/net/irda/ircomm_ttp.h
--- v2.3.15/linux/include/net/irda/ircomm_ttp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/ircomm_ttp.h	Mon Aug 30 10:30:24 1999
@@ -0,0 +1,70 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_ttp.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Wed Jun  9 10:06:07 1999
+ * Modified at:   Fri Aug 13 07:32:22 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_TTP_H
+#define IRCOMM_TTP_H
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_event.h>
+
+int  ircomm_open_tsap(struct ircomm_cb *self);
+int  ircomm_ttp_connect_request(struct ircomm_cb *self, 
+				struct sk_buff *userdata, 
+				struct ircomm_info *info);
+int  ircomm_ttp_connect_response(struct ircomm_cb *self, struct sk_buff *skb);
+int  ircomm_ttp_disconnect_request(struct ircomm_cb *self, 
+				   struct sk_buff *userdata, 
+				   struct ircomm_info *info);
+int  ircomm_ttp_data_request(struct ircomm_cb *self, struct sk_buff *skb, 
+			     int clen);
+int  ircomm_ttp_control_request(struct ircomm_cb *self, 
+			       struct sk_buff *userdata);
+int  ircomm_ttp_data_indication(void *instance, void *sap,
+				struct sk_buff *skb);
+void ircomm_ttp_connect_confirm(void *instance, void *sap,
+				struct qos_info *qos, 
+				__u32 max_sdu_size, 
+				__u8 max_header_size,
+				struct sk_buff *skb);
+void ircomm_ttp_connect_indication(void *instance, void *sap,
+				   struct qos_info *qos,
+				   __u32 max_sdu_size,
+				   __u8 max_header_size,
+				   struct sk_buff *skb);
+void ircomm_ttp_disconnect_indication(void *instance, void *sap, 
+				      LM_REASON reason,
+				      struct sk_buff *skb);
+void ircomm_ttp_flow_indication(void *instance, void *sap, LOCAL_FLOW cmd);
+
+#endif
+
+
+
+
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/ircomm_tty.h linux/include/net/irda/ircomm_tty.h
--- v2.3.15/linux/include/net/irda/ircomm_tty.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/ircomm_tty.h	Mon Aug 30 10:30:24 1999
@@ -0,0 +1,112 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_tty.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 23:24:22 1999
+ * Modified at:   Fri Aug 13 07:31:35 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_TTY_H
+#define IRCOMM_TTY_H
+
+#include <linux/serial.h>
+
+#include <net/irda/irias_object.h>
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_param.h>
+
+#define IRCOMM_TTY_PORTS 32
+#define IRCOMM_TTY_MAGIC 0x3432
+#define IRCOMM_TTY_MAJOR 161
+#define IRCOMM_TTY_MINOR 0
+
+/*
+ * IrCOMM TTY driver state
+ */
+struct ircomm_tty_cb {
+	QUEUE   queue;
+	magic_t magic;
+
+	int state;
+
+	struct tty_struct *tty;
+	struct ircomm_cb *ircomm;
+
+	struct sk_buff_head tx_queue;  /* Frames to be transmitted */
+	struct sk_buff *tx_skb;
+	struct sk_buff *ctrl_skb;
+
+	/* Parameters */
+	struct ircomm_params session;
+
+	__u8 service_type;
+
+	int line;
+	int flags;
+
+	__u8 dlsap_sel;
+	__u8 slsap_sel;
+
+	__u32 saddr;
+	__u32 daddr;
+
+	__u32 max_data_size;
+	__u32 max_header_size;
+
+	struct ias_object* obj;
+	int skey;
+	int ckey;
+
+	struct termios	  normal_termios;
+	struct termios	  callout_termios;
+
+	wait_queue_head_t open_wait;
+	struct timer_list watchdog_timer;
+	struct tq_struct  tqueue;
+
+	long pgrp;		/* pgrp of opening process */
+	int  open_count;
+	int  blocked_open;	/* # of blocked opens */
+};
+
+void ircomm_tty_start(struct tty_struct *tty);
+void ircomm_tty_stop(struct tty_struct *tty);
+void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self);
+
+extern void ircomm_tty_change_speed(struct ircomm_tty_cb *self);
+extern int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file, 
+			    unsigned int cmd, unsigned long arg);
+extern void ircomm_tty_set_termios(struct tty_struct *tty, 
+				   struct termios *old_termios);
+extern hashbin_t *ircomm_tty;
+
+#endif
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/ircomm_tty_attach.h linux/include/net/irda/ircomm_tty_attach.h
--- v2.3.15/linux/include/net/irda/ircomm_tty_attach.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/ircomm_tty_attach.h	Mon Aug 30 10:30:24 1999
@@ -0,0 +1,87 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_tty_attach.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Wed Jun  9 15:55:18 1999
+ * Modified at:   Mon Jul  5 12:56:56 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRCOMM_TTY_ATTACH_H
+#define IRCOMM_TTY_ATTACH_H
+
+#include <net/irda/ircomm_tty.h>
+
+typedef enum {
+        IRCOMM_TTY_IDLE,
+	IRCOMM_TTY_SEARCH,
+        IRCOMM_TTY_QUERY_PARAMETERS,
+	IRCOMM_TTY_QUERY_LSAP_SEL,
+	IRCOMM_TTY_SETUP,
+        IRCOMM_TTY_READY,
+} IRCOMM_TTY_STATE;
+
+/* IrCOMM TTY Events */
+typedef enum {
+	IRCOMM_TTY_ATTACH_CABLE,
+	IRCOMM_TTY_DETACH_CABLE,
+	IRCOMM_TTY_DATA_REQUEST,
+	IRCOMM_TTY_DATA_INDICATION,
+	IRCOMM_TTY_DISCOVERY_REQUEST,
+	IRCOMM_TTY_DISCOVERY_INDICATION,
+	IRCOMM_TTY_CONNECT_CONFIRM,
+	IRCOMM_TTY_CONNECT_INDICATION,
+	IRCOMM_TTY_WD_TIMER_EXPIRED,
+	IRCOMM_TTY_GOT_PARAMETERS,
+	IRCOMM_TTY_GOT_LSAPSEL,
+} IRCOMM_TTY_EVENT;
+
+/* Used for passing information through the state-machine */
+struct ircomm_tty_info {
+        __u32     saddr;               /* Source device address */
+        __u32     daddr;               /* Destination device address */
+        __u8      dlsap_sel;
+};
+
+extern char *ircomm_state[];
+extern char *ircomm_event[];
+
+int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
+			struct sk_buff *skb, struct ircomm_tty_info *info);
+void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_STATE state);
+
+
+int  ircomm_tty_attach_cable(struct ircomm_tty_cb *self);
+void ircomm_tty_detach_cable(struct ircomm_tty_cb *self);
+void ircomm_tty_connect_confirm(void *instance, void *sap, 
+				struct qos_info *qos, 
+				__u32 max_sdu_size, 
+				__u8 max_header_size, 
+				struct sk_buff *skb);
+void ircomm_tty_connect_indication(void *instance, void *sap, 
+				   struct qos_info *qos, 
+				   __u32 max_sdu_size,
+				   __u8 max_header_size, 
+				   struct sk_buff *skb);
+#endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irda.h linux/include/net/irda/irda.h
--- v2.3.15/linux/include/net/irda/irda.h	Wed Aug 18 16:44:31 1999
+++ linux/include/net/irda/irda.h	Tue Aug 31 16:13:00 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Mon May 10 09:51:13 1999
+ * Modified at:   Thu Jul  8 12:53:35 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -40,6 +40,10 @@
 #define FALSE 0
 #endif
 
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
 #define ALIGN __attribute__((aligned))
 #define PACK __attribute__((packed))
 
@@ -51,7 +55,7 @@
 /* use 0 for production, 1 for verification, >2 for debug */
 #define IRDA_DEBUG_LEVEL 0
 
-#define DEBUG(n, args...) if (irda_debug >= (n)) printk(KERN_DEBUG args)
+#define DEBUG(n, args...) (irda_debug >= (n)) ? (printk(KERN_DEBUG args)) : 0
 #define ASSERT(expr, func) \
 if(!(expr)) { \
         printk( "Assertion failed! %s,%s,%s,line=%d\n",\
@@ -66,12 +70,14 @@
 #define MESSAGE(args...) printk(KERN_INFO args)
 #define ERROR(args...)   printk(KERN_ERR args)
 
-#define MSECS_TO_JIFFIES(ms) (ms*HZ/1000)
+#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000)
 
 /*
  *  Magic numbers used by Linux/IR. Random numbers which must be unique to 
  *  give the best protection
  */
+typedef __u32 magic_t;
+
 #define IRTTY_MAGIC        0x2357
 #define LAP_MAGIC          0x1357
 #define LMP_MAGIC          0x4321
@@ -141,6 +147,16 @@
 	__u8  byte[2];
 } __u16_host_order;
 
+/* Per-packet information we need to hide inside sk_buff */
+struct irda_skb_cb {
+	magic_t magic;     /* Be sure that we can trust the information */
+	int     mtt;       /* minimum turn around time */
+	int     xbofs;     /* number of xbofs required, used by SIR mode */
+	int     line;      /* Used by IrCOMM in IrLPT mode */
+	void    *instance; /* Used by IrTTP */
+	void (*destructor)(struct sk_buff *skb); /* Used for flow control */
+};
+
 /*
  *  Information monitored by some layers
  */
@@ -222,7 +238,7 @@
 /*
  *  Notify structure used between transport and link management layers
  */
-struct notify_t {
+typedef struct {
 	int (*data_indication)(void *priv, void *sap, struct sk_buff *skb);
 	int (*udata_indication)(void *priv, void *sap, struct sk_buff *skb);
 	void (*connect_confirm)(void *instance, void *sap, 
@@ -236,7 +252,7 @@
 	void (*flow_indication)(void *instance, void *sap, LOCAL_FLOW flow);
 	void *instance; /* Layer instance pointer */
 	char name[16];  /* Name of layer */
-};
+} notify_t;
 
 #define NOTIFY_MAX_NAME 16
 
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h
--- v2.3.15/linux/include/net/irda/irda_device.h	Wed Aug 18 11:38:47 1999
+++ linux/include/net/irda/irda_device.h	Mon Aug 30 10:30:24 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Apr 14 12:41:42 1998
- * Modified at:   Wed May 19 08:44:48 1999
+ * Modified at:   Tue Aug 24 13:58:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -75,7 +75,7 @@
         int irqflags;         /* interrupt flags (ie, SA_SHIRQ|SA_INTERRUPT) */
 	int direction;        /* Link direction, used by some FIR drivers */
 
-	int baudrate;         /* Currently used baudrate */
+	__u32 baudrate;       /* Currently used baudrate */
 	int dongle_id;        /* Dongle or transceiver currently used */
 };
 
@@ -102,17 +102,17 @@
  * stuff from IrDA port implementations.
  */
 struct irda_device {
-	QUEUE q;               /* Must be first */
+	QUEUE   q;             /* Must be first */
+        magic_t magic;	       /* Our magic bullet */
 
-        int  magic;	       /* Our magic bullet */
 	char name[16];         /* Name of device "irda0" */
 	char description[32];  /* Something like "irda0 <-> ttyS0" */
 
-	struct irlap_cb *irlap; /* The link layer we are connected to  */
-	struct net_device netdev;   /* Yes! we are some kind of netdevice */
+	struct irlap_cb *irlap;   /* The link layer we are connected to  */
+	struct net_device netdev; /* Yes! we are some kind of netdevice */
 	struct enet_statistics stats;
 
- 	int flags;            /* Interface flags (see defs above) */
+ 	__u32 flags;          /* Interface flags (see defs above) */
 
  	void *priv;           /* Pointer to low level implementation */
 
@@ -130,11 +130,16 @@
 	int media_busy;
 	struct timer_list media_busy_timer;
 
-	/* Callbacks for driver specific implementation */
-        void (*change_speed)(struct irda_device *idev, int baud);
+	int raw_mode;
+
+	/* Callbacks to driver specific implementations */
+        void (*change_speed)(struct irda_device *idev, __u32 speed);
  	int  (*is_receiving)(struct irda_device *);    /* receiving? */
 	void (*set_dtr_rts)(struct irda_device *idev, int dtr, int rts);
+	void (*set_raw_mode)(struct irda_device *dev, int mode);
 	int  (*raw_write)(struct irda_device *idev, __u8 *buf, int len);
+	int  (*raw_read)(struct irda_device *idev, __u8 *buf, int len, 
+			 int timeout);
 	void (*wait_until_sent)(struct irda_device *);
 	void (*set_caddr)(struct irda_device *);      /* Set connection addr */
 };
@@ -155,15 +160,18 @@
 inline void irda_device_change_speed(struct irda_device *, int);
 
 inline struct qos_info *irda_device_get_qos(struct irda_device *self);
-int irda_device_txqueue_empty(struct irda_device *self);
+int  irda_device_txqueue_empty(struct irda_device *self);
 void irda_device_init_dongle(struct irda_device *self, int type);
 void irda_device_unregister_dongle(struct dongle *dongle);
-int irda_device_register_dongle(struct dongle *dongle);
-
-int irda_device_setup(struct net_device *dev);
+int  irda_device_register_dongle(struct dongle *dongle);
+int  irda_device_set_raw_mode(struct irda_device* self, int status);
+int  irda_device_setup(struct net_device *dev);
 
 void setup_dma(int channel, char *buffer, int count, int mode);
 
+int irda_device_net_open(struct net_device *dev);
+int irda_device_net_close(struct net_device *dev);
+
 /*
  * Function irda_get_mtt (skb)
  *
@@ -174,10 +182,10 @@
 {
 	__u16 mtt;
 
-	if (((struct irlap_skb_cb *)(skb->cb))->magic != LAP_MAGIC)
+	if (((struct irda_skb_cb *)(skb->cb))->magic != LAP_MAGIC)
 		mtt = 10000;
 	else
-		mtt = ((struct irlap_skb_cb *)(skb->cb))->mtt;
+		mtt = ((struct irda_skb_cb *)(skb->cb))->mtt;
 
 	ASSERT(mtt <= 10000, return 10000;);
 	
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/iriap.h linux/include/net/irda/iriap.h
--- v2.3.15/linux/include/net/irda/iriap.h	Sun May 30 10:27:04 1999
+++ linux/include/net/irda/iriap.h	Mon Aug 30 10:30:24 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Sun May  9 10:56:57 1999
+ * Modified at:   Thu Jul  1 10:10:42 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -57,9 +57,9 @@
 				 struct ias_value *value, void *priv);
 
 struct iriap_cb {
-	QUEUE queue; /* Must be first */
-	
-	int          magic;  /* Magic cookie */
+	QUEUE   queue;  /* Must be first */	
+	magic_t magic;  /* Magic cookie */
+
 	int          mode;   /* Client or server */
 
 	__u32        saddr;
@@ -88,9 +88,9 @@
 
 int  iriap_init(void);
 void iriap_cleanup(void);
-void iriap_getvaluebyclass_request( char *name, char *attr, 
-				    __u32 saddr, __u32 daddr,
-				    CONFIRM_CALLBACK callback, void *priv);
+void iriap_getvaluebyclass_request(char *name, char *attr, 
+				   __u32 saddr, __u32 daddr,
+				   CONFIRM_CALLBACK callback, void *priv);
 void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb);
 
 void iriap_send_ack( struct iriap_cb *self);
@@ -98,13 +98,13 @@
 
 void iriap_register_server(void);
 
-void iriap_watchdog_timer_expired( unsigned long data);
+void iriap_watchdog_timer_expired(void *data);
 
-static inline void iriap_start_watchdog_timer( struct iriap_cb *self, 
-					       int timeout) 
+static inline void iriap_start_watchdog_timer(struct iriap_cb *self, 
+					      int timeout) 
 {
-	irda_start_timer( &self->watchdog_timer, timeout, 
-			  (unsigned long) self, iriap_watchdog_timer_expired);
+	irda_start_timer(&self->watchdog_timer, timeout, self, 
+			 iriap_watchdog_timer_expired);
 }
 
 #endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irias_object.h linux/include/net/irda/irias_object.h
--- v2.3.15/linux/include/net/irda/irias_object.h	Sun Mar  7 15:26:43 1999
+++ linux/include/net/irda/irias_object.h	Mon Aug 30 10:30:24 1999
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct  1 22:49:50 1998
- * Modified at:   Wed Feb  3 10:38:02 1999
+ * Modified at:   Thu Jul  1 11:37:15 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -25,6 +25,7 @@
 #ifndef LM_IAS_OBJECT_H
 #define LM_IAS_OBJECT_H
 
+#include <net/irda/irda.h>
 #include <net/irda/irqueue.h>
 
 /* LM-IAS Attribute types */
@@ -37,8 +38,8 @@
  *  LM-IAS Object
  */
 struct ias_object {
-	QUEUE queue;     /* Must be first! */
-	int magic;
+	QUEUE   queue;     /* Must be first! */
+	magic_t magic;
 	
 	char  *name;
 	int   id;
@@ -72,12 +73,12 @@
 	struct ias_value *value; /* Attribute value */
 };
 
-char *strdup( char *str);
+char *strdup(char *str);
 
-struct ias_object *irias_new_object( char *name, int id);
-void irias_insert_object( struct ias_object *obj);
-void __irias_delete_object( struct ias_object *obj);
-void irias_delete_object( char *name);
+struct ias_object *irias_new_object(char *name, int id);
+void irias_insert_object(struct ias_object *obj);
+int  irias_delete_object(struct ias_object *obj);
+void __irias_delete_object(struct ias_object *obj);
 
 void irias_add_integer_attrib(struct ias_object *obj, char *name, int value);
 void irias_add_string_attrib(struct ias_object *obj, char *name, char *value);
@@ -85,13 +86,13 @@
 			     int len);
 int irias_object_change_attribute(char *obj_name, char *attrib_name, 
 				  struct ias_value *new_value);
-struct ias_object *irias_find_object( char *name);
-struct ias_attrib *irias_find_attrib( struct ias_object *obj, char *name);
+struct ias_object *irias_find_object(char *name);
+struct ias_attrib *irias_find_attrib(struct ias_object *obj, char *name);
 
-struct ias_value *irias_new_string_value( char *string);
-struct ias_value *irias_new_integer_value( int integer);
-struct ias_value *irias_new_octseq_value( __u8 *octseq , int len);
-void irias_delete_value( struct ias_value *value);
+struct ias_value *irias_new_string_value(char *string);
+struct ias_value *irias_new_integer_value(int integer);
+struct ias_value *irias_new_octseq_value(__u8 *octseq , int len);
+void irias_delete_value(struct ias_value *value);
 
 extern struct ias_value missing;
 extern hashbin_t *objects;
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irlap.h linux/include/net/irda/irlap.h
--- v2.3.15/linux/include/net/irda/irlap.h	Wed Aug 18 11:38:47 1999
+++ linux/include/net/irda/irlap.h	Mon Aug 30 10:30:24 1999
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sun May  9 11:38:18 1999
+ * Modified at:   Thu Jul  8 21:22:50 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -31,6 +32,7 @@
 #include <linux/netdevice.h>
 #include <linux/ppp_defs.h>
 #include <linux/ppp-comp.h>
+#include <linux/timer.h>
 
 #include <net/irda/irlap_event.h>
 
@@ -54,7 +56,7 @@
 #define XID_FORMAT 0x01       /* Discovery XID format */
 
 #define LAP_WINDOW_SIZE 8
-#define MAX_CONNECTIONS 1
+#define LAP_MAX_QUEUE  10
 
 #define NR_EXPECTED     1
 #define NR_UNEXPECTED   0
@@ -85,9 +87,8 @@
 
 /* Main structure of IrLAP */
 struct irlap_cb {
-	QUEUE q; /* Must be first */
-
-	int magic;
+	QUEUE   q;     /* Must be first */
+	magic_t magic;
 
 	struct irda_device *irdev;
 	struct net_device      *netdev;
@@ -138,12 +139,11 @@
 
 	__u8    vs;           /* Next frame to be sent */
 	__u8    vr;           /* Next frame to be received */
-/* 	int     tmp; */
 	__u8    va;           /* Last frame acked */
  	int     window;       /* Nr of I-frames allowed to send */
 	int     window_size;  /* Current negotiated window size */
-	int     window_bytes; /* Number of bytes allowed to send */
-	int     bytes_left;   /* Number of bytes allowed to transmit */
+	__u32   window_bytes; /* Number of bytes allowed to send */
+	__u32   bytes_left;   /* Number of bytes allowed to transmit */
 
 	struct sk_buff_head wx_list;
 
@@ -161,7 +161,7 @@
 	struct qos_info qos_tx;    /* QoS requested by peer */
 	struct qos_info qos_rx;    /* QoS requested by self */
 
-	struct notify_t notify; /* Callbacks to IrLMP */
+	notify_t notify; /* Callbacks to IrLMP */
 
 	int    mtt_required;  /* Minumum turnaround time required */
 	int    xbofs_delay;   /* Nr of XBOF's used to MTT */
@@ -180,55 +180,60 @@
 /* 
  *  Function prototypes 
  */
+int irlap_init(void);
+void irlap_cleanup(void);
 
-int irlap_init( void);
-void irlap_cleanup( void);
-
-struct irlap_cb *irlap_open( struct irda_device *dev);
-void irlap_close( struct irlap_cb *self);
+struct irlap_cb *irlap_open(struct irda_device *dev);
+void irlap_close(struct irlap_cb *self);
 
-void irlap_connect_request( struct irlap_cb *self, __u32 daddr, 
-			    struct qos_info *qos, int sniff);
-void irlap_connect_response( struct irlap_cb *self, struct sk_buff *skb);
-void irlap_connect_indication( struct irlap_cb *self, struct sk_buff *skb);
-void irlap_connect_confirm( struct irlap_cb *, struct sk_buff *skb);
+void irlap_connect_request(struct irlap_cb *self, __u32 daddr, 
+			   struct qos_info *qos, int sniff);
+void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb);
+void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb);
+void irlap_connect_confirm(struct irlap_cb *, struct sk_buff *skb);
 
-inline void irlap_data_indication( struct irlap_cb *, struct sk_buff *);
-inline void irlap_unit_data_indication( struct irlap_cb *, struct sk_buff *);
-inline void irlap_data_request( struct irlap_cb *, struct sk_buff *, 
-				int reliable);
+inline void irlap_data_indication(struct irlap_cb *, struct sk_buff *);
+inline void irlap_unit_data_indication(struct irlap_cb *, struct sk_buff *);
+inline void irlap_data_request(struct irlap_cb *, struct sk_buff *, 
+			       int reliable);
 
-void irlap_disconnect_request( struct irlap_cb *);
-void irlap_disconnect_indication( struct irlap_cb *, LAP_REASON reason);
+void irlap_disconnect_request(struct irlap_cb *);
+void irlap_disconnect_indication(struct irlap_cb *, LAP_REASON reason);
 
-void irlap_status_indication( int quality_of_link);
+void irlap_status_indication(int quality_of_link);
 
-void irlap_test_request( __u8 *info, int len);
+void irlap_test_request(__u8 *info, int len);
 
 void irlap_discovery_request(struct irlap_cb *, discovery_t *discovery);
 void irlap_discovery_confirm(struct irlap_cb *, hashbin_t *discovery_log);
 void irlap_discovery_indication(struct irlap_cb *, discovery_t *discovery);
 
-void irlap_reset_indication( struct irlap_cb *self);
+void irlap_reset_indication(struct irlap_cb *self);
 void irlap_reset_confirm(void);
 
-void irlap_update_nr_received( struct irlap_cb *, int nr);
-int irlap_validate_nr_received( struct irlap_cb *, int nr);
-int irlap_validate_ns_received( struct irlap_cb *, int ns);
+void irlap_update_nr_received(struct irlap_cb *, int nr);
+int irlap_validate_nr_received(struct irlap_cb *, int nr);
+int irlap_validate_ns_received(struct irlap_cb *, int ns);
 
-int  irlap_generate_rand_time_slot( int S, int s);
-void irlap_initiate_connection_state( struct irlap_cb *);
+int  irlap_generate_rand_time_slot(int S, int s);
+void irlap_initiate_connection_state(struct irlap_cb *);
 void irlap_flush_all_queues(struct irlap_cb *);
-void irlap_change_speed(struct irlap_cb *, int);
+void irlap_change_speed(struct irlap_cb *self, __u32 speed);
 void irlap_wait_min_turn_around(struct irlap_cb *, struct qos_info *);
 
 void irlap_init_qos_capabilities(struct irlap_cb *, struct qos_info *);
 void irlap_apply_default_connection_parameters(struct irlap_cb *self);
 void irlap_apply_connection_parameters(struct irlap_cb *, struct qos_info *);
+void irlap_set_local_busy(struct irlap_cb *self, int status);
 
 extern inline __u8 irlap_get_header_size(struct irlap_cb *self)
 {
 	return 2;
+}
+
+extern inline int irlap_get_tx_queue_len(struct irlap_cb *self)
+{
+	return skb_queue_len(&self->tx_list);
 }
 
 #endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irlap_event.h linux/include/net/irda/irlap_event.h
--- v2.3.15/linux/include/net/irda/irlap_event.h	Thu Apr 15 05:42:41 1999
+++ linux/include/net/irda/irlap_event.h	Mon Aug 30 10:30:24 1999
@@ -1,25 +1,33 @@
 /*********************************************************************
  *                
+ *                
  * Filename:      irlap_event.h
  * Version:       0.1
  * Description:   
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Tue Apr  6 17:10:38 1999
+ * Modified at:   Mon Aug 16 10:16:12 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
  ********************************************************************/
 
 #ifndef IRLAP_EVENT_H
@@ -115,9 +123,11 @@
 
 extern const char *irlap_state[];
 
-void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, 
-		     struct sk_buff *skb, struct irlap_info *info);
-void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state);
-void irlap_print_event( IRLAP_EVENT event);
+void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event, 
+		    struct sk_buff *skb, struct irlap_info *info);
+void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state);
+void irlap_print_event(IRLAP_EVENT event);
+
+extern int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb);
 
 #endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irlap_frame.h linux/include/net/irda/irlap_frame.h
--- v2.3.15/linux/include/net/irda/irlap_frame.h	Sat Apr 24 17:50:06 1999
+++ linux/include/net/irda/irlap_frame.h	Mon Aug 30 10:30:24 1999
@@ -2,24 +2,31 @@
  *                
  * Filename:      irlap_frame.h
  * Version:       0.9
- * Description:   Build and transmit IrLAP frames
+ * Description:   IrLAP frame declarations
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Fri Apr 23 09:33:55 1999
+ * Modified at:   Mon Aug 23 09:38:46 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997-1999 Dag Brattli <dagb@cs.uit.no>,
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
  ********************************************************************/
 
 #ifndef IRLAP_FRAME_H
@@ -73,7 +80,6 @@
 	__u8  flags; /* Discovery flags */
 	__u8  slotnr;
 	__u8  version;
-	__u8  discovery_info[0];
 } PACK;
 
 struct test_frame {
@@ -81,7 +87,6 @@
 	__u8 control;
 	__u32 saddr;         /* Source device address */
 	__u32 daddr;         /* Destination device address */
-	__u8 info[0];        /* Information */
 } PACK;
 
 struct ua_frame {
@@ -90,13 +95,11 @@
 
 	__u32 saddr; /* Source device address */
 	__u32 daddr; /* Dest device address */
-	__u8  params[0];
 } PACK;
 	
 struct i_frame {
 	__u8 caddr;
 	__u8 control;
-	__u8 data[0];
 } PACK;
 
 struct snrm_frame {
@@ -105,37 +108,30 @@
 	__u32 saddr;
 	__u32 daddr;
 	__u8  ncaddr;
-	__u8  params[0];
 } PACK;
 
-/* Per-packet information we need to hide inside sk_buff */
-struct irlap_skb_cb {
-	int magic; /* Be sure that we can trust the information */
-	int mtt;   /* minimum turn around time */
-	int xbofs; /* number of xbofs required */
-	int vs;    /* next frame to send */
-	int vr;    /* next frame to receive */
-};
-
-void irlap_send_discovery_xid_frame( struct irlap_cb *, int S, __u8 s, 
-				     __u8 command, discovery_t *discovery);
-void irlap_send_snrm_frame( struct irlap_cb *, struct qos_info *);
+void irlap_send_discovery_xid_frame(struct irlap_cb *, int S, __u8 s, 
+				    __u8 command, discovery_t *discovery);
+void irlap_send_snrm_frame(struct irlap_cb *, struct qos_info *);
 void irlap_send_test_frame(struct irlap_cb *self, __u32 daddr, 
 			   struct sk_buff *cmd);
-void irlap_send_ua_response_frame( struct irlap_cb *, struct qos_info *);
-void irlap_send_ui_frame( struct irlap_cb *self, struct sk_buff *skb,
-			  int command);
-void irlap_send_dm_frame( struct irlap_cb *);
-void irlap_send_disc_frame( struct irlap_cb *);
-void irlap_send_rr_frame( struct irlap_cb *, int command);
-
-void irlap_send_data_primary( struct irlap_cb *, struct sk_buff *);
-void irlap_send_data_primary_poll( struct irlap_cb *, struct sk_buff *);
-void irlap_send_data_secondary( struct irlap_cb *, struct sk_buff *);
-void irlap_send_data_secondary_final( struct irlap_cb *, struct sk_buff *);
-void irlap_resend_rejected_frames( struct irlap_cb *, int command);
+void irlap_send_ua_response_frame(struct irlap_cb *, struct qos_info *);
+void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
+			 int command);
+void irlap_send_dm_frame(struct irlap_cb *);
+void irlap_send_disc_frame(struct irlap_cb *);
+void irlap_send_rr_frame(struct irlap_cb *, int command);
+
+void irlap_send_data_primary(struct irlap_cb *, struct sk_buff *);
+void irlap_send_data_primary_poll(struct irlap_cb *, struct sk_buff *);
+void irlap_send_data_secondary(struct irlap_cb *, struct sk_buff *);
+void irlap_send_data_secondary_final(struct irlap_cb *, struct sk_buff *);
+void irlap_resend_rejected_frames(struct irlap_cb *, int command);
+
+void irlap_send_i_frame(struct irlap_cb *, struct sk_buff *, int command);
+void irlap_send_ui_frame(struct irlap_cb *, struct sk_buff *, int command);
 
-void irlap_send_i_frame( struct irlap_cb *, struct sk_buff *, int command);
-void irlap_send_ui_frame( struct irlap_cb *, struct sk_buff *, int command);
+extern int irlap_insert_qos_negotiation_params(struct irlap_cb *self, 
+					       struct sk_buff *skb);
 
 #endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irlmp.h linux/include/net/irda/irlmp.h
--- v2.3.15/linux/include/net/irda/irlmp.h	Sun May 30 10:27:04 1999
+++ linux/include/net/irda/irlmp.h	Mon Aug 30 10:30:24 1999
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Sun May  9 11:01:34 1999
+ * Modified at:   Thu Jul  8 13:44:20 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -97,9 +98,8 @@
  *  Information about each logical LSAP connection
  */
 struct lsap_cb {
-	QUEUE queue;      /* Must be first */
-
-	int   magic;
+	QUEUE   queue;      /* Must be first */
+	magic_t magic;
 
 	int   connected;
 	int   persistent;
@@ -114,7 +114,7 @@
 	struct timer_list watchdog_timer;
 
 	IRLMP_STATE     lsap_state;  /* Connection state */
-	struct notify_t notify;      /* Indication/Confirm entry points */
+	notify_t notify;             /* Indication/Confirm entry points */
 	struct qos_info qos;         /* QoS for this connection */
 
 	struct lap_cb *lap; /* Pointer to LAP connection structure */
@@ -124,9 +124,9 @@
  *  Information about each registred IrLAP layer
  */
 struct lap_cb {
-	QUEUE queue;      /* Must be first */
+	QUEUE   queue;      /* Must be first */
+	magic_t magic;
 
-	int magic;
 	int reason;    /* LAP disconnect reason */
 
 	IRLMP_STATE lap_state;
@@ -157,7 +157,7 @@
  *  Main structure for IrLMP
  */
 struct irlmp_cb {
-	int magic;
+	magic_t magic;
 
 	__u8 conflict_flag;
 	
@@ -187,7 +187,7 @@
 /* Prototype declarations */
 int  irlmp_init(void);
 void irlmp_cleanup(void);
-struct lsap_cb *irlmp_open_lsap( __u8 slsap, struct notify_t *notify);
+struct lsap_cb *irlmp_open_lsap( __u8 slsap, notify_t *notify);
 void irlmp_close_lsap( struct lsap_cb *self);
 
 __u16 irlmp_service_to_hint(int service);
@@ -199,27 +199,27 @@
 int irlmp_update_client(__u32 handle, __u16 hint_mask, 
 			DISCOVERY_CALLBACK1, DISCOVERY_CALLBACK2);
 
-void irlmp_register_link(struct irlap_cb *, __u32 saddr, struct notify_t *);
+void irlmp_register_link(struct irlap_cb *, __u32 saddr, notify_t *);
 void irlmp_unregister_link(__u32 saddr);
 
 int  irlmp_connect_request(struct lsap_cb *, __u8 dlsap_sel, 
 			   __u32 saddr, __u32 daddr,
 			   struct qos_info *, struct sk_buff *);
 void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb);
-void irlmp_connect_response(struct lsap_cb *, struct sk_buff *);
+int  irlmp_connect_response(struct lsap_cb *, struct sk_buff *);
 void irlmp_connect_confirm(struct lsap_cb *, struct sk_buff *);
 struct lsap_cb *irlmp_dup(struct lsap_cb *self, void *instance);
 
 void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason, 
 				 struct sk_buff *userdata);
-void irlmp_disconnect_request(struct lsap_cb *, struct sk_buff *userdata);
+int  irlmp_disconnect_request(struct lsap_cb *, struct sk_buff *userdata);
 
 void irlmp_discovery_confirm(hashbin_t *discovery_log);
 void irlmp_discovery_request(int nslots);
 void irlmp_do_discovery(int nslots);
 discovery_t *irlmp_get_discovery_response(void);
 
-void irlmp_data_request(struct lsap_cb *, struct sk_buff *);
+int irlmp_data_request(struct lsap_cb *, struct sk_buff *);
 inline void irlmp_udata_request(struct lsap_cb *, struct sk_buff *);
 inline void irlmp_data_indication(struct lsap_cb *, struct sk_buff *);
 inline void irlmp_udata_indication(struct lsap_cb *, struct sk_buff *);
@@ -235,10 +235,20 @@
 __u32 irlmp_get_daddr(struct lsap_cb *self);
 
 extern char *lmp_reasons[];
+extern int sysctl_discovery_timeout;
 extern int sysctl_discovery_slots;
 extern int sysctl_discovery;
 extern struct irlmp_cb *irlmp;
 
 static inline hashbin_t *irlmp_get_cachelog(void) { return irlmp->cachelog; }
+
+static inline int irlmp_get_lap_tx_queue_len(struct lsap_cb *self)
+{
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->lap != NULL, return 0;);
+	ASSERT(self->lap->irlap != NULL, return 0;);
+
+	return irlap_get_tx_queue_len(self->lap->irlap);
+}
 
 #endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irlmp_event.h linux/include/net/irda/irlmp_event.h
--- v2.3.15/linux/include/net/irda/irlmp_event.h	Thu Apr 15 05:42:41 1999
+++ linux/include/net/irda/irlmp_event.h	Mon Aug 30 10:30:24 1999
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Thu Feb 25 20:49:16 1999
+ * Modified at:   Thu Jul  8 12:18:54 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -98,17 +99,21 @@
 extern const char *irlmp_state[];
 extern const char *irlsap_state[];
 
-void irlmp_watchdog_timer_expired( unsigned long data);
-void irlmp_discovery_timer_expired( unsigned long data);
-void irlmp_idle_timer_expired( unsigned long data);
-
-void irlmp_next_station_state( IRLMP_STATE state);
-void irlmp_next_lsap_state( struct lsap_cb *self, LSAP_STATE state);
-void irlmp_next_lap_state( struct lap_cb *self, IRLMP_STATE state);
-
-void irlmp_do_lap_event( struct lap_cb *self, IRLMP_EVENT event, 
-			 struct sk_buff *skb);
-void irlmp_do_lsap_event( struct lsap_cb *self, IRLMP_EVENT event, 
-			  struct sk_buff *skb);
+void irlmp_watchdog_timer_expired(void *data);
+void irlmp_discovery_timer_expired(void *data);
+void irlmp_idle_timer_expired(void *data);
+
+void irlmp_next_station_state(IRLMP_STATE state);
+void irlmp_next_lsap_state(struct lsap_cb *self, LSAP_STATE state);
+void irlmp_next_lap_state(struct lap_cb *self, IRLMP_STATE state);
+
+void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event, 
+			struct sk_buff *skb);
+int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event, 
+			struct sk_buff *skb);
+
+#endif /* IRLMP_EVENT_H */
+
+
+
 
-#endif
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irmod.h linux/include/net/irda/irmod.h
--- v2.3.15/linux/include/net/irda/irmod.h	Mon Jul  5 20:02:10 1999
+++ linux/include/net/irda/irmod.h	Mon Aug 30 10:30:24 1999
@@ -119,7 +119,7 @@
 
 inline int irda_unlock(int *lock);
 
-void irda_notify_init(struct notify_t *notify);
+void irda_notify_init(notify_t *notify);
 
 void irda_execute_as_process(void *self, TODO_CALLBACK callback, __u32 param);
 void irmanager_notify(struct irmanager_event *event);
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irport.h linux/include/net/irda/irport.h
--- v2.3.15/linux/include/net/irda/irport.h	Wed Aug 18 11:38:48 1999
+++ linux/include/net/irda/irport.h	Mon Aug 30 10:30:24 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug  3 13:49:59 1997
- * Modified at:   Wed May 19 15:31:16 1999
+ * Modified at:   Sat Jun 26 16:57:03 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -53,7 +53,7 @@
 void irport_stop(struct irda_device *idev, int iobase);
 int  irport_probe(int iobase);
 
-void irport_change_speed(struct irda_device *idev, int speed);
+void irport_change_speed(struct irda_device *idev, __u32 speed);
 void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
 int  irport_hard_xmit(struct sk_buff *skb, struct net_device *dev);
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irqueue.h linux/include/net/irda/irqueue.h
--- v2.3.15/linux/include/net/irda/irqueue.h	Wed Aug 18 16:43:35 1999
+++ linux/include/net/irda/irqueue.h	Tue Aug 31 16:11:58 1999
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jun  9 13:26:50 1998
- * Modified at:   Tue May 25 07:54:41 1999
+ * Modified at:   Thu Jul  1 10:18:21 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (C) 1998, Aage Kvalnes <aage@cs.uit.no>
+ *     Copyright (C) 1998-1999, Aage Kvalnes <aage@cs.uit.no>
  *     Copyright (c) 1998, Dag Brattli
  *     All Rights Reserved.
  *      
@@ -70,25 +70,25 @@
 };
 
 typedef struct hashbin_t {
-	int    magic;
-	int    hb_type;
-	int    hb_size;
+	__u32      magic;
+	int        hb_type;
+	int        hb_size;
 	spinlock_t hb_mutex[ HASHBIN_SIZE ] ALIGN;
 	QUEUE*     hb_queue[ HASHBIN_SIZE ] ALIGN;
 
 	QUEUE* hb_current;
 } hashbin_t;
 
-hashbin_t *hashbin_new( int type);
-int      hashbin_delete( hashbin_t* hashbin, FREE_FUNC func);
-int      hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func);
-void     hashbin_insert( hashbin_t* hashbin, QUEUE* entry, __u32 hashv, 
-			 char* name);
-void*    hashbin_find( hashbin_t* hashbin, __u32 hashv, char* name);
-void*    hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name);
-void*    hashbin_remove_first( hashbin_t *hashbin);
-QUEUE   *hashbin_get_first( hashbin_t *hashbin);
-QUEUE   *hashbin_get_next( hashbin_t *hashbin);
+hashbin_t *hashbin_new(int type);
+int      hashbin_delete(hashbin_t* hashbin, FREE_FUNC func);
+int      hashbin_clear(hashbin_t* hashbin, FREE_FUNC free_func);
+void     hashbin_insert(hashbin_t* hashbin, QUEUE* entry, __u32 hashv, 
+			char* name);
+void*    hashbin_find(hashbin_t* hashbin, __u32 hashv, char* name);
+void*    hashbin_remove(hashbin_t* hashbin, __u32 hashv, char* name);
+void*    hashbin_remove_first(hashbin_t *hashbin);
+QUEUE   *hashbin_get_first(hashbin_t *hashbin);
+QUEUE   *hashbin_get_next(hashbin_t *hashbin);
 
 void enqueue_last(QUEUE **queue, QUEUE* element);
 void enqueue_first(QUEUE **queue, QUEUE* element);
@@ -100,7 +100,7 @@
  *    Returns the number of elements in the hashbin
  *
  */
-extern __inline__ int  hashbin_get_size( hashbin_t* hashbin) 
+extern __inline__ int  hashbin_get_size(hashbin_t* hashbin) 
 {
 	return hashbin->hb_size;
 }
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irttp.h linux/include/net/irda/irttp.h
--- v2.3.15/linux/include/net/irda/irttp.h	Sun May 30 10:27:04 1999
+++ linux/include/net/irda/irttp.h	Mon Aug 30 10:30:24 1999
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Mon May 10 19:14:51 1999
+ * Modified at:   Tue Aug 24 09:27:05 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -41,11 +42,11 @@
 #define TTP_PARAMETERS         0x80
 #define TTP_MORE               0x80
 
-#define DEFAULT_INITIAL_CREDIT 22
+#define DEFAULT_INITIAL_CREDIT 14
 
-#define LOW_THRESHOLD   4
-#define HIGH_THRESHOLD  8
-#define TTP_MAX_QUEUE  22
+#define LOW_THRESHOLD           4
+#define HIGH_THRESHOLD         10
+#define TTP_MAX_QUEUE          14
 
 /* Some priorities for disconnect requests */
 #define P_NORMAL    0
@@ -54,13 +55,16 @@
 #define SAR_DISABLE 0
 #define SAR_UNBOUND 0xffffffff
 
+/* Parameters */
+#define TTP_MAX_SDU_SIZE 0x01
+
 /*
  *  This structure contains all data assosiated with one instance of a TTP 
  *  connection.
  */
 struct tsap_cb {
-	QUEUE queue;          /* For linking it into the hashbin */
-	int  magic;           /* Just in case */
+	QUEUE   queue;        /* For linking it into the hashbin */
+	magic_t magic;        /* Just in case */
 
 	__u8 stsap_sel;       /* Source TSAP */
 	__u8 dtsap_sel;       /* Destination TSAP */
@@ -82,7 +86,7 @@
 	int rx_queue_lock;
 	spinlock_t lock;
 
-	struct notify_t notify;       /* Callbacks to client layer */
+	notify_t notify;       /* Callbacks to client layer */
 
 	struct irda_statistics stats;
 	struct timer_list todo_timer; 
@@ -103,16 +107,14 @@
 };
 
 struct irttp_cb {
-	int magic;
-	
+	magic_t    magic;	
 	hashbin_t *tsaps;
 };
 
 int  irttp_init(void);
 void irttp_cleanup(void);
 
-struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, 
-				struct notify_t *notify);
+struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify);
 int irttp_close_tsap(struct tsap_cb *self);
 
 int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb);
@@ -122,12 +124,12 @@
 			  __u32 saddr, __u32 daddr,
 			  struct qos_info *qos, __u32 max_sdu_size, 
 			  struct sk_buff *userdata);
-void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, 
+int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, 
 			    struct sk_buff *userdata);
-struct tsap_cb *irttp_dup(struct tsap_cb *self, void *instance);
-void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *skb,
-			      int priority);
+int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *skb,
+			     int priority);
 void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow);
+struct tsap_cb *irttp_dup(struct tsap_cb *self, void *instance);
 
 static __inline __u32 irttp_get_saddr(struct tsap_cb *self)
 {
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/irtty.h linux/include/net/irda/irtty.h
--- v2.3.15/linux/include/net/irda/irtty.h	Sun May 30 10:27:04 1999
+++ linux/include/net/irda/irtty.h	Mon Aug 30 10:30:24 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Mon May 10 13:22:23 1999
+ * Modified at:   Thu Jul  1 10:13:02 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *  
  *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
@@ -42,11 +42,10 @@
 #endif
 
 struct irtty_cb {
-	QUEUE q; /* Must be first */
-
-	int	magic;
+	QUEUE   q;     /* Must be first */
+	magic_t magic;
 	
-	struct  tty_struct  *tty;  /* Ptr to TTY structure */
+	struct  tty_struct  *tty;
 	struct  irda_device idev;
 };
  
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/parameters.h linux/include/net/irda/parameters.h
--- v2.3.15/linux/include/net/irda/parameters.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/parameters.h	Mon Aug 30 10:30:24 1999
@@ -0,0 +1,108 @@
+/*********************************************************************
+ *                
+ * Filename:      parameters.h
+ * Version:       1.0
+ * Description:   A more general way to handle (pi,pl,pv) parameters
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Jun  7 08:47:28 1999
+ * Modified at:   Sun Jun 13 09:17:54 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#ifndef IRDA_PARAMS_H
+#define IRDA_PARAMS_H
+
+/*
+ *  The currently supported types. Beware not to change the sequence since
+ *  it a good reason why the sized integers has a value equal to their size
+ */
+typedef enum {
+	PV_INTEGER,      /* Integer of any (pl) length */
+	PV_INT_8_BITS,   /* Integer of 8 bits in length */
+	PV_INT_16_BITS,  /* Integer of 16 bits in length */
+	PV_STRING,       /* \0 terminated string */
+	PV_INT_32_BITS,  /* Integer of 32 bits in length */
+	PV_OCT_SEQ,      /* Octet sequence */
+	PV_NO_VALUE      /* Does not contain any value (pl=0) */
+} PV_TYPE;
+
+/* Bit 7 of type field */
+#define PV_BIG_ENDIAN    0x80 
+#define PV_LITTLE_ENDIAN 0x00
+#define PV_MASK          0x7f   /* To mask away endian bit */
+
+#define PV_PUT 0
+#define PV_GET 1
+
+typedef union {
+	char   *c;
+	__u8    b;
+	__u16   s;
+	__u32   i;
+	__u8  *bp;
+	__u16 *sp;
+	__u32 *ip;
+} pv_t;
+
+typedef struct {
+	__u8 pi;
+	__u8 pl;
+	pv_t pv;
+} param_t;
+
+typedef int (*PI_HANDLER)(void *self, param_t *param, int get);
+typedef int (*PV_HANDLER)(void *self, __u8 *buf, int len, __u8 pi,
+			  PV_TYPE type, PI_HANDLER func);
+
+typedef struct {
+	PI_HANDLER func;  /* Handler for this parameter identifier */
+	PV_TYPE    type;  /* Data type for this parameter */
+} pi_minor_info_t;
+
+typedef struct {
+	pi_minor_info_t *pi_minor_call_table;
+	int len;
+} pi_major_info_t;
+
+typedef struct {
+	pi_major_info_t *tables;
+	int              len;
+	__u8             pi_mask;
+	int              pi_major_offset;
+} pi_param_info_t;
+
+int irda_param_pack(__u8 *buf, char *fmt, ...);
+int irda_param_unpack(__u8 *buf, char *fmt, ...);
+
+int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len, 
+		      pi_param_info_t *info);
+int irda_param_extract(void *self, __u8 *buf, int len, pi_param_info_t *info);
+int irda_param_extract_all(void *self, __u8 *buf, int len, 
+			   pi_param_info_t *info);
+
+extern inline int irda_param_insert_byte(__u8 *buf, __u8 pi, __u8 pv)
+{
+	return irda_param_pack(buf, "bbb", pi, 1, pv);
+}
+
+#endif /* IRDA_PARAMS_H */
+
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/qos.h linux/include/net/irda/qos.h
--- v2.3.15/linux/include/net/irda/qos.h	Wed Aug 18 16:44:28 1999
+++ linux/include/net/irda/qos.h	Tue Aug 31 16:12:58 1999
@@ -1,33 +1,41 @@
 /*********************************************************************
  *                
  * Filename:      qos.h
- * Version:       0.1
+ * Version:       1.0
  * Description:   Quality of Service definitions
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Sep 19 23:21:09 1997
- * Modified at:   Wed Dec  9 10:32:47 1998
+ * Modified at:   Mon Aug 16 10:00:18 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
  ********************************************************************/
 
-#ifndef QOS_H
-#define QOS_H
+#ifndef IRDA_QOS_H
+#define IRDA_QOS_H
 
 #include <linux/config.h>
 #include <linux/skbuff.h>
 
+#include <net/irda/parameters.h>
+
 #define PI_BAUD_RATE     0x01
 #define PI_MAX_TURN_TIME 0x82
 #define PI_DATA_SIZE     0x83
@@ -41,21 +49,22 @@
 #define IR_115200_MAX 0x3f
 
 /* Baud rates (first byte) */
-#define IR_2400    0x01
-#define IR_9600    0x02
-#define IR_19200   0x04
-#define IR_38400   0x08
-#define IR_57600   0x10
-#define IR_115200  0x20
-#define IR_576000  0x40
-#define IR_1152000 0x80
+#define IR_2400     0x01
+#define IR_9600     0x02
+#define IR_19200    0x04
+#define IR_38400    0x08
+#define IR_57600    0x10
+#define IR_115200   0x20
+#define IR_576000   0x40
+#define IR_1152000  0x80
 
 /* Baud rates (second byte) */
-#define IR_4000000 0x01
+#define IR_4000000  0x01
+#define IR_16000000 0x02
 
 /* Quality of Service information */
 typedef struct {
-	int value;
+	__u32 value;
 	__u16 bits; /* LSB is first byte, MSB is second byte */
 } qos_value_t;
 
@@ -77,24 +86,21 @@
 #endif
 };
 
-extern int baud_rates[];
-extern int data_size[];
-extern int min_turn_time[];
-extern int add_bofs[];
-extern int compression[];
-
-void irda_init_max_qos_capabilies( struct qos_info *qos);
-void irda_qos_compute_intersection( struct qos_info *, struct qos_info *);
-int  irda_insert_qos_negotiation_params( struct qos_info *qos, __u8 *fp);
-void irda_qos_negotiate( struct qos_info *qos_rx, struct qos_info *qos_tx,
-			 struct sk_buff *skb);
-
-int msb_index ( __u16 byte);
-int byte_value( __u8 byte, int *array);
-int value_index( int value, int *array);
-int index_value( int index, int *array);
+extern __u32 baud_rates[];
+extern __u32 data_size[];
+extern __u32 min_turn_time[];
+extern __u32 add_bofs[];
+extern __u32 compression[];
+
+void irda_init_max_qos_capabilies(struct qos_info *qos);
+void irda_qos_compute_intersection(struct qos_info *, struct qos_info *);
+
+int msb_index(__u16 byte);
+__u32 byte_value(__u8 byte, int *array);
+int value_index(__u32 value, int *array);
+__u32 index_value(int index, int *array);
 
-void irda_qos_bits_to_value( struct qos_info *qos);
+void irda_qos_bits_to_value(struct qos_info *qos);
 
 #endif
 
diff -u --recursive --new-file v2.3.15/linux/include/net/irda/timer.h linux/include/net/irda/timer.h
--- v2.3.15/linux/include/net/irda/timer.h	Thu Apr 15 05:42:42 1999
+++ linux/include/net/irda/timer.h	Mon Aug 30 10:30:24 1999
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Tue Apr  6 16:17:16 1999
+ * Modified at:   Wed Jun 23 22:56:51 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997, 1998 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1997, 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -37,28 +37,34 @@
 /* 
  *  Timeout definitions, some defined in IrLAP p. 92
  */
-#define POLL_TIMEOUT        450*HZ/1000    /* Must never exceed 500 ms */
-#define FINAL_TIMEOUT       500*HZ/1000    /* Must never exceed 500 ms */
+#define POLL_TIMEOUT        (450*HZ/1000)    /* Must never exceed 500 ms */
+#define FINAL_TIMEOUT       (500*HZ/1000)    /* Must never exceed 500 ms */
 
 /* 
  *  Normally twice of p-timer. Note 3, IrLAP p. 60 suggests at least twice 
  *  duration of the P-timer.
  */
-#define WD_TIMEOUT          POLL_TIMEOUT*2
-#define MEDIABUSY_TIMEOUT   500*HZ/1000    /* 500 msec */
+#define WD_TIMEOUT          (POLL_TIMEOUT*2)
+#define MEDIABUSY_TIMEOUT   (500*HZ/1000)    /* 500 msec */
 
 /*
  *  Slot timer must never exceed 85 ms, and must always be at least 25 ms, 
- *  suggested to  75-85 msec by IrDA lite
+ *  suggested to  75-85 msec by IrDA lite. This doesn't work with a lot of
+ *  devices, and other stackes uses a lot more, so it's best we do it as well
  */
-#define SLOT_TIMEOUT            80*HZ/1000
-#define QUERY_TIMEOUT           HZ          /* 1 sec */
+#define SLOT_TIMEOUT            (90*HZ/1000)
 
-#define WATCHDOG_TIMEOUT        20*HZ       /* 20 sec */
+/* 
+ *  We set the query timeout to 100 ms and then expect the value to be 
+ *  multiplied with the number of slots to product the actual timeout value
+ */
+#define QUERY_TIMEOUT           (HZ/10)       
+
+#define WATCHDOG_TIMEOUT        (20*HZ)       /* 20 sec */
 
-typedef void (*TIMER_CALLBACK)(unsigned long);
+typedef void (*TIMER_CALLBACK)(void *);
 
-void irda_start_timer(struct timer_list *ptimer, int timeout, int data,
+void irda_start_timer(struct timer_list *ptimer, int timeout, void* data,
 		      TIMER_CALLBACK callback);
 
 inline void irlap_start_slot_timer(struct irlap_cb *self, int timeout);
diff -u --recursive --new-file v2.3.15/linux/include/net/ndisc.h linux/include/net/ndisc.h
--- v2.3.15/linux/include/net/ndisc.h	Wed Aug 18 16:44:34 1999
+++ linux/include/net/ndisc.h	Tue Aug 31 16:13:02 1999
@@ -104,15 +104,9 @@
 extern __inline__ struct neighbour * ndisc_get_neigh(struct net_device *dev, struct in6_addr *addr)
 {
 
-	if (dev) {
-		struct neighbour *neigh;
+	if (dev)
+		return __neigh_lookup(&nd_tbl, addr, dev, 1);
 
-		start_bh_atomic();
-		neigh = __neigh_lookup(&nd_tbl, addr, dev, 1);
-		end_bh_atomic();
-
-		return neigh;
-	}
 	return NULL;
 }
 
diff -u --recursive --new-file v2.3.15/linux/include/video/fbcon.h linux/include/video/fbcon.h
--- v2.3.15/linux/include/video/fbcon.h	Thu Aug 26 13:05:41 1999
+++ linux/include/video/fbcon.h	Thu Aug 26 12:59:15 1999
@@ -12,6 +12,7 @@
 #define _VIDEO_FBCON_H
 
 #include <linux/config.h>
+#include <linux/types.h>
 #include <linux/console_struct.h>
 #include <linux/vt_buffer.h>
 
@@ -522,12 +523,12 @@
 
 #else
 
-#define fb_readb(addr) (*(volatile unsigned char *) __io_virt(addr))
-#define fb_readw(addr) (*(volatile unsigned short *) __io_virt(addr))
-#define fb_readl(addr) (*(volatile unsigned int *) __io_virt(addr))
-#define fb_writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
-#define fb_writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
-#define fb_writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
+#define fb_readb(addr) (*(volatile u8 *) (addr))
+#define fb_readw(addr) (*(volatile u16 *) (addr))
+#define fb_readl(addr) (*(volatile u32 *) (addr))
+#define fb_writeb(b,addr) (*(volatile u8 *) (addr) = (b))
+#define fb_writew(b,addr) (*(volatile u16 *) (addr) = (b))
+#define fb_writel(b,addr) (*(volatile u32 *) (addr) = (b))
 
 #endif
 
diff -u --recursive --new-file v2.3.15/linux/include/video/sbusfb.h linux/include/video/sbusfb.h
--- v2.3.15/linux/include/video/sbusfb.h	Thu Feb 25 10:02:11 1999
+++ linux/include/video/sbusfb.h	Tue Aug 31 11:25:33 1999
@@ -56,6 +56,10 @@
 	int ramsize;
 	int mode;
 };
+struct fb_info_p9100 {
+	struct p9100_ctrl *ctrl;
+	volatile u32 *fbmem;
+};
 
 struct cg_cursor {
 	char	enable;         /* cursor is enabled */
@@ -96,6 +100,7 @@
 		struct fb_info_tcx tcx;
 		struct fb_info_leo leo;
 		struct fb_info_cgfourteen cg14;
+		struct fb_info_p9100 p9100;
 	} s;
 	unsigned char *color_map;
 	struct cg_cursor cursor;
@@ -134,6 +139,7 @@
 extern char *leofb_init(struct fb_info_sbusfb *);
 extern char *bwtwofb_init(struct fb_info_sbusfb *);
 extern char *cgfourteenfb_init(struct fb_info_sbusfb *);
+extern char *p9100fb_init(struct fb_info_sbusfb *);
 
 #define sbusfbinfod(disp) ((struct fb_info_sbusfb *)(disp->fb_info))
 #define sbusfbinfo(info) ((struct fb_info_sbusfb *)(info))
diff -u --recursive --new-file v2.3.15/linux/init/main.c linux/init/main.c
--- v2.3.15/linux/init/main.c	Sun Aug 15 11:50:35 1999
+++ linux/init/main.c	Mon Aug 30 13:43:59 1999
@@ -88,9 +88,7 @@
 extern void free_initmem(void);
 extern void filesystem_setup(void);
 
-#ifdef CONFIG_ARCH_ACORN
 extern void ecard_init(void);
-#endif
 
 #if defined(CONFIG_SYSVIPC)
 extern void ipc_init(void);
@@ -655,6 +653,10 @@
 
 	/* .. filesystems .. */
 	filesystem_setup();
+
+#ifdef CONFIG_IRDA
+	irda_device_init(); /* Must be done after protocol initialization */
+#endif
 
 	/* Mount the root filesystem.. */
 	mount_root();
diff -u --recursive --new-file v2.3.15/linux/ipc/msg.c linux/ipc/msg.c
--- v2.3.15/linux/ipc/msg.c	Thu Aug 26 13:05:41 1999
+++ linux/ipc/msg.c	Mon Aug 30 10:23:14 1999
@@ -420,10 +420,10 @@
 		tbuf.msg_stime  = msq->msg_stime;
 		tbuf.msg_rtime  = msq->msg_rtime;
 		tbuf.msg_ctime  = msq->msg_ctime;
-		tbuf.msg_cbytes_old = msq->msg_cbytes;
 		tbuf.msg_cbytes = msq->msg_cbytes;
+		tbuf.msg_lcbytes = msq->msg_cbytes;
 		tbuf.msg_qnum   = msq->msg_qnum;
-		tbuf.msg_qbytes_old = msq->msg_qbytes;
+		tbuf.msg_lqbytes = msq->msg_qbytes;
 		tbuf.msg_qbytes = msq->msg_qbytes;
 		tbuf.msg_lspid  = msq->msg_lspid;
 		tbuf.msg_lrpid  = msq->msg_lrpid;
@@ -464,10 +464,10 @@
 		tbuf.msg_stime  = msq->msg_stime;
 		tbuf.msg_rtime  = msq->msg_rtime;
 		tbuf.msg_ctime  = msq->msg_ctime;
-		tbuf.msg_cbytes_old = msq->msg_cbytes;
+		tbuf.msg_lcbytes = msq->msg_cbytes;
 		tbuf.msg_cbytes = msq->msg_cbytes;
 		tbuf.msg_qnum   = msq->msg_qnum;
-		tbuf.msg_qbytes_old = msq->msg_qbytes;
+		tbuf.msg_lqbytes = msq->msg_qbytes;
 		tbuf.msg_qbytes = msq->msg_qbytes;
 		tbuf.msg_lspid  = msq->msg_lspid;
 		tbuf.msg_lrpid  = msq->msg_lrpid;
diff -u --recursive --new-file v2.3.15/linux/ipc/shm.c linux/ipc/shm.c
--- v2.3.15/linux/ipc/shm.c	Thu Aug 26 13:05:41 1999
+++ linux/ipc/shm.c	Mon Aug 30 13:47:18 1999
@@ -6,6 +6,7 @@
  * Fixed the shm swap deallocation (shm_unuse()), August 1998 Andrea Arcangeli.
  *
  * /proc/sysvipc/shm support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
+ * BIGMEM support, Andrea Arcangeli <andrea@suse.de>
  */
 
 #include <linux/config.h>
@@ -17,6 +18,7 @@
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/proc_fs.h>
+#include <linux/bigmem.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -657,9 +659,10 @@
 	pte = __pte(shp->shm_pages[idx]);
 	if (!pte_present(pte)) {
 		if (pte_none(pte)) {
-			page = get_free_page(GFP_USER);
+			page = __get_free_page(GFP_BIGUSER);
 			if (!page)
 				goto oom;
+			clear_bigpage(page);
 			if (pte_val(pte) != shp->shm_pages[idx])
 				goto changed;
 		} else {
@@ -677,6 +680,8 @@
 			if (!page_map)
 				goto oom;
 			delete_from_swap_cache(page_map);
+			page_map = replace_with_bigmem(page_map);
+			page = page_address(page_map);
 			swap_free(entry);
 			shm_swp--;
 		}
@@ -719,10 +724,12 @@
 	int loop = 0;
 	int counter;
 	struct page * page_map;
+	int ret = 0;
 	
+	lock_kernel();
 	counter = shm_rss >> prio;
 	if (!counter || !(swap_nr = get_swap_page()))
-		return 0;
+		goto out_unlock;
 
  check_id:
 	shp = shm_segs[swap_id];
@@ -750,15 +757,19 @@
 	page_map = &mem_map[MAP_NR(pte_page(page))];
 	if ((gfp_mask & __GFP_DMA) && !PageDMA(page_map))
 		goto check_table;
+	if (!(gfp_mask & __GFP_BIGMEM) && PageBIGMEM(page_map))
+		goto check_table;
 	swap_attempts++;
 
 	if (--counter < 0) { /* failed */
 		failed:
 		swap_free (swap_nr);
-		return 0;
+		goto out_unlock;
 	}
 	if (page_count(mem_map + MAP_NR(pte_page(page))) != 1)
 		goto check_table;
+	if (!(page_map = prepare_bigmem_swapout(page_map)))
+		goto check_table;
 	shp->shm_pages[idx] = swap_nr;
 	swap_duplicate(swap_nr);
 	add_to_swap_cache(page_map, swap_nr);
@@ -768,7 +779,10 @@
 	swap_successes++;
 	shm_swp++;
 	shm_rss--;
-	return 1;
+	ret = 1;
+ out_unlock:
+	unlock_kernel();
+	return ret;
 }
 
 /*
diff -u --recursive --new-file v2.3.15/linux/kernel/itimer.c linux/kernel/itimer.c
--- v2.3.15/linux/kernel/itimer.c	Thu Aug 26 13:05:42 1999
+++ linux/kernel/itimer.c	Mon Aug 30 10:23:14 1999
@@ -156,8 +156,6 @@
 	int error;
 
 	if (value) {
-		if(verify_area(VERIFY_READ, value, sizeof(*value)))
-			return -EFAULT;
 		if(copy_from_user(&set_buffer, value, sizeof(set_buffer)))
 			return -EFAULT;
 	} else
diff -u --recursive --new-file v2.3.15/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.3.15/linux/kernel/ksyms.c	Wed Aug 18 11:19:11 1999
+++ linux/kernel/ksyms.c	Thu Aug 26 09:41:36 1999
@@ -173,6 +173,7 @@
 EXPORT_SYMBOL(block_write_cont_page);
 EXPORT_SYMBOL(block_flushpage);
 EXPORT_SYMBOL(generic_file_read);
+EXPORT_SYMBOL(do_generic_file_read);
 EXPORT_SYMBOL(generic_file_write);
 EXPORT_SYMBOL(generic_file_mmap);
 EXPORT_SYMBOL(generic_buffer_fdatasync);
diff -u --recursive --new-file v2.3.15/linux/kernel/ptrace.c linux/kernel/ptrace.c
--- v2.3.15/linux/kernel/ptrace.c	Mon Jul 19 12:29:05 1999
+++ linux/kernel/ptrace.c	Thu Aug 26 12:34:55 1999
@@ -10,6 +10,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
+#include <linux/bigmem.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -52,7 +53,11 @@
 			dst = src;
 			src = buf;
 		}
+		src = (void *) kmap((unsigned long) src, KM_READ);
+		dst = (void *) kmap((unsigned long) dst, KM_WRITE);
 		memcpy(dst, src, len);
+		kunmap((unsigned long) src, KM_READ);
+		kunmap((unsigned long) dst, KM_WRITE);
 	}
 	flush_page_to_ram(page);
 	return len;
diff -u --recursive --new-file v2.3.15/linux/kernel/resource.c linux/kernel/resource.c
--- v2.3.15/linux/kernel/resource.c	Thu Aug 26 13:05:42 1999
+++ linux/kernel/resource.c	Tue Aug 31 11:02:32 1999
@@ -15,8 +15,8 @@
 
 #include <asm/spinlock.h>
 
-struct resource ioport_resource = { "PCI IO", 0x0000, 0xFFFF };
-struct resource iomem_resource = { "PCI mem", 0x00000000, 0xFFFFFFFF };
+struct resource ioport_resource = { "PCI IO", 0x0000, 0xFFFF, IORESOURCE_IO };
+struct resource iomem_resource = { "PCI mem", 0x00000000, 0xFFFFFFFF, IORESOURCE_MEM };
 
 static rwlock_t resource_lock = RW_LOCK_UNLOCKED;
 
diff -u --recursive --new-file v2.3.15/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.3.15/linux/kernel/sysctl.c	Thu Aug 26 13:05:42 1999
+++ linux/kernel/sysctl.c	Tue Aug 31 12:37:39 1999
@@ -86,6 +86,7 @@
 static ctl_table fs_table[];
 static ctl_table debug_table[];
 static ctl_table dev_table[];
+extern ctl_table random_table[];
 
 
 /* /proc declarations: */
@@ -221,6 +222,7 @@
 #endif	 
 	{KERN_MAX_THREADS, "threads-max", &max_threads, sizeof(int),
 	 0644, NULL, &proc_dointvec},
+	{KERN_RANDOM, "random", NULL, 0, 0555, random_table},
 	{0}
 };
 
diff -u --recursive --new-file v2.3.15/linux/lib/inflate.c linux/lib/inflate.c
--- v2.3.15/linux/lib/inflate.c	Wed Jun 24 14:30:11 1998
+++ linux/lib/inflate.c	Mon Aug 30 13:43:59 1999
@@ -6,6 +6,12 @@
 /* 
  * Adapted for booting Linux by Hannu Savolainen 1993
  * based on gzip-1.0.3 
+ *
+ * Nicolas Pitre <nico@visuaide.com>, 1999/04/14 :
+ *   Little mods for all variable to reside either into rodata or bss segments
+ *   by marking constant variables with 'const' and initializing all the others
+ *   at run-time only.  This allows for the kernel uncompressor to run
+ *   directly from Flash or ROM memory on embeded systems.
  */
 
 /*
@@ -132,8 +138,8 @@
 
 
 /* Function prototypes */
-STATIC int huft_build OF((unsigned *, unsigned, unsigned, ush *, ush *,
-                   struct huft **, int *));
+STATIC int huft_build OF((unsigned *, unsigned, unsigned, 
+		const ush *, const ush *, struct huft **, int *));
 STATIC int huft_free OF((struct huft *));
 STATIC int inflate_codes OF((struct huft *, struct huft *, int, int));
 STATIC int inflate_stored OF((void));
@@ -156,20 +162,20 @@
 #define flush_output(w) (wp=(w),flush_window())
 
 /* Tables for deflate from PKZIP's appnote.txt. */
-static unsigned border[] = {    /* Order of the bit length code lengths */
+static const unsigned border[] = {    /* Order of the bit length code lengths */
         16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-static ush cplens[] = {         /* Copy lengths for literal codes 257..285 */
+static const ush cplens[] = {         /* Copy lengths for literal codes 257..285 */
         3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
         35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
         /* note: see note #13 above about the 258 in this list. */
-static ush cplext[] = {         /* Extra bits for literal codes 257..285 */
+static const ush cplext[] = {         /* Extra bits for literal codes 257..285 */
         0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
         3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */
-static ush cpdist[] = {         /* Copy offsets for distance codes 0..29 */
+static const ush cpdist[] = {         /* Copy offsets for distance codes 0..29 */
         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
         257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
         8193, 12289, 16385, 24577};
-static ush cpdext[] = {         /* Extra bits for distance codes */
+static const ush cpdext[] = {         /* Extra bits for distance codes */
         0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
         7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
         12, 12, 13, 13};
@@ -209,7 +215,7 @@
 STATIC ulg bb;                         /* bit buffer */
 STATIC unsigned bk;                    /* bits in bit buffer */
 
-STATIC ush mask_bits[] = {
+STATIC const ush mask_bits[] = {
     0x0000,
     0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
     0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
@@ -253,8 +259,8 @@
  */
 
 
-STATIC int lbits = 9;          /* bits in base literal/length lookup table */
-STATIC int dbits = 6;          /* bits in base distance lookup table */
+STATIC const int lbits = 9;          /* bits in base literal/length lookup table */
+STATIC const int dbits = 6;          /* bits in base distance lookup table */
 
 
 /* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
@@ -269,8 +275,8 @@
 unsigned *b;            /* code lengths in bits (all assumed <= BMAX) */
 unsigned n;             /* number of codes (assumed <= N_MAX) */
 unsigned s;             /* number of simple-valued codes (0..s-1) */
-ush *d;                 /* list of base values for non-simple codes */
-ush *e;                 /* list of extra bits for non-simple codes */
+const ush *d;                 /* list of base values for non-simple codes */
+const ush *e;                 /* list of extra bits for non-simple codes */
 struct huft **t;        /* result: starting table */
 int *m;                 /* maximum lookup bits, returns actual */
 /* Given a list of code lengths and a maximum table size, make a set of
@@ -1002,7 +1008,7 @@
  **********************************************************************/
 
 static ulg crc_32_tab[256];
-static ulg crc = (ulg)0xffffffffL; /* shift register contents */
+static ulg crc;		/* initialized in makecrc() so it'll reside in bss */
 #define CRC_VALUE (crc ^ 0xffffffffL)
 
 /*
@@ -1021,7 +1027,7 @@
   int k;                /* byte being shifted into crc apparatus */
 
   /* terms of polynomial defining this crc (except x^32): */
-  static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+  static const int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
 
   /* Make exclusive-or pattern from polynomial */
   e = 0;
@@ -1041,6 +1047,9 @@
     }
     crc_32_tab[i] = c;
   }
+
+  /* this is initialized here so this code could reside in ROM */
+  crc = (ulg)0xffffffffL; /* shift register contents */
 }
 
 /* gzip flag byte */
diff -u --recursive --new-file v2.3.15/linux/mm/Makefile linux/mm/Makefile
--- v2.3.15/linux/mm/Makefile	Tue Nov 17 14:28:18 1998
+++ linux/mm/Makefile	Thu Aug 26 12:34:55 1999
@@ -12,4 +12,8 @@
 	    vmalloc.o slab.o \
 	    swap.o vmscan.o page_io.o page_alloc.o swap_state.o swapfile.o
 
+ifeq ($(CONFIG_BIGMEM),y)
+O_OBJS += bigmem.o
+endif
+
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.15/linux/mm/bigmem.c linux/mm/bigmem.c
--- v2.3.15/linux/mm/bigmem.c	Wed Dec 31 16:00:00 1969
+++ linux/mm/bigmem.c	Thu Aug 26 12:36:07 1999
@@ -0,0 +1,71 @@
+/*
+ * BIGMEM common code and variables.
+ *
+ * (C) 1999 Andrea Arcangeli, SuSE GmbH, andrea@suse.de
+ *          Gerhard Wichert, Siemens AG, Gerhard.Wichert@pdb.siemens.de
+ */
+
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/bigmem.h>
+
+unsigned long bigmem_mapnr;
+int nr_free_bigpages = 0;
+
+struct page * prepare_bigmem_swapout(struct page * page)
+{
+	/* if this is a bigmem page so it can't be swapped out directly
+	   otherwise the b_data buffer addresses will break
+	   the lowlevel device drivers. */
+	if (PageBIGMEM(page)) {
+		unsigned long regular_page;
+		unsigned long vaddr;
+
+		regular_page = __get_free_page(GFP_ATOMIC);
+		if (!regular_page)
+			return NULL;
+
+		vaddr = kmap(page_address(page), KM_READ);
+		copy_page(regular_page, vaddr);
+		kunmap(vaddr, KM_READ);
+
+		/* ok, we can just forget about our bigmem page since 
+		   we stored its data into the new regular_page. */
+		__free_page(page);
+
+		page = MAP_NR(regular_page) + mem_map;
+	}
+	return page;
+}
+
+struct page * replace_with_bigmem(struct page * page)
+{
+	if (!PageBIGMEM(page) && nr_free_bigpages) {
+		unsigned long kaddr;
+
+		kaddr = __get_free_page(GFP_ATOMIC|GFP_BIGMEM);
+		if (kaddr) {
+			struct page * bigmem_page;
+
+			bigmem_page = MAP_NR(kaddr) + mem_map;
+			if (PageBIGMEM(bigmem_page)) {
+				unsigned long vaddr;
+
+				vaddr = kmap(kaddr, KM_WRITE);
+				copy_page(vaddr, page_address(page));
+				kunmap(vaddr, KM_WRITE);
+
+				/* Preserve the caching of the swap_entry. */
+				bigmem_page->offset = page->offset;
+
+				/* We can just forget the old page since 
+				   we stored its data into the new
+				   bigmem_page. */
+				__free_page(page);
+
+				page = bigmem_page;
+			}
+		}
+	}
+	return page;
+}
diff -u --recursive --new-file v2.3.15/linux/mm/filemap.c linux/mm/filemap.c
--- v2.3.15/linux/mm/filemap.c	Thu Aug 26 13:05:42 1999
+++ linux/mm/filemap.c	Tue Aug 31 11:30:48 1999
@@ -33,6 +33,8 @@
  *
  * finished 'unifying' the page and buffer cache and SMP-threaded the
  * page-cache, 21.05.1999, Ingo Molnar <mingo@redhat.com>
+ *
+ * SMP-threaded pagemap-LRU 1999, Andrea Arcangeli <andrea@suse.de>
  */
 
 atomic_t page_cache_size = ATOMIC_INIT(0);
@@ -40,6 +42,11 @@
 struct page **page_hash_table;
 
 spinlock_t pagecache_lock = SPIN_LOCK_UNLOCKED;
+/*
+ * NOTE: to avoid deadlocking you must never acquire the pagecache_lock with
+ *       the pagemap_lru_lock held.
+ */
+spinlock_t pagemap_lru_lock = SPIN_LOCK_UNLOCKED;
 
 #define CLUSTER_PAGES		(1 << page_cluster)
 #define CLUSTER_SHIFT		(PAGE_CACHE_SHIFT + page_cluster)
@@ -121,6 +128,7 @@
 		}
 		if (page_count(page) != 2)
 			printk("hm, busy page invalidated? (not necesserily a bug)\n");
+		lru_cache_del(page);
 
 		remove_page_from_inode_queue(page);
 		remove_page_from_hash_queue(page);
@@ -155,8 +163,9 @@
 
 			lock_page(page);
 
-			if (inode->i_op->flushpage)
-				inode->i_op->flushpage(inode, page, 0);
+			if (!inode->i_op->flushpage ||
+			    inode->i_op->flushpage(inode, page, 0))
+				lru_cache_del(page);
 
 			/*
 			 * We remove the page from the page cache
@@ -218,81 +227,62 @@
 
 int shrink_mmap(int priority, int gfp_mask)
 {
-	static unsigned long clock = 0;
-	unsigned long limit = num_physpages << 1;
+	int ret = 0, count;
+	LIST_HEAD(young);
+	LIST_HEAD(old);
+	LIST_HEAD(forget);
+	struct list_head * page_lru, * dispose;
 	struct page * page;
-	int count, users;
 
-	count = limit >> priority;
+	count = nr_lru_pages / (priority+1);
 
-	page = mem_map + clock;
-	do {
-		int referenced;
+	spin_lock(&pagemap_lru_lock);
 
-		/* This works even in the presence of PageSkip because
-		 * the first two entries at the beginning of a hole will
-		 * be marked, not just the first.
-		 */
-		page++;
-		clock++;
-		if (clock >= max_mapnr) {
-			clock = 0;
-			page = mem_map;
-		}
-		if (PageSkip(page)) {
-			/* next_hash is overloaded for PageSkip */
-			page = page->next_hash;
-			clock = page - mem_map;
-		}
-		
-		referenced = test_and_clear_bit(PG_referenced, &page->flags);
+	while (count > 0 && (page_lru = lru_cache.prev) != &lru_cache) {
+		page = list_entry(page_lru, struct page, lru);
+		list_del(page_lru);
+
+		dispose = &lru_cache;
+		if (test_and_clear_bit(PG_referenced, &page->flags))
+			/* Roll the page at the top of the lru list,
+			 * we could also be more aggressive putting
+			 * the page in the young-dispose-list, so
+			 * avoiding to free young pages in each pass.
+			 */
+			goto dispose_continue;
 
+		dispose = &old;
+		/* don't account passes over not DMA pages */
 		if ((gfp_mask & __GFP_DMA) && !PageDMA(page))
-			continue;
+			goto dispose_continue;
+		if (!(gfp_mask & __GFP_BIGMEM) && PageBIGMEM(page))
+			goto dispose_continue;
 
 		count--;
 
-		/*
-		 * Some common cases that we just short-circuit without
-		 * getting the locks - we need to re-check this once we
-		 * have the lock, but that's fine.
-		 */
-		users = page_count(page);
-		if (!users)
-			continue;
-		if (!page->buffers) {
-			if (!page->inode)
-				continue;
-			if (users > 1)
-				continue;
-		}
-
-		/*
-		 * ok, now the page looks interesting. Re-check things
-		 * and keep the lock.
-		 */
+		dispose = &young;
+		if (TryLockPage(page))
+			goto dispose_continue;
+
+		/* Release the pagemap_lru lock even if the page is not yet
+		   queued in any lru queue since we have just locked down
+		   the page so nobody else may SMP race with us running
+		   a lru_cache_del() (lru_cache_del() always run with the
+		   page locked down ;). */
+		spin_unlock(&pagemap_lru_lock);
+
+		/* avoid unscalable SMP locking */
+		if (!page->buffers && page_count(page) > 1)
+			goto unlock_noput_continue;
+
+		/* Take the pagecache_lock spinlock held to avoid
+		   other tasks to notice the page while we are looking at its
+		   page count. If it's a pagecache-page we'll free it
+		   in one atomic transaction after checking its page count. */
 		spin_lock(&pagecache_lock);
-		if (!page->inode && !page->buffers) {
-			spin_unlock(&pagecache_lock);
-			continue;
-		}
-		if (!page_count(page)) {
-			spin_unlock(&pagecache_lock);
-			BUG();
-			continue;
-		}
-		get_page(page);
-		if (TryLockPage(page)) {
-			spin_unlock(&pagecache_lock);
-			goto put_continue;
-		}
 
-		/*
-		 * we keep pagecache_lock locked and unlock it in
-		 * each branch, so that the page->inode case doesnt
-		 * have to re-grab it. Here comes the 'real' logic
-		 * to free memory:
-		 */
+		/* avoid freeing the page while it's locked */
+		get_page(page);
 
 		/* Is it a buffer page? */
 		if (page->buffers) {
@@ -300,10 +290,9 @@
 			if (!try_to_free_buffers(page))
 				goto unlock_continue;
 			/* page was locked, inode can't go away under us */
-			if (!page->inode)
-			{
+			if (!page->inode) {
 				atomic_sub(PAGE_CACHE_SIZE, &buffermem);
-				goto made_progress;
+				goto made_buffer_progress;
 			}
 			spin_lock(&pagecache_lock);
 		}
@@ -313,7 +302,7 @@
 		 * (count == 2 because we added one ourselves above).
 		 */
 		if (page_count(page) != 2)
-			goto spin_unlock_continue;
+			goto cache_unlock_continue;
 
 		/*
 		 * Is it a page swap page? If so, we want to
@@ -322,35 +311,68 @@
 		 */
 		if (PageSwapCache(page)) {
 			spin_unlock(&pagecache_lock);
-			if (referenced && swap_count(page->offset) != 2)
-				goto unlock_continue;
 			__delete_from_swap_cache(page);
-			page_cache_release(page);
-			goto made_progress;
+			goto made_inode_progress;
 		}	
 
 		/* is it a page-cache page? */
-		if (!referenced && page->inode && !pgcache_under_min()) {
-			remove_page_from_inode_queue(page);
-			remove_page_from_hash_queue(page);
-			page->inode = NULL;
-			spin_unlock(&pagecache_lock);
-
-			page_cache_release(page);
-			goto made_progress;
+		if (page->inode)
+		{
+			dispose = &old;
+			if (!pgcache_under_min())
+			{
+				remove_page_from_inode_queue(page);
+				remove_page_from_hash_queue(page);
+				page->inode = NULL;
+				spin_unlock(&pagecache_lock);
+				goto made_inode_progress;
+			}
+			goto cache_unlock_continue;
 		}
-spin_unlock_continue:
+
+		dispose = &forget;
+		printk(KERN_ERR "shrink_mmap: unknown LRU page!\n");
+
+cache_unlock_continue:
 		spin_unlock(&pagecache_lock);
 unlock_continue:
 		UnlockPage(page);
-put_continue:
 		put_page(page);
-	} while (count > 0);
-	return 0;
-made_progress:
+dispose_relock_continue:
+		/* even if the dispose list is local, a truncate_inode_page()
+		   may remove a page from its queue so always
+		   synchronize with the lru lock while accesing the
+		   page->lru field */
+		spin_lock(&pagemap_lru_lock);
+		list_add(page_lru, dispose);
+		continue;
+
+unlock_noput_continue:
+		UnlockPage(page);
+		goto dispose_relock_continue;
+
+dispose_continue:
+		list_add(page_lru, dispose);
+	}
+	goto out;
+
+made_inode_progress:
+	page_cache_release(page);
+made_buffer_progress:
 	UnlockPage(page);
 	put_page(page);
-	return 1;
+	ret = 1;
+	spin_lock(&pagemap_lru_lock);
+	/* nr_lru_pages needs the spinlock */
+	nr_lru_pages--;
+
+out:
+	list_splice(&young, &lru_cache);
+	list_splice(&old, lru_cache.prev);
+
+	spin_unlock(&pagemap_lru_lock);
+
+	return ret;
 }
 
 static inline struct page * __find_page_nolock(struct inode * inode, unsigned long offset, struct page *page)
@@ -467,13 +489,14 @@
 {
 	unsigned long flags;
 
-	flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error));
-	page->flags = flags |  ((1 << PG_locked) | (1 << PG_referenced));
+	flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_referenced));
+	page->flags = flags | (1 << PG_locked);
 	page->owner = current;	/* REMOVEME */
 	get_page(page);
 	page->offset = offset;
 	add_page_to_inode_queue(inode, page);
 	__add_page_to_hash_queue(page, hash);
+	lru_cache_add(page);
 }
 
 void add_to_page_cache(struct page * page, struct inode * inode, unsigned long offset)
@@ -572,8 +595,8 @@
 
 	add_wait_queue(&page->wait, &wait);
 	do {
-		tsk->state = TASK_UNINTERRUPTIBLE;
 		run_task_queue(&tq_disk);
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 		if (!PageLocked(page))
 			break;
 		schedule();
@@ -587,23 +610,8 @@
  */
 void lock_page(struct page *page)
 {
-	if (TryLockPage(page)) {
-		struct task_struct *tsk = current;
-		DECLARE_WAITQUEUE(wait, current);
-
-		run_task_queue(&tq_disk);
-		add_wait_queue(&page->wait, &wait);
-		tsk->state = TASK_UNINTERRUPTIBLE;
-
-		while (TryLockPage(page)) {
-			run_task_queue(&tq_disk);
-			schedule();
-			tsk->state = TASK_UNINTERRUPTIBLE;
-		}
-
-		remove_wait_queue(&page->wait, &wait);
-		tsk->state = TASK_RUNNING;
-	}
+	while (TryLockPage(page))
+		___wait_on_page(page);
 }
 
 
@@ -632,13 +640,14 @@
 		struct task_struct *tsk = current;
 		DECLARE_WAITQUEUE(wait, tsk);
 
+		run_task_queue(&tq_disk);
+
+		__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 		add_wait_queue(&page->wait, &wait);
-		tsk->state = TASK_UNINTERRUPTIBLE;
 
-		run_task_queue(&tq_disk);
 		if (PageLocked(page))
 			schedule();
-		tsk->state = TASK_RUNNING;
+		__set_task_state(tsk, TASK_RUNNING);
 		remove_wait_queue(&page->wait, &wait);
 
 		/*
@@ -681,13 +690,14 @@
 		struct task_struct *tsk = current;
 		DECLARE_WAITQUEUE(wait, tsk);
 
+		run_task_queue(&tq_disk);
+
+		__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 		add_wait_queue(&page->wait, &wait);
-		tsk->state = TASK_UNINTERRUPTIBLE;
 
-		run_task_queue(&tq_disk);
 		if (PageLocked(page))
 			schedule();
-		tsk->state = TASK_RUNNING;
+		__set_task_state(tsk, TASK_RUNNING);
 		remove_wait_queue(&page->wait, &wait);
 
 		/*
@@ -937,23 +947,6 @@
 	return;
 }
 
-/*
- * "descriptor" for what we're up to with a read.
- * This allows us to use the same read code yet
- * have multiple different users of the data that
- * we read from a file.
- *
- * The simplest case just copies the data to user
- * mode.
- */
-typedef struct {
-	size_t written;
-	size_t count;
-	char * buf;
-	int error;
-} read_descriptor_t;
-
-typedef int (*read_actor_t)(read_descriptor_t *, const char *, unsigned long);
 
 /*
  * This is a generic file read routine, and uses the
@@ -963,7 +956,7 @@
  * This is really ugly. But the goto's actually try to clarify some
  * of the logic when it comes to error handling etc.
  */
-static void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc, read_actor_t actor)
+void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc, read_actor_t actor)
 {
 	struct dentry *dentry = filp->f_dentry;
 	struct inode *inode = dentry->d_inode;
diff -u --recursive --new-file v2.3.15/linux/mm/memory.c linux/mm/memory.c
--- v2.3.15/linux/mm/memory.c	Thu Aug 26 13:05:42 1999
+++ linux/mm/memory.c	Thu Aug 26 12:34:55 1999
@@ -31,6 +31,9 @@
 /*
  * 05.04.94  -  Multi-page memory management added for v1.1.
  * 		Idea by Alex Bligh (alex@cconcepts.co.uk)
+ *
+ * 16.07.99  -  Support of BIGMEM added by Gerhard Wichert, Siemens AG
+ *		(Gerhard.Wichert@pdb.siemens.de)
  */
 
 #include <linux/mm.h>
@@ -40,6 +43,7 @@
 #include <linux/smp_lock.h>
 #include <linux/swapctl.h>
 #include <linux/iobuf.h>
+#include <linux/bigmem.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -56,10 +60,10 @@
 static inline void copy_cow_page(unsigned long from, unsigned long to)
 {
 	if (from == ZERO_PAGE(to)) {
-		clear_page(to);
+		clear_bigpage(to);
 		return;
 	}
-	copy_page(to, from);
+	copy_bigpage(to, from);
 }
 
 mem_map_t * mem_map = NULL;
@@ -809,7 +813,7 @@
 	 * Ok, we need to copy. Oh, well..
 	 */
 	spin_unlock(&tsk->mm->page_table_lock);
-	new_page = __get_free_page(GFP_USER);
+	new_page = __get_free_page(GFP_BIGUSER);
 	if (!new_page)
 		return -1;
 	spin_lock(&tsk->mm->page_table_lock);
@@ -996,6 +1000,8 @@
 	set_bit(PG_swap_entry, &page->flags);
 	if (write_access && !is_page_shared(page)) {
 		delete_from_swap_cache(page);
+		page = replace_with_bigmem(page);
+		pte = mk_pte(page_address(page), vma->vm_page_prot);
 		pte = pte_mkwrite(pte_mkdirty(pte));
 	}
 	set_pte(page_table, pte);
@@ -1011,10 +1017,10 @@
 {
 	pte_t entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot));
 	if (write_access) {
-		unsigned long page = __get_free_page(GFP_USER);
+		unsigned long page = __get_free_page(GFP_BIGUSER);
 		if (!page)
 			return -1;
-		clear_page(page);
+		clear_bigpage(page);
 		entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
 		vma->vm_mm->rss++;
 		tsk->min_flt++;
diff -u --recursive --new-file v2.3.15/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.3.15/linux/mm/page_alloc.c	Mon Aug  9 11:37:05 1999
+++ linux/mm/page_alloc.c	Mon Aug 30 13:53:25 1999
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  *  Swap reorganised 29.12.95, Stephen Tweedie
+ *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
  */
 
 #include <linux/config.h>
@@ -13,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/pagemap.h>
+#include <linux/bigmem.h> /* export bigmem vars */
 
 #include <asm/dma.h>
 #include <asm/uaccess.h> /* for copy_to/from_user */
@@ -20,6 +22,8 @@
 
 int nr_swap_pages = 0;
 int nr_free_pages = 0;
+int nr_lru_pages;
+LIST_HEAD(lru_cache);
 
 /*
  * Free area management
@@ -45,7 +49,12 @@
 
 #define memory_head(x) ((struct page *)(x))
 
+#ifdef CONFIG_BIGMEM
+#define BIGMEM_LISTS_OFFSET	NR_MEM_LISTS
+static struct free_area_struct free_area[NR_MEM_LISTS*2];
+#else
 static struct free_area_struct free_area[NR_MEM_LISTS];
+#endif
 
 static inline void init_mem_queue(struct free_area_struct * head)
 {
@@ -101,6 +110,12 @@
 
 #define list(x) (mem_map+(x))
 
+#ifdef CONFIG_BIGMEM
+	if (map_nr >= bigmem_mapnr) {
+		area += BIGMEM_LISTS_OFFSET;
+		nr_free_bigpages -= mask;
+	}
+#endif
 	map_nr &= mask;
 	nr_free_pages -= mask;
 	while (mask + (1 << (NR_MEM_LISTS-1))) {
@@ -127,7 +142,6 @@
 		if (PageLocked(page))
 			PAGE_BUG(page);
 
-		page->flags &= ~(1 << PG_referenced);
 		free_pages_ok(page - mem_map, 0);
 		return 1;
 	}
@@ -145,7 +159,6 @@
 				PAGE_BUG(map);
 			if (PageLocked(map))
 				PAGE_BUG(map);
-			map->flags &= ~(1 << PG_referenced);
 			free_pages_ok(map_nr, order);
 			return 1;
 		}
@@ -160,6 +173,29 @@
 	change_bit((index) >> (1+(order)), (area)->map)
 #define CAN_DMA(x) (PageDMA(x))
 #define ADDRESS(x) (PAGE_OFFSET + ((x) << PAGE_SHIFT))
+
+#ifdef CONFIG_BIGMEM
+#define RMQUEUEBIG(order, gfp_mask) \
+if (gfp_mask & __GFP_BIGMEM) { \
+	struct free_area_struct * area = free_area+order+BIGMEM_LISTS_OFFSET; \
+	unsigned long new_order = order; \
+	do { struct page *prev = memory_head(area), *ret = prev->next; \
+		if (memory_head(area) != ret) { \
+			unsigned long map_nr; \
+			(prev->next = ret->next)->prev = prev; \
+			map_nr = ret - mem_map; \
+			MARK_USED(map_nr, new_order, area); \
+			nr_free_pages -= 1 << order; \
+			nr_free_bigpages -= 1 << order; \
+			EXPAND(ret, map_nr, order, new_order, area); \
+			spin_unlock_irqrestore(&page_alloc_lock, flags); \
+			return ADDRESS(map_nr); \
+		} \
+		new_order++; area++; \
+	} while (new_order < NR_MEM_LISTS); \
+}
+#endif
+
 #define RMQUEUE(order, gfp_mask) \
 do { struct free_area_struct * area = free_area+order; \
      unsigned long new_order = order; \
@@ -221,6 +257,7 @@
 		int freed;
 		static int low_on_memory = 0;
 
+#ifndef CONFIG_BIGMEM
 		if (nr_free_pages > freepages.min) {
 			if (!low_on_memory)
 				goto ok_to_allocate;
@@ -231,6 +268,32 @@
 		}
 
 		low_on_memory = 1;
+#else
+		static int low_on_bigmemory = 0;
+
+		if (gfp_mask & __GFP_BIGMEM)
+		{
+			if (nr_free_pages > freepages.min) {
+				if (!low_on_bigmemory)
+					goto ok_to_allocate;
+				if (nr_free_pages >= freepages.high) {
+					low_on_bigmemory = 0;
+					goto ok_to_allocate;
+				}
+			}
+			low_on_bigmemory = 1;
+		} else {
+			if (nr_free_pages-nr_free_bigpages > freepages.min) {
+				if (!low_on_memory)
+					goto ok_to_allocate;
+				if (nr_free_pages-nr_free_bigpages >= freepages.high) {
+					low_on_memory = 0;
+					goto ok_to_allocate;
+				}
+			}
+			low_on_memory = 1;
+		}
+#endif
 		current->flags |= PF_MEMALLOC;
 		freed = try_to_free_pages(gfp_mask);
 		current->flags &= ~PF_MEMALLOC;
@@ -240,6 +303,9 @@
 	}
 ok_to_allocate:
 	spin_lock_irqsave(&page_alloc_lock, flags);
+#ifdef CONFIG_BIGMEM
+	RMQUEUEBIG(order, gfp_mask);
+#endif
 	RMQUEUE(order, gfp_mask);
 	spin_unlock_irqrestore(&page_alloc_lock, flags);
 
@@ -267,9 +333,12 @@
  	unsigned long order, flags;
  	unsigned long total = 0;
 
-	printk("Free pages:      %6dkB\n ( ",nr_free_pages<<(PAGE_SHIFT-10));
-	printk("Free: %d (%d %d %d)\n",
+	printk("Free pages:      %6dkB (%6dkB BigMem)\n ( ",
+		nr_free_pages<<(PAGE_SHIFT-10),
+		nr_free_bigpages<<(PAGE_SHIFT-10));
+	printk("Free: %d, lru_cache: %d (%d %d %d)\n",
 		nr_free_pages,
+		nr_lru_pages,
 		freepages.min,
 		freepages.low,
 		freepages.high);
@@ -280,6 +349,13 @@
 		for (tmp = free_area[order].next ; tmp != memory_head(free_area+order) ; tmp = tmp->next) {
 			nr ++;
 		}
+#ifdef CONFIG_BIGMEM
+		for (tmp = free_area[BIGMEM_LISTS_OFFSET+order].next;
+		     tmp != memory_head(free_area+BIGMEM_LISTS_OFFSET+order);
+		     tmp = tmp->next) {
+			nr ++;
+		}
+#endif
 		total += nr * ((PAGE_SIZE>>10) << order);
 		printk("%lu*%lukB ", nr, (unsigned long)((PAGE_SIZE>>10) << order));
 	}
@@ -333,6 +409,9 @@
 	for (i = 0 ; i < NR_MEM_LISTS ; i++) {
 		unsigned long bitmap_size;
 		init_mem_queue(free_area+i);
+#ifdef CONFIG_BIGMEM
+		init_mem_queue(free_area+BIGMEM_LISTS_OFFSET+i);
+#endif
 		mask += mask;
 		end_mem = (end_mem + ~mask) & mask;
 		bitmap_size = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT + i);
@@ -341,6 +420,11 @@
 		free_area[i].map = (unsigned int *) start_mem;
 		memset((void *) start_mem, 0, bitmap_size);
 		start_mem += bitmap_size;
+#ifdef CONFIG_BIGMEM
+		free_area[BIGMEM_LISTS_OFFSET+i].map = (unsigned int *) start_mem;
+		memset((void *) start_mem, 0, bitmap_size);
+		start_mem += bitmap_size;
+#endif
 	}
 	return start_mem;
 }
diff -u --recursive --new-file v2.3.15/linux/mm/page_io.c linux/mm/page_io.c
--- v2.3.15/linux/mm/page_io.c	Wed Aug 18 10:49:38 1999
+++ linux/mm/page_io.c	Thu Aug 26 18:41:46 1999
@@ -33,7 +33,7 @@
  * that shared pages stay shared while being swapped.
  */
 
-static void rw_swap_page_base(int rw, unsigned long entry, struct page *page, int wait, int dolock)
+static void rw_swap_page_base(int rw, unsigned long entry, struct page *page, int wait)
 {
 	unsigned long type, offset;
 	struct swap_info_struct * p;
@@ -88,7 +88,6 @@
 	} else
 		kstat.pswpout++;
 
-	get_page(page);
 	if (p->swap_device) {
 		zones[0] = offset;
 		zones_used = 1;
@@ -111,18 +110,12 @@
 		dev = swapf->i_dev;
 	} else {
 		printk(KERN_ERR "rw_swap_page: no swap file or device\n");
-		put_page(page);
 		return;
 	}
  	if (!wait) {
  		set_bit(PG_decr_after, &page->flags);
  		atomic_inc(&nr_async_pages);
  	}
- 	if (dolock) {
- 		set_bit(PG_free_swap_after, &page->flags);
-		p->swap_map[offset]++;
- 	}
- 	set_bit(PG_free_after, &page->flags);
 
  	/* block_size == PAGE_SIZE/zones_used */
  	brw_page(rw, page, dev, zones, block_size, 0);
@@ -164,11 +157,10 @@
 		PAGE_BUG(page);
 	if (page->inode != &swapper_inode)
 		PAGE_BUG(page);
-	rw_swap_page_base(rw, entry, page, wait, 1);
+	rw_swap_page_base(rw, entry, page, wait);
 }
 
 /*
- * shmfs needs a version that doesn't put the page in the page cache!
  * The swap lock map insists that pages be in the page cache!
  * Therefore we can't use it.  Later when we can remove the need for the
  * lock map and we can reduce the number of functions exported.
@@ -181,5 +173,5 @@
 		PAGE_BUG(page);
 	if (PageSwapCache(page))
 		PAGE_BUG(page);
-	rw_swap_page_base(rw, entry, page, wait, 0);
+	rw_swap_page_base(rw, entry, page, wait);
 }
diff -u --recursive --new-file v2.3.15/linux/mm/slab.c linux/mm/slab.c
--- v2.3.15/linux/mm/slab.c	Sat Aug  7 13:00:25 1999
+++ linux/mm/slab.c	Thu Aug 26 12:37:07 1999
@@ -993,8 +993,7 @@
 	/* Find the cache in the chain of caches. */
 	down(&cache_chain_sem);
 	for (searchp = &cache_cache; searchp->c_nextp != &cache_cache;
-	     searchp = searchp->c_nextp)
-	{
+	     searchp = searchp->c_nextp) {
 		if (searchp->c_nextp != cachep)
 			continue;
 
@@ -1054,8 +1053,7 @@
 		return 2;
 	}
 
-	if (!is_chained_kmem_cache(cachep))
-	{
+	if (!is_chained_kmem_cache(cachep)) {
 		printk(KERN_ERR "kmem_shrink: Invalid cache addr %p\n",
 		       cachep);
 		return 2;
@@ -1087,8 +1085,7 @@
 	/* Find the cache in the chain of caches. */
 	down(&cache_chain_sem);
 	for (prev = &cache_cache; prev->c_nextp != &cache_cache;
-	     prev = prev->c_nextp)
-	{
+	     prev = prev->c_nextp) {
 		if (prev->c_nextp != cachep)
 			continue;
 
@@ -1104,15 +1101,13 @@
 	}
 	up(&cache_chain_sem);
 
-	if (!ret)
-	{
+	if (!ret) {
 		printk(KERN_ERR "kmem_destroy: Invalid cache addr %p\n",
 		       cachep);
 		return 1;
 	}
 
-	if (__kmem_cache_shrink(cachep))
-	{
+	if (__kmem_cache_shrink(cachep)) {
 		printk(KERN_ERR "kmem_destroy: Can't free all objects %p\n",
 		       cachep);
 		down(&cache_chain_sem);
diff -u --recursive --new-file v2.3.15/linux/mm/swap_state.c linux/mm/swap_state.c
--- v2.3.15/linux/mm/swap_state.c	Mon Aug  9 10:27:50 1999
+++ linux/mm/swap_state.c	Mon Aug 30 13:47:18 1999
@@ -214,8 +214,6 @@
 		   page_address(page), page_count(page));
 #endif
 	PageClearSwapCache(page);
-	if (inode->i_op->flushpage)
-		inode->i_op->flushpage(inode, page, 0);
 	remove_inode_page(page);
 }
 
@@ -239,6 +237,15 @@
 	swap_free (entry);
 }
 
+static void delete_from_swap_cache_nolock(struct page *page)
+{
+	if (!swapper_inode.i_op->flushpage ||
+	    swapper_inode.i_op->flushpage(&swapper_inode, page, 0))
+		lru_cache_del(page);
+
+	__delete_from_swap_cache(page);
+}
+
 /*
  * This must be called only on pages that have
  * been verified to be in the swap cache.
@@ -247,7 +254,7 @@
 {
 	lock_page(page);
 
-	__delete_from_swap_cache(page);
+	delete_from_swap_cache_nolock(page);
 
 	UnlockPage(page);
 	page_cache_release(page);
@@ -267,9 +274,7 @@
 	 */
 	lock_page(page);
 	if (PageSwapCache(page) && !is_page_shared(page)) {
-		long entry = page->offset;
-		remove_from_swap_cache(page);
-		swap_free(entry);
+		delete_from_swap_cache_nolock(page);
 		page_cache_release(page);
 	}
 	UnlockPage(page);
diff -u --recursive --new-file v2.3.15/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.3.15/linux/mm/swapfile.c	Thu Aug 26 13:05:42 1999
+++ linux/mm/swapfile.c	Thu Aug 26 12:47:12 1999
@@ -46,16 +46,36 @@
 		}
 	}
 	si->cluster_nr = SWAPFILE_CLUSTER;
+
+	/* try to find an empty (even not aligned) cluster. */
+	offset = si->lowest_bit;
+ check_next_cluster:
+	if (offset+SWAPFILE_CLUSTER-1 <= si->highest_bit)
+	{
+		int nr;
+		for (nr = offset; nr < offset+SWAPFILE_CLUSTER; nr++)
+			if (si->swap_map[nr])
+			{
+				offset = nr+1;
+				goto check_next_cluster;
+			}
+		/* We found a completly empty cluster, so start
+		 * using it.
+		 */
+		goto got_page;
+	}
+	/* No luck, so now go finegrined as usual. -Andrea */
 	for (offset = si->lowest_bit; offset <= si->highest_bit ; offset++) {
 		if (si->swap_map[offset])
 			continue;
-		si->lowest_bit = offset;
-got_page:
-		si->swap_map[offset] = 1;
-		nr_swap_pages--;
+	got_page:
+		if (offset == si->lowest_bit)
+			si->lowest_bit++;
 		if (offset == si->highest_bit)
 			si->highest_bit--;
-		si->cluster_next = offset;
+		si->swap_map[offset] = 1;
+		nr_swap_pages--;
+		si->cluster_next = offset+1;
 		return offset;
 	}
 	return 0;
@@ -81,12 +101,9 @@
 				entry = SWP_ENTRY(type,offset);
 				type = swap_info[type].next;
 				if (type < 0 ||
-					p->prio != swap_info[type].prio) 
-				{
+					p->prio != swap_info[type].prio) {
 						swap_list.next = swap_list.head;
-				}
-				else
-				{
+				} else {
 					swap_list.next = type;
 				}
 				return entry;
@@ -129,8 +146,7 @@
 	if (!p->swap_map[offset])
 		goto bad_free;
 	if (p->swap_map[offset] < SWAP_MAP_MAX) {
-		if (!--p->swap_map[offset])
-		{
+		if (!--p->swap_map[offset]) {
 			if (offset < p->lowest_bit)
 				p->lowest_bit = offset;
 			if (offset > p->highest_bit)
diff -u --recursive --new-file v2.3.15/linux/mm/vmalloc.c linux/mm/vmalloc.c
--- v2.3.15/linux/mm/vmalloc.c	Wed Apr 21 23:12:32 1999
+++ linux/mm/vmalloc.c	Thu Aug 26 12:34:55 1999
@@ -2,6 +2,7 @@
  *  linux/mm/vmalloc.c
  *
  *  Copyright (C) 1993  Linus Torvalds
+ *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
  */
 
 #include <linux/malloc.h>
@@ -94,7 +95,7 @@
 		unsigned long page;
 		if (!pte_none(*pte))
 			printk("alloc_area_pte: page already exists\n");
-		page = __get_free_page(GFP_KERNEL);
+		page = __get_free_page(GFP_KERNEL|GFP_BIGMEM);
 		if (!page)
 			return -ENOMEM;
 		set_pte(pte, mk_pte(page, PAGE_KERNEL));
diff -u --recursive --new-file v2.3.15/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.3.15/linux/mm/vmscan.c	Mon Aug 16 17:54:49 1999
+++ linux/mm/vmscan.c	Mon Aug 30 13:47:18 1999
@@ -17,6 +17,7 @@
 #include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
+#include <linux/bigmem.h>
 
 #include <asm/pgtable.h>
 
@@ -63,7 +64,8 @@
 
 	if (PageReserved(page)
 	    || PageLocked(page)
-	    || ((gfp_mask & __GFP_DMA) && !PageDMA(page)))
+	    || ((gfp_mask & __GFP_DMA) && !PageDMA(page))
+	    || (!(gfp_mask & __GFP_BIGMEM) && PageBIGMEM(page)))
 		goto out_failed_unlock;
 
 	/*
@@ -154,6 +156,9 @@
 	if (!entry)
 		goto out_failed_unlock; /* No swap space left */
 		
+	if (!(page = prepare_bigmem_swapout(page)))
+		goto out_swap_free_unlock;
+
 	vma->vm_mm->rss--;
 	set_pte(page_table, __pte(entry));
 	spin_unlock(&vma->vm_mm->page_table_lock);
@@ -174,6 +179,11 @@
 	spin_unlock(&vma->vm_mm->page_table_lock);
 out_failed:
 	return 0;
+out_swap_free_unlock:
+	swap_free(entry);
+	spin_unlock(&vma->vm_mm->page_table_lock);
+	return 0;
+
 }
 
 /*
@@ -316,7 +326,9 @@
 {
 	struct task_struct * p;
 	int counter;
+	int __ret = 0;
 
+	lock_kernel();
 	/* 
 	 * We make one or two passes through the task list, indexed by 
 	 * assign = {0, 1}:
@@ -379,11 +391,13 @@
 
 			if (ret < 0)
 				kill_proc(pid, SIGBUS, 1);
-			return 1;
+			__ret = 1;
+			goto out;
 		}
 	}
 out:
-	return 0;
+	unlock_kernel();
+	return __ret;
 }
 
 /*
@@ -400,8 +414,6 @@
 	int priority;
 	int count = SWAP_CLUSTER_MAX;
 
-	lock_kernel();
-
 	/* Always trim SLAB caches when memory gets low. */
 	kmem_cache_reap(gfp_mask);
 
@@ -429,7 +441,6 @@
 		shrink_dcache_memory(priority, gfp_mask);
 	} while (--priority >= 0);
 done:
-	unlock_kernel();
 
 	return priority >= 0;
 }
@@ -484,7 +495,9 @@
 		 * up on a more timely basis.
 		 */
 		do {
-			if (nr_free_pages >= freepages.high)
+			/* kswapd is critical to provide GFP_ATOMIC
+			   allocations (not GFP_BIGMEM ones). */
+			if (nr_free_pages - nr_free_bigpages >= freepages.high)
 				break;
 
 			if (!do_try_to_free_pages(GFP_KSWAPD))
diff -u --recursive --new-file v2.3.15/linux/net/Config.in linux/net/Config.in
--- v2.3.15/linux/net/Config.in	Thu Aug 26 13:05:42 1999
+++ linux/net/Config.in	Mon Aug 30 11:12:56 1999
@@ -12,7 +12,7 @@
   bool 'Routing messages' CONFIG_RTNETLINK
   tristate 'Netlink device emulation' CONFIG_NETLINK_DEV
 fi
-bool 'Network packet filtering' CONFIG_NETFILTER
+bool 'Network packet filtering (replaces ipchains)' CONFIG_NETFILTER
 if [ "$CONFIG_NETFILTER" = "y" ]; then
   bool 'Network packet filtering debugging' CONFIG_NETFILTER_DEBUG
 fi
diff -u --recursive --new-file v2.3.15/linux/net/atm/proc.c linux/net/atm/proc.c
--- v2.3.15/linux/net/atm/proc.c	Thu Aug 26 13:05:42 1999
+++ linux/net/atm/proc.c	Thu Aug 26 14:13:59 1999
@@ -31,7 +31,7 @@
 #include <linux/atmclip.h>
 #include <linux/atmarp.h>
 #include <linux/if_arp.h>
-#include <linux/init.h> /* for __initfunc */
+#include <linux/init.h> /* for __init */
 #include <asm/uaccess.h>
 #include <asm/param.h> /* for HZ */
 #include "resources.h"
@@ -596,7 +596,7 @@
 }
 
 
-__initfunc(int atm_proc_init(void))
+int __init atm_proc_init(void)
 {
 	int error;
 
diff -u --recursive --new-file v2.3.15/linux/net/atm/pvc.c linux/net/atm/pvc.c
--- v2.3.15/linux/net/atm/pvc.c	Thu Aug 26 13:05:42 1999
+++ linux/net/atm/pvc.c	Thu Aug 26 14:13:59 1999
@@ -139,7 +139,7 @@
  */
 
 
-__initfunc(void atmpvc_proto_init(struct net_proto *pro))
+void __init atmpvc_proto_init(struct net_proto *pro)
 {
 	int error;
 
diff -u --recursive --new-file v2.3.15/linux/net/atm/svc.c linux/net/atm/svc.c
--- v2.3.15/linux/net/atm/svc.c	Thu Aug 26 13:05:42 1999
+++ linux/net/atm/svc.c	Thu Aug 26 14:13:59 1999
@@ -386,7 +386,7 @@
  *	Initialize the ATM SVC protocol family
  */
 
-__initfunc(void atmsvc_proto_init(struct net_proto *pro))
+void __init atmsvc_proto_init(struct net_proto *pro)
 {
 	if (sock_register(&svc_family_ops) < 0) {
 		printk(KERN_ERR "ATMSVC: can't register");
diff -u --recursive --new-file v2.3.15/linux/net/bridge/br.c linux/net/bridge/br.c
--- v2.3.15/linux/net/bridge/br.c	Thu Aug 26 13:05:45 1999
+++ linux/net/bridge/br.c	Thu Aug 26 14:11:21 1999
@@ -839,7 +839,7 @@
 	br_tree_get_info
 };
 #endif
-__initfunc(void br_init(void))
+void __init br_init(void)
 {						  /* (4.8.1)	 */
 	int port_no;
 
diff -u --recursive --new-file v2.3.15/linux/net/core/datagram.c linux/net/core/datagram.c
--- v2.3.15/linux/net/core/datagram.c	Thu Aug 26 13:05:45 1999
+++ linux/net/core/datagram.c	Tue Aug 31 11:30:48 1999
@@ -65,10 +65,8 @@
 
 	DECLARE_WAITQUEUE(wait, current);
 
+	__set_current_state(TASK_INTERRUPTIBLE);
 	add_wait_queue(sk->sleep, &wait);
-	current->state = TASK_INTERRUPTIBLE;
-
-	barrier();
 
 	/* Socket errors? */
 	error = sock_error(sk);
diff -u --recursive --new-file v2.3.15/linux/net/core/dev.c linux/net/core/dev.c
--- v2.3.15/linux/net/core/dev.c	Thu Aug 26 13:05:45 1999
+++ linux/net/core/dev.c	Tue Aug 31 11:23:03 1999
@@ -1933,8 +1933,9 @@
 		return 0;
 	}
 
-	if (atomic_dec_and_test(&dev->refcnt)) {
-		netdev_finish_unregister(dev);
+	/* Last reference is our one */
+	if (atomic_read(&dev->refcnt) == 1) {
+		dev_put(dev);
 		return 0;
 	}
 
@@ -1942,16 +1943,46 @@
 	printk("unregister_netdevice: waiting %s refcnt=%d\n", dev->name, atomic_read(&dev->refcnt));
 #endif
 
+	/* EXPLANATION. If dev->refcnt is not 1 now (1 is our own reference)
+	   it means that someone in the kernel still has reference
+	   to this device and we cannot release it.
+
+	   "New style" devices have destructors, hence we can return from this
+	   function and destructor will do all the work later.
+
+	   "Old style" devices expect that device is free of any references
+	   upon exit from this function. WE CANNOT MAKE such release
+	   without delay. Note that it is not new feature. Referencing devices
+	   after they are released occured in 2.0 and 2.2.
+	   Now we just can know about each fact of illegal usage.
+
+	   So, we linger for 10*HZ (it is an arbitrary number)
+
+	   After 1 second, we start to rebroadcast unregister notifications
+	   in hope that careless clients will release the device.
+
+	   If timeout expired, we have no choice how to cross fingers
+	   and return. Real alternative would be block here forever
+	   and we will make it eventually, when all peaceful citizens
+	   will be notified and repaired.
+	 */
+
 	now = jiffies;
-	while (atomic_read(&dev->refcnt)) {
-		schedule_timeout(HZ/10);
+	while (atomic_read(&dev->refcnt) != 1) {
+		if ((jiffies - now) > 1*HZ) {
+			/* Rebroadcast unregister notification */
+			notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
+		}
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(HZ/4);
+		current->state = TASK_RUNNING;
 		if ((jiffies - now) > 10*HZ)
 			break;
 	}
 
-	if (atomic_read(&dev->refcnt))
-		printk("unregister_netdevice: Old style device %s leaked(refcnt=%d). Wait for crash.\n", dev->name, atomic_read(&dev->refcnt));
-
+	if (atomic_read(&dev->refcnt) != 1)
+		printk("unregister_netdevice: Old style device %s leaked(refcnt=%d). Wait for crash.\n", dev->name, atomic_read(&dev->refcnt)-1);
+	dev_put(dev);
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.15/linux/net/core/dst.c linux/net/core/dst.c
--- v2.3.15/linux/net/core/dst.c	Thu Aug 26 13:05:45 1999
+++ linux/net/core/dst.c	Tue Aug 31 11:23:03 1999
@@ -174,8 +174,27 @@
 		spin_lock_bh(&dst_lock);
 		for (dst = dst_garbage_list; dst; dst = dst->next) {
 			if (dst->dev == dev) {
-				dst->input = dst_discard;
-				dst->output = dst_blackhole;
+				/* Dirty hack. We did it in 2.2 (in __dst_free),
+				   we have _very_ good reasons not to repeat
+				   this mistake in 2.3, but we have no choice
+				   now. _It_ _is_ _explicit_ _deliberate_
+				   _race_ _condition_.
+				 */
+				if (event!=NETDEV_DOWN && !dev->new_style &&
+				    dst->output == dst_blackhole) {
+					dst->dev = &loopback_dev;
+					dev_put(dev);
+					dev_hold(&loopback_dev);
+					dst->output = dst_discard;
+					if (dst->neighbour && dst->neighbour->dev == dev) {
+						dst->neighbour->dev = &loopback_dev;
+						dev_put(dev);
+						dev_hold(&loopback_dev);
+					}
+				} else {
+					dst->input = dst_discard;
+					dst->output = dst_blackhole;
+				}
 			}
 		}
 		spin_unlock_bh(&dst_lock);
diff -u --recursive --new-file v2.3.15/linux/net/core/filter.c linux/net/core/filter.c
--- v2.3.15/linux/net/core/filter.c	Thu Aug 26 13:05:45 1999
+++ linux/net/core/filter.c	Tue Aug 31 11:23:03 1999
@@ -49,7 +49,7 @@
 	else if (k>=SKF_LL_OFF)
 		ptr = skb->mac.raw + k - SKF_LL_OFF;
 
-	if (ptr<skb->head && ptr < skb->tail)
+	if (ptr >= skb->head && ptr < skb->tail)
 		return ptr;
 	return NULL;
 }
@@ -248,6 +248,7 @@
 						continue;
 					}
 				}
+				return 0;
 
 			case BPF_LD|BPF_W|BPF_LEN:
 				A = len;
diff -u --recursive --new-file v2.3.15/linux/net/core/netfilter.c linux/net/core/netfilter.c
--- v2.3.15/linux/net/core/netfilter.c	Thu Aug 26 13:05:45 1999
+++ linux/net/core/netfilter.c	Thu Aug 26 14:06:34 1999
@@ -583,7 +583,7 @@
 }
 #endif /* CONFIG_NETFILTER_DEBUG */
 
-__initfunc(void netfilter_init(void))
+void __init netfilter_init(void)
 {
 	int i, h;
 
diff -u --recursive --new-file v2.3.15/linux/net/core/sock.c linux/net/core/sock.c
--- v2.3.15/linux/net/core/sock.c	Thu Aug 26 13:05:45 1999
+++ linux/net/core/sock.c	Tue Aug 31 11:30:48 1999
@@ -672,7 +672,7 @@
 	for (;;) {
 		if (signal_pending(current))
 			break;
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (atomic_read(&sk->wmem_alloc) < sk->sndbuf)
 			break;
 		if (sk->shutdown & SEND_SHUTDOWN)
@@ -681,7 +681,7 @@
 			break;
 		schedule();
 	}
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(sk->sleep, &wait);
 }
 
diff -u --recursive --new-file v2.3.15/linux/net/decnet/Makefile linux/net/decnet/Makefile
--- v2.3.15/linux/net/decnet/Makefile	Wed May 26 09:36:36 1999
+++ linux/net/decnet/Makefile	Tue Aug 31 11:23:03 1999
@@ -12,10 +12,6 @@
 O_OBJS += dn_raw.o
 endif
 
-#ifeq ($(CONFIG_DECNET_MOP),y)
-#O_OBJS += dn_mop.o
-#endif
-
 ifeq ($(CONFIG_DECNET_FW),y)
 O_OBJS += dn_fw.o
 endif
diff -u --recursive --new-file v2.3.15/linux/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c
--- v2.3.15/linux/net/decnet/af_decnet.c	Thu Aug 26 13:05:45 1999
+++ linux/net/decnet/af_decnet.c	Tue Aug 31 11:23:03 1999
@@ -639,7 +639,7 @@
 
 static int dn_create(struct socket *sock, int protocol)
 {
-	struct	sock	*sk;
+	struct sock *sk;
 
 	switch(sock->type) {
 		case SOCK_SEQPACKET:
@@ -651,9 +651,6 @@
 #ifdef CONFIG_DECNET_RAW
 		case SOCK_RAW:
 			if ((protocol != DNPROTO_NSP) &&
-#ifdef CONFIG_DECNET_MOP
-					(protocol != DNPROTO_MOP) &&
-#endif /* CONFIG_DECNET_MOP */
 					(protocol != DNPROTO_ROU))
 				return -EPROTONOSUPPORT;
 			break;
@@ -2116,7 +2113,7 @@
 #ifdef CONFIG_SYSCTL
 	dn_register_sysctl();
 #endif /* CONFIG_SYSCTL */
-        printk(KERN_INFO "NET4: DECnet for Linux: V.2.3.13s (C) 1995-1999 Linux DECnet Project Team\n");
+        printk(KERN_INFO "NET4: DECnet for Linux: V.2.3.15s (C) 1995-1999 Linux DECnet Project Team\n");
 
 }
 
diff -u --recursive --new-file v2.3.15/linux/net/decnet/dn_nsp_in.c linux/net/decnet/dn_nsp_in.c
--- v2.3.15/linux/net/decnet/dn_nsp_in.c	Thu Aug 26 13:05:45 1999
+++ linux/net/decnet/dn_nsp_in.c	Tue Aug 31 11:23:03 1999
@@ -20,6 +20,7 @@
  *                       Fixed various race conditions and possible nasties.
  *    Steve Whitehouse:  Now handles returned conninit frames.
  *     David S. Miller:  New socket locking
+ *    Steve Whitehouse:  Fixed lockup when socket filtering was enabled.
  */
 
 /******************************************************************************
@@ -394,16 +395,15 @@
 }
 
 /*
- * Copy of sock_queue_rcv_skb (from sock.h) to
- * queue other data segments. Also we send SIGURG here instead
- * of the normal SIGIO, 'cos its out of band data.
+ * Copy of sock_queue_rcv_skb (from sock.h) with out
+ * bh_lock_sock() (its already held when this is called) which
+ * also allows data and other data to be queued to a socket.
  */
-static __inline__ int dn_queue_other_skb(struct sock *sk, struct sk_buff *skb)
+static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig, struct sk_buff_head *queue)
 {
 #ifdef CONFIG_FILTER
 	struct sk_filter *filter;
 #endif
-	struct dn_scp *scp = &sk->protinfo.dn;
 	unsigned long flags;
 
         /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
@@ -416,24 +416,22 @@
 #ifdef CONFIG_FILTER
         if (sk->filter) {
 		int err = 0;
-		bh_lock_sock(sk);
                 if ((filter = sk->filter) != NULL && sk_filter(skb, sk->filter))
                         err = -EPERM;  /* Toss packet */
-		bh_unlock_sock(sk);
 		if (err)
 			return err;
         }
 #endif /* CONFIG_FILTER */
 
         skb_set_owner_r(skb, sk);
-        skb_queue_tail(&scp->other_receive_queue, skb);
+        skb_queue_tail(queue, skb);
 
 	read_lock_irqsave(&sk->callback_lock, flags);
         if (!sk->dead) {
 		struct socket *sock = sk->socket;
 		wake_up_interruptible(sk->sleep);
 		if (!(sock->flags & SO_WAITDATA) && sock->fasync_list)
-			kill_fasync(sock->fasync_list, SIGURG);
+			kill_fasync(sock->fasync_list, sig);
 	}
 	read_unlock_irqrestore(&sk->callback_lock, flags);
 
@@ -455,7 +453,7 @@
 
 	if (((sk->protinfo.dn.numoth_rcv + 1) & 0x0fff) == (segnum & 0x0fff)) {
 
-		if (dn_queue_other_skb(sk, skb) == 0) {
+		if (dn_queue_skb(sk, skb, SIGURG, &scp->other_receive_queue) == 0) {
 			sk->protinfo.dn.numoth_rcv++;
 			scp->other_report = 0;
 			queued = 1;
@@ -484,7 +482,7 @@
 	if (((sk->protinfo.dn.numdat_rcv + 1) & 0x0FFF) == 
                      (segnum & 0x0FFF)) {
 
-                if (sock_queue_rcv_skb(sk, skb) == 0) {
+                if (dn_queue_skb(sk, skb, SIGIO, &sk->receive_queue) == 0) {
 			sk->protinfo.dn.numdat_rcv++;
                 	queued = 1;
                 }
diff -u --recursive --new-file v2.3.15/linux/net/decnet/dn_route.c linux/net/decnet/dn_route.c
--- v2.3.15/linux/net/decnet/dn_route.c	Thu Aug 26 13:05:45 1999
+++ linux/net/decnet/dn_route.c	Tue Aug 31 11:23:03 1999
@@ -20,6 +20,8 @@
  *                                 DECnet routing design
  *              Alexey Kuznetsov : New SMP locking
  *              Steve Whitehouse : More SMP locking changes & dn_cache_dump()
+ *              Steve Whitehouse : Prerouting NF hook, now really is prerouting.
+ *				   Fixed possible skb leak in rtnetlink funcs.
  */
 
 /******************************************************************************
@@ -208,11 +210,10 @@
 	int i;
 	struct dn_route *rt, *next;
 
+	write_lock_bh(&dn_hash_lock);
 	for(i = 0; i < DN_HASHBUCKETS; i++) {
-		write_lock_bh(&dn_hash_lock);
 		if ((rt = xchg(&dn_route_cache[i], NULL)) == NULL)
 			continue;
-		write_unlock_bh(&dn_hash_lock);
 
 		for(; rt; rt=next) {
 			next = rt->u.rt_next;
@@ -220,14 +221,24 @@
 			dst_free((struct dst_entry *)rt);
 		}
 	}
+	write_unlock_bh(&dn_hash_lock);
 }
 
+static int dn_route_rx_packet(struct sk_buff *skb)
+{
+	int err;
+
+	if ((err = dn_route_input(skb)) == 0)
+		return skb->dst->input(skb);
+
+	kfree_skb(skb);
+	return err;
+}
 
 static int dn_route_rx_long(struct sk_buff *skb)
 {
 	struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
 	unsigned char *ptr = skb->data;
-	int err;
 
 	if (skb->len < 21) /* 20 for long header, 1 for shortest nsp */
 		goto drop_it;
@@ -253,8 +264,7 @@
         ptr++;
         cb->hops = *ptr++; /* Visit Count */
 
-	if ((err = dn_route_input(skb)) == 0)
-		return NF_HOOK(PF_DECnet, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, skb->dst->input);
+	return NF_HOOK(PF_DECnet, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, dn_route_rx_packet);
 
 drop_it:
 	kfree_skb(skb);
@@ -267,7 +277,6 @@
 {
 	struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
 	unsigned char *ptr = skb->data;
-	int err;
 
 	if (skb->len < 6) /* 5 for short header + 1 for shortest nsp */
 		goto drop_it;
@@ -281,8 +290,7 @@
         ptr += 2;
         cb->hops = *ptr & 0x3f;
 
-	if ((err = dn_route_input(skb)) == 0)
-		return NF_HOOK(PF_DECnet, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, skb->dst->input);
+	return NF_HOOK(PF_DECnet, NF_DN_PRE_ROUTING, skb, skb->dev, NULL, dn_route_rx_packet);
 
 drop_it:
         kfree_skb(skb);
@@ -836,10 +844,8 @@
 		dev_put(skb->dev);
 	skb->dev = NULL;
 	skb->rx_dev = NULL;
-	if (err) {
-		kfree_skb(skb);
-		return err;
-	}
+	if (err)
+		goto out_free;
 	skb->dst = &rt->u.dst;
 
 	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
@@ -847,12 +853,18 @@
 	err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0);
 
 	if (err == 0)
-		return 0;
-	if (err < 0)
-		return -EMSGSIZE;
+		goto out_free;
+	if (err < 0) {
+		err = -EMSGSIZE;
+		goto out_free;
+	}
 
 	err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
 
+	return err;
+
+out_free:
+	kfree_skb(skb);
 	return err;
 }
 
diff -u --recursive --new-file v2.3.15/linux/net/econet/econet.c linux/net/econet/econet.c
--- v2.3.15/linux/net/econet/econet.c	Thu Aug 26 13:05:45 1999
+++ linux/net/econet/econet.c	Thu Aug 26 14:13:59 1999
@@ -1008,7 +1008,7 @@
 	mod_timer(&ab_cleanup_timer, jiffies + (HZ*2));
 }
 
-__initfunc(static int aun_udp_initialise(void))
+static int __init aun_udp_initialise(void)
 {
 	int error;
 	struct sockaddr_in sin;
@@ -1106,7 +1106,7 @@
 
 int init_module(void)
 #else
-__initfunc(void econet_proto_init(struct net_proto *pro))
+void __init econet_proto_init(struct net_proto *pro)
 #endif
 {
 	spin_lock_init(&edevlist_lock);
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.3.15/linux/net/ipv4/af_inet.c	Thu Aug 26 13:05:45 1999
+++ linux/net/ipv4/af_inet.c	Tue Aug 31 11:30:48 1999
@@ -5,7 +5,7 @@
  *
  *		PF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.94 1999/08/20 11:04:51 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.95 1999/08/30 10:17:00 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -564,13 +564,9 @@
 {
 	DECLARE_WAITQUEUE(wait, current);
 
+	__set_current_state(TASK_INTERRUPTIBLE);
 	add_wait_queue(sk->sleep, &wait);
-	current->state = TASK_INTERRUPTIBLE;
 
-	/* RED-PEN. current->state is volatile. Is it enough to prevent
-	 * reordering it and sk->state check? I put barrier to be sure.
-	 */
-	barrier();
 	while ((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV)) {
 		if (signal_pending(current))
 			break;
@@ -579,10 +575,9 @@
 		release_sock(sk);
 		schedule();
 		lock_sock(sk);
-		current->state = TASK_INTERRUPTIBLE;
-		barrier();
+		set_current_state(TASK_INTERRUPTIBLE);
 	}
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(sk->sleep, &wait);
 }
 
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.3.15/linux/net/ipv4/arp.c	Thu Aug 26 13:05:45 1999
+++ linux/net/ipv4/arp.c	Tue Aug 31 11:23:03 1999
@@ -1,6 +1,6 @@
 /* linux/net/inet/arp.c
  *
- * Version:	$Id: arp.c,v 1.80 1999/08/20 11:04:54 davem Exp $
+ * Version:	$Id: arp.c,v 1.81 1999/08/30 10:17:05 davem Exp $
  *
  * Copyright (C) 1994 by Florian  La Roche
  *
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.3.15/linux/net/ipv4/devinet.c	Thu Aug 26 13:05:45 1999
+++ linux/net/ipv4/devinet.c	Tue Aug 31 11:23:03 1999
@@ -1,7 +1,7 @@
 /*
  *	NET3	IP device support routines.
  *
- *	Version: $Id: devinet.c,v 1.34 1999/08/20 11:04:57 davem Exp $
+ *	Version: $Id: devinet.c,v 1.35 1999/08/31 07:03:20 davem Exp $
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -1127,7 +1127,7 @@
 }
 #endif
 
-__initfunc(void devinet_init(void))
+void __init devinet_init(void)
 {
 	register_gifconf(PF_INET, inet_gifconf);
 	register_netdevice_notifier(&ip_netdev_notifier);
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v2.3.15/linux/net/ipv4/fib_frontend.c	Thu Aug 26 13:05:45 1999
+++ linux/net/ipv4/fib_frontend.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *
  *		IPv4 Forwarding Information Base: FIB frontend.
  *
- * Version:	$Id: fib_frontend.c,v 1.18 1999/08/20 11:04:59 davem Exp $
+ * Version:	$Id: fib_frontend.c,v 1.19 1999/08/31 07:03:23 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
@@ -645,7 +645,7 @@
 	0
 };
 
-__initfunc(void ip_fib_init(void))
+void __init ip_fib_init(void)
 {
 #ifdef CONFIG_PROC_FS
 	proc_net_register(&(struct proc_dir_entry) {
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/fib_hash.c linux/net/ipv4/fib_hash.c
--- v2.3.15/linux/net/ipv4/fib_hash.c	Thu Aug 26 13:05:45 1999
+++ linux/net/ipv4/fib_hash.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *
  *		IPv4 FIB: lookup engine and maintenance routines.
  *
- * Version:	$Id: fib_hash.c,v 1.11 1999/08/20 11:05:01 davem Exp $
+ * Version:	$Id: fib_hash.c,v 1.12 1999/08/31 07:03:27 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
@@ -899,7 +899,7 @@
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 struct fib_table * fib_hash_init(int id)
 #else
-__initfunc(struct fib_table * fib_hash_init(int id))
+struct fib_table * __init fib_hash_init(int id)
 #endif
 {
 	struct fib_table *tb;
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/fib_rules.c linux/net/ipv4/fib_rules.c
--- v2.3.15/linux/net/ipv4/fib_rules.c	Thu Aug 26 13:05:45 1999
+++ linux/net/ipv4/fib_rules.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *
  *		IPv4 Forwarding Information Base: policy rules.
  *
- * Version:	$Id: fib_rules.c,v 1.13 1999/08/20 11:05:05 davem Exp $
+ * Version:	$Id: fib_rules.c,v 1.14 1999/08/31 07:03:29 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
@@ -448,7 +448,7 @@
 
 #endif /* CONFIG_RTNETLINK */
 
-__initfunc(void fib_rules_init(void))
+void __init fib_rules_init(void)
 {
 	register_netdevice_notifier(&fib_rules_notifier);
 }
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.3.15/linux/net/ipv4/icmp.c	Thu Aug 26 13:05:45 1999
+++ linux/net/ipv4/icmp.c	Tue Aug 31 11:23:03 1999
@@ -3,7 +3,7 @@
  *	
  *		Alan Cox, <alan@redhat.com>
  *
- *	Version: $Id: icmp.c,v 1.60 1999/08/20 11:05:10 davem Exp $
+ *	Version: $Id: icmp.c,v 1.61 1999/08/31 07:03:33 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -1129,7 +1129,7 @@
  { &icmp_statistics.IcmpOutAddrMaskReps, &icmp_statistics.IcmpInAddrMaskReps, icmp_address_reply, 0, }
 };
 
-__initfunc(void icmp_init(struct net_proto_family *ops))
+void __init icmp_init(struct net_proto_family *ops)
 {
 	int err;
 
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c
--- v2.3.15/linux/net/ipv4/ip_fragment.c	Thu Aug 26 13:05:45 1999
+++ linux/net/ipv4/ip_fragment.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *
  *		The IP fragmentation functionality.
  *		
- * Version:	$Id: ip_fragment.c,v 1.44 1999/08/20 11:05:19 davem Exp $
+ * Version:	$Id: ip_fragment.c,v 1.45 1999/08/30 10:17:10 davem Exp $
  *
  * Authors:	Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
  *		Alan Cox <Alan.Cox@linux.org>
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/ip_gre.c linux/net/ipv4/ip_gre.c
--- v2.3.15/linux/net/ipv4/ip_gre.c	Thu Aug 26 13:05:45 1999
+++ linux/net/ipv4/ip_gre.c	Thu Aug 26 14:04:46 1999
@@ -1170,7 +1170,7 @@
 }
 #endif
 
-__initfunc(int ipgre_fb_tunnel_init(struct net_device *dev))
+int __init ipgre_fb_tunnel_init(struct net_device *dev)
 {
 	struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
 	struct iphdr *iph;
@@ -1211,7 +1211,7 @@
 #ifdef MODULE
 int init_module(void) 
 #else
-__initfunc(int ipgre_init(void))
+int __init ipgre_init(void)
 #endif
 {
 	printk(KERN_INFO "GRE over IPv4 tunneling driver\n");
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- v2.3.15/linux/net/ipv4/ip_output.c	Thu Aug 26 13:05:45 1999
+++ linux/net/ipv4/ip_output.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *
  *		The Internet Protocol (IP) output module.
  *
- * Version:	$Id: ip_output.c,v 1.69 1999/08/20 11:05:48 davem Exp $
+ * Version:	$Id: ip_output.c,v 1.70 1999/08/31 07:03:39 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1023,7 +1023,7 @@
  *	IP registers the packet type and then calls the subprotocol initialisers
  */
 
-__initfunc(void ip_init(void))
+void __init ip_init(void)
 {
 	dev_add_pack(&ip_packet_type);
 
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/ipip.c linux/net/ipv4/ipip.c
--- v2.3.15/linux/net/ipv4/ipip.c	Thu Aug 26 13:05:45 1999
+++ linux/net/ipv4/ipip.c	Tue Aug 31 11:23:03 1999
@@ -1,7 +1,7 @@
 /*
  *	Linux NET3:	IP/IP protocol decoder. 
  *
- *	Version: $Id: ipip.c,v 1.28 1999/08/20 11:05:51 davem Exp $
+ *	Version: $Id: ipip.c,v 1.29 1999/08/31 07:03:42 davem Exp $
  *
  *	Authors:
  *		Sam Lantinga (slouken@cs.ucdavis.edu)  02/01/95
@@ -826,7 +826,7 @@
 }
 #endif
 
-__initfunc(int ipip_fb_tunnel_init(struct net_device *dev))
+int __init ipip_fb_tunnel_init(struct net_device *dev)
 {
 	struct iphdr *iph;
 
@@ -859,7 +859,7 @@
 #ifdef MODULE
 int init_module(void) 
 #else
-__initfunc(int ipip_init(void))
+int __init ipip_init(void)
 #endif
 {
 	printk(KERN_INFO "IPv4 over IPv4 tunneling driver\n");
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v2.3.15/linux/net/ipv4/ipmr.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv4/ipmr.c	Tue Aug 31 11:23:03 1999
@@ -9,7 +9,7 @@
  *	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
  *
- *	Version: $Id: ipmr.c,v 1.45 1999/08/20 11:05:53 davem Exp $
+ *	Version: $Id: ipmr.c,v 1.46 1999/08/31 07:03:44 davem Exp $
  *
  *	Fixes:
  *	Michael Chastain	:	Incorrect size of copying.
@@ -1735,7 +1735,7 @@
  *	Setup for IP multicast routing
  */
  
-__initfunc(void ip_mr_init(void))
+void __init ip_mr_init(void)
 {
 	printk(KERN_INFO "Linux IP multicast router 0.06 plus PIM-SM\n");
 	mrt_cachep = kmem_cache_create("ip_mrt_cache",
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.3.15/linux/net/ipv4/route.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv4/route.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *
  *		ROUTE - implementation of the IP router.
  *
- * Version:	$Id: route.c,v 1.71 1999/08/20 11:05:58 davem Exp $
+ * Version:	$Id: route.c,v 1.72 1999/08/30 10:17:12 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.3.15/linux/net/ipv4/tcp.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv4/tcp.c	Tue Aug 31 11:30:48 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.148 1999/08/23 05:16:11 davem Exp $
+ * Version:	$Id: tcp.c,v 1.149 1999/08/30 10:17:17 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -689,7 +689,7 @@
 		if(signal_pending(tsk))
 			return -ERESTARTSYS;
 
-		tsk->state = TASK_INTERRUPTIBLE;
+		__set_task_state(tsk, TASK_INTERRUPTIBLE);
 		add_wait_queue(sk->sleep, &wait);
 		sk->tp_pinfo.af_tcp.write_pending++;
 
@@ -697,7 +697,7 @@
 		schedule();
 		lock_sock(sk);
 
-		tsk->state = TASK_RUNNING;
+		__set_task_state(tsk, TASK_RUNNING);
 		remove_wait_queue(sk->sleep, &wait);
 		sk->tp_pinfo.af_tcp.write_pending--;
 	}
@@ -720,7 +720,7 @@
 		sk->socket->flags &= ~SO_NOSPACE;
 		add_wait_queue(sk->sleep, &wait);
 		for (;;) {
-			current->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 
 			if (signal_pending(current))
 				break;
@@ -1121,7 +1121,7 @@
 
 	add_wait_queue(sk->sleep, &wait);
 
-	current->state = TASK_INTERRUPTIBLE;
+	__set_current_state(TASK_INTERRUPTIBLE);
 
 	sk->socket->flags |= SO_WAITDATA;
 	release_sock(sk);
@@ -1133,7 +1133,7 @@
 	sk->socket->flags &= ~SO_WAITDATA;
 
 	remove_wait_queue(sk->sleep, &wait);
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 }
 
 /*
@@ -1595,7 +1595,7 @@
 		add_wait_queue(sk->sleep, &wait);
 
 		while (1) {
-			tsk->state = TASK_INTERRUPTIBLE;
+			set_current_state(TASK_INTERRUPTIBLE);
 			if (!closing(sk))
 				break;
 			release_sock(sk);
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.3.15/linux/net/ipv4/tcp_ipv4.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv4/tcp_ipv4.c	Tue Aug 31 11:30:48 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.186 1999/08/21 21:46:29 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.187 1999/08/31 07:03:48 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -412,16 +412,16 @@
 		DECLARE_WAITQUEUE(wait, current);
 
 		add_wait_queue(&tcp_lhash_wait, &wait);
-		do {
-			current->state = TASK_UNINTERRUPTIBLE;
+		for (;;) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
 			if (atomic_read(&tcp_lhash_users) == 0)
 				break;
 			write_unlock_bh(&tcp_lhash_lock);
 			schedule();
 			write_lock_bh(&tcp_lhash_lock);
-		} while (atomic_read(&tcp_lhash_users));
+		}
 
-		current->state = TASK_RUNNING;
+		__set_current_state(TASK_RUNNING);
 		remove_wait_queue(&tcp_lhash_wait, &wait);
 	}
 }
@@ -2222,7 +2222,7 @@
 
 
 
-__initfunc(void tcp_v4_init(struct net_proto_family *ops))
+void __init tcp_v4_init(struct net_proto_family *ops)
 {
 	int err;
 
diff -u --recursive --new-file v2.3.15/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- v2.3.15/linux/net/ipv4/tcp_timer.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv4/tcp_timer.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_timer.c,v 1.66 1999/08/20 11:06:10 davem Exp $
+ * Version:	$Id: tcp_timer.c,v 1.67 1999/08/30 12:14:43 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -549,6 +549,14 @@
 		mod_timer(&tcp_slow_timer, (now + next));
 }
 
+/* __tcp_inc_slow_timer is called when an slow timer is started
+ * first time (slt->count was 0). There is race condition between
+ * timer creation and deletion and if we do not force adding timer here,
+ * we might lose timer. We could avoid it with global spinlock, but
+ * it is apparently overkill, so that we restart timer ALWAYS when
+ * this function is entered, it guarantees that timer will not lost.
+ */
+
 void __tcp_inc_slow_timer(struct tcp_sl_timer *slt)
 {
 	unsigned long now = jiffies;
@@ -558,13 +566,11 @@
 
 	when = now + slt->period;
 
-	if (tcp_slow_timer.prev) {
-		if ((long)(tcp_slow_timer.expires - when) >= 0)
-			mod_timer(&tcp_slow_timer, when);
-	} else {
-		tcp_slow_timer.expires = when;
-		add_timer(&tcp_slow_timer);
-	}
+	if (tcp_slow_timer.prev &&
+	    (long)(tcp_slow_timer.expires - when) < 0)
+		when = tcp_slow_timer.expires;
+
+	mod_timer(&tcp_slow_timer, when);
 }
 
 void tcp_delete_keepalive_timer (struct sock *sk)
diff -u --recursive --new-file v2.3.15/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- v2.3.15/linux/net/ipv6/addrconf.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv6/addrconf.c	Tue Aug 31 11:23:03 1999
@@ -6,7 +6,7 @@
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
- *	$Id: addrconf.c,v 1.52 1999/08/20 11:06:14 davem Exp $
+ *	$Id: addrconf.c,v 1.53 1999/08/31 07:03:54 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -1982,7 +1982,7 @@
  *	Init / cleanup code
  */
 
-__initfunc(void addrconf_init(void))
+void __init addrconf_init(void)
 {
 #ifdef MODULE
 	struct net_device *dev;
diff -u --recursive --new-file v2.3.15/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c
--- v2.3.15/linux/net/ipv6/af_inet6.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv6/af_inet6.c	Tue Aug 31 11:23:03 1999
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/af_inet.c
  *
- *	$Id: af_inet6.c,v 1.46 1999/08/20 11:06:16 davem Exp $
+ *	$Id: af_inet6.c,v 1.47 1999/08/31 07:03:58 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -509,7 +509,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__initfunc(void inet6_proto_init(struct net_proto *pro))
+void __init inet6_proto_init(struct net_proto *pro)
 #endif
 {
 	struct sk_buff *dummy_skb;
diff -u --recursive --new-file v2.3.15/linux/net/ipv6/ip6_fib.c linux/net/ipv6/ip6_fib.c
--- v2.3.15/linux/net/ipv6/ip6_fib.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv6/ip6_fib.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: ip6_fib.c,v 1.18 1999/08/20 11:06:19 davem Exp $
+ *	$Id: ip6_fib.c,v 1.19 1999/08/31 07:04:00 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -1204,7 +1204,7 @@
 	spin_unlock_bh(&fib6_gc_lock);
 }
 
-__initfunc(void fib6_init(void))
+void __init fib6_init(void)
 {
 	if (!fib6_node_kmem)
 		fib6_node_kmem = kmem_cache_create("fib6_nodes",
diff -u --recursive --new-file v2.3.15/linux/net/ipv6/ip6_fw.c linux/net/ipv6/ip6_fw.c
--- v2.3.15/linux/net/ipv6/ip6_fw.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv6/ip6_fw.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: ip6_fw.c,v 1.14 1999/08/20 11:06:20 davem Exp $
+ *	$Id: ip6_fw.c,v 1.15 1999/08/31 07:04:03 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -377,7 +377,7 @@
 #define ip6_fw_init module_init
 #endif
 
-__initfunc(void ip6_fw_init(void))
+void __init ip6_fw_init(void)
 {
 #ifdef CONFIG_NETLINK
 	netlink_attach(NETLINK_IP6_FW, ip6_fw_msgrcv);
diff -u --recursive --new-file v2.3.15/linux/net/ipv6/ip6_input.c linux/net/ipv6/ip6_input.c
--- v2.3.15/linux/net/ipv6/ip6_input.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv6/ip6_input.c	Tue Aug 31 11:23:03 1999
@@ -6,7 +6,7 @@
  *	Pedro Roque		<roque@di.fc.ul.pt>
  *	Ian P. Morris		<I.P.Morris@soton.ac.uk>
  *
- *	$Id: ip6_input.c,v 1.13 1999/08/20 11:06:21 davem Exp $
+ *	$Id: ip6_input.c,v 1.14 1999/08/30 12:14:56 davem Exp $
  *
  *	Based in linux/net/ipv4/ip_input.c
  *
@@ -159,7 +159,8 @@
 		if (ipprot->copy || raw_sk)
 			buff = skb_clone(skb, GFP_ATOMIC);
 
-		ipprot->handler(buff, len);
+		if (buff)
+			ipprot->handler(buff, len);
 		found = 1;
 	}
 	read_unlock(&inet6_protocol_lock);
diff -u --recursive --new-file v2.3.15/linux/net/ipv6/ipv6_sockglue.c linux/net/ipv6/ipv6_sockglue.c
--- v2.3.15/linux/net/ipv6/ipv6_sockglue.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv6/ipv6_sockglue.c	Tue Aug 31 11:23:03 1999
@@ -7,7 +7,7 @@
  *
  *	Based on linux/net/ipv4/ip_sockglue.c
  *
- *	$Id: ipv6_sockglue.c,v 1.28 1999/08/20 11:06:23 davem Exp $
+ *	$Id: ipv6_sockglue.c,v 1.29 1999/08/31 07:04:06 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -458,12 +458,12 @@
 extern void ipv6_sysctl_unregister(void);
 #endif
 
-__initfunc(void ipv6_packet_init(void))
+void __init ipv6_packet_init(void)
 {
 	dev_add_pack(&ipv6_packet_type);
 }
 
-__initfunc(void ipv6_netdev_notif_init(void))
+void __init ipv6_netdev_notif_init(void)
 {
 	register_netdevice_notifier(&ipv6_dev_notf);
 }
diff -u --recursive --new-file v2.3.15/linux/net/ipv6/mcast.c linux/net/ipv6/mcast.c
--- v2.3.15/linux/net/ipv6/mcast.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv6/mcast.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: mcast.c,v 1.25 1999/08/20 11:06:24 davem Exp $
+ *	$Id: mcast.c,v 1.26 1999/08/31 07:04:08 davem Exp $
  *
  *	Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c 
  *
@@ -705,7 +705,7 @@
 }
 #endif
 
-__initfunc(int igmp6_init(struct net_proto_family *ops))
+int __init igmp6_init(struct net_proto_family *ops)
 {
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *ent;
diff -u --recursive --new-file v2.3.15/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c
--- v2.3.15/linux/net/ipv6/ndisc.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv6/ndisc.c	Thu Aug 26 14:11:01 1999
@@ -1191,7 +1191,7 @@
 
 
 
-__initfunc(int ndisc_init(struct net_proto_family *ops))
+int __init ndisc_init(struct net_proto_family *ops)
 {
 	struct sock *sk;
         int err;
diff -u --recursive --new-file v2.3.15/linux/net/ipv6/route.c linux/net/ipv6/route.c
--- v2.3.15/linux/net/ipv6/route.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv6/route.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: route.c,v 1.39 1999/08/20 11:06:28 davem Exp $
+ *	$Id: route.c,v 1.40 1999/08/31 07:04:13 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -1928,7 +1928,7 @@
 #endif
 
 
-__initfunc(void ip6_route_init(void))
+void __init ip6_route_init(void)
 {
 	ip6_dst_ops.kmem_cachep = kmem_cache_create("ip6_dst_cache",
 						     sizeof(struct rt6_info),
diff -u --recursive --new-file v2.3.15/linux/net/ipv6/sit.c linux/net/ipv6/sit.c
--- v2.3.15/linux/net/ipv6/sit.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv6/sit.c	Tue Aug 31 11:23:03 1999
@@ -6,7 +6,7 @@
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
- *	$Id: sit.c,v 1.33 1999/08/20 11:06:29 davem Exp $
+ *	$Id: sit.c,v 1.34 1999/08/31 07:04:16 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -756,7 +756,7 @@
 }
 #endif
 
-__initfunc(int ipip6_fb_tunnel_init(struct net_device *dev))
+int __init ipip6_fb_tunnel_init(struct net_device *dev)
 {
 	struct iphdr *iph;
 
@@ -795,7 +795,7 @@
 }
 #endif
 
-__initfunc(int sit_init(void))
+int __init sit_init(void)
 {
 	printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n");
 
diff -u --recursive --new-file v2.3.15/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.3.15/linux/net/ipv6/tcp_ipv6.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipv6/tcp_ipv6.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.111 1999/08/21 21:46:35 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.112 1999/08/31 07:04:19 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -2143,7 +2143,7 @@
 	"TCPv6"			/* name			*/
 };
 
-__initfunc(void tcpv6_init(void))
+void __init tcpv6_init(void)
 {
 	/* register inet6 protocol */
 	inet6_add_protocol(&tcpv6_protocol);
diff -u --recursive --new-file v2.3.15/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v2.3.15/linux/net/ipx/af_ipx.c	Thu Aug 26 13:05:46 1999
+++ linux/net/ipx/af_ipx.c	Mon Aug 30 10:31:24 1999
@@ -767,6 +767,7 @@
 		{ 
 			/* < 8 hops && input itfc not in list */
 			*l = intrfc->if_netnum; /* insert recvd netnum into list */
+			ipx->ipx_tctrl++;
 			/* xmit on all other interfaces... */
 			for(ifcs = ipx_interfaces; ifcs != NULL; ifcs = ifcs->if_next) 
 			{
diff -u --recursive --new-file v2.3.15/linux/net/irda/Config.in linux/net/irda/Config.in
--- v2.3.15/linux/net/irda/Config.in	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/Config.in	Mon Aug 30 10:26:28 1999
@@ -5,14 +5,13 @@
 if [ "$CONFIG_NET" != "n" ] ; then
 
   mainmenu_option next_comment
-  comment 'IrDA subsystem support'
+  comment 'IrDA (infrared) support'
   dep_tristate 'IrDA subsystem support' CONFIG_IRDA $CONFIG_NET
 
   if [ "$CONFIG_IRDA" != "n" ] ; then
     comment 'IrDA protocols'
     source net/irda/irlan/Config.in
     source net/irda/ircomm/Config.in
-    source net/irda/irlpt/Config.in
 
     bool 'IrDA protocol options' CONFIG_IRDA_OPTIONS
     if [ "$CONFIG_IRDA_OPTIONS" != "n" ] ; then
diff -u --recursive --new-file v2.3.15/linux/net/irda/Makefile linux/net/irda/Makefile
--- v2.3.15/linux/net/irda/Makefile	Thu Apr 15 05:42:42 1999
+++ linux/net/irda/Makefile	Mon Aug 30 10:26:28 1999
@@ -7,7 +7,7 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
-ALL_SUB_DIRS := irlan ircomm irlpt compressors
+ALL_SUB_DIRS := irlan ircomm compressors
 SUB_DIRS :=
 MOD_SUB_DIRS :=
 OX_OBJS :=
@@ -16,7 +16,7 @@
 O_OBJS	 := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \
             irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \
             irttp.o irda_device.o irias_object.o crc.o wrapper.o af_irda.o \
-	    discovery.o
+	    discovery.o parameters.o
 OX_OBJS := irmod.o
 
 MOD_LIST_NAME := IRDA_MODULES
@@ -46,15 +46,6 @@
   endif
 endif
 
-ifeq ($(CONFIG_IRLPT),y)
-SUB_DIRS += irlpt
-O_OBJS += irlpt/irlpt.o
-else
-  ifeq ($(CONFIG_IRLPT),m)
-  MOD_IN_SUB_DIRS += irlpt
-  endif
-endif
-
 ifeq ($(CONFIG_IRDA_COMPRESSION),y)
 SUB_DIRS += compressors
 MOD_IN_SUB_DIRS += compressors
@@ -70,7 +61,7 @@
 
 ifeq ($(CONFIG_IRCOMM),y)
 SUB_DIRS += ircomm
-O_OBJS += ircomm/ircomm_n_vtd.o
+O_OBJS += ircomm/ircomm_and_tty.o
 else
   ifeq ($(CONFIG_IRCOMM),m)
   MOD_SUB_DIRS += ircomm
diff -u --recursive --new-file v2.3.15/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.3.15/linux/net/irda/af_irda.c	Thu Aug 26 13:05:46 1999
+++ linux/net/irda/af_irda.c	Mon Aug 30 10:26:28 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      af_irda.c
- * Version:       0.6
+ * Version:       0.7
  * Description:   IrDA sockets implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 31 10:12:43 1998
- * Modified at:   Wed May 19 16:12:06 1999
+ * Modified at:   Mon Aug 23 09:44:37 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
  * 
@@ -228,7 +228,6 @@
 	irttp_connect_response(self->tsap, self->max_sdu_size_rx, skb);
 }
 
-
 /*
  * Function irda_flow_indication (instance, sap, flow)
  *
@@ -335,10 +334,8 @@
  */
 static int irda_open_tsap(struct irda_sock *self, __u8 tsap_sel, char *name)
 {
-	struct notify_t notify;
+	notify_t notify;
 	
-	DEBUG(1, __FUNCTION__ "()\n");
-
 	/* Initialize callbacks to be used by the IrDA stack */
 	irda_notify_init(&notify);
 	notify.connect_confirm       = irda_connect_confirm;
@@ -457,8 +454,6 @@
 	__u16 hints = 0;
 	int err;
 
-	DEBUG(1, __FUNCTION__ "()\n");
-
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
 
@@ -591,8 +586,6 @@
 
 	self = sk->protinfo.irda;
 
-	DEBUG(1, __FUNCTION__ "()\n");
-
 	if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
 		sock->state = SS_CONNECTED;
 		return 0;   /* Connect completed during a ERESTARTSYS event */
@@ -703,9 +696,10 @@
 		return -ENOMEM;
 	memset(self, 0, sizeof(struct irda_sock));
 
+	init_waitqueue_head(&self->ias_wait);
+
 	self->sk = sk;
 	sk->protinfo.irda = self;
-
 	sock_init_data(sock, sk);
 
 	if (sock->type == SOCK_STREAM)
@@ -746,7 +740,7 @@
 
 	/* Unregister with LM-IAS */
 	if (self->ias_obj)
-		irias_delete_object(self->ias_obj->name);
+		irias_delete_object(self->ias_obj);
 
 	if (self->tsap) {
 		irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
@@ -1160,7 +1154,8 @@
 		if (sk != NULL) {
 			if (sk->stamp.tv_sec == 0)
 				return -ENOENT;
-			if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
+			if (copy_to_user((void *)arg, &sk->stamp, 
+					 sizeof(struct timeval)))
 				return -EFAULT;
 			return 0;
 		}
@@ -1200,8 +1195,6 @@
 	struct irda_sock *self;
 	int opt;
 	
-	DEBUG(0, __FUNCTION__ "()\n");
-
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
 
@@ -1247,8 +1240,6 @@
 	int len = 0;
 	int i = 0;
 
-	DEBUG(1, __FUNCTION__ "()\n");
-
 	self = sk->protinfo.irda;
 
 	if (level != SOL_IRLMP)
@@ -1259,24 +1250,16 @@
 
 	switch (optname) {
 	case IRLMP_ENUMDEVICES:
-		DEBUG(1, __FUNCTION__ "(), IRLMP_ENUMDEVICES\n");
-		
 		/* Tell IrLMP we want to be notified */
 		irlmp_update_client(self->ckey, self->mask, NULL, 
 				    irda_discovery_indication);
-
+		
 		/* Do some discovery */
 		irlmp_discovery_request(self->nslots);
-
-		/* Devices my be discovered already */
-		if (!cachelog) {
-			DEBUG(2, __FUNCTION__ "(), no log!\n");
-
-			/* Sleep until device(s) discovered */
-			interruptible_sleep_on(&discovery_wait);
-			if (!cachelog)
-				return -1;
-		}
+		
+		/* Check if the we got some results */
+		if (!cachelog)
+			return -EAGAIN;
 
 		list = (struct irda_device_list *) optbuf;
 		/* 
@@ -1294,7 +1277,8 @@
 				list->dev[i].charset = discovery->charset;
 				list->dev[i].hints[0] = discovery->hints.byte[0];
 				list->dev[i].hints[1] = discovery->hints.byte[1];
-				strncpy(list->dev[i].info, discovery->info, 22);
+				strncpy(list->dev[i].info, discovery->nickname,
+					NICKNAME_MAX_LEN);
 				if (++i >= 10)
 					break;
 			}
@@ -1439,16 +1423,14 @@
  *    Initialize IrDA protocol layer
  *
  */
-__initfunc(void irda_proto_init(struct net_proto *pro))
+void __init irda_proto_init(struct net_proto *pro)
 {
-	DEBUG( 4, __FUNCTION__ "\n");
-
 	sock_register(&irda_family_ops);
 
 	irda_packet_type.type = htons(ETH_P_IRDA);
         dev_add_pack(&irda_packet_type);
 
-	register_netdevice_notifier( &irda_dev_notifier);
+	register_netdevice_notifier(&irda_dev_notifier);
 
 	irda_init();
 }
@@ -1462,8 +1444,6 @@
 #ifdef MODULE
 void irda_proto_cleanup(void)
 {
-	DEBUG( 4, __FUNCTION__ "\n");
-
 	irda_packet_type.type = htons(ETH_P_IRDA);
         dev_remove_pack(&irda_packet_type);
 
diff -u --recursive --new-file v2.3.15/linux/net/irda/compressors/irda_deflate.c linux/net/irda/compressors/irda_deflate.c
--- v2.3.15/linux/net/irda/compressors/irda_deflate.c	Mon Jul  5 20:35:18 1999
+++ linux/net/irda/compressors/irda_deflate.c	Tue Aug 31 11:23:03 1999
@@ -594,7 +594,7 @@
 	z_comp_stats,		/* decomp_stat */
 };
 
-__initfunc(int irda_deflate_init(void))
+int __init irda_deflate_init(void)
 {
         int answer = irda_register_compressor ( &irda_deflate);
         if (answer == 0)
diff -u --recursive --new-file v2.3.15/linux/net/irda/discovery.c linux/net/irda/discovery.c
--- v2.3.15/linux/net/irda/discovery.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/discovery.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Apr  6 15:33:50 1999
- * Modified at:   Fri May 28 20:46:38 1999
+ * Modified at:   Mon Aug 23 09:48:40 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Modified at:   Fri May 28  3:11 CST 1999
  * Modified by:   Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
@@ -66,7 +66,7 @@
 			discovery = (discovery_t *) hashbin_get_next(cachelog);
 			
 			if ((node->daddr == new->daddr) || 
-			    (strcmp(node->info, new->info) == 0))
+			    (strcmp(node->nickname, new->nickname) == 0))
 			{
 				/* This discovery is a previous discovery 
 				 * from the same device, so just remove it
@@ -122,7 +122,7 @@
  *    Go through all discoveries and expire all that has stayed to long
  *
  */
-void irlmp_expire_discoveries(hashbin_t *log, int saddr, int force)
+void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
 {
 	discovery_t *discovery, *curr;
 
@@ -163,7 +163,7 @@
 		DEBUG(0, "Discovery:\n");
 		DEBUG(0, "  daddr=%08x\n", discovery->daddr);
 		DEBUG(0, "  saddr=%08x\n", discovery->saddr); 
-		DEBUG(0, "  name=%s\n", discovery->info);
+		DEBUG(0, "  nickname=%s\n", discovery->nickname);
 
 		discovery = (discovery_t *) hashbin_get_next(log);
 	}
@@ -178,8 +178,8 @@
  */
 __u32 irlmp_find_device(hashbin_t *cachelog, char *name, __u32 *saddr)
 {
-	discovery_t *d;
 	unsigned long flags;
+	discovery_t *d;
 
 	spin_lock_irqsave(&irlmp->lock, flags);
 
@@ -188,9 +188,9 @@
 	while (d != NULL) {
 		DEBUG(1, "Discovery:\n");
 		DEBUG(1, "  daddr=%08x\n", d->daddr);
-		DEBUG(1, "  name=%s\n", d->info);
+		DEBUG(1, "  nickname=%s\n", d->nickname);
 		
-		if (strcmp(name, d->info) == 0) {
+		if (strcmp(name, d->nickname) == 0) {
 			*saddr = d->saddr;
 			
 			spin_unlock_irqrestore(&irlmp->lock, flags);
@@ -227,7 +227,7 @@
 	
 	discovery = (discovery_t *) hashbin_get_first(cachelog);
 	while ( discovery != NULL) {
-		len += sprintf(buf+len, "name: %s,", discovery->info);
+		len += sprintf(buf+len, "nickname: %s,", discovery->nickname);
 		
 		len += sprintf(buf+len, " hint: 0x%02x%02x", 
 			       discovery->hints.byte[0], 
diff -u --recursive --new-file v2.3.15/linux/net/irda/ircomm/Makefile linux/net/irda/ircomm/Makefile
--- v2.3.15/linux/net/irda/ircomm/Makefile	Thu Apr 15 05:42:42 1999
+++ linux/net/irda/ircomm/Makefile	Mon Aug 30 10:26:28 1999
@@ -7,10 +7,10 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
-O_TARGET := ircomm_n_vtd.o
-O_OBJS	 := ircomm_common.o irvtd_driver.o
-M_OBJS   := ircomm.o ircomm_tty.o
-MI_OBJS  := ircomm_common.o irvtd_driver.o
+O_TARGET := ircomm_and_tty.o
+O_OBJS	 := ircomm_param.o ircomm_core.o ircomm_event.o ircomm_lmp.o ircomm_ttp.o ircomm_tty.o ircomm_tty_attach.o ircomm_tty_ioctl.c
+M_OBJS   := ircomm.o ircomm-tty.o
+MI_OBJS  := ircomm_param.o ircomm_core.o ircomm_event.o ircomm_lmp.o ircomm_ttp.o ircomm_tty.o ircomm_tty_attach.o ircomm_tty_ioctl.o
 
 OX_OBJS  += 
 
@@ -18,10 +18,12 @@
 
 ifeq ($(CONFIG_IRCOMM),m)
 ircomm.o:  $(MI_OBJS)
-	$(LD) $(LD_RFLAG) -r -o $@ ircomm_common.o
+	$(LD) $(LD_RFLAG) -r -o $@ ircomm_core.o ircomm_event.o ircomm_lmp.o ircomm_ttp.o
+
+ircomm-tty.o: $(MI_OBJS)
+	$(LD) $(LD_RFLAG) -r -o $@ ircomm_tty.o ircomm_tty_attach.o ircomm_tty_ioctl.o ircomm_param.o
+
 
-ircomm_tty.o: $(MI_OBJS)
-	$(LD) $(LD_RFLAG) -r -o $@ irvtd_driver.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.15/linux/net/irda/ircomm/ircomm_common.c linux/net/irda/ircomm/ircomm_common.c
--- v2.3.15/linux/net/irda/ircomm/ircomm_common.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/ircomm/ircomm_common.c	Wed Dec 31 16:00:00 1969
@@ -1,1921 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      ircomm_common.c
- * Version:       
- * Description:   An implementation of IrCOMM service interface, 
- *                state machine, and incidental function(s).
- * Status:        Experimental.
- * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
- * Source:        irlpt_event.c
- *
- *     Copyright (c) 1998-1999, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Takahide Higuchi, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-/*
- *    Reference: 
- *    "'IrCOMM':Serial and Parallel Port Emulation Over IR(Wire Replacement)"
- *    version 1.0, which is available at http://www.irda.org/.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irias_object.h>
-
-#include <net/irda/ircomm_common.h>
-
-static char *revision_date = "Tue May 18 03:11:39 1999";
-
-
-static void ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			      struct sk_buff *skb );
-static void ircomm_state_discoverywait(struct ircomm_cb *self, 
-				       IRCOMM_EVENT event, 
-				       struct sk_buff *skb );
-static void ircomm_state_queryparamwait(struct ircomm_cb *self, 
-					IRCOMM_EVENT event, 
-					struct sk_buff *skb );
-static void ircomm_state_querylsapwait(struct ircomm_cb *self, 
-				       IRCOMM_EVENT event, 
-				       struct sk_buff *skb );
-static void ircomm_state_waiti( struct ircomm_cb *self, IRCOMM_EVENT event, 
-				struct sk_buff *skb );
-static void ircomm_state_waitr( struct ircomm_cb *self, IRCOMM_EVENT event, 
-				struct sk_buff *skb );
-static void ircomm_state_conn( struct ircomm_cb *self, IRCOMM_EVENT event, 
-			       struct sk_buff *skb );
-static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event,
-			     struct sk_buff *skb);
-static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state);
-
-static void ircomm_discovery_indication(discovery_t *discovery);
-static void ircomm_tx_controlchannel(struct ircomm_cb *self );
-static int ircomm_proc_read(char *buf, char **start, off_t offset,
-			    int len, int unused);
-
-static void start_discovering(struct ircomm_cb *self);
-static void query_lsapsel(struct ircomm_cb * self);
-static void query_parameters(struct ircomm_cb *self);
-static void queryias_done(struct ircomm_cb *self);
-static void ircomm_getvalue_confirm(int result, __u16 obj_id, 
-				    struct ias_value *value, void *priv);
-
-
-struct ircomm_cb *discovering_instance;
-
-/*
- * debug parameter ircomm_cs:
- *  0 = client/server, 1 = client only 2 = server only
- * usage for example: 
- *  insmod ircomm ircomm_cs=1
- *  LILO boot : Linux ircomm_cs=2   etc.
- */
-
-static int ircomm_cs = 0;
-MODULE_PARM(ircomm_cs, "i");
-
-
-
-static char *ircommstate[] = {
-	"IDLE",
-
-	"DISCOVERY_WAIT",
-	"QUERYPARAM_WAIT",
-	"QUERYLSAP_WAIT",
-
-	"WAITI",
-	"WAITR",
-	"CONN",
-};
-
-static char *ircommservicetype[] = {
-	"N/A",
-	"THREE_WIRE_RAW",
-	"THREE_WIRE",
-	"NINE_WIRE",
-	"CENTRONICS",
-};
-static char *ircommporttype[] = {
-	"Unknown",
-	"SERIAL",
-	"PARALLEL",
-};
-
-
-struct ircomm_cb **ircomm = NULL;
-
-static char *ircommevent[] = {
-	"IRCOMM_CONNECT_REQUEST",
-	"TTP_CONNECT_INDICATION",
-	"LMP_CONNECT_INDICATION",
-
-	"TTP_CONNECT_CONFIRM",
-	"TTP_DISCONNECT_INDICATION",
-	"LMP_CONNECT_CONFIRM",
-	"LMP_DISCONNECT_INDICATION",
-
-	"IRCOMM_CONNECT_RESPONSE",
-	"IRCOMM_DISCONNECT_REQUEST",
-
-	"TTP_DATA_INDICATION",
-	"IRCOMM_DATA_REQUEST",
-	"LMP_DATA_INDICATION",
-	"IRCOMM_CONTROL_REQUEST",
-
-	"DISCOVERY_INDICATION",
-	"GOT_PARAMETERS",
-	"GOT_LSAPSEL",
-	"QUERYIAS_ERROR",
-};
-
-#ifdef CONFIG_PROC_FS
-extern struct proc_dir_entry *proc_irda;
-#endif
-
-static void (*state[])( struct ircomm_cb *self, IRCOMM_EVENT event,
-			struct sk_buff *skb) = 
-{
-	ircomm_state_idle,
-
-	ircomm_state_discoverywait,
-	ircomm_state_queryparamwait,
-	ircomm_state_querylsapwait,
-
-	ircomm_state_waiti,
-	ircomm_state_waitr,
-	ircomm_state_conn,
-};
-
-__initfunc(int ircomm_init(void))
-{
-	int i;
-
-	printk( "Linux-IrDA: IrCOMM protocol ( revision:%s ) \n",
-		revision_date);
-	DEBUG( 4, __FUNCTION__"()\n");
-
-	/* allocate master array */
-
-	ircomm = (struct ircomm_cb **) kmalloc( sizeof(struct ircomm_cb *) *
-						IRCOMM_MAX_CONNECTION,
-						GFP_KERNEL);
-	if ( ircomm == NULL) {
-		printk( KERN_ERR __FUNCTION__"(): kmalloc failed!\n");
-		return -ENOMEM;
-	}
-
-	memset( ircomm, 0, sizeof(struct ircomm_cb *) * IRCOMM_MAX_CONNECTION);
-
-	/* initialize structures */
-	   
-	for(i = 0;i < IRCOMM_MAX_CONNECTION; i++){
-		ircomm[i] = kmalloc( sizeof(struct ircomm_cb), GFP_KERNEL );
-
-		if(!ircomm[i]){
-			printk( KERN_ERR __FUNCTION__"(): kmalloc failed!\n");
-			return -ENOMEM;
-		} 
-
-		
-		memset( ircomm[i], 0, sizeof(struct ircomm_cb));
-
-		ircomm[i]->magic = IRCOMM_MAGIC;
-		/* default settings */
-		ircomm[i]->data_format = CS8;
-		ircomm[i]->flow_ctrl = USE_RTS|USE_DTR;  /*TODO: is this OK? */
-		ircomm[i]->xon_char = 0x11; 
-		ircomm[i]->xoff_char = 0x13;
-		ircomm[i]->enq_char = 0x05;
-		ircomm[i]->ack_char = 0x06;  
-
-		ircomm[i]->max_header_size = COMM_MAX_HEADER_SIZE;
-		ircomm[i]->tx_max_sdu_size = COMM_DEFAULT_SDU_SIZE;
-		ircomm[i]->rx_max_sdu_size = SAR_DISABLE;  
-		ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE
-						    + COMM_MAX_HEADER_SIZE);
-		if (ircomm[i]->ctrl_skb == NULL){
-			DEBUG(0,"ircomm:init_module:alloc_skb failed!\n");
-			return -ENOMEM;
-		}
-
-		skb_reserve(ircomm[i]->ctrl_skb,COMM_MAX_HEADER_SIZE);
-
-	}
-
-	/*
-	 * we register /proc/irda/ircomm
-	 */
-
-#ifdef CONFIG_PROC_FS
-	create_proc_entry("ircomm", 0, proc_irda)->get_info = ircomm_proc_read;
-#endif /* CONFIG_PROC_FS */
-
-	discovering_instance = NULL;
-	return 0;
-}
-
-#ifdef MODULE
-void ircomm_cleanup(void)
-{
-	int i;
-
-	DEBUG( 4, "ircomm:cleanup_module\n");
-	/*
-	 * free some resources
-	 */
-	if (ircomm) {
-		for (i=0; i<IRCOMM_MAX_CONNECTION; i++) {
-			if (ircomm[i]) {
-
-				if(ircomm[i]->ctrl_skb){
-					dev_kfree_skb(ircomm[i]->ctrl_skb);
-
-					ircomm[i]->ctrl_skb = NULL;
-				}
-
-				DEBUG( 4, "freeing structures(%d)\n",i);
-				kfree(ircomm[i]);
-				ircomm[i] = NULL;
-			}
-		}
-		DEBUG( 4, "freeing master array\n");
-		kfree(ircomm);
-		ircomm = NULL;
-	}
-
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry("ircomm", proc_irda);
-#endif /* CONFIG_PROC_FS */
-}
-#endif /* MODULE */
-
-/*
- * ---------------------------------------------------------------------- 
- * callbacks which accept incoming indication/confirm from IrTTP  (or IrLMP)
- * ---------------------------------------------------------------------- 
- */
-
-static int ircomm_accept_data_indication(void *instance, void *sap, 
-					 struct sk_buff *skb)
-{
-	struct ircomm_cb *self = (struct ircomm_cb *) instance;
-
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
-	ASSERT(skb != NULL, return -1;);
-       
-	DEBUG(4,__FUNCTION__"():\n");
-	ircomm_do_event(self, TTP_DATA_INDICATION, skb);
-	self->rx_packets++;
-	
-	return 0;
-}
-
-static void ircomm_accept_connect_confirm(void *instance, void *sap,
-					  struct qos_info *qos, 
-					  __u32 max_sdu_size, 
-					  __u8 max_header_size,
-					  struct sk_buff *skb)
-{
-	struct ircomm_cb *self = (struct ircomm_cb *) instance;
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRCOMM_MAGIC, return;);
-	ASSERT(skb != NULL, return;);
-	ASSERT(qos != NULL, return;);
-
-	DEBUG(0,__FUNCTION__"(): got connected!\n");
-
-	if (max_sdu_size == SAR_DISABLE)
-		self->tx_max_sdu_size =(qos->data_size.value - max_header_size
-					- COMM_HEADER_SIZE);
-	else {
-		ASSERT(max_sdu_size >= COMM_DEFAULT_SDU_SIZE, return;);
-		/* use fragmentation */
-		self->tx_max_sdu_size = max_sdu_size - COMM_HEADER_SIZE;
-	}
-
-	self->qos = qos;
-	self->max_header_size = max_header_size + COMM_HEADER_SIZE;
-	self->null_modem_mode = 0;         /* disable null modem emulation */
-
-	ircomm_do_event(self, TTP_CONNECT_CONFIRM, skb);
-}
-
-static void ircomm_accept_connect_indication(void *instance, void *sap,
-					     struct qos_info *qos,
-					     __u32 max_sdu_size,
-					     __u8 max_header_size,
-					     struct sk_buff *skb)
-{
-	struct ircomm_cb *self = (struct ircomm_cb *)instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-	ASSERT( qos != NULL, return;);
-
-	DEBUG(0,__FUNCTION__"()\n");
-
-	if (max_sdu_size == SAR_DISABLE)
-		self->tx_max_sdu_size =(qos->data_size.value - max_header_size
-					- COMM_HEADER_SIZE);
-	else
-		self->tx_max_sdu_size = max_sdu_size - COMM_HEADER_SIZE;
-
-	self->qos = qos;
-	self->max_header_size = max_header_size + COMM_HEADER_SIZE;
-
-	ircomm_do_event( self, TTP_CONNECT_INDICATION, skb);
-
-	/* stop connecting */
-	wake_up_interruptible( &self->discovery_wait);
-	wake_up_interruptible( &self->ias_wait);
-
-}
-
-static void ircomm_accept_disconnect_indication(void *instance, void *sap, 
-					 LM_REASON reason,
-					 struct sk_buff *skb)
-{
-	struct ircomm_cb *self = (struct ircomm_cb *)instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-
-	DEBUG(0,__FUNCTION__"():\n");
-	ircomm_do_event( self, TTP_DISCONNECT_INDICATION, skb);
-
-}
-
-static void ircomm_accept_flow_indication( void *instance, void *sap,
-					   LOCAL_FLOW cmd)
-{
-	IRCOMM_CMD command;
-	struct ircomm_cb *self = (struct ircomm_cb *)instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-
-	switch(cmd){
-	case FLOW_START:
-		DEBUG(4,__FUNCTION__"():START\n"); 
-		command = TX_READY;
-		self->ttp_stop = 0;
-		if(self->notify.flow_indication)
-			self->notify.flow_indication( self->notify.instance, 
-						      self, command);
-		break;
-		
-	case FLOW_STOP:
-		DEBUG(4,__FUNCTION__":STOP\n"); 
-		command = TX_BUSY;
-		self->ttp_stop = 1;
-		if(self->notify.flow_indication)
-			self->notify.flow_indication( self->notify.instance, 
-						      self, command);
-		break;
-
-	default:
-		DEBUG(0,__FUNCTION__"();unknown status!\n"); 
-	}
-
-}
-
-
-/*
- * ircomm_discovery_indication()
- *    Remote device is discovered, try query the remote IAS to see which
- *    device it is, and which services it has.
- */
-
-static void ircomm_discovery_indication(discovery_t *discovery)
-{
-	struct ircomm_cb *self;
-
-	self = discovering_instance;
-	if(self == NULL)
-		return;
-	ASSERT(self->magic == IRCOMM_MAGIC, return;);
-
-	self->daddr = discovery->daddr;
-	self->saddr = discovery->saddr;
-
-	DEBUG( 0, __FUNCTION__"():daddr=%08x\n", self->daddr);
-
-	ircomm_do_event(self, DISCOVERY_INDICATION, NULL);
-	return;
-}
-
-/*
- * ircomm_getvalue_confirm()
- * handler for iriap_getvaluebyclass_request() 
- */
-static void ircomm_getvalue_confirm(int result, __u16 obj_id, 
-				    struct ias_value *value, void *priv)
-{
-	struct ircomm_cb *self = (struct ircomm_cb *) priv;
-	struct sk_buff *skb= NULL;
-	__u8 *frame;
-	__u8 servicetype = 0 ;
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-
-	/* Check if request succeeded */
-	if (result != IAS_SUCCESS) {
-		DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
-		ircomm_do_event(self, QUERYIAS_ERROR, NULL);
-		return;
-	}
-
-	DEBUG(4, __FUNCTION__"():type(%d)\n", value->type);
-
-	self->ias_type = value->type;
-	switch(value->type){
- 	case IAS_OCT_SEQ:
-		
-		DEBUG(4, __FUNCTION__"():got octet sequence:\n");
-#if 0
-		{
-			int i;
-			for ( i=0;i<value->len;i++)
-				printk("%02x",
-				       (__u8)(*(value->t.oct_seq + i)));
-			printk("\n");
-		}
-#endif
-		skb = dev_alloc_skb((value->len) + 2);
-		ASSERT(skb != NULL, ircomm_do_event(self, QUERYIAS_ERROR, NULL);return;);
-		frame = skb_put(skb,2);
-		/* MSB first */
-		frame[0] = ( value->len >> 8 ) & 0xff;
-		frame[1] = value->len & 0xff;
-		
-		frame = skb_put(skb,value->len);
-		memcpy(frame, value->t.oct_seq, value->len);
-		ircomm_parse_tuples(self, skb, IAS_PARAM);
-		kfree_skb(skb);
-
-		/* 
-		 * check if servicetype we want is available 
-		 */
-
-		DEBUG(0,__FUNCTION__"():peer capability is:\n");
-		DEBUG(0,"3wire raw: %s\n",
-		      ((self->peer_servicetype & THREE_WIRE_RAW) ? "yes":"no"));
-		DEBUG(0,"3wire    : %s\n",
-		      ((self->peer_servicetype & THREE_WIRE) ? "yes":"no"));
-		DEBUG(0,"9wire    : %s\n",
-		      ((self->peer_servicetype & NINE_WIRE) ? "yes":"no"));
-		DEBUG(0,"IEEE1284 : %s\n",
-		      ((self->peer_servicetype & CENTRONICS) ? "yes":"no"));
-
-		self->servicetype &= self->peer_servicetype;
-		if(!(self->servicetype)){
-			DEBUG(0,__FUNCTION__"(): servicetype mismatch!\n");
-			ircomm_do_event(self, QUERYIAS_ERROR, NULL);
-			break;
-		}
-
-		/*
-		 * then choose better one 
-		 */
-		if(self->servicetype & THREE_WIRE_RAW)
-			servicetype = THREE_WIRE_RAW;
-		if(self->servicetype & THREE_WIRE)
-			servicetype = THREE_WIRE;
-		if(self->servicetype & NINE_WIRE)
-			servicetype = NINE_WIRE;
-		if(self->servicetype & CENTRONICS)
-			servicetype = CENTRONICS;
-
-		self->servicetype = servicetype;
-
-		/* enter next state */
-		ircomm_do_event(self, GOT_PARAMETERS, NULL);
-		break;
-
-	case IAS_INTEGER:
-		/* LsapSel seems to be sent to me */	
-		DEBUG(0, __FUNCTION__"():got lsapsel = %d\n", value->t.integer);
-
-		if ( value->t.integer == -1){
-			DEBUG( 0, __FUNCTION__"():invalid value!\n");
-			ircomm_do_event(self, QUERYIAS_ERROR, NULL);
-			return;
-		}
-		self->dlsap = value->t.integer;
-		ircomm_do_event(self, GOT_LSAPSEL, NULL);
-		break;
-
-	case IAS_MISSING:
-		DEBUG( 0, __FUNCTION__":got IAS_MISSING\n");
-		ircomm_do_event(self, QUERYIAS_ERROR, NULL);
-		break;
-   
-	default:
-		DEBUG( 0, __FUNCTION__":got unknown (strange?)type!\n");
-		ircomm_do_event(self, QUERYIAS_ERROR, NULL);
-		break;
-	}
-}
-
-
-
-/* 
- * ----------------------------------------------------------------------
- * Impl. of actions (descrived in section 7.4 of the reference)
- * ----------------------------------------------------------------------
- */
-
-static void issue_connect_request(struct ircomm_cb *self,
-				  struct sk_buff *userdata )
-{
-	/* TODO: we have to send/build userdata field which contains 
-	   InitialControlParameters */
-
-	switch(self->servicetype){
-	case THREE_WIRE_RAW:
-		DEBUG(0, __FUNCTION__"():THREE_WIRE_RAW is not implemented\n");
-		break;
-
-	case DEFAULT: 
-	case THREE_WIRE:
-	case NINE_WIRE:
-	case CENTRONICS:
-
-		irttp_connect_request(self->tsap, self->dlsap, 
-				      self->saddr, self->daddr, 
-				      NULL, self->rx_max_sdu_size, userdata); 
-		break;
-
-	default:
-		printk(KERN_ERR __FUNCTION__"():Illegal servicetype %d\n"
-		       ,self->servicetype);
-	}
-}	
-
-static void disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb)
-{
-
-	/*
-	 * Not implemented parameter"Reason".That is optional.
-	 * What is reason? maybe discribed in irmod.h?
-	 */
-
-	if(self->notify.disconnect_indication)
-		self->notify.disconnect_indication( self->notify.instance,
-						    self,
-						    self->reason, skb);
-						    
-}
-
-static void connect_indication(struct ircomm_cb *self, struct qos_info *qos, 
-			       struct sk_buff *skb)
-{
-
-/* If controlparameters don't exist, we use the servicetype"DEFAULT".*/
-/* 	if( !ircomm_parse_controlchannel( self, data)) */
-/* 		self->servicetype = DEFAULT;     TODOD:fix this! TH */
-
-	if (self->notify.connect_indication)
-		self->notify.connect_indication(self->notify.instance, self, 
-						qos, self->tx_max_sdu_size,
-						self->max_header_size, skb);
-}
-    
-#if 0
-/*   it's for THREE_WIRE_RAW.*/
-static void connect_indication_three_wire_raw(void)
-{ 
-	DEBUG(0,"ircomm:connect_indication_threewire():not implemented!");
-}    
-#endif 
-
-
-static void connect_confirm(struct ircomm_cb *self, struct sk_buff *skb)
-{
-	DEBUG(4 ,__FUNCTION__"()\n");
-
-	/* give a connect_confirm to the client */
-	if( self->notify.connect_confirm )
-		self->notify.connect_confirm(self->notify.instance,
-					     self, NULL, self->tx_max_sdu_size,
-					     self->max_header_size, skb);
-}
-
-static void issue_connect_response(struct ircomm_cb *self,
-				   struct sk_buff *skb)
-{
-	DEBUG(0,__FUNCTION__"()\n");
-	
-	if( self->servicetype == THREE_WIRE_RAW){
-		DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented yet\n");
-		/* irlmp_connect_rsp(); */
-	} else
-		irttp_connect_response(self->tsap, self->rx_max_sdu_size, skb);
-}
-
-static void issue_disconnect_request(struct ircomm_cb *self,
-				     struct sk_buff *userdata)
-{
-	if(self->servicetype == THREE_WIRE_RAW){
-		DEBUG(0,__FUNCTION__"():3wireraw is not implemented\n");
-	}
-	else
-		irttp_disconnect_request(self->tsap, userdata, 
-					 self->disconnect_priority);
-}
-    
-static void issue_data_request(struct ircomm_cb *self,
-			       struct sk_buff *userdata )
-{
-	int err;
-
-	if (self->servicetype == THREE_WIRE_RAW){
-		/* irlmp_data_request(self->lmhandle,userdata); */
-		DEBUG(0,__FUNCTION__"():not implemented!");
-		return;
-	}
-
-	DEBUG(4,__FUNCTION__"():sending frame\n");
-	err = irttp_data_request(self->tsap, userdata);
-	if (err){
-		printk(KERN_ERR __FUNCTION__":ttp_data_request failed\n");
-		if (userdata)
-			dev_kfree_skb( userdata);
-	}
-	self->tx_packets++;
-}
-
-static void issue_control_request(struct ircomm_cb *self,
-				  struct sk_buff *userdata)
-{
-	int err;
-
-	DEBUG(4,__FUNCTION__"()\n"); 
-	if (self->servicetype == THREE_WIRE_RAW) {
-		DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented\n");
-		
-	}
-	else 
-	{
-		err = irttp_data_request(self->tsap,userdata);
-		if(err)
-		{
-			printk( __FUNCTION__"():ttp_data_request failed\n");
-			if(userdata)
-				dev_kfree_skb(userdata);
-		}
-		else
-			self->tx_controls++;
-
-		self->pending_control_tuples = 0;
-	}
-}
-
-static void process_data(struct ircomm_cb *self, struct sk_buff *skb )
-{
-	
-	DEBUG(4,__FUNCTION__":skb->len=%d, ircomm header = 1, clen=%d\n",
-	      (int)skb->len ,(int)skb->data[0]);
-
-	/* we have to parse control channel when receiving.  (see
-	 * page17 of IrCOMM standard) but it is not parsed here since
-	 * upper layer may have some receive buffer.
-	 *
-	 * hence upper layer have to parse it when it consumes a packet.
-	 *   -- TH
-	 */
-
- 	/* ircomm_parse_control(self, skb, CONTROL_CHANNEL); */
-
-	if (self->notify.data_indication && skb->len)
-		self->notify.data_indication(self->notify.instance, self,
-					     skb);
-}
-
-int ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
-{
-	/* Not implemented yet:THREE_WIRE_RAW service uses this function.  */
-	DEBUG(0,"ircomm_data_indication:not implemented yet!\n");
-
-	return 0;
-}
-
-
-/* 
- * ----------------------------------------------------------------------
- * Implementation of state chart,
- * descrived in section 7.1 of the specification.
- * ----------------------------------------------------------------------
- */
-
-static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event,
-			     struct sk_buff *skb) 
-{
-	
-	DEBUG( 4, __FUNCTION__": STATE = %s, EVENT = %s\n",
-	       ircommstate[self->state], ircommevent[event]);
-	(*state[self->state])(self, event, skb);
-}
-
-static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) 
-{
-	self->state = state;
-	DEBUG( 0, __FUNCTION__": NEXT STATE=%d(%s), servicetype=(%d)\n", 
-	       (int)state, ircommstate[self->state],self->servicetype);
-}
-
-
-
-/*
- * ircomm_state_idle
- */
-
-static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, 
-			       struct sk_buff *skb )
-{
-	switch (event){
-	case IRCOMM_CONNECT_REQUEST:
-
-		/* ircomm_next_state(self, COMM_WAITI); */
-		/* issue_connect_request( self, skb ); */
-
-		ircomm_next_state(self, COMM_DISCOVERY_WAIT);
-		start_discovering(self);
-		break;
-		
-	case TTP_CONNECT_INDICATION:
-
-		ircomm_next_state(self, COMM_WAITR);
-		connect_indication( self, self->qos, skb);
-		break;
-
-	case LMP_CONNECT_INDICATION:
-
-		DEBUG(0,__FUNCTION__"():LMP_CONNECT_IND is notimplemented!");
- 		/* connect_indication_three_wire_raw(); */
- 		/* ircomm_next_state(self, COMM_WAITR); */
-		break;
-
-	default:
-		DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- * ircomm_state_discoverywait
- */
-static void ircomm_state_discoverywait(struct ircomm_cb *self, 
-				       IRCOMM_EVENT event, 
-				       struct sk_buff *skb )
-{
-	switch(event){
-
-	case TTP_CONNECT_INDICATION:
-
-		ircomm_next_state(self, COMM_WAITR);
-		queryias_done(self);
-		connect_indication( self, self->qos, skb);
-		break;
-
-	case DISCOVERY_INDICATION:
-		ircomm_next_state(self, COMM_QUERYPARAM_WAIT);
-		query_parameters(self);
-		break;
-
-	case IRCOMM_DISCONNECT_REQUEST:
-		ircomm_next_state(self, COMM_IDLE);
-		queryias_done(self);
-		break;
-
-	case QUERYIAS_ERROR:
-		ircomm_next_state(self, COMM_IDLE);
-		disconnect_indication(self, NULL);
-		queryias_done(self);
-		break;
-
-	default:
-		DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- * ircomm_state_queryparamwait
- */
-
-static void ircomm_state_queryparamwait(struct ircomm_cb *self, 
-					IRCOMM_EVENT event, 
-					struct sk_buff *skb)
-{
-	switch (event) {
-	case TTP_CONNECT_INDICATION:
-
-		ircomm_next_state(self, COMM_WAITR);
-		connect_indication( self, self->qos, skb);
-		break;
-
-	case GOT_PARAMETERS:
-		
-		ircomm_next_state(self, COMM_QUERYLSAP_WAIT);
-		query_lsapsel( self );
-		break;
-
-	case IRCOMM_DISCONNECT_REQUEST:
-		ircomm_next_state(self, COMM_IDLE);
-		queryias_done(self);
-		break;
-
-	case QUERYIAS_ERROR:
-		ircomm_next_state(self, COMM_IDLE);
-		disconnect_indication(self, NULL);
-		queryias_done(self);
-		break;
-
-	default:
-		DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- * ircomm_state_querylsapwait
- */
-
-static void ircomm_state_querylsapwait(struct ircomm_cb *self, 
-				       IRCOMM_EVENT event, 
-				       struct sk_buff *skb )
-{
-	switch (event) {
-
-	case TTP_CONNECT_INDICATION:
-
-		ircomm_next_state(self, COMM_WAITR);
-		connect_indication( self, self->qos, skb);
-		break;
-
-	case GOT_LSAPSEL:
-		
-		ircomm_next_state(self, COMM_WAITI);
-		queryias_done(self);
-		issue_connect_request( self, skb );
-		break;
-
-	case IRCOMM_DISCONNECT_REQUEST:
-		ircomm_next_state(self, COMM_IDLE);
-		queryias_done(self);
-		break;
-
-	case QUERYIAS_ERROR:
-		ircomm_next_state(self, COMM_IDLE);
-		disconnect_indication(self, NULL);
-		queryias_done(self);
-		break;
-
-
-	default:
-		DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- * ircomm_state_waiti
- */
-
-static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			  struct sk_buff *skb )
-{
-	switch (event) {
-	case TTP_CONNECT_CONFIRM:
-		ircomm_next_state(self, COMM_CONN);
-		connect_confirm(self, skb );
-		break;
-	case TTP_DISCONNECT_INDICATION:
-		ircomm_next_state(self, COMM_IDLE);
-		disconnect_indication(self, skb);
-		break;
-/* 	case LMP_CONNECT_CONFIRM: */
-/* 		ircomm_connect_cnfirmation; */
-/* 		ircomm_next_state(self, COMM_CONN); */
-/* 		break; */
-/* 	case LMP_DISCONNECT_INDICATION: */
-/* 		ircomm_disconnect_ind; */
-/* 		ircomm_next_state(self, COMM_IDLE); */
-/* 		break; */
-	default:
-		DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- * ircomm_state_waitr
- */
-static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			       struct sk_buff *skb ) 
-{
-	switch (event) {
-	case IRCOMM_CONNECT_RESPONSE:
-
-	        /* issue_connect_response */
-		
-		if (self->servicetype==THREE_WIRE_RAW) {
-			DEBUG(0,__FUNCTION__"():3WIRE_RAW is not implemented\n");
-			/* irlmp_connect_response(Vpeersap,
-			 *                         ACCEPT,null);
-			 */
-		} else {
-			ircomm_next_state(self, COMM_CONN);
-			issue_connect_response(self, skb);
-		}
-		break;
-
-	case IRCOMM_DISCONNECT_REQUEST:
-		ircomm_next_state(self, COMM_IDLE);
-		issue_disconnect_request(self, skb);
-		queryias_done(self);
-		break;
-
-	case TTP_DISCONNECT_INDICATION:
-		ircomm_next_state(self, COMM_IDLE);
-		disconnect_indication(self, skb);
-		break;
-
-	case DISCOVERY_INDICATION:
-		DEBUG(0, __FUNCTION__"():DISCOVERY_INDICATION\n");
-		queryias_done(self);
-		break;
-	case GOT_PARAMETERS:
-		DEBUG(0, __FUNCTION__"():GOT_PARAMETERS\n");
-		queryias_done(self);
-		break;
-	case GOT_LSAPSEL:
-		DEBUG(0, __FUNCTION__"():GOT_LSAPSEL\n");
-		queryias_done(self);
-		break;
-
-/* 	case LMP_DISCONNECT_INDICATION: */
-/* 		disconnect_indication();		 */
-/* 		ircomm_next_state(self, COMM_IDLE);		 */
-/* 		break; */
-	default:
-		DEBUG(0,"ircomm_state_waitr:unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- * ircomm_state_conn
- */
-
-static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
-			      struct sk_buff *skb )
-{
-	switch (event) {
-	case TTP_DATA_INDICATION:
-		process_data(self, skb);
-		break;
-	case IRCOMM_DATA_REQUEST:
-		issue_data_request(self, skb);
-		break;
-/* 	case LMP_DATA_INDICATION: */
-/* 		ircomm_data_indicated(); */
-/* 		break; */
-	case IRCOMM_CONTROL_REQUEST:
-		issue_control_request(self, skb);
-		break;
-	case TTP_DISCONNECT_INDICATION:
-		ircomm_next_state(self, COMM_IDLE);
-		disconnect_indication(self, skb);
-		break;
-	case IRCOMM_DISCONNECT_REQUEST:
-		ircomm_next_state(self, COMM_IDLE);
-		issue_disconnect_request(self, skb);
-		queryias_done(self);
-		break;
-/* 	case LM_DISCONNECT_INDICATION: */
-/* 		disconnect_indication(); */
-/* 		ircomm_next_state(self, COMM_IDLE); */
-/* 		break; */
-
-	case DISCOVERY_INDICATION:
-		DEBUG(0, __FUNCTION__"():DISCOVERY_INDICATION\n");
-		queryias_done(self);
-		break;
-	case GOT_PARAMETERS:
-		DEBUG(0, __FUNCTION__"():GOT_PARAMETERS\n");
-		queryias_done(self);
-		break;
-	case GOT_LSAPSEL:
-		DEBUG(0, __FUNCTION__"():GOT_LSAPSEL\n");
-		queryias_done(self);
-		break;
-
-	default:
-		DEBUG(0,"ircomm_state_conn:unknown event =%d(%s)\n",
-		      event, ircommevent[event]);
-	}
-}
-
-/*
- *  ----------------------------------------------------------------------
- *  IrCOMM service interfaces and supporting functions
- *
- *  ----------------------------------------------------------------------
- */
-
-/*
- * Function start_discovering (self)
- *
- *    Start discovering and enter DISCOVERY_WAIT state
- *
- */
-static void start_discovering(struct ircomm_cb *self)
-{
-	__u16  hints; 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-	DEBUG(4,__FUNCTION__"():servicetype = %d\n",self->servicetype);
-	
-
-	hints = irlmp_service_to_hint(S_COMM);
-
-	DEBUG(1,__FUNCTION__"():start discovering..\n");
-	switch (ircomm_cs) {
-	case 0:
-		MOD_INC_USE_COUNT;
-		self->queryias_lock = 1;
-		discovering_instance = self;
-		self->skey = irlmp_register_service(hints);
-		self->ckey = irlmp_register_client(hints, ircomm_discovery_indication,
-					     NULL);
-		break;
-		
-	case 1:    /* client only */
-		MOD_INC_USE_COUNT;
-		self->queryias_lock = 1;
-		discovering_instance = self;
-		DEBUG( 0, __FUNCTION__"():client only mode\n");
-		self->ckey = irlmp_register_client(hints, ircomm_discovery_indication,
-					     NULL);
-		break;
-
-	case 2:     /*  server only  */
-	default:
-		DEBUG( 0, __FUNCTION__"():server only mode\n");
-		self->skey = irlmp_register_service(hints);
-		discovering_instance = NULL;
-		break;
-	}
-	
-	return;
-}
-
-/*
- * queryias_done(self)
- *
- * 
- */
-
-/*
- * Function queryias_done (self)
- *
- *    Called when discovery process got wrong results, completed, or
- *    terminated.
- * 
- */
-static void queryias_done(struct ircomm_cb *self)
-{
-	DEBUG(0, __FUNCTION__"():\n");
-	if (self->queryias_lock){
-		self->queryias_lock = 0;
-		discovering_instance = NULL;
-		MOD_DEC_USE_COUNT;
-		irlmp_unregister_client(self->ckey);
-	}
-	if (ircomm_cs != 1)
-		irlmp_unregister_service(self->skey);
-	return;
-}
-
-
-
-static void query_parameters(struct ircomm_cb *self)
-{
-
-	DEBUG(0, __FUNCTION__"():querying IAS: Parameters..\n");
-	iriap_getvaluebyclass_request( "IrDA:IrCOMM", "Parameters",
-				       self->saddr, self->daddr,
-				       ircomm_getvalue_confirm, self );
-}
-
-static void query_lsapsel(struct ircomm_cb * self)
-{
-	DEBUG(0, __FUNCTION__"():querying IAS: Lsapsel...\n");
-
-	if (!(self->servicetype & THREE_WIRE_RAW)) {
-		iriap_getvaluebyclass_request( 
-			"IrDA:IrCOMM", "IrDA:TinyTP:LsapSel",
-			self->saddr, self->daddr,
-			ircomm_getvalue_confirm, self );
-	} else {
-		DEBUG(0, __FUNCTION__ "THREE_WIRE_RAW is not implemented!\n");
-	}
-}
-
-/*
- * Function ircomm_connect_request (self, servicetype)
- *
- *    Impl. of this function is differ from one of the reference. This
- *    function does discovery as well as sending connect request
- * 
- */
-void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype)
-{
-	/*
-	 * TODO:build a packet which contains "initial control parameters"
-	 * and send it with connect_request
-	 */
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-
-
-	DEBUG(1, __FUNCTION__"():sending connect_request...\n");
-
-	self->servicetype= servicetype;
-	/* ircomm_control_request(self, SERVICETYPE); */ /*servictype*/
-
-	self->rx_max_sdu_size = SAR_DISABLE;
-	ircomm_do_event(self, IRCOMM_CONNECT_REQUEST, NULL);
-}
-
-void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
-			     __u32 max_sdu_size)
-{
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-	/* ASSERT( userdata != NULL, return;); */
-
-	DEBUG(4,"ircomm_connect_response:\n");
-
-	/*
-	 * TODO:build a packet which contains "initial control parameters"
-	 * and send it with connect_response
-	 */
-
-	if (!userdata){
-		/* FIXME: check for errors and initialize? DB */
-		userdata = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + COMM_MAX_HEADER_SIZE);
-		if (userdata == NULL)
-			return;
-
-		skb_reserve(userdata,COMM_MAX_HEADER_SIZE);
-	}
-
-	/* enable null-modem emulation (i.e. server mode )*/
-	self->null_modem_mode = 1;
-
-	self->rx_max_sdu_size = max_sdu_size;
-	
-	ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata);
-}	
-
-void ircomm_disconnect_request(struct ircomm_cb *self, 
-			       struct sk_buff *userdata,
-			       int priority)
-{
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-	DEBUG(0,__FUNCTION__"()\n");
-
-#if 0
-	/* unregister layer */
-	switch (ircomm_cs) {
-	case 1:    /* client only */
-		irlmp_unregister_client(ckey);
-		break;
-
-	case 2:     /*  server only  */
-		irlmp_unregister_service(skey);
-		break;
-	case 0:
-	default:
-		irlmp_unregister_client(ckey);
-		irlmp_unregister_service(skey);
-		break;
-	}
-#endif
-
-	self->disconnect_priority = priority;
-	if(priority != P_HIGH)
-		self->disconnect_priority = P_NORMAL;
-
-	ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata);
-}	
-
-
-int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata)
-{
-	__u8 * frame;
-
-	DEBUG(4,__FUNCTION__"()\n");
-	ASSERT( self != NULL, return -EFAULT;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return -EFAULT;);
-	ASSERT( userdata != NULL, return -EFAULT;);
-	
-
-	if(self->state != COMM_CONN){
-		DEBUG(4,__FUNCTION__"():not connected, data is ignored\n");
-		return -EINVAL;
-	}
-
-	if(self->ttp_stop)
-		return -EBUSY;
-
-	if(self->control_ch_pending){
-		/* send control_channel */
-		ircomm_tx_controlchannel(self);
-	}
-
-	if(self->ttp_stop)
-		return -EBUSY;
-
-	/* add "clen" field */
-	frame = skb_push(userdata,1);
-	frame[0]=0;          /* without control channel */
-
-	ircomm_do_event(self, IRCOMM_DATA_REQUEST, userdata);
-	return 0;
-}
-
-/*
- *  ----------------------------------------------------------------------
- *  IrCOMM_control.req and friends
- *
- *  ----------------------------------------------------------------------
- */
-
-
-static void ircomm_tx_controlchannel(struct ircomm_cb *self )
-{
-
-	__u8 clen;
-	struct sk_buff *skb = self->ctrl_skb;
-	
-	DEBUG(4,__FUNCTION__"()\n");
-	/* 'self' should have been checked */
-	ASSERT(!self->ttp_stop, return ;);
-	ASSERT(self->state == COMM_CONN, return ;);
-
-	/* add "clen" field */
-
-	clen=skb->len;
-	ASSERT(clen != 0,return;);
-
-	skb_push(skb,1);
-	skb->data[0]=clen;
-
-#if 0
-	printk("tx_ctrl:");
-	{
-		int i;
-		for ( i=0;i<skb->len;i++)
-			printk("%02x", skb->data[i]);
-		printk("\n");
-	}
-#endif
-	
-	ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb);
-	self->control_ch_pending = 0;
-
-	skb = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + COMM_MAX_HEADER_SIZE);
-	ASSERT(skb != NULL, return ;);
-
-	skb_reserve(skb,COMM_MAX_HEADER_SIZE);
-	self->ctrl_skb = skb;
-}
-
-
-static void append_tuple(struct ircomm_cb *self, __u8 instruction, __u8 pl , 
-			 __u8 *value)
-{
-	__u8 *frame;
-	struct sk_buff *skb;
-	int i,c = 0;
-	unsigned long flags;
-
-	save_flags(flags);cli();
-
-	skb = self->ctrl_skb;
-	ASSERT(skb != NULL, return;);
-	
-	if(skb_tailroom(skb) < (pl+2)){
-		DEBUG(0, __FUNCTION__"there's no room.. ignore it\n");
-		self->ignored_control_tuples++;
-		restore_flags(flags);
-		return;
-	}
-
-	frame = skb_put(skb,pl+2);
-	frame[c++] = instruction;     /* PI */
-	frame[c++] = pl;              /* PL */
-	for(i=0; i < pl ; i++)
-		frame[c++] = *value++;   /* PV */
-	restore_flags(flags);	
-	self->pending_control_tuples++;
-	self->control_ch_pending = 1;
-}
-
-/*
- * Function ircomm_control_request (self, instruction)
- *
- *    This function is exported as a request to send some control-channel
- *    tuples * to peer device
- * 
- */
-void ircomm_control_request(struct ircomm_cb *self,  __u8 instruction)
-{
-
-	__u8  pv[32];      /* 32 max, for PORT_NAME */
-	__u8  *value = &pv[0];
-	__u32 temp;
-	int notsupp=0;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return;);
-
-	if(self->servicetype == THREE_WIRE_RAW){
-		DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW shuold not use me!\n");
-		return;
-	}
-
-	DEBUG(4,__FUNCTION__"()\n");
-
-	/* find parameter and its length */
-
-	if(self->servicetype == THREE_WIRE) goto threewire;
-	if(self->servicetype == NINE_WIRE) goto ninewire;
-
-
-	/* FIXME: centronics service is not fully implemented yet*/
-	switch(instruction){
-	case IEEE1284_MODE_SUPPORT:
-	case IEEE1284_DEVICEID:
-		append_tuple(self,instruction,0,NULL);
-		break;
-	case STATUS_QUERY:
-		append_tuple(self,instruction,0,NULL);
-		break;
-	case SET_BUSY_TIMEOUT:
-		value[0] = self->busy_timeout;
-		append_tuple(self,instruction,1,value);
-		break;
- 	case IEEE1284_ECP_EPP_DATA_TRANSFER: 
-		value[0] = self->ecp_epp_mode;
-		value[1] = self->channel_or_addr;
-		append_tuple(self,instruction,2,value); 
-		break; 
-	default:
-		notsupp=1;
-	}
-
- ninewire:
-	switch(instruction){
-	case POLL_FOR_LINE_SETTINGS:
-		append_tuple(self,instruction,0,NULL);
-		break;
-	case DTELINE_STATE:		
-		if(self->null_modem_mode){
-			/* null modem emulation */
-
-			/* output RTS as CTS */
-
-			if(self->dte & DELTA_RTS)
-				value[0] = DELTA_CTS;
-			if(self->dte & MCR_RTS)
-				value[0] |= MSR_CTS;
-
-			/* output DTR as {DSR & CD & RI} */
-
-			if(self->dte & DELTA_DTR)
-				value[0] |= (DELTA_DSR|DELTA_RI|DELTA_DCD);
-			if(self->dte & MCR_DTR)
-				value[0] |= (MSR_DSR|MSR_RI|MSR_DCD);
-			append_tuple(self,DCELINE_STATE,1,value);
-		}else{
-			value[0] = self->dte;
-			append_tuple(self,instruction,1,value);
-		}
-		self->dte &= ~(DELTA_RTS|DELTA_DTR);
-		break;
-
-	case DCELINE_STATE:		
-		value[0] = self->dce;
-		append_tuple(self,instruction,1,value);
-		break;
-
-	default:
-		notsupp=1;
-	}
-
- threewire:
-	switch(instruction){
-
-	case SERVICETYPE:
-		value[0] = self->servicetype;
-		append_tuple(self,instruction,1,value);
-		break;
-
-	case DATA_FORMAT:
-		value[0] = self->data_format;
-		append_tuple(self,instruction,1,value);
-		break;
-
-	case FLOW_CONTROL:
-		if(self->null_modem_mode){
-			/* inside out */
-			value[0]  = (self->flow_ctrl & 0x55) << 1;
-			value[0] |= (self->flow_ctrl & 0xAA) >> 1;
-		}else{
-			value[0] = self->flow_ctrl;
-		}
-		append_tuple(self,instruction,1,value);
-		break;
-
-	case LINESTATUS:
-		value[0] = self->line_status;
-		append_tuple(self,instruction,1,value);
-		break;
-
-	case BREAK_SIGNAL:
-		value[0] = self->break_signal;
-		append_tuple(self,instruction,1,value);
-		break;
-
-	case XON_XOFF_CHAR:
-		value[0] = self->xon_char;
-		value[1] = self->xoff_char;
-		append_tuple(self,instruction,2,value); 
-		break; 
-
-	case ENQ_ACK_CHAR:
-		value[0] = self->enq_char;
-		value[1] = self->ack_char;
-		append_tuple(self,instruction,2,value); 
-		break; 
-
-	case DATA_RATE:
-		temp = self->data_rate;
-		value[3] = (__u8)((temp >> 24) & 0x000000ff);
-		value[2] = (__u8)((temp >> 16) & 0x000000ff);
-		value[1] = (__u8)((temp >> 8) & 0x000000ff);
-		value[0] = (__u8)(temp & 0x000000ff);
- 		append_tuple(self,instruction,4,value);
- 		break;
-#if 0
-	case PORT_NAME:
-	case FIXED_PORT_NAME:
-		temp = strlen(&self->port_name);
-		if(temp < 32){
-			value = (__u8) (self->port_name);
-			append_tuple(self,instruction,temp,value);
-		}else
-			DEBUG(0,__FUNCTION__"() PORT_NAME:too long\n");
-#endif
-		break;
-
-	default:
-		if(notsupp)
-			DEBUG(0,__FUNCTION__"():instruction(0x%02x)is not"
-			      "implemented\n",instruction);
-	}
-
-
-}
-
-void ircomm_parse_tuples(struct ircomm_cb *self, struct sk_buff *skb, int type)
-{
-
-	__u8 *data;
-	__u8 pi,plen;
-	int clen = 0;
-	int indicate=0;
-
-	ASSERT(skb != NULL, return;);
-	ASSERT(self != NULL, return ;);
-	ASSERT(self->magic == IRCOMM_MAGIC, return ;);
-
-
-#ifdef IRCOMM_DEBUG_TUPLE
-	DEBUG(0, __FUNCTION__"():tuple sequence is:\n");
-	{
-		int i;
-		for ( i=0;i< skb->len;i++)
-			printk("%02x", (__u8)(skb->data[i]));
-		printk("\n");
-	}
-#endif
-
-	data = skb->data;
-	if(type == IAS_PARAM)
-	{
-		clen = (data[0] << 8) & 0xff00;
-		clen |= data[1] & 0x00ff;
-		ASSERT( clen <= (skb->len - 2) && clen <= 1024, goto corrupted;);
-		DEBUG(4, __FUNCTION__"():IAS_PARAM len = %d\n",clen );
-		skb_pull( skb, 2);
-	}
-	else
-	{
-		/* CONTROL_CHANNEL */
-		clen = data[0];
-		ASSERT( clen < skb->len, goto corrupted;);
-		DEBUG(4, __FUNCTION__"():CONTROL_CHANNEL:len = %d\n",clen );
-		skb_pull( skb, 1);
-	}
-
-	while( clen >= 2 ){
-		data = skb->data;
-		indicate = 0;
-
-		/* 
-		 * parse controlparameters and set value into structure 
-		 */
-		pi = data[0];
-		plen = data[1];
-
-		ASSERT( clen >= 2+plen, goto corrupted; );
-		DEBUG(4, __FUNCTION__"():instruction=0x%02x,len=%d\n",
-		      pi, plen) ;
-
-
-		switch(pi)
-		{
-		case POLL_FOR_LINE_SETTINGS:
-			ircomm_control_request(self, DTELINE_STATE);
-			break;
-		
-		case SERVICETYPE:
-			self->peer_servicetype = data[2];
-			break;
-
-		case PORT_TYPE:
-			self->peer_port_type = data[2];
-			break;
-
-		case DATA_FORMAT:   
-			self->peer_data_format = data[2];
-			break;
-
-		case FLOW_CONTROL:
-			self->peer_flow_ctrl = data[2];
-			indicate = 1;
-			break;
-
-		case LINESTATUS:
-			self->peer_line_status = data[2];
-			indicate = 1;
-			break;
-
-		case BREAK_SIGNAL:
-			self->peer_break_signal = data[2];
-			/* indicate = 1; */
-			break;
-
-		case DCELINE_STATE:
-			self->peer_dce = data[2];
-			indicate = 1;
-			break;
-
-		case DTELINE_STATE:
-			if(self->null_modem_mode){
-				/* input DTR as {DSR & CD & RI} */
-				self->peer_dce = 0;
-				if(data[2] & DELTA_DTR)
-					self->peer_dce |= (DELTA_DSR|
-							   DELTA_RI|
-							   DELTA_DCD);
-				if(data[2] & MCR_DTR)
-					self->peer_dce |= (MSR_DSR|
-							   MSR_RI|
-							   MSR_DCD);
-				/* rts as cts */
-				if(data[2] & DELTA_RTS)
-					self->peer_dce |= DELTA_CTS;
-				if(data[2] & MCR_RTS)
-					self->peer_dce |= MSR_CTS;
-			}else{
-				self->peer_dte = data[2];
-			}
-			indicate = 1;			
-			break;
-			
-		case XON_XOFF_CHAR:
-			self->peer_xon_char = data[2];
-			self->peer_xoff_char = data[3];
-			indicate = 1;
-			break;
-
-		case ENQ_ACK_CHAR:
-			self->peer_enq_char = data[2];
-			self->peer_ack_char = data[3];
-			indicate = 1;
-			break;
-
-		case DATA_RATE:
-			self->peer_data_rate = (  data[5]<<24
-						  & data[4]<<16
-						  & data[3]<<8
-						  & data[2]);
-			indicate = 1;
-			break;
-
-		case PORT_NAME:
-			ASSERT(plen <= 32 , goto corrupted;);
-			memcpy(self->port_name, data + 2, plen);
-			*(__u8 *)(self->port_name+plen) = 0;
-			break;
-
-		case FIXED_PORT_NAME:
-			ASSERT(plen <= 32 , goto corrupted;);
-			memcpy(self->port_name, data + 2, plen);
-			*(__u8 *)(self->port_name+plen) = 0;
-			/* 
-			 * We should not connect if user of IrCOMM can't
-			 * recognize the port name
-			 */
-			self->port_name_critical = TRUE;
-			break;
-
-		default:
-			DEBUG(0, __FUNCTION__
-			      "():not implemented (PI=%d)\n", pi);
-		}
-
-
-		if(indicate && 
-		   self->notify.flow_indication && type == CONTROL_CHANNEL)
-		{
-			DEBUG(4,__FUNCTION__":indicating..:\n");
-			self->pi = pi;
-			if(self->notify.flow_indication)
-				self->notify.flow_indication(self->notify.instance,
-							     self,
-							     CONTROL_CHANNEL);
-		}
-		skb_pull(skb, 2+plen);
-		clen -= (2+plen);
-	}
-
-	return;
-
- corrupted:
-	skb_pull(skb, skb->len);   /* remove suspicious data */
-	return;
-}
-
-/*
- * ----------------------------------------------------------------------
- * Function ircomm_open_instance() ,ircomm_close_instance() and friends
- *
- * ircomm_open_instance discoveres the peer device and then issues a
- * connect request
- * ----------------------------------------------------------------------
- */
-
-
-
-struct ircomm_cb * ircomm_open_instance( struct notify_t client_notify)
-{
-	int i;
-	struct ircomm_cb *self = NULL;
-	struct notify_t notify;
-	unsigned long flags;
-
-	ASSERT(ircomm != NULL,return NULL;);
-	DEBUG(0,__FUNCTION__"():\n");
-
-	/* find free handle */
-
-	save_flags(flags);
-	cli();
-	for(i = 0; i < IRCOMM_MAX_CONNECTION; i++){
-		ASSERT(ircomm[i] != NULL,return(NULL););
-		if(!ircomm[i]->in_use){
-			self = ircomm[i];
-			break;
-		}
-	}
-
-	if (!self){
-		DEBUG(0,__FUNCTION__"():no free handle!\n");
-		return (NULL);
-	}
-
-	self->in_use = 1;
-	restore_flags(flags);
-
-	self->notify = client_notify;
-	self->ttp_stop = 0;
-	self->control_ch_pending = 0;
-
-	/* register callbacks */
-
-	irda_notify_init(&notify);
-	notify.data_indication = ircomm_accept_data_indication;
-	notify.connect_confirm = ircomm_accept_connect_confirm;
-	notify.connect_indication = ircomm_accept_connect_indication;
-	notify.flow_indication = ircomm_accept_flow_indication;
-	notify.disconnect_indication = ircomm_accept_disconnect_indication;
-	notify.instance = self;
-	strncpy( notify.name, "IrCOMM", NOTIFY_MAX_NAME);
-
-	self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
-				     &notify);
-	if(!self->tsap){
-		DEBUG(0,__FUNCTION__"failed to allocate tsap\n");
-		return NULL;
-	}
-
-	ircomm_next_state(self, COMM_IDLE);	
-	return (self);
-}
-
-int ircomm_close_instance(struct ircomm_cb *self)
-{
-	ASSERT( self != NULL, return -EIO;);
-	ASSERT( self->magic == IRCOMM_MAGIC, return -EIO;);
-	ASSERT( self->ctrl_skb != NULL, return -EIO;);
-
-	DEBUG(0,__FUNCTION__"()\n");
-
-	/* shutdown ircomm layer */
-	if(self->state != COMM_IDLE && self->state != COMM_WAITI)
-	{
-		DEBUG(0,__FUNCTION__"():force disconnecting..\n");
-		ircomm_disconnect_request(self, NULL, P_HIGH);
-	}
-
-	skb_trim(self->ctrl_skb,0);
-	/* remove a tsap */
-	if(self->tsap)
-		irttp_close_tsap(self->tsap);
-	self->tsap = NULL;
-	self->in_use = 0;
-	return 0;
-}
-
-
-/*
- * ----------------------------------------------------------------------
- * Function init_module(void) ,cleanup_module()
- *
- *   Initializes the ircomm control structure
- *   These Function are called when you insmod / rmmod .
- * ----------------------------------------------------------------------
- */
-
-#ifdef MODULE
-int init_module(void) 
-{
-	int err;
-
-	err = ircomm_init();
-
-	DEBUG( 4, __FUNCTION__"():done.\n");
-	return err;
-}
-	
-void cleanup_module(void)
-{
-	ircomm_cleanup();
-	DEBUG( 4, __FUNCTION__"():done.\n");
-}
-#endif /* MODULE */
-
-/************************************************************
- *     proc stuff
- ************************************************************/
-
-#ifdef CONFIG_PROC_FS
-
-/*
- * Function proc_ircomm_read (buf, start, offset, len, unused)
- *
- * this function is called if there is a access on /proc/irda/comm .
- *
- */
-int ircomm_proc_read(char *buf, char **start, off_t offset,
-		     int len, int unused)
-{
-	int i, index;
-
-	len = 0;
-	for (i=0; i<IRCOMM_MAX_CONNECTION; i++) {
-
-		len += sprintf(buf+len, "instance %d:\n",i);
-		if(ircomm[i]->in_use == 0){
-			len += sprintf(buf+len, "\tunused\n");
-			continue;
-		}
-
-		if (ircomm[i] == NULL || ircomm[i]->magic != IRCOMM_MAGIC) {
-			len += sprintf(buf+len, "\tbroken???\n");
-			continue;
-		}
-
-		switch (ircomm[i]->servicetype) {
-		case UNKNOWN:
-			index = 0;
-			break;
-		case THREE_WIRE_RAW:
-			index = 1;
-			break;
-		case THREE_WIRE:
-			index = 2;
-			break;
-		case NINE_WIRE:
-			index = 3;
-			break;
-		case CENTRONICS:
-			index = 4;
-			break;
-		default:
-			index = 0;
-			break;
-		}
-		len += sprintf(buf+len, "    service: %s  ",
-			       ircommservicetype[index]);
-		if(!index)
-			continue;
-
-		len += sprintf(buf+len, "porttype: %s  ",
-			       ircommporttype[ircomm[i]->port_type]);
-		len += sprintf(buf+len, "state: %s  ",
-			       ircommstate[ircomm[i]->state]);
-		len += sprintf(buf+len, "user: %s\n",
-			       ircomm[i]->notify.name);
-		
-		len += sprintf(buf+len, "    tx packets: %d  ",
-			       ircomm[i]->tx_packets);
-		len += sprintf(buf+len, "rx packets: %d  ",
-			       ircomm[i]->rx_packets);
-		len += sprintf(buf+len, "tx controls: %d\n",
-			       ircomm[i]->tx_controls);
-		
-		len += sprintf(buf+len, "    pending tuples: %d  ",
-			       ircomm[i]->pending_control_tuples);
-		len += sprintf(buf+len, "    ignored tuples: %d\n",
-			       ircomm[i]->ignored_control_tuples);
-		
-		len += sprintf(buf+len, "    nullmodem emulation: %s  ",
-			       (ircomm[i]->null_modem_mode ? "yes":"no"));
-		len += sprintf(buf+len, "IrTTP: %s\n",
-			       (ircomm[i]->ttp_stop ? "BUSY":"READY"));
-
-		len += sprintf(buf+len, "    Peer capability: ");
-		if(ircomm[i]->peer_cap & THREE_WIRE_RAW)
-			len += sprintf(buf+len, "3wire-raw ");
-		if(ircomm[i]->peer_cap & THREE_WIRE)
-			len += sprintf(buf+len, "3wire ");
-		if(ircomm[i]->peer_cap & NINE_WIRE)
-			len += sprintf(buf+len, "9wire ");
-		if(ircomm[i]->peer_cap & CENTRONICS)
-			len += sprintf(buf+len, "centronics");
-
-		len += sprintf(buf+len, "\n    Port name: %s\n",
-			       (ircomm[i]->port_name));
-	}
-
-	return len;
-}
-
-#endif /* CONFIG_PROC_FS */
-
-
-
-
diff -u --recursive --new-file v2.3.15/linux/net/irda/ircomm/ircomm_core.c linux/net/irda/ircomm/ircomm_core.c
--- v2.3.15/linux/net/irda/ircomm/ircomm_core.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/ircomm_core.c	Tue Aug 31 11:23:03 1999
@@ -0,0 +1,508 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_core.c
+ * Version:       1.0
+ * Description:   IrCOMM service interface
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 20:37:34 1999
+ * Modified at:   Tue Aug 17 11:05:41 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irias_object.h>
+
+#include <net/irda/ircomm_event.h>
+#include <net/irda/ircomm_lmp.h>
+#include <net/irda/ircomm_ttp.h>
+#include <net/irda/ircomm_param.h>
+#include <net/irda/ircomm_core.h>
+
+static int __ircomm_close(struct ircomm_cb *self);
+static void ircomm_control_indication(struct ircomm_cb *self, 
+				      struct sk_buff *skb, int clen);
+
+#ifdef CONFIG_PROC_FS
+static int ircomm_proc_read(char *buf, char **start, off_t offset, int len, 
+			    int unused);
+
+extern struct proc_dir_entry *proc_irda;
+#endif /* CONFIG_PROC_FS */
+
+hashbin_t *ircomm = NULL;
+
+int __init ircomm_init(void)
+{
+	ircomm = hashbin_new(HB_LOCAL); 
+	if (ircomm == NULL) {
+		ERROR(__FUNCTION__ "(), can't allocate hashbin!\n");
+		return -ENOMEM;
+	}
+	
+#ifdef CONFIG_PROC_FS
+	create_proc_entry("ircomm", 0, proc_irda)->get_info = ircomm_proc_read;
+#endif /* CONFIG_PROC_FS */
+	
+	MESSAGE("IrCOMM protocol (Dag Brattli)\n");
+		
+	return 0;
+}
+
+#ifdef MODULE
+void ircomm_cleanup(void)
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	hashbin_delete(ircomm, (FREE_FUNC) __ircomm_close);
+
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("ircomm", proc_irda);
+#endif /* CONFIG_PROC_FS */
+}
+#endif /* MODULE */
+
+/*
+ * Function ircomm_open (client_notify)
+ *
+ *    Start a new IrCOMM instance
+ *
+ */
+struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line)
+{
+	struct ircomm_cb *self = NULL;
+	int ret;
+
+	DEBUG(2, __FUNCTION__ "(), service_type=0x%02x\n",
+	      service_type);
+
+	ASSERT(ircomm != NULL, return NULL;);
+
+	self = kmalloc(sizeof(struct ircomm_cb), GFP_ATOMIC);
+	if (self == NULL)
+		return NULL;
+
+	memset(self, 0, sizeof(struct ircomm_cb));
+
+	self->notify = *notify;
+	self->magic = IRCOMM_MAGIC;
+
+	/* Check if we should use IrLMP or IrTTP */
+	if (service_type & IRCOMM_3_WIRE_RAW) {
+		self->flow_status = FLOW_START;
+		ret = ircomm_open_lsap(self);
+	} else
+		ret = ircomm_open_tsap(self);
+
+	if (ret < 0)
+		return NULL;
+
+	self->service_type = service_type;
+	self->line = line;
+
+	hashbin_insert(ircomm, (QUEUE *) self, line, NULL);
+
+	ircomm_next_state(self, IRCOMM_IDLE);	
+
+	return self;
+}
+
+/*
+ * Function ircomm_close_instance (self)
+ *
+ *    Remove IrCOMM instance
+ *
+ */
+static int __ircomm_close(struct ircomm_cb *self)
+{
+	DEBUG(2, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return -EIO;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -EIO;);
+
+	/* Disconnect link if any */
+	ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, NULL, NULL);
+
+	/* Remove TSAP */
+	if (self->tsap)
+		irttp_close_tsap(self->tsap);
+	self->tsap = NULL;
+
+	/* Remove LSAP */
+	if (self->lsap) {
+		irlmp_close_lsap(self->lsap);
+		self->lsap = NULL;
+	}
+	self->magic = 0;
+
+	kfree(self);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_close (self)
+ *
+ *    Closes and removes the specified IrCOMM instance
+ *
+ */
+int ircomm_close(struct ircomm_cb *self)
+{
+	struct ircomm_cb *entry;
+
+	entry = hashbin_remove(ircomm, self->line, NULL);
+
+	ASSERT(entry == self, return -1;);
+	
+        return __ircomm_close(self);
+}
+
+/*
+ * Function ircomm_connect_request (self, service_type)
+ *
+ *    Impl. of this function is differ from one of the reference. This
+ *    function does discovery as well as sending connect request
+ * 
+ */
+int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel, 
+			   __u32 saddr, __u32 daddr, struct sk_buff *skb,
+			   __u8 service_type)
+{
+	struct ircomm_info info;
+	int ret;
+
+	DEBUG(2 , __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+
+	self->service_type= service_type;
+
+	info.dlsap_sel = dlsap_sel;
+	info.saddr = saddr;
+	info.daddr = daddr;
+
+	ret = ircomm_do_event(self, IRCOMM_CONNECT_REQUEST, skb, &info);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_connect_indication (self, qos, skb)
+ *
+ *    Notify user layer about the incomming connection
+ *
+ */
+void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+			       struct ircomm_info *info)
+{
+	int clen = 0;
+	
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	/* Check if the packet contains data on the control channel */
+	if (skb->len > 0)
+		clen = skb->data[0];
+	
+	/* 
+	 * If there are any data hiding in the control channel, we must 
+	 * deliver it first. The side effect is that the control channel 
+	 * will be removed from the skb
+	 */
+#if 0
+	if (clen > 0)
+		ircomm_control_indication(self, skb, clen);
+#endif
+	if (self->notify.connect_indication)
+		self->notify.connect_indication(self->notify.instance, self, 
+						info->qos, info->max_data_size,
+						info->max_header_size, skb);
+}
+
+/*
+ * Function ircomm_connect_response (self, userdata, max_sdu_size)
+ *
+ *    User accepts connection
+ *
+ */
+int ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata)
+{
+	int ret;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ret = ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata, NULL);
+
+	return ret;
+}	
+
+/*
+ * Function connect_confirm (self, skb)
+ *
+ *    Notify user layer that the link is now connected
+ *
+ */
+void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb,
+			    struct ircomm_info *info)
+{
+	DEBUG(4, __FUNCTION__"()\n");
+
+	if (self->notify.connect_confirm )
+		self->notify.connect_confirm(self->notify.instance,
+					     self, info->qos, 
+					     info->max_data_size,
+					     info->max_header_size, skb);
+}
+
+/*
+ * Function ircomm_data_request (self, userdata)
+ *
+ *    Send IrCOMM data to peer device
+ *
+ */
+int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *skb)
+{
+	int ret;
+
+	DEBUG(4, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return -EFAULT;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
+	ASSERT(skb != NULL, return -EFAULT;);
+	
+	ret = ircomm_do_event(self, IRCOMM_DATA_REQUEST, skb, NULL);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_data_indication (self, skb)
+ *
+ *    Data arrived, so deliver it to user
+ *
+ */
+void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
+{	
+	DEBUG(4, __FUNCTION__"()\n");
+
+	ASSERT(skb->len > 0, return;);
+
+	if (self->notify.data_indication)
+		self->notify.data_indication(self->notify.instance, self, skb);
+}
+
+/*
+ * Function ircomm_process_data (self, skb)
+ *
+ *    Data arrived which may contain control channel data
+ *
+ */
+void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
+{
+	int clen;
+
+	ASSERT(skb->len > 0, return;);
+
+	clen = skb->data[0];
+
+	/* 
+	 * If there are any data hiding in the control channel, we must 
+	 * deliver it first. The side effect is that the control channel 
+	 * will be removed from the skb
+	 */
+	if (clen > 0)
+		ircomm_control_indication(self, skb, clen);
+
+	/* Remove control channel from data channel */
+	skb_pull(skb, clen+1);
+
+	if (skb->len)
+		ircomm_data_indication(self, skb);		
+	else {
+		DEBUG(4, __FUNCTION__ "(), data was control info only!\n");
+		dev_kfree_skb(skb);
+	}
+}
+
+/*
+ * Function ircomm_control_request (self, params)
+ *
+ *    Send control data to peer device
+ *
+ */
+int ircomm_control_request(struct ircomm_cb *self, struct sk_buff *skb)
+{
+	int ret;
+	
+	DEBUG(2, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return -EFAULT;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
+	ASSERT(skb != NULL, return -EFAULT;);
+	
+	ret = ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb, NULL);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_control_indication (self, skb)
+ *
+ *    Data has arrived on the control channel
+ *
+ */
+static void ircomm_control_indication(struct ircomm_cb *self, 
+				      struct sk_buff *skb, int clen)
+{
+	struct sk_buff *ctrl_skb;
+
+	DEBUG(2, __FUNCTION__"()\n");	
+
+	ctrl_skb = skb_clone(skb, GFP_ATOMIC);
+	if (!ctrl_skb)
+		return;
+
+	/* Remove data channel from control channel */
+	skb_trim(ctrl_skb, clen+1);
+	
+	/* Use udata for delivering data on the control channel */
+	if (self->notify.udata_indication)
+		self->notify.udata_indication(self->notify.instance, self, 
+					      ctrl_skb);
+}
+
+/*
+ * Function ircomm_disconnect_request (self, userdata, priority)
+ *
+ *    User layer wants to disconnect the IrCOMM connection
+ *
+ */
+int ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata)
+{
+	struct ircomm_info info;
+	int ret;
+
+	DEBUG(2, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+
+	ret = ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata, 
+			      &info);
+	return ret;
+}
+
+/*
+ * Function disconnect_indication (self, skb)
+ *
+ *    Tell user that the link has been disconnected
+ *
+ */
+void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
+				  struct ircomm_info *info)
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+       
+	ASSERT(info != NULL, return;);
+
+	if (self->notify.disconnect_indication) {
+		self->notify.disconnect_indication(self->notify.instance, self,
+						   info->reason, skb);
+	}
+}
+
+/*
+ * Function ircomm_flow_request (self, flow)
+ *
+ *    
+ *
+ */
+void ircomm_flow_request(struct ircomm_cb *self, LOCAL_FLOW flow)
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+
+	if (self->service_type == IRCOMM_3_WIRE_RAW)
+		return;
+
+	irttp_flow_request(self->tsap, flow);
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Function ircomm_proc_read (buf, start, offset, len, unused)
+ *
+ *    
+ *
+ */
+int ircomm_proc_read(char *buf, char **start, off_t offset, int len, 
+		     int unused)
+{ 	
+	struct ircomm_cb *self;
+	unsigned long flags;
+	int i=0;
+	
+	save_flags(flags);
+	cli();
+
+	len = 0;
+
+	len += sprintf(buf+len, "Instance %d:\n", i++);
+
+	self = (struct ircomm_cb *) hashbin_get_first(ircomm);
+	while (self != NULL) {
+		ASSERT(self->magic == IRCOMM_MAGIC, return len;);
+
+		self = (struct ircomm_cb *) hashbin_get_next(ircomm);
+ 	} 
+	restore_flags(flags);
+
+	return len;
+}
+#endif /* CONFIG_PROC_FS */
+
+#ifdef MODULE
+int init_module(void) 
+{
+	return ircomm_init();
+}
+	
+void cleanup_module(void)
+{
+	ircomm_cleanup();
+}
+#endif /* MODULE */
+
diff -u --recursive --new-file v2.3.15/linux/net/irda/ircomm/ircomm_event.c linux/net/irda/ircomm/ircomm_event.c
--- v2.3.15/linux/net/irda/ircomm/ircomm_event.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/ircomm_event.c	Tue Aug 31 09:33:09 1999
@@ -0,0 +1,254 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_event.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 20:33:11 1999
+ * Modified at:   Wed Aug 25 12:58:27 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irias_object.h>
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_event.h>
+
+static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			     struct sk_buff *skb, struct ircomm_info *info);
+static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			      struct sk_buff *skb, struct ircomm_info *info);
+static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			      struct sk_buff *skb, struct ircomm_info *info);
+static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			     struct sk_buff *skb, struct ircomm_info *info);
+
+
+char *ircomm_state[] = {
+	"IRCOMM_IDLE",
+	"IRCOMM_WAITI",
+	"IRCOMM_WAITR",
+	"IRCOMM_CONN",
+};
+
+char *ircomm_event[] = {
+	"IRCOMM_CONNECT_REQUEST",
+        "IRCOMM_CONNECT_RESPONSE",
+        "IRCOMM_TTP_CONNECT_INDICATION",
+	"IRCOMM_LMP_CONNECT_INDICATION",
+        "IRCOMM_TTP_CONNECT_CONFIRM",
+	"IRCOMM_LMP_CONNECT_CONFIRM",
+
+        "IRCOMM_LMP_DISCONNECT_INDICATION",
+	"IRCOMM_TTP_DISCONNECT_INDICATION",
+        "IRCOMM_DISCONNECT_REQUEST",
+
+        "IRCOMM_TTP_DATA_INDICATION",
+	"IRCOMM_LMP_DATA_INDICATION",
+        "IRCOMM_DATA_REQUEST",
+        "IRCOMM_CONTROL_REQUEST",
+        "IRCOMM_CONTROL_INDICATION",
+};
+
+static int (*state[])(struct ircomm_cb *self, IRCOMM_EVENT event,
+		      struct sk_buff *skb, struct ircomm_info *info) = 
+{
+	ircomm_state_idle,
+	ircomm_state_waiti,
+	ircomm_state_waitr,
+	ircomm_state_conn,
+};
+
+/*
+ * Function ircomm_state_idle (self, event, skb)
+ *
+ *    IrCOMM is currently idle
+ *
+ */
+static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			     struct sk_buff *skb, struct ircomm_info *info)
+{
+	int ret = 0;
+
+	switch (event) {
+	case IRCOMM_CONNECT_REQUEST:
+		ircomm_next_state(self, IRCOMM_WAITI);		
+		ret = self->issue.connect_request(self, skb, info);
+		break;
+	case IRCOMM_TTP_CONNECT_INDICATION:
+	case IRCOMM_LMP_CONNECT_INDICATION:
+		ircomm_next_state(self, IRCOMM_WAITR);
+		ircomm_connect_indication(self, skb, info);
+		break;
+	default:
+		DEBUG(4, __FUNCTION__"(), unknown event: %s\n",
+		      ircomm_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_state_waiti (self, event, skb)
+ *
+ *    The IrCOMM user has requested an IrCOMM connection to the remote 
+ *    device and is awaiting confirmation
+ */
+static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			      struct sk_buff *skb, struct ircomm_info *info)
+{
+	int ret = 0;
+
+	switch (event) {
+	case IRCOMM_TTP_CONNECT_CONFIRM:
+	case IRCOMM_LMP_CONNECT_CONFIRM:
+		ircomm_next_state(self, IRCOMM_CONN);
+		ircomm_connect_confirm(self, skb, info);
+		break;
+	case IRCOMM_TTP_DISCONNECT_INDICATION:
+	case IRCOMM_LMP_DISCONNECT_INDICATION:
+		ircomm_next_state(self, IRCOMM_IDLE);
+		ircomm_disconnect_indication(self, skb, info);
+		break;
+	default:
+		DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+		      ircomm_event[event]);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_state_waitr (self, event, skb)
+ *
+ *    IrCOMM has received an incomming connection request and is awaiting
+ *    response from the user
+ */
+static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			      struct sk_buff *skb, struct ircomm_info *info) 
+{
+	int ret = 0;
+
+	switch (event) {
+	case IRCOMM_CONNECT_RESPONSE:
+		ircomm_next_state(self, IRCOMM_CONN);
+		ret = self->issue.connect_response(self, skb);
+		break;
+
+	case IRCOMM_DISCONNECT_REQUEST:
+		ircomm_next_state(self, IRCOMM_IDLE);
+		ret = self->issue.disconnect_request(self, skb, info);
+		break;
+
+	case IRCOMM_TTP_DISCONNECT_INDICATION:
+	case IRCOMM_LMP_DISCONNECT_INDICATION:
+		ircomm_next_state(self, IRCOMM_IDLE);
+		ircomm_disconnect_indication(self, skb, info);
+		break;
+
+	default:
+		DEBUG(0, __FUNCTION__ "(), unknown event = %s\n",
+		      ircomm_event[event]);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_state_conn (self, event, skb)
+ *
+ *    IrCOMM is connected to the peer IrCOMM device
+ *
+ */
+static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			     struct sk_buff *skb, struct ircomm_info *info)
+{
+	int ret = 0;
+
+	switch (event) {
+	case IRCOMM_DATA_REQUEST:
+		ret = self->issue.data_request(self, skb, 0);
+		break;
+	case IRCOMM_TTP_DATA_INDICATION:
+		ircomm_process_data(self, skb);
+		break;
+	case IRCOMM_LMP_DATA_INDICATION:
+		ircomm_data_indication(self, skb);
+		break;
+	case IRCOMM_CONTROL_REQUEST:
+		/* Just send a separate frame for now */
+		ret = self->issue.data_request(self, skb, skb->len);
+		break;
+	case IRCOMM_TTP_DISCONNECT_INDICATION:
+	case IRCOMM_LMP_DISCONNECT_INDICATION:
+		ircomm_next_state(self, IRCOMM_IDLE);
+		ircomm_disconnect_indication(self, skb, info);
+		break;
+	case IRCOMM_DISCONNECT_REQUEST:
+		ircomm_next_state(self, IRCOMM_IDLE);
+		ret = self->issue.disconnect_request(self, skb, info);
+		break;
+	default:
+		DEBUG(0, __FUNCTION__ "(), unknown event = %s\n",
+		      ircomm_event[event]);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+
+/*
+ * Function ircomm_do_event (self, event, skb)
+ *
+ *    Process event
+ *
+ */
+int ircomm_do_event(struct ircomm_cb *self, IRCOMM_EVENT event,
+		    struct sk_buff *skb, struct ircomm_info *info) 
+{
+	DEBUG(4, __FUNCTION__": state=%s, event=%s\n",
+	      ircomm_state[self->state], ircomm_event[event]);
+
+	return (*state[self->state])(self, event, skb, info);
+}
+
+/*
+ * Function ircomm_next_state (self, state)
+ *
+ *    Switch state
+ *
+ */
+void ircomm_next_state(struct ircomm_cb *self, IRCOMM_STATE state)
+{
+	self->state = state;
+	
+	DEBUG(4, __FUNCTION__": next state=%s, service type=%d\n", 
+	      ircomm_state[self->state], self->service_type);
+}
diff -u --recursive --new-file v2.3.15/linux/net/irda/ircomm/ircomm_lmp.c linux/net/irda/ircomm/ircomm_lmp.c
--- v2.3.15/linux/net/irda/ircomm/ircomm_lmp.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/ircomm_lmp.c	Tue Aug 31 09:33:09 1999
@@ -0,0 +1,327 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_lmp.c
+ * Version:       
+ * Description:   Interface between IrCOMM and IrLMP
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 20:48:27 1999
+ * Modified at:   Fri Aug 13 07:21:29 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:       Previous IrLPT work by Thomas Davis
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+
+#include <net/irda/ircomm_event.h>
+#include <net/irda/ircomm_lmp.h>
+
+/*
+ * Function ircomm_open_lsap (self)
+ *
+ *    Open LSAP. This function will only be used when using "raw" services
+ *
+ */
+int ircomm_open_lsap(struct ircomm_cb *self)
+{
+	notify_t notify;
+	
+	DEBUG(0, __FUNCTION__ "()\n");
+	
+        /* Register callbacks */
+        irda_notify_init(&notify);
+	notify.data_indication       = ircomm_lmp_data_indication;
+	notify.connect_confirm       = ircomm_lmp_connect_confirm;
+        notify.connect_indication    = ircomm_lmp_connect_indication;
+	notify.disconnect_indication = ircomm_lmp_disconnect_indication;
+	notify.instance = self;
+	strncpy(notify.name, "IrCOMM", NOTIFY_MAX_NAME);
+
+	self->lsap = irlmp_open_lsap(LSAP_ANY, &notify);
+	if (!self->lsap) {
+		DEBUG(0,__FUNCTION__"failed to allocate tsap\n");
+		return -1;
+	}
+	self->slsap_sel = self->lsap->slsap_sel;
+
+	/*
+	 *  Initialize the call-table for issuing commands
+	 */
+	self->issue.data_request       = ircomm_lmp_data_request;
+	self->issue.connect_request    = ircomm_lmp_connect_request;
+	self->issue.connect_response   = ircomm_lmp_connect_response;
+	self->issue.disconnect_request = ircomm_lmp_disconnect_request;
+
+	return 0;
+}
+
+/*
+ * Function ircomm_lmp_connect_request (self, userdata)
+ *
+ *    
+ *
+ */
+int ircomm_lmp_connect_request(struct ircomm_cb *self, 
+			       struct sk_buff *userdata, 
+			       struct ircomm_info *info)
+{
+	int ret = 0;
+
+	DEBUG(0, __FUNCTION__ "()\n");
+
+	ret = irlmp_connect_request(self->lsap, info->dlsap_sel,
+				    info->saddr, info->daddr, NULL, userdata); 
+	return ret;
+}	
+
+/*
+ * Function ircomm_lmp_connect_response (self, skb)
+ *
+ *    
+ *
+ */
+int ircomm_lmp_connect_response(struct ircomm_cb *self, struct sk_buff *skb)
+{
+	int ret;
+
+	DEBUG(0, __FUNCTION__"()\n");
+	
+	ret = irlmp_connect_response(self->lsap, skb);
+
+	return 0;
+}
+
+int ircomm_lmp_disconnect_request(struct ircomm_cb *self, 
+				  struct sk_buff *userdata, 
+				  struct ircomm_info *info)
+{
+        struct sk_buff *skb;
+	int ret;
+
+	DEBUG(0, __FUNCTION__ "()\n");
+
+        if (!userdata) {
+                skb = dev_alloc_skb(64);
+		if (!skb)
+			return -ENOMEM;
+		
+		/* 
+		 *  Reserve space for MUX and LAP header 
+		 */
+		skb_reserve(skb, LMP_MAX_HEADER);
+		
+		userdata = skb;
+	}
+	ret = irlmp_disconnect_request(self->lsap, userdata);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_lmp_flow_control (skb)
+ *
+ *    This function is called when a data frame we have sent to IrLAP has
+ *    been deallocated. We do this to make sure we don't flood IrLAP with 
+ *    frames, since we are not using the IrTTP flow control mechanism
+ */
+void ircomm_lmp_flow_control(struct sk_buff *skb)
+{
+	struct irda_skb_cb *cb;
+	struct ircomm_cb *self;
+	int line;
+
+	ASSERT(skb != NULL, return;);
+
+	cb = (struct irda_skb_cb *) skb->cb;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+ 
+        line = cb->line;
+
+	self = (struct ircomm_cb *) hashbin_find(ircomm, line, NULL);
+        if (!self) {
+		DEBUG(2, __FUNCTION__ "(), didn't find myself\n");
+                return;
+	}
+
+        ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+
+	self->pkt_count--;
+
+        if ((self->pkt_count < 2) && (self->flow_status == FLOW_STOP)) {
+                DEBUG(2, __FUNCTION__ "(), asking TTY to start again!\n");
+                self->flow_status = FLOW_START;
+                if (self->notify.flow_indication)
+                        self->notify.flow_indication(self->notify.instance, 
+						     self, FLOW_START);
+        }
+}
+    
+/*
+ * Function ircomm_lmp_data_request (self, userdata)
+ *
+ *    Send data frame to peer device
+ *
+ */
+int ircomm_lmp_data_request(struct ircomm_cb *self, struct sk_buff *skb, 
+			    int not_used)
+{
+	struct irda_skb_cb *cb;
+	int ret;
+
+	ASSERT(skb != NULL, return -1;);
+
+	cb = (struct irda_skb_cb *) skb->cb;
+	
+        cb->line = self->line;
+
+	DEBUG(4, __FUNCTION__"(), sending frame\n");
+
+	skb->destructor = ircomm_lmp_flow_control;
+	
+        if ((self->pkt_count++ > 7) && (self->flow_status == FLOW_START)) {
+		DEBUG(2, __FUNCTION__ "(), asking TTY to slow down!\n");
+	        self->flow_status = FLOW_STOP;
+                if (self->notify.flow_indication)
+             	        self->notify.flow_indication(self->notify.instance, 
+				                     self, FLOW_STOP);
+        }
+	ret = irlmp_data_request(self->lsap, skb);
+	if (ret) {
+		ERROR(__FUNCTION__ "(), failed\n");
+		dev_kfree_skb(skb);
+	}
+
+	return ret;
+}
+
+/*
+ * Function ircomm_lmp_data_indication (instance, sap, skb)
+ *
+ *    Incomming data which we must deliver to the state machine, to check
+ *    we are still connected.
+ */
+int ircomm_lmp_data_indication(void *instance, void *sap,
+			       struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+
+	DEBUG(4, __FUNCTION__"()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
+	
+	ircomm_do_event(self, IRCOMM_LMP_DATA_INDICATION, skb, NULL);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_lmp_connect_confirm (instance, sap, qos, max_sdu_size, 
+ *                                       max_header_size, skb)
+ *
+ *    Connection has been confirmed by peer device
+ *
+ */
+void ircomm_lmp_connect_confirm(void *instance, void *sap,
+				struct qos_info *qos, 
+				__u32 max_seg_size, 
+				__u8 max_header_size,
+				struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+	struct ircomm_info info;
+
+	DEBUG(0, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(qos != NULL, return;);
+
+	info.max_data_size = max_seg_size;
+	info.max_header_size = max_header_size;
+	info.qos = qos;
+
+	ircomm_do_event(self, IRCOMM_LMP_CONNECT_CONFIRM, skb, &info);
+}
+
+/*
+ * Function ircomm_lmp_connect_indication (instance, sap, qos, max_sdu_size,
+ *                                         max_header_size, skb)
+ *
+ *    Peer device wants to make a connection with us
+ *
+ */
+void ircomm_lmp_connect_indication(void *instance, void *sap,
+				   struct qos_info *qos,
+				   __u32 max_seg_size,
+				   __u8 max_header_size,
+				   struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *)instance;
+	struct ircomm_info info;
+
+	DEBUG(0, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(qos != NULL, return;);
+
+	info.max_data_size = max_seg_size;
+	info.max_header_size = max_header_size;
+	info.qos = qos;
+
+	ircomm_do_event(self, IRCOMM_LMP_CONNECT_INDICATION, skb, &info);
+}
+
+/*
+ * Function ircomm_lmp_disconnect_indication (instance, sap, reason, skb)
+ *
+ *    Peer device has closed the connection, or the link went down for some
+ *    other reason
+ */
+void ircomm_lmp_disconnect_indication(void *instance, void *sap, 
+				      LM_REASON reason,
+				      struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+	struct ircomm_info info;
+
+	DEBUG(0, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+
+	info.reason = reason;
+
+	ircomm_do_event(self, IRCOMM_LMP_DISCONNECT_INDICATION, skb, &info);
+}
+
+
diff -u --recursive --new-file v2.3.15/linux/net/irda/ircomm/ircomm_param.c linux/net/irda/ircomm/ircomm_param.c
--- v2.3.15/linux/net/irda/ircomm/ircomm_param.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/ircomm_param.c	Mon Aug 30 10:26:28 1999
@@ -0,0 +1,445 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_param.c
+ * Version:       1.0
+ * Description:   Parameter handling for the IrCOMM protocol
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Jun  7 10:25:11 1999
+ * Modified at:   Wed Aug 25 13:48:14 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <net/irda/irda.h>
+#include <net/irda/parameters.h>
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_tty_attach.h>
+#include <net/irda/ircomm_tty.h>
+
+#include <net/irda/ircomm_param.h>
+
+static int ircomm_param_service_type(void *instance, param_t *param, int get);
+static int ircomm_param_port_type(void *instance, param_t *param, int get);
+static int ircomm_param_port_name(void *instance, param_t *param, int get);
+static int ircomm_param_service_type(void *instance, param_t *param, int get);
+static int ircomm_param_data_rate(void *instance, param_t *param, int get);
+static int ircomm_param_data_format(void *instance, param_t *param, int get);
+static int ircomm_param_flow_control(void *instance, param_t *param, int get);
+static int ircomm_param_xon_xoff(void *instance, param_t *param, int get);
+static int ircomm_param_enq_ack(void *instance, param_t *param, int get);
+static int ircomm_param_line_status(void *instance, param_t *param, int get);
+static int ircomm_param_dte(void *instance, param_t *param, int get);
+static int ircomm_param_dce(void *instance, param_t *param, int get);
+static int ircomm_param_poll(void *instance, param_t *param, int get);
+
+static pi_minor_info_t pi_minor_call_table_common[] = {
+	{ ircomm_param_service_type, PV_INT_8_BITS },
+	{ ircomm_param_port_type,    PV_INT_8_BITS },
+	{ ircomm_param_port_name,    PV_STRING }
+};
+static pi_minor_info_t pi_minor_call_table_non_raw[] = {
+	{ ircomm_param_data_rate,    PV_INT_32_BITS | PV_BIG_ENDIAN },
+	{ ircomm_param_data_format,  PV_INT_8_BITS },
+	{ ircomm_param_flow_control, PV_INT_8_BITS },
+	{ ircomm_param_xon_xoff,     PV_INT_16_BITS },
+	{ ircomm_param_enq_ack,      PV_INT_16_BITS },
+	{ ircomm_param_line_status,  PV_INT_8_BITS }
+};
+static pi_minor_info_t pi_minor_call_table_9_wire[] = {
+	{ ircomm_param_dte,          PV_INT_8_BITS },
+	{ ircomm_param_dce,          PV_INT_8_BITS },
+	{ ircomm_param_poll,         PV_INT_8_BITS },
+};
+
+static pi_major_info_t pi_major_call_table[] = {
+	{ pi_minor_call_table_common,  3 },
+	{ pi_minor_call_table_non_raw, 6 },
+ 	{ pi_minor_call_table_9_wire,  3 }
+/* 	{ pi_minor_call_table_centronics }  */
+};
+
+pi_param_info_t ircomm_param_info = { pi_major_call_table, 3, 0x0f, 4 };
+
+/*
+ * Function ircomm_param_flush (self)
+ *
+ *    Flush (send) out all queued parameters
+ *
+ */
+int ircomm_param_flush(struct ircomm_tty_cb *self)
+{
+	if (self->ctrl_skb) {
+		ircomm_control_request(self->ircomm, self->ctrl_skb);
+		self->ctrl_skb = NULL;	
+	}
+	return 0;
+}
+
+/*
+ * Function ircomm_param_request (self, pi, flush)
+ *
+ *    Queue a parameter for the control channel
+ *
+ */
+int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
+{
+	struct sk_buff *skb;
+	int count;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	if (self->state != IRCOMM_TTY_READY) {
+		DEBUG(2, __FUNCTION__ "(), not ready yet!\n");
+		return 0;
+	}
+
+	/* Make sure we don't send parameters for raw mode */
+	if (self->service_type == IRCOMM_3_WIRE_RAW)
+		return 0;
+
+	skb = self->ctrl_skb;
+	
+	if (!skb) {
+		skb = dev_alloc_skb(256);
+		if (!skb)
+			return -1;
+		
+		skb_reserve(skb, self->max_header_size);
+
+		self->ctrl_skb = skb;		
+	}
+	/* 
+	 * Inserting is a little bit tricky since we don't know how much
+	 * room we will need. But this should hopefully work OK 
+	 */
+	count = irda_param_insert(self, pi, skb->tail, skb_tailroom(skb),
+				  &ircomm_param_info);
+	if (count > 0)
+		skb_put(skb, count);
+
+	if (flush) {
+		ircomm_control_request(self->ircomm, skb);
+		self->ctrl_skb = NULL;		
+	}
+	return count;
+}
+
+/*
+ * Function ircomm_param_service_type (self, buf, len)
+ *
+ *    Handle service type, this function will both be called after the LM-IAS
+ *    query and then the remote device sends its initial paramters
+ *
+ */
+static int ircomm_param_service_type(void *instance, param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	__u8 service_type = param->pv.b; /* We know it's a one byte integer */
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	if (get) {
+		param->pv.b = self->session.service_type;
+		return 0;
+	}
+
+	/*
+	 * Now choose a preferred service type of those available
+	 */
+	if (service_type & IRCOMM_3_WIRE_RAW) {
+		DEBUG(2, __FUNCTION__ "(), peer supports 3 wire raw\n");
+		self->session.service_type |= IRCOMM_3_WIRE_RAW;
+	}
+	if (service_type & IRCOMM_3_WIRE) {
+		DEBUG(2, __FUNCTION__ "(), peer supports 3 wire\n");
+		self->session.service_type |= IRCOMM_3_WIRE;
+	}
+	if (service_type & IRCOMM_9_WIRE) {
+		DEBUG(2, __FUNCTION__ "(), peer supports 9 wire\n");
+		self->session.service_type |= IRCOMM_9_WIRE;
+	}
+	if (service_type & IRCOMM_CENTRONICS) {
+		DEBUG(2, __FUNCTION__ "(), peer supports Centronics\n");
+		self->session.service_type |= IRCOMM_CENTRONICS;
+	}
+	
+	self->session.service_type &= self->service_type;
+	if (!self->session.service_type) {
+		DEBUG(2, __FUNCTION__"(), No common service type to use!\n");
+		return -1;
+	}
+	
+	DEBUG(2, __FUNCTION__ "(), resulting service type=0x%02x\n", 
+	      self->session.service_type);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_port_type (self, param)
+ *
+ *    
+ *
+ */
+static int ircomm_param_port_type(void *instance, param_t *param, int get)
+{
+	DEBUG(0, __FUNCTION__ "(), not impl.\n");
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_port_name (self, param)
+ *
+ *    
+ *
+ */
+static int ircomm_param_port_name(void *instance, param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+	
+	if (get)
+		DEBUG(0, __FUNCTION__ "(), not imp!\n");
+	else
+		DEBUG(0, __FUNCTION__ "(), port-name=%s\n", param->pv.c);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_data_rate (self, param)
+ *
+ *    
+ *
+ */
+static int ircomm_param_data_rate(void *instance, param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	if (get)
+		param->pv.i = self->session.data_rate;
+	else
+		self->session.data_rate = param->pv.i;
+	
+	DEBUG(2, __FUNCTION__ "(), data rate = %d\n", param->pv.i);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_data_format (self, param)
+ *
+ *    
+ *
+ */
+static int ircomm_param_data_format(void *instance, param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	if (get)
+		param->pv.b = self->session.data_format;
+	else
+		self->session.data_format = param->pv.b;
+	
+	DEBUG(1, __FUNCTION__ "(), data format = 0x%02x\n", param->pv.b);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_flow_control (self, param)
+ *
+ *    
+ *
+ */
+static int ircomm_param_flow_control(void *instance, param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->session.flow_control;
+	else
+		self->session.flow_control = param->pv.b;
+
+	DEBUG(1, __FUNCTION__ "(), flow control = 0x%02x\n", param->pv.b);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_xon_xoff (self, param)
+ *
+ *    
+ *
+ */
+static int ircomm_param_xon_xoff(void *instance, param_t *param, int get)
+{
+	DEBUG(2, __FUNCTION__ "(), not impl.\n");
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_enq_ack (self, param)
+ *
+ *    
+ *
+ */
+static int ircomm_param_enq_ack(void *instance, param_t *param, int get)
+{
+	DEBUG(2, __FUNCTION__ "(), not impl.\n");
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_line_status (self, param)
+ *
+ *    
+ *
+ */
+static int ircomm_param_line_status(void *instance, param_t *param, int get)
+{
+	DEBUG(2, __FUNCTION__ "(), not impl.\n");
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_dte (instance, param)
+ *
+ *    If we get here, there must be some sort of null-modem connection, and
+ *    we are probably working in server mode as well.
+ */
+static int ircomm_param_dte(void *instance, param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	__u8 dte;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	if (get)
+		param->pv.b = self->session.dte;
+	else {
+		dte = param->pv.b;
+		
+		/* Null modem cable emulator */
+		self->session.null_modem = TRUE;
+
+		if (dte & IRCOMM_DELTA_DTR)
+			self->session.dce |= (IRCOMM_DELTA_DSR|
+					      IRCOMM_DELTA_RI |
+					      IRCOMM_DELTA_CD);
+		if (dte & IRCOMM_DTR)
+			self->session.dce |= (IRCOMM_DSR|
+					      IRCOMM_RI |
+					      IRCOMM_CD);
+		
+		if (dte & IRCOMM_DELTA_RTS)
+			self->session.dce |= IRCOMM_DELTA_CTS;
+		if (dte & IRCOMM_RTS)
+			self->session.dce |= IRCOMM_CTS;
+
+		/* Take appropriate actions */
+		ircomm_tty_check_modem_status(self);
+
+		/* 
+		 * Send reply, and remember not to set delta values for the
+		 * initial parameters 
+		 */
+		self->session.dte = (IRCOMM_DTR| IRCOMM_RTS);
+		ircomm_param_request(self, IRCOMM_DTE, TRUE);
+	}
+	DEBUG(1, __FUNCTION__ "(), dte = 0x%02x\n", param->pv.b);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_dce (instance, param)
+ *
+ *    
+ *
+ */
+static int ircomm_param_dce(void *instance, param_t *param, int get)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	__u8 dce;
+
+	DEBUG(1, __FUNCTION__ "(), dce = 0x%02x\n", param->pv.b);
+
+	dce = param->pv.b;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	self->session.dce = dce;
+
+	/* Check if any of the settings have changed */
+	if (dce & 0x0f) {
+		if (dce & IRCOMM_DELTA_CTS) {
+			DEBUG(2, __FUNCTION__ "(), CTS \n");
+		}
+	}
+
+	ircomm_tty_check_modem_status(self);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_param_poll (instance, param)
+ *
+ *    
+ *
+ */
+static int ircomm_param_poll(void *instance, param_t *param, int get)
+{
+	DEBUG(0, __FUNCTION__ "(), not impl.\n");
+
+	return 0;
+}
+
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.3.15/linux/net/irda/ircomm/ircomm_ttp.c linux/net/irda/ircomm/ircomm_ttp.c
--- v2.3.15/linux/net/irda/ircomm/ircomm_ttp.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/ircomm_ttp.c	Tue Aug 31 09:33:09 1999
@@ -0,0 +1,302 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_ttp.c
+ * Version:       
+ * Description:   Interface between IrCOMM and IrTTP
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 20:48:27 1999
+ * Modified at:   Tue Aug 17 10:28:26 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irttp.h>
+
+#include <net/irda/ircomm_event.h>
+#include <net/irda/ircomm_ttp.h>
+
+/*
+ * Function ircomm_open_tsap (self)
+ *
+ *    
+ *
+ */
+int ircomm_open_tsap(struct ircomm_cb *self)
+{
+	notify_t notify;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	/* Register callbacks */
+	irda_notify_init(&notify);
+	notify.data_indication       = ircomm_ttp_data_indication;
+	notify.connect_confirm       = ircomm_ttp_connect_confirm;
+	notify.connect_indication    = ircomm_ttp_connect_indication;
+	notify.flow_indication       = ircomm_ttp_flow_indication;
+	notify.disconnect_indication = ircomm_ttp_disconnect_indication;
+	notify.instance = self;
+	strncpy(notify.name, "IrCOMM", NOTIFY_MAX_NAME);
+
+	self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
+				     &notify);
+	if (!self->tsap) {
+		DEBUG(0,__FUNCTION__"failed to allocate tsap\n");
+		return -1;
+	}
+	self->slsap_sel = self->tsap->stsap_sel;
+
+	/*
+	 *  Initialize the call-table for issuing commands
+	 */
+	self->issue.data_request       = ircomm_ttp_data_request;
+	self->issue.connect_request    = ircomm_ttp_connect_request;
+	self->issue.connect_response   = ircomm_ttp_connect_response;
+	self->issue.disconnect_request = ircomm_ttp_disconnect_request;
+
+	return 0;
+}
+
+/*
+ * Function ircomm_ttp_connect_request (self, userdata)
+ *
+ *    
+ *
+ */
+int ircomm_ttp_connect_request(struct ircomm_cb *self, 
+			       struct sk_buff *userdata, 
+			       struct ircomm_info *info)
+{
+	int ret = 0;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ret = irttp_connect_request(self->tsap, info->dlsap_sel,
+				    info->saddr, info->daddr, 
+				    NULL, SAR_DISABLE, userdata); 
+	return ret;
+}	
+
+/*
+ * Function ircomm_ttp_connect_response (self, skb)
+ *
+ *    
+ *
+ */
+int ircomm_ttp_connect_response(struct ircomm_cb *self, struct sk_buff *skb)
+{
+	int ret;
+
+	DEBUG(4, __FUNCTION__"()\n");
+	
+	ret = irttp_connect_response(self->tsap, SAR_DISABLE, skb);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_ttp_data_request (self, userdata)
+ *
+ *    Send IrCOMM data to IrTTP layer. Currently we do not try to combine 
+ *    control data with pure data, so they will be sent as separate frames. 
+ *    Should not be a big problem though, since control frames are rare. But
+ *    some of them are sent after connection establishment, so this can 
+ *    increase the latency a bit.
+ */
+int ircomm_ttp_data_request(struct ircomm_cb *self, struct sk_buff *skb, 
+			    int clen)
+{
+	int ret;
+
+	ASSERT(skb != NULL, return -1;);
+
+	DEBUG(2, __FUNCTION__"(), clen=%d\n", clen);
+
+	/* 
+	 * Insert clen field, currently we either send data only, or control
+	 * only frames, to make things easier and avoid queueing
+	 */
+	ASSERT(skb_headroom(skb) >= 1, return -1;);
+	skb_push(skb, IRCOMM_HEADER_SIZE);
+
+	skb->data[0] = clen;
+
+	ret = irttp_data_request(self->tsap, skb);
+	if (ret) {
+		ERROR(__FUNCTION__ "(), failed\n");
+		dev_kfree_skb(skb);
+	}
+
+	return ret;
+}
+
+/*
+ * Function ircomm_ttp_data_indication (instance, sap, skb)
+ *
+ *    Incomming data
+ *
+ */
+int ircomm_ttp_data_indication(void *instance, void *sap,
+			       struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+
+	DEBUG(4, __FUNCTION__"()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
+
+	ircomm_do_event(self, IRCOMM_TTP_DATA_INDICATION, skb, NULL);
+
+	return 0;
+}
+
+void ircomm_ttp_connect_confirm(void *instance, void *sap,
+				struct qos_info *qos, 
+				__u32 max_sdu_size, 
+				__u8 max_header_size,
+				struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+	struct ircomm_info info;
+
+	DEBUG(4, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(qos != NULL, return;);
+
+	if (max_sdu_size != SAR_DISABLE) {
+		ERROR(__FUNCTION__ "(), SAR not allowed for IrCOMM!\n");
+		return;
+	}
+
+	info.max_data_size = qos->data_size.value - max_header_size
+		- IRCOMM_HEADER_SIZE;
+	info.max_header_size = max_header_size + IRCOMM_HEADER_SIZE;
+	info.qos = qos;
+
+	ircomm_do_event(self, IRCOMM_TTP_CONNECT_CONFIRM, skb, &info);
+}
+
+/*
+ * Function ircomm_ttp_connect_indication (instance, sap, qos, max_sdu_size,
+ *                                            max_header_size, skb)
+ *
+ *    
+ *
+ */
+void ircomm_ttp_connect_indication(void *instance, void *sap,
+				   struct qos_info *qos,
+				   __u32 max_sdu_size,
+				   __u8 max_header_size,
+				   struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *)instance;
+	struct ircomm_info info;
+
+	DEBUG(4, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(qos != NULL, return;);
+
+	if (max_sdu_size != SAR_DISABLE) {
+		ERROR(__FUNCTION__ "(), SAR not allowed for IrCOMM!\n");
+		return;
+	}
+
+	info.max_data_size = qos->data_size.value - max_header_size
+		- IRCOMM_HEADER_SIZE;
+	info.max_header_size = max_header_size + IRCOMM_HEADER_SIZE;
+	info.qos = qos;
+
+	ircomm_do_event(self, IRCOMM_TTP_CONNECT_INDICATION, skb, &info);
+}
+
+/*
+ * Function ircomm_ttp_disconnect_request (self, userdata, info)
+ *
+ *    
+ *
+ */
+int ircomm_ttp_disconnect_request(struct ircomm_cb *self, 
+				  struct sk_buff *userdata, 
+				  struct ircomm_info *info)
+{
+	int ret;
+
+	ret = irttp_disconnect_request(self->tsap, userdata, P_NORMAL);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_ttp_disconnect_indication (instance, sap, reason, skb)
+ *
+ *    
+ *
+ */
+void ircomm_ttp_disconnect_indication(void *instance, void *sap, 
+				      LM_REASON reason,
+				      struct sk_buff *skb)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+	struct ircomm_info info;
+
+	DEBUG(4, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+
+	info.reason = reason;
+
+	ircomm_do_event(self, IRCOMM_TTP_DISCONNECT_INDICATION, skb, &info);
+}
+
+/*
+ * Function ircomm_ttp_flow_indication (instance, sap, cmd)
+ *
+ *    Layer below is telling us to start or stop the flow of data
+ *
+ */
+void ircomm_ttp_flow_indication(void *instance, void *sap, LOCAL_FLOW cmd)
+{
+	struct ircomm_cb *self = (struct ircomm_cb *) instance;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+	
+	if (self->notify.flow_indication)
+		self->notify.flow_indication(self->notify.instance, self, cmd);
+}
+
+
diff -u --recursive --new-file v2.3.15/linux/net/irda/ircomm/ircomm_tty.c linux/net/irda/ircomm/ircomm_tty.c
--- v2.3.15/linux/net/irda/ircomm/ircomm_tty.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/ircomm_tty.c	Tue Aug 31 11:30:48 1999
@@ -0,0 +1,1259 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_tty.c
+ * Version:       1.0
+ * Description:   IrCOMM serial TTY driver
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Jun  6 21:00:56 1999
+ * Modified at:   Wed Aug 25 15:12:18 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:       serial.c and previous IrCOMM work by Takahide Higuchi
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/termios.h>
+#include <linux/tty.h>
+#include <linux/interrupt.h>
+
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_param.h>
+#include <net/irda/ircomm_tty_attach.h>
+#include <net/irda/ircomm_tty.h>
+
+static int  ircomm_tty_open(struct tty_struct *tty, struct file *filp);
+static void ircomm_tty_close(struct tty_struct * tty, struct file *filp);
+static int  ircomm_tty_write(struct tty_struct * tty, int from_user,
+			     const unsigned char *buf, int count);
+static int  ircomm_tty_write_room(struct tty_struct *tty);
+static void ircomm_tty_throttle(struct tty_struct *tty);
+static void ircomm_tty_unthrottle(struct tty_struct *tty);
+static int  ircomm_tty_chars_in_buffer(struct tty_struct *tty);
+static void ircomm_tty_flush_buffer(struct tty_struct *tty);
+static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch);
+static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout);
+static void ircomm_tty_hangup(struct tty_struct *tty);
+static void ircomm_tty_break(struct tty_struct *tty, int break_state);
+static void ircomm_tty_do_softint(void *private_);
+static void ircomm_tty_disconnect_indication(void *instance, void *sap, 
+					     LM_REASON reason,
+					     struct sk_buff *skb);
+static int ircomm_tty_data_indication(void *instance, void *sap,
+				      struct sk_buff *skb);
+static int ircomm_tty_control_indication(void *instance, void *sap,
+					 struct sk_buff *skb);
+static void ircomm_tty_flow_indication(void *instance, void *sap, 
+				       LOCAL_FLOW cmd);
+static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
+				int *eof, void *unused);
+
+static struct tty_driver driver;
+static int ircomm_tty_refcount;       /* If we manage several devices */
+
+static struct tty_struct *ircomm_tty_table[NR_PTYS];
+static struct termios *ircomm_tty_termios[NR_PTYS];
+static struct termios *ircomm_tty_termios_locked[NR_PTYS];
+
+hashbin_t *ircomm_tty = NULL;
+
+/*
+ * Function ircomm_tty_init()
+ *
+ *    Init IrCOMM TTY layer/driver
+ *
+ */
+int __init ircomm_tty_init(void)
+{	
+	ircomm_tty = hashbin_new(HB_LOCAL); 
+	if (ircomm_tty == NULL) {
+		ERROR(__FUNCTION__ "(), can't allocate hashbin!\n");
+		return -ENOMEM;
+	}
+
+	memset(&driver, 0, sizeof(struct tty_driver));
+	driver.magic           = TTY_DRIVER_MAGIC;
+	driver.driver_name     = "ircomm";
+	driver.name            = "ircomm";
+	driver.major           = IRCOMM_TTY_MAJOR;
+	driver.minor_start     = IRCOMM_TTY_MINOR;
+	driver.num             = IRCOMM_TTY_PORTS;
+	driver.type            = TTY_DRIVER_TYPE_SERIAL;
+	driver.subtype         = SERIAL_TYPE_NORMAL;
+	driver.init_termios    = tty_std_termios;
+	driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	driver.flags           = TTY_DRIVER_REAL_RAW;
+	driver.refcount        = &ircomm_tty_refcount;
+	driver.table           = ircomm_tty_table;
+	driver.termios         = ircomm_tty_termios;
+	driver.termios_locked  = ircomm_tty_termios_locked;
+	driver.open            = ircomm_tty_open;
+	driver.close           = ircomm_tty_close;
+	driver.write           = ircomm_tty_write;
+	driver.write_room      = ircomm_tty_write_room;
+	driver.chars_in_buffer = ircomm_tty_chars_in_buffer;
+	driver.flush_buffer    = ircomm_tty_flush_buffer;
+	driver.ioctl           = ircomm_tty_ioctl;
+	driver.throttle        = ircomm_tty_throttle;
+	driver.unthrottle      = ircomm_tty_unthrottle;
+	driver.send_xchar      = ircomm_tty_send_xchar;
+	driver.set_termios     = ircomm_tty_set_termios;
+	driver.stop            = ircomm_tty_stop;
+	driver.start           = ircomm_tty_start;
+	driver.hangup          = ircomm_tty_hangup;
+	driver.break_ctl       = ircomm_tty_break;
+	driver.wait_until_sent = ircomm_tty_wait_until_sent;
+	driver.read_proc       = ircomm_tty_read_proc;
+
+	if (tty_register_driver(&driver)) {
+		ERROR(__FUNCTION__ "Couldn't register serial driver\n");
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * Function ircomm_tty_cleanup ()
+ *
+ *    Remove IrCOMM TTY layer/driver
+ *
+ */
+void ircomm_tty_cleanup(void)
+{
+	int ret;
+
+	DEBUG(4, __FUNCTION__"()\n");
+
+	ret = tty_unregister_driver(&driver);
+        if (ret) {
+                ERROR(__FUNCTION__ "(), failed to unregister driver\n");
+		return;
+	}
+
+	hashbin_delete(ircomm_tty, (FREE_FUNC) kfree);
+}
+
+/*
+ * Function ircomm_startup (self)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_startup(struct ircomm_tty_cb *self)
+{
+	notify_t notify;
+	int ret;
+
+	/* Already open */
+	if (self->flags & ASYNC_INITIALIZED) {
+		DEBUG(0, __FUNCTION__ "(), already open so break out!\n");
+		return 0;
+	}
+
+	/* Register with IrCOMM */
+	irda_notify_init(&notify);
+	/* These callbacks we must handle ourselves */
+	notify.data_indication       = ircomm_tty_data_indication;
+	notify.udata_indication      = ircomm_tty_control_indication;
+ 	notify.disconnect_indication = ircomm_tty_disconnect_indication;
+ 	notify.flow_indication       = ircomm_tty_flow_indication;
+
+	/* Use the ircomm_tty interface for these ones */
+	notify.connect_confirm       = ircomm_tty_connect_confirm;
+ 	notify.connect_indication    = ircomm_tty_connect_indication;
+	strncpy(notify.name, "ircomm_tty", NOTIFY_MAX_NAME);
+	notify.instance = self;
+
+	if (!self->ircomm)
+		self->ircomm = ircomm_open(&notify, self->service_type, 
+					   self->line);
+	if (!self->ircomm)
+		return -ENODEV;
+
+	self->slsap_sel = self->ircomm->slsap_sel;
+
+	/* Connect IrCOMM link with remote device */
+	ret = ircomm_tty_attach_cable(self);
+	if (ret < 0) {
+		DEBUG(0, __FUNCTION__ "(), error attaching cable!\n");
+		return ret;
+	}
+
+	self->flags |= ASYNC_INITIALIZED;
+
+	return 0;
+}
+
+/*
+ * Function ircomm_block_til_ready (self, filp)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, 
+				      struct file *filp)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int		retval;
+	int		do_clocal = 0, extra_count = 0;
+	unsigned long	flags;
+	struct tty_struct *tty;
+	
+	tty = self->tty;
+
+	DEBUG(1, __FUNCTION__ "()\n");
+
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+		/* this is a callout device */
+		/* just verify that normal device is not in use */
+		if (self->flags & ASYNC_NORMAL_ACTIVE)
+			return -EBUSY;
+#if 0
+		if ((self->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (self->flags & ASYNC_SESSION_LOCKOUT) &&
+		    (self->session != current->session))
+		    return -EBUSY;
+#endif
+		if ((self->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (self->flags & ASYNC_PGRP_LOCKOUT) &&
+		    (self->pgrp != current->pgrp))
+		    return -EBUSY;
+		self->flags |= ASYNC_CALLOUT_ACTIVE;
+		return 0;
+	}
+	
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 */	
+	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
+		/* nonblock mode is set or port is not enabled */
+		/* just verify that callout device is not active */
+		if (self->flags & ASYNC_CALLOUT_ACTIVE)
+			return -EBUSY;
+		self->flags |= ASYNC_NORMAL_ACTIVE;
+
+		DEBUG(1, __FUNCTION__ "(), O_NONBLOCK requested!\n");
+		return 0;
+	}
+
+	if (self->flags & ASYNC_CALLOUT_ACTIVE) {
+		if (self->normal_termios.c_cflag & CLOCAL)
+			DEBUG(1, __FUNCTION__ "(), doing CLOCAL!\n");
+			do_clocal = 1;
+	} else {
+		if (tty->termios->c_cflag & CLOCAL)
+			DEBUG(1, __FUNCTION__ "(), doing CLOCAL!\n");
+			do_clocal = 1;
+	}
+	
+	/* Wait for carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, self->open_count is dropped by one, so that
+	 * mgsl_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	 
+	retval = 0;
+	add_wait_queue(&self->open_wait, &wait);
+	
+	DEBUG(1, "%s(%d):block_til_ready before block on %s open_count=%d\n",
+	      __FILE__,__LINE__, tty->driver.name, self->open_count );
+
+	save_flags(flags); cli();
+	if (!tty_hung_up_p(filp)) {
+		extra_count = 1;
+		self->open_count--;
+	}
+	restore_flags(flags);
+	self->blocked_open++;
+	
+	while (1) {
+		if (!(self->flags & ASYNC_CALLOUT_ACTIVE) &&
+ 		    (tty->termios->c_cflag & CBAUD)) {
+			save_flags(flags); cli();
+			self->session.dte |= IRCOMM_RTS + IRCOMM_DTR;
+		 	
+			ircomm_param_request(self, IRCOMM_DTE, TRUE);
+			restore_flags(flags);
+		}
+		
+		set_current_state(TASK_INTERRUPTIBLE);
+		
+		if (tty_hung_up_p(filp) || !(self->flags & ASYNC_INITIALIZED)){
+			retval = (self->flags & ASYNC_HUP_NOTIFY) ?
+					-EAGAIN : -ERESTARTSYS;
+			break;
+		}
+		
+		/*  
+		 * Check if link is ready now. Even if CLOCAL is
+		 * specified, we cannot return before the IrCOMM link is
+		 * ready 
+		 */
+ 		if (!(self->flags & ASYNC_CALLOUT_ACTIVE) &&
+ 		    !(self->flags & ASYNC_CLOSING) &&
+ 		    (do_clocal || (self->session.dce & IRCOMM_CD)) &&
+		    self->state == IRCOMM_TTY_READY)
+		{
+ 			break;
+		}
+			
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+		
+		DEBUG(1, "%s(%d):block_til_ready blocking on %s open_count=%d\n",
+		      __FILE__,__LINE__, tty->driver.name, self->open_count );
+		
+		schedule();
+	}
+	
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(&self->open_wait, &wait);
+	
+	if (extra_count)
+		self->open_count++;
+	self->blocked_open--;
+	
+	DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",
+	      __FILE__,__LINE__, tty->driver.name, self->open_count);
+			 
+	if (!retval)
+		self->flags |= ASYNC_NORMAL_ACTIVE;
+		
+	return retval;	
+}
+
+/*
+ * Function ircomm_tty_open (tty, filp)
+ *
+ *    This routine is called when a particular tty device is opened. This
+ *    routine is mandatory; if this routine is not filled in, the attempted
+ *    open will fail with ENODEV.
+ */
+static int ircomm_tty_open(struct tty_struct *tty, struct file *filp)
+{
+	struct ircomm_tty_cb *self;
+	int line;
+	int ret;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	MOD_INC_USE_COUNT;
+	line = MINOR(tty->device) - tty->driver.minor_start;
+	if ((line < 0) || (line >= IRCOMM_TTY_PORTS)) {
+		MOD_DEC_USE_COUNT;
+		return -ENODEV;
+	}
+
+	/* Check if instance already exists */
+	self = hashbin_find(ircomm_tty, line, NULL);
+	if (!self) {
+		/* No, so make new instance */
+		self = kmalloc(sizeof(struct ircomm_tty_cb), GFP_KERNEL);
+		if (self == NULL) {
+			ERROR(__FUNCTION__"(), kmalloc failed!\n");
+			MOD_DEC_USE_COUNT;
+			return -ENOMEM;
+		}
+		memset(self, 0, sizeof(struct ircomm_tty_cb));
+		
+		self->magic = IRCOMM_TTY_MAGIC;
+		self->line = line;
+		self->tqueue.routine = ircomm_tty_do_softint;
+		self->tqueue.data = self;
+		self->max_header_size = 5;
+		self->max_data_size = 2048-self->max_header_size;
+
+		/* Init some important stuff */
+		init_timer(&self->watchdog_timer);
+		init_waitqueue_head(&self->open_wait);
+		skb_queue_head_init(&self->tx_queue);
+
+		/* Insert into hash */
+		hashbin_insert(ircomm_tty, (QUEUE *) self, line, NULL);
+
+	}
+	self->open_count++;
+
+	tty->driver_data = self;
+	self->tty = tty;
+
+	DEBUG(1, __FUNCTION__"(), %s%d, count = %d\n", tty->driver.name, 
+	      self->line, self->open_count);
+
+	/* Not really used by us, but lets do it anyway */
+	self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+	/* Check if this is a "normal" ircomm device, or an irlpt device */
+	if (line < 0x10) {
+		self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;
+		DEBUG(0, __FUNCTION__ "(), IrCOMM device\n");
+	} else {
+		DEBUG(0, __FUNCTION__ "(), IrLPT device\n");
+		self->service_type = IRCOMM_3_WIRE_RAW;
+	}
+
+	ret = ircomm_tty_startup(self);
+	if (ret)
+		return ret;
+
+	ret = ircomm_tty_block_til_ready(self, filp);
+	if (ret) {
+		/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
+		DEBUG(0, __FUNCTION__ 
+		      "(), returning after block_til_ready with %d\n",
+		      ret);
+
+		return ret;
+	}
+#if 0
+	self->session = current->session;
+#endif
+	self->pgrp = current->pgrp;
+
+	return 0;
+}
+
+/*
+ * Function ircomm_tty_close (tty, filp)
+ *
+ *    This routine is called when a particular tty device is closed.
+ *
+ */
+static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	struct sk_buff *skb;
+	unsigned long flags;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	if (!tty)
+		return;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	save_flags(flags); 
+	cli();
+
+	if (tty_hung_up_p(filp)) {
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+
+		DEBUG(2, __FUNCTION__ "(), returning 1\n");
+		return;
+	}
+
+	if (--self->open_count < 0) {
+		ERROR(__FUNCTION__ 
+		      "(), bad serial port count for ttys%d: %d\n",
+		      self->line, self->open_count);
+		self->open_count = 0;
+	}
+	if (self->open_count) {
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+
+		DEBUG(2, __FUNCTION__ "(), returning 2\n");
+		return;
+	}
+	self->flags |= ASYNC_CLOSING;
+
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+
+	if (tty->driver.flush_buffer)
+		tty->driver.flush_buffer(tty);
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+
+	tty->closing = 0;
+	self->tty = 0;
+
+	wake_up_interruptible(&self->open_wait);
+	
+	self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
+			 ASYNC_CLOSING);
+
+	MOD_DEC_USE_COUNT;
+	restore_flags(flags);
+
+	del_timer(&self->watchdog_timer);
+	
+	/* Free frames queued for transmission */
+	while ((skb = skb_dequeue(&self->tx_queue)) != NULL)
+		dev_kfree_skb(skb);
+
+	/* Free parameter buffer */
+	if (self->ctrl_skb) {
+		dev_kfree_skb(self->ctrl_skb);
+		self->ctrl_skb = NULL;
+	}
+
+	ircomm_tty_detach_cable(self);
+	ircomm_close(self->ircomm);
+
+	self->ircomm = NULL;
+	self->magic = 0;
+
+	hashbin_remove(ircomm_tty, self->line, NULL);
+
+	kfree(self);
+}
+
+/*
+ * Function ircomm_tty_flush_buffer (tty)
+ *
+ *    
+ *
+ */
+static void ircomm_tty_flush_buffer(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	/* Flush transmit buffer if any */
+	if ((self->tx_skb) && (!tty->hw_stopped)) {
+		DEBUG(0, __FUNCTION__ "(), flushing!\n");
+		ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST, 
+				    self->tx_skb, NULL);
+		self->tx_skb = NULL;
+	}
+}
+
+/*
+ * Function ircomm_tty_do_softint (private_)
+ *
+ *    We use this routine to give the write wakeup to the user at at a
+ *    safe time (as fast as possible after write have completed). This 
+ *    can be compared to the Tx interrupt.
+ */
+static void ircomm_tty_do_softint(void *private_)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) private_;
+	struct tty_struct *tty;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	tty = self->tty;
+	if (!tty)
+		return;
+
+	if (tty->hw_stopped) {
+		DEBUG(2, __FUNCTION__ "(), hw stopped!\n");
+		return;
+	}
+
+	/* Flush transmit buffer if any */
+	if (self->tx_skb) {
+		DEBUG(1, __FUNCTION__ "(), flushing!\n");
+		ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST, 
+				    self->tx_skb, NULL);
+		self->tx_skb = NULL;
+	}
+		
+	/* Check if user (still) wants to be waken up */
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && 
+	    tty->ldisc.write_wakeup)
+	{
+		(tty->ldisc.write_wakeup)(tty);
+	}
+	wake_up_interruptible(&tty->write_wait);
+}
+
+/*
+ * Function ircomm_tty_write (tty, from_user, buf, count)
+ *
+ *    This routine is called by the kernel to write a series of characters
+ *    to the tty device. The characters may come from user space or kernel
+ *    space. This routine will return the number of characters actually
+ *    accepted for writing. This routine is mandatory.
+ */
+static int ircomm_tty_write(struct tty_struct *tty, int from_user,
+			    const unsigned char *buf, int count)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	unsigned long flags;
+	struct sk_buff *skb;
+	int tailroom = 0;
+	int len = 0;
+	int size;
+
+	DEBUG(3, __FUNCTION__ "(), count=%d, hw_stopped=%d\n", count,
+	      tty->hw_stopped);
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+/*	save_flags(flags);
+	cli();
+*/
+	/* Fetch current transmit buffer */
+	skb = self->tx_skb;
+
+	/*  
+	 * Send out all the data we get, possibly as multiple fragmented
+	 * frames, but this will only happen if the data is larger than the
+	 * max data size. The normal case however is just the opposite, and
+	 * this function may be called multiple times, and will then actually
+	 * defragment the data and send it out as one packet as soon as 
+	 * possible, but at a safer point in time 
+	 */
+	while (count && !tty->hw_stopped) {
+		size = count;
+
+		/* Adjust data size to the max data size */
+		if (size > self->max_data_size) {
+			DEBUG(1, __FUNCTION__ 
+			      "(), size %d to big, clipping to %d!\n",
+			      size, self->max_data_size);
+			size = self->max_data_size;
+		}
+		
+		/* Do we already have a buffer ready for transmit? */
+		if (skb) {			
+			/* 
+			 * Any room for more data at the end of the current 
+			 * transmit buffer? Cannot use skb_tailroom, since
+			 * dev_alloc_skb gives us a larger skb than we 
+			 * requested
+			 */
+			if ((tailroom = (self->max_data_size-skb->len)) > 0) {
+				/* Adjust data to tailroom */
+				if (size > tailroom)
+					size = tailroom;
+			} else {
+				/* Current transmit frame is full */
+				DEBUG(1, __FUNCTION__ "(), flushing!\n");
+				ircomm_tty_do_event(self, 
+						    IRCOMM_TTY_DATA_REQUEST, 
+						    skb, NULL);
+				skb = self->tx_skb = NULL;
+			}
+		}
+
+		/* Check if we need to allocate a new frame */
+		if (!skb) {
+			DEBUG(3, __FUNCTION__ 
+			      "(), allocating new buffer of size %d!\n",
+			      self->max_data_size+self->max_header_size);
+			/* Prepare a full sized frame */
+			skb = dev_alloc_skb(self->max_data_size+
+					    self->max_header_size);
+			if (!skb) {
+				/*restore_flags(flags);*/
+				return -ENOBUFS;
+			}
+			skb_reserve(skb, self->max_header_size);
+			self->tx_skb = skb;
+		}
+		
+		/* Copy data */
+		if (from_user)
+			copy_from_user(skb_put(skb,size), buf+len, size);
+		else
+			memcpy(skb_put(skb,size), buf+len, size);
+		
+		DEBUG(1, __FUNCTION__ "(), size=%d\n", size);
+
+		count -= size;
+		len += size;
+	}
+
+	/*     
+	 * Schedule a new thread which will transmit the frame as soon
+	 * as possible, but at a safe point in time. We do this so the
+	 * "user" can give us data multiple times, as PPP does (because of
+	 * its 256 byte tx buffer). We will then defragment and send out
+	 * all this data as one single packet.  
+	 */
+	queue_task(&self->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+	
+	/*restore_flags(flags);*/
+
+	return len;
+}
+
+/*
+ * Function ircomm_tty_write_room (tty)
+ *
+ *    This routine returns the numbers of characters the tty driver will
+ *    accept for queuing to be written. This number is subject to change as
+ *    output buffers get emptied, or if the output flow control is acted.
+ */
+static int ircomm_tty_write_room(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	int ret;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	/* Check if we are allowed to transmit any data */
+	if (tty->hw_stopped)
+		ret = 0;
+	else {
+		if (self->tx_skb)
+			ret = self->max_data_size - self->tx_skb->len;
+		else
+			ret = self->max_data_size;
+	}
+	DEBUG(2, __FUNCTION__ "(), ret=%d\n", ret);
+
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_wait_until_sent (tty, timeout)
+ *
+ *    This routine waits until the device has written out all of the
+ *    characters in its transmitter FIFO.
+ */
+static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	DEBUG(2, __FUNCTION__ "(), not impl\n");
+}
+
+/*
+ * Function ircomm_tty_throttle (tty)
+ *
+ *    This routine notifies the tty driver that input buffers for the line
+ *    discipline are close to full, and it should somehow signal that no
+ *    more characters should be sent to the tty.  
+ */
+static void ircomm_tty_throttle(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	/* Software flow control? */
+	if (I_IXOFF(tty))
+		ircomm_tty_send_xchar(tty, STOP_CHAR(tty));
+	
+	/* Hardware flow control? */
+	if (tty->termios->c_cflag & CRTSCTS) {
+		self->session.dte &= ~IRCOMM_RTS;
+		self->session.dte |= IRCOMM_DELTA_RTS;
+	
+		ircomm_param_request(self, IRCOMM_DTE, TRUE);
+	}
+
+	DEBUG(1, __FUNCTION__"(), FLOW_STOP\n");
+        ircomm_flow_request(self->ircomm, FLOW_STOP);
+}
+
+/*
+ * Function ircomm_tty_unthrottle (tty)
+ *
+ *    This routine notifies the tty drivers that it should signals that
+ *    characters can now be sent to the tty without fear of overrunning the
+ *    input buffers of the line disciplines.
+ */
+static void ircomm_tty_unthrottle(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	/* Using software flow control? */
+	if (I_IXOFF(tty)) {
+		ircomm_tty_send_xchar(tty, START_CHAR(tty));
+	}
+
+	/* Using hardware flow control? */
+	if (tty->termios->c_cflag & CRTSCTS) {
+		self->session.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS);
+
+		ircomm_param_request(self, IRCOMM_DTE, TRUE);
+		DEBUG(1, __FUNCTION__"(), FLOW_START\n");
+	}
+        ircomm_flow_request(self->ircomm, FLOW_START);
+}
+
+/*
+ * Function ircomm_tty_chars_in_buffer (tty)
+ *
+ *    Indicates if there are any data in the buffer
+ *
+ */
+static int ircomm_tty_chars_in_buffer(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+
+	return 0; /* We don't have any "buffer" */
+}
+
+/*
+ * Function ircomm_tty_hangup (tty)
+ *
+ *    This routine notifies the tty driver that it should hangup the tty
+ *    device.
+ * 
+ */
+static void ircomm_tty_hangup(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	DEBUG(0, __FUNCTION__"()\n");
+
+	if (!tty)
+		return;
+
+	/* ircomm_tty_flush_buffer(tty); */
+	ircomm_tty_detach_cable(self);
+	ircomm_close(self->ircomm);
+
+	self->ircomm = NULL;
+
+	self->flags &= ~ASYNC_INITIALIZED;
+
+	self->open_count = 0;
+	self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+	self->tty = 0;
+
+	wake_up_interruptible(&self->open_wait);
+}
+
+/*
+ * Function ircomm_tty_send_xchar (tty, ch)
+ *
+ *    This routine is used to send a high-priority XON/XOFF character to
+ *    the device.
+ */
+static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	DEBUG(0, __FUNCTION__"(), not impl\n");
+}
+
+/*
+ * Function ircomm_tty_start (tty)
+ *
+ *    This routine notifies the tty driver that it resume sending
+ *    characters to the tty device.  
+ */
+void ircomm_tty_start(struct tty_struct *tty)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+	DEBUG(2, __FUNCTION__"()\n");
+
+	ircomm_flow_request(self->ircomm, FLOW_START);
+}
+
+/*
+ * Function ircomm_tty_stop (tty)
+ *
+ *     This routine notifies the tty driver that it should stop outputting
+ *     characters to the tty device. 
+ */
+void ircomm_tty_stop(struct tty_struct *tty) 
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+ 	DEBUG(2, __FUNCTION__"()\n");
+
+	ircomm_flow_request(self->ircomm, FLOW_STOP);
+}
+
+/*
+ * Function ircomm_tty_break (tty, break_state)
+ *
+ *    
+ *
+ */
+static void ircomm_tty_break(struct tty_struct *tty, int break_state)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+
+ 	DEBUG(0, __FUNCTION__"(), not impl\n");
+}
+
+/*
+ * Function ircomm_check_modem_status (self)
+ *
+ *    Check for any changes in the DCE's line settings. This function should
+ *    be called whenever the dce parameter settings changes, to update the
+ *    flow control settings and other things
+ */
+void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self)
+{
+	struct tty_struct *tty;
+	int status;
+
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	tty = self->tty;
+
+	status = self->session.dce;
+
+	if (status & IRCOMM_DCE_DELTA_ANY) {
+		/*wake_up_interruptible(&self->delta_msr_wait);*/
+	}
+	if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
+		DEBUG(2, __FUNCTION__ "(), ttys%d CD now %s...\n", self->line,
+		      (status & IRCOMM_CD) ? "on" : "off");
+
+		if (status & IRCOMM_CD) {
+			wake_up_interruptible(&self->open_wait);
+		} else if (!((self->flags & ASYNC_CALLOUT_ACTIVE) &&
+			   (self->flags & ASYNC_CALLOUT_NOHUP))) 
+		{
+			DEBUG(2, __FUNCTION__ "(), Doing serial hangup..\n");
+			
+			if (tty)
+				tty_hangup(tty);
+		}
+	}
+	if (self->flags & ASYNC_CTS_FLOW) {
+		if (tty->hw_stopped) {
+			if (status & IRCOMM_CTS) {
+				DEBUG(2, __FUNCTION__ "(), CTS tx start...\n");
+				
+				tty->hw_stopped = 0;
+				
+				if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) 
+				    && tty->ldisc.write_wakeup)
+				{
+					(tty->ldisc.write_wakeup)(tty);
+				}
+				wake_up_interruptible(&tty->write_wait);
+				return;
+			}
+		} else {
+			if (!(status & IRCOMM_CTS)) {
+				DEBUG(2, __FUNCTION__ "(), CTS tx stop...\n");
+
+				tty->hw_stopped = 1;
+			}
+		}
+	}
+}
+
+/*
+ * Function ircomm_tty_data_indication (instance, sap, skb)
+ *
+ *    Handle incomming data, and deliver it to the line discipline
+ *
+ */
+static int ircomm_tty_data_indication(void *instance, void *sap,
+				      struct sk_buff *skb)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	DEBUG(2, __FUNCTION__"()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
+
+	if (!self->tty)
+		return 0;
+
+	/* 
+	 * Just give it over to the line discipline. There is no need to
+	 * involve the flip buffers, since we are not running in an interrupt 
+	 * handler
+	 */
+	self->tty->ldisc.receive_buf(self->tty, skb->data, NULL, skb->len);
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_tty_control_indication (instance, sap, skb)
+ *
+ *    Parse all incomming parameters (easy!)
+ *
+ */
+static int ircomm_tty_control_indication(void *instance, void *sap,
+					 struct sk_buff *skb)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	int clen;
+
+	DEBUG(4, __FUNCTION__"()\n");
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+	ASSERT(skb != NULL, return -1;);
+
+	clen = skb->data[0];
+
+	irda_param_extract_all(self, skb->data+1, MIN(skb->len-1, clen), 
+			       &ircomm_param_info);
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_tty_disconnect_indication (instance, sap, reason, skb)
+ *
+ *    Link disconnected
+ *
+ */
+static void ircomm_tty_disconnect_indication(void *instance, void *sap, 
+					     LM_REASON reason,
+					     struct sk_buff *skb)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	if (!self->tty)
+		return;
+
+	/* Drop carrier */
+	self->session.dce = IRCOMM_DELTA_CD;
+	ircomm_tty_check_modem_status(self);
+#if 0
+	/* Disconnect */
+	tty_hangup(self->tty);
+#endif
+}
+
+/*
+ * Function ircomm_tty_flow_indication (instance, sap, cmd)
+ *
+ *    This function is called by IrTTP when it wants us to slow down the
+ *    transmission of data. We just mark the hardware as stopped, and wait
+ *    for IrTTP to notify us that things are OK again.
+ */
+static void ircomm_tty_flow_indication(void *instance, void *sap, 
+				       LOCAL_FLOW cmd)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	struct tty_struct *tty;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	tty = self->tty;
+
+	switch (cmd) {
+	case FLOW_START:
+		DEBUG(1, __FUNCTION__ "(), hw start!\n");
+		tty->hw_stopped = 0;
+		
+		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) 
+		    && tty->ldisc.write_wakeup)
+			(tty->ldisc.write_wakeup)(tty);
+		wake_up_interruptible(&tty->write_wait);
+		break;
+	default:
+		/* If we get here, something is very wrong, better stop */
+	case FLOW_STOP:
+		DEBUG(1, __FUNCTION__ "(), hw stopped!\n");
+		tty->hw_stopped = 1;
+		break;
+	}
+}
+
+static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf)
+{
+        int  ret=0;
+
+	ret += sprintf(buf+ret, "Service type: ");
+	if (self->service_type & IRCOMM_9_WIRE)
+		ret += sprintf(buf+ret, "9_WIRE");
+	else if (self->service_type & IRCOMM_3_WIRE)
+		ret += sprintf(buf+ret, "3_WIRE");
+	else if (self->service_type & IRCOMM_3_WIRE_RAW)
+		ret += sprintf(buf+ret, "3_WIRE_RAW");
+	else
+		ret += sprintf(buf+ret, "No common service type!\n");
+        ret += sprintf(buf+ret, "\n");
+
+	ret += sprintf(buf+ret, "DTE status: ");	
+        if (self->session.dte & IRCOMM_RTS)
+                ret += sprintf(buf+ret, "RTS|");
+        if (self->session.dte & IRCOMM_DTR)
+                ret += sprintf(buf+ret, "DTR|");
+	ret--; /* remove the last | */
+        ret += sprintf(buf+ret, "\n");
+
+	ret += sprintf(buf+ret, "DCE status: ");
+        if (self->session.dce & IRCOMM_CTS)
+                ret += sprintf(buf+ret, "CTS|");
+        if (self->session.dce & IRCOMM_DSR)
+                ret += sprintf(buf+ret, "DSR|");
+        if (self->session.dce & IRCOMM_CD)
+                ret += sprintf(buf+ret, "CD|");
+        if (self->session.dce & IRCOMM_RI) 
+                ret += sprintf(buf+ret, "RI|");
+	ret--; /* remove the last | */
+        ret += sprintf(buf+ret, "\n");
+
+	ret += sprintf(buf+ret, "Configuration: ");
+	if (!self->session.null_modem)
+		ret += sprintf(buf+ret, "DTE <-> DCE\n");
+	else
+		ret += sprintf(buf+ret, 
+			       "DTE <-> DTE (null modem emulation)\n");
+
+	ret += sprintf(buf+ret, "Data rate: %d\n", self->session.data_rate);
+
+	ret += sprintf(buf+ret, "Flow control: ");
+	if (self->session.flow_control & IRCOMM_XON_XOFF_IN)
+		ret += sprintf(buf+ret, "XON_XOFF_IN|");
+	if (self->session.flow_control & IRCOMM_XON_XOFF_OUT)
+		ret += sprintf(buf+ret, "XON_XOFF_OUT|");
+	if (self->session.flow_control & IRCOMM_RTS_CTS_IN)
+		ret += sprintf(buf+ret, "RTS_CTS_IN|");
+	if (self->session.flow_control & IRCOMM_RTS_CTS_OUT)
+		ret += sprintf(buf+ret, "RTS_CTS_OUT|");
+	if (self->session.flow_control & IRCOMM_DSR_DTR_IN)
+		ret += sprintf(buf+ret, "DSR_DTR_IN|");
+	if (self->session.flow_control & IRCOMM_DSR_DTR_OUT)
+		ret += sprintf(buf+ret, "DSR_DTR_OUT|");
+	if (self->session.flow_control & IRCOMM_ENQ_ACK_IN)
+		ret += sprintf(buf+ret, "ENQ_ACK_IN|");
+	if (self->session.flow_control & IRCOMM_ENQ_ACK_OUT)
+		ret += sprintf(buf+ret, "ENQ_ACK_OUT|");
+	ret--; /* remove the last | */
+        ret += sprintf(buf+ret, "\n");
+
+	ret += sprintf(buf+ret, "Flags: ");
+	if (self->flags & ASYNC_CTS_FLOW)
+		ret += sprintf(buf+ret, "ASYNC_CTS_FLOW|");
+	if (self->flags & ASYNC_CHECK_CD)
+		ret += sprintf(buf+ret, "ASYNC_CHECK_CD|");
+	if (self->flags & ASYNC_INITIALIZED)
+		ret += sprintf(buf+ret, "ASYNC_INITIALIZED|");
+	if (self->flags & ASYNC_LOW_LATENCY)
+		ret += sprintf(buf+ret, "ASYNC_LOW_LATENCY|");
+	if (self->flags & ASYNC_CLOSING)
+		ret += sprintf(buf+ret, "ASYNC_CLOSING|");
+	if (self->flags & ASYNC_NORMAL_ACTIVE)
+		ret += sprintf(buf+ret, "ASYNC_NORMAL_ACTIVE|");
+	if (self->flags & ASYNC_CALLOUT_ACTIVE)
+		ret += sprintf(buf+ret, "ASYNC_CALLOUT_ACTIVE|");
+	ret--; /* remove the last | */
+	ret += sprintf(buf+ret, "\n");
+
+	ret += sprintf(buf+ret, "Open count: %d\n", self->open_count);
+	if (self->tty)
+		ret += sprintf(buf+ret, "Hardware: %s\n", 
+			       self->tty->hw_stopped ? "Stopped" : "Running");
+
+ exit:
+        ret += sprintf(buf+ret, "\n");
+        return ret;
+}
+
+
+/*
+ * Function ircomm_tty_read_proc (buf, start, offset, len, eof, unused)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len,
+				int *eof, void *unused)
+{
+	struct ircomm_tty_cb *self;
+        int i, count = 0, l;
+        off_t begin = 0;
+
+	self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
+	while ((self != NULL) && (count < 4000)) {
+		if (self->magic != IRCOMM_TTY_MAGIC)
+			return 0;
+
+                l = ircomm_tty_line_info(self, buf + count);
+                count += l;
+                if (count+begin > offset+len)
+                        goto done;
+                if (count+begin < offset) {
+                        begin += count;
+                        count = 0;
+                }
+				
+		self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty);
+        }
+        *eof = 1;
+done:
+        if (offset >= count+begin)
+                return 0;
+        *start = buf + (begin-offset);
+        return ((len < begin+count-offset) ? len : begin+count-offset);
+}
+
+
+#ifdef MODULE
+int init_module(void) 
+{
+	return ircomm_tty_init();
+}
+
+void cleanup_module(void)
+{
+	ircomm_tty_cleanup();
+}
+
+#endif /* MODULE */
+
+
+
+
diff -u --recursive --new-file v2.3.15/linux/net/irda/ircomm/ircomm_tty_attach.c linux/net/irda/ircomm/ircomm_tty_attach.c
--- v2.3.15/linux/net/irda/ircomm/ircomm_tty_attach.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/ircomm_tty_attach.c	Tue Aug 31 09:33:09 1999
@@ -0,0 +1,819 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_tty_attach.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sat Jun  5 17:42:00 1999
+ * Modified at:   Wed Aug 25 13:32:00 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irias_object.h>
+#include <net/irda/parameters.h>
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_param.h>
+#include <net/irda/ircomm_event.h>
+
+#include <net/irda/ircomm_tty.h>
+#include <net/irda/ircomm_tty_attach.h>
+
+static void ircomm_tty_ias_register(struct ircomm_tty_cb *self);
+static void ircomm_tty_discovery_indication(discovery_t *discovery);
+static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, 
+					struct ias_value *value, void *priv);
+void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self, int timeout);
+void ircomm_tty_watchdog_timer_expired(void *data);
+
+static int ircomm_tty_state_idle(struct ircomm_tty_cb *self, 
+				 IRCOMM_TTY_EVENT event, 
+				 struct sk_buff *skb, 
+				 struct ircomm_tty_info *info);
+static int ircomm_tty_state_search(struct ircomm_tty_cb *self, 
+				   IRCOMM_TTY_EVENT event, 
+				   struct sk_buff *skb, 
+				   struct ircomm_tty_info *info);
+static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, 
+					     IRCOMM_TTY_EVENT event, 
+					     struct sk_buff *skb, 
+					     struct ircomm_tty_info *info);
+static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, 
+					   IRCOMM_TTY_EVENT event, 
+					   struct sk_buff *skb, 
+					   struct ircomm_tty_info *info);
+static int ircomm_tty_state_setup(struct ircomm_tty_cb *self, 
+				  IRCOMM_TTY_EVENT event, 
+				  struct sk_buff *skb, 
+				  struct ircomm_tty_info *info);
+static int ircomm_tty_state_ready(struct ircomm_tty_cb *self, 
+				  IRCOMM_TTY_EVENT event, 
+				  struct sk_buff *skb, 
+				  struct ircomm_tty_info *info);
+
+char *ircomm_tty_state[] = {
+	"IRCOMM_TTY_IDLE",
+	"IRCOMM_TTY_SEARCH",
+	"IRCOMM_TTY_QUERY_PARAMETERS",
+	"IRCOMM_TTY_QUERY_LSAP_SEL",
+	"IRCOMM_TTY_SETUP",
+	"IRCOMM_TTY_READY",
+	"*** ERROR *** ",
+};
+
+char *ircomm_tty_event[] = {
+	"IRCOMM_TTY_ATTACH_CABLE",
+	"IRCOMM_TTY_DETACH_CABLE",
+	"IRCOMM_TTY_DATA_REQUEST",
+	"IRCOMM_TTY_DATA_INDICATION",
+	"IRCOMM_TTY_DISCOVERY_REQUEST",
+	"IRCOMM_TTY_DISCOVERY_INDICATION",
+	"IRCOMM_TTY_CONNECT_CONFIRM",
+	"IRCOMM_TTY_CONNECT_INDICATION",
+	"IRCOMM_TTY_WD_TIMER_EXPIRED",
+	"IRCOMM_TTY_GOT_PARAMETERS",
+	"IRCOMM_TTY_GOT_LSAPSEL",
+	"*** ERROR ****",
+};
+
+static int (*state[])(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
+		      struct sk_buff *skb, struct ircomm_tty_info *info) = 
+{
+	ircomm_tty_state_idle,
+	ircomm_tty_state_search,
+	ircomm_tty_state_query_parameters,
+	ircomm_tty_state_query_lsap_sel,
+	ircomm_tty_state_setup,
+	ircomm_tty_state_ready,
+};
+
+/*
+ * Function ircomm_tty_attach_cable (driver)
+ *
+ *    Try to attach cable (IrCOMM link). This function will only return
+ *    when the link has been connected, or if an error condition occurs. 
+ *    If success, the return value is the resulting service type.
+ */
+int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+       	/* Check if somebody has already connected to us */
+	if (ircomm_is_connected(self->ircomm)) {
+		DEBUG(0, __FUNCTION__ "(), already connected!\n");
+		return 0;
+	}
+
+	/* Make sure nobody tries to write before the link is up */
+	self->tty->hw_stopped = 1;
+
+	ircomm_tty_ias_register(self);
+
+	/* Check if somebody has already connected to us */
+	if (ircomm_is_connected(self->ircomm)) {
+		DEBUG(0, __FUNCTION__ "(), already connected!\n");
+		return 0;
+	}
+
+	ircomm_tty_do_event(self, IRCOMM_TTY_ATTACH_CABLE, NULL, NULL);
+
+	return 0;
+}
+
+/*
+ * Function ircomm_detach_cable (driver)
+ *
+ *    Detach cable, or cable has been detached by peer
+ *
+ */
+void ircomm_tty_detach_cable(struct ircomm_tty_cb *self)
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	/* Remove IrCOMM hint bits */
+	irlmp_unregister_client(self->ckey);
+	irlmp_unregister_service(self->skey);
+
+	/* Remove LM-IAS object */
+	if (self->obj)
+		irias_delete_object(self->obj);
+
+	ircomm_tty_do_event(self, IRCOMM_TTY_DETACH_CABLE, NULL, NULL);
+
+	/* Reset some values */
+	self->daddr = self->saddr = 0;
+	self->dlsap_sel = self->slsap_sel = 0;
+
+	memset(&self->session, 0, sizeof(struct ircomm_params));
+}
+
+/*
+ * Function ircomm_tty_ias_register (self)
+ *
+ *    Register with LM-IAS depending on which service type we are
+ *
+ */
+static void ircomm_tty_ias_register(struct ircomm_tty_cb *self)
+{
+	__u8 oct_seq[6];
+	__u16 hints;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+	
+	if (self->service_type & IRCOMM_3_WIRE_RAW) {
+		hints = irlmp_service_to_hint(S_PRINTER);
+		hints |= irlmp_service_to_hint(S_COMM);
+		
+		/* Register IrLPT with LM-IAS */
+		self->obj = irias_new_object("IrLPT", IAS_IRLPT_ID);
+		irias_add_integer_attrib(self->obj, "IrDA:IrLMP:LsapSel", 
+					 self->slsap_sel);
+		irias_insert_object(self->obj);
+	} else {
+		hints = irlmp_service_to_hint(S_COMM);
+		
+		/* Register IrCOMM with LM-IAS */
+		self->obj = irias_new_object("IrDA:IrCOMM", IAS_IRCOMM_ID);
+		irias_add_integer_attrib(self->obj, "IrDA:TinyTP:LsapSel", 
+					 self->slsap_sel);
+		
+		/* Code the parameters into the buffer */
+		irda_param_pack(oct_seq, "bbbbbb", 
+				IRCOMM_SERVICE_TYPE, 1, self->service_type,
+				IRCOMM_PORT_TYPE,    1, IRCOMM_SERIAL);
+		
+		/* Register parameters with LM-IAS */
+		irias_add_octseq_attrib(self->obj, "Parameters", oct_seq, 6);
+		irias_insert_object(self->obj);
+	}
+	self->skey = irlmp_register_service(hints);
+	self->ckey = irlmp_register_client(
+		hints, ircomm_tty_discovery_indication, NULL);
+}
+
+/*
+ * Function ircomm_send_initial_parameters (self)
+ *
+ *    Send initial parameters to the remote IrCOMM device. These parameters
+ *    must be sent before any data.
+ */
+static int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self)
+{
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	if (self->service_type & IRCOMM_3_WIRE_RAW) 
+		return 0;
+
+	/* Set default values */
+	self->session.data_rate = 9600;
+	self->session.data_format = IRCOMM_WSIZE_8;  /* 8N1 */
+	self->session.flow_control = 0;              /* None */
+
+	/* Do not set delta values for the initial parameters */
+	self->session.dte = (IRCOMM_DTR| IRCOMM_RTS);
+
+	ircomm_param_request(self, IRCOMM_SERVICE_TYPE, FALSE);
+	ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE);
+	ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE);
+	
+	/* For a 3 wire service, we just flush the last parameter and return */
+	if (self->session.service_type == IRCOMM_3_WIRE) {
+		ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE);
+		return 0;
+	}
+
+	/* Only 9-wire service types continue here */
+#if 0
+	ircomm_param_request(self, IRCOMM_FLOW_CONTROL, FALSE);
+	ircomm_param_request(self, IRCOMM_XON_XOFF, FALSE);
+	ircomm_param_request(self, IRCOMM_ENQ_ACK, FALSE);
+#endif	
+	/* Notify peer that we are ready to receive data */
+	ircomm_param_request(self, IRCOMM_DTE, TRUE);
+	
+	return 0;
+}
+
+/*
+ * Function ircomm_tty_discovery_indication (discovery)
+ *
+ *    Remote device is discovered, try query the remote IAS to see which
+ *    device it is, and which services it has.
+ *
+ */
+static void ircomm_tty_discovery_indication(discovery_t *discovery)
+{
+	struct ircomm_tty_cb *self;
+	struct ircomm_tty_info info;
+
+	DEBUG(2, __FUNCTION__"()\n");
+
+	info.daddr = discovery->daddr;
+	info.saddr = discovery->saddr;
+
+	self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);
+	while (self != NULL) {
+		ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+		
+		ircomm_tty_do_event(self, IRCOMM_TTY_DISCOVERY_INDICATION, 
+				    NULL, &info);
+
+		self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty);
+	}
+}
+
+/*
+ * Function ircomm_tty_getvalue_confirm (result, obj_id, value, priv)
+ *
+ *    Got result from the IAS query we make
+ *
+ */
+static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, 
+					struct ias_value *value, 
+					void *priv)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) priv;
+
+	DEBUG(2, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	/* Check if request succeeded */
+	if (result != IAS_SUCCESS) {
+		DEBUG(0, __FUNCTION__ "(), got NULL value!\n");
+		return;
+	}
+
+	switch (value->type) {
+ 	case IAS_OCT_SEQ:
+		DEBUG(2, __FUNCTION__"(), got octet sequence\n");
+
+		irda_param_extract_all(self, value->t.oct_seq, value->len,
+				       &ircomm_param_info);
+
+		ircomm_tty_do_event(self, IRCOMM_TTY_GOT_PARAMETERS, NULL, 
+				    NULL);
+		break;
+	case IAS_INTEGER:
+		/* Got LSAP selector */	
+		DEBUG(2, __FUNCTION__"(), got lsapsel = %d\n", 
+		      value->t.integer);
+
+		if (value->t.integer == -1) {
+			DEBUG(0, __FUNCTION__"(), invalid value!\n");
+		} else
+			self->dlsap_sel = value->t.integer;
+
+		ircomm_tty_do_event(self, IRCOMM_TTY_GOT_LSAPSEL, NULL, NULL);
+		break;
+	case IAS_MISSING:
+		DEBUG(0, __FUNCTION__"(), got IAS_MISSING\n");
+		break;
+	default:
+		DEBUG(0, __FUNCTION__"(), got unknown type!\n");
+		break;
+	}
+}
+
+/*
+ * Function ircomm_tty_connect_confirm (instance, sap, qos, max_sdu_size, skb)
+ *
+ *    Connection confirmed
+ *
+ */
+void ircomm_tty_connect_confirm(void *instance, void *sap, 
+				struct qos_info *qos, 
+				__u32 max_data_size, 
+				__u8 max_header_size, 
+				struct sk_buff *skb)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	self->max_data_size = max_data_size;
+	self->max_header_size = max_header_size;
+
+	ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_CONFIRM, NULL, NULL);
+}
+
+/*
+ * Function ircomm_tty_connect_indication (instance, sap, qos, max_sdu_size, 
+ *                                         skb)
+ *
+ *    we are discovered and being requested to connect by remote device !
+ *
+ */
+void ircomm_tty_connect_indication(void *instance, void *sap, 
+				   struct qos_info *qos, 
+				   __u32 max_data_size,
+				   __u8 max_header_size, 
+				   struct sk_buff *skb)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
+	int clen;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	self->max_data_size = max_data_size;
+	self->max_header_size = max_header_size;
+
+	clen = skb->data[0];
+	if (clen)
+		irda_param_extract_all(self, skb->data+1, MIN(skb->len, clen), 
+				       &ircomm_param_info);
+
+	ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_INDICATION, NULL, NULL);
+}
+
+/*
+ * Function ircomm_tty_link_established (self)
+ *
+ *    Called when the IrCOMM link is established
+ *
+ */
+void ircomm_tty_link_established(struct ircomm_tty_cb *self)
+{
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	del_timer(&self->watchdog_timer);
+
+	/*  
+	 * IrCOMM link is now up, and if we are not using hardware
+	 * flow-control, then declare the hardware as running 
+	 */
+	if (!(self->flags & ASYNC_CTS_FLOW)) {
+		DEBUG(2, __FUNCTION__ "(), starting hardware!\n");
+		if (!self->tty)
+			return;
+		self->tty->hw_stopped = 0;
+
+		/* Kick client */
+		ircomm_tty_do_softint(self);
+	}
+}
+
+/*
+ * Function irlan_start_watchdog_timer (self, timeout)
+ *
+ *    
+ *
+ */
+void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self, int timeout)
+{
+	DEBUG(4, __FUNCTION__ "()\n");
+	
+	irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
+			 ircomm_tty_watchdog_timer_expired);
+}
+
+/*
+ * Function ircomm_tty_watchdog_timer_expired (data)
+ *
+ *    Called when the connect procedure have taken to much time.
+ *
+ */
+void ircomm_tty_watchdog_timer_expired(void *data)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) data;
+	
+	DEBUG(1, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	ircomm_tty_do_event(self, IRCOMM_TTY_WD_TIMER_EXPIRED, NULL, NULL);
+}
+
+/*
+ * Function ircomm_tty_state_idle (self, event, skb, info)
+ *
+ *    Just hanging around
+ *
+ */
+static int ircomm_tty_state_idle(struct ircomm_tty_cb *self, 
+				 IRCOMM_TTY_EVENT event, 
+				 struct sk_buff *skb, 
+				 struct ircomm_tty_info *info)
+{
+	int ret = 0;
+
+	DEBUG(1, __FUNCTION__": state=%s, event=%s\n",
+	      ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+	switch (event) {
+	case IRCOMM_TTY_ATTACH_CABLE:
+		/* Try to discover any remote devices */		
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
+
+		irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
+		break;
+	case IRCOMM_TTY_DISCOVERY_INDICATION:
+		self->daddr = info->daddr;
+		self->saddr = info->saddr;
+
+		iriap_getvaluebyclass_request("IrDA:IrCOMM", "Parameters",
+					      self->saddr, self->daddr,
+					      ircomm_tty_getvalue_confirm, 
+					      self);
+
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS);
+		break;
+	case IRCOMM_TTY_CONNECT_INDICATION:
+		del_timer(&self->watchdog_timer);
+
+		/* Accept connection */
+		ircomm_connect_response(self->ircomm, NULL);
+		
+		ircomm_tty_link_established(self);
+		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+		break;
+	case IRCOMM_TTY_WD_TIMER_EXPIRED:
+		/* Just stay idle */
+		break;
+	case IRCOMM_TTY_DETACH_CABLE:
+		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+		break;
+	default:
+		DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+		      ircomm_tty_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_state_search (self, event, skb, info)
+ *
+ *    Trying to discover an IrCOMM device
+ *
+ */
+static int ircomm_tty_state_search(struct ircomm_tty_cb *self, 
+				   IRCOMM_TTY_EVENT event, 
+				   struct sk_buff *skb, 
+				   struct ircomm_tty_info *info)
+{
+	int ret = 0;
+
+	DEBUG(1, __FUNCTION__": state=%s, event=%s\n",
+	      ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+	switch (event) {
+	case IRCOMM_TTY_DISCOVERY_INDICATION:
+		self->daddr = info->daddr;
+		self->saddr = info->saddr;
+
+		if (self->service_type == IRCOMM_3_WIRE_RAW) {
+			iriap_getvaluebyclass_request("IrLPT", 
+						      "IrDA:IrLMP:LsapSel",
+						      self->saddr, self->daddr,
+						      ircomm_tty_getvalue_confirm, 
+						      self);
+			ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL);
+		} else {
+			iriap_getvaluebyclass_request("IrDA:IrCOMM", 
+						      "Parameters",
+						      self->saddr, self->daddr,
+						      ircomm_tty_getvalue_confirm, 
+						      self);
+			ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_PARAMETERS);
+		}
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		break;
+	case IRCOMM_TTY_CONNECT_INDICATION:
+		del_timer(&self->watchdog_timer);
+
+		/* Accept connection */
+		ircomm_connect_response(self->ircomm, NULL);
+		ircomm_tty_link_established(self);
+		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+		break;
+	case IRCOMM_TTY_WD_TIMER_EXPIRED:
+		/* Try to discover any remote devices */		
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
+		break;
+	case IRCOMM_TTY_DETACH_CABLE:
+		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+		break;
+	default:
+		DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+		      ircomm_tty_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_state_query (self, event, skb, info)
+ *
+ *    Querying the remote LM-IAS for IrCOMM parameters
+ *
+ */
+static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self, 
+					     IRCOMM_TTY_EVENT event, 
+					     struct sk_buff *skb, 
+					     struct ircomm_tty_info *info)
+{
+	int ret = 0;
+
+	DEBUG(1, __FUNCTION__": state=%s, event=%s\n",
+	      ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+	switch (event) {
+	case IRCOMM_TTY_GOT_PARAMETERS:
+		iriap_getvaluebyclass_request("IrDA:IrCOMM", 
+					      "IrDA:TinyTP:LsapSel",
+					      self->saddr, self->daddr,
+					      ircomm_tty_getvalue_confirm, 
+					      self);
+
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		ircomm_tty_next_state(self, IRCOMM_TTY_QUERY_LSAP_SEL);
+		break;
+	case IRCOMM_TTY_WD_TIMER_EXPIRED:
+		/* Go back to search mode */
+		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
+		ircomm_tty_start_watchdog_timer(self, 3*HZ); 
+		break;
+	case IRCOMM_TTY_CONNECT_INDICATION:
+		del_timer(&self->watchdog_timer);
+
+		/* Accept connection */
+		ircomm_connect_response(self->ircomm, NULL);
+		ircomm_tty_link_established(self);
+		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+		break;
+	case IRCOMM_TTY_DETACH_CABLE:
+		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+		break;
+	default:
+		DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+		      ircomm_tty_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_state_query_lsap_sel (self, event, skb, info)
+ *
+ *    Query remote LM-IAS for the LSAP selector which we can connect to
+ *
+ */
+static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self, 
+					   IRCOMM_TTY_EVENT event, 
+					   struct sk_buff *skb, 
+					   struct ircomm_tty_info *info)
+{
+	int ret = 0;
+
+	DEBUG(1, __FUNCTION__": state=%s, event=%s\n",
+	      ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+	switch (event) {
+	case IRCOMM_TTY_GOT_LSAPSEL:
+		/* Connect to remote device */
+		ret = ircomm_connect_request(self->ircomm, self->dlsap_sel,
+					     self->saddr, self->daddr, 
+					     NULL, self->service_type);
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		ircomm_tty_next_state(self, IRCOMM_TTY_SETUP);
+		break;
+	case IRCOMM_TTY_WD_TIMER_EXPIRED:
+		/* Go back to search mode */
+		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		break;
+	case IRCOMM_TTY_CONNECT_INDICATION:
+		del_timer(&self->watchdog_timer);
+
+		/* Accept connection */
+		ircomm_connect_response(self->ircomm, NULL);
+		ircomm_tty_link_established(self);
+		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+		break;
+	case IRCOMM_TTY_DETACH_CABLE:
+		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+		break;
+	default:
+		DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+		      ircomm_tty_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_state_setup (self, event, skb, info)
+ *
+ *    Trying to connect
+ *
+ */
+static int ircomm_tty_state_setup(struct ircomm_tty_cb *self, 
+				  IRCOMM_TTY_EVENT event, 
+				  struct sk_buff *skb, 
+				  struct ircomm_tty_info *info)
+{
+	int ret = 0;
+
+	DEBUG(1, __FUNCTION__": state=%s, event=%s\n",
+	      ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+	switch (event) {
+	case IRCOMM_TTY_CONNECT_CONFIRM:
+		ircomm_tty_link_established(self);
+		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+
+		/* 
+		 * Send initial parameters. This will also send out queued
+		 * parameters waiting for the connection to come up 
+		 */
+		ircomm_tty_send_initial_parameters(self);
+
+		ASSERT(self->tty != NULL, return -1;);
+
+		/* Send queued frames */
+		while ((skb = skb_dequeue(&self->tx_queue))) {
+			ret = ircomm_data_request(self->ircomm, skb);
+			if (ret < 0)
+				break;
+		}
+		
+		/* Wake up processes blocked on open */
+		wake_up_interruptible(&self->open_wait);
+
+		/* 
+		 * Wake up processes blocked on write, or waiting for a write 
+		 * wakeup notification
+		 */
+		queue_task(&self->tqueue, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);
+		break;
+	case IRCOMM_TTY_CONNECT_INDICATION:
+		del_timer(&self->watchdog_timer);
+		
+		/* Accept connection */
+		ircomm_connect_response(self->ircomm, NULL);
+		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
+		break;
+	case IRCOMM_TTY_WD_TIMER_EXPIRED:
+		/* Go back to search mode */
+		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
+		ircomm_tty_start_watchdog_timer(self, 3*HZ);
+		break;
+	case IRCOMM_TTY_DETACH_CABLE:
+		ircomm_disconnect_request(self->ircomm, NULL);
+		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+		break;
+	default:
+		DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+		      ircomm_tty_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_state_ready (self, event, skb, info)
+ *
+ *    IrCOMM is now connected
+ *
+ */
+static int ircomm_tty_state_ready(struct ircomm_tty_cb *self, 
+				  IRCOMM_TTY_EVENT event, 
+				  struct sk_buff *skb, 
+				  struct ircomm_tty_info *info)
+{
+	int ret = 0;
+
+	switch (event) {
+	case IRCOMM_TTY_DATA_REQUEST:
+		ret = ircomm_data_request(self->ircomm, skb);
+		break;		
+	case IRCOMM_TTY_DATA_INDICATION:
+		break;
+	case IRCOMM_TTY_DETACH_CABLE:
+		ircomm_disconnect_request(self->ircomm, NULL);
+		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
+		break;
+	default:
+		DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
+		      ircomm_tty_event[event]);
+		return -EINVAL;
+	}
+	return ret;
+}
+
+/*
+ * Function ircomm_tty_do_event (self, event, skb)
+ *
+ *    Process event
+ *
+ */
+int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
+			struct sk_buff *skb, struct ircomm_tty_info *info) 
+{
+	DEBUG(2, __FUNCTION__": state=%s, event=%s\n",
+	      ircomm_tty_state[self->state], ircomm_tty_event[event]);
+
+	return (*state[self->state])(self, event, skb, info);
+}
+
+/*
+ * Function ircomm_tty_next_state (self, state)
+ *
+ *    Switch state
+ *
+ */
+void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_STATE state)
+{
+	self->state = state;
+	
+	DEBUG(1, __FUNCTION__": next state=%s, service type=%d\n", 
+	      ircomm_tty_state[self->state], self->service_type);
+}
+
diff -u --recursive --new-file v2.3.15/linux/net/irda/ircomm/ircomm_tty_ioctl.c linux/net/irda/ircomm/ircomm_tty_ioctl.c
--- v2.3.15/linux/net/irda/ircomm/ircomm_tty_ioctl.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/ircomm_tty_ioctl.c	Tue Aug 31 09:33:09 1999
@@ -0,0 +1,458 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_tty_ioctl.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Thu Jun 10 14:39:09 1999
+ * Modified at:   Wed Aug 25 14:11:02 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/termios.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+
+#include <net/irda/ircomm_core.h>
+#include <net/irda/ircomm_param.h>
+#include <net/irda/ircomm_tty_attach.h>
+#include <net/irda/ircomm_tty.h>
+
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+/*
+ * Function ircomm_tty_change_speed (driver)
+ *
+ *    Change speed of the driver. If the remote device is a DCE, then this
+ *    should make it change the speed of its serial port
+ */
+void ircomm_tty_change_speed(struct ircomm_tty_cb *self)
+{
+	unsigned cflag, cval;
+	int baud;
+
+	if (!self->tty || !self->tty->termios || !self->ircomm)
+		return;
+
+	cflag = self->tty->termios->c_cflag;
+
+	/*  byte size and parity */
+	switch (cflag & CSIZE) {
+	case CS5: cval = IRCOMM_WSIZE_5; break;
+	case CS6: cval = IRCOMM_WSIZE_6; break;
+	case CS7: cval = IRCOMM_WSIZE_7; break;
+	case CS8: cval = IRCOMM_WSIZE_8; break;
+	default:  cval = IRCOMM_WSIZE_5; break;
+	}
+	if (cflag & CSTOPB)
+		cval |= IRCOMM_2_STOP_BIT;
+	
+	if (cflag & PARENB)
+		cval |= IRCOMM_PARITY_ENABLE;
+	if (!(cflag & PARODD))
+		cval |= IRCOMM_PARITY_EVEN;
+
+	/* Determine divisor based on baud rate */
+	baud = tty_get_baud_rate(self->tty);
+	if (!baud)
+		baud = 9600;	/* B0 transition handled in rs_set_termios */
+
+	self->session.data_rate = baud;
+	ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE);
+	
+	/* CTS flow control flag and modem status interrupts */
+	if (cflag & CRTSCTS) {
+		self->flags |= ASYNC_CTS_FLOW;
+		self->session.flow_control |= IRCOMM_RTS_CTS_IN;
+	} else
+		self->flags &= ~ASYNC_CTS_FLOW;
+	
+	if (cflag & CLOCAL)
+		self->flags &= ~ASYNC_CHECK_CD;
+	else
+		self->flags |= ASYNC_CHECK_CD;
+#if 0	
+	/*
+	 * Set up parity check flag
+	 */
+
+	if (I_INPCK(self->tty))
+		driver->read_status_mask |= LSR_FE | LSR_PE;
+	if (I_BRKINT(driver->tty) || I_PARMRK(driver->tty))
+		driver->read_status_mask |= LSR_BI;
+	
+	/*
+	 * Characters to ignore
+	 */
+	driver->ignore_status_mask = 0;
+	if (I_IGNPAR(driver->tty))
+		driver->ignore_status_mask |= LSR_PE | LSR_FE;
+
+	if (I_IGNBRK(self->tty)) {
+		self->ignore_status_mask |= LSR_BI;
+		/*
+		 * If we're ignore parity and break indicators, ignore 
+		 * overruns too. (For real raw support).
+		 */
+		if (I_IGNPAR(self->tty)) 
+			self->ignore_status_mask |= LSR_OE;
+	}
+#endif
+	self->session.data_format = cval;
+
+	ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE);
+ 	ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE);
+}
+
+/*
+ * Function ircomm_tty_set_termios (tty, old_termios)
+ *
+ *    This routine allows the tty driver to be notified when device's
+ *    termios settings have changed.  Note that a well-designed tty driver
+ *    should be prepared to accept the case where old == NULL, and try to
+ *    do something rational.
+ */
+void ircomm_tty_set_termios(struct tty_struct *tty, 
+			    struct termios *old_termios)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	unsigned int cflag = tty->termios->c_cflag;
+	unsigned long flags;
+
+	if ((cflag == old_termios->c_cflag) && 
+	    (RELEVANT_IFLAG(tty->termios->c_iflag) == 
+	     RELEVANT_IFLAG(old_termios->c_iflag)))
+	{
+		return;
+	}
+
+	ircomm_tty_change_speed(self);
+
+	/* Handle transition to B0 status */
+	if ((old_termios->c_cflag & CBAUD) &&
+	    !(cflag & CBAUD)) {
+		self->session.dte &= ~(IRCOMM_DTR|IRCOMM_RTS);
+		ircomm_param_request(self, IRCOMM_DTE, TRUE);
+	}
+	
+	/* Handle transition away from B0 status */
+	if (!(old_termios->c_cflag & CBAUD) &&
+	    (cflag & CBAUD)) {
+		self->session.dte |= IRCOMM_DTR;
+		if (!(tty->termios->c_cflag & CRTSCTS) || 
+		    !test_bit(TTY_THROTTLED, &tty->flags)) {
+			self->session.dte |= IRCOMM_RTS;
+		}
+		ircomm_param_request(self, IRCOMM_DTE, TRUE);
+	}
+	
+	/* Handle turning off CRTSCTS */
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) 
+	{
+		tty->hw_stopped = 0;
+		ircomm_tty_start(tty);
+	}
+}
+
+/*
+ * Function ircomm_tty_get_modem_info (self, value)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_get_modem_info(struct ircomm_tty_cb *self, 
+				     unsigned int *value)
+{
+	unsigned int result;
+
+	DEBUG(1, __FUNCTION__ "()\n");
+
+	result =  ((self->session.dte & IRCOMM_RTS)       ? TIOCM_RTS : 0)
+		| ((self->session.dte & IRCOMM_DTR)       ? TIOCM_DTR : 0)
+		| ((self->session.dce & IRCOMM_DELTA_CD)  ? TIOCM_CAR : 0)
+		| ((self->session.dce & IRCOMM_DELTA_RI)  ? TIOCM_RNG : 0)
+		| ((self->session.dce & IRCOMM_DELTA_DSR) ? TIOCM_DSR : 0)
+		| ((self->session.dce & IRCOMM_DELTA_CTS) ? TIOCM_CTS : 0);
+
+	return put_user(result, value);
+}
+
+/*
+ * Function set_modem_info (driver, cmd, value)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_set_modem_info(struct ircomm_tty_cb *self, 
+				     unsigned int cmd, unsigned int *value)
+{ 
+	unsigned int arg;
+	__u8 old_rts, old_dtr;
+	int error;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
+	error = get_user(arg, value);
+	if (error)
+		return error;
+
+	old_rts = self->session.dte & IRCOMM_RTS;
+	old_dtr = self->session.dte & IRCOMM_DTR;
+
+	switch (cmd) {
+	case TIOCMBIS: 
+		if (arg & TIOCM_RTS) 
+			self->session.dte |= IRCOMM_RTS;
+		if (arg & TIOCM_DTR)
+			self->session.dte |= IRCOMM_DTR;
+		break;
+		
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS)
+			self->session.dte &= ~IRCOMM_RTS;
+		if (arg & TIOCM_DTR)
+ 			self->session.dte &= ~IRCOMM_DTR;
+ 		break;
+		
+	case TIOCMSET:
+ 		self->session.dte = 
+			((self->session.dte & ~(IRCOMM_RTS | IRCOMM_DTR))
+			 | ((arg & TIOCM_RTS) ? IRCOMM_RTS : 0)
+			 | ((arg & TIOCM_DTR) ? IRCOMM_DTR : 0));
+		break;
+		
+	default:
+		return -EINVAL;
+	}
+	
+	if ((self->session.dte & IRCOMM_RTS) != old_rts)
+		self->session.dte |= IRCOMM_DELTA_RTS;
+
+	if ((self->session.dte & IRCOMM_DTR) != old_dtr)
+		self->session.dte |= IRCOMM_DELTA_DTR;
+
+	ircomm_param_request(self, IRCOMM_DTE, TRUE);
+	
+	return 0;
+}
+
+/*
+ * Function get_serial_info (driver, retinfo)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_get_serial_info(struct ircomm_tty_cb *self,
+				      struct serial_struct *retinfo)
+{
+	struct serial_struct info;
+   
+	if (!retinfo)
+		return -EFAULT;
+
+	DEBUG(1, __FUNCTION__ "()\n");
+
+	memset(&info, 0, sizeof(info));
+	info.line = self->line;
+	/* info.flags = self->flags; */
+	info.baud_base = self->session.data_rate;
+#if 0
+	info.close_delay = driver->close_delay;
+	info.closing_wait = driver->closing_wait;
+#endif
+	/* For compatibility  */
+ 	info.type = PORT_16550A;
+ 	info.port = 0;
+ 	info.irq = 0;
+	info.xmit_fifo_size = 0;
+	info.hub6 = 0;   
+#if 0
+	info.custom_divisor = driver->custom_divisor;
+#endif
+	if (copy_to_user(retinfo, &info, sizeof(*retinfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Function set_serial_info (driver, new_info)
+ *
+ *    
+ *
+ */
+static int ircomm_tty_set_serial_info(struct ircomm_tty_cb *tty,
+				      struct serial_struct *new_info)
+{
+	struct serial_struct new_serial;
+	struct ircomm_tty_cb old_driver;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+#if 0
+
+	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+		return -EFAULT;
+
+	old_driver = *driver;
+  
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((new_serial.baud_base != driver->comm->data_rate) ||
+		    (new_serial.close_delay != driver->close_delay) ||
+		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
+		     (driver->flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		driver->flags = ((driver->flags & ~ASYNC_USR_MASK) |
+				 (new_serial.flags & ASYNC_USR_MASK));
+		driver->custom_divisor = new_serial.custom_divisor;
+		goto check_and_exit;
+	}
+
+	/*
+	 * OK, past this point, all the error checking has been done.
+	 * At this point, we start making changes.....
+	 */
+
+	if (self->session.data_rate != new_serial.baud_base) {
+		self->session.data_rate.data_rate = new_serial.baud_base;
+		if (driver->comm->state == IRCOMM_CONN)
+			ircomm_control_request(driver->comm, DATA_RATE);
+	}
+
+	driver->close_delay = new_serial.close_delay * HZ/100;
+	driver->closing_wait = new_serial.closing_wait * HZ/100;
+	driver->custom_divisor = new_serial.custom_divisor;
+
+	self->flags = ((self->flags & ~ASYNC_FLAGS) |
+		       (new_serial.flags & ASYNC_FLAGS));
+	self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+ check_and_exit:
+
+	if (self->flags & ASYNC_INITIALIZED) {
+		if (((old_driver.flags & ASYNC_SPD_MASK) !=
+		     (self->flags & ASYNC_SPD_MASK)) ||
+		    (old_driver.custom_divisor != driver->custom_divisor)) {
+			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+				driver->tty->alt_speed = 57600;
+			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+				driver->tty->alt_speed = 115200;
+			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+				driver->tty->alt_speed = 230400;
+			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+				driver->tty->alt_speed = 460800;
+			ircomm_tty_change_speed(driver);
+		}
+	}
+#endif
+	return 0;
+}
+
+/*
+ * Function ircomm_tty_ioctl (tty, file, cmd, arg)
+ *
+ *    
+ *
+ */
+int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file, 
+		     unsigned int cmd, unsigned long arg)
+{
+	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	int ret = 0;
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
+	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+
+	switch (cmd) {
+	case TIOCMGET:
+		ret = ircomm_tty_get_modem_info(self, (unsigned int *) arg);
+		break;
+	case TIOCMBIS:
+	case TIOCMBIC:
+	case TIOCMSET:
+		ret = ircomm_tty_set_modem_info(self, cmd, (unsigned int *) arg);
+		break;
+	case TIOCGSERIAL:
+		ret = ircomm_tty_get_serial_info(self, (struct serial_struct *) arg);
+		break;
+	case TIOCSSERIAL:
+		ret = ircomm_tty_set_serial_info(self, (struct serial_struct *) arg);
+		break;
+	case TIOCMIWAIT:
+		DEBUG(0, "(), TIOCMIWAIT, not impl!\n");
+		break;
+
+	case TIOCGICOUNT:
+		DEBUG(0, __FUNCTION__ "(), TIOCGICOUNT not impl!\n");
+#if 0
+		save_flags(flags); cli();
+		cnow = driver->icount;
+		restore_flags(flags);
+		p_cuser = (struct serial_icounter_struct *) arg;
+		error = put_user(cnow.cts, &p_cuser->cts);
+		if (error) return error;
+		error = put_user(cnow.dsr, &p_cuser->dsr);
+		if (error) return error;
+		error = put_user(cnow.rng, &p_cuser->rng);
+		if (error) return error;
+		error = put_user(cnow.dcd, &p_cuser->dcd);
+		if (error) return error;
+		error = put_user(cnow.rx, &p_cuser->rx);
+		if (error) return error;
+		error = put_user(cnow.tx, &p_cuser->tx);
+		if (error) return error;
+		error = put_user(cnow.frame, &p_cuser->frame);
+		if (error) return error;
+		error = put_user(cnow.overrun, &p_cuser->overrun);
+		if (error) return error;
+		error = put_user(cnow.parity, &p_cuser->parity);
+		if (error) return error;
+		error = put_user(cnow.brk, &p_cuser->brk);
+		if (error) return error;
+		error = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
+		if (error) return error;			
+#endif		
+		return 0;
+	default:
+		ret = -ENOIOCTLCMD;  /* ioctls which we must ignore */
+	}
+	return ret;
+}
+
+
+
diff -u --recursive --new-file v2.3.15/linux/net/irda/ircomm/irvtd_driver.c linux/net/irda/ircomm/irvtd_driver.c
--- v2.3.15/linux/net/irda/ircomm/irvtd_driver.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/ircomm/irvtd_driver.c	Wed Dec 31 16:00:00 1969
@@ -1,2071 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irvtd_driver.c
- * Version:       
- * Description:   Virtual tty driver (the "port emulation entity" of IrCOMM)
- * Status:        Experimental.
- * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
- * Source:        serial.c by Linus Torvalds
- *                isdn_tty.c by Fritz Elfert
- *
- *     Copyright (c) 1998-1999, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Takahide Higuchi, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/termios.h>
-#include <linux/tty.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irias_object.h>
-
-#include <net/irda/irvtd.h>
-
-#ifndef MIN
-#define MIN(a,b)        ((a) < (b) ? (a) : (b))
-#endif
-
-#define DO_RESTART
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-struct tty_driver irvtd_drv;
-struct tty_struct *irvtd_table[COMM_MAX_TTY];
-struct termios *irvtd_termios[COMM_MAX_TTY];
-struct termios *irvtd_termios_locked[COMM_MAX_TTY];
-static int irvtd_refcount;
-struct irvtd_cb **irvtd = NULL;
-
-static char *revision_date = "Wed May 26 00:49:11 1999";
-
-
-/*
- * prototypes
- */
-
-int irvtd_open(struct tty_struct *tty, struct file *filp);
-void irvtd_close(struct tty_struct * tty, struct file * filp);
-int irvtd_write(struct tty_struct * tty, int from_user,
-			const unsigned char *buf, int count);
-void irvtd_put_char(struct tty_struct *tty, unsigned char ch);
-int irvtd_write_room(struct tty_struct *tty);
-int irvtd_chars_in_buffer(struct tty_struct *tty);
-int irvtd_ioctl(struct tty_struct *tty, struct file * file,
-	     unsigned int cmd, unsigned long arg);
-void irvtd_set_termios(struct tty_struct *tty, struct termios * old);
-void irvtd_throttle(struct tty_struct *tty);
-void irvtd_unthrottle(struct tty_struct *tty);
-void irvtd_stop(struct tty_struct *tty);
-void irvtd_start(struct tty_struct *tty);
-void irvtd_hangup(struct tty_struct *tty);
-void irvtd_flush_buffer(struct tty_struct *tty);
-void irvtd_flush_chars(struct tty_struct *tty);
-
-static void change_speed(struct irvtd_cb *driver);
-static void irvtd_write_to_tty( struct irvtd_cb *);
-static void irvtd_send_data_request( struct irvtd_cb *);
-static void irvtd_break(struct tty_struct *tty, int break_state);
-static void irvtd_send_xchar(struct tty_struct *tty, char ch);
-static void irvtd_wait_until_sent(struct tty_struct *tty, int timeout);
-
-static void irvtd_start_tx_timer( struct irvtd_cb *driver, int timeout);
-static void irvtd_tx_timer_expired(unsigned long data);
-static void irvtd_start_rx_timer( struct irvtd_cb *driver, int timeout);
-static void irvtd_rx_timer_expired(unsigned long data);
-
-static int line_info(char *buf, struct irvtd_cb *driver);
-static int irvtd_read_proc(char *buf, char **start, off_t offset, int len,
-			   int *eof, void *unused);
-
-
-/*
- **********************************************************************
- *
- * ircomm_receive_data() and friends
- *
- * like interrupt handler in the serial.c,we receive data when 
- * ircomm_data_indication comes
- *
- **********************************************************************
- */
-
-
-
-/* 
- * irvtd_write_to_tty
- * send incoming/queued data to tty
- */
-
-static void irvtd_write_to_tty( struct irvtd_cb *driver)
-{	
-	int status, c, flag;
-	struct sk_buff *skb;
-	struct tty_struct *tty = driver->tty;
-	
-	if(driver->rx_disable)
-		return;
-
- 	skb = skb_dequeue(&driver->rxbuff);
-	if(skb == NULL)
-		return; /* there's nothing */
-
-	/* 
-	 * we should parse controlchannel field here. 
-	 * (see process_data() in ircomm.c)
-	 */
-	ircomm_parse_tuples(driver->comm, skb, CONTROL_CHANNEL);
-	
-#ifdef IRVTD_DEBUG_RX
-	printk("received data:");
-	{
-		int i;
-		for ( i=0;i<skb->len;i++)
-			printk("%02x ", skb->data[i]);
-		printk("\n");
-	}
-#endif
-	
-	status = driver->comm->peer_line_status & driver->read_status_mask;
-	
-	/* 
-	 * if there are too many errors which make a character ignored,
-	 * drop characters
-	 */
-
-	if(status & driver->ignore_status_mask){
-		DEBUG(0,__FUNCTION__":some error:ignore characters.\n");
-		dev_kfree_skb(skb);
-		return;
-	}
-	
-	c = MIN(skb->len, (TTY_FLIPBUF_SIZE - tty->flip.count));
-	DEBUG(4, __FUNCTION__"skb_len=%d, tty->flip.count=%d \n"
-	      ,(int)skb->len, tty->flip.count);
-	
-	if (driver->comm->peer_break_signal ) {
-		driver->comm->peer_break_signal = 0;
-		DEBUG(0,"handling break....\n");
-		
-		flag = TTY_BREAK;
-		if (driver->flags & ASYNC_SAK)
-			/*
-			 * do_SAK() seems to be an implementation of the 
-			 * idea called "Secure Attention Key",
-			 * which seems to be discribed in "Orange book".
-			 * (which is published by U.S.military!!?? ,
-			 * see source of do_SAK())
-			 *
-			 * but what kind of security do we need 
-			 * when we use infrared communication??? :p)
-			 */
-			do_SAK(tty);
-	}else if (status & LSR_PE)
-		flag = TTY_PARITY;
-	else if (status & LSR_FE)
-		flag = TTY_FRAME;
-	else if (status & LSR_OE)
-		flag = TTY_OVERRUN;
-	else 
-		flag = TTY_NORMAL;
-	
-	if(c){
-		DEBUG(4,"writing %d chars to tty\n",c);
-		driver->icount.rx += c;
-		memset(tty->flip.flag_buf_ptr, flag, c);
-		memcpy(tty->flip.char_buf_ptr, skb->data, c);
-		tty->flip.flag_buf_ptr += c;
-		tty->flip.char_buf_ptr += c;
-		tty->flip.count += c;
-		skb_pull(skb,c);
-	}
-
-	if(skb->len == 0)
-		dev_kfree_skb(skb);
-	else
-	{
-		/* queue rest of data again */
-		DEBUG(4,__FUNCTION__":retrying frame!\n");
-
-		/* build a dummy control channel */
-		skb_push(skb,1);
-		*skb->data = 0;  /* clen is 0 */
-		skb_queue_head( &driver->rxbuff, skb );
-	}
-	
-	if(c)
-	/* let the process read its buffer! */
-		tty_flip_buffer_push(tty);
-	
-	if(skb_queue_len(&driver->rxbuff)< IRVTD_RX_QUEUE_LOW &&
-	   driver->ttp_stoprx){
-		DEBUG(1, __FUNCTION__"():FLOW_START\n");
-		/* 
-		 * next 2 lines must follow this order since irttp_flow_request()
-		 * will run its rx queue
-		 */
-		driver->ttp_stoprx = 0;
-		irttp_flow_request(driver->comm->tsap, FLOW_START);
-	}
-
-	if(skb_queue_empty(&driver->rxbuff) && driver->disconnect_pend){
-		/* disconnect */
-		driver->disconnect_pend = 0;
-		driver->rx_disable = 1;
-		tty_hangup(driver->tty);
-	}
-}
-
-static int irvtd_receive_data(void *instance, void *sap, struct sk_buff *skb)
-{	
-	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
-
-	ASSERT(driver != NULL, return -1;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return -1;);
-	DEBUG(4, __FUNCTION__"(): queue frame\n");
-
-	/* queue incoming data and make bottom half handler ready */
-
-	skb_queue_tail( &driver->rxbuff, skb );
-
-	if(skb_queue_len(&driver->rxbuff) > IRVTD_RX_QUEUE_HIGH){
-		DEBUG(1, __FUNCTION__"():FLOW_STOP\n");
-		irttp_flow_request(driver->comm->tsap, FLOW_STOP);
-		driver->ttp_stoprx = 1;
-	}
-	irvtd_write_to_tty(driver);
-
-	if(!skb_queue_empty(&driver->rxbuff))
-		irvtd_start_rx_timer(driver,0);
-	return 0;
-}
-
-/*
- ***********************************************************************
- *
- * irvtd_send_data() and friends
- *
- * like interrupt handler in the serial.c,we send data when 
- * a timer is expired
- *
- ***********************************************************************
- */
-
-
-static void irvtd_start_tx_timer( struct irvtd_cb *driver, int timeout)
-{
-	ASSERT( driver != NULL, return;);
-	ASSERT( driver->magic == IRVTD_MAGIC, return;);
-
-	del_timer( &driver->tx_timer);
-	
-	driver->tx_timer.data     = (unsigned long) driver;
-	driver->tx_timer.function = &irvtd_tx_timer_expired;
-	driver->tx_timer.expires  = jiffies + timeout;
-	
-	add_timer( &driver->tx_timer);
-}
-
-static void irvtd_start_rx_timer( struct irvtd_cb *driver, int timeout)
-{
-	ASSERT( driver != NULL, return;);
-	ASSERT( driver->magic == IRVTD_MAGIC, return;);
-
-	del_timer( &driver->rx_timer);
-	
-	driver->rx_timer.data     = (unsigned long) driver;
-	driver->rx_timer.function = &irvtd_rx_timer_expired;
-	driver->rx_timer.expires  = jiffies + timeout;
-	
-	add_timer( &driver->rx_timer);
-}
-
-
-static void irvtd_tx_timer_expired(unsigned long data)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)data;
-
-	ASSERT(driver != NULL,return;);
-	ASSERT(driver->magic == IRVTD_MAGIC,return;);
-	DEBUG(4, __FUNCTION__"()\n");
-
-	irvtd_send_data_request(driver);
-}
-
-static void irvtd_rx_timer_expired(unsigned long data)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)data;
-
-	ASSERT(driver != NULL,return;);
-	ASSERT(driver->magic == IRVTD_MAGIC,return;);
-	DEBUG(4, __FUNCTION__"()\n");
-
-	while(TTY_FLIPBUF_SIZE - driver->tty->flip.count
-	      && !skb_queue_empty(&driver->rxbuff))
-		irvtd_write_to_tty(driver);
-
-	DEBUG(1, __FUNCTION__"(): room in flip_buffer = %d\n",
-	      TTY_FLIPBUF_SIZE - driver->tty->flip.count);
-	
-	if(!skb_queue_empty(&driver->rxbuff))
-		/* handle it later */
-		irvtd_start_rx_timer(driver, 1);
-}
-
-
-static void irvtd_send_data_request(struct irvtd_cb *driver)
-{
-	int err;
-	struct sk_buff *skb = driver->txbuff;
-
-	ASSERT(skb != NULL,return;);
-	DEBUG(4, __FUNCTION__"()\n");
-
-	if(driver->tty->hw_stopped || driver->tx_disable)
-		return;
-	if(!skb->len)
-		return;   /* no data to send */
-
-#ifdef IRVTD_DEBUG_TX
-	DEBUG(4, "flush_txbuff:count(%d)\n",(int)skb->len);
-	{
-		int i;
-		for ( i=0;i<skb->len;i++)
-			printk("%02x", skb->data[i]);
-		printk("\n");
-	}
-#endif
-
-	DEBUG(1, __FUNCTION__"():len = %d, room = %d\n",(int)skb->len,
-	      skb_tailroom(skb));
-	driver->icount.tx += skb->len;
-	err = ircomm_data_request(driver->comm, driver->txbuff);
-	if (err){
-		ASSERT(err == 0,;);
-		DEBUG(1,"%d chars are lost\n",(int)skb->len);
-		skb_trim(skb, 0);
-	}
-
-	/* allocate a new frame */
-	skb = driver->txbuff 
-		= dev_alloc_skb(driver->tx_max_sdu_size + driver->max_header_size);
-	if (skb == NULL){
-		printk(__FUNCTION__"():alloc_skb failed!\n");
-	} else {
-		skb_reserve(skb, driver->max_header_size);
-	}
-
-	wake_up_interruptible(&driver->tty->write_wait);
-}
-
-
-/*
- ***********************************************************************
- *
- * indication/confirmation handlers:
- *
- * these routines are handlers for IrCOMM protocol stack
- *
- ***********************************************************************
- */
-
-/*
- * Function irvtd_connect_confirm (instance, sap, qos, max_sdu_size, skb)
- *
- *    ircomm_connect_request which we have send, has succeeded!
- *
- */
-void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos,
-			   __u32 max_sdu_size, __u8 max_header_size, 
-			   struct sk_buff *skb)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
-	ASSERT(driver != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-
-
-	driver->tx_max_sdu_size = max_sdu_size;
-	driver->max_header_size = max_header_size;
-	/*
-	 * set default value
-	 */
-	
-	driver->msr |= (MSR_DCD|MSR_RI|MSR_DSR|MSR_CTS);
-
-	/*
-	 * sending initial control parameters here
-	 */
-	if (driver->comm->servicetype ==	THREE_WIRE_RAW)
-		return;                /* do nothing */
-
-	driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS);
-
-	ircomm_control_request(driver->comm, SERVICETYPE);
-	ircomm_control_request(driver->comm, DATA_RATE);
-	ircomm_control_request(driver->comm, DATA_FORMAT);
-	ircomm_control_request(driver->comm, FLOW_CONTROL);
-	ircomm_control_request(driver->comm, XON_XOFF_CHAR);
-	/* ircomm_control_request(driver->comm, ENQ_ACK_CHAR); */
-
-	switch (driver->comm->servicetype) {
-	case CENTRONICS:
-		break;
-
-	case NINE_WIRE:
-		ircomm_control_request(driver->comm, DTELINE_STATE);
-		break;
-	default:
-	}
-	
-	driver->tx_disable = 0;
-	wake_up_interruptible(&driver->open_wait);
-}
-
-/*
- * Function irvtd_connect_indication (instance, sap, qos, max_sdu_size, skb)
- *
- *    we are discovered and being requested to connect by remote device !
- *
- */
-void irvtd_connect_indication(void *instance, void *sap, struct qos_info *qos,
-			      __u32 max_sdu_size, __u8 max_header_size, 
-			      struct sk_buff *skb)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
-	struct ircomm_cb *comm = (struct ircomm_cb *)sap;
-
-	ASSERT(driver != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-	ASSERT(comm != NULL, return;);
-	ASSERT(comm->magic == IRCOMM_MAGIC, return;);
-
-	driver->tx_max_sdu_size = max_sdu_size;
-	driver->max_header_size = max_header_size;
-	DEBUG(4, __FUNCTION__ "():sending connect_response...\n");
-
-	ircomm_connect_response(comm, NULL, SAR_DISABLE );
-
-	driver->tx_disable = 0;
-
-	/*
-	 * send initial control parameters
-	 */
-	if (driver->comm->servicetype == THREE_WIRE_RAW)
-		return;                /* do nothing */
-
-	driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS);
-
-	switch(driver->comm->servicetype){
-	case NINE_WIRE:
-		ircomm_control_request(driver->comm, DTELINE_STATE);
-		break;
-	default:
-		DEBUG(0, __FUNCTION__ "(), not implemented!\n");
-	}
-
-
-	driver->msr |= (MSR_DCD|MSR_RI|MSR_DSR|MSR_CTS);
-	wake_up_interruptible(&driver->open_wait);
-}
-
-/*
- * Function irvtd_disconnect_indication (instance, sap, reason, skb)
- *
- *    This is a handler for ircomm_disconnect_indication. since this
- *    function is called in the context of interrupt handler,
- *    interruptible_sleep_on() MUST not be used.
- */
-void irvtd_disconnect_indication(void *instance, void *sap , LM_REASON reason,
-				 struct sk_buff *skb)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
-
-	ASSERT(driver != NULL, return;);
-	ASSERT(driver->tty != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-
-	DEBUG(4,"irvtd_disconnect_indication:\n");
-
-	driver->tx_disable = 1;
-	if(skb_queue_empty(&driver->rxbuff)){
-		/* disconnect */
-		driver->rx_disable = 1;
-		tty_hangup(driver->tty);
-	} else {
-		driver->disconnect_pend = 1;
-	}
-}
-
-/*
- * Function irvtd_control_indication (instance, sap, cmd)
- *
- *    
- *
- */
-void irvtd_control_indication(void *instance, void *sap, IRCOMM_CMD cmd)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
-
-	ASSERT(driver != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-
-	DEBUG(4,__FUNCTION__"()\n");
-
-	if(cmd == TX_READY){
-		driver->ttp_stoptx = 0;
-		driver->tty->hw_stopped = driver->cts_stoptx;
-
-		if(driver->cts_stoptx)
-			return;
-
-		/* push tx queue so that client can send at least 1 octet */
-		irvtd_send_data_request(driver);
-		/* 
-		 * driver->tty->write_wait will keep asleep if
-		 * our txbuff is full.
-		 * now that we can send packets to IrTTP layer,
-		 * we kick it here.
-		 */
-		if ((driver->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && 
-		    driver->tty->ldisc.write_wakeup)
-			(driver->tty->ldisc.write_wakeup)(driver->tty);
-		return;
-	}
-
-	if(cmd == TX_BUSY){
-		driver->ttp_stoptx = driver->tty->hw_stopped = 1;
-		del_timer( &driver->tx_timer);
-		return;
-	}
-
-
-	ASSERT(cmd == CONTROL_CHANNEL,return;);
-
-	switch(driver->comm->pi){
-
-	case DCELINE_STATE:
-	driver->msr = driver->comm->peer_dce;
-
-	if(driver->msr & (DELTA_CTS|DELTA_DSR|DELTA_RI|DELTA_DCD)){
-		if(driver->msr & DELTA_CTS)
-			driver->icount.cts++;
-		if(driver->msr & DELTA_DSR)
-			driver->icount.dsr++;
-		if(driver->msr & DELTA_RI)
-			driver->icount.rng++;
-		if(driver->msr & DELTA_DCD)
-			driver->icount.dcd++;
-		wake_up_interruptible(&driver->delta_msr_wait);
-	}
-
-	if ((driver->flags & ASYNC_CHECK_CD) && (driver->msr & DELTA_DCD)) {
-
-		DEBUG(0,"CD now %s...\n",
-		      (driver->msr & MSR_DCD) ? "on" : "off");
-
-		if (driver->msr & MSR_DCD)
-		{
-			/* DCD raised! */
-			wake_up_interruptible(&driver->open_wait);
-		}
-		else
-		{
-			/* DCD falled */
-                        DEBUG(0,__FUNCTION__"():hangup..\n");
-			tty_hangup(driver->tty);
-		}
-
-	}
-
-	if (driver->comm->flow_ctrl & USE_CTS) {
-		if (driver->tty->hw_stopped) {
-			if (driver->msr & MSR_CTS) {
-				DEBUG(0,"CTS tx start...\n");
-
-				driver->cts_stoptx = 0;
-				driver->tty->hw_stopped = driver->ttp_stoptx;
-				/*  
-				 * replacement of 
-				 * rs_sched_event(info, RS_EVENT_WRITE_WAKEUP)
-				 * in serial.c
-				 */
-
-				if ((driver->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-				    driver->tty->ldisc.write_wakeup)
-					(driver->tty->ldisc.write_wakeup)(driver->tty);
-
-				wake_up_interruptible(&driver->tty->write_wait);
-				return;
-			}
-		} else {
-			if (!(driver->msr & MSR_CTS)) {
-				DEBUG(0,"CTS tx stop...");
-
-				driver->cts_stoptx = 1;
-				driver->tty->hw_stopped = 1;
-                        }
-                }
-        }
-	break;
-
-	case FLOW_CONTROL:
-	case DATA_RATE:
-	case XON_XOFF_CHAR:
-	case DTELINE_STATE:
-	case ENQ_ACK_CHAR:	/* got this from win95 */
-		/* (maybe) nothing to do  */
-		break;
-	default:
-		DEBUG(0,__FUNCTION__"():PI = 0x%02x is not implemented\n",
-		      (int)driver->comm->pi);
-	}
-}
-
-/*
- ***********************************************************************
- *
- * driver kernel interfaces
- * these functions work as an interface between the kernel and this driver
- *
- ***********************************************************************
- */
-
-
-
-/*
- * ----------------------------------------------------------------------
- * irvtd_open() and friends
- *
- * ----------------------------------------------------------------------
- */
-
-
-static int irvtd_block_til_ready(struct tty_struct *tty, struct file * filp,
-				 struct irvtd_cb *driver)
-{
-
- 	DECLARE_WAITQUEUE(wait,current);
-	int		retval = 0;
-	int		do_clocal = 0;
-
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
-	 * then make the check up front and then exit.
-	 */
-
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR))) {
-
-		return 0;
-	}
-
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = 1;
-
-
-	/*
-	 * We wait until ircomm_connect_request() succeed or
-	 *   ircomm_connect_indication comes
-	 */
-
-
-	add_wait_queue(&driver->open_wait, &wait);
-
-	DEBUG(0,__FUNCTION__"():before block( line = %d, count = %d )\n",
-	      driver->line, driver->count);
-
-	driver->blocked_open++;
-
-	/* wait for a connection established */
-	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
-		
-		if (tty_hung_up_p(filp) ||
-		    !(driver->flags & ASYNC_INITIALIZED)) {
-#ifdef DO_RESTART
-			if (driver->flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;	
-#else
-			retval = -EAGAIN;
-#endif
-			break;
-		}
-
-		if (!(driver->flags & ASYNC_CLOSING) &&
-		    (driver->comm->state == COMM_CONN) && 
-		    ( do_clocal || (driver->msr & MSR_DCD)))
-			break;
-
-		if(signal_pending(current)){
-			retval = -ERESTARTSYS;
-			break;
-		}
-
-
-		DEBUG(4,__FUNCTION__"():blocking( %s%d, count = %d )\n",
-		      tty->driver.name, driver->line, driver->count);
-
-		schedule();
-	}
-
-	current->state = TASK_RUNNING;
-	remove_wait_queue(&driver->open_wait, &wait);
-
-	driver->blocked_open--;
-
-	DEBUG(1, __FUNCTION__"():after blocking\n");
-
-	if (retval)
-		return retval;
-	return 0;
-}	
-
-static void change_speed(struct irvtd_cb *driver)
-{
-	unsigned cflag,cval;
-
-	if (!driver->tty || !driver->tty->termios || !driver->comm)
-		return;
-	cflag = driver->tty->termios->c_cflag;
-
-	/* 
-	 * byte size and parity
-	 */
-	switch (cflag & CSIZE) 
-	{
-	case CS5: cval = IRCOMM_WLEN5; break;
-	case CS6: cval = IRCOMM_WLEN6; break;
-	case CS7: cval = IRCOMM_WLEN7; break;
-	case CS8: cval = IRCOMM_WLEN8; break;
-	default:  cval = IRCOMM_WLEN5; break;	/* too keep GCC shut... */
-	}
-	if (cflag & CSTOPB) {      /* use 2 stop bit mode */
-		cval |= IRCOMM_STOP2;
-	}
-	if (cflag & PARENB)
-		cval |= IRCOMM_PARENB;    /* enable parity check */
-	if (!(cflag & PARODD))
-		cval |= IRCOMM_PAREVEN;         /* even parity */
-	
-	/* CTS flow control flag and modem status interrupts */
-
-	if (cflag & CRTSCTS)
-		driver->comm->flow_ctrl |= USE_CTS;
-	else
-		driver->comm->flow_ctrl |= ~USE_CTS;
-	
-	if (cflag & CLOCAL)
-		driver->flags &= ~ASYNC_CHECK_CD;
-	else
-		driver->flags |= ASYNC_CHECK_CD;
-	
-	/*
-	 * Set up parity check flag
-	 */
-
-	driver->read_status_mask = LSR_OE;
-	if (I_INPCK(driver->tty))
-		driver->read_status_mask |= LSR_FE | LSR_PE;
-	if (I_BRKINT(driver->tty) || I_PARMRK(driver->tty))
-		driver->read_status_mask |= LSR_BI;
-	
-	/*
-	 * Characters to ignore
-	 */
-	driver->ignore_status_mask = 0;
-	if (I_IGNPAR(driver->tty))
-		driver->ignore_status_mask |= LSR_PE | LSR_FE;
-
-	if (I_IGNBRK(driver->tty)) {
-		driver->ignore_status_mask |= LSR_BI;
-		/*
-		 * If we're ignore parity and break indicators, ignore 
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(driver->tty)) 
-			driver->ignore_status_mask |= LSR_OE;
-	}
-
-	driver->comm->data_format = cval;
-	ircomm_control_request(driver->comm, DATA_FORMAT);
- 	ircomm_control_request(driver->comm, FLOW_CONTROL);
-}
-
-
-
-
-static int irvtd_startup(struct irvtd_cb *driver)
-{
-	struct ias_object* obj;
-	struct notify_t irvtd_notify;
-
-	/* FIXME: it should not be hard coded */
-	__u8 oct_seq[6] = { 0,1,6,1,1,1 }; 
-
-	DEBUG(4,__FUNCTION__"()\n" );
-	if(driver->flags & ASYNC_INITIALIZED)
-		return 0;
-
-	/*
-	 * initialize our tx/rx buffer
-	 */
-
-	skb_queue_head_init(&driver->rxbuff);
-	driver->txbuff = dev_alloc_skb(COMM_DEFAULT_SDU_SIZE + COMM_MAX_HEADER_SIZE); 
-	if (!driver->txbuff){
-		DEBUG(0,__FUNCTION__"(), alloc_skb failed!\n");
-		return -ENOMEM;
-	}
-	skb_reserve(driver->txbuff, COMM_MAX_HEADER_SIZE);
-
-	irda_notify_init(&irvtd_notify);
-	irvtd_notify.data_indication = irvtd_receive_data;
-	irvtd_notify.connect_confirm = irvtd_connect_confirm;
-	irvtd_notify.connect_indication = irvtd_connect_indication;
-	irvtd_notify.disconnect_indication = irvtd_disconnect_indication;
-	irvtd_notify.flow_indication = irvtd_control_indication;
-	strncpy( irvtd_notify.name, "ircomm_tty", NOTIFY_MAX_NAME);
-	irvtd_notify.instance = driver;
-
-	driver->comm = ircomm_open_instance(irvtd_notify);
-	if (!driver->comm)
-		return -ENODEV;
-
-
-	/* 
-         *  Register with LM-IAS as a server
-         */
-
-	obj = irias_new_object( "IrDA:IrCOMM", IAS_IRCOMM_ID);
-	irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", 
-				  driver->comm->tsap->stsap_sel );
-
-	irias_add_octseq_attrib( obj, "Parameters", &oct_seq[0], 6);
-	irias_insert_object( obj);
-
-	driver->flags |= ASYNC_INITIALIZED;
-
-	if (driver->tty)
-		clear_bit(TTY_IO_ERROR, &driver->tty->flags);
-
-	change_speed(driver);
-
-	/*
-	 * discover a peer device
-	 */
-	if(driver->tty->termios->c_cflag & CRTSCTS)
-	  ircomm_connect_request(driver->comm, NINE_WIRE);
-	else
-	  ircomm_connect_request(driver->comm, THREE_WIRE);
-
-	/* irvtd_start_timer( driver); */
-
-	driver->rx_disable = 0;
-	driver->tx_disable = 1;
-	driver->disconnect_pend = 0;
-	return 0;
-}
-
-
-int irvtd_open(struct tty_struct * tty, struct file * filp)
-{
-	struct irvtd_cb *driver;
-	int retval;
-	int line;
-
-	DEBUG(4, __FUNCTION__"():\n");
-	MOD_INC_USE_COUNT;
-
-	line = MINOR(tty->device) - tty->driver.minor_start;
-	if ((line <0) || (line >= COMM_MAX_TTY)){
-		MOD_DEC_USE_COUNT;
-		return -ENODEV;
-	}
-
-	driver = irvtd[line];
-	ASSERT(driver != NULL, MOD_DEC_USE_COUNT;return -ENOMEM;);
-	ASSERT(driver->magic == IRVTD_MAGIC, MOD_DEC_USE_COUNT;return -EINVAL;);
-
-	driver->count++;
-
-	DEBUG(0, __FUNCTION__"():%s%d count %d\n", tty->driver.name, line, 
-	      driver->count);
-	
-	tty->driver_data = driver;
-	driver->tty = tty;
-
-	driver->tty->low_latency = (driver->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * (sleep) until it's done, then exit.
-	 */
-
-	if (tty_hung_up_p(filp) ||
-	    (driver->flags & ASYNC_CLOSING)) {
-		if (driver->flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&driver->close_wait);
-#ifdef DO_RESTART
-		if (driver->flags & ASYNC_HUP_NOTIFY)
-			return -EAGAIN;
-		else
-			return -ERESTARTSYS;
-#else
-		return -EAGAIN;
-#endif
-	}
-
-	/* 
-	 * start up discovering process and ircomm_layer 
-	 */
-	
-	retval = irvtd_startup(driver);
-	if (retval){
-		DEBUG(0, __FUNCTION__"():irvtd_startup returns %d\n",retval);
-		return retval;
-	}
-
-	retval = irvtd_block_til_ready(tty, filp, driver);
-	if (retval){
-		DEBUG(0,__FUNCTION__
-		      "():returning after block_til_ready (errno = %d)\n", retval);
-                return retval;
-	}
-
-	driver->session = current->session;
-	driver->pgrp = current->pgrp;
-	return 0;
-}
-
-
-
-
-
-/*
- * ----------------------------------------------------------------------
- * irvtd_close() and friends
- *
- * most of this function is stolen from serial.c
- * ----------------------------------------------------------------------
- */
-
-/*
- * Function irvtd_wait_until_sent (tty, timeout)
- *
- *    wait until Tx queue of IrTTP is empty 
- *
- */
-static void irvtd_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	unsigned long orig_jiffies;
-
-	ASSERT(driver != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-	ASSERT(driver->comm != NULL, return;);
-
-	DEBUG(1, __FUNCTION__"():\n");	
-	if(!tty->closing)
-		return;   /* nothing to do */
-	
-	/* 
-	 * at disconnection, we should wait until Tx queue of IrTTP is
-	 * flushed
-	 */
-
- 	ircomm_disconnect_request(driver->comm, NULL, P_NORMAL);
-	orig_jiffies = jiffies;
-
-	while (driver->comm->tsap->disconnect_pend) {
-		DEBUG(1, __FUNCTION__"():wait..\n");
-		current->state = TASK_INTERRUPTIBLE;
-		current->counter = 0;	/* make us low-priority */
-		schedule_timeout(HZ);    /* 1sec */
-		if (signal_pending(current))
-			break;
-		if (timeout && time_after(jiffies, orig_jiffies + timeout))
-			break;
-	}
-	current->state = TASK_RUNNING;
-}
-
-
-static void irvtd_shutdown(struct irvtd_cb * driver)
-{
-	unsigned long	flags;
-
-	if (!(driver->flags & ASYNC_INITIALIZED))
-		return;
-
-	DEBUG(1,__FUNCTION__"()\n");
-
-	/*
-	 * This comment is written in serial.c:
-	 *
-	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
-	 * here so the queue might never be waken up
-	 */
- 	wake_up_interruptible(&driver->delta_msr_wait);
-	
-	/* clear DTR and RTS */
-	if (!driver->tty || (driver->tty->termios->c_cflag & HUPCL))
- 		driver->mcr &= ~(MCR_DTR|MCR_RTS);
-
-	driver->comm->dte = driver->mcr;
-	ircomm_control_request(driver->comm, DTELINE_STATE );
-
-
-
-	save_flags(flags); cli(); /* Disable interrupts */
-
-	if (driver->tty)
-		set_bit(TTY_IO_ERROR, &driver->tty->flags);
-	
-	del_timer( &driver->tx_timer);
-	del_timer( &driver->rx_timer);
-
-	irias_delete_object("IrDA:IrCOMM");
-
-	/*
-	 * Free the transmit buffer here 
-	 */
-
-	while(skb_queue_len(&driver->rxbuff)){
-		struct sk_buff *skb;
-		skb = skb_dequeue( &driver->rxbuff);
-		dev_kfree_skb(skb);
-	}
-	if(driver->txbuff){
-		dev_kfree_skb(driver->txbuff);
-		driver->txbuff = NULL;
-	}
-	ircomm_close_instance(driver->comm);
-	driver->comm = NULL;
-	driver->flags &= ~ASYNC_INITIALIZED;
-	restore_flags(flags);
-}
-
-void irvtd_close(struct tty_struct * tty, struct file * filp)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	int line;
-	unsigned long flags;
-
-	DEBUG(1, __FUNCTION__"():refcount= %d\n",irvtd_refcount);
-
-	ASSERT(driver != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-
-	save_flags(flags);cli();
-
-
-	if(tty_hung_up_p(filp)){
-		/*
-		 * upper tty layer caught a HUP signal and called irvtd_hangup()
-		 * before. so we do nothing here.
-		 */
-		DEBUG(1, __FUNCTION__"():tty_hung_up_p.\n");
-		MOD_DEC_USE_COUNT;
-		restore_flags(flags);
-		return;
-	}
-	
-
-	line = MINOR(tty->device) - tty->driver.minor_start;
-	DEBUG(0, __FUNCTION__"():%s%d count %d\n", tty->driver.name, line, 
-	      driver->count);
-
-	if ((tty->count == 1) && (driver->count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  Driver->count should always
-		 * be one in these conditions.  If it's greater than
-		 * one, we've got real problems, since it means the
-		 * ircomm service layer won't be shutdown.
-		 */
-		printk(KERN_ERR"irvtd_close: bad serial port count;" 
-		       "tty->count is 1, but driver->count is %d\n", driver->count);
-		driver->count = 1;
-	}
-	if (--driver->count < 0) {
-		printk(KERN_ERR"irvtd_close: bad count for line%d: %d\n",
-		       line, driver->count);
-		driver->count = 0;
-	}
-
-	if (driver->count) { 	/* do nothing */
-		DEBUG(0, __FUNCTION__"():driver->count is not 0\n");
-		MOD_DEC_USE_COUNT;
-		restore_flags(flags);
-		return; 
-	}
-
-	driver->flags |= ASYNC_CLOSING;
-	
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify 
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	if (driver->closing_wait != ASYNC_CLOSING_WAIT_NONE){
-		DEBUG(4, __FUNCTION__"():calling tty_wait_until_sent()\n");
-		tty_wait_until_sent(tty, driver->closing_wait);
-	}
-	/* 
-	 * we can send disconnect_request with P_HIGH since
-	 * tty_wait_until_sent() and irvtd_wait_until_sent() should
-	 * have disconnected the link
-	 */
-	ircomm_disconnect_request(driver->comm, NULL, P_HIGH);
-	
-	/* 
-	 * Now we stop accepting input.
-	 */
-
-	driver->rx_disable = TRUE;
-	/* drop ldisc's buffer */
-	if (tty->ldisc.flush_buffer)
-		tty->ldisc.flush_buffer(tty);
-
- 	if (tty->driver.flush_buffer) 
- 		tty->driver.flush_buffer(driver->tty);  
-
-	tty->closing = 0;
-	driver->tty = NULL;
-
-	if (driver->blocked_open)
-	{
-		if (driver->close_delay) {
-			/* kill time */
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(driver->close_delay);
-		}
-		wake_up_interruptible(&driver->open_wait);
-	}
-	irvtd_shutdown(driver);
-	driver->flags &= ~ASYNC_CLOSING;
-        wake_up_interruptible(&driver->close_wait); 
-
-	MOD_DEC_USE_COUNT;
-        restore_flags(flags);
-	DEBUG(4, __FUNCTION__"():done\n");
-}
-
-/*
- * ----------------------------------------------------------------------
- * irvtd_write() and friends
- * This routine will be called when something data are passed from
- * kernel or user.
- * ----------------------------------------------------------------------
- */
-
-int irvtd_write(struct tty_struct * tty, int from_user,
-		const unsigned char *buf, int count)
-{
-	struct irvtd_cb *driver;
-	int c = 0;
-	int wrote = 0;
- 	unsigned long flags;
-	struct sk_buff *skb;
-	__u8 *frame;
-
-	ASSERT(tty != NULL, return -EFAULT;);
-	driver = (struct irvtd_cb *)tty->driver_data;
-	ASSERT(driver != NULL, return -EFAULT;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return -EFAULT;);
-
-	DEBUG(4, __FUNCTION__"()\n");
-
-	save_flags(flags);
-	while(count > 0){
-		cli();
-		skb = driver->txbuff;
-		ASSERT(skb != NULL, break;);
-		c = MIN(count, (skb_tailroom(skb)));
-		if (c <= 0)
-		{
-			if(!driver->ttp_stoptx)
-			{
-				irvtd_send_data_request(driver);
-				continue;
-			}
-			else
-				break;
-		}
-
-		/* write to the frame */
-
-		frame = skb_put(skb,c);
-		if(from_user){
-			copy_from_user(frame,buf,c);
-		} else
-			memcpy(frame, buf, c);
-
-		restore_flags(flags);
-		wrote += c;
-		count -= c;
-		buf += c;
-	}
-	restore_flags(flags);
-	irvtd_send_data_request(driver);
-	return (wrote);
-}
-
-void irvtd_flush_chars(struct tty_struct *tty)
-{
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	ASSERT( driver != NULL, return;);
-	ASSERT( driver->magic == IRVTD_MAGIC, return;);
-
-	DEBUG(4, __FUNCTION__"()\n");
-	irvtd_send_data_request(driver);
-}
-
-
-/*
- * Function irvtd_put_char (tty, ch)
- *
- *    This routine is called by the kernel to pass a single character.
- *    If we exausted our buffer,we can ignore the character!
- *
- */
-void irvtd_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	__u8 *frame ;
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	ASSERT(driver != NULL, return;);
-	DEBUG(4, __FUNCTION__"()\n");
-
-
- again:
-	save_flags(flags);cli();
-	skb = driver->txbuff;
-	ASSERT(skb != NULL,return;);
-	if(!skb_tailroom(skb))
-	{
-		restore_flags(flags);
-		irvtd_send_data_request(driver);
-		goto again;
-	}
-	ASSERT(skb_tailroom(skb) > 0, return;);
-	DEBUG(4, "irvtd_put_char(0x%02x) skb_len(%d) room(%d):\n",
-	      (int)ch ,(int)skb->len,
-	      skb_tailroom(skb));
-
-	/* append a character  */
-	frame = skb_put(skb,1);
-	frame[0] = ch;
-
-	restore_flags(flags);
-	irvtd_start_tx_timer(driver,20);
-	return;
-}
-
-/*
- * Function irvtd_write_room (tty)
- *
- *    This routine returns the room that our buffer has now.
- *
- */
-int irvtd_write_room(struct tty_struct *tty){
-
-	int ret;
-	struct sk_buff *skb = ((struct irvtd_cb *) tty->driver_data)->txbuff;
-
-	ASSERT(skb !=NULL, return 0;);
-
-	ret = skb_tailroom(skb);
-
-	DEBUG(4, __FUNCTION__"(): room is %d bytes\n",ret);
-
-	return(ret);
-}
-
-/*
- * Function irvtd_chars_in_buffer (tty)
- *
- *    This function returns how many characters which have not been sent yet 
- *    are still in buffer.
- *
- */
-int irvtd_chars_in_buffer(struct tty_struct *tty){
-
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	DEBUG(4, __FUNCTION__"()\n");
-
-	save_flags(flags);cli();
-	skb = ((struct irvtd_cb *) tty->driver_data)->txbuff;
-	if(skb == NULL) goto err;
-
-	restore_flags(flags);
-	return (skb->len );
-err:	
-	ASSERT(skb != NULL, ;);
-	restore_flags(flags);
-	return 0;   /* why not -EFAULT or such? see driver/char/serial.c */
-}
-
-/*
- * Function irvtd_break (tty, break_state)
- *
- *    Routine which turns the break handling on or off
- *
- */
-static void irvtd_break(struct tty_struct *tty, int break_state){
-	
- 	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	unsigned long flags;
-
-	DEBUG(0, __FUNCTION__"()\n");
-	ASSERT(tty->driver_data != NULL, return;);
-	ASSERT(driver->magic == IRVTD_MAGIC, return;);
-	
-	save_flags(flags);cli();
-	if (break_state == -1)
-	{
-		driver->comm->break_signal = 0x01;
-		ircomm_control_request(driver->comm, BREAK_SIGNAL);
-
-	}
-	else
-	{
-		driver->comm->break_signal = 0x00;
-		ircomm_control_request(driver->comm, BREAK_SIGNAL);
-
-	}
-
-	restore_flags(flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- * irvtd_ioctl() and friends
- * This routine allows us to implement device-specific ioctl's.
- * If passed ioctl number (i.e.cmd) is unknown one, we should return 
- * ENOIOCTLCMD.
- *
- * TODO: we can't use setserial on IrCOMM because some ioctls are not implemented.
- * we should add some ioctls and make some tool which is resemble to setserial.
- * ----------------------------------------------------------------------
- */
-
-static int get_modem_info(struct irvtd_cb * driver, unsigned int *value)
-{
-	unsigned int result;
-	result =  ((driver->mcr & MCR_RTS) ? TIOCM_RTS : 0)
-		| ((driver->mcr & MCR_DTR) ? TIOCM_DTR : 0)
-		| ((driver->msr & DELTA_DCD) ? TIOCM_CAR : 0)
-		| ((driver->msr & DELTA_RI) ? TIOCM_RNG : 0)
-		| ((driver->msr & DELTA_DSR) ? TIOCM_DSR : 0)
-		| ((driver->msr & DELTA_CTS) ? TIOCM_CTS : 0);
-	return put_user(result,value);
-}
-
-static int set_modem_info(struct irvtd_cb * driver, unsigned int cmd,
-			  unsigned int *value)
-{ 
-	int error;
-	unsigned int arg;
-
-	error = get_user(arg, value);
-	if(error)
-		return error;
-
-	switch (cmd) {
-	case TIOCMBIS: 
-		if (arg & TIOCM_RTS) 
-			driver->mcr |= MCR_RTS;
-		if (arg & TIOCM_DTR)
-			driver->mcr |= MCR_DTR;
-		break;
-		
-	case TIOCMBIC:
-		if (arg & TIOCM_RTS)
-			driver->mcr &= ~MCR_RTS;
-		if (arg & TIOCM_DTR)
- 			driver->mcr &= ~MCR_DTR;
- 		break;
-		
-	case TIOCMSET:
- 		driver->mcr = ((driver->mcr & ~(MCR_RTS | MCR_DTR))
-			       | ((arg & TIOCM_RTS) ? MCR_RTS : 0)
-			       | ((arg & TIOCM_DTR) ? MCR_DTR : 0));
-		break;
-		
-	default:
-		return -EINVAL;
-	}
-	
-	driver->comm->dte = driver->mcr;
-	ircomm_control_request(driver->comm, DTELINE_STATE );
-
-	return 0;
-}
-
-static int get_serial_info(struct irvtd_cb * driver,
-			   struct serial_struct * retinfo)
-{
-	struct serial_struct tmp;
-   
-	if (!retinfo)
-		return -EFAULT;
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.line = driver->line;
-	tmp.flags = driver->flags;
-	tmp.baud_base = driver->comm->data_rate;
-	tmp.close_delay = driver->close_delay;
-	tmp.closing_wait = driver->closing_wait;
-
-	/* for compatibility  */
-
- 	tmp.type = PORT_16550A;
- 	tmp.port = 0;
- 	tmp.irq = 0;
-	tmp.xmit_fifo_size = 0;
-	tmp.hub6 = 0;   
-	tmp.custom_divisor = driver->custom_divisor;
-
-	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_serial_info(struct irvtd_cb * driver,
-			   struct serial_struct * new_info)
-{
-	struct serial_struct new_serial;
-	struct irvtd_cb old_driver;
-
-	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
-		return -EFAULT;
-
-	old_driver = *driver;
-  
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((new_serial.baud_base != driver->comm->data_rate) ||
-		    (new_serial.close_delay != driver->close_delay) ||
-		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
-		     (driver->flags & ~ASYNC_USR_MASK)))
-			return -EPERM;
-		driver->flags = ((driver->flags & ~ASYNC_USR_MASK) |
-				 (new_serial.flags & ASYNC_USR_MASK));
-		driver->custom_divisor = new_serial.custom_divisor;
-		goto check_and_exit;
-	}
-
-	/*
-	 * OK, past this point, all the error checking has been done.
-	 * At this point, we start making changes.....
-	 */
-
-	if(driver->comm->data_rate != new_serial.baud_base){
-		driver->comm->data_rate = new_serial.baud_base;
-		if(driver->comm->state == COMM_CONN)
-			ircomm_control_request(driver->comm,DATA_RATE);
-	}
-	driver->close_delay = new_serial.close_delay * HZ/100;
-	driver->closing_wait = new_serial.closing_wait * HZ/100;
-	driver->custom_divisor = new_serial.custom_divisor;
-
-	driver->flags = ((driver->flags & ~ASYNC_FLAGS) |
-			 (new_serial.flags & ASYNC_FLAGS));
-	driver->tty->low_latency = (driver->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
- check_and_exit:
-	if (driver->flags & ASYNC_INITIALIZED) {
-		if (((old_driver.flags & ASYNC_SPD_MASK) !=
-		     (driver->flags & ASYNC_SPD_MASK)) ||
-		    (old_driver.custom_divisor != driver->custom_divisor)) {
-			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-				driver->tty->alt_speed = 57600;
-			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-				driver->tty->alt_speed = 115200;
-			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-				driver->tty->alt_speed = 230400;
-			if ((driver->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-				driver->tty->alt_speed = 460800;
-			change_speed(driver);
-		}
-	}
-	return 0;
-}
-
-
-
-
-int irvtd_ioctl(struct tty_struct *tty, struct file * file,
-		unsigned int cmd, unsigned long arg)
-{
-	int error;
-	unsigned long flags;
- 	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-
-	struct serial_icounter_struct cnow,cprev;
-	struct serial_icounter_struct *p_cuser;	/* user space */
-
-
-	DEBUG(4,"irvtd_ioctl:requested ioctl(0x%08x)\n",cmd);
-
-#ifdef IRVTD_DEBUG_IOCTL
-	{
-		/* kill time so that debug messages will come slowly  */
-		save_flags(flags);cli();
-		current->state = TASK_INTERRUPTIBLE;
-		current->timeout = jiffies + HZ/4; /*0.25sec*/
-		schedule();
-		restore_flags(flags);
-	}
-#endif
-
-
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR)){
-			return -EIO;
-		}
-	}
-	
-	switch (cmd) {
-
-	case TIOCMGET:
-		return get_modem_info(driver, (unsigned int *) arg);
-
-	case TIOCMBIS:
-	case TIOCMBIC:
-	case TIOCMSET:
-		return set_modem_info(driver, cmd, (unsigned int *) arg);
-	case TIOCGSERIAL:
-		return get_serial_info(driver, (struct serial_struct *) arg);
-	case TIOCSSERIAL:
-		return set_serial_info(driver, (struct serial_struct *) arg);
-
-
-	case TIOCMIWAIT:
-		save_flags(flags); cli();
-		/* note the counters on entry */
-		cprev = driver->icount;
-		restore_flags(flags);
-		while (1) {
-			interruptible_sleep_on(&driver->delta_msr_wait);
-				/* see if a signal did it */
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-			save_flags(flags); cli();
-			cnow = driver->icount; /* atomic copy */
-			restore_flags(flags);
-			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 
-			    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-				return -EIO; /* no change => error */
-			if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-			     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-			     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-			     ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
-				return 0;
-			}
-			cprev = cnow;
-		}
-		/* NOTREACHED */
-
-	case TIOCGICOUNT:
-		save_flags(flags); cli();
-		cnow = driver->icount;
-		restore_flags(flags);
-		p_cuser = (struct serial_icounter_struct *) arg;
-		error = put_user(cnow.cts, &p_cuser->cts);
-		if (error) return error;
-		error = put_user(cnow.dsr, &p_cuser->dsr);
-		if (error) return error;
-		error = put_user(cnow.rng, &p_cuser->rng);
-		if (error) return error;
-		error = put_user(cnow.dcd, &p_cuser->dcd);
-		if (error) return error;
-		error = put_user(cnow.rx, &p_cuser->rx);
-		if (error) return error;
-		error = put_user(cnow.tx, &p_cuser->tx);
-		if (error) return error;
-		error = put_user(cnow.frame, &p_cuser->frame);
-		if (error) return error;
-		error = put_user(cnow.overrun, &p_cuser->overrun);
-		if (error) return error;
-		error = put_user(cnow.parity, &p_cuser->parity);
-		if (error) return error;
-		error = put_user(cnow.brk, &p_cuser->brk);
-		if (error) return error;
-		error = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
-		if (error) return error;			
-		return 0;
-		
-		
-		/* ioctls which are imcompatible with serial.c */
-
-	case TIOCSERGSTRUCT:
-		DEBUG(0,__FUNCTION__"():sorry, TIOCSERGSTRUCT is not supported\n");
-		return -ENOIOCTLCMD;  
-	case TIOCSERGETLSR:
-		DEBUG(0,__FUNCTION__"():sorry, TIOCSERGETLSR is not supported\n");
-		return -ENOIOCTLCMD;  
- 	case TIOCSERCONFIG:
-		DEBUG(0,__FUNCTION__"():sorry, TIOCSERCONFIG is not supported\n");
-		return -ENOIOCTLCMD;  
-
-
-	default:
-		return -ENOIOCTLCMD;  /* ioctls which we must ignore */
-	}
-	return 0;
-}
-
-
-
-/*
- * ----------------------------------------------------------------------
- * irvtd_set_termios()
- * This is called when termios is changed.
- * If things that changed is significant for us,(i.e. changing baud rate etc.)
- * send something to peer device.
- * ----------------------------------------------------------------------
- */
-
-void irvtd_set_termios(struct tty_struct *tty, struct termios * old_termios){
-
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-
-	ASSERT(driver != NULL,return;);
-	ASSERT(driver->magic == IRVTD_MAGIC ,return;);
-
-	DEBUG(0, "irvtd_set_termios:\n");
-	return;
-
-	if((tty->termios->c_cflag == old_termios->c_cflag) &&
-	   (RELEVANT_IFLAG(tty->termios->c_iflag) 
-	    == RELEVANT_IFLAG(old_termios->c_iflag)))
-		return;
-
-	change_speed(driver);
-
-	if((old_termios->c_cflag & CRTSCTS) &&
-	   !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = driver->ttp_stoptx;
-		/* irvtd_start(tty); */       /* we don't need this */
-	}
-}
-
-/*
- * ----------------------------------------------------------------------
- * irvtd_throttle,irvtd_unthrottle
- *   These routines will be called when we have to pause sending up data to tty.
- *   We use RTS virtual signal when servicetype is NINE_WIRE
- * ----------------------------------------------------------------------
- */
-
-static void irvtd_send_xchar(struct tty_struct *tty, char ch){
-
-	DEBUG(1, __FUNCTION__"():\n");
-	irvtd_put_char(tty, ch);
-}
-
-void irvtd_throttle(struct tty_struct *tty){
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-
-	DEBUG(1, "irvtd_throttle:\n");
-
-	if (I_IXOFF(tty))
-		irvtd_put_char(tty, STOP_CHAR(tty));
-
-	driver->mcr &= ~MCR_RTS; 
-	driver->mcr |= DELTA_RTS; 
-	driver->comm->dte = driver->mcr;
-	ircomm_control_request(driver->comm, DTELINE_STATE );
-
-	DEBUG(1, __FUNCTION__"():FLOW_STOP\n");
-        irttp_flow_request(driver->comm->tsap, FLOW_STOP);
-}
-
-void irvtd_unthrottle(struct tty_struct *tty){
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	DEBUG(1, "irvtd_unthrottle:\n");
-
-	if (I_IXOFF(tty))
-		irvtd_put_char(tty, START_CHAR(tty));
-
-	driver->mcr |= (MCR_RTS|DELTA_RTS);
-	driver->comm->dte = driver->mcr;
-	ircomm_control_request(driver->comm, DTELINE_STATE );
-
-	DEBUG(1, __FUNCTION__"():FLOW_START\n");
-        irttp_flow_request(driver->comm->tsap, FLOW_START);
-}
-
-
-/*
- * ------------------------------------------------------------
- * irvtd_stop() and irvtd_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable an interrupt which means "transmitter-is-ready"
- * in serial.c, but  I think these routine are not necessary for us. 
- * ------------------------------------------------------------
- */
-
-#if 0
-irvtd_stop(struct tty_struct *tty){
- 	DEBUG(0, "irvtd_stop()\n");
-
-	struct irvtd_cb *info = (struct irvtd_cb *)tty->driver_data; 
-	DEBUG(0, "irvtd_start():not implemented!\n");
-}
-irvtd_start(struct tty_struct *tty){
-
-	struct irvtd_cb *info = (struct irvtd_cb *)tty->driver_data;
-	DEBUG(0, "irvtd_start():not_implemented!\n");
-}
-#endif
-
-/*
- * ------------------------------------------------------------
- * irvtd_hangup()
- * This routine notifies that tty layer have got HUP signal
- * ------------------------------------------------------------
- */
-
-void irvtd_hangup(struct tty_struct *tty){
-
-	struct irvtd_cb *info = (struct irvtd_cb *)tty->driver_data;
-	DEBUG(0, __FUNCTION__"()\n");
-
-	irvtd_flush_buffer(tty);
-	irvtd_shutdown(info);
-	info->count = 0;
-	info->tty = NULL;
-	wake_up_interruptible(&info->open_wait);
-}
-
-void irvtd_flush_buffer(struct tty_struct *tty){
-
-	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
-	struct sk_buff *skb;
-
-	skb = driver->txbuff;
-	ASSERT(skb != NULL, return;); 
-
-	if(skb->len){
-		DEBUG(0, __FUNCTION__"():%d chars in txbuff are lost..\n",(int)skb->len);
-		skb_trim(skb,0); 
-	}
-	
-	/* write_wait is a wait queue of tty_wait_until_sent().
-	 * see tty_io.c of kernel 
-	 */
-	wake_up_interruptible(&tty->write_wait); 
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-}
-
-
-
-/*
- * Function ircomm_register_device(void), init_module() and friends
- *
- *   we register "port emulation entity"(see IrCOMM specification) here
- *   as a tty device.
- */
-
-int irvtd_register_ttydriver(void){
-
-        DEBUG( 4, "-->irvtd_register_ttydriver\n");
-
-	/* setup virtual serial port device */
-
-        /* Initialize the tty_driver structure ,which is defined in 
-	   tty_driver.h */
-        
-        memset(&irvtd_drv, 0, sizeof(struct tty_driver));
-	irvtd_drv.magic = IRVTD_MAGIC;
-	irvtd_drv.driver_name = "IrCOMM_tty";
-	irvtd_drv.name = "irnine";
-	irvtd_drv.major = IRCOMM_MAJOR;
-	irvtd_drv.minor_start = IRVTD_MINOR;
-	irvtd_drv.num = COMM_MAX_TTY;
-	irvtd_drv.type = TTY_DRIVER_TYPE_SERIAL;  /* see tty_driver.h */
-
-
-	/*
-	 * see drivers/char/tty_io.c and termios(3)
-	 */
-
-        irvtd_drv.init_termios = tty_std_termios;
-        irvtd_drv.init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-        irvtd_drv.flags = TTY_DRIVER_REAL_RAW;   /* see tty_driver.h */
-        irvtd_drv.refcount = &irvtd_refcount;
-
-	/* pointer to the tty data structures */
-
-        irvtd_drv.table = irvtd_table;  
-        irvtd_drv.termios = irvtd_termios;
-        irvtd_drv.termios_locked = irvtd_termios_locked;
-
-        /*
-         * Interface table from the kernel(tty driver) to the ircomm
-         * layer
-         */
-
-        irvtd_drv.open = irvtd_open;
-        irvtd_drv.close = irvtd_close;
-        irvtd_drv.write = irvtd_write;
-        irvtd_drv.put_char = irvtd_put_char;
-	irvtd_drv.flush_chars = irvtd_flush_chars;
-        irvtd_drv.write_room = irvtd_write_room;
-	irvtd_drv.chars_in_buffer = irvtd_chars_in_buffer; 
-        irvtd_drv.flush_buffer = irvtd_flush_buffer;
- 	irvtd_drv.ioctl = irvtd_ioctl; 
-	irvtd_drv.throttle = irvtd_throttle;
-	irvtd_drv.unthrottle = irvtd_unthrottle;
- 	irvtd_drv.set_termios = irvtd_set_termios;
-	irvtd_drv.stop = NULL;          /*  irvtd_stop; */
-	irvtd_drv.start = NULL;         /* irvtd_start; */
-        irvtd_drv.hangup = irvtd_hangup;
-
-        irvtd_drv.send_xchar = irvtd_send_xchar;
-	irvtd_drv.break_ctl = irvtd_break;
-	irvtd_drv.read_proc = irvtd_read_proc;
- 	irvtd_drv.wait_until_sent = irvtd_wait_until_sent;
-
-
-
-	if (tty_register_driver(&irvtd_drv)){
-		DEBUG(0,"IrCOMM:Couldn't register tty driver\n");
-		return(1);
-	}
-
-	DEBUG( 4, "irvtd_register_ttydriver: done.\n");
-	return(0);
-}
-
-
-/*
- * Function irvtd_unregister_device(void) 
- *   it will be called when you rmmod
- */
-
-void irvtd_unregister_ttydriver(void){
-
-	int err;	
-        DEBUG( 4, "--> irvtd_unregister_device\n");
-
-	/* unregister tty device   */
-
-	err = tty_unregister_driver(&irvtd_drv);
-        if (err)
-                printk("IrCOMM: failed to unregister vtd driver(%d)\n",err);
-        DEBUG( 4, "irvtd_unregister_device -->\n");
-	return;
-}
-
-/*
- **********************************************************************
- *    proc stuff
- *
- **********************************************************************
- */
-
-static int line_info(char *buf, struct irvtd_cb *driver)
-{
-	int	ret=0;
-
-	ASSERT(driver != NULL,goto exit;);
-	ASSERT(driver->magic == IRVTD_MAGIC,goto exit;);
-
-	ret += sprintf(buf, "tx: %d rx: %d"
-		      ,driver->icount.tx, driver->icount.rx);
-
-	if (driver->icount.frame)
-                ret += sprintf(buf+ret, " fe:%d", driver->icount.frame);
-        if (driver->icount.parity)
-                ret += sprintf(buf+ret, " pe:%d", driver->icount.parity);
-        if (driver->icount.brk)
-                ret += sprintf(buf+ret, " brk:%d", driver->icount.brk);  
-        if (driver->icount.overrun)
-                ret += sprintf(buf+ret, " oe:%d", driver->icount.overrun);
-
-	if (driver->mcr & MCR_RTS)
-                ret += sprintf(buf+ret, "|RTS");
-        if (driver->msr & MSR_CTS)
-                ret += sprintf(buf+ret, "|CTS");
-        if (driver->mcr & MCR_DTR)
-                ret += sprintf(buf+ret, "|DTR");
-        if (driver->msr & MSR_DSR)
-                ret += sprintf(buf+ret, "|DSR");
-        if (driver->msr & MSR_DCD)
-                ret += sprintf(buf+ret, "|CD");
-	if (driver->msr & MSR_RI) 
-		ret += sprintf(buf+ret, "|RI");
-
-	ret += sprintf(buf+ret, "\n");
-	ret += sprintf(buf+ret, "rx queue:%d",
-		       skb_queue_len( &driver->rxbuff));
-	ret += sprintf(buf+ret, "ttp_stoprx:%s",
-		       driver->ttp_stoprx?"TRUE":"FALSE");
-
- exit:
-	ret += sprintf(buf+ret, "\n");
-	return ret;
-}
-
-
-
-static int irvtd_read_proc(char *buf, char **start, off_t offset, int len,
-		 int *eof, void *unused)
-{
-	int i, count = 0, l;
-	off_t	begin = 0;
-
-	count += sprintf(buf, "driver revision:%s\n", revision_date);
-	for (i = 0; i < COMM_MAX_TTY && count < 4000; i++) {
-		l = line_info(buf + count, irvtd[i]);
-		count += l;
-		if (count+begin > offset+len)
-			goto done;
-		if (count+begin < offset) {
-			begin += count;
-			count = 0;
-		}
-	}
-	*eof = 1;
-done:
-	if (offset >= count+begin)
-		return 0;
-	*start = buf + (begin-offset);
-	return ((len < begin+count-offset) ? len : begin+count-offset);
-}
-
-
-
-
-/************************************************************
- *    init & cleanup this module 
- ************************************************************/
-
-__initfunc(int irvtd_init(void))
-{
-	int i;
-
-	DEBUG( 4, __FUNCTION__"()\n");
-	printk( KERN_INFO 
-		"ircomm_tty: virtual tty driver for IrCOMM ( revision:%s )\n",
-		revision_date);
-
-
-	/* allocate a master array */
-
-	irvtd = (struct irvtd_cb **) kmalloc( sizeof(void *) *
-						COMM_MAX_TTY,GFP_KERNEL);
-	if ( irvtd == NULL) {
-		printk( KERN_WARNING __FUNCTION__"(): kmalloc failed!\n");
-		return -ENOMEM;
-	}
-
-	memset( irvtd, 0, sizeof(void *) * COMM_MAX_TTY);
-
-	for (i=0; i < COMM_MAX_TTY; i++){
-		irvtd[i] = kmalloc( sizeof(struct irvtd_cb), GFP_KERNEL);	
-		if(irvtd[i] == NULL){
-			printk(KERN_ERR __FUNCTION__"(): kmalloc failed!\n");
-			return -ENOMEM;
-		}
-		memset( irvtd[i], 0, sizeof(struct irvtd_cb));
-		irvtd[i]->magic = IRVTD_MAGIC;
-		irvtd[i]->line = i;
-		irvtd[i]->closing_wait = 10*HZ ;
-		irvtd[i]->close_delay = 5*HZ/10 ; 
-		init_waitqueue_head(&irvtd[i]->open_wait);
-		init_waitqueue_head(&irvtd[i]->close_wait);
-		init_waitqueue_head(&irvtd[i]->tx_wait);
-		init_waitqueue_head(&irvtd[i]->delta_msr_wait);
-	}
-
-	/* 
-	 * initialize a "port emulation entity"
-	 */
-
-	if(irvtd_register_ttydriver()){
-		printk( KERN_WARNING "IrCOMM: Error in ircomm_register_device\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-void irvtd_cleanup(void)
-{
-	int i;
-	DEBUG( 4, __FUNCTION__"()\n");
-
-	/*
-	 * free some resources
-	 */
-	if (irvtd) {
-		for (i=0; i<COMM_MAX_TTY; i++) {
-			if (irvtd[i]) {
-				if(irvtd[i]->comm)
-					ircomm_close_instance(irvtd[i]->comm);
-				if(irvtd[i]->txbuff)
-					dev_kfree_skb(irvtd[i]->txbuff);
-				DEBUG( 4, "freeing structures\n");
-				kfree(irvtd[i]);
-				irvtd[i] = NULL;
-			}
-		}
-		DEBUG( 4, "freeing master array\n");
-		kfree(irvtd);
-		irvtd = NULL;
-	}
-
- 	irvtd_unregister_ttydriver();
-
-}
-
-#ifdef MODULE
-
-int init_module(void) 
-{
-	irvtd_init();
-	return 0;
-}
-
-/*
- * Function ircomm_cleanup (void)
- *   This is called when you rmmod.
- */
-
-void cleanup_module(void)
-{
-	irvtd_cleanup();
-}
-
-#endif /* MODULE */
diff -u --recursive --new-file v2.3.15/linux/net/irda/irda_device.c linux/net/irda/irda_device.c
--- v2.3.15/linux/net/irda/irda_device.c	Wed Aug 18 11:38:49 1999
+++ linux/net/irda/irda_device.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Sep  2 20:22:08 1998
- * Modified at:   Tue Jun  1 09:05:13 1999
+ * Modified at:   Tue Aug 24 14:31:13 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Modified at:   Fri May 28  3:11 CST 1999
  * Modified by:   Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
@@ -76,7 +76,7 @@
 
 #endif /* CONFIG_PROC_FS */
 
-__initfunc(int irda_device_init( void))
+int __init irda_device_init( void)
 {
 	/* Allocate master array */
 	irda_device = hashbin_new( HB_LOCAL);
@@ -123,10 +123,12 @@
 #ifdef CONFIG_GIRBIL_DONGLE
 	girbil_init();
 #endif
-#ifdef CONFIG_GIRBIL_DONGLE
+#ifdef CONFIG_LITELINK_DONGLE
 	litelink_init();
 #endif
-
+#ifdef CONFIG_AIRPORT_DONGLE
+ 	airport_init();
+#endif
 	return 0;
 }
 
@@ -163,8 +165,10 @@
 	if (self->tx_buff.truesize > 0) {
 		self->tx_buff.head = ( __u8 *) kmalloc(self->tx_buff.truesize, 
 						       self->tx_buff.flags);
-		if (self->tx_buff.head == NULL)
+		if (self->tx_buff.head == NULL) {
+			kfree(self->rx_buff.head);
 			return -ENOMEM;
+		}
 
 		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 	}
@@ -216,15 +220,6 @@
 
 	irda_device_set_media_busy(self, FALSE);
 
-	/* 
-	 * Open new IrLAP layer instance, now that everything should be
-	 * initialized properly 
-	 */
-	self->irlap = irlap_open(self);
-        
-	/* It's now safe to initilize the saddr */
-	memcpy(self->netdev.dev_addr, &self->irlap->saddr, 4);
-
 	return 0;
 }
 
@@ -278,11 +273,6 @@
 	if (self->dongle)
 		self->dongle->close(self);
 
-	/* Stop and remove instance of IrLAP */
-	if (self->irlap)
-		irlap_close(self->irlap);
-	self->irlap = NULL;
-
 	hashbin_remove(irda_device, (int) self, NULL);
 
 	__irda_device_close(self);
@@ -345,13 +335,15 @@
 
 		if (n++ > 10) {
 			WARNING(__FUNCTION__ "(), breaking loop!\n");
-			break;
+			return;
 		}
 	}
 	
+	/* Change speed of dongle */
 	if (self->dongle)
 		self->dongle->change_speed(self, speed);
 	
+	/* Change speed of IrDA port */
 	if (self->change_speed) {
 		self->change_speed(self, speed);
 		
@@ -452,6 +444,57 @@
 	return 0;
 }
 
+int irda_device_net_open(struct net_device *dev)
+{
+	struct irda_device *self;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* 
+	 * Open new IrLAP layer instance, now that everything should be
+	 * initialized properly 
+	 */
+	self->irlap = irlap_open(self);
+        
+	/* It's now safe to initilize the saddr */
+	memcpy(self->netdev.dev_addr, &self->irlap->saddr, 4);
+
+	return 0;
+}
+
+int irda_device_net_close(struct net_device *dev)
+{
+	struct irda_device *self;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return 0;);
+	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
+	
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	/* Stop and remove instance of IrLAP */
+	if (self->irlap)
+		irlap_close(self->irlap);
+	self->irlap = NULL;
+
+	return 0;
+}
+
 /*
  * Function irda_device_net_rebuild_header (buff, dev, dst, skb)
  *
@@ -618,7 +661,7 @@
 }
 
 /*
- * Function irda_device_transmit_finished (void)
+ * Function irda_device_txqueue_empty (irda_device)
  *
  *    Check if there is still some frames in the transmit queue for this
  *    device. Maybe we should use: q->q.qlen == 0.
@@ -672,6 +715,10 @@
 		MESSAGE("IrDA: Initializing Litelink dongle!\n");
 		request_module("litelink");
 		break;
+	case AIRPORT_DONGLE:
+		MESSAGE("IrDA: Initializing Airport dongle!\n");
+		request_module("airport");
+		break;
 	default:
 		ERROR("Unknown dongle type!\n");
 		return;
@@ -749,6 +796,31 @@
 		return;
 	}
 	kfree(node);
+}
+
+/*
+ * Function irda_device_set_raw_mode (self, status)
+ *
+ *    
+ *
+ */
+int irda_device_set_raw_mode(struct irda_device* self, int status)
+{	
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;);
+	
+	if (self->set_raw_mode == NULL) {
+		ERROR(__FUNCTION__ "(), set_raw_mode not impl. by "
+		      "device driver\n");
+		return -1;
+	}
+	
+	self->raw_mode = status;
+	self->set_raw_mode(self, status);
+	
+	return 0;
 }
 
 /*
diff -u --recursive --new-file v2.3.15/linux/net/irda/iriap.c linux/net/irda/iriap.c
--- v2.3.15/linux/net/irda/iriap.c	Sun May 30 10:27:04 1999
+++ linux/net/irda/iriap.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Sun May  9 15:59:05 1999
+ * Modified at:   Fri Aug 20 10:26:39 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -82,22 +82,19 @@
  *    Initializes the IrIAP layer, called by the module initialization code
  *    in irmod.c 
  */
-__initfunc(int iriap_init(void))
+int __init iriap_init(void)
 {
 	__u16 hints;
 	struct ias_object *obj;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
 	/* Allocate master array */
-	iriap = hashbin_new( HB_LOCAL);
-	if ( iriap == NULL)
+	iriap = hashbin_new(HB_LOCAL);
+	if (!iriap)
 		return -ENOMEM;
 
-	objects = hashbin_new( HB_LOCAL);
-	if ( objects == NULL) {
-		printk( KERN_WARNING 
-			"IrIAP: Can't allocate objects hashbin!\n");
+	objects = hashbin_new(HB_LOCAL);
+	if (!objects) {
+		WARNING(__FUNCTION__ "(), Can't allocate objects hashbin!\n");
 		return -ENOMEM;
 	}
 
@@ -111,15 +108,15 @@
 	/* 
 	 *  Register the Device object with LM-IAS
 	 */
-	obj = irias_new_object( "Device", IAS_DEVICE_ID);
-	irias_add_string_attrib( obj, "DeviceName", "Linux");
-	irias_insert_object( obj);
+	obj = irias_new_object("Device", IAS_DEVICE_ID);
+	irias_add_string_attrib(obj, "DeviceName", "Linux");
+	irias_insert_object(obj);
 
 	/*  
 	 *  Register server support with IrLMP so we can accept incoming 
 	 *  connections 
 	 */
-	iriap_open( LSAP_IAS, IAS_SERVER);
+	iriap_open(LSAP_IAS, IAS_SERVER);
 	
 	return 0;
 }
@@ -130,7 +127,7 @@
  *    Initializes the IrIAP layer, called by the module cleanup code in 
  *    irmod.c
  */
-void iriap_cleanup(void) 
+void iriap_cleanup(void)
 {
 	irlmp_unregister_service(service_handle);
 	
@@ -143,43 +140,42 @@
  *
  *    Opens an instance of the IrIAP layer, and registers with IrLMP
  */
-struct iriap_cb *iriap_open( __u8 slsap_sel, int mode)
+struct iriap_cb *iriap_open(__u8 slsap_sel, int mode)
 {
 	struct iriap_cb *self;
-	struct notify_t notify;
 	struct lsap_cb *lsap;
+	notify_t notify;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	self = kmalloc( sizeof(struct iriap_cb), GFP_ATOMIC);
-	if ( self == NULL) {
-		DEBUG( 0, "iriap_open(), Unable to kmalloc!\n");
+	self = kmalloc(sizeof(struct iriap_cb), GFP_ATOMIC);
+	if (!self) {
+		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
 
 	/*
 	 *  Initialize instance
 	 */
-	memset( self, 0, sizeof(struct iriap_cb));
+	memset(self, 0, sizeof(struct iriap_cb));
 
-	irda_notify_init( &notify);
-	notify.connect_confirm = iriap_connect_confirm;
-	notify.connect_indication = iriap_connect_indication;
+	irda_notify_init(&notify);
+	notify.connect_confirm       = iriap_connect_confirm;
+	notify.connect_indication    = iriap_connect_indication;
 	notify.disconnect_indication = iriap_disconnect_indication;
-	notify.data_indication = iriap_data_indication;
+	notify.data_indication       = iriap_data_indication;
 	notify.instance = self;
-	if ( mode == IAS_CLIENT)
-		strcpy( notify.name, "IrIAS cli");
+	if (mode == IAS_CLIENT)
+		strcpy(notify.name, "IrIAS cli");
 	else
-		strcpy( notify.name, "IrIAS srv");
+		strcpy(notify.name, "IrIAS srv");
 
-	lsap = irlmp_open_lsap( slsap_sel, &notify);
-	if ( lsap == NULL) {
-		DEBUG( 0, "iriap_open: Unable to allocated LSAP!\n");
+	lsap = irlmp_open_lsap(slsap_sel, &notify);
+	if (lsap == NULL) {
+		ERROR(__FUNCTION__ "(), Unable to allocated LSAP!\n");
 		return NULL;
 	}
 	slsap_sel = lsap->slsap_sel;
-	DEBUG( 4, __FUNCTION__ "(), source LSAP sel=%02x\n", slsap_sel);
 	
 	self->magic = IAS_MAGIC;
 	self->lsap = lsap;
@@ -188,12 +184,13 @@
 
 	init_timer(&self->watchdog_timer);
 
-	hashbin_insert( iriap, (QUEUE*) self, slsap_sel, NULL);
+	hashbin_insert(iriap, (QUEUE*) self, slsap_sel, NULL);
 	
-	iriap_next_client_state( self, S_DISCONNECT);
-	iriap_next_call_state( self, S_MAKE_CALL);
-	iriap_next_server_state( self, R_DISCONNECT);
-	iriap_next_r_connect_state( self, R_WAITING);
+	/* Initialize state machines */
+	iriap_next_client_state(self, S_DISCONNECT);
+	iriap_next_call_state(self, S_MAKE_CALL);
+	iriap_next_server_state(self, R_DISCONNECT);
+	iriap_next_r_connect_state(self, R_WAITING);
 	
 	return self;
 }
@@ -204,18 +201,18 @@
  *    Removes (deallocates) the IrIAP instance
  *
  */
-static void __iriap_close( struct iriap_cb *self)
+static void __iriap_close(struct iriap_cb *self)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
 	del_timer(&self->watchdog_timer);
 
 	self->magic = 0;
 
-	kfree( self);
+	kfree(self);
 }
 
 /*
@@ -223,25 +220,23 @@
  *
  *    Closes IrIAP and deregisters with IrLMP
  */
-void iriap_close( struct iriap_cb *self)
+void iriap_close(struct iriap_cb *self)
 {
 	struct iriap_cb *entry;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	if ( self->lsap) {
-		irlmp_close_lsap( self->lsap);
+	if (self->lsap) {
+		irlmp_close_lsap(self->lsap);
 		self->lsap = NULL;
 	}
 
-	entry = (struct iriap_cb *) hashbin_remove( iriap, self->slsap_sel, 
-						    NULL);
-	ASSERT( entry == self, return;);
+	entry = (struct iriap_cb *) hashbin_remove(iriap, self->slsap_sel, 
+						   NULL);
+	ASSERT(entry == self, return;);
 
-	__iriap_close( self);
+	__iriap_close(self);
 }
 
 /*
@@ -250,9 +245,9 @@
  *    Got disconnect, so clean up everything assosiated with this connection
  *
  */
-static void iriap_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, 
-					 struct sk_buff *userdata)
+static void iriap_disconnect_indication(void *instance, void *sap, 
+					LM_REASON reason, 
+					struct sk_buff *userdata)
 {
 	struct iriap_cb *self;
 
@@ -260,15 +255,15 @@
 
 	self = (struct iriap_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	ASSERT( iriap != NULL, return;);
+	ASSERT(iriap != NULL, return;);
 
 	del_timer(&self->watchdog_timer);
 
-	if ( self->mode == IAS_CLIENT) {
-		DEBUG( 4, __FUNCTION__ "(), disconnect as client\n");
+	if (self->mode == IAS_CLIENT) {
+		DEBUG(4, __FUNCTION__ "(), disconnect as client\n");
 
 		/* 
 		 * Inform service user that the request failed by sending 
@@ -278,19 +273,19 @@
  			self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
 		
 		
-		iriap_do_client_event( self, IAP_LM_DISCONNECT_INDICATION, 
-				       NULL);
+		iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION, 
+				      NULL);
 		/* Close instance only if client */
-		iriap_close( self);
+		iriap_close(self);
 		
 	} else {
-		DEBUG( 4, __FUNCTION__ "(), disconnect as server\n");
-		iriap_do_server_event( self, IAP_LM_DISCONNECT_INDICATION, 
-				       NULL);
+		DEBUG(4, __FUNCTION__ "(), disconnect as server\n");
+		iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION, 
+				      NULL);
 	}
 
 	if (userdata)
-		dev_kfree_skb( userdata);
+		dev_kfree_skb(userdata);
 }
 
 /*
@@ -325,27 +320,27 @@
 
 void iriap_getinfobasedetails_request(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getinfobasedetails_confirm(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getobjects_request(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getobjects_confirm(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getvalue(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 /*
@@ -360,11 +355,13 @@
 {
 	struct sk_buff *skb;
 	struct iriap_cb *self;
-	__u8 *frame;
 	int name_len, attr_len;
 	__u8 slsap = LSAP_ANY;  /* Source LSAP to use */
+	__u8 *frame;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	/* Client must supply the destination device address */
+	if (!daddr)
+		return;
 	
 	self = iriap_open(slsap, IAS_CLIENT);
 	if (!self)
@@ -417,7 +414,6 @@
 void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb) 
 {
 	struct ias_value *value;
-	int n;
 	int charset;
 	__u32 value_len;
 	__u32 tmp_cpu32;
@@ -425,6 +421,7 @@
 	__u16 len;
 	__u8  type;
 	__u8 *fp;
+	int n;
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
@@ -441,25 +438,23 @@
 
 	/* Get object ID, MSB first */
 	obj_id = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
-/* 	memcpy(&obj_id, fp+n, 2); n += 2; */
-/* 	be16_to_cpus(&obj_id); */
 
 	type = fp[n++];
-	DEBUG( 4, __FUNCTION__ "(), Value type = %d\n", type);
+	DEBUG(4, __FUNCTION__ "(), Value type = %d\n", type);
 
-	switch( type) {
+	switch (type) {
 	case IAS_INTEGER:
 		memcpy(&tmp_cpu32, fp+n, 4); n += 4;
 		be32_to_cpus(&tmp_cpu32);
 		value = irias_new_integer_value(tmp_cpu32);
 
 		/*  Legal values restricted to 0x01-0x6f, page 15 irttp */
-		DEBUG( 4, __FUNCTION__ "(), lsap=%d\n", value->t.integer); 
+		DEBUG(4, __FUNCTION__ "(), lsap=%d\n", value->t.integer); 
 		break;
 	case IAS_STRING:
 		charset = fp[n++];
 
-		switch(charset) {
+		switch (charset) {
 		case CS_ASCII:
 			break;
 /* 		case CS_ISO_8859_1: */
@@ -480,7 +475,7 @@
 		}
 		value_len = fp[n++];
 		DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
-		ASSERT( value_len < 64, return;);
+		ASSERT(value_len < 64, return;);
 		
 		/* Make sure the string is null-terminated */
 		fp[n+value_len] = 0x00;
@@ -492,8 +487,6 @@
 		value_len = be16_to_cpu(get_unaligned((__u16 *)(fp+n)));
 		n += 2;
 		
-		/* FIXME:should be 1024, but.... */
-		DEBUG(0, __FUNCTION__ "():octet sequence:len=%d\n", value_len);
 		ASSERT(value_len <= 55, return;);      
 		
 		value = irias_new_octseq_value(fp+n, value_len);
@@ -524,12 +517,12 @@
 	__u32 tmp_be32, tmp_be16;
 	__u8 *fp;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
-	ASSERT( value != NULL, return;);
-	ASSERT( value->len <= 1024, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
+	ASSERT(value != NULL, return;);
+	ASSERT(value->len <= 1024, return;);
 
 	/* Initialize variables */
 	n = 0;
@@ -589,7 +582,6 @@
 		skb_put( skb, 1);
 		fp[n++] = value->type;
 		break;
-
 	default:
 		DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
 		break;
@@ -606,33 +598,33 @@
 void iriap_getvaluebyclass_indication(struct iriap_cb *self, 
 				      struct sk_buff *skb)
 {
-	__u8 *fp;
-	int n;
+ 	struct ias_object *obj;
+	struct ias_attrib *attrib;
 	int name_len;
 	int attr_len;
 	char name[64];
 	char attr[64];
- 	struct ias_object *obj;
-	struct ias_attrib *attrib;
+	__u8 *fp;
+	int n;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	fp = skb->data;
 	n = 1;
 
 	name_len = fp[n++];
-	memcpy( name, fp+n, name_len); n+=name_len;
+	memcpy(name, fp+n, name_len); n+=name_len;
 	name[name_len] = '\0';
 
 	attr_len = fp[n++]; 
-	memcpy( attr, fp+n, attr_len); n+=attr_len;
+	memcpy(attr, fp+n, attr_len); n+=attr_len;
 	attr[attr_len] = '\0';
 
-	dev_kfree_skb( skb);
+	dev_kfree_skb(skb);
 
 	/* 
 	 *  Now, do some advanced parsing! :-) 
@@ -640,17 +632,17 @@
 	DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
 	obj = irias_find_object(name);
 	
-	if ( obj == NULL) {
-		DEBUG( 0, "LM-IAS: Object not found\n");
-		iriap_getvaluebyclass_response( self, 0x1235, 
-						IAS_CLASS_UNKNOWN, &missing);
+	if (obj == NULL) {
+		DEBUG(0, "LM-IAS: Object not found\n");
+		iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
+					       &missing);
 		return;
 	}
 	DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
 	
-	attrib = irias_find_attrib( obj, attr);
-	if ( attrib == NULL) {
-		DEBUG( 0, "LM-IAS: Attribute %s not found\n", attr);
+	attrib = irias_find_attrib(obj, attr);
+	if (attrib == NULL) {
+		DEBUG(0, "LM-IAS: Attribute %s not found\n", attr);
 		iriap_getvaluebyclass_response(self, obj->id,
 					       IAS_ATTRIB_UNKNOWN, &missing);
 		return;
@@ -661,8 +653,8 @@
 	/*
 	 * We have a match; send the value.
 	 */
-	iriap_getvaluebyclass_response( self, obj->id, IAS_SUCCESS, 
-					attrib->value);
+	iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS, 
+				       attrib->value);
 
 	return;
 }
@@ -673,15 +665,15 @@
  *    Currently not used
  *
  */
-void iriap_send_ack( struct iriap_cb *self) 
+void iriap_send_ack(struct iriap_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 
-	DEBUG( 6, __FUNCTION__ "()\n");
+	DEBUG(6, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
 	skb = dev_alloc_skb(64);
 	if (!skb)
@@ -775,32 +767,31 @@
 		return 0;
 	}
 	opcode = frame[0];
-	if ( ~opcode & 0x80) {
-		printk( KERN_ERR "IrIAS multiframe commands or results is "
-			"not implemented yet!\n");
+	if (~opcode & IAP_LST) {
+		WARNING(__FUNCTION__ "(), IrIAS multiframe commands or "
+			"results is not implemented yet!\n");
 		return 0;
 	}
-
-	if (~opcode & IAP_ACK) {
-		DEBUG(2, __FUNCTION__ "() Got ack frame!\n");
-	/* 	return; */
+	
+	/* Check for ack frames since they don't contain any data */
+	if (opcode & IAP_ACK) {
+		DEBUG(0, __FUNCTION__ "() Got ack frame!\n");
+	 	return 0;
 	}
 
 	opcode &= ~IAP_LST; /* Mask away LST bit */
 	
-	switch(opcode) {
+	switch (opcode) {
 	case GET_INFO_BASE:
-		DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n");
+		DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
 		break;
 	case GET_VALUE_BY_CLASS:
-		DEBUG( 4,"IrLMP GetValueByClass\n");
-		
-		switch(frame[1]) {
+		switch (frame[1]) {
 		case IAS_SUCCESS:
 			iriap_getvaluebyclass_confirm(self, skb);
 			break;
 		case IAS_CLASS_UNKNOWN:
-			printk(KERN_WARNING "IrIAP No such class!\n");
+			WARNING(__FUNCTION__ "(), No such class!\n");
 			/* Finished, close connection! */
 			iriap_disconnect_request(self);
 
@@ -809,7 +800,7 @@
 					      self->priv);
 			break;
 		case IAS_ATTRIB_UNKNOWN:
-			printk(KERN_WARNING "IrIAP No such attribute!\n");
+			WARNING(__FUNCTION__ "(), No such attribute!\n");
 		       	/* Finished, close connection! */
 			iriap_disconnect_request(self);
 
@@ -818,13 +809,13 @@
 					      self->priv);
 			break;
 		}
-		iriap_do_call_event( self, IAP_RECV_F_LST, skb);
+		iriap_do_call_event(self, IAP_RECV_F_LST, skb);
 
 		/*  
 		 *  We remove LSAPs used by IrIAS as a client since these
 		 *  are more difficult to reuse!  
 		 */
-		iriap_close( self);
+		iriap_close(self);
 		break;
 	default:
 		DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n", opcode);
@@ -839,33 +830,34 @@
  *    Received call to server from peer LM-IAS
  *
  */
-void iriap_call_indication( struct iriap_cb *self, struct sk_buff *skb)
+void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
 {
 	__u8 *fp;
-	__u8  opcode;
+	__u8 opcode;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	fp = skb->data;
 
 	opcode = fp[0];
-	if ( ~opcode & 0x80) {
-		printk( KERN_ERR "IrIAS multiframe commands or results is "
-			"not implemented yet!\n");
+	if (~opcode & 0x80) {
+		WARNING(__FUNCTION__ "(), IrIAS multiframe commands or results"
+			"is not implemented yet!\n");
 		return;
 	}
 	opcode &= 0x7f; /* Mask away LST bit */
 	
 	switch (opcode) {
 	case GET_INFO_BASE:
-		DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n");
+		WARNING(__FUNCTION__ 
+			"(), GetInfoBaseDetails not implemented yet!\n");
 		break;
 	case GET_VALUE_BY_CLASS:
-		iriap_getvaluebyclass_indication( self, skb);
+		iriap_getvaluebyclass_indication(self, skb);
 		break;
 	}
 }
@@ -873,18 +865,17 @@
 /*
  * Function iriap_watchdog_timer_expired (data)
  *
- *    
+ *    Query has taken to long time, so abort
  *
  */
-void iriap_watchdog_timer_expired( unsigned long data)
+void iriap_watchdog_timer_expired(void *data)
 {
-	struct iriap_cb *self = ( struct iriap_cb *) data;
+	struct iriap_cb *self = (struct iriap_cb *) data;
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	DEBUG(0, __FUNCTION__ "() Timeout! closing myself!\n");
-	iriap_close( self);
+	iriap_close(self);
 }
 
 #ifdef CONFIG_PROC_FS
@@ -909,56 +900,56 @@
 
 	len = 0;
 
-	len += sprintf( buf+len, "LM-IAS Objects:\n");
+	len += sprintf(buf+len, "LM-IAS Objects:\n");
 
 	/* List all objects */
-	obj = (struct ias_object *) hashbin_get_first( objects);
+	obj = (struct ias_object *) hashbin_get_first(objects);
 	while ( obj != NULL) {
-		ASSERT( obj->magic == IAS_OBJECT_MAGIC, return 0;);
+		ASSERT(obj->magic == IAS_OBJECT_MAGIC, return 0;);
 
-		len += sprintf( buf+len, "name: %s, ", obj->name);
-		len += sprintf( buf+len, "id=%d", obj->id);
-		len += sprintf( buf+len, "\n");
+		len += sprintf(buf+len, "name: %s, ", obj->name);
+		len += sprintf(buf+len, "id=%d", obj->id);
+		len += sprintf(buf+len, "\n");
 
 		/* List all attributes for this object */
 		attrib = (struct ias_attrib *) 
-			hashbin_get_first( obj->attribs);
-		while ( attrib != NULL) {
-			ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
-
-			len += sprintf( buf+len, " - Attribute name: \"%s\", ",
- 					attrib->name);
-			len += sprintf( buf+len, "value[%s]: ", 
-					ias_value_types[ attrib->value->type]);
+			hashbin_get_first(obj->attribs);
+		while (attrib != NULL) {
+			ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
+
+			len += sprintf(buf+len, " - Attribute name: \"%s\", ",
+				       attrib->name);
+			len += sprintf(buf+len, "value[%s]: ", 
+				       ias_value_types[attrib->value->type]);
 			
-			switch( attrib->value->type) {
+			switch (attrib->value->type) {
 			case IAS_INTEGER:
-				len += sprintf( buf+len, "%d\n", 
-						attrib->value->t.integer);
+				len += sprintf(buf+len, "%d\n", 
+					       attrib->value->t.integer);
 				break;
 			case IAS_STRING:
-				len += sprintf( buf+len, "\"%s\"\n", 
-						attrib->value->t.string);
+				len += sprintf(buf+len, "\"%s\"\n", 
+					       attrib->value->t.string);
 				break;
 			case IAS_OCT_SEQ:
-				len += sprintf( buf+len, "octet sequence\n");
+				len += sprintf(buf+len, "octet sequence\n");
 				break;
 			case IAS_MISSING:
-				len += sprintf( buf+len, "missing\n");
+				len += sprintf(buf+len, "missing\n");
 				break;
 			default:
-				DEBUG( 0, __FUNCTION__ 
-				       "(), Unknown value type!\n");
+				DEBUG(0, __FUNCTION__ 
+				      "(), Unknown value type!\n");
 				return -1;
 			}
-			len += sprintf( buf+len, "\n");
+			len += sprintf(buf+len, "\n");
 			
 			attrib = (struct ias_attrib *) 
 				hashbin_get_next(obj->attribs);
 		}
-	        obj = ( struct ias_object *) hashbin_get_next( objects);
+	        obj = (struct ias_object *) hashbin_get_next(objects);
  	} 
-	restore_flags( flags);
+	restore_flags(flags);
 
 	return len;
 }
diff -u --recursive --new-file v2.3.15/linux/net/irda/irias_object.c linux/net/irda/irias_object.c
--- v2.3.15/linux/net/irda/irias_object.c	Thu Apr 15 05:42:42 1999
+++ linux/net/irda/irias_object.c	Mon Aug 30 10:26:28 1999
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct  1 22:50:04 1998
- * Modified at:   Mon Mar 22 13:22:35 1999
+ * Modified at:   Mon Jun 21 16:11:13 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -35,9 +35,7 @@
 /*
  *  Used when a missing value needs to be returned
  */
-struct ias_value missing = {
-        IAS_MISSING,	0,	0,	{ 0 }
-};
+struct ias_value missing = { IAS_MISSING, 0, 0,	{0}};
 
 /*
  * Function strdup (str)
@@ -45,20 +43,20 @@
  *    My own kernel version of strdup!
  *
  */
-char *strdup( char *str)
+char *strdup(char *str)
 {
 	char *new_str;
 	
-	if ( str == NULL)
+	if (str == NULL)
 		return NULL;
 
-	ASSERT( strlen( str) < 64, return NULL;);
+	ASSERT(strlen( str) < 64, return NULL;);
 	
-        new_str = kmalloc( strlen( str)+1, GFP_ATOMIC);
-        if ( new_str == NULL)
+        new_str = kmalloc(strlen(str)+1, GFP_ATOMIC);
+        if (new_str == NULL)
 		return NULL;
 	
-	strcpy( new_str, str);
+	strcpy(new_str, str);
 	
 	return new_str;
 }
@@ -77,17 +75,17 @@
 
 	obj = (struct ias_object *) kmalloc( sizeof( struct ias_object), 
 					     GFP_ATOMIC);
-	if ( obj == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to allocate object!\n");
+	if (obj == NULL) {
+		DEBUG(0, __FUNCTION__ "(), Unable to allocate object!\n");
 		return NULL;
 	}
-	memset( obj, 0, sizeof( struct ias_object));
+	memset(obj, 0, sizeof( struct ias_object));
 
 	obj->magic = IAS_OBJECT_MAGIC;
 	obj->name = strdup( name);
 	obj->id = id;
 
-	obj->attribs = hashbin_new( HB_LOCAL);
+	obj->attribs = hashbin_new(HB_LOCAL);
 	
 	return obj;
 }
@@ -98,59 +96,56 @@
  *    Delete given attribute and deallocate all its memory
  *
  */
-void __irias_delete_attrib( struct ias_attrib *attrib)
+void __irias_delete_attrib(struct ias_attrib *attrib)
 {
-	ASSERT( attrib != NULL, return;);
-	ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return;);
+	ASSERT(attrib != NULL, return;);
+	ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;);
 
-	if ( attrib->name)
-		kfree( attrib->name);
+	if (attrib->name)
+		kfree(attrib->name);
 
-	irias_delete_value( attrib->value);
+	irias_delete_value(attrib->value);
 	attrib->magic = ~IAS_ATTRIB_MAGIC;
 	
-	kfree( attrib);
+	kfree(attrib);
 }
 
-/*
- * Function irias_delete_object (obj)
- *
- *    Remove object from hashbin and deallocate all attributes assosiated with
- *    with this object and the object itself
- *
- */
-void __irias_delete_object( struct ias_object *obj) 
+void __irias_delete_object(struct ias_object *obj)
 {
-	ASSERT( obj != NULL, return;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
-	
-	if ( obj->name)
-		kfree( obj->name);
+	ASSERT(obj != NULL, return;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
+
+	if (obj->name)
+		kfree(obj->name);
 	
-	hashbin_delete( obj->attribs, (FREE_FUNC) __irias_delete_attrib);
+	hashbin_delete(obj->attribs, (FREE_FUNC) __irias_delete_attrib);
 	
 	obj->magic = ~IAS_OBJECT_MAGIC;
 	
-	kfree( obj);
+	kfree(obj);
 }
 
 /*
- * Function irias_remove_object (obj)
+ * Function irias_delete_object (obj)
  *
- *    Remove object with give name from the LM-IAS object database
+ *    Remove object from hashbin and deallocate all attributes assosiated with
+ *    with this object and the object itself
  *
  */
-void irias_delete_object( char *obj_name)
+int irias_delete_object(struct ias_object *obj) 
 {
-	struct ias_object *obj;
+	struct ias_object *node;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	ASSERT(obj != NULL, return -1;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;);
 
-	ASSERT( obj_name != NULL, return;);
+	node = hashbin_remove(objects, 0, obj->name);
+	if (!node)
+		return 0; /* Already removed */
 
-	obj = hashbin_remove( objects, 0, obj_name);
+	__irias_delete_object(node);
 
-	__irias_delete_object( obj);
+	return 0;
 }
 
 /*
@@ -159,14 +154,14 @@
  *    Insert an object into the LM-IAS database
  *
  */
-void irias_insert_object( struct ias_object *obj)
+void irias_insert_object(struct ias_object *obj)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
-	ASSERT( obj != NULL, return;);
-	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+	ASSERT(obj != NULL, return;);
+	ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;);
 	
-	hashbin_insert( objects, (QUEUE *) obj, 0, obj->name);
+	hashbin_insert(objects, (QUEUE *) obj, 0, obj->name);
 }
 
 /*
@@ -175,11 +170,11 @@
  *    Find object with given name
  *
  */
-struct ias_object *irias_find_object( char *name)
+struct ias_object *irias_find_object(char *name)
 {
-	ASSERT( name != NULL, return NULL;);
+	ASSERT(name != NULL, return NULL;);
 
-	return hashbin_find( objects, 0, name);
+	return hashbin_find(objects, 0, name);
 }
 
 /*
@@ -278,8 +273,6 @@
 {
 	struct ias_attrib *attrib;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
 	ASSERT( obj != NULL, return;);
 	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
 	ASSERT( name != NULL, return;);
@@ -315,11 +308,6 @@
 {
 	struct ias_attrib *attrib;
 	
-	DEBUG( 0, __FUNCTION__ "()\n");
-	
-	DEBUG( 0, __FUNCTION__ ": name=%s\n", name);
-	DEBUG( 0, __FUNCTION__ ": len=%d\n", len);
-	
 	ASSERT( obj != NULL, return;);
 	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
 	
@@ -354,11 +342,6 @@
 {
 	struct ias_attrib *attrib;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	DEBUG( 4, __FUNCTION__ ": name=%s\n", name);
-	DEBUG( 4, __FUNCTION__ ": name=%s\n", value);
-	
 	ASSERT( obj != NULL, return;);
 	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
 
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlan/irlan_client.c linux/net/irda/irlan/irlan_client.c
--- v2.3.15/linux/net/irda/irlan/irlan_client.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/irlan/irlan_client.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon May 31 14:19:34 1999
+ * Modified at:   Thu Jul  8 13:50:16 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
@@ -67,7 +67,7 @@
 static void irlan_check_response_param(struct irlan_cb *self, char *param, 
 				       char *value, int val_len);
 
-static void irlan_client_kick_timer_expired(unsigned long data)
+static void irlan_client_kick_timer_expired(void *data)
 {
 	struct irlan_cb *self = (struct irlan_cb *) data;
 	
@@ -92,8 +92,7 @@
 {
 	DEBUG(4, __FUNCTION__ "()\n");
 	
-	irda_start_timer(&self->client.kick_timer, timeout, 
-			 (unsigned long) self, 
+	irda_start_timer(&self->client.kick_timer, timeout, (void *) self, 
 			 irlan_client_kick_timer_expired);
 }
 
@@ -166,7 +165,7 @@
  */
 void irlan_client_discovery_indication(discovery_t *discovery) 
 {
-	struct irlan_cb *self, *entry;
+	struct irlan_cb *self;
 	__u32 saddr, daddr;
 	
 	DEBUG(1, __FUNCTION__"()\n");
@@ -223,7 +222,8 @@
 	
 	irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb); 
 
-	/* Ready for a new command */
+	/* Ready for a new command */	
+	DEBUG(2, __FUNCTION__ "(), clearing tx_busy\n");
 	self->client.tx_busy = FALSE;
 
 	/* Check if we have some queued commands waiting to be sent */
@@ -238,6 +238,7 @@
 {
 	struct irlan_cb *self;
 	struct tsap_cb *tsap;
+	struct sk_buff *skb;
 
 	DEBUG(4, __FUNCTION__ "(), reason=%d\n", reason);
 	
@@ -251,6 +252,12 @@
 	
 	ASSERT(tsap == self->client.tsap_ctrl, return;);
 
+       	/* Remove frames queued on the control channel */
+	while ((skb = skb_dequeue(&self->client.txq))) {
+		dev_kfree_skb(skb);
+	}
+	self->client.tx_busy = FALSE;
+
 	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
 }
 
@@ -262,8 +269,8 @@
  */
 void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
 {
-	struct notify_t notify;
 	struct tsap_cb *tsap;
+	notify_t notify;
 
 	DEBUG(4, __FUNCTION__ "()\n");
 
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlan/irlan_client_event.c linux/net/irda/irlan/irlan_client_event.c
--- v2.3.15/linux/net/irda/irlan/irlan_client_event.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/irlan/irlan_client_event.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Fri May 14 23:08:15 1999
+ * Modified at:   Mon Jul  5 11:06:57 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
--- v2.3.15/linux/net/irda/irlan/irlan_common.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/irlan/irlan_common.c	Tue Aug 31 11:23:03 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon May 31 14:25:19 1999
+ * Modified at:   Tue Aug 17 15:30:40 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -106,10 +106,10 @@
 /*
  * Function irlan_watchdog_timer_expired (data)
  *
- *    
+ *    Something has gone wrong during the connection establishment
  *
  */
-void irlan_watchdog_timer_expired(unsigned long data)
+void irlan_watchdog_timer_expired(void *data)
 {
 	struct irmanager_event mgr_event;
 	struct irlan_cb *self;
@@ -123,7 +123,8 @@
 
 	/* Check if device still configured */
 	if (self->dev.start) {
-		DEBUG(0, __FUNCTION__ "(), notifying irmanager to stop irlan!\n");
+		DEBUG(0, __FUNCTION__ 
+		      "(), notifying irmanager to stop irlan!\n");
 		mgr_event.event = EVENT_IRLAN_STOP;
 		sprintf(mgr_event.devname, "%s", self->ifname);
 		irmanager_notify(&mgr_event);
@@ -137,12 +138,7 @@
 		self->notify_irmanager = FALSE;
 	} else {
 		DEBUG(0, __FUNCTION__ "(), closing instance!\n");
-		if (self->netdev_registered) {
-			DEBUG(0, __FUNCTION__ "(), removing netdev!\n");
-			unregister_netdev(&self->dev);
-			self->netdev_registered = FALSE;
-		}
-		irlan_close(self);
+		/*irlan_close(self);*/
 	}
 }
 
@@ -156,7 +152,7 @@
 {
 	DEBUG(4, __FUNCTION__ "()\n");
 	
-	irda_start_timer(&self->watchdog_timer, timeout, (unsigned long) self,
+	irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
 			 irlan_watchdog_timer_expired);
 }
 
@@ -166,14 +162,14 @@
  *    Initialize IrLAN layer
  *
  */
-__initfunc(int irlan_init(void))
+int __init irlan_init(void)
 {
 	struct irlan_cb *new;
 	__u16 hints;
 
 	DEBUG(4, __FUNCTION__"()\n");
 
-	/* Allocate master array */
+	/* Allocate master structure */
 	irlan = hashbin_new(HB_LOCAL); 
 	if (irlan == NULL) {
 		printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
@@ -323,6 +319,8 @@
  */
 static void __irlan_close(struct irlan_cb *self)
 {
+	struct sk_buff *skb;
+
 	DEBUG(2, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
@@ -334,6 +332,11 @@
 	/* Close all open connections and remove TSAPs */
 	irlan_close_tsaps(self);
 
+	/* Remove frames queued on the control channel */
+	while ((skb = skb_dequeue(&self->client.txq))) {
+		dev_kfree_skb(skb);
+	}
+
 	if (self->netdev_registered) {
 		unregister_netdev(&self->dev);
 		self->netdev_registered = FALSE;
@@ -352,7 +355,7 @@
 void irlan_close(struct irlan_cb *self)
 {
 	struct irlan_cb *entry;
-	
+
 	DEBUG(0, __FUNCTION__ "()\n");
 
         ASSERT(self != NULL, return;);
@@ -507,8 +510,8 @@
 
 void irlan_open_data_tsap(struct irlan_cb *self)
 {
-	struct notify_t notify;
 	struct tsap_cb *tsap;
+	notify_t notify;
 
 	DEBUG(2, __FUNCTION__ "()\n");
 
@@ -631,6 +634,8 @@
 {
 	struct sk_buff *skb;
 
+	DEBUG(3, __FUNCTION__ "()\n");
+
 	if (irda_lock(&self->client.tx_busy) == FALSE)
 		return -EBUSY;
 
@@ -639,11 +644,16 @@
 		self->client.tx_busy = FALSE;
 		return 0;
 	}
-	if (self->client.tsap_ctrl == NULL) {
+	
+	/* Check that it's really possible to send commands */
+	if ((self->client.tsap_ctrl == NULL) || 
+	    (self->client.state == IRLAN_IDLE)) 
+	{
 		self->client.tx_busy = FALSE;
 		dev_kfree_skb(skb);
 		return -1;
 	}
+	DEBUG(3, __FUNCTION__ "(), sending ...\n");
 
 	return irttp_data_request(self->client.tsap_ctrl, skb);
 }
@@ -656,6 +666,8 @@
  */
 void irlan_ctrl_data_request(struct irlan_cb *self, struct sk_buff *skb)
 {
+	DEBUG(2, __FUNCTION__ "()\n");
+
 	/* Queue command */
 	skb_queue_tail(&self->client.txq, skb);
 
@@ -764,7 +776,6 @@
 
 	irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
 
-	/* irttp_data_request(self->client.tsap_ctrl, skb); */
 	irlan_ctrl_data_request(self, skb);
 }
 
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c
--- v2.3.15/linux/net/irda/irlan/irlan_eth.c	Thu Aug 26 13:05:46 1999
+++ linux/net/irda/irlan/irlan_eth.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct 15 08:37:58 1998
- * Modified at:   Mon May 31 19:57:08 1999
+ * Modified at:   Sun Jun 20 20:23:33 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
@@ -252,9 +252,6 @@
 	struct irlan_cb *self;
 
 	self = (struct irlan_cb *) instance;
-
-	ASSERT(self != NULL, return 0;);
-	ASSERT(self->magic == IRLAN_MAGIC, return 0;);
 
 	if (skb == NULL) {
 		++self->stats.rx_dropped; 
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlan/irlan_provider.c linux/net/irda/irlan/irlan_provider.c
--- v2.3.15/linux/net/irda/irlan/irlan_provider.c	Sun May 30 10:27:04 1999
+++ linux/net/irda/irlan/irlan_provider.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Sun May  9 12:22:56 1999
+ * Modified at:   Wed Jun  9 11:03:29 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
@@ -439,8 +439,8 @@
  */
 int irlan_provider_open_ctrl_tsap(struct irlan_cb *self)
 {
-	struct notify_t notify;
 	struct tsap_cb *tsap;
+	notify_t notify;
 	
 	DEBUG(4, __FUNCTION__ "()\n");
 
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlap.c linux/net/irda/irlap.c
--- v2.3.15/linux/net/irda/irlap.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/irlap.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Mon May 31 21:43:55 1999
+ * Modified at:   Mon Aug 23 12:05:26 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -69,7 +69,7 @@
 
 #endif /* CONFIG_PROC_FS */
 
-__initfunc(int irlap_init(void))
+int __init irlap_init(void)
 {
 	/* Allocate master array */
 	irlap = hashbin_new(HB_LOCAL);
@@ -129,7 +129,7 @@
 
 	irlap_next_state(self, LAP_OFFLINE);
 
-	/* Initialize transmitt queue */
+	/* Initialize transmit queue */
 	skb_queue_head_init(&self->tx_list);
 	skb_queue_head_init(&self->wx_list);
 
@@ -360,11 +360,10 @@
  *
  */
 inline void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb,
-				int reliable)
+			       int reliable)
 {
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
-	ASSERT(skb != NULL, return;);
 
 #ifdef CONFIG_IRDA_COMPRESSION
 	if (self->qos_tx.compression.value) {
@@ -408,7 +407,7 @@
 		}
 		irlap_do_event(self, SEND_I_CMD, skb, NULL);
 	} else
-		skb_queue_tail(&self->tx_list, skb);	
+		skb_queue_tail(&self->tx_list, skb);
 }
 
 /*
@@ -423,6 +422,14 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 	
+	/* Don't disconnect until all data frames are successfully sent */
+	if (skb_queue_len(&self->tx_list) > 0) {
+		self->disconnect_pending = TRUE;
+		
+		return;
+	}
+
+	/* Check if we are in the right state for disconnecting */
 	switch (self->state) {
 	case LAP_XMIT_P:        /* FALLTROUGH */
 	case LAP_XMIT_S:        /* FALLTROUGH */
@@ -432,7 +439,7 @@
 		irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL);
 		break;
 	default:
-		DEBUG(0, __FUNCTION__ "(), disconnect pending!\n");
+		DEBUG(2, __FUNCTION__ "(), disconnect pending!\n");
 		self->disconnect_pending = TRUE;
 		break;
 	}
@@ -466,8 +473,8 @@
 	case LAP_DISC_INDICATION:  /* FALLTROUGH */
 	case LAP_FOUND_NONE:       /* FALLTROUGH */
 	case LAP_MEDIA_BUSY:
-		irlmp_link_disconnect_indication(self->notify.instance, 
-						  self, reason, NULL);
+		irlmp_link_disconnect_indication(self->notify.instance, self, 
+						 reason, NULL);
 		break;
 	default:
 		DEBUG(1, __FUNCTION__ "(), Reason %d not implemented!\n", 
@@ -495,11 +502,16 @@
 	       (discovery->nslots == 8) || (discovery->nslots == 16), 
 	       return;);
 	
+	/* Check if last discovery request finished in time */
+	if (self->discovery_log != NULL) {
+		hashbin_delete(self->discovery_log, (FREE_FUNC) kfree);
+		self->discovery_log = NULL;
+	}
+
   	/*
 	 *  Discovery is only possible in NDM mode
 	 */ 
 	if (self->state == LAP_NDM) {
-		ASSERT(self->discovery_log == NULL, return;);
 		self->discovery_log= hashbin_new(HB_LOCAL);
 		
 		info.S = discovery->nslots; /* Number of slots */
@@ -557,11 +569,6 @@
 	
 	/* Inform IrLMP */
 	irlmp_link_discovery_confirm(self->notify.instance, discovery_log);
-	
-	/* 
-	 *  IrLMP has now the responsibilities for the discovery_log 
-	 */
-	self->discovery_log = NULL;
 }
 
 /*
@@ -591,7 +598,7 @@
  */
 void irlap_status_indication(int quality_of_link) 
 {
-	switch(quality_of_link) {
+	switch (quality_of_link) {
 	case STATUS_NO_ACTIVITY:
 		printk(KERN_INFO "IrLAP, no activity on link!\n");
 		break;
@@ -666,16 +673,10 @@
 	struct sk_buff *skb = NULL;
 	int count = 0;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LAP_MAGIC, return;);
-
 	/*
          * Remove all the ack-ed frames from the window queue.
          */
 
-	DEBUG(4, "--> wx_list=%d, va=%d, nr=%d\n", 
-	       skb_queue_len(&self->wx_list), self->va, nr);
-
 	/* 
 	 *  Optimize for the common case. It is most likely that the receiver
 	 *  will acknowledge all the frames we have sent! So in that case we
@@ -683,7 +684,7 @@
 	 */
 	if (nr == self->vs) {
 		while ((skb = skb_dequeue(&self->wx_list)) != NULL) {
-		     dev_kfree_skb(skb);
+			dev_kfree_skb(skb);
 		}
 		/* The last acked frame is the next to send minus one */
 		self->va = nr - 1;
@@ -698,10 +699,6 @@
 			self->va = (self->va + 1) % 8;
 			count++;
 		}
-		
-		DEBUG(4, "irlap_update_nr_received(), removed %d\n", count);
-		DEBUG(4, "wx_list=%d, va=%d, nr=%d -->\n", 
-		       skb_queue_len(&self->wx_list), self->va, nr);
 	}
 	
 	/* Advance window */
@@ -715,20 +712,15 @@
  */
 int irlap_validate_ns_received(struct irlap_cb *self, int ns) 
 {
-	ASSERT(self != NULL, return -ENODEV;);
-	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
-
 	/*  ns as expected?  */
-	if (ns == self->vr) {
-		DEBUG(4, __FUNCTION__ "(), expected!\n");
+	if (ns == self->vr)
 		return NS_EXPECTED;
-	}
 	/*
 	 *  Stations are allowed to treat invalid NS as unexpected NS
 	 *  IrLAP, Recv ... with-invalid-Ns. p. 84
 	 */
 	return NS_UNEXPECTED;
-
+	
 	/* return NR_INVALID; */
 }
 /*
@@ -739,9 +731,6 @@
  */
 int irlap_validate_nr_received(struct irlap_cb *self, int nr) 
 {
-	ASSERT(self != NULL, return -ENODEV;);
-	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
-
 	/*  nr as expected?  */
 	if (nr == self->vs) {
 		DEBUG(4, __FUNCTION__ "(), expected!\n");
@@ -858,7 +847,7 @@
  *    Change the speed of the IrDA port
  *
  */
-void irlap_change_speed(struct irlap_cb *self, int speed)
+void irlap_change_speed(struct irlap_cb *self, __u32 speed)
 {
 	DEBUG(4, __FUNCTION__ "(), setting speed to %d\n", speed);
 
@@ -1079,6 +1068,24 @@
 		irlap_compressor_init(self, 0);
 	}
 #endif
+}
+
+/*
+ * Function irlap_set_local_busy (self, status)
+ *
+ *    
+ *
+ */
+void irlap_set_local_busy(struct irlap_cb *self, int status)
+{
+	DEBUG(0, __FUNCTION__ "()\n");
+
+	self->local_busy = status;
+	
+	if (status)
+		DEBUG(0, __FUNCTION__ "(), local busy ON\n");
+	else
+		DEBUG(0, __FUNCTION__ "(), local busy OFF\n");
 }
 
 #ifdef CONFIG_PROC_FS
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.3.15/linux/net/irda/irlap_event.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/irlap_event.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Mon May 31 21:55:42 1999
+ * Modified at:   Wed Aug 25 14:49:47 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
@@ -37,6 +37,7 @@
 #include <net/irda/irlap.h>
 #include <net/irda/irlap_frame.h>
 #include <net/irda/qos.h>
+#include <net/irda/parameters.h>
 
 #include <net/irda/irda_device.h>
 
@@ -152,7 +153,7 @@
  *    Poll timer has expired. Normally we must now send a RR frame to the
  *    remote device
  */
-static void irlap_poll_timer_expired(unsigned long data)
+static void irlap_poll_timer_expired(void *data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
 	
@@ -168,7 +169,11 @@
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
 #ifdef CONFIG_IRDA_FAST_RR
-	if (skb_queue_len(&self->tx_list) == 0) {
+	/* 
+	 * Send out the RR frames faster if our own transmit queue is empty, or
+	 * if the peer is busy. The effect is a much faster conversation
+	 */
+	if ((skb_queue_len(&self->tx_list) == 0) || (self->remote_busy)) {
 		if (self->fast_RR == TRUE) {
 			/*
 			 *  Assert that the fast poll timer has not reached the
@@ -179,7 +184,8 @@
 				 *  FIXME: this should be a more configurable
 				 *         function
 				 */
-				self->fast_RR_timeout += (sysctl_fast_poll_increase * HZ/1000);
+				self->fast_RR_timeout += 
+					(sysctl_fast_poll_increase * HZ/1000);
 
 				/* Use this fast(er) timeout instead */
 				timeout = self->fast_RR_timeout;
@@ -199,8 +205,8 @@
 	if (timeout == 0)
 		irlap_do_event(self, POLL_TIMER_EXPIRED, NULL, NULL);
 	else
-		irda_start_timer(&self->poll_timer, timeout, 
-				 (unsigned long) self, irlap_poll_timer_expired);
+		irda_start_timer(&self->poll_timer, timeout, self, 
+				 irlap_poll_timer_expired);
 }
 
 /*
@@ -220,7 +226,7 @@
   	DEBUG(4, __FUNCTION__ "(), event = %s, state = %s\n", 
 	      irlap_event[event], irlap_state[self->state]); 
 	
-	ret = (*state[ self->state]) (self, event, skb, info);
+	ret = (*state[self->state])(self, event, skb, info);
 	
 	/* 
 	 *  Check if there are any pending events that needs to be executed
@@ -238,7 +244,7 @@
 			while ((skb = skb_dequeue(&self->tx_list)) != NULL) {
 				ret = (*state[self->state])(self, SEND_I_CMD,
 							    skb, NULL);
-				if ( ret == -EPROTO)
+				if (ret == -EPROTO)
 					break; /* Try again later! */
 			}
 		} else if (self->disconnect_pending) {
@@ -298,37 +304,37 @@
  *    NDM (Normal Disconnected Mode) state
  *
  */
-static int irlap_state_ndm( struct irlap_cb *self, IRLAP_EVENT event, 
-			    struct sk_buff *skb,  struct irlap_info *info) 
+static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event, 
+			   struct sk_buff *skb, struct irlap_info *info) 
 {
 	discovery_t *discovery_rsp;
 	int ret = 0;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
 
-	switch(event) {
+	switch (event) {
 	case CONNECT_REQUEST:
-		ASSERT( self->irdev != NULL, return -1;);
+		ASSERT(self->irdev != NULL, return -1;);
 
 		if (irda_device_is_media_busy(self->irdev)) {
-			DEBUG( 0, __FUNCTION__
+			DEBUG(0, __FUNCTION__
 			      "(), CONNECT_REQUEST: media busy!\n");
 			
 			/* Always switch state before calling upper layers */
-			irlap_next_state( self, LAP_NDM);
+			irlap_next_state(self, LAP_NDM);
 			
-			irlap_disconnect_indication( self, LAP_MEDIA_BUSY);
+			irlap_disconnect_indication(self, LAP_MEDIA_BUSY);
 		} else {
-			irlap_send_snrm_frame( self, &self->qos_rx);
+			irlap_send_snrm_frame(self, &self->qos_rx);
 			
 			/* Start Final-bit timer */
 			irlap_start_final_timer(self, self->final_timeout);
 
 			self->retry_count = 0;
-			irlap_next_state( self, LAP_SETUP);
+			irlap_next_state(self, LAP_SETUP);
 		}
 		break;
 
@@ -336,13 +342,13 @@
 		self->daddr = info->daddr;
 		self->caddr = info->caddr;
 		
-		irlap_next_state( self, LAP_CONN);
+		irlap_next_state(self, LAP_CONN);
 
-		irlap_connect_indication( self, skb);
+		irlap_connect_indication(self, skb);
 		break;
 
 	case DISCOVERY_REQUEST:		
-		ASSERT( info != NULL, return -1;);
+		ASSERT(info != NULL, return -1;);
 
 	 	if (irda_device_is_media_busy(self->irdev)) {
  			DEBUG(0, __FUNCTION__ "(), media busy!\n"); 
@@ -370,17 +376,17 @@
 		ASSERT( info != NULL, return -1;);
 
 		/* Assert that this is not the final slot */
-		if ( info->s <= info->S) {
+		if (info->s <= info->S) {
 			/* self->daddr = info->daddr;  */
 			self->slot = irlap_generate_rand_time_slot(info->S,
 								   info->s);
-			DEBUG( 4, "XID_CMD: S=%d, s=%d, slot %d\n", info->S, 
-			       info->s, self->slot);
+			DEBUG(4, "XID_CMD: S=%d, s=%d, slot %d\n", info->S, 
+			      info->s, self->slot);
 
-			if ( self->slot == info->s) {
+			if (self->slot == info->s) {
 				discovery_rsp = irlmp_get_discovery_response();
 				discovery_rsp->daddr = info->daddr;
-
+				
 				irlap_send_discovery_xid_frame(self, info->S, 
 							       self->slot, 
 							       FALSE,
@@ -389,14 +395,23 @@
 			} else
 				self->frame_sent = FALSE;
 			
-			irlap_start_query_timer( self, QUERY_TIMEOUT);
-			irlap_next_state( self, LAP_REPLY);
+			/* 
+			 * Remember to multiply the query timeout value with 
+			 * the number of slots used
+			 */
+			irlap_start_query_timer(self, QUERY_TIMEOUT*info->S);
+			irlap_next_state(self, LAP_REPLY);
 		}
 		dev_kfree_skb(skb);
 		break;
-
 	case RECV_TEST_CMD:
+		/* Remove test frame header */
 		skb_pull(skb, sizeof(struct test_frame));
+
+		/* 
+		 * Send response. This skb will not be sent out again, and
+		 * will only be used to send out the same info as the cmd
+		 */
 		irlap_send_test_frame(self, info->daddr, skb);
 		dev_kfree_skb(skb);
 		break;
@@ -405,7 +420,7 @@
 		dev_kfree_skb(skb);
 		break;
 	default:
-		DEBUG(2, __FUNCTION__ "(), Unknown event %s", 
+		DEBUG(2, __FUNCTION__ "(), Unknown event %s\n", 
 		      irlap_event[event]);
 		ret = -1;
 		break;
@@ -419,30 +434,36 @@
  *    QUERY state
  *
  */
-static int irlap_state_query( struct irlap_cb *self, IRLAP_EVENT event, 
-			      struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event, 
+			     struct sk_buff *skb, struct irlap_info *info) 
 {
 	int ret = 0;
 
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
 
-	switch( event) {
+	switch(event) {
 	case RECV_DISCOVERY_XID_RSP:
-		ASSERT( info != NULL, return -1;);
-		ASSERT( info->discovery != NULL, return -1;);
+		ASSERT(info != NULL, return -1;);
+		ASSERT(info->discovery != NULL, return -1;);
 
 		DEBUG(4, __FUNCTION__ "(), daddr=%08x\n", 
 		      info->discovery->daddr);
 
-		hashbin_insert( self->discovery_log, 
-				(QUEUE *) info->discovery,
-				info->discovery->daddr, NULL);
+		if (!self->discovery_log) {
+			WARNING(__FUNCTION__ "(), discovery log is gone! "
+				"maybe the discovery timeout has been set to "
+				"short?\n");
+			break;
+		}
+		hashbin_insert(self->discovery_log, 
+			       (QUEUE *) info->discovery,
+			       info->discovery->daddr, NULL);
 
 		dev_kfree_skb(skb);
 
 		/* Keep state */
-		irlap_next_state( self, LAP_QUERY); 
+		irlap_next_state(self, LAP_QUERY); 
 		break;
 	case SLOT_TIMER_EXPIRED:
 		if (self->s < self->S) {
@@ -468,6 +489,9 @@
 			 *  so now we must return the results
 			 */
 			irlap_discovery_confirm(self, self->discovery_log);
+
+			/* IrLMP should now have taken care of the log */
+			self->discovery_log = NULL;
 		}
 		break;
 	default:
@@ -570,7 +594,8 @@
 		skb_pull(skb, sizeof(struct snrm_frame));
 
 		ASSERT(self->irdev != NULL, return -1;);
-		irda_qos_negotiate(&self->qos_rx, &self->qos_tx, skb);
+
+		irlap_qos_negotiate(self, skb);
 
 		irlap_initiate_connection_state( self);
 
@@ -625,44 +650,45 @@
  *    a remote peer layer and is awaiting a reply .
  *
  */
-static int irlap_state_setup( struct irlap_cb *self, IRLAP_EVENT event, 
-			      struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event, 
+			     struct sk_buff *skb, struct irlap_info *info) 
 {
 	int ret = 0;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
 
-	switch( event) {
+	switch(event) {
 	case FINAL_TIMER_EXPIRED:
-		if ( self->retry_count < self->N3) {
+		if (self->retry_count < self->N3) {
 /* 
  *  Perform random backoff, Wait a random number of time units, minimum 
  *  duration half the time taken to transmitt a SNRM frame, maximum duration 
  *  1.5 times the time taken to transmit a SNRM frame. So this time should 
  *  between 15 msecs and 45 msecs.
  */
-			irlap_start_backoff_timer( self, 2 + (jiffies % 3));
+			irlap_start_backoff_timer(self, MSECS_TO_JIFFIES(20 + 
+						        (jiffies % 30)));
 		} else {
 			/* Always switch state before calling upper layers */
-			irlap_next_state( self, LAP_NDM);
+			irlap_next_state(self, LAP_NDM);
 
-			irlap_disconnect_indication( self, LAP_FOUND_NONE);
+			irlap_disconnect_indication(self, LAP_FOUND_NONE);
 		}
 		break;
 	case BACKOFF_TIMER_EXPIRED:
-		irlap_send_snrm_frame( self, &self->qos_rx);
-		irlap_start_final_timer( self, self->final_timeout);
+		irlap_send_snrm_frame(self, &self->qos_rx);
+		irlap_start_final_timer(self, self->final_timeout);
 		self->retry_count++;
 		break;
 
 	case RECV_SNRM_CMD:
-		DEBUG( 4, __FUNCTION__ "(), SNRM battle!\n");
+		DEBUG(4, __FUNCTION__ "(), SNRM battle!\n");
 
-		ASSERT( skb != NULL, return 0;);
-		ASSERT( info != NULL, return 0;);
+		ASSERT(skb != NULL, return 0;);
+		ASSERT(info != NULL, return 0;);
 
 		/*
 		 *  The device with the largest device address wins the battle
@@ -673,9 +699,10 @@
 			irlap_initiate_connection_state(self);
 
 			ASSERT(self->irdev != NULL, return -1;);
-			/* skb_pull(skb, 11); */
+
 			skb_pull(skb, sizeof(struct snrm_frame));
-			irda_qos_negotiate(&self->qos_rx, &self->qos_tx, skb);
+
+			irlap_qos_negotiate(self, skb);
 			
 			irlap_send_ua_response_frame(self, &self->qos_rx);
 			irlap_apply_connection_parameters(self, &self->qos_tx);
@@ -696,36 +723,37 @@
 		break;
 	case RECV_UA_RSP:
 		/* Stop F-timer */
-		del_timer( &self->final_timer);
+		del_timer(&self->final_timer);
 
 		/* Initiate connection state */
-		irlap_initiate_connection_state( self);
+		irlap_initiate_connection_state(self);
 
 		/* Negotiate connection parameters */
-		ASSERT( skb->len > 10, return -1;);
-		/* skb_pull(skb, 10); */
+		ASSERT(skb->len > 10, return -1;);
+
 		skb_pull(skb, sizeof(struct ua_frame));
 
 		ASSERT(self->irdev != NULL, return -1;);
-		irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb);
 
-		irlap_apply_connection_parameters( self, &self->qos_tx); 
+		irlap_qos_negotiate(self, skb);
+
+		irlap_apply_connection_parameters(self, &self->qos_tx); 
 		self->retry_count = 0;
 		
 		/* This frame will just be sent at the old speed */
 		/* irlap_send_rr_frame( self, CMD_FRAME); */
 
-		irlap_start_final_timer( self, self->final_timeout/2);
-		irlap_next_state( self, LAP_NRM_P);
+		irlap_start_final_timer(self, self->final_timeout/2);
+		irlap_next_state(self, LAP_NRM_P);
 
-		irlap_connect_confirm( self, skb);
+		irlap_connect_confirm(self, skb);
 		break;
 
 	case RECV_DISC_FRAME:
-		del_timer( &self->final_timer);
-		irlap_next_state( self, LAP_NDM);
+		del_timer(&self->final_timer);
+		irlap_next_state(self, LAP_NDM);
 
-		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
 		break;
 
        /* DM handled in irlap_frame.c, irlap_input() */
@@ -744,8 +772,8 @@
  *    OFFLINE state, not used for now!
  *
  */
-static int irlap_state_offline( struct irlap_cb *self, IRLAP_EVENT event, 
-				struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_offline(struct irlap_cb *self, IRLAP_EVENT event, 
+			       struct sk_buff *skb, struct irlap_info *info) 
 {
 	DEBUG( 0, __FUNCTION__ "(), Unknown event\n");
 
@@ -765,9 +793,6 @@
 {
 	int ret = 0;
 	
-	DEBUG(4, __FUNCTION__ "(), event=%s, vs=%d, vr=%d", 
-	      irlap_event[event], self->vs, self->vr);
-		
 	switch (event) {
 	case SEND_I_CMD:
 		/*
@@ -801,14 +826,14 @@
 			 *  Send data with poll bit cleared only if window > 1
 			 *  and there is more frames after this one to be sent
 			 */
-			if (( self->window > 1) && 
+			if ((self->window > 1) && 
 			    skb_queue_len( &self->tx_list) > 0) 
 			{   
-				irlap_send_data_primary( self, skb);
-				irlap_next_state( self, LAP_XMIT_P);
+				irlap_send_data_primary(self, skb);
+				irlap_next_state(self, LAP_XMIT_P);
 			} else {
-				irlap_send_data_primary_poll( self, skb);
-				irlap_next_state( self, LAP_NRM_P);
+				irlap_send_data_primary_poll(self, skb);
+				irlap_next_state(self, LAP_NRM_P);
 				
 				/* 
 				 * Make sure state machine does not try to send
@@ -821,8 +846,8 @@
 			self->fast_RR = FALSE;
 #endif
 		} else {
-			DEBUG( 4, __FUNCTION__ 
-			       "(), Unable to send! remote busy?\n");
+			DEBUG(4, __FUNCTION__ 
+			      "(), Unable to send! remote busy?\n");
 			skb_queue_head(&self->tx_list, skb);
 
 			/*
@@ -849,6 +874,10 @@
 	default:
 		DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
 		      irlap_event[event]);
+
+		if (skb)
+			dev_kfree_skb(skb);
+
 		ret = -EINVAL;
 		break;
 	}
@@ -860,44 +889,44 @@
  *
  *    PCLOSE state
  */
-static int irlap_state_pclose( struct irlap_cb *self, IRLAP_EVENT event, 
-			       struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_pclose(struct irlap_cb *self, IRLAP_EVENT event, 
+			      struct sk_buff *skb, struct irlap_info *info) 
 {
 	int ret = 0;
 
 	DEBUG(1, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);	
 
-	switch( event) {
+	switch (event) {
 	case RECV_UA_RSP:
-		del_timer( &self->final_timer);
+		del_timer(&self->final_timer);
 		
-		irlap_apply_default_connection_parameters( self);
+		irlap_apply_default_connection_parameters(self);
 
 		/* Always switch state before calling upper layers */
-		irlap_next_state( self, LAP_NDM);
+		irlap_next_state(self, LAP_NDM);
 
-		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
 
 		break;
 	case FINAL_TIMER_EXPIRED:
-		if ( self->retry_count < self->N3) {
-			irlap_wait_min_turn_around( self, &self->qos_tx);
-			irlap_send_disc_frame( self);
-			irlap_start_final_timer( self, self->final_timeout);
+		if (self->retry_count < self->N3) {
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_disc_frame(self);
+			irlap_start_final_timer(self, self->final_timeout);
 			self->retry_count++;
 			/* Keep state */
 		} else {
-			irlap_apply_default_connection_parameters( self);
+			irlap_apply_default_connection_parameters(self);
 
 			/* 
 			 *  Always switch state before calling upper layers 
 			 */
-			irlap_next_state( self, LAP_NDM);
+			irlap_next_state(self, LAP_NDM);
 
-			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+			irlap_disconnect_indication(self, LAP_NO_RESPONSE);
 		}
 		break;
 	default:
@@ -995,8 +1024,8 @@
 		 */
 		if ((ns_status == NS_UNEXPECTED) && (nr_status == NR_EXPECTED))
 		{
-			if ( !info->pf) {
-				irlap_update_nr_received( self, info->nr);
+			if (!info->pf) {
+				irlap_update_nr_received(self, info->nr);
 				
 				/*
 				 *  Wait until the last frame before doing 
@@ -1004,23 +1033,23 @@
 				 */
 
 				/* Keep state */
-				irlap_next_state( self, LAP_NRM_P);
+				irlap_next_state(self, LAP_NRM_P);
 			} else {
 				DEBUG( 4, __FUNCTION__
 				       "(), missing or duplicate frame!\n");
 				
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 				
-				irlap_wait_min_turn_around( self, &self->qos_tx);
-				irlap_send_rr_frame( self, CMD_FRAME);
+				irlap_wait_min_turn_around(self, &self->qos_tx);
+				irlap_send_rr_frame(self, CMD_FRAME);
 				
 				self->ack_required = FALSE;
 			
-				irlap_start_final_timer( self, self->final_timeout);
-				irlap_next_state( self, LAP_NRM_P);
+				irlap_start_final_timer(self, self->final_timeout);
+				irlap_next_state(self, LAP_NRM_P);
 			}
-			dev_kfree_skb( skb);
+			dev_kfree_skb(skb);
 			break;
 		}
 		/* 
@@ -1028,22 +1057,22 @@
 		 */
 		if ((ns_status == NS_EXPECTED) && (nr_status == NR_UNEXPECTED))
 		{
-			if ( info->pf) {
+			if (info->pf) {
 				self->vr = (self->vr + 1) % 8;
 			
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 			
 				/* Resend rejected frames */
-				irlap_resend_rejected_frames( self, CMD_FRAME);
+				irlap_resend_rejected_frames(self, CMD_FRAME);
 				
 				self->ack_required = FALSE;
-				irlap_start_final_timer( self, self->final_timeout);
+				irlap_start_final_timer(self, self->final_timeout);
 				
 				/* Keep state, do not move this line */
-				irlap_next_state( self, LAP_NRM_P);
+				irlap_next_state(self, LAP_NRM_P);
 				
-				irlap_data_indication( self, skb);
+				irlap_data_indication(self, skb);
 			} else {
 				/* 
 				 *  Do not resend frames until the last
@@ -1054,14 +1083,14 @@
 				self->vr = (self->vr + 1) % 8;
 
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 				
 				self->ack_required = FALSE;
 
 				/* Keep state, do not move this line!*/
-				irlap_next_state( self, LAP_NRM_P); 
+				irlap_next_state(self, LAP_NRM_P); 
 				
-				irlap_data_indication( self, skb);
+				irlap_data_indication(self, skb);
 			}
 			break;
 		}
@@ -1073,15 +1102,15 @@
 		    (nr_status == NR_UNEXPECTED)) 
 		{
 			DEBUG( 4, "IrLAP: unexpected nr and ns!\n");
-			if ( info->pf) {
+			if (info->pf) {
 				/* Resend rejected frames */
-				irlap_resend_rejected_frames( self, CMD_FRAME);
+				irlap_resend_rejected_frames(self, CMD_FRAME);
 				
 				/* Give peer some time to retransmit! */
-				irlap_start_final_timer( self, self->final_timeout);
+				irlap_start_final_timer(self, self->final_timeout);
 
 				/* Keep state, do not move this line */
-				irlap_next_state( self, LAP_NRM_P);
+				irlap_next_state(self, LAP_NRM_P);
 			} else {
 				/* Update Nr received */
 				/* irlap_update_nr_received( info->nr); */
@@ -1158,63 +1187,65 @@
 			/* Start poll timer */
 			irlap_start_poll_timer(self, self->poll_timeout);
 		} else if (ret == NR_UNEXPECTED) {
-			ASSERT( info != NULL, return -1;);	
+			ASSERT(info != NULL, return -1;);	
 			/* 
 			 *  Unexpected nr! 
 			 */
 			
 			/* Update Nr received */
-			irlap_update_nr_received( self, info->nr);
+			irlap_update_nr_received(self, info->nr);
 
-			DEBUG( 4, "RECV_RR_FRAME: Retrans:%d, nr=%d, va=%d, "
-			       "vs=%d, vr=%d\n",
-			       self->retry_count, info->nr, self->va, 
-			       self->vs, self->vr);
+			DEBUG(4, "RECV_RR_FRAME: Retrans:%d, nr=%d, va=%d, "
+			      "vs=%d, vr=%d\n",
+			      self->retry_count, info->nr, self->va, 
+			      self->vs, self->vr);
 			
 			/* Resend rejected frames */
-			irlap_resend_rejected_frames( self, CMD_FRAME);
+			irlap_resend_rejected_frames(self, CMD_FRAME);
 			
-			irlap_next_state( self, LAP_NRM_P);
+			irlap_next_state(self, LAP_NRM_P);
 		} else if (ret == NR_INVALID) {
-			DEBUG(1, "irlap_state_nrm_p: received RR with "
+			DEBUG(1, __FUNCTION__ "(), Received RR with "
 			      "invalid nr !\n");
-			del_timer( &self->final_timer);
+			del_timer(&self->final_timer);
 
-			irlap_next_state( self, LAP_RESET_WAIT);
+			irlap_next_state(self, LAP_RESET_WAIT);
 
 			irlap_disconnect_indication(self, LAP_RESET_INDICATION);
 			self->xmitflag = TRUE;
 		}
 		if (skb)
-			dev_kfree_skb( skb);
+			dev_kfree_skb(skb);
 		break;
 	case RECV_RNR_FRAME:
-		DEBUG( 4, "irlap_state_nrm_p: RECV_RNR_FRAME: Retrans:%d, "
-		       "nr=%d, va=%d, vs=%d, vr=%d\n",
-		       self->retry_count, info->nr, self->va, self->vs, 
-		       self->vr);
+		DEBUG(4, "irlap_state_nrm_p: RECV_RNR_FRAME: Retrans:%d, "
+		      "nr=%d, va=%d, vs=%d, vr=%d\n",
+		      self->retry_count, info->nr, self->va, self->vs, 
+		      self->vr);
 
-		ASSERT( info != NULL, return -1;);
+		ASSERT(info != NULL, return -1;);
 
 		/* Stop final timer */
-		del_timer( &self->final_timer);
+		del_timer(&self->final_timer);
 		self->remote_busy = TRUE;
 
 		/* Update Nr received */
-		irlap_update_nr_received( self, info->nr);
+		irlap_update_nr_received(self, info->nr);
 
-		irlap_next_state( self, LAP_XMIT_P);
+		irlap_next_state(self, LAP_XMIT_P);
 			
 		/* Start poll timer */
-		irlap_start_poll_timer( self, self->poll_timeout);
-
-		dev_kfree_skb( skb);
+		irlap_start_poll_timer(self, self->poll_timeout);
+		if (skb)
+			dev_kfree_skb(skb);
 		break;
 	case RECV_FRMR_RSP:
-		del_timer( &self->final_timer);
+		del_timer(&self->final_timer);
 		self->xmitflag = TRUE;
-		irlap_next_state( self, LAP_RESET_WAIT);
-		irlap_reset_indication( self);
+		irlap_next_state(self, LAP_RESET_WAIT);
+		irlap_reset_indication(self);
+		if (skb)
+			dev_kfree_skb(skb);
 		break;
 	case FINAL_TIMER_EXPIRED:
 		/* 
@@ -1223,11 +1254,10 @@
 		 *  of receiving a frame (page 45, IrLAP). Check that
 		 *  we only do this once for each frame.
 		 */
-		if ( irda_device_is_receiving( self->irdev) && 
-		     !self->add_wait) {
-			DEBUG( 4, "FINAL_TIMER_EXPIRED when receiving a "
-			       "frame! Waiting a little bit more!\n");
-			irlap_start_final_timer( self, 30);
+		if (irda_device_is_receiving(self->irdev) && !self->add_wait) {
+			DEBUG(4, "FINAL_TIMER_EXPIRED when receiving a "
+			      "frame! Waiting a little bit more!\n");
+			irlap_start_final_timer(self, MSECS_TO_JIFFIES(300));
 
 			/*
 			 *  Don't allow this to happen one more time in a row, 
@@ -1239,60 +1269,64 @@
 		}
 		self->add_wait = FALSE;
 
-		if (( self->retry_count < self->N2) && 
-		    ( self->retry_count != self->N1)) {
+		if ((self->retry_count < self->N2) && 
+		    (self->retry_count != self->N1)) {
 			
-			irlap_wait_min_turn_around( self, &self->qos_tx);
-			irlap_send_rr_frame( self, CMD_FRAME);
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_rr_frame(self, CMD_FRAME);
 			
-			irlap_start_final_timer( self, self->final_timeout);
+			irlap_start_final_timer(self, self->final_timeout);
 		 	self->retry_count++;
 
-			DEBUG( 4, "irlap_state_nrm_p: FINAL_TIMER_EXPIRED:"
-			       " retry_count=%d\n", self->retry_count);
+			DEBUG(4, "irlap_state_nrm_p: FINAL_TIMER_EXPIRED:"
+			      " retry_count=%d\n", self->retry_count);
 			/* Keep state */
-		} else if ( self->retry_count == self->N1) {
-			irlap_status_indication( STATUS_NO_ACTIVITY);
-			irlap_wait_min_turn_around( self, &self->qos_tx);
-			irlap_send_rr_frame( self, CMD_FRAME);
+		} else if (self->retry_count == self->N1) {
+			irlap_status_indication(STATUS_NO_ACTIVITY);
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_rr_frame(self, CMD_FRAME);
 			
-			irlap_start_final_timer( self, self->final_timeout);
+			irlap_start_final_timer(self, self->final_timeout);
 			self->retry_count++;
 
-			DEBUG( 4, "retry count = N1; retry_count=%d\n", 
-			       self->retry_count);
+			DEBUG(4, "retry count = N1; retry_count=%d\n", 
+			      self->retry_count);
 			/* Keep state */
-		} else if ( self->retry_count >= self->N2) {
-			irlap_apply_default_connection_parameters( self);
+		} else if (self->retry_count >= self->N2) {
+			irlap_apply_default_connection_parameters(self);
 
 			/* Always switch state before calling upper layers */
-			irlap_next_state( self, LAP_NDM);
-			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+			irlap_next_state(self, LAP_NDM);
+			irlap_disconnect_indication(self, LAP_NO_RESPONSE);
 		}
 		break;
 	case RECV_DISC_FRAME: /* FIXME: Check how this is in the standard! */
 		DEBUG(1, __FUNCTION__ "(), RECV_DISC_FRAME()\n");
 
 		/* Always switch state before calling upper layers */
-		irlap_next_state( self, LAP_NDM);
+		irlap_next_state(self, LAP_NDM);
 		
-		irlap_wait_min_turn_around( self, &self->qos_tx);
-		irlap_send_ua_response_frame( self, NULL);
+		irlap_wait_min_turn_around(self, &self->qos_tx);
+		irlap_send_ua_response_frame(self, NULL);
 
- 		del_timer( &self->final_timer);
+ 		del_timer(&self->final_timer);
 		/* del_timer( &self->poll_timer); */
 
-		irlap_flush_all_queues( self);
-		irlap_apply_default_connection_parameters( self);
+		irlap_flush_all_queues(self);
+		irlap_apply_default_connection_parameters(self);
 
-		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
 		if (skb)
-			dev_kfree_skb( skb);
+			dev_kfree_skb(skb);
 		
 		break;
 	default:
 		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
 		      irlap_event[event]);
+
+		if (skb)
+			dev_kfree_skb(skb);
+
 		ret = -1;
 		break;
 	}
@@ -1311,21 +1345,21 @@
 {
 	int ret = 0;
 	
-	DEBUG( 3, __FUNCTION__ "(), event = %s\n", irlap_event[event]);
+	DEBUG(3, __FUNCTION__ "(), event = %s\n", irlap_event[event]);
 	
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
 	
-	switch( event) {
+	switch (event) {
 	case RESET_REQUEST:
-		if ( self->xmitflag) {
-			irlap_wait_min_turn_around( self, &self->qos_tx);
-			irlap_send_snrm_frame( self, NULL);
-			irlap_start_final_timer( self, self->final_timeout);
-			irlap_next_state( self, LAP_RESET);
+		if (self->xmitflag) {
+			irlap_wait_min_turn_around(self, &self->qos_tx);
+			irlap_send_snrm_frame(self, NULL);
+			irlap_start_final_timer(self, self->final_timeout);
+			irlap_next_state(self, LAP_RESET);
 		} else {
-			irlap_start_final_timer( self, self->final_timeout);
-			irlap_next_state( self, LAP_RESET);
+			irlap_start_final_timer(self, self->final_timeout);
+			irlap_next_state(self, LAP_RESET);
 		}
 		break;
 	case DISCONNECT_REQUEST:
@@ -1352,8 +1386,8 @@
  *    reply.
  *
  */
-static int irlap_state_reset( struct irlap_cb *self, IRLAP_EVENT event, 
-			      struct sk_buff *skb, struct irlap_info *info)
+static int irlap_state_reset(struct irlap_cb *self, IRLAP_EVENT event, 
+			     struct sk_buff *skb, struct irlap_info *info)
 {
 	int ret = 0;
 	
@@ -1362,66 +1396,64 @@
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LAP_MAGIC, return -1;);
 	
-	switch(event) {
+	switch (event) {
 	case RECV_DISC_FRAME:
 		del_timer(&self->final_timer);
 
-		irlap_apply_default_connection_parameters( self);
+		irlap_apply_default_connection_parameters(self);
 
 		/* Always switch state before calling upper layers */
-		irlap_next_state( self, LAP_NDM);
+		irlap_next_state(self, LAP_NDM);
 
-		irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+		irlap_disconnect_indication(self, LAP_NO_RESPONSE);
 		break;
 	case RECV_UA_RSP:
-		del_timer( &self->final_timer);
+		del_timer(&self->final_timer);
 		
 		/* Initiate connection state */
-		irlap_initiate_connection_state( self);
+		irlap_initiate_connection_state(self);
 		
 		irlap_reset_confirm();
 		
 		self->remote_busy = FALSE;
 
-		irlap_next_state( self, LAP_XMIT_P);
+		irlap_next_state(self, LAP_XMIT_P);
 
-		irlap_start_poll_timer( self, self->poll_timeout);
+		irlap_start_poll_timer(self, self->poll_timeout);
 		break;
 	case FINAL_TIMER_EXPIRED:
-		if ( self->retry_count < 3) {
-			irlap_wait_min_turn_around( self, &self->qos_tx);
+		if (self->retry_count < 3) {
+			irlap_wait_min_turn_around(self, &self->qos_tx);
 
-			ASSERT( self->irdev != NULL, return -1;);
+			ASSERT(self->irdev != NULL, return -1;);
 			irlap_send_snrm_frame(self, 
-					      irda_device_get_qos( self->irdev));
+					      irda_device_get_qos(self->irdev));
 
 			self->retry_count++; /* Experimental!! */
 
-			irlap_start_final_timer( self, self->final_timeout);
-			irlap_next_state( self, LAP_RESET);
-		} else if ( self->retry_count >= self->N3) {
-			irlap_apply_default_connection_parameters( self);
+			irlap_start_final_timer(self, self->final_timeout);
+			irlap_next_state(self, LAP_RESET);
+		} else if (self->retry_count >= self->N3) {
+			irlap_apply_default_connection_parameters(self);
 			
 			/* Always switch state before calling upper layers */
-			irlap_next_state( self, LAP_NDM);
+			irlap_next_state(self, LAP_NDM);
 			
-			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+			irlap_disconnect_indication(self, LAP_NO_RESPONSE);
 		}
 		break;
-
 	case RECV_SNRM_CMD:
-		DEBUG(3, "lap_reset: RECV_SNRM_CMD\n");
-		irlap_initiate_connection_state( self);
-		irlap_wait_min_turn_around( self, &self->qos_tx);
-		irlap_send_ua_response_frame( self, &self->qos_rx);
+		DEBUG(3, __FUNCTION__ "(), RECV_SNRM_CMD\n");
+		irlap_initiate_connection_state(self);
+		irlap_wait_min_turn_around(self, &self->qos_tx);
+		irlap_send_ua_response_frame(self, &self->qos_rx);
 		irlap_reset_confirm();
-		irlap_start_wd_timer( self, self->wd_timeout);
-		irlap_next_state( self, LAP_NDM);
+		irlap_start_wd_timer(self, self->wd_timeout);
+		irlap_next_state(self, LAP_NDM);
 		break;
-
 	default:
 		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[ event]);
+		      irlap_event[event]);
 		ret = -1;
 		break;	
 	}
@@ -1435,17 +1467,17 @@
  *   and we therefor do not expect to receive any transmissions from other
  *   stations.  
  */
-static int irlap_state_xmit_s( struct irlap_cb *self, IRLAP_EVENT event, 
-			       struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event, 
+			      struct sk_buff *skb, struct irlap_info *info) 
 {
 	int ret = 0;
 	
-	DEBUG( 4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
+	DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
 
-	ASSERT( self != NULL, return -ENODEV;);
-	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+	ASSERT(self != NULL, return -ENODEV;);
+	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
 	
-	switch( event) {
+	switch (event) {
 	case SEND_I_CMD:
 		/*
 		 *  Send frame only if send window > 1
@@ -1458,31 +1490,31 @@
 			 */
 			if ((skb->len+self->bofs_count) > self->bytes_left) {
 				DEBUG( 4, "IrDA: Not allowed to transmit more bytes!\n");
-				skb_queue_head( &self->tx_list, skb);
+				skb_queue_head(&self->tx_list, skb);
 				/*
 				 *  Switch to NRM_S, this is only possible
 				 *  when we are in secondary mode, since we 
 				 *  must be sure that we don't miss any RR
 				 *  frames
 				 */
-				irlap_next_state( self, LAP_NRM_S);
+				irlap_next_state(self, LAP_NRM_S);
 
 				return -EPROTO; /* Try again later */
 			}
-			self->bytes_left -= ( skb->len + self->bofs_count);
+			self->bytes_left -= (skb->len + self->bofs_count);
 
 			/*
 			 *  Send data with final bit cleared only if window > 1
 			 *  and there is more frames to be sent
 			 */
-			if (( self->window > 1) && 
-			    skb_queue_len( &self->tx_list) > 0) 
+			if ((self->window > 1) && 
+			    skb_queue_len(&self->tx_list) > 0) 
 			{   
-				irlap_send_data_secondary( self, skb);
-				irlap_next_state( self, LAP_XMIT_S);
+				irlap_send_data_secondary(self, skb);
+				irlap_next_state(self, LAP_XMIT_S);
 			} else {
-				irlap_send_data_secondary_final( self, skb);
-				irlap_next_state( self, LAP_NRM_S);
+				irlap_send_data_secondary_final(self, skb);
+				irlap_next_state(self, LAP_NRM_S);
 
 				/* 
 				 * Make sure state machine does not try to send
@@ -1498,7 +1530,7 @@
 		break;
 	default:
 		DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[ event]);
+		      irlap_event[event]);
 		ret = -EINVAL;
 		break;
 	}
@@ -1512,29 +1544,29 @@
  *    expecting to receive frames from the primary station
  *
  */
-static int irlap_state_nrm_s( struct irlap_cb *self, IRLAP_EVENT event, 
-			      struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event, 
+			     struct sk_buff *skb, struct irlap_info *info) 
 {
-	int ret = 0;
 	int ns_status;
 	int nr_status;
+	int ret = 0;
 
-	DEBUG( 4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
+	DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
 
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
 
-	switch(event) {
+	switch (event) {
 	case RECV_I_CMD: /* Optimize for the common case */
 		/* FIXME: must check for remote_busy below */
-		DEBUG( 4, __FUNCTION__ "(), event=%s nr=%d, vs=%d, ns=%d, "
-		       "vr=%d, pf=%d\n", irlap_event[event], info->nr, 
-		       self->vs, info->ns, self->vr, info->pf);
+		DEBUG(4, __FUNCTION__ "(), event=%s nr=%d, vs=%d, ns=%d, "
+		      "vr=%d, pf=%d\n", irlap_event[event], info->nr, 
+		      self->vs, info->ns, self->vr, info->pf);
 
 		self->retry_count = 0;
 
-		ns_status = irlap_validate_ns_received( self, info->ns);
-		nr_status = irlap_validate_nr_received( self, info->nr);
+		ns_status = irlap_validate_ns_received(self, info->ns);
+		nr_status = irlap_validate_nr_received(self, info->nr);
 		/* 
 		 *  Check for expected I(nformation) frame
 		 */
@@ -1546,7 +1578,7 @@
 				self->vr = (self->vr + 1) % 8;
 				
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 				
 				self->ack_required = TRUE;
 				
@@ -1557,7 +1589,7 @@
 				/* irda_start_timer( WD_TIMER, self->wd_timeout); */
 
 				/* Keep state, do not move this line */
-				irlap_next_state( self, LAP_NRM_S);
+				irlap_next_state(self, LAP_NRM_S);
 				
 				irlap_data_indication( self, skb);
 				break;
@@ -1593,7 +1625,8 @@
 					irlap_next_state(self, LAP_XMIT_S);
 				} else {
 					irlap_send_rr_frame(self, RSP_FRAME);
-					irlap_start_wd_timer(self, self->wd_timeout);
+					irlap_start_wd_timer(self, 
+							     self->wd_timeout);
 
 					/* Keep the state */
 					irlap_next_state(self, LAP_NRM_S);
@@ -1607,20 +1640,20 @@
 		if ((ns_status == NS_UNEXPECTED) && (nr_status == NR_EXPECTED))
 		{
 			/* Unexpected next to send, with final bit cleared */
-			if ( !info->pf) {
-				irlap_update_nr_received( self, info->nr);
+			if (!info->pf) {
+				irlap_update_nr_received(self, info->nr);
 				
-				irlap_start_wd_timer( self, self->wd_timeout);
+				irlap_start_wd_timer(self, self->wd_timeout);
 			} else {
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 			
-				irlap_wait_min_turn_around( self, &self->qos_tx);
-				irlap_send_rr_frame( self, CMD_FRAME);
+				irlap_wait_min_turn_around(self, &self->qos_tx);
+				irlap_send_rr_frame(self, CMD_FRAME);
 			
-				irlap_start_wd_timer( self, self->wd_timeout);
+				irlap_start_wd_timer(self, self->wd_timeout);
 			}
-			dev_kfree_skb( skb);
+			dev_kfree_skb(skb);
 			break;
 		}
 
@@ -1629,81 +1662,80 @@
 		 */
 		if ((ns_status == NS_EXPECTED) && (nr_status == NR_UNEXPECTED))
 		{
-			if ( info->pf) {
-				DEBUG( 4, "RECV_I_RSP: frame(s) lost\n");
+			if (info->pf) {
+				DEBUG(4, "RECV_I_RSP: frame(s) lost\n");
 				
 				self->vr = (self->vr + 1) % 8;
 				
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 				
 				/* Resend rejected frames */
-				irlap_resend_rejected_frames( self, RSP_FRAME);
+				irlap_resend_rejected_frames(self, RSP_FRAME);
 
 				/* Keep state, do not move this line */
-				irlap_next_state( self, LAP_NRM_S);
-
-				irlap_data_indication( self, skb);
-				irlap_start_wd_timer( self, self->wd_timeout);
+				irlap_next_state(self, LAP_NRM_S);
 
+				irlap_data_indication(self, skb);
+				irlap_start_wd_timer(self, self->wd_timeout);
 				break;
 			}
 			/*
 			 *  This is not documented in IrLAP!! Unexpected NR
 			 *  with poll bit cleared
 			 */
-			if ( !info->pf) {
+			if (!info->pf) {
 				self->vr = (self->vr + 1) % 8;
 				
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 				
 				/* Keep state, do not move this line */
-				irlap_next_state( self, LAP_NRM_S);
+				irlap_next_state(self, LAP_NRM_S);
 				
-				irlap_data_indication( self, skb);
-				irlap_start_wd_timer( self, self->wd_timeout);
+				irlap_data_indication(self, skb);
+				irlap_start_wd_timer(self, self->wd_timeout);
 			}
 		}
 		
-		if ( ret == NR_INVALID) {
-			DEBUG( 0, "NRM_S, NR_INVALID not implemented!\n");
+		if (ret == NR_INVALID) {
+			DEBUG(0, "NRM_S, NR_INVALID not implemented!\n");
 		}
-		if ( ret == NS_INVALID) {
-			DEBUG( 0, "NRM_S, NS_INVALID not implemented!\n");
+		if (ret == NS_INVALID) {
+			DEBUG(0, "NRM_S, NS_INVALID not implemented!\n");
 		}
 		break;
 	case RECV_UI_FRAME:
 		/* 
 		 *  poll bit cleared?
 		 */
-		if ( !info->pf) {
-			irlap_unit_data_indication( self, skb);
-			irlap_next_state( self, LAP_NRM_S); /* Keep state */
+		if (!info->pf) {
+			irlap_unit_data_indication(self, skb);
+			irlap_next_state(self, LAP_NRM_S); /* Keep state */
 		} else {
 			/*
 			 *  Any pending data requests?
 			 */
-			if (( skb_queue_len( &self->tx_list) > 0) && 
-			    ( self->window > 0) && !self->remote_busy) 
+			if ((skb_queue_len(&self->tx_list) > 0) && 
+			    (self->window > 0) && !self->remote_busy) 
 			{
-				irlap_unit_data_indication( self, skb);
+				irlap_unit_data_indication(self, skb);
 				
-				del_timer( &self->wd_timer);
+				del_timer(&self->wd_timer);
 
-				irlap_next_state( self, LAP_XMIT_S);
+				irlap_next_state(self, LAP_XMIT_S);
 			} else {
-				irlap_unit_data_indication( self, skb);
+				irlap_unit_data_indication(self, skb);
 
-				irlap_wait_min_turn_around( self, &self->qos_tx);
+				irlap_wait_min_turn_around(self, &self->qos_tx);
 
-				irlap_send_rr_frame( self, RSP_FRAME);
+				irlap_send_rr_frame(self, RSP_FRAME);
 				self->ack_required = FALSE;
 				
-				irlap_start_wd_timer( self, self->wd_timeout);
+				irlap_start_wd_timer(self, self->wd_timeout);
 
 				/* Keep the state */
-				irlap_next_state( self, LAP_NRM_S);
+				irlap_next_state(self, LAP_NRM_S);
 			}
 		}
 		break;
@@ -1713,18 +1745,18 @@
 		/* 
 		 *  Nr as expected? 
 		 */
-		nr_status = irlap_validate_nr_received( self, info->nr);
-		if ( nr_status == NR_EXPECTED) {
-			if (( skb_queue_len( &self->tx_list) > 0) && 
-			    ( self->window > 0)) {
+		nr_status = irlap_validate_nr_received(self, info->nr);
+		if (nr_status == NR_EXPECTED) {
+			if ((skb_queue_len( &self->tx_list) > 0) && 
+			    (self->window > 0)) {
 				self->remote_busy = FALSE;
 				
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
-				del_timer( &self->wd_timer);
+				irlap_update_nr_received(self, info->nr);
+				del_timer(&self->wd_timer);
 				
 				irlap_wait_min_turn_around(self, &self->qos_tx);
-				irlap_next_state( self, LAP_XMIT_S);
+				irlap_next_state(self, LAP_XMIT_S);
 			} else {			
 				self->remote_busy = FALSE;
 				/* Update Nr received */
@@ -1738,13 +1770,13 @@
 			}
 		} else if (nr_status == NR_UNEXPECTED) {
 			self->remote_busy = FALSE;
-			irlap_update_nr_received( self, info->nr);
+			irlap_update_nr_received(self, info->nr);
 			irlap_resend_rejected_frames( self, RSP_FRAME);
 
-			irlap_start_wd_timer( self, self->wd_timeout);
+			irlap_start_wd_timer(self, self->wd_timeout);
 
 			/* Keep state */
-			irlap_next_state( self, LAP_NRM_S); 
+			irlap_next_state(self, LAP_NRM_S); 
 		} else {
 			DEBUG(1, __FUNCTION__ "(), invalid nr not implemented!\n");
 		} 
@@ -1753,11 +1785,11 @@
 
 		break;
 	case RECV_SNRM_CMD:
-		del_timer( &self->wd_timer);
+		del_timer(&self->wd_timer);
 		DEBUG(1, __FUNCTION__ "(), received SNRM cmd\n");
-		irlap_next_state( self, LAP_RESET_CHECK);
+		irlap_next_state(self, LAP_RESET_CHECK);
 
-		irlap_reset_indication( self);
+		irlap_reset_indication(self);
 		break;
 	case WD_TIMER_EXPIRED:
 		DEBUG( 4, "WD_TIMER_EXPIRED: %ld\n", jiffies);
@@ -1769,61 +1801,54 @@
 		DEBUG(1, __FUNCTION__ "(), retry_count = %d\n", 
 		      self->retry_count);
 
-		if (( self->retry_count < (self->N2/2))  && 
-		    ( self->retry_count != self->N1/2)) {
+		if ((self->retry_count < (self->N2/2))  && 
+		    (self->retry_count != self->N1/2)) {
 			
-			irlap_start_wd_timer( self, self->wd_timeout);
+			irlap_start_wd_timer(self, self->wd_timeout);
 			self->retry_count++;		
-		} else if ( self->retry_count == (self->N1/2)) {
-			irlap_status_indication( STATUS_NO_ACTIVITY);
-			irlap_start_wd_timer( self, self->wd_timeout);
+		} else if (self->retry_count == (self->N1/2)) {
+			irlap_status_indication(STATUS_NO_ACTIVITY);
+			irlap_start_wd_timer(self, self->wd_timeout);
 			self->retry_count++;
-		} else if ( self->retry_count >= self->N2/2) {
-			irlap_apply_default_connection_parameters( self);
+		} else if (self->retry_count >= self->N2/2) {
+			irlap_apply_default_connection_parameters(self);
 			
 			/* Always switch state before calling upper layers */
-			irlap_next_state( self, LAP_NDM);
+			irlap_next_state(self, LAP_NDM);
 
-			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+			irlap_disconnect_indication(self, LAP_NO_RESPONSE);
 		}
 		break;
-
 	case RECV_DISC_FRAME:
 		/* Always switch state before calling upper layers */
-		irlap_next_state( self, LAP_NDM);
+		irlap_next_state(self, LAP_NDM);
 
-		irlap_wait_min_turn_around( self, &self->qos_tx);
-		irlap_send_ua_response_frame( self, NULL);
-		del_timer( &self->wd_timer);
-		irlap_flush_all_queues( self);
-		irlap_apply_default_connection_parameters( self);
+		irlap_wait_min_turn_around(self, &self->qos_tx);
+		irlap_send_ua_response_frame(self, NULL);
+		del_timer(&self->wd_timer);
+		irlap_flush_all_queues(self);
+		irlap_apply_default_connection_parameters(self);
 
-		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
 		if (skb)
-			dev_kfree_skb( skb);
+			dev_kfree_skb(skb);
 		
 		break;
-
 	case RECV_DISCOVERY_XID_CMD:
-		DEBUG( 3, "irlap_state_nrm_s: got event RECV_DISCOVER_XID_CMD!\n");
-		del_timer( &self->final_timer);
-		
-		irlap_apply_default_connection_parameters( self);
-
-		/* Always switch state before calling upper layers */
-		irlap_next_state( self, LAP_NDM);
-
-		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
-		
-#if 0
-		irlap_wait_min_turn_around( self, &self->qos_session);
-		irlap_send_rr_frame( RSP_FRAME);
-		irda_start_timer( WD_TIMER, self->wd_timeout);
-		irlap_next_state( self, LAP_NRM_S);
-#endif
+		irlap_wait_min_turn_around(self, &self->qos_tx);
+		irlap_send_rr_frame(self, RSP_FRAME);
+		self->ack_required = TRUE;
+		irlap_start_wd_timer(self, self->wd_timeout);
+		irlap_next_state(self, LAP_NRM_S);
 		break;
 	case RECV_TEST_CMD:
+		/* Remove test frame header */
 		skb_pull(skb, sizeof(struct test_frame));
+
+		irlap_wait_min_turn_around(self, &self->qos_tx);
+		irlap_start_wd_timer(self, self->wd_timeout);
+
+		/* Send response (info will be copied) */
 		irlap_send_test_frame(self, info->daddr, skb);
 		dev_kfree_skb(skb);
 		break;
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.3.15/linux/net/irda/irlap_frame.c	Wed Aug 18 11:38:49 1999
+++ linux/net/irda/irlap_frame.c	Mon Aug 30 10:26:28 1999
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Mon May 31 09:29:13 1999
+ * Modified at:   Wed Aug 25 13:15:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, All Rights Resrved.
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
+ *     All Rights Resrved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -50,10 +51,12 @@
  */
 static inline void irlap_insert_mtt(struct irlap_cb *self, struct sk_buff *skb)
 {
-	struct irlap_skb_cb *cb;
+	struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;
 
-	cb = (struct irlap_skb_cb *) skb->cb;
-	
+	/* 
+	 * Insert MTT (min. turn time) into skb, so that the device driver 
+	 * knows which MTT to use 
+	 */	
 	cb->magic = LAP_MAGIC;
 	cb->mtt = self->mtt_required;
 	
@@ -78,18 +81,21 @@
  */
 void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb)
 {
+	/* Make sure data is not larger than max data size plus LAP header */
+	if (skb->len > 2050) {
+		ERROR(__FUNCTION__ "(), size=%d of sk_buff to big!\n", 
+		      (int) skb->len);
+		return;
+	}
+	
 	/* Some common init stuff */
 	skb->dev = self->netdev;
 	skb->h.raw = skb->nh.raw = skb->mac.raw = skb->data;
  	skb->protocol = htons(ETH_P_IRDA);
 	skb->priority = TC_PRIO_BESTEFFORT;
 
-	/* 
-	 * Insert MTT (min. turn time) into skb, so that the device driver 
-	 * knows which MTT to use 
-	 */
 	irlap_insert_mtt(self, skb);
-	
+
 	dev_queue_xmit(skb);
 	self->stats.tx_packets++;
 }
@@ -103,7 +109,7 @@
 {
 	struct sk_buff *skb;
 	struct snrm_frame *frame;
-	int len;
+	int ret;
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -135,9 +141,11 @@
 
 		frame->ncaddr = self->caddr;
 				
-		len = irda_insert_qos_negotiation_params(qos, frame->params);
-		/* Should not be dangerous to do this afterwards */
-		skb_put(skb, len);
+		ret = irlap_insert_qos_negotiation_params(self, skb);
+		if (ret < 0) {
+			dev_kfree_skb(skb);
+			return;
+		}
 	}
 	irlap_queue_xmit(self, skb);
 }
@@ -186,7 +194,7 @@
 {
 	struct sk_buff *skb;
 	struct ua_frame *frame;
-	int len;
+	int ret;
 	
 	DEBUG(2, __FUNCTION__ "() <%ld>\n", jiffies);
 	
@@ -200,7 +208,7 @@
 	if (!skb)
 		return;
 
-	skb_put( skb, 10);
+	skb_put(skb, 10);
 	frame = (struct ua_frame *) skb->data;
 	
 	/* Build UA response */
@@ -212,8 +220,11 @@
 
 	/* Should we send QoS negotiation parameters? */
 	if (qos) {
-		len = irda_insert_qos_negotiation_params(qos, frame->params);
-		skb_put(skb, len);
+		ret = irlap_insert_qos_negotiation_params(self, skb);
+		if (ret < 0) {
+			dev_kfree_skb(skb);
+			return;
+		}
 	}
 
 	irlap_queue_xmit(self, skb);
@@ -292,12 +303,13 @@
 	struct sk_buff *skb = NULL;
 	struct xid_frame *frame;
 	__u32 bcast = BROADCAST;
+	__u8 *info;
 
- 	DEBUG( 4, __FUNCTION__ "(), s=%d, S=%d, command=%d\n", s, S, command);
+ 	DEBUG(4, __FUNCTION__ "(), s=%d, S=%d, command=%d\n", s, S, command);
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( discovery != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(discovery != NULL, return;);
 
 	skb = dev_alloc_skb(64);
 	if (!skb)
@@ -348,28 +360,24 @@
 	 *  responses. Send the second byte of the hint only if the
 	 *  EXTENSION bit is set in the first byte.
 	 */
-	if ( !command || ( frame->slotnr == 0xff)) {
+	if (!command || (frame->slotnr == 0xff)) {
 		int i;
 
 		if (discovery->hints.byte[0] & HINT_EXTENSION)
-			skb_put( skb, 3+discovery->info_len);
+			info = skb_put(skb, 3+discovery->name_len);
 		else
-			skb_put( skb, 2+discovery->info_len);
+			info = skb_put(skb, 2+discovery->name_len);
 		
 		i = 0;
-		frame->discovery_info[i++] = discovery->hints.byte[0];
-		if(discovery->hints.byte[0] & HINT_EXTENSION)
-			frame->discovery_info[i++] = discovery->hints.byte[1];
+		info[i++] = discovery->hints.byte[0];
+		if (discovery->hints.byte[0] & HINT_EXTENSION)
+			info[i++] = discovery->hints.byte[1];
 		
-		frame->discovery_info[i++] = discovery->charset;
-
-		ASSERT( discovery->info_len < 30, return;);
-
-		memcpy( &frame->discovery_info[i++], discovery->info, 
-			discovery->info_len);
-
+		info[i++] = discovery->charset;
+		
+		memcpy(&info[i++], discovery->nickname, discovery->name_len);
 	} 
-	ASSERT( self->netdev != NULL, return;);
+	ASSERT(self->netdev != NULL, return;);
 
 	irlap_queue_xmit(self, skb);
 }
@@ -386,14 +394,13 @@
 {
 	struct xid_frame *xid;
 	discovery_t *discovery = NULL;
+	__u8 *discovery_info;
 	char *text;
 
 	DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
-	ASSERT(skb != NULL, return;);
-	ASSERT(info != NULL, return;);
 
 	if ((discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC)) == NULL) {
 		DEBUG(0, __FUNCTION__ "(), kmalloc failed!\n");
@@ -413,24 +420,27 @@
 
 	DEBUG(4, __FUNCTION__ "(), daddr=%08x\n", discovery->daddr);
 
+	discovery_info = skb_pull(skb, sizeof(struct xid_frame));
+
 	/* Get info returned from peer */
-	discovery->hints.byte[0] = xid->discovery_info[0];
-	if (xid->discovery_info[0] & HINT_EXTENSION) {
+	discovery->hints.byte[0] = discovery_info[0];
+	if (discovery_info[0] & HINT_EXTENSION) {
 		DEBUG(4, "EXTENSION\n");
-		discovery->hints.byte[1] = xid->discovery_info[1];
-		discovery->charset = xid->discovery_info[2];
-		text = (char *) &xid->discovery_info[3];
+		discovery->hints.byte[1] = discovery_info[1];
+		discovery->charset = discovery_info[2];
+		text = (char *) &discovery_info[3];
 	} else {
 		discovery->hints.byte[1] = 0;
-		discovery->charset = xid->discovery_info[1];
-		text = (char *) &xid->discovery_info[2];
+		discovery->charset = discovery_info[1];
+		text = (char *) &discovery_info[2];
 	}
 	/* 
 	 *  Terminate string, should be safe since this is where the 
 	 *  FCS bytes resides.
 	 */
 	skb->data[skb->len] = '\0'; 
-	strcpy(discovery->info, text);
+	strncpy(discovery->nickname, text, NICKNAME_MAX_LEN);
+	discovery->name_len = strlen(discovery->nickname);
 
 	info->discovery = discovery;
 
@@ -443,27 +453,28 @@
  *    Received a XID discovery command
  *
  */
-static void irlap_recv_discovery_xid_cmd( struct irlap_cb *self, 
-					  struct sk_buff *skb, 
-					  struct irlap_info *info) 
+static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self, 
+					 struct sk_buff *skb, 
+					 struct irlap_info *info) 
 {
 	struct xid_frame *xid;
 	discovery_t *discovery = NULL;
+	__u8 *discovery_info;
 	char *text;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-	ASSERT( info != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(info != NULL, return;);
 
 	xid = (struct xid_frame *) skb->data;
 	
 	/* Copy peer device address */
 	info->daddr = le32_to_cpu(xid->saddr);
 
-	switch ( xid->flags & 0x03) {
+	switch (xid->flags & 0x03) {
 	case 0x00:
 		info->S = 1;
 		break;
@@ -482,46 +493,48 @@
 	}
 	info->s = xid->slotnr;
 	
+	discovery_info = skb_pull(skb, sizeof(struct xid_frame));
+
 	/* 
 	 *  Check if last frame 
 	 */
-	if ( info->s == 0xff) {
+	if (info->s == 0xff) {
 		/*
 		 *  We now have some discovery info to deliver!
 		 */
-		discovery = kmalloc( sizeof(discovery_t), GFP_ATOMIC);
-		if (!discovery)
+		discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC);
+		if (!discovery) {
+			WARNING(__FUNCTION__ "(), unable to malloc!\n");
 			return;
+		}
 	      
 		discovery->daddr = info->daddr;
 		discovery->saddr = self->saddr;
 		discovery->timestamp = jiffies;
 
-		DEBUG( 4, __FUNCTION__ "(), daddr=%08x\n", 
-		       discovery->daddr);
-
-		discovery->hints.byte[0] = xid->discovery_info[0];
-		if ( xid->discovery_info[0] & HINT_EXTENSION) {
-			discovery->hints.byte[1] = xid->discovery_info[1];
-			discovery->charset = xid->discovery_info[2];
-			text = (char *) &xid->discovery_info[3];
+		discovery->hints.byte[0] = discovery_info[0];
+		if (discovery_info[0] & HINT_EXTENSION) {
+			discovery->hints.byte[1] = discovery_info[1];
+			discovery->charset = discovery_info[2];
+			text = (char *) &discovery_info[3];
 		} else {
 			discovery->hints.byte[1] = 0;
-			discovery->charset = xid->discovery_info[1];
-			text = (char *) &xid->discovery_info[2];
+			discovery->charset = discovery_info[1];
+			text = (char *) &discovery_info[2];
 		}
 		/* 
 		 *  Terminate string, should be safe since this is where the 
 		 *  FCS bytes resides.
 		 */
 		skb->data[skb->len] = '\0'; 
-		strcpy( discovery->info, text);
+		strncpy(discovery->nickname, text, NICKNAME_MAX_LEN);
+		discovery->name_len = strlen(discovery->nickname);
 
 		info->discovery = discovery;
 	} else
 		info->discovery = NULL;
 	
-	irlap_do_event( self, RECV_DISCOVERY_XID_CMD, skb, info);
+	irlap_do_event(self, RECV_DISCOVERY_XID_CMD, skb, info);
 }
 
 /*
@@ -1027,9 +1040,6 @@
 	info->pf = skb->data[1] & PF_BIT;      /* Final bit */
 	info->ns = (skb->data[1] >> 1) & 0x07; /* Next to send */
 
- 	DEBUG(4, __FUNCTION__"(), ns=%d, nr=%d, pf=%d, %ld\n", 
-	      info->ns, info->nr, info->pf>>4, jiffies); 
-
 	/* Check if this is a command or a response frame */
 	if (command)
 		irlap_do_event(self, RECV_I_CMD, skb, info);
@@ -1054,7 +1064,7 @@
 
 	info->pf = frame[1] & PF_BIT;      /* Final bit */
 
-	irlap_do_event( self, RECV_UI_FRAME, skb, info);
+	irlap_do_event(self, RECV_UI_FRAME, skb, info);
 }
 
 /*
@@ -1118,7 +1128,8 @@
 {
 	struct sk_buff *skb;
 	struct test_frame *frame;
-	
+	__u8 *info;
+
 	skb = dev_alloc_skb(32);
 	if (!skb)
 		return;
@@ -1140,8 +1151,8 @@
 	frame->daddr = cpu_to_le32(daddr);
 
 	/* Copy info */
-	skb_put(skb, cmd->len);
-	memcpy(frame->info, cmd->data, cmd->len);
+	info = skb_put(skb, cmd->len);
+	memcpy(info, cmd->data, cmd->len);
 
 	/* Return to sender */
 	irlap_wait_min_turn_around(self, &self->qos_tx);
@@ -1191,32 +1202,23 @@
 	struct irlap_info info;
 	struct irlap_cb *self;
 	struct irda_device *idev;
-	__u8 *frame;
 	int command;
 	__u8 control;
 	
 	idev = (struct irda_device *) dev->priv;
-
-	ASSERT( idev != NULL, return -1;);
 	self = idev->irlap;
 
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LAP_MAGIC, return -1;);
-	ASSERT( skb->len > 1, return -1;);
+	ASSERT(skb->len > 1, return -1;);
 	
-	frame = skb->data;
-
-	command    = frame[0] & CMD_FRAME;
-	info.caddr = frame[0] & CBROADCAST;
+	command    = skb->data[0] & CMD_FRAME;
+	info.caddr = skb->data[0] & CBROADCAST;
 	
-	info.pf      = frame[1] &  PF_BIT;
-	info.control = frame[1] & ~PF_BIT; /* Mask away poll/final bit */
+	info.pf      = skb->data[1] &  PF_BIT;
+	info.control = skb->data[1] & ~PF_BIT; /* Mask away poll/final bit */
 
 	control = info.control;
 
-	/* 
-	 *  First check if this frame addressed to us 
-	 */
+	/*  First check if this frame addressed to us */
 	if ((info.caddr != self->caddr) && (info.caddr != CBROADCAST)) {
 		DEBUG(2, __FUNCTION__ "(), Received frame is not for us!\n");
 
@@ -1243,11 +1245,11 @@
 		 */
 		switch (control & 0x0f) {
 		case RR:
-			irlap_recv_rr_frame( self, skb, &info, command);
+			irlap_recv_rr_frame(self, skb, &info, command);
 			self->stats.rx_packets++;
 			break;
 		case RNR:
-			irlap_recv_rnr_frame( self, skb, &info);
+			irlap_recv_rnr_frame(self, skb, &info);
 			self->stats.rx_packets++;
 			break;
 		case REJ:
@@ -1257,8 +1259,8 @@
 			DEBUG( 0, "*** SREJ frame received! ***\n");
 			break;
 		default:
-			DEBUG( 0, "Unknown S frame %02x received!\n", 
-			       info.control);
+			WARNING(__FUNCTION__ "() Unknown S frame %02x received!\n",
+				info.control);
 			break;
 		}
 		return 0;
@@ -1284,22 +1286,21 @@
 		irlap_do_event(self, RECV_DISC_FRAME, skb, &info);
 		break;
 	case TEST_CMD:
-		DEBUG(0,__FUNCTION__ "(), TEST_FRAME\n");
 		irlap_recv_test_frame(self, skb, &info, command);
 		break;
 	case UA_RSP:
-		DEBUG( 4, "UA rsp frame received!\n");
-		irlap_recv_ua_frame( self, skb, &info);
+		irlap_recv_ua_frame(self, skb, &info);
 		break;
 	case FRMR_RSP:
-		irlap_recv_frmr_frame( self, skb, &info);
+		irlap_recv_frmr_frame(self, skb, &info);
 		break;
 	case UI_FRAME:
-		DEBUG( 4, "UI-frame received!\n");
-		irlap_recv_ui_frame( self, skb, &info);
+		DEBUG(4, "UI-frame received!\n");
+		irlap_recv_ui_frame(self, skb, &info);
 		break;
 	default:
-		DEBUG( 0, "Unknown frame %02x received!\n", info.control);
+		WARNING(__FUNCTION__ "(), Unknown frame %02x received!\n", 
+			info.control);
 		dev_kfree_skb( skb); 
 		break;
 	}
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.3.15/linux/net/irda/irlmp.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/irlmp.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Stable.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Mon May 31 21:49:41 1999
+ * Modified at:   Mon Aug 23 09:30:56 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -47,8 +47,9 @@
 struct irlmp_cb *irlmp = NULL;
 
 /* These can be altered by the sysctl interface */
-int  sysctl_discovery = 0;
-int  sysctl_discovery_slots = 6;
+int  sysctl_discovery         = 0;
+int  sysctl_discovery_timeout = 3; /* 3 seconds by default */
+int  sysctl_discovery_slots   = 6; /* 6 slots by default */
 char sysctl_devname[65];
 
 char *lmp_reasons[] = {
@@ -61,7 +62,7 @@
 	"ERROR, NOT USED",
 };
 
-__u8 *irlmp_hint_to_service( __u8 *hint);
+__u8 *irlmp_hint_to_service(__u8 *hint);
 #ifdef CONFIG_PROC_FS
 int irlmp_proc_read(char *buf, char **start, off_t offst, int len, int unused);
 #endif
@@ -72,7 +73,7 @@
  *    Create (allocate) the main IrLMP structure and the pointer array
  *    which will contain pointers to each instance of a LSAP.
  */
-__initfunc(int irlmp_init(void))
+int __init irlmp_init(void)
 {
 	/* Initialize the irlmp structure. */
 	if ( irlmp == NULL) {
@@ -98,7 +99,7 @@
 	
 	/* Do discovery every 3 seconds */
 	init_timer(&irlmp->discovery_timer);
-   	irlmp_start_discovery_timer(irlmp, 600); 
+   	irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout*HZ);
 
 	return 0;
 }
@@ -134,7 +135,7 @@
  *   Register with IrLMP and create a local LSAP,
  *   returns handle to LSAP.
  */
-struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, struct notify_t *notify)
+struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify)
 {
 	struct lsap_cb *self;
 
@@ -142,8 +143,6 @@
 	ASSERT(irlmp != NULL, return NULL;);
 	ASSERT(irlmp->magic == LMP_MAGIC, return NULL;);
 
-	DEBUG(4, __FUNCTION__ "(), slsap_sel=%02x\n", slsap_sel);
-
 	/* 
 	 *  Does the client care which Source LSAP selector it gets? 
 	 */
@@ -264,13 +263,10 @@
  *    instances of the IrLAP layer, each connected to different IrDA ports
  *
  */
-void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, 
-			 struct notify_t *notify)
+void irlmp_register_link(struct irlap_cb *irlap, __u32 saddr, notify_t *notify)
 {
 	struct lap_cb *lap;
 
-	DEBUG(4, __FUNCTION__ "(), Registered IrLAP, saddr = %08x\n", saddr);
-	
 	ASSERT(irlmp != NULL, return;);
 	ASSERT(irlmp->magic == LMP_MAGIC, return;);
 	ASSERT(notify != NULL, return;);
@@ -280,7 +276,7 @@
 	 */
 	lap = kmalloc(sizeof(struct lap_cb), GFP_KERNEL);
 	if (lap == NULL) {
-		DEBUG(3, __FUNCTION__ "(), unable to kmalloc\n");
+		ERROR(__FUNCTION__ "(), unable to kmalloc\n");
 		return;
 	}
 	memset(lap, 0, sizeof(struct lap_cb));
@@ -349,20 +345,20 @@
 	struct lsap_cb *lsap;
 	discovery_t *discovery;
 
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -EBADR;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -EBADR;);
 	
 	DEBUG(2, __FUNCTION__ 
 	      "(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n", 
 	      self->slsap_sel, dlsap_sel, saddr, daddr);
 	
-	if ( self->connected) 
+	if (self->connected) 
 		return -EISCONN;
-
+	
 	/* Client must supply destination device address */
 	if (!daddr)
 		return -EINVAL;
-
+	
 	/* Any userdata? */
 	if (userdata == NULL) {
 		skb = dev_alloc_skb(64);
@@ -480,11 +476,11 @@
  *    Service user is accepting connection
  *
  */
-void irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata) 
+int irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata) 
 {
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
-	ASSERT(userdata != NULL, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+	ASSERT(userdata != NULL, return -1;);
 
 	self->connected = TRUE;
 
@@ -492,10 +488,12 @@
 	      self->slsap_sel, self->dlsap_sel);
 
 	/* Make room for MUX control header ( 3 bytes) */
-	ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return;);
+	ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return -1;);
 	skb_push(userdata, LMP_CONTROL_HEADER);
 	
 	irlmp_do_lsap_event(self, LM_CONNECT_RESPONSE, userdata);
+
+	return 0;
 }
 
 /*
@@ -583,45 +581,43 @@
  *    The service user is requesting disconnection, this will not remove the 
  *    LSAP, but only mark it as disconnected
  */
-void irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata) 
+int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata) 
 {
 	struct lsap_cb *lsap;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
 	/* Already disconnected? */
-	if ( !self->connected) {
-		DEBUG( 1, __FUNCTION__ "(), already disconnected!\n");
-		return;
+	if (!self->connected) {
+		WARNING(__FUNCTION__ "(), already disconnected!\n");
+		return -1;
 	}
 
-	ASSERT( userdata != NULL, return;);
-	ASSERT( self->connected == TRUE, return;);
+	ASSERT(userdata != NULL, return -1;);
+	ASSERT(self->connected == TRUE, return -1;);
 	
-	skb_push( userdata, LMP_CONTROL_HEADER);
+	skb_push(userdata, LMP_CONTROL_HEADER);
 
 	/* 
 	 *  Do the event before the other stuff since we must know
 	 *  which lap layer that the frame should be transmitted on
 	 */
-	irlmp_do_lsap_event( self, LM_DISCONNECT_REQUEST, userdata);
+	irlmp_do_lsap_event(self, LM_DISCONNECT_REQUEST, userdata);
 
 	/* 
 	 *  Remove LSAP from list of connected LSAPs for the particular link
 	 *  and insert it into the list of unconnected LSAPs
 	 */
-	ASSERT( self->lap != NULL, return;);
-	ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;);
-	ASSERT( self->lap->lsaps != NULL, return;);
+	ASSERT(self->lap != NULL, return -1;);
+	ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
+	ASSERT(self->lap->lsaps != NULL, return -1;);
 
 	lsap = hashbin_remove(self->lap->lsaps, (int) self, NULL);
 
-	ASSERT( lsap != NULL, return;);
-	ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;);
-	ASSERT( lsap == self, return;);
+	ASSERT(lsap != NULL, return -1;);
+	ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
+	ASSERT(lsap == self, return -1;);
 
 	hashbin_insert(irlmp->unconnected_lsaps, (QUEUE *) self, (int) self, 
 		       NULL);
@@ -630,6 +626,8 @@
 	self->connected = FALSE;
 	self->dlsap_sel = LSAP_ANY;
 	self->lap = NULL;
+	
+	return 0;
 }
 
 /*
@@ -642,14 +640,14 @@
 {
 	struct lsap_cb *lsap;
 
-	DEBUG( 1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);	
+	DEBUG(1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);	
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
- 	ASSERT( self->connected == TRUE, return;); 
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ 	ASSERT(self->connected == TRUE, return;); 
 
-	DEBUG( 3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
-	       self->slsap_sel, self->dlsap_sel);
+	DEBUG(3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+	      self->slsap_sel, self->dlsap_sel);
 
 	self->connected = FALSE;
 	self->dlsap_sel = LSAP_ANY;
@@ -661,13 +659,13 @@
 	/* 
 	 *  Remove association between this LSAP and the link it used 
 	 */
-	ASSERT( self->lap != NULL, return;);
-	ASSERT( self->lap->lsaps != NULL, return;);
+	ASSERT(self->lap != NULL, return;);
+	ASSERT(self->lap->lsaps != NULL, return;);
 
-	lsap = hashbin_remove( self->lap->lsaps, (int) self, NULL);
+	lsap = hashbin_remove(self->lap->lsaps, (int) self, NULL);
 
-	ASSERT( lsap != NULL, return;);
-	ASSERT( lsap == self, return;);
+	ASSERT(lsap != NULL, return;);
+	ASSERT(lsap == self, return;);
 	hashbin_insert(irlmp->unconnected_lsaps, (QUEUE *) lsap, (int) lsap, 
 		       NULL);
 
@@ -676,9 +674,9 @@
 	/*
 	 *  Inform service user
 	 */
-	if ( self->notify.disconnect_indication) {
-		self->notify.disconnect_indication( self->notify.instance, 
-						    self, reason, userdata);
+	if (self->notify.disconnect_indication) {
+		self->notify.disconnect_indication(self->notify.instance, 
+						   self, reason, userdata);
 	}
 }
 
@@ -692,8 +690,10 @@
 {
 	struct lap_cb *lap;
 
-	/* Make sure value is sane */
-	if ((nslots != 1) && (nslots != 6) && (nslots != 8)&&(nslots != 16)) {
+	/* Make sure the value is sane */
+	if ((nslots != 1) && (nslots != 6) && 
+	    (nslots != 8) && (nslots != 16)) 
+	{
 		printk(KERN_WARNING __FUNCTION__ 
 		       "(), invalid value for number of slots!\n");
 		nslots = sysctl_discovery_slots = 8;
@@ -708,8 +708,9 @@
 	 *  end
 	 */
 	irlmp->discovery_cmd.charset = CS_ASCII;
-	strncpy(irlmp->discovery_cmd.info, sysctl_devname, 31);
-	irlmp->discovery_cmd.info_len = strlen(irlmp->discovery_cmd.info);
+	strncpy(irlmp->discovery_cmd.nickname, sysctl_devname, 
+		NICKNAME_MAX_LEN);
+	irlmp->discovery_cmd.name_len = strlen(irlmp->discovery_cmd.nickname);
 	irlmp->discovery_cmd.nslots = nslots;
 	
 	/*
@@ -740,21 +741,18 @@
  */
 void irlmp_discovery_request(int nslots)
 {
-	DEBUG(4, __FUNCTION__ "(), nslots=%d\n", nslots);
-
 	/* Check if user wants to override the default */
 	if (nslots == DISCOVERY_DEFAULT_SLOTS)
 		nslots = sysctl_discovery_slots;
 
+	/* Return current cached discovery log */
+	irlmp_discovery_confirm(irlmp->cachelog);
+
 	/* 
-	 * If discovery is already running, then just return the current 
-	 * discovery log
+	 * Start a single discovery operation if discovery is not already
+         * running 
 	 */
-	if (sysctl_discovery) {
-		DEBUG(2, __FUNCTION__ "() discovery already running, so we"
-		      " just return the old discovery log!\n");
-		irlmp_discovery_confirm(irlmp->cachelog);
-	} else
+	if (!sysctl_discovery)
 		irlmp_do_discovery(nslots);
 }
 
@@ -833,7 +831,11 @@
 	while (discovery != NULL) {
 		DEBUG(3, "discovery->daddr = 0x%08x\n", discovery->daddr); 
 		
-		if (client->hint_mask & discovery->hints.word) {
+		/* 
+		 * Any common hint bits? Remember to mask away the extension
+		 * bits ;-)
+		 */
+		if (client->hint_mask & discovery->hints.word & 0x7f7f) {
 			if (client->callback1)
 				client->callback1(discovery);
 		}
@@ -889,8 +891,9 @@
 	 */
 	irlmp->discovery_rsp.charset = CS_ASCII;
 
-	strncpy(irlmp->discovery_rsp.info, sysctl_devname, 31);
-	irlmp->discovery_rsp.info_len = strlen(irlmp->discovery_rsp.info) + 2;
+	strncpy(irlmp->discovery_rsp.nickname, sysctl_devname, 
+		NICKNAME_MAX_LEN);
+	irlmp->discovery_rsp.name_len = strlen(irlmp->discovery_rsp.nickname);
 
 	return &irlmp->discovery_rsp;
 }
@@ -901,17 +904,16 @@
  *    Send some data to peer device
  *
  */
-void irlmp_data_request(struct lsap_cb *self, struct sk_buff *skb) 
+int irlmp_data_request(struct lsap_cb *self, struct sk_buff *skb) 
 {
-	ASSERT(skb != NULL, return;);
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 	
 	/* Make room for MUX header */
-	ASSERT(skb_headroom( skb) >= LMP_HEADER, return;);
+	ASSERT(skb_headroom(skb) >= LMP_HEADER, return -1;);
 	skb_push(skb, LMP_HEADER);
-
-	irlmp_do_lsap_event(self, LM_DATA_REQUEST, skb);
+	
+	return irlmp_do_lsap_event(self, LM_DATA_REQUEST, skb);
 }
 
 /*
@@ -935,17 +937,17 @@
  *    
  *
  */
-inline void irlmp_udata_request( struct lsap_cb *self, struct sk_buff *skb) 
+inline void irlmp_udata_request(struct lsap_cb *self, struct sk_buff *skb) 
 {
- 	DEBUG( 4, __FUNCTION__ "()\n"); 
+ 	DEBUG(4, __FUNCTION__ "()\n"); 
 
-	ASSERT( skb != NULL, return;);
+	ASSERT(skb != NULL, return;);
 	
 	/* Make room for MUX header */
-	ASSERT( skb_headroom( skb) >= LMP_HEADER, return;);
-	skb_push( skb, LMP_HEADER);
+	ASSERT(skb_headroom(skb) >= LMP_HEADER, return;);
+	skb_push(skb, LMP_HEADER);
 
-	irlmp_do_lsap_event( self, LM_UDATA_REQUEST, skb);
+	irlmp_do_lsap_event(self, LM_UDATA_REQUEST, skb);
 }
 
 /*
@@ -954,16 +956,16 @@
  *    Send unreliable data (but still within the connection)
  *
  */
-void irlmp_udata_indication( struct lsap_cb *self, struct sk_buff *skb) 
+void irlmp_udata_indication(struct lsap_cb *self, struct sk_buff *skb) 
 {
- 	DEBUG( 4, __FUNCTION__ "()\n"); 
+ 	DEBUG(4, __FUNCTION__ "()\n"); 
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	/* Hide LMP header from layer above */
-	skb_pull( skb, LMP_HEADER);
+	skb_pull(skb, LMP_HEADER);
 
 	if (self->notify.udata_indication)
 		self->notify.udata_indication(self->notify.instance, self, skb);
@@ -986,19 +988,19 @@
  *    
  *
  */
-void irlmp_connectionless_data_indication( struct sk_buff *skb)
+void irlmp_connectionless_data_indication(struct sk_buff *skb)
 {
 	DEBUG( 1, __FUNCTION__ "()\n"); 
 }
 
 void irlmp_status_request(void) 
 {
-	DEBUG( 1, "irlmp_status_request(), Not implemented\n");
+	DEBUG(0, __FUNCTION__ "(), Not implemented\n");
 }
 
 void irlmp_status_indication(LINK_STATUS link, LOCK_STATUS lock) 
 {
-	DEBUG( 4, "irlmp_status_indication(), Not implemented\n");
+	DEBUG(1, __FUNCTION__ "(), Not implemented\n");
 }
 
 /*
@@ -1016,31 +1018,32 @@
 	 * Allocate array to store services in. 16 entries should be safe 
 	 * since we currently only support 2 hint bytes
 	 */
-	service = kmalloc( 16, GFP_ATOMIC);
-	if ( !service) {
+	service = kmalloc(16, GFP_ATOMIC);
+	if (!service) {
 		DEBUG(1, __FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
 
-	if ( !hint[0]) {
+	if (!hint[0]) {
 		DEBUG(1, "<None>\n");
+		kfree(service);
 		return NULL;
 	}
-	if ( hint[0] & HINT_PNP)
+	if (hint[0] & HINT_PNP)
 		DEBUG(1, "PnP Compatible ");
-	if ( hint[0] & HINT_PDA)
+	if (hint[0] & HINT_PDA)
 		DEBUG(1, "PDA/Palmtop ");
-	if ( hint[0] & HINT_COMPUTER)
+	if (hint[0] & HINT_COMPUTER)
 		DEBUG(1, "Computer ");
-	if ( hint[0] & HINT_PRINTER) {
+	if (hint[0] & HINT_PRINTER) {
 		DEBUG(1, "Printer ");
 		service[i++] = S_PRINTER;
 	}
-	if ( hint[0] & HINT_MODEM)
+	if (hint[0] & HINT_MODEM)
 		DEBUG(1, "Modem ");
-	if ( hint[0] & HINT_FAX)
+	if (hint[0] & HINT_FAX)
 		DEBUG(1, "Fax ");
-	if ( hint[0] & HINT_LAN) {
+	if (hint[0] & HINT_LAN) {
 		DEBUG(1, "LAN Access ");		
 		service[i++] = S_LAN;
 	}
@@ -1049,18 +1052,18 @@
 	 *  there, but this is not really required by the standard.
 	 *  (IrLMP p. 29)
 	 */
-	if ( hint[0] & HINT_EXTENSION) {
-		if ( hint[1] & HINT_TELEPHONY) {
+	if (hint[0] & HINT_EXTENSION) {
+		if (hint[1] & HINT_TELEPHONY) {
 			DEBUG(1, "Telephony ");
 			service[i++] = S_TELEPHONY;
-		} if ( hint[1] & HINT_FILE_SERVER)
+		} if (hint[1] & HINT_FILE_SERVER)
 			DEBUG(1, "File Server ");
 		
-		if ( hint[1] & HINT_COMM) {
+		if (hint[1] & HINT_COMM) {
 			DEBUG(1, "IrCOMM ");
 			service[i++] = S_COMM;
 		}
-		if ( hint[1] & HINT_OBEX) {
+		if (hint[1] & HINT_OBEX) {
 			DEBUG(1, "IrOBEX ");
 			service[i++] = S_OBEX;
 		}
@@ -1296,16 +1299,16 @@
  *
  *    Check if the given source LSAP selector is in use
  */
-int irlmp_slsap_inuse( __u8 slsap_sel)
+int irlmp_slsap_inuse(__u8 slsap_sel)
 {
 	struct lsap_cb *self;
 	struct lap_cb *lap;
 
-	ASSERT( irlmp != NULL, return TRUE;);
-	ASSERT( irlmp->magic == LMP_MAGIC, return TRUE;);
-	ASSERT( slsap_sel != LSAP_ANY, return TRUE;);
+	ASSERT(irlmp != NULL, return TRUE;);
+	ASSERT(irlmp->magic == LMP_MAGIC, return TRUE;);
+	ASSERT(slsap_sel != LSAP_ANY, return TRUE;);
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 
 	/* Valid values are between 0 and 127 */
 	if (slsap_sel > 127)
@@ -1324,16 +1327,14 @@
 		while (self != NULL) {
 			ASSERT(self->magic == LMP_LSAP_MAGIC, return TRUE;);
 
-			if ((self->slsap_sel == slsap_sel))/*  &&  */
-/* 			    ( self->dlsap_sel == LSAP_ANY)) */
-			{
-				DEBUG( 4, "Source LSAP selector=%02x in use\n",
-				       self->slsap_sel); 
+			if ((self->slsap_sel == slsap_sel)) {
+				DEBUG(4, "Source LSAP selector=%02x in use\n",
+				      self->slsap_sel); 
 				return TRUE;
 			}
-			self = (struct lsap_cb*) hashbin_get_next( lap->lsaps);
+			self = (struct lsap_cb*) hashbin_get_next(lap->lsaps);
 		}
-		lap = (struct lap_cb *) hashbin_get_next( irlmp->links);
+		lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
 	}     
 	return FALSE;
 }
@@ -1399,12 +1400,12 @@
 	case LAP_FOUND_NONE:
 	case LAP_MEDIA_BUSY:
 	case LAP_PRIMARY_CONFLICT:
-		DEBUG( 1, __FUNCTION__ "(), LAP_FOUND_NONE, LAP_MEDIA_BUSY or LAP_PRIMARY_CONFLICT\n");
+		DEBUG(1, __FUNCTION__ "(), LAP_FOUND_NONE, LAP_MEDIA_BUSY or LAP_PRIMARY_CONFLICT\n");
 		reason = LM_CONNECT_FAILURE;
 		break;
 	default:
-		DEBUG( 1, __FUNCTION__ 
-		       "(), Unknow IrLAP disconnect reason %d!\n", lap_reason);
+		DEBUG(1, __FUNCTION__ 
+		      "(), Unknow IrLAP disconnect reason %d!\n", lap_reason);
 		reason = LM_LAP_DISCONNECT;
 		break;
 	}
@@ -1414,8 +1415,6 @@
 
 __u32 irlmp_get_saddr(struct lsap_cb *self)
 {
-	DEBUG(3, __FUNCTION__ "()\n");
-
 	ASSERT(self != NULL, return 0;);
 	ASSERT(self->lap != NULL, return 0;);
 
@@ -1424,8 +1423,6 @@
 
 __u32 irlmp_get_daddr(struct lsap_cb *self)
 {
-	DEBUG(3, __FUNCTION__ "()\n");
-
 	ASSERT(self != NULL, return 0;);
 	ASSERT(self->lap != NULL, return 0;);
 	
@@ -1455,21 +1452,21 @@
 	
 	len += sprintf( buf+len, "Unconnected LSAPs:\n");
 	self = (struct lsap_cb *) hashbin_get_first( irlmp->unconnected_lsaps);
-	while ( self != NULL) {
-		ASSERT( self->magic == LMP_LSAP_MAGIC, return 0;);
-		len += sprintf( buf+len, "lsap state: %s, ", 
-				irlsap_state[ self->lsap_state]);
-		len += sprintf( buf+len, 
-				"slsap_sel: %#02x, dlsap_sel: %#02x, ",
-				self->slsap_sel, self->dlsap_sel); 
-		len += sprintf( buf+len, "(%s)", self->notify.name);
-		len += sprintf( buf+len, "\n");
+	while (self != NULL) {
+		ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
+		len += sprintf(buf+len, "lsap state: %s, ", 
+			       irlsap_state[ self->lsap_state]);
+		len += sprintf(buf+len, 
+			       "slsap_sel: %#02x, dlsap_sel: %#02x, ",
+			       self->slsap_sel, self->dlsap_sel); 
+		len += sprintf(buf+len, "(%s)", self->notify.name);
+		len += sprintf(buf+len, "\n");
 
-		self = ( struct lsap_cb *) hashbin_get_next( 
+		self = (struct lsap_cb *) hashbin_get_next(
 			irlmp->unconnected_lsaps);
  	} 
 
-	len += sprintf( buf+len, "\nRegistred Link Layers:\n");
+	len += sprintf(buf+len, "\nRegistred Link Layers:\n");
 
 	lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
 	while (lap != NULL) {
@@ -1480,8 +1477,8 @@
 			       lap->saddr, lap->daddr); 
 		len += sprintf(buf+len, "\n");
 
-		len += sprintf( buf+len, "\nConnected LSAPs:\n");
-		self = (struct lsap_cb *) hashbin_get_first( lap->lsaps);
+		len += sprintf(buf+len, "\nConnected LSAPs:\n");
+		self = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
 		while (self != NULL) {
 			ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;);
 			len += sprintf(buf+len, "lsap state: %s, ", 
@@ -1500,8 +1497,8 @@
 		lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
  	} 
 
-	restore_flags( flags);
-
+	restore_flags(flags);
+	
 	return len;
 }
 
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlmp_event.c linux/net/irda/irlmp_event.c
--- v2.3.15/linux/net/irda/irlmp_event.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/irlmp_event.c	Mon Aug 30 10:26:28 1999
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Fri Apr 23 08:57:23 1999
+ * Modified at:   Wed Aug 25 14:38:49 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
+ *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
  *     All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
@@ -75,35 +75,35 @@
 };
 
 /* LAP Connection control proto declarations */
-static void irlmp_state_standby  ( struct lap_cb *, IRLMP_EVENT, 
-				   struct sk_buff *);
-static void irlmp_state_u_connect( struct lap_cb *, IRLMP_EVENT, 
-				   struct sk_buff *);
-static void irlmp_state_active   ( struct lap_cb *, IRLMP_EVENT, 
-				   struct sk_buff *);
+static void irlmp_state_standby  (struct lap_cb *, IRLMP_EVENT, 
+				  struct sk_buff *);
+static void irlmp_state_u_connect(struct lap_cb *, IRLMP_EVENT, 
+				  struct sk_buff *);
+static void irlmp_state_active   (struct lap_cb *, IRLMP_EVENT, 
+				  struct sk_buff *);
 
 /* LSAP Connection control proto declarations */
-static void irlmp_state_disconnected( struct lsap_cb *, IRLMP_EVENT, 
-				      struct sk_buff *);
-static void irlmp_state_connect     ( struct lsap_cb *, IRLMP_EVENT, 
-				      struct sk_buff *);
-static void irlmp_state_connect_pend( struct lsap_cb *, IRLMP_EVENT,
-				      struct sk_buff *);
-static void irlmp_state_dtr         ( struct lsap_cb *, IRLMP_EVENT, 
-				      struct sk_buff *);
-static void irlmp_state_setup       ( struct lsap_cb *, IRLMP_EVENT, 
-				      struct sk_buff *);
-static void irlmp_state_setup_pend  ( struct lsap_cb *, IRLMP_EVENT, 
-				      struct sk_buff *);
+static int irlmp_state_disconnected(struct lsap_cb *, IRLMP_EVENT, 
+				    struct sk_buff *);
+static int irlmp_state_connect     (struct lsap_cb *, IRLMP_EVENT, 
+				    struct sk_buff *);
+static int irlmp_state_connect_pend(struct lsap_cb *, IRLMP_EVENT,
+				    struct sk_buff *);
+static int irlmp_state_dtr         (struct lsap_cb *, IRLMP_EVENT, 
+				    struct sk_buff *);
+static int irlmp_state_setup       (struct lsap_cb *, IRLMP_EVENT, 
+				    struct sk_buff *);
+static int irlmp_state_setup_pend  (struct lsap_cb *, IRLMP_EVENT, 
+				    struct sk_buff *);
 
-static void (*lap_state[]) ( struct lap_cb *, IRLMP_EVENT, struct sk_buff *) =
+static void (*lap_state[]) (struct lap_cb *, IRLMP_EVENT, struct sk_buff *) =
 {
 	irlmp_state_standby,
 	irlmp_state_u_connect,
 	irlmp_state_active,
 };
 
-static void (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) =
+static int (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) =
 {
 	irlmp_state_disconnected,
 	irlmp_state_connect,
@@ -114,16 +114,16 @@
 };
 
 /* Do connection control events */
-void irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event, 
-			 struct sk_buff *skb)
+int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event, 
+			struct sk_buff *skb)
 {
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
 	DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
 	      irlmp_event[ event], irlmp_state[ self->lsap_state]);
 
-	(*lsap_state[self->lsap_state]) (self, event, skb);
+	return (*lsap_state[self->lsap_state]) (self, event, skb);
 }
 
 /*
@@ -145,20 +145,20 @@
 	(*lap_state[self->lap_state]) (self, event, skb);
 }
 
-void irlmp_discovery_timer_expired( unsigned long data)
+void irlmp_discovery_timer_expired(void *data)
 {
-	DEBUG(4, "IrLMP, discovery timer expired!\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
 	if (sysctl_discovery)
 		irlmp_do_discovery(sysctl_discovery_slots);
 
 	/* Restart timer */
-	irlmp_start_discovery_timer(irlmp, 300);
+	irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout * HZ);
 }
 
-void irlmp_watchdog_timer_expired( unsigned long data)
+void irlmp_watchdog_timer_expired(void *data)
 {
-	struct lsap_cb *self = ( struct lsap_cb *) data;
+	struct lsap_cb *self = (struct lsap_cb *) data;
 	
 	DEBUG(2, __FUNCTION__ "()\n");
 
@@ -168,7 +168,7 @@
 	irlmp_do_lsap_event(self, LM_WATCHDOG_TIMEOUT, NULL);
 }
 
-void irlmp_idle_timer_expired(unsigned long data)
+void irlmp_idle_timer_expired(void *data)
 {
 	struct lap_cb *self = (struct lap_cb *) data;
 	
@@ -341,8 +341,6 @@
 		/* Keep state */
 		break;
 	case LM_LAP_DISCONNECT_REQUEST:
-		DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
-
 		/*
 		 *  Need to find out if we should close IrLAP or not. If there
 		 *  is only one LSAP connection left on this link, that LSAP 
@@ -360,31 +358,31 @@
 			irlmp_next_lap_state(self, LAP_STANDBY);
 			
 			irlap_disconnect_request(self->irlap);
-		}
+		} else
+			/* Still not ready, so wait a little bit more */
+			irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
-		DEBUG(4, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
-	
-		irlmp_next_lap_state( self, LAP_STANDBY);		
+		irlmp_next_lap_state(self, LAP_STANDBY);		
 		
 		/* 
 		 *  Inform all connected LSAP's using this link
 		 */
-		lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps);
-		while ( lsap != NULL ) {
-			ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;);
+		lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
+		while (lsap != NULL ) {
+			ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
 			
 			lsap_current = lsap;
 
 			/* Be sure to stay one item ahead */
-			lsap = ( struct lsap_cb *) hashbin_get_next( self->lsaps);
-			irlmp_do_lsap_event( lsap_current, 
-					     LM_LAP_DISCONNECT_INDICATION,
-					     NULL);
+			lsap = (struct lsap_cb *) hashbin_get_next(self->lsaps);
+			irlmp_do_lsap_event(lsap_current, 
+					    LM_LAP_DISCONNECT_INDICATION,
+					    NULL);
 		}
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
+		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}	
 }
@@ -401,23 +399,25 @@
  *    DISCONNECTED
  *
  */
-static void irlmp_state_disconnected( struct lsap_cb *self, IRLMP_EVENT event,
-				      struct sk_buff *skb) 
+static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
+				    struct sk_buff *skb) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	int ret = 0;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	switch( event) {
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+
+	switch (event) {
 	case LM_CONNECT_REQUEST:
-		DEBUG( 4, __FUNCTION__ "(), LM_CONNECT_REQUEST\n");
-		irlmp_next_lsap_state( self, LSAP_SETUP_PEND);
+		DEBUG(4, __FUNCTION__ "(), LM_CONNECT_REQUEST\n");
+		irlmp_next_lsap_state(self, LSAP_SETUP_PEND);
 
 		irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
 
-		/* Start watchdog timer ( 5 secs for now) */
-		irlmp_start_watchdog_timer(self, 500);
+		/* Start watchdog timer (5 secs for now) */
+		irlmp_start_watchdog_timer(self, 5*HZ);
 		break;
 	case LM_CONNECT_INDICATION:
 		irlmp_next_lsap_state(self, LSAP_CONNECT_PEND);
@@ -428,6 +428,7 @@
 		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
+	return ret;
 }
 
 /*
@@ -436,20 +437,19 @@
  *    CONNECT
  *
  */
-static void irlmp_state_connect( struct lsap_cb *self, IRLMP_EVENT event, 
-				 struct sk_buff *skb) 
+static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event, 
+				struct sk_buff *skb) 
 {
 	struct lsap_cb *lsap;
+	int ret = 0;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	DEBUG(4, __FUNCTION__ "()\n");
 	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
-	switch( event) {
+	switch (event) {
 	case LM_CONNECT_RESPONSE:
-		ASSERT( skb != NULL, return;);
-
 		/* 
 		 *  Bind this LSAP to the IrLAP link where the connect was
 		 *  received 
@@ -457,10 +457,9 @@
 		lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self, 
 				      NULL);
 
-		ASSERT(lsap == self, return;);
-		
-		ASSERT(self->lap != NULL, return;);
-		ASSERT(self->lap->lsaps != NULL, return;);
+		ASSERT(lsap == self, return -1;);		
+		ASSERT(self->lap != NULL, return -1;);
+		ASSERT(self->lap->lsaps != NULL, return -1;);
 		
 		hashbin_insert(self->lap->lsaps, (QUEUE *) self, (int) self, 
 			       NULL);
@@ -476,6 +475,7 @@
 		DEBUG( 4, __FUNCTION__ "(), Unknown event\n");
 		break;
 	}
+	return ret;
 }
 
 /*
@@ -484,15 +484,17 @@
  *    CONNECT_PEND
  *
  */
-static void irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
-				     struct sk_buff *skb) 
+static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
+				    struct sk_buff *skb) 
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	int ret = 0;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	DEBUG(4, __FUNCTION__ "()\n");
 
-	switch( event) {
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+
+	switch (event) {
 	case LM_CONNECT_REQUEST:
 		/* Keep state */
 		break;
@@ -514,7 +516,8 @@
 	default:
 		DEBUG( 4, __FUNCTION__ "Unknown event %d\n", event);
 		break;	
-	}	
+	}
+	return ret;
 }
 
 /*
@@ -523,16 +526,17 @@
  *    DATA_TRANSFER_READY
  *
  */
-static void irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event, 
-			    struct sk_buff *skb) 
+static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event, 
+			   struct sk_buff *skb) 
 {
 	LM_REASON reason;
+	int ret = 0;
 
  	DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
-	ASSERT(self->lap != NULL, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
+	ASSERT(self->lap != NULL, return -1;);
 
 	switch (event) {
 	case LM_DATA_REQUEST: /* Optimize for the common case */
@@ -545,7 +549,7 @@
 		/* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/
 		break;
 	case LM_UDATA_REQUEST:
-		ASSERT(skb != NULL, return;);
+		ASSERT(skb != NULL, return -1;);
 		irlmp_send_data_pdu(self->lap, self->dlsap_sel, 
 				    self->slsap_sel, TRUE, skb);
 		break;
@@ -564,8 +568,6 @@
 		/* Keep state */
 		break;
 	case LM_DISCONNECT_REQUEST:
-		ASSERT(skb != NULL, return;);
-
 		irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, 
 				   self->slsap_sel, DISCONNECT, skb);
 		irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
@@ -588,11 +590,11 @@
 	case LM_DISCONNECT_INDICATION:
 		irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
 			
-		ASSERT(self->lap != NULL, return;);
-		ASSERT(self->lap->magic == LMP_LAP_MAGIC, return;);
+		ASSERT(self->lap != NULL, return -1;);
+		ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
 	
-		ASSERT(skb != NULL, return;);
-		ASSERT(skb->len > 3, return;);
+		ASSERT(skb != NULL, return -1;);
+		ASSERT(skb->len > 3, return -1;);
 		reason = skb->data[3];
 
 		 /* Try to close the LAP connection */
@@ -604,7 +606,8 @@
 	default:
 		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;	
-	}	
+	}
+	return ret;
 }
 
 /*
@@ -614,25 +617,24 @@
  *    An LSAP connection request has been transmitted to the peer
  *    LSAP-Connection Control FSM and we are awaiting reply.
  */
-static void irlmp_state_setup( struct lsap_cb *self, IRLMP_EVENT event, 
-			       struct sk_buff *skb) 
+static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event, 
+			     struct sk_buff *skb) 
 {
 	LM_REASON reason;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	int ret = 0;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
-	switch( event) {
-	case LM_CONNECT_CONFIRM:
-		ASSERT( skb != NULL, return;);
+	DEBUG(4, __FUNCTION__ "()\n");
 
-		irlmp_next_lsap_state( self, LSAP_DATA_TRANSFER_READY);
+	switch (event) {
+	case LM_CONNECT_CONFIRM:
+		irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
 
-		del_timer( &self->watchdog_timer);
+		del_timer(&self->watchdog_timer);
 		
-		irlmp_connect_confirm( self, skb);
+		irlmp_connect_confirm(self, skb);
 		break;
 	case LM_DISCONNECT_INDICATION:
 		DEBUG(0, __FUNCTION__ "(), this should never happen!!\n");
@@ -642,26 +644,27 @@
 
 		del_timer(&self->watchdog_timer);
 
-		ASSERT(self->lap != NULL, return;);
-		ASSERT(self->lap->magic == LMP_LAP_MAGIC, return;);
+		ASSERT(self->lap != NULL, return -1;);
+		ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
 		
 		reason = irlmp_convert_lap_reason(self->lap->reason);
 
 		irlmp_disconnect_indication(self, reason, skb);
 		break;
 	case LM_WATCHDOG_TIMEOUT:
-		DEBUG( 0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
+		DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
 		
-		ASSERT( self->lap != NULL, return;);
-		irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
-		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+		ASSERT(self->lap != NULL, return -1;);
+		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+		irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
 		
-		irlmp_disconnect_indication( self, LM_CONNECT_FAILURE, NULL);
+		irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
+		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;	
 	}
+	return ret;
 }
 
 /*
@@ -672,27 +675,28 @@
  *    LAP FSM to set up the underlying IrLAP connection, and we
  *    are awaiting confirm.
  */
-static void irlmp_state_setup_pend( struct lsap_cb *self, IRLMP_EVENT event, 
-				    struct sk_buff *skb) 
+static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event, 
+				  struct sk_buff *skb) 
 {
 	LM_REASON reason;
+	int ret = 0;
 
-	DEBUG( 4, __FUNCTION__ "()\n"); 
+	DEBUG(4, __FUNCTION__ "()\n"); 
 
-	ASSERT( self != NULL, return;);
-	ASSERT( irlmp != NULL, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(irlmp != NULL, return -1;);
 
-	switch( event) {
+	switch (event) {
 	case LM_LAP_CONNECT_CONFIRM:
-		irlmp_send_lcf_pdu( self->lap, self->dlsap_sel, 
-				    self->slsap_sel, CONNECT_CMD, 
-				    self->tmp_skb);
-		irlmp_next_lsap_state( self, LSAP_SETUP);
+		irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, 
+				   self->slsap_sel, CONNECT_CMD, 
+				   self->tmp_skb);
+		irlmp_next_lsap_state(self, LSAP_SETUP);
 		break;
 	case LM_WATCHDOG_TIMEOUT:
-		DEBUG( 0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
+		DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
 
-		ASSERT( self->lap != NULL, return;);
+		ASSERT(self->lap != NULL, return -1;);
 		irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
 		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
 
@@ -705,24 +709,25 @@
 		
 		reason = irlmp_convert_lap_reason( self->lap->reason);
 		
-		irlmp_disconnect_indication( self, reason, NULL);
+		irlmp_disconnect_indication(self, reason, NULL);
 		break;
 	default:
-		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
+		DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;	
 	}
+	return ret;
 }
 
-void irlmp_next_lap_state( struct lap_cb *self, IRLMP_STATE state) 
+void irlmp_next_lap_state(struct lap_cb *self, IRLMP_STATE state) 
 {
-	DEBUG( 4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
+	DEBUG(4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
 	self->lap_state = state;
 }
 
-void irlmp_next_lsap_state( struct lsap_cb *self, LSAP_STATE state) 
+void irlmp_next_lsap_state(struct lsap_cb *self, LSAP_STATE state) 
 {
-	ASSERT( self != NULL, return;);
+	ASSERT(self != NULL, return;);
 
-	DEBUG( 4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
+	DEBUG(4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
 	self->lsap_state = state;
 }
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlmp_frame.c linux/net/irda/irlmp_frame.c
--- v2.3.15/linux/net/irda/irlmp_frame.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/irlmp_frame.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Mon May 31 09:53:16 1999
+ * Modified at:   Thu Jul  8 12:12:02 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -40,18 +40,14 @@
 inline void irlmp_send_data_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap,
 				int expedited, struct sk_buff *skb)
 {
-	__u8 *frame;
-
-	frame = skb->data;
-
-	frame[0] = dlsap;
-	frame[1] = slsap;
+	skb->data[0] = dlsap;
+	skb->data[1] = slsap;
 
 	if (expedited) {
-		DEBUG( 4, __FUNCTION__ "(), sending expedited data\n");
-		irlap_data_request( self->irlap, skb, FALSE);
+		DEBUG(4, __FUNCTION__ "(), sending expedited data\n");
+		irlap_data_request(self->irlap, skb, FALSE);
 	} else
-		irlap_data_request( self->irlap, skb, TRUE);
+		irlap_data_request(self->irlap, skb, TRUE);
 }
 
 /*
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlpt/Config.in linux/net/irda/irlpt/Config.in
--- v2.3.15/linux/net/irda/irlpt/Config.in	Wed Jan 20 11:05:33 1999
+++ linux/net/irda/irlpt/Config.in	Wed Dec 31 16:00:00 1969
@@ -1,7 +0,0 @@
-
-dep_tristate 'IrLPT protocol' CONFIG_IRLPT $CONFIG_IRDA
-
-if [ "$CONFIG_IRLPT" != "n" ]; then
-  dep_tristate '   IrLPT client support' CONFIG_IRLPT_CLIENT $CONFIG_IRLPT
-  dep_tristate '   IrLPT server support' CONFIG_IRLPT_SERVER $CONFIG_IRLPT
-fi
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlpt/Makefile linux/net/irda/irlpt/Makefile
--- v2.3.15/linux/net/irda/irlpt/Makefile	Wed Jan 20 11:05:33 1999
+++ linux/net/irda/irlpt/Makefile	Wed Dec 31 16:00:00 1969
@@ -1,48 +0,0 @@
-#
-# Makefile for the Linux IrDA IrLPT protocol layer.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definition is now in the main makefile...
-
-MOD_LIST_NAME := IRDA_MODULES
-O_TARGET := irlpt.o
-O_OBJS	 := irlpt_common.o
-M_OBJS   := $(O_TARGET)
-MI_OBJS  :=
-
-OX_OBJS  += 
-
-ifeq ($(CONFIG_IRLPT_CLIENT),y)
-O_OBJS += irlpt_cli.o irlpt_cli_fsm.o
-else
-  ifeq ($(CONFIG_IRLPT_CLIENT),m)
-  M_OBJS += irlpt_client.o
-  endif
-endif
-
-ifeq ($(CONFIG_IRLPT_SERVER),y)
-O_OBJS += irlpt_srvr.o irlpt_srvr_fsm.o
-else
-  ifeq ($(CONFIG_IRLPT_SERVER),m)
-  M_OBJS += irlpt_server.o
-  endif
-endif
-
-# Special rule to build the composite modules
-ifeq ($(CONFIG_IRLPT_CLIENT),m)
-irlpt_client.o: irlpt_cli.o irlpt_cli_fsm.o
-	$(LD) $(LD_RFLAG) -r -o $@ irlpt_cli.o irlpt_cli_fsm.o
-endif
-ifeq ($(CONFIG_IRLPT_SERVER),m)
-irlpt_server.o: irlpt_srvr.o irlpt_srvr_fsm.o
-	$(LD) $(LD_RFLAG) -r -o $@ irlpt_srvr.o irlpt_srvr_fsm.o
-endif
-
-include $(TOPDIR)/Rules.make
-
-tar:
-	tar -cvf /dev/f1 .
-
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlpt/irlpt_cli.c linux/net/irda/irlpt/irlpt_cli.c
--- v2.3.15/linux/net/irda/irlpt/irlpt_cli.c	Sun May 30 10:27:04 1999
+++ linux/net/irda/irlpt/irlpt_cli.c	Wed Dec 31 16:00:00 1969
@@ -1,660 +0,0 @@
-/*********************************************************************
- *
- * Filename:      irlpt_cli.c
- * Version:       
- * Description:   
- * Status:        Experimental.
- * Author:        Thomas Davis, <ratbert@radiks.net>
- * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Sun Mar  8 23:44:19 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:	  irlan.c
- *
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
- *     Copyright (c) 1998, Dag Brattli,  <dagb@cs.uit.no>
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Thomas Davis, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <net/irda/irlap.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irias_object.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irlpt_common.h>
-#include <net/irda/irlpt_cli.h>
-#include <net/irda/irlpt_cli_fsm.h>
-#include <net/irda/timer.h>
-#include <net/irda/irda.h>
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include <asm/uaccess.h>
-#include <linux/miscdevice.h>
-#include <linux/proc_fs.h>
-
-int irlpt_client_init(void);
-static void irlpt_client_close(struct irlpt_cb *self);
-
-static void irlpt_client_discovery_indication(discovery_t *);
-
-static void irlpt_client_connect_confirm(void *instance, void *sap, 
-					 struct qos_info *qos, 
-					 __u32 max_seg_size, 
-					 __u8 max_header_size,
-					 struct sk_buff *skb);
-static void irlpt_client_disconnect_indication(void *instance, void *sap, 
-					       LM_REASON reason,
-					       struct sk_buff *userdata);
-static void irlpt_client_expired(unsigned long data);
-
-#if 0
-static char *rcsid = "$Id: irlpt_client.c,v 1.10 1998/11/10 22:50:57 dagb Exp $";
-#endif
-static char *version = "IrLPT client, v2 (Thomas Davis)";
-
-static __u32 ckey; /* IrLMP client handle */
-
-struct file_operations client_fops = {
-	irlpt_seek,    /* seek */
-	NULL,          /* read_irlpt (server) */
-	irlpt_write,   /* write */
-	NULL,	       /* readdir */
-	NULL,          /* poll */
-	NULL,	       /* ioctl */
-	NULL,	       /* mmap */
-	irlpt_open,    /* open */
-	NULL,          /* flush */
-	irlpt_close,   /* release */
-	NULL,          /* fsync */
-	NULL,          /* fasync */
-	NULL,          /* check_media_change */
-	NULL,          /* revalidate */
-	NULL,          /* lock */
-};
-
-int irlpt_client_debug = 4;
-
-extern char *irlptstate[];
-
-#ifdef CONFIG_PROC_FS
-
-/*
- * Function client_proc_read (buf, start, offset, len, unused)
- *
- */
-static int irlpt_client_proc_read( char *buf, char **start, off_t offset, 
-				   int len, int unused)
-{
-	struct irlpt_cb *self;
-	int index;
-
-	len = sprintf(buf, "%s\n\n", version);
-
-	self = (struct irlpt_cb *) hashbin_get_first( irlpt_clients);
-	while( self) {
-	        ASSERT( self != NULL, return len;);
-          	ASSERT( self->magic == IRLPT_MAGIC, return len;);
-		if (self->in_use == FALSE) {
-		        break;
-		}
-
-		len += sprintf(buf+len, "ifname: %s\n", self->ifname);
-		len += sprintf(buf+len, "minor: %d\n", self->ir_dev.minor);
-
-		switch ( self->servicetype) {
-		case IRLPT_UNKNOWN:
-			index = 0;
-			break;
-		case IRLPT_THREE_WIRE_RAW:
-			index = 1;
-			break;
-		case IRLPT_THREE_WIRE:
-			index = 2;
-			break;
-		case IRLPT_NINE_WIRE:
-			index = 3;
-			break;
-		case IRLPT_CENTRONICS:
-			index = 4;
-			break;
-		case IRLPT_SERVER_MODE:
-			index = 5;
-			break;
-		default:
-			index = 0;
-			break;
-		}
-		
-		len += sprintf(buf+len, "service_type: %s, port type: %s\n", 
-			       irlpt_service_type[index],
-			       irlpt_port_type[ self->porttype]);
-
-		len += sprintf(buf+len, "saddr: 0x%08x, daddr: 0x%08x\n", 
-			       self->saddr, self->daddr);
-		len += sprintf(buf+len, 
-			       "retries: %d, count: %d, queued packets: %d\n", 
-			       self->open_retries,
-			       self->count, self->pkt_count);
-		len += sprintf(buf+len, "slsap: %d, dlsap: %d\n", 
-			       self->slsap_sel, self->dlsap_sel);
-		len += sprintf(buf+len, "fsm state: %s\n", 
-			       irlpt_client_fsm_state[self->state]);
-		len += sprintf(buf+len, "\n\n");
-		
-		self = (struct irlpt_cb *) hashbin_get_next( irlpt_clients);
-	}
-	
-	return len;
-}
-
-extern struct proc_dir_entry *proc_irda;
-
-#endif /* CONFIG_PROC_FS */
-
-/*
- * Function irlpt_client_init (dev)
- *
- *   Initializes the irlpt control structure
- *
- */
-__initfunc(int irlpt_client_init(void))
-{
-	__u16 hints;
-	
-	DEBUG( irlpt_client_debug, "--> "__FUNCTION__ "\n");
-
-	printk( KERN_INFO "%s\n", version);
-
-	irlpt_clients = hashbin_new( HB_LOCAL); 
-	if ( irlpt_clients == NULL) {
-		printk( KERN_WARNING 
-			"IrLPT client: Can't allocate hashbin!\n");
-		return -ENOMEM;
-	}
-	hints = irlmp_service_to_hint(S_PRINTER);
-	ckey = irlmp_register_client(hints, irlpt_client_discovery_indication,
-				     NULL);
-
-#ifdef CONFIG_PROC_FS
-	create_proc_entry("irlpt_client", 0, proc_irda)->get_info
-		= irlpt_client_proc_read;
-#endif /* CONFIG_PROC_FS */
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-
-#ifdef MODULE
-/*
- * Function irlpt_client_cleanup (void)
- *
- */
-static void irlpt_client_cleanup(void)
-{
-	DEBUG( irlpt_client_debug, "--> "__FUNCTION__ "\n");
-
-	irlmp_unregister_client(ckey);
-
-	/*
-	 *  Delete hashbin and close all irlpt client instances in it
-	 */
-	hashbin_delete( irlpt_clients, (FREE_FUNC) irlpt_client_close);
-
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry("irlpt_client", proc_irda);
-#endif
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-#endif /* MODULE */
-
-
-/*
- * Function irlpt_client_open (void)
- *
- */
-static struct irlpt_cb *irlpt_client_open( __u32 daddr)
-{
-	struct irmanager_event mgr_event;
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_client_debug, "--> "__FUNCTION__ "\n");
-
-	self = (struct irlpt_cb *) hashbin_find(irlpt_clients, daddr, NULL);
-
-	if (self == NULL) {
-	        self = kmalloc(sizeof(struct irlpt_cb), GFP_ATOMIC);
-		if (self == NULL)
-		        return NULL;
-
-		memset(self, 0, sizeof(struct irlpt_cb));
-
-		ASSERT( self != NULL, return NULL;);
-
-		sprintf(self->ifname, "irlpt%d", 
-			hashbin_get_size(irlpt_clients));
-
-		hashbin_insert( irlpt_clients, (QUEUE *) self, daddr, NULL);
-	}
-
-	self->ir_dev.minor = MISC_DYNAMIC_MINOR;
-	self->ir_dev.name = self->ifname;
-	self->ir_dev.fops = &client_fops;
-
-	misc_register(&self->ir_dev);
-
-	self->magic = IRLPT_MAGIC;
-	self->in_use = TRUE;
-	self->servicetype = IRLPT_THREE_WIRE_RAW;
-	self->porttype = IRLPT_SERIAL;
-	self->do_event = irlpt_client_do_event;
-
-	skb_queue_head_init(&self->rx_queue);
-
-	irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-
-	/* Tell irmanager to create /dev/irlpt<X> */
-	mgr_event.event = EVENT_IRLPT_START;
-	sprintf(mgr_event.devname, "%s", self->ifname);
-	irmanager_notify(&mgr_event);
-
-	MOD_INC_USE_COUNT;
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-
-	return self;
-}
-
-/*
- * Function irlpt_client_close (self)
- *
- *    This function closes and marks the IrLPT instance as not in use.
- */
-static void irlpt_client_close( struct irlpt_cb *self)
-{
-	struct irmanager_event mgr_event;
-	struct sk_buff *skb;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	/* Tell irmanager to remove /dev/irlpt<X> */
-	mgr_event.event = EVENT_IRLPT_STOP;
- 	sprintf(mgr_event.devname, "%s", self->ifname);
- 	irmanager_notify(&mgr_event);
-
-	while (( skb = skb_dequeue(&self->rx_queue)) != NULL) {
-		DEBUG(irlpt_client_debug, 
-		      __FUNCTION__ ": freeing SKB\n");
-                dev_kfree_skb( skb);
-	}
-
-	misc_deregister(&self->ir_dev);
-	self->in_use = FALSE;
-
-	MOD_DEC_USE_COUNT;
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_discovery_indication (daddr)
- *
- *    Remote device discovered, try query the remote IAS to see which
- *    device it is, and which services it has.
- *
- */
-static void irlpt_client_discovery_indication(discovery_t *discovery)
-{
-	struct irlpt_info info;
-	struct irlpt_cb *self;
-	__u32 daddr; /* address of remote printer */
-	__u32 saddr; /* address of local link where it was discovered */
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	ASSERT( irlpt_clients != NULL, return;);
-	ASSERT( discovery != NULL, return;);
-
-	daddr = info.daddr = discovery->daddr;
-	saddr = info.saddr = discovery->saddr;
-
-	/*
-	 *  Check if an instance is already dealing with this device
-	 *  (daddr)
-	 */
-	self = (struct irlpt_cb *) hashbin_find( irlpt_clients, daddr, NULL);
-      	if (self == NULL || self->in_use == FALSE) {
-	        DEBUG( irlpt_client_debug, __FUNCTION__ 
-		       ": daddr 0x%08x not found or was closed\n", daddr);
-	        /*
-		 * We have no instance for daddr, so time to start a new 
-		 * instance. First we must find a free entry in master array
-		 */
-		if (( self = irlpt_client_open( daddr)) == NULL) {
-			DEBUG(irlpt_client_debug, __FUNCTION__ 
-			      ": failed!\n");
-			return;
-		}
-	}
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRLPT_MAGIC, return;);
-
-	self->daddr = daddr;
-	self->saddr = saddr;
-	self->timeout = irlpt_client_expired;
-
-	irda_start_timer( &self->lpt_timer, 5000, (unsigned long) self, 
-			  self->timeout);
-	
-#if 0
-	/* changed to wake up when we get connected; that way,
-	   if the connection drops, we can easily kill the link. */
-	wake_up_interruptible( &self->write_wait);
-#endif
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_disconnect_indication (handle)
- *
- */
-static void irlpt_client_disconnect_indication( void *instance,
-						void *sap, 
-						LM_REASON reason,
-						struct sk_buff *skb)
-{
-	struct irlpt_info info;
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	self = ( struct irlpt_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	info.daddr = self->daddr;
-
-        DEBUG( irlpt_client_debug, 
-	       __FUNCTION__ ": reason=%d (%s), peersap=%d\n",
-	       reason, irlpt_reasons[reason], self->dlsap_sel);
-
-	self->connected = IRLPT_DISCONNECTED;
-	self->eof = reason;
-
-	wake_up_interruptible( &self->write_wait);
-
-	irlpt_client_do_event( self, LMP_DISCONNECT, NULL, NULL);
-
-	if (skb)
-		dev_kfree_skb( skb);
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_connect_confirm (handle, qos, skb)
- *
- *    LSAP connection confirmed!
- */
-static void irlpt_client_connect_confirm(void *instance, void *sap, 
-					 struct qos_info *qos, 
-					 __u32 max_seg_size,
-					 __u8 max_header_size,
-					 struct sk_buff *skb)
-{
-	struct irlpt_info info;
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	self = ( struct irlpt_cb *) instance;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	info.daddr = self->daddr;
-
-#if 0
-	/*
-	 *  Check if we have got some QoS parameters back! This should be the
-	 *  negotiated QoS for the link.
-	 */
-	if ( qos) {
-		DEBUG( irlpt_client_debug, __FUNCTION__ ": Frame Size: %d\n",
-		       qos->data_size.value);
-	}
-#endif
-
-	self->max_data_size = max_seg_size;
-	self->max_header_size = max_header_size;
-	self->connected = TRUE;
-	
-	irlpt_client_do_event( self, LMP_CONNECT, NULL, NULL);
-
-	if (skb)
-		dev_kfree_skb( skb);
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function client_data_indication (handle, skb)
- *
- *    This function gets the data that is received on the data channel
- *
- */
-static int irlpt_client_data_indication(void *instance, void *sap, 
-					struct sk_buff *skb) 
-{
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	ASSERT( skb != NULL, return -1;);
-	DEBUG( irlpt_client_debug, __FUNCTION__ ": len=%d\n", (int) skb->len);
-
-	self = ( struct irlpt_cb *) instance;
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-#if 1
-	{
-		int i;
-
-		for(i=0;i<skb->len;i++)
-			if (skb->data[i] > 31 && skb->data[i] < 128) {
-				printk("%c", skb->data[i]);
-			} else {
-				if (skb->data[i] == 0x0d) {
-					printk("\n");
-				} else {
-					printk(".");
-				}
-			}
-
-		printk("\n");
-	}
-#endif
-	
-	skb_queue_tail(&self->rx_queue, skb);
-        wake_up_interruptible(&self->read_wait);
-
-/* 	if (skb) { */
-/* 		dev_kfree_skb( skb); */
-/* 	} */
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function irlpt_get_value_confirm (obj_id, type, value_int, value_char, priv)
- *
- *    Fixed to match changes in iriap.h, DB.
- *
- */
-void irlpt_client_get_value_confirm(int result, __u16 obj_id, 
-				    struct ias_value *value, void *priv)
-{
-	struct irlpt_info info;
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	ASSERT( priv != NULL, return;);
-
-	self = (struct irlpt_cb *) priv;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	/* Check if request succeeded */
-	if (result != IAS_SUCCESS) {
-		DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
-		irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, NULL, 
-				       &info);
-		return;
-	}
-
-	if ( value->type == IAS_INTEGER && value->t.integer != -1) {
-	        info.dlsap_sel = value->t.integer;
-		self->dlsap_sel = value->t.integer;
-
-		DEBUG( irlpt_client_debug, __FUNCTION__ 
-		       ": obj_id = %d, value = %d\n", 
-		       obj_id, value->t.integer);
-
-		irlpt_client_do_event( self, IAS_PROVIDER_AVAIL, NULL, &info);
-	} else
-		irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, NULL, 
-				       &info);
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-void irlpt_client_connect_request( struct irlpt_cb *self) 
-{
-	struct notify_t lpt_notify;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	irda_notify_init( &lpt_notify);
-
-	lpt_notify.connect_confirm = irlpt_client_connect_confirm;
-	lpt_notify.disconnect_indication = irlpt_client_disconnect_indication;
-	lpt_notify.data_indication = irlpt_client_data_indication;
-	strcpy( lpt_notify.name, "IrLPT client");
-	lpt_notify.instance = self;
-
-	self->lsap = irlmp_open_lsap( LSAP_ANY, &lpt_notify);
-	DEBUG( irlpt_client_debug, __FUNCTION__ ": Dest LSAP sel= %d\n", 
-	       self->dlsap_sel);
-	
-	if (self->servicetype == IRLPT_THREE_WIRE_RAW) {
-	        DEBUG( irlpt_client_debug, __FUNCTION__ 
-		       ": issue THREE_WIRE_RAW connect\n");
-		irlmp_connect_request( self->lsap, self->dlsap_sel, 
-				       self->saddr, self->daddr, NULL, NULL);
-	}
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-static void irlpt_client_expired(unsigned long data)
-{
-	struct irlpt_cb *self = (struct irlpt_cb *) data;
-	struct sk_buff *skb;
-
-	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
-
-	DEBUG( irlpt_client_debug, __FUNCTION__
-	       ": removing irlpt_cb!\n");
-
-	ASSERT(self != NULL, return; );
-	ASSERT(self->magic == IRLPT_MAGIC, return;);
-
-	if (self->state == IRLPT_CLIENT_CONN) {
-		skb = dev_alloc_skb(64);
-		if (skb == NULL) {
-			DEBUG( 0, __FUNCTION__ "(: Could not allocate an "
-			       "sk_buff of length %d\n", 64);
-			return;
-		}
-
-		skb_reserve(skb, LMP_MAX_HEADER);
-		irlmp_disconnect_request(self->lsap, skb);
-		DEBUG(irlpt_client_debug, __FUNCTION__
-		      ": irlmp_close_slap(self->lsap)\n");
-		irlmp_close_lsap(self->lsap);
-	}
-
-	irlpt_client_close(self);
-
-	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
-MODULE_DESCRIPTION("The Linux IrDA/IrLPT client protocol");
-MODULE_PARM(irlpt_client_debug,"1i");
-MODULE_PARM(irlpt_client_fsm_debug,"1i");
-
-/*
- * Function init_module (void)
- *
- *    Initialize the IrLPT client module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void)
-{
-
-        DEBUG( irlpt_client_debug, "--> IrLPT client: init_module\n");
-
-        irlpt_client_init();
-
-        DEBUG( irlpt_client_debug, "IrLPT client: init_module -->\n");
-
-        return 0;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the IrLPT server module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void)
-{
-        DEBUG( irlpt_client_debug, "--> IrLPT client: cleanup_module\n");
-        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
-        /* Free some memory */
-        irlpt_client_cleanup();
-
-        DEBUG( irlpt_client_debug, "IrLPT client: cleanup_module -->\n");
-}
-
-#endif /* MODULE */
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlpt/irlpt_cli_fsm.c linux/net/irda/irlpt/irlpt_cli_fsm.c
--- v2.3.15/linux/net/irda/irlpt/irlpt_cli_fsm.c	Sun May 30 10:27:04 1999
+++ linux/net/irda/irlpt/irlpt_cli_fsm.c	Wed Dec 31 16:00:00 1969
@@ -1,369 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlpt_cli_fsm.c
- * Version:       0.1
- * Description:   
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Tue Jan 12 11:06:00 1999
- * Modified at:   Sun May  9 13:36:13 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998-1999, Thomas Davis, <ratbert@radiks.net>
- *     Copyright (c) 1998, Dag Brattli, <dagb@cs.uit.no>
- *     All Rights Reserved.
- *      
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *  
- *     I, Thomas Davis, provide no warranty for any of this software. This 
- *     material is provided "AS-IS" and at no charge.
- *     
- ********************************************************************/
-
-#include <net/irda/iriap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irlpt_common.h>
-#include <net/irda/irlpt_cli.h>
-#include <net/irda/irlpt_cli_fsm.h>
-#include <net/irda/irda.h>
-
-#if 0
-static char *rcsid = "$Id: irlpt_client_fsm.c,v 1.3 1998/10/05 05:46:44 ratbert Exp $";
-#endif
-
-static int irlpt_client_state_idle  ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event,
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-static int irlpt_client_state_query ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event,
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-static int irlpt_client_state_ready ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event, 
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-static int irlpt_client_state_waiti ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event,
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-static int irlpt_client_state_conn  ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event,
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-
-int irlpt_client_fsm_debug = 4;
-
-int (*irlpt_client_state[])( struct irlpt_cb *self, 
-			     IRLPT_EVENT event, 
-			     struct sk_buff *skb, 
-			     struct irlpt_info *info) = 
-{ 
-	irlpt_client_state_idle,
-	irlpt_client_state_query,
-	irlpt_client_state_ready,
-	irlpt_client_state_waiti,
-	irlpt_client_state_conn,
-};
-
-void irlpt_client_do_event( struct irlpt_cb *self, 
-			    IRLPT_EVENT event, 
-			    struct sk_buff *skb, 
-			    struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ "\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	DEBUG( irlpt_client_fsm_debug, 
-	       __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
-	       irlpt_server_fsm_state[self->state], irlpt_fsm_event[event]);
-
-	(*irlpt_client_state[ self->state]) ( self, event, skb, info);
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-}
-
-void irlpt_client_next_state( struct irlpt_cb *self, 
-			      IRLPT_CLIENT_STATE state) 
-{
-	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": NEXT STATE = %s\n", 
-	       irlpt_client_fsm_state[state]);
-
-	self->state = state;
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_client_state_idle (self, event, skb, info)
- *
- *    IDLE, We are waiting for an indication that there is a provider
- *    available.
- */
-static int irlpt_client_state_idle( struct irlpt_cb *self, 
-				    IRLPT_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case IRLPT_DISCOVERY_INDICATION:
-		/* Get some values from peer IAS */
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": IRLPT_DISCOVERY_INDICATION, "
-		       "sending getvaluebyclass command..\n");
-		iriap_getvaluebyclass_request( 
-			"IrLPT", "IrDA:IrLMP:LsapSel",
-			info->saddr, info->daddr,
-			irlpt_client_get_value_confirm,
-			(void *) self);
-		irlpt_client_next_state( self, IRLPT_CLIENT_QUERY);
-		break;
-
-	default:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d (%s)\n",
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if (skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function irlpt_client_state_query
- *
- *    QUERY, We have queryed the remote IAS and is ready to connect
- *    to provider, just waiting for the confirm.
- *
- */
-static int irlpt_client_state_query( struct irlpt_cb *self, 
-				     IRLPT_EVENT event, 
-				     struct sk_buff *skb, 
-				     struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case IAS_PROVIDER_AVAIL:
-		DEBUG( irlpt_client_fsm_debug, 
-		       __FUNCTION__ ": IAS_PROVIDER_AVAIL\n");
-		self->open_retries = 0;
-		irlpt_client_next_state( self, IRLPT_CLIENT_READY);
-		irlpt_client_do_event( self, IRLPT_CONNECT_REQUEST, 
-				       NULL, NULL);
-		break;
-
-	case IAS_PROVIDER_NOT_AVAIL:
-		DEBUG( irlpt_client_fsm_debug, 
-		       __FUNCTION__ ": IAS_PROVIDER_NOT_AVAIL\n");
-		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
-		      ": waking any sleepers..\n");
-		wake_up_interruptible(&self->read_wait);
-		break;
-
-	case LMP_DISCONNECT:
-	case LAP_DISCONNECT:
-	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": LMP_DISCONNECT or LAP_DISCONNECT\n");
-		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
-		      ": waking any sleepers..\n");
-		wake_up_interruptible(&self->read_wait);
-		break;
-	default:
-		DEBUG( irlpt_client_fsm_debug, 
-		       __FUNCTION__ ": Unknown event %d (%s)\n",
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if (skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function irlpt_client_state_info 
- *
- *    INFO, We have issued a GetInfo command and is awaiting a reply.
- */
-static int irlpt_client_state_ready( struct irlpt_cb *self, 
-				     IRLPT_EVENT event,
-				     struct sk_buff *skb, 
-				     struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case IRLPT_CONNECT_REQUEST:
-	        DEBUG( irlpt_client_fsm_debug, 
-		       __FUNCTION__ ": IRLPT_CONNECT_REQUEST\n");
-		irlpt_client_connect_request(self);
-		irlpt_client_next_state( self, IRLPT_CLIENT_WAITI);
-		break;
-	case LMP_DISCONNECT:
-	case LAP_DISCONNECT:
-	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": LMP_DISCONNECT or LAP_DISCONNECT\n");
-		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
-		      ": waking any sleepers..\n");
-		wake_up_interruptible(&self->read_wait);
-		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		break;
-	default:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d (%s)\n", 
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-
-/*
- * Function irlpt_client_state_waiti 
- *
- *
- */
-static int irlpt_client_state_waiti( struct irlpt_cb *self, 
-				     IRLPT_EVENT event, 
-				     struct sk_buff *skb, 
-				     struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case LMP_CONNECT:
-	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_CONNECT\n");
-	        irlpt_client_next_state(self, IRLPT_CLIENT_CONN);
-		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
-		      ": waking any sleepers..\n");
-		wake_up_interruptible(&self->read_wait);
-	        break;
-	case LAP_DISCONNECT:
-	case LMP_DISCONNECT:
-	        DEBUG( irlpt_client_fsm_debug, 
-		       __FUNCTION__ ": LMP_DISCONNECT\n");
-		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
-		      ": waking any sleepers..\n");
-		wake_up_interruptible(&self->read_wait);
-	        irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-	        break;
-
-	default:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d (%s)\n", 
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function irlpt_client_state_conn (self, event, skb, info)
- *
- *    CONN, We have connected to a provider but has not issued any
- *    commands yet.
- *
- */
-static int irlpt_client_state_conn( struct irlpt_cb *self, 
-				    IRLPT_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlpt_info *info) 
-{
-	DEBUG( irlpt_client_fsm_debug, "--> " __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case CLIENT_DATA_INDICATION:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": CLIENT_DATA_INDICATION\n");
-		irlpt_client_next_state( self, IRLPT_CLIENT_CONN);
-		break;
-
-	case LMP_DISCONNECT:
-	case LAP_DISCONNECT:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": LMP_DISCONNECT/LAP_DISCONNECT\n");
-		DEBUG(irlpt_client_fsm_debug, __FUNCTION__
-		      ": waking any sleepers..\n");
-		wake_up_interruptible(&self->read_wait);
-	        irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-		break;
-
-	default:
-		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d (%s)\n",
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-void irlpt_client_print_event( IRLPT_EVENT event) 
-{
-	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-	       ": IRLPT_EVENT = %s\n", irlpt_fsm_event[event]);
-}
-
-
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlpt/irlpt_common.c linux/net/irda/irlpt/irlpt_common.c
--- v2.3.15/linux/net/irda/irlpt/irlpt_common.c	Sun May 30 10:27:04 1999
+++ linux/net/irda/irlpt/irlpt_common.c	Wed Dec 31 16:00:00 1969
@@ -1,509 +0,0 @@
-/*********************************************************************
- *
- * Filename:      irlpt_common.c
- * Version:       
- * Description:   
- * Status:        Experimental.
- * Author:        Thomas Davis, <ratbert@radiks.net>
- * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Sun Mar  8 23:44:19 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:	  irlpt.c
- *
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
- *     Copyright (c) 1998, Dag Brattli,  <dagb@cs.uit.no>
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Thomas Davis, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <linux/module.h> 
-
-#include <asm/segment.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irlap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irttp.h>
-#include <net/irda/timer.h>
-
-#include <net/irda/irlpt_common.h>
-/* #include "irlpt_client.h" */
-/* #include "irlpt_server.h" */
-
-#include <asm/uaccess.h>
-#include <linux/miscdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/fs.h>
-
-char *irlpt_service_type[] = {
-	"IRLPT_UNKNOWN",
-	"IRLPT_THREE_WIRE_RAW",
-	"IRLPT_THREE_WIRE",
-	"IRLPT_NINE_WIRE",
-	"IRLPT_CENTRONICS",
-	"IRLPT_SERVER_MODE",
-};
-
-char *irlpt_port_type[] = {
-	"IRLPT_UNKNOWN",
-	"IRLPT_SERIAL",
-	"IRLPT_PARALLEL",
-};
-
-char *irlpt_connected[] = {
-	"IRLPT_DISCONNECTED",
-	"IRLPT_WAITING",
-	"IRLPT_CONNECTED",
-	"IRLPT_FLUSHED",
-};
-
-char *irlpt_reasons[] = {
-	"SERVICE_CLOSE",     /* Service has closed the connection */
-	"DISC_INDICATION",   /* Received disconnect request from peer entity*/
-	"NO_RESPONSE",       /* To many retransmits without response */
-	"DEADLOCK_DETECTED", /* To many retransmits _with_ response */
-	"FOUND_NONE",        /* No devices were discovered */
-	"MEDIA_BUSY",
-
-};
-
-char *irlpt_client_fsm_state[] = {
-	"IRLPT_CLIENT_IDLE",
-	"IRLPT_CLIENT_QUERY",
-	"IRLPT_CLIENT_READY",
-	"IRLPT_CLIENT_WAITI",
-	"IRLPT_CLIENT_CONN"
-};
-
-char *irlpt_server_fsm_state[] = {
-	"IRLPT_SERVER_IDLE",
-	"IRLPT_SERVER_CONN"
-};
-
-char *irlpt_fsm_event[] = {
-	"QUERY_REMOTE_IAS",
-	"IAS_PROVIDER_AVAIL",
-	"IAS_PROVIDER_NOT_AVAIL",
-	"LAP_DISCONNECT",
-	"LMP_CONNECT",
-	"LMP_DISCONNECT",
-	"LMP_CONNECT_INDICATION",
-	"LMP_DISCONNECT_INDICATION",
-        "IRLPT_DISCOVERY_INDICATION",
-	"IRLPT_CONNECT_REQUEST",
-	"IRLPT_DISCONNECT_REQUEST",
-	"CLIENT_DATA_INDICATION",
-};
-
-hashbin_t *irlpt_clients = NULL;
-struct irlpt_cb *irlpt_server = NULL;
-int irlpt_common_debug = 4;  /* want to change this? please don't! 
-				use irlpt_common_debug=3 on the 
-				command line! */
-
-#if 0
-static char *rcsid = "$Id: irlpt_common.c,v 1.6 1998/11/10 22:50:58 dagb Exp $";
-#endif
-
-struct irlpt_cb *irlpt_find_handle(unsigned int minor)
-{
-	struct irlpt_cb *self;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-	
-	/* Check for server */
-	if (irlpt_server != NULL && irlpt_server->ir_dev.minor == minor) {
-		DEBUG(irlpt_common_debug, __FUNCTION__ 
-		      ": irlpt_server file handle!\n");
-		return irlpt_server;
-	}
-
-	/* Check the clients */
-	self = (struct irlpt_cb *) hashbin_get_first( irlpt_clients);
-	while ( self) {
-		ASSERT( self->magic == IRLPT_MAGIC, return NULL;);
-		
-		if ( minor == self->ir_dev.minor)
-			return self;
-
-		self = (struct irlpt_cb *) hashbin_get_next( irlpt_clients);
-	}
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-
-	return NULL;
-}
-
-ssize_t irlpt_read( struct file *file, char *buffer, size_t count, loff_t
-		    *noidea)
-{
-	int len=0;
-	char *ptr = buffer;
-	struct irlpt_cb *self;
-	struct sk_buff *skb = NULL;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	self = irlpt_find_handle(MINOR( file->f_dentry->d_inode->i_rdev));
-
-	ASSERT( self != NULL, return 0;);
-	ASSERT( self->magic == IRLPT_MAGIC, return 0;);
-
-	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ": count=%d, skb_len=%d, connected=%d (%s) eof=%d\n", 
-	       count, skb_queue_len(&self->rx_queue), self->connected, 
-	       irlpt_connected[self->connected], self->eof);
-
-	if (self->eof && !skb_queue_len(&self->rx_queue)) {
-		switch (self->eof) {
-		case LM_USER_REQUEST:
-			self->eof = FALSE;
-			DEBUG(irlpt_common_debug, 
-			      __FUNCTION__ ": returning 0\n");
-			return 0;
-		case LM_LAP_DISCONNECT:
-			self->eof = FALSE;
-			return 0;
-		case LM_LAP_RESET:
-			self->eof = FALSE;
-			return -ECONNRESET;
-		default:
-			self->eof = FALSE;
-			return -EIO;
-		}
-	}
-
-	while (len <= count) {
-		skb = skb_dequeue(&self->rx_queue);
-
-		if (skb != NULL) {
-			DEBUG(irlpt_common_debug, __FUNCTION__ 
-			      ": len=%d, skb->len=%d, count=%d\n", 
-			       len, (int) skb->len, count);
-
-			if ((skb->len + len) < count) {
-				copy_to_user(ptr, skb->data, skb->len);
-				len += skb->len;
-				ptr += skb->len;
-		
-				dev_kfree_skb( skb);
-			} else {
-				skb_queue_head(&self->rx_queue, skb);
-				break;
-			}
-		} else {
-			DEBUG( irlpt_common_debug, __FUNCTION__ 
-			       ": skb=NULL, len=%d, count=%d, eof=%d\n", 
-			       len, count, self->eof);
-
-			if (!signal_pending(current) && !self->eof) {
-				interruptible_sleep_on(&self->read_wait);
-			} else
-				break;
-		}
-	}
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ ": len=%d\n", len);
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-	return len;
-}
-
-ssize_t irlpt_write(struct file *file, const char *buffer,
-		    size_t count, loff_t *noidea)
-{
-	struct irlpt_cb *self;
-	struct sk_buff *skb;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	self = irlpt_find_handle(MINOR( file->f_dentry->d_inode->i_rdev));
-
-	ASSERT( self != NULL, return 0;);
-	ASSERT( self->magic == IRLPT_MAGIC, return 0;);
-	
-	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ": count = %d\n", count);
-
-	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ": pkt_count = %d\n", self->pkt_count);
-	if (self->pkt_count > 8) {
-		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": too many outstanding buffers, going to sleep\n");
-		interruptible_sleep_on(&self->write_wait);
-	}
-
-	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ": pkt_count = %d\n", self->pkt_count);
-
-	if (self->state != IRLPT_CLIENT_CONN) {
-		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": state != IRLPT_CONN (possible link problems?)\n");
-		return -ENOLINK;
-	}
-
-	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ": count = %d, max_data_size = %d, IRLPT_MAX_HEADER = %d\n",
-		count, self->max_data_size, IRLPT_MAX_HEADER);
-
- 	if (count > self->max_data_size) {
- 		count = self->max_data_size;
- 		DEBUG(irlpt_common_debug, __FUNCTION__ 
-		      ": setting count to %d\n", count);
- 	}
-
-	DEBUG( irlpt_common_debug, __FUNCTION__ ": count = %d\n", count);
-
-	skb = dev_alloc_skb(count + self->max_header_size);
-	if ( skb == NULL) {
-		printk( KERN_INFO 
-			__FUNCTION__ ": couldn't allocate skbuff!\n");
-		return 0;
-	}
-
-	/*
-	 * we use the unused stamp field to hold the device minor
-	 * number, so we can look it up when the skb is destroyed.
-	 */
-	*((__u32 *) &skb->stamp) = MINOR( file->f_dentry->d_inode->i_rdev);
-
-	skb_reserve( skb, IRLPT_MAX_HEADER);
-	skb_put( skb, count);
-
-	skb->destructor = irlpt_flow_control;
-	self->pkt_count++;
-
-	copy_from_user( skb->data, buffer, count);
-
-	irlmp_data_request(self->lsap, skb);
-
-	irda_start_timer( &self->lpt_timer, 5000, (unsigned long) self, 
-			  self->timeout);
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-
-	return(count);
-}
-
-loff_t irlpt_seek( struct file *file, loff_t offset, int count)
-{
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-	return -ESPIPE;
-}
-
-/*
- * Function irlpt_poll (file, wait)
- *
- *    
- *
- */
-u_int irlpt_poll(struct file *file, poll_table *wait)
-{
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	/* check out /usr/src/pcmcia/modules/ds.c for an example */
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-	return 0;
-}
-
-/*
- * Function open_irlpt (inode, file)
- *
- *
- *
- */
-int irlpt_open(struct inode *inode, struct file *file)
-{
-	struct irlpt_cb *self;
-	struct irlpt_info info;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	self = irlpt_find_handle(MINOR( file->f_dentry->d_inode->i_rdev));
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	if (self->count++) {
-		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": count not zero; actual = %d\n", self->count);
-		self->count--;
-		return -EBUSY;
-	}
-
-	self->eof = FALSE;
-
-	/* ok, now, if it's idle, try to get some information
-	   about the remote end, and sleep till we get totally connected.. */
-
-	if ((self->servicetype != IRLPT_SERVER_MODE) && 
-	    self->state != IRLPT_CLIENT_CONN) {
-		DEBUG(irlpt_common_debug, __FUNCTION__
-		      ": self->state != IRLPT_CLIENT_CONN\n");
-
-		info.daddr = self->daddr;
-		info.saddr = self->saddr;
-
-		if (self->do_event != NULL) {
-			DEBUG(irlpt_common_debug, __FUNCTION__ 
-			      ": doing a discovery..\n");
-			self->do_event( self, 
-					IRLPT_DISCOVERY_INDICATION, 
-					NULL, &info);
-			DEBUG(irlpt_common_debug, __FUNCTION__ 
-			      ": sleeping until connected.\n");
-			interruptible_sleep_on(&self->read_wait);
-		}
-	}
-
-	/* at this point, if it's a client, we have a connection.
-	 * if it's the server, it's waiting for a connection.
-	 */
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function close_irlpt (inode, file)
- *
- *
- *
- */
-int irlpt_close(struct inode *inode, 
-		struct file *file)
-{
-	struct irlpt_cb *self;
-	struct sk_buff *skb;
-	struct irlpt_info info;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	self = irlpt_find_handle(MINOR( file->f_dentry->d_inode->i_rdev));
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ ": have handle!\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	DEBUG(irlpt_common_debug, 
-	      __FUNCTION__ ": self->count=%d\n", self->count);
-
-	if (self->count > 0)
-		self->count--;
-
-	while (self->pkt_count > 0) {
-		interruptible_sleep_on(&self->write_wait);
-	}
-
-	/* all done, tear down the connection and wait for the next open */
-	if ((self->servicetype != IRLPT_SERVER_MODE) &&
-	    self->state == IRLPT_CLIENT_CONN) {
-		skb = dev_alloc_skb(64);
-		if (skb == NULL) {
-			DEBUG( 0, __FUNCTION__ "(: Could not allocate an "
-			       "sk_buff of length %d\n", 64);
-			return 0;
-		}
-
-		skb_reserve( skb, LMP_MAX_HEADER);
-		irlmp_disconnect_request(self->lsap, skb);
-		DEBUG(irlpt_common_debug, __FUNCTION__
-		      ": irlmp_close_slap(self->lsap)\n");
-		irlmp_close_lsap(self->lsap);
-	}
-
-	info.daddr = self->daddr;
-
-	if (self->do_event != NULL) {
-	        DEBUG(irlpt_common_debug, __FUNCTION__ 
-		      ": closing connection..\n");
-		self->do_event( self, LMP_DISCONNECT, NULL, &info);
-	}
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-	return 0;
-}
-
-void irlpt_dump_buffer( struct sk_buff *skb) 
-{
-	int i;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	for(i=0;i<skb->len;i++)
-		if (skb->data[i] > 31 && skb->data[i] < 128) {
-			printk("%c", skb->data[i]);
-		} else {
-			if (skb->data[i] == 0x0d) {
-				printk("\n");
-			} else {
-				printk(".");
-			}
-		}
-	
-	printk("\n");
-	
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-}
-
-void irlpt_flow_control(struct sk_buff *skb)
-{
-	struct irlpt_cb *self;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-
-	self = irlpt_find_handle( *((__u32 *) &skb->stamp));
-
-	self->pkt_count--;
-
-	ASSERT(self->pkt_count >= 0, return;);
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ 
-	      ": packet destroyed, count = %d\n", self->pkt_count);
-
-	wake_up_interruptible( &self->write_wait);
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
-MODULE_DESCRIPTION("The Linux IrDA/IrLPT common");
-MODULE_PARM(irlpt_common_debug,"1i");
-
-/*
- * Function init_module (void)
- *
- *    Initialize the module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void) 
-{
-	return 0;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void) 
-{
-
-}
-
-#endif /* MODULE */
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlpt/irlpt_srvr.c linux/net/irda/irlpt/irlpt_srvr.c
--- v2.3.15/linux/net/irda/irlpt/irlpt_srvr.c	Sun May 30 10:27:04 1999
+++ linux/net/irda/irlpt/irlpt_srvr.c	Wed Dec 31 16:00:00 1969
@@ -1,530 +0,0 @@
-/*********************************************************************
- *
- * Filename:      irlpt.c
- * Version:       
- * Description:   
- * Status:        Experimental.
- * Author:        Thomas Davis, <ratbert@radiks.net>
- * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Sun Mar  8 23:44:19 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:	  irlan.c
- *
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
- *			   Dag Brattli,  <dagb@cs.uit.no>
- *     All Rights Reserved.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     I, Thomas Davis, provide no warranty for any of this software.
- *     This material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include <asm/uaccess.h>
-#include <linux/miscdevice.h>
-#include <linux/proc_fs.h>
-
-#include <net/irda/irlap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irias_object.h>
-#include <net/irda/timer.h>
-#include <net/irda/irda.h>
-#include <net/irda/irlpt_common.h>
-#include <net/irda/irlpt_server.h>
-#include <net/irda/irlpt_server_fsm.h>
-
-#ifdef CONFIG_PROC_FS
-static int irlpt_server_proc_read(char *buf, char **start, off_t offset, 
-				  int len, int unused);
-#endif /* CONFIG_PROC_FS */
-
-int irlpt_server_init(void);
-static void irlpt_server_disconnect_indication(void *instance, void *sap, 
-						LM_REASON reason,
-						struct sk_buff *skb);
-
-#if 0
-static void irlpt_server_connect_confirm(void *instance, void *sap, 
-					 struct qos_info *qos,  
-					 __u32 max_seg_size,
-					 __u8 max_header_size,
-					 struct sk_buff *skb);
-static void irlpt_server_connect_indication(void *instance, 
-					    void *sap, 
-					    struct qos_info *qos, 
-					    __u32 max_seg_size,
-					    __u8 max_header_size,
-					    struct sk_buff *skb);
-#endif
-
-static int irlpt_server_data_indication(void *instance, void *sap, 
-					struct sk_buff *skb);
-static void register_irlpt_server(void);
-static void deregister_irlpt_server(void);
-
-static __u32 skey; /* IrLMP service handle */
-
-int irlpt_server_lsap = LSAP_IRLPT;
-int irlpt_server_debug = 4;
-
-#if 0
-static char *rcsid = "$Id: irlpt_server.c,v 1.9 1998/10/22 12:02:22 dagb Exp $";
-#endif
-
-static char *version = "IrLPT server, v2 (Thomas Davis)";
-
-struct file_operations irlpt_fops = {
-	irlpt_seek,	/* seek */
-	irlpt_read,     /* read */   
-	irlpt_write,
-	NULL,		/* readdir */
-	NULL,           /* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	irlpt_open,     /* open */
-	NULL,           /* flush */
-	irlpt_close,    /* release */
-	NULL,           /* fsync */
-	NULL,           /* fasync */
-	NULL,           /* check_media_change */
-	NULL,           /* revalidate */
-        NULL,           /* lock */
-};
-
-#ifdef CONFIG_PROC_FS
-
-/*
- * Function irlpt_server_proc_read (buf, start, offset, len, unused)
- *
- *
- *
- */
-static int irlpt_server_proc_read(char *buf, char **start, off_t offset, 
-				  int len, int unused)
-{
-	int index;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	if (irlpt_server != NULL) {
-	        len = sprintf(buf, "%s\n\n", version);
-		len += sprintf(buf+len, "ifname: %s\n", irlpt_server->ifname);
-		len += sprintf(buf+len, "minor: %d\n", irlpt_server->ir_dev.minor);
-
-		switch (irlpt_server->servicetype) {
-		case IRLPT_UNKNOWN:
-			index = 0;
-			break;
-		case IRLPT_THREE_WIRE_RAW:
-			index = 1;
-			break;
-		case IRLPT_THREE_WIRE:
-			index = 2;
-			break;
-		case IRLPT_NINE_WIRE:
-			index = 3;
-			break;
-		case IRLPT_CENTRONICS:
-			index = 4;
-			break;
-		case IRLPT_SERVER_MODE:
-			index = 5;
-			break;
-		default:
-			index = 0;
-			break;
-		}
-
-		len += sprintf(buf+len, "servicetype: %s, porttype: %s\n",
-			       irlpt_service_type[index],
-			       irlpt_port_type[irlpt_server->porttype]);
-		len += sprintf(buf+len, "saddr: 0x%08x, daddr: 0x%08x\n", 
-			       irlpt_server->saddr, irlpt_server->daddr);
-		len += sprintf(buf+len, "slsap: 0x%08x, dlsap: 0x%08x\n", 
-			       irlpt_server->slsap_sel, 
-			       irlpt_server->dlsap_sel);
-		len += sprintf(buf+len, "retries: %d, count: %d\n", 
-			       irlpt_server->open_retries,
-			       irlpt_server->count);
-		len += sprintf(buf+len, "fsm state: %s, rx queue depth: %d\n", 
-			       irlpt_server_fsm_state[irlpt_server->state],
-			       skb_queue_len(&irlpt_server->rx_queue));
-		len += sprintf(buf+len, "\n");
-	}
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-
-	return len;
-}
-
-extern struct proc_dir_entry *proc_irda;
-#endif /* CONFIG_PROC_FS */
-
-/*
- * Function irlpt_init (dev)
- *
- *   Initializes the irlpt control structure
- *
- */
-
-__initfunc(int irlpt_server_init(void))
-{
-	struct irmanager_event mgr_event;
-	__u16 hints;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	printk( KERN_INFO "%s\n", version);
-
-	irlpt_server = (struct irlpt_cb *) kmalloc (sizeof(struct irlpt_cb), 
-						    GFP_KERNEL);
-
-	if ( irlpt_server == NULL) {
-		printk( KERN_WARNING "IrLPT server: Can't allocate" 
-			" irlpt_server control block!\n");
-		return -ENOMEM;
-	}
-	memset( irlpt_server, 0, sizeof(struct irlpt_cb));
-
-	sprintf(irlpt_server->ifname, "irlpt_server");
-	irlpt_server->ir_dev.minor = MISC_DYNAMIC_MINOR;
-	irlpt_server->ir_dev.name = irlpt_server->ifname;
-	irlpt_server->ir_dev.fops = &irlpt_fops;
-	misc_register(&irlpt_server->ir_dev);
-	irlpt_server->magic = IRLPT_MAGIC;
-	irlpt_server->in_use = TRUE;
-	irlpt_server->servicetype = IRLPT_THREE_WIRE_RAW;
-	irlpt_server->porttype = IRLPT_SERIAL;
-
-	skb_queue_head_init(&irlpt_server->rx_queue);
-
-	hints = irlmp_service_to_hint(S_PRINTER);
-	skey = irlmp_register_service(hints);
-	
-	register_irlpt_server();
-
-#ifdef CONFIG_PROC_FS
-	create_proc_entry("irlpt_server", 0, proc_irda)->get_info
-		= irlpt_server_proc_read;
-#endif /* CONFIG_PROC_FS */
-
-	mgr_event.event = EVENT_IRLPT_START;
-        sprintf(mgr_event.devname, "%s", irlpt_server->ifname);
-        irmanager_notify(&mgr_event);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function irlpt_cleanup (void)
- *
- *
- *
- */
-static void irlpt_server_cleanup(void)
-{
-	struct irmanager_event mgr_event;
-	struct sk_buff *skb;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	irlmp_unregister_service(skey);
-	deregister_irlpt_server();
-
-	while (( skb = skb_dequeue(&irlpt_server->rx_queue)) != NULL) {
-		DEBUG(irlpt_server_debug, __FUNCTION__ ": freeing SKB\n");
-                dev_kfree_skb( skb);
-	}
-
-	misc_deregister(&irlpt_server->ir_dev);
-
-	kfree(irlpt_server);
-
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry("irlpt_server", proc_irda);
-#endif
-
-        mgr_event.event = EVENT_IRLPT_STOP;
-        sprintf( mgr_event.devname, "%s", irlpt_server->ifname);
-        irmanager_notify( &mgr_event);
- 
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_disconnect_indication (handle)
- *
- */
-static void irlpt_server_disconnect_indication( void *instance, 
-						void *sap, 
-						LM_REASON reason,
-						struct sk_buff *userdata)
-{
-#if 0
-	struct irlpt_info info;
-#endif
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	self = ( struct irlpt_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-#if 0
-	info.daddr = self->daddr;
-#endif
-
-	DEBUG( irlpt_server_debug, 
-	       __FUNCTION__ ": reason=%d (%s), dlsap_sel=%d\n",
-	       reason, irlpt_reasons[reason], self->dlsap_sel);
-
-	self->connected = IRLPT_DISCONNECTED;
-	self->eof = reason;
-
-        wake_up_interruptible(&self->read_wait);
-	wake_up_interruptible(&self->write_wait);
-	wake_up_interruptible(&self->ex_wait);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ ": rx queue length: %d\n",
-	       skb_queue_len(&irlpt_server->rx_queue));
-
-	irlpt_server_do_event( self, LMP_DISCONNECT, NULL, NULL);
-
-	deregister_irlpt_server();
-	register_irlpt_server();
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_connect_confirm (handle, qos, skb)
- *
- *    LSAP connection confirmed!
- */
-static void irlpt_server_connect_confirm(void *instance, 
-					 void *sap, 
-					 struct qos_info *qos,
-					 __u32 max_seg_size,
-					 __u8 max_header_size,
-					 struct sk_buff *skb)
-{
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-	self = ( struct irlpt_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	self->max_data_size = max_seg_size;
-	self->max_header_size = max_header_size;
-
-	self->connected = TRUE;
-
-	irlpt_server_do_event( self, LMP_CONNECT, NULL, NULL);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_connect_indication (handle)
- *
- */
-static void irlpt_server_connect_indication(void *instance, 
-					    void *sap, 
-					    struct qos_info *qos, 
-					    __u32 max_seg_size,
-					    __u8 max_header_size,
-					    struct sk_buff *skb)
-{
-	struct irlpt_cb *self;
-	struct irlpt_info info;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	self = ( struct irlpt_cb *) instance;
-
-	info.lsap  = (struct lsap_cb *) sap;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	self->max_data_size = max_seg_size;
-	self->max_header_size = max_header_size;
-
-	self->connected = IRLPT_CONNECTED;
-	self->eof = FALSE;
-
-	irlpt_server_do_event( self, LMP_CONNECT, NULL, &info);
-
-	if (skb)
-		dev_kfree_skb( skb);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function irlpt_server_data_indication (handle, skb)
- *
- *    This function gets the data that is received on the data channel
- *
- */
-static int irlpt_server_data_indication(void *instance, void *sap, 
-					struct sk_buff *skb) 
-{
-	struct irlpt_cb *self;
-
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	self = ( struct irlpt_cb *) instance;
-	     
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	ASSERT( skb != NULL, return -1;);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ ": len=%d\n", (int) skb->len);
-
-#if 0
-	dump_buffer(skb);
-#endif
-	
-	skb_queue_tail(&self->rx_queue, skb);
-        wake_up_interruptible(&self->read_wait);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-	
-	return 0;
-}
-
-/*
- * Function register_irlpt_server(void)
- *
- *    Register server support so we can accept incoming connections. We
- *    must register both a TSAP for control and data
- * 
- */
-static void register_irlpt_server(void)
-{
-	struct notify_t notify;
-	struct ias_object *obj;
-	
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	/*
-	 *  First register control TSAP
-	 */
-	if ( !irlpt_server || irlpt_server->magic != IRLPT_MAGIC) {
-		DEBUG( 0, __FUNCTION__ ": unable to obtain handle!\n");
-		return;
-	}
-
-	irda_notify_init(&notify);
-
-	notify.connect_confirm = irlpt_server_connect_confirm;
-	notify.connect_indication = irlpt_server_connect_indication;
-	notify.disconnect_indication = irlpt_server_disconnect_indication;
-	notify.data_indication = irlpt_server_data_indication;
-	notify.instance = irlpt_server;
-	strcpy(notify.name, "IrLPT server");
-
-	irlpt_server->lsap = irlmp_open_lsap( irlpt_server_lsap, &notify);
-
-	irlpt_server->connected = IRLPT_WAITING;
-	irlpt_server->service_LSAP = irlpt_server_lsap;
-	irlpt_server->slsap_sel = irlpt_server_lsap;
-
-	/* 
-	 *  Register with LM-IAS
-	 */
-
-	obj = irias_new_object("IrLPT", IAS_IRLPT_ID);
-	irias_add_integer_attrib(obj, "IrDA:IrLMP:LsapSel", irlpt_server_lsap);
-	irias_insert_object(obj);
-
-	DEBUG( irlpt_server_debug, __FUNCTION__ 
-	       ": Source LSAP sel=%d\n", irlpt_server->slsap_sel);
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function register_irlpt_server(void)
- *
- *    Register server support so we can accept incoming connections. We
- *    must register both a TSAP for control and data
- * 
- */
-static void deregister_irlpt_server(void)
-{
-	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-
-	irlpt_server->connected = IRLPT_DISCONNECTED;
-
-	/* 
-	 *  de-Register with LM-IAS
-	 */
-	irias_delete_object( "IrLPT");
-
-	DEBUG( irlpt_server_debug, 
-	       __FUNCTION__ ": Source LSAP sel=%d\n", irlpt_server->slsap_sel);
-	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
-MODULE_DESCRIPTION("The Linux IrDA/IrLPT server protocol");
-MODULE_PARM(irlpt_server_debug,"1i");
-MODULE_PARM(irlpt_server_fsm_debug, "1i");
-
-/*
- * Function init_module (void)
- *
- *    Initialize the IrLPT server module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void)
-{
-	int ret;
-
-        DEBUG( irlpt_server_debug, "--> IrLPT server: init_module\n");
-
-        ret = irlpt_server_init();
-
-        DEBUG( irlpt_server_debug, "IrLPT server: init_module -->\n");
-
-        return ret;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the IrLPT server module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void)
-{
-        DEBUG( irlpt_server_debug, "--> IrLPT server: cleanup_module\n");
-
-        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
-        /* Free some memory */
-        irlpt_server_cleanup();
-
-        DEBUG( irlpt_server_debug, "IrLPT server: cleanup_module -->\n");
-}
-
-#endif /* MODULE */
diff -u --recursive --new-file v2.3.15/linux/net/irda/irlpt/irlpt_srvr_fsm.c linux/net/irda/irlpt/irlpt_srvr_fsm.c
--- v2.3.15/linux/net/irda/irlpt/irlpt_srvr_fsm.c	Sun Mar  7 15:26:44 1999
+++ linux/net/irda/irlpt/irlpt_srvr_fsm.c	Wed Dec 31 16:00:00 1969
@@ -1,187 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlpt_srvr_fsm.c
- * Version:       0.1
- * Sources:       irlan_event.c
- * 
- *     Copyright (c) 1997, Dag Brattli <dagb@cs.uit.no>, 
- *		All Rights Reserved.
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
- *		All Rights Reserved.
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
- *     the License, or (at your option) any later version.
- *
- *     I, Thomas Davis, provide no warranty for any of this software. This 
- *     material is provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <net/irda/iriap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irlpt_common.h>
-#include <net/irda/irlpt_server.h>
-#include <net/irda/irlpt_server_fsm.h>
-#include <net/irda/irda.h>
-
-static int irlpt_server_state_idle  ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event,
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-static int irlpt_server_state_conn  ( struct irlpt_cb *self, 
-				      IRLPT_EVENT event, 
-				      struct sk_buff *skb, 
-				      struct irlpt_info *info);
-
-#if 0
-static char *rcsid = "$Id: irlpt_server_fsm.c,v 1.4 1998/10/05 05:46:45 ratbert Exp $";
-#endif
-
-int irlpt_server_fsm_debug = 4; /* don't change this! */
-
-static int (*irlpt_server_state[])( struct irlpt_cb *self, 
-				    IRLPT_EVENT event, 
-				    struct sk_buff *skb,
-				    struct irlpt_info *info) = 
-{ 
-	irlpt_server_state_idle,
-	irlpt_server_state_conn,
-};
-
-void irlpt_server_do_event( struct irlpt_cb *self, 
-			    IRLPT_EVENT event, 
-			    struct sk_buff *skb, 
-			    struct irlpt_info *info) 
-{
-	DEBUG( irlpt_server_fsm_debug, 
-	       __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
-	       irlpt_server_fsm_state[self->state], irlpt_fsm_event[event]);
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	(*irlpt_server_state[ self->state]) ( self, event, skb, info);
-
-	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
-}
-
-void irlpt_server_next_state( struct irlpt_cb *self, 
-			      IRLPT_CLIENT_STATE state) 
-{
-
-	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ ": NEXT STATE = %s\n", 
-	       irlpt_server_fsm_state[state]);
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IRLPT_MAGIC, return;);
-
-	self->state = state;
-
-	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
-}
-
-/*
- * Function server_state_idle (event, skb, info)
- *
- *    IDLE, We are waiting for an indication that there is a provider
- *    available.
- */
-static int irlpt_server_state_idle( struct irlpt_cb *self, 
-				    IRLPT_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlpt_info *info) 
-{
-	struct sk_buff *r_skb;
-
-	DEBUG( irlpt_server_fsm_debug, "--> " __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case LMP_CONNECT:
-		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
-		       ": LM_CONNECT, remote lsap: 0x%08x\n",
-		       info->lsap->dlsap_sel);
-
-		self->dlsap_sel = info->lsap->dlsap_sel;
-		self->daddr = info->daddr;
-		self->saddr = info->saddr;
-
-		r_skb = dev_alloc_skb(64);
-		if (r_skb == NULL) { 
-			printk( KERN_INFO __FUNCTION__ 
-				": can't allocate sk_buff of length 64\n");
-			return 0;
-		}
-		skb_reserve( r_skb, LMP_MAX_HEADER);
-		irlmp_connect_response( self->lsap, r_skb);
-		irlpt_server_next_state( self, IRLPT_SERVER_CONN);
-		break;
-
-	default:
-		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d (%s)\n", 
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if (skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-/*
- * Function server_state_conn (event, skb, info)
- *
- *    CONN, We have connected to a provider but has not issued any
- *    commands yet.
- *
- */
-static int irlpt_server_state_conn( struct irlpt_cb *self, 
-				    IRLPT_EVENT event, 
-				    struct sk_buff *skb, 
-				    struct irlpt_info *info) 
-{
-	DEBUG( irlpt_server_fsm_debug, "--> " __FUNCTION__ ":\n");
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch( event) {
-	case LMP_DISCONNECT:
-	case LAP_DISCONNECT:
-		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
-		       ": LMP_DISCONNECT/LAP_DISCONNECT\n");
-		irlpt_server_next_state( self, IRLPT_SERVER_IDLE);
-		break;
-
-	default:
-		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
-		       ": Unknown event %d (%s)\n", 
-		       event, irlpt_fsm_event[event]);
-		break;
-	}
-
-	if ( skb) {
-		dev_kfree_skb( skb);
-	}
-
-	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-#if 0
-static void irlpt_server_print_event( IRLPT_EVENT event) 
-{
-	DEBUG( 0, "IRLPT_EVENT = %s\n", irlpt_fsm_event[event]);
-}
-#endif
diff -u --recursive --new-file v2.3.15/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.3.15/linux/net/irda/irmod.c	Mon Jul  5 20:03:14 1999
+++ linux/net/irda/irmod.c	Mon Aug 30 10:28:52 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:55:39 1997
- * Modified at:   Fri May 14 13:46:02 1999
+ * Modified at:   Wed Aug 11 08:53:56 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
@@ -27,10 +27,10 @@
 
 #include <linux/init.h>
 #include <linux/poll.h>
-#include <asm/segment.h>
-
 #include <linux/proc_fs.h>
 
+#include <asm/segment.h>
+
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
 #include <net/irda/irlap.h>
@@ -44,6 +44,7 @@
 #include <net/irda/irda_device.h>
 #include <net/irda/wrapper.h>
 #include <net/irda/timer.h>
+#include <net/irda/parameters.h>
 
 extern struct proc_dir_entry *proc_irda;
 
@@ -66,7 +67,7 @@
 extern int irlan_client_init(void);
 extern int irlan_server_init(void);
 extern int ircomm_init(void);
-extern int irvtd_init(void);
+extern int ircomm_tty_init(void);
 extern int irlpt_client_init(void);
 extern int irlpt_server_init(void);
 
@@ -120,6 +121,11 @@
 EXPORT_SYMBOL(irmanager_notify);
 EXPORT_SYMBOL(irda_lock);
 EXPORT_SYMBOL(proc_irda);
+EXPORT_SYMBOL(irda_param_insert);
+EXPORT_SYMBOL(irda_param_extract);
+EXPORT_SYMBOL(irda_param_extract_all);
+EXPORT_SYMBOL(irda_param_pack);
+EXPORT_SYMBOL(irda_param_unpack);
 
 /* IrIAP/IrIAS */
 EXPORT_SYMBOL(iriap_getvaluebyclass_request);
@@ -176,6 +182,8 @@
 EXPORT_SYMBOL(irda_device_setup);
 EXPORT_SYMBOL(irda_device_set_media_busy);
 EXPORT_SYMBOL(irda_device_txqueue_empty);
+EXPORT_SYMBOL(irda_device_net_open);
+EXPORT_SYMBOL(irda_device_net_close);
 
 EXPORT_SYMBOL(irda_device_init_dongle);
 EXPORT_SYMBOL(irda_device_register_dongle);
@@ -184,22 +192,25 @@
 EXPORT_SYMBOL(async_wrap_skb);
 EXPORT_SYMBOL(async_unwrap_char);
 EXPORT_SYMBOL(irda_start_timer);
-/* EXPORT_SYMBOL(irda_get_mtt); */
 EXPORT_SYMBOL(setup_dma);
 
 #ifdef CONFIG_IRTTY
 EXPORT_SYMBOL(irtty_set_dtr_rts);
 EXPORT_SYMBOL(irtty_register_dongle);
 EXPORT_SYMBOL(irtty_unregister_dongle);
+EXPORT_SYMBOL(irtty_set_packet_mode);
 #endif
 
-__initfunc(int irda_init(void))
+int __init irda_init(void)
 {
-        printk(KERN_INFO "IrDA (tm) Protocols for Linux-2.2 (Dag Brattli)\n");
+	printk(KERN_INFO "IrDA (tm) Protocols for Linux-2.3 (Dag Brattli)\n");
 
  	irlmp_init();
 	irlap_init();
-	irda_device_init();
+
+#ifdef MODULE
+	irda_device_init();	/* Called by init/main.c when non-modular */
+#endif
 
 	iriap_init();
  	irttp_init();
@@ -210,12 +221,12 @@
 #ifdef CONFIG_SYSCTL
 	irda_sysctl_register();
 #endif
-
+	init_waitqueue_head(&irda.wait_queue);
 	irda.dev.minor = MISC_DYNAMIC_MINOR;
 	irda.dev.name = "irda";
 	irda.dev.fops = &irda_fops;
 	
-	misc_register( &irda.dev);
+	misc_register(&irda.dev);
 
 	irda.in_use = FALSE;
 	
@@ -229,15 +240,7 @@
 #endif
 #ifdef CONFIG_IRCOMM
 	ircomm_init();
-	irvtd_init();
-#endif
-
-#ifdef CONFIG_IRLPT_CLIENT
-	irlpt_client_init();
-#endif
-
-#ifdef CONFIG_IRLPT_SERVER
-	irlpt_server_init();
+	ircomm_tty_init();
 #endif
 
 #ifdef CONFIG_IRDA_COMPRESSION
@@ -252,7 +255,7 @@
 #ifdef MODULE
 void irda_cleanup(void)
 {
-	misc_deregister( &irda.dev);
+	misc_deregister(&irda.dev);
 
 #ifdef CONFIG_SYSCTL
 	irda_sysctl_unregister();
@@ -261,7 +264,6 @@
 #ifdef CONFIG_PROC_FS
 	irda_proc_unregister();
 #endif
-
 	/* Remove higher layers */
 	irttp_cleanup();
 	iriap_cleanup();
@@ -296,7 +298,7 @@
  *    Used for initializing the notify structure
  *
  */
-void irda_notify_init( struct notify_t *notify)
+void irda_notify_init(notify_t *notify)
 {
 	notify->data_indication = NULL;
 	notify->udata_indication = NULL;
@@ -305,7 +307,7 @@
 	notify->disconnect_indication = NULL;
 	notify->flow_indication = NULL;
 	notify->instance = NULL;
-	strncpy( notify->name, "Unknown", NOTIFY_MAX_NAME);
+	strncpy(notify->name, "Unknown", NOTIFY_MAX_NAME);
 }
 
 /*
@@ -340,12 +342,12 @@
 	new->param = param;
 	
 	/* Queue todo */
-	enqueue_last( &irda.todo_queue, (QUEUE *) new);
+	enqueue_last(&irda.todo_queue, (QUEUE *) new);
 
 	event.event = EVENT_NEED_PROCESS_CONTEXT;
 
 	/* Notify the user space manager */
-	irmanager_notify( &event);
+	irmanager_notify(&event);
 }
 
 /*
@@ -475,6 +477,8 @@
 		return -ERESTARTSYS;
 
 	event = (struct irda_event *) dequeue_first( &irda.event_queue);
+	if (!event)
+		return 0;
 
 	len = sizeof(struct irmanager_event);
 	copy_to_user( buffer, &event->event, len);
diff -u --recursive --new-file v2.3.15/linux/net/irda/irproc.c linux/net/irda/irproc.c
--- v2.3.15/linux/net/irda/irproc.c	Sun May 30 10:27:04 1999
+++ linux/net/irda/irproc.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Thomas Davis, <ratbert@radiks.net>
  * Created at:    Sat Feb 21 21:33:24 1998
- * Modified at:   Fri May  7 08:06:49 1999
+ * Modified at:   Fri Jun  4 09:39:49 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999, Thomas Davis, <ratbert@radiks.net>, 
@@ -41,8 +41,6 @@
 extern int irias_proc_read(char *buf, char **start, off_t offset, int len,
 			   int unused);
 extern int discovery_proc_read(char *buf, char **start, off_t offset, int len, 
-			       int unused);
-static int proc_discovery_read(char *buf, char **start, off_t offset, int len,
 			       int unused);
 
 /* enum irda_directory_inos { */
diff -u --recursive --new-file v2.3.15/linux/net/irda/irqueue.c linux/net/irda/irqueue.c
--- v2.3.15/linux/net/irda/irqueue.c	Thu Apr 15 05:42:42 1999
+++ linux/net/irda/irqueue.c	Mon Aug 30 10:26:28 1999
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jun  9 13:29:31 1998
- * Modified at:   Thu Mar 11 13:27:04 1999
+ * Modified at:   Thu Jun 10 11:00:12 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (C) 1998, Aage Kvalnes <aage@cs.uit.no>
+ *     Copyright (C) 1998-1999, Aage Kvalnes <aage@cs.uit.no>
  *     Copyright (C) 1998, Dag Brattli, 
  *     All Rights Reserved.
  *
@@ -50,8 +50,6 @@
 	hashbin_t* hashbin;
 	int i;
 	
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
 	/*
 	 * Allocate new hashbin
 	 */
@@ -84,8 +82,8 @@
 	QUEUE* queue;
 	int i;
 	
-	ASSERT( hashbin != NULL, return -1;);
-	ASSERT( hashbin->magic == HB_MAGIC, return -1;);
+	ASSERT(hashbin != NULL, return -1;);
+	ASSERT(hashbin->magic == HB_MAGIC, return -1;);
 
 	/*
 	 * Free the entries in the hashbin
@@ -114,22 +112,23 @@
  */
 int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
 {
-	int i;
 	QUEUE* queue;
+	int i;
 
-	DEBUG( 4, "hashbin_destroy()\n");
+	ASSERT(hashbin != NULL, return -1;);
+	ASSERT(hashbin->magic == HB_MAGIC, return -1;);
 	
 	/*
 	 *  Free the entries in the hashbin, TODO: use hashbin_clear when
 	 *  it has been shown to work
 	 */
-	for ( i = 0; i < HASHBIN_SIZE; i ++ ) {
-		queue = dequeue_first( (QUEUE**) &hashbin->hb_queue[ i ] );
-		while( queue ) {
-			if ( free_func)
-				(*free_func)( queue );
+	for (i = 0; i < HASHBIN_SIZE; i ++ ) {
+		queue = dequeue_first((QUEUE**) &hashbin->hb_queue[i]);
+		while (queue ) {
+			if (free_func)
+				(*free_func)(queue);
 			queue = dequeue_first( 
-				(QUEUE**) &hashbin->hb_queue[ i ]);
+				(QUEUE**) &hashbin->hb_queue[i]);
 		}
 	}
 	
@@ -137,7 +136,7 @@
 	 *  Free the hashbin structure
 	 */
 	hashbin->magic = ~HB_MAGIC;
-	kfree( hashbin );
+	kfree(hashbin);
 
 	return 0;
 }
@@ -148,28 +147,28 @@
  *    Lock the hashbin
  *
  */
-void hashbin_lock( hashbin_t* hashbin, __u32 hashv, char* name, 
-		   unsigned long flags)
+void hashbin_lock(hashbin_t* hashbin, __u32 hashv, char* name, 
+		  unsigned long flags)
 {
 	int bin;
 	
-	DEBUG( 0, "hashbin_lock\n");
+	DEBUG(0, "hashbin_lock\n");
 
-	ASSERT( hashbin != NULL, return;);
-	ASSERT( hashbin->magic == HB_MAGIC, return;);
+	ASSERT(hashbin != NULL, return;);
+	ASSERT(hashbin->magic == HB_MAGIC, return;);
 
 	/*
 	 * Locate hashbin
 	 */
-	if ( name )
-		hashv = hash( name );
-	bin = GET_HASHBIN( hashv);
+	if (name)
+		hashv = hash(name);
+	bin = GET_HASHBIN(hashv);
 	
 	/* Synchronize */
 	if ( hashbin->hb_type & HB_GLOBAL )
-		spin_lock_irqsave( &hashbin->hb_mutex[ bin], flags);
+		spin_lock_irqsave(&hashbin->hb_mutex[ bin], flags);
 	else {
-		save_flags( flags);
+		save_flags(flags);
 		cli();
 	}
 }
diff -u --recursive --new-file v2.3.15/linux/net/irda/irsysctl.c linux/net/irda/irsysctl.c
--- v2.3.15/linux/net/irda/irsysctl.c	Sun May 30 10:27:04 1999
+++ linux/net/irda/irsysctl.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 24 22:12:06 1998
- * Modified at:   Thu May  6 21:32:46 1999
+ * Modified at:   Fri Jun  4 02:50:15 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
@@ -31,13 +31,15 @@
 #include <net/irda/irda.h>
 
 #define NET_IRDA 412 /* Random number */
-enum { DISCOVERY=1, DEVNAME, COMPRESSION, DEBUG, SLOTS, SLOT_TIMEOUT };
+enum { DISCOVERY=1, DEVNAME, COMPRESSION, DEBUG, SLOTS, DISCOVERY_TIMEOUT, 
+       SLOT_TIMEOUT };
 
-extern int sysctl_discovery;
-extern int sysctl_discovery_slots;
-extern int sysctl_slot_timeout;
-extern int sysctl_fast_poll_increase;
-int sysctl_compression = 0;
+extern int  sysctl_discovery;
+extern int  sysctl_discovery_slots;
+extern int  sysctl_discovery_timeout;
+extern int  sysctl_slot_timeout;
+extern int  sysctl_fast_poll_increase;
+int         sysctl_compression = 0;
 extern char sysctl_devname[];
 
 #ifdef CONFIG_IRDA_DEBUG
@@ -62,6 +64,8 @@
 #endif
 	{ SLOTS, "discovery_slots", &sysctl_discovery_slots,
 	  sizeof(int), 0644, NULL, &proc_dointvec },
+	{ DISCOVERY_TIMEOUT, "discovery_timeout", &sysctl_discovery_timeout,
+	  sizeof(int), 0644, NULL, &proc_dointvec },
 	{ SLOT_TIMEOUT, "slot_timeout", &sysctl_slot_timeout,
 	  sizeof(int), 0644, NULL, &proc_dointvec },
 	{ 0 }
@@ -89,9 +93,10 @@
  */
 int irda_sysctl_register(void)
 {
-	irda_table_header = register_sysctl_table( irda_root_table, 0);
-	if ( !irda_table_header)
+	irda_table_header = register_sysctl_table(irda_root_table, 0);
+	if (!irda_table_header)
 		return -ENOMEM;
+
 	return 0;
 }
 
@@ -103,7 +108,7 @@
  */
 void irda_sysctl_unregister(void) 
 {
-	unregister_sysctl_table( irda_table_header);
+	unregister_sysctl_table(irda_table_header);
 }
 
 
diff -u --recursive --new-file v2.3.15/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.3.15/linux/net/irda/irttp.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/irttp.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Mon May 31 10:29:56 1999
+ * Modified at:   Thu Jul  8 21:25:31 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -32,7 +32,9 @@
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
+#include <net/irda/irlap.h>
 #include <net/irda/irlmp.h>
+#include <net/irda/parameters.h>
 #include <net/irda/irttp.h>
 
 static struct irttp_cb *irttp = NULL;
@@ -58,6 +60,15 @@
 static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb);
 static void irttp_start_todo_timer(struct tsap_cb *self, int timeout);
 static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
+static int irttp_param_max_sdu_size(void *instance, param_t *param, int get);
+
+/* Information for parsing parameters in IrTTP */
+static pi_minor_info_t pi_minor_call_table[] = {
+	{ NULL, 0 },                                             /* 0x00 */
+	{ irttp_param_max_sdu_size, PV_INTEGER | PV_BIG_ENDIAN } /* 0x01 */
+};
+static pi_major_info_t pi_major_call_table[] = {{ pi_minor_call_table, 2 }};
+static pi_param_info_t param_info = { pi_major_call_table, 1, 0x0f, 4 };
 
 /*
  * Function irttp_init (void)
@@ -65,7 +76,7 @@
  *    Initialize the IrTTP layer. Called by module initialization code
  *
  */
-__initfunc(int irttp_init(void))
+int __init irttp_init(void)
 {
 	/* Initialize the irttp structure. */
 	if (irttp == NULL) {
@@ -118,12 +129,11 @@
  *
  *    Create TSAP connection endpoint,
  */
-struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, 
-				struct notify_t *notify) 
+struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify) 
 {
-	struct notify_t ttp_notify;
 	struct tsap_cb *self;
 	struct lsap_cb *lsap;
+	notify_t ttp_notify;
 
 	ASSERT(irttp != NULL, return NULL;);
 	ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
@@ -230,7 +240,7 @@
 			irttp_disconnect_request(self, NULL, P_NORMAL);
 		}
 		self->close_pend = TRUE;
-		irttp_start_todo_timer(self, 100);
+		irttp_start_todo_timer(self, 1*HZ);
 
 		return 0; /* Will be back! */
 	}
@@ -297,7 +307,7 @@
 
 	/* Check that nothing bad happens */
 	if ((skb->len == 0) || (!self->connected)) {
-		ERROR(__FUNCTION__ "(), No data, or not connected\n");
+		WARNING(__FUNCTION__ "(), No data, or not connected\n");
 		return -ENOTCONN;
 	}
 
@@ -375,25 +385,36 @@
 /*
  * Function irttp_run_tx_queue (self)
  *
- *    If possible, transmit a frame queued for transmission.
+ *    Transmit packets queued for transmission (if possible)
  *
  */
 static void irttp_run_tx_queue(struct tsap_cb *self) 
 {
-	struct sk_buff *skb = NULL;
+	struct sk_buff *skb;
 	unsigned long flags;
 	int n;
 
 	if (irda_lock(&self->tx_queue_lock) == FALSE)
 		return;
 
-	while ((self->send_credit > 0) && !skb_queue_empty(&self->tx_queue)) {
-		skb = skb_dequeue(&self->tx_queue);
-		ASSERT(skb != NULL, return;);
-		
-		/* Make room for TTP header */
-		ASSERT(skb_headroom(skb) >= TTP_HEADER, return;);
-				
+	/* Try to send out frames as long as we have credits */
+	while ((self->send_credit > 0) &&
+	       (skb = skb_dequeue(&self->tx_queue)))
+	{
+		/* 
+		 * Make sure we don't flood IrLAP with frames just because
+		 * the remote device has given us a lot of credits
+		 */
+		if (irlmp_get_lap_tx_queue_len(self->lsap) > LAP_MAX_QUEUE) {
+			/* Re-queue packet */
+			skb_queue_head(&self->tx_queue, skb);
+
+			/* Try later. Would be better if IrLAP could notify us */
+			irttp_start_todo_timer(self, MSECS_TO_JIFFIES(10));
+			
+			break;
+		}
+
 		/*
 		 *  Since we can transmit and receive frames concurrently, 
 		 *  the code below is a critical region and we must assure that
@@ -521,7 +542,7 @@
 }
 
 /*
- * Function irttp_data_indication (handle, skb)
+ * Function irttp_data_indication (instance, sap, skb)
  *
  *    Receive segment from IrLMP. 
  *
@@ -534,20 +555,15 @@
 
 	self = (struct tsap_cb *) instance;
 
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
-
 	n = skb->data[0] & 0x7f;     /* Extract the credits */
 
 	self->stats.rx_packets++;
 
 	/* 
-	 *  Data or dataless frame? Dataless frames only contain the 
-	 *  TTP_HEADER
+	 *  Data or dataless packet? Dataless frames contains only the 
+	 *  TTP_HEADER. 
 	 */
-	if (skb->len == 1)
-		self->send_credit += n;	/* Dataless flowdata TTP-PDU */
-	else {
+	if (skb->len > 1) {
 		/* Deal with inbound credit */
 		self->send_credit += n;
 		self->remote_credit--;
@@ -557,7 +573,8 @@
 		 *  more bit, so the defragment routing knows what to do
 		 */
 		skb_queue_tail(&self->rx_queue, skb);
-	} 
+	} else
+		self->send_credit += n;	/* Dataless flowdata TTP-PDU */
 
 	irttp_run_rx_queue(self);
 
@@ -570,13 +587,17 @@
 	{
 		/* Schedule to start immediately after this thread */
 		irttp_start_todo_timer(self, 0);
+		/*irttp_give_credit(self);*/
 	}
-
-	/* If peer has given us some credites and we didn't have anyone
-         * from before, the we need to shedule the tx queue? 
+	
+	/* 
+	 * If the peer device has given us some credits and we didn't have
+         * anyone from before, the we need to shedule the tx queue?  
 	 */
-	if (self->send_credit == n)
+	if (self->send_credit == n) {
+		/*irttp_run_tx_queue(self);*/
 		irttp_start_todo_timer(self, 0);
+	}
 	return 0;
 }
 
@@ -627,9 +648,12 @@
 	
 	DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); 
 	
-	ASSERT(self != NULL, return -1;);
-	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+	ASSERT(self != NULL, return -EBADR;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -EBADR;);
 
+	if (self->connected)
+		return -EISCONN;
+	
 	/* Any userdata supplied? */
 	if (userdata == NULL) {
 		skb = dev_alloc_skb(64);
@@ -711,8 +735,8 @@
 {
 	struct tsap_cb *self;
 	int parameters;
-	__u8 *frame;
-	__u8 plen, pi, pl;
+	int ret;
+	__u8 plen;
 	__u8 n;
 
 	DEBUG(4, __FUNCTION__ "()\n");
@@ -737,8 +761,7 @@
 		       qos->baud_rate.value);
 	}
 
-	frame = skb->data;
-	n = frame[0] & 0x7f;
+	n = skb->data[0] & 0x7f;
 	
 	DEBUG(4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
 	
@@ -746,45 +769,36 @@
 	self->tx_max_sdu_size = 0;
 	self->connected = TRUE;
 
-	parameters = frame[0] & 0x80;	
+	parameters = skb->data[0] & 0x80;	
 
 	ASSERT(skb->len >= TTP_HEADER, return;);
 	skb_pull(skb, TTP_HEADER);
-		
+
 	if (parameters) {
-		plen = frame[1];
-		pi   = frame[2];
-		pl   = frame[3];
-
-		switch (pl) {
-		case 1:
-			self->tx_max_sdu_size = *(frame+4);
-			break;
-		case 2:
-			self->tx_max_sdu_size = 
-				be16_to_cpu(get_unaligned((__u16 *)(frame+4)));
-			break;
-		case 4:
-			self->tx_max_sdu_size = 
-				be32_to_cpu(get_unaligned((__u32 *)(frame+4)));
-			break;
-		default:
-			printk(KERN_ERR __FUNCTION__ 
-			       "() illegal value length for max_sdu_size!\n");
-			self->tx_max_sdu_size = 0;
-		};
+		plen = skb->data[0];
 
-		DEBUG(4, __FUNCTION__ "(), RxMaxSduSize=%d\n", 
-		      self->tx_max_sdu_size);
-		
+		ret = irda_param_extract_all(self, skb->data+1,
+					     MIN(skb->len-1, plen), 
+					     &param_info);
+
+		/* Any errors in the parameter list? */
+		if (ret < 0) {
+			WARNING(__FUNCTION__ 
+				"(), error extracting parameters\n");
+			dev_kfree_skb(skb);
+
+			/* Do not accept this connection attempt */
+			return;
+		}
 		/* Remove parameters */
-		ASSERT(skb->len >= (plen+1), return;);
-		skb_pull(skb, plen+1);
+		skb_pull(skb, MIN(skb->len, plen+1));
 	}
 	
 	DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
 	      self->send_credit, self->avail_credit, self->remote_credit);
 
+	DEBUG(0, __FUNCTION__ "(), MaxSduSize=%d\n", self->tx_max_sdu_size);
+
 	if (self->notify.connect_confirm) {
 		self->notify.connect_confirm(self->notify.instance, self, qos,
 					     self->tx_max_sdu_size, 
@@ -805,8 +819,8 @@
 	struct tsap_cb *self;
 	struct lsap_cb *lsap;
 	int parameters;
-	__u8 *frame;
-	__u8 plen, pi, pl;
+	int ret;
+	__u8 plen;
 	__u8 n;
 
 	self = (struct tsap_cb *) instance;
@@ -818,7 +832,6 @@
 	lsap = (struct lsap_cb *) sap;
 
 	self->max_seg_size = max_seg_size;
-
 	self->max_header_size = max_header_size+TTP_HEADER;
 
 	DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
@@ -826,54 +839,42 @@
 	/* Need to update dtsap_sel if its equal to LSAP_ANY */
 	self->dtsap_sel = lsap->dlsap_sel;
 
-	frame = skb->data;
-	n = frame[0] & 0x7f;
+	n = skb->data[0] & 0x7f;
 
 	self->send_credit = n;
 	self->tx_max_sdu_size = 0;
 	
-	parameters = frame[0] & 0x80;
+	parameters = skb->data[0] & 0x80;
 
 	ASSERT(skb->len >= TTP_HEADER, return;);
 	skb_pull(skb, TTP_HEADER);
-		
+
 	if (parameters) {
-		DEBUG(3, __FUNCTION__ "(), Contains parameters!\n");
-		plen = frame[1];
-		pi   = frame[2];
-		pl   = frame[3];
-
-		switch (pl) {
-		case 1:
-			self->tx_max_sdu_size = frame[4];
-			break;
-		case 2:
-			self->tx_max_sdu_size = 
-				be16_to_cpu(get_unaligned((__u16 *)(frame+4)));
-			break;
-		case 4:
-			self->tx_max_sdu_size = 
-				be32_to_cpu(get_unaligned((__u32 *)(frame+4)));
-			break;
-		default:
-			printk(KERN_ERR __FUNCTION__ 
-			       "() illegal value length for max_sdu_size!\n");
-			self->tx_max_sdu_size = 0;
-		};
+		plen = skb->data[0];
 		
-		/* Remove parameters */
-		ASSERT(skb->len >= (plen+1), return;);
-		skb_pull(skb, plen+1);
+		ret = irda_param_extract_all(self, skb->data+1,
+					     MIN(skb->len-1, plen), 
+					     &param_info);
+
+		/* Any errors in the parameter list? */
+		if (ret < 0) {
+			WARNING(__FUNCTION__ 
+				"(), error extracting parameters\n");
+			dev_kfree_skb(skb);
+			
+			/* Do not accept this connection attempt */
+			return;
+		}
 
-		DEBUG(3, __FUNCTION__ "(), MaxSduSize=%d\n", 
-		      self->tx_max_sdu_size);
+		/* Remove parameters */
+		skb_pull(skb, MIN(skb->len, plen+1));
 	}
 
 	DEBUG(4, __FUNCTION__ "(), initial send_credit=%d\n", n);
 
 	if (self->notify.connect_indication) {
 		self->notify.connect_indication(self->notify.instance, self, 
-						qos, self->rx_max_sdu_size, 
+						qos, self->tx_max_sdu_size, 
 						self->max_header_size, skb);
 	}
 }
@@ -885,15 +886,16 @@
  *    IrLMP!
  * 
  */
-void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, 
-			    struct sk_buff *userdata)
+int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, 
+			   struct sk_buff *userdata)
 {
 	struct sk_buff *skb;
 	__u8 *frame;
+	int ret;
 	__u8 n;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
 
 	DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n", 
 	      self->stsap_sel);
@@ -902,7 +904,7 @@
 	if (userdata == NULL) {
 		skb = dev_alloc_skb(64);
 		if (!skb)
-			return;
+			return -ENOMEM;
 
 		/* Reserve space for MUX_CONTROL and LAP header */
 		skb_reserve(skb, TTP_MAX_HEADER);
@@ -912,7 +914,7 @@
 		 *  Check that the client has reserved enough space for 
 		 *  headers
 		 */
-		ASSERT(skb_headroom(skb) >= TTP_MAX_HEADER, return;);
+		ASSERT(skb_headroom(skb) >= TTP_MAX_HEADER, return -1;);
 	}
 	
 	self->avail_credit = 0;
@@ -935,13 +937,17 @@
 	/* SAR enabled? */
 	if (max_sdu_size > 0) {
 		ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER+TTP_SAR_HEADER), 
-		       return;);
+		       return -1;);
 		
 		/* Insert TTP header with SAR parameters */
 		frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER);
 		
 		frame[0] = TTP_PARAMETERS | n;
 		frame[1] = 0x04; /* Length */
+
+		/* irda_param_insert(self, IRTTP_MAX_SDU_SIZE, frame+1,  */
+/* 				  TTP_SAR_HEADER, &param_info) */
+		
 		frame[2] = 0x01; /* MaxSduSize */
 		frame[3] = 0x02; /* Value length */
 
@@ -954,7 +960,9 @@
 		frame[0] = n & 0x7f;
 	}
 	 
-	irlmp_connect_response(self->lsap, skb);
+	ret = irlmp_connect_response(self->lsap, skb);
+
+	return ret;
 }
 
 /*
@@ -1002,20 +1010,19 @@
  *    segments, if any, will be deallocated first
  *
  */
-void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata, 
-			      int priority)
+int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata, 
+			     int priority)
 {
 	struct sk_buff *skb;
+	int ret;
 
-	DEBUG(2, __FUNCTION__ "()\n");
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
 
 	/* Already disconnected? */
 	if (!self->connected) {
 		DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
-		return;
+		return -1;
 	}
 
 	/* Disconnect already pending? */
@@ -1027,7 +1034,7 @@
 
 		/* Try to make some progress */
 		irttp_run_rx_queue(self);
-		return;
+		return -1;
 	}
 
 	/*
@@ -1057,8 +1064,8 @@
 
 			irttp_run_tx_queue(self);
 
-			irttp_start_todo_timer(self, 100);
-			return;
+			irttp_start_todo_timer(self, MSECS_TO_JIFFIES(1000));
+			return -1;
 		}
 	}
 	DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
@@ -1068,7 +1075,7 @@
 	if (!userdata) {
 		skb = dev_alloc_skb(64);
 		if (!skb)
-			return;
+			return -ENOMEM;
 		
 		/* 
 		 *  Reserve space for MUX and LAP header 
@@ -1077,7 +1084,9 @@
 		
 		userdata = skb;
 	}
-	irlmp_disconnect_request(self->lsap, userdata);
+	ret = irlmp_disconnect_request(self->lsap, userdata);
+
+	return ret;
 }
 
 /*
@@ -1373,6 +1382,32 @@
 }
 
 /*
+ * Function irttp_param_max_sdu_size (self, param)
+ *
+ *    Handle the MaxSduSize parameter in the connect frames, this function
+ *    will be called both when this parameter needs to be inserted into, and
+ *    extracted from the connect frames
+ */
+static int irttp_param_max_sdu_size(void *instance, param_t *param, int get)
+{
+	struct tsap_cb *self;
+
+	self = (struct tsap_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+
+	if (get)
+		param->pv.i = self->tx_max_sdu_size;
+	else
+		self->tx_max_sdu_size = param->pv.i;
+
+	DEBUG(0, __FUNCTION__ "(), MaxSduSize=%d\n", param->pv.i);
+	
+	return 0;
+}
+
+/*
  * Function irttp_todo_expired (data)
  *
  *    Todo timer has expired!
@@ -1382,16 +1417,13 @@
 {
 	struct tsap_cb *self = (struct tsap_cb *) data;
 
-	DEBUG(4, __FUNCTION__ "()\n");
-	
 	/* Check that we still exist */
-	if (!self || self->magic != TTP_TSAP_MAGIC) {
+	if (!self || self->magic != TTP_TSAP_MAGIC)
 		return;
-	}
-
+	
 	irttp_run_rx_queue(self);
 	irttp_run_tx_queue(self);
-
+		
 	/*  Give avay some credits to peer?  */
 	if ((self->remote_credit < LOW_THRESHOLD) && 
 	    (self->avail_credit > 0) && (skb_queue_empty(&self->tx_queue)))
@@ -1414,13 +1446,13 @@
 				irttp_disconnect_request(self, NULL, P_NORMAL);
 		} else {
 			/* Try again later */
-			irttp_start_todo_timer(self, 100);
+			irttp_start_todo_timer(self, 1*HZ);
 			
 			/* No reason to try and close now */
 			return;
 		}
 	}
-
+	
 	/* Check if it's closing time */
 	if (self->close_pend)
 		irttp_close_tsap(self);
@@ -1442,7 +1474,7 @@
 	self->todo_timer.data     = (unsigned long) self;
 	self->todo_timer.function = &irttp_todo_expired;
 	self->todo_timer.expires  = jiffies + timeout;
-	
+
 	add_timer(&self->todo_timer);
 }
 
@@ -1467,42 +1499,40 @@
 
 	self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps);
 	while (self != NULL) {
-		if (!self || self->magic != TTP_TSAP_MAGIC) {
-			DEBUG(1, "irttp_proc_read: bad ptr self\n");
+		if (!self || self->magic != TTP_TSAP_MAGIC)
 			return len;
-		}
 
 		len += sprintf(buf+len, "TSAP %d, ", i++);
 		len += sprintf(buf+len, "stsap_sel: %02x, ", 
-				self->stsap_sel);
+			       self->stsap_sel);
 		len += sprintf(buf+len, "dtsap_sel: %02x\n", 
-				self->dtsap_sel);
+			       self->dtsap_sel);
 		len += sprintf(buf+len, "  connected: %s, ",
-				self->connected? "TRUE":"FALSE");
+			       self->connected? "TRUE":"FALSE");
 		len += sprintf(buf+len, "avail credit: %d, ",
-				self->avail_credit);
+			       self->avail_credit);
 		len += sprintf(buf+len, "remote credit: %d, ",
-				self->remote_credit);
+			       self->remote_credit);
 		len += sprintf(buf+len, "send credit: %d\n",
-				self->send_credit);
+			       self->send_credit);
 		len += sprintf(buf+len, "  tx packets: %d, ",
-				self->stats.tx_packets);
+			       self->stats.tx_packets);
 		len += sprintf(buf+len, "rx packets: %d, ",
-				self->stats.rx_packets);
+			       self->stats.rx_packets);
 		len += sprintf(buf+len, "tx_queue len: %d ", 
-				skb_queue_len(&self->tx_queue));
+			       skb_queue_len(&self->tx_queue));
 		len += sprintf(buf+len, "rx_queue len: %d\n", 
-				skb_queue_len(&self->rx_queue));
+			       skb_queue_len(&self->rx_queue));
 		len += sprintf(buf+len, "  tx_sdu_busy: %s, ",
-				self->tx_sdu_busy? "TRUE":"FALSE");
+			       self->tx_sdu_busy? "TRUE":"FALSE");
 		len += sprintf(buf+len, "rx_sdu_busy: %s\n",
-				self->rx_sdu_busy? "TRUE":"FALSE");
+			       self->rx_sdu_busy? "TRUE":"FALSE");
 		len += sprintf(buf+len, "  max_seg_size: %d, ",
-				self->max_seg_size);
+			       self->max_seg_size);
 		len += sprintf(buf+len, "tx_max_sdu_size: %d, ",
-				self->tx_max_sdu_size);
+			       self->tx_max_sdu_size);
 		len += sprintf(buf+len, "rx_max_sdu_size: %d\n",
-				self->rx_max_sdu_size);
+			       self->rx_max_sdu_size);
 
 		len += sprintf(buf+len, "  Used by (%s)\n", 
 				self->notify.name);
diff -u --recursive --new-file v2.3.15/linux/net/irda/parameters.c linux/net/irda/parameters.c
--- v2.3.15/linux/net/irda/parameters.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/parameters.c	Mon Aug 30 10:26:28 1999
@@ -0,0 +1,577 @@
+/*********************************************************************
+ *                
+ * Filename:      parameters.c
+ * Version:       1.0
+ * Description:   A more general way to handle (pi,pl,pv) parameters
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Jun  7 10:25:11 1999
+ * Modified at:   Wed Aug 25 13:31:32 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
+ ********************************************************************/
+
+#include <asm/unaligned.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/parameters.h>
+
+static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi, 
+				PV_TYPE type, PI_HANDLER func);
+static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi, 
+			       PV_TYPE type, PI_HANDLER func);
+static int irda_extract_octseq(void *self, __u8 *buf, int len, __u8 pi, 
+			       PV_TYPE type, PI_HANDLER func);
+static int irda_extract_no_value(void *self, __u8 *buf, int len, __u8 pi, 
+				 PV_TYPE type, PI_HANDLER func);
+
+static int irda_insert_integer(void *self, __u8 *buf, int len, __u8 pi, 
+			       PV_TYPE type, PI_HANDLER func);
+static int irda_insert_no_value(void *self, __u8 *buf, int len, __u8 pi, 
+				PV_TYPE type, PI_HANDLER func);
+
+/* Parameter value call table. Must match PV_TYPE */
+static PV_HANDLER pv_extract_table[] = {
+	irda_extract_integer, /* Handler for any length integers */
+	irda_extract_integer, /* Handler for 8  bits integers */
+	irda_extract_integer, /* Handler for 16 bits integers */
+	irda_extract_string,  /* Handler for strings */
+	irda_extract_integer, /* Handler for 32 bits integers */
+	irda_extract_octseq,  /* Handler for octet sequences */
+	irda_extract_no_value /* Handler for no value parameters */
+};
+
+static PV_HANDLER pv_insert_table[] = {
+	irda_insert_integer, /* Handler for any length integers */
+	irda_insert_integer, /* Handler for 8  bits integers */
+	irda_insert_integer, /* Handler for 16 bits integers */
+	NULL,                /* Handler for strings */
+	irda_insert_integer, /* Handler for 32 bits integers */
+	NULL,                /* Handler for octet sequences */
+	irda_insert_no_value /* Handler for no value parameters */
+};
+
+/*
+ * Function irda_insert_no_value (self, buf, len, pi, type, func)
+ *
+ *    
+ *
+ */
+static int irda_insert_no_value(void *self, __u8 *buf, int len, __u8 pi, 
+				PV_TYPE type, PI_HANDLER func)
+{
+	param_t p;
+	int ret;
+
+	p.pi = pi;
+	p.pl = 0;
+
+	/* Call handler for this parameter */
+	ret = (*func)(self, &p, PV_GET);
+
+	/* Extract values anyway, since handler may need them */
+	irda_param_pack(buf, "bb", p.pi, &p.pl);
+
+	if (ret < 0)
+		return ret;
+	 
+	return 2; /* Inserted pl+2 bytes */
+}
+
+/*
+ * Function irda_extract_no_value (self, buf, len, type, func)
+ *
+ *    Extracts a parameter without a pv field (pl=0)
+ *
+ */
+static int irda_extract_no_value(void *self, __u8 *buf, int len, __u8 pi, 
+				 PV_TYPE type, PI_HANDLER func)
+{
+	param_t p;
+	int ret;
+
+	/* Extract values anyway, since handler may need them */
+	irda_param_unpack(buf, "bb", &p.pi, &p.pl);
+
+	/* Call handler for this parameter */
+	ret = (*func)(self, &p, PV_PUT);
+
+	if (ret < 0)
+		return ret;
+	 
+	return 2; /* Extracted pl+2 bytes */
+}
+
+/*
+ * Function irda_insert_integer (self, buf, len, pi, type, func)
+ *
+ *    
+ *
+ */
+static int irda_insert_integer(void *self, __u8 *buf, int len, __u8 pi, 
+			       PV_TYPE type, PI_HANDLER func)
+{
+	param_t p;
+	int n = 0;
+	int err;
+
+	p.pi = pi;             /* In case handler needs to know */
+	p.pl = type & PV_MASK; /* The integer type codes the lenght as well */
+	p.pv.i = 0;            /* Clear value */
+
+	/* Call handler for this parameter */
+	err = (*func)(self, &p, PV_GET);
+	if (err < 0)
+		return err; 
+
+	/* 
+	 * If parameter lenght is still 0, then (1) this is an any length 
+	 * integer, and (2) the handler function does not care which length
+	 * we choose to use, so we pick the one the gives the fewest bytes.
+	 */
+	if (p.pl == 0) {
+		if (p.pv.i < 0xff) {
+			DEBUG(2, __FUNCTION__ "(), using 1 byte\n");
+			p.pl = 1;
+		} else if (p.pv.i < 0xffff) {
+			DEBUG(2, __FUNCTION__ "(), using 2 bytes\n");
+			p.pl = 2;
+		} else {
+			DEBUG(2, __FUNCTION__ "(), using 4 bytes\n");
+			p.pl = 4; /* Default length */
+		}
+	}
+	/* Check if buffer is long enough for insertion */
+	if (len < (2+p.pl)) {
+		WARNING(__FUNCTION__ "(), buffer to short for insertion!\n");
+		return -1;
+	}
+	DEBUG(2, __FUNCTION__ "(), pi=%#x, pl=%d, pi=%d\n", p.pi, p.pl, p.pv.i);
+	switch (p.pl) {
+	case 1:
+		n += irda_param_pack(buf, "bbb", p.pi, p.pl, p.pv.b);
+		break;
+	case 2:
+		if (type & PV_BIG_ENDIAN)
+			cpu_to_be16s(&p.pv.s);
+		else
+			cpu_to_le16s(&p.pv.s);
+		n += irda_param_pack(buf, "bbs", p.pi, p.pl, p.pv.s);
+		break;
+	case 4:
+		if (type & PV_BIG_ENDIAN)
+			cpu_to_be32s(&p.pv.i);
+		else
+			cpu_to_le32s(&p.pv.i);
+		n += irda_param_pack(buf, "bbi", p.pi, p.pl, p.pv.i);
+
+		break;
+	default:
+		WARNING(__FUNCTION__ "() length %d not supported\n", p.pl);
+		/* Skip parameter */ 
+		return -1;
+	}
+
+	return p.pl+2; /* Inserted pl+2 bytes */
+}
+
+/*
+ * Function irda_extract integer (self, buf, len, pi, type, func)
+ *
+ *    Extract a possibly variable length integer from buffer, and call 
+ *    handler for processing of the parameter
+ */
+static int irda_extract_integer(void *self, __u8 *buf, int len, __u8 pi, 
+				PV_TYPE type, PI_HANDLER func)
+{
+	param_t p;
+	int n = 0;
+	int err;
+
+	p.pi = pi;     /* In case handler needs to know */
+	p.pl = buf[1]; /* Extract lenght of value */
+	p.pv.i = 0;    /* Clear value */
+
+	/* Check if buffer is long enough for parsing */
+	if (len < (2+p.pl)) {
+		WARNING(__FUNCTION__ "(), buffer to short for parsing! "
+			"Need %d bytes, but len is only %d\n", p.pl, len);
+		return -1;
+	}
+
+	/* 
+	 * Check that the integer length is what we expect it to be. If the
+	 * handler want a 16 bits integer then a 32 bits is not good enough
+	 */
+	if (((type & PV_MASK) != PV_INTEGER) && ((type & PV_MASK) != p.pl)) {
+		ERROR(__FUNCTION__ "(), invalid parameter length! "
+		      "Expected %d bytes, but value had %d bytes!\n",
+		      type & PV_MASK, p.pl);
+		
+		/* Skip parameter */
+		return p.pl+2;
+	}
+
+	switch (p.pl) {
+	case 1:
+		n += irda_param_unpack(buf+2, "b", &p.pv.b);
+		break;
+	case 2:
+		n += irda_param_unpack(buf+2, "s", &p.pv.s);
+		if (type & PV_BIG_ENDIAN)
+			be16_to_cpus(&p.pv.s);
+		else
+			le16_to_cpus(&p.pv.s);
+		break;
+	case 4:
+		n += irda_param_unpack(buf+2, "i", &p.pv.i);
+		if (type & PV_BIG_ENDIAN)
+			be32_to_cpus(&p.pv.i);
+		else
+			le32_to_cpus(&p.pv.i);
+		break;
+	default:
+		WARNING(__FUNCTION__ "() length %d not supported\n", p.pl);
+
+		/* Skip parameter */ 
+		return p.pl+2;
+	}
+
+	/* Call handler for this parameter */
+	err = (*func)(self, &p, PV_PUT);
+	if (err < 0)
+		return err; 
+
+	return p.pl+2; /* Extracted pl+2 bytes */
+}
+
+/*
+ * Function irda_extract_string (self, buf, len, type, func)
+ *
+ *    
+ *
+ */
+static int irda_extract_string(void *self, __u8 *buf, int len, __u8 pi, 
+			       PV_TYPE type, PI_HANDLER func)
+{
+	char str[33];
+	param_t p;
+	int err;
+
+	DEBUG(2, __FUNCTION__ "()\n");
+
+	p.pi = pi;     /* In case handler needs to know */
+	p.pl = buf[1]; /* Extract lenght of value */
+
+	DEBUG(2, __FUNCTION__ "(), pi=%#x, pl=%d\n", p.pi, p.pl);
+
+	/* Check if buffer is long enough for parsing */
+	if (len < (2+p.pl)) {
+		WARNING(__FUNCTION__ "(), buffer to short for parsing! "
+			"Need %d bytes, but len is only %d\n", p.pl, len);
+		return -1;
+	}
+
+	/* Should be safe to copy string like this since we have already 
+	 * checked that the buffer is long enough */
+	strncpy(str, buf+2, p.pl);
+
+	DEBUG(2, __FUNCTION__ "(), str=0x%02x 0x%02x\n", (__u8) str[0], 
+	      (__u8) str[1]);
+	
+	/* Null terminate string */
+	str[p.pl+1] = '\0';
+
+	p.pv.c = str; /* Handler will need to take a copy */
+
+	/* Call handler for this parameter */
+	err = (*func)(self, &p, PV_PUT);
+	if (err < 0)
+		return err; 
+
+	return p.pl+2; /* Extracted pl+2 bytes */
+}
+
+/*
+ * Function irda_extract_octseq (self, buf, len, type, func)
+ *
+ *    
+ *
+ */
+static int irda_extract_octseq(void *self, __u8 *buf, int len, __u8 pi,
+			       PV_TYPE type, PI_HANDLER func)
+{
+	param_t p;
+
+	p.pi = pi;     /* In case handler needs to know */
+	p.pl = buf[1]; /* Extract lenght of value */
+
+	/* Check if buffer is long enough for parsing */
+	if (len < (2+p.pl)) {
+		WARNING(__FUNCTION__ "(), buffer to short for parsing! "
+			"Need %d bytes, but len is only %d\n", p.pl, len);
+		return -1;
+	}
+
+	DEBUG(0, __FUNCTION__ "(), not impl\n");
+	
+	return p.pl+2; /* Extracted pl+2 bytes */
+}
+
+/*
+ * Function irda_param_pack (skb, fmt, ...)
+ *
+ *    Format:
+ *        'i' = 32 bits integer
+ *        's' = string
+ *
+ */
+int irda_param_pack(__u8 *buf, char *fmt, ...)
+{
+	va_list args;
+	char *p;
+	int n = 0;
+	pv_t arg;
+	
+	va_start(args, fmt);
+
+	for (p = fmt; *p != '\0'; p++) {
+		switch (*p) {
+		case 'b':  /* 8 bits unsigned byte */
+			buf[n++] = va_arg(args, __u8);
+			break;
+		case 's':  /* 16 bits unsigned short */
+			arg.s = va_arg(args, __u16);
+			put_unaligned(arg.s, (__u16 *)(buf+n)); n+=2;
+			break;
+		case 'i':  /* 32 bits unsigned integer */
+			arg.i = va_arg(args, __u32);
+			put_unaligned(arg.i, (__u32 *)(buf+n)); n+=4;
+			break;
+		case 'c': /* \0 terminated string */
+			arg.c = va_arg(args, char *);
+			strcpy(buf+n, arg.c);
+			n += strlen(arg.c) + 1;
+			break;
+		default:
+			va_end(args);
+			return -1;
+		}
+		
+	}
+	va_end(args);
+
+	return 0;
+}
+
+/*
+ * Function irda_param_unpack (skb, fmt, ...)
+ *
+ *    
+ *
+ */
+int irda_param_unpack(__u8 *buf, char *fmt, ...)
+{
+	va_list args;
+	char *p;
+	int n = 0;
+	pv_t arg;
+
+	va_start(args, fmt);
+
+	for (p = fmt; *p != '\0'; p++) {
+		switch (*p) {
+		case 'b':  /* 8 bits byte */
+			arg.bp = va_arg(args, __u8 *);
+			*arg.bp = buf[n++];
+			break;
+		case 's':  /* 16 bits short */
+			arg.sp = va_arg(args, __u16 *);
+			*arg.sp = get_unaligned((__u16 *)(buf+n)); n+=2;
+			break;
+		case 'i':  /* 32 bits unsigned integer */
+			arg.ip = va_arg(args, __u32 *);
+			*arg.ip = get_unaligned((__u32 *)(buf+n)); n+=4;
+			break;
+#if 0
+		case 'c':   /* \0 terminated string */
+			arg.c = va_arg(args, char *);
+			strcpy(arg.c, buf+n);
+			n += strlen(arg.c) + 1;
+			break;
+#endif
+		default:
+			va_end(args);
+			return -1;
+		}
+		
+	}
+	va_end(args);
+
+	return 0;
+}
+
+/*
+ * Function irda_param_insert (self, pi, buf, len, info)
+ *
+ *    Insert the specified parameter (pi) into buffer. Returns number of
+ *    bytes inserted
+ */
+int irda_param_insert(void *self, __u8 pi, __u8 *buf, int len, 
+		      pi_param_info_t *info)
+{
+	pi_minor_info_t *pi_minor_info;
+	__u8 pi_minor;
+	__u8 pi_major;
+	int type;
+	int ret = -1;
+	int n = 0;
+
+	ASSERT(buf != NULL, return ret;);
+	ASSERT(info != 0, return ret;);
+
+	pi_minor = pi & info->pi_mask;
+	pi_major = pi >> info->pi_major_offset;
+
+	/* Check if the identifier value (pi) is valid */
+	if ((pi_major > info->len-1) || 
+	    (pi_minor > info->tables[pi_major].len-1))
+	{
+		DEBUG(0, __FUNCTION__ 
+		      "(), no handler for parameter=0x%02x\n", pi);
+		
+		/* Skip this parameter */
+		return -1;
+	}
+	
+	/* Lookup the info on how to parse this parameter */
+	pi_minor_info = &info->tables[pi_major].pi_minor_call_table[pi_minor];
+
+	/* Find expected data type for this parameter identifier (pi)*/
+	type = pi_minor_info->type;
+
+	DEBUG(3, __FUNCTION__ "(), pi=[%d,%d], type=%d\n",
+	      pi_major, pi_minor, type);
+		
+	/*  Check if handler has been implemented */
+	if (!pi_minor_info->func) {
+		MESSAGE(__FUNCTION__"(), no handler for pi=%#x\n", pi);
+		/* Skip this parameter */
+		return -1;
+	}
+	
+	/* Insert parameter value */
+	ret = (*pv_insert_table[type & PV_MASK])(self, buf+n, len, pi, type, 
+						 pi_minor_info->func);
+	return ret;
+}
+
+/*
+ * Function irda_param_extract_all (self, buf, len, info)
+ *
+ *    Parse all parameters. If len is correct, then everything should be
+ *    safe. Returns the number of bytes that was parsed
+ *
+ */
+int irda_param_extract(void *self, __u8 *buf, int len, pi_param_info_t *info)
+{
+	pi_minor_info_t *pi_minor_info;
+	__u8 pi_minor;
+	__u8 pi_major;
+	int type;
+	int ret = -1;
+	int n = 0;
+
+	ASSERT(buf != NULL, return ret;);
+	ASSERT(info != 0, return ret;);
+
+	pi_minor = buf[n] & info->pi_mask;
+	pi_major = buf[n] >> info->pi_major_offset;
+	
+	/* Check if the identifier value (pi) is valid */
+	if ((pi_major > info->len-1) || 
+	    (pi_minor > info->tables[pi_major].len-1))
+	{
+		DEBUG(0, __FUNCTION__ "(), no handler for parameter=0x%02x\n",
+		      buf[0]);
+		
+		/* Skip this parameter */
+		n += (2 + buf[n+1]);
+		len -= (2 + buf[n+1]);
+
+		return 0;  /* Continue */
+	}
+
+	/* Lookup the info on how to parse this parameter */
+	pi_minor_info = &info->tables[pi_major].pi_minor_call_table[pi_minor];
+
+	/* Find expected data type for this parameter identifier (pi)*/
+	type = pi_minor_info->type;
+	
+	DEBUG(3, __FUNCTION__ "(), pi=[%d,%d], type=%d\n",
+	      pi_major, pi_minor, type);
+	
+	/*  Check if handler has been implemented */
+	if (!pi_minor_info->func) {
+		MESSAGE(__FUNCTION__"(), no handler for pi=%#x\n", buf[n]);
+		/* Skip this parameter */
+		n += (2 + buf[n+1]);
+		len -= (2 + buf[n+1]);
+
+		return 0; /* Continue */
+	}
+
+	/* Parse parameter value */
+	ret = (*pv_extract_table[type & PV_MASK])(self, buf+n, len, buf[n],
+						  type, pi_minor_info->func);
+	return ret;
+}
+
+/*
+ * Function irda_param_extract_all (self, buf, len, info)
+ *
+ *    Parse all parameters. If len is correct, then everything should be
+ *    safe. Returns the number of bytes that was parsed
+ *
+ */
+int irda_param_extract_all(void *self, __u8 *buf, int len, 
+			   pi_param_info_t *info)
+{
+	int ret = -1;
+	int n = 0;
+
+	ASSERT(buf != NULL, return ret;);
+	ASSERT(info != 0, return ret;);
+
+	/*
+	 * Parse all parameters. Each parameter must be at least two bytes
+	 * long or else there is no point in trying to parse it
+	 */
+	while (len > 2) {
+		ret = irda_param_extract(self, buf+n, len, info);
+		if (ret < 0)
+			return ret;
+
+		n += ret;
+		len -= ret;
+	}
+	return n;
+}
+
diff -u --recursive --new-file v2.3.15/linux/net/irda/qos.c linux/net/irda/qos.c
--- v2.3.15/linux/net/irda/qos.c	Sun May 30 10:27:04 1999
+++ linux/net/irda/qos.c	Mon Aug 30 10:26:28 1999
@@ -1,12 +1,13 @@
 /*********************************************************************
  *                
+ *                
  * Filename:      qos.c
- * Version:       0.8
- * Description:   IrLAP QoS negotiation
+ * Version:       1.0
+ * Description:   IrLAP QoS parameter negotiation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Sep  9 00:00:26 1997
- * Modified at:   Mon May  3 21:15:08 1999
+ * Modified at:   Tue Aug 17 10:25:21 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -16,17 +17,24 @@
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License 
+ *     along with this program; if not, write to the Free Software 
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *     MA 02111-1307 USA
+ *     
  ********************************************************************/
 
 #include <linux/config.h>
 #include <asm/byteorder.h>
 
 #include <net/irda/irda.h>
+#include <net/irda/parameters.h>
 #include <net/irda/qos.h>
 #include <net/irda/irlap.h>
 #ifdef CONFIG_IRDA_COMPRESSION
@@ -36,17 +44,55 @@
 #define CI_BZIP2  27 /* Random pick */
 #endif
 
-int min_turn_time[] = { 10000, 5000, 1000, 500, 100, 50, 10, 0 };
-int baud_rates[] = { 2400, 9600, 19200, 38400, 57600, 115200, 576000, 1152000,
-		     4000000 };
-int data_size[]  = { 64, 128, 256, 512, 1024, 2048 };
-int add_bofs[]   = { 48, 24, 12, 5, 3, 2, 1, 0 };
-int max_turn_time[] = { 500, 250, 100, 50 };
-int link_disc_time[] = { 3, 8, 12, 16, 20, 25, 30, 40 };
+static int irlap_param_baud_rate(void *instance, param_t *param, int get);
+static int irlap_param_link_disconnect(void *instance, param_t *parm, int get);
+static int irlap_param_max_turn_time(void *instance, param_t *param, int get);
+static int irlap_param_data_size(void *instance, param_t *param, int get);
+static int irlap_param_window_size(void *instance, param_t *param, int get);
+static int irlap_param_additional_bofs(void *instance, param_t *parm, int get);
+static int irlap_param_min_turn_time(void *instance, param_t *param, int get);
+
+__u32 min_turn_time[]  = { 10000, 5000, 1000, 500, 100, 50, 10, 0 }; /* us */
+__u32 baud_rates[]     = { 2400, 9600, 19200, 38400, 57600, 115200, 576000, 
+			   1152000, 4000000, 16000000 };            /* bps */
+__u32 data_size[]      = { 64, 128, 256, 512, 1024, 2048 };         /* bytes */
+__u32 add_bofs[]       = { 48, 24, 12, 5, 3, 2, 1, 0 };             /* bytes */
+__u32 max_turn_time[]  = { 500, 250, 100, 50 };                     /* ms */
+__u32 link_disc_time[] = { 3, 8, 12, 16, 20, 25, 30, 40 };          /* secs */
 
 #ifdef CONFIG_IRDA_COMPRESSION
-int compression[] = { CI_BZIP2, CI_DEFLATE, CI_DEFLATE_DRAFT };
+__u32 compression[] = { CI_BZIP2, CI_DEFLATE, CI_DEFLATE_DRAFT };
 #endif
+
+static pi_minor_info_t pi_minor_call_table_type_0[] = {
+	{ NULL, 0 },
+/* 01 */{ irlap_param_baud_rate,       PV_INTEGER | PV_LITTLE_ENDIAN },
+	{ NULL, 0 },
+	{ NULL, 0 },
+	{ NULL, 0 },
+	{ NULL, 0 },
+	{ NULL, 0 },
+	{ NULL, 0 },
+/* 08 */{ irlap_param_link_disconnect, PV_INT_8_BITS }
+};
+
+static pi_minor_info_t pi_minor_call_table_type_1[] = {
+	{ NULL, 0 },
+	{ NULL, 0 },
+/* 82 */{ irlap_param_max_turn_time,   PV_INT_8_BITS },
+/* 83 */{ irlap_param_data_size,       PV_INT_8_BITS },
+/* 84 */{ irlap_param_window_size,     PV_INT_8_BITS },
+/* 85 */{ irlap_param_additional_bofs, PV_INT_8_BITS },
+/* 86 */{ irlap_param_min_turn_time,   PV_INT_8_BITS },
+};
+
+static pi_major_info_t pi_major_call_table[] = {
+	{ pi_minor_call_table_type_0, 9 },
+	{ pi_minor_call_table_type_1, 7 },
+};
+
+static pi_param_info_t irlap_param_info = { pi_major_call_table, 2, 0x7f, 7 };
+
 /*
  * Function irda_qos_compute_intersection (qos, new)
  *
@@ -81,7 +127,7 @@
  *    set the maximum QoS possible and then "and in" their own limitations
  * 
  */
-void irda_init_max_qos_capabilies( struct qos_info *qos)
+void irda_init_max_qos_capabilies(struct qos_info *qos)
 {
 	/* 
 	 *  These are the maximum supported values as specified on pages
@@ -110,158 +156,46 @@
  *    We just set the QoS capabilities for the peer station
  *
  */
-void irda_qos_negotiate(struct qos_info *qos_rx, struct qos_info *qos_tx, 
-			struct sk_buff *skb) 
+int irlap_qos_negotiate(struct irlap_cb *self, struct sk_buff *skb) 
 {
-	int n=0;
+	int ret;
 #ifdef CONFIG_IRDA_COMPRESSION
 	int comp_seen = FALSE;
 #endif
-	__u8 length;
-	__u8 *frame;
-	__u8 final_byte;
-	__u8 code;
-	__u8 byte;
- 	__u16 final_word;
-	__u16_host_order word;
-
-	ASSERT( qos_tx != NULL, return;);
-	ASSERT( qos_rx != NULL, return;);
-	ASSERT( skb != NULL, return;);
-
-	frame = skb->data;
-
-	while( n < skb->len-2) {
-		code = frame[n++];
-		/* Length */
-		length = frame[n++];
-
-		/*  
-		 *  Get the value, since baud_rate may need two bytes, we
-		 *  Just use word size all the time
-		 */
-		switch( length) {
-		case 1:
-			byte = frame[n++];
-			word.word = byte; /* To make things a little easier */
-			break;
-		case 2:
-#ifdef __LITTLE_ENDIAN
-			word.byte[0] = frame[n++];
-			word.byte[1] = frame[n++];
-#else ifdef __BIG_ENDIAN
-			word.byte[1] = frame[n++];
-			word.byte[0] = frame[n++];
-#endif
-			byte = 0;
-			break;
-		default:
-			DEBUG( 0, __FUNCTION__ "Error\n");
-			word.word = byte = 0;
-			n += length;
-			
-			break;
-		}
-
-		switch(code) {
-		case PI_BAUD_RATE:
-			/* 
-			 *  Stations must agree on baud rate, so calculate
-                         *  intersection 
-			 */
-			DEBUG( 4, "Requested BAUD_RATE: 0x%04x\n", word.word);
-			final_word = word.word & qos_rx->baud_rate.bits;
-			DEBUG( 4, "Final BAUD_RATE: 0x%04x\n", final_word);
-			qos_tx->baud_rate.bits = final_word;
-			qos_rx->baud_rate.bits = final_word;
-			break;
-		case PI_MAX_TURN_TIME:
-			/*
-			 *  Negotiated independently for each station
-			 */
-			DEBUG(4, __FUNCTION__ "(), MAX_TURN_TIME: %02x\n", 
-			      byte);
-			qos_tx->max_turn_time.bits = byte;
-			break;
-		case PI_DATA_SIZE:
-			/*
-			 *  Negotiated independently for each station
-			 */
-			DEBUG( 4, "DATA_SIZE: %02x\n", byte);
-			qos_tx->data_size.bits = byte;
-			break;
-		case PI_WINDOW_SIZE:
-			/*
-			 *  Negotiated independently for each station
-			 */
-			qos_tx->window_size.bits = byte;
-			break;
-		case PI_ADD_BOFS:
-			/*
-			 *  Negotiated independently for each station
-			 */
-			DEBUG( 4, "ADD_BOFS: %02x\n", byte);
-			qos_tx->additional_bofs.bits = byte;	
-			break;
-		case PI_MIN_TURN_TIME:
-			DEBUG( 4, "MIN_TURN_TIME: %02x\n", byte);
-			qos_tx->min_turn_time.bits = byte;
-			break;
-		case PI_LINK_DISC:
-			/*  
-			 *  Stations must agree on link disconnect/threshold 
-			 *  time.
-			 */
-			DEBUG( 4, "LINK_DISC: %02x\n", byte);
-			
-			final_byte = byte & qos_rx->link_disc_time.bits;
-			DEBUG( 4, "Final LINK_DISC: %02x\n", final_byte);
-			qos_tx->link_disc_time.bits = final_byte;
-			qos_rx->link_disc_time.bits = final_byte;
-			break;
-#ifdef CONFIG_IRDA_COMPRESSION
-		case PI_COMPRESSION:
-			final_byte = byte & qos_rx->compression.bits;
-			qos_rx->compression.bits = byte;
-			qos_tx->compression.bits = byte;
-			comp_seen = TRUE;
-			break;
-#endif
-		default:
-			DEBUG( 0, __FUNCTION__ "(), Unknown value\n");
-			break;
-		}
-	}
+	ret = irda_param_extract_all(self, skb->data, skb->len, 
+				     &irlap_param_info);
+	
 #ifdef CONFIG_IRDA_COMPRESSION
-	if ( !comp_seen) {
+	if (!comp_seen) {
 		DEBUG( 4, __FUNCTION__ "(), Compression not seen!\n");
-		qos_tx->compression.bits = 0x00;
-		qos_rx->compression.bits = 0x00;
+		self->qos_tx.compression.bits = 0x00;
+		self->qos_rx.compression.bits = 0x00;
 	}
 #endif
+
 	/* Convert the negotiated bits to values */
-	irda_qos_bits_to_value( qos_tx);
-	irda_qos_bits_to_value( qos_rx);
+	irda_qos_bits_to_value(&self->qos_tx);
+	irda_qos_bits_to_value(&self->qos_rx);
 		
-	DEBUG( 4, "Setting BAUD_RATE to %d bps.\n", 
-	       qos_tx->baud_rate.value);
-	DEBUG( 4, "Setting DATA_SIZE to %d bytes\n",
-	       qos_tx->data_size.value);
-	DEBUG( 4, "Setting WINDOW_SIZE to %d\n", 
-	       qos_tx->window_size.value);
-	DEBUG( 4, "Setting XBOFS to %d\n", 
-	       qos_tx->additional_bofs.value);
-	DEBUG( 4, "Setting MAX_TURN_TIME to %d ms.\n",
-	       qos_tx->max_turn_time.value);
-	DEBUG( 4, "Setting MIN_TURN_TIME to %d usecs.\n",
-	       qos_tx->min_turn_time.value);
-	DEBUG( 4, "Setting LINK_DISC to %d secs.\n", 
-	       qos_tx->link_disc_time.value);
+	DEBUG(2, "Setting BAUD_RATE to %d bps.\n", 
+	      self->qos_tx.baud_rate.value);
+	DEBUG(2, "Setting DATA_SIZE to %d bytes\n",
+	      self->qos_tx.data_size.value);
+	DEBUG(2, "Setting WINDOW_SIZE to %d\n", 
+	      self->qos_tx.window_size.value);
+	DEBUG(2, "Setting XBOFS to %d\n", 
+	      self->qos_tx.additional_bofs.value);
+	DEBUG(2, "Setting MAX_TURN_TIME to %d ms.\n",
+	      self->qos_tx.max_turn_time.value);
+	DEBUG(2, "Setting MIN_TURN_TIME to %d usecs.\n",
+	      self->qos_tx.min_turn_time.value);
+	DEBUG(2, "Setting LINK_DISC to %d secs.\n", 
+	      self->qos_tx.link_disc_time.value);
 #ifdef CONFIG_IRDA_COMPRESSION
-	DEBUG( 4, "Setting COMPRESSION to %d\n", 
-	       qos_tx->compression.value);
-#endif
-	
+	DEBUG(2, "Setting COMPRESSION to %d\n", 
+	      self->qos_tx.compression.value);
+#endif	
+	return ret;
 }
 
 /*
@@ -270,100 +204,247 @@
  *    Insert QoS negotiaion pararameters into frame
  *
  */
-int irda_insert_qos_negotiation_params(struct qos_info *qos, __u8 *frame)
+int irlap_insert_qos_negotiation_params(struct irlap_cb *self, 
+					struct sk_buff *skb)
 {
-	int n;
-	__u16_host_order word;
+	int ret;
 
-	ASSERT( qos != NULL, return 0;);
-	ASSERT( frame != NULL, return 0;);
+	/* Insert data rate */
+	ret = irda_param_insert(self, PI_BAUD_RATE, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	/* Insert max turnaround time */
+	ret = irda_param_insert(self, PI_MAX_TURN_TIME, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	/* Insert data size */
+	ret = irda_param_insert(self, PI_DATA_SIZE, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	/* Insert window size */
+	ret = irda_param_insert(self, PI_WINDOW_SIZE, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	/* Insert additional BOFs */
+	ret = irda_param_insert(self, PI_ADD_BOFS, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	/* Insert minimum turnaround time */
+	ret = irda_param_insert(self, PI_MIN_TURN_TIME, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
+
+	/* Insert link disconnect/threshold time */
+	ret = irda_param_insert(self, PI_LINK_DISC, skb->tail, 
+				skb_tailroom(skb), &irlap_param_info);
+	if (ret < 0)
+		return ret;
+	skb_put(skb, ret);
 
-	n = 0;
+	return 0;
+}
 
-	/* Set baud rate */
-	if (qos->baud_rate.bits < 256) {
-		frame[n++] = PI_BAUD_RATE;
-		frame[n++] = 0x01;   /* length 1 */
-		frame[n++] = qos->baud_rate.bits;
+/*
+ * Function irlap_param_baud_rate (instance, param, get)
+ *
+ *    Negotiate data-rate
+ *
+ */
+static int irlap_param_baud_rate(void *instance, param_t *param, int get)
+{
+	__u16 final;
+
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+
+	if (get) {
+		param->pv.i = self->qos_rx.baud_rate.bits;
+		DEBUG(0, __FUNCTION__ "(), baud rate = 0x%02x\n", param->pv.i);		
 	} else {
-		frame[n++] = PI_BAUD_RATE;
-		frame[n++] = 0x02;   /* length 2 */
-		
 		/* 
-		 *  qos->baud_rate.bits is in host byte order, so make sure
-		 *  we transmit it in little endian format 
+		 *  Stations must agree on baud rate, so calculate
+		 *  intersection 
 		 */
-		word.word = qos->baud_rate.bits;
-#ifdef __LITTLE_ENDIAN
-		frame[n++] = word.byte[0]; /* LSB */
-		frame[n++] = word.byte[1]; /* MSB */
-#else ifdef __BIG_ENDIAN
-		frame[n++] = word.byte[1]; /* LSB */
-		frame[n++] = word.byte[0]; /* MSB */
-#endif
+		DEBUG(2, "Requested BAUD_RATE: 0x%04x\n", param->pv.s);
+		final = param->pv.s & self->qos_rx.baud_rate.bits;
+
+		DEBUG(2, "Final BAUD_RATE: 0x%04x\n", final);
+		self->qos_tx.baud_rate.bits = final;
+		self->qos_rx.baud_rate.bits = final;	       
 	}
 
-	/* Set Maximum Turn Around Time */
-	frame[n++] = PI_MAX_TURN_TIME;
-	frame[n++] = 0x01;   /* length 1 */
-	frame[n++] = qos->max_turn_time.bits;
-	
-	/* Set data size */
-	frame[n++] = PI_DATA_SIZE;
-	frame[n++] = 0x01;   /* length 1 */
-	frame[n++] = qos->data_size.bits;
-
-	/* Set window size */
-	frame[n++] = PI_WINDOW_SIZE;
-	frame[n++] = 0x01;   /* length 1 */
-	frame[n++] = qos->window_size.bits;
-
-	/* Set additional BOFs */
-	frame[n++] = PI_ADD_BOFS;
-	frame[n++] = 0x01;   /* length 1 */
-	frame[n++] = qos->additional_bofs.bits;
-
-	/* Set minimum turn around time */
-	frame[n++] = PI_MIN_TURN_TIME;
-	frame[n++] = 0x01;   /* length 1 */
-	frame[n++] = qos->min_turn_time.bits;
-
-	/* Set Link Disconnect/Threshold Time */
-	frame[n++] = PI_LINK_DISC;
-	frame[n++] = 0x01;   /* length 1 */
-	frame[n++] = qos->link_disc_time.bits;
-#ifdef CONFIG_IRDA_COMPRESSION
-	/* Set compression bits*/
-	if ( qos->compression.bits) {
-		DEBUG( 4, __FUNCTION__ "(), inserting compresion bits\n");
-		frame[n++] = PI_COMPRESSION;
-		frame[n++] = 0x01;   /* length 1 */
-		frame[n++] = qos->compression.bits;
+	return 0;
+}
+
+/*
+ * Function irlap_param_link_disconnect (instance, param, get)
+ *
+ *    Negotiate link disconnect/threshold time. 
+ *
+ */
+static int irlap_param_link_disconnect(void *instance, param_t *param, int get)
+{
+	__u16 final;
+	
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->qos_rx.link_disc_time.bits;
+	else {
+		/*  
+		 *  Stations must agree on link disconnect/threshold 
+		 *  time.
+		 */
+		DEBUG(2, "LINK_DISC: %02x\n", param->pv.b);
+		final = param->pv.b & self->qos_rx.link_disc_time.bits;
+
+		DEBUG(2, "Final LINK_DISC: %02x\n", final);
+		self->qos_tx.link_disc_time.bits = final;
+		self->qos_rx.link_disc_time.bits = final;
 	}
-#endif
-	return n;
+	return 0;
 }
 
-int byte_value( __u8 byte, int *array) 
+/*
+ * Function irlap_param_max_turn_time (instance, param, get)
+ *
+ *    Negotiate the maximum turnaround time. This is a type 1 parameter and
+ *    will be negotiated independently for each station
+ *
+ */
+static int irlap_param_max_turn_time(void *instance, param_t *param, int get)
 {
-	int index;
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->qos_rx.max_turn_time.bits;
+	else
+		self->qos_tx.max_turn_time.bits = param->pv.b;
 
-	ASSERT( array != NULL, return -1;);
+	return 0;
+}
 
-	index = msb_index( byte);
-	return index_value( index, array);
+/*
+ * Function irlap_param_data_size (instance, param, get)
+ *
+ *    Negotiate the data size. This is a type 1 parameter and
+ *    will be negotiated independently for each station
+ *
+ */
+static int irlap_param_data_size(void *instance, param_t *param, int get)
+{
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->qos_rx.data_size.bits;
+	else
+		self->qos_tx.data_size.bits = param->pv.b;
+
+	return 0;
 }
 
+/*
+ * Function irlap_param_window_size (instance, param, get)
+ *
+ *    Negotiate the window size. This is a type 1 parameter and
+ *    will be negotiated independently for each station
+ *
+ */
+static int irlap_param_window_size(void *instance, param_t *param, int get)
+{
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->qos_rx.window_size.bits;
+	else
+		self->qos_tx.window_size.bits = param->pv.b;
 
-/* __u8 value_byte( int value, int *array) */
-/* { */
-/* 	int index; */
-/* 	__u8 byte; */
+	return 0;
+}
 
-/* 	index = value_index( value, array); */
+/*
+ * Function irlap_param_additional_bofs (instance, param, get)
+ *
+ *    Negotiate additional BOF characters. This is a type 1 parameter and
+ *    will be negotiated independently for each station.
+ */
+static int irlap_param_additional_bofs(void *instance, param_t *param, int get)
+{
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->qos_rx.additional_bofs.bits;
+	else
+		self->qos_tx.additional_bofs.bits = param->pv.b;
+
+	return 0;
+}
+
+/*
+ * Function irlap_param_min_turn_time (instance, param, get)
+ *
+ *    Negotiate the minimum turn around time. This is a type 1 parameter and
+ *    will be negotiated independently for each station
+ */
+static int irlap_param_min_turn_time(void *instance, param_t *param, int get)
+{
+	struct irlap_cb *self = (struct irlap_cb *) instance;
+	
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == LAP_MAGIC, return -1;);
+	
+	if (get)
+		param->pv.b = self->qos_rx.min_turn_time.bits;
+	else
+		self->qos_tx.min_turn_time.bits = param->pv.b;
+
+	return 0;
+}
+
+__u32 byte_value(__u8 byte, int *array) 
+{
+	int index;
 
-/* 	byte =  */
-/* } */
+	ASSERT(array != NULL, return -1;);
+
+	index = msb_index(byte);
+
+	return index_value(index, array);
+}
 
 /*
  * Function msb_index (word)
@@ -371,18 +452,18 @@
  *    Returns index to most significant bit (MSB) in word
  *
  */
-int msb_index ( __u16 word) 
+int msb_index (__u16 word) 
 {
 	__u16 msb = 0x8000;
 	int index = 15;   /* Current MSB */
 	
-	while( msb) {
-		if ( word & msb)
+	while (msb) {
+		if (word & msb)
 			break;   /* Found it! */
 		msb >>=1;
 		index--;
 	}
-
+	
 	return index;
 }
 
@@ -391,12 +472,12 @@
  *
  *    Returns the index to the value in the specified array
  */
-int value_index( int value, int *array) 
+int value_index(__u32 value, int *array) 
 {
 	int i;
 	
-	for( i=0;i<8;i++)
-		if ( array[i] == value)
+	for (i=0;i<8;i++)
+		if (array[i] == value)
 			break;
 	return i;
 }
@@ -407,44 +488,50 @@
  *    Returns value to index in array, easy!
  *
  */
-int index_value( int index, int *array) 
+__u32 index_value(int index, int *array) 
 {
 	return array[index];
 }
 
-void irda_qos_bits_to_value( struct qos_info *qos)
+void irda_qos_bits_to_value(struct qos_info *qos)
 {
 	int index;
 
-	ASSERT( qos != NULL, return;);
+	ASSERT(qos != NULL, return;);
 	
-	index = msb_index( qos->baud_rate.bits);
+	index = msb_index(qos->baud_rate.bits);
 	qos->baud_rate.value = baud_rates[index];
 
-	index = msb_index( qos->data_size.bits);
+	index = msb_index(qos->data_size.bits);
 	qos->data_size.value = data_size[index];
 
-	index = msb_index( qos->window_size.bits);
+	index = msb_index(qos->window_size.bits);
 	qos->window_size.value = index+1;
 
-	index = msb_index( qos->min_turn_time.bits);
+	index = msb_index(qos->min_turn_time.bits);
 	qos->min_turn_time.value = min_turn_time[index];
 	
-	index = msb_index( qos->max_turn_time.bits);
+	index = msb_index(qos->max_turn_time.bits);
 	qos->max_turn_time.value = max_turn_time[index];
 
-	index = msb_index( qos->link_disc_time.bits);
+	index = msb_index(qos->link_disc_time.bits);
 	qos->link_disc_time.value = link_disc_time[index];
 	
-	index = msb_index( qos->additional_bofs.bits);
+	index = msb_index(qos->additional_bofs.bits);
 	qos->additional_bofs.value = add_bofs[index];
 
 #ifdef CONFIG_IRDA_COMPRESSION
-	index = msb_index( qos->compression.bits);
-	if ( index >= 0)
+	index = msb_index(qos->compression.bits);
+	if (index >= 0)
 		qos->compression.value = compression[index];
 	else 
 		qos->compression.value = 0;
 #endif
 }
+
+
+
+
+
+
 
diff -u --recursive --new-file v2.3.15/linux/net/irda/timer.c linux/net/irda/timer.c
--- v2.3.15/linux/net/irda/timer.c	Sun Mar  7 15:26:44 1999
+++ linux/net/irda/timer.c	Mon Aug 30 10:26:28 1999
@@ -6,10 +6,10 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Thu Feb  4 10:49:38 1999
+ * Modified at:   Sat Jun 26 17:03:22 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
  *     
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -31,84 +31,90 @@
 #include <net/irda/irlap.h>
 #include <net/irda/irlmp_event.h>
 
-static void irlap_slot_timer_expired( unsigned long data);
-static void irlap_query_timer_expired( unsigned long data);
-static void irlap_final_timer_expired( unsigned long data);
-static void irlap_wd_timer_expired( unsigned long data);
-static void irlap_backoff_timer_expired( unsigned long data);
+static void irlap_slot_timer_expired( void* data);
+static void irlap_query_timer_expired( void* data);
+static void irlap_final_timer_expired( void* data);
+static void irlap_wd_timer_expired( void* data);
+static void irlap_backoff_timer_expired( void* data);
 
-static void irda_device_media_busy_expired( unsigned long data); 
+static void irda_device_media_busy_expired( void* data); 
 /*
  * Function irda_start_timer (timer, timeout)
  *
  *    Start an IrDA timer
  *
  */
-void irda_start_timer( struct timer_list *ptimer, int timeout, int data,
-		       TIMER_CALLBACK callback) 
+void irda_start_timer(struct timer_list *ptimer, int timeout, void *data,
+		      TIMER_CALLBACK callback) 
 {
-	del_timer( ptimer);
+	del_timer(ptimer);
  
 	ptimer->data = (unsigned long) data;
-	ptimer->function = callback;
+
+	/* 
+	 * For most architectures void * is the same as unsigned long, but
+	 * at least we try to use void * as long as possible. Since the 
+	 * timer functions use unsigned long, we cast the function here
+	 */
+	ptimer->function = (void (*)(unsigned long)) callback;
 	ptimer->expires = jiffies + timeout;
 	
-	add_timer( ptimer);
+	add_timer(ptimer);
 }
 
-inline void irlap_start_slot_timer( struct irlap_cb *self, int timeout)
+inline void irlap_start_slot_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer( &self->slot_timer, timeout, (unsigned long) self, 
-			  irlap_slot_timer_expired);
+	irda_start_timer(&self->slot_timer, timeout, (void *) self, 
+			 irlap_slot_timer_expired);
 }
 
-inline void irlap_start_query_timer( struct irlap_cb *self, int timeout)
+inline void irlap_start_query_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer( &self->query_timer, timeout, (unsigned long) self, 
+	irda_start_timer( &self->query_timer, timeout, (void *) self, 
 			  irlap_query_timer_expired);
 }
 
-inline void irlap_start_final_timer( struct irlap_cb *self, int timeout)
+inline void irlap_start_final_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer( &self->final_timer, timeout,  (unsigned long) self, 
-			  irlap_final_timer_expired);
+	irda_start_timer(&self->final_timer, timeout, (void *) self, 
+			 irlap_final_timer_expired);
 }
 
-inline void irlap_start_wd_timer( struct irlap_cb *self, int timeout)
+inline void irlap_start_wd_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer( &self->wd_timer, timeout, (unsigned long) self, 
-			  irlap_wd_timer_expired);
+	irda_start_timer(&self->wd_timer, timeout, (void *) self, 
+			 irlap_wd_timer_expired);
 }
 
-inline void irlap_start_backoff_timer( struct irlap_cb *self, int timeout)
+inline void irlap_start_backoff_timer(struct irlap_cb *self, int timeout)
 {
-	irda_start_timer( &self->backoff_timer, timeout, (unsigned long) self, 
-			  irlap_backoff_timer_expired);
+	irda_start_timer(&self->backoff_timer, timeout, (void *) self, 
+			 irlap_backoff_timer_expired);
 }
 
-inline void irda_device_start_mbusy_timer( struct irda_device *self) 
+inline void irda_device_start_mbusy_timer(struct irda_device *self) 
 {
-	irda_start_timer( &self->media_busy_timer, MEDIABUSY_TIMEOUT, 
-			  (unsigned long) self, 
-			  irda_device_media_busy_expired);
+	irda_start_timer(&self->media_busy_timer, MEDIABUSY_TIMEOUT, 
+			 (void *) self, 
+			 irda_device_media_busy_expired);
 	
 }
 
-inline void irlmp_start_watchdog_timer( struct lsap_cb *self, int timeout) 
+inline void irlmp_start_watchdog_timer(struct lsap_cb *self, int timeout) 
 {
-	irda_start_timer( &self->watchdog_timer, timeout, (unsigned long) self,
-			  irlmp_watchdog_timer_expired);
+	irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
+			 irlmp_watchdog_timer_expired);
 }
 
 inline void irlmp_start_discovery_timer(struct irlmp_cb *self, int timeout) 
 {
-	irda_start_timer(&self->discovery_timer, timeout, (unsigned long) self,
+	irda_start_timer(&self->discovery_timer, timeout, (void *) self,
 			 irlmp_discovery_timer_expired);
 }
 
 inline void irlmp_start_idle_timer(struct lap_cb *self, int timeout) 
 {
-	irda_start_timer(&self->idle_timer, timeout, (unsigned long) self,
+	irda_start_timer(&self->idle_timer, timeout, (void *) self,
 			 irlmp_idle_timer_expired);
 }
 
@@ -118,7 +124,7 @@
  *    IrLAP slot timer has expired
  *
  */
-static void irlap_slot_timer_expired( unsigned long data)
+static void irlap_slot_timer_expired( void* data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
 
@@ -136,7 +142,7 @@
  *    IrLAP query timer has expired
  *
  */
-static void irlap_query_timer_expired( unsigned long data)
+static void irlap_query_timer_expired( void* data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
 
@@ -154,7 +160,7 @@
  *    
  *
  */
-static void irlap_final_timer_expired( unsigned long data)
+static void irlap_final_timer_expired( void* data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
 
@@ -172,7 +178,7 @@
  *    
  *
  */
-static void irlap_wd_timer_expired( unsigned long data)
+static void irlap_wd_timer_expired( void* data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
 	
@@ -190,7 +196,7 @@
  *    
  *
  */
-static void irlap_backoff_timer_expired( unsigned long data)
+static void irlap_backoff_timer_expired( void* data)
 {
 	struct irlap_cb *self = (struct irlap_cb *) data;
 	
@@ -208,7 +214,7 @@
  *
  *    
  */
-void irda_device_media_busy_expired( unsigned long data) 
+void irda_device_media_busy_expired( void* data)
 {
 	struct irda_device *self = ( struct irda_device *) data;
 
diff -u --recursive --new-file v2.3.15/linux/net/irda/wrapper.c linux/net/irda/wrapper.c
--- v2.3.15/linux/net/irda/wrapper.c	Mon Jun  7 16:18:58 1999
+++ linux/net/irda/wrapper.c	Mon Aug 30 10:26:28 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Fri May 28 20:30:24 1999
+ * Modified at:   Wed Aug 25 13:13:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Modified at:   Fri May 28  3:11 CST 1999
  * Modified by:   Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
@@ -53,7 +53,7 @@
 };
 
 /*
- * Function async_wrap (skb, *tx_buff)
+ * Function async_wrap (skb, *tx_buff, buffsize)
  *
  *    Makes a new buffer with wrapping and stuffing, should check that 
  *    we don't get tx buffer overflow.
@@ -72,21 +72,15 @@
 	fcs.value = INIT_FCS;
 	n = 0;
 
-	if (skb->len > 2048) {
-		DEBUG(0, __FUNCTION__ "Warning size=%d of sk_buff to big!\n", 
-		      (int) skb->len);
-		return 0;
-	}
-	
 	/*
 	 *  Send  XBOF's for required min. turn time and for the negotiated
 	 *  additional XBOFS
 	 */
-	if (((struct irlap_skb_cb *)(skb->cb))->magic != LAP_MAGIC) {
+	if (((struct irda_skb_cb *)(skb->cb))->magic != LAP_MAGIC) {
 		DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n");
 		xbofs = 10;
 	} else
-		xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs;
+		xbofs = ((struct irda_skb_cb *)(skb->cb))->xbofs;
 
 	memset(tx_buff+n, XBOF, xbofs);
 	n += xbofs;
@@ -122,7 +116,7 @@
 }
 
 /*
- * Function async_bump (idev)
+ * Function async_bump (idev, buf, len)
  *
  *    Got a frame, make a copy of it, and pass it up the stack!
  *
@@ -182,7 +176,7 @@
 }
 
 /*
- * Function async_unwrap (skb)
+ * Function async_unwrap_char (idev, byte)
  *
  *    Parse and de-stuff frame received from the IrDA-port
  *
diff -u --recursive --new-file v2.3.15/linux/net/khttpd/datasending.c linux/net/khttpd/datasending.c
--- v2.3.15/linux/net/khttpd/datasending.c	Thu Aug 26 13:05:46 1999
+++ linux/net/khttpd/datasending.c	Thu Aug 26 09:41:36 1999
@@ -36,6 +36,7 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/locks.h>
 #include <linux/skbuff.h>
 
 #include <net/tcp.h>
@@ -48,6 +49,33 @@
 
 static	char	*Block[CONFIG_KHTTPD_NUMCPU];
 
+/*
+
+This send_actor is for use with do_generic_file_read (ie sendfile())
+It sends the data to the socket indicated by desc->buf.
+
+*/
+static int sock_send_actor(read_descriptor_t * desc, const char *area, unsigned long size)
+{
+	int written;
+	unsigned long count = desc->count;
+	struct socket *sock = (struct socket *) desc->buf;
+
+	if (size > count)
+		size = count;
+	written = SendBuffer_async(sock,(char *)area,size);
+
+	if (written < 0) {
+		desc->error = written;
+		written = 0;
+	}
+	desc->count = count - written;
+	desc->written += written;
+	return written;
+}
+
+
+
 
 int DataSending(const int CPUNR)
 {
@@ -62,45 +90,61 @@
 	{
 		int ReadSize,Space;
 		int retval;
-		mm_segment_t oldfs;
 
 
 		/* First, test if the socket has any buffer-space left.
 		   If not, no need to actually try to send something.  */
 		  
 		
-		Space=4096;
-		if (CurrentRequest->sock->sk!=NULL) /* It's impossible */
-		{
-			Space = sock_wspace(CurrentRequest->sock->sk);
-		}
+		Space = sock_wspace(CurrentRequest->sock->sk);
 		
-		ReadSize = min(4096,CurrentRequest->FileLength - CurrentRequest->BytesSent);
+		ReadSize = min(4*4096,CurrentRequest->FileLength - CurrentRequest->BytesSent);
 		ReadSize = min(ReadSize , Space );
-		
-		if (ReadSize>0)
-		{
-			/* This part does a redundant data-copy. To bad for now. 
-			   In the future, we might want to nick the data right out
-			   of the page-cache
 
-			   WHY DO YOU NOT USE SENDFILE?
-			*/
-		
-			CurrentRequest->filp->f_pos = CurrentRequest->BytesSent;
-		
-			oldfs = get_fs(); set_fs(KERNEL_DS);
-			retval = CurrentRequest->filp->f_op->read(CurrentRequest->filp, Block[CPUNR], ReadSize, &CurrentRequest->filp->f_pos);
-			set_fs(oldfs);
-		
-			if (retval>0)
+		if (ReadSize>0)
+		{			
+			struct inode *inode;
+			
+			inode = CurrentRequest->filp->f_dentry->d_inode;
+			
+			if ( (inode!=NULL)&&(inode->i_op!=NULL)&&(inode->i_op->readpage!=NULL))
 			{
-				retval = SendBuffer_async(CurrentRequest->sock,Block[CPUNR],(size_t)retval);
-				if (retval>0)
-				{
-					CurrentRequest->BytesSent += retval;
+				/* This does the actual transfer using sendfile */		
+				read_descriptor_t desc;
+				loff_t *ppos;
+		
+				CurrentRequest->filp->f_pos = CurrentRequest->BytesSent;
+
+				ppos = &CurrentRequest->filp->f_pos;
+
+				desc.written = 0;
+				desc.count = ReadSize;
+				desc.buf = (char *) CurrentRequest->sock;
+				desc.error = 0;
+				do_generic_file_read(CurrentRequest->filp, ppos, &desc, sock_send_actor);
+				if (desc.written>0)
+				{	
+					CurrentRequest->BytesSent += desc.written;
 					count++;
+				}			
+			} 
+			else  /* FS doesn't support sendfile() */
+			{
+				mm_segment_t oldfs;
+				CurrentRequest->filp->f_pos = CurrentRequest->BytesSent;
 				
+				oldfs = get_fs(); set_fs(KERNEL_DS);
+				retval = CurrentRequest->filp->f_op->read(CurrentRequest->filp, Block[CPUNR], ReadSize, &CurrentRequest->filp->f_pos);
+				set_fs(oldfs);
+		
+				if (retval>0)
+				{
+					retval = SendBuffer_async(CurrentRequest->sock,Block[CPUNR],(size_t)retval);
+					if (retval>0)
+					{
+						CurrentRequest->BytesSent += retval;
+						count++;				
+					}
 				}
 			}
 		
diff -u --recursive --new-file v2.3.15/linux/net/khttpd/main.c linux/net/khttpd/main.c
--- v2.3.15/linux/net/khttpd/main.c	Thu Aug 26 13:05:46 1999
+++ linux/net/khttpd/main.c	Tue Aug 31 11:30:48 1999
@@ -144,7 +144,7 @@
 			changes +=AcceptConnections(CPUNR,MainSocket);
 		}
 		
-		current->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE;	
+		set_current_state(TASK_INTERRUPTIBLE|TASK_EXCLUSIVE);	
 		if (changes==0) 
 		{
 			(void)interruptible_sleep_on_timeout(&(DummyWQ[CPUNR]),1);	
diff -u --recursive --new-file v2.3.15/linux/net/lapb/lapb_iface.c linux/net/lapb/lapb_iface.c
--- v2.3.15/linux/net/lapb/lapb_iface.c	Mon Jan  4 15:31:35 1999
+++ linux/net/lapb/lapb_iface.c	Thu Aug 26 14:13:59 1999
@@ -401,7 +401,7 @@
 EXPORT_SYMBOL(lapb_data_request);
 EXPORT_SYMBOL(lapb_data_received);
 
-__initfunc(void lapb_proto_init(struct net_proto *pro))
+void __init lapb_proto_init(struct net_proto *pro)
 {
 	printk(KERN_INFO "NET4: LAPB for Linux. Version 0.01 for NET4.0\n");
 }
diff -u --recursive --new-file v2.3.15/linux/net/netlink/af_netlink.c linux/net/netlink/af_netlink.c
--- v2.3.15/linux/net/netlink/af_netlink.c	Thu Aug 26 13:05:46 1999
+++ linux/net/netlink/af_netlink.c	Tue Aug 31 11:30:48 1999
@@ -103,16 +103,16 @@
 		DECLARE_WAITQUEUE(wait, current);
 
 		add_wait_queue(&nl_table_wait, &wait);
-		do {
-			current->state = TASK_UNINTERRUPTIBLE;
+		for(;;) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
 			if (atomic_read(&nl_table_users) == 0)
 				break;
 			write_unlock_bh(&nl_table_lock);
 			schedule();
 			write_lock_bh(&nl_table_lock);
-		} while (atomic_read(&nl_table_users));
+		}
 
-		current->state = TASK_RUNNING;
+		__set_current_state(TASK_RUNNING);
 		remove_wait_queue(&nl_table_wait, &wait);
 	}
 }
@@ -417,10 +417,8 @@
 			return -EAGAIN;
 		}
 
+		__set_current_state(TASK_INTERRUPTIBLE);
 		add_wait_queue(&sk->protinfo.af_netlink->wait, &wait);
-		current->state = TASK_INTERRUPTIBLE;
-
-		barrier();
 
 		if ((atomic_read(&sk->rmem_alloc) > sk->rcvbuf ||
 		    test_bit(0, &sk->protinfo.af_netlink->state)) &&
@@ -428,7 +426,7 @@
 		    !sk->dead)
 			schedule();
 
-		current->state = TASK_RUNNING;
+		__set_current_state(TASK_RUNNING);
 		remove_wait_queue(&sk->protinfo.af_netlink->wait, &wait);
 		sock_put(sk);
 
diff -u --recursive --new-file v2.3.15/linux/net/netlink/netlink_dev.c linux/net/netlink/netlink_dev.c
--- v2.3.15/linux/net/netlink/netlink_dev.c	Thu Aug 26 13:05:46 1999
+++ linux/net/netlink/netlink_dev.c	Thu Aug 26 14:13:59 1999
@@ -178,7 +178,7 @@
 	netlink_release
 };
 
-__initfunc(int init_netlink(void))
+int __init init_netlink(void)
 {
 	if (register_chrdev(NETLINK_MAJOR,"netlink", &netlink_fops)) {
 		printk(KERN_ERR "netlink: unable to get major %d\n", NETLINK_MAJOR);
diff -u --recursive --new-file v2.3.15/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v2.3.15/linux/net/netrom/af_netrom.c	Thu Aug 26 13:05:46 1999
+++ linux/net/netrom/af_netrom.c	Thu Aug 26 14:13:59 1999
@@ -1295,7 +1295,7 @@
 
 static struct net_device *dev_nr;
 
-__initfunc(void nr_proto_init(struct net_proto *pro))
+void __init nr_proto_init(struct net_proto *pro)
 {
 	int i;
 
diff -u --recursive --new-file v2.3.15/linux/net/netrom/sysctl_net_netrom.c linux/net/netrom/sysctl_net_netrom.c
--- v2.3.15/linux/net/netrom/sysctl_net_netrom.c	Mon Jul  7 08:20:00 1997
+++ linux/net/netrom/sysctl_net_netrom.c	Thu Aug 26 14:13:59 1999
@@ -79,7 +79,7 @@
 	{0}
 };
 
-__initfunc(void nr_register_sysctl(void))
+void __init nr_register_sysctl(void)
 {
 	nr_table_header = register_sysctl_table(nr_root_table, 1);
 }
diff -u --recursive --new-file v2.3.15/linux/net/netsyms.c linux/net/netsyms.c
--- v2.3.15/linux/net/netsyms.c	Thu Aug 26 13:05:46 1999
+++ linux/net/netsyms.c	Thu Aug 26 12:50:51 1999
@@ -32,6 +32,11 @@
 #include <net/br.h>
 #endif
 
+#ifdef CONFIG_NET
+extern __u32 sysctl_wmem_max;
+extern __u32 sysctl_rmem_max;
+#endif
+
 #ifdef CONFIG_INET
 #include <linux/ip.h>
 #include <net/protocol.h>
@@ -46,8 +51,6 @@
 #include <linux/igmp.h>
 
 extern struct net_proto_family inet_family_ops;
-extern __u32 sysctl_wmem_max;
-extern __u32 sysctl_rmem_max;
 
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) || defined (CONFIG_KHTTPD) || defined (CONFIG_KHTTPD_MODULE)
 #include <linux/in6.h>
@@ -221,7 +224,6 @@
 /* Internet layer registration */
 EXPORT_SYMBOL(inet_add_protocol);
 EXPORT_SYMBOL(inet_del_protocol);
-EXPORT_SYMBOL(init_etherdev);
 EXPORT_SYMBOL(ip_route_output);
 EXPORT_SYMBOL(ip_route_input);
 EXPORT_SYMBOL(icmp_send);
@@ -279,6 +281,7 @@
 EXPORT_SYMBOL(inet_recvmsg);
 EXPORT_SYMBOL(inet_sock_nr);
 EXPORT_SYMBOL(inet_sock_destruct);
+EXPORT_SYMBOL(inet_sock_release);
 
 /* Socket demultiplexing. */
 EXPORT_SYMBOL(tcp_ehash);
@@ -303,8 +306,10 @@
 /* UDP/TCP exported functions for TCPv6 */
 EXPORT_SYMBOL(udp_ioctl);
 EXPORT_SYMBOL(udp_connect);
+EXPORT_SYMBOL(udp_disconnect);
 EXPORT_SYMBOL(udp_sendmsg);
 EXPORT_SYMBOL(tcp_close);
+EXPORT_SYMBOL(tcp_disconnect);
 EXPORT_SYMBOL(tcp_accept);
 EXPORT_SYMBOL(tcp_write_wakeup);
 EXPORT_SYMBOL(tcp_read_wakeup);
@@ -327,6 +332,8 @@
 EXPORT_SYMBOL(tcp_statistics);
 EXPORT_SYMBOL(tcp_rcv_state_process);
 EXPORT_SYMBOL(tcp_timewait_state_process);
+EXPORT_SYMBOL(tcp_timewait_cachep);
+EXPORT_SYMBOL(tcp_timewait_kill);
 EXPORT_SYMBOL(tcp_do_sendmsg);
 EXPORT_SYMBOL(tcp_v4_rebuild_header);
 EXPORT_SYMBOL(tcp_v4_send_check);
@@ -350,6 +357,7 @@
 EXPORT_SYMBOL(tcp_connect);
 EXPORT_SYMBOL(tcp_make_synack);
 EXPORT_SYMBOL(tcp_tw_death_row_slot);
+EXPORT_SYMBOL(tcp_tw_deschedule);
 EXPORT_SYMBOL(sysctl_local_port_range);
 EXPORT_SYMBOL(tcp_port_rover);
 EXPORT_SYMBOL(udp_port_rover);
@@ -385,6 +393,7 @@
 EXPORT_SYMBOL(rtnetlink_links);
 EXPORT_SYMBOL(__rta_fill);
 EXPORT_SYMBOL(rtnetlink_dump_ifinfo);
+EXPORT_SYMBOL(rtnetlink_put_metrics);
 EXPORT_SYMBOL(rtnl);
 EXPORT_SYMBOL(neigh_delete);
 EXPORT_SYMBOL(neigh_add);
@@ -444,6 +453,7 @@
 
 /* support for loadable net drivers */
 #ifdef CONFIG_NET
+EXPORT_SYMBOL(init_etherdev);
 EXPORT_SYMBOL(loopback_dev);
 EXPORT_SYMBOL(register_netdevice);
 EXPORT_SYMBOL(unregister_netdevice);
diff -u --recursive --new-file v2.3.15/linux/net/packet/af_packet.c linux/net/packet/af_packet.c
--- v2.3.15/linux/net/packet/af_packet.c	Thu Aug 26 13:05:46 1999
+++ linux/net/packet/af_packet.c	Tue Aug 31 11:23:03 1999
@@ -5,7 +5,7 @@
  *
  *		PACKET - implements raw packet sockets.
  *
- * Version:	$Id: af_packet.c,v 1.23 1999/08/23 06:30:40 davem Exp $
+ * Version:	$Id: af_packet.c,v 1.24 1999/08/30 12:14:52 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -241,7 +241,7 @@
 static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,  struct packet_type *pt)
 {
 	struct sock *sk;
-	struct sockaddr_pkt *spkt = (struct sockaddr_pkt*)skb->cb;
+	struct sockaddr_pkt *spkt;
 
 	/*
 	 *	When we registered the protocol we saved the socket in the data
@@ -266,6 +266,8 @@
 
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
 		goto oom;
+
+	spkt = (struct sockaddr_pkt*)skb->cb;
 
 	skb_push(skb, skb->data-skb->mac.raw);
 
diff -u --recursive --new-file v2.3.15/linux/net/rose/af_rose.c linux/net/rose/af_rose.c
--- v2.3.15/linux/net/rose/af_rose.c	Thu Aug 26 13:05:46 1999
+++ linux/net/rose/af_rose.c	Thu Aug 26 14:13:59 1999
@@ -1491,7 +1491,7 @@
 
 static struct net_device *dev_rose;
 
-__initfunc(void rose_proto_init(struct net_proto *pro))
+void __init rose_proto_init(struct net_proto *pro)
 {
 	int i;
 
diff -u --recursive --new-file v2.3.15/linux/net/rose/sysctl_net_rose.c linux/net/rose/sysctl_net_rose.c
--- v2.3.15/linux/net/rose/sysctl_net_rose.c	Mon Jul  7 08:20:00 1997
+++ linux/net/rose/sysctl_net_rose.c	Thu Aug 26 14:13:59 1999
@@ -67,7 +67,7 @@
 	{0}
 };
 
-__initfunc(void rose_register_sysctl(void))
+void __init rose_register_sysctl(void)
 {
 	rose_table_header = register_sysctl_table(rose_root_table, 1);
 }
diff -u --recursive --new-file v2.3.15/linux/net/sched/cls_api.c linux/net/sched/cls_api.c
--- v2.3.15/linux/net/sched/cls_api.c	Thu Aug 26 13:05:46 1999
+++ linux/net/sched/cls_api.c	Thu Aug 26 14:09:23 1999
@@ -433,7 +433,7 @@
 #endif
 
 
-__initfunc(int tc_filter_init(void))
+int __init tc_filter_init(void)
 {
 #ifdef CONFIG_RTNETLINK
 	struct rtnetlink_link *link_p = rtnetlink_links[PF_UNSPEC];
diff -u --recursive --new-file v2.3.15/linux/net/sched/sch_api.c linux/net/sched/sch_api.c
--- v2.3.15/linux/net/sched/sch_api.c	Thu Aug 26 13:05:46 1999
+++ linux/net/sched/sch_api.c	Thu Aug 26 14:09:23 1999
@@ -1089,7 +1089,7 @@
 #endif
 
 #if PSCHED_CLOCK_SOURCE == PSCHED_CPU
-__initfunc(int psched_calibrate_clock(void))
+int __init psched_calibrate_clock(void)
 {
 	psched_time_t stamp, stamp1;
 	struct timeval tv, tv1;
@@ -1128,7 +1128,7 @@
 }
 #endif
 
-__initfunc(int pktsched_init(void))
+int __init pktsched_init(void)
 {
 #ifdef CONFIG_RTNETLINK
 	struct rtnetlink_link *link_p;
diff -u --recursive --new-file v2.3.15/linux/net/sched/sch_teql.c linux/net/sched/sch_teql.c
--- v2.3.15/linux/net/sched/sch_teql.c	Thu Aug 26 13:05:46 1999
+++ linux/net/sched/sch_teql.c	Thu Aug 26 14:09:34 1999
@@ -467,7 +467,7 @@
 #ifdef MODULE
 int init_module(void)
 #else
-__initfunc(int teql_init(void))
+int __init teql_init(void)
 #endif
 {
 	int err;
diff -u --recursive --new-file v2.3.15/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.3.15/linux/net/unix/af_unix.c	Thu Aug 26 13:05:47 1999
+++ linux/net/unix/af_unix.c	Tue Aug 31 11:30:48 1999
@@ -8,7 +8,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  *
- * Version:	$Id: af_unix.c,v 1.81 1999/08/20 11:06:56 davem Exp $
+ * Version:	$Id: af_unix.c,v 1.82 1999/08/30 10:17:37 davem Exp $
  *
  * Fixes:
  *		Linus Torvalds	:	Assorted bug cures.
@@ -747,10 +747,8 @@
 	int sched;
 	DECLARE_WAITQUEUE(wait, current);
 
+	__set_current_state(TASK_INTERRUPTIBLE);
 	add_wait_queue(&other->protinfo.af_unix.peer_wait, &wait);
-	current->state = TASK_INTERRUPTIBLE;
-
-	barrier();
 
 	sched = (!other->dead &&
 		 !(other->shutdown&RCV_SHUTDOWN) &&
@@ -762,7 +760,7 @@
 	if (sched)
 		schedule();
 
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&other->protinfo.af_unix.peer_wait, &wait);
 }
 
@@ -1393,9 +1391,7 @@
 	add_wait_queue(sk->sleep, &wait);
 
 	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
-
-		barrier();
+		set_current_state(TASK_INTERRUPTIBLE);
 
 		if (skb_queue_len(&sk->receive_queue) ||
 		    sk->err ||
@@ -1410,7 +1406,7 @@
 		sk->socket->flags &= ~SO_WAITDATA;
 	}
 
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(sk->sleep, &wait);
 	unix_state_runlock(sk);
 }
diff -u --recursive --new-file v2.3.15/linux/net/wanrouter/wanmain.c linux/net/wanrouter/wanmain.c
--- v2.3.15/linux/net/wanrouter/wanmain.c	Wed Aug 18 11:38:49 1999
+++ linux/net/wanrouter/wanmain.c	Thu Aug 26 14:13:59 1999
@@ -30,7 +30,7 @@
 * Dec 22, 1998  Arnaldo Melo    vmalloc/vfree used in device_setup to allocate
 *                               kernel memory and copy configuration data to
 *                               kernel space (for big firmwares)
-* May 19, 1999  Arnaldo Melo    __initfunc in wanrouter_init
+* May 19, 1999  Arnaldo Melo    __init in wanrouter_init
 *****************************************************************************/
 
 #include <linux/config.h>
@@ -46,7 +46,7 @@
 #include <asm/byteorder.h>	/* htons(), etc. */
 #include <asm/uaccess.h>	/* copy_to/from_user */
 #include <linux/wanrouter.h>	/* WAN router API definitions */
-#include <linux/init.h>		/* __initfunc et al. */
+#include <linux/init.h>		/* __init et al. */
 
 /****** Defines and Macros **************************************************/
 
@@ -105,7 +105,7 @@
 #endif
 
 #ifndef MODULE
-__initfunc(int wanrouter_init(void))
+int __init wanrouter_init(void)
 {
 	int err;
 	extern int wanpipe_init(void),
diff -u --recursive --new-file v2.3.15/linux/net/wanrouter/wanproc.c linux/net/wanrouter/wanproc.c
--- v2.3.15/linux/net/wanrouter/wanproc.c	Sun Jul  4 10:02:30 1999
+++ linux/net/wanrouter/wanproc.c	Thu Aug 26 14:13:59 1999
@@ -26,7 +26,7 @@
 #include <linux/malloc.h>	/* kmalloc(), kfree() */
 #include <linux/mm.h>		/* verify_area(), etc. */
 #include <linux/string.h>	/* inline mem*, str* functions */
-#include <linux/init.h>		/* __initfunc et al. */
+#include <linux/init.h>		/* __init et al. */
 #include <asm/segment.h>	/* kernel <-> user copy */
 #include <asm/byteorder.h>	/* htons(), etc. */
 #include <asm/uaccess.h>	/* copy_to_user */
@@ -269,7 +269,7 @@
  *	Initialize router proc interface.
  */
 
-__initfunc(int wanrouter_proc_init (void))
+int __init wanrouter_proc_init (void)
 {
 	int err = proc_register(proc_net, &proc_router);
 
@@ -543,7 +543,7 @@
  *	No /proc - output stubs
  */
  
-__initfunc(int wanrouter_proc_init(void))
+int __init wanrouter_proc_init(void)
 {
 	return 0;
 }
diff -u --recursive --new-file v2.3.15/linux/net/x25/af_x25.c linux/net/x25/af_x25.c
--- v2.3.15/linux/net/x25/af_x25.c	Thu Aug 26 13:05:47 1999
+++ linux/net/x25/af_x25.c	Mon Aug 30 10:31:24 1999
@@ -1055,22 +1055,22 @@
 
 	switch (cmd) {
 		case TIOCOUTQ: {
-			long amount;
+			int amount;
 			amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
 			if (amount < 0)
 				amount = 0;
-			if (put_user(amount, (unsigned long *)arg))
+			if (put_user(amount, (unsigned int *)arg))
 				return -EFAULT;
 			return 0;
 		}
 
 		case TIOCINQ: {
 			struct sk_buff *skb;
-			long amount = 0L;
+			int amount = 0;
 			/* These two are safe on a single CPU system as only user tasks fiddle here */
 			if ((skb = skb_peek(&sk->receive_queue)) != NULL)
 				amount = skb->len;
-			if (put_user(amount, (unsigned long *)arg))
+			if (put_user(amount, (unsigned int *)arg))
 				return -EFAULT;
 			return 0;
 		}
@@ -1298,7 +1298,7 @@
 };
 #endif	
 
-__initfunc(void x25_proto_init(struct net_proto *pro))
+void __init x25_proto_init(struct net_proto *pro)
 {
 	sock_register(&x25_family_ops);
 
diff -u --recursive --new-file v2.3.15/linux/net/x25/sysctl_net_x25.c linux/net/x25/sysctl_net_x25.c
--- v2.3.15/linux/net/x25/sysctl_net_x25.c	Mon Jul  7 08:20:00 1997
+++ linux/net/x25/sysctl_net_x25.c	Thu Aug 26 14:13:59 1999
@@ -47,7 +47,7 @@
 	{0}
 };
 
-__initfunc(void x25_register_sysctl(void))
+void __init x25_register_sysctl(void)
 {
 	x25_table_header = register_sysctl_table(x25_root_table, 1);
 }
diff -u --recursive --new-file v2.3.15/linux/scripts/checkconfig.pl linux/scripts/checkconfig.pl
--- v2.3.15/linux/scripts/checkconfig.pl	Mon Feb  2 13:43:59 1998
+++ linux/scripts/checkconfig.pl	Tue Aug 31 09:33:09 1999
@@ -25,12 +25,12 @@
 	m+/\*+o && (s+/\*.*?\*/+ +go, (s+/\*.*$+ +o && ($fInComment = 1)));
 
 	# Pick up definitions.
-	if ( m/^#/o )
+	if ( m/^\s*#/o )
 	{
-	    $iLinuxConfig      = $. if m/^#\s*include\s*<linux\/config\.h>/o;
-	    $configList{uc $1} = 1  if m/^#\s*include\s*<config\/(\S*)\.h>/o;
-	    $configList{$1}    = 1  if m/^#\s*define\s+CONFIG_(\w*)/o;
-	    $configList{$1}    = 1  if m/^#\s*undef\s+CONFIG_(\w*)/o;
+	    $iLinuxConfig      = $. if m/^\s*#\s*include\s*<linux\/config\.h>/o;
+	    $configList{uc $1} = 1  if m/^\s*#\s*include\s*<config\/(\S*)\.h>/o;
+	    $configList{$1}    = 1  if m/^\s*#\s*define\s+CONFIG_(\w*)/o;
+	    $configList{$1}    = 1  if m/^\s*#\s*undef\s+CONFIG_(\w*)/o;
 	}
 
 	# Look for usages.
