diff -u --recursive --new-file v2.3.34/linux/CREDITS linux/CREDITS
--- v2.3.34/linux/CREDITS	Mon Dec 20 18:48:21 1999
+++ linux/CREDITS	Sun Dec 26 19:34:04 1999
@@ -331,6 +331,10 @@
 S: Amsterdam
 S: The Netherlands
 
+N: Zach Brown
+E: zab@zabbo.net
+D: maestro pci sound
+
 N: Ray Burr
 E: ryb@nightmare.com
 D: Original author of Amiga FFS filesystem
@@ -997,12 +1001,12 @@
 S: United Kingdom
 
 N: Jakub Jelinek
-E: jj@sunsite.mff.cuni.cz
+E: jakub@redhat.com
 W: http://sunsite.mff.cuni.cz/~jj
 P: 1024/0F7623C5 53 95 71 3C EB 73 99 97  02 49 40 47 F9 19 68 20
 D: Sparc hacker, SILO, mc
 D: Maintain sunsite.mff.cuni.cz
-S: Na Orechovce 7
+S: K osmidomkum 723
 S: 160 00 Praha 6
 S: Czech Republic
 
diff -u --recursive --new-file v2.3.34/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.34/linux/Documentation/Configure.help	Mon Dec 20 18:48:21 1999
+++ linux/Documentation/Configure.help	Mon Dec 27 14:01:53 1999
@@ -7852,18 +7852,18 @@
 Support for USB (EXPERIMENTAL)
 CONFIG_USB
   Universal Serial Bus (USB) is a specification for a serial bus
-  system which offers higher speeds and more features than the
+  subsystem which offers higher speeds and more features than the
   traditional PC serial port. The bus supplies power to peripherals
   and allows for hot swapping. Up to 127 USB peripherals can be
-  connected to a single USB port in a tree structure; the USB port is
-  the root of the tree, the peripherals are the leafs and the inner
-  nodes are special USB devices called hubs. Many newer PC's have USB
+  connected to a single USB port in a tree structure. The USB port is
+  the root of the tree, the peripherals are the leaves, and the inner
+  nodes are special USB devices called hubs. Many newer PCs have USB
   ports and newer peripherals such as scanners, keyboards, mice,
-  modems and printers support the USB protocol and can be connected to
-  the PC via those ports.
+  modems, and printers support the USB protocol and can be connected
+  to the PC via those ports.
 
   Say Y here if your computer has a USB port and you want to
-  experiment with USB devices. You then need to say Y to at least one
+  use USB devices. You then need to say Y to at least one
   of "UHCI support" or "OHCI support" below (the type of interface
   that the USB hardware in your computer provides) and then choose
   from among the drivers for USB peripherals.
@@ -7873,7 +7873,7 @@
   The module will be called usbcore.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-UHCI (intel PIIX4 and others) support?
+UHCI (intel PIIX4, VIA, and others) support?
 CONFIG_USB_UHCI
   The Universal Host Controller Interface is a standard by Intel for
   accessing the USB hardware in the PC (which is also called the USB
@@ -7886,20 +7886,17 @@
   The module will be called usb-uhci.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
   
-OHCI-HCD (compaq and some others) support?
+OHCI-HCD (Compaq, iMacs, OPTi, SiS, and others) support?
 CONFIG_USB_OHCI_HCD
-  The Open Host Controller Interface is a standard by Compaq for
-  accessing the USB PC hardware (also called USB host controller). If
-  your USB host controller conforms to this standard, say Y. The USB
-  host controllers on most non-Intel architectures and on several x86
-  compatibles with non-Intel chipsets conform to this standard.
+  The Open Host Controller Interface is a standard by
+  Compaq/Microsoft/National for accessing the USB PC hardware (also
+  called USB host controller). If your USB host controller conforms
+  to this standard, say Y. The USB host controllers on most
+  non-Intel architectures and on several x86 compatibles with
+  non-Intel chipsets conform to this standard.
 
   You may want to read the file drivers/usb/README.ohci_hcd.
 
-  There are currently two OHCI drivers in development. You should
-  compile at most one. The other one is "OHCI (compaq and some others)
-  support?", above.
-
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
   The module will be called usb-ohci-hcd.o. If you want to compile it
@@ -7915,11 +7912,11 @@
   The module will be called mouse.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-USB HP scanner support
-CONFIG_USB_HP_SCANNER
-  Say Y here if you want to connect a USB HP scanner to your
-  computer's USB port. Please read drivers/usb/README.hp_scanner
-  for more information.
+USB scanner support
+CONFIG_USB_SCANNER
+  Say Y here if you want to connect a USB scanner to your
+  computer's USB port. Please read drivers/usb/README.scanner
+  and drivers/usb/README.scanner_hp_sane for more information.
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -7938,7 +7935,7 @@
 
 USB audio parsing support
 CONFIG_USB_AUDIO
-  Say Y here if you want to connect audio equipment such as USB
+  Say Y here if you want to connect USB audio equipment such as
   speakers to your computer's USB port.
 
   This code is also available as a module ( = code which can be
@@ -7957,9 +7954,10 @@
   The module will be called acm.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-USB Belkin and Peracom serial support
+USB serial converter support
 CONFIG_USB_SERIAL
-  Say Y here if you want to connect a Belkin, Peracom, or eTek
+  Say Y here if you want to connect a Connect Tech WhiteHEAT 
+  multi-port USB to serial converter, or a Belkin, Peracom, or eTek
   single port USB to serial converter.
   
   This code is also available as a module ( = code which can be
@@ -7969,7 +7967,7 @@
 
 USB Printer support
 CONFIG_USB_PRINTER
-  Say Y here if you want to connect a printer to your computer's USB
+  Say Y here if you want to connect a USB printer to your computer's USB
   port.
 
   This code is also available as a module ( = code which can be
@@ -8001,8 +7999,13 @@
 
 USB SCSI Support
 CONFIG_USB_SCSI
-  Say Y here if you want to connect SCSI devices to your computer's
-  USB port.
+  Say Y here if you want to connect USB mass storage devices to your
+  computer's USB port.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called usb-scsi.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
 
 USB SCSI verbose debug
 CONFIG_USB_SCSI_DEBUG
@@ -8027,7 +8030,7 @@
 
   Manual mode is not limited to printers, any parallel port
   device should work. This driver utilizes manual mode.
-  Note however that some operations are three orders of a magnitude
+  Note however that some operations are three orders of magnitude
   slower than on a PCI/ISA Parallel Port, so timing critical
   applications might not work.
 
@@ -8039,22 +8042,27 @@
   The module will be called uss720.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
   
-USB /proc filesystem entry support (Preliminary)
+USB /proc filesystem support
 CONFIG_USB_PROC
   This reports USB drivers and devices in the /proc filesystem.
   Entries are located in /proc/bus/usb. The entries are described in
   the file Documentation/proc_usb_info.txt.
 
-  Note that you must say Y to "/proc filesystem support" below for
-  this to work.
+  Note that you must say Y to global "/proc filesystem support" under
+  Filesystems for this to work.
 
 DABUSB driver
 CONFIG_USB_DABUSB
-  A Digital Audio Broadcasting (DAB) Receiver for USB and Linux brought to
-  you by the DAB-Team (http://dab.in.tum.de). 
+  A Digital Audio Broadcasting (DAB) Receiver for USB and Linux brought
+  to you by the DAB-Team (http://dab.in.tum.de). 
   This driver can be taken as an example for URB-based bulk, control, and
   isochronous transactions.
 
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called dabusb.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+  
 ACPI support
 CONFIG_ACPI
   Advanced Configuration and Power Interface (ACPI) is an interface
@@ -8834,10 +8842,9 @@
 Lowercase DOS filenames on LONG namespace volume
 CONFIG_NCPFS_SMALLDOS
   If you say Y here, every filename on a NetWare server volume using
-  the OS2/LONG namespace will be converted to lowercase characters.
-  (For regular NetWare file server volumes with DOS namespace, this is
-  done automatically, even if you say N here.) Saying N here will give
-  you these filenames in uppercase.
+  the OS2/LONG namespace and created under DOS or on a volume using
+  DOS namespace will be converted to lowercase characters.
+  Saying N here will give you these filenames in uppercase.
   
   This is only a cosmetic option since the OS2/LONG namespace is case
   insensitive. The only major reason for this option is backward
@@ -11171,6 +11178,12 @@
   engine.
 
   See Documentation/sound/NM256 for further information.
+
+ESS Maestro sound chipsets
+CONFIG_SOUND_MAESTRO
+  Say Y or M if you have a sound system driven by ESS's Maestro line
+  of PCI sound chips.  These include the Maestro 1, Maestro 2, and
+  Maestro 2E.  See Documentation/sound/Maestro for more details.
 
 Are you using a crosscompiler
 CONFIG_CROSSCOMPILE
diff -u --recursive --new-file v2.3.34/linux/Documentation/filesystems/cramfs.txt linux/Documentation/filesystems/cramfs.txt
--- v2.3.34/linux/Documentation/filesystems/cramfs.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/filesystems/cramfs.txt	Mon Dec 27 13:16:57 1999
@@ -0,0 +1,13 @@
+
+	Cramfs - cram a filesystem onto a small ROM
+
+cramfs is designed to be simple and small, and to compress things well. 
+
+It uses the zlib routines to compress a file one page at a time, and
+allows random page access.  The meta-data is not compressed, but is
+expressed in a very terse representation to make it use much less
+diskspace than traditional filesystems. 
+
+You can't write to a cramfs filesystem (making it compressible and
+compact also makes it _very_ hard to update on-the-fly), so you have to
+create the disk image with the "mkcramfs" utility in scripts/cramfs.
diff -u --recursive --new-file v2.3.34/linux/Documentation/filesystems/vfat.txt linux/Documentation/filesystems/vfat.txt
--- v2.3.34/linux/Documentation/filesystems/vfat.txt	Mon Dec 20 18:48:21 1999
+++ linux/Documentation/filesystems/vfat.txt	Tue Dec 21 14:28:39 1999
@@ -29,8 +29,8 @@
 		 a '?' is used when no translation is possible.  The
 		 escape character is ':' because it is otherwise
 		 illegal on the vfat filesystem.  The escape sequence
-		 that gets used, where u is the unicode character, is:
-			':', (u & 0x3f), ((u>>6) & 0x3f), (u>>12),
+		 that gets used is ':' and the four digits of hexadecimal
+		 unicode.
 posix=<bool>  -- Allow names of same letters, different case such as
                  'LongFileName' and 'longfilename' to coexist.  This has some
                  problems currently because 8.3 conflicts are not handled
diff -u --recursive --new-file v2.3.34/linux/Documentation/networking/sis900.txt linux/Documentation/networking/sis900.txt
--- v2.3.34/linux/Documentation/networking/sis900.txt	Tue Nov 23 22:42:20 1999
+++ linux/Documentation/networking/sis900.txt	Sat Dec 25 11:21:15 1999
@@ -1,6 +1,6 @@
   SiS 900/7016 Fast Ethernet Device Driver
   by Ollie Lho (ollie@sis.com.tw)
-  November 4, 1999. Document Revision: 0.1
+  November 4, 1999. Document Revision: 0.2
 
   This document gives some information on installation and usage of SiS
   900/7016 device driver under Linux.
@@ -17,7 +17,7 @@
 
   4. Tested Environment
 
-  5. Files in This Rackage
+  5. Files in This Package
 
   6. Installation
 
@@ -111,9 +111,11 @@
 
   9. Names of variables were changed to be more consistent.
 
- 10. Clean up of auo-negotiation and timer code.
+  10.
+     Clean up of auo-negotiation and timer code.
 
- 11. Automatic detection and change of PHY on the fly.
+  11.
+     Automatic detection and change of PHY on the fly.
 
 
   4.  Tested Environment
@@ -137,7 +139,7 @@
   o  Samba version 2.0.3
 
 
-  5.  Files in This Rackage
+  5.  Files in This Package
 
   In the package you can find these files:
 
@@ -157,10 +159,16 @@
 
   6.  Installation
 
-  Before trying to install the driver, be sure to get the latest
-  revision from SiS' Home Page.  If you have no prior experience in
-  networking under Linux, please read Ethernet HOWTO and Networking
-  HOWTO available from Linux Documentation Project (LDP).
+  Silicon Integrated System Corp. is cooperating closely with core Linux
+  Kernel developers. The revisions of SiS 900 driver are distributed by
+  the usuall channels for kernel tar files and patches. Those kernel tar
+  files for official kernel and patches for kernel pre-release can be
+  download at official kernel ftp site
+  <http://ftp.kernel.org/pub/linux/kernel/> and its mirrors.  The 1.06
+  revision can be found in kernel version later than 2.3.15 and
+  pre-2.2.14.  If you have no prior experience in networking under
+  Linux, please read Ethernet HOWTO and Networking HOWTO available from
+  Linux Documentation Project (LDP).
 
   The installation procedure are different according to your kernel
   versions.
@@ -244,6 +252,7 @@
        sis900.c: v1.06  11/04/99
        eth0: SiS 900 PCI Fast Ethernet at 0xd000, IRQ 10, 00:00:e8:83:7f:a4.
        eth0: SiS 900 Internal MII PHY transceiver found at address 1.
+       eth0: Using SiS 900 Internal MII PHY as default
 
 
 
@@ -269,7 +278,6 @@
 
 
 
-       eth0: Using SiS 900 Internal MII PHY as default
        eth0: Media Link On 100mbps full-duplex
 
 
diff -u --recursive --new-file v2.3.34/linux/Documentation/proc_usb_info.txt linux/Documentation/proc_usb_info.txt
--- v2.3.34/linux/Documentation/proc_usb_info.txt	Mon Dec 20 18:48:21 1999
+++ linux/Documentation/proc_usb_info.txt	Tue Dec 21 11:51:03 1999
@@ -149,6 +149,9 @@
 of the USB devices on a system's root hub.  (See more below
 on how to do this.)
 
+The Interface lines can be used to determine what driver is
+being used for each device.
+
 The Configuration lines could be used to list maximum power
 (in milliamps) that a system's USB devices are using.
 For example, "grep ^C: /proc/bus/usb/devices".
@@ -156,65 +159,57 @@
 
 Here's an example, from a system which has a UHCI root hub,
 an external hub connected to the root hub, and a mouse and
-a video camera connected to the external hub.  [The video
-camera is listed as (none) since it is not recognized by
-any driver.]
-
+a serial converter connected to the external hub.
 
-T:  Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= -1 Spd=12  If#=  0 MxCh= 2 Driver=(root hub)
-T:  Lev=01 Prnt=00 Port=00 Cnt=01 Dev#=  1 Spd=12  If#=  0 MxCh= 4 Driver=hub
+T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
+B:  Alloc= 28/900 us ( 3%), #Int=  2, #Iso=  0
+T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
 D:  Ver= 1.00 Cls=09(hub  ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
 P:  Vendor=0451 ProdID=1446 Rev= 1.00
-C:* #If= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
-I:  If#= 0 Alt= 0 #EP= 1 Cls=09(hub  ) Sub=00 Prot=00
+C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
+I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
 E:  Ad=81(I) Atr=03(Int.) MxPS=   1 Ivl=255ms
-T:  Lev=02 Prnt=01 Port=00 Cnt=01 Dev#=  3 Spd=1.5 If#=  0 MxCh= 0 Driver=mouse
+T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
 D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
-P:  Vendor=0458 ProdID=0001 Rev= 0.00
-C:* #If= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
-I:  If#= 0 Alt= 0 #EP= 1 Cls=03(HID  ) Sub=01 Prot=02
+P:  Vendor=04b4 ProdID=0001 Rev= 0.00
+C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
+I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
 E:  Ad=81(I) Atr=03(Int.) MxPS=   3 Ivl= 10ms
-T:  Lev=02 Prnt=01 Port=02 Cnt=02 Dev#=  4 Spd=12  If#=  0 MxCh= 0 Driver=(none)
+T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
 D:  Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
-P:  Vendor=04c8 ProdID=0720 Rev= 1.01
-C:* #If= 1 Cfg#= 1 Atr=80 MxPwr=500mA
-I:  If#= 0 Alt= 0 #EP= 2 Cls=0a(unk. ) Sub=ff Prot=00
-E:  Ad=81(I) Atr=01(Isoc) MxPS=   1 Ivl=  1ms
-E:  Ad=82(I) Atr=01(Isoc) MxPS= 384 Ivl=  1ms
-I:  If#= 0 Alt= 1 #EP= 2 Cls=0a(unk. ) Sub=ff Prot=00
-E:  Ad=81(I) Atr=01(Isoc) MxPS=   1 Ivl=  1ms
-E:  Ad=82(I) Atr=01(Isoc) MxPS= 240 Ivl=  1ms
-I:  If#= 0 Alt= 2 #EP= 2 Cls=0a(unk. ) Sub=ff Prot=00
-E:  Ad=81(I) Atr=01(Isoc) MxPS=   1 Ivl=  1ms
-E:  Ad=82(I) Atr=01(Isoc) MxPS= 576 Ivl=  1ms
-I:  If#= 0 Alt= 3 #EP= 2 Cls=0a(unk. ) Sub=ff Prot=00
-E:  Ad=81(I) Atr=01(Isoc) MxPS=   1 Ivl=  1ms
-E:  Ad=82(I) Atr=01(Isoc) MxPS= 464 Ivl=  1ms
-I:  If#= 0 Alt= 4 #EP= 2 Cls=0a(unk. ) Sub=ff Prot=00
-E:  Ad=81(I) Atr=01(Isoc) MxPS=   1 Ivl=  1ms
-E:  Ad=82(I) Atr=01(Isoc) MxPS= 688 Ivl=  1ms
-
-
-Selecting only the "T:" lines from this (for example, by using
-"procusb t"), we have:
-
-T:  Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= -1 Spd=12  If#=  0 MxCh= 2 Driver=(root hub)
-T:  Lev=01 Prnt=00 Port=00 Cnt=01 Dev#=  1 Spd=12  If#=  0 MxCh= 4 Driver=hub
-T:  Lev=02 Prnt=01 Port=00 Cnt=01 Dev#=  3 Spd=1.5 If#=  0 MxCh= 0 Driver=mouse
-T:  Lev=02 Prnt=01 Port=02 Cnt=02 Dev#=  4 Spd=12  If#=  0 MxCh= 0 Driver=(none)
+P:  Vendor=0565 ProdID=0001 Rev= 1.08
+S:  Manufacturer=Peracom Networks, Inc.
+S:  Product=Peracom USB to Serial Converter
+C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
+I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
+E:  Ad=81(I) Atr=02(Bulk) MxPS=  64 Ivl= 16ms
+E:  Ad=01(O) Atr=02(Bulk) MxPS=  16 Ivl= 16ms
+E:  Ad=82(I) Atr=03(Int.) MxPS=   8 Ivl=  8ms
+
+
+Selecting only the "T:" and "I:" lines from this (for example, by using
+"procusb ti"), we have:
+
+T:  Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=12  MxCh= 2
+T:  Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 4
+I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
+T:  Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#=  3 Spd=1.5 MxCh= 0
+I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=mouse
+T:  Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#=  4 Spd=12  MxCh= 0
+I:  If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
 
 
 Physically this looks like (or could be converted to):
 
                       +------------------+
-                      |  PC/root_hub (12)|   Dev# = -1
+                      |  PC/root_hub (12)|   Dev# = 1
                       +------------------+   (nn) is Mbps.
     Level 0           |  CN.0   |  CN.1  |   [CN = connector/port #]
                       +------------------+
                           /
                          /
             +-----------------------+
-  Level 1   | Dev#1: 4-port hub (12)|
+  Level 1   | Dev#2: 4-port hub (12)|
             +-----------------------+
             |CN.0 |CN.1 |CN.2 |CN.3 |
             +-----------------------+
@@ -222,7 +217,7 @@
                  \_____                          \
                        \                          \
                +--------------------+      +--------------------+
-  Level 2      | Dev# 3: mouse (1.5)|      | Dev# 4: (none) (12)|
+  Level 2      | Dev# 3: mouse (1.5)|      | Dev# 4: serial (12)|
                +--------------------+      +--------------------+
 
 
@@ -230,11 +225,11 @@
 Or, in a more tree-like structure (ports [Connectors] without
 connections could be omitted):
 
-PC:  Dev# -1, root hub, 2 ports, 12 Mbps
-|_ CN.0:  Dev# 1, hub, 4 ports, 12 Mbps
+PC:  Dev# 1, root hub, 2 ports, 12 Mbps
+|_ CN.0:  Dev# 2, hub, 4 ports, 12 Mbps
      |_ CN.0:  Dev #3, mouse, 1.5 Mbps
      |_ CN.1:
-     |_ CN.2:  Dev #4, (none), 12 Mbps  [or use "unknown" for (none)]
+     |_ CN.2:  Dev #4, serial, 12 Mbps
      |_ CN.3:
 |_ CN.1:
 
diff -u --recursive --new-file v2.3.34/linux/Documentation/sound/Maestro linux/Documentation/sound/Maestro
--- v2.3.34/linux/Documentation/sound/Maestro	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/Maestro	Sun Dec 26 19:34:04 1999
@@ -0,0 +1,98 @@
+	An OSS/Lite Driver for the ESS Maestro family of sound cards
+
+			Zach Brown, December 1999
+
+Driver Status and Availability
+------------------------------
+
+The most recent version of this driver will hopefully always be available at
+	http://people.redhat.com/zab/maestro/
+
+I will try and maintain the most recent stable version of the driver
+in both the stable and development kernel lines.
+
+ESS Maestro Chip Family
+-----------------------
+
+There are 3 main variants of the ESS Maestro PCI sound chip.  The first
+is the Maestro 1.  It was originally produced by Platform Tech as the
+'AGOGO'.  It can be recognized by Platform Tech's PCI ID 0x1285 with
+0x0100 as the device ID.  It was put on some sound boards and a few laptops.  
+ESS bought the design and cleaned it up as the Maestro 2.  This starts
+their marking with the ESS vendor ID 0x125D and the 'year' device IDs.
+The Maestro 2 claims 0x1968 while the Maestro 2e has 0x1978.
+
+The various families of Maestro are mostly identical as far as this 
+driver is concerned.  It doesn't touch the DSP parts that differ (though
+it could for FM synthesis)
+
+Driver OSS Behavior
+--------------------
+
+This OSS driver exports /dev/mixer and /dev/dsp to applications, which
+mostly adhere to the OSS spec.   This driver doesn't register itself
+with /dev/sndstat, so don't expect information to appear there.
+
+The /dev/dsp device exported behaves almost as expected.  Playback is
+supported in all the various lovely formats.  8/16bit stereo/mono from
+8khz to 48khz, and mmap()ing for playback behaves.  Capture/recording
+is limited due to oddities with the Maestro hardware.  One can only
+record in 16bit stereo.  For recording the maestro uses non interleaved
+stereo buffers so that mmap()ing the incoming data does not result in
+a ring buffer of LRLR data.  mmap()ing of the read buffers is therefore
+disallowed until this can be cleaned up.
+
+/dev/mixer is an interface to the AC'97 codec on the Maestro.  It is
+worth noting that there are a variety of AC'97s that can be wired to
+the Maestro.  Which is used is entirely up to the hardware implementor.
+This should only be visible to the user by the presence, or lack, of
+'Bass' and 'Treble' sliders in the mixer.  Not all AC'97s have them.
+
+The driver doesn't support MIDI or FM playback at the moment.  Typically
+the Maestro is wired to an MPU MIDI chip, but some hardware implementations
+don't.  We need to assemble a white list of hardware implementations that
+have MIDI wired properly before we can claim to support it safely.
+
+Compiling and Installing
+------------------------
+
+With the drivers inclusion into the kernel, compiling and installing
+is the same as most OSS/Lite modular sound drivers.  Compilation
+of the driver is enabled through the CONFIG_SOUND_MAESTRO variable
+in the config system.  
+
+It may be modular or statically linked.  If it is modular it should be
+installed with the rest of the modules for the kernel on the system.
+Typically this will be in /lib/modules/ somewhere.  'alias sound maestro'
+should also be added to your module configs (typically /etc/conf.modules)
+if you're using modular OSS/Lite sound and want to default to using a
+maestro chip.
+
+As this is a PCI device, the module does not need to be informed of
+any IO or IRQ resources it should use, it devines these from the
+system.  Somtimes, on sucky PCs, the BIOS fails to allocated resources
+for the maestro.  This will result in a message like:
+	maestro: PCI subsystem reports IRQ 0, this might not be correct.
+from the kernel.  Should this happen the sound chip most likely will
+not operate correctly.  To solve this one has to dig through their BIOS
+(typically entered by hitting a hot key at boot time) and figure out
+what magic needs to happen so that the BIOS will reward the maestro with
+an IRQ.  This operation is incredibly system specific, so you're on your
+own.  Sometimes the magic lies in 'PNP Capable Operating System' settings.
+
+There are very few options to the driver.  One is 'debug' which will 
+tell the driver to print minimal debugging information as it runs.  This
+can be collected with 'dmesg' or through the klogd daemon.
+
+The other, more interesting option, is 'dsps_order'.  Typically at
+install time the driver will only register one available /dev/dsp device
+for its use.  The 'dsps_order' module parameter allows for more devices
+to be allocated, as a power of two.  Up to 4 devices can be registered
+( dsps_order=2 ).  These devices act as fully distinct units and use
+separate channels in the maestro.
+
+.. more details ..
+-----------------
+
+drivers/sound/maestro.c contains comments that hopefully explain
+the maestro implementation.
diff -u --recursive --new-file v2.3.34/linux/MAINTAINERS linux/MAINTAINERS
--- v2.3.34/linux/MAINTAINERS	Mon Dec 20 18:48:21 1999
+++ linux/MAINTAINERS	Sun Dec 26 19:34:04 1999
@@ -529,6 +529,12 @@
 L:	linuxppc-dev@lists.linuxppc.org
 S:	Maintained
 
+MAESTRO PCI SOUND DRIVER
+P:	Zach Brown
+M:	zab@redhat.com
+W:	http://people.redhat.com/zab/maestro/
+S:	Supported
+
 M68K
 P:	Jes Sorensen
 M:	Jes.Sorensen@cern.ch
diff -u --recursive --new-file v2.3.34/linux/Makefile linux/Makefile
--- v2.3.34/linux/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/Makefile	Mon Dec 27 15:59:32 1999
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 34
+SUBLEVEL = 35
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -109,7 +109,6 @@
 #
 
 CORE_FILES	=kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o
-FILESYSTEMS	=fs/filesystems.a
 NETWORKS	=net/network.a
 DRIVERS		=drivers/block/block.a \
 		 drivers/char/char.o \
@@ -256,7 +255,6 @@
 	$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
 		--start-group \
 		$(CORE_FILES) \
-		$(FILESYSTEMS) \
 		$(NETWORKS) \
 		$(DRIVERS) \
 		$(LIBS) \
diff -u --recursive --new-file v2.3.34/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.3.34/linux/arch/i386/config.in	Mon Dec 20 18:48:21 1999
+++ linux/arch/i386/config.in	Sat Dec 25 15:03:57 1999
@@ -119,6 +119,7 @@
 
 source drivers/parport/Config.in
 
+bool 'ACPI support' CONFIG_ACPI
 bool 'Advanced Power Management BIOS support' CONFIG_APM
 if [ "$CONFIG_APM" != "n" ]; then
    bool '  Ignore USER SUSPEND' CONFIG_APM_IGNORE_USER_SUSPEND
diff -u --recursive --new-file v2.3.34/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.3.34/linux/arch/i386/defconfig	Mon Dec 20 18:48:21 1999
+++ linux/arch/i386/defconfig	Tue Dec 28 10:59:24 1999
@@ -59,8 +59,9 @@
 #
 CONFIG_PCMCIA=y
 CONFIG_CARDBUS=y
-CONFIG_I82365=y
-# CONFIG_TCIC is not set
+CONFIG_YENTA=y
+# CONFIG_I82365 is not set
+CONFIG_TCIC=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
@@ -70,6 +71,7 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
 # CONFIG_PARPORT is not set
+CONFIG_ACPI=y
 # CONFIG_APM is not set
 
 #
@@ -404,7 +406,6 @@
 #
 # Misc devices
 #
-CONFIG_ACPI=y
 
 #
 # Filesystems
@@ -416,6 +417,7 @@
 # CONFIG_MSDOS_FS is not set
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
+# CONFIG_CRAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
diff -u --recursive --new-file v2.3.34/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
--- v2.3.34/linux/arch/i386/kernel/Makefile	Thu Nov 11 20:11:31 1999
+++ linux/arch/i386/kernel/Makefile	Sat Dec 25 15:04:47 1999
@@ -39,6 +39,10 @@
   endif
 endif
 
+ifeq ($(CONFIG_ACPI),y)
+  OX_OBJS += acpi.o
+endif
+
 ifeq ($(CONFIG_APM),y)
 OX_OBJS += apm.o
 else
diff -u --recursive --new-file v2.3.34/linux/arch/i386/kernel/acpi.c linux/arch/i386/kernel/acpi.c
--- v2.3.34/linux/arch/i386/kernel/acpi.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/i386/kernel/acpi.c	Sat Dec 25 14:52:52 1999
@@ -0,0 +1,1318 @@
+/*
+ *  acpi.c - Linux ACPI driver
+ *
+ *  Copyright (C) 1999 Andrew Henroid
+ *
+ *  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
+ */
+
+/*
+ * See http://www.geocities.com/SiliconValley/Hardware/3165/
+ * for the user-level ACPI stuff
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <linux/sysctl.h>
+#include <linux/delay.h>
+#include <linux/acpi.h>
+
+/*
+ * Defines for 2.2.x
+ */
+#ifndef __exit
+#define __exit
+#endif
+#ifndef module_init
+#define module_init(x) int init_module(void) {return x();}
+#endif
+#ifndef module_exit
+#define module_exit(x) void cleanup_module(void) {x();}
+#endif
+#ifndef DECLARE_WAIT_QUEUE_HEAD
+#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue * x = NULL
+#endif
+
+/*
+ * Yes, it's unfortunate that we are relying on get_cmos_time
+ * because it is slow (> 1 sec.) and i386 only.	 It might be better
+ * to use some of the code from drivers/char/rtc.c in the near future
+ */
+extern unsigned long get_cmos_time(void);
+
+static int acpi_control_thread(void *context);
+static int acpi_do_ulong(ctl_table *ctl,
+			 int write,
+			 struct file *file,
+			 void *buffer,
+			 size_t *len);
+static int acpi_do_event_reg(ctl_table *ctl,
+			     int write,
+			     struct file *file,
+			     void *buffer,
+			     size_t *len);
+static int acpi_do_event(ctl_table *ctl,
+			 int write,
+			 struct file *file,
+			 void *buffer,
+			 size_t *len);
+static int acpi_do_sleep(ctl_table *ctl,
+			 int write,
+			 struct file *file,
+			 void *buffer,
+			 size_t *len);
+
+DECLARE_WAIT_QUEUE_HEAD(acpi_control_wait);
+
+static struct ctl_table_header *acpi_sysctl = NULL;
+
+static struct acpi_facp *acpi_facp = NULL;
+static int acpi_fake_facp = 0;
+static struct acpi_facs *acpi_facs = NULL;
+static unsigned long acpi_facp_addr = 0;
+static unsigned long acpi_dsdt_addr = 0;
+
+// current system sleep state (S0 - S4)
+static acpi_sstate_t acpi_sleep_state = ACPI_S0;
+// time sleep began
+static unsigned long acpi_sleep_start = 0;
+
+static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED;
+static volatile u32 acpi_pm1_status = 0;
+static volatile u32 acpi_gpe_status = 0;
+static volatile u32 acpi_gpe_level = 0;
+static volatile acpi_sstate_t acpi_event_state = ACPI_S0;
+static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait);
+
+static spinlock_t acpi_devs_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(acpi_devs);
+
+/* Make it impossible to enter C2/C3 until after we've initialized */
+static unsigned long acpi_enter_lvl2_lat = ACPI_INFINITE_LAT;
+static unsigned long acpi_enter_lvl3_lat = ACPI_INFINITE_LAT;
+static unsigned long acpi_p_lvl2_lat = ACPI_INFINITE_LAT;
+static unsigned long acpi_p_lvl3_lat = ACPI_INFINITE_LAT;
+
+static unsigned long acpi_p_blk = 0;
+
+static int acpi_p_lvl2_tested = 0;
+static int acpi_p_lvl3_tested = 0;
+
+// bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb
+static unsigned long acpi_slp_typ[] = 
+{
+	ACPI_SLP_TYP_DISABLED, /* S0 */
+	ACPI_SLP_TYP_DISABLED, /* S1 */
+	ACPI_SLP_TYP_DISABLED, /* S2 */
+	ACPI_SLP_TYP_DISABLED, /* S3 */
+	ACPI_SLP_TYP_DISABLED, /* S4 */
+	ACPI_SLP_TYP_DISABLED  /* S5 */
+};
+
+static struct ctl_table acpi_table[] =
+{
+	{ACPI_FACP, "facp",
+	 &acpi_facp_addr, sizeof(acpi_facp_addr),
+	 0400, NULL, &acpi_do_ulong},
+
+	{ACPI_DSDT, "dsdt",
+	 &acpi_dsdt_addr, sizeof(acpi_dsdt_addr),
+	 0400, NULL, &acpi_do_ulong},
+
+	{ACPI_PM1_ENABLE, "pm1_enable",
+	 NULL, 0,
+	 0600, NULL, &acpi_do_event_reg},
+
+	{ACPI_GPE_ENABLE, "gpe_enable",
+	 NULL, 0,
+	 0600, NULL, &acpi_do_event_reg},
+
+	{ACPI_GPE_LEVEL, "gpe_level",
+	 NULL, 0,
+	 0600, NULL, &acpi_do_event_reg},
+
+	{ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event},
+
+	{ACPI_P_BLK, "p_blk",
+	 &acpi_p_blk, sizeof(acpi_p_blk),
+	 0600, NULL, &acpi_do_ulong},
+
+	{ACPI_P_LVL2_LAT, "p_lvl2_lat",
+	 &acpi_p_lvl2_lat, sizeof(acpi_p_lvl2_lat),
+	 0644, NULL, &acpi_do_ulong},
+
+	{ACPI_P_LVL3_LAT, "p_lvl3_lat",
+	 &acpi_p_lvl3_lat, sizeof(acpi_p_lvl3_lat),
+	 0644, NULL, &acpi_do_ulong},
+
+	{ACPI_S0_SLP_TYP, "s0_slp_typ",
+	 &acpi_slp_typ[ACPI_S0], sizeof(acpi_slp_typ[ACPI_S0]),
+	 0600, NULL, &acpi_do_ulong},
+
+	{ACPI_S1_SLP_TYP, "s1_slp_typ",
+	 &acpi_slp_typ[ACPI_S1], sizeof(acpi_slp_typ[ACPI_S1]),
+	 0600, NULL, &acpi_do_ulong},
+
+	{ACPI_S5_SLP_TYP, "s5_slp_typ",
+	 &acpi_slp_typ[ACPI_S5], sizeof(acpi_slp_typ[ACPI_S5]),
+	 0600, NULL, &acpi_do_ulong},
+
+	{ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},
+
+	{0}
+};
+
+static struct ctl_table acpi_dir_table[] =
+{
+	{CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table},
+	{0}
+};
+
+
+/*
+ * Get the value of the PM1 control register (SCI_EN, ...)
+ */
+static u32 acpi_read_pm1_control(struct acpi_facp *facp)
+{
+	u32 value = 0;
+	if (facp->pm1a_cnt)
+		value = inw(facp->pm1a_cnt);
+	if (facp->pm1b_cnt)
+		value |= inw(facp->pm1b_cnt);
+	return value;
+}
+
+/*
+ * Set the value of the PM1 control register (BM_RLD, ...)
+ */
+static void acpi_write_pm1_control(struct acpi_facp *facp, u32 value)
+{
+	if (facp->pm1a_cnt)
+		outw(value, facp->pm1a_cnt);
+	if (facp->pm1b_cnt)
+		outw(value, facp->pm1b_cnt);
+}
+
+/*
+ * Get the value of the fixed event status register
+ */
+static u32 acpi_read_pm1_status(struct acpi_facp *facp)
+{
+	u32 value = 0;
+	if (facp->pm1a_evt)
+		value = inw(facp->pm1a_evt);
+	if (facp->pm1b_evt)
+		value |= inw(facp->pm1b_evt);
+	return value;
+}
+
+/*
+ * Set the value of the fixed event status register (clear events)
+ */
+static void acpi_write_pm1_status(struct acpi_facp *facp, u32 value)
+{
+	if (facp->pm1a_evt)
+		outw(value, facp->pm1a_evt);
+	if (facp->pm1b_evt)
+		outw(value, facp->pm1b_evt);
+}
+
+/*
+ * Get the value of the fixed event enable register
+ */
+static u32 acpi_read_pm1_enable(struct acpi_facp *facp)
+{
+	int offset = facp->pm1_evt_len >> 1;
+	u32 value = 0;
+	if (facp->pm1a_evt)
+		value = inw(facp->pm1a_evt + offset);
+	if (facp->pm1b_evt)
+		value |= inw(facp->pm1b_evt + offset);
+	return value;
+}
+
+/*
+ * Set the value of the fixed event enable register (enable events)
+ */
+static void acpi_write_pm1_enable(struct acpi_facp *facp, u32 value)
+{
+	int offset = facp->pm1_evt_len >> 1;
+	if (facp->pm1a_evt)
+		outw(value, facp->pm1a_evt + offset);
+	if (facp->pm1b_evt)
+		outw(value, facp->pm1b_evt + offset);
+}
+
+/*
+ * Get the value of the general-purpose event status register
+ */
+static u32 acpi_read_gpe_status(struct acpi_facp *facp)
+{
+	u32 value = 0;
+	int i, size;
+
+	if (facp->gpe1) {
+		size = facp->gpe1_len >> 1;
+		for (i = size - 1; i >= 0; i--)
+			value = (value << 8) | inb(facp->gpe1 + i);
+	}
+	if (facp->gpe0) {
+		size = facp->gpe0_len >> 1;
+		for (i = size - 1; i >= 0; i--)
+			value = (value << 8) | inb(facp->gpe0 + i);
+	}
+	return value;
+}
+
+/*
+ * Set the value of the general-purpose event status register (clear events)
+ */
+static void acpi_write_gpe_status(struct acpi_facp *facp, u32 value)
+{
+	int i, size;
+
+	if (facp->gpe0) {
+		size = facp->gpe0_len >> 1;
+		for (i = 0; i < size; i++) {
+			outb(value & 0xff, facp->gpe0 + i);
+			value >>= 8;
+		}
+	}
+	if (facp->gpe1) {
+		size = facp->gpe1_len >> 1;
+		for (i = 0; i < size; i++) {
+			outb(value & 0xff, facp->gpe1 + i);
+			value >>= 8;
+		}
+	}
+}
+
+/*
+ * Get the value of the general-purpose event enable register
+ */
+static u32 acpi_read_gpe_enable(struct acpi_facp *facp)
+{
+	u32 value = 0;
+	int i, size, offset;
+	
+	offset = facp->gpe0_len >> 1;
+	if (facp->gpe1) {
+		size = facp->gpe1_len >> 1;
+		for (i = size - 1; i >= 0; i--) {
+			value = (value << 8) | inb(facp->gpe1 + offset + i);
+		}
+	}
+	if (facp->gpe0) {
+		size = facp->gpe0_len >> 1;
+		for (i = size - 1; i >= 0; i--)
+			value = (value << 8) | inb(facp->gpe0 + offset + i);
+	}
+	return value;
+}
+
+/*
+ * Set the value of the general-purpose event enable register (enable events)
+ */
+static void acpi_write_gpe_enable(struct acpi_facp *facp, u32 value)
+{
+	int i, offset;
+
+	offset = facp->gpe0_len >> 1;
+	if (facp->gpe0) {
+		for (i = 0; i < offset; i++) {
+			outb(value & 0xff, facp->gpe0 + offset + i);
+			value >>= 8;
+		}
+	}
+	if (facp->gpe1) {
+		offset = facp->gpe1_len >> 1;
+		for (i = 0; i < offset; i++) {
+			outb(value & 0xff, facp->gpe1 + offset + i);
+			value >>= 8;
+		}
+	}
+}
+
+/*
+ * Map an ACPI table into virtual memory
+ */
+static struct acpi_table *__init acpi_map_table(u32 addr)
+{
+	struct acpi_table *table = NULL;
+	if (addr) {
+		// map table header to determine size
+		table = (struct acpi_table *)
+			ioremap((unsigned long) addr,
+				sizeof(struct acpi_table));
+		if (table) {
+			unsigned long table_size = table->length;
+			iounmap(table);
+			// remap entire table
+			table = (struct acpi_table *)
+				ioremap((unsigned long) addr, table_size);
+		}
+
+		if (!table) {
+			/* ioremap is a pain, it returns NULL if the
+			 * table starts within mapped physical memory.
+			 * Hopefully, no table straddles a mapped/unmapped
+			 * physical memory boundary, ugh
+			 */
+			table = (struct acpi_table*) phys_to_virt(addr);
+		}
+	}
+	return table;
+}
+
+/*
+ * Unmap an ACPI table from virtual memory
+ */
+static void acpi_unmap_table(struct acpi_table *table)
+{
+	// iounmap ignores addresses within physical memory
+	if (table)
+		iounmap(table);
+}
+
+/*
+ * Locate and map ACPI tables
+ */
+static int __init acpi_find_tables(void)
+{
+	struct acpi_rsdp *rsdp;
+	struct acpi_table *rsdt;
+	u32 *rsdt_entry;
+	int rsdt_entry_count;
+	unsigned long i;
+
+	// search BIOS memory for RSDP
+	for (i = ACPI_BIOS_ROM_BASE; i < ACPI_BIOS_ROM_END; i += 16) {
+		rsdp = (struct acpi_rsdp *) phys_to_virt(i);
+		if (rsdp->signature[0] == ACPI_RSDP1_SIG
+		    && rsdp->signature[1] == ACPI_RSDP2_SIG) {
+			char oem[7];
+			int j;
+
+			// strip trailing space and print OEM identifier
+			memcpy(oem, rsdp->oem, 6);
+			oem[6] = '\0';
+			for (j = 5;
+			     j > 0 && (oem[j] == '\0' || oem[j] == ' ');
+			     j--) {
+				oem[j] = '\0';
+			}
+			printk(KERN_INFO "ACPI: \"%s\" found at 0x%p\n",
+			       oem, (void *) i);
+
+			break;
+		}
+	}
+	if (i >= ACPI_BIOS_ROM_END)
+		return -ENODEV;
+
+	// fetch RSDT from RSDP
+	rsdt = acpi_map_table(rsdp->rsdt);
+	if (!rsdt) {
+		printk(KERN_ERR "ACPI: missing RSDT at 0x%p\n",
+		       (void*) rsdp->rsdt);
+		return -ENODEV;
+	}
+	else if (rsdt->signature != ACPI_RSDT_SIG) {
+		printk(KERN_ERR "ACPI: bad RSDT at 0x%p (%08x)\n",
+		       (void*) rsdp->rsdt, (unsigned) rsdt->signature);
+		acpi_unmap_table(rsdt);
+		return -ENODEV;
+	}
+	// search RSDT for FACP
+	acpi_facp = NULL;
+	rsdt_entry = (u32 *) (rsdt + 1);
+	rsdt_entry_count = (int) ((rsdt->length - sizeof(*rsdt)) >> 2);
+	while (rsdt_entry_count) {
+		struct acpi_table *dt = acpi_map_table(*rsdt_entry);
+		if (dt && dt->signature == ACPI_FACP_SIG) {
+			acpi_facp = (struct acpi_facp*) dt;
+			acpi_facp_addr = *rsdt_entry;
+			acpi_dsdt_addr = acpi_facp->dsdt;
+
+			// map FACS if it exists
+			if (acpi_facp->facs) {
+				dt = acpi_map_table(acpi_facp->facs);
+				if (dt && dt->signature == ACPI_FACS_SIG) {
+					acpi_facs = (struct acpi_facs*) dt;
+				}
+				else {
+					acpi_unmap_table(dt);
+				}
+			}
+		}
+		else {
+			acpi_unmap_table(dt);
+		}
+		rsdt_entry++;
+		rsdt_entry_count--;
+	}
+
+	acpi_unmap_table(rsdt);
+
+	if (!acpi_facp) {
+		printk(KERN_ERR "ACPI: missing FACP\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+/*
+ * Unmap or destroy ACPI tables
+ */
+static void acpi_destroy_tables(void)
+{
+	if (!acpi_fake_facp)
+		acpi_unmap_table((struct acpi_table*) acpi_facp);
+	else
+		kfree(acpi_facp);
+	acpi_unmap_table((struct acpi_table*) acpi_facs);
+}
+
+/*
+ * Locate PIIX4 device and create a fake FACP
+ */
+static int __init acpi_find_piix4(void)
+{
+	struct pci_dev *dev;
+	u32 base;
+	u16 cmd;
+	u8 pmregmisc;
+
+	dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+			      PCI_DEVICE_ID_INTEL_82371AB_3,
+			      NULL);
+	if (!dev)
+		return -ENODEV;
+	
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	if (!(cmd & PCI_COMMAND_IO))
+		return -ENODEV;
+	
+	pci_read_config_byte(dev, ACPI_PIIX4_PMREGMISC, &pmregmisc);
+	if (!(pmregmisc & ACPI_PIIX4_PMIOSE))
+		return -ENODEV;
+	
+	pci_read_config_dword(dev, 0x40, &base);
+	if (!(base & PCI_BASE_ADDRESS_SPACE_IO))
+		return -ENODEV;
+	
+	base &= PCI_BASE_ADDRESS_IO_MASK;
+	if (!base)
+		return -ENODEV;
+
+	printk(KERN_INFO "ACPI: found PIIX4 at 0x%04x\n", base);
+
+	acpi_facp = kmalloc(sizeof(struct acpi_facp), GFP_KERNEL);
+	if (!acpi_facp)
+		return -ENOMEM;
+
+	acpi_fake_facp = 1;
+	memset(acpi_facp, 0, sizeof(struct acpi_facp));
+	acpi_facp->int_model = ACPI_PIIX4_INT_MODEL;
+	acpi_facp->sci_int = ACPI_PIIX4_SCI_INT;
+	acpi_facp->smi_cmd = ACPI_PIIX4_SMI_CMD;
+	acpi_facp->acpi_enable = ACPI_PIIX4_ACPI_ENABLE;
+	acpi_facp->acpi_disable = ACPI_PIIX4_ACPI_DISABLE;
+	acpi_facp->s4bios_req = ACPI_PIIX4_S4BIOS_REQ;
+	acpi_facp->pm1a_evt = base + ACPI_PIIX4_PM1_EVT;
+	acpi_facp->pm1a_cnt = base + ACPI_PIIX4_PM1_CNT;
+	acpi_facp->pm2_cnt = ACPI_PIIX4_PM2_CNT;
+	acpi_facp->pm_tmr = base + ACPI_PIIX4_PM_TMR;
+	acpi_facp->gpe0 = base + ACPI_PIIX4_GPE0;
+	acpi_facp->pm1_evt_len = ACPI_PIIX4_PM1_EVT_LEN;
+	acpi_facp->pm1_cnt_len = ACPI_PIIX4_PM1_CNT_LEN;
+	acpi_facp->pm2_cnt_len = ACPI_PIIX4_PM2_CNT_LEN;
+	acpi_facp->pm_tm_len = ACPI_PIIX4_PM_TM_LEN;
+	acpi_facp->gpe0_len = ACPI_PIIX4_GPE0_LEN;
+	acpi_facp->p_lvl2_lat = (__u16) ACPI_INFINITE_LAT;
+	acpi_facp->p_lvl3_lat = (__u16) ACPI_INFINITE_LAT;
+
+	acpi_facp_addr = virt_to_phys(acpi_facp);
+	acpi_dsdt_addr = 0;
+
+	acpi_p_blk = base + ACPI_PIIX4_P_BLK;
+
+	return 0;
+}
+
+/*
+ * Handle an ACPI SCI (fixed or general purpose event)
+ */
+static void acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u32 pm1_status, gpe_status, gpe_level, gpe_edge;
+	unsigned long flags;
+
+	// detect and clear fixed events
+	pm1_status = (acpi_read_pm1_status(acpi_facp)
+		      & acpi_read_pm1_enable(acpi_facp));
+	acpi_write_pm1_status(acpi_facp, pm1_status);
+	
+	// detect and handle general-purpose events
+	gpe_status = (acpi_read_gpe_status(acpi_facp)
+		      & acpi_read_gpe_enable(acpi_facp));
+	gpe_level = gpe_status & acpi_gpe_level;
+	if (gpe_level) {
+		// disable level-triggered events (re-enabled after handling)
+		acpi_write_gpe_enable(
+			acpi_facp,
+			acpi_read_gpe_enable(acpi_facp) & ~gpe_level);
+	}
+	gpe_edge = gpe_status & ~gpe_level;
+	if (gpe_edge) {
+		// clear edge-triggered events
+		while (acpi_read_gpe_status(acpi_facp) & gpe_edge)
+			acpi_write_gpe_status(acpi_facp, gpe_edge);
+	}
+
+	// notify process waiting on /dev/acpi
+	spin_lock_irqsave(&acpi_event_lock, flags);
+	acpi_pm1_status |= pm1_status;
+	acpi_gpe_status |= gpe_status;
+	spin_unlock_irqrestore(&acpi_event_lock, flags);
+	acpi_event_state = acpi_sleep_state;
+	wake_up_interruptible(&acpi_event_wait);
+}
+
+/*
+ * Is ACPI enabled or not?
+ */
+static inline int acpi_is_enabled(struct acpi_facp *facp)
+{
+	return ((acpi_read_pm1_control(facp) & ACPI_SCI_EN) ? 1:0);
+}
+
+/*
+ * Enable SCI
+ */
+static int acpi_enable(struct acpi_facp *facp)
+{
+	if (facp->smi_cmd)
+		outb(facp->acpi_enable, facp->smi_cmd);
+	return (acpi_is_enabled(facp) ? 0:-1);
+}
+
+/*
+ * Disable SCI
+ */
+static int acpi_disable(struct acpi_facp *facp)
+{
+	// disable and clear any pending events
+	acpi_write_gpe_enable(facp, 0);
+	while (acpi_read_gpe_status(facp))
+		acpi_write_gpe_status(facp, acpi_read_gpe_status(facp));
+	acpi_write_pm1_enable(facp, 0);
+	acpi_write_pm1_status(facp, acpi_read_pm1_status(facp));
+
+	/* writing acpi_disable to smi_cmd would be appropriate
+	 * here but this causes a nasty crash on many systems
+	 */
+
+	return 0;
+}
+
+static inline int bm_activity(void)
+{
+	return 0 && acpi_read_pm1_status(acpi_facp) & ACPI_BM;
+}
+
+static inline void clear_bm_activity(void)
+{
+	acpi_write_pm1_status(acpi_facp, ACPI_BM);
+}
+
+static void sleep_on_busmaster(void)
+{
+	u32 pm1_cntr = acpi_read_pm1_control(acpi_facp);
+	if (pm1_cntr & ACPI_BM_RLD) {
+		pm1_cntr &= ~ACPI_BM_RLD;
+		acpi_write_pm1_control(acpi_facp, pm1_cntr);
+	}
+}
+
+static void wake_on_busmaster(void)
+{
+	u32 pm1_cntr = acpi_read_pm1_control(acpi_facp);
+	if (!(pm1_cntr & ACPI_BM_RLD)) {
+		pm1_cntr |= ACPI_BM_RLD;
+		acpi_write_pm1_control(acpi_facp, pm1_cntr);
+	}
+	clear_bm_activity();
+}
+
+/*
+ * Idle loop (uniprocessor only)
+ */
+static void acpi_idle_handler(void)
+{
+	static int sleep_level = 1;
+
+	if (!acpi_facp->pm_tmr || !acpi_p_blk)
+		goto not_initialized;
+
+	/*
+	 * start from the previous sleep level..
+	 */
+	if (sleep_level == 1)
+		goto sleep1;
+	if (sleep_level == 2 || bm_activity())
+		goto sleep2;
+sleep3:
+	sleep_level = 3;
+	if (!acpi_p_lvl3_tested) {
+		printk("ACPI C3 works\n");
+		acpi_p_lvl3_tested = 1;
+	}
+	wake_on_busmaster();
+	if (acpi_facp->pm2_cnt)
+		goto sleep3_with_arbiter;
+
+	for (;;) {
+		unsigned long time;
+		__cli();
+		if (current->need_resched)
+			goto out;
+		time = inl(acpi_facp->pm_tmr);
+		inb(acpi_p_blk + ACPI_P_LVL3);
+		time = inl(acpi_facp->pm_tmr) - time;
+		__sti();
+		if (time > acpi_p_lvl3_lat || bm_activity())
+			goto sleep2;
+	}
+
+sleep3_with_arbiter:
+	for (;;) {
+		unsigned long time;
+		unsigned int pm2_cntr = acpi_facp->pm2_cnt;
+		__cli();
+		if (current->need_resched)
+			goto out;
+		time = inl(acpi_facp->pm_tmr);
+		outb(inb(pm2_cntr) | ACPI_ARB_DIS, pm2_cntr);
+		inb(acpi_p_blk + ACPI_P_LVL3);
+		outb(inb(pm2_cntr) & ~ACPI_ARB_DIS, pm2_cntr);
+		time = inl(acpi_facp->pm_tmr) - time;
+		__sti();
+		if (time > acpi_p_lvl3_lat || bm_activity())
+			goto sleep2;
+	}
+
+sleep2:
+	sleep_level = 2;
+	if (!acpi_p_lvl2_tested) {
+		printk("ACPI C2 works\n");
+		acpi_p_lvl2_tested = 1;
+	}
+	wake_on_busmaster();	/* Required to track BM activity.. */
+	for (;;) {
+		unsigned long time;
+		__cli();
+		if (current->need_resched)
+			goto out;
+		time = inl(acpi_facp->pm_tmr);
+		inb(acpi_p_blk + ACPI_P_LVL2);
+		time = inl(acpi_facp->pm_tmr) - time;
+		__sti();
+		if (time > acpi_p_lvl2_lat)
+			goto sleep1;
+		if (bm_activity()) {
+			clear_bm_activity();
+			continue;
+		}
+		if (time < acpi_enter_lvl3_lat)
+			goto sleep3;
+	}
+
+sleep1:
+	sleep_level = 1;
+	sleep_on_busmaster();
+	for (;;) {
+		unsigned long time;
+		__cli();
+		if (current->need_resched)
+			goto out;
+		time = inl(acpi_facp->pm_tmr);
+		__asm__ __volatile__("sti ; hlt": : :"memory");
+		time = inl(acpi_facp->pm_tmr) - time;
+		if (time < acpi_enter_lvl2_lat)
+			goto sleep2;
+	}
+
+not_initialized:
+	for (;;) {
+		__cli();
+		if (current->need_resched)
+			goto out;
+		__asm__ __volatile__("sti ; hlt": : :"memory");
+	}
+
+out:
+	__sti();
+}
+
+/*
+ * Put all devices into specified D-state
+ */
+static int acpi_enter_dx(acpi_dstate_t state)
+{
+	int status = 0;
+	struct list_head *i = acpi_devs.next;
+
+	while (i != &acpi_devs)	{
+		struct acpi_dev *dev = list_entry(i, struct acpi_dev, entry);
+		if (dev->state != state) {
+			int dev_status = 0;
+			if (dev->info.transition)
+				dev_status = dev->info.transition(dev, state);
+			if (!dev_status) {
+				// put hardware into D-state
+				dev->state = state;
+			}
+			if (dev_status)
+				status = dev_status;
+		}
+
+		i = i->next;
+	}
+
+	return status;
+}
+
+/*
+ * Update system time from real-time clock
+ */
+static void acpi_update_clock(void)
+{
+	if (acpi_sleep_start) {
+		unsigned long delta;
+		struct timeval tv;
+		
+		delta = get_cmos_time() - acpi_sleep_start;
+		do_gettimeofday(&tv);
+		tv.tv_sec += delta;
+		do_settimeofday(&tv);
+		
+		acpi_sleep_start = 0;
+	}
+}
+
+
+/*
+ * Enter system sleep state
+ */
+static void acpi_enter_sx(acpi_sstate_t state)
+{
+	unsigned long slp_typ = acpi_slp_typ[(int) state];
+	if (slp_typ != ACPI_SLP_TYP_DISABLED) {
+		u16 typa, typb, value;
+
+		// bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb
+		typa = (slp_typ >> 8) & 0xff;
+		typb = slp_typ & 0xff;
+
+		typa = ((typa << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK);
+		typb = ((typb << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK);
+
+		if (state != ACPI_S0) {
+			acpi_sleep_start = get_cmos_time();
+			acpi_enter_dx(ACPI_D3);
+			acpi_sleep_state = state;
+		}
+
+		// clear wake status
+		acpi_write_pm1_status(acpi_facp, ACPI_WAK);
+
+		// set SLP_TYPa/b and SLP_EN
+		if (acpi_facp->pm1a_cnt) {
+			value = inw(acpi_facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK;
+			outw(value | typa | ACPI_SLP_EN, acpi_facp->pm1a_cnt);
+		}
+		if (acpi_facp->pm1b_cnt) {
+			value = inw(acpi_facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK;
+			outw(value | typb | ACPI_SLP_EN, acpi_facp->pm1b_cnt);
+		}
+
+		if (state == ACPI_S0) {
+			acpi_sleep_state = state;
+			acpi_enter_dx(ACPI_D0);
+			acpi_sleep_start = 0;
+		}
+		else if (state == ACPI_S1) {
+			// wait until S1 is entered
+			while (!(acpi_read_pm1_status(acpi_facp) & ACPI_WAK)) ;
+			// finished sleeping, update system time
+			acpi_update_clock();
+		}
+	}
+}
+
+/*
+ * Enter soft-off (S5)
+ */
+static void acpi_power_off_handler(void)
+{
+	acpi_enter_sx(ACPI_S5);
+}
+
+/*
+ * Claim ACPI I/O ports
+ */
+static int acpi_claim_ioports(struct acpi_facp *facp)
+{
+	// we don't get a guarantee of contiguity for any of the ACPI registers
+	if (facp->pm1a_evt)
+		request_region(facp->pm1a_evt, facp->pm1_evt_len, "acpi");
+	if (facp->pm1b_evt)
+		request_region(facp->pm1b_evt, facp->pm1_evt_len, "acpi");
+	if (facp->pm1a_cnt)
+		request_region(facp->pm1a_cnt, facp->pm1_cnt_len, "acpi");
+	if (facp->pm1b_cnt)
+		request_region(facp->pm1b_cnt, facp->pm1_cnt_len, "acpi");
+	if (facp->pm_tmr)
+		request_region(facp->pm_tmr, facp->pm_tm_len, "acpi");
+	if (facp->gpe0)
+		request_region(facp->gpe0, facp->gpe0_len, "acpi");
+	if (facp->gpe1)
+		request_region(facp->gpe1, facp->gpe1_len, "acpi");
+
+	return 0;
+}
+
+/*
+ * Free ACPI I/O ports
+ */
+static int acpi_release_ioports(struct acpi_facp *facp)
+{
+	// we don't get a guarantee of contiguity for any of the ACPI registers
+	if (facp->pm1a_evt)
+		release_region(facp->pm1a_evt, facp->pm1_evt_len);
+	if (facp->pm1b_evt)
+		release_region(facp->pm1b_evt, facp->pm1_evt_len);
+	if (facp->pm1a_cnt)
+		release_region(facp->pm1a_cnt, facp->pm1_cnt_len);
+	if (facp->pm1b_cnt)
+		release_region(facp->pm1b_cnt, facp->pm1_cnt_len);
+	if (facp->pm_tmr)
+		release_region(facp->pm_tmr, facp->pm_tm_len);
+	if (facp->gpe0)
+		release_region(facp->gpe0, facp->gpe0_len);
+	if (facp->gpe1)
+		release_region(facp->gpe1, facp->gpe1_len);
+
+	return 0;
+}
+
+/*
+ * Examine/modify value
+ */
+static int acpi_do_ulong(ctl_table *ctl,
+			 int write,
+			 struct file *file,
+			 void *buffer,
+			 size_t *len)
+{
+	char str[2 * sizeof(unsigned long) + 4], *strend;
+	unsigned long val;
+	int size;
+
+	if (!write) {
+		if (file->f_pos) {
+			*len = 0;
+			return 0;
+		}
+
+		val = *(unsigned long*) ctl->data;
+		size = sprintf(str, "0x%08lx\n", val);
+		if (*len >= size) {
+			copy_to_user(buffer, str, size);
+			*len = size;
+		}
+		else
+			*len = 0;
+	}
+	else {
+		size = sizeof(str) - 1;
+		if (size > *len)
+			size = *len;
+		copy_from_user(str, buffer, size);
+		str[size] = '\0';
+		val = simple_strtoul(str, &strend, 0);
+		if (strend == str)
+			return -EINVAL;
+		*(unsigned long*) ctl->data = val;
+	}
+
+	file->f_pos += *len;
+	return 0;
+}
+
+/*
+ * Examine/modify event register
+ */
+static int acpi_do_event_reg(ctl_table *ctl,
+			     int write,
+			     struct file *file,
+			     void *buffer,
+			     size_t *len)
+{
+	char str[2 * sizeof(u32) + 4], *strend;
+	u32 val, enabling;
+	int size;
+
+	if (!write) {
+		if (file->f_pos) {
+			*len = 0;
+			return 0;
+		}
+
+		val = 0;
+		switch (ctl->ctl_name) {
+		case ACPI_PM1_ENABLE:
+			val = acpi_read_pm1_enable(acpi_facp);
+			break;
+		case ACPI_GPE_ENABLE:
+			val = acpi_read_gpe_enable(acpi_facp);
+			break;
+		case ACPI_GPE_LEVEL:
+			val = acpi_gpe_level;
+			break;
+		}
+		
+		size = sprintf(str, "0x%08x\n", val);
+		if (*len >= size) {
+			copy_to_user(buffer, str, size);
+			*len = size;
+		}
+		else
+			*len = 0;
+	}
+	else
+	{
+		// fetch user value
+		size = sizeof(str) - 1;
+		if (size > *len)
+			size = *len;
+		copy_from_user(str, buffer, size);
+		str[size] = '\0';
+		val = (u32) simple_strtoul(str, &strend, 0);
+		if (strend == str)
+			return -EINVAL;
+
+		// store value in register
+		switch (ctl->ctl_name) {
+		case ACPI_PM1_ENABLE:
+			// clear previously disabled events
+			enabling = (val
+				    & ~acpi_read_pm1_enable(acpi_facp));
+			acpi_write_pm1_status(acpi_facp, enabling);
+			
+			if (val) {
+				// enable ACPI unless it is already
+				if (!acpi_is_enabled(acpi_facp))
+					acpi_enable(acpi_facp);
+			}
+			else if (!acpi_read_gpe_enable(acpi_facp)) {
+				// disable ACPI unless it is already
+				if (acpi_is_enabled(acpi_facp))
+					acpi_disable(acpi_facp);
+			}
+			
+			acpi_write_pm1_enable(acpi_facp, val);
+			break;
+		case ACPI_GPE_ENABLE:
+			// clear previously disabled events
+			enabling = (val
+				    & ~acpi_read_gpe_enable(acpi_facp));
+			while (acpi_read_gpe_status(acpi_facp) & enabling)
+				acpi_write_gpe_status(acpi_facp, enabling);
+			
+			if (val) {
+				// enable ACPI unless it is already
+				if (!acpi_is_enabled(acpi_facp))
+					acpi_enable(acpi_facp);
+			}
+			else if (!acpi_read_pm1_enable(acpi_facp)) {
+				// disable ACPI unless it is already
+				if (acpi_is_enabled(acpi_facp))
+					acpi_disable(acpi_facp);
+			}
+			
+			acpi_write_gpe_enable(acpi_facp, val);
+			break;
+		case ACPI_GPE_LEVEL:
+			acpi_gpe_level = val;
+			break;
+		}
+	}
+
+	file->f_pos += *len;
+	return 0;
+}
+
+/*
+ * Wait for next event
+ */
+static int acpi_do_event(ctl_table *ctl,
+			 int write,
+			 struct file *file,
+			 void *buffer,
+			 size_t *len)
+{
+	u32 pm1_status = 0, gpe_status = 0;
+	acpi_sstate_t event_state = 0;
+	char str[27];
+	int size;
+
+	if (write)
+		return -EPERM;
+	if (*len < sizeof(str)) {
+		*len = 0;
+		return 0;
+	}
+
+	for (;;) {
+		unsigned long flags;
+		
+		// we need an atomic exchange here
+		spin_lock_irqsave(&acpi_event_lock, flags);
+		pm1_status = acpi_pm1_status;
+		acpi_pm1_status = 0;
+		gpe_status = acpi_gpe_status;
+		acpi_gpe_status = 0;
+		spin_unlock_irqrestore(&acpi_event_lock, flags);
+		event_state = acpi_event_state;
+		
+		if (pm1_status || gpe_status)
+			break;
+		
+		// wait for an event to arrive
+		interruptible_sleep_on(&acpi_event_wait);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+	}
+
+	size = sprintf(str, "0x%08x 0x%08x 0x%01x\n",
+		       pm1_status,
+		       gpe_status,
+		       event_state);
+	copy_to_user(buffer, str, size);
+	*len = size;
+	file->f_pos += size;
+
+	return 0;
+}
+
+/*
+ * Enter system sleep state
+ */
+static int acpi_do_sleep(ctl_table *ctl,
+			 int write,
+			 struct file *file,
+			 void *buffer,
+			 size_t *len)
+{
+	if (!write) {
+		if (file->f_pos) {
+			*len = 0;
+			return 0;
+		}
+	}
+	else
+	{
+		acpi_enter_sx(ACPI_S1);
+		acpi_enter_sx(ACPI_S0);
+	}
+	file->f_pos += *len;
+	return 0;
+}
+
+/*
+ * Initialize and enable ACPI
+ */
+static int __init acpi_init(void)
+{
+	int pid;
+
+	if (acpi_find_tables() && acpi_find_piix4()) {
+		// no ACPI tables and not PIIX4
+		return -ENODEV;
+	}
+
+    	/*
+    	 * Are the latencies in uS or in ticks in the tables? 
+    	 * Maybe this should do ACPI_uS_TO_TMR_TICKS?
+    	 *
+    	 * Whatever. Internally we always keep them in timer
+    	 * ticks, which is simpler and more consistent (what is
+    	 * an uS to us?). Besides, that gives people more
+    	 * control in the /proc interfaces.
+    	 */
+	if (acpi_facp->p_lvl2_lat
+	    && acpi_facp->p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT) {
+		acpi_p_lvl2_lat = acpi_facp->p_lvl2_lat;
+		acpi_enter_lvl2_lat = ACPI_TMR_HZ / 1000;
+	}
+	if (acpi_facp->p_lvl3_lat
+	    && acpi_facp->p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT) {
+		acpi_p_lvl3_lat = acpi_facp->p_lvl3_lat;
+		acpi_enter_lvl3_lat = acpi_facp->p_lvl3_lat * 5;
+	}
+
+	if (acpi_facp->sci_int
+	    && request_irq(acpi_facp->sci_int,
+			   acpi_irq,
+			   SA_INTERRUPT | SA_SHIRQ,
+			   "acpi",
+			   acpi_facp)) {
+		printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n",
+		       acpi_facp->sci_int);
+		acpi_destroy_tables();
+		return -ENODEV;
+	}
+
+	acpi_claim_ioports(acpi_facp);
+	acpi_sysctl = register_sysctl_table(acpi_dir_table, 1);
+
+	pid = kernel_thread(acpi_control_thread,
+			    NULL,
+			    CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+
+	acpi_power_off = acpi_power_off_handler;
+
+	/*
+	 * Set up the ACPI idle function. Note that we can't really
+	 * do this with multiple CPU's, we'd need a per-CPU ACPI
+	 * device..
+	 */
+#ifdef __SMP__
+	if (smp_num_cpus > 1)
+		return 0;
+#endif
+
+	if (acpi_facp->pm_tmr)
+		acpi_idle = acpi_idle_handler;
+
+	return 0;
+}
+
+/*
+ * Disable and deinitialize ACPI
+ */
+static void __exit acpi_exit(void)
+{
+	acpi_idle = NULL;
+	acpi_power_off = NULL;
+
+	unregister_sysctl_table(acpi_sysctl);
+	acpi_disable(acpi_facp);
+	acpi_release_ioports(acpi_facp);
+
+	if (acpi_facp->sci_int)
+		free_irq(acpi_facp->sci_int, acpi_facp);
+
+	acpi_destroy_tables();
+}
+
+/*
+ * Register a device with the ACPI subsystem
+ */
+struct acpi_dev* acpi_register(struct acpi_dev_info *info, unsigned long adr)
+{
+	struct acpi_dev *dev = NULL;
+	if (info) {
+		dev = kmalloc(sizeof(struct acpi_dev), GFP_KERNEL);
+		if (dev) {
+			unsigned long flags;
+			
+			memset(dev, 0, sizeof(*dev));
+			memcpy(&dev->info, info, sizeof(dev->info));
+			dev->adr = adr;
+			
+			spin_lock_irqsave(&acpi_devs_lock, flags);
+			list_add(&dev->entry, &acpi_devs);
+			spin_unlock_irqrestore(&acpi_devs_lock, flags);
+		}
+	}
+	return dev;
+}
+
+/*
+ * Unregister a device with ACPI
+ */
+void acpi_unregister(struct acpi_dev *dev)
+{
+	if (dev) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&acpi_devs_lock, flags);
+		list_del(&dev->entry);
+		spin_unlock_irqrestore(&acpi_devs_lock, flags);
+
+		kfree(dev);
+	}
+}
+
+/*
+ * Wake up a device
+ */
+void acpi_wakeup(struct acpi_dev *dev)
+{
+	// run _PS0 or tell parent bus to wake device up
+}
+
+/*
+ * Manage idle devices
+ */
+static int acpi_control_thread(void *context)
+{
+	exit_mm(current);
+	exit_files(current);
+	strcpy(current->comm, "acpi");
+	
+	for(;;) {
+		interruptible_sleep_on(&acpi_control_wait);
+		if (signal_pending(current))
+			break;
+
+		// find all idle devices and set idle timer
+	}
+
+	return 0;
+}
+
+__initcall(acpi_init);
+
+/*
+ * Module visible symbols
+ */
+EXPORT_SYMBOL(acpi_control_wait);
+EXPORT_SYMBOL(acpi_register);
+EXPORT_SYMBOL(acpi_unregister);
+EXPORT_SYMBOL(acpi_wakeup);
diff -u --recursive --new-file v2.3.34/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.3.34/linux/arch/i386/kernel/irq.c	Tue Dec  7 09:32:40 1999
+++ linux/arch/i386/kernel/irq.c	Thu Dec 23 14:32:16 1999
@@ -772,6 +772,41 @@
 	return 0x12345678;
 }
 
+/*
+ * Return a mask of triggered interrupts (this
+ * can handle only legacy ISA interrupts).
+ */
+unsigned int probe_irq_mask(unsigned long unused)
+{
+	int i;
+	unsigned int mask;
+
+	if (unused != 0x12345678)
+		printk("Bad IRQ probe from %lx\n", (&unused)[-1]);
+
+	mask = 0;
+	spin_lock_irq(&irq_controller_lock);
+	for (i = 0; i < 16; i++) {
+		unsigned int status = irq_desc[i].status;
+
+		if (!(status & IRQ_AUTODETECT))
+			continue;
+
+		if (!(status & IRQ_WAITING))
+			mask |= 1 << i;
+
+		irq_desc[i].status = status & ~IRQ_AUTODETECT;
+		irq_desc[i].handler->shutdown(i);
+	}
+	spin_unlock_irq(&irq_controller_lock);
+
+	return mask;
+}
+
+/*
+ * Return the one interrupt that triggered (this can
+ * handle any interrupt source)
+ */
 int probe_irq_off(unsigned long unused)
 {
 	int i, irq_found, nr_irqs;
diff -u --recursive --new-file v2.3.34/linux/arch/i386/kernel/pci-i386.c linux/arch/i386/kernel/pci-i386.c
--- v2.3.34/linux/arch/i386/kernel/pci-i386.c	Tue Dec  7 09:32:40 1999
+++ linux/arch/i386/kernel/pci-i386.c	Tue Dec 21 12:07:32 1999
@@ -102,7 +102,7 @@
  * Expects start=0, end=size-1, flags=resource type.
  */
 
-static int __init pcibios_assign_resource(struct pci_dev *dev, int i)
+int pci_assign_resource(struct pci_dev *dev, int i)
 {
 	struct resource *r = &dev->resource[i];
 	struct resource *pr = pci_find_parent_resource(dev, r);
@@ -272,7 +272,7 @@
 				 *  the BIOS forgot to do so or because we have decided the old
 				 *  address was unusable for some reason.
 				 */
-				pcibios_assign_resource(dev, idx);
+				pci_assign_resource(dev, idx);
 			}
 		}
 		if (pci_probe & PCI_ASSIGN_ROMS) {
@@ -280,7 +280,7 @@
 			r->end -= r->start;
 			r->start = 0;
 			if (r->end)
-				pcibios_assign_resource(dev, PCI_ROM_RESOURCE);
+				pci_assign_resource(dev, PCI_ROM_RESOURCE);
 		}
 	}
 }
diff -u --recursive --new-file v2.3.34/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.3.34/linux/arch/i386/kernel/setup.c	Mon Dec 20 18:48:21 1999
+++ linux/arch/i386/kernel/setup.c	Fri Dec 24 13:06:05 1999
@@ -709,7 +709,7 @@
 #endif
 
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (LOADER_TYPE) {
+	if (LOADER_TYPE && INITRD_START) {
 		if (INITRD_START + INITRD_SIZE < (max_low_pfn << PAGE_SHIFT)) {
 			reserve_bootmem(INITRD_START, INITRD_SIZE);
 			initrd_start =
diff -u --recursive --new-file v2.3.34/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.3.34/linux/arch/ppc/config.in	Wed Dec  8 14:11:25 1999
+++ linux/arch/ppc/config.in	Mon Dec 27 14:10:20 1999
@@ -85,12 +85,16 @@
 
 if [ "$CONFIG_APUS" = "y" ]; then
   define_bool CONFIG_PCI n
-else if [ "$CONFIG_OAK" = "y" ]; then
+fi
+if [ "$CONFIG_OAK" = "y" ]; then
   define_bool CONFIG_PCI n
-else if [ "$CONFIG_8xx" = "y" ]; then
+fi
+if [ "$CONFIG_8xx" = "y" ]; then
     bool 'QSpan PCI' CONFIG_PCI
 else
+  if [ "$CONFIG_APUS" != "y" ]; then
     define_bool CONFIG_PCI y
+  fi
 fi
 
 bool 'Networking support' CONFIG_NET
diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.3.34/linux/arch/ppc/kernel/chrp_setup.c	Thu Nov 11 20:11:32 1999
+++ linux/arch/ppc/kernel/chrp_setup.c	Mon Dec 27 14:10:20 1999
@@ -249,7 +249,7 @@
 	else
 #endif
 		ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
-	
+sprintf(cmd_line, "console=ttyS0,9600 console=tty0");
 	printk("Boot arguments: %s\n", cmd_line);
 	
 	request_region(0x20,0x20,"pic1");
@@ -391,7 +391,7 @@
 	 * openpic irq.  So we just check to make sure the controller
 	 * is an openpic and if it is then eoi
 	 *
-	 * We do it this way since our irq_desc[irq].ctl can change
+	 * We do it this way since our irq_desc[irq].handler can change
 	 * with RTL and no longer be open_pic -- Cort
 	 */
 	if ( irq >= open_pic.irq_offset)
@@ -413,10 +413,10 @@
 	}
 	open_pic.irq_offset = 16;
 	for ( i = 16 ; i < NR_IRQS ; i++ )
-		irq_desc[i].ctl = &open_pic;
+		irq_desc[i].handler = &open_pic;
 	openpic_init(1);
 	for ( i = 0 ; i < 16  ; i++ )
-		irq_desc[i].ctl = &i8259_pic;
+		irq_desc[i].handler = &i8259_pic;
 	i8259_init();
 #ifdef CONFIG_XMON
 	request_irq(openpic_to_irq(HYDRA_INT_ADB_NMI),
diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/gemini_setup.c linux/arch/ppc/kernel/gemini_setup.c
--- v2.3.34/linux/arch/ppc/kernel/gemini_setup.c	Mon Dec 20 18:48:21 1999
+++ linux/arch/ppc/kernel/gemini_setup.c	Mon Dec 27 14:10:20 1999
@@ -332,7 +332,7 @@
 	/* gemini has no 8259 */
 	open_pic.irq_offset = 0;
 	for( i=0; i < NR_IRQS; i++ ) 
-		irq_desc[i].ctl = &open_pic;
+		irq_desc[i].handler = &open_pic;
 	openpic_init(1);
 #ifdef __SMP__
  	request_irq(OPENPIC_VEC_IPI, openpic_ipi_action,
@@ -512,7 +512,7 @@
 	 * openpic irq.  So we just check to make sure the controller
 	 * is an openpic and if it is then eoi
 	 *
-	 * We do it this way since our irq_desc[irq].ctl can change
+	 * We do it this way since our irq_desc[irq].handler can change
 	 * with RTL and no longer be open_pic -- Cort
 	 */
 	if ( irq >= open_pic.irq_offset)
diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.3.34/linux/arch/ppc/kernel/irq.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/ppc/kernel/irq.c	Mon Dec 27 14:10:20 1999
@@ -44,6 +44,7 @@
 #include <linux/openpic.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
 
 #include <asm/bitops.h>
 #include <asm/hydra.h>
@@ -71,7 +72,7 @@
 
 #define NR_MASK_WORDS	((NR_IRQS + 31) / 32)
 
-struct irqdesc irq_desc[NR_IRQS] = {{0, 0}, };
+irq_desc_t irq_desc[NR_IRQS];
 int ppc_spurious_interrupts = 0;
 unsigned int ppc_local_bh_count[NR_CPUS];
 unsigned int ppc_local_irq_count[NR_CPUS];
@@ -244,8 +245,8 @@
 #else		
 		len += sprintf(buf+len, "%10u ", kstat_irqs(i));
 #endif /* __SMP__ */
-		if ( irq_desc[i].ctl )		
-			len += sprintf(buf+len, " %s ", irq_desc[i].ctl->typename );
+		if ( irq_desc[i].handler )		
+			len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename );
 		else
 			len += sprintf(buf+len, "  None      ");
 		len += sprintf(buf+len, "    %s",action->name);
diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/local_irq.h linux/arch/ppc/kernel/local_irq.h
--- v2.3.34/linux/arch/ppc/kernel/local_irq.h	Sat Oct  9 11:47:50 1999
+++ linux/arch/ppc/kernel/local_irq.h	Mon Dec 27 14:10:20 1999
@@ -4,7 +4,7 @@
 
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
-#include <asm/irq_control.h>
+#include <linux/irq.h>
 
 void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
 
diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c
--- v2.3.34/linux/arch/ppc/kernel/m8xx_setup.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/ppc/kernel/m8xx_setup.c	Mon Dec 27 14:10:20 1999
@@ -278,7 +278,7 @@
 
         ppc8xx_pic.irq_offset = 0;
         for ( i = 0 ; i < NR_SIU_INTS ; i++ )
-                irq_desc[i].ctl = &ppc8xx_pic;
+                irq_desc[i].handler = &ppc8xx_pic;
 	
 	/* We could probably incorporate the CPM into the multilevel
 	 * interrupt structure.
@@ -288,7 +288,7 @@
 
 #if defined(CONFIG_PCI)
         for ( i = NR_SIU_INTS ; i < (NR_SIU_INTS + NR_8259_INTS) ; i++ )
-                irq_desc[i].ctl = &i8259_pic;
+                irq_desc[i].handler = &i8259_pic;
         i8259_pic.irq_offset = NR_SIU_INTS;
         i8259_init();
         request_8xxirq(ISA_BRIDGE_INT, mbx_i8259_action, 0, "8259 cascade", NULL);
diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/mbx_pci.c linux/arch/ppc/kernel/mbx_pci.c
--- v2.3.34/linux/arch/ppc/kernel/mbx_pci.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/ppc/kernel/mbx_pci.c	Wed Dec 31 16:00:00 1969
@@ -1,269 +0,0 @@
-/*
- * MBX pci routines.
- * The MBX uses the QSpan PCI bridge.  The config address register
- * is located 0x500 from the base of the bridge control/status registers.
- * The data register is located at 0x504.
- * This is a two step operation.  First, the address register is written,
- * then the data register is read/written as required.
- * I don't know what to do about interrupts (yet).
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/bios32.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/mbx.h>
-
-
-/*
- * This blows......The MBX uses the Tundra QSpan PCI bridge.  When
- * reading the configuration space, if something does not respond
- * the bus times out and we get a machine check interrupt.  So, the
- * good ol' exception tables come to mind to trap it and return some
- * value.
- *
- * On an error we just return a -1, since that is what the caller wants
- * returned if nothing is present.  I copied this from __get_user_asm,
- * with the only difference of returning -1 instead of EFAULT.
- * There is an associated hack in the machine check trap code.
- *
- * The QSPAN is also a big endian device, that is it makes the PCI
- * look big endian to us.  This presents a problem for the Linux PCI
- * functions, which assume little endian.  For example, we see the
- * first 32-bit word like this:
- *	------------------------
- *	| Device ID | Vendor ID |
- *	------------------------
- * If we read/write as a double word, that's OK.  But in our world,
- * when read as a word, device ID is at location 0, not location 2 as
- * the little endian PCI would believe.  We have to switch bits in
- * the PCI addresses given to us to get the data to/from the correct
- * byte lanes.
- *
- * The QSPAN only supports 4 bits of "slot" in the dev_fn instead of 5.
- * It always forces the MS bit to zero.  Therefore, dev_fn values
- * greater than 128 are returned as "no device found" errors.
- *
- * The QSPAN can only perform long word (32-bit) configuration cycles.
- * The "offset" must have the two LS bits set to zero.  Read operations
- * require we read the entire word and then sort out what should be
- * returned.  Write operations other than long word require that we
- * read the long word, update the proper word or byte, then write the
- * entire long word back.
- *
- * PCI Bridge hack.  We assume (correctly) that bus 0 is the primary
- * PCI bus from the QSPAN.  If we are called with a bus number other
- * than zero, we create a Type 1 configuration access that a downstream
- * PCI bridge will interpret.
- */
-
-#define __get_mbx_pci_config(x, addr, op)		\
-	__asm__ __volatile__(				\
-		"1:	"op" %0,0(%1)\n"		\
-		"	eieio\n"			\
-		"2:\n"					\
-		".section .fixup,\"ax\"\n"		\
-		"3:	li %0,-1\n"			\
-		"	b 2b\n"				\
-		".section __ex_table,\"a\"\n"		\
-		"	.align 2\n"			\
-		"	.long 1b,3b\n"			\
-		".text"					\
-		: "=r"(x) : "r"(addr))
-
-#define QS_CONFIG_ADDR	((volatile uint *)(PCI_CSR_ADDR + 0x500))
-#define QS_CONFIG_DATA	((volatile uint *)(PCI_CSR_ADDR + 0x504))
-
-#define mk_config_addr(bus, dev, offset) \
-	(((bus)<<16) | ((dev)<<8) | (offset & 0xfc))
-
-#define mk_config_type1(bus, dev, offset) \
-	mk_config_addr(bus, dev, offset) | 1;
-
-int mbx_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
-				  unsigned char offset, unsigned char *val)
-{
-	uint	temp;
-	u_char	*cp;
-
-	if ((bus > 7) || (dev_fn > 127)) {
-		*val = 0xff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-
-	if (bus == 0)
-		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
-	else
-		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
-	__get_mbx_pci_config(temp, QS_CONFIG_DATA, "lwz");
-
-	offset ^= 0x03;
-	cp = ((u_char *)&temp) + (offset & 0x03);
-	*val = *cp;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int mbx_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
-				  unsigned char offset, unsigned short *val)
-{
-	uint	temp;
-	ushort	*sp;
-
-	if ((bus > 7) || (dev_fn > 127)) {
-		*val = 0xffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-
-	if (bus == 0)
-		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
-	else
-		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
-	__get_mbx_pci_config(temp, QS_CONFIG_DATA, "lwz");
-	offset ^= 0x02;
-
-	sp = ((ushort *)&temp) + ((offset >> 1) & 1);
-	*val = *sp;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int mbx_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned int *val)
-{
-	if ((bus > 7) || (dev_fn > 127)) {
-		*val = 0xffffffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	if (bus == 0)
-		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
-	else
-		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
-	__get_mbx_pci_config(*val, QS_CONFIG_DATA, "lwz");
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int mbx_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned char val)
-{
-	uint	temp;
-	u_char	*cp;
-
-	if ((bus > 7) || (dev_fn > 127))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	mbx_pcibios_read_config_dword(bus, dev_fn, offset, &temp);
-
-	offset ^= 0x03;
-	cp = ((u_char *)&temp) + (offset & 0x03);
-	*cp = val;
-
-	if (bus == 0)
-		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
-	else
-		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
-	*QS_CONFIG_DATA = temp;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int mbx_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
-				   unsigned char offset, unsigned short val)
-{
-	uint	temp;
-	ushort	*sp;
-
-	if ((bus > 7) || (dev_fn > 127))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	mbx_pcibios_read_config_dword(bus, dev_fn, offset, &temp);
-
-	offset ^= 0x02;
-	sp = ((ushort *)&temp) + ((offset >> 1) & 1);
-	*sp = val;
-
-	if (bus == 0)
-		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
-	else
-		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
-	*QS_CONFIG_DATA = temp;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int mbx_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
-				    unsigned char offset, unsigned int val)
-{
-	if ((bus > 7) || (dev_fn > 127))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	if (bus == 0)
-		*QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset);
-	else
-		*QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset);
-	*(unsigned int *)QS_CONFIG_DATA = val;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int mbx_pcibios_find_device(unsigned short vendor, unsigned short dev_id,
-			     unsigned short index, unsigned char *bus_ptr,
-			     unsigned char *dev_fn_ptr)
-{
-    int num, devfn;
-    unsigned int x, vendev;
-
-    if (vendor == 0xffff)
-	return PCIBIOS_BAD_VENDOR_ID;
-    vendev = (dev_id << 16) + vendor;
-    num = 0;
-    for (devfn = 0;  devfn < 32;  devfn++) {
-	mbx_pcibios_read_config_dword(0, devfn<<3, PCI_VENDOR_ID, &x);
-	if (x == vendev) {
-	    if (index == num) {
-		*bus_ptr = 0;
-		*dev_fn_ptr = devfn<<3;
-		return PCIBIOS_SUCCESSFUL;
-	    }
-	    ++num;
-	}
-    }
-    return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-int mbx_pcibios_find_class(unsigned int class_code, unsigned short index,
-			    unsigned char *bus_ptr, unsigned char *dev_fn_ptr)
-{
-    int devnr, x, num;
-
-    num = 0;
-    for (devnr = 0;  devnr < 32;  devnr++) {
-	mbx_pcibios_read_config_dword(0, devnr<<3, PCI_CLASS_REVISION, &x);
-	if ((x>>8) == class_code) {
-	    if (index == num) {
-		*bus_ptr = 0;
-		*dev_fn_ptr = devnr<<3;
-		return PCIBIOS_SUCCESSFUL;
-	    }
-	    ++num;
-	}
-    }
-    return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-void __init
-mbx_pcibios_fixup(void)
-{
-   /* Nothing to do here? */
-}
-
-void __init
-mbx_setup_pci_ptrs(void)
-{
-	set_config_access_method(mbx);
-
-	ppc_md.pcibios_fixup = mbx_pcibios_fixup;
-}
-
diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/mbx_setup.c linux/arch/ppc/kernel/mbx_setup.c
--- v2.3.34/linux/arch/ppc/kernel/mbx_setup.c	Fri Oct 22 13:21:45 1999
+++ linux/arch/ppc/kernel/mbx_setup.c	Wed Dec 31 16:00:00 1969
@@ -1,486 +0,0 @@
-/*
- * $Id: mbx_setup.c,v 1.12 1999/08/31 06:53:56 davem Exp $
- *
- *  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)
- *  Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net)
- */
-
-/*
- * bootup setup stuff..
- */
-
-#include <linux/config.h>
-#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/major.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/blk.h>
-#include <linux/ide.h>
-#include <linux/ioport.h>
-
-#include <asm/mmu.h>
-#include <asm/processor.h>
-#include <asm/residual.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/mbx.h>
-#include <asm/machdep.h>
-
-#include "time.h"
-#include "local_irq.h"
-
-static int mbx_set_rtc_time(unsigned long time);
-unsigned long mbx_get_rtc_time(void);
-void mbx_calibrate_decr(void);
-
-extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int mackbd_getkeycode(unsigned int scancode);
-extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
-			   char raw_mode);
-extern char mackbd_unexpected_up(unsigned char keycode);
-extern void mackbd_leds(unsigned char leds);
-extern void mackbd_init_hw(void);
-
-extern unsigned long loops_per_sec;
-
-unsigned long empty_zero_page[1024];
-
-#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 char saved_command_line[256];
-
-extern unsigned long find_available_memory(void);
-extern void m8xx_cpm_reset(uint);
-
-void __init adbdev_init(void)
-{
-}
-
-void __init
-mbx_setup_arch(void)
-{
-	int	cpm_page;
-	extern char cmd_line[];
-	
-	cpm_page = (int) alloc_bootmem_pages(PAGE_SIZE);
-	
-	sprintf(cmd_line,
-"%s root=/dev/nfs nfsroot=/sys/mbxroot",
-		cmd_line);
-	printk("Boot arguments: %s\n", cmd_line);
-
-	/* Reset the Communication Processor Module.
-	*/
-	m8xx_cpm_reset(cpm_page);
-
-#ifdef notdef
-	ROOT_DEV = to_kdev_t(0x0301); /* hda1 */
-#endif
-	
-#ifdef CONFIG_BLK_DEV_INITRD
-#if 0
-	ROOT_DEV = to_kdev_t(0x0200); /* floppy */  
-	rd_prompt = 1;
-	rd_doload = 1;
-	rd_image_start = 0;
-#endif
-#if 0	/* XXX this may need to be updated for the new bootmem stuff,
-	   or possibly just deleted (see set_phys_avail() in init.c).
-	   - paulus. */
-	/* initrd_start and size are setup by boot/head.S and kernel/head.S */
-	if ( initrd_start )
-	{
-		if (initrd_end > *memory_end_p)
-		{
-			printk("initrd extends beyond end of memory "
-			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
-			       initrd_end,*memory_end_p);
-			initrd_start = 0;
-		}
-	}
-#endif
-#endif
-
-#ifdef notdef
-	request_region(0x20,0x20,"pic1");
-	request_region(0xa0,0x20,"pic2");
-	request_region(0x00,0x20,"dma1");
-	request_region(0x40,0x20,"timer");
-	request_region(0x80,0x10,"dma page reg");
-	request_region(0xc0,0x20,"dma2");
-#endif
-}
-
-void
-abort(void)
-{
-#ifdef CONFIG_XMON
-	extern void xmon(void *);
-	xmon(0);
-#endif
-	machine_restart(NULL);
-}
-
-/* The decrementer counts at the system (internal) clock frequency divided by
- * sixteen, or external oscillator divided by four.  Currently, we only
- * support the MBX, which is system clock divided by sixteen.
- */
-void __init mbx_calibrate_decr(void)
-{
-	bd_t	*binfo = (bd_t *)&res;
-	int freq, fp, divisor;
-
-	if ((((immap_t *)MBX_IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0)
-		printk("WARNING: Wrong decrementer source clock.\n");
-
-	/* The manual says the frequency is in Hz, but it is really
-	 * as MHz.  The value 'fp' is the number of decrementer ticks
-	 * per second.
-	 */
-	fp = (binfo->bi_intfreq * 1000000) / 16;
-	freq = fp*60;	/* try to make freq/1e6 an integer */
-        divisor = 60;
-        printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
-        decrementer_count = freq / HZ / divisor;
-        count_period_num = divisor;
-        count_period_den = freq / 1000000;
-}
-
-/* A place holder for time base interrupts, if they are ever enabled.
-*/
-void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
-{
-	printk("timebase_interrupt()\n");
-}
-
-/* The RTC on the MPC8xx is an internal register.
- * We want to protect this during power down, so we need to unlock,
- * modify, and re-lock.
- */
-static int
-mbx_set_rtc_time(unsigned long time)
-{
-	((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
-	((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc = time;
-	((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
-	return(0);
-}
-
-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
-	 * that are maintained by keep alive power are "locked".  To
-	 * modify these registers we have to write the key value to
-	 * the key location associated with the register.
-	 */
-	((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY;
-	((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY;
-
-
-	/* Disable the RTC one second and alarm interrupts.
-	*/
-	((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtcsc &=
-						~(RTCSC_SIE | RTCSC_ALE);
-
-	/* Enabling the decrementer also enables the timebase interrupts
-	 * (or from the other point of view, to get decrementer interrupts
-	 * we have to enable the timebase).  The decrementer interrupt
-	 * is wired into the vector table, nothing to do here for that.
-	 */
-	((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_tbscr =
-				((mk_int_int_mask(DEC_INTERRUPT) << 8) |
-					 (TBSCR_TBF | TBSCR_TBE));
-	if (request_irq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0)
-		panic("Could not allocate timer IRQ!");
-
-	/* Get time from the RTC.
-	*/
-	return ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc;
-}
-
-void
-mbx_restart(char *cmd)
-{
-	extern void MBX_gorom(void);
-
-	MBX_gorom();
-}
-
-void
-mbx_power_off(void)
-{
-   mbx_restart(NULL);
-}
-
-void
-mbx_halt(void)
-{
-   mbx_restart(NULL)
-}
-
-
-int mbx_setup_residual(char *buffer)
-{
-        int     len = 0;
-	bd_t	*bp;
-	extern	RESIDUAL *res;
-			
-	bp = (bd_t *)res;
-			
-	len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
-		       "bus clock\t: %dMHz\n",
-		       bp->bi_intfreq /*/ 1000000*/,
-		       bp->bi_busfreq /*/ 1000000*/);
-
-	return len;
-}
-
-void
-mbx_do_IRQ(struct pt_regs *regs,
-	   int            cpu,
-           int            isfake)
-{
-	int irq;
-        unsigned long bits = 0;
-
-        /* For MPC8xx, read the SIVEC register and shift the bits down
-         * to get the irq number.         */
-        bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec;
-        irq = bits >> 26;
-        irq += ppc8xx_pic.irq_offset;
-        bits = 1UL << irq;
-
-	if (irq < 0) {
-		printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
-		       irq, regs->nip);
-		spurious_interrupts++;
-	}
-	else {
-                ppc_irq_dispatch_handler( regs, irq );
-	}
-
-}
-
-static void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
-	int bits, irq;
-
-	/* A bug in the QSpan chip causes it to give us 0xff always
-	 * when doing a character read.  So read 32 bits and shift.
-	 * This doesn't seem to return useful values anyway, but
-	 * read it to make sure things are acked.
-	 * -- Cort
-	 */
-	irq = (inl(0x508) >> 24)&0xff;
-	if ( irq != 0xff ) printk("iack %d\n", irq);
-	
-	outb(0x0C, 0x20);
-	irq = inb(0x20) & 7;
-	if (irq == 2)
-	{
-		outb(0x0C, 0xA0);
-		irq = inb(0xA0);
-		irq = (irq&7) + 8;
-	}
-	bits = 1UL << irq;
-	irq += i8259_pic.irq_offset;
-	ppc_irq_dispatch_handler( regs, irq );
-}
-
-
-/* On MBX8xx, the interrupt control (SIEL) was set by EPPC-bug.  External
- * 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).
- */
-void __init
-mbx_init_IRQ(void)
-{
-	int i;
-
-        ppc8xx_pic.irq_offset = 16;
-        for ( i = 16 ; i < 32 ; i++ )
-                irq_desc[i].ctl = &ppc8xx_pic;
-        unmask_irq(CPM_INTERRUPT);
-
-        for ( i = 0 ; i < 16 ; i++ )
-                irq_desc[i].ctl = &i8259_pic;
-        i8259_init();
-        request_irq(ISA_BRIDGE_INT, mbx_i8259_action, 0, "8259 cascade", NULL);
-        enable_irq(ISA_BRIDGE_INT);
-}
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/*
- * IDE stuff.
- */
-void
-mbx_ide_insw(ide_ioreg_t port, void *buf, int ns)
-{
-	ide_insw(port+_IO_BASE), buf, ns);
-}
-
-void
-mbx_ide_outsw(ide_ioreg_t port, void *buf, int ns)
-{
-	ide_outsw(port+_IO_BASE, buf, ns);
-}
-
-int
-mbx_ide_default_irq(ide_ioreg_t base)
-{
-        return 14;
-}
-
-ide_ioreg_t
-mbx_ide_default_io_base(int index)
-{
-        return index;
-}
-
-int
-mbx_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-        return 0
-}
-
-void
-mbx_ide_request_region(ide_ioreg_t from,
-			unsigned int extent,
-			const char *name)
-{
-}
-
-void
-mbx_ide_release_region(ide_ioreg_t from,
-			unsigned int extent)
-{
-}
-
-void
-mbx_ide_fix_driveid(struct hd_driveid *id)
-{
-        ppc_generic_ide_fix_driveid(id);
-}
-
-void
-mbx_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;
-
-	*irq = 0;
-
-	if (data_port != 0)	/* Only map the first ATA flash drive */
-		return;
-
-#ifdef ATA_FLASH
-
-	reg = (ide_ioreg_t) ioremap(PCMCIA_MEM_ADDR, 0x200);
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg;
-		reg += 1;
-	}
-
-	/* Does not matter */
-
-	if (ctrl_port) {
-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-	} else {
-		hw->io_ports[IDE_CONTROL_OFFSET] = reg;
-	}
-	if (irq)
-		hw->irq = 13;
-#endif
-}
-#endif
-
-void __init
-mbx_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	 unsigned long r6, unsigned long r7)
-{
-
-	if ( r3 )
-		memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
-	
-#ifdef CONFIG_PCI
-	mbx_setup_pci_ptrs();
-#endif
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	/* take care of initrd if we have one */
-	if ( r4 )
-	{
-		initrd_start = r4 + KERNELBASE;
-		initrd_end = r5 + KERNELBASE;
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
-	/* take care of cmd line */
-	if ( r6 )
-	{
-		
-		*(char *)(r7+KERNELBASE) = 0;
-		strcpy(cmd_line, (char *)(r6+KERNELBASE));
-	}
-
-	ppc_md.setup_arch     = mbx_setup_arch;
-	ppc_md.setup_residual = mbx_setup_residual;
-	ppc_md.get_cpuinfo    = NULL;
-	ppc_md.irq_cannonicalize = NULL;
-	ppc_md.init_IRQ       = mbx_init_IRQ;
-	ppc_md.do_IRQ         = mbx_do_IRQ;
-	ppc_md.init           = NULL;
-
-	ppc_md.restart        = mbx_restart;
-	ppc_md.power_off      = mbx_power_off;
-	ppc_md.halt           = mbx_halt;
-
-	ppc_md.time_init      = NULL;
-	ppc_md.set_rtc_time   = mbx_set_rtc_time;
-	ppc_md.get_rtc_time   = mbx_get_rtc_time;
-	ppc_md.calibrate_decr = mbx_calibrate_decr;
-
-	ppc_md.kbd_setkeycode    = pckbd_setkeycode;
-	ppc_md.kbd_getkeycode    = pckbd_getkeycode;
-	ppc_md.kbd_translate     = pckbd_translate;
-	ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
-	ppc_md.kbd_leds          = pckbd_leds;
-	ppc_md.kbd_init_hw       = pckbd_init_hw;
-#ifdef CONFIG_MAGIC_SYSRQ
-	ppc_md.kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
-#endif
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-        ppc_ide_md.insw = mbx_ide_insw;
-        ppc_ide_md.outsw = mbx_ide_outsw;
-        ppc_ide_md.default_irq = mbx_ide_default_irq;
-        ppc_ide_md.default_io_base = mbx_ide_default_io_base;
-        ppc_ide_md.ide_check_region = mbx_ide_check_region;
-        ppc_ide_md.ide_request_region = mbx_ide_request_region;
-        ppc_ide_md.ide_release_region = mbx_ide_release_region;
-        ppc_ide_md.fix_driveid = mbx_ide_fix_driveid;
-        ppc_ide_md.ide_init_hwif = mbx_ide_init_hwif_ports;
-
-        ppc_ide_md.io_base = _IO_BASE;
-#endif		
-}
diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
--- v2.3.34/linux/arch/ppc/kernel/open_pic.c	Mon Dec 20 18:48:21 1999
+++ linux/arch/ppc/kernel/open_pic.c	Mon Dec 27 14:10:20 1999
@@ -416,13 +416,13 @@
 void openpic_enable_irq(u_int irq)
 {
 	check_arg_irq(irq);
-	openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].ctl->irq_offset].Vector_Priority, OPENPIC_MASK);
+	openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK);
 }
 
 void openpic_disable_irq(u_int irq)
 {
 	check_arg_irq(irq);
-	openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].ctl->irq_offset].Vector_Priority, OPENPIC_MASK);
+	openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK);
 }
 
 /*
diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
--- v2.3.34/linux/arch/ppc/kernel/pmac_pic.c	Mon Dec 20 18:48:21 1999
+++ linux/arch/ppc/kernel/pmac_pic.c	Mon Dec 27 14:10:20 1999
@@ -135,7 +135,7 @@
 	 * don't.  Put this here to check for it.
 	 * -- Cort
 	 */
-	if ( irq_desc[irq].ctl != &gatwick_pic )
+	if ( irq_desc[irq].handler != &gatwick_pic )
 		printk("gatwick irq not from gatwick pic\n");
 	else
 		ppc_irq_dispatch_handler( regs, irq );
@@ -361,7 +361,7 @@
 			max_irqs = 64;
 	}
 	for ( i = 0; i < max_real_irqs ; i++ )
-		irq_desc[i].ctl = &pmac_pic;
+		irq_desc[i].handler = &pmac_pic;
 
 	/* get addresses of first controller */
 	if (irqctrler) {
@@ -401,7 +401,7 @@
 		if (device_is_compatible(irqctrler, "gatwick"))
 			pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
 		for ( i = max_real_irqs ; i < max_irqs ; i++ )
-			irq_desc[i].ctl = &gatwick_pic;
+			irq_desc[i].handler = &gatwick_pic;
 		request_irq( second_irq, gatwick_action, SA_INTERRUPT,
 			     "gatwick cascade", 0 );
 	}
diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.3.34/linux/arch/ppc/kernel/ppc_ksyms.c	Mon Dec 20 18:48:21 1999
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Mon Dec 27 14:10:20 1999
@@ -10,6 +10,7 @@
 #include <linux/nvram.h>
 #include <linux/spinlock.h>
 #include <linux/console.h>
+#include <linux/irq.h>
 
 #include <asm/page.h>
 #include <asm/semaphore.h>
diff -u --recursive --new-file v2.3.34/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.3.34/linux/arch/ppc/kernel/prep_setup.c	Tue Dec  7 09:32:42 1999
+++ linux/arch/ppc/kernel/prep_setup.c	Mon Dec 27 14:10:20 1999
@@ -617,12 +617,12 @@
 
 	if (OpenPIC != NULL) {
 		for ( i = 16 ; i < 36 ; i++ )
-			irq_desc[i].ctl = &open_pic;
+			irq_desc[i].handler = &open_pic;
 		openpic_init(1);
 	}
 	
         for ( i = 0 ; i < 16  ; i++ )
-                irq_desc[i].ctl = &i8259_pic;
+                irq_desc[i].handler = &i8259_pic;
         i8259_init();
 #ifdef __SMP__
 	request_irq(openpic_to_irq(OPENPIC_VEC_SPURIOUS), openpic_ipi_action,
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.3.34/linux/arch/sparc/config.in	Wed Dec  8 14:11:25 1999
+++ linux/arch/sparc/config.in	Wed Dec 22 19:55:38 1999
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.73 1999/08/31 10:09:01 davem Exp $
+# $Id: config.in,v 1.79 1999/12/23 01:46:00 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -57,21 +57,18 @@
    fi
 fi
 
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS
-fi
+tristate 'Openprom tree appears in /proc/openprom' CONFIG_SUN_OPENPROMFS
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 if [ "$CONFIG_PROC_FS" = "y" ]; then
-   choice 'Kernel core (/proc/kcore) format' \
-	"ELF		CONFIG_KCORE_ELF	\
-	 A.OUT		CONFIG_KCORE_AOUT" ELF
+   define_bool CONFIG_KCORE_ELF y
 fi
 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
+bool 'SunOS binary emulation' CONFIG_SUNOS_EMUL
 source drivers/parport/Config.in
 dep_tristate '  Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
 endmenu
@@ -89,7 +86,7 @@
 comment 'Floppy, IDE, and other block devices'
 
 bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD
-
+define_bool CONFIG_BLK_DEV_IDE n
 bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
 if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
    tristate '  Linear (append) mode' CONFIG_MD_LINEAR
@@ -146,7 +143,7 @@
    mainmenu_option next_comment
    comment 'SCSI low-level drivers'
 
-   bool 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
+   tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
    tristate 'PTI Qlogic,ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
    endmenu
 fi
@@ -173,9 +170,7 @@
       fi
       tristate '  Sun LANCE support' CONFIG_SUNLANCE
       tristate '  Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL
-      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-	 tristate '  Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC
-      fi
+      tristate '  Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC
       tristate '  Sun QuadEthernet support' CONFIG_SUNQE
       tristate '  MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS
 #      bool '  FDDI driver support' CONFIG_FDDI
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.3.34/linux/arch/sparc/defconfig	Wed Dec  8 14:11:25 1999
+++ linux/arch/sparc/defconfig	Mon Dec 20 22:05:52 1999
@@ -37,6 +37,7 @@
 CONFIG_FB_CGTHREE=y
 CONFIG_FB_TCX=y
 CONFIG_FB_CGFOURTEEN=y
+# CONFIG_FB_P9100 is not set
 CONFIG_FB_LEO=y
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
@@ -47,7 +48,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
@@ -65,6 +66,7 @@
 # CONFIG_SUN_BPP is not set
 # CONFIG_SUN_VIDEOPIX is not set
 CONFIG_SUN_AURORA=m
+# CONFIG_TADPOLE_TS102_UCTRL is not set
 
 #
 # Linux/SPARC audio subsystem (EXPERIMENTAL)
@@ -84,6 +86,9 @@
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
+CONFIG_SUNOS_EMUL=y
+# CONFIG_PARPORT is not set
+# CONFIG_PRINTER is not set
 
 #
 # Floppy, IDE, and other block devices
@@ -103,8 +108,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
@@ -120,10 +126,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
 
 #
 #  
@@ -144,7 +151,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
@@ -240,6 +246,7 @@
 CONFIG_EFS_FS=m
 CONFIG_ISO9660_FS=m
 # CONFIG_JOLIET is not set
+# CONFIG_UDF_FS is not set
 CONFIG_MINIX_FS=m
 # CONFIG_NTFS_FS is not set
 CONFIG_HPFS_FS=m
@@ -275,13 +282,13 @@
 #
 # Partition Types
 #
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
 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_UNIXWARE_DISKLABEL is not set
-CONFIG_AMIGA_PARTITION=y
+# CONFIG_SGI_PARTITION is not set
+CONFIG_SUN_PARTITION=y
 CONFIG_NLS=y
 
 #
@@ -312,6 +319,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.34/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile
--- v2.3.34/linux/arch/sparc/kernel/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/arch/sparc/kernel/Makefile	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.50 1999/08/31 13:26:13 anton Exp $
+# $Id: Makefile,v 1.52 1999/12/21 04:02:17 davem Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -19,15 +19,19 @@
 IRQ_OBJS := irq.o sun4m_irq.o sun4c_irq.o sun4d_irq.o
 O_OBJS   := entry.o wof.o wuf.o etrap.o rtrap.o traps.o ${IRQ_OBJS} \
 	    process.o signal.o ioport.o setup.o idprom.o \
-	    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 \
+	    sys_sparc.o sunos_asm.o sparc-stub.o systbls.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 semaphore.o
 
 OX_OBJS  := sparc_ksyms.o
 
 ifdef CONFIG_SUN4
 O_OBJS += sun4setup.o
+endif
+
+ifdef CONFIG_SUNOS_EMUL
+O_OBJS += sys_sunos.o sunos_ioctl.o
 endif
 
 ifdef CONFIG_SMP
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/auxio.c linux/arch/sparc/kernel/auxio.c
--- v2.3.34/linux/arch/sparc/kernel/auxio.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/kernel/auxio.c	Mon Dec 20 22:05:52 1999
@@ -9,6 +9,7 @@
 #include <asm/oplib.h>
 #include <asm/io.h>
 #include <asm/auxio.h>
+#include <asm/string.h>		/* memset(), Linux has no bzero() */
 
 /* Probe and map in the Auxiliary I/O register */
 unsigned char *auxio_register;
@@ -17,6 +18,7 @@
 {
 	int node, auxio_nd;
 	struct linux_prom_registers auxregs[1];
+	struct resource r;
 
 	switch (sparc_cpu_model) {
 	case sun4d:
@@ -51,10 +53,11 @@
 	prom_getproperty(auxio_nd, "reg", (char *) auxregs, sizeof(auxregs));
 	prom_apply_obio_ranges(auxregs, 0x1);
 	/* Map the register both read and write */
-	auxio_register = (unsigned char *) sparc_alloc_io(auxregs[0].phys_addr, 0,
-							  auxregs[0].reg_size,
-							  "auxiliaryIO",
-							  auxregs[0].which_io, 0x0);
+	r.flags = auxregs[0].which_io & 0xF;
+	r.start = auxregs[0].phys_addr;
+	r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1;
+	auxio_register = (unsigned char *) sbus_ioremap(&r, 0,
+	    auxregs[0].reg_size, "auxio");
 	/* Fix the address on sun4m and sun4c. */
 	if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 ||
 	   sparc_cpu_model == sun4c)
@@ -72,6 +75,7 @@
 {
 	struct linux_prom_registers regs;
 	int node;
+	struct resource r;
 
 	/* Attempt to find the sun4m power control node. */
 	node = prom_getchild(prom_root_node);
@@ -84,9 +88,12 @@
 	/* Map the power control register. */
 	prom_getproperty(node, "reg", (char *)&regs, sizeof(regs));
 	prom_apply_obio_ranges(&regs, 1);
-	auxio_power_register = (volatile unsigned char *)
-		sparc_alloc_io(regs.phys_addr, 0, regs.reg_size,
-			       "power off control", regs.which_io, 0);
+	memset(&r, 0, sizeof(r));
+	r.flags = regs.which_io & 0xF;
+	r.start = regs.phys_addr;
+	r.end = regs.phys_addr + regs.reg_size - 1;
+	auxio_power_register = (unsigned char *) sbus_ioremap(&r, 0,
+	    regs.reg_size, "auxpower");
 
 	/* Display a quick message on the console. */
 	if (auxio_power_register)
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/ebus.c linux/arch/sparc/kernel/ebus.c
--- v2.3.34/linux/arch/sparc/kernel/ebus.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/kernel/ebus.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.4 1999/08/31 06:54:19 davem Exp $
+/* $Id: ebus.c,v 1.8 1999/11/27 22:40:38 zaitcev Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -23,9 +23,8 @@
 #include <asm/bpp.h>
 
 #undef PROM_DEBUG
-#undef DEBUG_FILL_EBUS_DEV
 
-#ifdef PROM_DEBUG
+#if 0	/* separate from PROM_DEBUG for the sake of PROLL */
 #define dprintk prom_printf
 #else
 #define dprintk printk
@@ -79,7 +78,7 @@
 				    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[regs[i]].start; /* XXX resource */
 	}
 
 	/*
@@ -110,22 +109,8 @@
 			dev->irqs[0] = 0;
 		} else {
 			dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name);
-/* P3 remove */ printk("EBUS: dev %s irq %d from PROM\n", dev->prom_name, dev->irqs[0]);
 		}
 	}
-
-#ifdef DEBUG_FILL_EBUS_DEV
-	dprintk("child '%s': address%s\n", dev->prom_name,
-	       dev->num_addrs > 1 ? "es" : "");
-	for (i = 0; i < dev->num_addrs; i++)
-		dprintk("        %016lx\n", dev->base_address[i]);
-	if (dev->num_irqs) {
-		dprintk("        IRQ%s", dev->num_irqs > 1 ? "s" : "");
-		for (i = 0; i < dev->num_irqs; i++)
-			dprintk(" %08x", dev->irqs[i]);
-		dprintk("\n");
-	}
-#endif
 }
 
 void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
@@ -135,6 +120,7 @@
 	int irqs[PROMINTR_MAX];
 	char lbuf[128];
 	int i, n, len;
+	unsigned long baseaddr;
 
 	dev->prom_node = node;
 	prom_getstring(node, "name", lbuf, sizeof(lbuf));
@@ -175,28 +161,20 @@
 			;
 		}
 
-		dev->base_address[i] = dev->bus->self->base_address[n];
-		dev->base_address[i] += regs[i].phys_addr;
-
-		if (dev->base_address[i]) {
-		    dev->base_address[i] =
-		       (unsigned long)sparc_alloc_io (dev->base_address[i], 0,
-						      regs[i].reg_size,
-						      dev->prom_name, 0, 0);
-#if 0
 /*
- * This release_region() screwes those who do sparc_alloc_io().
- * Change drivers which do check_region(). See drivers/block/floppy.c.
+ * XXX Now as we have regions, why don't we make an on-demand allocation...
  */
-		    /* Some drivers call 'check_region', so we release it */
-                    release_region(dev->base_address[i] & PAGE_MASK, PAGE_SIZE);
-#endif
-
-		    if (dev->base_address[i] == 0 ) {
-			panic("ebus: unable sparc_alloc_io for dev %s",
-			      dev->prom_name);
-		    }
+		dev->resource[i].start = 0;
+		if ((baseaddr = dev->bus->self->resource[n].start +
+		    regs[i].phys_addr) != 0) {
+			/* dev->resource[i].name = dev->prom_name; */
+			if ((baseaddr = (unsigned long) ioremap(baseaddr,
+			    regs[i].reg_size)) == 0) {
+				panic("ebus: unable to remap dev %s",
+				    dev->prom_name);
+			}
 		}
+		dev->resource[i].start = baseaddr;	/* XXX Unaligned */
 	}
 
 	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
@@ -216,22 +194,9 @@
 			dev->irqs[0] = 0;
 		} else {
 			dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name);
-/* P3 remove */ printk("EBUS: child %s irq %d from PROM\n", dev->prom_name, dev->irqs[0]);
 		}
 	}
 
-#ifdef DEBUG_FILL_EBUS_DEV
-	dprintk("'%s': address%s\n", dev->prom_name,
-	       dev->num_addrs > 1 ? "es" : "");
-	for (i = 0; i < dev->num_addrs; i++)
-		dprintk("  %016lx\n", dev->base_address[i]);
-	if (dev->num_irqs) {
-		dprintk("  IRQ%s", dev->num_irqs > 1 ? "s" : "");
-		for (i = 0; i < dev->num_irqs; i++)
-			dprintk(" %08x", dev->irqs[i]);
-		dprintk("\n");
-	}
-#endif
 	if ((node = prom_getchild(node))) {
 		dev->children = (struct linux_ebus_child *)
 			ebus_alloc(sizeof(struct linux_ebus_child));
@@ -312,7 +277,7 @@
 		}
 		nreg = len / sizeof(struct linux_prom_pci_registers);
 
-		base = &ebus->self->base_address[0];
+		base = &ebus->self->resource[0].start;
 		for (reg = 0; reg < nreg; reg++) {
 			if (!(regs[reg].which_io & 0x03000000))
 				continue;
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S
--- v2.3.34/linux/arch/sparc/kernel/entry.S	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/kernel/entry.S	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.161 1999/08/14 03:51:05 anton Exp $
+/* $Id: entry.S,v 1.163 1999/11/19 04:11:24 davem Exp $
  * arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -826,13 +826,13 @@
 	.globl	C_LABEL(invalid_segment_patch1_ff)
 	.globl	C_LABEL(invalid_segment_patch2_ff)
 C_LABEL(invalid_segment_patch1_ff):	cmp	%l4, 0xff
-C_LABEL(invalid_segment_patch2_ff):	mov	0xff, %l4
+C_LABEL(invalid_segment_patch2_ff):	mov	0xff, %l3
 
 	.align	4
 	.globl	C_LABEL(invalid_segment_patch1_1ff)
 	.globl	C_LABEL(invalid_segment_patch2_1ff)
 C_LABEL(invalid_segment_patch1_1ff):	cmp	%l4, 0x1ff
-C_LABEL(invalid_segment_patch2_1ff):	mov	0x1ff, %l4
+C_LABEL(invalid_segment_patch2_1ff):	mov	0x1ff, %l3
 
 	.align	4
 	.globl	C_LABEL(num_context_patch1_16), C_LABEL(num_context_patch2_16)
@@ -853,7 +853,7 @@
 #ifdef CONFIG_SUN4
 C_LABEL(vac_hwflush_patch1_on):		nop
 #else
-C_LABEL(vac_hwflush_patch1_on):		subcc	%l7, (PAGE_SIZE - 4), %l7
+C_LABEL(vac_hwflush_patch1_on):		addcc	%l7, -PAGE_SIZE, %l7
 #endif
 
 C_LABEL(vac_hwflush_patch2_on):		sta	%g0, [%l3 + %l7] ASI_HWFLUSHSEG
@@ -969,12 +969,12 @@
 	bne	1f
 	 sethi	%hi(C_LABEL(sun4c_kfree_ring)), %l4
 	or	%l4, %lo(C_LABEL(sun4c_kfree_ring)), %l4
-	ld	[%l4 + 0x10], %l3
+	ld	[%l4 + 0x18], %l3
 	deccc	%l3			! do we have a free entry?
 	bcs,a	2f			! no, unmap one.
 	 sethi	%hi(C_LABEL(sun4c_kernel_ring)), %l4
 
-	st	%l3, [%l4 + 0x10]	! sun4c_kfree_ring.num_entries--
+	st	%l3, [%l4 + 0x18]	! sun4c_kfree_ring.num_entries--
 
 	ld	[%l4 + 0x00], %l6	! entry = sun4c_kfree_ring.ringhd.next
 	st	%l5, [%l6 + 0x08]	! entry->vaddr = address
@@ -997,10 +997,10 @@
 
 	st	%l6, [%l4 + 0x00]	! head->next = entry
 
-	ld	[%l4 + 0x10], %l3
+	ld	[%l4 + 0x18], %l3
 	inc	%l3			! sun4c_kernel_ring.num_entries++
 	b	4f
-	 st	%l3, [%l4 + 0x10]
+	 ld	[%l6 + 0x08], %l5
 
 2:
 	or	%l4, %lo(C_LABEL(sun4c_kernel_ring)), %l4
@@ -1020,7 +1020,7 @@
 C_LABEL(vac_hwflush_patch1):
 C_LABEL(vac_linesize_patch):
 	subcc	%l7, 16, %l7
-	bg	9b
+	bne	9b
 C_LABEL(vac_hwflush_patch2):
 	 sta	%g0, [%l3 + %l7] ASI_FLUSHSEG
 
@@ -1041,47 +1041,36 @@
 
 	mov	%l3, %l5		! address = tmp
 
+4:
 C_LABEL(num_context_patch1):
 	mov	0x08, %l7
 
-C_LABEL(invalid_segment_patch2):
-	mov	0x7f, %l4
+	ld	[%l6 + 0x08], %l4
+	ldub	[%l6 + 0x0c], %l3
+	or	%l4, %l3, %l4		! encode new vaddr/pseg into l4
 
 	sethi	%hi(AC_CONTEXT), %l3
 	lduba	[%l3] ASI_CONTROL, %l6
 
-3:
-	deccc	%l7
-	stba	%l7, [%l3] ASI_CONTROL
-	bne	3b
-	 stXa	%l4, [%l5] ASI_SEGMAP
-
-	stba	%l6, [%l3] ASI_CONTROL
-
-	! reload the entry
-
-	sethi	%hi(C_LABEL(sun4c_kernel_ring)), %l4
-	ld	[%l4 + %lo(C_LABEL(sun4c_kernel_ring))], %l6
-
-	ld	[%l6 + 0x08], %l5	! restore address from entry->vaddr
-
-4:
-C_LABEL(num_context_patch2):
-	mov	0x08, %l7
-
-	ldub	[%l6 + 0x0c], %l4	! entry->pseg
-
+	/* Invalidate old mapping, instantiate new mapping,
+	 * for each context.  Registers l6/l7 are live across
+	 * this loop.
+	 */
+3:	deccc	%l7
 	sethi	%hi(AC_CONTEXT), %l3
-	lduba	[%l3] ASI_CONTROL, %l6
-
-3:
-	deccc	%l7
 	stba	%l7, [%l3] ASI_CONTROL
+C_LABEL(invalid_segment_patch2):
+	mov	0x7f, %l3
+	stXa	%l3, [%l5] ASI_SEGMAP
+	andn	%l4, 0x1ff, %l3
 	bne	3b
-	 stXa	%l4, [%l5] ASI_SEGMAP
+	 stXa	%l4, [%l3] ASI_SEGMAP
 
+	sethi	%hi(AC_CONTEXT), %l3
 	stba	%l6, [%l3] ASI_CONTROL
 
+	andn	%l4, 0x1ff, %l5
+
 1:
 	sethi	%hi(SUN4C_VMALLOC_START), %l4
 	cmp	%l5, %l4
@@ -1149,6 +1138,7 @@
 
 sun4c_fault_fromuser:
 	SAVE_ALL
+	 nop
 	
 	mov	%l7, %o1		! Decode the info from %l7
 	mov	%l7, %o2
@@ -1199,6 +1189,7 @@
 
 	RESTORE_ALL
 
+#ifdef CONFIG_SUNOS_EMUL
 	/* SunOS uses syscall zero as the 'indirect syscall' it looks
 	 * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
 	 * This is complete brain damage.
@@ -1226,6 +1217,7 @@
 	mov	%o5, %o4
 	call	%l6
 	 mov	%l4, %o7
+#endif
 
 	.align	4
 	.globl	C_LABEL(sys_nis_syscall)
@@ -1638,6 +1630,20 @@
 	sub	%l1, 1, %l1
  	b	ret_trap_entry	
 	 st	%l1, [%sp + REGWIN_SZ + PT_NPC]
+
+#ifndef CONFIG_SUNOS_EMUL
+	.align	4
+	.globl	sunos_syscall
+sunos_syscall:
+	SAVE_ALL_HEAD
+	 rd	%wim, %l3
+	wr	%l0, PSR_ET, %psr
+	nop
+	nop
+	mov	%i0, %l5
+	call	C_LABEL(do_sunos_syscall)
+	 add	%sp, REGWIN_SZ, %o0
+#endif
 
 	/* {net, open}bsd system calls enter here... */
 	.align	4
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S
--- v2.3.34/linux/arch/sparc/kernel/head.S	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/kernel/head.S	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.97 1999/08/14 03:51:10 anton Exp $
+/* $Id: head.S,v 1.101 1999/12/02 08:34:56 jj Exp $
  * head.S: The initial boot code for the Sparc port of Linux.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -78,6 +78,11 @@
         .asciz  "Sparc-Linux sun4e support does not exist\n\n"
 	.align 4
 
+#ifndef CONFIG_SUNOS_EMUL
+#undef SUNOS_SYSCALL_TRAP
+#define SUNOS_SYSCALL_TRAP SUNOS_NO_SYSCALL_TRAP
+#endif
+
 	/* The Sparc trap table, bootloader gives us control at _start. */
 	.text
 	.globl	start, _stext, _start, __stext
@@ -171,7 +176,8 @@
 t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f)
 t_getcc:GETCC_TRAP                          /* Get Condition Codes           */
 t_setcc:SETCC_TRAP                          /* Set Condition Codes           */
-t_bada2:BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+t_getpsr:GETPSR_TRAP                        /* Get PSR Register              */
+t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
 t_slowi:INDIRECT_SOLARIS_SYSCALL(156)
 t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
 t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
@@ -247,8 +253,8 @@
 	LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
 	BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
 	BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
-	BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP
-	BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+	BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
+	BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
 	INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
 	BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
 	BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
@@ -315,8 +321,8 @@
 	LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
 	BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
 	BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
-	BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP
-	BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+	BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
+	BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
 	INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
 	BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
 	BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
@@ -383,8 +389,8 @@
 	LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94)
 	BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99)
 	BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e)
-	BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP
-	BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+	BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP
+	BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
 	INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
 	BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
 	BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
@@ -436,7 +442,7 @@
  */
 	.ascii	"HdrS"
 	.word	LINUX_VERSION_CODE
-	.half	0x0201		/* HdrS version */
+	.half	0x0203		/* HdrS version */
 C_LABEL(root_flags):
 	.half	1
 C_LABEL(root_dev):
@@ -448,6 +454,8 @@
 C_LABEL(sparc_ramdisk_size):
 	.word	0
 	.word	C_LABEL(reboot_command)
+	.word	0, 0, 0
+	.word	_end
 
 /* Cool, here we go. Pick up the romvec pointer in %o0 and stash it in
  * %g7 and at prom_vector_p. And also quickly check whether we are on
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/ioport.c linux/arch/sparc/kernel/ioport.c
--- v2.3.34/linux/arch/sparc/kernel/ioport.c	Mon Apr 14 16:28:07 1997
+++ linux/arch/sparc/kernel/ioport.c	Mon Dec 20 22:05:52 1999
@@ -1,22 +1,20 @@
-/* $Id: ioport.c,v 1.24 1997/04/10 03:02:32 davem Exp $
+/* $Id: ioport.c,v 1.27 1999/11/14 06:23:04 zaitcev Exp $
  * ioport.c:  Simple io mapping allocator.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
  *
- * The routines in this file should be changed for a memory allocator
- * that would be setup just like NetBSD does : you create regions that
- * are administered by a general purpose allocator, and then you call
- * that allocator with your handle and the block size instead of this
- * weak stuff.
+ * 1996: sparc_free_io, 1999: ioremap()/iounmap() by Pete Zaitcev.
  */
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
+#include <linux/malloc.h>
 
 #include <asm/io.h>
 #include <asm/vaddrs.h>
@@ -24,116 +22,511 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 
-/* This points to the next to use virtual memory for io mappings */
-static unsigned long dvma_next_free   = DVMA_VADDR;
-unsigned long sparc_iobase_vaddr = IOBASE_VADDR;
+struct resource *sparc_find_resource_bystart(struct resource *, unsigned long);
+struct resource *sparc_find_resource_by_hit(struct resource *, unsigned long);
+
+static void *_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz);
+static void *_sparc_alloc_io(unsigned int busno, unsigned long phys,
+    unsigned long size, char *name);
+static void _sparc_free_io(struct resource *res);
+
+/* This points to the next to use virtual memory for DVMA mappings */
+static struct resource sparc_dvma = {
+	"sparc_dvma", DVMA_VADDR, DVMA_VADDR + DVMA_LEN - 1
+};
+/* This points to the start of I/O mappings, cluable from outside. */
+       struct resource sparc_iomap = {
+	"sparc_iomap", IOBASE_VADDR, IOBASE_END-1
+};
 
 /*
- * sparc_alloc_io:
- * Map and allocates an obio device.
- * Implements a simple linear allocator, you can force the function
- * to use your own mapping, but in practice this should not be used.
- *
- * Input:
- *  address: the obio address to map
- *  virtual: if non zero, specifies a fixed virtual address where
- *           the mapping should take place.
- *  len:     the length of the mapping
- *  bus_type: The bus on which this io area sits.
+ * Our mini-allocator...
+ * Boy this is gross! We need it because we must map I/O for
+ * timers and interrupt controller before the kmalloc is available.
+ */
+
+#define XNMLN  15
+#define XNRES  10	/* SS-10 uses 8 */
+
+struct xresource {
+	struct resource xres;	/* Must be first */
+	int xflag;		/* 1 == used */
+	char xname[XNMLN+1];
+};
+
+static struct xresource xresv[XNRES];
+
+static struct xresource *xres_alloc(void) {
+	struct xresource *xrp;
+	int n;
+
+	xrp = xresv;
+	for (n = 0; n < XNRES; n++) {
+		if (xrp->xflag == 0) {
+			xrp->xflag = 1;
+			return xrp;
+		}
+		xrp++;
+	}
+	return NULL;
+}
+
+static void xres_free(struct xresource *xrp) {
+	xrp->xflag = 0;
+}
+
+/*
+ */
+extern void sun4c_mapioaddr(unsigned long, unsigned long, int bus_type, int rdonly);
+extern void srmmu_mapioaddr(unsigned long, unsigned long, int bus_type, int rdonly);
+
+static void mapioaddr(unsigned long physaddr, unsigned long virt_addr,
+				 int bus, int rdonly)
+{
+	switch(sparc_cpu_model) {
+	case sun4c:
+	case sun4:
+		sun4c_mapioaddr(physaddr, virt_addr, bus, rdonly);
+		break;
+	case sun4m:
+	case sun4d:
+	case sun4e:
+		srmmu_mapioaddr(physaddr, virt_addr, bus, rdonly);
+		break;
+	default:
+		printk("mapioaddr: Trying to map IO space for unsupported machine.\n");
+		printk("mapioaddr: sparc_cpu_model = %d\n", sparc_cpu_model);
+		printk("mapioaddr: Halting...\n");
+		halt();
+	};
+	return;
+}
+
+extern void srmmu_unmapioaddr(unsigned long virt);
+extern void sun4c_unmapioaddr(unsigned long virt);
+
+static void unmapioaddr(unsigned long virt_addr)
+{
+	switch(sparc_cpu_model) {
+	case sun4c:
+	case sun4:
+		sun4c_unmapioaddr(virt_addr);
+		break;
+	case sun4m:
+	case sun4d:
+	case sun4e:
+		srmmu_unmapioaddr(virt_addr);
+		break;
+	default:
+		printk("unmapioaddr: sparc_cpu_model = %d, halt...\n", sparc_cpu_model);
+		halt();
+	};
+	return;
+}
+
+/*
+ * These are typically used in PCI drivers
+ * which are trying to be cross-platform.
  *
- * Returns:
- *  The virtual address where the mapping actually took place.
+ * Bus type is always zero on IIep.
  */
+void *ioremap(unsigned long offset, unsigned long size)
+{
+	char name[14];
+
+	sprintf(name, "phys_%08x", (u32)offset);
+	return _sparc_alloc_io(0, offset, size, name);
+}
 
-void *sparc_alloc_io (u32 address, void *virtual, int len, char *name,
-		      u32 bus_type, int rdonly)
+/*
+ * Comlimentary to ioremap().
+ */
+void iounmap(void *virtual)
 {
-	unsigned long vaddr, base_address;
-	unsigned long addr = (unsigned long) address;
-	unsigned long offset = (addr & (~PAGE_MASK));
+	unsigned long vaddr = (unsigned long) virtual & PAGE_MASK;
+	struct resource *res;
 
-	if (virtual) {
-		vaddr = (unsigned long) virtual;
+	if ((res = sparc_find_resource_bystart(&sparc_iomap, vaddr)) == NULL) {
+		printk("free_io/iounmap: cannot free %lx\n", vaddr);
+		return;
+	}
+	_sparc_free_io(res);
 
-		len += offset;
-		if(((unsigned long) virtual + len) > (IOBASE_VADDR + IOBASE_LEN)) {
-			prom_printf("alloc_io: Mapping outside IOBASE area\n");
-			prom_halt();
-		}
-		if(check_region ((vaddr | offset), len)) {
-			prom_printf("alloc_io: 0x%lx is already in use\n", vaddr);
-			prom_halt();
-		}
+	if ((char *)res >= (char*)xresv && (char *)res < (char *)&xresv[XNRES]) {
+		xres_free((struct xresource *)res);
+	} else {
+		kfree(res);
+	}
+}
 
-		/* Tell Linux resource manager about the mapping */
-		request_region ((vaddr | offset), len, name);
+/*
+ * Davem's version of sbus_ioremap.
+ */
+unsigned long sbus_ioremap(struct resource *phyres, unsigned long offset,
+    unsigned long size, char *name)
+{
+	return (unsigned long) _sparc_alloc_io(phyres->flags & 0xF,
+	    phyres->start + offset, size, name);
+}
+
+/*
+ */
+void sbus_iounmap(unsigned long addr, unsigned long size)
+{
+	iounmap((void *)addr);
+}
+
+/*
+ * Meat of mapping
+ */
+static void *_sparc_alloc_io(unsigned int busno, unsigned long phys,
+    unsigned long size, char *name)
+{
+	static int printed_full = 0;
+	struct xresource *xres;
+	struct resource *res;
+	char *tack;
+	int tlen;
+	void *va;	/* P3 diag */
+
+	if (name == NULL) name = "???";
+
+	if ((xres = xres_alloc()) != 0) {
+		tack = xres->xname;
+		res = &xres->xres;
 	} else {
-		vaddr = occupy_region(sparc_iobase_vaddr, IOBASE_END,
-				(offset + len + PAGE_SIZE-1) & PAGE_MASK, PAGE_SIZE, name);
-		if (vaddr == 0) {
-			/* Usually we cannot see printks in this case. */
-			prom_printf("alloc_io: cannot occupy %d region\n", len);
-			prom_halt();
+		if (!printed_full) {
+			printk("ioremap: done with statics, switching to malloc\n");
+			printed_full = 1;
 		}
+		tlen = strlen(name);
+		tack = kmalloc(sizeof (struct resource) + tlen + 1, GFP_KERNEL);
+		if (tack == NULL) return NULL;
+		res = (struct resource *) tack;
+		tack += sizeof (struct resource);
 	}
 
-	base_address = vaddr;
-	/* Do the actual mapping */
-	for (; len > 0; len -= PAGE_SIZE) {
-		mapioaddr(addr, vaddr, bus_type, rdonly);
-		vaddr += PAGE_SIZE;
-		addr += PAGE_SIZE;
+	strncpy(tack, name, XNMLN);
+	tack[XNMLN] = 0;
+	res->name = tack;
+
+	va = _sparc_ioremap(res, busno, phys, size);
+	/* printk("ioremap(0x%x:%08lx[0x%lx])=%p\n", busno, phys, size, va); */ /* P3 diag */
+	return va;
+}
+
+/*
+ * This is called from _sparc_alloc_io only, we left it separate
+ * in case Davem changes his mind about interface to sbus_ioremap().
+ */
+static void *
+_sparc_ioremap(struct resource *res, u32 bus, u32 pa, int sz)
+{
+	unsigned long offset = ((unsigned long) pa) & (~PAGE_MASK);
+	unsigned long va;
+	unsigned int psz;
+
+	if (allocate_resource(&sparc_iomap, res,
+	    (offset + sz + PAGE_SIZE-1) & PAGE_MASK,
+	    sparc_iomap.start, sparc_iomap.end, PAGE_SIZE) != 0) {
+		/* Usually we cannot see printks in this case. */
+		prom_printf("alloc_io_res(%s): cannot occupy\n",
+		    (res->name != NULL)? res->name: "???");
+		prom_halt();
+	}
+
+	va = res->start;
+	pa &= PAGE_MASK;
+	for (psz = res->end - res->start + 1; psz != 0; psz -= PAGE_SIZE) {
+		mapioaddr(pa, va, bus, 0);
+		va += PAGE_SIZE;
+		pa += PAGE_SIZE;
 	}
 
-	return (void *) (base_address | offset);
+	/*
+	 * XXX Playing with implementation details here.
+	 * On sparc64 Ebus has resources with precise boundaries.
+	 * We share drivers with sparc64. Too clever drivers use
+	 * start of a resource instead of a base adress.
+	 *
+	 * XXX-2 This may be not valid anymore, clean when
+	 * interface to sbus_ioremap() is resolved.
+	 */
+	res->start += offset;
+	res->end = res->start + sz - 1;		/* not strictly necessary.. */
+
+	return (void *) res->start;
 }
 
-void sparc_free_io (void *virtual, int len)
+/*
+ * Comlimentary to _sparc_ioremap().
+ */
+static void _sparc_free_io(struct resource *res)
 {
-	unsigned long vaddr = (unsigned long) virtual & PAGE_MASK;
-	unsigned long plen = (((unsigned long)virtual & ~PAGE_MASK) + len + PAGE_SIZE-1) & PAGE_MASK;
-
-	release_region(vaddr, plen);
+	unsigned long plen;
 
-	for (; plen != 0;) {
+	plen = res->end - res->start + 1;
+	while (plen != 0) {
 		plen -= PAGE_SIZE;
-		unmapioaddr(vaddr + plen);
+		unmapioaddr(res->start + plen);
 	}
+
+	release_resource(res);
+}
+
+#ifdef CONFIG_SBUS
+
+void sbus_set_sbus64(struct sbus_dev *sdev, int x) {
+	printk("sbus_set_sbus64: unsupported\n");
 }
 
-/* Does DVMA allocations with PAGE_SIZE granularity.  How this basically
- * works is that the ESP chip can do DVMA transfers at ANY address with
- * certain size and boundary restrictions.  But other devices that are
- * attached to it and would like to do DVMA have to set things up in
- * a special way, if the DVMA sees a device attached to it transfer data
- * at addresses above DVMA_VADDR it will grab them, this way it does not
- * now have to know the peculiarities of where to read the Lance data
- * from. (for example)
+/*
+ * Allocate a chunk of memory suitable for DMA.
+ * Typically devices use them for control blocks.
+ * CPU may access them without any explicit flushing.
  */
-void *_sparc_dvma_malloc (int len, char *name)
+void *sbus_alloc_consistant(struct sbus_dev *sdev, long len, u32 *dma_addrp)
 {
-	unsigned long vaddr, base_address;
+	unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
+	unsigned long va;
+	struct resource *res;
+	int order;
+
+	/* XXX why are some lenghts signed, others unsigned? */
+	if (len <= 0) {
+		return NULL;
+	}
+	/* XXX So what is maxphys for us and how do drivers know it? */
+	if (len > 256*1024) {			/* __get_free_pages() limit */
+		return NULL;
+	}
 
-	vaddr = dvma_next_free;
-	if(check_region (vaddr, len)) {
-		prom_printf("alloc_dma: 0x%lx is already in use\n", vaddr);
-		prom_halt();
+	for (order = 0; order < 6; order++)	/* 2^6 pages == 256K */
+		if ((1 << (order + PAGE_SHIFT)) >= len_total)
+			break;
+	va = __get_free_pages(GFP_KERNEL, order);
+	if (va == 0) {
+		/*
+		 * printk here may be flooding... Consider removal XXX.
+		 */
+		printk("sbus_alloc_consistant: no %ld pages\n", len_total>>PAGE_SHIFT);
+		return NULL;
 	}
-	if(vaddr + len > (DVMA_VADDR + DVMA_LEN)) {
-		prom_printf("alloc_dvma: out of dvma memory\n");
-		prom_halt();
+
+	if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
+		free_pages(va, order);
+		printk("sbus_alloc_consistant: no core\n");
+		return NULL;
 	}
 
-	/* Basically these can be mapped just like any old
-	 * IO pages, cacheable bit off, etc.  The physical
-	 * pages are now mapped dynamically to save space.
+	if (allocate_resource(&sparc_dvma, res, len_total,
+	    sparc_dvma.start, sparc_dvma.end, PAGE_SIZE) != 0) {
+		printk("sbus_alloc_consistant: cannot occupy 0x%lx", len);
+		free_pages(va, order);
+		kfree(res);
+		return NULL;
+	}
+
+	*dma_addrp = res->start;
+	mmu_map_dma_area(va, res->start, len);
+
+	/*
+	 * "Official" or "natural" address of pages we got is va.
+	 * We want to return uncached range. We could make va[len]
+	 * uncached but it's difficult to make cached back [P3: hmm]
+	 * We use the artefact of sun4c, replicated everywhere else,
+	 * that CPU can use bus addresses to access the same memory.
 	 */
-	base_address = vaddr;
-	mmu_map_dma_area(base_address, len);
-	/* Assign the memory area. */
-	dvma_next_free = PAGE_ALIGN(dvma_next_free+len);
+	res->name = (void *)va;	/* XXX Ouch.. we got to hide it somewhere */
+	return (void *)res->start;
+}
+
+void sbus_free_consistant(struct sbus_dev *sdev, long n, void *p, u32 ba)
+{
+	struct resource *res;
+	unsigned long pgp;
+	int order;
+
+	if ((res = sparc_find_resource_bystart(&sparc_dvma,
+	    (unsigned long)p)) == NULL) {
+		printk("sbus_free_consistant: cannot free %p\n", p);
+		return;
+	}
+
+	if (((unsigned long)p & (PAGE_MASK-1)) != 0) {
+		printk("sbus_free_consistant: unaligned va %p\n", p);
+		return;
+	}
+
+	n = (n + PAGE_SIZE-1) & PAGE_MASK;
+	if ((res->end-res->start)+1 != n) {
+		printk("sbus_free_consistant: region 0x%lx asked 0x%lx\n",
+		    (long)((res->end-res->start)+1), n);
+		return;
+	}
+
+	mmu_inval_dma_area((unsigned long)res->name, n);	/* XXX Ouch */
+	mmu_unmap_dma_area(ba, n);
+	release_resource(res);
+
+	pgp = (unsigned long) res->name;	/* XXX Ouch */
+	for (order = 0; order < 6; order++)
+		if ((1 << (order + PAGE_SHIFT)) >= n)
+			break;
+	free_pages(pgp, order);
+
+	kfree(res);
+}
+
+/*
+ * Map a chunk of memory so that devices can see it.
+ * CPU view of this memory may be inconsistent with
+ * a device view and explicit flushing is necessary.
+ */
+u32 sbus_map_single(struct sbus_dev *sdev, void *va, long len)
+{
+#if 0 /* This is the version that abuses consistant space */
+	unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
+	struct resource *res;
+
+	/* XXX why are some lenghts signed, others unsigned? */
+	if (len <= 0) {
+		return 0;
+	}
+	/* XXX So what is maxphys for us and how do drivers know it? */
+	if (len > 256*1024) {			/* __get_free_pages() limit */
+		return 0;
+	}
+
+	if ((res = kmalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
+		printk("sbus_map_single: no core\n");
+		return 0;
+	}
+	res->name = va;
+
+	if (allocate_resource(&sparc_dvma, res, len_total,
+	    sparc_dvma.start, sparc_dvma.end, PAGE_SIZE) != 0) {
+		printk("sbus_map_single: cannot occupy 0x%lx", len);
+		kfree(res);
+		return 0;
+	}
+
+	mmu_map_dma_area(va, res->start, len_total);
+	mmu_flush_dma_area((unsigned long)va, len_total); /* in all contexts? */
+
+	return res->start;
+#endif
+#if 1 /* "trampoline" version */
+	/* XXX why are some lenghts signed, others unsigned? */
+	if (len <= 0) {
+		return 0;
+	}
+	/* XXX So what is maxphys for us and how do drivers know it? */
+	if (len > 256*1024) {			/* __get_free_pages() limit */
+		return 0;
+	}
+/* BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, char *, unsigned long, struct sbus_bus *sbus) */
+	return mmu_get_scsi_one(va, len, sdev->bus);
+#endif
+}
 
-	request_region(base_address, len, name);
+void sbus_unmap_single(struct sbus_dev *sdev, u32 ba, long n)
+{
+#if 0 /* This is the version that abuses consistant space */
+	struct resource *res;
+	unsigned long va;
+
+	if ((res = sparc_find_resource_bystart(&sparc_dvma, ba)) == NULL) {
+		printk("sbus_unmap_single: cannot find %08x\n", (unsigned)ba);
+		return;
+	}
+
+	n = (n + PAGE_SIZE-1) & PAGE_MASK;
+	if ((res->end-res->start)+1 != n) {
+		printk("sbus_unmap_single: region 0x%lx asked 0x%lx\n",
+		    (long)((res->end-res->start)+1), n);
+		return;
+	}
+
+	va = (unsigned long) res->name;	/* XXX Ouch */
+	mmu_inval_dma_area(va, n);	/* in all contexts, mm's?... */
+	mmu_unmap_dma_area(ba, n);	/* iounit cache flush is here */
+	release_resource(res);
+	kfree(res);
+#endif
+#if 1 /* "trampoline" version */
+/* BTFIXUPDEF_CALL(void,  mmu_release_scsi_one, __u32, unsigned long, struct sbus_bus *sbus) */
+	mmu_release_scsi_one(ba, n, sdev->bus);
+#endif
+}
+
+void sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n)
+{
+/* BTFIXUPDEF_CALL(void,  mmu_get_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) */
+	mmu_get_scsi_sgl(sg, n, sdev->bus);
+}
+
+void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n)
+{
+/* BTFIXUPDEF_CALL(void,  mmu_release_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) */
+	mmu_release_scsi_sgl(sg, n, sdev->bus);
+}
+#endif
+
+/*
+ * P3: I think a partial flush is permitted...
+ * We are not too efficient at doing it though.
+ *
+ * If only DaveM understood a concept of an allocation cookie,
+ * we could avoid find_resource_by_hit() here and a major
+ * performance hit.
+ */
+void sbus_dma_sync_single(struct sbus_dev *sdev, u32 ba, long size)
+{
+	unsigned long va;
+	struct resource *res;
+
+	res = sparc_find_resource_by_hit(&sparc_dvma, ba);
+	if (res == NULL)
+		panic("sbus_dma_sync_single: 0x%x\n", ba);
+
+	va = (unsigned long) res->name;
+	/* if (va == 0) */
+
+	mmu_inval_dma_area(va, (res->end - res->start) + 1);
+}
+
+void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n)
+{
+	printk("dma_sync_sg: not implemented yet\n");
+}
+
+/*
+ * This is a version of find_resource and it belongs to kernel/resource.c.
+ * Until we have agreement with Linus and Martin, it lingers here.
+ *
+ * "same start" is more strict than "hit into"
+ */
+struct resource *
+sparc_find_resource_bystart(struct resource *root, unsigned long start)
+{
+        struct resource *tmp;
+
+        for (tmp = root->child; tmp != 0; tmp = tmp->sibling) {
+                if (tmp->start == start)
+			return tmp;
+        }
+        return NULL;
+}
+
+struct resource *
+sparc_find_resource_by_hit(struct resource *root, unsigned long hit)
+{
+        struct resource *tmp;
 
-	return (void *) base_address;
+        for (tmp = root->child; tmp != 0; tmp = tmp->sibling) {
+                if (tmp->start <= hit && tmp->end >= hit)
+			return tmp;
+        }
+        return NULL;
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- v2.3.34/linux/arch/sparc/kernel/irq.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc/kernel/irq.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/*  $Id: irq.c,v 1.97 1999/09/10 10:40:21 davem Exp $
+/*  $Id: irq.c,v 1.98 1999/11/17 07:34:05 zaitcev 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
@@ -726,7 +726,7 @@
 	case sun4m:
 #ifdef CONFIG_PCI
 		pcic_probe();
-		if (pci_present()) {
+		if (pcic_present()) {
 			sun4m_pci_init_IRQ();
 			break;
 		}
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/pcic.c linux/arch/sparc/kernel/pcic.c
--- v2.3.34/linux/arch/sparc/kernel/pcic.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/kernel/pcic.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: pcic.c,v 1.8 1999/08/31 06:54:22 davem Exp $
+/* $Id: pcic.c,v 1.11 1999/11/25 05:22:05 zaitcev Exp $
  * pcic.c: Sparc/PCI controller support
  *
  * Copyright (C) 1998 V. Roganov and G. Raiko
@@ -22,17 +22,6 @@
 #include <asm/swift.h> /* for cache flushing. */
 #include <asm/io.h>
 
-#undef PROM_DEBUG
-#undef FIXUP_REGS_DEBUG
-#undef FIXUP_IRQ_DEBUG
-#undef FIXUP_VMA_DEBUG
-
-#ifdef PROM_DEBUG
-#define dprintf	prom_printf
-#else
-#define dprintf printk
-#endif
-
 #include <linux/ctype.h>
 #include <linux/pci.h>
 #include <linux/timex.h>
@@ -57,7 +46,7 @@
 				  unsigned long len,
 				  unsigned char *buf)
 {
-	return 0;
+	return -EINVAL;
 }
 
 asmlinkage int sys_pciconfig_write(unsigned long bus,
@@ -66,11 +55,19 @@
 				   unsigned long len,
 				   unsigned char *buf)
 {
-	return 0;
+	return -EINVAL;
 }
 
 #else
 
+#ifdef CONFIG_SUN_JSFLASH
+extern int jsflash_init(void);
+#endif
+
+struct pci_fixup pcibios_fixups[] = {
+	{ 0 }
+};
+
 unsigned int pcic_pin_to_irq(unsigned int pin, char *name);
 
 /*
@@ -120,7 +117,8 @@
 	{ 0, 0x00, 0, 13, 0 },		/* Ebus - serial and keyboard */
 	{ 0, 0x01, 1,  6, 0 },		/* hme */
 	{ 0, 0x08, 2,  9, 0 },		/* VGA - we hope not used :) */
-	{ 0, 0x18, 6,  8, 0 },		/* PCI INTA# in Slot 1 */
+	{ 0, 0x10, 6,  8, 0 },		/* PCI INTA# in Slot 1 */
+	{ 0, 0x18, 7, 12, 0 },		/* PCI INTA# in Slot 2, shared w. RTC */
 	{ 0, 0x38, 4,  9, 0 },		/* All ISA devices. Read 8259. */
 	{ 0, 0x80, 5, 11, 0 },		/* EIDE */
 	/* {0,0x88, 0,0,0} - unknown device... PMU? Probably no interrupt. */
@@ -144,6 +142,16 @@
 };
 
 /*
+ * Krups (courtesy of Varol Kaptan)
+ * No documentation available, so we guess it, based on Espresso layout.
+ * Since we always run PROLL on Krups we may put map in there.
+ */
+static struct pcic_ca2irq pcic_i_jk[] = {
+	{ 0, 0x00, 0, 13, 0 },		/* Ebus - serial and keyboard */
+	{ 0, 0x01, 1,  6, 0 },		/* hme */
+};
+
+/*
  * Several entries in this list may point to the same routing map
  * as several PROMs may be installed on the same physical board.
  */
@@ -154,11 +162,17 @@
 	SN2L_INIT("JE-1-name", pcic_i_je1),  /* XXX Gleb, put name here, pls */
 	SN2L_INIT("SUNW,JS-E", pcic_i_jse),	/* PROLL JavaStation-E */
 	SN2L_INIT("SUNW,SPARCengine-6", pcic_i_se6), /* SPARCengine-6/CP-1200 */
+	SN2L_INIT("SUNW,JS-NC", pcic_i_jk),	/* PROLL JavaStation-NC */
+	SN2L_INIT("SUNW,JSIIep", pcic_i_jk),	/* OBP JavaStation-NC */
 	{ NULL, NULL, 0 }
 };
 
-static struct linux_pcic PCIC;
-static struct linux_pcic *pcic = NULL;
+/*
+ * Only one PCIC per IIep,
+ * and since we have no SMP IIep, only one per system.
+ */
+static int pcic0_up = 0;
+static struct linux_pcic pcic0;
 
 unsigned int pcic_regs;
 volatile int pcic_speculative;
@@ -167,23 +181,144 @@
 static void pci_do_gettimeofday(struct timeval *tv);
 static void pci_do_settimeofday(struct timeval *tv);
 
-void __init pcic_probe(void)
+#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3))
+
+static int pcic_read_config_dword(struct pci_dev *dev, int where, u32 *value);
+static int pcic_write_config_dword(struct pci_dev *dev, int where, u32 value);
+
+static int pcic_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+{
+	unsigned int v;
+
+	pcic_read_config_dword(dev, where&~3, &v);
+	*value = 0xff & (v >> (8*(where & 3)));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pcic_read_config_word(struct pci_dev *dev, int where, u16 *value)
+{
+	unsigned int v;
+	if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	pcic_read_config_dword(dev, where&~3, &v);
+	*value = 0xffff & (v >> (8*(where & 3)));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pcic_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
+	unsigned char bus = dev->bus->number;
+	unsigned char device_fn = dev->devfn;
+	/* unsigned char where; */
+
+	struct linux_pcic *pcic;
+	unsigned long flags;
+
+	if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
+	if (bus != 0) return PCIBIOS_DEVICE_NOT_FOUND;
+	pcic = &pcic0;
+
+	save_and_cli(flags);
+#if 0 /* does not fail here */
+	pcic_speculative = 1;
+	pcic_trapped = 0;
+#endif
+	writel(CONFIG_CMD(bus,device_fn,where), pcic->pcic_config_space_addr);
+#if 0 /* does not fail here */
+	nop();
+	if (pcic_trapped) {
+		restore_flags(flags);
+		*value = ~0;
+		return PCIBIOS_SUCCESSFUL;
+	}
+#endif
+	pcic_speculative = 2;
+	pcic_trapped = 0;
+	*value = readl(pcic->pcic_config_space_data + (where&4));
+	nop();
+	if (pcic_trapped) {
+		pcic_speculative = 0;
+		restore_flags(flags);
+		*value = ~0;
+		return PCIBIOS_SUCCESSFUL;
+	}
+	pcic_speculative = 0;
+	restore_flags(flags);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pcic_write_config_byte(struct pci_dev *dev, int where, u8 value)
+{
+	unsigned int v;
+
+	pcic_read_config_dword(dev, where&~3, &v);
+        v = (v & ~(0xff << (8*(where&3)))) |
+            ((0xff&(unsigned)value) << (8*(where&3)));
+	return pcic_write_config_dword(dev, where&~3, v);
+}
+
+static int pcic_write_config_word(struct pci_dev *dev, int where, u16 value)
+{
+	unsigned int v;
+
+	if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
+	pcic_read_config_dword(dev, where&~3, &v);
+	v = (v & ~(0xffff << (8*(where&3)))) |
+	    ((0xffff&(unsigned)value) << (8*(where&3)));
+	return pcic_write_config_dword(dev, where&~3, v);
+}
+
+static int pcic_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+	unsigned char bus = dev->bus->number;
+	unsigned char devfn = dev->devfn;
+	struct linux_pcic *pcic;
+	unsigned long flags;
+
+	if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
+	if (bus != 0) return PCIBIOS_DEVICE_NOT_FOUND;
+	pcic = &pcic0;
+
+	save_and_cli(flags);
+	writel(CONFIG_CMD(bus,devfn,where), pcic->pcic_config_space_addr);
+	writel(value, pcic->pcic_config_space_data + (where&4));
+	restore_flags(flags);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pcic_ops = {
+	pcic_read_config_byte,
+	pcic_read_config_word,
+	pcic_read_config_dword,
+	pcic_write_config_byte,
+	pcic_write_config_word,
+	pcic_write_config_dword,
+};
+
+/*
+ * On sparc64 pcibios_init() calls pci_controller_probe().
+ * We want PCIC probed little ahead so that interrupt controller
+ * would be operational.
+ */
+int __init pcic_probe(void)
+{
+	struct linux_pcic *pcic;
 	struct linux_prom_registers regs[PROMREG_MAX];
 	struct linux_pbm_info* pbm;
 	char namebuf[64];
 	int node;
 	int err;
 
-	if (pcibios_present()) {
+	if (pcic0_up) {
 		prom_printf("PCIC: called twice!\n");
 		prom_halt();
 	}
+	pcic = &pcic0;
 
 	node = prom_getchild (prom_root_node);
 	node = prom_searchsiblings (node, "pci");
 	if (node == 0)
-		return;
+		return -ENODEV;
 	/*
 	 * Map in PCIC register set, config space, and IO base
 	 */
@@ -193,31 +328,27 @@
 			    "from PROM.\n");
 		prom_halt();
 	}
-	
-	pcic = &PCIC;
 
-	pcic->pcic_regs = (unsigned long)sparc_alloc_io(regs[0].phys_addr, NULL,
-					      regs[0].reg_size,
-					      "PCIC Registers", 0, 0);
+	pcic0_up = 1;
+
+	pcic->pcic_res_regs.name = "pcic_registers";
+	pcic->pcic_regs = (unsigned long)
+	    ioremap(regs[0].phys_addr, regs[0].reg_size);
 	if (!pcic->pcic_regs) {
 		prom_printf("PCIC: Error, cannot map PCIC registers.\n");
 		prom_halt();
 	}
 
-	pcic->pcic_io_phys = regs[1].phys_addr;
-	pcic->pcic_io = (unsigned long)sparc_alloc_io(regs[1].phys_addr, NULL,
-					    regs[1].reg_size,
-					    "PCIC IO Base", 0, 0);
-	if (pcic->pcic_io == 0UL) {
+	pcic->pcic_res_io.name = "pcic_io";
+	if ((pcic->pcic_io = (unsigned long)
+	    ioremap(regs[1].phys_addr, 0x10000)) == 0) {
 		prom_printf("PCIC: Error, cannot map PCIC IO Base.\n");
 		prom_halt();
 	}
 
-	pcic->pcic_config_space_addr =
-			(unsigned long)sparc_alloc_io (regs[2].phys_addr, NULL,
-					     regs[2].reg_size * 2,
-					     "PCI Config Space Address", 0, 0);
-	if (pcic->pcic_config_space_addr == 0UL) {
+	pcic->pcic_res_cfg_addr.name = "pcic_cfg_addr";
+	if ((pcic->pcic_config_space_addr = (unsigned long)
+	    ioremap(regs[2].phys_addr, regs[2].reg_size * 2)) == 0) {
 		prom_printf("PCIC: Error, cannot map" 
 			    "PCI Configuration Space Address.\n");
 		prom_halt();
@@ -227,11 +358,9 @@
 	 * Docs say three least significant bits in address and data
 	 * must be the same. Thus, we need adjust size of data.
 	 */
-	pcic->pcic_config_space_data =
-			(unsigned long)sparc_alloc_io (regs[3].phys_addr, NULL,
-					     regs[3].reg_size * 2,
-					     "PCI Config Space Data", 0, 0);
-	if (pcic->pcic_config_space_data == 0UL) {
+	pcic->pcic_res_cfg_data.name = "pcic_cfg_data";
+	if ((pcic->pcic_config_space_data = (unsigned long)
+	    ioremap(regs[3].phys_addr, regs[3].reg_size * 2)) == 0) {
 		prom_printf("PCIC: Error, cannot map" 
 			    "PCI Configuration Space Data.\n");
 		prom_halt();
@@ -239,7 +368,7 @@
 
 	pbm = &pcic->pbm;
 	pbm->prom_node = node;
-	prom_getstring(node, "name", namebuf, sizeof(namebuf));
+	prom_getstring(node, "name", namebuf, 63);  namebuf[63] = 0;
 	strcpy(pbm->prom_name, namebuf);
 
 	{
@@ -254,7 +383,7 @@
 		pcic_regs = pcic->pcic_regs;
 	}
 
-	prom_getstring(prom_root_node, "name", namebuf, sizeof(namebuf));
+	prom_getstring(prom_root_node, "name", namebuf, 63);  namebuf[63] = 0;
 	{
 		struct pcic_sn2list *p;
 
@@ -272,21 +401,37 @@
 		printk("PCIC: System %s is unknown, cannot route interrupts\n",
 		    namebuf);
 	}
+
+	return 0;
+}
+
+static void __init pcic_pbm_scan_bus(struct linux_pcic *pcic)
+{
+	struct linux_pbm_info *pbm = &pcic->pbm;
+
+	pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, &pcic_ops, pbm);
+#if 0 /* deadwood transplanted from sparc64 */
+	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);
+#endif
 }
 
+/*
+ * Main entry point from the PCI subsystem.
+ */
 void __init pcibios_init(void)
 {
+	struct linux_pcic *pcic;
+
 	/*
 	 * PCIC should be initialized at start of the timer.
 	 * So, here we report the presence of PCIC and do some magic passes.
 	 */
-	if(!pcic)
+	if(!pcic0_up)
 		return;
-
-	printk("PCIC MAP: config addr=0x%lx; config data=0x%lx, "
-	       "regs=0x%lx io=0x%lx\n",
-	       pcic->pcic_config_space_addr, pcic->pcic_config_space_data,
-	       pcic->pcic_regs, pcic->pcic_io);
+	pcic = &pcic0;
 
 	/*
 	 *      Switch off IOTLB translation.
@@ -302,11 +447,18 @@
 	writel(0xF0000000UL, pcic->pcic_regs+PCI_SIZE_0);
 	writel(0+PCI_BASE_ADDRESS_SPACE_MEMORY, 
 	       pcic->pcic_regs+PCI_BASE_ADDRESS_0);
+
+	pcic_pbm_scan_bus(pcic);
+
+	ebus_init();
+#ifdef CONFIG_SUN_JSFLASH
+	jsflash_init();
+#endif
 }
 
-int pcibios_present(void)
+int pcic_present(void)
 {
-	return pcic != NULL;
+	return pcic0_up;
 }
 
 static int __init pdev_to_pnode(struct linux_pbm_info *pbm, 
@@ -334,91 +486,77 @@
 	return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC);
 }
 
-static void pcic_map_pci_device (struct pci_dev *dev, int node) {
-	struct linux_prom_pci_assigned_addresses addrs[6];
-	int addrlen;
-	int i, j;
-
-	/* Is any valid address present ? */
-	i = 0;
-	for(j = 0; j < 6; j++)
-		if (dev->base_address[j]) i++;
-	if (!i) return; /* nothing to do */
+static void pcic_map_pci_device(struct linux_pcic *pcic,
+    struct pci_dev *dev, int node)
+{
+	char namebuf[64];
+	unsigned long address;
+	unsigned long flags;
+	int j;
 
 	if (node == 0 || node == -1) {
-		printk("PCIC: no prom node for device ID (%x,%x)\n",
-		    dev->device, dev->vendor);
-		return;
-	}
-
-	/*
-	 * find related address and get it's window length
-	 */
-	addrlen = prom_getproperty(node,"assigned-addresses",
-					       (char*)addrs, sizeof(addrs));
-	if (addrlen == -1) {
-		printk("PCIC: no \"assigned-addresses\" for device (%x,%x)\n",
-		    dev->device, dev->vendor);
-		return;
+		strcpy(namebuf, "???");
+	} else {
+		prom_getstring(node, "name", namebuf, 63); namebuf[63] = 0;
 	}
 
-	addrlen /= sizeof(struct linux_prom_pci_assigned_addresses);
-	for (i = 0; i < addrlen; i++ )
-	    for (j = 0; j < 6; j++) {
-		if (!dev->base_address[j] || !addrs[i].phys_lo)
-			continue;
-		if (addrs[i].phys_lo == dev->base_address[j]) {
-			unsigned long address = dev->base_address[j];
-			int length  = addrs[i].size_lo;
-			char namebuf[128] = { 0, };
-			unsigned long mapaddr, addrflags;
-
-			prom_getstring(node, "name", namebuf, sizeof(namebuf));
-
-			/*
-			 *      failure in allocation too large space
-			 */
-			if (length > 0x200000) {
-				length = 0x200000;
-				prom_printf("PCIC: map window for device '%s' "
-					    "reduced to 2MB !\n", namebuf);
-			}
-
-			/*
-			 *  Be careful with MEM/IO address flags
-			 */
-			if ((address & PCI_BASE_ADDRESS_SPACE) ==
-				 PCI_BASE_ADDRESS_SPACE_IO) {
-				mapaddr = address & PCI_BASE_ADDRESS_IO_MASK;
+	for (j = 0; j < 6; j++) {
+		address = dev->resource[j].start;
+		if (address == 0) break;	/* are sequential */
+		flags = dev->resource[j].flags;
+		if ((flags & IORESOURCE_IO) != 0) {
+			if (address < 0x10000) {
+				/*
+				 * A device responds to I/O cycles on PCI.
+				 * We generate these cycles with memory
+				 * access into the fixed map (phys 0x30000000).
+				 *
+				 * Since a device driver does not want to
+				 * do ioremap() before accessing PC-style I/O,
+				 * we supply virtual, ready to access address.
+				 *
+				 * Ebus devices do not come here even if
+				 * CheerIO makes a similar conversion.
+				 * See ebus.c for details.
+				 *
+				 * Note that check_region()/request_region()
+				 * work for these devices.
+				 *
+				 * XXX Neat trick, but it's a *bad* idea
+				 * to shit into regions like that.
+				 * What if we want to allocate one more
+				 * PCI base address...
+				 */
+				dev->resource[j].start =
+				    pcic->pcic_io + address;
+				dev->resource[j].end = 1;  /* XXX */
+				dev->resource[j].flags =
+				    (flags & ~IORESOURCE_IO) | IORESOURCE_MEM;
 			} else {
-				mapaddr = address & PCI_BASE_ADDRESS_MEM_MASK;
+				/*
+				 * OOPS... PCI Spec allows this. Sun does
+				 * not have any devices getting above 64K
+				 * so it must be user with a weird I/O
+				 * board in a PCI slot. We must remap it
+				 * under 64K but it is not done yet. XXX
+				 */
+				printk("PCIC: Skipping I/O space at 0x%lx,"
+				    "this will Oops if a driver attaches;"
+				    "device '%s' (%x,%x)\n", address, namebuf,
+	    			    dev->device, dev->vendor);
 			}
-			addrflags = address ^ mapaddr;
-
-			dev->base_address[j] =
-				(unsigned long)sparc_alloc_io(address, 0, 
-							      length,
-							      namebuf, 0, 0);
-			if ( dev->base_address[j] == 0 )
-				panic("PCIC: failed make mapping for "
-				      "pci device '%s' with address %lx\n",
-				       namebuf, address);
-
-			dev->base_address[j] ^= addrflags;
-			return;
 		}
-	    }
-
-	printk("PCIC: unable to match addresses for device (%x,%x)\n",
-	    dev->device, dev->vendor);
+	}
 }
 
-static void pcic_fill_irq(struct pci_dev *dev, int node) {
+static void
+pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
+{
 	struct pcic_ca2irq *p;
 	int i, ivec;
 	char namebuf[64];  /* P3 remove */
 
-	if (node == -1) {
+	if (node == 0 || node == -1) {
 		strcpy(namebuf, "???");
 	} else {
 		prom_getstring(node, "name", namebuf, sizeof(namebuf)); /* P3 remove */
@@ -474,53 +612,33 @@
 }
 
 /*
- * Assign IO space for a device.
- * This is a chance for devices which have the same IO and Mem Space to
- * fork access to IO and Mem.
- *
- * Now, we assume there is one such device only (IGA 1682) but code below
- * should work in cases when space of all such devices is less then 16MB.
- */
-unsigned long pcic_alloc_io( unsigned long* addr )
-{
-	unsigned long paddr = *addr;
-	unsigned long offset;
-
-	if(pcic->pcic_mapped_io == 0) {
-		pcic->pcic_mapped_io = paddr & ~(PCI_SPACE_SIZE-1) ;
-		writeb((pcic->pcic_mapped_io>>24) & 0xff, 
-		       pcic->pcic_regs+PCI_PIBAR);
-		writeb((pcic->pcic_io_phys>>24) & PCI_SIBAR_ADDRESS_MASK,
-		       pcic->pcic_regs+PCI_SIBAR);
-		writeb(PCI_ISIZE_16M, pcic->pcic_regs+PCI_ISIZE);
-
-	}
-	if(paddr < pcic->pcic_mapped_io ||
-	   paddr >= pcic->pcic_mapped_io + 0x10000)
-		return 0;
-	offset = paddr - pcic->pcic_mapped_io;
-	*addr = pcic->pcic_io_phys + offset;
-	return pcic->pcic_io + offset;
-}
-
-/*
- * Stolen from both i386 and sparc64 branch 
+ * Normally called from {do_}pci_scan_bus...
  */
-void __init pcibios_fixup(void)
+void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
-  struct pci_dev *dev;
-  int i, has_io, has_mem;
-  unsigned short cmd;
-	struct linux_pbm_info* pbm = &pcic->pbm;
+	struct pci_dev *dev;
+	int i, has_io, has_mem;
+	unsigned short cmd;
+	struct linux_pcic *pcic;
+	/* struct linux_pbm_info* pbm = &pcic->pbm; */
 	int node;
 	struct pcidev_cookie *pcp;
 
-	if(pcic == NULL) {
-		prom_printf("PCI: Error, PCIC not found.\n");
-		prom_halt();
+	if (!pcic0_up) {
+		printk("pcibios_fixup_bus: no PCIC\n");
+		return;
 	}
+	pcic = &pcic0;
 
-	for (dev = pci_devices; dev; dev=dev->next) {
+	/*
+	 * Next crud is an equivalent of pbm = pcic_bus_to_pbm(bus);
+	 */
+	if (bus->number != 0) {
+		printk("pcibios_fixup_bus: nonzero bus 0x%x\n", bus->number);
+		return;
+	}
+
+	for (dev = bus->devices; dev; dev = dev->sibling) {
 		/*
 		 * Comment from i386 branch:
 		 *     There are buggy BIOSes that forget to enable I/O and memory
@@ -531,44 +649,42 @@
 		 */
 		has_io = has_mem = 0;
 		for(i=0; i<6; i++) {
-			unsigned long a = dev->base_address[i];
-			if (a & PCI_BASE_ADDRESS_SPACE_IO) {
+			unsigned long f = dev->resource[i].flags;
+			if (f & IORESOURCE_IO) {
 				has_io = 1;
-			} else if (a & PCI_BASE_ADDRESS_MEM_MASK)
+			} else if (f & IORESOURCE_MEM)
 				has_mem = 1;
 		}
-		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		pcic_read_config_word(dev, PCI_COMMAND, &cmd);
 		if (has_io && !(cmd & PCI_COMMAND_IO)) {
 			printk("PCIC: Enabling I/O for device %02x:%02x\n",
 				dev->bus->number, dev->devfn);
 			cmd |= PCI_COMMAND_IO;
-			pci_write_config_word(dev, PCI_COMMAND, cmd);
+			pcic_write_config_word(dev, PCI_COMMAND, cmd);
 		}
 		if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
 			printk("PCIC: Enabling memory for device %02x:%02x\n",
 				dev->bus->number, dev->devfn);
 			cmd |= PCI_COMMAND_MEMORY;
-			pci_write_config_word(dev, PCI_COMMAND, cmd);
+			pcic_write_config_word(dev, PCI_COMMAND, cmd);
 		}    
 
-		node = pdev_to_pnode(pbm, dev);
+		node = pdev_to_pnode(&pcic->pbm, dev);
 		if(node == 0)
 			node = -1;
 
 		/* cookies */
 		pcp = pci_devcookie_alloc();
-		pcp->pbm = pbm;
+		pcp->pbm = &pcic->pbm;
 		pcp->prom_node = node;
 		dev->sysdata = pcp;
 
-		/* memory mapping */
+		/* fixing I/O to look like memory */
 		if ((dev->class>>16) != PCI_BASE_CLASS_BRIDGE)
-			pcic_map_pci_device(dev, node);
+			pcic_map_pci_device(pcic, dev, node);
 
-		pcic_fill_irq(dev, node);
+		pcic_fill_irq(pcic, dev, node);
 	}
-
-	ebus_init();
 }
 
 /*
@@ -577,6 +693,7 @@
 unsigned int
 pcic_pin_to_irq(unsigned int pin, char *name)
 {
+	struct linux_pcic *pcic = &pcic0;
 	unsigned int irq;
 	unsigned int ivec;
 
@@ -599,7 +716,7 @@
 
 static void pcic_clear_clock_irq(void)
 {
-	pcic_timer_dummy = readl(pcic->pcic_regs+PCI_SYS_LIMIT);
+	pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT);
 }
 
 static void pcic_timer_handler (int irq, void *h, struct pt_regs *regs)
@@ -613,6 +730,7 @@
 
 void __init pci_time_init(void)
 {
+	struct linux_pcic *pcic = &pcic0;
 	unsigned long v;
 	int timer_irq, irq;
 
@@ -620,9 +738,9 @@
 	/* A hack until do_gettimeofday prototype is moved to arch specific headers
 	   and btfixupped. Patch do_gettimeofday with ba pci_do_gettimeofday; nop */
 	((unsigned int *)do_gettimeofday)[0] = 
-		0x10800000 | ((((unsigned long)pci_do_gettimeofday - (unsigned long)do_gettimeofday) >> 2) & 0x003fffff);
-	((unsigned int *)do_gettimeofday)[1] =
-		0x01000000;
+	    0x10800000 | ((((unsigned long)pci_do_gettimeofday -
+	     (unsigned long)do_gettimeofday) >> 2) & 0x003fffff);
+	((unsigned int *)do_gettimeofday)[1] = 0x01000000;
 	BTFIXUPSET_CALL(bus_do_settimeofday, pci_do_settimeofday, BTFIXUPCALL_NORM);
 	btfixup();
 
@@ -650,7 +768,7 @@
 	 * to have microsecond resolution and to avoid overflow
 	 */
 	unsigned long count = 
-	    readl(pcic->pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;
+	    readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;
 	count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100);
 
 	if(test_bit(TIMER_BH, &bh_active))
@@ -705,103 +823,9 @@
 }
 #endif
 
-#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3))
-
-int pcibios_read_config_byte(unsigned char bus, unsigned char device_fn,
-			     unsigned char where, unsigned char *value)
-{
-	unsigned int v;
-
-	pcibios_read_config_dword (bus, device_fn, where&~3, &v);
-	*value = 0xff & (v >> (8*(where & 3)));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int pcibios_read_config_word (unsigned char bus,
-			      unsigned char device_fn, 
-			      unsigned char where, unsigned short *value)
-{
-	unsigned int v;
-	if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
-  
-	pcibios_read_config_dword (bus, device_fn, where&~3, &v);
-	*value = 0xffff & (v >> (8*(where & 3)));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
-			       unsigned char where, unsigned int *value)
-{
-	unsigned long flags;
-
-	if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	save_and_cli(flags);
-#if 0
-	pcic_speculative = 1;
-	pcic_trapped = 0;
-#endif
-	writel(CONFIG_CMD(bus,device_fn,where), pcic->pcic_config_space_addr);
-#if 0
-	nop();
-	if (pcic_trapped) {
-		restore_flags(flags);
-		*value = ~0;
-		return PCIBIOS_SUCCESSFUL;
-	}
-#endif
-	pcic_speculative = 2;
-	pcic_trapped = 0;
-	*value = readl(pcic->pcic_config_space_data + (where&4));
-	nop();
-	if (pcic_trapped) {
-		pcic_speculative = 0;
-		restore_flags(flags);
-		*value = ~0;
-		return PCIBIOS_SUCCESSFUL;
-	}
-	pcic_speculative = 0;
-	restore_flags(flags);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char devfn,
-			       unsigned char where, unsigned char value)
-{
-	unsigned int v;
-
-	pcibios_read_config_dword (bus, devfn, where&~3, &v);
-	v = (v & ~(0xff << (8*(where&3)))) | 
-	    ((0xff&(unsigned)value) << (8*(where&3)));
-	return pcibios_write_config_dword (bus, devfn, where&~3, v);
-}
-
-int pcibios_write_config_word (unsigned char bus, unsigned char devfn,
-			       unsigned char where, unsigned short value)
-{
-	unsigned int v;
-	if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	pcibios_read_config_dword (bus, devfn, where&~3, &v);
-	v = (v & ~(0xffff << (8*(where&3)))) | 
-	    ((0xffff&(unsigned)value) << (8*(where&3)));
-	return pcibios_write_config_dword (bus, devfn, where&~3, v);
-}
-  
-int pcibios_write_config_dword (unsigned char bus, unsigned char devfn,
-				unsigned char where, unsigned int value)
-{
-	unsigned long flags;
-
-	if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	save_and_cli(flags);
-	writel(CONFIG_CMD(bus,devfn,where),pcic->pcic_config_space_addr);
-	writel(value, pcic->pcic_config_space_data + (where&4));
-	restore_flags(flags);
-	return PCIBIOS_SUCCESSFUL;
-}
-
+/*
+ * Other archs parse arguments here.
+ */
 char * __init pcibios_setup(char *str)
 {
 	return str;
@@ -831,6 +855,9 @@
 }
 
 /*
+ * XXX  Gleb wrote me that he needs this for X server (only).
+ * Since we successfuly use XF86_FBDev, we do not need these anymore.
+ *
  *  Following code added to handle extra PCI-related system calls 
  */
 asmlinkage int sys_pciconfig_read(unsigned long bus,
@@ -870,7 +897,7 @@
 
 	return err;
 }
-   
+
 asmlinkage int sys_pciconfig_write(unsigned long bus,
 				   unsigned long dfn,
 				   unsigned long off,
@@ -936,7 +963,7 @@
 
 	mask = get_irqmask(irq_nr);
 	save_and_cli(flags);
-	writel(mask, pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_SET);
+	writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET);
 	restore_flags(flags);
 }
 
@@ -946,7 +973,7 @@
 
 	mask = get_irqmask(irq_nr);
 	save_and_cli(flags);
-	writel(mask, pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR);
+	writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR);
 	restore_flags(flags);
 }
 
@@ -965,12 +992,12 @@
  */
 static void pcic_disable_pil_irq(unsigned int pil)
 {
-	writel(get_irqmask(pil), pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_SET);
+	writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET);
 }
 
 static void pcic_enable_pil_irq(unsigned int pil)
 {
-	writel(get_irqmask(pil), pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR);
+	writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR);
 }
 
 void __init sun4m_pci_init_IRQ(void)
@@ -985,8 +1012,9 @@
 	BTFIXUPSET_CALL(__irq_itoa, pcic_irq_itoa, BTFIXUPCALL_NORM);
 }
 
-void __init pcibios_fixup_bus(struct pci_bus *bus)
+int pcibios_assign_resource(struct pci_dev *pdev, int resource)
 {
+	return -ENXIO;
 }
 
 #endif
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v2.3.34/linux/arch/sparc/kernel/process.c	Thu Nov 11 20:11:32 1999
+++ linux/arch/sparc/kernel/process.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.139 1999/08/14 03:51:14 anton Exp $
+/*  $Id: process.c,v 1.141 1999/10/24 06:25:02 anton Exp $
  *  linux/arch/sparc/kernel/process.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -55,7 +55,6 @@
 {
 	int ret = -EPERM;
 
-	lock_kernel();
 	if (current->pid != 0)
 		goto out;
 
@@ -100,7 +99,6 @@
 	}
 	ret = 0;
 out:
-	unlock_kernel();
 	return ret;
 }
 
@@ -188,9 +186,7 @@
 	       rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
 }
 
-#ifdef __SMP__
 static spinlock_t sparc_backtrace_lock = SPIN_LOCK_UNLOCKED;
-#endif
 
 void __show_backtrace(unsigned long fp)
 {
@@ -702,37 +698,3 @@
 			   "g1", "g2", "g3", "o0", "o1", "memory", "cc");
 	return retval;
 }
-
-/*
- * These bracket the sleeping functions..
- */
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-#define first_sched	((unsigned long) scheduling_functions_start_here)
-#define last_sched	((unsigned long) scheduling_functions_end_here)
-
-unsigned long get_wchan(struct task_struct *p)
-{
-	unsigned long pc, fp, bias = 0;
-	unsigned long task_base = (unsigned long) p;
-	struct reg_window *rw;
-	int count = 0;
-	if (!p || p == current || p->state == TASK_RUNNING)
-		return 0;
-
-	fp = p->thread.ksp + bias;
-	do {
-		/* Bogus frame pointer? */
-		if (fp < (task_base + sizeof(struct task_struct)) ||
-		    fp >= (task_base + (2 * PAGE_SIZE)))
-			break;
-		rw = (struct reg_window *) fp;
-		pc = rw->ins[7];
-		if (pc < first_sched || pc >= last_sched)
-			return pc;
-		fp = rw->ins[6] + bias;
-	} while (++count < 16);
-	return 0;
-}
-#undef last_sched
-#undef first_sched
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c
--- v2.3.34/linux/arch/sparc/kernel/setup.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc/kernel/setup.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.111 1999/09/10 10:40:24 davem Exp $
+/*  $Id: setup.c,v 1.113 1999/12/16 14:37:35 anton Exp $
  *  linux/arch/sparc/kernel/setup.c
  *
  *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
@@ -124,7 +124,9 @@
 #ifdef CONFIG_SUN_CONSOLE
 static int console_fb = 0;
 #endif
-static unsigned long memory_size __initdata = 0;
+
+/* Exported for mm/init.c:paging_init. */
+unsigned long cmdline_memory_size __initdata = 0;
 
 void kernel_enter_debugger(void)
 {
@@ -238,13 +240,13 @@
 				 * "mem=XXX[kKmM] overrides the PROM-reported
 				 * memory size.
 				 */
-				memory_size = simple_strtoul(commands + 4,
+				cmdline_memory_size = simple_strtoul(commands + 4,
 							     &commands, 0);
 				if (*commands == 'K' || *commands == 'k') {
-					memory_size <<= 10;
+					cmdline_memory_size <<= 10;
 					commands++;
 				} else if (*commands=='M' || *commands=='m') {
-					memory_size <<= 20;
+					cmdline_memory_size <<= 20;
 					commands++;
 				}
 			}
@@ -266,7 +268,7 @@
 extern unsigned long start, end;
 extern void panic_setup(char *, int *);
 extern void srmmu_end_memory(unsigned long, unsigned long *);
-extern unsigned long sun_serial_setup(unsigned long);
+extern void sun_serial_setup(void);
 
 extern unsigned short root_flags;
 extern unsigned short root_dev;
@@ -297,10 +299,10 @@
 	"PROM", prom_cons_write, 0, 0, 0, 0, 0, CON_PRINTBUFFER, 0, 0, 0
 };
 
-void __init setup_arch(char **cmdline_p,
-	unsigned long * memory_start_p, unsigned long * memory_end_p)
+void __init setup_arch(char **cmdline_p)
 {
-	int total, i, packed;
+	int i;
+	unsigned long highest_paddr;
 
 	sparc_ttable = (struct tt_entry *) &start;
 
@@ -329,27 +331,21 @@
 	strcpy(&cputypval, "ap+");
 #endif
 	printk("ARCH: ");
-	packed = 0;
 	switch(sparc_cpu_model) {
 	case sun4:
 		printk("SUN4\n");
-		packed = 0;
 		break;
 	case sun4c:
 		printk("SUN4C\n");
-		packed = 0;
 		break;
 	case sun4m:
 		printk("SUN4M\n");
-		packed = 1;
 		break;
 	case sun4d:
 		printk("SUN4D\n");
-		packed = 1;
 		break;
 	case sun4e:
 		printk("SUN4E\n");
-		packed = 0;
 		break;
 	case sun4u:
 		printk("SUN4U\n");
@@ -357,7 +353,6 @@
 	case ap1000:
 		register_console(&prom_console);
 		printk("AP1000\n");
-		packed = 1;
 		break;
 	default:
 		printk("UNKNOWN!\n");
@@ -375,26 +370,20 @@
 	if (ARCH_SUN4C_SUN4)
 		sun4c_probe_vac();
 	load_mmu();
-	total = prom_probe_memory();
-	*memory_start_p = PAGE_ALIGN(((unsigned long) &end));
+	(void) prom_probe_memory();
 
-	if(!packed) {
-		for(i=0; sp_banks[i].num_bytes != 0; i++) {
-			end_of_phys_memory = sp_banks[i].base_addr +
-					     sp_banks[i].num_bytes;
-			if (memory_size) {
-				if (end_of_phys_memory > memory_size) {
-					sp_banks[i].num_bytes -=
-					    (end_of_phys_memory - memory_size);
-					end_of_phys_memory = memory_size;
-					sp_banks[++i].base_addr = 0xdeadbeef;
-					sp_banks[i].num_bytes = 0;
-				}
-			}
-		}
-		*memory_end_p = (end_of_phys_memory + KERNBASE);
-	} else
-		srmmu_end_memory(memory_size, memory_end_p);
+	phys_base = 0xffffffffUL;
+	highest_paddr = 0UL;
+	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
+		unsigned long top;
+
+		if (sp_banks[i].base_addr < phys_base)
+			phys_base = sp_banks[i].base_addr;
+		top = sp_banks[i].base_addr +
+			sp_banks[i].num_bytes;
+		if (highest_paddr < top)
+			highest_paddr = top;
+	}
 
 	if (!root_flags)
 		root_mountflags &= ~MS_RDONLY;
@@ -405,6 +394,7 @@
 	rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);	
 #endif
 #ifdef CONFIG_BLK_DEV_INITRD
+// FIXME needs to do the new bootmem alloc stuff
 	if (sparc_ramdisk_image) {
 		initrd_start = sparc_ramdisk_image;
 		if (initrd_start < KERNBASE) initrd_start += KERNBASE;
@@ -434,7 +424,10 @@
 	prom_setsync(prom_sync_me);
 
 #ifdef CONFIG_SUN_SERIAL
-	*memory_start_p = sun_serial_setup(*memory_start_p); /* set this up ASAP */
+#if 0
+	/* XXX We can't do this until the bootmem allocator is working. */
+	sun_serial_setup(); /* set this up ASAP */
+#endif
 #endif
 	{
 #if !CONFIG_SUN_SERIAL
@@ -489,11 +482,10 @@
 		breakpoint();
 	}
 
-
 	/* Due to stack alignment restrictions and assumptions... */
 	init_mm.mmap->vm_page_prot = PAGE_SHARED;
-	init_mm.mmap->vm_start = KERNBASE;
-	init_mm.mmap->vm_end = *memory_end_p;
+	init_mm.mmap->vm_start = PAGE_OFFSET;
+	init_mm.mmap->vm_end = PAGE_OFFSET + highest_paddr;
 	init_mm.context = (unsigned long) NO_CONTEXT;
 	init_task.thread.kregs = &fake_swapper_regs;
 
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c
--- v2.3.34/linux/arch/sparc/kernel/signal.c	Tue Nov 23 22:42:20 1999
+++ linux/arch/sparc/kernel/signal.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.95 1999/08/14 03:51:22 anton Exp $
+/*  $Id: signal.c,v 1.98 1999/12/15 22:24:23 davem Exp $
  *  linux/arch/sparc/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c
--- v2.3.34/linux/arch/sparc/kernel/smp.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc/kernel/smp.c	Mon Dec 20 22:05:52 1999
@@ -163,7 +163,7 @@
 			local_flush_tlb_mm(mm);
 		} else {
 			xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm);
-			if(atomic_read(&mm->count) == 1 && current->mm == mm)
+			if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm)
 				mm->cpu_vm_mask = (1 << smp_processor_id());
 		}
 	}
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.3.34/linux/arch/sparc/kernel/sparc_ksyms.c	Thu Nov 11 20:11:32 1999
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.79 1999/09/10 10:40:28 davem Exp $
+/* $Id: sparc_ksyms.c,v 1.83 1999/11/19 04:11:28 davem Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -50,8 +50,6 @@
 
 extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *);
 extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *);
-extern unsigned long sunos_mmap(unsigned long, unsigned long, unsigned long,
-				unsigned long, unsigned long, unsigned long);
 void _sigpause_common (unsigned int set, struct pt_regs *);
 extern void (*__copy_1page)(void *, const void *);
 extern void __memmove(void *, const void *, __kernel_size_t);
@@ -65,6 +63,7 @@
 
 extern void bcopy (const char *, char *, int);
 extern int __ashrdi3(int, int);
+extern int __ashldi3(int, int);
 extern int __lshrdi3(int, int);
 
 extern void dump_thread(struct pt_regs *, struct user *);
@@ -157,11 +156,10 @@
 EXPORT_SYMBOL(auxio_register);
 #endif
 EXPORT_SYMBOL(request_fast_irq);
-EXPORT_SYMBOL(sparc_alloc_io);
-EXPORT_SYMBOL(sparc_free_io);
 EXPORT_SYMBOL(io_remap_page_range);
-EXPORT_SYMBOL(iounit_map_dma_init);
-EXPORT_SYMBOL(iounit_map_dma_page);
+  /* P3: iounit_xxx may be needed, sun4d users */
+/* EXPORT_SYMBOL(iounit_map_dma_init); */
+/* EXPORT_SYMBOL(iounit_map_dma_page); */
 
 /* Btfixup stuff cannot have versions, it would be complicated too much */
 #ifndef __SMP__
@@ -180,19 +178,27 @@
 EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_release_scsi_sgl));
 EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_release_scsi_one));
 
-EXPORT_SYMBOL(_sparc_dvma_malloc);
-EXPORT_SYMBOL(sun4c_unmapioaddr);
-EXPORT_SYMBOL(srmmu_unmapioaddr);
 #if CONFIG_SBUS
-EXPORT_SYMBOL(SBus_chain);
+EXPORT_SYMBOL(sbus_root);
 EXPORT_SYMBOL(dma_chain);
+EXPORT_SYMBOL(sbus_set_sbus64);
+EXPORT_SYMBOL(sbus_alloc_consistant);
+EXPORT_SYMBOL(sbus_free_consistant);
+EXPORT_SYMBOL(sbus_map_single);
+EXPORT_SYMBOL(sbus_unmap_single);
+EXPORT_SYMBOL(sbus_map_sg);
+EXPORT_SYMBOL(sbus_unmap_sg);
+EXPORT_SYMBOL(sbus_dma_sync_single);
+EXPORT_SYMBOL(sbus_dma_sync_sg);
+#endif
+#if CONFIG_PCI
+/* We do not have modular drivers for PCI devices yet. */
 #endif
 
 /* Solaris/SunOS binary compatibility */
 EXPORT_SYMBOL(svr4_setcontext);
 EXPORT_SYMBOL(svr4_getcontext);
 EXPORT_SYMBOL(_sigpause_common);
-EXPORT_SYMBOL(sunos_mmap);
 
 /* Should really be in linux/kernel/ksyms.c */
 EXPORT_SYMBOL(dump_thread);
@@ -215,9 +221,9 @@
 EXPORT_SYMBOL(prom_feval);
 EXPORT_SYMBOL(prom_getbool);
 EXPORT_SYMBOL(prom_getstring);
-EXPORT_SYMBOL(prom_apply_sbus_ranges);
 EXPORT_SYMBOL(prom_getint);
 EXPORT_SYMBOL(prom_getintdefault);
+EXPORT_SYMBOL(prom_finddevice);
 EXPORT_SYMBOL(romvec);
 EXPORT_SYMBOL(__prom_getchild);
 EXPORT_SYMBOL(__prom_getsibling);
@@ -271,6 +277,7 @@
 EXPORT_SYMBOL_NOVERS(memset);
 EXPORT_SYMBOL_NOVERS(memmove);
 EXPORT_SYMBOL_NOVERS(__ashrdi3);
+EXPORT_SYMBOL_NOVERS(__ashldi3);
 EXPORT_SYMBOL_NOVERS(__lshrdi3);
 
 EXPORT_SYMBOL_DOT(rem);
@@ -279,5 +286,3 @@
 EXPORT_SYMBOL_DOT(umul);
 EXPORT_SYMBOL_DOT(div);
 EXPORT_SYMBOL_DOT(udiv);
-
-EXPORT_SYMBOL(get_wchan);
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sun4c_irq.c linux/arch/sparc/kernel/sun4c_irq.c
--- v2.3.34/linux/arch/sparc/kernel/sun4c_irq.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/kernel/sun4c_irq.c	Mon Dec 20 22:05:52 1999
@@ -35,6 +35,11 @@
 #include <asm/idprom.h>
 #include <asm/machines.h>
 
+#if 0
+static struct resource sun4c_timer_eb = { "sun4c_timer" };
+static struct resource sun4c_intr_eb = { "sun4c_intr" };
+#endif
+
 /* Pointer to the interrupt enable byte
  *
  * Dave Redman (djhr@tadpole.co.uk)
@@ -150,10 +155,9 @@
 		sun4c_timers = &sun4_timer;
 	else
 #endif
-	sun4c_timers = sparc_alloc_io (SUN_TIMER_PHYSADDR, 0,
-				       sizeof(struct sun4c_timer_info),
-				       "timer", 0x0, 0x0);
-    
+	sun4c_timers = ioremap(SUN_TIMER_PHYSADDR,
+	    sizeof(struct sun4c_timer_info));
+
 	/* Have the level 10 timer tick at 100HZ.  We don't touch the
 	 * level 14 timer limit since we are letting the prom handle
 	 * them until we have a real console driver so L1-A works.
@@ -190,13 +194,11 @@
 	int ie_node;
 
 	if (ARCH_SUN4) {
-		interrupt_enable =
-			(char *) sparc_alloc_io(sun4_ie_physaddr, 0,
-					   	PAGE_SIZE,
-					   	"sun4c_interrupts",
-					   	0x0, 0x0);
+		interrupt_enable = (char *)
+		    ioremap(sun4_ie_physaddr, PAGE_SIZE);
 	} else {
-    
+		struct resource phyres;
+
 		ie_node = prom_searchsiblings (prom_getchild(prom_root_node),
 				       	"interrupt-enable");
 		if(ie_node == 0)
@@ -204,11 +206,11 @@
 
 		/* Depending on the "address" property is bad news... */
 		prom_getproperty(ie_node, "reg", (char *) int_regs, sizeof(int_regs));
-		interrupt_enable =
-			(char *) sparc_alloc_io(int_regs[0].phys_addr, 0,
-					   	int_regs[0].reg_size,
-					   	"sun4c_interrupts",
-					   	int_regs[0].which_io, 0x0);
+		memset(&phyres, 0, sizeof(struct resource));
+		phyres.flags = int_regs[0].which_io;
+		phyres.start = int_regs[0].phys_addr;
+		interrupt_enable = (char *) sbus_ioremap(&phyres, 0,
+		    int_regs[0].reg_size, "sun4c_intr");
 	}
 
 	BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM);
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c
--- v2.3.34/linux/arch/sparc/kernel/sun4d_irq.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc/kernel/sun4d_irq.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/*  $Id: sun4d_irq.c,v 1.20 1999/09/10 10:40:30 davem Exp $
+/*  $Id: sun4d_irq.c,v 1.23 1999/10/19 04:33:26 zaitcev Exp $
  *  arch/sparc/kernel/sun4d_irq.c:
  *			SS1000/SC2000 interrupt handling.
  *
@@ -237,12 +237,12 @@
 	irq_exit(cpu, irq);
 }
 
-unsigned int sun4d_build_irq(struct linux_sbus_device *sdev, int irq)
+unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq)
 {
 	int sbusl = pil_to_sbus[irq];
-	
+
 	if (sbusl)
-		return ((sdev->my_bus->board + 1) << 5) + (sbusl << 2) + sdev->slot;
+		return ((sdev->bus->board + 1) << 5) + (sbusl << 2) + sdev->slot;
 	else
 		return irq;
 }
@@ -369,7 +369,7 @@
 void __init sun4d_distribute_irqs(void)
 {
 #ifdef DISTRIBUTE_IRQS
-	struct linux_sbus *sbus;
+	struct sbus_bus *sbus;
 	unsigned long sbus_serving_map;
 
 	sbus_serving_map = cpu_present_map;
@@ -401,7 +401,7 @@
 		set_sbi_tid(sbus->devid, sbus_tid[sbus->board] << 3);
 	}
 #else
-	struct linux_sbus *sbus;
+	struct sbus_bus *sbus;
 	int cpuid = cpu_logical_map(1);
 
 	if (cpuid == -1)
@@ -436,16 +436,19 @@
 	int irq;
 	extern struct prom_cpuinfo linux_cpus[NR_CPUS];
 	int cpu;
+	struct resource r;
 
 	/* Map the User Timer registers. */
+	memset(&r, 0, sizeof(r));
 #ifdef __SMP__
-	sun4d_timers = sparc_alloc_io(CSR_BASE(boot_cpu_id)+BW_TIMER_LIMIT, 0,
-				      PAGE_SIZE, "user timer", 0xf, 0x0);
+	r.start = CSR_BASE(boot_cpu_id)+BW_TIMER_LIMIT;
 #else
-	sun4d_timers = sparc_alloc_io(CSR_BASE(0)+BW_TIMER_LIMIT, 0,
-				      PAGE_SIZE, "user timer", 0xf, 0x0);
+	r.start = CSR_BASE(0)+BW_TIMER_LIMIT;
 #endif
-    
+	r.flags = 0xf;
+	sun4d_timers = (struct sun4d_timer_regs *) sbus_ioremap(&r, 0,
+	    PAGE_SIZE, "user timer");
+
 	sun4d_timers->l10_timer_limit =  (((1000000/HZ) + 1) << 10);
 	master_l10_counter = &sun4d_timers->l10_cur_count;
 	master_l10_limit = &sun4d_timers->l10_timer_limit;
@@ -494,7 +497,7 @@
 
 void __init sun4d_init_sbi_irq(void)
 {
-	struct linux_sbus *sbus;
+	struct sbus_bus *sbus;
 	unsigned mask;
 
 	nsbi = 0;
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sun4d_smp.c linux/arch/sparc/kernel/sun4d_smp.c
--- v2.3.34/linux/arch/sparc/kernel/sun4d_smp.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc/kernel/sun4d_smp.c	Mon Dec 20 22:05:52 1999
@@ -99,6 +99,14 @@
 	local_flush_cache_all();
 	local_flush_tlb_all();
 
+	/*
+	 * Unblock the master CPU _only_ when the scheduler state
+	 * of all secondary CPUs will be up-to-date, so after
+	 * the SMP initialization the master will be just allowed
+	 * to call the scheduler code.
+	 */
+	init_idle();
+
 	/* Get our local ticker going. */
 	smp_setup_percpu_timer();
 
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sun4m_irq.c linux/arch/sparc/kernel/sun4m_irq.c
--- v2.3.34/linux/arch/sparc/kernel/sun4m_irq.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/kernel/sun4m_irq.c	Mon Dec 20 22:05:52 1999
@@ -19,6 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/malloc.h>
 #include <linux/init.h>
+#include <linux/ioport.h>
 
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -225,6 +226,7 @@
 	int reg_count, irq, cpu;
 	struct linux_prom_registers cnt_regs[PROMREG_MAX];
 	int obio_node, cnt_node;
+	struct resource r;
 
 	cnt_node = 0;
 	if((obio_node =
@@ -250,18 +252,19 @@
 		cnt_regs[obio_node].reg_size = cnt_regs[obio_node-1].reg_size;
 		cnt_regs[obio_node].which_io = cnt_regs[obio_node-1].which_io;
 	}
-    
+
+	memset((char*)&r, 0, sizeof(struct resource));
 	/* Map the per-cpu Counter registers. */
-	sun4m_timers = sparc_alloc_io(cnt_regs[0].phys_addr, 0,
-				      PAGE_SIZE*SUN4M_NCPUS, "counters_percpu",
-				      cnt_regs[0].which_io, 0x0);
-    
+	r.flags = cnt_regs[0].which_io;
+	r.start = cnt_regs[0].phys_addr;
+	sun4m_timers = (struct sun4m_timer_regs *) sbus_ioremap(&r, 0,
+	    PAGE_SIZE*SUN4M_NCPUS, "sun4m_cpu_cnt");
 	/* Map the system Counter register. */
-	sparc_alloc_io(cnt_regs[4].phys_addr, 0,
-		       cnt_regs[4].reg_size,
-		       "counters_system",
-		       cnt_regs[4].which_io, 0x0);
-    
+	/* XXX Here we expect consequent calls to yeld adjusent maps. */
+	r.flags = cnt_regs[4].which_io;
+	r.start = cnt_regs[4].phys_addr;
+	sbus_ioremap(&r, 0, cnt_regs[4].reg_size, "sun4m_sys_cnt");
+
 	sun4m_timers->l10_timer_limit =  (((1000000/HZ) + 1) << 10);
 	master_l10_counter = &sun4m_timers->l10_cur_count;
 	master_l10_limit = &sun4m_timers->l10_timer_limit;
@@ -308,6 +311,7 @@
 	int ie_node,i;
 	struct linux_prom_registers int_regs[PROMREG_MAX];
 	int num_regs;
+	struct resource r;
     
 	__cli();
 	if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 ||
@@ -332,16 +336,18 @@
 		int_regs[ie_node].which_io = int_regs[ie_node-1].which_io;
 	}
 
+	memset((char *)&r, 0, sizeof(struct resource));
 	/* Map the interrupt registers for all possible cpus. */
-	sun4m_interrupts = sparc_alloc_io(int_regs[0].phys_addr, 0,
-					  PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu",
-					  int_regs[0].which_io, 0x0);
-    
+	r.flags = int_regs[0].which_io;
+	r.start = int_regs[0].phys_addr;
+	sun4m_interrupts = (struct sun4m_intregs *) sbus_ioremap(&r, 0,
+	    PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu");
+
 	/* Map the system interrupt control registers. */
-	sparc_alloc_io(int_regs[4].phys_addr, 0,
-		       int_regs[4].reg_size, "interrupts_system",
-		       int_regs[4].which_io, 0x0);
-    
+	r.flags = int_regs[4].which_io;
+	r.start = int_regs[4].phys_addr;
+	sbus_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system");
+
 	sun4m_interrupts->set = ~SUN4M_INT_MASKALL;
 	for (i=0; i<linux_num_cpus; i++)
 		sun4m_interrupts->cpu_intregs[i].clear = ~0x17fff;
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c
--- v2.3.34/linux/arch/sparc/kernel/sun4m_smp.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc/kernel/sun4m_smp.c	Mon Dec 20 22:05:52 1999
@@ -93,6 +93,14 @@
 	local_flush_cache_all();
 	local_flush_tlb_all();
 
+	/*
+	 * Unblock the master CPU _only_ when the scheduler state
+	 * of all secondary CPUs will be up-to-date, so after
+	 * the SMP initialization the master will be just allowed
+	 * to call the scheduler code.
+	 */
+	init_idle();
+
 	/* Allow master to continue. */
 	swap((unsigned long *)&cpu_callin_map[cpuid], 1);
 	local_flush_cache_all();
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sys_solaris.c linux/arch/sparc/kernel/sys_solaris.c
--- v2.3.34/linux/arch/sparc/kernel/sys_solaris.c	Sun Jan 26 02:07:08 1997
+++ linux/arch/sparc/kernel/sys_solaris.c	Mon Dec 20 22:05:52 1999
@@ -4,6 +4,7 @@
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
  */
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -24,7 +25,7 @@
 	current->exec_domain = lookup_exec_domain(PER_SVR4);
 
 	if (current->exec_domain && current->exec_domain->handler){
-		current->exec_domain->handler (regs);
+		current->exec_domain->handler (0, regs);
 
 		/* What is going on here?  Why do we do this? */
 
@@ -39,3 +40,16 @@
 	unlock_kernel();
 	return ret;
 }
+
+#ifndef CONFIG_SUNOS_EMUL
+asmlinkage int
+do_sunos_syscall (struct pt_regs *regs)
+{
+	static int cnt = 0;
+	if (++cnt < 10) printk ("SunOS binary emulation not compiled in\n");
+	lock_kernel();
+	force_sig (SIGSEGV, current);
+	unlock_kernel();
+	return 0;
+}
+#endif
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c
--- v2.3.34/linux/arch/sparc/kernel/sys_sparc.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/kernel/sys_sparc.c	Tue Dec 21 21:56:42 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.53 1999/08/14 03:51:25 anton Exp $
+/* $Id: sys_sparc.c,v 1.55 1999/12/21 14:09:09 jj Exp $
  * linux/arch/sparc/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -176,26 +176,34 @@
 }
 
 /* Linux version of mmap */
-asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
+static unsigned long do_mmap2(unsigned long addr, unsigned long len,
 	unsigned long prot, unsigned long flags, unsigned long fd,
-	unsigned long off)
+	unsigned long pgoff)
 {
 	struct file * file = NULL;
 	unsigned long retval = -EBADF;
 
-	down(&current->mm->mmap_sem);
-	lock_kernel();
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
 		if (!file)
 			goto out;
 	}
+
+	down(&current->mm->mmap_sem);
+	lock_kernel();
 	retval = -ENOMEM;
 	len = PAGE_ALIGN(len);
-	if(!(flags & MAP_FIXED) && !addr) {
-		addr = get_unmapped_area(addr, len);
+	if(!(flags & MAP_FIXED) &&
+	   (!addr || (ARCH_SUN4C_SUN4 &&
+		      (addr >= 0x20000000 && addr < 0xe0000000)))) {
+		addr = get_unmapped_area(0, len);
 		if(!addr)
 			goto out_putf;
+		if (ARCH_SUN4C_SUN4 &&
+		    (addr >= 0x20000000 && addr < 0xe0000000)) {
+			retval = -EINVAL;
+			goto out_putf;
+		}
 	}
 
 	/* See asm-sparc/uaccess.h */
@@ -203,24 +211,30 @@
 	if((len > (TASK_SIZE - PAGE_SIZE)) || (addr > (TASK_SIZE-len-PAGE_SIZE)))
 		goto out_putf;
 
-	if(ARCH_SUN4C_SUN4) {
-		if(((addr >= 0x20000000) && (addr < 0xe0000000))) {
-			/* VM hole */
-			retval = current->mm->brk;
-			goto out_putf;
-		}
-	}
-
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	retval = do_mmap(file, addr, len, prot, flags, off);
+	retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 
 out_putf:
+	unlock_kernel();
+	up(&current->mm->mmap_sem);
 	if (file)
 		fput(file);
 out:
-	unlock_kernel();
-	up(&current->mm->mmap_sem);
 	return retval;
+}
+
+asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
+	unsigned long prot, unsigned long flags, unsigned long fd,
+	unsigned long pgoff)
+{
+	return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
+	unsigned long prot, unsigned long flags, unsigned long fd,
+	unsigned long off)
+{
+	return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
 }
 
 /* we come to here via sys_nis_syscall so it can setup the regs argument */
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.3.34/linux/arch/sparc/kernel/sys_sunos.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/kernel/sys_sunos.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.104 1999/08/31 12:30:50 anton Exp $
+/* $Id: sys_sunos.c,v 1.106 1999/12/16 11:57:27 anton Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -85,10 +85,17 @@
 	}
 
 	retval = -ENOMEM;
-	if(!(flags & MAP_FIXED) && !addr) {
-		addr = get_unmapped_area(addr, len);
+	if(!(flags & MAP_FIXED) &&
+	   (!addr || (ARCH_SUN4C_SUN4 &&
+		      (addr >= 0x20000000 && addr < 0xe0000000)))) {
+		addr = get_unmapped_area(0, len);
 		if(!addr)
 			goto out_putf;
+		if (ARCH_SUN4C_SUN4 &&
+		    (addr >= 0x20000000 && addr < 0xe0000000)) {
+			retval = -EINVAL;
+			goto out_putf;
+		}
 	}
 	/* If this is ld.so or a shared library doing an mmap
 	 * of /dev/zero, transform it into an anonymous mapping.
@@ -111,13 +118,6 @@
 	if((len > (TASK_SIZE - PAGE_SIZE)) || (addr > (TASK_SIZE-len-PAGE_SIZE)))
 		goto out_putf;
 
-	if(ARCH_SUN4C_SUN4) {
-		if(((addr >= 0x20000000) && (addr < 0xe0000000))) {
-			retval = current->mm->brk;
-			goto out_putf;
-		}
-	}
-
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	retval = do_mmap(file, addr, len, prot, flags, off);
 	if(!ret_type)
@@ -195,7 +195,7 @@
 	 * simple, it hopefully works in most obvious cases.. Easy to
 	 * fool it, but this should catch most mistakes.
 	 */
-	freepages = atomic_read(&buffermem) >> PAGE_SHIFT;
+	freepages = atomic_read(&buffermem_pages) >> PAGE_SHIFT;
 	freepages += atomic_read(&page_cache_size);
 	freepages >>= 1;
 	freepages += nr_free_pages;
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S
--- v2.3.34/linux/arch/sparc/kernel/systbls.S	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/kernel/systbls.S	Tue Dec 21 21:56:42 1999
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.84 1999/08/14 03:51:29 anton Exp $
+/* $Id: systbls.S,v 1.88 1999/12/21 14:09:06 jj Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -9,6 +9,8 @@
  * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  */
 
+#include <linux/config.h>
+
 	.data
 	.align 4
 
@@ -27,12 +29,12 @@
 /*40*/	.long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall
 /*45*/	.long sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
 /*50*/	.long sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl
-/*55*/	.long sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve
-/*60*/	.long sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize
+/*55*/	.long sys_reboot, sys_mmap2, sys_symlink, sys_readlink, sys_execve
+/*60*/	.long sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize
 /*65*/	.long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_nis_syscall
 /*70*/	.long sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect
-/*75*/	.long sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys_getgroups
-/*80*/	.long sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall
+/*75*/	.long sys_nis_syscall, sys_vhangup, sys_truncate64, sys_nis_syscall, sys_getgroups
+/*80*/	.long sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_ftruncate64
 /*85*/	.long sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall
 /*90*/	.long sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall
 /*95*/	.long sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
@@ -42,8 +44,8 @@
 /*115*/	.long sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_getcwd
 /*120*/	.long sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
 /*125*/	.long sys_nis_syscall, sys_setreuid, sys_setregid, sys_rename, sys_truncate
-/*130*/	.long sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-/*135*/	.long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_nis_syscall
+/*130*/	.long sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall
+/*135*/	.long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_stat64
 /*140*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
 /*145*/	.long sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
 /*150*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall
@@ -70,6 +72,7 @@
 /*250*/	.long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
 /*255*/	.long sys_aplib, sys_nis_syscall
 
+#ifdef CONFIG_SUNOS_EMUL
 	/* Now the SunOS syscall table. */
 
 	.align 4
@@ -162,3 +165,5 @@
 	.long sunos_nosys, sunos_nosys
 /*250*/	.long sunos_nosys, sunos_nosys, sunos_nosys
 	.long sunos_nosys, sunos_nosys, sys_aplib
+
+#endif
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c
--- v2.3.34/linux/arch/sparc/kernel/time.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/kernel/time.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.46 1999/08/31 13:11:26 anton Exp $
+/* $Id: time.c,v 1.49 1999/11/17 07:34:07 zaitcev Exp $
  * linux/arch/sparc/kernel/time.c
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -26,6 +26,7 @@
 #include <linux/timex.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/ioport.h>
 
 #include <asm/oplib.h>
 #include <asm/segment.h>
@@ -38,6 +39,7 @@
 #include <asm/machines.h>
 #include <asm/sun4paddr.h>
 #include <asm/page.h>
+#include <asm/pcic.h>
 
 extern rwlock_t xtime_lock;
 
@@ -207,13 +209,14 @@
 {
 #ifdef CONFIG_SUN4
 	int temp;
+	struct resource r;
 
+	memset(&r, 0, sizeof(r));
 	if( idprom->id_machtype == (SM_SUN4 | SM_4_330) ) {
 		sp_clock_typ = MSTK48T02;
-		mstk48t02_regs = (unsigned long) 
-				sparc_alloc_io(sun4_clock_physaddr, 0,
-				       sizeof(struct mostek48t02),
-				       "clock", 0x0, 0x0);
+		r.start = sun4_clock_physaddr;
+		mstk48t02_regs = sbus_ioremap(&r, 0,
+				       sizeof(struct mostek48t02), 0);
 		mstk48t08_regs = 0;  /* To catch weirdness */
 		intersil_clock = 0;  /* just in case */
 
@@ -224,10 +227,9 @@
 		/* intersil setup code */
 		printk("Clock: INTERSIL at %8x ",sun4_clock_physaddr);
 		sp_clock_typ = INTERSIL;
+		r.start = sun4_clock_physaddr;
 		intersil_clock = (struct intersil *) 
-			sparc_alloc_io(sun4_clock_physaddr, 0,
-				       sizeof(*intersil_clock),
-			       	       "clock", 0x0, 0x0);
+		    sparc_ioremap(&r, 0, sizeof(*intersil_clock), "intersil");
 		mstk48t02_regs = 0;  /* just be sure */
 		mstk48t08_regs = 0;  /* ditto */
 		/* initialise the clock */
@@ -256,8 +258,10 @@
 	struct linux_prom_registers clk_reg[2];
 	char model[128];
 	register int node, cpuunit, bootbus;
+	struct resource r;
 
 	cpuunit = bootbus = 0;
+	memset(&r, 0, sizeof(r));
 
 	/* Determine the correct starting PROM node for the probe. */
 	node = prom_getchild(prom_root_node);
@@ -297,10 +301,10 @@
 		else
 			prom_apply_obio_ranges(clk_reg, 1);
 		/* Map the clock register io area read-only */
-		mstk48t02_regs = (unsigned long) 
-			sparc_alloc_io(clk_reg[0].phys_addr,
-				       (void *) 0, sizeof(struct mostek48t02),
-				       "clock", clk_reg[0].which_io, 0x0);
+		r.flags = clk_reg[0].which_io;
+		r.start = clk_reg[0].phys_addr;
+		mstk48t02_regs = sbus_ioremap(&r, 0,
+		    sizeof(struct mostek48t02), "mk48t02");
 		mstk48t08_regs = 0;  /* To catch weirdness */
 	} else if (strcmp(model, "mk48t08") == 0) {
 		sp_clock_typ = MSTK48T08;
@@ -314,10 +318,11 @@
 		else
 			prom_apply_obio_ranges(clk_reg, 1);
 		/* Map the clock register io area read-only */
-		mstk48t08_regs = (struct mostek48t08 *)
-			sparc_alloc_io(clk_reg[0].phys_addr,
-				       (void *) 0, sizeof(*mstk48t08_regs),
-				       "clock", clk_reg[0].which_io, 0x0);
+		/* XXX r/o attribute is somewhere in r.flags */
+		r.flags = clk_reg[0].which_io;
+		r.start = clk_reg[0].phys_addr;
+		mstk48t08_regs = (struct mostek48t08 *) sbus_ioremap(&r, 0,
+		    sizeof(struct mostek48t08), "mk48t08");
 
 		mstk48t02_regs = (unsigned long)&mstk48t08_regs->regs;
 	} else {
@@ -420,7 +425,7 @@
 {
 #ifdef CONFIG_PCI
 	extern void pci_time_init(void);
-	if (pci_present()) {
+	if (pcic_present()) {
 		pci_time_init();
 		return;
 	}
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/lib/Makefile linux/arch/sparc/lib/Makefile
--- v2.3.34/linux/arch/sparc/lib/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/arch/sparc/lib/Makefile	Mon Dec 20 22:05:52 1999
@@ -1,11 +1,12 @@
-# $Id: Makefile,v 1.28 1999/03/21 06:37:44 davem Exp $
+# $Id: Makefile,v 1.30 1999/12/21 04:02:18 davem Exp $
 # Makefile for Sparc library files..
 #
 
 OBJS  = mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \
         strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \
 	strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
-	copy_user.o locks.o atomic.o bitops.o debuglocks.o lshrdi3.o
+	copy_user.o locks.o atomic.o bitops.o debuglocks.o lshrdi3.o \
+	ashldi3.o
 
 ifdef CONFIG_SMP
 OBJS += irqlock.o
@@ -88,6 +89,9 @@
 
 ashrdi3.o: ashrdi3.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o ashrdi3.o ashrdi3.S
+
+ashldi3.o: ashldi3.S
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o ashldi3.o ashldi3.S
 
 lshrdi3.o: lshrdi3.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o lshrdi3.o lshrdi3.S
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/lib/ashldi3.S linux/arch/sparc/lib/ashldi3.S
--- v2.3.34/linux/arch/sparc/lib/ashldi3.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc/lib/ashldi3.S	Mon Dec 20 22:05:52 1999
@@ -0,0 +1,36 @@
+/* $Id: ashldi3.S,v 1.2 1999/11/19 04:11:46 davem Exp $
+ * ashldi3.S:	GCC emits these for certain drivers playing
+ *		with long longs.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include <asm/cprefix.h>
+
+	.text
+	.align	4
+	.globl	C_LABEL(__ashldi3)
+C_LABEL(__ashldi3):
+	cmp	%o2, 0
+	be	9f
+	 mov	0x20, %g2
+
+	sub	%g2, %o2, %g2
+	cmp	%g2, 0
+	bg	7f
+	 sll	%o0, %o2, %g3
+
+	neg	%g2
+	clr	%o5
+	b	8f
+	 sll	%o1, %g2, %o4
+7:
+	srl	%o1, %g2, %g2
+	sll	%o1, %o2, %o5
+	or	%g3, %g2, %o4
+8:
+	mov	%o4, %o0
+	mov	%o5, %o1
+9:
+	retl
+	 nop
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/lib/ashrdi3.S linux/arch/sparc/lib/ashrdi3.S
--- v2.3.34/linux/arch/sparc/lib/ashrdi3.S	Sat Nov  9 00:12:00 1996
+++ linux/arch/sparc/lib/ashrdi3.S	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ashrdi3.S,v 1.3 1996/09/07 23:18:10 davem Exp $
+/* $Id: ashrdi3.S,v 1.4 1999/11/19 04:11:49 davem Exp $
  * ashrdi3.S:	The filesystem code creates all kinds of references to
  *              this little routine on the sparc with gcc.
  *
@@ -7,7 +7,9 @@
 
 #include <asm/cprefix.h>
 
-		.globl C_LABEL(__ashrdi3)
+	.text
+	.align	4
+	.globl C_LABEL(__ashrdi3)
 C_LABEL(__ashrdi3):
 	tst	%o2
 	be	3f
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/lib/strlen_user.S linux/arch/sparc/lib/strlen_user.S
--- v2.3.34/linux/arch/sparc/lib/strlen_user.S	Fri Dec 13 01:37:31 1996
+++ linux/arch/sparc/lib/strlen_user.S	Mon Dec 20 22:05:52 1999
@@ -47,8 +47,11 @@
 	 mov	3, %o0
 
 	.align 4
-	.global C_LABEL(__strlen_user)
+	.global C_LABEL(__strlen_user), C_LABEL(__strnlen_user)
 C_LABEL(__strlen_user):
+	sethi	%hi(32768), %o1
+C_LABEL(__strnlen_user):
+	mov	%o1, %g1
 	mov	%o0, %o1
 	andcc	%o0, 3, %g0
 	bne	10b
@@ -63,11 +66,16 @@
 2:
 	sub	%o5, %o2, %o4
 	andcc	%o4, %o3, %g0
-	be	13b
+	bne	82f
 	 add	%o0, 4, %o0
+	sub	%o0, %o1, %g2
+81:	cmp	%g2, %g1
+	blu	13b
+	 mov	%o0, %o4
+	ba,a	1f
 
 	/* Check every byte. */
-	srl	%o5, 24, %g5
+82:	srl	%o5, 24, %g5
 	andcc	%g5, 0xff, %g0
 	be	1f
 	 add	%o0, -3, %o4
@@ -80,9 +88,9 @@
 	be	1f
 	 add	%o4, 1, %o4
 	andcc	%o5, 0xff, %g0
-	bne,a	2b
-14:
-	 ld	[%o0], %o5
+	bne	81b
+	 sub	%o0, %o1, %g2
+
 	add	%o4, 1, %o4
 1:
 	retl
@@ -101,4 +109,3 @@
 	.word	11b, 9b
 	.word	12b, 9b
 	.word	13b, 9b
-	.word	14b, 9b
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/Makefile linux/arch/sparc/mm/Makefile
--- v2.3.34/linux/arch/sparc/mm/Makefile	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/mm/Makefile	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.34 1999/08/14 03:51:42 anton Exp $
+# $Id: Makefile,v 1.35 1999/10/09 05:32:01 zaitcev Exp $
 # Makefile for the linux Sparc-specific parts of the memory manager.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -15,7 +15,7 @@
 ifeq ($(CONFIG_SUN4),y)
 O_OBJS	 += nosrmmu.o
 else
-O_OBJS	 += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o
+O_OBJS	 += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o swift.o
 endif
 ifdef CONFIG_SMP
 O_OBJS   += nosun4c.o
@@ -33,3 +33,6 @@
 
 tsunami.o: tsunami.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o tsunami.o tsunami.S
+
+swift.o: swift.S
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o swift.o swift.S
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c
--- v2.3.34/linux/arch/sparc/mm/fault.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/mm/fault.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.107 1999/08/14 03:51:46 anton Exp $
+/* $Id: fault.c,v 1.111 1999/10/24 13:45:59 anton Exp $
  * fault.c:  Page fault handlers for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -146,10 +146,11 @@
 		printk(KERN_ALERT "Unable to handle kernel paging request "
 		       "at virtual address %08lx\n", address);
 	}
-	printk(KERN_ALERT "tsk->mm->context = %08lx\n",
-	       (unsigned long) tsk->mm->context);
-	printk(KERN_ALERT "tsk->mm->pgd = %08lx\n",
-	       (unsigned long) tsk->mm->pgd);
+	printk(KERN_ALERT "tsk->{mm,active_mm}->context = %08lx\n",
+		(tsk->mm ? tsk->mm->context : tsk->active_mm->context));
+	printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %08lx\n",
+		(tsk->mm ? (unsigned long) tsk->mm->pgd :
+		 	(unsigned long) tsk->active_mm->pgd));
 	die_if_kernel("Oops", regs);
 }
 
@@ -309,8 +310,18 @@
 	pgd_t *pgdp;
 	pte_t *ptep;
 
-	if (text_fault)
+	if (text_fault) {
 		address = regs->pc;
+	} else if (!write &&
+		   !(regs->psr & PSR_PS)) {
+		unsigned int insn, *ip;
+
+		ip = (unsigned int *)regs->pc;
+		if (! get_user(insn, ip)) {
+			if ((insn & 0xc1680000) == 0xc0680000)
+				write = 1;
+		}
+	}
 
 	pgdp = sun4c_pgd_offset(mm, address);
 	ptep = sun4c_pte_offset((pmd_t *) pgdp, address);
@@ -319,28 +330,36 @@
 	    if (write) {
 		if ((pte_val(*ptep) & (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_PRESENT))
 				   == (_SUN4C_PAGE_WRITE|_SUN4C_PAGE_PRESENT)) {
+			unsigned long flags;
 
 			*ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED |
 				      _SUN4C_PAGE_MODIFIED |
 				      _SUN4C_PAGE_VALID |
 				      _SUN4C_PAGE_DIRTY);
 
+			save_and_cli(flags);
 			if (sun4c_get_segmap(address) != invalid_segment) {
 				sun4c_put_pte(address, pte_val(*ptep));
+				restore_flags(flags);
 				return;
 			}
+			restore_flags(flags);
 		}
 	    } else {
 		if ((pte_val(*ptep) & (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT))
 				   == (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT)) {
+			unsigned long flags;
 
 			*ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED |
 				      _SUN4C_PAGE_VALID);
 
+			save_and_cli(flags);
 			if (sun4c_get_segmap(address) != invalid_segment) {
 				sun4c_put_pte(address, pte_val(*ptep));
+				restore_flags(flags);
 				return;
 			}
+			restore_flags(flags);
 		}
 	    }
 	}
@@ -415,31 +434,25 @@
 {
 	unsigned long sp;
 
-	lock_kernel();
 	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);
-	unlock_kernel();
 }
 
 void window_underflow_fault(unsigned long sp)
 {
-	lock_kernel();
 	if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
 		force_user_fault(sp + 0x38, 0);
 	force_user_fault(sp, 0);
-	unlock_kernel();
 }
 
 void window_ret_fault(struct pt_regs *regs)
 {
 	unsigned long sp;
 
-	lock_kernel();
 	sp = regs->u_regs[UREG_FP];
 	if(((sp + 0x38) & PAGE_MASK) != (sp & PAGE_MASK))
 		force_user_fault(sp + 0x38, 0);
 	force_user_fault(sp, 0);
-	unlock_kernel();
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/generic.c linux/arch/sparc/mm/generic.c
--- v2.3.34/linux/arch/sparc/mm/generic.c	Tue Dec  7 09:32:42 1999
+++ linux/arch/sparc/mm/generic.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: generic.c,v 1.6 1998/10/27 23:28:00 davem Exp $
+/* $Id: generic.c,v 1.8 1999/12/20 05:01:49 davem Exp $
  * generic.c: Generic Sparc mm routines that are not dependent upon
  *            MMU type but are Sparc specific.
  *
@@ -12,43 +12,22 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 
-
-/* Allocate a block of RAM which is aligned to its size.
- * This procedure can be used until the call to mem_init().
- */
-void *sparc_init_alloc(unsigned long *kbrk, unsigned long size)
-{
-        unsigned long mask = size - 1;
-        unsigned long ret;
-
-        if(!size)
-                return 0x0;
-        if(size & mask) {
-                prom_printf("panic: sparc_init_alloc botch\n");
-                prom_halt();
-        }
-        ret = (*kbrk + mask) & ~mask;
-        *kbrk = ret + size;
-        memset((void*) ret, 0, size);
-        return (void*) ret;
-}
-
 static inline void forget_pte(pte_t page)
 {
 	if (pte_none(page))
 		return;
 	if (pte_present(page)) {
-		unsigned long addr = pte_page(page);
-		if (MAP_NR(addr) >= max_mapnr || PageReserved(mem_map+MAP_NR(addr)))
+		unsigned long nr = pte_pagenr(page);
+		if (nr >= max_mapnr || PageReserved(mem_map+nr))
 			return;
 		/* 
 		 * free_page() used to be able to clear swap cache
 		 * entries.  We may now have to do it manually.  
 		 */
-		free_page_and_swap_cache(addr);
+		free_page_and_swap_cache(mem_map+nr);
 		return;
 	}
-	swap_free(pte_val(page));
+	swap_free(page);
 }
 
 /* Remap IO memory, the same way as remap_page_range(), but use
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- v2.3.34/linux/arch/sparc/mm/init.c	Fri Oct 22 13:21:46 1999
+++ linux/arch/sparc/mm/init.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.69 1999/09/06 22:56:17 ecd Exp $
+/*  $Id: init.c,v 1.71 1999/12/16 12:58:33 anton Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -22,6 +22,8 @@
 #include <linux/blk.h>
 #endif
 #include <linux/init.h>
+#include <linux/highmem.h>
+#include <linux/bootmem.h>
 
 #include <asm/system.h>
 #include <asm/segment.h>
@@ -30,22 +32,21 @@
 #include <asm/pgtable.h>
 #include <asm/vaddrs.h>
 
-/* Turn this off if you suspect some place in some physical memory hole
-   might get into page tables (something would be broken very much). */
-   
-#define FREE_UNUSED_MEM_MAP
-
 extern void show_net_buffers(void);
 
 unsigned long *sparc_valid_addr_bitmap;
 
+unsigned long phys_base;
+
 struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
 unsigned long sparc_unmapped_base;
 
 struct pgtable_cache_struct pgt_quicklists;
 
 /* References to section boundaries */
-extern char __init_begin, __init_end, etext;
+extern char __init_begin, __init_end, _start, _end, etext , edata;
+
+static unsigned long totalram_pages = 0;
 
 /*
  * BAD_PAGE is the page that is used for page faults when linux
@@ -62,50 +63,31 @@
  */
 pte_t *__bad_pagetable(void)
 {
-	memset((void *) EMPTY_PGT, 0, PAGE_SIZE);
-	return (pte_t *) EMPTY_PGT;
+	memset((void *) &empty_bad_page_table, 0, PAGE_SIZE);
+	return (pte_t *) &empty_bad_page_table;
 }
 
 pte_t __bad_page(void)
 {
-	memset((void *) EMPTY_PGE, 0, PAGE_SIZE);
-	return pte_mkdirty(mk_pte((unsigned long) EMPTY_PGE, PAGE_SHARED));
+	memset((void *) &empty_bad_page, 0, PAGE_SIZE);
+	return pte_mkdirty(mk_pte_phys((((unsigned long) &empty_bad_page) 
+					- PAGE_OFFSET + phys_base),
+				       PAGE_SHARED));
 }
 
 void show_mem(void)
 {
-	int free = 0,total = 0,reserved = 0;
-	int shared = 0, cached = 0;
-	struct page *page, *end;
-
-	printk("\nMem-info:\n");
+	printk("Mem-info:\n");
 	show_free_areas();
-	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-	for (page = mem_map, end = mem_map + max_mapnr;
-	     page < end; page++) {
-		if (PageSkip(page)) {
-			if (page->next_hash < page)
-				break;
-			page = page->next_hash;
-		}
-		total++;
-		if (PageReserved(page))
-			reserved++;
-		else if (PageSwapCache(page))
-			cached++;
-		else if (!atomic_read(&page->count))
-			free++;
-		else
-			shared += atomic_read(&page->count) - 1;
-	}
-	printk("%d pages of RAM\n",total);
-	printk("%d free pages\n",free);
-	printk("%d reserved pages\n",reserved);
-	printk("%d pages shared\n",shared);
-	printk("%d pages swap cached\n",cached);
-	printk("%ld page tables cached\n",pgtable_cache_size);
+	printk("Free swap:       %6dkB\n",
+	       nr_swap_pages << (PAGE_SHIFT-10));
+	printk("%ld pages of RAM\n", totalram_pages);
+	printk("%d free pages\n", nr_free_pages);
+	printk("%ld pages in page table cache\n",pgtable_cache_size);
+#ifndef __SMP__
 	if (sparc_cpu_model == sun4m || sparc_cpu_model == sun4d)
-		printk("%ld page dirs cached\n", pgd_cache_size);
+		printk("%ld entries in page dir cache\n",pgd_cache_size);
+#endif	
 	show_buffers();
 #ifdef CONFIG_NET
 	show_net_buffers();
@@ -114,12 +96,12 @@
 
 extern pgprot_t protection_map[16];
 
-unsigned long __init sparc_context_init(unsigned long start_mem, int numctx)
+void __init sparc_context_init(int numctx)
 {
 	int ctx;
 
-	ctx_list_pool = (struct ctx_list *) start_mem;
-	start_mem += (numctx * sizeof(struct ctx_list));
+	ctx_list_pool = __alloc_bootmem(numctx * sizeof(struct ctx_list), SMP_CACHE_BYTES, 0UL);
+
 	for(ctx = 0; ctx < numctx; ctx++) {
 		struct ctx_list *clist;
 
@@ -131,7 +113,98 @@
 	ctx_used.next = ctx_used.prev = &ctx_used;
 	for(ctx = 0; ctx < numctx; ctx++)
 		add_to_free_ctxlist(ctx_list_pool + ctx);
-	return start_mem;
+}
+
+#undef DEBUG_BOOTMEM
+
+extern unsigned long cmdline_memory_size;
+
+unsigned long __init bootmem_init(void)
+{
+	unsigned long bootmap_size, start_pfn, end_pfn;
+	unsigned long end_of_phys_memory = 0UL;
+	int i;
+
+	/* XXX It is a bit ambiguous here, whether we should
+	 * XXX treat the user specified mem=xxx as total wanted
+	 * XXX physical memory, or as a limit to the upper
+	 * XXX physical address we allow.  For now it is the
+	 * XXX latter. -DaveM
+	 */
+#ifdef DEBUG_BOOTMEM
+	prom_printf("bootmem_init: Scan sp_banks,  ");
+#endif
+	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
+		end_of_phys_memory = sp_banks[i].base_addr +
+			sp_banks[i].num_bytes;
+		if (cmdline_memory_size) {
+			if (end_of_phys_memory > cmdline_memory_size) {
+				if (cmdline_memory_size > sp_banks[i].base_addr) {
+					end_of_phys_memory =
+						sp_banks[i-1].base_addr +
+						sp_banks[i-1].num_bytes;
+					sp_banks[i].base_addr = 0xdeadbeef;
+					sp_banks[i].num_bytes = 0;
+				} else {
+					sp_banks[i].num_bytes -=
+						(end_of_phys_memory -
+						 cmdline_memory_size);
+					end_of_phys_memory = cmdline_memory_size;
+					sp_banks[++i].base_addr = 0xdeadbeef;
+					sp_banks[i].num_bytes = 0;
+				}
+				break;
+			}
+		}
+	}
+
+	/* Start with page aligned address of last symbol in kernel
+	 * image.  
+	 */
+	start_pfn  = PAGE_ALIGN((unsigned long) &_end) - PAGE_OFFSET;
+
+	/* Adjust up to the physical address where the kernel begins. */
+	start_pfn += phys_base;
+
+	/* Now shift down to get the real physical page frame number. */
+	start_pfn >>= PAGE_SHIFT;
+
+	end_pfn = end_of_phys_memory >> PAGE_SHIFT;
+
+	/* Initialize the boot-time allocator. */
+#ifdef DEBUG_BOOTMEM
+	prom_printf("init_bootmem(spfn[%lx],epfn[%lx])\n",
+		    start_pfn, end_pfn);
+#endif
+	bootmap_size = init_bootmem(start_pfn, end_pfn);
+
+	/* Now register the available physical memory with the
+	 * allocator.
+	 */
+	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
+#ifdef DEBUG_BOOTMEM
+		prom_printf("free_bootmem: base[%lx] size[%lx]\n",
+			    sp_banks[i].base_addr,
+			    sp_banks[i].num_bytes);
+#endif
+		free_bootmem(sp_banks[i].base_addr,
+			     sp_banks[i].num_bytes);
+	}
+
+	/* Reserve the kernel text/data/bss and the bootmem bitmap. */
+#ifdef DEBUG_BOOTMEM
+	prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
+		    phys_base,
+		    (((start_pfn << PAGE_SHIFT) +
+		      bootmap_size) - phys_base));
+#endif
+	reserve_bootmem(phys_base, (((start_pfn << PAGE_SHIFT) +
+				     bootmap_size) - phys_base));
+
+#ifdef DEBUG_BOOTMEM
+	prom_printf("init_bootmem: return end_pfn[%lx]\n", end_pfn);
+#endif
+	return end_pfn;
 }
 
 /*
@@ -139,31 +212,32 @@
  * init routine based upon the Sun model type on the Sparc.
  *
  */
-extern unsigned long sun4c_paging_init(unsigned long, unsigned long);
-extern unsigned long srmmu_paging_init(unsigned long, unsigned long);
-extern unsigned long device_scan(unsigned long);
+extern void sun4c_paging_init(void);
+extern void srmmu_paging_init(void);
+extern void device_scan(void);
+
+unsigned long last_valid_pfn;
 
-unsigned long __init
-paging_init(unsigned long start_mem, unsigned long end_mem)
+void __init paging_init(void)
 {
 	switch(sparc_cpu_model) {
 	case sun4c:
 	case sun4e:
 	case sun4:
-		start_mem = sun4c_paging_init(start_mem, end_mem);
+		sun4c_paging_init();
 		sparc_unmapped_base = 0xe0000000;
 		BTFIXUPSET_SETHI(sparc_unmapped_base, 0xe0000000);
 		break;
 	case sun4m:
 	case sun4d:
-		start_mem = srmmu_paging_init(start_mem, end_mem);
+		srmmu_paging_init();
 		sparc_unmapped_base = 0x50000000;
 		BTFIXUPSET_SETHI(sparc_unmapped_base, 0x50000000);
 		break;
 
 	case ap1000:
 #if CONFIG_AP1000
-		start_mem = apmmu_paging_init(start_mem, end_mem);
+		apmmu_paging_init();
 		sparc_unmapped_base = 0x50000000;
 		BTFIXUPSET_SETHI(sparc_unmapped_base, 0x50000000);
 		break;
@@ -194,74 +268,121 @@
 	protection_map[14] = PAGE_SHARED;
 	protection_map[15] = PAGE_SHARED;
 	btfixup();
-	return device_scan(start_mem);
+	device_scan();
 }
 
 struct cache_palias *sparc_aliases;
 
-extern void srmmu_frob_mem_map(unsigned long);
+static void __init taint_real_pages(void)
+{
+	int i;
 
-int physmem_mapped_contig __initdata = 1;
+	for (i = 0; sp_banks[i].num_bytes; i++) {
+		unsigned long start, end;
 
-static void __init taint_real_pages(unsigned long start_mem, unsigned long end_mem)
+		start = sp_banks[i].base_addr;
+		end = start +
+			sp_banks[i].num_bytes;
+		while (start < end) {
+			set_bit (start >> 20,
+				sparc_valid_addr_bitmap);
+				start += PAGE_SIZE;
+		}
+	}
+}
+
+void __init free_mem_map_range(struct page *first, struct page *last)
 {
-	unsigned long addr, tmp2 = 0;
+	first = (struct page *) PAGE_ALIGN((unsigned long)first);
+	last  = (struct page *) ((unsigned long)last & PAGE_MASK);
+#ifdef DEBUG_BOOTMEM
+	prom_printf("[%p,%p] ", first, last);
+#endif
+	while (first < last) {
+		ClearPageReserved(mem_map + MAP_NR(first));
+		set_page_count(mem_map + MAP_NR(first), 1);
+		free_page((unsigned long)first);
+		totalram_pages++;
+		num_physpages++;
 
-	if(physmem_mapped_contig) {
-		for(addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) {
-			if(addr >= KERNBASE && addr < start_mem)
-				addr = start_mem;
-			for(tmp2=0; sp_banks[tmp2].num_bytes != 0; tmp2++) {
-				unsigned long phys_addr = (addr - PAGE_OFFSET);
-				unsigned long base = sp_banks[tmp2].base_addr;
-				unsigned long limit = base + sp_banks[tmp2].num_bytes;
-
-				if((phys_addr >= base) && (phys_addr < limit) &&
-				   ((phys_addr + PAGE_SIZE) < limit)) {
-					mem_map[MAP_NR(addr)].flags &= ~(1<<PG_reserved);
-					set_bit(MAP_NR(addr) >> 8, sparc_valid_addr_bitmap);
-				}
-			}
-		}
-	} else {
-		if((sparc_cpu_model == sun4m) || (sparc_cpu_model == sun4d)) {
-			srmmu_frob_mem_map(start_mem);
+		first = (struct page *)((unsigned long)first + PAGE_SIZE);
+	}
+}
+
+/* Walk through holes in sp_banks regions, if the mem_map array
+ * areas representing those holes consume a page or more, free
+ * up such pages.  This helps a lot on machines where physical
+ * ram is configured such that it begins at some hugh value.
+ *
+ * The sp_banks array is sorted by base address.
+ */
+void __init free_unused_mem_map(void)
+{
+	int i;
+
+#ifdef DEBUG_BOOTMEM
+	prom_printf("free_unused_mem_map: ");
+#endif
+	for (i = 0; sp_banks[i].num_bytes; i++) {
+		if (i == 0) {
+			struct page *first, *last;
+
+			first = mem_map;
+			last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT];
+			free_mem_map_range(first, last);
 		} else {
-			for(addr = start_mem; addr < end_mem; addr += PAGE_SIZE) {
-				mem_map[MAP_NR(addr)].flags &= ~(1<<PG_reserved);
-				set_bit(MAP_NR(addr) >> 8, sparc_valid_addr_bitmap);
+			struct page *first, *last;
+			unsigned long prev_end;
+
+			prev_end = sp_banks[i-1].base_addr +
+				sp_banks[i-1].num_bytes;
+			prev_end = PAGE_ALIGN(prev_end);
+			first = &mem_map[prev_end >> PAGE_SHIFT];
+			last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT];
+
+			free_mem_map_range(first, last);
+
+			if (!sp_banks[i+1].num_bytes) {
+				prev_end = sp_banks[i].base_addr +
+					sp_banks[i].num_bytes;
+				first = &mem_map[prev_end >> PAGE_SHIFT];
+				last = &mem_map[last_valid_pfn];
+				free_mem_map_range(first, last);
 			}
 		}
 	}
+#ifdef DEBUG_BOOTMEM
+	prom_printf("\n");
+#endif
 }
 
-void __init mem_init(unsigned long start_mem, unsigned long end_mem)
+void __init mem_init(void)
 {
 	int codepages = 0;
 	int datapages = 0;
 	int initpages = 0; 
 	int i;
-	unsigned long addr;
-	struct page *page, *end;
+	unsigned long addr, last;
 
 	/* Saves us work later. */
 	memset((void *) ZERO_PAGE(0), 0, PAGE_SIZE);
 
-	end_mem &= PAGE_MASK;
-	max_mapnr = MAP_NR(end_mem);
-	high_memory = (void *) end_mem;
-	
-	sparc_valid_addr_bitmap = (unsigned long *)start_mem;
-	i = max_mapnr >> (8 + 5);
+	i = last_valid_pfn >> (8 + 5);
 	i += 1;
-	memset(sparc_valid_addr_bitmap, 0, i << 2);
-	start_mem += i << 2;
 
-	start_mem = PAGE_ALIGN(start_mem);
-	num_physpages = 0;
+	sparc_valid_addr_bitmap = (unsigned long *)
+		__alloc_bootmem(i << 2, SMP_CACHE_BYTES, 0UL);
+
+	if (sparc_valid_addr_bitmap == NULL) {
+		prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
+		prom_halt();
+	}
+	memset(sparc_valid_addr_bitmap, 0, i << 2);
 
 	addr = KERNBASE;
-	while(addr < start_mem) {
+	last = PAGE_ALIGN((unsigned long)&_end);
+	/* fix this */
+	while(addr < last) {
 #ifdef CONFIG_BLK_DEV_INITRD
 		if (initrd_below_start_ok && addr >= initrd_start && addr < initrd_end)
 			mem_map[MAP_NR(addr)].flags &= ~(1<<PG_reserved);
@@ -272,63 +393,31 @@
 		addr += PAGE_SIZE;
 	}
 
-	taint_real_pages(start_mem, end_mem);
-	
-#ifdef FREE_UNUSED_MEM_MAP
-	end = mem_map + max_mapnr;
-	for (page = mem_map; page < end; page++) {
-		if (PageSkip(page)) {
-			unsigned long low, high;
-
-			/* See srmmu_frob_mem_map() for why this is done.  -DaveM */
-			page++;
-
-			low = PAGE_ALIGN((unsigned long)(page+1));
-			if (page->next_hash < page)
-				high = ((unsigned long)end) & PAGE_MASK;
-			else
-				high = ((unsigned long)page->next_hash) & PAGE_MASK;
-			while (low < high) {
-				mem_map[MAP_NR(low)].flags &= ~(1<<PG_reserved);
-				low += PAGE_SIZE;
-			}
-		}
-	}
-#endif
-	
-	for (addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) {
-		if (PageSkip(mem_map + MAP_NR(addr))) {
-			unsigned long next = mem_map[MAP_NR(addr)].next_hash - mem_map;
+	taint_real_pages();
 
-			next = (next << PAGE_SHIFT) + PAGE_OFFSET;
-			if (next < addr || next >= end_mem)
-				break;
-			addr = next;
-		}
-		num_physpages++;
-		if(PageReserved(mem_map + MAP_NR(addr))) {
-			if ((addr < (unsigned long) &etext) && (addr >= KERNBASE))
-				codepages++;
-			else if((addr >= (unsigned long)&__init_begin && addr < (unsigned long)&__init_end))
-				initpages++;
-			else if((addr < start_mem) && (addr >= KERNBASE))
-				datapages++;
-			continue;
-		}
-		atomic_set(&mem_map[MAP_NR(addr)].count, 1);
-#ifdef CONFIG_BLK_DEV_INITRD
-		if (!initrd_start ||
-		    (addr < initrd_start || addr >= initrd_end))
+#ifdef DEBUG_BOOTMEM
+	prom_printf("mem_init: Calling free_all_bootmem().\n");
 #endif
-			free_page(addr);
-	}
+	num_physpages = totalram_pages = free_all_bootmem();
+
+	free_unused_mem_map();
+
+	max_mapnr = last_valid_pfn;
+	high_memory = __va(last_valid_pfn << PAGE_SHIFT);
+
+	codepages = (((unsigned long) &etext) - ((unsigned long)&_start));
+	codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT;
+	datapages = (((unsigned long) &edata) - ((unsigned long)&etext));
+	datapages = PAGE_ALIGN(datapages) >> PAGE_SHIFT;
+	initpages = (((unsigned long) &__init_end) - ((unsigned long) &__init_begin));
+	initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT;
 
 	printk("Memory: %dk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n",
 	       nr_free_pages << (PAGE_SHIFT-10),
 	       codepages << (PAGE_SHIFT-10),
 	       datapages << (PAGE_SHIFT-10), 
 	       initpages << (PAGE_SHIFT-10),
-	       (unsigned long)PAGE_OFFSET, end_mem);
+	       (unsigned long)PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT));
 
 	/* NOTE NOTE NOTE NOTE
 	 * Please keep track of things and make sure this
@@ -347,39 +436,26 @@
 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);
-		atomic_set(&mem_map[MAP_NR(addr)].count, 1);
+		ClearPageReserved(mem_map + MAP_NR(addr));
+		set_page_count(mem_map + MAP_NR(addr), 1);
 		free_page(addr);
+		totalram_pages++;
+		num_physpages++;
 	}
 }
 
 void si_meminfo(struct sysinfo *val)
 {
-	struct page *page, *end;
-
-	val->totalram = 0;
+	val->totalram = totalram_pages;
 	val->sharedram = 0;
-	val->freeram = nr_free_pages << PAGE_SHIFT;
-	val->bufferram = atomic_read(&buffermem);
-	for (page = mem_map, end = mem_map + max_mapnr;
-	     page < end; page++) {
-		if (PageSkip(page)) {
-			if (page->next_hash < page)
-				break;
-			page = page->next_hash;
-		}
-		if (PageReserved(page))
-			continue;
-		val->totalram++;
-		if (!atomic_read(&page->count))
-			continue;
-		val->sharedram += atomic_read(&page->count) - 1;
-	}
-	val->totalram <<= PAGE_SHIFT;
-	val->sharedram <<= PAGE_SHIFT;
-	val->totalbig = 0;
-	val->freebig = 0;
+	val->freeram = nr_free_pages;
+	val->bufferram = atomic_read(&buffermem_pages);
+
+	val->totalhigh = 0;
+	val->freehigh = nr_free_highpages;
+
+	val->mem_unit = PAGE_SIZE;
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/io-unit.c linux/arch/sparc/mm/io-unit.c
--- v2.3.34/linux/arch/sparc/mm/io-unit.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc/mm/io-unit.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: io-unit.c,v 1.15 1999/09/10 10:40:38 davem Exp $
+/* $Id: io-unit.c,v 1.17 1999/10/18 01:46:54 zaitcev Exp $
  * io-unit.c:  IO-UNIT specific routines for memory management.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek    (jj@sunsite.mff.cuni.cz)
@@ -9,6 +9,7 @@
 #include <linux/init.h>
 #include <linux/malloc.h>
 #include <linux/spinlock.h>
+#include <asm/scatterlist.h>
 #include <asm/pgtable.h>
 #include <asm/sbus.h>
 #include <asm/io.h>
@@ -27,14 +28,15 @@
 #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM)
 
 void __init
-iounit_init(int sbi_node, int io_node, struct linux_sbus *sbus)
+iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus)
 {
 	iopte_t *xpt, *xptend;
 	struct iounit_struct *iounit;
 	struct linux_prom_registers iommu_promregs[PROMREG_MAX];
-	
+	struct resource r;
+
 	iounit = kmalloc(sizeof(struct iounit_struct), GFP_ATOMIC);
-	
+
 	memset(iounit, 0, sizeof(*iounit));
 	iounit->limit[0] = IOUNIT_BMAP1_START;
 	iounit->limit[1] = IOUNIT_BMAP2_START;
@@ -42,13 +44,14 @@
 	iounit->limit[3] = IOUNIT_BMAPM_END;
 	iounit->rotor[1] = IOUNIT_BMAP2_START;
 	iounit->rotor[2] = IOUNIT_BMAPM_START;
-	
+
 	prom_getproperty(sbi_node, "reg", (void *) iommu_promregs,
 			 sizeof(iommu_promregs));
 	prom_apply_generic_ranges(io_node, 0, iommu_promregs, 3);
-	xpt = (iopte_t *)
-		sparc_alloc_io(iommu_promregs[2].phys_addr, 0, (PAGE_SIZE * 16),
-			       "XPT", iommu_promregs[2].which_io, 0x0);
+	memset(&r, 0, sizeof(r));
+	r.flags = iommu_promregs[2].which_io;
+	r.start = iommu_promregs[2].phys_addr;
+	xpt = (iopte_t *) sbus_ioremap(&r, 0, PAGE_SIZE * 16, "XPT");
 	if(!xpt) panic("Cannot map External Page Table.");
 	
 	sbus->iommu = (struct iommu_struct *)iounit;
@@ -108,7 +111,7 @@
 	return vaddr;
 }
 
-static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct linux_sbus *sbus)
+static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct sbus_bus *sbus)
 {
 	unsigned long ret, flags;
 	struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
@@ -119,7 +122,7 @@
 	return ret;
 }
 
-static void iounit_get_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
+static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
 	unsigned long flags;
 	struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
@@ -127,12 +130,13 @@
 	/* FIXME: Cache some resolved pages - often several sg entries are to the same page */
 	spin_lock_irqsave(&iounit->lock, flags);
 	for (; sz >= 0; sz--) {
-		sg[sz].dvma_addr = iounit_get_area(iounit, (unsigned long)sg[sz].addr, sg[sz].len);
+		sg[sz].dvma_address = iounit_get_area(iounit, (unsigned long)sg[sz].address, sg[sz].length);
+		sg[sz].dvma_length = sg[sz].length;
 	}
 	spin_unlock_irqrestore(&iounit->lock, flags);
 }
 
-static void iounit_release_scsi_one(__u32 vaddr, unsigned long len, struct linux_sbus *sbus)
+static void iounit_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_bus *sbus)
 {
 	unsigned long flags;
 	struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
@@ -146,16 +150,16 @@
 	spin_unlock_irqrestore(&iounit->lock, flags);
 }
 
-static void iounit_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
+static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
 	unsigned long flags;
 	unsigned long vaddr, len;
 	struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
-	
+
 	spin_lock_irqsave(&iounit->lock, flags);
 	for (; sz >= 0; sz--) {
-		len = ((sg[sz].dvma_addr & ~PAGE_MASK) + sg[sz].len + (PAGE_SIZE-1)) >> PAGE_SHIFT;
-		vaddr = (sg[sz].dvma_addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
+		len = ((sg[sz].dvma_address & ~PAGE_MASK) + sg[sz].length + (PAGE_SIZE-1)) >> PAGE_SHIFT;
+		vaddr = (sg[sz].dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
 		IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr));
 		for (len += vaddr; vaddr < len; vaddr++)
 			clear_bit(vaddr, iounit->bmap);
@@ -164,21 +168,18 @@
 }
 
 #ifdef CONFIG_SBUS
-static void iounit_map_dma_area(unsigned long addr, int len)
+static void iounit_map_dma_area(unsigned long va, __u32 addr, int len)
 {
 	unsigned long page, end;
 	pgprot_t dvma_prot;
 	iopte_t *iopte;
-	struct linux_sbus *sbus;
+	struct sbus_bus *sbus;
 
 	dvma_prot = __pgprot(SRMMU_CACHE | SRMMU_ET_PTE | SRMMU_PRIV);
 	end = PAGE_ALIGN((addr + len));
 	while(addr < end) {
-		page = get_free_page(GFP_KERNEL);
-		if(!page) {
-			prom_printf("alloc_dvma: Cannot get a dvma page\n");
-			prom_halt();
-		} else {
+		page = va;
+		{
 			pgd_t *pgdp;
 			pmd_t *pmdp;
 			pte_t *ptep;
@@ -200,10 +201,15 @@
 			}
 		}
 		addr += PAGE_SIZE;
+		va += PAGE_SIZE;
 	}
 	flush_cache_all();
 	flush_tlb_all();
 }
+
+static void iounit_unmap_dma_area(unsigned long addr, int len)
+{
+}
 #endif
 
 static char *iounit_lockarea(char *vaddr, unsigned long len)
@@ -229,10 +235,11 @@
 
 #ifdef CONFIG_SBUS
 	BTFIXUPSET_CALL(mmu_map_dma_area, iounit_map_dma_area, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(mmu_unmap_dma_area, iounit_unmap_dma_area, BTFIXUPCALL_NORM);
 #endif
 }
 
-__u32 iounit_map_dma_init(struct linux_sbus *sbus, int size)
+__u32 iounit_map_dma_init(struct sbus_bus *sbus, int size)
 {
 	int i, j, k, npages;
 	unsigned long rotor, scan, limit;
@@ -271,7 +278,7 @@
 	return ret;
 }
 
-__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct linux_sbus *sbus)
+__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus)
 {
 	int scan = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
 	struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/iommu.c linux/arch/sparc/mm/iommu.c
--- v2.3.34/linux/arch/sparc/mm/iommu.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/mm/iommu.c	Mon Dec 20 22:05:52 1999
@@ -1,8 +1,8 @@
-/* $Id: iommu.c,v 1.11 1999/08/31 06:54:34 davem Exp $
+/* $Id: iommu.c,v 1.15 1999/11/19 04:11:53 davem Exp $
  * iommu.c:  IOMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
- * Copyright (C) 1995 Peter A. Zaitcev (zaitcev@ithil.mcst.ru)
+ * Copyright (C) 1995 Pete Zaitcev
  * Copyright (C) 1996 Eddie C. Dost    (ecd@skynet.be)
  * Copyright (C) 1997,1998 Jakub Jelinek    (jj@sunsite.mff.cuni.cz)
  */
@@ -12,10 +12,12 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
+#include <asm/scatterlist.h>
 #include <asm/pgtable.h>
 #include <asm/sbus.h>
 #include <asm/io.h>
 #include <asm/mxcc.h>
+#include <asm/mbus.h>
 
 /* srmmu.c */
 extern int viking_mxcc_present;
@@ -45,20 +47,23 @@
 }
 
 void __init
-iommu_init(int iommund, struct linux_sbus *sbus)
+iommu_init(int iommund, struct sbus_bus *sbus)
 {
 	unsigned int impl, vers, ptsize;
 	unsigned long tmp;
 	struct iommu_struct *iommu;
 	struct linux_prom_registers iommu_promregs[PROMREG_MAX];
+	struct resource r;
 	int i;
 
 	iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC);
 	prom_getproperty(iommund, "reg", (void *) iommu_promregs,
 			 sizeof(iommu_promregs));
+	memset(&r, 0, sizeof(r));
+	r.flags = iommu_promregs[0].which_io;
+	r.start = iommu_promregs[0].phys_addr;
 	iommu->regs = (struct iommu_regs *)
-		sparc_alloc_io(iommu_promregs[0].phys_addr, 0, (PAGE_SIZE * 3),
-			       "IOMMU registers", iommu_promregs[0].which_io, 0x0);
+		sbus_ioremap(&r, 0, PAGE_SIZE * 3, "iommu_regs");
 	if(!iommu->regs)
 		panic("Cannot map IOMMU registers.");
 	impl = (iommu->regs->control & IOMMU_CTRL_IMPL) >> 28;
@@ -137,18 +142,18 @@
 	       impl, vers, iommu->page_table, ptsize);
 }
 
-static __u32 iommu_get_scsi_one_noflush(char *vaddr, unsigned long len, struct linux_sbus *sbus)
+static __u32 iommu_get_scsi_one_noflush(char *vaddr, unsigned long len, struct sbus_bus *sbus)
 {
 	return (__u32)vaddr;
 }
 
-static __u32 iommu_get_scsi_one_gflush(char *vaddr, unsigned long len, struct linux_sbus *sbus)
+static __u32 iommu_get_scsi_one_gflush(char *vaddr, unsigned long len, struct sbus_bus *sbus)
 {
 	flush_page_for_dma(0);
 	return (__u32)vaddr;
 }
 
-static __u32 iommu_get_scsi_one_pflush(char *vaddr, unsigned long len, struct linux_sbus *sbus)
+static __u32 iommu_get_scsi_one_pflush(char *vaddr, unsigned long len, struct sbus_bus *sbus)
 {
 	unsigned long page = ((unsigned long) vaddr) & PAGE_MASK;
 
@@ -159,81 +164,110 @@
 	return (__u32)vaddr;
 }
 
-static void iommu_get_scsi_sgl_noflush(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
+static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
-	for (; sz >= 0; sz--)
-		sg[sz].dvma_addr = (__u32) (sg[sz].addr);
+	for (; sz >= 0; sz--) {
+		sg[sz].dvma_address = (__u32) (sg[sz].address);
+		sg[sz].dvma_length = (__u32) (sg[sz].length);
+	}
 }
 
-static void iommu_get_scsi_sgl_gflush(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
+static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
 	flush_page_for_dma(0);
-	for (; sz >= 0; sz--)
-		sg[sz].dvma_addr = (__u32) (sg[sz].addr);
+	for (; sz >= 0; sz--) {
+		sg[sz].dvma_address = (__u32) (sg[sz].address);
+		sg[sz].dvma_length = (__u32) (sg[sz].length);
+	}
 }
 
-static void iommu_get_scsi_sgl_pflush(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
+static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
 	unsigned long page, oldpage = 0;
 
 	while(sz >= 0) {
-		page = ((unsigned long) sg[sz].addr) & PAGE_MASK;
+		page = ((unsigned long) sg[sz].address) & PAGE_MASK;
 		if (oldpage == page)
 			page += PAGE_SIZE; /* We flushed that page already */
-		while(page < (unsigned long)(sg[sz].addr + sg[sz].len)) {
+		while(page < (unsigned long)(sg[sz].address + sg[sz].length)) {
 			flush_page_for_dma(page);
 			page += PAGE_SIZE;
 		}
-		sg[sz].dvma_addr = (__u32) (sg[sz].addr);
+		sg[sz].dvma_address = (__u32) (sg[sz].address);
+		sg[sz].dvma_length = (__u32) (sg[sz].length);
 		sz--;
 		oldpage = page - PAGE_SIZE;
 	}
 }
 
-static void iommu_release_scsi_one(__u32 vaddr, unsigned long len, struct linux_sbus *sbus)
+static void iommu_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_bus *sbus)
 {
 }
 
-static void iommu_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
+static void iommu_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
 }
 
 #ifdef CONFIG_SBUS
-static void iommu_map_dma_area(unsigned long addr, int len)
+static void iommu_map_dma_area(unsigned long va, __u32 addr, int len)
 {
-	unsigned long page, end;
+	unsigned long page, end, ipte_cache;
 	pgprot_t dvma_prot;
-	struct iommu_struct *iommu = SBus_chain->iommu;
+	struct iommu_struct *iommu = sbus_root->iommu;
 	iopte_t *iopte = iommu->page_table;
 	iopte_t *first;
 
-	if(viking_mxcc_present)
+	if(viking_mxcc_present || srmmu_modtype == HyperSparc) {
 		dvma_prot = __pgprot(SRMMU_CACHE | SRMMU_ET_PTE | SRMMU_PRIV);
-	else
+		ipte_cache = 1;
+	} else {
 		dvma_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV);
+		ipte_cache = 0;
+	}
 
 	iopte += ((addr - iommu->start) >> PAGE_SHIFT);
 	first = iopte;
 	end = PAGE_ALIGN((addr + len));
 	while(addr < end) {
-		page = get_free_page(GFP_KERNEL);
-		if(!page) {
-			prom_printf("alloc_dvma: Cannot get a dvma page\n");
-			prom_halt();
-		} else {
+		page = va;
+		{
 			pgd_t *pgdp;
 			pmd_t *pmdp;
 			pte_t *ptep;
 
-			pgdp = pgd_offset(init_task.mm, addr);
+			if (viking_mxcc_present)
+				viking_mxcc_flush_page(page);
+			else if (viking_flush)
+				viking_flush_page(page);
+			else
+				flush_page_to_ram(page);
+
+			pgdp = pgd_offset(&init_mm, addr);
 			pmdp = pmd_offset(pgdp, addr);
 			ptep = pte_offset(pmdp, addr);
 
 			set_pte(ptep, pte_val(mk_pte(page, dvma_prot)));
-			iopte_val(*iopte++) = MKIOPTE(mmu_v2p(page));
+			if (ipte_cache != 0) {
+				iopte_val(*iopte++) = MKIOPTE(mmu_v2p(page));
+			} else {
+				iopte_val(*iopte++) =
+					MKIOPTE(mmu_v2p(page)) & ~IOPTE_CACHE;
+			}
 		}
 		addr += PAGE_SIZE;
+		va += PAGE_SIZE;
 	}
+	/* P3: why do we need this?
+	 *
+	 * DAVEM: Because there are several aspects, none of which
+	 *        are handled by a single interface.  Some cpus are
+	 *        completely not I/O DMA coherent, and some have
+	 *        virtually indexed caches.  The driver DMA flushing
+	 *        methods handle the former case, but here during
+	 *        IOMMU page table modifications, and usage of non-cacheable
+	 *        cpu mappings of pages potentially in the cpu caches, we have
+	 *        to handle the latter case as well.
+	 */
 	flush_cache_all();
 	if(viking_mxcc_present) {
 		unsigned long start = ((unsigned long) first) & PAGE_MASK;
@@ -253,6 +287,10 @@
 	flush_tlb_all();
 	iommu_invalidate(iommu->regs);
 }
+
+static void iommu_unmap_dma_area(unsigned long addr, int len)
+{
+}
 #endif
 
 static char *iommu_lockarea(char *vaddr, unsigned long len)
@@ -287,5 +325,6 @@
 
 #ifdef CONFIG_SBUS
 	BTFIXUPSET_CALL(mmu_map_dma_area, iommu_map_dma_area, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(mmu_unmap_dma_area, iommu_unmap_dma_area, BTFIXUPCALL_NORM);
 #endif
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/nosrmmu.c linux/arch/sparc/mm/nosrmmu.c
--- v2.3.34/linux/arch/sparc/mm/nosrmmu.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/mm/nosrmmu.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: nosrmmu.c,v 1.3 1999/08/31 06:54:35 davem Exp $
+/* $Id: nosrmmu.c,v 1.5 1999/11/19 04:11:54 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,6 +14,8 @@
 
 enum mbus_module srmmu_modtype;
 
+int vac_cache_size = 0;
+
 static void __init should_not_happen(void)
 {
 	prom_printf(shouldnothappen);
@@ -49,12 +51,12 @@
 	return 0;
 }
 
-__u32 iounit_map_dma_init(struct linux_sbus *sbus, int size)
+__u32 iounit_map_dma_init(struct sbus_bus *sbus, int size)
 {
 	return 0;
 }
 
-__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct linux_sbus *sbus)
+__u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus)
 {
 	return 0;
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v2.3.34/linux/arch/sparc/mm/srmmu.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc/mm/srmmu.c	Wed Dec 22 19:55:38 1999
@@ -1,8 +1,8 @@
-/* $Id: srmmu.c,v 1.192 1999/09/10 10:40:40 davem Exp $
+/* $Id: srmmu.c,v 1.199 1999/12/23 02:00:51 davem Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
- * Copyright (C) 1995 Peter A. Zaitcev (zaitcev@ithil.mcst.ru)
+ * Copyright (C) 1995 Pete Zaitcev
  * Copyright (C) 1996 Eddie C. Dost    (ecd@skynet.be)
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
@@ -53,7 +53,7 @@
 int vac_line_size;
 int vac_badbits;
 
-extern unsigned long sparc_iobase_vaddr;
+extern struct resource sparc_iomap;
 
 #ifdef __SMP__
 #define FLUSH_BEGIN(mm)
@@ -284,7 +284,7 @@
 }
 
 /* The very generic SRMMU page table operations. */
-static inline int srmmu_device_memory(unsigned long x) 
+static inline int srmmu_device_memory(unsigned long x)
 {
 	return ((x & 0xF0000000) != 0);
 }
@@ -464,17 +464,6 @@
 	return (pte_t *) srmmu_s_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1));
 }
 
-/* This must update the context table entry for this process. */
-static void srmmu_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) 
-{
-	if(tsk->mm->context != NO_CONTEXT &&
-	   tsk->mm->pgd != pgdp) {
-		flush_cache_mm(tsk->mm);
-		ctxd_set(&srmmu_context_table[tsk->mm->context], pgdp);
-		flush_tlb_mm(tsk->mm);
-	}
-}
-
 static inline pte_t *srmmu_get_pte_fast(void)
 {
 	struct page *ret;
@@ -777,11 +766,11 @@
 #else
 	printk("Kernel faults at addr=0x%08lx\n", address);
 	printk("PTE=%08lx\n", srmmu_hwprobe((address & PAGE_MASK)));
-	die_if_kernel("SRMMU bolixed...", current->tss.kregs);
+	die_if_kernel("SRMMU bolixed...", current->thread.kregs);
 #endif
 }
 
-static inline void alloc_context(struct mm_struct *mm)
+static inline void alloc_context(struct mm_struct *old_mm, struct mm_struct *mm)
 {
 	struct ctx_list *ctxp;
 
@@ -794,7 +783,7 @@
 		return;
 	}
 	ctxp = ctx_used.next;
-	if(ctxp->ctx_mm == current->mm)
+	if(ctxp->ctx_mm == old_mm)
 		ctxp = ctxp->next;
 	if(ctxp == &ctx_used)
 		panic("out of mmu contexts");
@@ -817,29 +806,16 @@
 }
 
 
-static void srmmu_switch_to_context(struct task_struct *tsk)
+static void srmmu_switch_mm(struct mm_struct *old_mm, struct mm_struct *mm,
+    struct task_struct *tsk, int cpu)
 {
-	if(tsk->mm->context == NO_CONTEXT) {
+	if(mm->context == NO_CONTEXT) {
 		spin_lock(&srmmu_context_spinlock);
-		alloc_context(tsk->mm);
+		alloc_context(old_mm, mm);
 		spin_unlock(&srmmu_context_spinlock);
-		ctxd_set(&srmmu_context_table[tsk->mm->context], tsk->mm->pgd);
+		ctxd_set(&srmmu_context_table[mm->context], mm->pgd);
 	}
-	srmmu_set_context(tsk->mm->context);
-}
-
-static void srmmu_init_new_context(struct mm_struct *mm)
-{
-	spin_lock(&srmmu_context_spinlock);
-	alloc_context(mm);
-	spin_unlock(&srmmu_context_spinlock);
-
-	flush_cache_mm(mm);
-	ctxd_set(&srmmu_context_table[mm->context], mm->pgd);
-	flush_tlb_mm(mm);
-
-	if(mm == current->mm)
-		srmmu_set_context(mm->context);
+	srmmu_set_context(mm->context);
 }
 
 /* Low level IO area allocation on the SRMMU. */
@@ -885,9 +861,6 @@
 	flush_tlb_all();
 }
 
-/* This is used in many routines below. */
-#define UWINMASK_OFFSET (const unsigned long)(&(((struct task_struct *)0)->tss.uwinmask))
-
 /* On the SRMMU we do not have the problems with limited tlb entries
  * for mapping kernel pages, so we just take things from the free page
  * pool.  As a side effect we are putting a little too much pressure
@@ -919,110 +892,85 @@
 extern void tsunami_flush_tlb_mm(struct mm_struct *mm);
 extern void tsunami_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end);
 extern void tsunami_flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
+extern void tsunami_setup_blockops(void);
 
-/* Workaround, until we find what's going on with Swift. When low on memory, it sometimes
- * loops in fault/handle_mm_fault incl. flush_tlb_page to find out it is already in page tables/
- * fault again on the same instruction. I really don't understand it, have checked it and contexts
- * are right, flush_tlb_all is done as well, and it faults again... Strange. -jj
+/* Workaround, until we find what's going on with Swift. When low on memory,
+ * it sometimes loops in fault/handle_mm_fault incl. flush_tlb_page to find
+ * out it is already in page tables/ fault again on the same instruction.
+ * I really don't understand it, have checked it and contexts
+ * are right, flush_tlb_all is done as well, and it faults again...
+ * Strange. -jj
+ *
+ * The following code is a deadwood that may be necessary when
+ * we start to make precise page flushes again. --zaitcev
  */
 static void swift_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte)
 {
+#if 0
 	static unsigned long last;
+	unsigned int val;
+	/* unsigned int n; */
 
-	if (last == address) viking_hwprobe(address);
+	if (address == last) {
+		val = srmmu_hwprobe(address);
+		if (val != 0 && pte_val(pte) != val) {
+			printk("swift_update_mmu_cache: "
+			    "addr %lx put %08x probed %08x from %p\n",
+			    address, pte_val(pte), val,
+			    __builtin_return_address(0));
+			srmmu_flush_whole_tlb();
+		}
+	}
 	last = address;
+#endif
 }
 
-/* Swift flushes.  It has the recommended SRMMU specification flushing
- * facilities, so we can do things in a more fine grained fashion than we
- * could on the tsunami.  Let's watch out for HARDWARE BUGS...
- */
-
-static void swift_flush_cache_all(void)
-{
-	flush_user_windows();
-	swift_idflash_clear();
-}
-
-static void swift_flush_cache_mm(struct mm_struct *mm)
-{
-	FLUSH_BEGIN(mm)
-	flush_user_windows();
-	swift_idflash_clear();
-	FLUSH_END
-}
-
-static void swift_flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end)
-{
-	FLUSH_BEGIN(mm)
-	flush_user_windows();
-	swift_idflash_clear();
-	FLUSH_END
-}
-
-static void swift_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
-{
-	FLUSH_BEGIN(vma->vm_mm)
-	flush_user_windows();
-	if(vma->vm_flags & VM_EXEC)
-		swift_flush_icache();
-	swift_flush_dcache();
-	FLUSH_END
-}
-
-/* Not copy-back on swift. */
-static void swift_flush_page_to_ram(unsigned long page)
-{
-}
-
-/* But not IO coherent either. */
-static void swift_flush_page_for_dma(unsigned long page)
-{
-	swift_flush_dcache();
-}
-
-/* Again, Swift is non-snooping split I/D cache'd just like tsunami,
- * so have to punt the icache for on-stack signal insns.  Only the
- * icache need be flushed since the dcache is write-through.
- */
-static void swift_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
-{
-	swift_flush_icache();
-}
-
-static void swift_flush_chunk(unsigned long chunk)
-{
-}
-
-static void swift_flush_tlb_all(void)
-{
-	srmmu_flush_whole_tlb();
-	module_stats.invall++;
-}
-
-static void swift_flush_tlb_mm(struct mm_struct *mm)
-{
-	FLUSH_BEGIN(mm)
-	srmmu_flush_whole_tlb();
-	module_stats.invmm++;
-	FLUSH_END
-}
+/* swift.S */
+extern void swift_flush_cache_all(void);
+extern void swift_flush_cache_mm(struct mm_struct *mm);
+extern void swift_flush_cache_range(struct mm_struct *mm,
+				    unsigned long start, unsigned long end);
+extern void swift_flush_cache_page(struct vm_area_struct *vma, unsigned long page);
+extern void swift_flush_page_to_ram(unsigned long page);
+extern void swift_flush_page_for_dma(unsigned long page);
+extern void swift_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);
+extern void swift_flush_chunk(unsigned long chunk);
+extern void swift_flush_tlb_all(void);
+extern void swift_flush_tlb_mm(struct mm_struct *mm);
+extern void swift_flush_tlb_range(struct mm_struct *mm,
+				  unsigned long start, unsigned long end);
+extern void swift_flush_tlb_page(struct vm_area_struct *vma, unsigned long page);
 
-static void swift_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
+#if 0  /* P3: deadwood to debug precise flushes on Swift. */
+void swift_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
-	FLUSH_BEGIN(mm)
-	srmmu_flush_whole_tlb();
-	module_stats.invrnge++;
-	FLUSH_END
-}
+	int cctx, ctx1;
 
-static void swift_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
-	FLUSH_BEGIN(vma->vm_mm)
-	srmmu_flush_whole_tlb();
+	page &= PAGE_MASK;
+	if ((ctx1 = vma->vm_mm->context) != -1) {
+		cctx = srmmu_get_context();
+/* Is context # ever different from current context? P3 */
+		if (cctx != ctx1) {
+			printk("flush ctx %02x curr %02x\n", ctx1, cctx);
+			srmmu_set_context(ctx1);
+			swift_flush_page(page);
+			__asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
+					"r" (page), "i" (ASI_M_FLUSH_PROBE));
+			srmmu_set_context(cctx);
+		} else {
+			 /* Rm. prot. bits from virt. c. */
+			/* swift_flush_cache_all(); */
+			/* swift_flush_cache_page(vma, page); */
+			swift_flush_page(page);
+
+			__asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
+				"r" (page), "i" (ASI_M_FLUSH_PROBE));
+			/* same as above: srmmu_flush_tlb_page() */
+		}
+	}
 	module_stats.invpg++;
-	FLUSH_END
 }
+#endif
 
 /* The following are all MBUS based SRMMU modules, and therefore could
  * be found in a multiprocessor configuration.  On the whole, these
@@ -1333,103 +1281,21 @@
 	hyper_flush_whole_icache();
 }
 
-static void hypersparc_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) 
-{
-	unsigned long page = ((unsigned long) pgdp) & PAGE_MASK;
-
-	if(pgdp != swapper_pg_dir)
-		hypersparc_flush_page_to_ram(page);
-
-	if(tsk->mm->context != NO_CONTEXT &&
-	   tsk->mm->pgd != pgdp) {
-		flush_cache_mm(tsk->mm);
-		ctxd_set(&srmmu_context_table[tsk->mm->context], pgdp);
-		flush_tlb_mm(tsk->mm);
-	}
-}
-
-static void viking_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) 
-{
-	if(pgdp != swapper_pg_dir)
-		flush_chunk((unsigned long)pgdp);
-	if(tsk->mm->context != NO_CONTEXT &&
-	   tsk->mm->pgd != pgdp) {
-		flush_cache_mm(tsk->mm);
-		ctxd_set(&srmmu_context_table[tsk->mm->context], pgdp);
-		flush_tlb_mm(tsk->mm);
-	}
-}
-
-static void cypress_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) 
-{
-	register unsigned long a, b, c, d, e, f, g;
-	unsigned long page = ((unsigned long) pgdp) & PAGE_MASK;
-	unsigned long line;
-
-	if(pgdp == swapper_pg_dir)
-		goto skip_flush;
-
-	a = 0x20; b = 0x40; c = 0x60; d = 0x80; e = 0xa0; f = 0xc0; g = 0xe0;
-	page &= PAGE_MASK;
-	line = (page + PAGE_SIZE) - 0x100;
-	goto inside;
-	do {
-		line -= 0x100;
-	inside:
-		__asm__ __volatile__("sta %%g0, [%0] %1\n\t"
-				     "sta %%g0, [%0 + %2] %1\n\t"
-				     "sta %%g0, [%0 + %3] %1\n\t"
-				     "sta %%g0, [%0 + %4] %1\n\t"
-				     "sta %%g0, [%0 + %5] %1\n\t"
-				     "sta %%g0, [%0 + %6] %1\n\t"
-				     "sta %%g0, [%0 + %7] %1\n\t"
-				     "sta %%g0, [%0 + %8] %1\n\t" : :
-				     "r" (line),
-				     "i" (ASI_M_FLUSH_PAGE),
-				     "r" (a), "r" (b), "r" (c), "r" (d),
-				     "r" (e), "r" (f), "r" (g));
-	} while(line != page);
-skip_flush:
-	if(tsk->mm->context != NO_CONTEXT &&
-	   tsk->mm->pgd != pgdp) {
-		flush_cache_mm(tsk->mm);
-		ctxd_set(&srmmu_context_table[tsk->mm->context], pgdp);
-		flush_tlb_mm(tsk->mm);
-	}
-}
-
-static void hypersparc_switch_to_context(struct task_struct *tsk)
+static void hypersparc_switch_mm(struct mm_struct *old_mm,
+    struct mm_struct *mm, struct task_struct *tsk, int cpu)
 {
-	if(tsk->mm->context == NO_CONTEXT) {
+	if(mm->context == NO_CONTEXT) {
 		ctxd_t *ctxp;
 
 		spin_lock(&srmmu_context_spinlock);
-		alloc_context(tsk->mm);
+		alloc_context(old_mm, mm);
 		spin_unlock(&srmmu_context_spinlock);
-		ctxp = &srmmu_context_table[tsk->mm->context];
-		srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) tsk->mm->pgd) >> 4))));
+		ctxp = &srmmu_context_table[mm->context];
+		srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) mm->pgd) >> 4))));
 		hypersparc_flush_page_to_ram((unsigned long)ctxp);
 	}
 	hyper_flush_whole_icache();
-	srmmu_set_context(tsk->mm->context);
-}
-
-static void hypersparc_init_new_context(struct mm_struct *mm)
-{
-	ctxd_t *ctxp;
-
-	spin_lock(&srmmu_context_spinlock);
-	alloc_context(mm);
-	spin_unlock(&srmmu_context_spinlock);
-
-	ctxp = &srmmu_context_table[mm->context];
-	srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) mm->pgd) >> 4))));
-	hypersparc_flush_page_to_ram((unsigned long)ctxp);
-
-	if(mm == current->mm) {
-		hyper_flush_whole_icache();
-		srmmu_set_context(mm->context);
-	}
+	srmmu_set_context(mm->context);
 }
 
 static unsigned long mempool;
@@ -1694,7 +1560,8 @@
 	srmmu_map[srmmu_bank].vbase = vbase;
 	srmmu_map[srmmu_bank].pbase = sp_banks[sp_entry].base_addr;
 	srmmu_map[srmmu_bank].size = sp_banks[sp_entry].num_bytes;
-	srmmu_bank++;
+	if (srmmu_map[srmmu_bank].size)
+		srmmu_bank++;
 	map_spbank_last_pa = pstart - SRMMU_PGDIR_SIZE;
 	return vstart;
 }
@@ -1949,8 +1816,8 @@
 	int i, cpunode;
 	char node_str[128];
 
-	sparc_iobase_vaddr = 0xfd000000;    /* 16MB of IOSPACE on all sun4m's. */
-	physmem_mapped_contig = 0;	    /* for init.c:taint_real_pages()   */
+	sparc_iomap.start = 0xfd000000;    /* 16MB of IOSPACE on all sun4m's. */
+	physmem_mapped_contig = 0;         /* for init.c:taint_real_pages()   */
 
 	if (sparc_cpu_model == sun4d)
 		num_contexts = 65536; /* We know it is Viking */
@@ -1981,7 +1848,7 @@
 
 	srmmu_allocate_ptable_skeleton(KERNBASE, end_mem);
 #if CONFIG_SUN_IO
-	srmmu_allocate_ptable_skeleton(sparc_iobase_vaddr, IOBASE_END);
+	srmmu_allocate_ptable_skeleton(sparc_iomap.start, IOBASE_END);
 	srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END);
 #endif
 
@@ -2051,16 +1918,14 @@
 
 static void srmmu_destroy_context(struct mm_struct *mm)
 {
-	if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) {
-		/* XXX This could be drastically improved.
-		 * XXX We are only called from __exit_mm and it just did
-		 * XXX cache/tlb mm flush and right after this will (re-)
-		 * XXX SET_PAGE_DIR to swapper_pg_dir.  -DaveM
-		 */
+
+	if(mm->context != NO_CONTEXT) {
 		flush_cache_mm(mm);
 		ctxd_set(&srmmu_context_table[mm->context], swapper_pg_dir);
 		flush_tlb_mm(mm);
+		spin_lock(&srmmu_context_spinlock);
 		free_context(mm->context);
+		spin_unlock(&srmmu_context_spinlock);
 		mm->context = NO_CONTEXT;
 	}
 }
@@ -2136,7 +2001,7 @@
 
 static void hypersparc_destroy_context(struct mm_struct *mm)
 {
-	if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) {
+	if(mm->context != NO_CONTEXT) {
 		ctxd_t *ctxp;
 
 		/* HyperSparc is copy-back, any data for this
@@ -2151,7 +2016,9 @@
 		hypersparc_flush_page_to_ram((unsigned long)ctxp);
 
 		flush_tlb_mm(mm);
+		spin_lock(&srmmu_context_spinlock);
 		free_context(mm->context);
+		spin_unlock(&srmmu_context_spinlock);
 		mm->context = NO_CONTEXT;
 	}
 }
@@ -2267,11 +2134,9 @@
 	BTFIXUPSET_CALL(flush_chunk, hypersparc_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */
 
 	BTFIXUPSET_CALL(ctxd_set, hypersparc_ctxd_set, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(switch_to_context, hypersparc_switch_to_context, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(init_new_context, hypersparc_init_new_context, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(switch_mm, hypersparc_switch_mm, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(destroy_context, hypersparc_destroy_context, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(update_mmu_cache, srmmu_vac_update_mmu_cache, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(sparc_update_rootmmu_dir, hypersparc_update_rootmmu_dir, BTFIXUPCALL_NORM);
 	poke_srmmu = poke_hypersparc;
 
 	hypersparc_setup_blockops();
@@ -2339,7 +2204,6 @@
 	BTFIXUPSET_CALL(flush_page_to_ram, cypress_flush_page_to_ram, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_sig_insns, cypress_flush_sig_insns, BTFIXUPCALL_NOP);
 	BTFIXUPSET_CALL(flush_page_for_dma, cypress_flush_page_for_dma, BTFIXUPCALL_NOP);
-	BTFIXUPSET_CALL(sparc_update_rootmmu_dir, cypress_update_rootmmu_dir, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(update_mmu_cache, srmmu_vac_update_mmu_cache, BTFIXUPCALL_NORM);
 	poke_srmmu = poke_cypress;
@@ -2371,12 +2235,14 @@
 
 static void __init poke_swift(void)
 {
-	unsigned long mreg = srmmu_get_mmureg();
+	unsigned long mreg;
 
 	/* Clear any crap from the cache or else... */
-	swift_idflash_clear();
-	mreg |= (SWIFT_IE | SWIFT_DE); /* I & D caches on */
+	swift_flush_cache_all();
 
+	/* Enable I & D caches */
+	mreg = srmmu_get_mmureg();
+	mreg |= (SWIFT_IE | SWIFT_DE);
 	/* The Swift branch folding logic is completely broken.  At
 	 * trap time, if things are just right, if can mistakenly
 	 * think that a trap is coming from kernel mode when in fact
@@ -2442,19 +2308,21 @@
 	BTFIXUPSET_CALL(flush_cache_page, swift_flush_cache_page, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_cache_range, swift_flush_cache_range, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(flush_chunk, swift_flush_chunk, BTFIXUPCALL_NOP); /* local flush _only_ */
+	BTFIXUPSET_CALL(flush_chunk, swift_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */
 
 	BTFIXUPSET_CALL(flush_tlb_all, swift_flush_tlb_all, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_tlb_mm, swift_flush_tlb_mm, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_tlb_page, swift_flush_tlb_page, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_tlb_range, swift_flush_tlb_range, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NOP);
+	BTFIXUPSET_CALL(flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_sig_insns, swift_flush_sig_insns, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_page_for_dma, swift_flush_page_for_dma, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(update_mmu_cache, swift_update_mmu_cache, BTFIXUPCALL_NORM);
 
+	flush_page_for_dma_global = 0;
+
 	/* Are you now convinced that the Swift is one of the
 	 * biggest VLSI abortions of all time?  Bravo Fujitsu!
 	 * Fujitsu, the !#?!%$'d up processor people.  I bet if
@@ -2611,7 +2479,7 @@
 	BTFIXUPSET_CALL(flush_chunk, turbosparc_flush_chunk, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(flush_sig_insns, turbosparc_flush_sig_insns, BTFIXUPCALL_NOP);
-	BTFIXUPSET_CALL(flush_page_for_dma, turbosparc_flush_page_for_dma, BTFIXUPCALL_NOP);
+	BTFIXUPSET_CALL(flush_page_for_dma, turbosparc_flush_page_for_dma, BTFIXUPCALL_NORM);
 
 	poke_srmmu = poke_turbosparc;
 }
@@ -2642,7 +2510,7 @@
 	BTFIXUPSET_CALL(flush_cache_page, tsunami_flush_cache_page, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_cache_range, tsunami_flush_cache_range, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(flush_chunk, tsunami_flush_chunk, BTFIXUPCALL_NOP); /* local flush _only_ */
+	BTFIXUPSET_CALL(flush_chunk, tsunami_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */
 
 	BTFIXUPSET_CALL(flush_tlb_all, tsunami_flush_tlb_all, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_tlb_mm, tsunami_flush_tlb_mm, BTFIXUPCALL_NORM);
@@ -2654,6 +2522,8 @@
 	BTFIXUPSET_CALL(flush_page_for_dma, tsunami_flush_page_for_dma, BTFIXUPCALL_NORM);
 
 	poke_srmmu = poke_tsunami;
+
+	tsunami_setup_blockops();
 }
 
 static void __init poke_viking(void)
@@ -2725,7 +2595,6 @@
 		BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(pmd_clear, srmmu_pmd_clear, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(pgd_clear, srmmu_pgd_clear, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(sparc_update_rootmmu_dir, viking_update_rootmmu_dir, BTFIXUPCALL_NORM);
 
 		BTFIXUPSET_CALL(flush_chunk, viking_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */
 
@@ -2736,8 +2605,7 @@
 		 * which we use the IOMMU.
 		 */
 		BTFIXUPSET_CALL(flush_page_for_dma, viking_flush_page, BTFIXUPCALL_NORM);
-		/* Also, this is so far the only chip which actually uses
-		   the page argument to flush_page_for_dma */
+
 		flush_page_for_dma_global = 0;
 	} else {
 		srmmu_name = "TI Viking/MXCC";
@@ -2928,6 +2796,16 @@
 	return freed;
 }
 
+static void srmmu_flush_dma_area(unsigned long addr, int len)
+{
+	/* XXX Later */
+}
+
+static void srmmu_inval_dma_area(unsigned long addr, int len)
+{
+	/* XXX Later */
+}
+
 extern unsigned long spwin_mmu_patchme, fwin_mmu_patchme,
 	tsetup_mmu_patchme, rtrap_mmu_patchme;
 
@@ -2999,21 +2877,18 @@
 	BTFIXUPSET_CALL(free_pte_slow, srmmu_free_pte_slow, BTFIXUPCALL_NOP);
 	BTFIXUPSET_CALL(free_pgd_slow, srmmu_free_pgd_slow, BTFIXUPCALL_NOP);
 	BTFIXUPSET_CALL(do_check_pgt_cache, srmmu_check_pgt_cache, BTFIXUPCALL_NORM);
-	
+
 	BTFIXUPSET_CALL(set_pgdir, srmmu_set_pgdir, BTFIXUPCALL_NORM);
-	    
+
 	BTFIXUPSET_CALL(set_pte, srmmu_set_pte_cacheable, BTFIXUPCALL_SWAPO0O1);
-	BTFIXUPSET_CALL(init_new_context, srmmu_init_new_context, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(switch_to_context, srmmu_switch_to_context, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(switch_mm, srmmu_switch_mm, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(pte_page, srmmu_pte_page, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pgd_page, srmmu_pgd_page, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(sparc_update_rootmmu_dir, srmmu_update_rootmmu_dir, BTFIXUPCALL_NORM);
+	BTFIXUPSET_SETHI(none_mask, 0xF0000000);	/* P3: is it used? */
 
-	BTFIXUPSET_SETHI(none_mask, 0xF0000000);
-	
 	BTFIXUPSET_CALL(pte_present, srmmu_pte_present, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pte_clear, srmmu_pte_clear, BTFIXUPCALL_SWAPO0G0);
 
@@ -3072,6 +2947,11 @@
 	BTFIXUPSET_CALL(ctxd_set, srmmu_ctxd_set, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pmd_set, srmmu_pmd_set, BTFIXUPCALL_NORM);
 
+/* hmm isn't flush_dma_area the same thing as flush_page_for_dma? */
+/* It is, except flush_page_for_dma was local to srmmu.c */
+	BTFIXUPSET_CALL(mmu_flush_dma_area, srmmu_flush_dma_area, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(mmu_inval_dma_area, srmmu_inval_dma_area, BTFIXUPCALL_NORM);
+
 	get_srmmu_type();
 	patch_window_trap_handlers();
 
@@ -3104,6 +2984,7 @@
 	BTFIXUPSET_CALL(flush_sig_insns, smp_flush_sig_insns, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_page_for_dma, smp_flush_page_for_dma, BTFIXUPCALL_NORM);
 #endif
+
 	if (sparc_cpu_model == sun4d)
 		ld_mmu_iounit();
 	else
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- v2.3.34/linux/arch/sparc/mm/sun4c.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/mm/sun4c.c	Mon Dec 20 22:05:52 1999
@@ -1,18 +1,22 @@
-/* $Id: sun4c.c,v 1.176 1999/08/31 06:54:42 davem Exp $
+/* $Id: sun4c.c,v 1.181 1999/12/16 14:34:21 anton Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
  * Copyright (C) 1996 Andrew Tridgell (Andrew.Tridgell@anu.edu.au)
- * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au)
+ * Copyright (C) 1997,99 Anton Blanchard (anton@progsoc.uts.edu.au)
  * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
+#define NR_TASK_BUCKETS 512
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 
+#include <asm/scatterlist.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/vaddrs.h>
@@ -27,42 +31,19 @@
 #include <asm/mmu_context.h>
 #include <asm/sun4paddr.h>
 
-/* TODO: Make it such that interrupt handlers cannot dick with
- *       the user segment lists, most of the cli/sti pairs can
- *       disappear once that is taken care of.
- */
-
-/* XXX Ok the real performance win, I figure, will be to use a combined hashing
- * XXX and bitmap scheme to keep track of what we have mapped where.  The whole
- * XXX incentive is to make it such that the range flushes can be serviced
- * XXX always in near constant time. --DaveM
+/* Because of our dynamic kernel TLB miss strategy, and how
+ * our DVMA mapping allocation works, you _MUST_:
+ *
+ * 1) Disable interrupts _and_ not touch any dynamic kernel
+ *    memory while messing with kernel MMU state.  By
+ *    dynamic memory I mean any object which is not in
+ *    the kernel image itself or a task_struct (both of
+ *    which are locked into the MMU).
+ * 2) Disable interrupts while messing with user MMU state.
  */
 
 extern int num_segmaps, num_contexts;
 
-/* Define this to get extremely anal debugging, undefine for performance. */
-/* #define DEBUG_SUN4C_MM */
-
-#define UWINMASK_OFFSET (const unsigned long)(&(((struct task_struct *)0)->tss.uwinmask))
-
-/* This is used in many routines below. */
-#define FUW_INLINE do {							\
-	register int ctr asm("g5");					\
-	ctr = 0;							\
-	__asm__ __volatile__("\n"					\
-	"1:	ld	[%%g6 + %2], %%g4	! flush user windows\n"	\
-	"	orcc	%%g0, %%g4, %%g0\n"				\
-	"	add	%0, 1, %0\n"					\
-	"	bne	1b\n"						\
-	"	 save	%%sp, -64, %%sp\n"				\
-	"2:	subcc	%0, 1, %0\n"					\
-	"	bne	2b\n"						\
-	"	 restore %%g0, %%g0, %%g0\n"				\
-	: "=&r" (ctr)							\
-	: "0" (ctr), "i" (UWINMASK_OFFSET)				\
-	: "g4", "cc");							\
-} while(0);
-
 #ifdef CONFIG_SUN4
 #define SUN4C_VAC_SIZE sun4c_vacinfo.num_bytes
 #else
@@ -82,58 +63,21 @@
 #define MIN(a,b) ((a)<(b)?(a):(b))
 #endif
 
-
-#define KGPROF_PROFILING 0
-#if KGPROF_PROFILING
-#define KGPROF_DEPTH 3 /* this needs to match the code below */
-#define KGPROF_SIZE 100
-static struct {
-	unsigned addr[KGPROF_DEPTH];
-	unsigned count;
-} kgprof_counters[KGPROF_SIZE];
-
-/* just call this function from whatever function you think needs it then
-   look at /proc/cpuinfo to see where the function is being called from
-   and how often. This gives a type of "kernel gprof" */
-#define NEXT_PROF(prev,lvl) (prev>PAGE_OFFSET?__builtin_return_address(lvl):0)
-static inline void kgprof_profile(void)
-{
-	unsigned ret[KGPROF_DEPTH];
-	int i,j;
-	/* you can't use a variable argument to __builtin_return_address() */
-	ret[0] = (unsigned)__builtin_return_address(0);
-	ret[1] = (unsigned)NEXT_PROF(ret[0],1);
-	ret[2] = (unsigned)NEXT_PROF(ret[1],2);
-
-	for (i=0;i<KGPROF_SIZE && kgprof_counters[i].addr[0];i++) {
-		for (j=0;j<KGPROF_DEPTH;j++) 
-			if (ret[j] != kgprof_counters[i].addr[j]) break;
-		if (j==KGPROF_DEPTH) break;
-	}
-	if (i<KGPROF_SIZE) {		
-		for (j=0;j<KGPROF_DEPTH;j++)
-			kgprof_counters[i].addr[j] = ret[j];
-		kgprof_counters[i].count++;
-	}
-}
-#endif
-
-
 /* Flushing the cache. */
 struct sun4c_vac_props sun4c_vacinfo;
-static int ctxflushes, segflushes, pageflushes;
 unsigned long sun4c_kernel_faults;
 
 /* convert a virtual address to a physical address and vice
-   versa. Easy on the 4c */
+ * versa. Easy on the 4c
+ */
 static unsigned long sun4c_v2p(unsigned long vaddr)
 {
-  return(vaddr - PAGE_OFFSET);
+	return (vaddr - PAGE_OFFSET);
 }
 
 static unsigned long sun4c_p2v(unsigned long vaddr)
 {
-  return(vaddr + PAGE_OFFSET);
+	return (vaddr + PAGE_OFFSET);
 }
 
 
@@ -142,44 +86,64 @@
 {
 	unsigned long begin, end;
 
-	if(sun4c_vacinfo.on)
+	if (sun4c_vacinfo.on)
 		panic("SUN4C: AIEEE, trying to invalidate vac while"
                       " it is on.");
 
 	/* Clear 'valid' bit in all cache line tags */
 	begin = AC_CACHETAGS;
 	end = (AC_CACHETAGS + SUN4C_VAC_SIZE);
-	while(begin < end) {
+	while (begin < end) {
 		__asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
 				     "r" (begin), "i" (ASI_CONTROL));
 		begin += sun4c_vacinfo.linesize;
 	}
 }
 
-/* Context level flush. */
-static inline void sun4c_flush_context_hw(void)
+static __inline__ void sun4c_flush_context_hw(void)
 {
 	unsigned long end = SUN4C_VAC_SIZE;
-	unsigned pgsz = PAGE_SIZE;
 
-	ctxflushes++;
-	__asm__ __volatile__("
-1:	subcc	%0, %2, %0
-	bg	1b
-	 sta	%%g0, [%0] %3
-	nop; nop; nop;		! Weitek hwbug
-"	: "=&r" (end)
-	: "0" (end), "r" (pgsz), "i" (ASI_HWFLUSHCONTEXT)
+	__asm__ __volatile__(
+		"1:	addcc	%0, -4096, %0\n\t"
+		"	bne	1b\n\t"
+		"	 sta	%%g0, [%0] %2"
+	: "=&r" (end)
+	: "0" (end), "i" (ASI_HWFLUSHCONTEXT)
 	: "cc");
 }
 
+/* Must be called minimally with IRQs disabled. */
+static void sun4c_flush_segment_hw(unsigned long addr)
+{
+	if (sun4c_get_segmap(addr) != invalid_segment) {
+		unsigned long vac_size = SUN4C_VAC_SIZE;
+
+		__asm__ __volatile__(
+			"1:	addcc	%0, -4096, %0\n\t"
+			"	bne	1b\n\t"
+			"	 sta	%%g0, [%2 + %0] %3"
+			: "=&r" (vac_size)
+			: "0" (vac_size), "r" (addr), "i" (ASI_HWFLUSHSEG)
+			: "cc");
+	}
+}
+
+/* Must be called minimally with interrupts disabled. */
+static __inline__ void sun4c_flush_page_hw(unsigned long addr)
+{
+	addr &= PAGE_MASK;
+	if ((int)sun4c_get_pte(addr) < 0)
+		__asm__ __volatile__("sta %%g0, [%0] %1"
+				     : : "r" (addr), "i" (ASI_HWFLUSHPAGE));
+}
+
 /* Don't inline the software version as it eats too many cache lines if expanded. */
 static void sun4c_flush_context_sw(void)
 {
 	unsigned long nbytes = SUN4C_VAC_SIZE;
 	unsigned long lsize = sun4c_vacinfo.linesize;
 
-	ctxflushes++;
 	__asm__ __volatile__("
 	add	%2, %2, %%g1
 	add	%2, %%g1, %%g2
@@ -203,72 +167,13 @@
 	: "g1", "g2", "g3", "g4", "g5", "o4", "o5", "cc");
 }
 
-/* Scrape the segment starting at ADDR from the virtual cache. */
-static inline void sun4c_flush_segment(unsigned long addr)
-{
-	if(sun4c_get_segmap(addr) == invalid_segment)
-		return;
-
-	segflushes++;
-	if(sun4c_vacinfo.do_hwflushes) {
-		unsigned long end = (addr + SUN4C_VAC_SIZE);
-
-		for( ; addr < end; addr += PAGE_SIZE)
-			__asm__ __volatile__("sta %%g0, [%0] %1;nop;nop;nop;\n\t" : :
-					     "r" (addr), "i" (ASI_HWFLUSHSEG));
-	} else {
-		unsigned long nbytes = SUN4C_VAC_SIZE;
-		unsigned long lsize = sun4c_vacinfo.linesize;
-
-		__asm__ __volatile__("add	%2, %2, %%g1\n\t"
-				     "add	%2, %%g1, %%g2\n\t"
-				     "add	%2, %%g2, %%g3\n\t"
-				     "add	%2, %%g3, %%g4\n\t"
-				     "add	%2, %%g4, %%g5\n\t"
-				     "add	%2, %%g5, %%o4\n\t"
-				     "add	%2, %%o4, %%o5\n"
-				     "1:\n\t"
-				     "subcc	%1, %%o5, %1\n\t"
-				     "sta	%%g0, [%0] %6\n\t"
-				     "sta	%%g0, [%0 + %2] %6\n\t"
-				     "sta	%%g0, [%0 + %%g1] %6\n\t"
-				     "sta	%%g0, [%0 + %%g2] %6\n\t"
-				     "sta	%%g0, [%0 + %%g3] %6\n\t"
-				     "sta	%%g0, [%0 + %%g4] %6\n\t"
-				     "sta	%%g0, [%0 + %%g5] %6\n\t"
-				     "sta	%%g0, [%0 + %%o4] %6\n\t"
-				     "bg	1b\n\t"
-				     " add	%0, %%o5, %0\n\t"
-				     : "=&r" (addr), "=&r" (nbytes), "=&r" (lsize)
-				     : "0" (addr), "1" (nbytes), "2" (lsize),
-				       "i" (ASI_FLUSHSEG)
-				     : "g1", "g2", "g3", "g4", "g5", "o4", "o5", "cc");
-	}
-}
-
-/* Call this version when you know hardware flushes are available. */
-static inline void sun4c_flush_segment_hw(unsigned long addr)
-{
-	if(sun4c_get_segmap(addr) != invalid_segment) {
-		unsigned long end;
-
-		segflushes++;
-		for(end = addr + SUN4C_VAC_SIZE; addr < end; addr += PAGE_SIZE)
-			__asm__ __volatile__("sta %%g0, [%0] %1"
-					     : : "r" (addr), "i" (ASI_HWFLUSHSEG));
-		/* Weitek POWER-UP hwbug workaround. */
-		__asm__ __volatile__("nop;nop;nop;	! Weitek hwbug");
-	}
-}
-
 /* Don't inline the software version as it eats too many cache lines if expanded. */
 static void sun4c_flush_segment_sw(unsigned long addr)
 {
-	if(sun4c_get_segmap(addr) != invalid_segment) {
+	if (sun4c_get_segmap(addr) != invalid_segment) {
 		unsigned long nbytes = SUN4C_VAC_SIZE;
 		unsigned long lsize = sun4c_vacinfo.linesize;
 
-		segflushes++;
 		__asm__ __volatile__("
 		add	%2, %2, %%g1
 		add	%2, %%g1, %%g2
@@ -300,12 +205,11 @@
 {
 	addr &= PAGE_MASK;
 
-	if((sun4c_get_pte(addr) & (_SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_VALID)) !=
-	   _SUN4C_PAGE_VALID)
+	if ((sun4c_get_pte(addr) & (_SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_VALID)) !=
+	    _SUN4C_PAGE_VALID)
 		return;
 
-	pageflushes++;
-	if(sun4c_vacinfo.do_hwflushes) {
+	if (sun4c_vacinfo.do_hwflushes) {
 		__asm__ __volatile__("sta %%g0, [%0] %1;nop;nop;nop;\n\t" : :
 				     "r" (addr), "i" (ASI_HWFLUSHPAGE));
 	} else {
@@ -338,30 +242,15 @@
 	}
 }
 
-/* Again, hw-only and sw-only cache page-level flush variants. */
-static inline void sun4c_flush_page_hw(unsigned long addr)
-{
-	addr &= PAGE_MASK;
-	if((sun4c_get_pte(addr) & (_SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_VALID)) ==
-	   _SUN4C_PAGE_VALID) {
-		pageflushes++;
-		__asm__ __volatile__("sta %%g0, [%0] %1"
-				     : : "r" (addr), "i" (ASI_HWFLUSHPAGE));
-		/* Weitek POWER-UP hwbug workaround. */
-		__asm__ __volatile__("nop;nop;nop;	! Weitek hwbug");
-	}
-}
-
 /* Don't inline the software version as it eats too many cache lines if expanded. */
 static void sun4c_flush_page_sw(unsigned long addr)
 {
 	addr &= PAGE_MASK;
-	if((sun4c_get_pte(addr) & (_SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_VALID)) ==
-	   _SUN4C_PAGE_VALID) {
+	if ((sun4c_get_pte(addr) & (_SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_VALID)) ==
+	    _SUN4C_PAGE_VALID) {
 		unsigned long left = PAGE_SIZE;
 		unsigned long lsize = sun4c_vacinfo.linesize;
 
-		pageflushes++;
 		__asm__ __volatile__("
 		add	%2, %2, %%g1
 		add	%2, %%g1, %%g2
@@ -411,7 +300,7 @@
 	unsigned long vaddr;
 
 	sun4c_put_segmap(0, pseg);
-	for(vaddr = 0; vaddr < SUN4C_REAL_PGDIR_SIZE; vaddr+=PAGE_SIZE)
+	for (vaddr = 0; vaddr < SUN4C_REAL_PGDIR_SIZE; vaddr += PAGE_SIZE)
 		sun4c_put_pte(vaddr, 0);
 	sun4c_put_segmap(0, invalid_segment);
 }
@@ -423,15 +312,15 @@
 
 	savectx = sun4c_get_context();
 	kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
-	for(ctx = 0; ctx < num_contexts; ctx++) {
+	for (ctx = 0; ctx < num_contexts; ctx++) {
 		sun4c_set_context(ctx);
-		for(vaddr = 0; vaddr < 0x20000000; vaddr += SUN4C_REAL_PGDIR_SIZE)
+		for (vaddr = 0; vaddr < 0x20000000; vaddr += SUN4C_REAL_PGDIR_SIZE)
 			sun4c_put_segmap(vaddr, invalid_segment);
-		for(vaddr = 0xe0000000; vaddr < KERNBASE; vaddr += SUN4C_REAL_PGDIR_SIZE)
+		for (vaddr = 0xe0000000; vaddr < KERNBASE; vaddr += SUN4C_REAL_PGDIR_SIZE)
 			sun4c_put_segmap(vaddr, invalid_segment);
-		for(vaddr = kernel_end; vaddr < KADB_DEBUGGER_BEGVM; vaddr += SUN4C_REAL_PGDIR_SIZE)
+		for (vaddr = kernel_end; vaddr < KADB_DEBUGGER_BEGVM; vaddr += SUN4C_REAL_PGDIR_SIZE)
 			sun4c_put_segmap(vaddr, invalid_segment);
-		for(vaddr = LINUX_OPPROM_ENDVM; vaddr; vaddr += SUN4C_REAL_PGDIR_SIZE)
+		for (vaddr = LINUX_OPPROM_ENDVM; vaddr; vaddr += SUN4C_REAL_PGDIR_SIZE)
 			sun4c_put_segmap(vaddr, invalid_segment);
 	}
 	sun4c_set_context(savectx);
@@ -442,7 +331,7 @@
 	sun4c_disable_vac();
 
 	if (ARCH_SUN4) {
-		switch(idprom->id_machtype) {
+		switch (idprom->id_machtype) {
 
 		case (SM_SUN4|SM_4_110):
 			sun4c_vacinfo.type = NONE;
@@ -477,12 +366,12 @@
 		default:
 			prom_printf("Cannot initialize VAC - wierd sun4 model idprom->id_machtype = %d", idprom->id_machtype);
 			prom_halt();
-		}
+		};
 	} else {
 		sun4c_vacinfo.type = WRITE_THROUGH;
 
-		if((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
-		   (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
+		if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
+		    (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
 			/* PROM on SS1 lacks this info, to be super safe we
 			 * hard code it here since this arch is cast in stone.
 			 */
@@ -497,7 +386,7 @@
 		sun4c_vacinfo.do_hwflushes =
 		 prom_getintdefault(prom_root_node, "vac-hwflush", 0);
 
-		if(sun4c_vacinfo.do_hwflushes == 0)
+		if (sun4c_vacinfo.do_hwflushes == 0)
 			sun4c_vacinfo.do_hwflushes =
 			 prom_getintdefault(prom_root_node, "vac_hwflush", 0);
 
@@ -509,7 +398,7 @@
 
 	sun4c_vacinfo.num_lines =
 		(sun4c_vacinfo.num_bytes / sun4c_vacinfo.linesize);
-	switch(sun4c_vacinfo.linesize) {
+	switch (sun4c_vacinfo.linesize) {
 	case 16:
 		sun4c_vacinfo.log2lsize = 4;
 		break;
@@ -566,7 +455,7 @@
 			prom_printf("Unhandled number of segmaps: %d\n",
 				    num_segmaps);
 			prom_halt();
-	}
+	};
 	switch (num_contexts) {
 		case 8:
 			/* Default, nothing to do. */
@@ -574,19 +463,22 @@
 		case 16:
 			PATCH_INSN(num_context_patch1_16,
 				   num_context_patch1);
+#if 0
 			PATCH_INSN(num_context_patch2_16,
 				   num_context_patch2);
+#endif
 			break;
 		default:
 			prom_printf("Unhandled number of contexts: %d\n",
 				    num_contexts);
 			prom_halt();
-	}
-	if(sun4c_vacinfo.do_hwflushes != 0) {
+	};
+
+	if (sun4c_vacinfo.do_hwflushes != 0) {
 		PATCH_INSN(vac_hwflush_patch1_on, vac_hwflush_patch1);
 		PATCH_INSN(vac_hwflush_patch2_on, vac_hwflush_patch2);
 	} else {
-		switch(sun4c_vacinfo.linesize) {
+		switch (sun4c_vacinfo.linesize) {
 		case 16:
 			/* Default, nothing to do. */
 			break;
@@ -604,7 +496,7 @@
 static void __init sun4c_probe_mmu(void)
 {
 	if (ARCH_SUN4) {
-		switch(idprom->id_machtype) {
+		switch (idprom->id_machtype) {
 		case (SM_SUN4|SM_4_110):
 			prom_printf("No support for 4100 yet\n");
 			prom_halt();
@@ -631,10 +523,10 @@
 		default:
 			prom_printf("Invalid SUN4 model\n");
 			prom_halt();
-		}
+		};
 	} else {
-		if((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
-	   	(idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
+		if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
+		    (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
 			/* Hardcode these just to be safe, PROM on SS1 does
 		 	* not have this info available in the root node.
 		 	*/
@@ -658,20 +550,15 @@
 	struct linux_prom_registers regs[1];
 
 	if (ARCH_SUN4) {
-		sun4c_memerr_reg = sparc_alloc_io(sun4_memreg_physaddr, 0,
-					  	PAGE_SIZE,
-					  	"memory parity error",
-					  	0x0, 0);
+		sun4c_memerr_reg = ioremap(sun4_memreg_physaddr, PAGE_SIZE);
 	} else {
 		node = prom_getchild(prom_root_node);
 		node = prom_searchsiblings(prom_root_node, "memory-error");
 		if (!node)
 			return;
 		prom_getproperty(node, "reg", (char *)regs, sizeof(regs));
-		sun4c_memerr_reg = sparc_alloc_io(regs[0].phys_addr, 0,
-					  	regs[0].reg_size,
-					  	"memory parity error",
-					  	regs[0].which_io, 0);
+		/* hmm I think regs[0].which_io is zero here anyways */
+		sun4c_memerr_reg = ioremap(regs[0].phys_addr, regs[0].reg_size);
 	}
 }
 
@@ -679,10 +566,10 @@
 {
 	extern unsigned long start;
 
-	if((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) ||
-	   (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) ||
-	   (idprom->id_machtype == (SM_SUN4 | SM_4_330)) ||
-	   (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) {
+	if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) ||
+	    (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) ||
+	    (idprom->id_machtype == (SM_SUN4 | SM_4_330)) ||
+	    (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) {
 		/* Whee.. */
 		printk("SS2 cache bug detected, uncaching trap table page\n");
 		sun4c_flush_page((unsigned int) &start);
@@ -692,17 +579,13 @@
 }
 
 /* Addr is always aligned on a page boundry for us already. */
-static void sun4c_map_dma_area(unsigned long addr, int len)
+static void sun4c_map_dma_area(unsigned long va, u32 addr, int len)
 {
 	unsigned long page, end;
 
 	end = PAGE_ALIGN((addr + len));
-	while(addr < end) {
-		page = get_free_page(GFP_KERNEL);
-		if(!page) {
-			prom_printf("alloc_dvma: Cannot get a dvma page\n");
-			prom_halt();
-		}
+	while (addr < end) {
+		page = va;
 		sun4c_flush_page(page);
 		page -= PAGE_OFFSET;
 		page >>= PAGE_SHIFT;
@@ -710,9 +593,21 @@
 			 _SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_PRIV);
 		sun4c_put_pte(addr, page);
 		addr += PAGE_SIZE;
+		va += PAGE_SIZE;
 	}
 }
 
+static void sun4c_unmap_dma_area(unsigned long addr, int len)
+{
+}
+
+static void sun4c_inval_dma_area(unsigned long addr, int len)
+{
+}
+
+static void sun4c_flush_dma_area(unsigned long addr, int len)
+{
+}
 
 /* TLB management. */
 
@@ -726,6 +621,13 @@
 	unsigned long vaddr;
 	unsigned char pseg;
 	unsigned char locked;
+
+	/* For user mappings only, and completely hidden from kernel
+	 * TLB miss code.
+	 */
+	unsigned char ctx;
+	struct sun4c_mmu_entry *lru_next;
+	struct sun4c_mmu_entry *lru_prev;
 };
 
 static struct sun4c_mmu_entry mmu_entry_pool[SUN4C_MAX_SEGMAPS];
@@ -734,12 +636,15 @@
 {
 	int i;
 
-	for(i=0; i < SUN4C_MAX_SEGMAPS; i++) {
+	for (i=0; i < SUN4C_MAX_SEGMAPS; i++) {
 		mmu_entry_pool[i].pseg = i;
 		mmu_entry_pool[i].next = 0;
 		mmu_entry_pool[i].prev = 0;
 		mmu_entry_pool[i].vaddr = 0;
 		mmu_entry_pool[i].locked = 0;
+		mmu_entry_pool[i].ctx = 0;
+		mmu_entry_pool[i].lru_next = 0;
+		mmu_entry_pool[i].lru_prev = 0;
 	}
 	mmu_entry_pool[invalid_segment].locked = 1;
 }
@@ -750,8 +655,8 @@
 	unsigned long start, end;
 
 	end = vaddr + SUN4C_REAL_PGDIR_SIZE;
-	for(start = vaddr; start < end; start += PAGE_SIZE)
-		if(sun4c_get_pte(start) & _SUN4C_PAGE_VALID)
+	for (start = vaddr; start < end; start += PAGE_SIZE)
+		if (sun4c_get_pte(start) & _SUN4C_PAGE_VALID)
 			sun4c_put_pte(start, (sun4c_get_pte(start) | bits_on) &
 				      ~bits_off);
 }
@@ -762,16 +667,16 @@
 	unsigned char pseg, ctx;
 #ifdef CONFIG_SUN4
 	/* sun4/110 and 260 have no kadb. */
-	if((idprom->id_machtype != (SM_SUN4 | SM_4_260)) && 
-	   (idprom->id_machtype != (SM_SUN4 | SM_4_110))) {
+	if ((idprom->id_machtype != (SM_SUN4 | SM_4_260)) && 
+	    (idprom->id_machtype != (SM_SUN4 | SM_4_110))) {
 #endif
-	for(vaddr = KADB_DEBUGGER_BEGVM;
-	    vaddr < LINUX_OPPROM_ENDVM;
-	    vaddr += SUN4C_REAL_PGDIR_SIZE) {
+	for (vaddr = KADB_DEBUGGER_BEGVM;
+	     vaddr < LINUX_OPPROM_ENDVM;
+	     vaddr += SUN4C_REAL_PGDIR_SIZE) {
 		pseg = sun4c_get_segmap(vaddr);
-		if(pseg != invalid_segment) {
+		if (pseg != invalid_segment) {
 			mmu_entry_pool[pseg].locked = 1;
-			for(ctx = 0; ctx < num_contexts; ctx++)
+			for (ctx = 0; ctx < num_contexts; ctx++)
 				prom_putsegment(ctx, vaddr, pseg);
 			fix_permissions(vaddr, _SUN4C_PAGE_PRIV, 0);
 		}
@@ -779,10 +684,10 @@
 #ifdef CONFIG_SUN4
 	}
 #endif
-	for(vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) {
+	for (vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) {
 		pseg = sun4c_get_segmap(vaddr);
 		mmu_entry_pool[pseg].locked = 1;
-		for(ctx = 0; ctx < num_contexts; ctx++)
+		for (ctx = 0; ctx < num_contexts; ctx++)
 			prom_putsegment(ctx, vaddr, pseg);
 		fix_permissions(vaddr, _SUN4C_PAGE_PRIV, _SUN4C_PAGE_NOCACHE);
 	}
@@ -792,13 +697,13 @@
 {
 	int i, ctx;
 
-	while(start < end) {
-		for(i=0; i < invalid_segment; i++)
-			if(!mmu_entry_pool[i].locked)
+	while (start < end) {
+		for (i = 0; i < invalid_segment; i++)
+			if (!mmu_entry_pool[i].locked)
 				break;
 		mmu_entry_pool[i].locked = 1;
 		sun4c_init_clean_segmap(i);
-		for(ctx = 0; ctx < num_contexts; ctx++)
+		for (ctx = 0; ctx < num_contexts; ctx++)
 			prom_putsegment(ctx, start, mmu_entry_pool[i].pseg);
 		start += SUN4C_REAL_PGDIR_SIZE;
 	}
@@ -815,13 +720,15 @@
 
 static struct sun4c_mmu_ring sun4c_context_ring[SUN4C_MAX_CONTEXTS]; /* used user entries */
 static struct sun4c_mmu_ring sun4c_ufree_ring;       /* free user entries */
+static struct sun4c_mmu_ring sun4c_ulru_ring;	     /* LRU user entries */
 struct sun4c_mmu_ring sun4c_kernel_ring;      /* used kernel entries */
 struct sun4c_mmu_ring sun4c_kfree_ring;       /* free kernel entries */
 
-static inline void sun4c_init_rings(unsigned long *mempool)
+static inline void sun4c_init_rings(void)
 {
 	int i;
-	for(i=0; i<SUN4C_MAX_CONTEXTS; i++) {
+
+	for (i = 0; i < SUN4C_MAX_CONTEXTS; i++) {
 		sun4c_context_ring[i].ringhd.next =
 			sun4c_context_ring[i].ringhd.prev =
 			&sun4c_context_ring[i].ringhd;
@@ -830,6 +737,9 @@
 	sun4c_ufree_ring.ringhd.next = sun4c_ufree_ring.ringhd.prev =
 		&sun4c_ufree_ring.ringhd;
 	sun4c_ufree_ring.num_entries = 0;
+	sun4c_ulru_ring.ringhd.lru_next = sun4c_ulru_ring.ringhd.lru_prev =
+		&sun4c_ulru_ring.ringhd;
+	sun4c_ulru_ring.num_entries = 0;
 	sun4c_kernel_ring.ringhd.next = sun4c_kernel_ring.ringhd.prev =
 		&sun4c_kernel_ring.ringhd;
 	sun4c_kernel_ring.num_entries = 0;
@@ -838,8 +748,8 @@
 	sun4c_kfree_ring.num_entries = 0;
 }
 
-static inline void add_ring(struct sun4c_mmu_ring *ring,
-			    struct sun4c_mmu_entry *entry)
+static void add_ring(struct sun4c_mmu_ring *ring,
+		     struct sun4c_mmu_entry *entry)
 {
 	struct sun4c_mmu_entry *head = &ring->ringhd;
 
@@ -849,49 +759,58 @@
 	ring->num_entries++;
 }
 
-static inline void add_ring_ordered(struct sun4c_mmu_ring *ring,
-				    struct sun4c_mmu_entry *entry)
+static __inline__ void add_lru(struct sun4c_mmu_entry *entry)
+{
+	struct sun4c_mmu_ring *ring = &sun4c_ulru_ring;
+	struct sun4c_mmu_entry *head = &ring->ringhd;
+
+	entry->lru_next = head;
+	(entry->lru_prev = head->lru_prev)->lru_next = entry;
+	head->lru_prev = entry;
+}
+
+static void add_ring_ordered(struct sun4c_mmu_ring *ring,
+			     struct sun4c_mmu_entry *entry)
 {
 	struct sun4c_mmu_entry *head = &ring->ringhd;
 	unsigned long addr = entry->vaddr;
 
-	if(head->next != &ring->ringhd) {
-		while((head->next != &ring->ringhd) && (head->next->vaddr < addr))
-			head = head->next;
-	}
+	while ((head->next != &ring->ringhd) && (head->next->vaddr < addr))
+		head = head->next;
+
 	entry->prev = head;
 	(entry->next = head->next)->prev = entry;
 	head->next = entry;
 	ring->num_entries++;
+
+	add_lru(entry);
 }
 
-static inline void remove_ring(struct sun4c_mmu_ring *ring,
-			       struct sun4c_mmu_entry *entry)
+static __inline__ void remove_ring(struct sun4c_mmu_ring *ring,
+				   struct sun4c_mmu_entry *entry)
 {
 	struct sun4c_mmu_entry *next = entry->next;
 
 	(next->prev = entry->prev)->next = next;
 	ring->num_entries--;
-#ifdef DEBUG_SUN4C_MM
-	if(ring->num_entries < 0)
-		panic("sun4c: Ring num_entries < 0!");
-#endif
 }
 
-static inline void free_user_entry(int ctx, struct sun4c_mmu_entry *entry)
+static void remove_lru(struct sun4c_mmu_entry *entry)
 {
-        remove_ring(sun4c_context_ring+ctx, entry);
-        add_ring(&sun4c_ufree_ring, entry);
+	struct sun4c_mmu_entry *next = entry->lru_next;
+
+	(next->lru_prev = entry->lru_prev)->lru_next = next;
 }
 
-static inline void assign_user_entry(int ctx, struct sun4c_mmu_entry *entry) 
+static void free_user_entry(int ctx, struct sun4c_mmu_entry *entry)
 {
-        remove_ring(&sun4c_ufree_ring, entry);
-        add_ring_ordered(sun4c_context_ring+ctx, entry);
+        remove_ring(sun4c_context_ring+ctx, entry);
+	remove_lru(entry);
+        add_ring(&sun4c_ufree_ring, entry);
 }
 
-static inline void free_kernel_entry(struct sun4c_mmu_entry *entry,
-				     struct sun4c_mmu_ring *ring)
+static void free_kernel_entry(struct sun4c_mmu_entry *entry,
+			      struct sun4c_mmu_ring *ring)
 {
         remove_ring(ring, entry);
         add_ring(&sun4c_kfree_ring, entry);
@@ -901,9 +820,9 @@
 {
 	int i;
 
-	while(howmany) {
-		for(i=0; i < invalid_segment; i++)
-			if(!mmu_entry_pool[i].locked)
+	while (howmany) {
+		for (i = 0; i < invalid_segment; i++)
+			if (!mmu_entry_pool[i].locked)
 				break;
 		mmu_entry_pool[i].locked = 1;
 		sun4c_init_clean_segmap(i);
@@ -916,54 +835,40 @@
 {
 	int i;
 
-	for(i=0; i < invalid_segment; i++) {
-		if(mmu_entry_pool[i].locked)
+	for (i = 0; i < invalid_segment; i++) {
+		if (mmu_entry_pool[i].locked)
 			continue;
 		sun4c_init_clean_segmap(i);
 		add_ring(&sun4c_ufree_ring, &mmu_entry_pool[i]);
 	}
 }
 
-static inline void sun4c_kernel_unmap(struct sun4c_mmu_entry *kentry)
+static void sun4c_kernel_unmap(struct sun4c_mmu_entry *kentry)
 {
 	int savectx, ctx;
 
 	savectx = sun4c_get_context();
-	for(ctx = 0; ctx < num_contexts; ctx++) {
+	for (ctx = 0; ctx < num_contexts; ctx++) {
 		sun4c_set_context(ctx);
 		sun4c_put_segmap(kentry->vaddr, invalid_segment);
 	}
 	sun4c_set_context(savectx);
 }
 
-static inline void sun4c_kernel_map(struct sun4c_mmu_entry *kentry)
+static void sun4c_kernel_map(struct sun4c_mmu_entry *kentry)
 {
 	int savectx, ctx;
 
 	savectx = sun4c_get_context();
-	for(ctx = 0; ctx < num_contexts; ctx++) {
+	for (ctx = 0; ctx < num_contexts; ctx++) {
 		sun4c_set_context(ctx);
 		sun4c_put_segmap(kentry->vaddr, kentry->pseg);
 	}
 	sun4c_set_context(savectx);
 }
 
-static inline void sun4c_user_unmap(struct sun4c_mmu_entry *uentry)
-{
-	sun4c_put_segmap(uentry->vaddr, invalid_segment);
-}
-
-static inline void sun4c_user_map(struct sun4c_mmu_entry *uentry)
-{
-	unsigned long start = uentry->vaddr;
-	unsigned long end = start + SUN4C_REAL_PGDIR_SIZE;
-
-	sun4c_put_segmap(uentry->vaddr, uentry->pseg);
-	while(start < end) {
-		sun4c_put_pte(start, 0);
-		start += PAGE_SIZE;
-	}
-}
+#define sun4c_user_unmap(__entry) \
+	sun4c_put_segmap((__entry)->vaddr, invalid_segment)
 
 static void sun4c_demap_context_hw(struct sun4c_mmu_ring *crp, unsigned char ctx)
 {
@@ -971,11 +876,11 @@
 	unsigned long flags;
 
 	save_and_cli(flags);
-	if(head->next != head) {
+	if (head->next != head) {
 		struct sun4c_mmu_entry *entry = head->next;
 		int savectx = sun4c_get_context();
 
-		FUW_INLINE
+		flush_user_windows();
 		sun4c_set_context(ctx);
 		sun4c_flush_context_hw();
 		do {
@@ -985,7 +890,7 @@
 			free_user_entry(ctx, entry);
 
 			entry = next;
-		} while(entry != head);
+		} while (entry != head);
 		sun4c_set_context(savectx);
 	}
 	restore_flags(flags);
@@ -997,11 +902,11 @@
 	unsigned long flags;
 
 	save_and_cli(flags);
-	if(head->next != head) {
+	if (head->next != head) {
 		struct sun4c_mmu_entry *entry = head->next;
 		int savectx = sun4c_get_context();
 
-		FUW_INLINE
+		flush_user_windows();
 		sun4c_set_context(ctx);
 		sun4c_flush_context_sw();
 		do {
@@ -1011,49 +916,31 @@
 			free_user_entry(ctx, entry);
 
 			entry = next;
-		} while(entry != head);
+		} while (entry != head);
 		sun4c_set_context(savectx);
 	}
 	restore_flags(flags);
 }
 
-static inline void sun4c_demap_one(struct sun4c_mmu_ring *crp, unsigned char ctx)
-{
-	/* by using .prev we get a kind of "lru" algorithm */
-	struct sun4c_mmu_entry *entry = crp->ringhd.prev;
-	unsigned long flags;
-	int savectx = sun4c_get_context();
-
-#ifdef DEBUG_SUN4C_MM
-	if(entry == &crp->ringhd)
-		panic("sun4c_demap_one: Freeing from empty ctx ring.");
-#endif
-	FUW_INLINE
-	save_and_cli(flags);
-	sun4c_set_context(ctx);
-	sun4c_flush_segment(entry->vaddr);
-	sun4c_user_unmap(entry);
-	free_user_entry(ctx, entry);
-	sun4c_set_context(savectx);
-	restore_flags(flags);
-}
-
 static int sun4c_user_taken_entries = 0;  /* This is how much we have.             */
 static int max_user_taken_entries = 0;    /* This limits us and prevents deadlock. */
 
-static inline struct sun4c_mmu_entry *sun4c_kernel_strategy(void)
+static struct sun4c_mmu_entry *sun4c_kernel_strategy(void)
 {
 	struct sun4c_mmu_entry *this_entry;
 
 	/* If some are free, return first one. */
-	if(sun4c_kfree_ring.num_entries) {
+	if (sun4c_kfree_ring.num_entries) {
 		this_entry = sun4c_kfree_ring.ringhd.next;
 		return this_entry;
 	}
 
 	/* Else free one up. */
 	this_entry = sun4c_kernel_ring.ringhd.prev;
-	sun4c_flush_segment(this_entry->vaddr);
+	if (sun4c_vacinfo.do_hwflushes)
+		sun4c_flush_segment_hw(this_entry->vaddr);
+	else
+		sun4c_flush_segment_sw(this_entry->vaddr);
 	sun4c_kernel_unmap(this_entry);
 	free_kernel_entry(this_entry, &sun4c_kernel_ring);
 	this_entry = sun4c_kfree_ring.ringhd.next;
@@ -1061,141 +948,73 @@
 	return this_entry;
 }
 
-void sun4c_shrink_kernel_ring(void)
-{
-	struct sun4c_mmu_entry *entry;
-	unsigned long flags;
-
-	/* If an interrupt comes in here, we die... */
-	save_and_cli(flags);
-
-	if (sun4c_user_taken_entries) {
-		entry = sun4c_kernel_strategy();
-        	remove_ring(&sun4c_kfree_ring, entry);
-		add_ring(&sun4c_ufree_ring, entry);
-		sun4c_user_taken_entries--;
-#if 0
-		printk("shrink: ufree= %d, kfree= %d, kernel= %d\n",
-			sun4c_ufree_ring.num_entries,
-			sun4c_kfree_ring.num_entries,
-			sun4c_kernel_ring.num_entries);
-#endif
-#ifdef DEBUG_SUN4C_MM
-		if(sun4c_user_taken_entries < 0)
-			panic("sun4c_shrink_kernel_ring: taken < 0.");
-#endif
-	}
-	restore_flags(flags);
-}
-
 /* Using this method to free up mmu entries eliminates a lot of
  * potential races since we have a kernel that incurs tlb
  * replacement faults.  There may be performance penalties.
+ *
+ * NOTE: Must be called with interrupts disabled.
  */
-static inline struct sun4c_mmu_entry *sun4c_user_strategy(void)
+static struct sun4c_mmu_entry *sun4c_user_strategy(void)
 {
-	struct ctx_list *next_one;
-	struct sun4c_mmu_ring *rp = 0;
+	struct sun4c_mmu_entry *entry;
 	unsigned char ctx;
-#ifdef DEBUG_SUN4C_MM
-	int lim = num_contexts;
-#endif
+	int savectx;
 
 	/* If some are free, return first one. */
-	if(sun4c_ufree_ring.num_entries) {
-#ifdef DEBUG_SUN4C_MM
-		if(sun4c_ufree_ring.ringhd.next == &sun4c_ufree_ring.ringhd)
-			panic("sun4c_user_strategy: num_entries!=0 but ring empty.");
-#endif
-		return sun4c_ufree_ring.ringhd.next;
+	if (sun4c_ufree_ring.num_entries) {
+		entry = sun4c_ufree_ring.ringhd.next;
+		goto unlink_out;
 	}
 
 	if (sun4c_user_taken_entries) {
-		sun4c_shrink_kernel_ring();
-#ifdef DEBUG_SUN4C_MM
-		if(sun4c_ufree_ring.ringhd.next == &sun4c_ufree_ring.ringhd)
-			panic("sun4c_user_strategy: kernel shrunk but ufree empty.");
-#endif
-		return sun4c_ufree_ring.ringhd.next;
+		entry = sun4c_kernel_strategy();
+		sun4c_user_taken_entries--;
+		goto kunlink_out;
 	}
 
-	/* Grab one from the LRU context. */
-	next_one = ctx_used.next;
-	while ((sun4c_context_ring[next_one->ctx_number].num_entries == 0)
-#ifdef DEBUG_SUN4C_MM
-	       && (--lim >= 0)
-#endif
-	       )
-		next_one = next_one->next;
+	/* Grab from the beginning of the LRU list. */
+	entry = sun4c_ulru_ring.ringhd.lru_next;
+	ctx = entry->ctx;
 
-#ifdef DEBUG_SUN4C_MM
-	if(lim < 0)
-		panic("No user segmaps!");
-#endif
+	savectx = sun4c_get_context();
+	flush_user_windows();
+	sun4c_set_context(ctx);
+	if (sun4c_vacinfo.do_hwflushes)
+		sun4c_flush_segment_hw(entry->vaddr);
+	else
+		sun4c_flush_segment_sw(entry->vaddr);
+	sun4c_user_unmap(entry);
+	remove_ring(sun4c_context_ring + ctx, entry);
+	remove_lru(entry);
+	sun4c_set_context(savectx);
 
-	ctx = next_one->ctx_number;
-	rp = &sun4c_context_ring[ctx];
+	return entry;
 
-	sun4c_demap_one(rp, ctx);
-#ifdef DEBUG_SUN4C_MM
-	if(sun4c_ufree_ring.ringhd.next == &sun4c_ufree_ring.ringhd)
-		panic("sun4c_user_strategy: demapped one but ufree empty.");
-#endif
-	return sun4c_ufree_ring.ringhd.next;
+unlink_out:
+	remove_ring(&sun4c_ufree_ring, entry);
+	return entry;
+kunlink_out:
+	remove_ring(&sun4c_kfree_ring, entry);
+	return entry;
 }
 
+/* NOTE: Must be called with interrupts disabled. */
 void sun4c_grow_kernel_ring(void)
 {
 	struct sun4c_mmu_entry *entry;
 
-#if 0
-	printk("grow: ");
-#endif
-
 	/* Prevent deadlock condition. */
-	if(sun4c_user_taken_entries >= max_user_taken_entries) {
-#if 0
-		printk("deadlock avoidance, taken= %d max= %d\n",
-		       sun4c_user_taken_entries, max_user_taken_entries);
-#endif
+	if (sun4c_user_taken_entries >= max_user_taken_entries)
 		return;
-	}
 
 	if (sun4c_ufree_ring.num_entries) {
 		entry = sun4c_ufree_ring.ringhd.next;
-#ifdef DEBUG_SUN4C_MM
-		if(entry == &sun4c_ufree_ring.ringhd)
-			panic("\nsun4c_grow_kernel_ring: num_entries!=0, ring empty.");
-#endif
         	remove_ring(&sun4c_ufree_ring, entry);
 		add_ring(&sun4c_kfree_ring, entry);
-#ifdef DEBUG_SUN4C_MM
-		if(sun4c_user_taken_entries < 0)
-			panic("\nsun4c_grow_kernel_ring: taken < 0.");
-#endif
 		sun4c_user_taken_entries++;
-#if 0
-		printk("ufree= %d, kfree= %d, kernel= %d\n",
-			sun4c_ufree_ring.num_entries,
-			sun4c_kfree_ring.num_entries,
-			sun4c_kernel_ring.num_entries);
-#endif
 	}
 }
 
-static inline void alloc_user_segment(unsigned long address, unsigned char ctx)
-{
-	struct sun4c_mmu_entry *entry;
-	unsigned long flags;
-
-	save_and_cli(flags);
-	entry = sun4c_user_strategy();
-	entry->vaddr = (address & SUN4C_REAL_PGDIR_MASK);
-	assign_user_entry(ctx, entry);
-	sun4c_user_map(entry);
-	restore_flags(flags);
-}
-
 /* This is now a fast in-window trap handler to avoid any and all races. */
 static void sun4c_quick_kernel_fault(unsigned long address)
 {
@@ -1209,8 +1028,8 @@
  * bucket[0]
  * bucket[1]
  *   [ ... ]
- * bucket[NR_TASKS-1]
- * TASK_STACK_BEGIN + (sizeof(struct task_bucket) * NR_TASKS)
+ * bucket[NR_TASK_BUCKETS-1]
+ * TASK_STACK_BEGIN + (sizeof(struct task_bucket) * NR_TASK_BUCKETS)
  *
  * Each slot looks like:
  *
@@ -1218,7 +1037,7 @@
  *  page 2 --  rest of kernel stack
  */
 
-union task_union *sun4c_bucket[NR_TASKS];
+union task_union *sun4c_bucket[NR_TASK_BUCKETS];
 
 static int sun4c_lowbucket_avail;
 
@@ -1232,7 +1051,7 @@
 #define BUCKET_PTE_PAGE(pte)   \
         (PAGE_OFFSET + (((pte) & SUN4C_PFN_MASK) << PAGE_SHIFT))
 
-static inline void get_locked_segment(unsigned long addr)
+static void get_locked_segment(unsigned long addr)
 {
 	struct sun4c_mmu_entry *stolen;
 	unsigned long flags;
@@ -1240,19 +1059,14 @@
 	save_and_cli(flags);
 	addr &= SUN4C_REAL_PGDIR_MASK;
 	stolen = sun4c_user_strategy();
-	remove_ring(&sun4c_ufree_ring, stolen);
 	max_user_taken_entries--;
-#ifdef DEBUG_SUN4C_MM
-	if(max_user_taken_entries < 0)
-		panic("get_locked_segment: max_user_taken < 0.");
-#endif
 	stolen->vaddr = addr;
-	FUW_INLINE
+	flush_user_windows();
 	sun4c_kernel_map(stolen);
 	restore_flags(flags);
 }
 
-static inline void free_locked_segment(unsigned long addr)
+static void free_locked_segment(unsigned long addr)
 {
 	struct sun4c_mmu_entry *entry;
 	unsigned long flags;
@@ -1263,14 +1077,13 @@
 	pseg = sun4c_get_segmap(addr);
 	entry = &mmu_entry_pool[pseg];
 
-	FUW_INLINE
-	sun4c_flush_segment(addr);
+	flush_user_windows();
+	if (sun4c_vacinfo.do_hwflushes)
+		sun4c_flush_segment_hw(addr);
+	else
+		sun4c_flush_segment_sw(addr);
 	sun4c_kernel_unmap(entry);
 	add_ring(&sun4c_ufree_ring, entry);
-#ifdef DEBUG_SUN4C_MM
-	if(max_user_taken_entries < 0)
-		panic("free_locked_segment: max_user_taken < 0.");
-#endif
 	max_user_taken_entries++;
 	restore_flags(flags);
 }
@@ -1282,8 +1095,8 @@
 	/* 32 buckets per segment... */
 	entry &= ~31;
 	start = entry;
-	for(end = (start + 32); start < end; start++)
-		if(sun4c_bucket[start] != BUCKET_EMPTY)
+	for (end = (start + 32); start < end; start++)
+		if (sun4c_bucket[start] != BUCKET_EMPTY)
 			return;
 
 	/* Entire segment empty, release it. */
@@ -1302,23 +1115,39 @@
 	int entry;
 
 	pages = __get_free_pages(GFP_KERNEL, TASK_STRUCT_ORDER);
-	if(!pages)
+	if (!pages)
 		return (struct task_struct *) 0;
 
-	for(entry = sun4c_lowbucket_avail; entry < NR_TASKS; entry++)
-		if(sun4c_bucket[entry] == BUCKET_EMPTY)
+	for (entry = sun4c_lowbucket_avail; entry < NR_TASK_BUCKETS; entry++)
+		if (sun4c_bucket[entry] == BUCKET_EMPTY)
 			break;
-	if(entry == NR_TASKS) {
+	if (entry == NR_TASK_BUCKETS) {
 		free_pages(pages, TASK_STRUCT_ORDER);
 		return (struct task_struct *) 0;
 	}
-	if(entry >= sun4c_lowbucket_avail)
+	if (entry >= sun4c_lowbucket_avail)
 		sun4c_lowbucket_avail = entry + 1;
 
 	addr = BUCKET_ADDR(entry);
 	sun4c_bucket[entry] = (union task_union *) addr;
 	if(sun4c_get_segmap(addr) == invalid_segment)
 		get_locked_segment(addr);
+
+	/* We are changing the virtual color of the page(s)
+	 * so we must flush the cache to guarentee consistancy.
+	 */
+	if (sun4c_vacinfo.do_hwflushes) {
+		sun4c_flush_page_hw(pages);
+#ifndef CONFIG_SUN4	
+		sun4c_flush_page_hw(pages + PAGE_SIZE);
+#endif
+	} else {
+		sun4c_flush_page_sw(pages);
+#ifndef CONFIG_SUN4	
+		sun4c_flush_page_sw(pages + PAGE_SIZE);
+#endif
+	}
+
 	sun4c_put_pte(addr, BUCKET_PTE(pages));
 #ifndef CONFIG_SUN4	
 	sun4c_put_pte(addr + PAGE_SIZE, BUCKET_PTE(pages + PAGE_SIZE));
@@ -1342,7 +1171,7 @@
 	sun4c_put_pte(tsaddr + PAGE_SIZE, 0);
 #endif
 	sun4c_bucket[entry] = BUCKET_EMPTY;
-	if(entry < sun4c_lowbucket_avail)
+	if (entry < sun4c_lowbucket_avail)
 		sun4c_lowbucket_avail = entry;
 
 	free_pages(pages, TASK_STRUCT_ORDER);
@@ -1365,7 +1194,7 @@
 	sun4c_put_pte(tsaddr + PAGE_SIZE, 0);
 #endif
 	sun4c_bucket[entry] = BUCKET_EMPTY;
-	if(entry < sun4c_lowbucket_avail)
+	if (entry < sun4c_lowbucket_avail)
 		sun4c_lowbucket_avail = entry;
 
 	free_pages(pages, TASK_STRUCT_ORDER);
@@ -1376,10 +1205,10 @@
 {
 	int entry;
 
-	if(sizeof(union task_union) != (PAGE_SIZE << TASK_STRUCT_ORDER)) {
+	if (sizeof(union task_union) != (PAGE_SIZE << TASK_STRUCT_ORDER)) {
 		prom_printf("task union not %d page(s)!\n", 1 << TASK_STRUCT_ORDER);
 	}
-	for(entry = 0; entry < NR_TASKS; entry++)
+	for (entry = 0; entry < NR_TASK_BUCKETS; entry++)
 		sun4c_bucket[entry] = BUCKET_EMPTY;
 	sun4c_lowbucket_avail = 0;
 }
@@ -1494,37 +1323,38 @@
  * by implication and fool the page locking code above
  * if passed to by mistake.
  */
-static __u32 sun4c_get_scsi_one(char *bufptr, unsigned long len, struct linux_sbus *sbus)
+static __u32 sun4c_get_scsi_one(char *bufptr, unsigned long len, struct sbus_bus *sbus)
 {
 	unsigned long page;
 
 	page = ((unsigned long)bufptr) & PAGE_MASK;
-	if(MAP_NR(page) > max_mapnr) {
+	if (MAP_NR(page) > max_mapnr) {
 		sun4c_flush_page(page);
 		return (__u32)bufptr; /* already locked */
 	}
 	return (__u32)sun4c_lockarea(bufptr, len);
 }
 
-static void sun4c_get_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
+static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
-	while(sz >= 0) {
-		sg[sz].dvma_addr = (__u32)sun4c_lockarea(sg[sz].addr, sg[sz].len);
+	while (sz >= 0) {
+		sg[sz].dvma_address = (__u32)sun4c_lockarea(sg[sz].address, sg[sz].length);
+		sg[sz].dvma_length = sg[sz].length;
 		sz--;
 	}
 }
 
-static void sun4c_release_scsi_one(__u32 bufptr, unsigned long len, struct linux_sbus *sbus)
+static void sun4c_release_scsi_one(__u32 bufptr, unsigned long len, struct sbus_bus *sbus)
 {
-	if(bufptr < sun4c_iobuffer_start)
+	if (bufptr < sun4c_iobuffer_start)
 		return; /* On kernel stack or similar, see above */
 	sun4c_unlockarea((char *)bufptr, len);
 }
 
-static void sun4c_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
+static void sun4c_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
 {
-	while(sz >= 0) {
-		sun4c_unlockarea((char *)sg[sz].dvma_addr, sg[sz].len);
+	while (sz >= 0) {
+		sun4c_unlockarea((char *)sg[sz].dvma_address, sg[sz].length);
 		sz--;
 	}
 }
@@ -1534,7 +1364,7 @@
 
 struct vm_area_struct sun4c_kstack_vma;
 
-static unsigned long __init sun4c_init_lock_areas(unsigned long start_mem)
+static void __init sun4c_init_lock_areas(void)
 {
 	unsigned long sun4c_taskstack_start;
 	unsigned long sun4c_taskstack_end;
@@ -1543,9 +1373,9 @@
 	sun4c_init_buckets();
 	sun4c_taskstack_start = SUN4C_LOCK_VADDR;
 	sun4c_taskstack_end = (sun4c_taskstack_start +
-			       (TASK_ENTRY_SIZE * NR_TASKS));
-	if(sun4c_taskstack_end >= SUN4C_LOCK_END) {
-		prom_printf("Too many tasks, decrease NR_TASKS please.\n");
+			       (TASK_ENTRY_SIZE * NR_TASK_BUCKETS));
+	if (sun4c_taskstack_end >= SUN4C_LOCK_END) {
+		prom_printf("Too many tasks, decrease NR_TASK_BUCKETS please.\n");
 		prom_halt();
 	}
 
@@ -1556,9 +1386,8 @@
 	bitmap_size = (bitmap_size + 7) >> 3;
 	bitmap_size = LONG_ALIGN(bitmap_size);
 	iobuffer_map_size = bitmap_size << 3;
-	sun4c_iobuffer_map = (unsigned long *) start_mem;
-	memset((void *) start_mem, 0, bitmap_size);
-	start_mem += bitmap_size;
+	sun4c_iobuffer_map = __alloc_bootmem(bitmap_size, SMP_CACHE_BYTES, 0UL);
+	memset((void *) sun4c_iobuffer_map, 0, bitmap_size);
 
 	sun4c_kstack_vma.vm_mm = &init_mm;
 	sun4c_kstack_vma.vm_start = sun4c_taskstack_start;
@@ -1566,7 +1395,6 @@
 	sun4c_kstack_vma.vm_page_prot = PAGE_SHARED;
 	sun4c_kstack_vma.vm_flags = VM_READ | VM_WRITE | VM_EXEC;
 	insert_vm_struct(&init_mm, &sun4c_kstack_vma);
-	return start_mem;
 }
 
 /* Cache flushing on the sun4c. */
@@ -1574,12 +1402,12 @@
 {
 	unsigned long begin, end;
 
-	FUW_INLINE
+	flush_user_windows();
 	begin = (KERNBASE + SUN4C_REAL_PGDIR_SIZE);
 	end = (begin + SUN4C_VAC_SIZE);
 
-	if(sun4c_vacinfo.linesize == 32) {
-		while(begin < end) {
+	if (sun4c_vacinfo.linesize == 32) {
+		while (begin < end) {
 			__asm__ __volatile__("
 			ld	[%0 + 0x00], %%g0
 			ld	[%0 + 0x20], %%g0
@@ -1601,7 +1429,7 @@
 			begin += 512;
 		}
 	} else {
-		while(begin < end) {
+		while (begin < end) {
 			__asm__ __volatile__("
 			ld	[%0 + 0x00], %%g0
 			ld	[%0 + 0x10], %%g0
@@ -1629,29 +1457,31 @@
 {
 	int new_ctx = mm->context;
 
-	if(new_ctx != NO_CONTEXT && sun4c_context_ring[new_ctx].num_entries) {
-		struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
-		unsigned long flags;
-
-		save_and_cli(flags);
-		if(head->next != head) {
-			struct sun4c_mmu_entry *entry = head->next;
-			int savectx = sun4c_get_context();
-
-			FUW_INLINE
-			sun4c_set_context(new_ctx);
-			sun4c_flush_context_hw();
-			do {
-				struct sun4c_mmu_entry *next = entry->next;
+	if (new_ctx != NO_CONTEXT) {
+		flush_user_windows();
+		if (sun4c_context_ring[new_ctx].num_entries) {
+			struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
+			unsigned long flags;
+
+			save_and_cli(flags);
+			if (head->next != head) {
+				struct sun4c_mmu_entry *entry = head->next;
+				int savectx = sun4c_get_context();
+
+				sun4c_set_context(new_ctx);
+				sun4c_flush_context_hw();
+				do {
+					struct sun4c_mmu_entry *next = entry->next;
 
-				sun4c_user_unmap(entry);
-				free_user_entry(new_ctx, entry);
+					sun4c_user_unmap(entry);
+					free_user_entry(new_ctx, entry);
 
-				entry = next;
-			} while(entry != head);
-			sun4c_set_context(savectx);
+					entry = next;
+				} while (entry != head);
+				sun4c_set_context(savectx);
+			}
+			restore_flags(flags);
 		}
-		restore_flags(flags);
 	}
 }
 
@@ -1659,29 +1489,28 @@
 {
 	int new_ctx = mm->context;
 	
-#if KGPROF_PROFILING
-	kgprof_profile();
-#endif
-	if(new_ctx != NO_CONTEXT) {
+	if (new_ctx != NO_CONTEXT) {
 		struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
 		struct sun4c_mmu_entry *entry;
 		unsigned long flags;
 
-		FUW_INLINE
+		flush_user_windows();
+
 		save_and_cli(flags);
 
 		/* All user segmap chains are ordered on entry->vaddr. */
-		for(entry = head->next;
-		    (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
-		    entry = entry->next)
+		for (entry = head->next;
+		     (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
+		     entry = entry->next)
 			;
 
 		/* Tracing various job mixtures showed that this conditional
 		 * only passes ~35% of the time for most worse case situations,
 		 * therefore we avoid all of this gross overhead ~65% of the time.
 		 */
-		if((entry != head) && (entry->vaddr < end)) {
+		if ((entry != head) && (entry->vaddr < end)) {
 			int octx = sun4c_get_context();
+
 			sun4c_set_context(new_ctx);
 
 			/* At this point, always, (start >= entry->vaddr) and
@@ -1696,11 +1525,11 @@
 
 				/* "realstart" is always >= entry->vaddr */
 				realend = entry->vaddr + SUN4C_REAL_PGDIR_SIZE;
-				if(end < realend)
+				if (end < realend)
 					realend = end;
-				if((realend - entry->vaddr) <= (PAGE_SIZE << 3)) {
+				if ((realend - entry->vaddr) <= (PAGE_SIZE << 3)) {
 					unsigned long page = entry->vaddr;
-					while(page < realend) {
+					while (page < realend) {
 						sun4c_flush_page_hw(page);
 						page += PAGE_SIZE;
 					}
@@ -1710,14 +1539,13 @@
 					free_user_entry(new_ctx, entry);
 				}
 				entry = next;
-			} while((entry != head) && (entry->vaddr < end));
+			} while ((entry != head) && (entry->vaddr < end));
 			sun4c_set_context(octx);
 		}
 		restore_flags(flags);
 	}
 }
 
-/* XXX no save_and_cli/restore_flags needed, but put here if darkside still crashes */
 static void sun4c_flush_cache_page_hw(struct vm_area_struct *vma, unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
@@ -1726,76 +1554,85 @@
 	/* Sun4c has no separate I/D caches so cannot optimize for non
 	 * text page flushes.
 	 */
-	if(new_ctx != NO_CONTEXT) {
+	if (new_ctx != NO_CONTEXT) {
 		int octx = sun4c_get_context();
+		unsigned long flags;
 
-		FUW_INLINE
+		flush_user_windows();
+		save_and_cli(flags);
 		sun4c_set_context(new_ctx);
 		sun4c_flush_page_hw(page);
 		sun4c_set_context(octx);
+		restore_flags(flags);
 	}
 }
 
-static void sun4c_flush_page_to_ram_hw(unsigned long page)
+static void sun4c_flush_page_to_ram_hw(struct page *page)
 {
-	sun4c_flush_page_hw(page);
+	unsigned long flags;
+	unsigned long addr = page_address(page);
+
+	save_and_cli(flags);
+	sun4c_flush_page_hw(addr);
+	restore_flags(flags);
 }
 
 static void sun4c_flush_cache_mm_sw(struct mm_struct *mm)
 {
 	int new_ctx = mm->context;
 
-	if(new_ctx != NO_CONTEXT && sun4c_context_ring[new_ctx].num_entries) {
-		struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
-		unsigned long flags;
+	if (new_ctx != NO_CONTEXT) {
+		flush_user_windows();
 
-		save_and_cli(flags);
-		if(head->next != head) {
-			struct sun4c_mmu_entry *entry = head->next;
-			int savectx = sun4c_get_context();
+		if (sun4c_context_ring[new_ctx].num_entries) {
+			struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
+			unsigned long flags;
+
+			save_and_cli(flags);
+			if (head->next != head) {
+				struct sun4c_mmu_entry *entry = head->next;
+				int savectx = sun4c_get_context();
+
+				sun4c_set_context(new_ctx);
+				sun4c_flush_context_sw();
+				do {
+					struct sun4c_mmu_entry *next = entry->next;
 
-			FUW_INLINE
-			sun4c_set_context(new_ctx);
-			sun4c_flush_context_sw();
-			do {
-				struct sun4c_mmu_entry *next = entry->next;
-
-				sun4c_user_unmap(entry);
-				free_user_entry(new_ctx, entry);
+					sun4c_user_unmap(entry);
+					free_user_entry(new_ctx, entry);
 
-				entry = next;
-			} while(entry != head);
-			sun4c_set_context(savectx);
+					entry = next;
+				} while (entry != head);
+				sun4c_set_context(savectx);
+			}
+			restore_flags(flags);
 		}
-		restore_flags(flags);
 	}
 }
 
 static void sun4c_flush_cache_range_sw(struct mm_struct *mm, unsigned long start, unsigned long end)
 {
 	int new_ctx = mm->context;
-	
-#if KGPROF_PROFILING
-	kgprof_profile();
-#endif
-	if(new_ctx != NO_CONTEXT) {
+
+	if (new_ctx != NO_CONTEXT) {
 		struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
 		struct sun4c_mmu_entry *entry;
 		unsigned long flags;
 
-		FUW_INLINE
+		flush_user_windows();
+
 		save_and_cli(flags);
 		/* All user segmap chains are ordered on entry->vaddr. */
-		for(entry = head->next;
-		    (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
-		    entry = entry->next)
+		for (entry = head->next;
+		     (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
+		     entry = entry->next)
 			;
 
 		/* Tracing various job mixtures showed that this conditional
 		 * only passes ~35% of the time for most worse case situations,
 		 * therefore we avoid all of this gross overhead ~65% of the time.
 		 */
-		if((entry != head) && (entry->vaddr < end)) {
+		if ((entry != head) && (entry->vaddr < end)) {
 			int octx = sun4c_get_context();
 			sun4c_set_context(new_ctx);
 
@@ -1811,11 +1648,11 @@
 
 				/* "realstart" is always >= entry->vaddr */
 				realend = entry->vaddr + SUN4C_REAL_PGDIR_SIZE;
-				if(end < realend)
+				if (end < realend)
 					realend = end;
-				if((realend - entry->vaddr) <= (PAGE_SIZE << 3)) {
+				if ((realend - entry->vaddr) <= (PAGE_SIZE << 3)) {
 					unsigned long page = entry->vaddr;
-					while(page < realend) {
+					while (page < realend) {
 						sun4c_flush_page_sw(page);
 						page += PAGE_SIZE;
 					}
@@ -1825,7 +1662,7 @@
 					free_user_entry(new_ctx, entry);
 				}
 				entry = next;
-			} while((entry != head) && (entry->vaddr < end));
+			} while ((entry != head) && (entry->vaddr < end));
 			sun4c_set_context(octx);
 		}
 		restore_flags(flags);
@@ -1840,19 +1677,27 @@
 	/* Sun4c has no separate I/D caches so cannot optimize for non
 	 * text page flushes.
 	 */
-	if(new_ctx != NO_CONTEXT) {
+	if (new_ctx != NO_CONTEXT) {
 		int octx = sun4c_get_context();
+		unsigned long flags;
 
-		FUW_INLINE
+		flush_user_windows();
+		save_and_cli(flags);
 		sun4c_set_context(new_ctx);
 		sun4c_flush_page_sw(page);
 		sun4c_set_context(octx);
+		restore_flags(flags);
 	}
 }
 
-static void sun4c_flush_page_to_ram_sw(unsigned long page)
+static void sun4c_flush_page_to_ram_sw(struct page *page)
 {
-	sun4c_flush_page_sw(page);
+	unsigned long flags;
+	unsigned long addr = page_address(page);
+
+	save_and_cli(flags);
+	sun4c_flush_page_sw(addr);
+	restore_flags(flags);
 }
 
 /* Sun4c cache is unified, both instructions and data live there, so
@@ -1879,8 +1724,11 @@
 	flush_user_windows();
 	while (sun4c_kernel_ring.num_entries) {
 		next_entry = this_entry->next;
-		sun4c_flush_segment(this_entry->vaddr);
-		for(ctx = 0; ctx < num_contexts; ctx++) {
+		if (sun4c_vacinfo.do_hwflushes)
+			sun4c_flush_segment_hw(this_entry->vaddr);
+		else
+			sun4c_flush_segment_sw(this_entry->vaddr);
+		for (ctx = 0; ctx < num_contexts; ctx++) {
 			sun4c_set_context(ctx);
 			sun4c_put_segmap(this_entry->vaddr, invalid_segment);
 		}
@@ -1895,16 +1743,15 @@
 {
 	int new_ctx = mm->context;
 
-	if(new_ctx != NO_CONTEXT) {
+	if (new_ctx != NO_CONTEXT) {
 		struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
 		unsigned long flags;
 
 		save_and_cli(flags);
-		if(head->next != head) {
+		if (head->next != head) {
 			struct sun4c_mmu_entry *entry = head->next;
 			int savectx = sun4c_get_context();
 
-			FUW_INLINE
 			sun4c_set_context(new_ctx);
 			sun4c_flush_context_hw();
 			do {
@@ -1914,7 +1761,7 @@
 				free_user_entry(new_ctx, entry);
 
 				entry = next;
-			} while(entry != head);
+			} while (entry != head);
 			sun4c_set_context(savectx);
 		}
 		restore_flags(flags);
@@ -1925,26 +1772,21 @@
 {
 	int new_ctx = mm->context;
 
-	if(new_ctx != NO_CONTEXT) {
+	if (new_ctx != NO_CONTEXT) {
 		struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
 		struct sun4c_mmu_entry *entry;
 		unsigned long flags;
-#if KGPROF_PROFILING
-		kgprof_profile();
-#endif
 
 		save_and_cli(flags);
 		/* See commentary in sun4c_flush_cache_range_*(). */
-		for(entry = head->next;
-		    (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
-		    entry = entry->next)
+		for (entry = head->next;
+		     (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
+		     entry = entry->next)
 			;
 
-		if((entry != head) && (entry->vaddr < end)) {
+		if ((entry != head) && (entry->vaddr < end)) {
 			int octx = sun4c_get_context();
 
-			/* This window flush is paranoid I think... -DaveM */
-			FUW_INLINE
 			sun4c_set_context(new_ctx);
 			do {
 				struct sun4c_mmu_entry *next = entry->next;
@@ -1954,7 +1796,7 @@
 				free_user_entry(new_ctx, entry);
 
 				entry = next;
-			} while((entry != head) && (entry->vaddr < end));
+			} while ((entry != head) && (entry->vaddr < end));
 			sun4c_set_context(octx);
 		}
 		restore_flags(flags);
@@ -1966,15 +1808,17 @@
 	struct mm_struct *mm = vma->vm_mm;
 	int new_ctx = mm->context;
 
-	if(new_ctx != NO_CONTEXT) {
+	if (new_ctx != NO_CONTEXT) {
 		int savectx = sun4c_get_context();
+		unsigned long flags;
 
-		FUW_INLINE
+		save_and_cli(flags);
 		sun4c_set_context(new_ctx);
 		page &= PAGE_MASK;
 		sun4c_flush_page_hw(page);
 		sun4c_put_pte(page, 0);
 		sun4c_set_context(savectx);
+		restore_flags(flags);
 	}
 }
 
@@ -1982,16 +1826,15 @@
 {
 	int new_ctx = mm->context;
 
-	if(new_ctx != NO_CONTEXT) {
+	if (new_ctx != NO_CONTEXT) {
 		struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
 		unsigned long flags;
 
 		save_and_cli(flags);
-		if(head->next != head) {
+		if (head->next != head) {
 			struct sun4c_mmu_entry *entry = head->next;
 			int savectx = sun4c_get_context();
 
-			FUW_INLINE
 			sun4c_set_context(new_ctx);
 			sun4c_flush_context_sw();
 			do {
@@ -2001,7 +1844,7 @@
 				free_user_entry(new_ctx, entry);
 
 				entry = next;
-			} while(entry != head);
+			} while (entry != head);
 			sun4c_set_context(savectx);
 		}
 		restore_flags(flags);
@@ -2012,27 +1855,21 @@
 {
 	int new_ctx = mm->context;
 
-	if(new_ctx != NO_CONTEXT) {
+	if (new_ctx != NO_CONTEXT) {
 		struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd;
 		struct sun4c_mmu_entry *entry;
 		unsigned long flags;
 
-#if KGPROF_PROFILING
-		kgprof_profile();
-#endif
-
 		save_and_cli(flags);
 		/* See commentary in sun4c_flush_cache_range_*(). */
-		for(entry = head->next;
-		    (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
-		    entry = entry->next)
+		for (entry = head->next;
+		     (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
+		     entry = entry->next)
 			;
 
-		if((entry != head) && (entry->vaddr < end)) {
+		if ((entry != head) && (entry->vaddr < end)) {
 			int octx = sun4c_get_context();
 
-			/* This window flush is paranoid I think... -DaveM */
-			FUW_INLINE
 			sun4c_set_context(new_ctx);
 			do {
 				struct sun4c_mmu_entry *next = entry->next;
@@ -2042,7 +1879,7 @@
 				free_user_entry(new_ctx, entry);
 
 				entry = next;
-			} while((entry != head) && (entry->vaddr < end));
+			} while ((entry != head) && (entry->vaddr < end));
 			sun4c_set_context(octx);
 		}
 		restore_flags(flags);
@@ -2054,15 +1891,17 @@
 	struct mm_struct *mm = vma->vm_mm;
 	int new_ctx = mm->context;
 
-	if(new_ctx != NO_CONTEXT) {
+	if (new_ctx != NO_CONTEXT) {
 		int savectx = sun4c_get_context();
+		unsigned long flags;
 
-		FUW_INLINE
+		save_and_cli(flags);
 		sun4c_set_context(new_ctx);
 		page &= PAGE_MASK;
 		sun4c_flush_page_sw(page);
 		sun4c_put_pte(page, 0);
 		sun4c_set_context(savectx);
+		restore_flags(flags);
 	}
 }
 
@@ -2075,7 +1914,6 @@
 {
 }
 
-
 void sun4c_mapioaddr(unsigned long physaddr, unsigned long virt_addr,
 		     int bus_type, int rdonly)
 {
@@ -2083,7 +1921,7 @@
 
 	page_entry = ((physaddr >> PAGE_SHIFT) & SUN4C_PFN_MASK);
 	page_entry |= ((pg_iobits | _SUN4C_PAGE_PRIV) & ~(_SUN4C_PAGE_PRESENT));
-	if(rdonly)
+	if (rdonly)
 		page_entry &= ~_SUN4C_WRITEABLE;
 	sun4c_put_pte(virt_addr, page_entry);
 }
@@ -2093,12 +1931,12 @@
 	sun4c_put_pte(virt_addr, 0);
 }
 
-static void sun4c_alloc_context_hw(struct mm_struct *mm)
+static void sun4c_alloc_context_hw(struct mm_struct *old_mm, struct mm_struct *mm)
 {
 	struct ctx_list *ctxp;
 
 	ctxp = ctx_free.next;
-	if(ctxp != &ctx_free) {
+	if (ctxp != &ctx_free) {
 		remove_from_ctx_list(ctxp);
 		add_to_used_ctxlist(ctxp);
 		mm->context = ctxp->ctx_number;
@@ -2106,40 +1944,37 @@
 		return;
 	}
 	ctxp = ctx_used.next;
-	if(ctxp->ctx_mm == current->mm)
+	if (ctxp->ctx_mm == old_mm)
 		ctxp = ctxp->next;
-#ifdef DEBUG_SUN4C_MM
-	if(ctxp == &ctx_used)
-		panic("out of mmu contexts");
-#endif
 	remove_from_ctx_list(ctxp);
 	add_to_used_ctxlist(ctxp);
 	ctxp->ctx_mm->context = NO_CONTEXT;
 	ctxp->ctx_mm = mm;
 	mm->context = ctxp->ctx_number;
 	sun4c_demap_context_hw(&sun4c_context_ring[ctxp->ctx_number],
-			    ctxp->ctx_number);
+			       ctxp->ctx_number);
 }
 
-static void sun4c_switch_to_context_hw(struct task_struct *tsk)
+/* Switch the current MM context. */
+static void sun4c_switch_mm_hw(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk, int cpu)
 {
 	struct ctx_list *ctx;
+	int dirty = 0;
 
-	if(tsk->mm->context == NO_CONTEXT) {
-		sun4c_alloc_context_hw(tsk->mm);
+	if (mm->context == NO_CONTEXT) {
+		dirty = 1;
+		sun4c_alloc_context_hw(old_mm, mm);
 	} else {
 		/* Update the LRU ring of contexts. */
-		ctx = ctx_list_pool + tsk->mm->context;
+		ctx = ctx_list_pool + mm->context;
+#ifdef DEBUG_SUN4C_MM
+		if (!ctx->ctx_mm)
+			panic("context was not set up");
+#endif
 		remove_from_ctx_list(ctx);
 		add_to_used_ctxlist(ctx);
 	}
-	sun4c_set_context(tsk->mm->context);
-}
-
-static void sun4c_init_new_context_hw(struct mm_struct *mm)
-{
-	sun4c_alloc_context_hw(mm);
-	if(mm == current->mm)
+	if (dirty || old_mm != mm)
 		sun4c_set_context(mm->context);
 }
 
@@ -2147,7 +1982,7 @@
 {
 	struct ctx_list *ctx_old;
 
-	if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) {
+	if (mm->context != NO_CONTEXT) {
 		sun4c_demap_context_hw(&sun4c_context_ring[mm->context], mm->context);
 		ctx_old = ctx_list_pool + mm->context;
 		remove_from_ctx_list(ctx_old);
@@ -2156,12 +1991,12 @@
 	}
 }
 
-static void sun4c_alloc_context_sw(struct mm_struct *mm)
+static void sun4c_alloc_context_sw(struct mm_struct *old_mm, struct mm_struct *mm)
 {
 	struct ctx_list *ctxp;
 
 	ctxp = ctx_free.next;
-	if(ctxp != &ctx_free) {
+	if (ctxp != &ctx_free) {
 		remove_from_ctx_list(ctxp);
 		add_to_used_ctxlist(ctxp);
 		mm->context = ctxp->ctx_number;
@@ -2169,40 +2004,38 @@
 		return;
 	}
 	ctxp = ctx_used.next;
-	if(ctxp->ctx_mm == current->mm)
+	if(ctxp->ctx_mm == old_mm)
 		ctxp = ctxp->next;
-#ifdef DEBUG_SUN4C_MM
-	if(ctxp == &ctx_used)
-		panic("out of mmu contexts");
-#endif
 	remove_from_ctx_list(ctxp);
 	add_to_used_ctxlist(ctxp);
 	ctxp->ctx_mm->context = NO_CONTEXT;
 	ctxp->ctx_mm = mm;
 	mm->context = ctxp->ctx_number;
 	sun4c_demap_context_sw(&sun4c_context_ring[ctxp->ctx_number],
-			    ctxp->ctx_number);
+			       ctxp->ctx_number);
 }
 
-static void sun4c_switch_to_context_sw(struct task_struct *tsk)
+/* Switch the current MM context. */
+static void sun4c_switch_mm_sw(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk, int cpu)
 {
 	struct ctx_list *ctx;
+	int dirty = 0;
 
-	if(tsk->mm->context == NO_CONTEXT) {
-		sun4c_alloc_context_sw(tsk->mm);
+	if (mm->context == NO_CONTEXT) {
+		dirty = 1;
+		sun4c_alloc_context_sw(old_mm, mm);
 	} else {
 		/* Update the LRU ring of contexts. */
-		ctx = ctx_list_pool + tsk->mm->context;
+		ctx = ctx_list_pool + mm->context;
+#ifdef DEBUG_SUN4C_MM
+		if (!ctx->ctx_mm)
+			panic("context was not set up");
+#endif
 		remove_from_ctx_list(ctx);
 		add_to_used_ctxlist(ctx);
 	}
-	sun4c_set_context(tsk->mm->context);
-}
 
-static void sun4c_init_new_context_sw(struct mm_struct *mm)
-{
-	sun4c_alloc_context_sw(mm);
-	if(mm == current->mm)
+	if (dirty || old_mm != mm)
 		sun4c_set_context(mm->context);
 }
 
@@ -2210,7 +2043,7 @@
 {
 	struct ctx_list *ctx_old;
 
-	if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) {
+	if (mm->context != NO_CONTEXT) {
 		sun4c_demap_context_sw(&sun4c_context_ring[mm->context], mm->context);
 		ctx_old = ctx_list_pool + mm->context;
 		remove_from_ctx_list(ctx_old);
@@ -2225,7 +2058,7 @@
 	int len;
 
 	used_user_entries = 0;
-	for(i=0; i < num_contexts; i++)
+	for (i = 0; i < num_contexts; i++)
 		used_user_entries += sun4c_context_ring[i].num_entries;
 
 	len = sprintf(buf, 
@@ -2239,10 +2072,7 @@
 		"usedpsegs\t: %d\n"
 		"ufreepsegs\t: %d\n"
 		"user_taken\t: %d\n"
-		"max_taken\t: %d\n"
-		"context\t\t: %d flushes\n"
-		"segment\t\t: %d flushes\n"
-		"page\t\t: %d flushes\n",
+		"max_taken\t: %d\n",
 		sun4c_vacinfo.num_bytes,
 		(sun4c_vacinfo.do_hwflushes ? "yes" : "no"),
 		sun4c_vacinfo.linesize,
@@ -2253,22 +2083,7 @@
 		used_user_entries,
 		sun4c_ufree_ring.num_entries,
 		sun4c_user_taken_entries,
-		max_user_taken_entries,
-		ctxflushes, segflushes, pageflushes);
-
-#if KGPROF_PROFILING
-	{
-		int i,j;
-		len += sprintf(buf + len,"kgprof profiling:\n");
-		for (i=0;i<KGPROF_SIZE && kgprof_counters[i].addr[0];i++) {
-			len += sprintf(buf + len,"%5d  ",kgprof_counters[i].count);
-			for (j=0;j<KGPROF_DEPTH;j++) {
-				len += sprintf(buf + len,"%08x ",kgprof_counters[i].addr[j]);
-			}
-			len += sprintf(buf + len,"\n");
-		}
-	}
-#endif
+		max_user_taken_entries);
 
 	return len;
 }
@@ -2277,13 +2092,6 @@
  * data structures.
  */
 
-#if 0 /* Not used due to BTFIXUPs */
-static unsigned int sun4c_pmd_align(unsigned int addr) { return SUN4C_PMD_ALIGN(addr); }
-#endif
-#if 0 /* Not used due to BTFIXUPs */
-static unsigned int sun4c_pgdir_align(unsigned int addr) { return SUN4C_PGDIR_ALIGN(addr); }
-#endif
-
 /* First the functions which the mid-level code uses to directly
  * manipulate the software page tables.  Some defines since we are
  * emulating the i386 page directory layout.
@@ -2295,17 +2103,6 @@
 #define PGD_DIRTY    0x040
 #define PGD_TABLE    (PGD_PRESENT | PGD_RW | PGD_USER | PGD_ACCESSED | PGD_DIRTY)
 
-#if 0 /* Not used due to BTFIXUPs */
-static unsigned long sun4c_vmalloc_start(void)
-{
-	return SUN4C_VMALLOC_START;
-}
-#endif
-
-#if 0 /* Not used due to BTFIXUPs */
-static int sun4c_pte_none(pte_t pte)		{ return !pte_val(pte); }
-#endif
-
 static int sun4c_pte_present(pte_t pte)
 {
 	return ((pte_val(pte) & (_SUN4C_PAGE_PRESENT | _SUN4C_PAGE_PRIV)) != 0);
@@ -2334,48 +2131,6 @@
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-#if 0 /* Not used due to BTFIXUPs */
-static int sun4c_pte_write(pte_t pte)
-{
-	return pte_val(pte) & _SUN4C_PAGE_WRITE;
-}
-#endif
-
-#if 0 /* Not used due to BTFIXUPs */
-static int sun4c_pte_dirty(pte_t pte)
-{
-	return pte_val(pte) & _SUN4C_PAGE_MODIFIED;
-}
-#endif
-
-#if 0 /* Not used due to BTFIXUPs */
-static int sun4c_pte_young(pte_t pte)
-{
-	return pte_val(pte) & _SUN4C_PAGE_ACCESSED;
-}
-#endif
-
-#if 0 /* Not used due to BTFIXUPs */
-static pte_t sun4c_pte_wrprotect(pte_t pte)
-{
-	return __pte(pte_val(pte) & ~(_SUN4C_PAGE_WRITE | _SUN4C_PAGE_SILENT_WRITE));
-}
-#endif
-
-#if 0 /* Not used due to BTFIXUPs */
-static pte_t sun4c_pte_mkclean(pte_t pte)
-{
-	return __pte(pte_val(pte) & ~(_SUN4C_PAGE_MODIFIED | _SUN4C_PAGE_SILENT_WRITE));
-}
-#endif
-
-#if 0 /* Not used due to BTFIXUPs */
-static pte_t sun4c_pte_mkold(pte_t pte)
-{
-	return __pte(pte_val(pte) & ~(_SUN4C_PAGE_ACCESSED | _SUN4C_PAGE_SILENT_READ));
-}
-#endif
-
 static pte_t sun4c_pte_mkwrite(pte_t pte)
 {
 	pte = __pte(pte_val(pte) | _SUN4C_PAGE_WRITE);
@@ -2404,9 +2159,9 @@
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
-static pte_t sun4c_mk_pte(unsigned long page, pgprot_t pgprot)
+static pte_t sun4c_mk_pte(struct page *page, pgprot_t pgprot)
 {
-	return __pte(((page - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(pgprot));
+	return __pte((page - mem_map) | pgprot_val(pgprot));
 }
 
 static pte_t sun4c_mk_pte_phys(unsigned long phys_page, pgprot_t pgprot)
@@ -2419,17 +2174,9 @@
 	return __pte(((page - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(pgprot));
 }
 
-#if 0 /* Not used due to BTFIXUPs */
-static pte_t sun4c_pte_modify(pte_t pte, pgprot_t newprot)
-{
-	return __pte((pte_val(pte) & _SUN4C_PAGE_CHG_MASK) |
-		     pgprot_val(newprot));
-}
-#endif
-
-static unsigned long sun4c_pte_page(pte_t pte)
+static unsigned long sun4c_pte_pagenr(pte_t pte)
 {
-	return (PAGE_OFFSET + ((pte_val(pte) & SUN4C_PFN_MASK) << (PAGE_SHIFT)));
+	return (pte_val(pte) & SUN4C_PFN_MASK);
 }
 
 static inline unsigned long sun4c_pmd_page(pmd_t pmd)
@@ -2460,11 +2207,6 @@
 	return (pte_t *) sun4c_pmd_page(*dir) +	((address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1));
 }
 
-/* Update the root mmu directory. */
-static void sun4c_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdir)
-{
-}
-
 /* Please take special note on the foo_kernel() routines below, our
  * fast in window fault handler wants to get at the pte's for vmalloc
  * area with traps off, therefore they _MUST_ be locked down to prevent
@@ -2487,7 +2229,7 @@
 
 static pte_t *sun4c_pte_alloc_kernel(pmd_t *pmd, unsigned long address)
 {
-	if(address >= SUN4C_LOCK_VADDR)
+	if (address >= SUN4C_LOCK_VADDR)
 		return NULL;
 	address = (address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1);
 	if (sun4c_pmd_none(*pmd))
@@ -2527,7 +2269,7 @@
 {
 	unsigned long *ret;
 
-	if((ret = pgd_quicklist) != NULL) {
+	if ((ret = pgd_quicklist) != NULL) {
 		pgd_quicklist = (unsigned long *)(*ret);
 		ret[0] = ret[1];
 		pgtable_cache_size--;
@@ -2546,15 +2288,15 @@
 static int sun4c_check_pgt_cache(int low, int high)
 {
 	int freed = 0;
-	if(pgtable_cache_size > high) {
+	if (pgtable_cache_size > high) {
 		do {
-			if(pgd_quicklist)
+			if (pgd_quicklist)
 				free_pgd_slow(get_pgd_fast()), freed++;
-			if(pmd_quicklist)
+			if (pmd_quicklist)
 				free_pmd_slow(get_pmd_fast()), freed++;
-			if(pte_quicklist)
+			if (pte_quicklist)
 				free_pte_slow(get_pte_fast()), freed++;
-		} while(pgtable_cache_size > low);
+		} while (pgtable_cache_size > low);
 	}
 	return freed;
 }
@@ -2575,7 +2317,7 @@
 {
 	unsigned long *ret;
 
-	if((ret = (unsigned long *)pte_quicklist) != NULL) {
+	if ((ret = (unsigned long *)pte_quicklist) != NULL) {
 		pte_quicklist = (unsigned long *)(*ret);
 		ret[0] = ret[1];
 		pgtable_cache_size--;
@@ -2691,19 +2433,21 @@
 			unsigned long start;
 
 			/* Do not mistake ourselves as another mapping. */
-			if(vmaring == vma)
+			if (vmaring == vma)
 				continue;
 
 			if (S4CVAC_BADALIAS(vaddr, address)) {
 				alias_found++;
 				start = vmaring->vm_start;
-				while(start < vmaring->vm_end) {
+				while (start < vmaring->vm_end) {
 					pgdp = sun4c_pgd_offset(vmaring->vm_mm, start);
-					if(!pgdp) goto next;
+					if (!pgdp)
+						goto next;
 					ptep = sun4c_pte_offset((pmd_t *) pgdp, start);
-					if(!ptep) goto next;
+					if (!ptep)
+						goto next;
 
-					if(pte_val(*ptep) & _SUN4C_PAGE_PRESENT) {
+					if (pte_val(*ptep) & _SUN4C_PAGE_PRESENT) {
 						flush_cache_page(vmaring, start);
 						*ptep = __pte(pte_val(*ptep) |
 							      _SUN4C_PAGE_NOCACHE);
@@ -2716,7 +2460,7 @@
 		} while ((vmaring = vmaring->vm_next_share) != NULL);
 		spin_unlock(&inode->i_shared_lock);
 
-		if(alias_found && !(pte_val(pte) & _SUN4C_PAGE_NOCACHE)) {
+		if (alias_found && !(pte_val(pte) & _SUN4C_PAGE_NOCACHE)) {
 			pgdp = sun4c_pgd_offset(vma->vm_mm, address);
 			ptep = sun4c_pte_offset((pmd_t *) pgdp, address);
 			*ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_NOCACHE);
@@ -2725,45 +2469,103 @@
 	}
 }
 
+/* An experiment, turn off by default for now... -DaveM */
+#define SUN4C_PRELOAD_PSEG
+
 void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
 	unsigned long flags;
+	int pseg;
 
 	save_and_cli(flags);
 	address &= PAGE_MASK;
-	if(sun4c_get_segmap(address) == invalid_segment)
-		alloc_user_segment(address, sun4c_get_context());
+	if ((pseg = sun4c_get_segmap(address)) == invalid_segment) {
+		struct sun4c_mmu_entry *entry = sun4c_user_strategy();
+		struct mm_struct *mm = vma->vm_mm;
+		unsigned long start, end;
+
+		entry->vaddr = start = (address & SUN4C_REAL_PGDIR_MASK);
+		entry->ctx = mm->context;
+		add_ring_ordered(sun4c_context_ring + mm->context, entry);
+		sun4c_put_segmap(entry->vaddr, entry->pseg);
+		end = start + SUN4C_REAL_PGDIR_SIZE;
+		while (start < end) {
+#ifdef SUN4C_PRELOAD_PSEG
+			pgd_t *pgdp = sun4c_pgd_offset(mm, start);
+			pte_t *ptep;
+
+			if (!pgdp)
+				goto no_mapping;
+			ptep = sun4c_pte_offset((pmd_t *) pgdp, start);
+			if (!ptep || !(pte_val(*ptep) & _SUN4C_PAGE_PRESENT))
+				goto no_mapping;
+			sun4c_put_pte(start, pte_val(*ptep));
+			goto next;
+
+		no_mapping:
+#endif
+			sun4c_put_pte(start, 0);
+#ifdef SUN4C_PRELOAD_PSEG
+		next:
+#endif
+			start += PAGE_SIZE;
+		}
+		if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED))
+			sun4c_vac_alias_fixup(vma, address, pte);
+#ifndef SUN4C_PRELOAD_PSEG
+		sun4c_put_pte(address, pte_val(pte));
+#endif
+		restore_flags(flags);
+		return;
+	} else {
+		struct sun4c_mmu_entry *entry = &mmu_entry_pool[pseg];
+
+		remove_lru(entry);
+		add_lru(entry);
+	}
 
-	if((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED))
+	if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED))
 		sun4c_vac_alias_fixup(vma, address, pte);
 
 	sun4c_put_pte(address, pte_val(pte));
 	restore_flags(flags);
 }
 
-extern unsigned long free_area_init(unsigned long, unsigned long);
-extern unsigned long sparc_context_init(unsigned long, int);
+extern void sparc_context_init(int);
 extern unsigned long end;
+extern unsigned long bootmem_init(void);
+extern unsigned long last_valid_pfn;
+extern void sun_serial_setup(void);
 
-unsigned long __init sun4c_paging_init(unsigned long start_mem, unsigned long end_mem)
+void __init sun4c_paging_init(void)
 {
 	int i, cnt;
 	unsigned long kernel_end, vaddr;
-	extern unsigned long sparc_iobase_vaddr;
+	extern struct resource sparc_iomap;
+	unsigned long end_pfn;
 
 	kernel_end = (unsigned long) &end;
 	kernel_end += (SUN4C_REAL_PGDIR_SIZE * 4);
 	kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
+
+	last_valid_pfn = end_pfn = bootmem_init();
+
+	/* This does not logically belong here, but we need to
+	 * call it at the moment we are able to use the bootmem
+	 * allocator.
+	 */
+	sun_serial_setup();
+
 	sun4c_probe_mmu();
 	invalid_segment = (num_segmaps - 1);
 	sun4c_init_mmu_entry_pool();
-	sun4c_init_rings(&start_mem);
+	sun4c_init_rings();
 	sun4c_init_map_kernelprom(kernel_end);
 	sun4c_init_clean_mmu(kernel_end);
 	sun4c_init_fill_kernel_ring(SUN4C_KERNEL_BUCKETS);
-	sun4c_init_lock_area(sparc_iobase_vaddr, IOBASE_END);
+	sun4c_init_lock_area(sparc_iomap.start, IOBASE_END);
 	sun4c_init_lock_area(DVMA_VADDR, DVMA_END);
-	start_mem = sun4c_init_lock_areas(start_mem);
+	sun4c_init_lock_areas();
 	sun4c_init_fill_user_ring();
 
 	sun4c_set_context(0);
@@ -2783,18 +2585,16 @@
 	vaddr += SUN4C_PGDIR_SIZE;
 	swapper_pg_dir[vaddr>>SUN4C_PGDIR_SHIFT] = __pgd(PGD_TABLE | (unsigned long) pg3);
 	sun4c_init_ss2_cache_bug();
-	start_mem = PAGE_ALIGN(start_mem);
-	start_mem = sparc_context_init(start_mem, num_contexts);
-	start_mem = free_area_init(start_mem, end_mem);
+	sparc_context_init(num_contexts);
+	free_area_init(end_pfn);
 	cnt = 0;
-	for(i = 0; i < num_segmaps; i++)
-		if(mmu_entry_pool[i].locked)
+	for (i = 0; i < num_segmaps; i++)
+		if (mmu_entry_pool[i].locked)
 			cnt++;
 
 	max_user_taken_entries = num_segmaps - cnt - 40 - 1;
 
 	printk("SUN4C: %d mmu entries for the kernel\n", cnt);
-	return start_mem;
 }
 
 /* Load up routines and constants for sun4c mmu */
@@ -2839,7 +2639,7 @@
 
 	BTFIXUPSET_CALL(flush_cache_all, sun4c_flush_cache_all, BTFIXUPCALL_NORM);
 
-	if(sun4c_vacinfo.do_hwflushes) {
+	if (sun4c_vacinfo.do_hwflushes) {
 		BTFIXUPSET_CALL(flush_cache_mm, sun4c_flush_cache_mm_hw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_cache_range, sun4c_flush_cache_range_hw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_cache_page, sun4c_flush_cache_page_hw, BTFIXUPCALL_NORM);
@@ -2848,9 +2648,8 @@
 		BTFIXUPSET_CALL(flush_tlb_range, sun4c_flush_tlb_range_hw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_tlb_page, sun4c_flush_tlb_page_hw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(free_task_struct, sun4c_free_task_struct_hw, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(switch_to_context, sun4c_switch_to_context_hw, BTFIXUPCALL_NORM);
+		BTFIXUPSET_CALL(switch_mm, sun4c_switch_mm_hw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(destroy_context, sun4c_destroy_context_hw, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(init_new_context, sun4c_init_new_context_hw, BTFIXUPCALL_NORM);
 	} else {
 		BTFIXUPSET_CALL(flush_cache_mm, sun4c_flush_cache_mm_sw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_cache_range, sun4c_flush_cache_range_sw, BTFIXUPCALL_NORM);
@@ -2860,9 +2659,8 @@
 		BTFIXUPSET_CALL(flush_tlb_range, sun4c_flush_tlb_range_sw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_tlb_page, sun4c_flush_tlb_page_sw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(free_task_struct, sun4c_free_task_struct_sw, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(switch_to_context, sun4c_switch_to_context_sw, BTFIXUPCALL_NORM);
+		BTFIXUPSET_CALL(switch_mm, sun4c_switch_mm_sw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(destroy_context, sun4c_destroy_context_sw, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(init_new_context, sun4c_init_new_context_sw, BTFIXUPCALL_NORM);
 	}
 
 	BTFIXUPSET_CALL(flush_tlb_all, sun4c_flush_tlb_all, BTFIXUPCALL_NORM);
@@ -2871,15 +2669,13 @@
 
 	BTFIXUPSET_CALL(set_pte, sun4c_set_pte, BTFIXUPCALL_STO1O0);
 
-	BTFIXUPSET_CALL(pte_page, sun4c_pte_page, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(pte_pagenr, sun4c_pte_pagenr, BTFIXUPCALL_NORM);
 #if PAGE_SHIFT <= 12	
 	BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_ANDNINT(PAGE_SIZE - 1));
 #else
 	BTFIXUPSET_CALL(pmd_page, sun4c_pmd_page, BTFIXUPCALL_NORM);
 #endif
 
-	BTFIXUPSET_CALL(sparc_update_rootmmu_dir, sun4c_update_rootmmu_dir, BTFIXUPCALL_NOP);
-
 	BTFIXUPSET_CALL(pte_present, sun4c_pte_present, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pte_clear, sun4c_pte_clear, BTFIXUPCALL_STG0O0);
 
@@ -2931,6 +2727,9 @@
 	BTFIXUPSET_CALL(mmu_release_scsi_sgl, sun4c_release_scsi_sgl, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(mmu_map_dma_area, sun4c_map_dma_area, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(mmu_unmap_dma_area, sun4c_unmap_dma_area, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(mmu_flush_dma_area, sun4c_flush_dma_area, BTFIXUPCALL_NOP);
+	BTFIXUPSET_CALL(mmu_inval_dma_area, sun4c_inval_dma_area, BTFIXUPCALL_NORM);
 
         BTFIXUPSET_CALL(mmu_v2p, sun4c_v2p, BTFIXUPCALL_NORM);
         BTFIXUPSET_CALL(mmu_p2v, sun4c_p2v, BTFIXUPCALL_NORM);
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/swift.S linux/arch/sparc/mm/swift.S
--- v2.3.34/linux/arch/sparc/mm/swift.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc/mm/swift.S	Mon Dec 20 22:05:52 1999
@@ -0,0 +1,275 @@
+/* $Id: swift.S,v 1.3 1999/11/14 06:13:56 zaitcev Exp $
+ * swift.S: MicroSparc-II mmu/cache operations.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include <asm/psr.h>
+#include <asm/asi.h>
+#include <asm/page.h>
+#include <asm/pgtsrmmu.h>
+#include <asm/asm_offsets.h>
+
+#define WINDOW_FLUSH(tmp1, tmp2)					\
+	mov	0, tmp1;						\
+98:	ld	[%g6 + AOFF_task_thread + AOFF_thread_uwinmask], tmp2;	\
+	orcc	%g0, tmp2, %g0;						\
+	add	tmp1, 1, tmp1;						\
+	bne	98b;							\
+	 save	%sp, -64, %sp;						\
+99:	subcc	tmp1, 1, tmp1;						\
+	bne	99b;							\
+	 restore %g0, %g0, %g0;
+
+	.text
+	.align	4
+
+#if 1	/* XXX screw this, I can't get the VAC flushes working
+	 * XXX reliably... -DaveM
+	 */
+	.globl	swift_flush_cache_all, swift_flush_cache_mm
+	.globl	swift_flush_cache_range, swift_flush_cache_page
+	.globl	swift_flush_page_for_dma, swift_flush_chunk
+	.globl	swift_flush_page_to_ram
+
+swift_flush_cache_all:
+swift_flush_cache_mm:
+swift_flush_cache_range:
+swift_flush_cache_page:
+swift_flush_page_for_dma:
+swift_flush_chunk:
+swift_flush_page_to_ram:
+	sethi	%hi(0x2000), %o0
+1:	subcc	%o0, 0x10, %o0
+	sta	%g0, [%o0] ASI_M_TXTC_TAG
+	sta	%g0, [%o0] ASI_M_DATAC_TAG
+	bne	1b
+	 nop
+	retl
+	 nop
+#else
+
+	.globl	swift_flush_cache_all
+swift_flush_cache_all:
+	WINDOW_FLUSH(%g4, %g5)
+
+	/* Just clear out all the tags. */
+	sethi	%hi(16 * 1024), %o0
+1:	subcc	%o0, 16, %o0
+	sta	%g0, [%o0] ASI_M_TXTC_TAG
+	bne	1b
+	 sta	%g0, [%o0] ASI_M_DATAC_TAG
+	retl
+	 nop
+
+	.globl	swift_flush_cache_mm
+swift_flush_cache_mm:
+#ifndef __SMP__
+	ld	[%o0 + AOFF_mm_context], %g2
+	cmp	%g2, -1
+	be	swift_flush_cache_mm_out
+#endif
+	WINDOW_FLUSH(%g4, %g5)
+	rd	%psr, %g1
+	andn	%g1, PSR_ET, %g3
+	wr	%g3, 0x0, %psr
+	nop
+	nop
+	mov	SRMMU_CTX_REG, %g7
+	lda	[%g7] ASI_M_MMUREGS, %g5
+	sta	%g2, [%g7] ASI_M_MMUREGS
+
+#if 1
+	sethi	%hi(0x2000), %o0
+1:	subcc	%o0, 0x10, %o0
+	sta	%g0, [%o0] ASI_M_FLUSH_CTX
+	bne	1b
+	 nop
+#else
+	clr	%o0
+	or	%g0, 2048, %g7
+	or	%g0, 2048, %o1
+	add	%o1, 2048, %o2
+	add	%o2, 2048, %o3
+	mov	16, %o4
+	add	%o4, 2048, %o5
+	add	%o5, 2048, %g2
+	add	%g2, 2048, %g3
+1:	sta	%g0, [%o0      ] ASI_M_FLUSH_CTX
+	sta	%g0, [%o0 + %o1] ASI_M_FLUSH_CTX
+	sta	%g0, [%o0 + %o2] ASI_M_FLUSH_CTX
+	sta	%g0, [%o0 + %o3] ASI_M_FLUSH_CTX
+	sta	%g0, [%o0 + %o4] ASI_M_FLUSH_CTX
+	sta	%g0, [%o0 + %o5] ASI_M_FLUSH_CTX
+	sta	%g0, [%o0 + %g2] ASI_M_FLUSH_CTX
+	sta	%g0, [%o0 + %g3] ASI_M_FLUSH_CTX
+	subcc	%g7, 32, %g7
+	bne	1b
+	 add	%o0, 32, %o0
+#endif
+
+	mov	SRMMU_CTX_REG, %g7
+	sta	%g5, [%g7] ASI_M_MMUREGS
+	wr	%g1, 0x0, %psr
+	nop
+	nop
+swift_flush_cache_mm_out:
+	retl
+	 nop
+
+	.globl	swift_flush_cache_range
+swift_flush_cache_range:
+	sub	%o2, %o1, %o2
+	sethi	%hi(4096), %o3
+	cmp	%o2, %o3
+	bgu	swift_flush_cache_mm
+	 nop
+	b	70f
+	 nop
+
+	.globl	swift_flush_cache_page
+swift_flush_cache_page:
+	ld	[%o0 + 0x0], %o0		/* XXX vma->vm_mm, GROSS XXX */
+70:
+#ifndef __SMP__
+	ld	[%o0 + AOFF_mm_context], %g2
+	cmp	%g2, -1
+	be	swift_flush_cache_page_out
+#endif
+	WINDOW_FLUSH(%g4, %g5)
+	rd	%psr, %g1
+	andn	%g1, PSR_ET, %g3
+	wr	%g3, 0x0, %psr
+	nop
+	nop
+	mov	SRMMU_CTX_REG, %g7
+	lda	[%g7] ASI_M_MMUREGS, %g5
+	sta	%g2, [%g7] ASI_M_MMUREGS
+
+	andn	%o1, (PAGE_SIZE - 1), %o1
+#if 1
+	sethi	%hi(0x1000), %o0
+1:	subcc	%o0, 0x10, %o0
+	sta	%g0, [%o1 + %o0] ASI_M_FLUSH_PAGE
+	bne	1b
+	 nop
+#else
+	or	%g0, 512, %g7
+	or	%g0, 512, %o0
+	add	%o0, 512, %o2
+	add	%o2, 512, %o3
+	add	%o3, 512, %o4
+	add	%o4, 512, %o5
+	add	%o5, 512, %g3
+	add	%g3, 512, %g4
+1:	sta	%g0, [%o1      ] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %o0] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %o2] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %o3] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %o4] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %o5] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %g3] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %g4] ASI_M_FLUSH_PAGE
+	subcc	%g7, 16, %g7
+	bne	1b
+	 add	%o1, 16, %o1
+#endif
+
+	mov	SRMMU_CTX_REG, %g7
+	sta	%g5, [%g7] ASI_M_MMUREGS
+	wr	%g1, 0x0, %psr
+	nop
+	nop
+swift_flush_cache_page_out:
+	retl
+	 nop
+
+	/* Swift is write-thru, however it is not
+	 * I/O nor TLB-walk coherent.  Also it has
+	 * caches which are virtually indexed and tagged.
+	 */
+	.globl	swift_flush_page_for_dma
+	.globl	swift_flush_chunk
+	.globl	swift_flush_page_to_ram
+swift_flush_page_for_dma:
+swift_flush_chunk:
+swift_flush_page_to_ram:
+	andn	%o0, (PAGE_SIZE - 1), %o1
+#if 1
+	sethi	%hi(0x1000), %o0
+1:	subcc	%o0, 0x10, %o0
+	sta	%g0, [%o1 + %o0] ASI_M_FLUSH_PAGE
+	bne	1b
+	 nop
+#else
+	or	%g0, 512, %g7
+	or	%g0, 512, %o0
+	add	%o0, 512, %o2
+	add	%o2, 512, %o3
+	add	%o3, 512, %o4
+	add	%o4, 512, %o5
+	add	%o5, 512, %g3
+	add	%g3, 512, %g4
+1:	sta	%g0, [%o1      ] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %o0] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %o2] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %o3] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %o4] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %o5] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %g3] ASI_M_FLUSH_PAGE
+	sta	%g0, [%o1 + %g4] ASI_M_FLUSH_PAGE
+	subcc	%g7, 16, %g7
+	bne	1b
+	 add	%o1, 16, %o1
+#endif
+	retl
+	 nop
+#endif
+
+	.globl	swift_flush_sig_insns
+swift_flush_sig_insns:
+	flush	%o1
+	retl
+	 flush	%o1 + 4
+
+	.globl	swift_flush_tlb_mm
+	.globl	swift_flush_tlb_range
+	.globl	swift_flush_tlb_all
+swift_flush_tlb_mm:
+swift_flush_tlb_range:
+#ifndef __SMP__
+	ld	[%o0 + AOFF_mm_context], %g2
+	cmp	%g2, -1
+	be	swift_flush_tlb_all_out
+#endif
+swift_flush_tlb_all:
+	mov	0x400, %o1
+	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
+swift_flush_tlb_all_out:
+	retl
+	 nop
+
+	.globl	swift_flush_tlb_page
+swift_flush_tlb_page:
+	ld	[%o0 + 0x00], %o0	/* XXX vma->vm_mm GROSS XXX */
+	mov	SRMMU_CTX_REG, %g1
+	ld	[%o0 + AOFF_mm_context], %o3
+	andn	%o1, (PAGE_SIZE - 1), %o1
+#ifndef __SMP__
+	cmp	%o3, -1
+	be	swift_flush_tlb_page_out
+	 nop
+#endif
+#if 1
+	mov	0x400, %o1
+	sta	%g0, [%o1] ASI_M_FLUSH_PROBE	
+#else
+	lda	[%g1] ASI_M_MMUREGS, %g5
+	sta	%o3, [%g1] ASI_M_MMUREGS
+	sta	%g0, [%o1] ASI_M_FLUSH_PAGE	/* rem. virt. cache. prot. */
+	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
+	sta	%g5, [%g1] ASI_M_MMUREGS
+#endif
+swift_flush_tlb_page_out:
+	retl
+	 nop
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/mm/tsunami.S linux/arch/sparc/mm/tsunami.S
--- v2.3.34/linux/arch/sparc/mm/tsunami.S	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/mm/tsunami.S	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: tsunami.S,v 1.2 1999/08/14 03:51:48 anton Exp $
+/* $Id: tsunami.S,v 1.3 1999/10/09 05:32:19 zaitcev Exp $
  * tsunami.S: High speed MicroSparc-I mmu/cache operations.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -44,11 +44,11 @@
 tsunami_flush_cache_all:
 	WINDOW_FLUSH(%g4, %g5)
 tsunami_flush_page_for_dma:
-	sta	%g0, [%g0] ASI_M_DC_FLCLEAR
 	sta	%g0, [%g0] ASI_M_IC_FLCLEAR
+tsunami_flush_chunk:
+	sta	%g0, [%g0] ASI_M_DC_FLCLEAR
 tsunami_flush_cache_out:
 tsunami_flush_page_to_ram:
-tsunami_flush_chunk:
 	retl
 	 nop
 
@@ -68,6 +68,11 @@
 tsunami_flush_tlb_all:
 	 mov	0x400, %o1
 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
+	nop
+	nop
+	nop
+	nop
+	nop
 tsunami_flush_tlb_out:
 	retl
 	 nop
@@ -85,6 +90,59 @@
 	 lda	[%g1] ASI_M_MMUREGS, %g5
 	sta	%o3, [%g1] ASI_M_MMUREGS
 	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
+	nop
+	nop
+	nop
+	nop
+	nop
 tsunami_flush_tlb_page_out:
 	retl
 	 sta	%g5, [%g1] ASI_M_MMUREGS
+
+#define MIRROR_BLOCK(dst, src, offset, t0, t1, t2, t3) \
+	ldd	[src + offset + 0x18], t0; \
+	std	t0, [dst + offset + 0x18]; \
+	ldd	[src + offset + 0x10], t2; \
+	std	t2, [dst + offset + 0x10]; \
+	ldd	[src + offset + 0x08], t0; \
+	std	t0, [dst + offset + 0x08]; \
+	ldd	[src + offset + 0x00], t2; \
+	std	t2, [dst + offset + 0x00];
+
+	.globl	tsunami_copy_1page
+tsunami_copy_1page:
+/* NOTE: This routine has to be shorter than 70insns --jj */
+	or	%g0, (PAGE_SIZE >> 8), %g1
+1:
+	MIRROR_BLOCK(%o0, %o1, 0x00, %o2, %o3, %o4, %o5)
+	MIRROR_BLOCK(%o0, %o1, 0x20, %o2, %o3, %o4, %o5)
+	MIRROR_BLOCK(%o0, %o1, 0x40, %o2, %o3, %o4, %o5)
+	MIRROR_BLOCK(%o0, %o1, 0x60, %o2, %o3, %o4, %o5)
+	MIRROR_BLOCK(%o0, %o1, 0x80, %o2, %o3, %o4, %o5)
+	MIRROR_BLOCK(%o0, %o1, 0xa0, %o2, %o3, %o4, %o5)
+	MIRROR_BLOCK(%o0, %o1, 0xc0, %o2, %o3, %o4, %o5)
+	MIRROR_BLOCK(%o0, %o1, 0xe0, %o2, %o3, %o4, %o5)
+	subcc	%g1, 1, %g1
+	add	%o0, 0x100, %o0
+	bne	1b
+	 add	%o1, 0x100, %o1
+
+	.globl	tsunami_setup_blockops
+tsunami_setup_blockops:
+	sethi	%hi(__copy_1page), %o0
+	or	%o0, %lo(__copy_1page), %o0
+	sethi	%hi(tsunami_copy_1page), %o1
+	or	%o1, %lo(tsunami_copy_1page), %o1
+	sethi	%hi(tsunami_setup_blockops), %o2
+	or	%o2, %lo(tsunami_setup_blockops), %o2
+	ld	[%o1], %o4
+1:	add	%o1, 4, %o1
+	st	%o4, [%o0]
+	add	%o0, 4, %o0
+	cmp	%o1, %o2
+	bne	1b
+	ld	[%o1], %o4
+	sta	%g0, [%g0] ASI_M_IC_FLCLEAR
+	sta	%g0, [%g0] ASI_M_DC_FLCLEAR
+	retl
+	 nop
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/prom/Makefile linux/arch/sparc/prom/Makefile
--- v2.3.34/linux/arch/sparc/prom/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/arch/sparc/prom/Makefile	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.6 1998/01/30 10:58:59 jj Exp $
+# $Id: Makefile,v 1.7 1999/12/21 04:02:21 davem Exp $
 # Makefile for the Sun Boot PROM interface library under
 # Linux.
 #
diff -u --recursive --new-file v2.3.34/linux/arch/sparc/prom/ranges.c linux/arch/sparc/prom/ranges.c
--- v2.3.34/linux/arch/sparc/prom/ranges.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/prom/ranges.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ranges.c,v 1.12 1999/08/31 06:54:47 davem Exp $
+/* $Id: ranges.c,v 1.14 1999/10/06 19:28:54 zaitcev Exp $
  * ranges.c: Handle ranges in newer proms for obio/sbus.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -8,6 +8,7 @@
 #include <linux/init.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
+#include <asm/types.h>
 #include <asm/sbus.h>
 #include <asm/system.h>
 
@@ -64,24 +65,6 @@
 		prom_adjust_regs(regs, nregs, promlib_obio_ranges, num_obio_ranges);
 }
 
-/* Apply probed sbus ranges to registers passed, if no ranges return. */
-void prom_apply_sbus_ranges(struct linux_sbus *sbus, struct linux_prom_registers *regs,
-			    int nregs, struct linux_sbus_device *sdev)
-{
-	if(sbus && sbus->num_sbus_ranges) {
-		if(sdev && (sdev->ranges_applied == 0)) {
-			sdev->ranges_applied = 1;
-			prom_adjust_regs(regs, nregs, sbus->sbus_ranges,
-					 sbus->num_sbus_ranges);
-		} else if(!sdev) {
-			printk("PROMLIB: Aieee, old SBUS driver, update it to use new "
-			       "prom_apply_sbus_ranges interface now!\n");
-			prom_adjust_regs(regs, nregs, sbus->sbus_ranges,
-					 sbus->num_sbus_ranges);
-		}
-	}
-}
-
 void __init prom_ranges_init(void)
 {
 	int node, obio_node;
@@ -105,32 +88,6 @@
 		prom_printf("PROMLIB: obio_ranges %d\n", num_obio_ranges);
 
 	return;
-}
-
-void __init prom_sbus_ranges_init(int parentnd, struct linux_sbus *sbus)
-{
-	int success;
-	
-	sbus->num_sbus_ranges = 0;
-	if(sparc_cpu_model == sun4c)
-		return;
-	success = prom_getproperty(sbus->prom_node, "ranges",
-				   (char *) sbus->sbus_ranges,
-				   sizeof (sbus->sbus_ranges));
-	if (success != -1)
-		sbus->num_sbus_ranges = (success/sizeof(struct linux_prom_ranges));
-	if (sparc_cpu_model == sun4d) {
-		struct linux_prom_ranges iounit_ranges[PROMREG_MAX];
-		int num_iounit_ranges;
-		
-		success = prom_getproperty(parentnd, "ranges",
-				   	(char *) iounit_ranges,
-				   	sizeof (iounit_ranges));
-		if (success != -1) {
-			num_iounit_ranges = (success/sizeof(struct linux_prom_ranges));
-			prom_adjust_ranges (sbus->sbus_ranges, sbus->num_sbus_ranges, iounit_ranges, num_iounit_ranges);
-		}
-	}
 }
 
 void
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile
--- v2.3.34/linux/arch/sparc64/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/arch/sparc64/Makefile	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.40 1999/08/19 02:31:57 davem Exp $
+# $Id: Makefile,v 1.41 1999/12/21 04:02:23 davem Exp $
 # sparc64/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.3.34/linux/arch/sparc64/config.in	Wed Dec  8 14:11:25 1999
+++ linux/arch/sparc64/config.in	Wed Dec 22 19:55:38 1999
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.78 1999/09/06 01:17:28 davem Exp $
+# $Id: config.in,v 1.86 1999/12/23 01:46:09 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -41,17 +41,13 @@
 source drivers/sbus/char/Config.in
 source drivers/sbus/audio/Config.in
 
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS
-fi
+tristate 'Openprom tree appears in /proc/openprom' CONFIG_SUN_OPENPROMFS
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 if [ "$CONFIG_PROC_FS" = "y" ]; then
-   choice 'Kernel core (/proc/kcore) format' \
-	"ELF		CONFIG_KCORE_ELF	\
-	 A.OUT		CONFIG_KCORE_AOUT" ELF
+   define_bool CONFIG_KCORE_ELF y
 fi
 bool 'Kernel support for Linux/Sparc 32bit binary compatibility' CONFIG_SPARC32_COMPAT
 if [ "$CONFIG_SPARC32_COMPAT" != "n" ]; then
@@ -60,6 +56,7 @@
 fi
 tristate 'Kernel support for 64-bit ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+bool 'SunOS binary emulation' CONFIG_SUNOS_EMUL
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    tristate 'Solaris binary emulation (EXPERIMENTAL)' CONFIG_SOLARIS_EMUL
 fi
@@ -148,7 +145,7 @@
    mainmenu_option next_comment
    comment 'SCSI low-level drivers'
 
-   bool 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
+   tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
    tristate 'PTI Qlogic, ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
 
    if [ "$CONFIG_PCI" != "n" ]; then
@@ -159,8 +156,8 @@
   	 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 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI
-      if [ "$CONFIG_SCSI_NCR53C8XX" != "n" ]; then
+      dep_tristate 'SYM53C8XX SCSI support' CONFIG_SCSI_SYM53C8XX $CONFIG_SCSI
+      if [ "$CONFIG_SCSI_SYM53C8XX" != "n" ]; then
 	 int 'default tagged command queue depth' CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS 8
 	 int 'maximum number of queued commands' CONFIG_SCSI_NCR53C8XX_MAX_TAGS 32
 	 int 'synchronous transfers frequency in MHz' CONFIG_SCSI_NCR53C8XX_SYNC 10
@@ -190,7 +187,10 @@
       tristate '  Dummy net driver support' CONFIG_DUMMY
       tristate '  PPP (point-to-point) support' CONFIG_PPP
       if [ ! "$CONFIG_PPP" = "n" ]; then
-	 comment '    CCP compressors for PPP are only built as modules.'
+         dep_tristate '  PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP
+         dep_tristate '  PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
+         dep_tristate '  PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
+         dep_tristate '  PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m
       fi
       tristate '  SLIP (serial line) support' CONFIG_SLIP
       if [ "$CONFIG_SLIP" != "n" ]; then
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.3.34/linux/arch/sparc64/defconfig	Tue Dec 14 01:27:23 1999
+++ linux/arch/sparc64/defconfig	Mon Dec 20 22:05:52 1999
@@ -8,13 +8,6 @@
 CONFIG_EXPERIMENTAL=y
 
 #
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
 # General setup
 #
 CONFIG_VT=y
@@ -26,11 +19,21 @@
 #
 CONFIG_PROM_CONSOLE=y
 CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_RIVA is not set
 # CONFIG_FB_CLGEN is not set
-# CONFIG_FB_PM2 is not set
+CONFIG_FB_PM2=y
+# CONFIG_FB_PM2_FIFO_DISCONNECT is not set
+CONFIG_FB_PM2_PCI=y
 # CONFIG_FB_MATROX is not set
 CONFIG_FB_ATY=y
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_3DFX is not set
 CONFIG_FB_SBUS=y
 CONFIG_FB_CREATOR=y
 CONFIG_FB_CGSIX=y
@@ -73,6 +76,7 @@
 # CONFIG_SUN_VIDEOPIX is not set
 CONFIG_SUN_AURORA=m
 # CONFIG_TADPOLE_TS102_UCTRL is not set
+# CONFIG_SUN_JSFLASH is not set
 CONFIG_APM_RTC_IS_GMT=y
 # CONFIG_RTC is not set
 
@@ -90,12 +94,12 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
 CONFIG_SPARC32_COMPAT=y
-CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_ELF32=y
 # CONFIG_BINFMT_AOUT32 is not set
+CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
+# CONFIG_SUNOS_EMUL is not set
 CONFIG_SOLARIS_EMUL=m
 CONFIG_PARPORT=m
 CONFIG_PARPORT_PC=m
@@ -110,12 +114,18 @@
 CONFIG_ENVCTRL=m
 
 #
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
 # Floppy, IDE, and other block devices
 #
 CONFIG_BLK_DEV_FD=y
 # CONFIG_BLK_DEV_MD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_IDE=y
@@ -127,7 +137,7 @@
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_BLK_DEV_IDEDMA=y
 CONFIG_IDEDMA_AUTO=y
-IDEDMA_NEW_DRIVE_LISTINGS=y
+CONFIG_IDEDMA_NEW_DRIVE_LISTINGS=y
 CONFIG_BLK_DEV_NS87415=y
 CONFIG_BLK_DEV_CMD646=y
 
@@ -210,11 +220,11 @@
 CONFIG_SCSI_SUNESP=y
 CONFIG_SCSI_QLOGICPTI=m
 CONFIG_SCSI_AIC7XXX=y
-# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
-# CONFIG_CMDS_PER_DEVICE is not set
+CONFIG_AIC7XXX_TAGGED_QUEUEING=y
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
 CONFIG_AIC7XXX_PROC_STATS=y
 CONFIG_AIC7XXX_RESET_DELAY=5
-CONFIG_SCSI_NCR53C8XX=y
+CONFIG_SCSI_SYM53C8XX=y
 CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4
 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
 CONFIG_SCSI_NCR53C8XX_SYNC=10
@@ -245,10 +255,10 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_PPP=m
-
-#
-# CCP compressors for PPP are only built as modules.
-#
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
@@ -275,7 +285,7 @@
 # Video For Linux
 #
 CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_BT848=y
+# CONFIG_VIDEO_BT848 is not set
 
 #
 # Filesystems
@@ -285,6 +295,8 @@
 # CONFIG_ADFS_FS is not set
 CONFIG_AFFS_FS=m
 # CONFIG_HFS_FS is not set
+CONFIG_BFS_FS=m
+# CONFIG_BFS_FS_WRITE is not set
 CONFIG_FAT_FS=m
 CONFIG_MSDOS_FS=m
 # CONFIG_UMSDOS_FS is not set
@@ -292,8 +304,6 @@
 CONFIG_EFS_FS=m
 CONFIG_ISO9660_FS=m
 # CONFIG_JOLIET is not set
-CONFIG_UDF_FS=m
-# CONFIG_UDF_RW is not set
 CONFIG_MINIX_FS=m
 # CONFIG_NTFS_FS is not set
 CONFIG_HPFS_FS=m
@@ -303,6 +313,9 @@
 CONFIG_ROMFS_FS=m
 CONFIG_EXT2_FS=y
 CONFIG_SYSV_FS=m
+# CONFIG_SYSV_FS_WRITE is not set
+CONFIG_UDF_FS=m
+# CONFIG_UDF_RW is not set
 CONFIG_UFS_FS=m
 CONFIG_UFS_FS_WRITE=y
 
@@ -312,7 +325,7 @@
 CONFIG_CODA_FS=m
 CONFIG_NFS_FS=y
 CONFIG_NFSD=m
-# CONFIG_NFSD_SUN is not set
+CONFIG_NFSD_V3=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_SMB_FS=m
@@ -322,7 +335,9 @@
 # CONFIG_NCPFS_STRONG is not set
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
 # CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile
--- v2.3.34/linux/arch/sparc64/kernel/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/arch/sparc64/kernel/Makefile	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.46 1999/08/31 04:39:34 davem Exp $
+# $Id: Makefile,v 1.50 1999/12/21 04:02:24 davem Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -17,16 +17,23 @@
 
 O_TARGET := kernel.o
 O_OBJS   := process.o setup.o cpu.o idprom.o \
-	    traps.o devices.o auxio.o ioport.o \
+	    traps.o devices.o auxio.o \
 	    irq.o ptrace.o time.o sys_sparc.o signal.o \
-	    unaligned.o sys_sunos32.o sunos_ioctl32.o \
-	    central.o pci.o pci_common.o pci_iommu.o \
+	    unaligned.o central.o pci.o pci_common.o pci_iommu.o \
 	    pci_psycho.o pci_sabre.o starfire.o semaphore.o \
-	    power.o
+	    power.o sbus.o iommu_common.o
 OX_OBJS  := sparc64_ksyms.o
 
 ifdef CONFIG_PCI
   O_OBJS += ebus.o
+endif
+
+ifdef CONFIG_SUNOS_EMUL
+  O_OBJS += sys_sunos32.o sunos_ioctl32.o
+else
+  ifdef CONFIG_SOLARIS_EMUL
+    O_OBJS += sys_sunos32.o sunos_ioctl32.o
+  endif
 endif
 
 ifdef CONFIG_SMP
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/auxio.c linux/arch/sparc64/kernel/auxio.c
--- v2.3.34/linux/arch/sparc64/kernel/auxio.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/kernel/auxio.c	Mon Dec 20 22:05:52 1999
@@ -20,22 +20,21 @@
 #include <asm/fhc.h>
 
 /* Probe and map in the Auxiliary I/O register */
-unsigned char *auxio_register;
+unsigned long auxio_register = 0;
 
 void __init auxio_probe(void)
 {
-        struct linux_sbus *bus;
-        struct linux_sbus_device *sdev = 0;
-	struct linux_prom_registers auxregs[1];
-
-        for_each_sbus(bus) {
-                for_each_sbusdev(sdev, bus) {
-                        if(!strcmp(sdev->prom_name, "auxio")) {
-				break;
-                        }
+        struct sbus_bus *sbus;
+        struct sbus_dev *sdev = 0;
+
+        for_each_sbus(sbus) {
+                for_each_sbusdev(sdev, sbus) {
+                        if(!strcmp(sdev->prom_name, "auxio"))
+				goto found_sdev;
                 }
         }
 
+found_sdev:
 	if (!sdev) {
 #ifdef CONFIG_PCI
 		struct linux_ebus *ebus;
@@ -57,19 +56,15 @@
 		}
 #endif
 		if(central_bus) {
-			auxio_register = NULL;
+			auxio_register = 0UL;
 			return;
 		}
 		prom_printf("Cannot find auxio node, cannot continue...\n");
 		prom_halt();
 	}
 
-	prom_getproperty(sdev->prom_node, "reg", (char *) auxregs, sizeof(auxregs));
-	prom_apply_sbus_ranges(sdev->my_bus, auxregs, 0x1, sdev);
 	/* Map the register both read and write */
-	auxio_register = (unsigned char *) sparc_alloc_io(auxregs[0].phys_addr, 0,
-							  auxregs[0].reg_size,
-							  "auxiliaryIO",
-							  auxregs[0].which_io, 0x0);
+	auxio_register = sbus_ioremap(&sdev->resource[0], 0,
+				      sdev->reg_addrs[0].reg_size, "auxiliaryIO");
 	TURN_ON_LED;
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/central.c linux/arch/sparc64/kernel/central.c
--- v2.3.34/linux/arch/sparc64/kernel/central.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/kernel/central.c	Mon Dec 20 22:05:52 1999
@@ -1,7 +1,7 @@
-/* $Id: central.c,v 1.11 1998/12/14 12:18:16 davem Exp $
+/* $Id: central.c,v 1.13 1999/12/01 10:44:43 davem Exp $
  * central.c: Central FHC driver for Sunfire/Starfire/Wildfire.
  *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com)
  */
 
 #include <linux/kernel.h>
@@ -10,6 +10,8 @@
 #include <linux/timer.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
 
 #include <asm/page.h>
 #include <asm/fhc.h>
@@ -25,10 +27,80 @@
 		~(sizeof(unsigned long) - 1));
 }
 
-extern void prom_central_ranges_init(int cnode, struct linux_central *central);
-extern void prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc);
+static void central_ranges_init(int cnode, struct linux_central *central)
+{
+	int success;
+	
+	central->num_central_ranges = 0;
+	success = prom_getproperty(central->prom_node, "ranges",
+				   (char *) central->central_ranges,
+				   sizeof (central->central_ranges));
+	if (success != -1)
+		central->num_central_ranges = (success/sizeof(struct linux_prom_ranges));
+}
+
+static void fhc_ranges_init(int fnode, struct linux_fhc *fhc)
+{
+	int success;
+	
+	fhc->num_fhc_ranges = 0;
+	success = prom_getproperty(fhc->prom_node, "ranges",
+				   (char *) fhc->fhc_ranges,
+				   sizeof (fhc->fhc_ranges));
+	if (success != -1)
+		fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges));
+}
+
+/* Range application routines are exported to various drivers,
+ * so do not __init this.
+ */
+static void adjust_regs(struct linux_prom_registers *regp, int nregs,
+			struct linux_prom_ranges *rangep, int nranges)
+{
+	int regc, rngc;
+
+	for (regc = 0; regc < nregs; regc++) {
+		for (rngc = 0; rngc < nranges; rngc++)
+			if (regp[regc].which_io == rangep[rngc].ot_child_space)
+				break; /* Fount it */
+		if (rngc == nranges) /* oops */
+			prom_printf("adjust_regs: Could not find range with matching bus type...\n");
+		regp[regc].which_io = rangep[rngc].ot_parent_space;
+		regp[regc].phys_addr += rangep[rngc].ot_parent_base;
+	}
+}
+
+/* Apply probed fhc ranges to registers passed, if no ranges return. */
+void apply_fhc_ranges(struct linux_fhc *fhc,
+		      struct linux_prom_registers *regs,
+		      int nregs)
+{
+	if(fhc->num_fhc_ranges)
+		adjust_regs(regs, nregs, fhc->fhc_ranges,
+			    fhc->num_fhc_ranges);
+}
+
+/* Apply probed central ranges to registers passed, if no ranges return. */
+void apply_central_ranges(struct linux_central *central,
+			  struct linux_prom_registers *regs, int nregs)
+{
+	if(central->num_central_ranges)
+		adjust_regs(regs, nregs, central->central_ranges,
+			    central->num_central_ranges);
+}
 
-static unsigned long probe_other_fhcs(unsigned long memory_start)
+void * __init central_alloc_bootmem(unsigned long size)
+{
+	void *ret;
+
+	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+	if (ret != NULL)
+		memset(ret, 0, size);
+
+	return ret;
+}
+
+static void probe_other_fhcs(void)
 {
 	struct linux_prom64_registers fpregs[6];
 	char namebuf[128];
@@ -45,9 +117,12 @@
 		int board;
 		u32 tmp;
 
-		fhc = (struct linux_fhc *)memory_start;
-		memory_start += sizeof(struct linux_fhc);
-		memory_start = long_align(memory_start);
+		fhc = (struct linux_fhc *)
+			central_alloc_bootmem(sizeof(struct linux_fhc));
+		if (fhc == NULL) {
+			prom_printf("probe_other_fhcs: Cannot alloc fhc.\n");
+			prom_halt();
+		}
 
 		/* Link it into the FHC chain. */
 		fhc->next = fhc_list;
@@ -59,7 +134,7 @@
 		fhc->prom_node = node;
 		prom_getstring(node, "name", namebuf, sizeof(namebuf));
 		strcpy(fhc->prom_name, namebuf);
-		prom_fhc_ranges_init(node, fhc);
+		fhc_ranges_init(node, fhc);
 
 		/* Non-central FHC's have 64-bit OBP format registers. */
 		if(prom_getproperty(node, "reg",
@@ -69,29 +144,23 @@
 		}
 
 		/* Only central FHC needs special ranges applied. */
-		fhc->fhc_regs.pregs = (struct fhc_internal_regs *)
-			__va(fpregs[0].phys_addr);
-		fhc->fhc_regs.ireg = (struct fhc_ign_reg *)
-			__va(fpregs[1].phys_addr);
-		fhc->fhc_regs.ffregs = (struct fhc_fanfail_regs *)
-			__va(fpregs[2].phys_addr);
-		fhc->fhc_regs.sregs = (struct fhc_system_regs *)
-			__va(fpregs[3].phys_addr);
-		fhc->fhc_regs.uregs = (struct fhc_uart_regs *)
-			__va(fpregs[4].phys_addr);
-		fhc->fhc_regs.tregs = (struct fhc_tod_regs *)
-			__va(fpregs[5].phys_addr);
+		fhc->fhc_regs.pregs = fpregs[0].phys_addr;
+		fhc->fhc_regs.ireg = fpregs[1].phys_addr;
+		fhc->fhc_regs.ffregs = fpregs[2].phys_addr;
+		fhc->fhc_regs.sregs = fpregs[3].phys_addr;
+		fhc->fhc_regs.uregs = fpregs[4].phys_addr;
+		fhc->fhc_regs.tregs = fpregs[5].phys_addr;
 
 		board = prom_getintdefault(node, "board#", -1);
 		fhc->board = board;
 
-		tmp = fhc->fhc_regs.pregs->fhc_jtag_ctrl;
+		tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL);
 		if((tmp & FHC_JTAG_CTRL_MENAB) != 0)
 			fhc->jtag_master = 1;
 		else
 			fhc->jtag_master = 0;
 
-		tmp = fhc->fhc_regs.pregs->fhc_id;
+		tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID);
 		printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] %s\n",
 		       board,
 		       (tmp & FHC_ID_VERS) >> 28,
@@ -103,7 +172,9 @@
 		 * the system.  When it is clear, this identifies
 		 * the central board.
 		 */
-		fhc->fhc_regs.pregs->fhc_control |= FHC_CONTROL_IXIST;
+		tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
+		tmp |= FHC_CONTROL_IXIST;
+		upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
 
 		/* Look for the next FHC. */
 		node = prom_getsibling(node);
@@ -113,8 +184,6 @@
 		if(node == 0)
 			break;
 	}
-
-	return memory_start;
 }
 
 static void probe_clock_board(struct linux_central *central,
@@ -135,22 +204,20 @@
 		prom_halt();
 	}
 	nregs /= sizeof(struct linux_prom_registers);
-	prom_apply_fhc_ranges(fhc, &cregs[0], nregs);
-	prom_apply_central_ranges(central, &cregs[0], nregs);
-	central->cfreg = (volatile u8 *)
-		__va((((unsigned long)cregs[0].which_io) << 32) |
-		     (((unsigned long)cregs[0].phys_addr)+0x02));
-	central->clkregs = (struct clock_board_regs *)
-		__va((((unsigned long)cregs[1].which_io) << 32) |
-		     (((unsigned long)cregs[1].phys_addr)));
+	apply_fhc_ranges(fhc, &cregs[0], nregs);
+	apply_central_ranges(central, &cregs[0], nregs);
+	central->cfreg = ((((unsigned long)cregs[0].which_io) << 32UL) |
+			  ((unsigned long)cregs[0].phys_addr));
+	central->clkregs = ((((unsigned long)cregs[1].which_io) << 32UL) |
+			    ((unsigned long)cregs[1].phys_addr));
+
 	if(nregs == 2)
-		central->clkver = NULL;
+		central->clkver = 0UL;
 	else
-		central->clkver = (volatile u8 *)
-			__va((((unsigned long)cregs[2].which_io) << 32) |
-			     (((unsigned long)cregs[2].phys_addr)));
+		central->clkver = ((((unsigned long)cregs[2].which_io) << 32UL) |
+				   ((unsigned long)cregs[2].phys_addr));
 
-	tmp = central->clkregs->stat1;
+	tmp = upa_readb(central->clkregs + CLOCK_STAT1);
 	tmp &= 0xc0;
 	switch(tmp) {
 	case 0x40:
@@ -160,9 +227,9 @@
 		nslots = 8;
 		break;
 	case 0x80:
-		if(central->clkver != NULL &&
-		   *(central->clkver) != 0) {
-			if((*(central->clkver) & 0x80) != 0)
+		if(central->clkver != 0UL &&
+		   upa_readb(central->clkver) != 0) {
+			if((upa_readb(central->clkver) & 0x80) != 0)
 				nslots = 4;
 			else
 				nslots = 5;
@@ -174,11 +241,11 @@
 	};
 	central->slots = nslots;
 	printk("CENTRAL: Detected %d slot Enterprise system. cfreg[%02x] cver[%02x]\n",
-	       central->slots, *(central->cfreg),
-	       (central->clkver ? *(central->clkver) : 0x00));
+	       central->slots, upa_readb(central->cfreg),
+	       (central->clkver ? upa_readb(central->clkver) : 0x00));
 }
 
-unsigned long central_probe(unsigned long memory_start)
+void central_probe(void)
 {
 	struct linux_prom_registers fpregs[6];
 	struct linux_fhc *fhc;
@@ -190,18 +257,23 @@
 		extern void starfire_check(void);
 
 		starfire_check();
-		return memory_start;
+		return;
 	}
 
 	/* Ok we got one, grab some memory for software state. */
-	memory_start = long_align(memory_start);
-	central_bus = (struct linux_central *) (memory_start);
+	central_bus = (struct linux_central *)
+		central_alloc_bootmem(sizeof(struct linux_central));
+	if (central_bus == NULL) {
+		prom_printf("central_probe: Cannot alloc central_bus.\n");
+		prom_halt();
+	}
 
-	memory_start += sizeof(struct linux_central);
-	memory_start = long_align(memory_start);
-	fhc = (struct linux_fhc *)(memory_start);
-	memory_start += sizeof(struct linux_fhc);
-	memory_start = long_align(memory_start);
+	fhc = (struct linux_fhc *)
+		central_alloc_bootmem(sizeof(struct linux_fhc));
+	if (fhc == NULL) {
+		prom_printf("central_probe: Cannot alloc central fhc.\n");
+		prom_halt();
+	}
 
 	/* First init central. */
 	central_bus->child = fhc;
@@ -210,7 +282,7 @@
 	prom_getstring(cnode, "name", namebuf, sizeof(namebuf));
 	strcpy(central_bus->prom_name, namebuf);
 
-	prom_central_ranges_init(cnode, central_bus);
+	central_ranges_init(cnode, central_bus);
 
 	/* And then central's FHC. */
 	fhc->next = fhc_list;
@@ -226,38 +298,32 @@
 	prom_getstring(fnode, "name", namebuf, sizeof(namebuf));
 	strcpy(fhc->prom_name, namebuf);
 
-	prom_fhc_ranges_init(fnode, fhc);
+	fhc_ranges_init(fnode, fhc);
 
 	/* Now, map in FHC register set. */
 	if (prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)) == -1) {
 		prom_printf("CENTRAL: Fatal error, cannot get fhc regs.\n");
 		prom_halt();
 	}
-	prom_apply_central_ranges(central_bus, &fpregs[0], 6);
+	apply_central_ranges(central_bus, &fpregs[0], 6);
 	
-	fhc->fhc_regs.pregs = (struct fhc_internal_regs *)
-		__va((((unsigned long)fpregs[0].which_io)<<32) |
-		     (((unsigned long)fpregs[0].phys_addr)));
-	fhc->fhc_regs.ireg = (struct fhc_ign_reg *)
-		__va((((unsigned long)fpregs[1].which_io)<<32) |
-		     (((unsigned long)fpregs[1].phys_addr)));
-	fhc->fhc_regs.ffregs = (struct fhc_fanfail_regs *)
-		__va((((unsigned long)fpregs[2].which_io)<<32) |
-		     (((unsigned long)fpregs[2].phys_addr)));
-	fhc->fhc_regs.sregs = (struct fhc_system_regs *)
-		__va((((unsigned long)fpregs[3].which_io)<<32) |
-		     (((unsigned long)fpregs[3].phys_addr)));
-	fhc->fhc_regs.uregs = (struct fhc_uart_regs *)
-		__va((((unsigned long)fpregs[4].which_io)<<32) |
-		     (((unsigned long)fpregs[4].phys_addr)));
-	fhc->fhc_regs.tregs = (struct fhc_tod_regs *)
-		__va((((unsigned long)fpregs[5].which_io)<<32) |
-		     (((unsigned long)fpregs[5].phys_addr)));
+	fhc->fhc_regs.pregs = ((((unsigned long)fpregs[0].which_io)<<32UL) |
+			       ((unsigned long)fpregs[0].phys_addr));
+	fhc->fhc_regs.ireg = ((((unsigned long)fpregs[1].which_io)<<32UL) |
+			      ((unsigned long)fpregs[1].phys_addr));
+	fhc->fhc_regs.ffregs = ((((unsigned long)fpregs[2].which_io)<<32UL) |
+				((unsigned long)fpregs[2].phys_addr));
+	fhc->fhc_regs.sregs = ((((unsigned long)fpregs[3].which_io)<<32UL) |
+			       ((unsigned long)fpregs[3].phys_addr));
+	fhc->fhc_regs.uregs = ((((unsigned long)fpregs[4].which_io)<<32UL) |
+			       ((unsigned long)fpregs[4].phys_addr));
+	fhc->fhc_regs.tregs = ((((unsigned long)fpregs[5].which_io)<<32UL) |
+			       ((unsigned long)fpregs[5].phys_addr));
 
 	/* Obtain board number from board status register, Central's
 	 * FHC lacks "board#" property.
 	 */
-	err = fhc->fhc_regs.pregs->fhc_bsr;
+	err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_BSR);
 	fhc->board = (((err >> 16) & 0x01) |
 		      ((err >> 12) & 0x0e));
 
@@ -266,23 +332,21 @@
 	/* Attach the clock board registers for CENTRAL. */
 	probe_clock_board(central_bus, fhc, cnode, fnode);
 
-	err = fhc->fhc_regs.pregs->fhc_id;
+	err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID);
 	printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n",
 	       fhc->board,
 	       ((err & FHC_ID_VERS) >> 28),
 	       ((err & FHC_ID_PARTID) >> 12),
 	       ((err & FHC_ID_MANUF) >> 1));
 
-	return probe_other_fhcs(memory_start);
+	probe_other_fhcs();
 }
 
 static __inline__ void fhc_ledblink(struct linux_fhc *fhc, int on)
 {
-	volatile u32 *ctrl = (volatile u32 *)
-		&fhc->fhc_regs.pregs->fhc_control;
 	u32 tmp;
 
-	tmp = *ctrl;
+	tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
 
 	/* NOTE: reverse logic on this bit */
 	if (on)
@@ -291,16 +355,15 @@
 		tmp |= FHC_CONTROL_RLED;
 	tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE);
 
-	*ctrl = tmp;
-	tmp = *ctrl;
+	upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
+	upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
 }
 
 static __inline__ void central_ledblink(struct linux_central *central, int on)
 {
-	volatile u8 *ctrl = (volatile u8 *) &central->clkregs->control;
-	int tmp;
+	u8 tmp;
 
-	tmp = *ctrl;
+	tmp = upa_readb(central->clkregs + CLOCK_CTRL);
 
 	/* NOTE: reverse logic on this bit */
 	if(on)
@@ -308,8 +371,8 @@
 	else
 		tmp |= CLOCK_CTRL_RLED;
 
-	*ctrl = tmp;
-	tmp = *ctrl;
+	upa_writeb(tmp, central->clkregs + CLOCK_CTRL);
+	upa_readb(central->clkregs + CLOCK_CTRL);
 }
 
 static struct timer_list sftimer;
@@ -335,41 +398,41 @@
 {
 	struct linux_central *central = central_bus;
 	struct linux_fhc *fhc;
+	u8 ctrl;
 
 	/* No central bus, nothing to do. */
 	if (central == NULL)
 		return;
 
 	for(fhc = fhc_list; fhc != NULL; fhc = fhc->next) {
-		volatile u32 *ctrl = (volatile u32 *)
-			&fhc->fhc_regs.pregs->fhc_control;
 		u32 tmp;
 
 		/* Clear all of the interrupt mapping registers
 		 * just in case OBP left them in a foul state.
 		 */
-#define ZAP(REG1, REG2) \
-do {	volatile u32 *__iclr = (volatile u32 *)(&(REG1)); \
-	volatile u32 *__imap = (volatile u32 *)(&(REG2)); \
-	*(__iclr) = 0; \
-	(void) *(__iclr); \
-	*(__imap) &= ~(0x80000000); \
-	(void) *(__imap); \
-} while(0)
-
-		ZAP(fhc->fhc_regs.ffregs->fhc_ff_iclr,
-		    fhc->fhc_regs.ffregs->fhc_ff_imap);
-		ZAP(fhc->fhc_regs.sregs->fhc_sys_iclr,
-		    fhc->fhc_regs.sregs->fhc_sys_imap);
-		ZAP(fhc->fhc_regs.uregs->fhc_uart_iclr,
-		    fhc->fhc_regs.uregs->fhc_uart_imap);
-		ZAP(fhc->fhc_regs.tregs->fhc_tod_iclr,
-		    fhc->fhc_regs.tregs->fhc_tod_imap);
+#define ZAP(ICLR, IMAP) \
+do {	u32 imap_tmp; \
+	upa_writel(0, (ICLR)); \
+	upa_readl(ICLR); \
+	imap_tmp = upa_readl(IMAP); \
+	imap_tmp &= ~(0x80000000); \
+	upa_writel(imap_tmp, (IMAP)); \
+	upa_readl(IMAP); \
+} while (0)
+
+		ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR,
+		    fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP);
+		ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR,
+		    fhc->fhc_regs.sregs + FHC_SREGS_IMAP);
+		ZAP(fhc->fhc_regs.uregs + FHC_UREGS_ICLR,
+		    fhc->fhc_regs.uregs + FHC_UREGS_IMAP);
+		ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR,
+		    fhc->fhc_regs.tregs + FHC_TREGS_IMAP);
 
 #undef ZAP
 
 		/* Setup FHC control register. */
-		tmp = *ctrl;
+		tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
 
 		/* All non-central boards have this bit set. */
 		if(! IS_CENTRAL_FHC(fhc))
@@ -379,14 +442,17 @@
 		 * line and both low power mode enables.
 		 */
 		tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE);
-		*ctrl = tmp;
-		tmp = *ctrl; /* Ensure completion */
+
+		upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
+		upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
 	}
 
 	/* OBP leaves it on, turn it off so clock board timer LED
 	 * is in sync with FHC ones.
 	 */
-	central->clkregs->control &= ~(CLOCK_CTRL_RLED);
+	ctrl = upa_readb(central->clkregs + CLOCK_CTRL);
+	ctrl &= ~(CLOCK_CTRL_RLED);
+	upa_writeb(ctrl, central->clkregs + CLOCK_CTRL);
 
 	led_state = 0;
 	init_timer(&sftimer);
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/devices.c linux/arch/sparc64/kernel/devices.c
--- v2.3.34/linux/arch/sparc64/kernel/devices.c	Tue Sep  7 12:14:06 1999
+++ linux/arch/sparc64/kernel/devices.c	Mon Dec 20 22:05:52 1999
@@ -19,10 +19,9 @@
 int linux_num_cpus = 0;
 
 extern void cpu_probe(void);
-extern unsigned long central_probe(unsigned long);
+extern void central_probe(void);
 
-unsigned long __init
-device_scan(unsigned long mem_start)
+void __init device_scan(void)
 {
 	char node_str[128];
 	int nd, prom_node_cpu, thismid;
@@ -54,13 +53,8 @@
 				prom_getproperty(scan, "upa-portid",
 						 (char *) &thismid, sizeof(thismid));
 				linux_cpus[cpu_ctr].mid = thismid;
-#ifdef __SMP__				
-				/* Don't pollute PROM screen with these messages. If the kernel is screwed enough
-				   that console does not start up, then we don't care how many CPUs have been found,
-				   if it starts up, the user can use console=prom to see it. */
-				/* prom_printf("Found CPU %d (node=%08x,mid=%d)\n", cpu_ctr, (unsigned) scan, thismid); */
-				printk("Found CPU %d (node=%08x,mid=%d)\n", cpu_ctr, (unsigned) scan, thismid);
-#endif				       
+				printk("Found CPU %d (node=%08x,mid=%d)\n",
+				       cpu_ctr, (unsigned) scan, thismid);
 				cpu_ctr++;
 			}
 		};
@@ -68,19 +62,15 @@
 			prom_printf("No CPU nodes found, cannot continue.\n");
 			prom_halt();
 		}
-#ifdef __SMP__		
 		printk("Found %d CPU prom device tree node(s).\n", cpu_ctr);
-#endif		
-	};
+	}
 	prom_node_cpu = cpu_nds[0];
 
 	linux_num_cpus = cpu_ctr;
 	
 	prom_cpu_nodes[0] = prom_node_cpu;
 
-	mem_start = central_probe(mem_start);
+	central_probe();
 
 	cpu_probe();
-
-	return mem_start;
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/dtlb_backend.S linux/arch/sparc64/kernel/dtlb_backend.S
--- v2.3.34/linux/arch/sparc64/kernel/dtlb_backend.S	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/kernel/dtlb_backend.S	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: dtlb_backend.S,v 1.7 1998/12/16 04:33:28 davem Exp $
+/* $Id: dtlb_backend.S,v 1.8 1999/12/05 10:41:35 davem Exp $
  * dtlb_backend.S: Back end to DTLB miss replacement strategy.
  *                 This is included directly into the trap table.
  *
@@ -10,7 +10,7 @@
 #define VPTE_SHIFT		(PAGE_SHIFT - 3)
 #define PMD_SHIFT		(23 - PAGE_SHIFT + 3)
 #define PGD_SHIFT		(34 - PAGE_SHIFT + 3)
-#define VPTE_BITS		(_PAGE_CP | _PAGE_P | _PAGE_W)
+#define VPTE_BITS		(_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
 
 /* Ways we can get here:
  *
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c
--- v2.3.34/linux/arch/sparc64/kernel/ebus.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/kernel/ebus.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.44 1999/09/05 09:28:09 ecd Exp $
+/* $Id: ebus.c,v 1.46 1999/11/19 05:52:48 davem Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -22,9 +22,6 @@
 
 struct linux_ebus *ebus_chain = 0;
 
-extern void prom_ebus_ranges_init(struct linux_ebus *);
-extern void prom_ebus_intmap_init(struct linux_ebus *);
-
 #ifdef CONFIG_SUN_OPENPROMIO
 extern int openprom_init(void);
 #endif
@@ -49,15 +46,49 @@
 	return mem;
 }
 
-void __init ebus_intmap_match(struct linux_ebus *ebus,
-			      struct linux_prom_registers *reg,
-			      int *interrupt)
+static void __init ebus_ranges_init(struct linux_ebus *ebus)
+{
+	int success;
+
+	ebus->num_ebus_ranges = 0;
+	success = prom_getproperty(ebus->prom_node, "ranges",
+				   (char *)ebus->ebus_ranges,
+				   sizeof(ebus->ebus_ranges));
+	if (success != -1)
+		ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges));
+}
+
+static void __init ebus_intmap_init(struct linux_ebus *ebus)
+{
+	int success;
+
+	ebus->num_ebus_intmap = 0;
+	success = prom_getproperty(ebus->prom_node, "interrupt-map",
+				   (char *)ebus->ebus_intmap,
+				   sizeof(ebus->ebus_intmap));
+	if (success == -1)
+		return;
+
+	ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap));
+
+	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();
+	}
+}
+
+int __init ebus_intmap_match(struct linux_ebus *ebus,
+			     struct linux_prom_registers *reg,
+			     int *interrupt)
 {
 	unsigned int hi, lo, irq;
 	int i;
 
 	if (!ebus->num_ebus_intmap)
-		return;
+		return 0;
 
 	hi = reg->which_io & ebus->ebus_intmask.phys_hi;
 	lo = reg->phys_addr & ebus->ebus_intmask.phys_lo;
@@ -67,13 +98,10 @@
 		    (ebus->ebus_intmap[i].phys_lo == lo) &&
 		    (ebus->ebus_intmap[i].interrupt == irq)) {
 			*interrupt = ebus->ebus_intmap[i].cinterrupt;
-			return;
+			return 0;
 		}
 	}
-
-	prom_printf("ebus: IRQ [%08x.%08x.%08x] not found in interrupt-map\n",
-		    reg->which_io, reg->phys_addr, *interrupt);
-	prom_halt();
+	return -1;
 }
 
 void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
@@ -139,8 +167,16 @@
 			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] = p->irq_build(p, dev->bus->self, irqs[i]);
+			if (ebus_intmap_match(dev->bus, preg, &irqs[i]) != -1) {
+				dev->irqs[i] = p->irq_build(p,
+							    dev->bus->self,
+							    irqs[i]);
+			} else {
+				/* If we get a bogus interrupt property, just
+				 * record the raw value instead of punting.
+				 */
+				dev->irqs[i] = irqs[i];
+			}
 		}
 	}
 }
@@ -194,8 +230,16 @@
 			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] = p->irq_build(p, dev->bus->self, irqs[i]);
+			if (ebus_intmap_match(dev->bus, &regs[0], &irqs[i]) != -1) {
+				dev->irqs[i] = p->irq_build(p,
+							    dev->bus->self,
+							    irqs[i]);
+			} else {
+				/* If we get a bogus interrupt property, just
+				 * record the raw value instead of punting.
+				 */
+				dev->irqs[i] = irqs[i];
+			}
 		}
 	}
 
@@ -295,8 +339,8 @@
 		/* NOTE: Cache line size is in 32-bit word units. */
 		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 64/sizeof(u32));
 
-		prom_ebus_ranges_init(ebus);
-		prom_ebus_intmap_init(ebus);
+		ebus_ranges_init(ebus);
+		ebus_intmap_init(ebus);
 
 		nd = prom_getchild(ebusnd);
 		if (!nd)
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S
--- v2.3.34/linux/arch/sparc64/kernel/entry.S	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/kernel/entry.S	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.107 1999/08/31 19:25:29 davem Exp $
+/* $Id: entry.S,v 1.110 1999/11/19 05:52:50 davem Exp $
  * arch/sparc64/kernel/entry.S:  Sparc64 trap low-level entry points.
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -214,8 +214,8 @@
 	.align		32
 	.globl		do_ivec
 do_ivec:
-	wr		%g0, ASI_UDB_INTR_R, %asi
-	ldxa		[%g0 + 0x40] %asi, %g3
+	mov		0x40, %g3
+	ldxa		[%g3 + %g0] ASI_UDB_INTR_R, %g3
 	sethi		%hi(KERNBASE), %g4
 	cmp		%g3, %g4
 	bgeu,pn		%xcc, do_ivec_xcall
@@ -234,22 +234,25 @@
 
 	sllx		%g2, %g4, %g2
 	sllx		%g4, 2, %g4
-	lduw		[%g1 + %g4], %g5	/* g5 = irq_work(cpu, pil) */
+	lduw		[%g6 + %g4], %g5	/* g5 = irq_work(cpu, pil) */
 	stw		%g5, [%g3 + 0x00]	/* bucket->irq_chain = g5 */
-	stw		%g3, [%g1 + %g4]	/* irq_work(cpu, pil) = bucket */
+	stw		%g3, [%g6 + %g4]	/* irq_work(cpu, pil) = bucket */
 	wr		%g2, 0x0, %set_softint
 	retry
 do_ivec_xcall:
-	ldxa		[%g0 + 0x50] %asi, %g6
+	mov		0x50, %g1
 
+	ldxa		[%g1 + %g0] ASI_UDB_INTR_R, %g1
 	srl		%g3, 0, %g3
-	ldxa		[%g0 + 0x60] %asi, %g7
+	mov		0x60, %g7
+	ldxa		[%g7 + %g0] ASI_UDB_INTR_R, %g7
 	stxa		%g0, [%g0] ASI_INTR_RECEIVE
 	membar		#Sync
 	jmpl		%g3, %g0
 	 nop
+
 do_ivec_spurious:
-	stw		%g3, [%g1 + 0x00]	/* irq_work(cpu, 0) = bucket */
+	stw		%g3, [%g6 + 0x00]	/* irq_work(cpu, 0) = bucket */
 	rdpr		%pstate, %g5
 
 	wrpr		%g5, PSTATE_IG | PSTATE_AG, %pstate
@@ -261,6 +264,76 @@
 	ba,pt		%xcc, rtrap
 	 clr		%l6
 
+	.globl		save_alternate_globals
+save_alternate_globals: /* %o0 = save_area */
+	rdpr		%pstate, %o5
+	andn		%o5, PSTATE_IE, %o1
+	wrpr		%o1, PSTATE_AG, %pstate
+	stx		%g0, [%o0 + 0x00]
+	stx		%g1, [%o0 + 0x08]
+	stx		%g2, [%o0 + 0x10]
+	stx		%g3, [%o0 + 0x18]
+	stx		%g4, [%o0 + 0x20]
+	stx		%g5, [%o0 + 0x28]
+	stx		%g6, [%o0 + 0x30]
+	stx		%g7, [%o0 + 0x38]
+	wrpr		%o1, PSTATE_IG, %pstate
+	stx		%g0, [%o0 + 0x40]
+	stx		%g1, [%o0 + 0x48]
+	stx		%g2, [%o0 + 0x50]
+	stx		%g3, [%o0 + 0x58]
+	stx		%g4, [%o0 + 0x60]
+	stx		%g5, [%o0 + 0x68]
+	stx		%g6, [%o0 + 0x70]
+	stx		%g7, [%o0 + 0x78]
+	wrpr		%o1, PSTATE_MG, %pstate
+	stx		%g0, [%o0 + 0x80]
+	stx		%g1, [%o0 + 0x88]
+	stx		%g2, [%o0 + 0x90]
+	stx		%g3, [%o0 + 0x98]
+	stx		%g4, [%o0 + 0xa0]
+	stx		%g5, [%o0 + 0xa8]
+	stx		%g6, [%o0 + 0xb0]
+	stx		%g7, [%o0 + 0xb8]
+	wrpr		%o5, 0x0, %pstate
+	retl
+	 nop
+
+	.globl		restore_alternate_globals
+restore_alternate_globals: /* %o0 = save_area */
+	rdpr		%pstate, %o5
+	andn		%o5, PSTATE_IE, %o1
+	wrpr		%o1, PSTATE_AG, %pstate
+	ldx		[%o0 + 0x00], %g0
+	ldx		[%o0 + 0x08], %g1
+	ldx		[%o0 + 0x10], %g2
+	ldx		[%o0 + 0x18], %g3
+	ldx		[%o0 + 0x20], %g4
+	ldx		[%o0 + 0x28], %g5
+	ldx		[%o0 + 0x30], %g6
+	ldx		[%o0 + 0x38], %g7
+	wrpr		%o1, PSTATE_IG, %pstate
+	ldx		[%o0 + 0x40], %g0
+	ldx		[%o0 + 0x48], %g1
+	ldx		[%o0 + 0x50], %g2
+	ldx		[%o0 + 0x58], %g3
+	ldx		[%o0 + 0x60], %g4
+	ldx		[%o0 + 0x68], %g5
+	ldx		[%o0 + 0x70], %g6
+	ldx		[%o0 + 0x78], %g7
+	wrpr		%o1, PSTATE_MG, %pstate
+	ldx		[%o0 + 0x80], %g0
+	ldx		[%o0 + 0x88], %g1
+	ldx		[%o0 + 0x90], %g2
+	ldx		[%o0 + 0x98], %g3
+	ldx		[%o0 + 0xa0], %g4
+	ldx		[%o0 + 0xa8], %g5
+	ldx		[%o0 + 0xb0], %g6
+	ldx		[%o0 + 0xb8], %g7
+	wrpr		%o5, 0x0, %pstate
+	retl
+	 nop
+
 	.globl		getcc, setcc
 getcc:
 	ldx		[%o0 + PT_V9_TSTATE], %o1
@@ -313,7 +386,7 @@
 	ldx		[%g5 + %lo(pdma_size)], %g5
 
 next_byte:
-	ldub		[%g3], %g7
+	lduba		[%g3] ASI_PHYS_BYPASS_EC_E, %g7
 	andcc		%g7, 0x80, %g0
 	be,pn		%icc, floppy_fifo_emptied
 	 andcc		%g7, 0x20, %g0
@@ -322,7 +395,9 @@
 	be,pn		%icc, floppy_write
 	 sub		%g5, 1, %g5
 
-	ldub		[%g3 + 1], %g7
+	inc		%g3
+	lduba		[%g3] ASI_PHYS_BYPASS_EC_E, %g7
+	dec		%g3
 	orcc		%g0, %g5, %g0
 	stb		%g7, [%g4]
 	bne,pn		%xcc, next_byte
@@ -334,7 +409,9 @@
 floppy_write:
 	ldub		[%g4], %g7
 	orcc		%g0, %g5, %g0
-	stb		%g7, [%g3 + 1]
+	inc		%g3
+	stba		%g7, [%g3] ASI_PHYS_BYPASS_EC_E
+	dec		%g3
 	bne,pn		%xcc, next_byte
 	 add		%g4, 1, %g4
 
@@ -368,7 +445,7 @@
 	ldx		[%g1 + (11 << 3)], %g3		! irqaction[floppy_irq]
 	ldx		[%g3 + 0x10], %g4		! action->mask == ino_bucket ptr
 	ldx		[%g4 + 0x10], %g4		! bucket->iclr
-	stw		%g0, [%g4]			! SYSIO_ICLR_IDLE
+	stwa		%g0, [%g4] ASI_PHYS_BYPASS_EC_E	! ICLR_IDLE
 	membar		#Sync				! probably not needed...
 	retry
 
@@ -652,6 +729,8 @@
 	ba,pt		%xcc, rtrap
 	 nop
 
+#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
+    defined(CONFIG_SOLARIS_EMUL_MODULE)
 	/* SunOS uses syscall zero as the 'indirect syscall' it looks
 	 * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
 	 * This is complete brain damage.
@@ -705,6 +784,7 @@
 	 stx	%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
 	b,pt	%xcc, ret_sys_call
 	 stx	%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
+#endif
 
 	/* SunOS's execv() call only specifies the argv argument, the
 	 * environment settings are the same as the calling processes.
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S
--- v2.3.34/linux/arch/sparc64/kernel/head.S	Thu May 27 09:55:21 1999
+++ linux/arch/sparc64/kernel/head.S	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.61 1999/05/25 16:53:10 jj Exp $
+/* $Id: head.S,v 1.63 1999/11/19 05:52:49 davem Exp $
  * head.S: Initial boot code for the Sparc64 port of Linux.
  *
  * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -52,7 +52,7 @@
 
         .ascii  "HdrS"
         .word   LINUX_VERSION_CODE
-        .half   0x0202          /* HdrS version */
+        .half   0x0203          /* HdrS version */
 root_flags:
         .half   1
 root_dev:
@@ -65,6 +65,7 @@
         .word   0
         .xword  reboot_command
 	.xword	bootstr_len
+	.word	_end
 
 	/* We must be careful, 32-bit OpenBOOT will get confused if it
 	 * tries to save away a register window to a 64-bit kernel
@@ -92,28 +93,6 @@
 	wrpr    %g0, (PSTATE_PRIV|PSTATE_PEF|PSTATE_IE), %pstate
 	wr	%g0, 0, %fprs
 
-#ifdef __SMP__
-	/* Ugly but necessary... */
-	sethi	%hi(KERNBASE), %g7
-	sethi	%hi(sparc64_cpu_startup), %g5
-	or	%g5, %lo(sparc64_cpu_startup), %g5
-	sub	%g5, %g7, %g5
-	sethi	%hi(sparc64_cpu_startup_end), %g6
-	or	%g6, %lo(sparc64_cpu_startup_end), %g6
-	sub	%g6, %g7, %g6
-	sethi	%hi(smp_trampoline), %g3
-	or	%g3, %lo(smp_trampoline), %g3
-	sub	%g3, %g7, %g3
-1:	ldx	[%g5], %g1
-	stx	%g1, [%g3]
-	membar	#StoreStore
-	flush	%g3
-	add	%g5, 8, %g5
-	cmp	%g5, %g6
-	blu,pt	%xcc, 1b
-	 add	%g3, 8, %g3
-#endif
-
 create_mappings:
 	/* %g5 holds the tlb data */
         sethi   %uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
@@ -380,7 +359,7 @@
 	wrpr	%o1, (PSTATE_IG|PSTATE_IE), %pstate
 #ifndef __SMP__
 	sethi	%hi(__up_workvec), %g5
-	or	%g5, %lo(__up_workvec), %g1
+	or	%g5, %lo(__up_workvec), %g6
 #else
 	/* By definition of where we are, this is boot_cpu. */
 	sethi	%hi(cpu_data), %g5
@@ -404,7 +383,7 @@
 set_worklist:
 	sllx	%g1, 7, %g1
 	add	%g5, %g1, %g5
-	add	%g5, 64, %g1
+	add	%g5, 64, %g6
 #endif
 
 	/* Kill PROM timer */
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.3.34/linux/arch/sparc64/kernel/ioctl32.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/kernel/ioctl32.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.68 1999/09/10 05:59:25 davem Exp $
+/* $Id: ioctl32.c,v 1.71 1999/12/19 23:13:13 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997  Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
@@ -1921,6 +1921,9 @@
 	case TIOCSCTTY:
 	case TIOCGPTN:
 	case TIOCSPTLCK:
+	case TIOCGSERIAL:
+	case TIOCSSERIAL:
+	case TIOCSERGETLSR:
 	
 	/* Big F */
 	case FBIOGTYPE:
@@ -2124,6 +2127,9 @@
 	case OPROMGETCONS:
 	case OPROMGETFBNAME:
 	case OPROMGETBOOTARGS:
+	case OPROMSETCUR:
+	case OPROMPCI2NODE:
+	case OPROMPATH2NODE:
 
 	/* Socket level stuff */
 	case FIOSETOWN:
@@ -2175,6 +2181,10 @@
 	case PPPIOCSNPMODE:
 	case PPPIOCGDEBUG:
 	case PPPIOCSDEBUG:
+	case PPPIOCGIDLE:
+	case PPPIOCNEWUNIT:
+	case PPPIOCATTACH:
+	case PPPIOCDETACH:
 
 	/* CDROM stuff */
 	case CDROMPAUSE:
@@ -2204,6 +2214,9 @@
 	case CDROM_DRIVE_STATUS:
 	case CDROM_DISC_STATUS:
 	case CDROM_CHANGER_NSLOTS:
+	case CDROM_LOCKDOOR:
+	case CDROM_DEBUG:
+	case CDROM_GET_CAPABILITY:
 	
 	/* Big L */
 	case LOOP_SET_FD:
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/iommu_common.c linux/arch/sparc64/kernel/iommu_common.c
--- v2.3.34/linux/arch/sparc64/kernel/iommu_common.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/iommu_common.c	Mon Dec 20 22:05:52 1999
@@ -0,0 +1,233 @@
+/* $Id: iommu_common.c,v 1.2 1999/12/19 09:17:53 davem Exp $
+ * iommu_common.c: UltraSparc SBUS/PCI common iommu code.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include "iommu_common.h"
+
+/* You are _strongly_ advised to enable the following debugging code
+ * any time you make changes to the sg code below, run it for a while
+ * with filesystems mounted read-only before buying the farm... -DaveM
+ */
+
+#ifdef VERIFY_SG
+int verify_lengths(struct scatterlist *sg, int nents, int npages)
+{
+	int sg_len, dma_len;
+	int i, pgcount;
+
+	sg_len = 0;
+	for (i = 0; i < nents; i++)
+		sg_len += sg[i].length;
+
+	dma_len = 0;
+	for (i = 0; i < nents && sg[i].dvma_length; i++)
+		dma_len += sg[i].dvma_length;
+
+	if (sg_len != dma_len) {
+		printk("verify_lengths: Error, different, sg[%d] dma[%d]\n",
+		       sg_len, dma_len);
+		return -1;
+	}
+
+	pgcount = 0;
+	for (i = 0; i < nents && sg[i].dvma_length; i++) {
+		unsigned long start, end;
+
+		start = sg[i].dvma_address;
+		start = start & PAGE_MASK;
+
+		end = sg[i].dvma_address + sg[i].dvma_length;
+		end = (end + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+		pgcount += ((end - start) >> PAGE_SHIFT);
+	}
+
+	if (pgcount != npages) {
+		printk("verify_langths: Error, page count wrong, "
+		       "npages[%d] pgcount[%d]\n",
+		       npages, pgcount);
+		return -1;
+	}
+
+	/* This test passes... */
+	return 0;
+}
+
+int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte)
+{
+	struct scatterlist *sg = *__sg;
+	iopte_t *iopte = *__iopte;
+	int retval = 0;
+	u32 dlen = dma_sg->dvma_length;
+	u32 daddr = dma_sg->dvma_address;
+	unsigned int sglen;
+	unsigned long sgaddr;
+
+	sglen = sg->length;
+	sgaddr = (unsigned long) sg->address;
+	while (dlen > 0) {
+		unsigned long paddr;
+
+		/* SG and DMA_SG must begin at the same sub-page boundary. */
+		if ((sgaddr & ~PAGE_MASK) != (daddr & ~PAGE_MASK)) {
+			printk("verify_one_map: Wrong start offset "
+			       "sg[%08lx] dma[%08x]\n",
+			       sgaddr, daddr);
+			retval = -nents;
+			goto out;
+		}
+
+		/* Verify the IOPTE points to the right page. */
+		paddr = iopte_val(*iopte) & IOPTE_PAGE;
+		if ((paddr + PAGE_OFFSET) != (sgaddr & PAGE_MASK)) {
+			printk("verify_one_map: IOPTE[%08lx] maps the "
+			       "wrong page, should be [%08lx]\n",
+			       iopte_val(*iopte), (sgaddr & PAGE_MASK) - PAGE_OFFSET);
+			retval = -nents;
+			goto out;
+		}
+
+		/* If this SG crosses a page, adjust to that next page
+		 * boundary and loop.
+		 */
+		if ((sgaddr & PAGE_MASK) ^ ((sgaddr + sglen - 1) & PAGE_MASK)) {
+			unsigned long next_page, diff;
+
+			next_page = (sgaddr + PAGE_SIZE) & PAGE_MASK;
+			diff = next_page - sgaddr;
+			sgaddr += diff;
+			daddr += diff;
+			sglen -= diff;
+			dlen -= diff;
+			if (dlen > 0)
+				iopte++;
+			continue;
+		}
+
+		/* SG wholly consumed within this page. */
+		daddr += sglen;
+		dlen -= sglen;
+
+		if (dlen > 0 && ((daddr & ~PAGE_MASK) == 0))
+			iopte++;
+
+		sg++;
+		sgaddr = (unsigned long) sg->address;
+		sglen = sg->length;
+	}
+	if (dlen < 0) {
+		/* Transfer overrun, big problems. */
+		printk("verify_one_map: Transfer overrun by %d bytes.\n",
+		       -dlen);
+		retval = -nents;
+	} else {
+		/* Advance to next dma_sg implies that the next iopte will
+		 * begin it.
+		 */
+		iopte++;
+	}
+
+out:
+	*__sg = sg;
+	*__iopte = iopte;
+	return retval;
+}
+
+int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte)
+{
+	struct scatterlist *dma_sg = sg;
+	struct scatterlist *orig_dma_sg = dma_sg;
+	int orig_nents = nents;
+
+	for (;;) {
+		nents = verify_one_map(dma_sg, &sg, nents, &iopte);
+		if (nents <= 0)
+			break;
+		dma_sg++;
+		if (dma_sg->dvma_length == 0)
+			break;
+	}
+
+	if (nents > 0) {
+		printk("verify_maps: dma maps consumed by some sgs remain (%d)\n",
+		       nents);
+		return -1;
+	}
+
+	if (nents < 0) {
+		printk("verify_maps: Error, messed up mappings, "
+		       "at sg %d dma_sg %d\n",
+		       (int) (orig_nents + nents), (int) (dma_sg - orig_dma_sg));
+		return -1;
+	}
+
+	/* This test passes... */
+	return 0;
+}
+
+void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages)
+{
+	if (verify_lengths(sg, nents, npages) < 0 ||
+	    verify_maps(sg, nents, iopte) < 0) {
+		int i;
+
+		printk("verify_sglist: Crap, messed up mappings, dumping, iodma at %08x.\n",
+		       (u32) (sg->dvma_address & PAGE_MASK));
+		for (i = 0; i < nents; i++) {
+			printk("sg(%d): address(%p) length(%x) "
+			       "dma_address[%08x] dma_length[%08x]\n",
+			       i,
+			       sg[i].address, sg[i].length,
+			       sg[i].dvma_address, sg[i].dvma_length);
+		}
+	}
+
+	/* Seems to be ok */
+}
+#endif
+
+/* Two addresses are "virtually contiguous" if and only if:
+ * 1) They are equal, or...
+ * 2) They are both on a page boundry
+ */
+#define VCONTIG(__X, __Y)	(((__X) == (__Y)) || \
+				 (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL)
+
+unsigned long prepare_sg(struct scatterlist *sg, int nents)
+{
+	struct scatterlist *dma_sg = sg;
+	unsigned long prev;
+	u32 dent_addr, dent_len;
+
+	prev  = (unsigned long) sg->address;
+	prev += (unsigned long) (dent_len = sg->length);
+	dent_addr = (u32) ((unsigned long)sg->address & (PAGE_SIZE - 1UL));
+	while (--nents) {
+		unsigned long addr;
+
+		sg++;
+		addr = (unsigned long) sg->address;
+		if (! VCONTIG(prev, addr)) {
+			dma_sg->dvma_address = dent_addr;
+			dma_sg->dvma_length = dent_len;
+			dma_sg++;
+
+			dent_addr = ((dent_addr +
+				      dent_len +
+				      (PAGE_SIZE - 1UL)) >> PAGE_SHIFT);
+			dent_addr <<= PAGE_SHIFT;
+			dent_addr += addr & (PAGE_SIZE - 1UL);
+			dent_len = 0;
+		}
+		dent_len += sg->length;
+		prev = addr + sg->length;
+	}
+	dma_sg->dvma_address = dent_addr;
+	dma_sg->dvma_length = dent_len;
+
+	return ((unsigned long) dent_addr +
+		(unsigned long) dent_len +
+		(PAGE_SIZE - 1UL)) >> PAGE_SHIFT;
+}
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/iommu_common.h linux/arch/sparc64/kernel/iommu_common.h
--- v2.3.34/linux/arch/sparc64/kernel/iommu_common.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/iommu_common.h	Mon Dec 20 22:05:52 1999
@@ -0,0 +1,34 @@
+/* $Id: iommu_common.h,v 1.1 1999/12/17 12:31:54 jj Exp $
+ * iommu_common.h: UltraSparc SBUS/PCI common iommu declarations.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/page.h>
+#include <asm/iommu.h>
+#include <asm/scatterlist.h>
+
+/* You are _strongly_ advised to enable the following debugging code
+ * any time you make changes to the sg code below, run it for a while
+ * with filesystems mounted read-only before buying the farm... -DaveM
+ */
+#undef VERIFY_SG
+
+#ifdef VERIFY_SG
+int verify_lengths(struct scatterlist *sg, int nents, int npages);
+int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, int nents, iopte_t **__iopte);
+int verify_maps(struct scatterlist *sg, int nents, iopte_t *iopte);
+void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages);
+#endif
+
+/* Two addresses are "virtually contiguous" if and only if:
+ * 1) They are equal, or...
+ * 2) They are both on a page boundry
+ */
+#define VCONTIG(__X, __Y)	(((__X) == (__Y)) || \
+				 (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL)
+
+unsigned long prepare_sg(struct scatterlist *sg, int nents);
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/ioport.c linux/arch/sparc64/kernel/ioport.c
--- v2.3.34/linux/arch/sparc64/kernel/ioport.c	Tue Aug  4 16:03:35 1998
+++ linux/arch/sparc64/kernel/ioport.c	Wed Dec 31 16:00:00 1969
@@ -1,107 +0,0 @@
-/* $Id: ioport.c,v 1.14 1998/05/11 06:23:36 davem Exp $
- * ioport.c:  Simple io mapping allocator.
- *
- * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
- */
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/vaddrs.h>
-#include <asm/oplib.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-/* This points to the next to use virtual memory for io mappings */
-static unsigned long dvma_next_free   = DVMA_VADDR;
-
-extern void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr);
-
-/*
- * sparc_alloc_io:
- * Map and allocates an obio device.
- * Implements a simple linear allocator, you can force the function
- * to use your own mapping, but in practice this should not be used.
- *
- * Input:
- *  address: Physical address to map
- *  virtual: if non zero, specifies a fixed virtual address where
- *           the mapping should take place, not supported on Ultra
- *           and this feature is scheduled to be removed as nobody
- *           uses it. -DaveM
- *  len:     the length of the mapping
- *  bus_type: Optional high word of physical address.
- *
- * Returns:
- *  The virtual address where the mapping actually took place.
- */
-
-void *sparc_alloc_io (u32 address, void *virtual, int len, char *name,
-		      u32 bus_type, int rdonly)
-{
-	unsigned long addr = ((unsigned long)address) + (((unsigned long)bus_type)<<32);
-	unsigned long vaddr = (unsigned long) __va(addr);
-
-	if(virtual)
-		panic("sparc_alloc_io: Fixed virtual mappings unsupported on Ultra.");
-
-	if(!check_region(vaddr, len))
-		request_region(vaddr, len, name);
-
-	return (void *) vaddr;
-}
-
-void sparc_free_io (void *virtual, int len)
-{
-	unsigned long vaddr = (unsigned long) virtual & PAGE_MASK;
-	unsigned long plen = (((unsigned long)virtual & ~PAGE_MASK) +
-			      len + PAGE_SIZE-1) & PAGE_MASK;
-	release_region(vaddr, plen);
-}
-
-/* Does DVMA allocations with PAGE_SIZE granularity.  How this basically
- * works is that the ESP chip can do DVMA transfers at ANY address with
- * certain size and boundary restrictions.  But other devices that are
- * attached to it and would like to do DVMA have to set things up in
- * a special way, if the DVMA sees a device attached to it transfer data
- * at addresses above DVMA_VADDR it will grab them, this way it does not
- * now have to know the peculiarities of where to read the Lance data
- * from. (for example)
- *
- * Returns CPU visible address for the buffer returned, dvma_addr is
- * set to the DVMA visible address.
- */
-void *sparc_dvma_malloc (int len, char *name, __u32 *dvma_addr)
-{
-	unsigned long vaddr, base_address;
-
-	vaddr = dvma_next_free;
-	if(check_region (vaddr, len)) {
-		prom_printf("alloc_dma: 0x%lx is already in use\n", vaddr);
-		prom_halt();
-	}
-	if(vaddr + len > (DVMA_VADDR + DVMA_LEN)) {
-		prom_printf("alloc_dvma: out of dvma memory\n");
-		prom_halt();
-	}
-
-	/* Basically these can be mapped just like any old
-	 * IO pages, cacheable bit off, etc.  The physical
-	 * pages are now mapped dynamically to save space.
-	 */
-	base_address = vaddr;
-	mmu_map_dma_area(base_address, len, dvma_addr);
-
-	/* Assign the memory area. */
-	dvma_next_free = PAGE_ALIGN(dvma_next_free+len);
-
-	request_region(base_address, len, name);
-
-	return (void *) base_address;
-}
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- v2.3.34/linux/arch/sparc64/kernel/irq.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/kernel/irq.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.78 1999/08/31 06:54:54 davem Exp $
+/* $Id: irq.c,v 1.80 1999/12/06 03:14:48 davem Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
@@ -106,89 +106,16 @@
 	return len;
 }
 
-/* SBUS SYSIO INO number to Sparc PIL level. */
-unsigned char sysio_ino_to_pil[] = {
-	0, 1, 2, 7, 5, 7, 8, 9,		/* SBUS slot 0 */
-	0, 1, 2, 7, 5, 7, 8, 9,		/* SBUS slot 1 */
-	0, 1, 2, 7, 5, 7, 8, 9,		/* SBUS slot 2 */
-	0, 1, 2, 7, 5, 7, 8, 9,		/* SBUS slot 3 */
-	3, /* Onboard SCSI */
-	5, /* Onboard Ethernet */
-/*XXX*/	8, /* Onboard BPP */
-	0, /* Bogon */
-       13, /* Audio */
-/*XXX*/15, /* PowerFail */
-	0, /* Bogon */
-	0, /* Bogon */
-       12, /* Zilog Serial Channels (incl. Keyboard/Mouse lines) */
-       11, /* Floppy */
-	0, /* Spare Hardware (bogon for now) */
-	0, /* Keyboard (bogon for now) */
-	0, /* Mouse (bogon for now) */
-	0, /* Serial (bogon for now) */
-     0, 0, /* Bogon, Bogon */
-       10, /* Timer 0 */
-       11, /* Timer 1 */
-     0, 0, /* Bogon, Bogon */
-       15, /* Uncorrectable SBUS Error */
-       15, /* Correctable SBUS Error */
-       15, /* SBUS Error */
-/*XXX*/ 0, /* Power Management (bogon for now) */
-};
-
-/* INO number to IMAP register offset for SYSIO external IRQ's.
- * This should conform to both Sunfire/Wildfire server and Fusion
- * desktop designs.
- */
-#define offset(x) ((unsigned long)(&(((struct sysio_regs *)0)->x)))
-#define bogon     ((unsigned long) -1)
-static unsigned long sysio_irq_offsets[] = {
-/* SBUS Slot 0 --> 3, level 1 --> 7 */
-offset(imap_slot0),offset(imap_slot0),offset(imap_slot0),offset(imap_slot0),
-offset(imap_slot0),offset(imap_slot0),offset(imap_slot0),offset(imap_slot0),
-offset(imap_slot1),offset(imap_slot1),offset(imap_slot1),offset(imap_slot1),
-offset(imap_slot1),offset(imap_slot1),offset(imap_slot1),offset(imap_slot1),
-offset(imap_slot2),offset(imap_slot2),offset(imap_slot2),offset(imap_slot2),
-offset(imap_slot2),offset(imap_slot2),offset(imap_slot2),offset(imap_slot2),
-offset(imap_slot3),offset(imap_slot3),offset(imap_slot3),offset(imap_slot3),
-offset(imap_slot3),offset(imap_slot3),offset(imap_slot3),offset(imap_slot3),
-/* Onboard devices (not relevant/used on SunFire). */
-offset(imap_scsi), offset(imap_eth), offset(imap_bpp), bogon,
-offset(imap_audio), offset(imap_pfail), bogon, bogon,
-offset(imap_kms), offset(imap_flpy), offset(imap_shw),
-offset(imap_kbd), offset(imap_ms), offset(imap_ser), bogon, bogon,
-offset(imap_tim0), offset(imap_tim1), bogon, bogon,
-offset(imap_ue), offset(imap_ce), offset(imap_sberr),
-offset(imap_pmgmt),
-};
-
-#undef bogon
-
-#define NUM_SYSIO_OFFSETS (sizeof(sysio_irq_offsets) / sizeof(sysio_irq_offsets[0]))
-
-/* Convert Interrupt Mapping register pointer to assosciated
- * Interrupt Clear register pointer, SYSIO specific version.
- */
-static volatile unsigned int *sysio_imap_to_iclr(volatile unsigned int *imap)
-{
-	unsigned long diff;
-
-	diff = offset(iclr_unused0) - offset(imap_slot0);
-	return (volatile unsigned int *) (((unsigned long)imap) + diff);
-}
-
-#undef offset
-
 /* 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);
-	volatile unsigned int *imap;
+	unsigned long imap;
 	unsigned long tid;
 
 	imap = bucket->imap;
-	if (!imap)
+	if (imap == 0UL)
 		return;
 
 	if(this_is_starfire == 0) {
@@ -198,7 +125,7 @@
 				     : "i" (ASI_UPA_CONFIG));
 		tid = ((tid & UPA_CONFIG_MID) << 9);
 	} else {
-		extern unsigned int starfire_translate(volatile unsigned int *imap,
+		extern unsigned int starfire_translate(unsigned long imap,
 						       unsigned int upaid);
 
 		tid = (starfire_translate(imap, current->processor) << 26);
@@ -208,27 +135,31 @@
 	 * of this SYSIO's preconfigured IGN in the SYSIO Control
 	 * Register, the hardware just mirrors that value here.
 	 * However for Graphics and UPA Slave devices the full
-	 * SYSIO_IMAP_INR field can be set by the programmer here.
+	 * IMAP_INR field can be set by the programmer here.
 	 *
 	 * Things like FFB can now be handled via the new IRQ mechanism.
 	 */
-	*imap = SYSIO_IMAP_VALID | (tid & SYSIO_IMAP_TID);
+	upa_writel(IMAP_VALID | (tid & IMAP_TID), imap);
 }
 
 /* This now gets passed true ino's as well. */
 void disable_irq(unsigned int irq)
 {
 	struct ino_bucket *bucket = __bucket(irq);
-	volatile unsigned int *imap;
+	unsigned long imap;
 
 	imap = bucket->imap;
-	if (imap != NULL) {
+	if (imap != 0UL) {
+		u32 tmp;
+
 		/* NOTE: We do not want to futz with the IRQ clear registers
 		 *       and move the state to IDLE, the SCSI code does call
 		 *       disable_irq() to assure atomicity in the queue cmd
 		 *       SCSI adapter driver code.  Thus we'd lose interrupts.
 		 */
-		*imap &= ~(SYSIO_IMAP_VALID);
+		tmp = upa_readl(imap);
+		tmp &= ~IMAP_VALID;
+		upa_writel(tmp, imap);
 	}
 }
 
@@ -243,18 +174,18 @@
 	0,	/* flags */
 	0,	/* __unused */
 	NULL,	/* irq_info */
-	NULL,	/* iclr */
-	NULL,	/* imap */
+	0UL,	/* iclr */
+	0UL,	/* imap */
 };
 
-unsigned int build_irq(int pil, int inofixup, volatile unsigned int *iclr, volatile unsigned int *imap)
+unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap)
 {
 	struct ino_bucket *bucket;
 	int ino;
 
 	if(pil == 0) {
-		if(iclr != NULL || imap != NULL) {
-			prom_printf("Invalid dummy bucket for PIL0 (%p:%p)\n",
+		if(iclr != 0UL || imap != 0UL) {
+			prom_printf("Invalid dummy bucket for PIL0 (%lx:%lx)\n",
 				    iclr, imap);
 			prom_halt();
 		}
@@ -262,13 +193,13 @@
 	}
 
 	/* RULE: Both must be specified in all other cases. */
-	if (iclr == NULL || imap == NULL) {
+	if (iclr == 0UL || imap == 0UL) {
 		prom_printf("Invalid build_irq %d %d %016lx %016lx\n",
 			    pil, inofixup, iclr, imap);
 		prom_halt();
 	}
 	
-	ino = (*imap & (SYSIO_IMAP_IGN | SYSIO_IMAP_INO)) + inofixup;
+	ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
 	if(ino > NUM_IVECS) {
 		prom_printf("Invalid INO %04x (%d:%d:%016lx:%016lx)\n",
 			    ino, pil, inofixup, iclr, imap);
@@ -300,64 +231,6 @@
 	return __irq(bucket);
 }
 
-unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
-{
-	struct linux_sbus *sbus = (struct linux_sbus *)buscookie;
-	struct sysio_regs *sregs = sbus->iommu->sysio_regs;
-	unsigned long offset;
-	int pil;
-	volatile unsigned int *imap, *iclr;
-	int sbus_level = 0;
-
-	pil = sysio_ino_to_pil[ino];
-	if(!pil) {
-		printk("sbus_irq_build: Bad SYSIO INO[%x]\n", ino);
-		panic("Bad SYSIO IRQ translations...");
-	}
-	offset = sysio_irq_offsets[ino];
-	if(offset == ((unsigned long)-1)) {
-		printk("get_irq_translations: Bad SYSIO INO[%x] cpu[%d]\n",
-			ino, pil);
-		panic("BAD SYSIO IRQ offset...");
-	}
-	offset += ((unsigned long)sregs);
-	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
-	 * bits.
-	 */
-	if(ino >= 0x20) {
-		iclr = sysio_imap_to_iclr(imap);
-	} else {
-		unsigned long iclraddr;
-		int sbus_slot = (ino & 0x18)>>3;
-		
-		sbus_level = ino & 0x7;
-
-		switch(sbus_slot) {
-		case 0:
-			iclr = &sregs->iclr_slot0;
-			break;
-		case 1:
-			iclr = &sregs->iclr_slot1;
-			break;
-		case 2:
-			iclr = &sregs->iclr_slot2;
-			break;
-		default:
-		case 3:
-			iclr = &sregs->iclr_slot3;
-			break;
-		};
-
-		iclraddr = (unsigned long) iclr;
-		iclraddr += ((sbus_level - 1) * 8);
-		iclr = (volatile unsigned int *) iclraddr;
-	}
-	return build_irq(pil, sbus_level, iclr, imap);
-}
-
 static void atomic_bucket_insert(struct ino_bucket *bucket)
 {
 	unsigned long pstate;
@@ -602,7 +475,7 @@
 		*(bucket->pil + irq_action) = action->next;
 
 	if(action->flags & SA_IMAP_MASKED) {
-		volatile unsigned int *imap = bucket->imap;
+		unsigned long imap = bucket->imap;
 		void **vector, *orig;
 		int ent;
 
@@ -696,10 +569,10 @@
 	int cpu = smp_processor_id();
 
 	printk("\n%s, CPU %d:\n", str, cpu);
-	printk("irq:  %d [%ld %ld]\n",
+	printk("irq:  %d [%u %u]\n",
 	       atomic_read(&global_irq_count),
 	       cpu_data[0].irq_count, cpu_data[1].irq_count);
-	printk("bh:   %d [%ld %ld]\n",
+	printk("bh:   %d [%u %u]\n",
 	       (spin_is_locked(&global_bh_count) ? 1 : 0),
 	       cpu_data[0].bh_count, cpu_data[1].bh_count);
 }
@@ -947,10 +820,10 @@
 				if (should_forward != 0) {
 					/* Push it to our buddy. */
 					should_forward = 0;
-					*(bp->imap) = (buddy | SYSIO_IMAP_VALID);
+					upa_writel(buddy | IMAP_VALID, bp->imap);
 				}
 #endif
-				*(bp->iclr) = SYSIO_ICLR_IDLE;
+				upa_writel(ICLR_IDLE, bp->iclr);
 			}
 		} else
 			bp->pending = 1;
@@ -974,7 +847,7 @@
 	bucket = (struct ino_bucket *)action->mask;
 
 	floppy_interrupt(irq, dev_cookie, regs);
-	*(bucket->iclr) = SYSIO_ICLR_IDLE;
+	upa_writel(ICLR_IDLE, bucket->iclr);
 
 	irq_exit(cpu, irq);
 }
@@ -1116,7 +989,7 @@
 #endif
 
 	/* Register IRQ handler. */
-	err = request_irq(build_irq(0, 0, NULL, NULL), cfunc, (SA_INTERRUPT | SA_STATIC_ALLOC),
+	err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, (SA_INTERRUPT | SA_STATIC_ALLOC),
 			  "timer", NULL);
 
 	if(err) {
@@ -1157,7 +1030,7 @@
 {
 	extern int this_is_starfire;
 	struct ino_bucket *bucket = __bucket(p->mask);
-	volatile unsigned int *imap = bucket->imap;
+	unsigned long imap = bucket->imap;
 	unsigned int tid;
 
 	/* Never change this, it causes problems on Ex000 systems. */
@@ -1167,12 +1040,12 @@
 	if(this_is_starfire == 0) {
 		tid = __cpu_logical_map[goal_cpu] << 26;
 	} else {
-		extern unsigned int starfire_translate(volatile unsigned int *imap,
+		extern unsigned int starfire_translate(unsigned long imap,
 						       unsigned int upaid);
 
 		tid = (starfire_translate(imap, __cpu_logical_map[goal_cpu]) << 26);
 	}
-	*imap = SYSIO_IMAP_VALID | (tid & SYSIO_IMAP_TID);
+	upa_writel(IMAP_VALID | (tid & IMAP_TID), imap);
 
 	goal_cpu++;
 	if(goal_cpu >= NR_CPUS ||
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c
--- v2.3.34/linux/arch/sparc64/kernel/pci.c	Sat Oct  9 11:47:50 1999
+++ linux/arch/sparc64/kernel/pci.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.6 1999/09/08 03:40:41 davem Exp $
+/* $Id: pci.c,v 1.11 1999/12/20 05:02:07 davem Exp $
  * pci.c: UltraSparc PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -20,8 +20,11 @@
 #include <asm/irq.h>
 #include <asm/ebus.h>
 
+#ifndef NEW_PCI_DMA_MAP
 unsigned long pci_dvma_v2p_hash[PCI_DVMA_HASHSZ];
 unsigned long pci_dvma_p2v_hash[PCI_DVMA_HASHSZ];
+#endif
+
 unsigned long pci_memspace_mask = 0xffffffffUL;
 
 #ifndef CONFIG_PCI
@@ -199,6 +202,30 @@
 };
 
 void pcibios_fixup_bus(struct pci_bus *pbus)
+{
+}
+
+void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1,
+			     struct resource *res2, int index)
+{
+}
+
+void pcibios_update_irq(struct pci_dev *pdev, int irq)
+{
+}
+
+unsigned long resource_fixup(struct pci_dev *pdev, struct resource *res,
+			     unsigned long start, unsigned long size)
+{
+	return start;
+}
+
+void pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
+			       struct pbus_set_ranges_data *pranges)
+{
+}
+
+void pcibios_align_resource(void *data, struct resource *res, unsigned long size)
 {
 }
 
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/pci_common.c linux/arch/sparc64/kernel/pci_common.c
--- v2.3.34/linux/arch/sparc64/kernel/pci_common.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/kernel/pci_common.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: pci_common.c,v 1.3 1999/09/04 22:26:32 ecd Exp $
+/* $Id: pci_common.c,v 1.5 1999/12/20 05:02:11 davem Exp $
  * pci_common.c: PCI controller common support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -362,7 +362,7 @@
 
 		size = res->end - res->start;
 		align = size + 1;
-		if (allocate_resource(root, res, size + 1, min, max, align) < 0) {
+		if (allocate_resource(root, res, size + 1, min, max, align, NULL, NULL) < 0) {
 			/* uh oh */
 			prom_printf("PCI: Failed to allocate resource %d for %s\n",
 				    i, pdev->name);
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/pci_impl.h linux/arch/sparc64/kernel/pci_impl.h
--- v2.3.34/linux/arch/sparc64/kernel/pci_impl.h	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/kernel/pci_impl.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: pci_impl.h,v 1.3 1999/09/10 10:40:44 davem Exp $
+/* $Id: pci_impl.h,v 1.4 1999/12/17 12:32:03 jj Exp $
  * pci_impl.h: Helper definitions for PCI controller support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -34,6 +34,7 @@
 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 *);
 
+#ifndef NEW_PCI_DMA_MAP
 /* IOMMU/DVMA initialization. */
 #define PCI_DVMA_HASH_NONE	~0UL
 static __inline__ void set_dvma_hash(unsigned long dvma_offset,
@@ -46,6 +47,7 @@
 	pci_dvma_v2p_hash[pci_dvma_ahashfn(paddr)] = dvma_addr - vaddr;
 	pci_dvma_p2v_hash[pci_dvma_ahashfn(dvma_addr)] = vaddr - dvma_addr;
 }
+#endif
 
 /* Configuration space access. */
 extern spinlock_t pci_poke_lock;
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/pci_iommu.c linux/arch/sparc64/kernel/pci_iommu.c
--- v2.3.34/linux/arch/sparc64/kernel/pci_iommu.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/kernel/pci_iommu.c	Mon Dec 20 22:05:52 1999
@@ -1,12 +1,17 @@
-/* $Id: pci_iommu.c,v 1.1 1999/08/30 10:00:47 davem Exp $
+/* $Id: pci_iommu.c,v 1.7 1999/12/20 14:08:15 jj Exp $
  * pci_iommu.c: UltraSparc PCI controller IOM/STC support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
  */
 
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
 #include <asm/pbm.h>
-#include <asm/iommu.h>
-#include <asm/scatterlist.h>
+
+#include "iommu_common.h"
 
 #define PCI_STC_CTXMATCH_ADDR(STC, CTX)	\
 	((STC)->strbuf_ctxmatch_base + ((CTX) << 3))
@@ -29,27 +34,67 @@
 			     : "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)
+static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages)
 {
-	int i;
+	iopte_t *iopte;
+	unsigned long cnum, ent;
 
-	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;
-				}
+	cnum = 0;
+	while ((1UL << cnum) < npages)
+		cnum++;
+	iopte  = iommu->page_table + (cnum << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS));
+	iopte += ((ent = iommu->lowest_free[cnum]) << cnum);
+
+	if (iopte_val(iopte[(1UL << cnum)]) == 0UL) {
+		/* Fast path. */
+		iommu->lowest_free[cnum] = ent + 1;
+	} else {
+		unsigned long pte_off = 1;
+
+		ent += 1;
+		do {
+			pte_off++;
+			ent++;
+		} while (iopte_val(iopte[(pte_off << cnum)]) != 0UL);
+		iommu->lowest_free[cnum] = ent;
+	}
+
+	/* I've got your streaming cluster right here buddy boy... */
+	return iopte;
+}
+
+static inline void free_streaming_cluster(struct pci_iommu *iommu, u32 base, unsigned long npages)
+{
+	unsigned long cnum, ent;
+
+	cnum = 0;
+	while ((1UL << cnum) < npages)
+		cnum++;
+	ent = (base << (32 - PAGE_SHIFT + PBM_LOGCLUSTERS - iommu->page_table_sz_bits))
+		>> (32 + PBM_LOGCLUSTERS + cnum - iommu->page_table_sz_bits);
+	if (ent < iommu->lowest_free[cnum])
+		iommu->lowest_free[cnum] = ent;
+}
+
+/* We allocate consistant mappings from the end of cluster zero. */
+static iopte_t *alloc_consistant_cluster(struct pci_iommu *iommu, unsigned long npages)
+{
+	iopte_t *iopte;
+
+	iopte = iommu->page_table + (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS));
+	while (iopte > iommu->page_table) {
+		iopte--;
+		if (!(iopte_val(*iopte) & IOPTE_VALID)) {
+			unsigned long tmp = npages;
+
+			while (--tmp) {
+				iopte--;
+				if (iopte_val(*iopte) & IOPTE_VALID)
+					break;
 			}
-			return &pgt[i];
+			if (tmp == 0)
+				return iopte;
 		}
-	do_next:
 	}
 	return NULL;
 }
@@ -64,123 +109,168 @@
 
 #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.
+/* Allocate and map kernel buffer of size SIZE using consistant mode
+ * DMA for PCI device PDEV.  Return non-NULL cpu-side address if
+ * successful and set *DMA_ADDRP to the PCI side dma address.
  */
-u32 pci_map_consistant(struct pci_dev *pdev, void *addr, int sz)
+void *pci_alloc_consistant(struct pci_dev *pdev, long size, u32 *dma_addrp)
 {
-	struct pcidev_cookie *pcp = pdev->sysdata;
-	struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
-	iopte_t *base;
-	unsigned long flags, npages, oaddr;
-	u32 ret;
+	struct pcidev_cookie *pcp;
+	struct pci_iommu *iommu;
+	iopte_t *iopte;
+	unsigned long flags, order, first_page, ctx;
+	void *ret;
+	int npages;
+
+	if (size <= 0 || pdev == NULL ||
+	    pdev->sysdata == NULL || dma_addrp == NULL)
+		return NULL;
+
+	size = PAGE_ALIGN(size);
+	for (order = 0; order < 10; order++) {
+		if ((PAGE_SIZE << order) >= size)
+			break;
+	}
+	if (order == 10)
+		return NULL;
+
+	first_page = __get_free_pages(GFP_ATOMIC, order);
+	if (first_page == 0UL)
+		return NULL;
+	memset((char *)first_page, 0, PAGE_SIZE << order);
+
+	pcp = pdev->sysdata;
+	iommu = &pcp->pbm->parent->iommu;
 
 	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);
+	iopte = alloc_consistant_cluster(iommu, size >> PAGE_SHIFT);
+	if (iopte == NULL) {
+		spin_unlock_irqrestore(&iommu->lock, flags);
+		free_pages(first_page, order);
+		return NULL;
 	}
+
+	*dma_addrp = (iommu->page_table_map_base +
+		      ((iopte - iommu->page_table) << PAGE_SHIFT));
+	ret = (void *) first_page;
+	npages = size >> PAGE_SHIFT;
+	ctx = 0;
+	if (iommu->iommu_ctxflush)
+		ctx = iommu->iommu_cur_ctx++;
+	first_page = __pa(first_page);
+	while (npages--) {
+		iopte_val(*iopte) = IOPTE_CONSISTANT(ctx, first_page);
+		iopte++;
+		first_page += PAGE_SIZE;
+	}
+
+	if (iommu->iommu_ctxflush) {
+		pci_iommu_write(iommu->iommu_ctxflush, ctx);
+	} else {
+		int i;
+		u32 daddr = *dma_addrp;
+
+		npages = size >> PAGE_SHIFT;
+		for (i = 0; i < npages; i++) {
+			pci_iommu_write(iommu->iommu_flush, daddr);
+			daddr += PAGE_SIZE;
+		}
+	}
+
 	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)
+/* Free and unmap a consistant DMA translation. */
+void pci_free_consistant(struct pci_dev *pdev, long size, void *cpu, u32 dvma)
 {
-	struct pcidev_cookie *pcp = pdev->sysdata;
-	struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
-	iopte_t *base;
-	unsigned long flags, npages, i, ctx;
+	struct pcidev_cookie *pcp;
+	struct pci_iommu *iommu;
+	iopte_t *iopte;
+	unsigned long flags, order, npages, i;
+
+	if (size <= 0 || pdev == NULL ||
+	    pdev->sysdata == NULL || cpu == NULL)
+		return;
+
+	npages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+	pcp = pdev->sysdata;
+	iommu = &pcp->pbm->parent->iommu;
+	iopte = iommu->page_table +
+		((dvma - iommu->page_table_map_base) >> PAGE_SHIFT);
 
 	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.
+	 * buffers, so we only need to update the TSB.  Flush of the
+	 * IOTLB is done later when these ioptes are used for a new
+	 * allocation.
 	 */
 
-	/* 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);
+	for (i = 0; i < npages; i++, iopte++)
+		iopte_val(*iopte) = IOPTE_INVALID;
 
 	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	for (order = 0; order < 10; order++) {
+		if ((PAGE_SIZE << order) >= size)
+			break;
+	}
+	if (order < 10)
+		free_pages((unsigned long)cpu, order);
 }
 
 /* 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)
+u32 pci_map_single(struct pci_dev *pdev, void *ptr, long 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, oaddr;
-	u32 ret;
+	unsigned long i, base_paddr, ctx;
+	u32 bus_addr, 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++;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+
+	base = alloc_streaming_cluster(iommu, npages);
+	bus_addr = (iommu->page_table_map_base +
+		    ((base - iommu->page_table) << PAGE_SHIFT));
+	ret = bus_addr | (oaddr & ~PAGE_MASK);
+	base_paddr = __pa(oaddr & PAGE_MASK);
+	ctx = 0;
+	if (iommu->iommu_ctxflush)
+		ctx = iommu->iommu_cur_ctx++;
+	if (strbuf->strbuf_enabled) {
 		for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE)
 			iopte_val(*base) = IOPTE_STREAMING(ctx, base_paddr);
+	} else {
+		for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE)
+			iopte_val(*base) = IOPTE_CONSISTANT(ctx, base_paddr);
+	}
+
+	/* Flush the IOMMU TLB. */
+	if (iommu->iommu_ctxflush) {
+		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);
 	}
+
 	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)
+void pci_unmap_single(struct pci_dev *pdev, u32 bus_addr, long sz)
 {
 	struct pcidev_cookie *pcp = pdev->sysdata;
 	struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
@@ -188,25 +278,26 @@
 	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;
+	spin_lock_irqsave(&iommu->lock, flags);
 
-	/* Step 2: Kick data out of streaming buffers if necessary. */
+	/* Step 1: Kick data out of streaming buffers if necessary. */
 	if (strbuf->strbuf_enabled) {
 		u32 vaddr = bus_addr;
 
+		/* Record the context, if any. */
+		ctx = 0;
+		if (iommu->iommu_ctxflush)
+			ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+
 		PCI_STC_FLUSHFLAG_INIT(strbuf);
-		if (strbuf->strbuf_has_ctx_flush &&
-		    iommu->iommu_has_ctx_flush) {
+		if (strbuf->strbuf_ctxflush &&
+		    iommu->iommu_ctxflush) {
 			unsigned long matchreg, flushreg;
 
 			flushreg = strbuf->strbuf_ctxflush;
@@ -225,69 +316,159 @@
 			membar("#LoadLoad");
 	}
 
-	/* Step 3: Clear out TSB entries. */
-	for (i = 0; i < npages; i++, base++)
-		iopte_val(*base) = IOPTE_INVALID;
+	/* Step 2: Clear out first TSB entry. */
+	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);
-	}
+	free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages);
 
-	/* Step 5: Ensure completion of previous PIO writes. */
+	/* Step 3: Ensure completion of previous PIO writes. */
 	(void) pci_iommu_read(iommu->write_complete_reg);
 
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
+static inline struct scatterlist *fill_sg(iopte_t *iopte, struct scatterlist *sg, int nents, unsigned long ctx, int streaming)
+{
+	struct scatterlist *dma_sg = sg;
+
+	do {
+		unsigned long pteval = ~0UL;
+		u32 dma_npages;
+
+		dma_npages = ((dma_sg->dvma_address & (PAGE_SIZE - 1UL)) +
+			      dma_sg->dvma_length +
+			      ((u32)(PAGE_SIZE - 1UL))) >> PAGE_SHIFT;
+		do {
+			unsigned long offset;
+			signed int len;
+
+			/* If we are here, we know we have at least one
+			 * more page to map.  So walk forward until we
+			 * hit a page crossing, and begin creating new
+			 * mappings from that spot.
+			 */
+			for (;;) {
+				unsigned long tmp;
+
+				tmp = (unsigned long) __pa(sg->address);
+				len = sg->length;
+				if (((tmp ^ pteval) >> PAGE_SHIFT) != 0UL) {
+					pteval = tmp & PAGE_MASK;
+					offset = tmp & (PAGE_SIZE - 1UL);
+					break;
+				}
+				if (((tmp ^ (tmp + len - 1UL)) >> PAGE_SHIFT) != 0UL) {
+					pteval = (tmp + PAGE_SIZE) & PAGE_MASK;
+					offset = 0UL;
+					len -= (PAGE_SIZE - (tmp & (PAGE_SIZE - 1UL)));
+					break;
+				}
+				sg++;
+			}
+
+			if (streaming)
+				pteval = IOPTE_STREAMING(ctx, pteval);
+			else
+				pteval = IOPTE_CONSISTANT(ctx, pteval);
+			while (len > 0) {
+				*iopte++ = __iopte(pteval);
+				pteval += PAGE_SIZE;
+				len -= (PAGE_SIZE - offset);
+				offset = 0;
+				dma_npages--;
+			}
+
+			pteval = (pteval & IOPTE_PAGE) + len;
+			sg++;
+
+			/* Skip over any tail mappings we've fully mapped,
+			 * adjusting pteval along the way.  Stop when we
+			 * detect a page crossing event.
+			 */
+			while ((pteval << (64 - PAGE_SHIFT)) != 0UL &&
+			       pteval == __pa(sg->address) &&
+			       ((pteval ^
+				 (__pa(sg->address) + sg->length - 1UL)) >> PAGE_SHIFT) == 0UL) {
+				pteval += sg->length;
+				sg++;
+			}
+			if ((pteval << (64 - PAGE_SHIFT)) == 0UL)
+				pteval = ~0UL;
+		} while (dma_npages != 0);
+		dma_sg++;
+	} while (dma_sg->dvma_length != 0);
+	return dma_sg;
+}
+
 /* Map a set of buffers described by SGLIST with NELEMS array
  * elements in streaming mode for PCI DMA.
+ * When making changes here, inspect the assembly output. I was having
+ * hard time to kepp this routine out of using stack slots for holding variables.
  */
-void pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems)
+int 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;
+	struct pcidev_cookie *pcp;
+	struct pci_iommu *iommu;
+	struct pci_strbuf *strbuf;
+	unsigned long flags, ctx, i, npages;
+	iopte_t *base;
+	u32 dma_base;
+	struct scatterlist *sgtmp;
+	int tmp;
+
+	/* Fast path single entry scatterlists. */
+	if (nelems == 1) {
+		sglist->dvma_address = pci_map_single(pdev, sglist->address, sglist->length);
+		sglist->dvma_length = sglist->length;
+		return 1;
+	}
+                                                                        
+	pcp = pdev->sysdata;
+	iommu = &pcp->pbm->parent->iommu;
+	strbuf = &pcp->pbm->stc;
+	
+	/* Step 1: Prepare scatter list. */
+
+	npages = prepare_sg(sglist, nelems);
+
+	/* Step 2: Allocate a cluster. */
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
-	/* Step 1: Choose a context if necessary. */
+	base = alloc_streaming_cluster(iommu, npages);
+	dma_base = iommu->page_table_map_base + ((base - iommu->page_table) << PAGE_SHIFT);
+
+	/* Step 3: Normalize DMA addresses. */
+	tmp = nelems;
+
+	sgtmp = sglist;
+	while (tmp-- && sgtmp->dvma_length) {
+		sgtmp->dvma_address += dma_base;
+		sgtmp++;
+	}
+
+	/* Step 4: Choose a context if necessary. */
 	ctx = 0;
-	if (iommu->iommu_has_ctx_flush)
+	if (iommu->iommu_ctxflush)
 		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;
-		}
+	/* Step 5: Create the mappings. */
+	sgtmp = fill_sg (base, sglist, nelems, ctx, strbuf->strbuf_enabled);
+#ifdef VERIFY_SG
+	verify_sglist(sglist, nelems, base, npages);
+#endif
+
+	/* Step 6: Flush the IOMMU TLB. */
+	if (iommu->iommu_ctxflush) {
+		pci_iommu_write(iommu->iommu_ctxflush, ctx);
+	} else {
+		for (i = 0; i < npages; i++, dma_base += PAGE_SIZE)
+			pci_iommu_write(iommu->iommu_flush, dma_base);
 	}
 
 	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	return sgtmp - sglist;
 }
 
 /* Unmap a set of streaming mode DMA translations. */
@@ -296,25 +477,38 @@
 	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;
+	iopte_t *base;
+	unsigned long flags, ctx, i, npages;
+	u32 bus_addr;
+	
+	bus_addr = sglist->dvma_address & PAGE_MASK;
+
+	i = 0;
+	if (nelems > 1) {
+		for (; i < nelems; i++)
+			if (sglist[i].dvma_length == 0)
+				break;
+		i--;
+	}
+	npages = (PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> PAGE_SHIFT;
+
+	base = iommu->page_table +
+		((bus_addr - iommu->page_table_map_base) >> PAGE_SHIFT);
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
-	/* Step 1: Record the context, if any. */
-	ctx = 0;
-	if (iommu->iommu_has_ctx_flush) {
-		iopte_t *iopte;
+	/* Step 1: Kick data out of streaming buffers if necessary. */
+	if (strbuf->strbuf_enabled) {
+		u32 vaddr = bus_addr;
 
-		iopte = iommu->page_table +
-			((sglist[0].dvma_address - iommu->page_table_map_base) >> PAGE_SHIFT);
-		ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
-	}
+		/* Record the context, if any. */
+		ctx = 0;
+		if (iommu->iommu_ctxflush)
+			ctx = (iopte_val(*base) & 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) {
+		if (strbuf->strbuf_ctxflush &&
+		    iommu->iommu_ctxflush) {
 			unsigned long matchreg, flushreg;
 
 			flushreg = strbuf->strbuf_ctxflush;
@@ -323,66 +517,22 @@
 				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");
+			for (i = 0; i < npages; i++, vaddr += PAGE_SIZE)
+				pci_iommu_write(strbuf->strbuf_pflush, vaddr);
 		}
-	}
-
-	/* 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;
+		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 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;
+	/* Step 2: Clear out first TSB entry. */
+	iopte_val(*base) = IOPTE_INVALID;
 
-			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);
-		}
-	}
+	free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages);
 
-	/* Step 5: Ensure completion of previous PIO writes. */
+	/* Step 3: Ensure completion of previous PIO writes. */
 	(void) pci_iommu_read(iommu->write_complete_reg);
 
 	spin_unlock_irqrestore(&iommu->lock, flags);
@@ -391,7 +541,7 @@
 /* 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)
+void pci_dma_sync_single(struct pci_dev *pdev, u32 bus_addr, long sz)
 {
 	struct pcidev_cookie *pcp = pdev->sysdata;
 	struct pci_iommu *iommu = &pcp->pbm->parent->iommu;
@@ -409,8 +559,8 @@
 
 	/* Step 1: Record the context, if any. */
 	ctx = 0;
-	if (iommu->iommu_has_ctx_flush &&
-	    strbuf->strbuf_has_ctx_flush) {
+	if (iommu->iommu_ctxflush &&
+	    strbuf->strbuf_ctxflush) {
 		iopte_t *iopte;
 
 		iopte = iommu->page_table +
@@ -420,8 +570,8 @@
 
 	/* Step 2: Kick data out of streaming buffers. */
 	PCI_STC_FLUSHFLAG_INIT(strbuf);
-	if (iommu->iommu_has_ctx_flush &&
-	    strbuf->strbuf_has_ctx_flush) {
+	if (iommu->iommu_ctxflush &&
+	    strbuf->strbuf_ctxflush) {
 		unsigned long matchreg, flushreg;
 
 		flushreg = strbuf->strbuf_ctxflush;
@@ -462,8 +612,8 @@
 
 	/* Step 1: Record the context, if any. */
 	ctx = 0;
-	if (iommu->iommu_has_ctx_flush &&
-	    strbuf->strbuf_has_ctx_flush) {
+	if (iommu->iommu_ctxflush &&
+	    strbuf->strbuf_ctxflush) {
 		iopte_t *iopte;
 
 		iopte = iommu->page_table +
@@ -473,8 +623,8 @@
 
 	/* Step 2: Kick data out of streaming buffers. */
 	PCI_STC_FLUSHFLAG_INIT(strbuf);
-	if (iommu->iommu_has_ctx_flush &&
-	    strbuf->strbuf_has_ctx_flush) {
+	if (iommu->iommu_ctxflush &&
+	    strbuf->strbuf_ctxflush) {
 		unsigned long matchreg, flushreg;
 
 		flushreg = strbuf->strbuf_ctxflush;
@@ -483,21 +633,21 @@
 			pci_iommu_write(flushreg, ctx);
 		} while (((long)pci_iommu_read(matchreg)) < 0L);
 	} else {
-		unsigned long i;
+		unsigned long i, npages;
+		u32 bus_addr;
 
-		for(i = 0; i < nelems; i++) {
-			unsigned long bus_addr, npages, j;
+		i = 0;
+		bus_addr = sglist[0].dvma_address & PAGE_MASK;
 
-			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);
+		if (nelems > 1) {
+			for(; i < nelems; i++)
+				if (!sglist[i].dvma_length)
+					break;
+			i--;
 		}
+		npages = (PAGE_ALIGN(sglist[i].dvma_address + sglist[i].dvma_length) - bus_addr) >> PAGE_SHIFT;
+		for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE)
+			pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
 	}
 
 	/* Step 3: Perform flush synchronization sequence. */
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c
--- v2.3.34/linux/arch/sparc64/kernel/pci_psycho.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/kernel/pci_psycho.c	Mon Dec 20 22:05:52 1999
@@ -1,9 +1,9 @@
-/* $Id: pci_psycho.c,v 1.4 1999/09/05 09:33:36 ecd Exp $
+/* $Id: pci_psycho.c,v 1.7 1999/12/17 12:31:57 jj 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)
+ * Copyright (C) 1999 Jakub Jelinek   (jakub@redhat.com)
  */
 
 #include <linux/kernel.h>
@@ -380,7 +380,7 @@
 					    unsigned int ino)
 {
 	struct ino_bucket *bucket;
-	volatile unsigned int *imap, *iclr;
+	unsigned long imap, iclr;
 	unsigned long imap_off, iclr_off;
 	int pil, inofixup = 0;
 
@@ -399,12 +399,12 @@
 
 	/* Now build the IRQ bucket. */
 	pil = psycho_ino_to_pil(pdev, ino);
-	imap = (volatile unsigned int *)__va(p->controller_regs + imap_off);
-	imap += 1;
+	imap = p->controller_regs + imap_off;
+	imap += 4;
 
 	iclr_off = psycho_iclr_offset(ino);
-	iclr = (volatile unsigned int *)__va(p->controller_regs + iclr_off);
-	iclr += 1;
+	iclr = p->controller_regs + iclr_off;
+	iclr += 4;
 
 	if ((ino & 0x20) == 0)
 		inofixup = ino & 0x03;
@@ -838,6 +838,10 @@
 		  "DMA Read" :
 		  ((error_bits & PSYCHO_CEAFSR_PDWR) ?
 		   "DMA Write" : "???")))));
+
+	/* XXX Use syndrome and afar to print out module string just like
+	 * XXX UDB CE trap handler does... -DaveM
+	 */
 	printk("PSYCHO%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] "
 	       "UPA_MID[%02lx] was_block(%d)\n",
 	       p->index,
@@ -1213,26 +1217,28 @@
 	psycho_register_error_handlers(p);
 }
 
-static void __init psycho_iommu_init(struct pci_controller_info *p, int tsbsize)
+static void __init psycho_iommu_init(struct pci_controller_info *p)
 {
-	extern int this_is_starfire;
-	extern void *starfire_hookup(int);
+#ifndef NEW_PCI_DMA_MAP
 	struct linux_mlist_p1275 *mlist;
-	unsigned long tsbbase, i, n, order;
+	unsigned long n;
 	iopte_t *iopte;
+	int tsbsize = 32;
+#endif
+	extern int this_is_starfire;
+	extern void *starfire_hookup(int);
+	unsigned long tsbbase, i;
 	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;
+	/* PSYCHO's IOMMU lacks ctx flushing. */
 	p->iommu.iommu_ctxflush = 0;
 
 	/* We use the main control register of PSYCHO as the write
@@ -1252,18 +1258,29 @@
 	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);
+#ifndef NEW_PCI_DMA_MAP
+	/* Using assumed page size 64K with 32K entries we need 256KB iommu page
+	 * table (32K ioptes * 8 bytes per iopte).  This is
+	 * page order 5 on UltraSparc.
+	 */
+	tsbbase = __get_free_pages(GFP_KERNEL, 5);
+#else
+	/* Using assumed page size 8K with 128K entries we need 1MB iommu page
+	 * table (128K ioptes * 8 bytes per iopte).  This is
+	 * page order 7 on UltraSparc.
+	 */
+	tsbbase = __get_free_pages(GFP_KERNEL, 7);
+#endif	
 	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);
+	p->iommu.page_table = (iopte_t *)tsbbase;
+	p->iommu.page_table_sz_bits = 17;
+	p->iommu.page_table_map_base = 0xc0000000;
 
+#ifndef NEW_PCI_DMA_MAP
+	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;
@@ -1329,10 +1346,11 @@
 		prom_printf("Try booting with mem=xxxM or similar\n");
 		prom_halt();
 	}
-
+#endif
 	psycho_write(p->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase));
 
 	control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL);
+#ifndef NEW_PCI_DMA_MAP
 	control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ);
 	control |= (PSYCHO_IOMMU_CTRL_TBWSZ | PSYCHO_IOMMU_CTRL_ENAB);
 	switch(tsbsize) {
@@ -1353,6 +1371,10 @@
 		prom_halt();
 		break;
 	}
+#else
+	control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ);
+	control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB);
+#endif
 	psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
 
 	/* If necessary, hook us up for starfire IRQ translations. */
@@ -1426,9 +1448,6 @@
 	/* 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;
@@ -1438,6 +1457,7 @@
 		pbm->stc.strbuf_pflush   = base + PSYCHO_STRBUF_FLUSH_B;
 		pbm->stc.strbuf_fsync    = base + PSYCHO_STRBUF_FSYNC_B;
 	}
+	/* PSYCHO's streaming buffer lacks ctx flushing. */
 	pbm->stc.strbuf_ctxflush      = 0;
 	pbm->stc.strbuf_ctxmatch_base = 0;
 
@@ -1599,7 +1619,7 @@
 
 	psycho_controller_hwinit(p);
 
-	psycho_iommu_init(p, 32);
+	psycho_iommu_init(p);
 
 	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.34/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c
--- v2.3.34/linux/arch/sparc64/kernel/pci_sabre.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/kernel/pci_sabre.c	Mon Dec 20 22:05:52 1999
@@ -1,9 +1,9 @@
-/* $Id: pci_sabre.c,v 1.2 1999/09/05 04:58:06 davem Exp $
+/* $Id: pci_sabre.c,v 1.7 1999/12/19 09:17:51 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)
+ * Copyright (C) 1999 Jakub Jelinek   (jakub@redhat.com)
  */
 
 #include <linux/kernel.h>
@@ -65,6 +65,14 @@
 #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_IOMMU_TSBSZ_1K   0x0000000000000000
+#define  SABRE_IOMMU_TSBSZ_2K   0x0000000000010000
+#define  SABRE_IOMMU_TSBSZ_4K   0x0000000000020000
+#define  SABRE_IOMMU_TSBSZ_8K   0x0000000000030000
+#define  SABRE_IOMMU_TSBSZ_16K  0x0000000000040000
+#define  SABRE_IOMMU_TSBSZ_32K  0x0000000000050000
+#define  SABRE_IOMMU_TSBSZ_64K  0x0000000000060000
+#define  SABRE_IOMMU_TSBSZ_128K 0x0000000000070000
 #define  SABRE_IOMMUCTRL_TBWSZ	 0x0000000000000004UL	/* TSB assumed page size */
 #define  SABRE_IOMMUCTRL_DENAB	 0x0000000000000002UL	/* Diagnostic Mode Enable */
 #define  SABRE_IOMMUCTRL_ENAB	 0x0000000000000001UL	/* IOMMU Enable */
@@ -601,7 +609,7 @@
 					   unsigned int ino)
 {
 	struct ino_bucket *bucket;
-	volatile unsigned int *imap, *iclr;
+	unsigned long imap, iclr;
 	unsigned long imap_off, iclr_off;
 	int pil, inofixup = 0;
 
@@ -620,12 +628,12 @@
 
 	/* Now build the IRQ bucket. */
 	pil = sabre_ino_to_pil(pdev, ino);
-	imap = (volatile unsigned int *)__va(p->controller_regs + imap_off);
-	imap += 1;
+	imap = p->controller_regs + imap_off;
+	imap += 4;
 
 	iclr_off = sabre_iclr_offset(ino);
-	iclr = (volatile unsigned int *)__va(p->controller_regs + iclr_off);
-	iclr += 1;
+	iclr = p->controller_regs + iclr_off;
+	iclr += 4;
 
 	if ((ino & 0x20) == 0)
 		inofixup = ino & 0x03;
@@ -717,13 +725,13 @@
 				type_string = "Unknown";
 				break;
 			};
-			printk("SABRE%d: IOMMU TAG(%d)[error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n",
-			       p->index, i, type_string,
+			printk("SABRE%d: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n",
+			       p->index, i, tag, 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,
+			printk("SABRE%d: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n",
+			       p->index, i, data,
 			       ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0),
 			       ((data & SABRE_IOMMUDATA_USED) ? 1 : 0),
 			       ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0),
@@ -814,6 +822,10 @@
 		"DMA Read" :
 		((error_bits & SABRE_CEAFSR_PDWR) ?
 		 "DMA Write" : "???")));
+
+	/* XXX Use syndrome and afar to print out module string just like
+	 * XXX UDB CE trap handler does... -DaveM
+	 */
 	printk("SABRE%d: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] "
 	       "was_block(%d)\n",
 	       p->index,
@@ -1021,17 +1033,8 @@
 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) {
@@ -1044,32 +1047,6 @@
 			/* 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);
 		}
 	}
 }
@@ -1124,30 +1101,49 @@
 static void __init sabre_iommu_init(struct pci_controller_info *p,
 				    int tsbsize, unsigned long dvma_offset)
 {
+#ifndef NEW_PCI_DMA_MAP
 	struct linux_mlist_p1275 *mlist;
-	unsigned long tsbbase, i, n, order;
+	unsigned long n;
 	iopte_t *iopte;
+#endif
+	unsigned long tsbbase, i, order;
 	u64 control;
 
+	/* Setup initial software IOMMU state. */
+	spin_lock_init(&p->iommu.lock);
+	p->iommu.iommu_cur_ctx = 0;
+
+	/* Register addresses. */
+	p->iommu.iommu_control  = p->controller_regs + SABRE_IOMMU_CONTROL;
+	p->iommu.iommu_tsbbase  = p->controller_regs + SABRE_IOMMU_TSBBASE;
+	p->iommu.iommu_flush    = p->controller_regs + SABRE_IOMMU_FLUSH;
+	p->iommu.write_complete_reg = p->controller_regs + SABRE_WRSYNC;
+	/* Sabre's IOMMU lacks ctx flushing. */
+	p->iommu.iommu_ctxflush = 0;
+                                        
 	/* Invalidate TLB Entries. */
 	control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);
-	control |= IOMMU_CTRL_DENAB;
+	control |= SABRE_IOMMUCTRL_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);
+	control &= ~(SABRE_IOMMUCTRL_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);
+	tsbbase = __get_free_pages(GFP_KERNEL, order);
 	if (!tsbbase) {
 		prom_printf("SABRE_IOMMU: Error, gfp(tsb) failed.\n");
 		prom_halt();
 	}
+	p->iommu.page_table = (iopte_t *)tsbbase;
+	p->iommu.page_table_map_base = dvma_offset;
+
+#ifndef NEW_PCI_DMA_MAP
 	iopte = (iopte_t *)tsbbase;
 
 	/* Initialize to "none" settings. */
@@ -1216,27 +1212,47 @@
 		prom_printf("Try booting with mem=xxxM or similar\n");
 		prom_halt();
 	}
+#endif
 
 	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);
+#ifndef NEW_PCI_DMA_MAP
+	control &= ~(SABRE_IOMMUCTRL_TSBSZ);
+	control |= (SABRE_IOMMUCTRL_TBWSZ | SABRE_IOMMUCTRL_ENAB);
 	switch(tsbsize) {
 	case 8:
-		control |= IOMMU_TSBSZ_8K;
+		control |= SABRE_IOMMU_TSBSZ_8K;
 		break;
 	case 16:
-		control |= IOMMU_TSBSZ_16K;
+		control |= SABRE_IOMMU_TSBSZ_16K;
 		break;
 	case 32:
-		control |= IOMMU_TSBSZ_32K;
+		control |= SABRE_IOMMU_TSBSZ_32K;
 		break;
 	default:
 		prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
 		prom_halt();
 		break;
 	}
+#else
+	control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ);
+	control |= SABRE_IOMMUCTRL_ENAB;
+	switch(tsbsize) {
+	case 64:
+		control |= SABRE_IOMMU_TSBSZ_64K;
+		p->iommu.page_table_sz_bits = 16;
+		break;
+	case 128:
+		control |= SABRE_IOMMU_TSBSZ_128K;
+		p->iommu.page_table_sz_bits = 17;
+		break;
+	default:
+		prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize);
+		prom_halt();
+		break;
+	}
+#endif
 	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
 }
 
@@ -1445,6 +1461,7 @@
 	}
 
 	switch(vdma[1]) {
+#ifndef NEW_PCI_DMA_MAP
 		case 0x20000000:
 			tsbsize = 8;
 			break;
@@ -1454,6 +1471,15 @@
 		case 0x80000000:
 			tsbsize = 32;
 			break;
+#else
+		case 0x20000000:
+			tsbsize = 64;
+			break;
+		case 0x40000000:
+		case 0x80000000:
+			tsbsize = 128;
+			break;
+#endif
 		default:
 			prom_printf("SABRE: strange virtual-dma size.\n");
 			prom_halt();
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/power.c linux/arch/sparc64/kernel/power.c
--- v2.3.34/linux/arch/sparc64/kernel/power.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/kernel/power.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: power.c,v 1.4 1999/08/31 18:22:05 davem Exp $
+/* $Id: power.c,v 1.5 1999/12/19 23:28:00 davem Exp $
  * power.c: Power management driver.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -90,16 +90,18 @@
 	return;
 
 found:
-	power_reg = edev->resource[0].start;
+	power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4);
 	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");
+	if (edev->irqs[0] != 0) {
+		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.34/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- v2.3.34/linux/arch/sparc64/kernel/process.c	Thu Nov 11 20:11:32 1999
+++ linux/arch/sparc64/kernel/process.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.100 1999/08/31 04:39:39 davem Exp $
+/*  $Id: process.c,v 1.102 1999/12/15 22:24:49 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -33,6 +33,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/page.h>
+#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/pstate.h>
@@ -268,7 +269,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&regdump_lock, flags);
-	printk("CPU[%d]: local_irq_count[%ld] global_irq_count[%d]\n",
+	printk("CPU[%d]: local_irq_count[%u] global_irq_count[%d]\n",
 	       smp_processor_id(), local_irq_count,
 	       atomic_read(&global_irq_count));
 #endif
@@ -801,36 +802,4 @@
 out:
 	unlock_kernel();
 	return error;
-}
-
-/*
- * These bracket the sleeping functions..
- */
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-#define first_sched	((unsigned long) scheduling_functions_start_here)
-#define last_sched	((unsigned long) scheduling_functions_end_here)
-
-unsigned long get_wchan(struct task_struct *p)
-{
-	unsigned long pc, fp, bias = 0;
-	unsigned long task_base = (unsigned long) p;
-	struct reg_window *rw;
-	int count = 0;
-	if (!p || p == current || p->state == TASK_RUNNING)
-		return 0;
-	bias = STACK_BIAS;
-	fp = p->thread.ksp + bias;
-	do {
-		/* Bogus frame pointer? */
-		if (fp < (task_base + sizeof(struct task_struct)) ||
-		    fp >= (task_base + (2 * PAGE_SIZE)))
-			break;
-		rw = (struct reg_window *) fp;
-		pc = rw->ins[7];
-		if (pc < first_sched || pc >= last_sched)
-			return pc;
-		fp = rw->ins[6] + bias;
-	} while (++count < 16);
-	return 0;
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/sbus.c linux/arch/sparc64/kernel/sbus.c
--- v2.3.34/linux/arch/sparc64/kernel/sbus.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/sbus.c	Mon Dec 20 22:05:52 1999
@@ -0,0 +1,1145 @@
+/* $Id: sbus.c,v 1.6 1999/12/20 14:08:17 jj Exp $
+ * sbus.c: UltraSparc SBUS controller support.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+
+#include <asm/page.h>
+#include <asm/sbus.h>
+#include <asm/io.h>
+#include <asm/upa.h>
+#include <asm/cache.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+
+#include "iommu_common.h"
+
+/* These should be allocated on an SMP_CACHE_BYTES
+ * aligned boundry for optimal performance.
+ *
+ * On SYSIO, using an 8K page size we have 1GB of SBUS
+ * DMA space mapped.  We divide this space into equally
+ * sized clusters.  Currently we allow clusters up to a
+ * size of 1MB.  If anything begins to generate DMA
+ * mapping requests larger than this we will need to
+ * increase things a bit.
+ */
+
+#define NCLUSTERS	8UL
+#define ONE_GIG		(1UL * 1024UL * 1024UL * 1024UL)
+#define CLUSTER_SIZE	(ONE_GIG / NCLUSTERS)
+#define CLUSTER_MASK	(CLUSTER_SIZE - 1)
+#define CLUSTER_NPAGES	(CLUSTER_SIZE >> PAGE_SHIFT)
+#define MAP_BASE	((u32)0xc0000000)
+
+struct sbus_iommu {
+/*0x00*/spinlock_t		lock;
+
+/*0x08*/iopte_t			*page_table;
+/*0x10*/unsigned long		strbuf_regs;
+/*0x18*/unsigned long		iommu_regs;
+/*0x20*/unsigned long		sbus_control_reg;
+
+/*0x28*/volatile unsigned long	strbuf_flushflag;
+
+	/* If NCLUSTERS is ever decresed to 4 or lower,
+	 * you must increase the size of the type of
+	 * these counters.  You have been duly warned. -DaveM
+	 */
+/*0x30*/u16			lowest_free[NCLUSTERS];
+};
+
+/* Flushing heuristics */
+#define IOMMU_DIAG_LIM	16
+#define STRBUF_DIAG_LIM	32
+
+/* Offsets from iommu_regs */
+#define SYSIO_IOMMUREG_BASE	0x2400UL
+#define IOMMU_CONTROL	(0x2400UL - 0x2400UL)	/* IOMMU control register */
+#define IOMMU_TSBBASE	(0x2408UL - 0x2400UL)	/* TSB base address register */
+#define IOMMU_FLUSH	(0x2410UL - 0x2400UL)	/* IOMMU flush register */
+#define IOMMU_VADIAG	(0x4400UL - 0x2400UL)	/* SBUS virtual address diagnostic */
+#define IOMMU_TAGCMP	(0x4408UL - 0x2400UL)	/* TLB tag compare diagnostics */
+#define IOMMU_LRUDIAG	(0x4500UL - 0x2400UL)	/* IOMMU LRU queue diagnostics */
+#define IOMMU_TAGDIAG	(0x4580UL - 0x2400UL)	/* TLB tag diagnostics */
+#define IOMMU_DRAMDIAG	(0x4600UL - 0x2400UL)	/* TLB data RAM diagnostics */
+
+#define IOMMU_DRAM_VALID	(1UL << 30UL)
+
+static void __iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
+{
+	int hit = 0;
+
+	if (npages <= IOMMU_DIAG_LIM) {
+		while (npages--)
+			upa_writeq(base + (npages << PAGE_SHIFT),
+				   iommu->iommu_regs + IOMMU_FLUSH);
+		hit = 1;
+	} else {
+		u32 limit = base + ((npages << PAGE_SHIFT) - 1UL);
+		unsigned long dram = iommu->iommu_regs + IOMMU_DRAMDIAG;
+		unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG;
+		int entry;
+
+		for (entry = 0; entry < 16; entry++, dram += 8, tag += 8) {
+			u32 addr = ((u32)upa_readq(tag) << PAGE_SHIFT);
+			if (addr >= base && addr <= limit) {
+				u64 val = upa_readq(dram);
+
+				if (val & IOMMU_DRAM_VALID) {
+					upa_writeq(addr,
+						   iommu->iommu_regs + IOMMU_FLUSH);
+					hit = 1;
+				}
+			}
+		}
+	}
+	if (hit != 0)
+		upa_readq(iommu->sbus_control_reg);
+}
+
+/* In an effort to keep latency under control, we special
+ * case single page IOMMU flushes.
+ */
+static __inline__ void iommu_flush(struct sbus_iommu *iommu,
+				   u32 base, unsigned long npages)
+{
+	if (npages == 1) {
+		upa_writeq(base, iommu->iommu_regs + IOMMU_FLUSH);
+		upa_readq(iommu->sbus_control_reg);
+	} else
+		__iommu_flush(iommu, base, npages);
+}
+
+/* Offsets from strbuf_regs */
+#define SYSIO_STRBUFREG_BASE	0x2800UL
+#define STRBUF_CONTROL	(0x2800UL - 0x2800UL)	/* Control */
+#define STRBUF_PFLUSH	(0x2808UL - 0x2800UL)	/* Page flush/invalidate */
+#define STRBUF_FSYNC	(0x2810UL - 0x2800UL)	/* Flush synchronization */
+#define STRBUF_DRAMDIAG	(0x5000UL - 0x2800UL)	/* data RAM diagnostic */
+#define STRBUF_ERRDIAG	(0x5400UL - 0x2800UL)	/* error status diagnostics */
+#define STRBUF_PTAGDIAG	(0x5800UL - 0x2800UL)	/* Page tag diagnostics */
+#define STRBUF_LTAGDIAG	(0x5900UL - 0x2800UL)	/* Line tag diagnostics */
+
+#define STRBUF_TAG_VALID	0x02UL
+
+static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
+{
+	int hit = 0;
+
+	iommu->strbuf_flushflag = 0UL;
+	if (npages <= STRBUF_DIAG_LIM) {
+		while (npages--)
+			upa_writeq(base + (npages << PAGE_SHIFT),
+				   iommu->strbuf_regs + STRBUF_PFLUSH);
+		hit = 1;
+	} else {
+		u32 limit = base + ((npages << PAGE_SHIFT) - 1UL);
+		unsigned long tag = iommu->strbuf_regs + STRBUF_PTAGDIAG;
+		int entry;
+
+		for (entry = 0; entry < 16; entry++, tag += 8) {
+			u64 val = upa_readq(tag);
+
+			if (val & STRBUF_TAG_VALID) {
+				u32 addr = ((u32)(val & ~3UL)) << (PAGE_SHIFT - 2UL);
+				if (addr >= base && addr <= limit) {
+					upa_writeq(addr,
+						   iommu->strbuf_regs + STRBUF_PFLUSH);
+					hit = 1;
+				}
+			}
+		}
+	}
+	if (hit != 0) {
+		/* Whoopee cushion! */
+		upa_writeq(__pa(&iommu->strbuf_flushflag),
+			   iommu->strbuf_regs + STRBUF_FSYNC);
+		upa_readq(iommu->sbus_control_reg);
+		while (iommu->strbuf_flushflag == 0UL)
+			membar("#LoadLoad");
+	}
+}
+
+static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages)
+{
+	iopte_t *iopte;
+	unsigned long cnum, ent;
+
+	cnum = 0;
+	while ((1UL << cnum) < npages)
+		cnum++;
+	iopte  = iommu->page_table + (cnum * CLUSTER_NPAGES);
+	iopte += ((ent = iommu->lowest_free[cnum]) << cnum);
+
+	if (iopte_val(iopte[(1UL << cnum)]) == 0UL) {
+		/* Fast path. */
+		iommu->lowest_free[cnum] = ent + 1;
+	} else {
+		unsigned long pte_off = 1;
+
+		ent += 1;
+		do {
+			pte_off++;
+			ent++;
+		} while (iopte_val(iopte[(pte_off << cnum)]) != 0UL);
+		iommu->lowest_free[cnum] = ent;
+	}
+
+	/* I've got your streaming cluster right here buddy boy... */
+	return iopte;
+}
+
+static void free_streaming_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages)
+{
+	unsigned long cnum, ent;
+	iopte_t *iopte;
+
+	cnum = 0;
+	while ((1UL << cnum) < npages)
+		cnum++;
+	ent = (base & CLUSTER_MASK) >> (PAGE_SHIFT + cnum);
+	iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT);
+	iopte_val(*iopte) = 0UL;
+	if (ent < iommu->lowest_free[cnum])
+		iommu->lowest_free[cnum] = ent;
+}
+
+/* We allocate consistant mappings from the end of cluster zero. */
+static iopte_t *alloc_consistant_cluster(struct sbus_iommu *iommu, unsigned long npages)
+{
+	iopte_t *iopte;
+
+	iopte = iommu->page_table + (1 * CLUSTER_NPAGES);
+	while (iopte > iommu->page_table) {
+		iopte--;
+		if (!(iopte_val(*iopte) & IOPTE_VALID)) {
+			unsigned long tmp = npages;
+
+			while (--tmp) {
+				iopte--;
+				if (iopte_val(*iopte) & IOPTE_VALID)
+					break;
+			}
+			if (tmp == 0)
+				return iopte;
+		}
+	}
+	return NULL;
+}
+
+static void free_consistant_cluster(struct sbus_iommu *iommu, u32 base, unsigned long npages)
+{
+	iopte_t *iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT);
+
+	while (npages--)
+		*iopte++ = __iopte(0UL);
+}
+
+void *sbus_alloc_consistant(struct sbus_dev *sdev, long size, u32 *dvma_addr)
+{
+	unsigned long order, first_page, flags;
+	struct sbus_iommu *iommu;
+	iopte_t *iopte;
+	void *ret;
+	int npages;
+
+	if (size <= 0 || sdev == NULL || dvma_addr == NULL)
+		return NULL;
+
+	size = PAGE_ALIGN(size);
+	for (order = 0; order < 10; order++) {
+		if ((PAGE_SIZE << order) >= size)
+			break;
+	}
+	if (order == 10)
+		return NULL;
+	first_page = __get_free_pages(GFP_KERNEL, order);
+	if (first_page == 0UL)
+		return NULL;
+	memset((char *)first_page, 0, PAGE_SIZE << order);
+
+	iommu = sdev->bus->iommu;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	iopte = alloc_consistant_cluster(iommu, size >> PAGE_SHIFT);
+	if (iopte == NULL) {
+		spin_unlock_irqrestore(&iommu->lock, flags);
+		free_pages(first_page, order);
+		return NULL;
+	}
+
+	/* Ok, we're committed at this point. */
+	*dvma_addr = MAP_BASE +	((iopte - iommu->page_table) << PAGE_SHIFT);
+	ret = (void *) first_page;
+	npages = size >> PAGE_SHIFT;
+	while (npages--) {
+		*iopte++ = __iopte(IOPTE_VALID | IOPTE_CACHE | IOPTE_WRITE |
+				   (__pa(first_page) & IOPTE_PAGE));
+		first_page += PAGE_SIZE;
+	}
+	iommu_flush(iommu, *dvma_addr, size >> PAGE_SHIFT);
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	return ret;
+}
+
+void sbus_free_consistant(struct sbus_dev *sdev, long size, void *cpu, u32 dvma)
+{
+	unsigned long order, npages;
+	struct sbus_iommu *iommu;
+
+	if (size <= 0 || sdev == NULL || cpu == NULL)
+		return;
+
+	npages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+	iommu = sdev->bus->iommu;
+
+	spin_lock_irq(&iommu->lock);
+	free_consistant_cluster(iommu, dvma, npages);
+	spin_unlock_irq(&iommu->lock);
+
+	for (order = 0; order < 10; order++) {
+		if ((PAGE_SIZE << order) >= size)
+			break;
+	}
+	if (order < 10)
+		free_pages((unsigned long)cpu, order);
+}
+
+u32 sbus_map_single(struct sbus_dev *sdev, void *ptr, long size)
+{
+	struct sbus_iommu *iommu = sdev->bus->iommu;
+	unsigned long npages, phys_base, flags;
+	iopte_t *iopte;
+	u32 dma_base, offset;
+
+	phys_base = (unsigned long) ptr;
+	offset = (u32) (phys_base & ~PAGE_MASK);
+	size = (PAGE_ALIGN(phys_base + size) - (phys_base & PAGE_MASK));
+	phys_base = (unsigned long) __pa(phys_base & PAGE_MASK);
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	npages = size >> PAGE_SHIFT;
+	iopte = alloc_streaming_cluster(iommu, npages);
+	dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT);
+	npages = size >> PAGE_SHIFT;
+	while (npages--) {
+		*iopte++ = __iopte(IOPTE_VALID | IOPTE_STBUF |
+				   IOPTE_CACHE | IOPTE_WRITE |
+				   (phys_base & IOPTE_PAGE));
+		phys_base += PAGE_SIZE;
+	}
+	npages = size >> PAGE_SHIFT;
+	iommu_flush(iommu, dma_base, npages);
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	return (dma_base | offset);
+}
+
+void sbus_unmap_single(struct sbus_dev *sdev, u32 dma_addr, long size)
+{
+	struct sbus_iommu *iommu = sdev->bus->iommu;
+	u32 dma_base = dma_addr & PAGE_MASK;
+	unsigned long flags;
+
+	size = (PAGE_ALIGN(dma_addr + size) - dma_base);
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	free_streaming_cluster(iommu, dma_base, size >> PAGE_SHIFT);
+	strbuf_flush(iommu, dma_base, size >> PAGE_SHIFT);
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nents)
+{
+	struct scatterlist *dma_sg = sg;
+
+	do {
+		unsigned long pteval = ~0UL;
+		u32 dma_npages;
+
+		dma_npages = ((dma_sg->dvma_address & (PAGE_SIZE - 1UL)) +
+			      dma_sg->dvma_length +
+			      ((u32)(PAGE_SIZE - 1UL))) >> PAGE_SHIFT;
+		do {
+			unsigned long offset;
+			signed int len;
+
+			/* If we are here, we know we have at least one
+			 * more page to map.  So walk forward until we
+			 * hit a page crossing, and begin creating new
+			 * mappings from that spot.
+			 */
+			for (;;) {
+				unsigned long tmp;
+
+				tmp = (unsigned long) __pa(sg->address);
+				len = sg->length;
+				if (((tmp ^ pteval) >> PAGE_SHIFT) != 0UL) {
+					pteval = tmp & PAGE_MASK;
+					offset = tmp & (PAGE_SIZE - 1UL);
+					break;
+				}
+				if (((tmp ^ (tmp + len - 1UL)) >> PAGE_SHIFT) != 0UL) {
+					pteval = (tmp + PAGE_SIZE) & PAGE_MASK;
+					offset = 0UL;
+					len -= (PAGE_SIZE - (tmp & (PAGE_SIZE - 1UL)));
+					break;
+				}
+				sg++;
+			}
+
+			pteval = ((pteval & IOPTE_PAGE) |
+				  IOPTE_VALID | IOPTE_STBUF |
+				  IOPTE_CACHE | IOPTE_WRITE);
+			while (len > 0) {
+				*iopte++ = __iopte(pteval);
+				pteval += PAGE_SIZE;
+				len -= (PAGE_SIZE - offset);
+				offset = 0;
+				dma_npages--;
+			}
+
+			pteval = (pteval & IOPTE_PAGE) + len;
+			sg++;
+
+			/* Skip over any tail mappings we've fully mapped,
+			 * adjusting pteval along the way.  Stop when we
+			 * detect a page crossing event.
+			 */
+			while ((pteval << (64 - PAGE_SHIFT)) != 0UL &&
+			       pteval == __pa(sg->address) &&
+			       ((pteval ^
+				 (__pa(sg->address) + sg->length - 1UL)) >> PAGE_SHIFT) == 0UL) {
+				pteval += sg->length;
+				sg++;
+			}
+			if ((pteval << (64 - PAGE_SHIFT)) == 0UL)
+				pteval = ~0UL;
+		} while (dma_npages != 0);
+		dma_sg++;
+	} while (dma_sg->dvma_length != 0);
+}
+
+int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
+{
+	struct sbus_iommu *iommu = sdev->bus->iommu;
+	unsigned long flags, npages;
+	iopte_t *iopte;
+	u32 dma_base;
+	struct scatterlist *sgtmp;
+	int unused;
+
+	/* Fast path single entry scatterlists. */
+	if (nents == 1) {
+		sg->dvma_address = sbus_map_single(sdev, sg->address, sg->length);
+		sg->dvma_length = sg->length;
+		return 1;
+	}
+
+	npages = prepare_sg(sg, nents);
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	iopte = alloc_streaming_cluster(iommu, npages);
+	dma_base = MAP_BASE + ((iopte - iommu->page_table) << PAGE_SHIFT);
+
+	/* Normalize DVMA addresses. */
+	sgtmp = sg;
+	unused = nents;
+
+	while (unused && sgtmp->dvma_length) {
+		sgtmp->dvma_address += dma_base;
+		sgtmp++;
+		unused--;
+	}
+
+	fill_sg(iopte, sg, nents);
+#ifdef VERIFY_SG
+	verify_sglist(sg, nents, iopte, npages);
+#endif
+	iommu_flush(iommu, dma_base, npages);
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	return nents - unused;
+}
+
+void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
+{
+	unsigned long size, flags;
+	struct sbus_iommu *iommu;
+	u32 dvma_base;
+	int i;
+
+	/* Fast path single entry scatterlists. */
+	if (nents == 1) {
+		sbus_unmap_single(sdev, sg->dvma_address, sg->dvma_length);
+		return;
+	}
+
+	dvma_base = sg[0].dvma_address & PAGE_MASK;
+	for (i = 0; i < nents; i++) {
+		if (sg[i].dvma_length == 0)
+			break;
+	}
+	i--;
+	size = PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - dvma_base;
+
+	iommu = sdev->bus->iommu;
+	spin_lock_irqsave(&iommu->lock, flags);
+	free_streaming_cluster(iommu, dvma_base, size >> PAGE_SHIFT);
+	strbuf_flush(iommu, dvma_base, size >> PAGE_SHIFT);
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+void sbus_dma_sync_single(struct sbus_dev *sdev, u32 base, long size)
+{
+	struct sbus_iommu *iommu = sdev->bus->iommu;
+	unsigned long flags;
+
+	size = (PAGE_ALIGN(base + size) - (base & PAGE_MASK));
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	strbuf_flush(iommu, base & PAGE_MASK, size >> PAGE_SHIFT);
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents)
+{
+	struct sbus_iommu *iommu = sdev->bus->iommu;
+	unsigned long flags, size;
+	u32 base;
+	int i;
+
+	base = sg[0].dvma_address & PAGE_MASK;
+	for (i = 0; i < nents; i++) {
+		if (sg[i].dvma_length == 0)
+			break;
+	}
+	i--;
+	size = PAGE_ALIGN(sg[i].dvma_address + sg[i].dvma_length) - base;
+
+	spin_lock_irqsave(&iommu->lock, flags);
+	strbuf_flush(iommu, base, size >> PAGE_SHIFT);
+	spin_unlock_irqrestore(&iommu->lock, flags);
+}
+
+/* Enable 64-bit DVMA mode for the given device. */
+void sbus_set_sbus64(struct sbus_dev *sdev, int bursts)
+{
+	struct sbus_iommu *iommu = sdev->bus->iommu;
+	int slot = sdev->slot;
+	unsigned long cfg_reg;
+	u64 val;
+
+	cfg_reg = iommu->sbus_control_reg;
+	switch (slot) {
+	case 0:
+		cfg_reg += 0x20UL;
+		break;
+	case 1:
+		cfg_reg += 0x28UL;
+		break;
+	case 2:
+		cfg_reg += 0x30UL;
+		break;
+	case 3:
+		cfg_reg += 0x38UL;
+		break;
+	case 13:
+		cfg_reg += 0x40UL;
+		break;
+	case 14:
+		cfg_reg += 0x48UL;
+		break;
+	case 15:
+		cfg_reg += 0x50UL;
+		break;
+
+	default:
+		return;
+	};
+
+	val = upa_readq(cfg_reg);
+	if (val & (1UL << 14UL)) {
+		/* Extended transfer mode already enabled. */
+		return;
+	}
+
+	val |= (1UL << 14UL);
+
+	if (bursts & DMA_BURST8)
+		val |= (1UL << 1UL);
+	if (bursts & DMA_BURST16)
+		val |= (1UL << 2UL);
+	if (bursts & DMA_BURST32)
+		val |= (1UL << 3UL);
+	if (bursts & DMA_BURST64)
+		val |= (1UL << 4UL);
+	upa_writeq(val, cfg_reg);
+}
+
+/* SBUS SYSIO INO number to Sparc PIL level. */
+static unsigned char sysio_ino_to_pil[] = {
+	0, 1, 2, 7, 5, 7, 8, 9,		/* SBUS slot 0 */
+	0, 1, 2, 7, 5, 7, 8, 9,		/* SBUS slot 1 */
+	0, 1, 2, 7, 5, 7, 8, 9,		/* SBUS slot 2 */
+	0, 1, 2, 7, 5, 7, 8, 9,		/* SBUS slot 3 */
+	3, /* Onboard SCSI */
+	5, /* Onboard Ethernet */
+/*XXX*/	8, /* Onboard BPP */
+	0, /* Bogon */
+       13, /* Audio */
+/*XXX*/15, /* PowerFail */
+	0, /* Bogon */
+	0, /* Bogon */
+       12, /* Zilog Serial Channels (incl. Keyboard/Mouse lines) */
+       11, /* Floppy */
+	0, /* Spare Hardware (bogon for now) */
+	0, /* Keyboard (bogon for now) */
+	0, /* Mouse (bogon for now) */
+	0, /* Serial (bogon for now) */
+     0, 0, /* Bogon, Bogon */
+       10, /* Timer 0 */
+       11, /* Timer 1 */
+     0, 0, /* Bogon, Bogon */
+       15, /* Uncorrectable SBUS Error */
+       15, /* Correctable SBUS Error */
+       15, /* SBUS Error */
+/*XXX*/ 0, /* Power Management (bogon for now) */
+};
+
+/* INO number to IMAP register offset for SYSIO external IRQ's.
+ * This should conform to both Sunfire/Wildfire server and Fusion
+ * desktop designs.
+ */
+#define SYSIO_IMAP_SLOT0	0x2c04UL
+#define SYSIO_IMAP_SLOT1	0x2c0cUL
+#define SYSIO_IMAP_SLOT2	0x2c14UL
+#define SYSIO_IMAP_SLOT3	0x2c1cUL
+#define SYSIO_IMAP_SCSI		0x3004UL
+#define SYSIO_IMAP_ETH		0x300cUL
+#define SYSIO_IMAP_BPP		0x3014UL
+#define SYSIO_IMAP_AUDIO	0x301cUL
+#define SYSIO_IMAP_PFAIL	0x3024UL
+#define SYSIO_IMAP_KMS		0x302cUL
+#define SYSIO_IMAP_FLPY		0x3034UL
+#define SYSIO_IMAP_SHW		0x303cUL
+#define SYSIO_IMAP_KBD		0x3044UL
+#define SYSIO_IMAP_MS		0x304cUL
+#define SYSIO_IMAP_SER		0x3054UL
+#define SYSIO_IMAP_TIM0		0x3064UL
+#define SYSIO_IMAP_TIM1		0x306cUL
+#define SYSIO_IMAP_UE		0x3074UL
+#define SYSIO_IMAP_CE		0x307cUL
+#define SYSIO_IMAP_SBERR	0x3084UL
+#define SYSIO_IMAP_PMGMT	0x308cUL
+#define SYSIO_IMAP_GFX		0x3094UL
+#define SYSIO_IMAP_EUPA		0x309cUL
+
+#define bogon     ((unsigned long) -1)
+static unsigned long sysio_irq_offsets[] = {
+	/* SBUS Slot 0 --> 3, level 1 --> 7 */
+	SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0,
+	SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0,
+	SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1,
+	SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1,
+	SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2,
+	SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2,
+	SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3,
+	SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3,
+
+	/* Onboard devices (not relevant/used on SunFire). */
+	SYSIO_IMAP_SCSI,
+	SYSIO_IMAP_ETH,
+	SYSIO_IMAP_BPP,
+	bogon,
+	SYSIO_IMAP_AUDIO,
+	SYSIO_IMAP_PFAIL,
+	bogon,
+	bogon,
+	SYSIO_IMAP_KMS,
+	SYSIO_IMAP_FLPY,
+	SYSIO_IMAP_SHW,
+	SYSIO_IMAP_KBD,
+	SYSIO_IMAP_MS,
+	SYSIO_IMAP_SER,
+	bogon,
+	bogon,
+	SYSIO_IMAP_TIM0,
+	SYSIO_IMAP_TIM1,
+	bogon,
+	bogon,
+	SYSIO_IMAP_UE,
+	SYSIO_IMAP_CE,
+	SYSIO_IMAP_SBERR,
+	SYSIO_IMAP_PMGMT,
+};
+
+#undef bogon
+
+#define NUM_SYSIO_OFFSETS (sizeof(sysio_irq_offsets) / sizeof(sysio_irq_offsets[0]))
+
+/* Convert Interrupt Mapping register pointer to assosciated
+ * Interrupt Clear register pointer, SYSIO specific version.
+ */
+#define SYSIO_ICLR_UNUSED0	0x3400UL
+#define SYSIO_ICLR_SLOT0	0x340cUL
+#define SYSIO_ICLR_SLOT1	0x344cUL
+#define SYSIO_ICLR_SLOT2	0x348cUL
+#define SYSIO_ICLR_SLOT3	0x34ccUL
+static unsigned long sysio_imap_to_iclr(unsigned long imap)
+{
+	unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0;
+	return imap + diff;
+}
+
+unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
+{
+	struct sbus_bus *sbus = (struct sbus_bus *)buscookie;
+	struct sbus_iommu *iommu = sbus->iommu;
+	unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;
+	unsigned long imap, iclr;
+	int pil, sbus_level = 0;
+
+	pil = sysio_ino_to_pil[ino];
+	if (!pil) {
+		printk("sbus_irq_build: Bad SYSIO INO[%x]\n", ino);
+		panic("Bad SYSIO IRQ translations...");
+	}
+	imap = sysio_irq_offsets[ino];
+	if (imap == ((unsigned long)-1)) {
+		prom_printf("get_irq_translations: Bad SYSIO INO[%x] cpu[%d]\n",
+			    ino, pil);
+		prom_halt();
+	}
+	imap += reg_base;
+
+	/* SYSIO inconsistancy.  For external SLOTS, we have to select
+	 * the right ICLR register based upon the lower SBUS irq level
+	 * bits.
+	 */
+	if (ino >= 0x20) {
+		iclr = sysio_imap_to_iclr(imap);
+	} else {
+		int sbus_slot = (ino & 0x18)>>3;
+		
+		sbus_level = ino & 0x7;
+
+		switch(sbus_slot) {
+		case 0:
+			iclr = reg_base + SYSIO_ICLR_SLOT0;
+			break;
+		case 1:
+			iclr = reg_base + SYSIO_ICLR_SLOT1;
+			break;
+		case 2:
+			iclr = reg_base + SYSIO_ICLR_SLOT2;
+			break;
+		default:
+		case 3:
+			iclr = reg_base + SYSIO_ICLR_SLOT3;
+			break;
+		};
+
+		iclr += ((unsigned long)sbus_level - 1UL) * 8UL;
+	}
+	return build_irq(pil, sbus_level, iclr, imap);
+}
+
+/* Error interrupt handling. */
+#define SYSIO_UE_AFSR	0x0030UL
+#define SYSIO_UE_AFAR	0x0038UL
+#define  SYSIO_UEAFSR_PPIO	0x8000000000000000 /* Primary PIO is cause         */
+#define  SYSIO_UEAFSR_PDRD	0x4000000000000000 /* Primary DVMA read is cause   */
+#define  SYSIO_UEAFSR_PDWR	0x2000000000000000 /* Primary DVMA write is cause  */
+#define  SYSIO_UEAFSR_SPIO	0x1000000000000000 /* Secondary PIO is cause       */
+#define  SYSIO_UEAFSR_SDRD	0x0800000000000000 /* Secondary DVMA read is cause */
+#define  SYSIO_UEAFSR_SDWR	0x0400000000000000 /* Secondary DVMA write is cause*/
+#define  SYSIO_UEAFSR_RESV1	0x03ff000000000000 /* Reserved                     */
+#define  SYSIO_UEAFSR_DOFF	0x0000e00000000000 /* Doubleword Offset            */
+#define  SYSIO_UEAFSR_SIZE	0x00001c0000000000 /* Bad transfer size is 2**SIZE */
+#define  SYSIO_UEAFSR_MID	0x000003e000000000 /* UPA MID causing the fault    */
+#define  SYSIO_UEAFSR_RESV2	0x0000001fffffffff /* Reserved                     */
+static void sysio_ue_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct sbus_bus *sbus = dev_id;
+	struct sbus_iommu *iommu = sbus->iommu;
+	unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;
+	unsigned long afsr_reg, afar_reg;
+	unsigned long afsr, afar, error_bits;
+	int reported;
+
+	afsr_reg = reg_base + SYSIO_UE_AFSR;
+	afar_reg = reg_base + SYSIO_UE_AFAR;
+
+	/* Latch error status. */
+	afsr = upa_readq(afsr_reg);
+	afar = upa_readq(afar_reg);
+
+	/* Clear primary/secondary error status bits. */
+	error_bits = afsr &
+		(SYSIO_UEAFSR_PPIO | SYSIO_UEAFSR_PDRD | SYSIO_UEAFSR_PDWR |
+		 SYSIO_UEAFSR_SPIO | SYSIO_UEAFSR_SDRD | SYSIO_UEAFSR_SDWR);
+	upa_writeq(error_bits, afsr_reg);
+
+	/* Log the error. */
+	printk("SYSIO[%x]: Uncorrectable ECC Error, primary error type[%s]\n",
+	       sbus->portid,
+	       (((error_bits & SYSIO_UEAFSR_PPIO) ?
+		 "PIO" :
+		 ((error_bits & SYSIO_UEAFSR_PDRD) ?
+		  "DVMA Read" :
+		  ((error_bits & SYSIO_UEAFSR_PDWR) ?
+		   "DVMA Write" : "???")))));
+	printk("SYSIO[%x]: DOFF[%lx] SIZE[%lx] MID[%lx]\n",
+	       sbus->portid,
+	       (afsr & SYSIO_UEAFSR_DOFF) >> 45UL,
+	       (afsr & SYSIO_UEAFSR_SIZE) >> 42UL,
+	       (afsr & SYSIO_UEAFSR_MID) >> 37UL);
+	printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar);
+	printk("SYSIO[%x]: Secondary UE errors [", sbus->portid);
+	reported = 0;
+	if (afsr & SYSIO_UEAFSR_SPIO) {
+		reported++;
+		printk("(PIO)");
+	}
+	if (afsr & SYSIO_UEAFSR_SDRD) {
+		reported++;
+		printk("(DVMA Read)");
+	}
+	if (afsr & SYSIO_UEAFSR_SDWR) {
+		reported++;
+		printk("(DVMA Write)");
+	}
+	if (!reported)
+		printk("(none)");
+	printk("]\n");
+}
+
+#define SYSIO_CE_AFSR	0x0040UL
+#define SYSIO_CE_AFAR	0x0048UL
+#define  SYSIO_CEAFSR_PPIO	0x8000000000000000 /* Primary PIO is cause         */
+#define  SYSIO_CEAFSR_PDRD	0x4000000000000000 /* Primary DVMA read is cause   */
+#define  SYSIO_CEAFSR_PDWR	0x2000000000000000 /* Primary DVMA write is cause  */
+#define  SYSIO_CEAFSR_SPIO	0x1000000000000000 /* Secondary PIO is cause       */
+#define  SYSIO_CEAFSR_SDRD	0x0800000000000000 /* Secondary DVMA read is cause */
+#define  SYSIO_CEAFSR_SDWR	0x0400000000000000 /* Secondary DVMA write is cause*/
+#define  SYSIO_CEAFSR_RESV1	0x0300000000000000 /* Reserved                     */
+#define  SYSIO_CEAFSR_ESYND	0x00ff000000000000 /* Syndrome Bits                */
+#define  SYSIO_CEAFSR_DOFF	0x0000e00000000000 /* Double Offset                */
+#define  SYSIO_CEAFSR_SIZE	0x00001c0000000000 /* Bad transfer size is 2**SIZE */
+#define  SYSIO_CEAFSR_MID	0x000003e000000000 /* UPA MID causing the fault    */
+#define  SYSIO_CEAFSR_RESV2	0x0000001fffffffff /* Reserved                     */
+static void sysio_ce_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct sbus_bus *sbus = dev_id;
+	struct sbus_iommu *iommu = sbus->iommu;
+	unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;
+	unsigned long afsr_reg, afar_reg;
+	unsigned long afsr, afar, error_bits;
+	int reported;
+
+	afsr_reg = reg_base + SYSIO_CE_AFSR;
+	afar_reg = reg_base + SYSIO_CE_AFAR;
+
+	/* Latch error status. */
+	afsr = upa_readq(afsr_reg);
+	afar = upa_readq(afar_reg);
+
+	/* Clear primary/secondary error status bits. */
+	error_bits = afsr &
+		(SYSIO_CEAFSR_PPIO | SYSIO_CEAFSR_PDRD | SYSIO_CEAFSR_PDWR |
+		 SYSIO_CEAFSR_SPIO | SYSIO_CEAFSR_SDRD | SYSIO_CEAFSR_SDWR);
+	upa_writeq(error_bits, afsr_reg);
+
+	printk("SYSIO[%x]: Correctable ECC Error, primary error type[%s]\n",
+	       sbus->portid,
+	       (((error_bits & SYSIO_CEAFSR_PPIO) ?
+		 "PIO" :
+		 ((error_bits & SYSIO_CEAFSR_PDRD) ?
+		  "DVMA Read" :
+		  ((error_bits & SYSIO_CEAFSR_PDWR) ?
+		   "DVMA Write" : "???")))));
+
+	/* XXX Use syndrome and afar to print out module string just like
+	 * XXX UDB CE trap handler does... -DaveM
+	 */
+	printk("SYSIO[%x]: DOFF[%lx] ECC Syndrome[%lx] Size[%lx] MID[%lx]\n",
+	       sbus->portid,
+	       (afsr & SYSIO_CEAFSR_DOFF) >> 45UL,
+	       (afsr & SYSIO_CEAFSR_ESYND) >> 48UL,
+	       (afsr & SYSIO_CEAFSR_SIZE) >> 42UL,
+	       (afsr & SYSIO_CEAFSR_MID) >> 37UL);
+	printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar);
+
+	printk("SYSIO[%x]: Secondary CE errors [", sbus->portid);
+	reported = 0;
+	if (afsr & SYSIO_CEAFSR_SPIO) {
+		reported++;
+		printk("(PIO)");
+	}
+	if (afsr & SYSIO_CEAFSR_SDRD) {
+		reported++;
+		printk("(DVMA Read)");
+	}
+	if (afsr & SYSIO_CEAFSR_SDWR) {
+		reported++;
+		printk("(DVMA Write)");
+	}
+	if (!reported)
+		printk("(none)");
+	printk("]\n");
+}
+
+#define SYSIO_SBUS_AFSR		0x2010UL
+#define SYSIO_SBUS_AFAR		0x2018UL
+#define  SYSIO_SBAFSR_PLE	0x8000000000000000 /* Primary Late PIO Error       */
+#define  SYSIO_SBAFSR_PTO	0x4000000000000000 /* Primary SBUS Timeout         */
+#define  SYSIO_SBAFSR_PBERR	0x2000000000000000 /* Primary SBUS Error ACK       */
+#define  SYSIO_SBAFSR_SLE	0x1000000000000000 /* Secondary Late PIO Error     */
+#define  SYSIO_SBAFSR_STO	0x0800000000000000 /* Secondary SBUS Timeout       */
+#define  SYSIO_SBAFSR_SBERR	0x0400000000000000 /* Secondary SBUS Error ACK     */
+#define  SYSIO_SBAFSR_RESV1	0x03ff000000000000 /* Reserved                     */
+#define  SYSIO_SBAFSR_RD	0x0000800000000000 /* Primary was late PIO read    */
+#define  SYSIO_SBAFSR_RESV2	0x0000600000000000 /* Reserved                     */
+#define  SYSIO_SBAFSR_SIZE	0x00001c0000000000 /* Size of transfer             */
+#define  SYSIO_SBAFSR_MID	0x000003e000000000 /* MID causing the error        */
+#define  SYSIO_SBAFSR_RESV3	0x0000001fffffffff /* Reserved                     */
+static void sysio_sbus_error_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct sbus_bus *sbus = dev_id;
+	struct sbus_iommu *iommu = sbus->iommu;
+	unsigned long afsr_reg, afar_reg, reg_base;
+	unsigned long afsr, afar, error_bits;
+	int reported;
+
+	reg_base = iommu->sbus_control_reg - 0x2000UL;
+	afsr_reg = reg_base + SYSIO_SBUS_AFSR;
+	afar_reg = reg_base + SYSIO_SBUS_AFAR;
+
+	afsr = upa_readq(afsr_reg);
+	afar = upa_readq(afar_reg);
+
+	/* Clear primary/secondary error status bits. */
+	error_bits = afsr &
+		(SYSIO_SBAFSR_PLE | SYSIO_SBAFSR_PTO | SYSIO_SBAFSR_PBERR |
+		 SYSIO_SBAFSR_SLE | SYSIO_SBAFSR_STO | SYSIO_SBAFSR_SBERR);
+	upa_writeq(error_bits, afsr_reg);
+
+	/* Log the error. */
+	printk("SYSIO[%x]: SBUS Error, primary error type[%s] read(%d)\n",
+	       sbus->portid,
+	       (((error_bits & SYSIO_SBAFSR_PLE) ?
+		 "Late PIO Error" :
+		 ((error_bits & SYSIO_SBAFSR_PTO) ?
+		  "Time Out" :
+		  ((error_bits & SYSIO_SBAFSR_PBERR) ?
+		   "Error Ack" : "???")))),
+	       (afsr & SYSIO_SBAFSR_RD) ? 1 : 0);
+	printk("SYSIO[%x]: size[%lx] MID[%lx]\n",
+	       sbus->portid,
+	       (afsr & SYSIO_SBAFSR_SIZE) >> 42UL,
+	       (afsr & SYSIO_SBAFSR_MID) >> 37UL);
+	printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar);
+	printk("SYSIO[%x]: Secondary SBUS errors [", sbus->portid);
+	reported = 0;
+	if (afsr & SYSIO_SBAFSR_SLE) {
+		reported++;
+		printk("(Late PIO Error)");
+	}
+	if (afsr & SYSIO_SBAFSR_STO) {
+		reported++;
+		printk("(Time Out)");
+	}
+	if (afsr & SYSIO_SBAFSR_SBERR) {
+		reported++;
+		printk("(Error Ack)");
+	}
+	if (!reported)
+		printk("(none)");
+	printk("]\n");
+
+	/* XXX check iommu/strbuf for further error status XXX */
+}
+
+#define ECC_CONTROL	0x0020UL
+#define  SYSIO_ECNTRL_ECCEN	0x8000000000000000 /* Enable ECC Checking          */
+#define  SYSIO_ECNTRL_UEEN	0x4000000000000000 /* Enable UE Interrupts         */
+#define  SYSIO_ECNTRL_CEEN	0x2000000000000000 /* Enable CE Interrupts         */
+
+#define SYSIO_UE_INO		0x34
+#define SYSIO_CE_INO		0x35
+#define SYSIO_SBUSERR_INO	0x36
+
+static void __init sysio_register_error_handlers(struct sbus_bus *sbus)
+{
+	struct sbus_iommu *iommu = sbus->iommu;
+	unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;
+	unsigned int irq;
+	u64 control;
+
+	irq = sbus_build_irq(sbus, SYSIO_UE_INO);
+	if (request_irq(irq, sysio_ue_handler,
+			SA_SHIRQ, "SYSIO UE", sbus) < 0) {
+		prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n",
+			    sbus->portid);
+		prom_halt();
+	}
+
+	irq = sbus_build_irq(sbus, SYSIO_CE_INO);
+	if (request_irq(irq, sysio_ce_handler,
+			SA_SHIRQ, "SYSIO CE", sbus) < 0) {
+		prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n",
+			    sbus->portid);
+		prom_halt();
+	}
+
+	irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO);
+	if (request_irq(irq, sysio_sbus_error_handler,
+			SA_SHIRQ, "SYSIO SBUS Error", sbus) < 0) {
+		prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n",
+			    sbus->portid);
+		prom_halt();
+	}
+
+	/* Now turn the error interrupts on and also enable ECC checking. */
+	upa_writeq((SYSIO_ECNTRL_ECCEN |
+		    SYSIO_ECNTRL_UEEN  |
+		    SYSIO_ECNTRL_CEEN),
+		   reg_base + ECC_CONTROL);
+
+	control = upa_readq(iommu->sbus_control_reg);
+	control |= 0x100UL; /* SBUS Error Interrupt Enable */
+	upa_writeq(control, iommu->sbus_control_reg);
+}
+
+/* Boot time initialization. */
+void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus)
+{
+	struct linux_prom64_registers rprop;
+	struct sbus_iommu *iommu;
+	unsigned long regs, tsb_base;
+	u64 control;
+	int err, i;
+
+	sbus->portid = prom_getintdefault(sbus->prom_node,
+					  "upa-portid", -1);
+
+	err = prom_getproperty(prom_node, "reg",
+			       (char *)&rprop, sizeof(rprop));
+	if (err < 0) {
+		prom_printf("sbus_iommu_init: Cannot map SYSIO control registers.\n");
+		prom_halt();
+	}
+	regs = rprop.phys_addr;
+
+	iommu = kmalloc(sizeof(*iommu) + SMP_CACHE_BYTES, GFP_ATOMIC);
+	if (iommu == NULL) {
+		prom_printf("sbus_iommu_init: Fatal error, kmalloc(iommu) failed\n");
+		prom_halt();
+	}
+
+	/* Align on E$ line boundry. */
+	iommu = (struct sbus_iommu *)
+		(((unsigned long)iommu + (SMP_CACHE_BYTES - 1UL)) &
+		 ~(SMP_CACHE_BYTES - 1UL));
+
+	memset(iommu, 0, sizeof(*iommu));
+
+	/* Setup spinlock. */
+	spin_lock_init(&iommu->lock);
+
+	/* Init register offsets. */
+	iommu->iommu_regs = regs + SYSIO_IOMMUREG_BASE;
+	iommu->strbuf_regs = regs + SYSIO_STRBUFREG_BASE;
+
+	/* The SYSIO SBUS control register is used for dummy reads
+	 * in order to ensure write completion.
+	 */
+	iommu->sbus_control_reg = regs + 0x2000UL;
+
+	/* Link into SYSIO software state. */
+	sbus->iommu = iommu;
+
+	printk("SYSIO: UPA portID %x, at %016lx\n",
+	       sbus->portid, regs);
+
+	/* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */
+	control = upa_readq(iommu->iommu_regs + IOMMU_CONTROL);
+	control = ((7UL << 16UL)	|
+		   (0UL << 2UL)		|
+		   (1UL << 1UL)		|
+		   (1UL << 0UL));
+
+	/* Using the above configuration we need 1MB iommu page
+	 * table (128K ioptes * 8 bytes per iopte).  This is
+	 * page order 7 on UltraSparc.
+	 */
+	tsb_base = __get_free_pages(GFP_ATOMIC, 7);
+	if (tsb_base == 0UL) {
+		prom_printf("sbus_iommu_init: Fatal error, cannot alloc TSB table.\n");
+		prom_halt();
+	}
+
+	iommu->page_table = (iopte_t *) tsb_base;
+	memset(iommu->page_table, 0, (PAGE_SIZE << 7));
+
+	upa_writeq(control, iommu->iommu_regs + IOMMU_CONTROL);
+
+	/* Clean out any cruft in the IOMMU using
+	 * diagnostic accesses.
+	 */
+	for (i = 0; i < 16; i++) {
+		unsigned long dram = iommu->iommu_regs + IOMMU_DRAMDIAG;
+
+		dram += (unsigned long)i * 8UL;
+		upa_writeq(0, dram);
+	}
+	upa_readq(iommu->sbus_control_reg);
+
+	/* Give the TSB to SYSIO. */
+	upa_writeq(__pa(tsb_base), iommu->iommu_regs + IOMMU_TSBBASE);
+
+	/* Setup streaming buffer, DE=1 SB_EN=1 */
+	control = (1UL << 1UL) | (1UL << 0UL);
+	upa_writeq(control, iommu->strbuf_regs + STRBUF_CONTROL);
+
+	/* Clear out the tags using diagnostics. */
+	for (i = 0; i < 16; i++) {
+		unsigned long ptag, ltag;
+
+		ptag = iommu->strbuf_regs + STRBUF_PTAGDIAG;
+		ltag = iommu->strbuf_regs + STRBUF_LTAGDIAG;
+		ptag += (unsigned long)i * 8UL;
+		ltag += (unsigned long)i * 8UL;
+
+		upa_writeq(0UL, ptag);
+		upa_writeq(0UL, ltag);
+	}
+
+	/* Enable DVMA arbitration for all devices/slots. */
+	control = upa_readq(iommu->sbus_control_reg);
+	control |= 0x3fUL;
+	upa_writeq(control, iommu->sbus_control_reg);
+
+	/* Now some Xfire specific grot... */
+	{
+		extern void *starfire_hookup(int);
+		extern int this_is_starfire;
+
+		if (this_is_starfire)
+			sbus->starfire_cookie = starfire_hookup(sbus->portid);
+		else
+			sbus->starfire_cookie = NULL;
+	}
+
+	sysio_register_error_handlers(sbus);
+}
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- v2.3.34/linux/arch/sparc64/kernel/setup.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/kernel/setup.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.47 1999/08/31 06:54:55 davem Exp $
+/*  $Id: setup.c,v 1.50 1999/12/01 10:44:45 davem Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
@@ -279,7 +279,9 @@
 #ifdef CONFIG_SUN_CONSOLE
 static int console_fb __initdata = 0;
 #endif
-static unsigned long memory_size = 0;
+
+/* Exported for mm/init.c:paging_init. */
+unsigned long cmdline_memory_size = 0;
 
 #ifdef PROM_DEBUG_CONSOLE
 static struct console prom_debug_console = {
@@ -398,13 +400,13 @@
 				 * "mem=XXX[kKmM]" overrides the PROM-reported
 				 * memory size.
 				 */
-				memory_size = simple_strtoul(commands + 4,
-							     &commands, 0);
+				cmdline_memory_size = simple_strtoul(commands + 4,
+								     &commands, 0);
 				if (*commands == 'K' || *commands == 'k') {
-					memory_size <<= 10;
+					cmdline_memory_size <<= 10;
 					commands++;
 				} else if (*commands=='M' || *commands=='m') {
-					memory_size <<= 20;
+					cmdline_memory_size <<= 20;
 					commands++;
 				}
 			}
@@ -438,12 +440,22 @@
 
 extern struct consw sun_serial_con;
 
-void __init setup_arch(char **cmdline_p,
-	unsigned long * memory_start_p, unsigned long * memory_end_p)
+void register_prom_callbacks(void)
+{
+	prom_setcallback(prom_callback);
+	prom_feval(": linux-va>tte-data 2 \" va>tte-data\" $callback drop ; "
+		   "' linux-va>tte-data to va>tte-data");
+	prom_feval(": linux-.soft1 1 \" .soft1\" $callback 2drop ; "
+		   "' linux-.soft1 to .soft1");
+	prom_feval(": linux-.soft2 1 \" .soft2\" $callback 2drop ; "
+		   "' linux-.soft2 to .soft2");
+}
+
+void __init setup_arch(char **cmdline_p)
 {
 	extern int serial_console;  /* in console.c, of course */
-	unsigned long lowest_paddr, end_of_phys_memory = 0;
-	int total, i;
+	unsigned long highest_paddr;
+	int i;
 
 	/* Initialize PROM console and command line. */
 	*cmdline_p = prom_getbootargs();
@@ -464,44 +476,23 @@
 	boot_flags_init(*cmdline_p);
 
 	idprom_init();
-	total = prom_probe_memory();
-
-	lowest_paddr = 0xffffffffffffffffUL;
-	for(i=0; sp_banks[i].num_bytes != 0; i++) {
-		if(sp_banks[i].base_addr < lowest_paddr)
-			lowest_paddr = sp_banks[i].base_addr;
-		end_of_phys_memory = sp_banks[i].base_addr +
-			sp_banks[i].num_bytes;
-		if (memory_size) {
-			if (end_of_phys_memory > memory_size) {
-				sp_banks[i].num_bytes -=
-					(end_of_phys_memory - memory_size);
-				end_of_phys_memory = memory_size;
-				sp_banks[++i].base_addr = 0xdeadbeef;
-				sp_banks[i].num_bytes = 0;
-			}
-		}
-	}
-	prom_setcallback(prom_callback);
-	prom_feval(": linux-va>tte-data 2 \" va>tte-data\" $callback drop ; "
-		   "' linux-va>tte-data to va>tte-data");
-	prom_feval(": linux-.soft1 1 \" .soft1\" $callback 2drop ; "
-		   "' linux-.soft1 to .soft1");
-	prom_feval(": linux-.soft2 1 \" .soft2\" $callback 2drop ; "
-		   "' linux-.soft2 to .soft2");
+	(void) prom_probe_memory();
 
 	/* In paging_init() we tip off this value to see if we need
 	 * to change init_mm.pgd to point to the real alias mapping.
 	 */
-	phys_base = lowest_paddr;
-
-	*memory_start_p = PAGE_ALIGN(((unsigned long) &end));
-	*memory_end_p = (end_of_phys_memory + PAGE_OFFSET);
-
-#ifdef DAVEM_DEBUGGING
-	prom_printf("phys_base[%016lx] memory_start[%016lx] memory_end[%016lx]\n",
-		    phys_base, *memory_start_p, *memory_end_p);
-#endif
+	phys_base = 0xffffffffffffffffUL;
+	highest_paddr = 0UL;
+	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
+		unsigned long top;
+
+		if (sp_banks[i].base_addr < phys_base)
+			phys_base = sp_banks[i].base_addr;
+		top = sp_banks[i].base_addr +
+			sp_banks[i].num_bytes;
+		if (highest_paddr < top)
+			highest_paddr = top;
+	}
 
 	if (!root_flags)
 		root_mountflags &= ~MS_RDONLY;
@@ -512,6 +503,7 @@
 	rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);	
 #endif
 #ifdef CONFIG_BLK_DEV_INITRD
+// FIXME needs to do the new bootmem alloc stuff
 	if (sparc_ramdisk_image) {
 		unsigned long start = 0;
 		
@@ -537,7 +529,7 @@
 	/* Due to stack alignment restrictions and assumptions... */
 	init_mm.mmap->vm_page_prot = PAGE_SHARED;
 	init_mm.mmap->vm_start = PAGE_OFFSET;
-	init_mm.mmap->vm_end = *memory_end_p;
+	init_mm.mmap->vm_end = PAGE_OFFSET + highest_paddr;
 	init_task.thread.kregs = &fake_swapper_regs;
 
 #ifdef CONFIG_IP_PNP
@@ -642,6 +634,13 @@
 	len += mmu_info(buffer + len);
 #ifdef __SMP__
 	len += smp_info(buffer + len);
+#endif
+#undef ZS_LOG
+#ifdef ZS_LOG
+	{
+		extern int zs_dumplog(char *);
+		len += zs_dumplog(buffer + len);
+	}
 #endif
 	return len;
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c
--- v2.3.34/linux/arch/sparc64/kernel/signal.c	Tue Nov 23 22:42:20 1999
+++ linux/arch/sparc64/kernel/signal.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.45 1999/09/06 08:21:59 jj Exp $
+/*  $Id: signal.c,v 1.48 1999/12/15 22:24:52 davem Exp $
  *  arch/sparc64/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c
--- v2.3.34/linux/arch/sparc64/kernel/signal32.c	Sun Nov  7 16:37:34 1999
+++ linux/arch/sparc64/kernel/signal32.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/*  $Id: signal32.c,v 1.50 1999/07/30 09:35:25 davem Exp $
+/*  $Id: signal32.c,v 1.56 1999/12/20 01:16:16 davem Exp $
  *  arch/sparc64/kernel/signal32.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -663,7 +663,8 @@
 			goto sigsegv;
 
 		if(pte_present(*ptep)) {
-			unsigned long page = pte_page(*ptep);
+			unsigned long page = (unsigned long)
+				__va(pte_pagenr(*ptep) << PAGE_SHIFT);
 
 			__asm__ __volatile__("
 			membar	#StoreStore
@@ -1033,6 +1034,26 @@
 		err |= __put_user(0, &sf->fpu_save);
 	}
 
+	/* Update the siginfo structure.  Is this good?  */
+	if (info->si_code == 0) {
+		info->si_signo = signr;
+		info->si_errno = 0;
+
+		switch (signr) {
+		case SIGSEGV:
+		case SIGILL:
+		case SIGFPE:
+		case SIGBUS:
+		case SIGEMT:
+			info->si_code = current->thread.sig_desc;
+			info->si_addr = (void *)current->thread.sig_address;
+			info->si_trapno = 0;
+			break;
+		default:
+			break;
+		}
+	}
+
 	err = __put_user (info->si_signo, &sf->info.si_signo);
 	err |= __put_user (info->si_errno, &sf->info.si_errno);
 	err |= __put_user (info->si_code, &sf->info.si_code);
@@ -1084,7 +1105,7 @@
 	case 1: seta.sig[1] = (oldset->sig[0] >> 32);
 		seta.sig[0] = oldset->sig[0];
 	}
-	err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t));
+	err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t32));
 
 	err |= copy_in_user((u32 *)sf,
 			    (u32 *)(regs->u_regs[UREG_FP]),
@@ -1122,7 +1143,8 @@
 			goto sigsegv;
 
 		if(pte_present(*ptep)) {
-			unsigned long page = pte_page(*ptep);
+			unsigned long page = (unsigned long)
+				__va(pte_pagenr(*ptep) << PAGE_SHIFT);
 
 			__asm__ __volatile__("
 			membar	#StoreStore
@@ -1326,7 +1348,8 @@
 				continue;
 
 			case SIGQUIT: case SIGILL: case SIGTRAP:
-			case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS:
+			case SIGABRT: case SIGFPE: case SIGSEGV:
+			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
 				if (do_coredump(signr, regs))
 					exit_code |= 0x80;
 #ifdef DEBUG_SIGNALS
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- v2.3.34/linux/arch/sparc64/kernel/smp.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/kernel/smp.c	Mon Dec 20 22:05:52 1999
@@ -94,7 +94,8 @@
 	cpu_data[id].udelay_val			= loops_per_sec;
 
 	cpu_data[id].pgcache_size		= 0;
-	cpu_data[id].pte_cache			= NULL;
+	cpu_data[id].pte_cache[0]		= NULL;
+	cpu_data[id].pte_cache[1]		= NULL;
 	cpu_data[id].pgdcache_size		= 0;
 	cpu_data[id].pgd_cache			= NULL;
 	cpu_data[id].idle_volume		= 1;
@@ -184,7 +185,7 @@
 
 extern struct prom_cpuinfo linux_cpus[64];
 
-extern unsigned long smp_trampoline;
+extern unsigned long sparc64_cpu_startup;
 
 /* The OBP cpu startup callback truncates the 3rd arg cookie to
  * 32-bits (I think) so to be safe we have it read the pointer
@@ -210,15 +211,13 @@
 			continue;
 
 		if(cpu_present_map & (1UL << i)) {
-			unsigned long entry = (unsigned long)(&smp_trampoline);
+			unsigned long entry = (unsigned long)(&sparc64_cpu_startup);
 			unsigned long cookie = (unsigned long)(&cpu_new_task);
 			struct task_struct *p;
 			int timeout;
 			int no;
-			extern unsigned long phys_base;
 
-			entry += phys_base - KERNBASE;
-			cookie += phys_base - KERNBASE;
+			prom_printf("Starting CPU %d... ", i);
 			kernel_thread(start_secondary, NULL, CLONE_PID);
 			cpucount++;
 
@@ -247,9 +246,11 @@
 				cpu_number_map[i] = cpucount;
 				__cpu_logical_map[cpucount] = i;
 				prom_cpu_nodes[i] = linux_cpus[no].prom_node;
+				prom_printf("OK\n");
 			} else {
 				cpucount--;
 				printk("Processor %d is stuck.\n", i);
+				prom_printf("FAILED\n");
 			}
 		}
 		if(!callin_flag) {
@@ -537,14 +538,31 @@
 /* Imprisoned penguins run with %pil == 15, but PSTATE_IE set, so they
  * can service tlb flush xcalls...
  */
+extern void prom_world(int);
+extern void save_alternate_globals(unsigned long *);
+extern void restore_alternate_globals(unsigned long *);
 void smp_penguin_jailcell(void)
 {
-	flushw_user();
+	unsigned long global_save[24];
+
+	__asm__ __volatile__("flushw");
+	save_alternate_globals(global_save);
+	prom_world(1);
 	atomic_inc(&smp_capture_registry);
 	membar("#StoreLoad | #StoreStore");
 	while(penguins_are_doing_time)
 		membar("#LoadLoad");
+	restore_alternate_globals(global_save);
 	atomic_dec(&smp_capture_registry);
+	prom_world(0);
+}
+
+extern unsigned long xcall_promstop;
+
+void smp_promstop_others(void)
+{
+	if (smp_processors_ready)
+		smp_cross_call(&xcall_promstop, 0, 0, 0);
 }
 
 static inline void sparc64_do_profile(unsigned long pc, unsigned long g3)
@@ -701,14 +719,13 @@
 		/* Failure. */
 		if(p >= (mem_map + max_mapnr))
 			return 0UL;
-		if(PageSkip(p)) {
-			p = p->next_hash;
-			base = page_address(p);
+		if(PageReserved(p)) {
 			found = size;
+			base = page_address(p);
 		} else {
 			found -= PAGE_SIZE;
-			p++;
 		}
+		p++;
 	}
 	return base;
 }
@@ -718,7 +735,7 @@
 static void __init smp_tune_scheduling (void)
 {
 	unsigned long flush_base, flags, *p;
-	unsigned int ecache_size;
+	unsigned int ecache_size, order;
 	cycles_t tick1, tick2, raw;
 
 	/* Approximate heuristic for SMP scheduling.  It is an
@@ -733,18 +750,22 @@
 	 */
 	printk("SMP: Calibrating ecache flush... ");
 	ecache_size = prom_getintdefault(linux_cpus[0].prom_node,
-					 "ecache-size", (512 *1024));
-	flush_base = find_flush_base(ecache_size << 1);
+					 "ecache-size", (512 * 1024));
+	if (ecache_size > (4 * 1024 * 1024))
+		ecache_size = (4 * 1024 * 1024);
+	for (order = 0UL; (PAGE_SIZE << order) < ecache_size; order++)
+		;
+	flush_base = __get_free_pages(GFP_KERNEL, order);
 
-	if(flush_base != 0UL) {
+	if (flush_base != 0UL) {
 		__save_and_cli(flags);
 
 		/* Scan twice the size once just to get the TLB entries
 		 * loaded and make sure the second scan measures pure misses.
 		 */
-		for(p = (unsigned long *)flush_base;
-		    ((unsigned long)p) < (flush_base + (ecache_size<<1));
-		    p += (64 / sizeof(unsigned long)))
+		for (p = (unsigned long *)flush_base;
+		     ((unsigned long)p) < (flush_base + (ecache_size<<1));
+		     p += (64 / sizeof(unsigned long)))
 			*((volatile unsigned long *)p);
 
 		/* Now the real measurement. */
@@ -775,9 +796,12 @@
 		 * sharing the cache and fitting.
 		 */
 		cacheflush_time = (raw - (raw >> 2));
-	} else
+
+		free_pages(flush_base, order);
+	} else {
 		cacheflush_time = ((ecache_size << 2) +
 				   (ecache_size << 1));
+	}
 
 	printk("Using heuristic of %d cycles.\n",
 	       (int) cacheflush_time);
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.3.34/linux/arch/sparc64/kernel/sparc64_ksyms.c	Thu Nov 11 20:11:32 1999
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.64 1999/09/05 09:33:38 ecd Exp $
+/* $Id: sparc64_ksyms.c,v 1.68 1999/12/17 12:32:05 jj Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -55,8 +55,6 @@
 extern unsigned prom_cpu_nodes[64];
 extern void die_if_kernel(char *str, struct pt_regs *regs);
 extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-extern unsigned long sunos_mmap(unsigned long, unsigned long, unsigned long,
-				unsigned long, unsigned long, unsigned long);
 void _sigpause_common (unsigned int set, struct pt_regs *);
 extern void *__bzero(void *, size_t);
 extern void *__bzero_noasi(void *, size_t);
@@ -117,11 +115,13 @@
 
 /* used by various drivers */
 #ifdef __SMP__
+#ifndef SPIN_LOCK_DEBUG
 /* Out of line rw-locking implementation. */
 EXPORT_SYMBOL_PRIVATE(read_lock);
 EXPORT_SYMBOL_PRIVATE(read_unlock);
 EXPORT_SYMBOL_PRIVATE(write_lock);
 EXPORT_SYMBOL_PRIVATE(write_unlock);
+#endif
 
 /* Kernel wide locking */
 EXPORT_SYMBOL(kernel_flag);
@@ -175,23 +175,25 @@
 
 EXPORT_SYMBOL(mstk48t02_regs);
 EXPORT_SYMBOL(request_fast_irq);
-EXPORT_SYMBOL(sparc_alloc_io);
-EXPORT_SYMBOL(sparc_free_io);
-EXPORT_SYMBOL(sparc_ultra_unmapioaddr);
-EXPORT_SYMBOL(mmu_get_scsi_sgl);
-EXPORT_SYMBOL(mmu_get_scsi_one);
-EXPORT_SYMBOL(sparc_dvma_malloc);
-EXPORT_SYMBOL(mmu_release_scsi_one);
-EXPORT_SYMBOL(mmu_release_scsi_sgl);
 #if CONFIG_SBUS
-EXPORT_SYMBOL(mmu_set_sbus64);
-EXPORT_SYMBOL(SBus_chain);
+EXPORT_SYMBOL(sbus_root);
 EXPORT_SYMBOL(dma_chain);
+EXPORT_SYMBOL(sbus_set_sbus64);
+EXPORT_SYMBOL(sbus_alloc_consistant);
+EXPORT_SYMBOL(sbus_free_consistant);
+EXPORT_SYMBOL(sbus_map_single);
+EXPORT_SYMBOL(sbus_unmap_single);
+EXPORT_SYMBOL(sbus_map_sg);
+EXPORT_SYMBOL(sbus_unmap_sg);
+EXPORT_SYMBOL(sbus_dma_sync_single);
+EXPORT_SYMBOL(sbus_dma_sync_sg);
 #endif
 #if CONFIG_PCI
 EXPORT_SYMBOL(ebus_chain);
+#ifndef NEW_PCI_DMA_MAP
 EXPORT_SYMBOL(pci_dvma_v2p_hash);
 EXPORT_SYMBOL(pci_dvma_p2v_hash);
+#endif
 EXPORT_SYMBOL(pci_memspace_mask);
 EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(outsb);
@@ -204,7 +206,6 @@
 
 /* Solaris/SunOS binary compatibility */
 EXPORT_SYMBOL(_sigpause_common);
-EXPORT_SYMBOL(sunos_mmap);
 
 /* Should really be in linux/kernel/ksyms.c */
 EXPORT_SYMBOL(dump_thread);
@@ -229,10 +230,10 @@
 EXPORT_SYMBOL(prom_setprop);
 EXPORT_SYMBOL(saved_command_line);
 EXPORT_SYMBOL(prom_getname);
+EXPORT_SYMBOL(prom_finddevice);
 EXPORT_SYMBOL(prom_feval);
 EXPORT_SYMBOL(prom_getbool);
 EXPORT_SYMBOL(prom_getstring);
-EXPORT_SYMBOL(prom_apply_sbus_ranges);
 EXPORT_SYMBOL(prom_getint);
 EXPORT_SYMBOL(prom_getintdefault);
 EXPORT_SYMBOL(__prom_getchild);
@@ -311,5 +312,3 @@
 EXPORT_SYMBOL_NOVERS(memcpy);
 EXPORT_SYMBOL_NOVERS(memset);
 EXPORT_SYMBOL_NOVERS(memmove);
-
-EXPORT_SYMBOL(get_wchan);
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/starfire.c linux/arch/sparc64/kernel/starfire.c
--- v2.3.34/linux/arch/sparc64/kernel/starfire.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/kernel/starfire.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: starfire.c,v 1.3 1999/08/30 10:01:13 davem Exp $
+/* $Id: starfire.c,v 1.4 1999/09/21 14:35:25 davem Exp $
  * starfire.c: Starfire/E10000 support.
  *
  * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
@@ -10,6 +10,7 @@
 #include <asm/page.h>
 #include <asm/oplib.h>
 #include <asm/smp.h>
+#include <asm/upa.h>
 
 /* A few places around the kernel check this to see if
  * they need to call us to do things in a Starfire specific
@@ -43,7 +44,7 @@
 
 int starfire_hard_smp_processor_id(void)
 {
-	return *((volatile unsigned int *) __va(0x1fff40000d0));
+	return upa_readl(0x1fff40000d0UL);
 }
 
 /* Each Starfire board has 32 registers which perform translation
@@ -52,8 +53,8 @@
  * bits than in all previous Sun5 systems.
  */
 struct starfire_irqinfo {
-	volatile unsigned int *imap_slots[32];
-	volatile unsigned int *tregs[32];
+	unsigned long imap_slots[32];
+	unsigned long tregs[32];
 	struct starfire_irqinfo *next;
 	int upaid, hwmid;
 };
@@ -79,8 +80,8 @@
 	treg_base += (hwmid << 33UL);
 	treg_base += 0x200UL;
 	for(i = 0; i < 32; i++) {
-		p->imap_slots[i] = NULL;
-		p->tregs[i] = (volatile unsigned int *)__va(treg_base + (i * 0x10));
+		p->imap_slots[i] = 0UL;
+		p->tregs[i] = treg_base + (i * 0x10UL);
 	}
 	p->upaid = upaid;
 	p->next = sflist;
@@ -89,7 +90,7 @@
 	return (void *) p;
 }
 
-unsigned int starfire_translate(volatile unsigned int *imap,
+unsigned int starfire_translate(unsigned long imap,
 				unsigned int upaid)
 {
 	struct starfire_irqinfo *p;
@@ -107,7 +108,7 @@
 	}
 	for(i = 0; i < 32; i++) {
 		if(p->imap_slots[i] == imap ||
-		   p->imap_slots[i] == NULL)
+		   p->imap_slots[i] == 0UL)
 			break;
 	}
 	if(i == 32) {
@@ -115,7 +116,7 @@
 		panic("Lucy in the sky....");
 	}
 	p->imap_slots[i] = imap;
-	*(p->tregs[i]) = upaid;
+	upa_writel(upaid, p->tregs[i]);
 
 	return i;
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/sys32.S linux/arch/sparc64/kernel/sys32.S
--- v2.3.34/linux/arch/sparc64/kernel/sys32.S	Mon Nov 16 10:37:28 1998
+++ linux/arch/sparc64/kernel/sys32.S	Tue Dec 21 21:56:42 1999
@@ -1,4 +1,4 @@
-/* $Id: sys32.S,v 1.8 1998/10/28 08:10:37 jj Exp $
+/* $Id: sys32.S,v 1.9 1999/12/21 14:09:18 jj Exp $
  * sys32.S: I-cache tricks for 32-bit compatability layer simple
  *          conversions.
  *
@@ -74,3 +74,12 @@
 	sethi		%hi(sys_bdflush), %g1
 	jmpl		%g1 + %lo(sys_bdflush), %g0
 	 sra		%o1, 0, %o1
+
+	.align		32
+	.globl		sys32_mmap2
+sys32_mmap2:
+	srl		%o4, 0, %o4
+	sethi		%hi(sys_mmap), %g1
+	srl		%o5, 0, %o5
+	jmpl		%g1 + %lo(sys_mmap), %g0
+	 sllx		%o5, 12, %o5
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c
--- v2.3.34/linux/arch/sparc64/kernel/sys_sparc.c	Fri Aug  6 11:58:00 1999
+++ linux/arch/sparc64/kernel/sys_sparc.c	Tue Dec 21 21:56:42 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.29 1999/08/04 07:04:10 jj Exp $
+/* $Id: sys_sparc.c,v 1.31 1999/12/21 14:09:25 jj Exp $
  * linux/arch/sparc64/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -156,15 +156,16 @@
 	struct file * file = NULL;
 	unsigned long retval = -EBADF;
 
-	down(&current->mm->mmap_sem);
-	lock_kernel();
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
 		if (!file)
 			goto out;
 	}
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	retval = -ENOMEM;
 	len = PAGE_ALIGN(len);
+	down(&current->mm->mmap_sem);
+	lock_kernel();
 	if(!(flags & MAP_FIXED) && !addr) {
 		addr = get_unmapped_area(addr, len);
 		if(!addr)
@@ -187,15 +188,14 @@
 		}
 	}
 
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	retval = do_mmap(file, addr, len, prot, flags, off);
 
 out_putf:
+	unlock_kernel();
+	up(&current->mm->mmap_sem);
 	if (file)
 		fput(file);
 out:
-	unlock_kernel();
-	up(&current->mm->mmap_sem);
 	return retval;
 }
 
@@ -274,6 +274,21 @@
 	unlock_kernel();
 	return -ENOSYS;
 }
+
+#ifndef CONFIG_SUNOS_EMUL
+asmlinkage int sunos_syscall(struct pt_regs *regs)
+{
+	static int count = 0;
+	lock_kernel();
+	regs->tpc = regs->tnpc;
+	regs->tnpc += 4;
+	if(++count <= 20)
+		printk ("SunOS binary emulation not compiled in\n");
+	force_sig(SIGSEGV, current);
+	unlock_kernel();
+	return -ENOSYS;
+}
+#endif
 
 asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p,
 				 utrap_handler_t new_d,
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.3.34/linux/arch/sparc64/kernel/sys_sparc32.c	Tue Dec 14 01:27:23 1999
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Tue Dec 21 21:56:42 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.118 1999/08/30 10:01:15 davem Exp $
+/* $Id: sys_sparc32.c,v 1.126 1999/12/21 14:09:21 jj Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/fs.h> 
+#include <linux/mm.h> 
 #include <linux/file.h> 
 #include <linux/signal.h>
 #include <linux/utime.h>
@@ -40,6 +41,8 @@
 #include <linux/poll.h>
 #include <linux/personality.h>
 #include <linux/stat.h>
+#include <linux/filter.h>
+#include <linux/highmem.h>
 
 #include <asm/types.h>
 #include <asm/ipc.h>
@@ -712,6 +715,25 @@
 	return ret;
 }
 
+extern asmlinkage long sys_truncate(const char * path, unsigned long length);
+extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
+
+asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low)
+{
+	if ((int)high < 0)
+		return -EINVAL;
+	else
+		return sys_truncate(path, (high << 32) | low);
+}
+
+asmlinkage int sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
+{
+	if ((int)high < 0)
+		return -EINVAL;
+	else
+		return sys_ftruncate(fd, (high << 32) | low);
+}
+
 extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);
 
 struct utimbuf32 {
@@ -1125,8 +1147,10 @@
 	}
 
 	ret = -EINVAL;
-	if (n < 0 || n > KFDS_NR)
+	if (n < 0)
 		goto out_nofds;
+	if (n > current->files->max_fdset)
+		n = current->files->max_fdset;
 
 	/*
 	 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
@@ -1186,84 +1210,157 @@
 	return ret;
 }
 
-static inline int putstat(struct stat32 *ubuf, struct stat *kbuf)
+static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
 {
+	unsigned long ino, blksize, blocks;
+	kdev_t dev, rdev;
+	umode_t mode;
+	nlink_t nlink;
+	uid_t uid;
+	gid_t gid;
+	off_t size;
+	time_t atime, mtime, ctime;
 	int err;
-	
-	err = put_user (kbuf->st_dev, &ubuf->st_dev);
-	err |= __put_user (kbuf->st_ino, &ubuf->st_ino);
-	err |= __put_user (kbuf->st_mode, &ubuf->st_mode);
-	err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink);
-	err |= __put_user (kbuf->st_uid, &ubuf->st_uid);
-	err |= __put_user (kbuf->st_gid, &ubuf->st_gid);
-	err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev);
-	err |= __put_user (kbuf->st_size, &ubuf->st_size);
-	err |= __put_user (kbuf->st_atime, &ubuf->st_atime);
-	err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime);
-	err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime);
-	err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize);
-	err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks);
+
+	/* Stream the loads of inode data into the load buffer,
+	 * then we push it all into the store buffer below.  This
+	 * should give optimal cache performance.
+	 */
+	ino = inode->i_ino;
+	dev = inode->i_dev;
+	mode = inode->i_mode;
+	nlink = inode->i_nlink;
+	uid = inode->i_uid;
+	gid = inode->i_gid;
+	rdev = inode->i_rdev;
+	size = inode->i_size;
+	atime = inode->i_atime;
+	mtime = inode->i_mtime;
+	ctime = inode->i_ctime;
+	blksize = inode->i_blksize;
+	blocks = inode->i_blocks;
+
+	err  = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
+	err |= put_user(ino, &statbuf->st_ino);
+	err |= put_user(mode, &statbuf->st_mode);
+	err |= put_user(nlink, &statbuf->st_nlink);
+	err |= put_user(uid, &statbuf->st_uid);
+	err |= put_user(gid, &statbuf->st_gid);
+	err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
+	err |= put_user(size, &statbuf->st_size);
+	err |= put_user(atime, &statbuf->st_atime);
+	err |= put_user(0, &statbuf->__unused1);
+	err |= put_user(mtime, &statbuf->st_mtime);
+	err |= put_user(0, &statbuf->__unused2);
+	err |= put_user(ctime, &statbuf->st_ctime);
+	err |= put_user(0, &statbuf->__unused3);
+	if (blksize) {
+		err |= put_user(blksize, &statbuf->st_blksize);
+		err |= put_user(blocks, &statbuf->st_blocks);
+	} else {
+		unsigned int tmp_blocks;
+
+#define D_B   7
+#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
+		tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+		if (tmp_blocks > D_B) {
+			unsigned int indirect;
+
+			indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
+			tmp_blocks += indirect;
+			if (indirect > 1) {
+				indirect = (indirect - 1 + I_B - 1) / I_B;
+				tmp_blocks += indirect;
+				if (indirect > 1)
+					tmp_blocks++;
+			}
+		}
+		err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
+		err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
+#undef D_B
+#undef I_B
+	}
+	err |= put_user(0, &statbuf->__unused4[0]);
+	err |= put_user(0, &statbuf->__unused4[1]);
+
 	return err;
 }
 
-extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf);
-
 asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
 {
-	int ret;
-	struct stat s;
-	char *filenam;
-	mm_segment_t old_fs = get_fs();
-	
-	filenam = getname32 (filename);
-	ret = PTR_ERR(filenam);
-	if (!IS_ERR(filenam)) {
-		set_fs (KERNEL_DS);
-		ret = sys_newstat(filenam, &s);
-		set_fs (old_fs);
-		putname (filenam);
-		if (putstat (statbuf, &s))
-			return -EFAULT;
+	struct dentry *dentry;
+	int error;
+
+	lock_kernel();
+	dentry = namei(filename);
+
+	error = PTR_ERR(dentry);
+	if (!IS_ERR(dentry)) {
+		struct inode *inode = dentry->d_inode;
+
+		if (inode->i_op &&
+		    inode->i_op->revalidate)
+			error = inode->i_op->revalidate(dentry);
+		else
+			error = 0;
+		if (!error)
+			error = cp_new_stat32(inode, statbuf);
+
+		dput(dentry);
 	}
-	return ret;
+	unlock_kernel();
+	return error;
 }
 
-extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf);
-
 asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
 {
-	int ret;
-	struct stat s;
-	char *filenam;
-	mm_segment_t old_fs = get_fs();
-	
-	filenam = getname32 (filename);
-	ret = PTR_ERR(filenam);
-	if (!IS_ERR(filenam)) {
-		set_fs (KERNEL_DS);
-		ret = sys_newlstat(filenam, &s);
-		set_fs (old_fs);
-		putname (filenam);
-		if (putstat (statbuf, &s))
-			return -EFAULT;
+	struct dentry *dentry;
+	int error;
+
+	lock_kernel();
+	dentry = lnamei(filename);
+
+	error = PTR_ERR(dentry);
+	if (!IS_ERR(dentry)) {
+		struct inode *inode = dentry->d_inode;
+
+		if (inode->i_op &&
+		    inode->i_op->revalidate)
+			error = inode->i_op->revalidate(dentry);
+		else
+			error = 0;
+		if (!error)
+			error = cp_new_stat32(inode, statbuf);
+
+		dput(dentry);
 	}
-	return ret;
+	unlock_kernel();
+	return error;
 }
 
-extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf);
-
 asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
 {
-	int ret;
-	struct stat s;
-	mm_segment_t old_fs = get_fs();
-	
-	set_fs (KERNEL_DS);
-	ret = sys_newfstat(fd, &s);
-	set_fs (old_fs);
-	if (putstat (statbuf, &s))
-		return -EFAULT;
-	return ret;
+	struct file *f;
+	int err = -EBADF;
+
+	lock_kernel();
+	f = fget(fd);
+	if (f) {
+		struct dentry *dentry = f->f_dentry;
+		struct inode *inode = dentry->d_inode;
+
+		if (inode->i_op &&
+		    inode->i_op->revalidate)
+			err = inode->i_op->revalidate(dentry);
+		else
+			err = 0;
+		if (!err)
+			err = cp_new_stat32(inode, statbuf);
+
+		fput(f);
+	}
+	unlock_kernel();
+	return err;
 }
 
 extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
@@ -1912,8 +2009,8 @@
 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
 
 struct rlimit32 {
-	s32	rlim_cur;
-	s32	rlim_max;
+	u32	rlim_cur;
+	u32	rlim_max;
 };
 
 extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim);
@@ -2523,6 +2620,48 @@
 	return len;
 }
 
+extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
+				     char *optval, int optlen);
+
+asmlinkage int sys32_setsockopt(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	if (optname == SO_ATTACH_FILTER) {
+		struct sock_fprog32 {
+			__u16 len;
+			__u32 filter;
+		} *fprog32 = (struct sock_fprog32 *)optval;
+		struct sock_fprog kfprog;
+		struct sock_filter *kfilter;
+		unsigned int fsize;
+		mm_segment_t old_fs;
+		__u32 uptr;
+		int ret;
+
+		if (get_user(kfprog.len, &fprog32->len) ||
+		    __get_user(uptr, &fprog32->filter))
+			return -EFAULT;
+		kfprog.filter = (struct sock_filter *)A(uptr);
+		fsize = kfprog.len * sizeof(struct sock_filter);
+		kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
+		if (kfilter == NULL)
+			return -ENOMEM;
+		if (copy_from_user(kfilter, kfprog.filter, fsize)) {
+			kfree(kfilter);
+			return -EFAULT;
+		}
+		kfprog.filter = kfilter;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		ret = sys_setsockopt(fd, level, optname,
+				     (char *)&kfprog, sizeof(kfprog));
+		set_fs(old_fs);
+		kfree(kfilter);
+		return ret;
+	}
+	return sys_setsockopt(fd, level, optname, optval, optlen);
+}
+
 /* Argument list sizes for sys_socketcall */
 #define AL(x) ((x) * sizeof(u32))
 static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
@@ -2541,8 +2680,6 @@
 extern asmlinkage int sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
 extern asmlinkage int sys32_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size,
 				     unsigned flags, u32 addr, u32 addr_len);
-extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
-				     char *optval, int optlen);
 extern asmlinkage int sys32_getsockopt(int fd, int level, int optname,
 				       u32 optval, u32 optlen);
 
@@ -2593,7 +2730,7 @@
 		case SYS_SHUTDOWN:
 			return sys_shutdown(a0,a1);
 		case SYS_SETSOCKOPT:
-			return sys_setsockopt(a0, a1, a[2], (char *)A(a[3]), a[4]);
+			return sys32_setsockopt(a0, a1, a[2], (char *)A(a[3]), a[4]);
 		case SYS_GETSOCKOPT:
 			return sys32_getsockopt(a0, a1, a[2], a[3], a[4]);
 		case SYS_SENDMSG:
@@ -2727,8 +2864,9 @@
 
 		if (get_user(str, argv + argc) ||
 		    !str ||
-		    !(len = strlen_user((char *)A(str))))
+		    !(len = strnlen_user((char *)A(str), bprm->p)))
 			return -EFAULT;
+
 		if (bprm->p < len)
 			return -E2BIG;
 
@@ -2736,20 +2874,38 @@
 
 		pos = bprm->p;
 		while (len) {
-			char *pag;
-			int offset, bytes_to_copy;
+			char *kaddr;
+			struct page *page;
+			int offset, bytes_to_copy, new, err;
 
 			offset = pos % PAGE_SIZE;
-			if (!(pag = (char *) bprm->page[pos/PAGE_SIZE]) &&
-			    !(pag = (char *) bprm->page[pos/PAGE_SIZE] =
-			      (unsigned long *) get_free_page(GFP_USER)))
-				return -ENOMEM;
+			page = bprm->page[pos / PAGE_SIZE];
+			new = 0;
+			if (!page) {
+				page = alloc_page(GFP_USER);
+				bprm->page[pos / PAGE_SIZE] = page;
+				if (!page)
+					return -ENOMEM;
+				new = 1;
+			}
+			kaddr = (char *)kmap(page);
 
+			if (new && offset)
+				memset(kaddr, 0, offset);
 			bytes_to_copy = PAGE_SIZE - offset;
-			if (bytes_to_copy > len)
+			if (bytes_to_copy > len) {
 				bytes_to_copy = len;
+				if (new)
+					memset(kaddr+offset+len, 0,
+					       PAGE_SIZE-offset-len);
+			}
+
+			err = copy_from_user(kaddr + offset, (char *)A(str),
+					     bytes_to_copy);
+			flush_page_to_ram(page);
+			kunmap((unsigned long)kaddr);
 
-			if (copy_from_user(pag + offset, (char *)A(str), bytes_to_copy))
+			if (err)
 				return -EFAULT;
 
 			pos += bytes_to_copy;
@@ -2772,8 +2928,7 @@
 	int i;
 
 	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
-	for (i=0 ; i<MAX_ARG_PAGES ; i++)	/* clear page-table */
-		bprm.page[i] = 0;
+	memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
 
 	dentry = open_namei(filename, 0, 0);
 	retval = PTR_ERR(dentry);
@@ -2822,7 +2977,8 @@
 		dput(bprm.dentry);
 
 	for (i=0 ; i<MAX_ARG_PAGES ; i++)
-		free_page(bprm.page[i]);
+		if (bprm.page[i])
+			__free_page(bprm.page[i]);
 
 	return retval;
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- v2.3.34/linux/arch/sparc64/kernel/sys_sunos32.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.31 1999/08/30 10:01:19 davem Exp $
+/* $Id: sys_sunos32.c,v 1.33 1999/12/15 14:24:25 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -162,10 +162,10 @@
 	 * simple, it hopefully works in most obvious cases.. Easy to
 	 * fool it, but this should catch most mistakes.
 	 */
-	freepages = atomic_read(&buffermem) >> PAGE_SHIFT;
+	freepages = atomic_read(&buffermem_pages) >> PAGE_SHIFT;
 	freepages += atomic_read(&page_cache_size);
 	freepages >>= 1;
-	freepages += nr_free_pages;
+	freepages += nr_free_pages();
 	freepages += nr_swap_pages;
 	freepages -= num_physpages >> 4;
 	freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S
--- v2.3.34/linux/arch/sparc64/kernel/systbls.S	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/kernel/systbls.S	Tue Dec 21 21:56:42 1999
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.56 1999/07/31 00:06:17 davem Exp $
+/* $Id: systbls.S,v 1.61 1999/12/21 14:09:15 jj Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -10,6 +10,8 @@
  * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  */
 
+#include <linux/config.h>
+
 	.text
 	.align	1024
 
@@ -28,12 +30,12 @@
 /*40*/	.word sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_nis_syscall
 	.word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
 /*50*/	.word sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl
-	.word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys32_execve
-/*60*/	.word sys_umask, sys_chroot, sys32_newfstat, sys_nis_syscall, sys_getpagesize
+	.word sys_reboot, sys32_mmap2, sys_symlink, sys_readlink, sys32_execve
+/*60*/	.word sys_umask, sys_chroot, sys32_newfstat, sys_fstat64, sys_getpagesize
 	.word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_nis_syscall
 /*70*/	.word sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys_munmap, sys_mprotect
-	.word sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys32_getgroups
-/*80*/	.word sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys_nis_syscall
+	.word sys_nis_syscall, sys_vhangup, sys32_truncate64, sys_nis_syscall, sys32_getgroups
+/*80*/	.word sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys32_ftruncate64
 	.word sys_swapon, sys32_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall
 /*90*/	.word sys_dup2, sys_nis_syscall, sys32_fcntl, sys32_select, sys_nis_syscall
 	.word sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
@@ -43,8 +45,8 @@
 	.word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
 /*120*/	.word sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod
 	.word sys_nis_syscall, sys32_setreuid, sys32_setregid, sys_rename, sys_truncate
-/*130*/	.word sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-	.word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_nis_syscall
+/*130*/	.word sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall
+	.word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_stat64
 /*140*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit
 	.word sys32_setrlimit, sys_nis_syscall, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write
 /*150*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall
@@ -129,6 +131,8 @@
 /*250*/	.word sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
 	.word sys_aplib
 
+#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
+    defined(CONFIG_SOLARIS_EMUL_MODULE)
 	/* Now the 32-bit SunOS syscall table. */
 
 	.align 1024
@@ -221,3 +225,5 @@
 	.word sunos_nosys, sunos_nosys
 /*250*/	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_nosys, sunos_nosys, sys_aplib
+
+#endif
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c
--- v2.3.34/linux/arch/sparc64/kernel/time.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/kernel/time.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.22 1999/08/30 10:01:22 davem Exp $
+/* $Id: time.c,v 1.23 1999/09/21 14:35:27 davem Exp $
  * time.c: UltraSparc timer and TOD clock support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -268,7 +268,7 @@
 	int node, busnd = -1, err;
 	unsigned long flags;
 #ifdef CONFIG_PCI
-	struct linux_ebus *ebus = 0;
+	struct linux_ebus *ebus = NULL;
 #endif
 
 	__save_and_cli(flags);
@@ -282,8 +282,8 @@
 		busnd = ebus->prom_node;
 	}
 #endif
-	else {
-		busnd = SBus_chain->prom_node;
+	else if (sbus_root != NULL) {
+		busnd = sbus_root->prom_node;
 	}
 
 	if(busnd == -1) {
@@ -304,9 +304,9 @@
 		   	if (node)
 				node = prom_getsibling(node);
 #ifdef CONFIG_PCI
-			while ((node == 0) && ebus) {
+			while ((node == 0) && ebus != NULL) {
 				ebus = ebus->next;
-				if (ebus) {
+				if (ebus != NULL) {
 					busnd = ebus->prom_node;
 					node = prom_getchild(busnd);
 				}
@@ -327,17 +327,17 @@
 		}
 
 		if(central_bus) {
-			prom_apply_fhc_ranges(central_bus->child, clk_reg, 1);
-			prom_apply_central_ranges(central_bus, clk_reg, 1);
+			apply_fhc_ranges(central_bus->child, clk_reg, 1);
+			apply_central_ranges(central_bus, clk_reg, 1);
 		}
 #ifdef CONFIG_PCI
-		else if (ebus_chain) {
+		else if (ebus_chain != NULL) {
 			struct linux_ebus_device *edev;
 
 			for_each_ebusdev(edev, ebus)
 				if (edev->prom_node == node)
 					break;
-			if (!edev) {
+			if (edev == NULL) {
 				prom_printf("%s: Mostek not probed by EBUS\n",
 					    __FUNCTION__);
 				prom_halt();
@@ -349,9 +349,24 @@
 		}
 #endif
 		else {
-			prom_adjust_regs(clk_reg, 1,
-					 SBus_chain->sbus_ranges,
-					 SBus_chain->num_sbus_ranges);
+			if (sbus_root->num_sbus_ranges) {
+				int nranges = sbus_root->num_sbus_ranges;
+				int rngc;
+
+				for (rngc = 0; rngc < nranges; rngc++)
+					if (clk_reg[0].which_io ==
+					    sbus_root->sbus_ranges[rngc].ot_child_space)
+						break;
+				if (rngc == nranges) {
+					prom_printf("clock_probe: Cannot find ranges for "
+						    "clock regs.\n");
+					prom_halt();
+				}
+				clk_reg[0].which_io =
+					sbus_root->sbus_ranges[rngc].ot_parent_space;
+				clk_reg[0].phys_addr +=
+					sbus_root->sbus_ranges[rngc].ot_parent_base;
+			}
 		}
 
 		if(model[5] == '0' && model[6] == '2') {
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/trampoline.S linux/arch/sparc64/kernel/trampoline.S
--- v2.3.34/linux/arch/sparc64/kernel/trampoline.S	Thu Nov 18 20:25:37 1999
+++ linux/arch/sparc64/kernel/trampoline.S	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: trampoline.S,v 1.10 1999/09/10 10:40:48 davem Exp $
+/* $Id: trampoline.S,v 1.12 1999/12/15 15:45:12 davem Exp $
  * trampoline.S: Jump start slave processors on sparc64.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -14,21 +14,107 @@
 #include <asm/asm_offsets.h>
 
 	.data
-	.align		8
-	.globl		smp_trampoline
-smp_trampoline:		.skip	0x300
+	.align	8
+call_method:
+	.asciz	"call-method"
+	.align	8
+itlb_load:
+	.asciz	"SUNW,itlb-load"
+	.align	8
+dtlb_load:
+	.asciz	"SUNW,dtlb-load"
 
 	.text
 	.align		8
 	.globl		sparc64_cpu_startup, sparc64_cpu_startup_end
 sparc64_cpu_startup:
 	flushw
+
 	mov	(LSU_CONTROL_IC | LSU_CONTROL_DC | LSU_CONTROL_IM | LSU_CONTROL_DM), %g1
 	stxa	%g1, [%g0] ASI_LSU_CONTROL
 	membar	#Sync
-	wrpr	%g0, (PSTATE_PRIV | PSTATE_PEF | PSTATE_IE), %pstate
-	wr	%g0, 0, %fprs
+
 	wrpr	%g0, 15, %pil
+	wr	%g0, 0, %tick_cmpr
+
+	/* Call OBP by hand to lock KERNBASE into i/d tlbs. */
+	mov	%o0, %l0
+
+	sethi	%hi(prom_entry_lock), %g2
+1:	ldstub	[%g2 + %lo(prom_entry_lock)], %g1
+	brnz,pn	%g1, 1b
+	 membar	#StoreLoad | #StoreStore
+
+	sethi	%hi(p1275buf), %g2
+	or	%g2, %lo(p1275buf), %g2
+	ldx	[%g2 + 0x10], %l2
+	mov	%sp, %l1
+	add	%l2, -(192 + 128), %sp
+	flushw
+
+	sethi	%hi(call_method), %g2
+	or	%g2, %lo(call_method), %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x00]
+	mov	5, %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x08]
+	mov	1, %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x10]
+	sethi	%hi(itlb_load), %g2
+	or	%g2, %lo(itlb_load), %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x18]
+	sethi	%hi(mmu_ihandle_cache), %g2
+	lduw	[%g2 + %lo(mmu_ihandle_cache)], %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x20]
+	sethi	%hi(KERNBASE), %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x28]
+	sethi	%hi(kern_locked_tte_data), %g2
+	ldx	[%g2 + %lo(kern_locked_tte_data)], %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x30]
+	mov	63, %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x38]
+	sethi	%hi(p1275buf), %g2
+	or	%g2, %lo(p1275buf), %g2
+	ldx	[%g2 + 0x08], %o1
+	call	%o1
+	 add	%sp, (2047 + 128), %o0
+
+	sethi	%hi(call_method), %g2
+	or	%g2, %lo(call_method), %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x00]
+	mov	5, %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x08]
+	mov	1, %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x10]
+	sethi	%hi(dtlb_load), %g2
+	or	%g2, %lo(dtlb_load), %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x18]
+	sethi	%hi(mmu_ihandle_cache), %g2
+	lduw	[%g2 + %lo(mmu_ihandle_cache)], %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x20]
+	sethi	%hi(KERNBASE), %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x28]
+	sethi	%hi(kern_locked_tte_data), %g2
+	ldx	[%g2 + %lo(kern_locked_tte_data)], %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x30]
+	mov	63, %g2
+	stx	%g2, [%sp + 2047 + 128 + 0x38]
+	sethi	%hi(p1275buf), %g2
+	or	%g2, %lo(p1275buf), %g2
+	ldx	[%g2 + 0x08], %o1
+	call	%o1
+	 add	%sp, (2047 + 128), %o0
+
+	sethi	%hi(prom_entry_lock), %g2
+	stb	%g0, [%g2 + %lo(prom_entry_lock)]
+	membar	#StoreStore | #StoreLoad
+
+	mov	%l1, %sp
+	flushw
+
+	mov	%l0, %o0
+
+	wrpr	%g0, (PSTATE_PRIV | PSTATE_PEF), %pstate
+	wr	%g0, 0, %fprs
 
 	sethi	%uhi(PAGE_OFFSET), %g4
 	sllx	%g4, 32, %g4
@@ -37,99 +123,6 @@
 	srl	%o0, 0, %o0
 	ldx	[%o0], %g6
 
-	sethi	%uhi(_PAGE_VALID | _PAGE_SZ4MB), %g5
-	sllx	%g5, 32, %g5
-	or	%g5, (_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W | _PAGE_G), %g5
-
-	sethi	%uhi(_PAGE_PADDR), %g3
-	or	%g3, %ulo(_PAGE_PADDR), %g3
-	sllx	%g3, 32, %g3
-	sethi	%hi(_PAGE_PADDR), %g7
-	or	%g7, %lo(_PAGE_PADDR), %g7
-	or	%g3, %g7, %g3
-
-	clr	%l0
-	set	0x1fff, %l2
-	rd	%pc, %l3
-	andn	%l3, %l2, %g2
-1:	ldxa	[%l0] ASI_ITLB_TAG_READ, %g1
-	nop
-	nop
-	nop
-	andn	%g1, %l2, %g1
-	cmp	%g1, %g2
-	be,a,pn	%xcc, 2f
-	 ldxa	[%l0] ASI_ITLB_DATA_ACCESS, %g1
-	cmp	%l0, (63 << 3)
-	blu,pt	%xcc, 1b
-	 add	%l0, (1 << 3), %l0
-
-2:	nop
-	nop
-	nop
-	and	%g1, %g3, %g1
-	sub	%g1, %g2, %g1
-	or	%g5, %g1, %g5
-	clr	%l0
-	sethi	%hi(KERNBASE), %g3
-	sethi	%hi(KERNBASE<<1), %g7
-	mov	TLB_TAG_ACCESS, %l7
-1:	ldxa	[%l0] ASI_ITLB_TAG_READ, %g1
-	nop
-	nop
-	nop
-	andn	%g1, %l2, %g1
-	cmp	%g1, %g3
-	blu,pn	%xcc, 2f
-	 cmp	%g1, %g7
-	bgeu,pn	%xcc, 2f
-	 nop
-	stxa	%g0, [%l7] ASI_IMMU
-	stxa	%g0, [%l0] ASI_ITLB_DATA_ACCESS
-2:	cmp	%l0, (63 << 3)
-	blu,pt	%xcc, 1b
-	 add	%l0, (1 << 3), %l0
-
-	nop
-	nop
-	nop
-	clr	%l0
-1:	ldxa	[%l0] ASI_DTLB_TAG_READ, %g1
-	nop
-	nop
-	nop
-	andn	%g1, %l2, %g1
-	cmp	%g1, %g3
-	blu,pn	%xcc, 2f
-	 cmp	%g1, %g7
-	bgeu,pn	%xcc, 2f
-	 nop
-	stxa	%g0, [%l7] ASI_DMMU
-	stxa	%g0, [%l0] ASI_DTLB_DATA_ACCESS
-2:	cmp	%l0, (63 << 3)
-	blu,pt	%xcc, 1b
-	 add	%l0, (1 << 3), %l0
-
-	nop
-	nop
-	nop
-	sethi	%hi(KERNBASE), %g3
-	mov	(63 << 3), %g7
-	stxa	%g3, [%l7] ASI_DMMU
-	stxa	%g5, [%g7] ASI_DTLB_DATA_ACCESS
-	membar	#Sync
-	stxa	%g3, [%l7] ASI_IMMU
-	stxa	%g5, [%g7] ASI_ITLB_DATA_ACCESS
-	membar	#Sync
-	flush	%g3
-	membar	#Sync
-	b,pt	%xcc, 1f
-	 nop
-1:	set	bounce, %g2
-	jmpl	%g2 + %g0, %g0
-	 nop
-
-bounce:
 	wr	%g0, ASI_P, %asi
 
 	mov	PRIMARY_CONTEXT, %g7
@@ -139,24 +132,6 @@
 	stxa	%g0, [%g7] ASI_DMMU
 	membar	#Sync
 
-	mov	TLB_TAG_ACCESS, %g2
-	stxa	%g3, [%g2] ASI_IMMU
-	stxa	%g3, [%g2] ASI_DMMU
-
-	mov	(63 << 3), %g7
-	ldxa	[%g7] ASI_ITLB_DATA_ACCESS, %g1
-	andn	%g1, (_PAGE_G), %g1
-	stxa	%g1, [%g7] ASI_ITLB_DATA_ACCESS
-	membar	#Sync
-
-	ldxa	[%g7] ASI_DTLB_DATA_ACCESS, %g1
-	andn	%g1, (_PAGE_G), %g1
-	stxa	%g1, [%g7] ASI_DTLB_DATA_ACCESS
-	membar	#Sync
-
-	flush	%g3
-	membar	#Sync
-
 	mov	1, %g5
 	sllx	%g5, (PAGE_SHIFT + 1), %g5
 	sub	%g5, (REGWIN_SZ + STACK_BIAS), %g5
@@ -169,12 +144,12 @@
 	/* Setup the trap globals, then we can resurface. */
 	rdpr	%pstate, %o1
 	mov	%g6, %o2
-	wrpr	%o1, (PSTATE_AG | PSTATE_IE), %pstate
+	wrpr	%o1, PSTATE_AG, %pstate
 	sethi	%hi(sparc64_ttable_tl0), %g5
 	wrpr	%g5, %tba
 	mov	%o2, %g6
 
-	wrpr	%o1, (PSTATE_MG | PSTATE_IE), %pstate
+	wrpr	%o1, PSTATE_MG, %pstate
 #define KERN_HIGHBITS		((_PAGE_VALID | _PAGE_SZ4MB) ^ 0xfffff80000000000)
 #define KERN_LOWBITS		(_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
 #ifdef THIS_IS_CHEETAH
@@ -200,7 +175,7 @@
 #undef VPTE_BASE
 
 	/* Setup interrupt globals, we are always SMP. */
-	wrpr	%o1, (PSTATE_IG | PSTATE_IE), %pstate
+	wrpr	%o1, PSTATE_IG, %pstate
 
 	/* Get our UPA MID. */
 	lduw	[%o2 + AOFF_task_processor], %g1
@@ -210,11 +185,14 @@
 	/* In theory this is: &(cpu_data[this_upamid].irq_worklists[0]) */
 	sllx	%g1, 7, %g1
 	add	%g5, %g1, %g1
-	add	%g1, 64, %g1
+	add	%g1, 64, %g6
 
 	wrpr	%g0, 0, %wstate
 	or	%o1, PSTATE_IE, %o1
 	wrpr	%o1, 0, %pstate
+
+	call	prom_set_trap_table
+	 sethi	%hi(sparc64_ttable_tl0), %o0
 
 	call	smp_callin
 	 nop
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c
--- v2.3.34/linux/arch/sparc64/kernel/traps.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/kernel/traps.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.62 1999/08/31 19:25:35 davem Exp $
+/* $Id: traps.c,v 1.64 1999/12/19 23:53:13 davem Exp $
  * arch/sparc64/kernel/traps.c
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -26,6 +26,7 @@
 #include <asm/uaccess.h>
 #include <asm/fpumacro.h>
 #include <asm/lsu.h>
+#include <asm/psrcompat.h>
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
@@ -519,8 +520,22 @@
 		regs->tpc = regs->tnpc;
 		regs->tnpc += 4;
 	} else {
+		unsigned long fsr = current->thread.xfsr[0];
+
 		current->thread.sig_address = regs->tpc;
 		current->thread.sig_desc = SUBSIG_FPERROR;
+		if ((fsr & 0x1c000) == (1 << 14)) {
+			if (fsr & 0x01)
+				current->thread.sig_desc = SUBSIG_FPINEXACT;
+			else if (fsr & 0x02)
+				current->thread.sig_desc = SUBSIG_FPDIVZERO;
+			else if (fsr & 0x04)
+				current->thread.sig_desc = SUBSIG_FPUNFLOW;
+			else if (fsr & 0x08)
+				current->thread.sig_desc = SUBSIG_FPOVFLOW;
+			else if (fsr & 0x10)
+				current->thread.sig_desc = SUBSIG_FPINTOVFL;
+		}
 		send_sig(SIGFPE, current, 1);
 	}
 }
@@ -564,7 +579,9 @@
 
 void do_div0(struct pt_regs *regs)
 {
-	send_sig(SIGILL, current, 1);
+	current->thread.sig_address = regs->tpc;
+	current->thread.sig_desc = SUBSIG_IDIVZERO;
+	send_sig(SIGFPE, current, 1);
 }
 
 void instruction_dump (unsigned int *pc)
@@ -712,10 +729,12 @@
 	send_sig(SIGILL, current, 1);
 }
 
-void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
-		       unsigned long psr)
+void handle_hw_divzero(struct pt_regs *regs, unsigned long pc,
+		       unsigned long npc, unsigned long psr)
 {
-	send_sig(SIGILL, current, 1);
+	current->thread.sig_address = regs->tpc;
+	current->thread.sig_desc = SUBSIG_IDIVZERO;
+	send_sig(SIGFPE, current, 1);
 }
 
 /* Trap level 1 stuff or other traps we should never see... */
@@ -841,6 +860,13 @@
 #endif
 }
 #endif
+
+void do_getpsr(struct pt_regs *regs)
+{
+	regs->u_regs[UREG_I0] = tstate_to_psr(regs->tstate);
+	regs->tpc   = regs->tnpc;
+	regs->tnpc += 4;
+}
 
 void trap_init(void)
 {
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/ttable.S linux/arch/sparc64/kernel/ttable.S
--- v2.3.34/linux/arch/sparc64/kernel/ttable.S	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/kernel/ttable.S	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ttable.S,v 1.29 1999/08/31 19:25:37 davem Exp $
+/* $Id: ttable.S,v 1.30 1999/12/01 23:52:03 davem Exp $
  * ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -120,7 +120,8 @@
 tl0_resv11e:	TRAP_UTRAP(UT_TRAP_INSTRUCTION_30,0x11e) TRAP_UTRAP(UT_TRAP_INSTRUCTION_31,0x11f)
 tl0_getcc:	GETCC_TRAP
 tl0_setcc:	SETCC_TRAP
-tl0_resv122:	BTRAP(0x122) BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126)
+tl0_getpsr:	TRAP(do_getpsr)
+tl0_resv123:	BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126)
 tl0_solindir:	INDIRECT_SOLARIS_SYSCALL(156)
 tl0_resv128:	BTRAP(0x128) BTRAP(0x129) BTRAP(0x12a) BTRAP(0x12b) BTRAP(0x12c)
 tl0_resv12d:	BTRAP(0x12d) BTRAP(0x12e) BTRAP(0x12f) BTRAP(0x130) BTRAP(0x131)
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S
--- v2.3.34/linux/arch/sparc64/lib/blockops.S	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/lib/blockops.S	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: blockops.S,v 1.18 1999/07/30 09:35:37 davem Exp $
+/* $Id: blockops.S,v 1.19 1999/11/19 05:52:45 davem Exp $
  * blockops.S: UltraSparc block zero optimized routines.
  *
  * Copyright (C) 1996,1998 David S. Miller (davem@caip.rutgers.edu)
@@ -136,19 +136,19 @@
 
 	faddd		%f0, %f2, %f12			! FPA	Group
 	fmuld		%f0, %f2, %f14			! FPM
-	rd		%asi, %g2			! LSU	Group
-	wr		%g0, ASI_BLK_P, %asi		! LSU	Group
 	membar		#StoreLoad | #StoreStore | #LoadStore	! LSU	Group
-1:	stda		%f0, [%o0 + 0x00] %asi		! Store	Group
-	stda		%f0, [%o0 + 0x40] %asi		! Store	Group
-	stda		%f0, [%o0 + 0x80] %asi		! Store	Group
-	stda		%f0, [%o0 + 0xc0] %asi		! Store	Group
+1:	stda		%f0, [%o0 + %g0] ASI_BLK_P	! Store	Group
+	add		%o0, 0x40, %o0			! IEU0
+	stda		%f0, [%o0 + %g0] ASI_BLK_P	! Store	Group
+	add		%o0, 0x40, %o0			! IEU0
+	stda		%f0, [%o0 + %g0] ASI_BLK_P	! Store	Group
 
+	add		%o0, 0x40, %o0			! IEU0	Group
+	stda		%f0, [%o0 + %g0] ASI_BLK_P	! Store	Group
 	subcc		%o1, 1, %o1			! IEU1
 	bne,pt		%icc, 1b			! CTI
-	 add		%o0, 0x100, %o0			! IEU0	Group
+	 add		%o0, 0x40, %o0			! IEU0	Group
 	membar		#Sync				! LSU	Group
-	wr		%g2, %g0, %asi			! LSU	Group
 	VISExitHalf
 
 	stxa		%g5, [%o2] ASI_DMMU
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/lib/strlen_user.S linux/arch/sparc64/lib/strlen_user.S
--- v2.3.34/linux/arch/sparc64/lib/strlen_user.S	Thu May 27 09:55:21 1999
+++ linux/arch/sparc64/lib/strlen_user.S	Mon Dec 20 22:05:52 1999
@@ -4,7 +4,7 @@
  * or 0 for error
  *
  * Copyright (C) 1991,1996 Free Software Foundation
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1999 David S. Miller (davem@redhat.com)
  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
@@ -14,8 +14,11 @@
 #define HI_MAGIC 0x80808080
 
 	.align 4
-	.global __strlen_user
+	.global __strlen_user, __strnlen_user
 __strlen_user:
+	sethi	%hi(32768), %o1
+__strnlen_user:	
+	mov	%o1, %g1
 	mov	%o0, %o1
 	andcc	%o0, 3, %g0
 	be,pt	%icc, 9f
@@ -42,11 +45,16 @@
 13:	lda	[%o0] %asi, %o5
 2:	sub	%o5, %o2, %o4
 	andcc	%o4, %o3, %g0
-	be,pt	%icc, 13b
+	bne,pn	%icc, 82f
 	 add	%o0, 4, %o0
+	sub	%o0, %o1, %g2
+81:	cmp	%g2, %g1
+	blu,pt	%icc, 13b
+	 mov	%o0, %o4
+	ba,a,pt	%xcc, 1f
 
 	/* Check every byte. */
-	srl	%o5, 24, %g5
+82:	srl	%o5, 24, %g5
 	andcc	%g5, 0xff, %g0
 	be,pn	%icc, 1f
 	 add	%o0, -3, %o4
@@ -59,8 +67,8 @@
 	be,pn	%icc, 1f
 	 add	%o4, 1, %o4
 	andcc	%o5, 0xff, %g0
-	bne,a,pt %icc, 2b
-14:	 lda	[%o0] %asi, %o5
+	bne,pt	%icc, 81b
+	 sub	%o0, %o1, %g2
 	add	%o4, 1, %o4
 1:	retl
 	 sub	%o4, %o1, %o0
@@ -85,4 +93,3 @@
 	.word	12b, 30b
 	.word	15b, 30b
 	.word	13b, 30b
-	.word	14b, 30b
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/math-emu/math.c linux/arch/sparc64/math-emu/math.c
--- v2.3.34/linux/arch/sparc64/math-emu/math.c	Tue Dec  7 09:32:42 1999
+++ linux/arch/sparc64/math-emu/math.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: math.c,v 1.10 1999/08/13 16:02:06 jj Exp $
+/* $Id: math.c,v 1.11 1999/12/20 05:02:25 davem Exp $
  * arch/sparc64/math-emu/math.c
  *
  * Copyright (C) 1997,1999 Jakub Jelinek (jj@ultra.linux.cz)
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/math-emu/sfp-util.h linux/arch/sparc64/math-emu/sfp-util.h
--- v2.3.34/linux/arch/sparc64/math-emu/sfp-util.h	Wed Jun  9 14:44:25 1999
+++ linux/arch/sparc64/math-emu/sfp-util.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: sfp-util.h,v 1.2 1999/06/07 18:24:15 jj Exp $
+/* $Id: sfp-util.h,v 1.4 1999/09/20 12:14:19 jj Exp $
  * arch/sparc64/math-emu/sfp-util.h
  *
  * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/mm/asyncd.c linux/arch/sparc64/mm/asyncd.c
--- v2.3.34/linux/arch/sparc64/mm/asyncd.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/mm/asyncd.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/*  $Id: asyncd.c,v 1.9 1999/07/30 09:35:43 davem Exp $
+/*  $Id: asyncd.c,v 1.10 1999/12/15 22:25:02 davem Exp $
  *  The asyncd kernel daemon. This handles paging on behalf of 
  *  processes that receive page faults due to remote (async) memory
  *  accesses. 
@@ -25,6 +25,7 @@
 #include <asm/system.h> /* for cli()/sti() */
 #include <asm/segment.h> /* for memcpy_to/fromfs */
 #include <asm/bitops.h>
+#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 
 #define DEBUG 0
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c
--- v2.3.34/linux/arch/sparc64/mm/fault.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/mm/fault.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.39 1999/08/30 10:07:09 davem Exp $
+/* $Id: fault.c,v 1.40 1999/12/01 10:44:53 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)
@@ -113,7 +113,9 @@
 	ptep = pte_offset(pmdp, tpc);
 	if(!pte_present(*ptep))
 		return 0;
-	insn = *(unsigned int *)(pte_page(*ptep) + (tpc & ~PAGE_MASK));
+	insn = *(unsigned int *)
+		((unsigned long)__va(pte_pagenr(*ptep) << PAGE_SHIFT) +
+		 (tpc & ~PAGE_MASK));
 #else
 	register unsigned long pte asm("l1");
 
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/mm/generic.c linux/arch/sparc64/mm/generic.c
--- v2.3.34/linux/arch/sparc64/mm/generic.c	Tue Dec  7 09:32:42 1999
+++ linux/arch/sparc64/mm/generic.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: generic.c,v 1.9 1999/07/23 22:32:01 davem Exp $
+/* $Id: generic.c,v 1.13 1999/12/20 05:02:33 davem Exp $
  * generic.c: Generic Sparc mm routines that are not dependent upon
  *            MMU type but are Sparc specific.
  *
@@ -9,46 +9,26 @@
 #include <linux/mm.h>
 #include <linux/swap.h>
 
+#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 
-
-/* Allocate a block of RAM which is aligned to its size.
- * This procedure can be used until the call to mem_init().
- */
-void *sparc_init_alloc(unsigned long *kbrk, unsigned long size)
-{
-        unsigned long mask = size - 1;
-        unsigned long ret;
-
-        if(!size)
-                return 0x0;
-        if(size & mask) {
-                prom_printf("panic: sparc_init_alloc botch\n");
-                prom_halt();
-        }
-        ret = (*kbrk + mask) & ~mask;
-        *kbrk = ret + size;
-        memset((void*) ret, 0, size);
-        return (void*) ret;
-}
-
 static inline void forget_pte(pte_t page)
 {
 	if (pte_none(page))
 		return;
 	if (pte_present(page)) {
-		unsigned long addr = pte_page(page);
-		if (MAP_NR(addr) >= max_mapnr || PageReserved(mem_map+MAP_NR(addr)))
+		unsigned long nr = pte_pagenr(page);
+		if (nr >= max_mapnr || PageReserved(mem_map+nr))
 			return;
 		/* 
 		 * free_page() used to be able to clear swap cache
 		 * entries.  We may now have to do it manually.  
 		 */
-		free_page_and_swap_cache(addr);
+		free_page_and_swap_cache(mem_map+nr);
 		return;
 	}
-	swap_free(pte_val(page));
+	swap_free(pte_to_swp_entry(page));
 }
 
 /* Remap IO memory, the same way as remap_page_range(), but use
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.3.34/linux/arch/sparc64/mm/init.c	Fri Oct 22 13:21:47 1999
+++ linux/arch/sparc64/mm/init.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.135 1999/09/06 22:55:10 ecd Exp $
+/*  $Id: init.c,v 1.143 1999/12/16 16:15:14 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -6,8 +6,11 @@
  */
  
 #include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
 #include <linux/blk.h>
@@ -17,6 +20,7 @@
 #include <asm/head.h>
 #include <asm/system.h>
 #include <asm/page.h>
+#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
 #include <asm/iommu.h>
@@ -26,13 +30,8 @@
 #include <asm/vaddrs.h>
 #include <asm/dma.h>
 
-/* Turn this off if you suspect some place in some physical memory hole
-   might get into page tables (something would be broken very much). */
-   
-#define FREE_UNUSED_MEM_MAP
-
 extern void show_net_buffers(void);
-extern unsigned long device_scan(unsigned long);
+extern void device_scan(void);
 
 struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
 
@@ -41,6 +40,8 @@
 /* Ugly, but necessary... -DaveM */
 unsigned long phys_base;
 
+static unsigned long totalram_pages = 0;
+
 /* get_new_mmu_context() uses "cache + 1".  */
 spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED;
 unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
@@ -48,7 +49,7 @@
 unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
 
 /* References to section boundaries */
-extern char __init_begin, __init_end, etext, __bss_start;
+extern char __init_begin, __init_end, _start, _end, etext, edata;
 
 int do_check_pgt_cache(int low, int high)
 {
@@ -60,8 +61,10 @@
 			if(pgd_quicklist)
 				free_pgd_slow(get_pgd_fast()), freed++;
 #endif
-			if(pte_quicklist)
-				free_pte_slow(get_pte_fast()), freed++;
+			if(pte_quicklist[0])
+				free_pte_slow(get_pte_fast(0)), freed++;
+			if(pte_quicklist[1])
+				free_pte_slow(get_pte_fast(1)), freed++;
 		} while(pgtable_cache_size > low);
 	}
 #ifndef __SMP__ 
@@ -110,42 +113,20 @@
 pte_t __bad_page(void)
 {
 	memset((void *) &empty_bad_page, 0, PAGE_SIZE);
-	return pte_mkdirty(mk_pte((((unsigned long) &empty_bad_page) 
-		- ((unsigned long)&empty_zero_page) + phys_base + PAGE_OFFSET),
-				  PAGE_SHARED));
+	return pte_mkdirty(mk_pte_phys((((unsigned long) &empty_bad_page) 
+					- ((unsigned long)&empty_zero_page)
+					+ phys_base),
+				       PAGE_SHARED));
 }
 
 void show_mem(void)
 {
-	int free = 0,total = 0,reserved = 0;
-	int shared = 0, cached = 0;
-	struct page *page, *end;
-
-	printk("\nMem-info:\n");
+	printk("Mem-info:\n");
 	show_free_areas();
-	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-	for (page = mem_map, end = mem_map + max_mapnr;
-	     page < end; page++) {
-		if (PageSkip(page)) {
-			if (page->next_hash < page)
-				break;
-			page = page->next_hash;
-		}
-		total++;
-		if (PageReserved(page))
-			reserved++;
-		else if (PageSwapCache(page))
-			cached++;
-		else if (!atomic_read(&page->count))
-			free++;
-		else
-			shared += atomic_read(&page->count) - 1;
-	}
-	printk("%d pages of RAM\n",total);
-	printk("%d free pages\n",free);
-	printk("%d reserved pages\n",reserved);
-	printk("%d pages shared\n",shared);
-	printk("%d pages swap cached\n",cached);
+	printk("Free swap:       %6dkB\n",
+	       nr_swap_pages << (PAGE_SHIFT-10));
+	printk("%ld pages of RAM\n", totalram_pages);
+	printk("%d free pages\n", nr_free_pages());
 	printk("%d pages in page table cache\n",pgtable_cache_size);
 #ifndef __SMP__
 	printk("%d entries in page dir cache\n",pgd_cache_size);
@@ -156,508 +137,46 @@
 #endif
 }
 
-/* IOMMU support, the ideas are right, the code should be cleaned a bit still... */
-
-/* This keeps track of pages used in sparc_alloc_dvma() invocations. */
-/* NOTE: All of these are inited to 0 in bss, don't need to make data segment bigger */
-#define DVMAIO_SIZE 0x2000000
-static unsigned long dvma_map_pages[DVMAIO_SIZE >> 16];
-static unsigned long dvma_pages_current_offset;
-static int dvma_pages_current_index;
-static unsigned long dvmaiobase = 0;
-static unsigned long dvmaiosz __initdata = 0;
-
-void __init dvmaio_init(void)
-{
-	long i;
-	
-	if (!dvmaiobase) {
-		for (i = 0; sp_banks[i].num_bytes != 0; i++)
-			if (sp_banks[i].base_addr + sp_banks[i].num_bytes > dvmaiobase)
-				dvmaiobase = sp_banks[i].base_addr + sp_banks[i].num_bytes;
-
-		/* We map directly phys_base to phys_base+(4GB-DVMAIO_SIZE). */
-		dvmaiobase -= phys_base;
-
-		dvmaiobase = (dvmaiobase + DVMAIO_SIZE + 0x400000 - 1) & ~(0x400000 - 1);
-		for (i = 0; i < 6; i++)
-			if (dvmaiobase <= ((1024L * 64 * 1024) << i))
-				break;
-		dvmaiobase = ((1024L * 64 * 1024) << i) - DVMAIO_SIZE;
-		dvmaiosz = i;
-	}
-}
-
-void __init iommu_init(int iommu_node, struct linux_sbus *sbus)
-{
-	extern int this_is_starfire;
-	extern void *starfire_hookup(int);
-	struct iommu_struct *iommu;
-	struct sysio_regs *sregs;
-	struct linux_prom64_registers rprop;
-	unsigned long impl, vers;
-	unsigned long control, tsbbase;
-	unsigned long tsbbases[32];
-	unsigned long *iopte;
-	int err, i, j;
-	
-	dvmaio_init();
-	err = prom_getproperty(iommu_node, "reg", (char *)&rprop,
-			       sizeof(rprop));
-	if(err == -1) {
-		prom_printf("iommu_init: Cannot map SYSIO control registers.\n");
-		prom_halt();
-	}
-	sregs = (struct sysio_regs *) __va(rprop.phys_addr);
-
-	if(!sregs) {
-		prom_printf("iommu_init: Fatal error, sysio regs not mapped\n");
-		prom_halt();
-	}
-
-	iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC);
-	if (!iommu) {
-		prom_printf("iommu_init: Fatal error, kmalloc(iommu) failed\n");
-		prom_halt();
-	}
-
-	spin_lock_init(&iommu->iommu_lock);
-	iommu->sysio_regs = sregs;
-	sbus->iommu = iommu;
-
-	control = sregs->iommu_control;
-	impl = (control & IOMMU_CTRL_IMPL) >> 60;
-	vers = (control & IOMMU_CTRL_VERS) >> 56;
-	printk("IOMMU(SBUS): IMPL[%x] VERS[%x] SYSIO mapped at %016lx\n",
-	       (unsigned int) impl, (unsigned int)vers, (unsigned long) sregs);
-	
-	/* Streaming buffer is unreliable on VERS 0 of SYSIO,
-	 * although such parts were never shipped in production
-	 * Sun hardware, I check just to be robust.  --DaveM
-	 */
-	vers = ((sregs->control & SYSIO_CONTROL_VER) >> 56);
-	if (vers == 0)
-		iommu->strbuf_enabled = 0;
-	else
-		iommu->strbuf_enabled = 1;
-
-	control &= ~(IOMMU_CTRL_TSBSZ);
-	control |= ((IOMMU_TSBSZ_2K * dvmaiosz) | IOMMU_CTRL_TBWSZ | IOMMU_CTRL_ENAB);
-
-	/* Use only 64k pages, things are layed out in the 32-bit SBUS
-	 * address space like this:
-	 *
-	 * 0x00000000	  ----------------------------------------
-	 *		  | Direct physical mappings for most    |
-	 *                | DVMA to paddr's within this range    |
-	 * dvmaiobase     ----------------------------------------
-	 * 		  | For mappings requested via           |
-	 *                | sparc_alloc_dvma()		         |
-	 * dvmaiobase+32M ----------------------------------------
-	 *
-	 * NOTE: we need to order 2 contiguous order 5, that's the largest
-	 *       chunk page_alloc will give us.   -JJ */
-	tsbbase = 0;
-	if (dvmaiosz == 6) {
-		memset (tsbbases, 0, sizeof(tsbbases));
-		for (i = 0; i < 32; i++) {
-			tsbbases[i] = __get_free_pages(GFP_DMA, 5);
-			for (j = 0; j < i; j++)
-				if (tsbbases[j] == tsbbases[i] + 32768*sizeof(iopte_t)) {
-					tsbbase = tsbbases[i];
-					break;
-				} else if (tsbbases[i] == tsbbases[j] + 32768*sizeof(iopte_t)) {
-					tsbbase = tsbbases[j];
-					break;
-				}
-			if (tsbbase) {
-				tsbbases[i] = 0;
-				tsbbases[j] = 0;
-				break;
-			}
-		}
-		for (i = 0; i < 32; i++)
-			if (tsbbases[i])
-				free_pages(tsbbases[i], 5);
-	} else
-		tsbbase = __get_free_pages(GFP_DMA, dvmaiosz);
-	if (!tsbbase) {
-		prom_printf("Strange. Could not allocate 512K of contiguous RAM.\n");
-		prom_halt();
-	}
-	iommu->page_table = (iopte_t *) tsbbase;
-	iopte = (unsigned long *) tsbbase;
-
-	/* Setup aliased mappings... */
-	for(i = 0; i < (dvmaiobase >> 16); i++) {
-		unsigned long val = ((((unsigned long)i) << 16UL) + phys_base);
-
-		val |= IOPTE_VALID | IOPTE_64K | IOPTE_WRITE;
-		if (iommu->strbuf_enabled)
-			val |= IOPTE_STBUF;
-		else
-			val |= IOPTE_CACHE;
-		*iopte = val;
-		iopte++;
-	}
-
-	/* Clear all sparc_alloc_dvma() maps. */
-	for( ; i < ((dvmaiobase + DVMAIO_SIZE) >> 16); i++)
-		*iopte++ = 0;
-
-	sregs->iommu_tsbbase = __pa(tsbbase);
-	sregs->iommu_control = control;
-
-	/* Get the streaming buffer going. */
-	control = sregs->sbuf_control;
-	impl = (control & SYSIO_SBUFCTRL_IMPL) >> 60;
-	vers = (control & SYSIO_SBUFCTRL_REV) >> 56;
-	printk("IOMMU: Streaming Buffer IMPL[%x] REV[%x] ... ",
-	       (unsigned int)impl, (unsigned int)vers);
-	iommu->flushflag = 0;
-
-	if (iommu->strbuf_enabled != 0) {
-		sregs->sbuf_control = (control | SYSIO_SBUFCTRL_SB_EN);
-		printk("ENABLED\n");
-	} else {
-		sregs->sbuf_control = (control & ~(SYSIO_SBUFCTRL_SB_EN));
-		printk("DISABLED\n");
-	}
-
-	/* Finally enable DVMA arbitration for all devices, just in case. */
-	sregs->sbus_control |= SYSIO_SBCNTRL_AEN;
-
-	/* If necessary, hook us up for starfire IRQ translations. */
-	sbus->upaid = prom_getintdefault(sbus->prom_node, "upa-portid", -1);
-	if(this_is_starfire)
-		sbus->starfire_cookie = starfire_hookup(sbus->upaid);
-	else
-		sbus->starfire_cookie = NULL;
-}
-
-void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr,
-		      struct linux_sbus *sbus)
-{
-	pgd_t *pgdp;
-	pmd_t *pmdp;
-	pte_t *ptep;
-
-	/* Find out if we need to grab some pages. */
-	if(!dvma_map_pages[dvma_pages_current_index] ||
-	   ((dvma_pages_current_offset + len) > (1 << 16))) {
-		struct linux_sbus *sbus;
-		unsigned long *iopte;
-		unsigned long newpages = __get_free_pages(GFP_KERNEL, 3);
-		int i;
-
-		if(!newpages)
-			panic("AIEEE cannot get DVMA pages.");
-
-		memset((char *)newpages, 0, (1 << 16));
-
-		if(!dvma_map_pages[dvma_pages_current_index]) {
-			dvma_map_pages[dvma_pages_current_index] = newpages;
-			i = dvma_pages_current_index;
-		} else {
-			dvma_map_pages[dvma_pages_current_index + 1] = newpages;
-			i = dvma_pages_current_index + 1;
-		}
-
-		/* Stick it in the IOMMU. */
-		i = (dvmaiobase >> 16) + i;
-		for_each_sbus(sbus) {
-			struct iommu_struct *iommu = sbus->iommu;
-			unsigned long flags;
-
-			spin_lock_irqsave(&iommu->iommu_lock, flags);
-			iopte = (unsigned long *)(iommu->page_table + i);
-			*iopte  = (IOPTE_VALID | IOPTE_64K | IOPTE_CACHE | IOPTE_WRITE);
-			*iopte |= __pa(newpages);
-			spin_unlock_irqrestore(&iommu->iommu_lock, flags);
-		}
-	}
-
-	/* Get this out of the way. */
-	*dvma_addr = (__u32) ((dvmaiobase) +
-			      (dvma_pages_current_index << 16) +
-			      (dvma_pages_current_offset));
-
-	while(len > 0) {
-		while((len > 0) && (dvma_pages_current_offset < (1 << 16))) {
-			pte_t pte;
-			unsigned long the_page =
-				dvma_map_pages[dvma_pages_current_index] +
-				dvma_pages_current_offset;
-
-			/* Map the CPU's view. */
-			pgdp = pgd_offset(&init_mm, addr);
-			pmdp = pmd_alloc_kernel(pgdp, addr);
-			ptep = pte_alloc_kernel(pmdp, addr);
-			pte = mk_pte(the_page, PAGE_KERNEL);
-			set_pte(ptep, pte);
-
-			dvma_pages_current_offset += PAGE_SIZE;
-			addr += PAGE_SIZE;
-			len -= PAGE_SIZE;
-		}
-		dvma_pages_current_index++;
-		dvma_pages_current_offset = 0;
-	}
-}
-
-__u32 mmu_get_scsi_one(char *vaddr, unsigned long len, struct linux_sbus *sbus)
-{
-	struct iommu_struct *iommu = sbus->iommu;
-	struct sysio_regs *sregs = iommu->sysio_regs;
-	unsigned long start = (unsigned long) vaddr;
-	unsigned long end = PAGE_ALIGN(start + len);
-	unsigned long flags, tmp;
-	volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control;
-
-	start &= PAGE_MASK;
-	if (end > MAX_DMA_ADDRESS) {
-		printk("mmu_get_scsi_one: Bogus DMA buffer address [%016lx:%d]\n",
-		       (unsigned long) vaddr, (int)len);
-		panic("DMA address too large, tell DaveM");
-	}
-
-	if (iommu->strbuf_enabled) {
-		volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush;
-
-		spin_lock_irqsave(&iommu->iommu_lock, flags);
-		iommu->flushflag = 0;
-		while(start < end) {
-			*sbuf_pflush = start;
-			start += PAGE_SIZE;
-		}
-		sregs->sbuf_fsync = __pa(&(iommu->flushflag));
-		tmp = *sbctrl;
-		while(iommu->flushflag == 0)
-			membar("#LoadLoad");
-		spin_unlock_irqrestore(&iommu->iommu_lock, flags);
-	}
-
-	return sbus_dvma_addr(vaddr);
-}
-
-void mmu_release_scsi_one(u32 vaddr, unsigned long len, struct linux_sbus *sbus)
-{
-	struct iommu_struct *iommu = sbus->iommu;
-	struct sysio_regs *sregs = iommu->sysio_regs;
-	unsigned long start = (unsigned long) vaddr;
-	unsigned long end = PAGE_ALIGN(start + len);
-	unsigned long flags, tmp;
-	volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control;
-
-	start &= PAGE_MASK;
-
-	if (iommu->strbuf_enabled) {
-		volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush;
-
-		spin_lock_irqsave(&iommu->iommu_lock, flags);
-
-		/* 1) Clear the flush flag word */
-		iommu->flushflag = 0;
-
-		/* 2) Tell the streaming buffer which entries
-		 *    we want flushed.
-		 */
-		while(start < end) {
-			*sbuf_pflush = start;
-			start += PAGE_SIZE;
-		}
-
-		/* 3) Initiate flush sequence. */
-		sregs->sbuf_fsync = __pa(&(iommu->flushflag));
-
-		/* 4) Guarentee completion of all previous writes
-		 *    by reading SYSIO's SBUS control register.
-		 */
-		tmp = *sbctrl;
-
-		/* 5) Wait for flush flag to get set. */
-		while(iommu->flushflag == 0)
-			membar("#LoadLoad");
-
-		spin_unlock_irqrestore(&iommu->iommu_lock, flags);
-	}
-}
-
-void mmu_get_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
-{
-	struct iommu_struct *iommu = sbus->iommu;
-	struct sysio_regs *sregs = iommu->sysio_regs;
-	unsigned long flags, tmp;
-	volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control;
-
-	if (iommu->strbuf_enabled) {
-		volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush;
-
-		spin_lock_irqsave(&iommu->iommu_lock, flags);
-		iommu->flushflag = 0;
-
-		while(sz >= 0) {
-			unsigned long start = (unsigned long)sg[sz].addr;
-			unsigned long end = PAGE_ALIGN(start + sg[sz].len);
-
-			if (end > MAX_DMA_ADDRESS) {
-				printk("mmu_get_scsi_sgl: Bogus DMA buffer address "
-				       "[%016lx:%d]\n", start, (int) sg[sz].len);
-				panic("DMA address too large, tell DaveM");
-			}
-
-			sg[sz--].dvma_addr = sbus_dvma_addr(start);
-			start &= PAGE_MASK;
-			while(start < end) {
-				*sbuf_pflush = start;
-				start += PAGE_SIZE;
-			}
-		}
-
-		sregs->sbuf_fsync = __pa(&(iommu->flushflag));
-		tmp = *sbctrl;
-		while(iommu->flushflag == 0)
-			membar("#LoadLoad");
-		spin_unlock_irqrestore(&iommu->iommu_lock, flags);
-	} else {
-		/* Just verify the addresses and fill in the
-		 * dvma_addr fields in this case.
-		 */
-		while(sz >= 0) {
-			unsigned long start = (unsigned long)sg[sz].addr;
-			unsigned long end = PAGE_ALIGN(start + sg[sz].len);
-			if (end > MAX_DMA_ADDRESS) {
-				printk("mmu_get_scsi_sgl: Bogus DMA buffer address "
-				       "[%016lx:%d]\n", start, (int) sg[sz].len);
-				panic("DMA address too large, tell DaveM");
-			}
-			sg[sz--].dvma_addr = sbus_dvma_addr(start);
-		}
-	}
-}
-
-void mmu_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus)
-{
-	struct iommu_struct *iommu = sbus->iommu;
-	struct sysio_regs *sregs = iommu->sysio_regs;
-	volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control;
-	unsigned long flags, tmp;
-
-	if (iommu->strbuf_enabled) {
-		volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush;
-
-		spin_lock_irqsave(&iommu->iommu_lock, flags);
-
-		/* 1) Clear the flush flag word */
-		iommu->flushflag = 0;
-
-		/* 2) Tell the streaming buffer which entries
-		 *    we want flushed.
-		 */
-		while(sz >= 0) {
-			unsigned long start = sg[sz].dvma_addr;
-			unsigned long end = PAGE_ALIGN(start + sg[sz].len);
-
-			start &= PAGE_MASK;
-			while(start < end) {
-				*sbuf_pflush = start;
-				start += PAGE_SIZE;
-			}
-			sz--;
-		}
-
-		/* 3) Initiate flush sequence. */
-		sregs->sbuf_fsync = __pa(&(iommu->flushflag));
-
-		/* 4) Guarentee completion of previous writes
-		 *    by reading SYSIO's SBUS control register.
-		 */
-		tmp = *sbctrl;
-
-		/* 5) Wait for flush flag to get set. */
-		while(iommu->flushflag == 0)
-			membar("#LoadLoad");
-
-		spin_unlock_irqrestore(&iommu->iommu_lock, flags);
-	}
-}
-
-void mmu_set_sbus64(struct linux_sbus_device *sdev, int bursts)
-{
-	struct linux_sbus *sbus = sdev->my_bus;
-	struct sysio_regs *sregs = sbus->iommu->sysio_regs;
-	int slot = sdev->slot;
-	volatile u64 *cfg;
-	u64 tmp;
-
-	switch(slot) {
-	case 0:
-		cfg = &sregs->sbus_s0cfg;
-		break;
-	case 1:
-		cfg = &sregs->sbus_s1cfg;
-		break;
-	case 2:
-		cfg = &sregs->sbus_s2cfg;
-		break;
-	case 3:
-		cfg = &sregs->sbus_s3cfg;
-		break;
-
-	case 13:
-		cfg = &sregs->sbus_s4cfg;
-		break;
-	case 14:
-		cfg = &sregs->sbus_s5cfg;
-		break;
-	case 15:
-		cfg = &sregs->sbus_s6cfg;
-		break;
-
-	default:
-		return;
-	};
-
-	/* ETM already enabled?  If so, we're done. */
-	tmp = *cfg;
-	if ((tmp & SYSIO_SBSCFG_ETM) != 0)
-		return;
-
-	/* Set burst bits. */
-	if (bursts & DMA_BURST8)
-		tmp |= SYSIO_SBSCFG_BA8;
-	if (bursts & DMA_BURST16)
-		tmp |= SYSIO_SBSCFG_BA16;
-	if (bursts & DMA_BURST32)
-		tmp |= SYSIO_SBSCFG_BA32;
-	if (bursts & DMA_BURST64)
-		tmp |= SYSIO_SBSCFG_BA64;
-
-	/* Finally turn on ETM and set register. */
-	*cfg = (tmp | SYSIO_SBSCFG_ETM);
-}
-
 int mmu_info(char *buf)
 {
 	/* We'll do the rest later to make it nice... -DaveM */
+#if 0
+	if (this_is_cheetah)
+		sprintf(buf, "MMU Type\t: One bad ass cpu\n");
+	else
+#endif
 	return sprintf(buf, "MMU Type\t: Spitfire\n");
 }
 
-static unsigned long mempool;
-
 struct linux_prom_translation {
 	unsigned long virt;
 	unsigned long size;
 	unsigned long data;
 };
 
-static inline void inherit_prom_mappings(void)
+extern unsigned long prom_boot_page;
+extern void prom_remap(unsigned long physpage, unsigned long virtpage, int mmu_ihandle);
+extern int prom_get_mmu_ihandle(void);
+extern void register_prom_callbacks(void);
+
+/* Exported for SMP bootup purposes. */
+unsigned long kern_locked_tte_data;
+
+void __init early_pgtable_allocfail(char *type)
+{
+	prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type);
+	prom_halt();
+}
+
+static void inherit_prom_mappings(void)
 {
 	struct linux_prom_translation *trans;
+	unsigned long phys_page, tte_vaddr, tte_data;
+	void (*remap_func)(unsigned long, unsigned long, int);
 	pgd_t *pgdp;
 	pmd_t *pmdp;
 	pte_t *ptep;
-	int node, n, i;
+	int node, n, i, tsz;
 
 	node = prom_finddevice("/virtual-memory");
 	n = prom_getproplen(node, "translations");
@@ -665,11 +184,17 @@
 		prom_printf("Couldn't get translation property\n");
 		prom_halt();
 	}
+	n += 5 * sizeof(struct linux_prom_translation);
+	for (tsz = 1; tsz < n; tsz <<= 1)
+		/* empty */;
+	trans = __alloc_bootmem(tsz, SMP_CACHE_BYTES, 0UL);
+	if (trans == NULL) {
+		prom_printf("inherit_prom_mappings: Cannot alloc translations.\n");
+		prom_halt();
+	}
+	memset(trans, 0, tsz);
 
-	for (i = 1; i < n; i <<= 1) /* empty */;
-	trans = sparc_init_alloc(&mempool, i);
-
-	if (prom_getproperty(node, "translations", (char *)trans, i) == -1) {
+	if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) {
 		prom_printf("Couldn't get translation property\n");
 		prom_halt();
 	}
@@ -684,15 +209,22 @@
 			     vaddr += PAGE_SIZE) {
 				pgdp = pgd_offset(&init_mm, vaddr);
 				if (pgd_none(*pgdp)) {
-					pmdp = sparc_init_alloc(&mempool,
-							 PMD_TABLE_SIZE);
-					memset(pmdp, 0, PAGE_SIZE);
+					pmdp = __alloc_bootmem(PMD_TABLE_SIZE,
+							       PMD_TABLE_SIZE,
+							       0UL);
+					if (pmdp == NULL)
+						early_pgtable_allocfail("pmd");
+					memset(pmdp, 0, PMD_TABLE_SIZE);
 					pgd_set(pgdp, pmdp);
 				}
 				pmdp = pmd_offset(pgdp, vaddr);
 				if (pmd_none(*pmdp)) {
-					ptep = sparc_init_alloc(&mempool,
-							 PTE_TABLE_SIZE);
+					ptep = __alloc_bootmem(PTE_TABLE_SIZE,
+							       PTE_TABLE_SIZE,
+							       0UL);
+					if (ptep == NULL)
+						early_pgtable_allocfail("pte");
+					memset(ptep, 0, PTE_TABLE_SIZE);
 					pmd_set(pmdp, ptep);
 				}
 				ptep = pte_offset(pmdp, vaddr);
@@ -701,6 +233,83 @@
 			}
 		}
 	}
+
+	/* Now fixup OBP's idea about where we really are mapped. */
+	prom_printf("Remapping the kernel... ");
+	phys_page = spitfire_get_dtlb_data(63) & _PAGE_PADDR;
+	phys_page += ((unsigned long)&prom_boot_page -
+		      (unsigned long)&empty_zero_page);
+
+	/* Lock this into i/d tlb entry 59 */
+	__asm__ __volatile__(
+		"stxa	%%g0, [%2] %3\n\t"
+		"stxa	%0, [%1] %4\n\t"
+		"membar	#Sync\n\t"
+		"flush	%%g6\n\t"
+		"stxa	%%g0, [%2] %5\n\t"
+		"stxa	%0, [%1] %6\n\t"
+		"membar	#Sync\n\t"
+		"flush	%%g6"
+		: : "r" (phys_page | _PAGE_VALID | _PAGE_SZ8K | _PAGE_CP |
+			 _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W),
+		    "r" (59 << 3), "r" (TLB_TAG_ACCESS),
+		    "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS),
+		    "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_ACCESS)
+		: "memory");
+
+	tte_vaddr = (unsigned long) &empty_zero_page;
+	kern_locked_tte_data = tte_data = spitfire_get_dtlb_data(63);
+
+	remap_func = (void *)  ((unsigned long) &prom_remap -
+				(unsigned long) &prom_boot_page);
+
+	remap_func(spitfire_get_dtlb_data(63) & _PAGE_PADDR,
+		   (unsigned long) &empty_zero_page,
+		   prom_get_mmu_ihandle());
+
+	/* Flush out that temporary mapping. */
+	spitfire_flush_dtlb_nucleus_page(0x0);
+	spitfire_flush_itlb_nucleus_page(0x0);
+
+	/* Now lock us back into the TLBs via OBP. */
+	prom_dtlb_load(63, tte_data, tte_vaddr);
+	prom_itlb_load(63, tte_data, tte_vaddr);
+
+	/* Re-read translations property. */
+	if ((n = prom_getproperty(node, "translations", (char *)trans, tsz)) == -1) {
+		prom_printf("Couldn't get translation property\n");
+		prom_halt();
+	}
+	n = n / sizeof(*trans);
+
+	for (i = 0; i < n; i++) {
+		unsigned long vaddr = trans[i].virt;
+		unsigned long size = trans[i].size;
+
+		if (vaddr < 0xf0000000UL) {
+			unsigned long avoid_start = (unsigned long) &empty_zero_page;
+			unsigned long avoid_end = avoid_start + (4 * 1024 * 1024);
+
+			if (vaddr < avoid_start) {
+				unsigned long top = vaddr + size;
+
+				if (top > avoid_start)
+					top = avoid_start;
+				prom_unmap(top - vaddr, vaddr);
+			}
+			if ((vaddr + size) > avoid_end) {
+				unsigned long bottom = vaddr;
+
+				if (bottom < avoid_end)
+					bottom = avoid_end;
+				prom_unmap((vaddr + size) - bottom, bottom);
+			}
+		}
+	}
+
+	prom_printf("done.\n");
+
+	register_prom_callbacks();
 }
 
 /* The OBP specifications for sun4u mark 0xfffffffc00000000 and
@@ -1020,6 +629,10 @@
 struct pgtable_cache_struct pgt_quicklists;
 #endif
 
+/* For PMDs we don't care about the color, writes are
+ * only done via Dcache which is write-thru, so non-Dcache
+ * reads will always see correct data.
+ */
 pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset)
 {
 	pmd_t *pmd;
@@ -1033,79 +646,55 @@
 	return NULL;
 }
 
-pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
-{
-	pte_t *pte;
-
-	pte = (pte_t *) __get_free_page(GFP_KERNEL);
-	if(pte) {
-		memset(pte, 0, PAGE_SIZE);
-		pmd_set(pmd, pte);
-		return pte + offset;
-	}
-	return NULL;
-}
-
-static void __init
-allocate_ptable_skeleton(unsigned long start, unsigned long end)
-{
-	pgd_t *pgdp;
-	pmd_t *pmdp;
-	pte_t *ptep;
-
-	while (start < end) {
-		pgdp = pgd_offset(&init_mm, start);
-		if (pgd_none(*pgdp)) {
-			pmdp = sparc_init_alloc(&mempool, PAGE_SIZE);
-			memset(pmdp, 0, PAGE_SIZE);
-			pgd_set(pgdp, pmdp);
-		}
-		pmdp = pmd_offset(pgdp, start);
-		if (pmd_none(*pmdp)) {
-			ptep = sparc_init_alloc(&mempool, PAGE_SIZE);
-			memset(ptep, 0, PAGE_SIZE);
-			pmd_set(pmdp, ptep);
-		}
-		start = (start + PMD_SIZE) & PMD_MASK;
-	}
-}
-
-/*
- * Create a mapping for an I/O register.  Have to make sure the side-effect
- * bit is set.
+/* OK, we have to color these pages because during DTLB
+ * protection faults we set the dirty bit via a non-Dcache
+ * enabled mapping in the VPTE area.  The kernel can end
+ * up missing the dirty bit resulting in processes crashing
+ * _iff_ the VPTE mapping of the ptes have a virtual address
+ * bit 13 which is different from bit 13 of the physical address.
+ *
+ * The sequence is:
+ *	1) DTLB protection fault, write dirty bit into pte via VPTE
+ *	   mappings.
+ *	2) Swapper checks pte, does not see dirty bit, frees page.
+ *	3) Process faults back in the page, the old pre-dirtied copy
+ *	   is provided and here is the corruption.
  */
- 
-void sparc_ultra_mapioaddr(unsigned long physaddr, unsigned long virt_addr,
-			   int bus, int rdonly)
+pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset, unsigned long color)
 {
-	pgd_t *pgdp = pgd_offset(&init_mm, virt_addr);
-	pmd_t *pmdp = pmd_offset(pgdp, virt_addr);
-	pte_t *ptep = pte_offset(pmdp, virt_addr);
-	pte_t pte;
+	unsigned long paddr = __get_free_pages(GFP_KERNEL, 1);
 
-	physaddr &= PAGE_MASK;
+	if (paddr) {
+		struct page *page2 = mem_map + MAP_NR(paddr + PAGE_SIZE);
+		unsigned long *to_free;
+		pte_t *pte;
 
-	if(rdonly)
-		pte = mk_pte_phys(physaddr, __pgprot(pg_iobits | __PRIV_BITS));
-	else
-		pte = mk_pte_phys(physaddr, __pgprot(pg_iobits | __DIRTY_BITS | __PRIV_BITS));
+		/* Set count of second page, so we can free it
+		 * seperately later on.
+		 */
+		atomic_set(&page2->count, 1);
 
-	set_pte(ptep, pte);
-}
+		/* Clear out both pages now. */
+		memset((char *)paddr, 0, (PAGE_SIZE << 1));
 
-/* XXX no longer used, remove me... -DaveM */
-void sparc_ultra_unmapioaddr(unsigned long virt_addr)
-{
-	pgd_t *pgdp;
-	pmd_t *pmdp;
-	pte_t *ptep;
+		/* Determine which page we give to this request. */
+		if (!color) {
+			pte = (pte_t *) paddr;
+			to_free = (unsigned long *) (paddr + PAGE_SIZE);
+		} else {
+			pte = (pte_t *) (paddr + PAGE_SIZE);
+			to_free = (unsigned long *) paddr;
+		}
 
-	pgdp = pgd_offset(&init_mm, virt_addr);
-	pmdp = pmd_offset(pgdp, virt_addr);
-	ptep = pte_offset(pmdp, virt_addr);
+		/* Now free the other one up, adjust cache size. */
+		*to_free = (unsigned long) pte_quicklist[color ^ 0x1];
+		pte_quicklist[color ^ 0x1] = to_free;
+		pgtable_cache_size++;
 
-	/* No need to flush uncacheable page. */
-	pte_clear(ptep);
+		pmd_set(pmd, pte);
+		return pte + offset;
+	}
+	return NULL;
 }
 
 void sparc_ultra_dump_itlb(void)
@@ -1139,21 +728,114 @@
         }
 }
 
+#undef DEBUG_BOOTMEM
+
+extern unsigned long cmdline_memory_size;
+
+unsigned long __init bootmem_init(void)
+{
+	unsigned long bootmap_size, start_pfn, end_pfn;
+	unsigned long end_of_phys_memory = 0UL;
+	int i;
+
+	/* XXX It is a bit ambiguous here, whether we should
+	 * XXX treat the user specified mem=xxx as total wanted
+	 * XXX physical memory, or as a limit to the upper
+	 * XXX physical address we allow.  For now it is the
+	 * XXX latter. -DaveM
+	 */
+#ifdef DEBUG_BOOTMEM
+	prom_printf("bootmem_init: Scan sp_banks,  ");
+#endif
+	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
+		end_of_phys_memory = sp_banks[i].base_addr +
+			sp_banks[i].num_bytes;
+		if (cmdline_memory_size) {
+			if (end_of_phys_memory > cmdline_memory_size) {
+				if (cmdline_memory_size > sp_banks[i].base_addr) {
+					end_of_phys_memory =
+						sp_banks[i-1].base_addr +
+						sp_banks[i-1].num_bytes;
+					sp_banks[i].base_addr = 0xdeadbeef;
+					sp_banks[i].num_bytes = 0;
+				} else {
+					sp_banks[i].num_bytes -=
+						(end_of_phys_memory -
+						 cmdline_memory_size);
+					end_of_phys_memory = cmdline_memory_size;
+					sp_banks[++i].base_addr = 0xdeadbeef;
+					sp_banks[i].num_bytes = 0;
+				}
+				break;
+			}
+		}
+	}
+
+	/* Start with page aligned address of last symbol in kernel
+	 * image.  The kernel is hard mapped below PAGE_OFFSET in a
+	 * 4MB locked TLB translation.
+	 */
+	start_pfn  = PAGE_ALIGN((unsigned long) &_end) -
+		((unsigned long) &empty_zero_page);
+
+	/* Adjust up to the physical address where the kernel begins. */
+	start_pfn += phys_base;
+
+	/* Now shift down to get the real physical page frame number. */
+	start_pfn >>= PAGE_SHIFT;
+
+	end_pfn = end_of_phys_memory >> PAGE_SHIFT;
+
+	/* Initialize the boot-time allocator. */
+#ifdef DEBUG_BOOTMEM
+	prom_printf("init_bootmem(spfn[%lx],epfn[%lx])\n",
+		    start_pfn, end_pfn);
+#endif
+	bootmap_size = init_bootmem(start_pfn, end_pfn);
+
+	/* Now register the available physical memory with the
+	 * allocator.
+	 */
+	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
+#ifdef DEBUG_BOOTMEM
+		prom_printf("free_bootmem: base[%lx] size[%lx]\n",
+			    sp_banks[i].base_addr,
+			    sp_banks[i].num_bytes);
+#endif
+		free_bootmem(sp_banks[i].base_addr,
+			     sp_banks[i].num_bytes);
+	}
+
+	/* Reserve the kernel text/data/bss and the bootmem bitmap. */
+#ifdef DEBUG_BOOTMEM
+	prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
+		    phys_base,
+		    (((start_pfn << PAGE_SHIFT) +
+		      bootmap_size) - phys_base));
+#endif
+	reserve_bootmem(phys_base, (((start_pfn << PAGE_SHIFT) +
+				     bootmap_size) - phys_base));
+
+#ifdef DEBUG_BOOTMEM
+	prom_printf("init_bootmem: return end_pfn[%lx]\n", end_pfn);
+#endif
+	return end_pfn;
+}
+
 /* paging_init() sets up the page tables */
 
-extern unsigned long free_area_init(unsigned long, unsigned long);
-extern unsigned long sun_serial_setup(unsigned long);
+extern void sun_serial_setup(void);
+
+static unsigned long last_valid_pfn;
 
-unsigned long __init
-paging_init(unsigned long start_mem, unsigned long end_mem)
+void __init paging_init(void)
 {
 	extern pmd_t swapper_pmd_dir[1024];
 	extern unsigned int sparc64_vpte_patchme1[1];
 	extern unsigned int sparc64_vpte_patchme2[1];
 	unsigned long alias_base = phys_base + PAGE_OFFSET;
 	unsigned long second_alias_page = 0;
-	unsigned long pt;
-	unsigned long flags;
+	unsigned long pt, flags, end_pfn;
 	unsigned long shift = alias_base - ((unsigned long)&empty_zero_page);
 
 	set_bit(0, mmu_context_bmap);
@@ -1176,7 +858,7 @@
 	: "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
 	  "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3)
 	: "memory");
-	if (start_mem >= KERNBASE + 0x340000) {
+	if (((unsigned long)&_end) >= KERNBASE + 0x340000) {
 		second_alias_page = alias_base + 0x400000;
 		__asm__ __volatile__("
 		stxa	%1, [%0] %3
@@ -1203,24 +885,22 @@
 	/* Now can init the kernel/bad page tables. */
 	pgd_set(&swapper_pg_dir[0], swapper_pmd_dir + (shift / sizeof(pgd_t)));
 	
-	sparc64_vpte_patchme1[0] |= (init_mm.pgd[0] >> 10);
-	sparc64_vpte_patchme2[0] |= (init_mm.pgd[0] & 0x3ff);
+	sparc64_vpte_patchme1[0] |= (pgd_val(init_mm.pgd[0]) >> 10);
+	sparc64_vpte_patchme2[0] |= (pgd_val(init_mm.pgd[0]) & 0x3ff);
 	flushi((long)&sparc64_vpte_patchme1[0]);
 	
-	/* We use mempool to create page tables, therefore adjust it up
-	 * such that __pa() macros etc. work.
-	 */
-	mempool = PAGE_ALIGN(start_mem) + shift;
-	
+	/* Setup bootmem... */
+	last_valid_pfn = end_pfn = bootmem_init();
+
 #ifdef CONFIG_SUN_SERIAL
-	/* This does not logically belong here, but is the first place
-	   we can initialize it at, so that we work in the PAGE_OFFSET+
-	   address space. */
-	mempool = sun_serial_setup(mempool);
+	/* This does not logically belong here, but we need to
+	 * call it at the moment we are able to use the bootmem
+	 * allocator.
+	 */
+	sun_serial_setup();
 #endif
 
-	/* Allocate 64M for dynamic DVMA mapping area. */
-	allocate_ptable_skeleton(DVMA_VADDR, DVMA_VADDR + 0x4000000);
+	/* Inherit non-locked OBP mappings. */
 	inherit_prom_mappings();
 	
 	/* Ok, we can use our TLB miss and window trap handlers safely.
@@ -1231,205 +911,314 @@
 	{
 		extern void setup_tba(int);
 		int is_starfire = prom_finddevice("/ssp-serial");
-		if(is_starfire != 0 && is_starfire != -1)
+		if (is_starfire != 0 && is_starfire != -1)
 			is_starfire = 1;
 		else
 			is_starfire = 0;
 		setup_tba(is_starfire);
 	}
 
-	/* Really paranoid. */
-	flushi((long)&empty_zero_page);
-	membar("#Sync");
-
-	/* Cleanup the extra locked TLB entry we created since we have the
-	 * nice TLB miss handlers of ours installed now.
-	 */
+	inherit_locked_prom_mappings(1);
+	
 	/* We only created DTLB mapping of this stuff. */
 	spitfire_flush_dtlb_nucleus_page(alias_base);
 	if (second_alias_page)
 		spitfire_flush_dtlb_nucleus_page(second_alias_page);
-	membar("#Sync");
 
-	/* Paranoid */
-	flushi((long)&empty_zero_page);
-	membar("#Sync");
+	flush_tlb_all();
 
-	inherit_locked_prom_mappings(1);
+	{
+		unsigned int zones_size[MAX_NR_ZONES] = { 0, 0, 0};
 
-	flush_tlb_all();
+		zones_size[ZONE_DMA] = end_pfn;
+		free_area_init(zones_size);
+	}
 
-	start_mem = free_area_init(PAGE_ALIGN(mempool), end_mem);
+	device_scan();
+}
 
-	return device_scan (PAGE_ALIGN (start_mem));
+/* Ok, it seems that the prom can allocate some more memory chunks
+ * as a side effect of some prom calls we perform during the
+ * boot sequence.  My most likely theory is that it is from the
+ * prom_set_traptable() call, and OBP is allocating a scratchpad
+ * for saving client program register state etc.
+ */
+void __init sort_memlist(struct linux_mlist_p1275 *thislist)
+{
+	int swapi = 0;
+	int i, mitr;
+	unsigned long tmpaddr, tmpsize;
+	unsigned long lowest;
+
+	for (i = 0; thislist[i].theres_more != 0; i++) {
+		lowest = thislist[i].start_adr;
+		for (mitr = i+1; thislist[mitr-1].theres_more != 0; mitr++)
+			if (thislist[mitr].start_adr < lowest) {
+				lowest = thislist[mitr].start_adr;
+				swapi = mitr;
+			}
+		if (lowest == thislist[i].start_adr)
+			continue;
+		tmpaddr = thislist[swapi].start_adr;
+		tmpsize = thislist[swapi].num_bytes;
+		for (mitr = swapi; mitr > i; mitr--) {
+			thislist[mitr].start_adr = thislist[mitr-1].start_adr;
+			thislist[mitr].num_bytes = thislist[mitr-1].num_bytes;
+		}
+		thislist[i].start_adr = tmpaddr;
+		thislist[i].num_bytes = tmpsize;
+	}
 }
 
-static void __init taint_real_pages(unsigned long start_mem, unsigned long end_mem)
+void __init rescan_sp_banks(void)
 {
-	unsigned long tmp = 0, paddr, endaddr;
-	unsigned long end = __pa(end_mem);
+	struct linux_prom64_registers memlist[64];
+	struct linux_mlist_p1275 avail[64], *mlist;
+	unsigned long bytes, base_paddr;
+	int num_regs, node = prom_finddevice("/memory");
+	int i;
 
-	dvmaio_init();
-	for (paddr = __pa(start_mem); paddr < end; ) {
-		for (; sp_banks[tmp].num_bytes != 0; tmp++)
-			if (sp_banks[tmp].base_addr + sp_banks[tmp].num_bytes > paddr)
-				break;
-		if (!sp_banks[tmp].num_bytes) {
-			mem_map[paddr>>PAGE_SHIFT].flags |= (1<<PG_skip);
-			mem_map[paddr>>PAGE_SHIFT].next_hash = mem_map + (phys_base >> PAGE_SHIFT);
-			mem_map[(paddr>>PAGE_SHIFT)+1UL].flags |= (1<<PG_skip);
-			mem_map[(paddr>>PAGE_SHIFT)+1UL].next_hash = mem_map + (phys_base >> PAGE_SHIFT);
-			return;
+	num_regs = prom_getproperty(node, "available",
+				    (char *) memlist, sizeof(memlist));
+	num_regs = (num_regs / sizeof(struct linux_prom64_registers));
+	for (i = 0; i < num_regs; i++) {
+		avail[i].start_adr = memlist[i].phys_addr;
+		avail[i].num_bytes = memlist[i].reg_size;
+		avail[i].theres_more = &avail[i + 1];
+	}
+	avail[i - 1].theres_more = NULL;
+	sort_memlist(avail);
+
+	mlist = &avail[0];
+	i = 0;
+	bytes = mlist->num_bytes;
+	base_paddr = mlist->start_adr;
+  
+	sp_banks[0].base_addr = base_paddr;
+	sp_banks[0].num_bytes = bytes;
+
+	while (mlist->theres_more != NULL){
+		i++;
+		mlist = mlist->theres_more;
+		bytes = mlist->num_bytes;
+		if (i >= SPARC_PHYS_BANKS-1) {
+			printk ("The machine has more banks than "
+				"this kernel can support\n"
+				"Increase the SPARC_PHYS_BANKS "
+				"setting (currently %d)\n",
+				SPARC_PHYS_BANKS);
+			i = SPARC_PHYS_BANKS-1;
+			break;
 		}
-		
-		if (sp_banks[tmp].base_addr > paddr) {
-			/* Making a one or two pages PG_skip holes
-			 * is not necessary.  We add one more because
-			 * we must set the PG_skip flag on the first
-			 * two mem_map[] entries for the hole.  Go and
-			 * see the mm/filemap.c:shrink_mmap() loop for
-			 * details. -DaveM
-			 */
-			if (sp_banks[tmp].base_addr - paddr > 3 * PAGE_SIZE) {
-				mem_map[paddr>>PAGE_SHIFT].flags |= (1<<PG_skip);
-				mem_map[paddr>>PAGE_SHIFT].next_hash = mem_map + (sp_banks[tmp].base_addr >> PAGE_SHIFT);
-				mem_map[(paddr>>PAGE_SHIFT)+1UL].flags |= (1<<PG_skip);
-				mem_map[(paddr>>PAGE_SHIFT)+1UL].next_hash = mem_map + (sp_banks[tmp].base_addr >> PAGE_SHIFT);
+    
+		sp_banks[i].base_addr = mlist->start_adr;
+		sp_banks[i].num_bytes = mlist->num_bytes;
+	}
+
+	i++;
+	sp_banks[i].base_addr = 0xdeadbeefbeefdeadUL;
+	sp_banks[i].num_bytes = 0;
+
+	for (i = 0; sp_banks[i].num_bytes != 0; i++)
+		sp_banks[i].num_bytes &= PAGE_MASK;
+}
+
+static void __init taint_real_pages(void)
+{
+	struct sparc_phys_banks saved_sp_banks[SPARC_PHYS_BANKS];
+	int i;
+
+#ifdef DEBUG_BOOTMEM
+	prom_printf("taint_real_pages: Rescan sp_banks[].\n");
+#endif
+	for (i = 0; i < SPARC_PHYS_BANKS; i++) {
+		saved_sp_banks[i].base_addr =
+			sp_banks[i].base_addr;
+		saved_sp_banks[i].num_bytes =
+			sp_banks[i].num_bytes;
+	}
+
+	rescan_sp_banks();
+
+	/* Find changes discovered in the sp_bank rescan and
+	 * reserve the lost portions in the bootmem maps.
+	 */
+	for (i = 0; saved_sp_banks[i].num_bytes; i++) {
+		unsigned long old_start, old_end;
+
+		old_start = saved_sp_banks[i].base_addr;
+		old_end = old_start +
+			saved_sp_banks[i].num_bytes;
+		while (old_start < old_end) {
+			int n;
+
+			for (n = 0; sp_banks[n].num_bytes; n++) {
+				unsigned long new_start, new_end;
+
+				new_start = sp_banks[n].base_addr;
+				new_end = new_start + sp_banks[n].num_bytes;
+
+				if (new_start <= old_start &&
+				    new_end >= (old_start + PAGE_SIZE)) {
+					set_bit (old_start >> 22,
+						 sparc64_valid_addr_bitmap);
+					goto do_next_page;
+				}
 			}
-			paddr = sp_banks[tmp].base_addr;
+#ifdef DEBUG_BOOTMEM
+			prom_printf("taint: Page went away, reserve page %lx.\n",
+				    old_start);
+#endif
+			reserve_bootmem(old_start, PAGE_SIZE);
+
+		do_next_page:
+			old_start += PAGE_SIZE;
 		}
-		
-		endaddr = sp_banks[tmp].base_addr + sp_banks[tmp].num_bytes;
-		while (paddr < endaddr) {
-			mem_map[paddr>>PAGE_SHIFT].flags &= ~(1<<PG_reserved);
-			set_bit(paddr >> 22, sparc64_valid_addr_bitmap);
-			if (paddr >= (MAX_DMA_ADDRESS - PAGE_OFFSET))
-				mem_map[paddr>>PAGE_SHIFT].flags &= ~(1<<PG_DMA);
-			paddr += PAGE_SIZE;
+	}
+}
+
+void __init free_mem_map_range(struct page *first, struct page *last)
+{
+	first = (struct page *) PAGE_ALIGN((unsigned long)first);
+	last  = (struct page *) ((unsigned long)last & PAGE_MASK);
+#ifdef DEBUG_BOOTMEM
+	prom_printf("[%p,%p] ", first, last);
+#endif
+	while (first < last) {
+		ClearPageReserved(mem_map + MAP_NR(first));
+		set_page_count(mem_map + MAP_NR(first), 1);
+		free_page((unsigned long)first);
+		totalram_pages++;
+		num_physpages++;
+
+		first = (struct page *)((unsigned long)first + PAGE_SIZE);
+	}
+}
+
+/* Walk through holes in sp_banks regions, if the mem_map array
+ * areas representing those holes consume a page or more, free
+ * up such pages.  This helps a lot on machines where physical
+ * ram is configured such that it begins at some hugh value.
+ *
+ * The sp_banks array is sorted by base address.
+ */
+void __init free_unused_mem_map(void)
+{
+	int i;
+
+#ifdef DEBUG_BOOTMEM
+	prom_printf("free_unused_mem_map: ");
+#endif
+	for (i = 0; sp_banks[i].num_bytes; i++) {
+		if (i == 0) {
+			struct page *first, *last;
+
+			first = mem_map;
+			last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT];
+			free_mem_map_range(first, last);
+		} else {
+			struct page *first, *last;
+			unsigned long prev_end;
+
+			prev_end = sp_banks[i-1].base_addr +
+				sp_banks[i-1].num_bytes;
+			prev_end = PAGE_ALIGN(prev_end);
+			first = &mem_map[prev_end >> PAGE_SHIFT];
+			last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT];
+
+			free_mem_map_range(first, last);
+
+			if (!sp_banks[i+1].num_bytes) {
+				prev_end = sp_banks[i].base_addr +
+					sp_banks[i].num_bytes;
+				first = &mem_map[prev_end >> PAGE_SHIFT];
+				last = &mem_map[last_valid_pfn];
+				free_mem_map_range(first, last);
+			}
 		}
 	}
+#ifdef DEBUG_BOOTMEM
+	prom_printf("\n");
+#endif
 }
 
-void __init mem_init(unsigned long start_mem, unsigned long end_mem)
+void __init mem_init(void)
 {
-	int codepages = 0;
-	int datapages = 0;
-	int initpages = 0;
-	unsigned long addr;
-	unsigned long alias_base = phys_base + PAGE_OFFSET - (long)(&empty_zero_page);
-	struct page *page, *end;
+	unsigned long codepages, datapages, initpages;
+	unsigned long addr, last;
 	int i;
 
-	end_mem &= PAGE_MASK;
-	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 = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
 	i += 1;
-	memset(sparc64_valid_addr_bitmap, 0, i << 3);
-	start_mem += i << 3;
-
-	start_mem = PAGE_ALIGN(start_mem);
-	num_physpages = 0;
-	
-	if (phys_base) {
-		mem_map[0].flags |= (1<<PG_skip) | (1<<PG_reserved);
-		mem_map[0].next_hash = mem_map + (phys_base >> PAGE_SHIFT);
-		mem_map[1].flags |= (1<<PG_skip) | (1<<PG_reserved);
-		mem_map[1].next_hash = mem_map + (phys_base >> PAGE_SHIFT);
+	sparc64_valid_addr_bitmap = (unsigned long *)
+		__alloc_bootmem(i << 3, SMP_CACHE_BYTES, 0UL);
+	if (sparc64_valid_addr_bitmap == NULL) {
+		prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
+		prom_halt();
 	}
+	memset(sparc64_valid_addr_bitmap, 0, i << 3);
 
 	addr = PAGE_OFFSET + phys_base;
-	while(addr < start_mem) {
+	last = PAGE_ALIGN((unsigned long)&_end) -
+		((unsigned long) &empty_zero_page);
+	last += PAGE_OFFSET + phys_base;
+	while (addr < last) {
 #ifdef CONFIG_BLK_DEV_INITRD
+// FIXME to use bootmem scheme...
 		if (initrd_below_start_ok && addr >= initrd_start && addr < initrd_end)
 			mem_map[MAP_NR(addr)].flags &= ~(1<<PG_reserved);
-		else
 #endif	
-			mem_map[MAP_NR(addr)].flags |= (1<<PG_reserved);
 		set_bit(__pa(addr) >> 22, sparc64_valid_addr_bitmap);
 		addr += PAGE_SIZE;
 	}
 
-	taint_real_pages(start_mem, end_mem);
-	
-#ifdef FREE_UNUSED_MEM_MAP	
-	end = mem_map + max_mapnr;
-	for (page = mem_map; page < end; page++) {
-		if (PageSkip(page)) {
-			unsigned long low, high;
-			
-			/* See taint_real_pages() for why this is done.  -DaveM */
-			page++;
-
-			low = PAGE_ALIGN((unsigned long)(page+1));
-			if (page->next_hash < page)
-				high = ((unsigned long)end) & PAGE_MASK;
-			else
-				high = ((unsigned long)page->next_hash) & PAGE_MASK;
-			while (low < high) {
-				mem_map[MAP_NR(low)].flags &= ~(1<<PG_reserved);
-				low += PAGE_SIZE;
-			}
-		}
-	}
+	taint_real_pages();
+
+	max_mapnr = last_valid_pfn;
+	high_memory = __va(last_valid_pfn << PAGE_SHIFT);
+
+#ifdef DEBUG_BOOTMEM
+	prom_printf("mem_init: Calling free_all_bootmem().\n");
 #endif
-	
-	for (addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) {
-		if (PageSkip(mem_map + MAP_NR(addr))) {
-			unsigned long next = mem_map[MAP_NR(addr)].next_hash - mem_map;
-			
-			next = (next << PAGE_SHIFT) + PAGE_OFFSET;
-			if (next < addr || next >= end_mem)
-				break;
-			addr = next;
-		}
-		num_physpages++;
-		if (PageReserved(mem_map + MAP_NR(addr))) {
-			if ((addr < ((unsigned long) &etext) + alias_base) && (addr >= alias_base))
-				codepages++;
-			else if((addr >= ((unsigned long)&__init_begin) + alias_base)
-				&& (addr < ((unsigned long)&__init_end) + alias_base))
-				initpages++;
-			else if((addr < start_mem) && (addr >= alias_base))
-				datapages++;
-			continue;
-		}
-		atomic_set(&mem_map[MAP_NR(addr)].count, 1);
-#ifdef CONFIG_BLK_DEV_INITRD
-		if (!initrd_start ||
-		    (addr < initrd_start || addr >= initrd_end))
+	num_physpages = totalram_pages = free_all_bootmem();
+#if 0
+	free_unused_mem_map();
 #endif
-			free_page(addr);
-	}
-	
+	codepages = (((unsigned long) &etext) - ((unsigned long)&_start));
+	codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT;
+	datapages = (((unsigned long) &edata) - ((unsigned long)&etext));
+	datapages = PAGE_ALIGN(datapages) >> PAGE_SHIFT;
+	initpages = (((unsigned long) &__init_end) - ((unsigned long) &__init_begin));
+	initpages = PAGE_ALIGN(initpages) >> PAGE_SHIFT;
+
 #ifndef __SMP__
 	{
 		/* Put empty_pg_dir on pgd_quicklist */
 		extern pgd_t empty_pg_dir[1024];
 		unsigned long addr = (unsigned long)empty_pg_dir;
+		unsigned long alias_base = phys_base + PAGE_OFFSET -
+			(long)(&empty_zero_page);
 		
 		memset(empty_pg_dir, 0, sizeof(empty_pg_dir));
 		addr += alias_base;
-		mem_map[MAP_NR(addr)].pprev_hash = 0;
 		free_pgd_fast((pgd_t *)addr);
+		totalram_pages++;
+		num_physpages++;
 	}
 #endif
 
-	printk("Memory: %uk available (%dk kernel code, %dk data, %dk init) [%016lx,%016lx]\n",
-	       nr_free_pages << (PAGE_SHIFT-10),
+	printk("Memory: %uk available (%ldk kernel code, %ldk data, %ldk init) [%016lx,%016lx]\n",
+	       nr_free_pages() << (PAGE_SHIFT-10),
 	       codepages << (PAGE_SHIFT-10),
 	       datapages << (PAGE_SHIFT-10), 
 	       initpages << (PAGE_SHIFT-10), 
-	       PAGE_OFFSET, end_mem);
+	       PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT));
 
 	/* NOTE NOTE NOTE NOTE
 	 * Please keep track of things and make sure this
 	 * always matches the code in mm/page_alloc.c -DaveM
 	 */
-	i = nr_free_pages >> 7;
+	i = nr_free_pages() >> 7;
 	if (i < 48)
 		i = 48;
 	if (i > 256)
@@ -1442,42 +1231,35 @@
 void free_initmem (void)
 {
 	unsigned long addr;
-	
+
 	addr = (unsigned long)(&__init_begin);
 	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
-		unsigned long page = addr + (long)__va(phys_base)
-					- (long)(&empty_zero_page);
+		unsigned long page;
+		struct page *p;
 
-		mem_map[MAP_NR(page)].flags &= ~(1 << PG_reserved);
-		atomic_set(&mem_map[MAP_NR(page)].count, 1);
-		free_page(page);
+		page = (addr +
+			((unsigned long) __va(phys_base)) -
+			((unsigned long) &empty_zero_page));
+		p = mem_map + MAP_NR(page);
+
+		ClearPageReserved(p);
+		set_page_count(p, 1);
+		__free_page(p);
+		totalram_pages++;
+		num_physpages++;
 	}
 }
 
 void si_meminfo(struct sysinfo *val)
 {
-	struct page *page, *end;
-
-	val->totalram = 0;
+	val->totalram = totalram_pages;
 	val->sharedram = 0;
-	val->freeram = ((unsigned long)nr_free_pages) << PAGE_SHIFT;
-	val->bufferram = atomic_read(&buffermem);
-	for (page = mem_map, end = mem_map + max_mapnr;
-	     page < end; page++) {
-		if (PageSkip(page)) {
-			if (page->next_hash < page)
-				break;
-			page = page->next_hash;
-		}
-		if (PageReserved(page))
-			continue;
-		val->totalram++;
-		if (!atomic_read(&page->count))
-			continue;
-		val->sharedram += atomic_read(&page->count) - 1;
-	}
-	val->totalram <<= PAGE_SHIFT;
-	val->sharedram <<= PAGE_SHIFT;
-	val->totalbig = 0;
-	val->freebig = 0;
+	val->freeram = nr_free_pages();
+	val->bufferram = atomic_read(&buffermem_pages);
+
+	/* These are always zero on Sparc64. */
+	val->totalhigh = 0;
+	val->freehigh = 0;
+
+	val->mem_unit = PAGE_SIZE;
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S
--- v2.3.34/linux/arch/sparc64/mm/ultra.S	Thu Nov 18 20:25:37 1999
+++ linux/arch/sparc64/mm/ultra.S	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ultra.S,v 1.34 1999/09/10 10:40:51 davem Exp $
+/* $Id: ultra.S,v 1.36 1999/12/15 15:45:18 davem Exp $
  * ultra.S: Don't expand these all over the place...
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -174,10 +174,10 @@
 	 *
 	 * Register usage:
 	 *   %g5	mm->context	(all tlb flushes)
-	 *   %g6	address arg 1	(tlb page and range flushes)
+	 *   %g1	address arg 1	(tlb page and range flushes)
 	 *   %g7	address arg 2	(tlb range flush only)
 	 *
-	 *   %g1	ivector table, don't touch
+	 *   %g6	ivector table, don't touch
 	 *   %g2	scratch 1
 	 *   %g3	scratch 2
 	 *   %g4	scratch 3
@@ -188,7 +188,7 @@
 	.globl		xcall_flush_tlb_page, xcall_flush_tlb_mm, xcall_flush_tlb_range
 xcall_flush_tlb_page:
 	mov		SECONDARY_CONTEXT, %g2
-	or		%g6, 0x10, %g4
+	or		%g1, 0x10, %g4
 	ldxa		[%g2] ASI_DMMU, %g3
 	stxa		%g5, [%g2] ASI_DMMU
 	stxa		%g0, [%g4] ASI_DMMU_DEMAP
@@ -209,11 +209,11 @@
 xcall_flush_tlb_range:
 	sethi		%hi(8192 - 1), %g2
 	or		%g2, %lo(8192 - 1), %g2
-	andn		%g6, %g2, %g6
+	andn		%g1, %g2, %g1
 	andn		%g7, %g2, %g7
-	sub		%g7, %g6, %g3
+	sub		%g7, %g1, %g3
 	add		%g2, 1, %g2
-	orcc		%g6, 0x10, %g6
+	orcc		%g1, 0x10, %g1
 	srlx		%g3, 13, %g4
 
 	cmp		%g4, 96
@@ -225,8 +225,8 @@
 	nop
 	nop
 
-1:	stxa		%g0, [%g6 + %g3] ASI_DMMU_DEMAP
-	stxa		%g0, [%g6 + %g3] ASI_IMMU_DEMAP
+1:	stxa		%g0, [%g1 + %g3] ASI_DMMU_DEMAP
+	stxa		%g0, [%g1 + %g3] ASI_IMMU_DEMAP
 	brnz,pt		%g3, 1b
 	 sub		%g3, %g2, %g3
 	stxa		%g7, [%g4] ASI_DMMU
@@ -262,6 +262,22 @@
 	b,pt		%xcc, rtrap
 	 clr		%l6
 
+	.globl		xcall_promstop
+xcall_promstop:
+	rdpr		%pstate, %g2
+	wrpr		%g2, PSTATE_IG | PSTATE_AG, %pstate
+	rdpr		%pil, %g2
+	wrpr		%g0, 15, %pil
+	sethi		%hi(109f), %g7
+	b,pt		%xcc, etrap_irq
+109:	 or		%g7, %lo(109b), %g7
+	flushw
+	call		prom_stopself
+	 nop
+	/* We should not return, just spin if we do... */
+1:	b,a,pt		%xcc, 1b
+	nop
+
 	.globl		xcall_receive_signal
 xcall_receive_signal:
 	rdpr		%pstate, %g2
@@ -303,7 +319,7 @@
 	cmp		%g2, 63
 	ble,pt		%icc, 1b
 	 sll		%g2, 3, %g3
-	flush		%g1
+	flush		%g6
 	retry
 
 	.globl		xcall_flush_cache_all
@@ -316,6 +332,6 @@
 	cmp		%g3, %g2
 	bleu,pt		%xcc, 1b
 	 nop
-	flush		%g1
+	flush		%g6
 	retry
 #endif /* __SMP__ */
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/prom/Makefile linux/arch/sparc64/prom/Makefile
--- v2.3.34/linux/arch/sparc64/prom/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/arch/sparc64/prom/Makefile	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.2 1997/02/25 12:40:25 jj Exp $
+# $Id: Makefile,v 1.5 1999/12/21 04:02:26 davem Exp $
 # Makefile for the Sun Boot PROM interface library under
 # Linux.
 #
@@ -9,13 +9,19 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 OBJS  = bootstr.o devops.o init.o memory.o misc.o \
-        ranges.o tree.o console.o printf.o p1275.o
+        tree.o console.o printf.o p1275.o map.o
 
 all: promlib.a
 
 promlib.a: $(OBJS)
 	$(AR) rcs promlib.a $(OBJS)
 	sync
+
+.S.s:
+	$(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s
+
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o
 
 dep:
 	$(CPP) $(CPPFLAGS) -M *.c > .depend
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/prom/init.c linux/arch/sparc64/prom/init.c
--- v2.3.34/linux/arch/sparc64/prom/init.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/prom/init.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.9 1999/08/31 06:55:03 davem Exp $
+/* $Id: init.c,v 1.10 1999/09/21 14:35:59 davem Exp $
  * init.c:  Initialize internal variables used by the PROM
  *          library functions.
  *
@@ -28,7 +28,6 @@
  */
 
 extern void prom_meminit(void);
-extern void prom_ranges_init(void);
 extern void prom_cif_init(void *, void *);
 
 void __init prom_init(void *cif_handler, void *cif_stack)
@@ -81,8 +80,6 @@
 	printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + 4);
 
 	prom_meminit();
-
-	prom_ranges_init();
 
 	/* Initialization successful. */
 	return;
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/prom/map.S linux/arch/sparc64/prom/map.S
--- v2.3.34/linux/arch/sparc64/prom/map.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/prom/map.S	Mon Dec 20 22:05:52 1999
@@ -0,0 +1,70 @@
+/* $Id: map.S,v 1.2 1999/11/19 05:53:02 davem Exp $
+ * map.S: Tricky coding required to fixup the kernel OBP maps
+ *	  properly.
+ *
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ */
+
+	.text
+	.align	8192
+	.globl	prom_boot_page
+prom_boot_page:
+call_method:
+	.asciz	"call-method"
+	.align	8
+map:
+	.asciz	"map"
+	.align	8
+
+	/* When we are invoked, our caller has remapped us to
+	 * page zero, therefore we must use PC relative addressing
+	 * for everything after we begin performing the unmap/map
+	 * calls.
+	 */
+	.globl	prom_remap
+prom_remap:	/* %o0 = physpage, %o1 = virtpage, %o2 = mmu_ihandle */
+	rd	%pc, %g1
+	srl	%o2, 0, %o2			! kill sign extension
+	sethi	%hi(p1275buf), %g2
+	or	%g2, %lo(p1275buf), %g2
+	ldx	[%g2 + 0x10], %g3		! prom_cif_stack
+	save	%g3, -(192 + 128), %sp
+	ldx	[%g2 + 0x08], %l0		! prom_cif_handler
+	mov	%g6, %i3
+	mov	%g4, %i4
+	flushw
+
+	sethi	%hi(prom_remap - call_method), %g7
+	or	%g7, %lo(prom_remap - call_method), %g7
+	sub	%g1, %g7, %l2			! call-method string
+	sethi	%hi(prom_remap - map), %g7
+	or	%g7, %lo(prom_remap - map), %g7
+	sub	%g1, %g7, %l4			! map string
+
+	/* OK, map the 4MB region we really live at. */
+	stx	%l2, [%sp + 2047 + 128 + 0x00]	! call-method
+	mov	7, %l5
+	stx	%l5, [%sp + 2047 + 128 + 0x08]	! num_args
+	mov	1, %l5
+	stx	%l5, [%sp + 2047 + 128 + 0x10]	! num_rets
+	stx	%l4, [%sp + 2047 + 128 + 0x18]	! map
+	stx	%i2, [%sp + 2047 + 128 + 0x20]	! mmu_ihandle
+	mov	-1, %l5
+	stx	%l5, [%sp + 2047 + 128 + 0x28]	! mode == default
+	sethi	%hi(4 * 1024 * 1024), %l5
+	stx	%l5, [%sp + 2047 + 128 + 0x30]	! size
+	stx	%i1, [%sp + 2047 + 128 + 0x38]	! vaddr
+	stx	%g0, [%sp + 2047 + 128 + 0x40]	! filler
+	stx	%i0, [%sp + 2047 + 128 + 0x48]	! paddr
+	call	%l0
+	 add	%sp, (2047 + 128), %o0		! argument array
+
+	/* Restore hard-coded globals. */
+	mov	%i3, %g6
+	mov	%i4, %g4
+
+	/* Wheee.... we are done. */
+	ret
+	restore
+
+	.align	8192
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/prom/misc.c linux/arch/sparc64/prom/misc.c
--- v2.3.34/linux/arch/sparc64/prom/misc.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/prom/misc.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.15 1999/08/31 19:25:41 davem Exp $
+/* $Id: misc.c,v 1.16 1999/11/19 05:53:04 davem Exp $
  * misc.c:  Miscellaneous prom functions that don't belong
  *          anywhere else.
  *
@@ -10,6 +10,8 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 
@@ -37,6 +39,11 @@
 extern int serial_console;
 #endif
 
+#ifdef __SMP__
+extern void smp_capture(void);
+extern void smp_release(void);
+#endif
+
 /* Drop into the prom, with the chance to continue with the 'go'
  * prom command.
  */
@@ -44,26 +51,57 @@
 prom_cmdline(void)
 {
 	unsigned long flags;
-    
+
+	__save_and_cli(flags);
+
 #ifdef CONFIG_SUN_CONSOLE
 	if(!serial_console && prom_palette)
 		prom_palette (1);
 #endif
-	__save_and_cli(flags);
+
+	/* We always arrive here via a serial interrupt.
+	 * So in order for everything to work reliably, even
+	 * on SMP, we need to drop the IRQ locks we hold.
+	 */
+#ifdef __SMP__
+	hardirq_exit(smp_processor_id());
+	smp_capture();
+#else
+	local_irq_count--;
+#endif
+
 	p1275_cmd ("enter", P1275_INOUT(0,0));
-	__restore_flags(flags);
+
+#ifdef __SMP__
+	smp_release();
+	hardirq_enter(smp_processor_id());
+	spin_unlock_wait(&global_irq_lock);
+#else
+	local_irq_count++;
+#endif
+
 #ifdef CONFIG_SUN_CONSOLE
 	if(!serial_console && prom_palette)
 		prom_palette (0);
 #endif
+
+	__restore_flags(flags);
 }
 
+#ifdef __SMP__
+extern void smp_promstop_others(void);
+#endif
+
 /* Drop into the prom, but completely terminate the program.
  * No chance of continuing.
  */
 void
 prom_halt(void)
 {
+#ifdef __SMP__
+	smp_promstop_others();
+	udelay(8000);
+#endif
 again:
 	p1275_cmd ("exit", P1275_INOUT(0,0));
 	goto again; /* PROM is out to get me -DaveM */
@@ -122,10 +160,10 @@
 	p1275_cmd("SUNW,set-trap-table", P1275_INOUT(1, 0), tba);
 }
 
-/* This is only used internally below. */
-static int prom_get_mmu_ihandle(void)
+int mmu_ihandle_cache = 0;
+
+int prom_get_mmu_ihandle(void)
 {
-	static int mmu_ihandle_cache = 0;
 	int node, ret;
 
 	if (mmu_ihandle_cache != 0)
@@ -165,7 +203,10 @@
 		    unsigned long vaddr)
 {
 	return p1275_cmd("call-method",
-			 (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 1)),
+			 (P1275_ARG(0, P1275_ARG_IN_STRING) |
+			  P1275_ARG(2, P1275_ARG_IN_64B) |
+			  P1275_ARG(3, P1275_ARG_IN_64B) |
+			  P1275_INOUT(5, 1)),
 			 "SUNW,itlb-load",
 			 prom_get_mmu_ihandle(),
 			 /* And then our actual args are pushed backwards. */
@@ -179,7 +220,10 @@
 		    unsigned long vaddr)
 {
 	return p1275_cmd("call-method",
-			 (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 1)),
+			 (P1275_ARG(0, P1275_ARG_IN_STRING) |
+			  P1275_ARG(2, P1275_ARG_IN_64B) |
+			  P1275_ARG(3, P1275_ARG_IN_64B) |
+			  P1275_INOUT(5, 1)),
 			 "SUNW,dtlb-load",
 			 prom_get_mmu_ihandle(),
 			 /* And then our actual args are pushed backwards. */
@@ -188,6 +232,41 @@
 			 index);
 }
 
+int prom_map(int mode, unsigned long size,
+	     unsigned long vaddr, unsigned long paddr)
+{
+	int ret = p1275_cmd("call-method",
+			    (P1275_ARG(0, P1275_ARG_IN_STRING) |
+			     P1275_ARG(3, P1275_ARG_IN_64B) |
+			     P1275_ARG(4, P1275_ARG_IN_64B) |
+			     P1275_ARG(6, P1275_ARG_IN_64B) |
+			     P1275_INOUT(7, 1)),
+			    "map",
+			    prom_get_mmu_ihandle(),
+			    mode,
+			    size,
+			    vaddr,
+			    0,
+			    paddr);
+
+	if (ret == 0)
+		ret = -1;
+	return ret;
+}
+
+void prom_unmap(unsigned long size, unsigned long vaddr)
+{
+	p1275_cmd("call-method",
+		  (P1275_ARG(0, P1275_ARG_IN_STRING) |
+		   P1275_ARG(2, P1275_ARG_IN_64B) |
+		   P1275_ARG(3, P1275_ARG_IN_64B) |
+		   P1275_INOUT(4, 0)),
+		  "unmap",
+		  prom_get_mmu_ihandle(),
+		  size,
+		  vaddr);
+}
+
 /* Set aside physical memory which is not touched or modified
  * across soft resets.
  */
@@ -226,7 +305,7 @@
 	return p1275_cmd("call-method",
 			 (P1275_ARG(0, P1275_ARG_IN_STRING)	|
 			  P1275_ARG(3, P1275_ARG_OUT_BUF)	|
-			  P1275_ARG(5, P1275_ARG_IN_64B)	|
+			  P1275_ARG(6, P1275_ARG_IN_64B)	|
 			  P1275_INOUT(8, 2)),
 			 "SUNW,get-unumber", prom_get_memory_ihandle(),
 			 buflen, buf, P1275_SIZE(buflen),
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/prom/p1275.c linux/arch/sparc64/prom/p1275.c
--- v2.3.34/linux/arch/sparc64/prom/p1275.c	Fri Sep 10 23:57:28 1999
+++ linux/arch/sparc64/prom/p1275.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: p1275.c,v 1.18 1999/09/10 10:40:53 davem Exp $
+/* $Id: p1275.c,v 1.20 1999/11/23 23:47:56 davem Exp $
  * p1275.c: Sun IEEE 1275 PROM low level interface routines
  *
  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -252,11 +252,7 @@
  * the counter is needed.  -DaveM
  */
 static int prom_entry_depth = 0;
-static spinlock_t prom_entry_lock = SPIN_LOCK_UNLOCKED;
-#ifdef __SMP__
-extern void smp_capture(void);
-extern void smp_release(void);
-#endif
+spinlock_t prom_entry_lock = SPIN_LOCK_UNLOCKED;
 
 static __inline__ unsigned long prom_get_lock(void)
 {
@@ -270,9 +266,6 @@
 		if (prom_entry_depth != 0)
 			panic("prom_get_lock");
 #endif
-#ifdef __SMP__
-		smp_capture();
-#endif
 	}
 	prom_entry_depth++;
 
@@ -281,12 +274,9 @@
 
 static __inline__ void prom_release_lock(unsigned long flags)
 {
-	if (--prom_entry_depth == 0) {
-#ifdef __SMP__
-		smp_release();
-#endif
+	if (--prom_entry_depth == 0)
 		spin_unlock(&prom_entry_lock);
-	}
+
 	__restore_flags(flags);
 }
 
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/prom/ranges.c linux/arch/sparc64/prom/ranges.c
--- v2.3.34/linux/arch/sparc64/prom/ranges.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/prom/ranges.c	Wed Dec 31 16:00:00 1969
@@ -1,192 +0,0 @@
-/* $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)
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/sbus.h>
-#include <asm/fhc.h>
-#include <asm/system.h>
-#ifdef CONFIG_PCI
-#include <asm/pbm.h>
-#include <asm/ebus.h>
-#endif
-
-struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX];
-int num_obio_ranges;
-
-/* Adjust register values based upon the ranges parameters. */
-inline void
-prom_adjust_regs(struct linux_prom_registers *regp, int nregs,
-		 struct linux_prom_ranges *rangep, int nranges)
-{
-	int regc, rngc;
-
-	for(regc=0; regc < nregs; regc++) {
-		for(rngc=0; rngc < nranges; rngc++)
-			if(regp[regc].which_io == rangep[rngc].ot_child_space)
-				break; /* Fount it */
-		if(rngc==nranges) /* oops */
-			prom_printf("adjust_regs: Could not find range with matching bus type...\n");
-		regp[regc].which_io = rangep[rngc].ot_parent_space;
-		regp[regc].phys_addr += rangep[rngc].ot_parent_base;
-	}
-}
-
-inline void
-prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1,
-		   struct linux_prom_ranges *ranges2, int nranges2)
-{
-	int rng1c, rng2c;
-
-	for(rng1c=0; rng1c < nranges1; rng1c++) {
-		for(rng2c=0; rng2c < nranges2; rng2c++)
-			if(ranges1[rng1c].ot_child_space ==
-			   ranges2[rng2c].ot_child_space) break;
-		if(rng2c == nranges2) /* oops */
-			prom_printf("adjust_ranges: Could not find matching bus type...\n");
-		ranges1[rng1c].ot_parent_space = ranges2[rng2c].ot_parent_space;
-		ranges1[rng1c].ot_parent_base += ranges2[rng2c].ot_parent_base;
-	}
-}
-
-/* Apply probed sbus ranges to registers passed, if no ranges return. */
-void prom_apply_sbus_ranges(struct linux_sbus *sbus, struct linux_prom_registers *regs,
-			    int nregs, struct linux_sbus_device *sdev)
-{
-	if(sbus->num_sbus_ranges) {
-		if(sdev && (sdev->ranges_applied == 0)) {
-			sdev->ranges_applied = 1;
-			prom_adjust_regs(regs, nregs, sbus->sbus_ranges,
-					 sbus->num_sbus_ranges);
-		}
-	}
-}
-
-/* Apply probed fhc ranges to registers passed, if no ranges return. */
-void prom_apply_fhc_ranges(struct linux_fhc *fhc,
-			   struct linux_prom_registers *regs,
-			   int nregs)
-{
-	if(fhc->num_fhc_ranges)
-		prom_adjust_regs(regs, nregs, fhc->fhc_ranges,
-				 fhc->num_fhc_ranges);
-}
-
-/* Apply probed central ranges to registers passed, if no ranges return. */
-void prom_apply_central_ranges(struct linux_central *central,
-			       struct linux_prom_registers *regs, int nregs)
-{
-	if(central->num_central_ranges)
-		prom_adjust_regs(regs, nregs, central->central_ranges,
-				 central->num_central_ranges);
-}
-
-void __init prom_ranges_init(void)
-{
-}
-
-void __init prom_sbus_ranges_init(int iommund, struct linux_sbus *sbus)
-{
-	int success;
-	
-	sbus->num_sbus_ranges = 0;
-	success = prom_getproperty(sbus->prom_node, "ranges",
-				   (char *) sbus->sbus_ranges,
-				   sizeof (sbus->sbus_ranges));
-	if (success != -1)
-		sbus->num_sbus_ranges = (success/sizeof(struct linux_prom_ranges));
-}
-
-void __init prom_central_ranges_init(int cnode, struct linux_central *central)
-{
-	int success;
-	
-	central->num_central_ranges = 0;
-	success = prom_getproperty(central->prom_node, "ranges",
-				   (char *) central->central_ranges,
-				   sizeof (central->central_ranges));
-	if (success != -1)
-		central->num_central_ranges = (success/sizeof(struct linux_prom_ranges));
-}
-
-void __init prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc)
-{
-	int success;
-	
-	fhc->num_fhc_ranges = 0;
-	success = prom_getproperty(fhc->prom_node, "ranges",
-				   (char *) fhc->fhc_ranges,
-				   sizeof (fhc->fhc_ranges));
-	if (success != -1)
-		fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges));
-}
-
-#ifdef CONFIG_PCI
-void __init prom_ebus_ranges_init(struct linux_ebus *ebus)
-{
-	int success;
-
-	ebus->num_ebus_ranges = 0;
-	success = prom_getproperty(ebus->prom_node, "ranges",
-				   (char *)ebus->ebus_ranges,
-				   sizeof(ebus->ebus_ranges));
-	if (success != -1)
-		ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges));
-}
-
-void __init prom_ebus_intmap_init(struct linux_ebus *ebus)
-{
-	int success;
-
-	ebus->num_ebus_intmap = 0;
-	success = prom_getproperty(ebus->prom_node, "interrupt-map",
-				   (char *)ebus->ebus_intmap,
-				   sizeof(ebus->ebus_intmap));
-	if (success == -1)
-		return;
-
-	ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap));
-
-	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();
-	}
-}
-#endif
-
-void
-prom_apply_generic_ranges (int node, int parent, struct linux_prom_registers *regs, int nregs)
-{
-	int success;
-	int num_ranges;
-	struct linux_prom_ranges ranges[PROMREG_MAX];
-	
-	success = prom_getproperty(node, "ranges",
-				   (char *) ranges,
-				   sizeof (ranges));
-	if (success != -1) {
-		num_ranges = (success/sizeof(struct linux_prom_ranges));
-		if (parent) {
-			struct linux_prom_ranges parent_ranges[PROMREG_MAX];
-			int num_parent_ranges;
-		
-			success = prom_getproperty(parent, "ranges",
-				   		   (char *) parent_ranges,
-				   		   sizeof (parent_ranges));
-			if (success != -1) {
-				num_parent_ranges = (success/sizeof(struct linux_prom_ranges));
-				prom_adjust_ranges (ranges, num_ranges, parent_ranges, num_parent_ranges);
-			}
-		}
-		prom_adjust_regs(regs, nregs, ranges, num_ranges);
-	}
-}
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c
--- v2.3.34/linux/arch/sparc64/solaris/fs.c	Sat May 15 11:12:09 1999
+++ linux/arch/sparc64/solaris/fs.c	Mon Dec 20 22:05:52 1999
@@ -1,7 +1,10 @@
-/* $Id: fs.c,v 1.13 1999/05/14 07:24:37 davem Exp $
+/* $Id: fs.c,v 1.14 1999/09/22 09:28:49 davem Exp $
  * fs.c: fs related syscall emulation for Solaris
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * 1999-08-19 Implemented solaris F_FREESP (truncate)
+ *            fcntl, by Jason Rappleye (rappleye@ccr.buffalo.edu)
  */
 
 #include <linux/types.h>
@@ -661,7 +664,16 @@
 			__put_user_ret (0, &((struct sol_flock *)A(arg))->l_sysid, -EFAULT);
 			return ret;
 		}
-	}
+	case SOL_F_FREESP:
+	        { 
+		    int length;
+		    int (*sys_newftruncate)(unsigned int, unsigned long)=
+			    (int (*)(unsigned int, unsigned long))SYS(ftruncate);
+
+		    get_user_ret(length, &((struct sol_flock*)A(arg))->l_start, -EFAULT);
+		    return sys_newftruncate(fd, length);
+		}
+	};
 	return -EINVAL;
 }
 
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/solaris/ioctl.c linux/arch/sparc64/solaris/ioctl.c
--- v2.3.34/linux/arch/sparc64/solaris/ioctl.c	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc64/solaris/ioctl.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ioctl.c,v 1.13 1999/08/20 00:27:15 davem Exp $
+/* $Id: ioctl.c,v 1.14 1999/09/22 09:28:50 davem Exp $
  * ioctl.c: Solaris ioctl emulation.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -7,6 +7,9 @@
  * Streams & timod emulation based on code
  * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
  *
+ * 1999-08-19 Implemented solaris 'm' (mag tape) and
+ *            'O' (openprom) ioctls, by Jason Rappleye
+ *             (rappleye@ccr.buffalo.edu)
  */
 
 #include <linux/types.h>
@@ -18,9 +21,12 @@
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/netdevice.h>
+#include <linux/mtio.h>
+#include <linux/time.h>
 
 #include <asm/uaccess.h>
 #include <asm/termios.h>
+#include <asm/openpromio.h>
 
 #include "conv.h"
 #include "socksys.h"
@@ -678,6 +684,90 @@
 	return -ENOSYS;
 }
 
+static int solaris_m(unsigned int fd, unsigned int cmd, u32 arg)
+{
+	int ret;
+
+	switch (cmd & 0xff) {
+	case 1: /* MTIOCTOP */
+		ret = sys_ioctl(fd, MTIOCTOP, (unsigned long)&arg);
+		break;
+	case 2: /* MTIOCGET */
+		ret = sys_ioctl(fd, MTIOCGET, (unsigned long)&arg);
+		break;
+	case 3: /* MTIOCGETDRIVETYPE */
+	case 4: /* MTIOCPERSISTENT */
+	case 5: /* MTIOCPERSISTENTSTATUS */
+	case 6: /* MTIOCLRERR */
+	case 7: /* MTIOCGUARANTEEDORDER */
+	case 8: /* MTIOCRESERVE */
+	case 9: /* MTIOCRELEASE */
+	case 10: /* MTIOCFORCERESERVE */
+	case 13: /* MTIOCSTATE */
+	case 14: /* MTIOCREADIGNOREILI */
+	case 15: /* MTIOCREADIGNOREEOFS */
+	case 16: /* MTIOCSHORTFMK */
+	default:
+		ret = -ENOSYS; /* linux doesn't support these */
+		break;
+	};
+
+	return ret;
+}
+
+static int solaris_O(unsigned int fd, unsigned int cmd, u32 arg)
+{
+	int ret = -EINVAL;
+
+	switch (cmd & 0xff) {
+	case 1: /* OPROMGETOPT */
+		ret = sys_ioctl(fd, OPROMGETOPT, arg);
+		break;
+	case 2: /* OPROMSETOPT */
+		ret = sys_ioctl(fd, OPROMSETOPT, arg);
+		break;
+	case 3: /* OPROMNXTOPT */
+		ret = sys_ioctl(fd, OPROMNXTOPT, arg);
+		break;
+	case 4: /* OPROMSETOPT2 */
+		ret = sys_ioctl(fd, OPROMSETOPT2, arg);
+		break;
+	case 5: /* OPROMNEXT */
+		ret = sys_ioctl(fd, OPROMNEXT, arg);
+		break;
+	case 6: /* OPROMCHILD */
+		ret = sys_ioctl(fd, OPROMCHILD, arg);
+		break;
+	case 7: /* OPROMGETPROP */
+		ret = sys_ioctl(fd, OPROMGETPROP, arg);
+		break;
+	case 8: /* OPROMNXTPROP */
+		ret = sys_ioctl(fd, OPROMNXTPROP, arg);
+		break;
+	case 9: /* OPROMU2P */
+		ret = sys_ioctl(fd, OPROMU2P, arg);
+		break;
+	case 10: /* OPROMGETCONS */
+		ret = sys_ioctl(fd, OPROMGETCONS, arg);
+		break;
+	case 11: /* OPROMGETFBNAME */
+		ret = sys_ioctl(fd, OPROMGETFBNAME, arg);
+		break;
+	case 12: /* OPROMGETBOOTARGS */
+		ret = sys_ioctl(fd, OPROMGETBOOTARGS, arg);
+		break;
+	case 13: /* OPROMGETVERSION */
+	case 14: /* OPROMPATH2DRV */
+	case 15: /* OPROMDEV2PROMNAME */
+	case 16: /* OPROMPROM2DEVNAME */
+	case 17: /* OPROMGETPROPLEN */
+	default:
+		ret = -EINVAL;
+		break;
+	};
+	return ret;
+}
+
 /* }}} */
 
 asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
@@ -699,6 +789,8 @@
 	case 's': error = solaris_s(fd, cmd, arg); break;
 	case 't': error = solaris_t(fd, cmd, arg); break;
 	case 'f': error = sys_ioctl(fd, cmd, arg); break;
+	case 'm': error = solaris_m(fd, cmd, arg); break;
+	case 'O': error = solaris_O(fd, cmd, arg); break;
 	default:
 		error = -ENOSYS;
 		break;
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/solaris/ipc.c linux/arch/sparc64/solaris/ipc.c
--- v2.3.34/linux/arch/sparc64/solaris/ipc.c	Sat May 15 11:12:09 1999
+++ linux/arch/sparc64/solaris/ipc.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ipc.c,v 1.4 1999/05/13 07:11:37 jj Exp $
+/* $Id: ipc.c,v 1.5 1999/12/09 00:41:00 davem Exp $
  * ipc.c: Solaris IPC emulation
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -8,6 +8,7 @@
 #include <linux/types.h>
 #include <linux/smp_lock.h>
 #include <linux/wait.h>
+#include <linux/mm.h>
 #include <linux/shm.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/solaris/misc.c linux/arch/sparc64/solaris/misc.c
--- v2.3.34/linux/arch/sparc64/solaris/misc.c	Tue Jun 29 09:22:08 1999
+++ linux/arch/sparc64/solaris/misc.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.14 1999/06/25 11:00:53 davem Exp $
+/* $Id: misc.c,v 1.19 1999/12/15 17:51:25 jj Exp $
  * misc.c: Miscelaneous syscall emulation for Solaris
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -476,8 +476,8 @@
 #define RLIMIT_SOL_VMEM		6
 
 struct rlimit32 {
-	s32	rlim_cur;
-	s32	rlim_max;
+	u32	rlim_cur;
+	u32	rlim_max;
 };
 
 asmlinkage int solaris_getrlimit(unsigned int resource, struct rlimit32 *rlim)
@@ -747,11 +747,7 @@
 	1, 1,	/* PER_SVR4 personality */
 	solaris_to_linux_signals,
 	linux_to_solaris_signals,
-#ifdef MODULE
-	&__this_module,
-#else
-	NULL,
-#endif
+	THIS_MODULE,
 	NULL
 };
 
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/solaris/socket.c linux/arch/sparc64/solaris/socket.c
--- v2.3.34/linux/arch/sparc64/solaris/socket.c	Mon Nov 16 10:37:28 1998
+++ linux/arch/sparc64/solaris/socket.c	Mon Dec 20 22:05:52 1999
@@ -1,7 +1,10 @@
-/* $Id: socket.c,v 1.1 1998/10/28 08:12:11 jj Exp $
+/* $Id: socket.c,v 1.2 1999/09/22 09:28:50 davem Exp $
  * socket.c: Socket syscall emulation for Solaris 2.6+
  *
  * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
+ *
+ * 1999-08-19 Fixed socketpair code 
+ *            Jason Rappleye (rappleye@ccr.buffalo.edu)
  */
 
 #include <linux/types.h>
@@ -25,6 +28,18 @@
 #define SOCK_SOL_RDM		5
 #define SOCK_SOL_SEQPACKET	6
 
+#define SOL_SO_SNDLOWAT		0x1003
+#define SOL_SO_RCVLOWAT		0x1004
+#define SOL_SO_SNDTIMEO		0x1005
+#define SOL_SO_RCVTIMEO		0x1006
+#define SOL_SO_STATE		0x2000
+
+#define SOL_SS_NDELAY		0x040
+#define SOL_SS_NONBLOCK		0x080
+#define SOL_SS_ASYNC		0x100
+
+#define SO_STATE		0x000e
+
 static int socket_check(int family, int type)
 {
 	if (family != PF_UNIX && family != PF_INET)
@@ -40,6 +55,19 @@
 	return type;
 }
 
+static int solaris_to_linux_sockopt(int optname) 
+{
+	switch (optname) {
+	case SOL_SO_SNDLOWAT: optname = SO_SNDLOWAT; break;
+	case SOL_SO_RCVLOWAT: optname = SO_RCVLOWAT; break;
+	case SOL_SO_SNDTIMEO: optname = SO_SNDTIMEO; break;
+	case SOL_SO_RCVTIMEO: optname = SO_RCVTIMEO; break;
+	case SOL_SO_STATE: optname = SO_STATE; break;
+	};
+	
+	return optname;
+}
+	
 asmlinkage int solaris_socket(int family, int type, int protocol)
 {
 	int (*sys_socket)(int, int, int) =
@@ -50,14 +78,19 @@
 	return sys_socket(family, type, protocol);
 }
 
-asmlinkage int solaris_socketpair(int family, int type, int protocol, int *usockvec)
+asmlinkage int solaris_socketpair(int *usockvec)
 {
 	int (*sys_socketpair)(int, int, int, int *) =
 		(int (*)(int, int, int, int *))SYS(socketpair);
 
-	type = socket_check (family, type);
-	if (type < 0) return type;
-	return sys_socketpair(family, type, protocol, usockvec);
+	/* solaris socketpair really only takes one arg at the syscall
+	 * level, int * usockvec. The libs apparently take care of 
+	 * making sure that family==AF_UNIX and type==SOCK_STREAM. The 
+	 * pointer we really want ends up residing in the first (and
+	 * supposedly only) argument.
+	 */
+
+	return sys_socketpair(AF_UNIX, SOCK_STREAM, 0, (int *)usockvec);
 }
 
 asmlinkage int solaris_bind(int fd, struct sockaddr *addr, int addrlen)
@@ -73,6 +106,12 @@
 	int (*sunos_setsockopt)(int, int, int, u32, int) =
 		(int (*)(int, int, int, u32, int))SUNOS(105);
 
+	optname = solaris_to_linux_sockopt(optname);
+	if (optname < 0)
+		return optname;
+	if (optname == SO_STATE)
+		return 0;
+
 	return sunos_setsockopt(fd, level, optname, optval, optlen);
 }
 
@@ -80,6 +119,13 @@
 {
 	int (*sunos_getsockopt)(int, int, int, u32, u32) =
 		(int (*)(int, int, int, u32, u32))SUNOS(118);
+
+	optname = solaris_to_linux_sockopt(optname);
+	if (optname < 0)
+		return optname;
+
+	if (optname == SO_STATE)
+		optname = SOL_SO_STATE;
 
 	return sunos_getsockopt(fd, level, optname, optval, optlen);
 }
diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/solaris/timod.c linux/arch/sparc64/solaris/timod.c
--- v2.3.34/linux/arch/sparc64/solaris/timod.c	Mon Oct 11 15:38:14 1999
+++ linux/arch/sparc64/solaris/timod.c	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: timod.c,v 1.4 1999/09/01 08:07:47 davem Exp $
+/* $Id: timod.c,v 1.5 1999/11/23 08:55:24 davem Exp $
  * timod.c: timod emulation.
  *
  * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
diff -u --recursive --new-file v2.3.34/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c
--- v2.3.34/linux/drivers/block/ide-probe.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/ide-probe.c	Tue Dec 21 21:56:42 1999
@@ -624,7 +624,7 @@
 		hwif->io_ports[IDE_DATA_OFFSET]+7,
 		hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq);
 #elif defined(__sparc__)
-	printk("%s at 0x%03x-0x%03x,0x%03x on irq %s", hwif->name,
+	printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %s", hwif->name,
 		hwif->io_ports[IDE_DATA_OFFSET],
 		hwif->io_ports[IDE_DATA_OFFSET]+7,
 		hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq));
diff -u --recursive --new-file v2.3.34/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.3.34/linux/drivers/block/rd.c	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/rd.c	Fri Dec 24 13:06:05 1999
@@ -185,6 +185,8 @@
 {
 	unsigned int minor;
 	unsigned long offset, len;
+	struct buffer_head *rbh;
+	struct buffer_head *sbh;
 
 repeat:
 	INIT_REQUEST;
@@ -211,16 +213,66 @@
 	}
 
 	/*
-	 * If we're reading, fill the buffer with 0's.  This is okay since
-         * we're using protected buffers which should never get freed...
+	 * This has become somewhat more complicated with the addition of
+	 * the page cache.  The problem is that in some cases the furnished
+	 * buffer is "real", i.e., part of the existing ramdisk, while in
+	 * others it is "unreal", e.g., part of a page.  In the first case
+	 * not much needs to be done, while in the second, some kind of
+	 * transfer is needed.
+ 	 *
+	 * The two cases are distinguished here by checking whether the
+	 * real buffer is already in the buffer cache, and whether it is
+	 * the same as the one supplied.
 	 *
-	 * If we're writing, we protect the buffer.
-  	 */
-
-	if (CURRENT->cmd == READ) 
-		memset(CURRENT->buffer, 0, len); 
-	else
-		set_bit(BH_Protected, &CURRENT->bh->b_state);
+	 * There are three cases with read/write to consider:
+	 *
+	 * 1. Supplied buffer matched one in the buffer cache:
+	 *    Read - Clear the buffer, as it wasn't already valid.
+	 *    Write - Mark the buffer as "Protected".
+	 *
+	 * 2. Supplied buffer mismatched one in the buffer cache:
+	 *    Read - Copy the data from the buffer cache entry.
+	 *    Write - Copy the data to the buffer cache entry.
+	 *
+	 * 3  No buffer cache entry existed:
+	 *    Read - Clear the supplied buffer, but do not create a real
+	 *    one.
+	 *    Write - Create a real buffer, copy the data to it, and mark
+	 *    it as "Protected".
+	 *
+	 * NOTE: There seems to be some schizophrenia here - the logic
+	 * using "len" seems to assume arbitrary request lengths, while
+	 * the "protect" logic assumes a single buffer cache entry.
+	 * This seems to be left over from the ancient contiguous ramdisk
+	 * logic.
+	 */
+
+	sbh = CURRENT->bh;
+	rbh = get_hash_table(sbh->b_dev, sbh->b_blocknr, sbh->b_size);
+	if (sbh == rbh) {
+		if (CURRENT->cmd == READ) 
+			memset(CURRENT->buffer, 1, len);
+	} else if (rbh) {
+		if (CURRENT->cmd == READ)
+			memcpy(CURRENT->buffer, rbh->b_data, rbh->b_size);
+		else
+			memcpy(rbh->b_data, CURRENT->buffer, rbh->b_size);
+	} else { /* !rbh */
+		if (CURRENT->cmd == READ)
+			memset(sbh->b_data, 2, len);
+		else {
+			rbh = getblk(sbh->b_dev, sbh->b_blocknr, sbh->b_size);
+			if (rbh)
+				memcpy(rbh->b_data, CURRENT->buffer,
+				    rbh->b_size);
+			else
+				BUG();	/* No buffer, what to do here? */
+		}
+	}
+	if (rbh) {
+ 		set_bit(BH_Protected, &rbh->b_state);
+		brelse(rbh);
+	}
 
 	end_request(1);
 	goto repeat;
diff -u --recursive --new-file v2.3.34/linux/drivers/char/n_hdlc.c linux/drivers/char/n_hdlc.c
--- v2.3.34/linux/drivers/char/n_hdlc.c	Thu Nov 11 20:11:34 1999
+++ linux/drivers/char/n_hdlc.c	Tue Dec 21 10:13:00 1999
@@ -9,7 +9,7 @@
  *	Al Longyear <longyear@netcom.com>, Paul Mackerras <Paul.Mackerras@cs.anu.edu.au>
  *
  * Original release 01/11/99
- * ==FILEDATE 19990901==
+ * ==FILEDATE 19991217==
  *
  * This code is released under the GNU General Public License (GPL)
  *
@@ -78,7 +78,7 @@
  */
 
 #define HDLC_MAGIC 0x239e
-#define HDLC_VERSION "1.11"
+#define HDLC_VERSION "1.13"
 
 #include <linux/version.h>
 #include <linux/config.h>
@@ -171,6 +171,7 @@
 #if LINUX_VERSION_CODE < VERSION(2,1,0)
 #define __init
 typedef int spinlock_t;
+#define spin_lock_init(a)
 #define spin_lock_irqsave(a,b) {save_flags((b));cli();}
 #define spin_unlock_irqrestore(a,b) {restore_flags((b));}
 #define spin_lock(a)
@@ -659,8 +660,11 @@
 	/* wake up any blocked reads and perform async signalling */
 	wake_up_interruptible (&n_hdlc->read_wait);
 	if (n_hdlc->tty->fasync != NULL)
+#if LINUX_VERSION_CODE < VERSION(2,3,0) 
+		kill_fasync (n_hdlc->tty->fasync, SIGIO);
+#else
 		kill_fasync (n_hdlc->tty->fasync, SIGIO, POLL_IN);
-
+#endif
 }	/* end of n_hdlc_tty_receive() */
 
 /* n_hdlc_tty_read()
@@ -1072,7 +1076,7 @@
 void n_hdlc_buf_list_init(N_HDLC_BUF_LIST *list)
 {
 	memset(list,0,sizeof(N_HDLC_BUF_LIST));
-		
+	spin_lock_init(&list->spinlock);
 }	/* end of n_hdlc_buf_list_init() */
 
 /* n_hdlc_buf_put()
diff -u --recursive --new-file v2.3.34/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.3.34/linux/drivers/char/pc_keyb.c	Wed Dec 15 10:43:16 1999
+++ linux/drivers/char/pc_keyb.c	Wed Dec 22 10:53:57 1999
@@ -746,6 +746,10 @@
 	int loops = 10;
 	int retval = 0;
 
+	/* Check if the BIOS detected a device on the auxiliary port. */
+	if (aux_device_present == 0xaa)
+		return 1;
+
 	spin_lock_irqsave(&kbd_controller_lock, flags);
 
 	/* Put the value 0x5A in the output buffer using the "Write
diff -u --recursive --new-file v2.3.34/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.3.34/linux/drivers/char/serial.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/char/serial.c	Mon Dec 20 21:14:42 1999
@@ -74,6 +74,7 @@
 
 #include <linux/config.h>
 #include <linux/version.h>
+#include <linux/sysrq.h>
 
 #undef SERIAL_PARANOIA_CHECK
 #define CONFIG_SERIAL_NOPAUSE_IO
diff -u --recursive --new-file v2.3.34/linux/drivers/char/synclink.c linux/drivers/char/synclink.c
--- v2.3.34/linux/drivers/char/synclink.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/char/synclink.c	Tue Dec 21 10:13:06 1999
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink.c
  *
- * ==FILEDATE 19991207==
+ * ==FILEDATE 19991217==
  *
  * Device driver for Microgate SyncLink ISA and PCI
  * high speed multiprotocol serial adapters.
@@ -158,6 +158,7 @@
 #define SERIAL_TYPE_NORMAL	1
 #define SERIAL_TYPE_CALLOUT	2
 typedef int spinlock_t;
+#define spin_lock_init(a)
 #define spin_lock_irqsave(a,b) {save_flags((b));cli();}
 #define spin_unlock_irqrestore(a,b) {restore_flags((b));}
 #define spin_lock(a)
@@ -925,7 +926,7 @@
 #endif
 
 static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "1.15";
+static char *driver_version = "1.16";
 
 static struct tty_driver serial_driver, callout_driver;
 static int serial_refcount;
@@ -4456,7 +4457,7 @@
 		init_waitqueue_head(&info->close_wait);
 		init_waitqueue_head(&info->status_event_wait_q);
 		init_waitqueue_head(&info->event_wait_q);
-
+		spin_lock_init(&info->irq_spinlock);
 		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
 		info->idle_mode = HDLC_TXIDLE_FLAGS;		
 	}
diff -u --recursive --new-file v2.3.34/linux/drivers/fc4/fc.c linux/drivers/fc4/fc.c
--- v2.3.34/linux/drivers/fc4/fc.c	Wed May 12 08:41:15 1999
+++ linux/drivers/fc4/fc.c	Mon Dec 20 22:06:42 1999
@@ -54,29 +54,29 @@
 #endif
 
 #ifdef __sparc__
-static inline void *fc_dma_alloc(long size, char *name, dma_handle *dma)
+static inline void *fc_dma_alloc(long size, dma_handle *dma, fc_channel *fc)
 {
-	return (void *) sparc_dvma_malloc (size, name, dma);
+	return sbus_alloc_consistant(fc->dev, size, dma);
 }
 
-static inline dma_handle fc_sync_dma_entry(void *buf, int len, fc_channel *fc)
+static inline dma_handle fc_sync_dma_entry(void *buf, long len, fc_channel *fc)
 {
-	return mmu_get_scsi_one (buf, len, fc->dev->my_bus);
+	return sbus_map_single(fc->dev, buf, len);
 }
 
 static inline void fc_sync_dma_exit(dma_handle dmh, long size, fc_channel *fc)
 {
-	mmu_release_scsi_one (dmh, size, fc->dev->my_bus);
+	sbus_unmap_single(fc->dev, dmh, size);
 }
 
 static inline void fc_sync_dma_entry_sg(struct scatterlist *list, int count, fc_channel *fc)
 {
-	mmu_get_scsi_sgl((struct mmu_sglist *)list, count - 1, fc->dev->my_bus);
+	sbus_map_sg(fc->dev, list, count);
 }
 
 static inline void fc_sync_dma_exit_sg(struct scatterlist *list, int count, fc_channel *fc)
 {
-	mmu_release_scsi_sgl ((struct mmu_sglist *)list, count - 1, fc->dev->my_bus);
+	sbus_unmap_sg(fc->dev, list, count);
 }
 #else
 #error Port this
@@ -352,7 +352,7 @@
 		if (!unregister) {
 			fc->scsi_cmd_pool = 
 				(fcp_cmd *) fc_dma_alloc (slots * (sizeof (fcp_cmd) + fc->rsp_size), 
-							  "FCP SCSI cmd & rsp queues", &fc->dma_scsi_cmd);
+							  &fc->dma_scsi_cmd, fc);
 			fc->scsi_rsp_pool = (char *)(fc->scsi_cmd_pool + slots);
 			fc->dma_scsi_rsp = fc->dma_scsi_cmd + slots * sizeof (fcp_cmd);
 			fc->scsi_bitmap_end = (slots + 63) & ~63;
@@ -555,7 +555,7 @@
 	l->timer.function = fcp_login_timeout;
 	l->timer.data = (unsigned long)l;
 	atomic_set (&l->todo, count);
-	l->logi = kmalloc (count * 3 * sizeof(logi), GFP_DMA);
+	l->logi = kmalloc (count * 3 * sizeof(logi), GFP_KERNEL);
 	l->fcmds = kmalloc (count * sizeof(fcp_cmnd), GFP_KERNEL);
 	if (!l->logi || !l->fcmds) {
 		if (l->logi) kfree (l->logi);
@@ -821,7 +821,7 @@
 				if (SCpnt->use_sg > 1) printk ("%s: SG for use_sg > 1 not handled yet\n", fc->name);
 				fc_sync_dma_entry_sg (sg, SCpnt->use_sg, fc);
 				fcmd->data = sg->dvma_address;
-				cmd->fcp_data_len = sg->length;
+				cmd->fcp_data_len = sg->dvma_length;
 			}
 		}
 		memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len);
@@ -1103,7 +1103,7 @@
 	logi *l;
 	int status;
 
-	l = (logi *)kmalloc(2 * sizeof(logi), GFP_DMA);
+	l = (logi *)kmalloc(2 * sizeof(logi), GFP_KERNEL);
 	if (!l) return -ENOMEM;
 	memset(l, 0, 2 * sizeof(logi));
 	l->code = LS_PLOGI;
@@ -1138,7 +1138,7 @@
 	prli *p;
 	int status;
 
-	p = (prli *)kmalloc(2 * sizeof(prli), GFP_DMA);
+	p = (prli *)kmalloc(2 * sizeof(prli), GFP_KERNEL);
 	if (!p) return -ENOMEM;
 	memset(p, 0, 2 * sizeof(prli));
 	p->code = LS_PRLI;
diff -u --recursive --new-file v2.3.34/linux/drivers/fc4/fcp_impl.h linux/drivers/fc4/fcp_impl.h
--- v2.3.34/linux/drivers/fc4/fcp_impl.h	Mon Mar 15 16:11:29 1999
+++ linux/drivers/fc4/fcp_impl.h	Mon Dec 20 22:06:42 1999
@@ -84,7 +84,7 @@
 	common_svc_parm		*common_svc;
 	svc_parm		*class_svcs;
 #ifdef __sparc__	
-	struct linux_sbus_device *dev;
+	struct sbus_dev		*dev;
 #endif
 	struct module		*module;
 	/* FCP SCSI stuff */
diff -u --recursive --new-file v2.3.34/linux/drivers/fc4/soc.c linux/drivers/fc4/soc.c
--- v2.3.34/linux/drivers/fc4/soc.c	Thu Aug  5 14:34:02 1999
+++ linux/drivers/fc4/soc.c	Mon Dec 20 22:06:42 1999
@@ -66,16 +66,18 @@
 
 static inline void soc_disable(struct soc *s)
 {
-	s->regs->imask = 0; s->regs->cmd = SOC_CMD_SOFT_RESET;
+	sbus_writel(0, s->regs + IMASK);
+	sbus_writel(SOC_CMD_SOFT_RESET, s->regs + CMD);
 }
 
 static inline void soc_enable(struct soc *s)
 {
 	SOD(("enable %08x\n", s->cfg))
-	s->regs->sae = 0; s->regs->cfg = s->cfg;
-	s->regs->cmd = SOC_CMD_RSP_QALL; 
+	sbus_writel(0, s->regs + SAE);
+	sbus_writel(s->cfg, s->regs + CFG);
+	sbus_writel(SOC_CMD_RSP_QALL, s->regs + CMD);
 	SOC_SETIMASK(s, SOC_IMASK_RSP_QALL | SOC_IMASK_SAE);
-	SOD(("imask %08lx %08lx\n", s->imask, s->regs->imask));
+	SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMAK)));
 }
 
 static void soc_reset(fc_channel *fc)
@@ -114,23 +116,29 @@
 	sw_cq = &s->rsp[SOC_SOLICITED_RSP_Q];
 
 	if (sw_cq->pool == NULL)
-		sw_cq->pool =
-			(soc_req *)(s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address) / sizeof(u16)));
+		sw_cq->pool = (soc_req *)
+			(s->xram + xram_get_32low ((xram_p)&sw_cq->hw_cq->address));
 	sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
-	SOD (("soc_solicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last))
+	SOD (("soc_solicited, %d pkts arrived\n", (sw_cq->in-sw_cq->out) & sw_cq->last))
 	for (;;) {
 		hwrsp = (soc_rsp *)sw_cq->pool + sw_cq->out;
 		token = xram_get_32low ((xram_p)&hwrsp->shdr.token);
 		status = xram_get_32low ((xram_p)&hwrsp->status);
 		fc = (fc_channel *)(&s->port[(token >> 11) & 1]);
 		
-		if (status == SOC_OK)
-			fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), FC_STATUS_OK, NULL);
-		else {
+		if (status == SOC_OK) {
+			fcp_receive_solicited(fc, token >> 12,
+					      token & ((1 << 11) - 1),
+					      FC_STATUS_OK, NULL);
+		} else {
 			xram_copy_from(&fchdr, (xram_p)&hwrsp->fchdr, sizeof(fchdr));
-			/* We have intentionally defined FC_STATUS_* constants to match SOC_* constants, otherwise
-			   we'd have to translate status */
-			fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), status, &fchdr);
+			/* We have intentionally defined FC_STATUS_* constants
+			 * to match SOC_* constants, otherwise we'd have to
+			 * translate status.
+			 */
+			fcp_receive_solicited(fc, token >> 12,
+					      token & ((1 << 11) - 1),
+					      status, &fchdr);
 		}
 			
 		if (++sw_cq->out > sw_cq->last) {
@@ -142,9 +150,13 @@
 			sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
 			if (sw_cq->out == sw_cq->in) {
 				/* Tell the hardware about it */
-				s->regs->cmd = (sw_cq->out << 24) | (SOC_CMD_RSP_QALL & ~(SOC_CMD_RSP_Q0 << SOC_SOLICITED_RSP_Q));
+				sbus_writel((sw_cq->out << 24) |
+					    (SOC_CMD_RSP_QALL &
+					     ~(SOC_CMD_RSP_Q0 << SOC_SOLICITED_RSP_Q)),
+					    s->regs + CMD);
+
 				/* Read it, so that we're sure it has been updated */
-				s->regs->cmd;
+				sbus_readl(s->regs + CMD);
 				sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
 				if (sw_cq->out == sw_cq->in)
 					break;
@@ -156,15 +168,18 @@
 static void inline soc_request (struct soc *s, u32 cmd)
 {
 	SOC_SETIMASK(s, s->imask & ~(cmd & SOC_CMD_REQ_QALL));
-	SOD(("imask %08lx %08lx\n", s->imask, s->regs->imask));
+	SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK)));
 
-	SOD(("Queues available %08x OUT %X %X\n", cmd, xram_get_8((xram_p)&s->req[0].hw_cq->out), xram_get_8((xram_p)&s->req[0].hw_cq->out)))
+	SOD(("Queues available %08x OUT %X %X\n", cmd,
+	     xram_get_8((xram_p)&s->req[0].hw_cq->out),
+	     xram_get_8((xram_p)&s->req[0].hw_cq->out)))
 	if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) {
 		fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port]));
 		if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out))
 			fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
-	} else
+	} else {
 		fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
+	}
 	if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE)
 		s->curr_port ^= 1;
 }
@@ -180,8 +195,8 @@
 
 	sw_cq = &s->rsp[SOC_UNSOLICITED_RSP_Q];
 	if (sw_cq->pool == NULL)
-		sw_cq->pool =
-			(soc_req *)(s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address) / sizeof(u16)));
+		sw_cq->pool = (soc_req *)
+			(s->xram + (xram_get_32low ((xram_p)&sw_cq->hw_cq->address)));
 
 	sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
 	SOD (("soc_unsolicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last))
@@ -193,27 +208,34 @@
 		flags = hwrsp->shdr.flags;
 		count = xram_get_8 ((xram_p)&hwrsp->count);
 		fc = (fc_channel *)&s->port[flags & SOC_PORT_B];
-		SOD(("FC %08lx fcp_state_change %08lx\n", (long)fc, (long)fc->fcp_state_change))
+		SOD(("FC %08lx fcp_state_change %08lx\n",
+		     (long)fc, (long)fc->fcp_state_change))
 		
 		if (count != 1) {
 			/* Ugh, continuation entries */
 			u8 in;
 
 			if (count != 2) {
-				printk("%s: Too many continuations entries %d\n", fc->name, count);
+				printk("%s: Too many continuations entries %d\n",
+				       fc->name, count);
 				goto update_out;
 			}
 			
 			in = sw_cq->in;
 			if (in < sw_cq->out) in += sw_cq->last + 1;
 			if (in < sw_cq->out + 2) {
-				/* Ask the hardware about it if they haven't arrived yet */
-				s->regs->cmd = (sw_cq->out << 24) | (SOC_CMD_RSP_QALL & ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q));
+				/* Ask the hardware if they haven't arrived yet. */
+				sbus_writel((sw_cq->out << 24) |
+					    (SOC_CMD_RSP_QALL &
+					     ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)),
+					    s->regs + CMD);
+
 				/* Read it, so that we're sure it has been updated */
-				s->regs->cmd;
+				sbus_readl(s->regs + CMD);
 				sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
 				in = sw_cq->in;
-				if (in < sw_cq->out) in += sw_cq->last + 1;
+				if (in < sw_cq->out)
+					in += sw_cq->last + 1;
 				if (in < sw_cq->out + 2) /* Nothing came, let us wait */
 					return;
 			}
@@ -236,7 +258,8 @@
 				fcp_state_change(fc, FC_STATE_OFFLINE);
 				break;
 			default:
-				printk ("%s: Unknown STATUS no %d\n", fc->name, status);
+				printk ("%s: Unknown STATUS no %d\n",
+					fc->name, status);
 				break;
 			}
 			break;
@@ -248,29 +271,40 @@
 				
 				if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) {
 					len = xram_get_32 ((xram_p)&hwrsp->shdr.bytecnt);
-					if (len < 4 || !hwrspc)
-						printk ("%s: Invalid R_CTL %02x continuation entries\n", fc->name, r_ctl);
-					else {
-						if (len > 60) len = 60;
-						xram_copy_from (buf, (xram_p)hwrspc, (len + 3) & ~3);
+					if (len < 4 || !hwrspc) {
+						printk ("%s: Invalid R_CTL %02x "
+							"continuation entries\n",
+							fc->name, r_ctl);
+					} else {
+						if (len > 60)
+							len = 60;
+						xram_copy_from (buf, (xram_p)hwrspc,
+								(len + 3) & ~3);
 						if (*(u32 *)buf == LS_DISPLAY) {
 							int i;
 							
 							for (i = 4; i < len; i++)
-								if (buf[i] == '\n') buf[i] = ' ';
+								if (buf[i] == '\n')
+									buf[i] = ' ';
 							buf[len] = 0;
-							printk ("%s message: %s\n", fc->name, buf + 4);
-						} else
-							printk ("%s: Unknown LS_CMD %02x\n", fc->name, buf[0]);
+							printk ("%s message: %s\n",
+								fc->name, buf + 4);
+						} else {
+							printk ("%s: Unknown LS_CMD "
+								"%02x\n", fc->name,
+								buf[0]);
+						}
 					}
-				} else
-					printk ("%s: Unsolicited R_CTL %02x not handled\n", fc->name, r_ctl);
+				} else {
+					printk ("%s: Unsolicited R_CTL %02x "
+						"not handled\n", fc->name, r_ctl);
+				}
 			}
 			break;
 		default:
 			printk ("%s: Unexpected flags %08x\n", fc->name, flags);
 			break;
-		}
+		};
 update_out:
 		if (++sw_cq->out > sw_cq->last) {
 			sw_cq->seqno++;
@@ -288,9 +322,13 @@
 			sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
 			if (sw_cq->out == sw_cq->in) {
 				/* Tell the hardware about it */
-				s->regs->cmd = (sw_cq->out << 24) | (SOC_CMD_RSP_QALL & ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q));
+				sbus_writel((sw_cq->out << 24) |
+					    (SOC_CMD_RSP_QALL &
+					     ~(SOC_CMD_RSP_Q0 << SOC_UNSOLICITED_RSP_Q)),
+					    s->regs + CMD);
+
 				/* Read it, so that we're sure it has been updated */
-				s->regs->cmd;
+				sbus_readl(s->regs + CMD);
 				sw_cq->in = xram_get_8 ((xram_p)&sw_cq->hw_cq->in);
 			}
 		}
@@ -304,8 +342,8 @@
 	register struct soc *s = (struct soc *)dev_id;
 
 	spin_lock_irqsave(&io_request_lock, flags);
-	cmd = s->regs->cmd;
-	for (; (cmd = SOC_INTR (s, cmd)); cmd = s->regs->cmd) {
+	cmd = sbus_readl(s->regs + CMD);
+	for (; (cmd = SOC_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) {
 		if (cmd & SOC_CMD_RSP_Q1) soc_unsolicited (s);
 		if (cmd & SOC_CMD_RSP_Q0) soc_solicited (s);
 		if (cmd & SOC_CMD_REQ_QALL) soc_request (s, cmd);
@@ -338,11 +376,11 @@
 	sw_cq = s->req + qno;
 	cq_next_in = (sw_cq->in + 1) & sw_cq->last;
 	
-	if (cq_next_in == sw_cq->out 
-		    && cq_next_in == (sw_cq->out = xram_get_8((xram_p)&sw_cq->hw_cq->out))) {
+	if (cq_next_in == sw_cq->out &&
+	    cq_next_in == (sw_cq->out = xram_get_8((xram_p)&sw_cq->hw_cq->out))) {
 		SOD(("%d IN %d OUT %d LAST %d\n", qno, sw_cq->in, sw_cq->out, sw_cq->last))
 		SOC_SETIMASK(s, s->imask | (SOC_IMASK_REQ_Q0 << qno));
-		SOD(("imask %08lx %08lx\n", s->imask, s->regs->imask));
+		SOD(("imask %08lx %08lx\n", s->imask, sbus_readl(s->regs + IMASK)));
 		/* If queue is full, just say NO */
 		return -EBUSY;
 	}
@@ -363,7 +401,8 @@
 			request->shdr.bytecnt = i;
 			request->data[2].base = fcmd->data;
 			request->data[2].count = i;
-			request->type = (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ?
+			request->type =
+			    (fc->scsi_cmd_pool[fcmd->token].fcp_cntl & FCP_CNTL_WRITE) ?
 				SOC_CQTYPE_IO_WRITE : SOC_CQTYPE_IO_READ;
 		} else {
 			request->shdr.segcnt = 2;
@@ -374,7 +413,8 @@
 		}
 		FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did);
 		FILL_FCHDR_SID(fch, fc->sid);
-		FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
+		FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP,
+				     F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
 		FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
 		FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
 		fch->param = 0;
@@ -388,7 +428,8 @@
 		request->type = SOC_CQTYPE_OFFLINE;
 		FILL_FCHDR_RCTL_DID(fch, R_CTL_COMMAND, fc->did);
 		FILL_FCHDR_SID(fch, fc->sid);
-		FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP, F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
+		FILL_FCHDR_TYPE_FCTL(fch, TYPE_SCSI_FCP,
+				     F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE);
 		FILL_FCHDR_SEQ_DF_SEQ(fch, 0, 0, 0);
 		FILL_FCHDR_OXRX(fch, 0xffff, 0xffff);
 		request->shdr.flags = port->flags;
@@ -436,7 +477,9 @@
 			request->data[1].base = fcmd->rsp;
 			request->data[0].count = fcmd->cmdlen;
 			request->data[1].count = fcmd->rsplen;
-			request->type = (fcmd->class == FC_CLASS_IO_READ) ? SOC_CQTYPE_IO_READ : SOC_CQTYPE_IO_WRITE;
+			request->type =
+			      (fcmd->class == FC_CLASS_IO_READ) ?
+				SOC_CQTYPE_IO_READ : SOC_CQTYPE_IO_WRITE;
 			if (fcmd->data) {
 				request->data[2].base = fcmd->data;
 				request->data[2].count = fcmd->datalen;
@@ -447,9 +490,9 @@
 				request->shdr.segcnt = 2;
 			}
 			break;
-		}
+		};
 		break;
-	}
+	};
 
 	request->count = 1;
 	request->flags = 0;
@@ -462,11 +505,14 @@
 		sw_cq->seqno++;
 	}
 	
-	SOD(("Putting %08x into cmd\n", SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno)))
+	SOD(("Putting %08x into cmd\n",
+	     SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno)))
 	
-	s->regs->cmd = SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno);
-	/* Read so that command is completed */	
-	s->regs->cmd;
+	sbus_writel(SOC_CMD_RSP_QALL | (sw_cq->in << 24) | (SOC_CMD_REQ_Q0 << qno),
+		    s->regs + CMD);
+
+	/* Read so that command is completed. */	
+	sbus_readl(s->regs + CMD);
 	
 	return 0;
 }
@@ -475,19 +521,19 @@
 {
 #ifdef HAVE_SOC_UCODE
 	xram_copy_to (s->xram, soc_ucode, sizeof(soc_ucode));
-	xram_bzero (s->xram + (sizeof(soc_ucode)/sizeof(u16)), 32768 - sizeof(soc_ucode));
+	xram_bzero (s->xram + sizeof(soc_ucode), 32768 - sizeof(soc_ucode));
 #endif
 }
 
 /* Check for what the best SBUS burst we can use happens
  * to be on this machine.
  */
-static inline void soc_init_bursts(struct soc *s, struct linux_sbus_device *sdev)
+static inline void soc_init_bursts(struct soc *s, struct sbus_dev *sdev)
 {
 	int bsizes, bsizes_more;
 
 	bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff);
-	bsizes_more = (prom_getintdefault(sdev->my_bus->prom_node, "burst-sizes", 0xff) & 0xff);
+	bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff);
 	bsizes &= bsizes_more;
 	if ((bsizes & 0x7f) == 0x7f)
 		s->cfg = SOC_CFG_BURST_64;
@@ -499,22 +545,24 @@
 		s->cfg = SOC_CFG_BURST_4;
 }
 
-static inline void soc_init(struct linux_sbus_device *sdev, int no)
+static inline void soc_init(struct sbus_dev *sdev, int no)
 {
 	unsigned char tmp[60];
 	int propl;
 	struct soc *s;
-	static unsigned version_printed = 0;
+	static int version_printed = 0;
 	soc_hw_cq cq[8];
 	int size, i;
 	int irq;
 	
 	s = kmalloc (sizeof (struct soc), GFP_KERNEL);
-	if (!s) return;
+	if (s == NULL)
+		return;
 	memset (s, 0, sizeof(struct soc));
 	s->soc_no = no;
 
-	SOD(("socs %08lx soc_intr %08lx soc_hw_enque %08x\n", (long)socs, (long)soc_intr, (long)soc_hw_enque))	
+	SOD(("socs %08lx soc_intr %08lx soc_hw_enque %08x\n",
+	     (long)socs, (long)soc_intr, (long)soc_hw_enque))	
 	if (version_printed++ == 0)
 		printk (version);
 #ifdef MODULE
@@ -558,9 +606,9 @@
 	memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
 	memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
 	SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n", 
-		*(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
-		*(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
-		*(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo))
+	     *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
+	     *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
+	     *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo))
 		
 	s->port[0].fc.sid = 1;
 	s->port[1].fc.sid = 17;
@@ -570,26 +618,18 @@
 	s->port[0].fc.reset = soc_reset;
 	s->port[1].fc.reset = soc_reset;
 	
-	/* Setup the reg property for this device. */
-	prom_apply_sbus_ranges(sdev->my_bus, sdev->reg_addrs, sdev->num_registers, sdev);
-                                                                                                                                               	
 	if (sdev->num_registers == 1) {
 		/* Probably SunFire onboard SOC */
-		s->xram = (xram_p)
-			sparc_alloc_io (sdev->reg_addrs [0].phys_addr, 0, 
-				sdev->reg_addrs [0].reg_size, "soc_xram",
-				sdev->reg_addrs [0].which_io, 0);
-		s->regs = (struct soc_regs *)((char *)s->xram + 0x10000);
+		s->xram = sbus_ioremap(&sdev->resource[0], 0,
+				       0x10000UL, "soc xram");
+		s->regs = sbus_ioremap(&sdev->resource[0], 0x10000UL,
+				       0x10UL, "soc regs");
 	} else {
 		/* Probably SOC sbus card */
-		s->xram = (xram_p)
-			sparc_alloc_io (sdev->reg_addrs [1].phys_addr, 0, 
-				sdev->reg_addrs [1].reg_size, "soc_xram",
-				sdev->reg_addrs [1].which_io, 0);
-		s->regs = (struct soc_regs *)
-			sparc_alloc_io (sdev->reg_addrs [2].phys_addr, 0, 
-				sdev->reg_addrs [2].reg_size, "soc_regs",
-				sdev->reg_addrs [2].which_io, 0);
+		s->xram = sbus_ioremap(&sdev->resource[1], 0,
+				       sdev->reg_addrs[1].reg_size, "soc xram");
+		s->regs = sbus_ioremap(&sdev->resource[2], 0,
+				       sdev->reg_addrs[2].reg_size, "soc regs");
 	}
 	
 	soc_init_bursts(s, sdev);
@@ -628,13 +668,15 @@
 	memset (cq, 0, sizeof(cq));
 	
 	size = (SOC_CQ_REQ0_SIZE + SOC_CQ_REQ1_SIZE) * sizeof(soc_req);
-	s->req[0].pool = (soc_req *) sparc_dvma_malloc (size, "SOC request queues", &cq[0].address);
+	s->req_cpu = sbus_alloc_consistant(sdev, size, &s->req_dvma);
+	s->req[0].pool = s->req_cpu;
+	cq[0].address = s->req_dvma;
 	s->req[1].pool = s->req[0].pool + SOC_CQ_REQ0_SIZE;
 	
 	s->req[0].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_REQ_OFFSET);
-	s->req[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_REQ_OFFSET + sizeof(soc_hw_cq) / sizeof(u16));
+	s->req[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_REQ_OFFSET + sizeof(soc_hw_cq));
 	s->rsp[0].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_RSP_OFFSET);
-	s->rsp[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_RSP_OFFSET + sizeof(soc_hw_cq) / sizeof(u16));
+	s->rsp[1].hw_cq = (soc_hw_cq *)(s->xram + SOC_CQ_RSP_OFFSET + sizeof(soc_hw_cq));
 	
 	cq[1].address = cq[0].address + (SOC_CQ_REQ0_SIZE * sizeof(soc_req));
 	cq[4].address = 1;
@@ -677,13 +719,13 @@
 int init_module(void)
 #endif
 {
-	struct linux_sbus *bus;
-	struct linux_sbus_device *sdev = 0;
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev = 0;
 	struct soc *s;
 	int cards = 0;
 
-	for_each_sbus(bus) {
-		for_each_sbusdev(sdev, bus) {
+	for_each_sbus(sbus) {
+		for_each_sbusdev(sdev, sbus) {
 			if(!strcmp(sdev->prom_name, "SUNW,soc")) {
 				soc_init(sdev, cards);
 				cards++;
@@ -706,7 +748,7 @@
 {
 	struct soc *s;
 	int irq;
-	struct linux_sbus_device *sdev;
+	struct sbus_dev *sdev;
 	
 	for_each_soc(s) {
 		irq = s->port[0].fc.irq;
@@ -716,13 +758,16 @@
 		fcp_release(&(s->port[0].fc), 2);
 
 		sdev = s->port[0].fc.dev;
-		if (sdev->num_registers == 1)
-			sparc_free_io ((char *)s->xram, sdev->reg_addrs [0].reg_size);
-		else {
-			sparc_free_io ((char *)s->xram, sdev->reg_addrs [1].reg_size);
-			sparc_free_io ((char *)s->regs, sdev->reg_addrs [2].reg_size);
+		if (sdev->num_registers == 1) {
+			sbus_iounmap(s->xram, 0x10000UL);
+			sbus_iounmap(s->regs, 0x10UL);
+		} else {
+			sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size);
+			sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size);
 		}
-		/* FIXME: sparc_dvma_free() ??? */
+		sbus_free_consistant(sdev,
+				     (SOC_CQ_REQ0_SIZE+SOC_CQ_REQ1_SIZE)*sizeof(soc_req),
+				     s->req_cpu, s->req_dvma);
 	}
 }
 #endif
diff -u --recursive --new-file v2.3.34/linux/drivers/fc4/soc.h linux/drivers/fc4/soc.h
--- v2.3.34/linux/drivers/fc4/soc.h	Mon Mar 15 16:11:29 1999
+++ linux/drivers/fc4/soc.h	Mon Dec 20 22:06:42 1999
@@ -10,14 +10,11 @@
 #include "fcp.h"
 #include "fcp_impl.h"
 
-/* Hardware structures and constants first {{{ */
-
-struct soc_regs {
-	volatile u32 cfg;			/* Config Register */
-	volatile u32 sae;			/* Slave Access Error Register */
-	volatile u32 cmd;			/* Command & Status Register */
-	volatile u32 imask;			/* Interrupt Mask Register */
-};
+/* Hardware register offsets and constants first {{{ */
+#define CFG	0x00UL		/* Config Register */
+#define SAE	0x04UL		/* Slave Access Error Register */
+#define CMD	0x08UL		/* Command and Status Register */
+#define IMASK	0x0cUL		/* Interrupt Mask Register */
 
 /* Config Register */
 #define SOC_CFG_EXT_RAM_BANK_MASK	0x07000000
@@ -74,7 +71,9 @@
 	 & s->imask)
 	 
 #define SOC_SETIMASK(s, i) \
-	(s)->imask = (i); (s)->regs->imask = (i)
+do {	(s)->imask = (i); \
+	sbus_writel((i), (s)->regs + IMASK); \
+} while(0)
 
 /* XRAM
  *
@@ -82,56 +81,61 @@
  * That's why here are the following inline functions...
  */
  
-typedef u16 *xram_p;
+typedef unsigned long xram_p;
 
 /* Get 32bit number from XRAM */
 static inline u32 xram_get_32 (xram_p x)
 {
-	return (((u32)*x) << 16) | (x[1]);
+	return ((sbus_readw(x + 0x00UL) << 16) |
+		(sbus_readw(x + 0x02UL)));
 }
 
 /* Like the above, but when we don't care about the high 16 bits */
 static inline u32 xram_get_32low (xram_p x)
 {
-	return (u32)x[1];
+	return (u32) sbus_readw(x + 0x02UL);
 }
 
 static inline u8 xram_get_8 (xram_p x)
 {
-	if (((long)x) & 1) {
-		x = (xram_p)((long)x - 1);
-		return (u8)*x;
-	} else
-		return (u8)(*x >> 8);
+	if (x & (xram_p)0x1) {
+		x = x - 1;
+		return (u8) sbus_readw(x);
+	} else {
+		return (u8) (sbus_readw(x) >> 8);
+	}
 }
 
 static inline void xram_copy_from (void *p, xram_p x, int len)
 {
-	for (len >>= 2; len > 0; len--, x += 2) {
-		*((u32 *)p)++ = (((u32)(*x)) << 16) | (x[1]);
+	for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
+		u32 val;
+
+		val = ((sbus_readw(x + 0x00UL) << 16) |
+		       (sbus_readw(x + 0x02UL)));
+		*((u32 *)p)++ = val;
 	}
 }
 
 static inline void xram_copy_to (xram_p x, void *p, int len)
 {
-	register u32 tmp;
-	for (len >>= 2; len > 0; len--, x += 2) {
-		tmp = *((u32 *)p)++;
-		*x = tmp >> 16;
-		x[1] = tmp;
+	for (len >>= 2; len > 0; len--, x += sizeof(u32)) {
+		u32 tmp = *((u32 *)p)++;
+		sbus_writew(tmp >> 16, x + 0x00UL);
+		sbus_writew(tmp, x + 0x02UL);
 	}
 }
 
 static inline void xram_bzero (xram_p x, int len)
 {
-	for (len >>= 1; len > 0; len--) *x++ = 0;
+	for (len >>= 1; len > 0; len--, x += sizeof(u16))
+		sbus_writew(0, x);
 }
 
 /* Circular Queue */
 
-/* These two are in sizeof(u16) units */
-#define SOC_CQ_REQ_OFFSET	0x100
-#define SOC_CQ_RSP_OFFSET	0x110
+#define SOC_CQ_REQ_OFFSET	(0x100 * sizeof(u16))
+#define SOC_CQ_RSP_OFFSET	(0x110 * sizeof(u16))
 
 typedef struct {
 	u32			address;
@@ -260,7 +264,7 @@
 	soc_cq			req[2]; /* Request CQs */
 	soc_cq			rsp[2]; /* Response CQs */
 	int			soc_no;
-	struct soc_regs		*regs;
+	unsigned long		regs;
 	xram_p			xram;
 	fc_wwn			wwn;
 	u32			imask;	/* Our copy of regs->imask */
@@ -268,6 +272,9 @@
 	char			serv_params[80];
 	struct soc		*next;
 	int			curr_port; /* Which port will have priority to fcp_queue_empty */
+
+	soc_req			*req_cpu;
+	u32			req_dvma;
 };
 
 /* }}} */
diff -u --recursive --new-file v2.3.34/linux/drivers/fc4/socal.c linux/drivers/fc4/socal.c
--- v2.3.34/linux/drivers/fc4/socal.c	Thu Aug  5 14:34:02 1999
+++ linux/drivers/fc4/socal.c	Mon Dec 20 22:06:42 1999
@@ -61,23 +61,33 @@
 #define for_each_socal(s) for (s = socals; s; s = s->next)
 struct socal *socals = NULL;
 
-/* I don't think our VIS mem* routines will behave well
-   in IO... */
-static void socal_memcpy(void *d, void *s, int size)
+static void socal_copy_from_xram(void *d, unsigned long xram, long size)
 {
-	u32 *dp = (u32 *)d, *sp = (u32 *)s;
+	u32 *dp = (u32 *) d;
 	while (size) {
-		*dp++ = *sp++;
+		*dp++ = sbus_readl(xram);
+		xram += sizeof(u32);
+		size -= sizeof(u32);
+	}
+}
+
+static void socal_copy_to_xram(unsigned long xram, void *s, long size)
+{
+	u32 *sp = (u32 *) s;
+	while (size) {
+		u32 val = *sp++;
+		sbus_writel(val, xram);
+		xram += sizeof(u32);
 		size -= sizeof(u32);
 	}
 }
 
 #ifdef HAVE_SOCAL_UCODE
-static void socal_bzero(void *d, int size)
+static void socal_bzero(unsigned long xram, int size)
 {
-	u32 *dp = (u32 *)d;
 	while (size) {
-		*dp++ = 0;
+		sbus_writel(0, xram);
+		xram += sizeof(u32);
 		size -= sizeof(u32);
 	}
 }
@@ -85,16 +95,18 @@
 
 static inline void socal_disable(struct socal *s)
 {
-	s->regs->imask = 0; s->regs->cmd = SOCAL_CMD_SOFT_RESET;
+	sbus_writel(0, s->regs + IMASK);
+	sbus_writel(SOCAL_CMD_SOFT_RESET, s->regs + CMD);
 }
 
 static inline void socal_enable(struct socal *s)
 {
 	SOD(("enable %08x\n", s->cfg))
-	s->regs->sae = 0; s->regs->cfg = s->cfg;
-	s->regs->cmd = SOCAL_CMD_RSP_QALL; 
+	sbus_writel(0, s->regs + SAE);
+	sbus_writel(s->cfg, s->regs + CFG);
+	sbus_writel(SOCAL_CMD_RSP_QALL, s->regs + CMD);
 	SOCAL_SETIMASK(s, SOCAL_IMASK_RSP_QALL | SOCAL_IMASK_SAE);
-	SOD(("imask %08x %08x\n", s->imask, s->regs->imask));
+	SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK)));
 }
 
 static void socal_reset(fc_channel *fc)
@@ -121,7 +133,7 @@
 	socal_enable(s);
 }
 
-static void inline socal_solicited (struct socal *s, int qno)
+static void inline socal_solicited(struct socal *s, unsigned long qno)
 {
 	fc_hdr fchdr;
 	socal_rsp *hwrsp;
@@ -138,8 +150,9 @@
 			(socal_req *)(s->xram + (sw_cq->hw_cq->address & 0xfffe));
 	}
 	/* Finally an improvement against old SOC :) */
-	sw_cq->in = s->regs->respr[qno];
-	SOD (("socal_solicited, %d packets arrived\n", (sw_cq->in - sw_cq->out) & sw_cq->last))
+	sw_cq->in = sbus_readb(s->regs + RESP + qno);
+	SOD (("socal_solicited, %d packets arrived\n",
+	      (sw_cq->in - sw_cq->out) & sw_cq->last))
 	for (;;) {
 		hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out;
 		SOD(("hwrsp %p out %d\n", hwrsp, sw_cq->out))
@@ -147,16 +160,28 @@
 #if defined(SOCALDEBUG) && 0
 		{
 		u32 *u = (u32 *)hwrsp;
-		SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+		SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
+		     u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
 		u += 8;
-		SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+		SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
+		     u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
 		u = (u32 *)s->xram;
 		while (u < ((u32 *)s->regs)) {
-			if (u[0] == 0x00003000 || u[0] == 0x00003801) {
-			SOD(("Found at %04lx\n", (unsigned long)u - (unsigned long)s->xram))
-			SOD(("  %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+			if (sbus_readl(&u[0]) == 0x00003000 ||
+			    sbus_readl(&u[0]) == 0x00003801) {
+			SOD(("Found at %04lx\n",
+			     (unsigned long)u - (unsigned long)s->xram))
+			SOD(("  %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
+			     sbus_readl(&u[0]), sbus_readl(&u[1]),
+			     sbus_readl(&u[2]), sbus_readl(&u[3]),
+			     sbus_readl(&u[4]), sbus_readl(&u[5]),
+			     sbus_readl(&u[6]), sbus_readl(&u[7])))
 			u += 8;
-			SOD(("  %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+			SOD(("  %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
+			     sbus_readl(&u[0]), sbus_readl(&u[1]),
+			     sbus_readl(&u[2]), sbus_readl(&u[3]),
+			     sbus_readl(&u[4]), sbus_readl(&u[5]),
+			     sbus_readl(&u[6]), sbus_readl(&u[7])))
 			u -= 8;
 			}
 			u++;
@@ -169,13 +194,18 @@
 		fc = (fc_channel *)(&s->port[(token >> 11) & 1]);
 		
 		SOD(("Solicited token %08x status %08x\n", token, status))
-		if (status == SOCAL_OK)
-			fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), FC_STATUS_OK, NULL);
-		else {
-			socal_memcpy(&fchdr, &hwrsp->fchdr, sizeof(fchdr));
-			/* We have intentionally defined FC_STATUS_* constants to match SOCAL_* constants, otherwise
-			   we'd have to translate status */
-			fcp_receive_solicited(fc, token >> 12, token & ((1 << 11) - 1), status, &fchdr);
+		if (status == SOCAL_OK) {
+			fcp_receive_solicited(fc, token >> 12,
+					      token & ((1 << 11) - 1),
+					      FC_STATUS_OK, NULL);
+		} else {
+			socal_copy_from_xram(&fchdr, &hwrsp->fchdr, sizeof(fchdr));
+			/* We have intentionally defined FC_STATUS_* constants
+			 * to match SOCAL_* constants, otherwise we'd have to
+			 * translate status.
+			 */
+			fcp_receive_solicited(fc, token >> 12,
+					      token & ((1 << 11) - 1), status, &fchdr);
 		}
 			
 		if (++sw_cq->out > sw_cq->last) {
@@ -184,13 +214,17 @@
 		}
 		
 		if (sw_cq->out == sw_cq->in) {
-			sw_cq->in = s->regs->respr[qno];
+			sw_cq->in = sbus_readb(s->regs + RESP + qno);
 			if (sw_cq->out == sw_cq->in) {
 				/* Tell the hardware about it */
-				s->regs->cmd = (sw_cq->out << 24) | (SOCAL_CMD_RSP_QALL & ~(SOCAL_CMD_RSP_Q0 << qno));
+				sbus_writel((sw_cq->out << 24) |
+					    (SOCAL_CMD_RSP_QALL &
+					     ~(SOCAL_CMD_RSP_Q0 << qno)),
+					    s->regs + CMD);
+
 				/* Read it, so that we're sure it has been updated */
-				s->regs->cmd;
-				sw_cq->in = s->regs->respr[qno];
+				sbus_readl(s->regs + CMD);
+				sw_cq->in = sbus_readb(s->regs + RESP + qno);
 				if (sw_cq->out == sw_cq->in)
 					break;
 			}
@@ -201,20 +235,21 @@
 static void inline socal_request (struct socal *s, u32 cmd)
 {
 	SOCAL_SETIMASK(s, s->imask & ~(cmd & SOCAL_CMD_REQ_QALL));
-	SOD(("imask %08x %08x\n", s->imask, s->regs->imask));
+	SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK)));
 
 	SOD(("Queues available %08x OUT %X\n", cmd, s->regs->reqpr[0]))
 	if (s->port[s->curr_port].fc.state != FC_STATE_OFFLINE) {
 		fcp_queue_empty ((fc_channel *)&(s->port[s->curr_port]));
 		if (((s->req[1].in + 1) & s->req[1].last) != (s->req[1].out))
 			fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
-	} else
+	} else {
 		fcp_queue_empty ((fc_channel *)&(s->port[1 - s->curr_port]));
+	}
 	if (s->port[1 - s->curr_port].fc.state != FC_STATE_OFFLINE)
 		s->curr_port ^= 1;
 }
 
-static void inline socal_unsolicited (struct socal *s, int qno)
+static void inline socal_unsolicited (struct socal *s, unsigned long qno)
 {
 	socal_rsp *hwrsp, *hwrspc;
 	socal_cq *sw_cq;
@@ -225,13 +260,14 @@
 
 	sw_cq = &s->rsp[qno];
 	if (sw_cq->pool == NULL) {
-		SOD(("address %08x xram %p\n", sw_cq->hw_cq->address, s->xram))
+		SOD(("address %08x xram %lx\n", sw_cq->hw_cq->address, s->xram))
 		sw_cq->pool =
 			(socal_req *)(s->xram + (sw_cq->hw_cq->address & 0xfffe));
 	}
 
-	sw_cq->in = s->regs->respr[qno];
-	SOD (("socal_unsolicited, %d packets arrived, in %d\n", (sw_cq->in - sw_cq->out) & sw_cq->last, sw_cq->in))
+	sw_cq->in = sbus_readb(s->regs + RESP + qno);
+	SOD (("socal_unsolicited, %d packets arrived, in %d\n",
+	      (sw_cq->in - sw_cq->out) & sw_cq->last, sw_cq->in))
 	while (sw_cq->in != sw_cq->out) {
 		/* ...real work per entry here... */
 		hwrsp = (socal_rsp *)sw_cq->pool + sw_cq->out;
@@ -240,9 +276,11 @@
 #if defined(SOCALDEBUG) && 0
 		{
 		u32 *u = (u32 *)hwrsp;
-		SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+		SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
+		     u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
 		u += 8;
-		SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n", u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
+		SOD(("%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x\n",
+		     u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7]))
 		}
 #endif
 
@@ -257,20 +295,27 @@
 			u8 in;
 
 			if (count != 2) {
-				printk("%s: Too many continuations entries %d\n", fc->name, count);
+				printk("%s: Too many continuations entries %d\n",
+				       fc->name, count);
 				goto update_out;
 			}
 			
 			in = sw_cq->in;
-			if (in < sw_cq->out) in += sw_cq->last + 1;
+			if (in < sw_cq->out)
+				in += sw_cq->last + 1;
 			if (in < sw_cq->out + 2) {
-				/* Ask the hardware about it if they haven't arrived yet */
-				s->regs->cmd = (sw_cq->out << 24) | (SOCAL_CMD_RSP_QALL & ~(SOCAL_CMD_RSP_Q0 << qno));
+				/* Ask the hardware if they haven't arrived yet. */
+				sbus_writel((sw_cq->out << 24) |
+					    (SOCAL_CMD_RSP_QALL &
+					     ~(SOCAL_CMD_RSP_Q0 << qno)),
+					    s->regs + CMD);
+
 				/* Read it, so that we're sure it has been updated */
-				s->regs->cmd;
-				sw_cq->in = s->regs->respr[qno];
+				sbus_readl(s->regs + CMD);
+				sw_cq->in = sbus_readb(s->regs + RESP + qno);
 				in = sw_cq->in;
-				if (in < sw_cq->out) in += sw_cq->last + 1;
+				if (in < sw_cq->out)
+					in += sw_cq->last + 1;
 				if (in < sw_cq->out + 2) /* Nothing came, let us wait */
 					return;
 			}
@@ -297,9 +342,11 @@
 				fcp_state_change(fc, FC_STATE_OFFLINE);
 				break;
 			default:
-				printk ("%s: Unknown STATUS no %d\n", fc->name, status);
+				printk ("%s: Unknown STATUS no %d\n",
+					fc->name, status);
 				break;
-			}
+			};
+
 			break;
 		case (SOCAL_UNSOLICITED|SOCAL_FC_HDR):
 			{
@@ -309,30 +356,40 @@
 				
 				if ((r_ctl & 0xf0) == R_CTL_EXTENDED_SVC) {
 					len = hwrsp->shdr.bytecnt;
-					if (len < 4 || !hwrspc)
-						printk ("%s: Invalid R_CTL %02x continuation entries\n", fc->name, r_ctl);
-					else {
-						if (len > 60) len = 60;
-						socal_memcpy (buf, hwrspc, (len + 3) & ~3);
+					if (len < 4 || !hwrspc) {
+						printk ("%s: Invalid R_CTL %02x "
+							"continuation entries\n",
+							fc->name, r_ctl);
+					} else {
+						if (len > 60)
+							len = 60;
+						socal_copy_from_xram(buf, hwrspc,
+								     (len + 3) & ~3);
 						if (*(u32 *)buf == LS_DISPLAY) {
 							int i;
 							
 							for (i = 4; i < len; i++)
-								if (buf[i] == '\n') buf[i] = ' ';
+								if (buf[i] == '\n')
+									buf[i] = ' ';
 							buf[len] = 0;
-							printk ("%s message: %s\n", fc->name, buf + 4);
+							printk ("%s message: %s\n",
+								fc->name, buf + 4);
 						} else {
-							printk ("%s: Unknown LS_CMD %08x\n", fc->name, *(u32 *)buf);
+							printk ("%s: Unknown LS_CMD "
+								"%08x\n", fc->name,
+								*(u32 *)buf);
 						}
 					}
-				} else
-					printk ("%s: Unsolicited R_CTL %02x not handled\n", fc->name, r_ctl);
+				} else {
+					printk ("%s: Unsolicited R_CTL %02x "
+						"not handled\n", fc->name, r_ctl);
+				}
 			}
 			break;
 		default:
 			printk ("%s: Unexpected flags %08x\n", fc->name, flags);
 			break;
-		}
+		};
 update_out:
 		if (++sw_cq->out > sw_cq->last) {
 			sw_cq->seqno++;
@@ -347,13 +404,17 @@
 		}
 		
 		if (sw_cq->out == sw_cq->in) {
-			sw_cq->in = s->regs->respr[qno];
+			sw_cq->in = sbus_readb(s->regs + RESP + qno);
 			if (sw_cq->out == sw_cq->in) {
 				/* Tell the hardware about it */
-				s->regs->cmd = (sw_cq->out << 24) | (SOCAL_CMD_RSP_QALL & ~(SOCAL_CMD_RSP_Q0 << qno));
+				sbus_writel((sw_cq->out << 24) |
+					    (SOCAL_CMD_RSP_QALL &
+					     ~(SOCAL_CMD_RSP_Q0 << qno)),
+					    s->regs + CMD);
+
 				/* Read it, so that we're sure it has been updated */
-				s->regs->cmd;
-				sw_cq->in = s->regs->respr[qno];
+				sbus_readl(s->regs + CMD);
+				sw_cq->in = sbus_readb(s->regs + RESP + qno);
 			}
 		}
 	}
@@ -366,16 +427,21 @@
 	register struct socal *s = (struct socal *)dev_id;
 
 	spin_lock_irqsave(&io_request_lock, flags);
-	cmd = s->regs->cmd;
-	for (; (cmd = SOCAL_INTR (s, cmd)); cmd = s->regs->cmd) {
+	cmd = sbus_readl(s->regs + CMD);
+	for (; (cmd = SOCAL_INTR (s, cmd)); cmd = sbus_readl(s->regs + CMD)) {
 #ifdef SOCALDEBUG
 		static int cnt = 0;
-		if (cnt++ < 50) printk("soc_intr %08x\n", cmd);
+		if (cnt++ < 50)
+			printk("soc_intr %08x\n", cmd);
 #endif	
-		if (cmd & SOCAL_CMD_RSP_Q2) socal_unsolicited (s, SOCAL_UNSOLICITED_RSP_Q);
-		if (cmd & SOCAL_CMD_RSP_Q1) socal_unsolicited (s, SOCAL_SOLICITED_BAD_RSP_Q);
-		if (cmd & SOCAL_CMD_RSP_Q0) socal_solicited (s, SOCAL_SOLICITED_RSP_Q);
-		if (cmd & SOCAL_CMD_REQ_QALL) socal_request (s, cmd);
+		if (cmd & SOCAL_CMD_RSP_Q2)
+			socal_unsolicited (s, SOCAL_UNSOLICITED_RSP_Q);
+		if (cmd & SOCAL_CMD_RSP_Q1)
+			socal_unsolicited (s, SOCAL_SOLICITED_BAD_RSP_Q);
+		if (cmd & SOCAL_CMD_RSP_Q0)
+			socal_solicited (s, SOCAL_SOLICITED_RSP_Q);
+		if (cmd & SOCAL_CMD_REQ_QALL)
+			socal_request (s, cmd);
 	}
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
@@ -386,7 +452,7 @@
 {
 	socal_port *port = (socal_port *)fc;
 	struct socal *s = port->s;
-	int qno;
+	unsigned long qno;
 	socal_cq *sw_cq;
 	int cq_next_in;
 	socal_req *request;
@@ -405,12 +471,15 @@
 	sw_cq = s->req + qno;
 	cq_next_in = (sw_cq->in + 1) & sw_cq->last;
 	
-	if (cq_next_in == sw_cq->out 
-		    && cq_next_in == (sw_cq->out = s->regs->reqpr[qno])) {
-		SOD(("%d IN %d OUT %d LAST %d\n", qno, sw_cq->in, sw_cq->out, sw_cq->last))
+	if (cq_next_in == sw_cq->out &&
+	    cq_next_in == (sw_cq->out = sbus_readb(s->regs + REQP + qno))) {
+		SOD(("%d IN %d OUT %d LAST %d\n",
+		     qno, sw_cq->in,
+		     sw_cq->out, sw_cq->last))
 		SOCAL_SETIMASK(s, s->imask | (SOCAL_IMASK_REQ_Q0 << qno));
-		SOD(("imask %08x %08x\n", s->imask, s->regs->imask));
-		/* If queue is full, just say NO */
+		SOD(("imask %08x %08x\n", s->imask, sbus_readl(s->regs + IMASK)));
+
+		/* If queue is full, just say NO. */
 		return -EBUSY;
 	}
 	
@@ -540,9 +609,11 @@
 	
 	SOD(("Putting %08x into cmd\n", SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno)))
 	
-	s->regs->cmd = SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno);
+	sbus_writel(SOCAL_CMD_RSP_QALL | (sw_cq->in << 24) | (SOCAL_CMD_REQ_Q0 << qno),
+		    s->regs + CMD);
+
 	/* Read so that command is completed */	
-	s->regs->cmd;
+	sbus_readl(s->regs + CMD);
 	
 	return 0;
 }
@@ -551,7 +622,7 @@
 {
 #ifdef HAVE_SOCAL_UCODE
 	SOD(("Loading %ld bytes from %p to %p\n", sizeof(socal_ucode), socal_ucode, s->xram))
-	socal_memcpy (s->xram, socal_ucode, sizeof(socal_ucode));
+	socal_copy_to_xram(s->xram, socal_ucode, sizeof(socal_ucode));
 	SOD(("Clearing the rest of memory\n"))
 	socal_bzero (s->xram + sizeof(socal_ucode), 65536 - sizeof(socal_ucode));
 	SOD(("Done\n"))
@@ -561,13 +632,13 @@
 /* Check for what the best SBUS burst we can use happens
  * to be on this machine.
  */
-static inline void socal_init_bursts(struct socal *s, struct linux_sbus_device *sdev)
+static inline void socal_init_bursts(struct socal *s, struct sbus_dev *sdev)
 {
 	int bsizes, bsizes_more;
 	u32 cfg;
 
 	bsizes = (prom_getintdefault(sdev->prom_node,"burst-sizes",0xff) & 0xff);
-	bsizes_more = (prom_getintdefault(sdev->my_bus->prom_node, "burst-sizes", 0xff) & 0xff);
+	bsizes_more = (prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff) & 0xff);
 	bsizes &= bsizes_more;
 #ifdef USE_64BIT_MODE
 #ifdef __sparc_v9__
@@ -598,7 +669,7 @@
 	s->cfg = cfg;
 }
 
-static inline void socal_init(struct linux_sbus_device *sdev, int no)
+static inline void socal_init(struct sbus_dev *sdev, int no)
 {
 	unsigned char tmp[60];
 	int propl;
@@ -613,7 +684,8 @@
 	memset (s, 0, sizeof(struct socal));
 	s->socal_no = no;
 
-	SOD(("socals %08lx socal_intr %08lx socal_hw_enque %08lx\n", (long)socals, (long)socal_intr, (long)socal_hw_enque))
+	SOD(("socals %08lx socal_intr %08lx socal_hw_enque %08lx\n",
+	     (long)socals, (long)socal_intr, (long)socal_hw_enque))
 	if (version_printed++ == 0)
 		printk (version);
 #ifdef MODULE
@@ -663,16 +735,17 @@
 			break;
 		default:
 			break;
-		}
+		};
+
 		node = prom_getsibling(node);
 	}
 
 	memcpy (&s->port[0].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
 	memcpy (&s->port[1].fc.wwn_node, &s->wwn, sizeof (fc_wwn));
 	SOD(("Got wwns %08x%08x ports %08x%08x and %08x%08x\n", 
-		*(u32 *)&s->port[0].fc.wwn_node, s->port[0].fc.wwn_node.lo,
-		*(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
-		*(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo))
+	     *(u32 *)&s->port[0].fc.wwn_node, s->port[0].fc.wwn_node.lo,
+	     *(u32 *)&s->port[0].fc.wwn_nport, s->port[0].fc.wwn_nport.lo,
+	     *(u32 *)&s->port[1].fc.wwn_nport, s->port[1].fc.wwn_nport.lo))
 		
 	s->port[0].fc.sid = 1;
 	s->port[1].fc.sid = 17;
@@ -682,29 +755,20 @@
 	s->port[0].fc.reset = socal_reset;
 	s->port[1].fc.reset = socal_reset;
 	
-	/* Setup the reg property for this device. */
-	prom_apply_sbus_ranges(sdev->my_bus, sdev->reg_addrs, sdev->num_registers, sdev);
-                                                                                                                                               	
 	if (sdev->num_registers == 1) {
-		s->eeprom = (u8 *)
-			sparc_alloc_io (sdev->reg_addrs [0].phys_addr, 0, 
-				sdev->reg_addrs [0].reg_size, "socal_xram",
-				sdev->reg_addrs [0].which_io, 0);
-		if (sdev->reg_addrs [0].reg_size > 0x20000)
-			s->xram = s->eeprom + 0x10000;
+		s->eeprom = sbus_ioremap(&sdev->resource[0], 0,
+					 sdev->reg_addrs[0].reg_size, "socal xram");
+		if (sdev->reg_addrs[0].reg_size > 0x20000)
+			s->xram = s->eeprom + 0x10000UL;
 		else
 			s->xram = s->eeprom;
-		s->regs = (struct socal_regs *)(s->xram + 0x10000);
+		s->regs = (s->xram + 0x10000UL);
 	} else {
 		/* E.g. starfire presents 3 registers for SOCAL */
-		s->xram = (u8 *)
-			sparc_alloc_io (sdev->reg_addrs [1].phys_addr, 0, 
-				sdev->reg_addrs [1].reg_size, "socal_xram",
-				sdev->reg_addrs [1].which_io, 0);
-		s->regs = (struct socal_regs *)
-			sparc_alloc_io (sdev->reg_addrs [2].phys_addr, 0, 
-				sdev->reg_addrs [2].reg_size, "socal_regs",
-				sdev->reg_addrs [2].which_io, 0);
+		s->xram = sbus_ioremap(&sdev->resource[1], 0,
+				       sdev->reg_addrs[1].reg_size, "socal xram");
+		s->regs = sbus_ioremap(&sdev->resource[2], 0,
+				       sdev->reg_addrs[2].reg_size, "socal regs");
 	}
 	
 	socal_init_bursts(s, sdev);
@@ -742,8 +806,12 @@
 	/* Now setup xram circular queues */
 	memset (cq, 0, sizeof(cq));
 
-	size = (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE + SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE + SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req);
-	s->req[0].pool = (socal_req *) sparc_dvma_malloc (size, "SOCAL request queues", &cq[0].address);
+	size = (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE +
+		SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE +
+		SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req);
+	s->req_cpu = sbus_alloc_consistant(sdev, size, &s->req_dvma);
+	s->req[0].pool = s->req_cpu;
+	cq[0].address = s->req_dvma;
 	s->req[1].pool = s->req[0].pool + SOCAL_CQ_REQ0_SIZE;
 	s->rsp[0].pool = s->req[1].pool + SOCAL_CQ_REQ1_SIZE;
 	s->rsp[1].pool = s->rsp[0].pool + SOCAL_CQ_RSP0_SIZE;
@@ -780,12 +848,12 @@
 	s->rsp[1].seqno = 1;
 	s->rsp[2].seqno = 1;
 	
-	socal_memcpy (s->xram + SOCAL_CQ_REQ_OFFSET, cq, sizeof(cq));
+	socal_copy_to_xram(s->xram + SOCAL_CQ_REQ_OFFSET, cq, sizeof(cq));
 	
 	SOD(("Setting up params\n"))
 	
 	/* Make our sw copy of SOCAL service parameters */
-	socal_memcpy (s->serv_params, s->xram + 0x280, sizeof (s->serv_params));
+	socal_copy_from_xram(s->serv_params, s->xram + 0x280, sizeof (s->serv_params));
 	
 	s->port[0].fc.common_svc = (common_svc_parm *)s->serv_params;
 	s->port[0].fc.class_svcs = (svc_parm *)(s->serv_params + 0x20);
@@ -803,20 +871,21 @@
 int init_module(void)
 #endif
 {
-	struct linux_sbus *bus;
-	struct linux_sbus_device *sdev = 0;
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev = 0;
 	struct socal *s;
 	int cards = 0;
 
-	for_each_sbus(bus) {
-		for_each_sbusdev(sdev, bus) {
+	for_each_sbus(sbus) {
+		for_each_sbusdev(sdev, sbus) {
 			if(!strcmp(sdev->prom_name, "SUNW,socal")) {
 				socal_init(sdev, cards);
 				cards++;
 			}
 		}
 	}
-	if (!cards) return -EIO;
+	if (!cards)
+		return -EIO;
 
 	for_each_socal(s)
 		if (s->next)
@@ -833,7 +902,7 @@
 {
 	struct socal *s;
 	int irq;
-	struct linux_sbus_device *sdev;
+	struct sbus_dev *sdev;
 	
 	for_each_socal(s) {
 		irq = s->port[0].fc.irq;
@@ -843,13 +912,17 @@
 		fcp_release(&(s->port[0].fc), 2);
 
 		sdev = s->port[0].fc.dev;
-		if (sdev->num_registers == 1)
-			sparc_free_io (s->eeprom, sdev->reg_addrs [0].reg_size);
-		else {
-			sparc_free_io (s->xram, sdev->reg_addrs [1].reg_size);
-			sparc_free_io ((char *)s->regs, sdev->reg_addrs [2].reg_size);
+		if (sdev->num_registers == 1) {
+			sbus_iounmap(s->eeprom, sdev->reg_addrs[0].reg_size);
+		} else {
+			sbus_iounmap(s->xram, sdev->reg_addrs[1].reg_size);
+			sbus_iounmap(s->regs, sdev->reg_addrs[2].reg_size);
 		}
-		/* FIXME: sparc_dvma_free() ??? */
+		sbus_free_consistant(sdev,
+				     (SOCAL_CQ_REQ0_SIZE + SOCAL_CQ_REQ1_SIZE +
+				      SOCAL_CQ_RSP0_SIZE + SOCAL_CQ_RSP1_SIZE +
+				      SOCAL_CQ_RSP2_SIZE) * sizeof(socal_req),
+				     s->req_cpu, s->req_dvma);
 	}
 }
 #endif
diff -u --recursive --new-file v2.3.34/linux/drivers/fc4/socal.h linux/drivers/fc4/socal.h
--- v2.3.34/linux/drivers/fc4/socal.h	Mon Mar 15 16:11:29 1999
+++ linux/drivers/fc4/socal.h	Mon Dec 20 22:06:42 1999
@@ -10,24 +10,13 @@
 #include "fcp.h"
 #include "fcp_impl.h"
 
-/* Hardware structures and constants first {{{ */
-
-union socal_rq_reg {
-	volatile u8 read[4];
-	volatile u32 write;
-};
-struct socal_regs {
-	volatile u32 cfg;		/* Config Register */
-	volatile u32 sae;		/* Slave Access Error Register */
-	volatile u32 cmd;		/* Command & Status Register */
-	volatile u32 imask;		/* Interrupt Mask Register */
-	union socal_rq_reg reqp;	/* Request Queue Index Register */
-	union socal_rq_reg resp;	/* Response Queue Index Register */
-#define reqpr reqp.read
-#define reqpw reqp.write
-#define respr resp.read
-#define respw resp.write
-};
+/* Hardware register offsets and constants first {{{ */
+#define CFG	0x00UL
+#define SAE	0x04UL
+#define CMD	0x08UL
+#define IMASK	0x0cUL
+#define REQP	0x10UL
+#define RESP	0x14UL
 
 /* Config Register */
 #define SOCAL_CFG_EXT_RAM_BANK_MASK	0x07000000
@@ -86,7 +75,9 @@
 	 & s->imask)
 	 
 #define SOCAL_SETIMASK(s, i) \
-	(s)->imask = (i); (s)->regs->imask = (i)
+do {	(s)->imask = (i); \
+	sbus_writel((i), (s)->regs + IMASK); \
+} while (0)
 	
 #define SOCAL_MAX_EXCHANGES		1024
 
@@ -303,15 +294,18 @@
 	socal_cq		req[4]; /* Request CQs */
 	socal_cq		rsp[4]; /* Response CQs */
 	int			socal_no;
-	struct socal_regs	*regs;
-	u8			*xram;
-	u8			*eeprom;
+	unsigned long		regs;
+	unsigned long		xram;
+	unsigned long		eeprom;
 	fc_wwn			wwn;
 	u32			imask;	/* Our copy of regs->imask */
 	u32			cfg;	/* Our copy of regs->cfg */
 	char			serv_params[80];
 	struct socal		*next;
 	int			curr_port; /* Which port will have priority to fcp_queue_empty */
+
+	socal_req *		req_cpu;
+	u32			req_dvma;
 };
 
 /* }}} */
diff -u --recursive --new-file v2.3.34/linux/drivers/misc/Config.in linux/drivers/misc/Config.in
--- v2.3.34/linux/drivers/misc/Config.in	Thu Nov 11 20:11:39 1999
+++ linux/drivers/misc/Config.in	Sat Dec 25 15:04:56 1999
@@ -4,6 +4,4 @@
 mainmenu_option next_comment
 comment 'Misc devices'
 
-bool 'ACPI support' CONFIG_ACPI
-
 endmenu
diff -u --recursive --new-file v2.3.34/linux/drivers/misc/Makefile linux/drivers/misc/Makefile
--- v2.3.34/linux/drivers/misc/Makefile	Thu Nov 11 20:11:39 1999
+++ linux/drivers/misc/Makefile	Sat Dec 25 15:05:05 1999
@@ -18,10 +18,6 @@
 O_OBJS   :=
 OX_OBJS  :=
 
-ifeq ($(CONFIG_ACPI),y)
-  OX_OBJS += acpi.o
-endif
-
 include $(TOPDIR)/Rules.make
 
 fastdep:
diff -u --recursive --new-file v2.3.34/linux/drivers/misc/acpi.c linux/drivers/misc/acpi.c
--- v2.3.34/linux/drivers/misc/acpi.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/misc/acpi.c	Wed Dec 31 16:00:00 1969
@@ -1,1255 +0,0 @@
-/*
- *  acpi.c - Linux ACPI driver
- *
- *  Copyright (C) 1999 Andrew Henroid
- *
- *  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
- */
-
-/*
- * See http://www.geocities.com/SiliconValley/Hardware/3165/
- * for the user-level ACPI stuff
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/miscdevice.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/wait.h>
-#include <linux/spinlock.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <linux/sysctl.h>
-#include <linux/delay.h>
-#include <linux/acpi.h>
-
-/*
- * Defines for 2.2.x
- */
-#ifndef __exit
-#define __exit
-#endif
-#ifndef module_init
-#define module_init(x) int init_module(void) {return x();}
-#endif
-#ifndef module_exit
-#define module_exit(x) void cleanup_module(void) {x();}
-#endif
-#ifndef DECLARE_WAIT_QUEUE_HEAD
-#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue * x = NULL
-#endif
-
-/*
- * Yes, it's unfortunate that we are relying on get_cmos_time
- * because it is slow (> 1 sec.) and i386 only.	 It might be better
- * to use some of the code from drivers/char/rtc.c in the near future
- */
-extern unsigned long get_cmos_time(void);
-
-static int acpi_control_thread(void *context);
-static int acpi_do_ulong(ctl_table *ctl,
-			 int write,
-			 struct file *file,
-			 void *buffer,
-			 size_t *len);
-static int acpi_do_event_reg(ctl_table *ctl,
-			     int write,
-			     struct file *file,
-			     void *buffer,
-			     size_t *len);
-static int acpi_do_event(ctl_table *ctl,
-			 int write,
-			 struct file *file,
-			 void *buffer,
-			 size_t *len);
-static int acpi_do_sleep(ctl_table *ctl,
-			 int write,
-			 struct file *file,
-			 void *buffer,
-			 size_t *len);
-
-DECLARE_WAIT_QUEUE_HEAD(acpi_control_wait);
-
-static struct ctl_table_header *acpi_sysctl = NULL;
-
-static struct acpi_facp *acpi_facp = NULL;
-static int acpi_fake_facp = 0;
-static struct acpi_facs *acpi_facs = NULL;
-static unsigned long acpi_facp_addr = 0;
-static unsigned long acpi_dsdt_addr = 0;
-
-// current system sleep state (S0 - S4)
-static acpi_sstate_t acpi_sleep_state = ACPI_S0;
-// time sleep began
-static unsigned long acpi_sleep_start = 0;
-
-static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED;
-static volatile u32 acpi_pm1_status = 0;
-static volatile u32 acpi_gpe_status = 0;
-static volatile u32 acpi_gpe_level = 0;
-static volatile acpi_sstate_t acpi_event_state = ACPI_S0;
-static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait);
-
-static spinlock_t acpi_devs_lock = SPIN_LOCK_UNLOCKED;
-static LIST_HEAD(acpi_devs);
-
-/* Make it impossible to enter C2/C3 until after we've initialized */
-static unsigned long acpi_p_lvl2_lat = ACPI_INFINITE_LAT;
-static unsigned long acpi_p_lvl3_lat = ACPI_INFINITE_LAT;
-
-static unsigned long acpi_p_blk = 0;
-
-static int acpi_p_lvl2_tested = 0;
-static int acpi_p_lvl3_tested = 0;
-
-// bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb
-static unsigned long acpi_slp_typ[] = 
-{
-	ACPI_SLP_TYP_DISABLED, /* S0 */
-	ACPI_SLP_TYP_DISABLED, /* S1 */
-	ACPI_SLP_TYP_DISABLED, /* S2 */
-	ACPI_SLP_TYP_DISABLED, /* S3 */
-	ACPI_SLP_TYP_DISABLED, /* S4 */
-	ACPI_SLP_TYP_DISABLED  /* S5 */
-};
-
-static struct ctl_table acpi_table[] =
-{
-	{ACPI_FACP, "facp",
-	 &acpi_facp_addr, sizeof(acpi_facp_addr),
-	 0400, NULL, &acpi_do_ulong},
-
-	{ACPI_DSDT, "dsdt",
-	 &acpi_dsdt_addr, sizeof(acpi_dsdt_addr),
-	 0400, NULL, &acpi_do_ulong},
-
-	{ACPI_PM1_ENABLE, "pm1_enable",
-	 NULL, 0,
-	 0600, NULL, &acpi_do_event_reg},
-
-	{ACPI_GPE_ENABLE, "gpe_enable",
-	 NULL, 0,
-	 0600, NULL, &acpi_do_event_reg},
-
-	{ACPI_GPE_LEVEL, "gpe_level",
-	 NULL, 0,
-	 0600, NULL, &acpi_do_event_reg},
-
-	{ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event},
-
-	{ACPI_P_BLK, "p_blk",
-	 &acpi_p_blk, sizeof(acpi_p_blk),
-	 0600, NULL, &acpi_do_ulong},
-
-	{ACPI_P_LVL2_LAT, "p_lvl2_lat",
-	 &acpi_p_lvl2_lat, sizeof(acpi_p_lvl2_lat),
-	 0644, NULL, &acpi_do_ulong},
-
-	{ACPI_P_LVL3_LAT, "p_lvl3_lat",
-	 &acpi_p_lvl3_lat, sizeof(acpi_p_lvl3_lat),
-	 0644, NULL, &acpi_do_ulong},
-
-	{ACPI_S0_SLP_TYP, "s0_slp_typ",
-	 &acpi_slp_typ[ACPI_S0], sizeof(acpi_slp_typ[ACPI_S0]),
-	 0600, NULL, &acpi_do_ulong},
-
-	{ACPI_S1_SLP_TYP, "s1_slp_typ",
-	 &acpi_slp_typ[ACPI_S1], sizeof(acpi_slp_typ[ACPI_S1]),
-	 0600, NULL, &acpi_do_ulong},
-
-	{ACPI_S5_SLP_TYP, "s5_slp_typ",
-	 &acpi_slp_typ[ACPI_S5], sizeof(acpi_slp_typ[ACPI_S5]),
-	 0600, NULL, &acpi_do_ulong},
-
-	{ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},
-
-	{0}
-};
-
-static struct ctl_table acpi_dir_table[] =
-{
-	{CTL_ACPI, "acpi", NULL, 0, 0555, acpi_table},
-	{0}
-};
-
-
-/*
- * Get the value of the PM1 control register (SCI_EN, ...)
- */
-static u32 acpi_read_pm1_control(struct acpi_facp *facp)
-{
-	u32 value = 0;
-	if (facp->pm1a_cnt)
-		value = inw(facp->pm1a_cnt);
-	if (facp->pm1b_cnt)
-		value |= inw(facp->pm1b_cnt);
-	return value;
-}
-
-/*
- * Set the value of the PM1 control register (BM_RLD, ...)
- */
-static void acpi_write_pm1_control(struct acpi_facp *facp, u32 value)
-{
-	if (facp->pm1a_cnt)
-		outw(value, facp->pm1a_cnt);
-	if (facp->pm1b_cnt)
-		outw(value, facp->pm1b_cnt);
-}
-
-/*
- * Get the value of the fixed event status register
- */
-static u32 acpi_read_pm1_status(struct acpi_facp *facp)
-{
-	u32 value = 0;
-	if (facp->pm1a_evt)
-		value = inw(facp->pm1a_evt);
-	if (facp->pm1b_evt)
-		value |= inw(facp->pm1b_evt);
-	return value;
-}
-
-/*
- * Set the value of the fixed event status register (clear events)
- */
-static void acpi_write_pm1_status(struct acpi_facp *facp, u32 value)
-{
-	if (facp->pm1a_evt)
-		outw(value, facp->pm1a_evt);
-	if (facp->pm1b_evt)
-		outw(value, facp->pm1b_evt);
-}
-
-/*
- * Get the value of the fixed event enable register
- */
-static u32 acpi_read_pm1_enable(struct acpi_facp *facp)
-{
-	int offset = facp->pm1_evt_len >> 1;
-	u32 value = 0;
-	if (facp->pm1a_evt)
-		value = inw(facp->pm1a_evt + offset);
-	if (facp->pm1b_evt)
-		value |= inw(facp->pm1b_evt + offset);
-	return value;
-}
-
-/*
- * Set the value of the fixed event enable register (enable events)
- */
-static void acpi_write_pm1_enable(struct acpi_facp *facp, u32 value)
-{
-	int offset = facp->pm1_evt_len >> 1;
-	if (facp->pm1a_evt)
-		outw(value, facp->pm1a_evt + offset);
-	if (facp->pm1b_evt)
-		outw(value, facp->pm1b_evt + offset);
-}
-
-/*
- * Get the value of the general-purpose event status register
- */
-static u32 acpi_read_gpe_status(struct acpi_facp *facp)
-{
-	u32 value = 0;
-	int i, size;
-
-	if (facp->gpe1) {
-		size = facp->gpe1_len >> 1;
-		for (i = size - 1; i >= 0; i--)
-			value = (value << 8) | inb(facp->gpe1 + i);
-	}
-	if (facp->gpe0) {
-		size = facp->gpe0_len >> 1;
-		for (i = size - 1; i >= 0; i--)
-			value = (value << 8) | inb(facp->gpe0 + i);
-	}
-	return value;
-}
-
-/*
- * Set the value of the general-purpose event status register (clear events)
- */
-static void acpi_write_gpe_status(struct acpi_facp *facp, u32 value)
-{
-	int i, size;
-
-	if (facp->gpe0) {
-		size = facp->gpe0_len >> 1;
-		for (i = 0; i < size; i++) {
-			outb(value & 0xff, facp->gpe0 + i);
-			value >>= 8;
-		}
-	}
-	if (facp->gpe1) {
-		size = facp->gpe1_len >> 1;
-		for (i = 0; i < size; i++) {
-			outb(value & 0xff, facp->gpe1 + i);
-			value >>= 8;
-		}
-	}
-}
-
-/*
- * Get the value of the general-purpose event enable register
- */
-static u32 acpi_read_gpe_enable(struct acpi_facp *facp)
-{
-	u32 value = 0;
-	int i, size, offset;
-	
-	offset = facp->gpe0_len >> 1;
-	if (facp->gpe1) {
-		size = facp->gpe1_len >> 1;
-		for (i = size - 1; i >= 0; i--) {
-			value = (value << 8) | inb(facp->gpe1 + offset + i);
-		}
-	}
-	if (facp->gpe0) {
-		size = facp->gpe0_len >> 1;
-		for (i = size - 1; i >= 0; i--)
-			value = (value << 8) | inb(facp->gpe0 + offset + i);
-	}
-	return value;
-}
-
-/*
- * Set the value of the general-purpose event enable register (enable events)
- */
-static void acpi_write_gpe_enable(struct acpi_facp *facp, u32 value)
-{
-	int i, offset;
-
-	offset = facp->gpe0_len >> 1;
-	if (facp->gpe0) {
-		for (i = 0; i < offset; i++) {
-			outb(value & 0xff, facp->gpe0 + offset + i);
-			value >>= 8;
-		}
-	}
-	if (facp->gpe1) {
-		offset = facp->gpe1_len >> 1;
-		for (i = 0; i < offset; i++) {
-			outb(value & 0xff, facp->gpe1 + offset + i);
-			value >>= 8;
-		}
-	}
-}
-
-/*
- * Map an ACPI table into virtual memory
- */
-static struct acpi_table *__init acpi_map_table(u32 addr)
-{
-	struct acpi_table *table = NULL;
-	if (addr) {
-		// map table header to determine size
-		table = (struct acpi_table *)
-			ioremap((unsigned long) addr,
-				sizeof(struct acpi_table));
-		if (table) {
-			unsigned long table_size = table->length;
-			iounmap(table);
-			// remap entire table
-			table = (struct acpi_table *)
-				ioremap((unsigned long) addr, table_size);
-		}
-
-		if (!table) {
-			/* ioremap is a pain, it returns NULL if the
-			 * table starts within mapped physical memory.
-			 * Hopefully, no table straddles a mapped/unmapped
-			 * physical memory boundary, ugh
-			 */
-			table = (struct acpi_table*) phys_to_virt(addr);
-		}
-	}
-	return table;
-}
-
-/*
- * Unmap an ACPI table from virtual memory
- */
-static void acpi_unmap_table(struct acpi_table *table)
-{
-	// iounmap ignores addresses within physical memory
-	if (table)
-		iounmap(table);
-}
-
-/*
- * Locate and map ACPI tables
- */
-static int __init acpi_find_tables(void)
-{
-	struct acpi_rsdp *rsdp;
-	struct acpi_table *rsdt;
-	u32 *rsdt_entry;
-	int rsdt_entry_count;
-	unsigned long i;
-
-	// search BIOS memory for RSDP
-	for (i = ACPI_BIOS_ROM_BASE; i < ACPI_BIOS_ROM_END; i += 16) {
-		rsdp = (struct acpi_rsdp *) phys_to_virt(i);
-		if (rsdp->signature[0] == ACPI_RSDP1_SIG
-		    && rsdp->signature[1] == ACPI_RSDP2_SIG) {
-			char oem[7];
-			int j;
-
-			// strip trailing space and print OEM identifier
-			memcpy(oem, rsdp->oem, 6);
-			oem[6] = '\0';
-			for (j = 5;
-			     j > 0 && (oem[j] == '\0' || oem[j] == ' ');
-			     j--) {
-				oem[j] = '\0';
-			}
-			printk(KERN_INFO "ACPI: \"%s\" found at 0x%p\n",
-			       oem, (void *) i);
-
-			break;
-		}
-	}
-	if (i >= ACPI_BIOS_ROM_END)
-		return -ENODEV;
-
-	// fetch RSDT from RSDP
-	rsdt = acpi_map_table(rsdp->rsdt);
-	if (!rsdt) {
-		printk(KERN_ERR "ACPI: missing RSDT at 0x%p\n",
-		       (void*) rsdp->rsdt);
-		return -ENODEV;
-	}
-	else if (rsdt->signature != ACPI_RSDT_SIG) {
-		printk(KERN_ERR "ACPI: bad RSDT at 0x%p (%08x)\n",
-		       (void*) rsdp->rsdt, (unsigned) rsdt->signature);
-		acpi_unmap_table(rsdt);
-		return -ENODEV;
-	}
-	// search RSDT for FACP
-	acpi_facp = NULL;
-	rsdt_entry = (u32 *) (rsdt + 1);
-	rsdt_entry_count = (int) ((rsdt->length - sizeof(*rsdt)) >> 2);
-	while (rsdt_entry_count) {
-		struct acpi_table *dt = acpi_map_table(*rsdt_entry);
-		if (dt && dt->signature == ACPI_FACP_SIG) {
-			acpi_facp = (struct acpi_facp*) dt;
-			acpi_facp_addr = *rsdt_entry;
-			acpi_dsdt_addr = acpi_facp->dsdt;
-
-			// map FACS if it exists
-			if (acpi_facp->facs) {
-				dt = acpi_map_table(acpi_facp->facs);
-				if (dt && dt->signature == ACPI_FACS_SIG) {
-					acpi_facs = (struct acpi_facs*) dt;
-				}
-				else {
-					acpi_unmap_table(dt);
-				}
-			}
-		}
-		else {
-			acpi_unmap_table(dt);
-		}
-		rsdt_entry++;
-		rsdt_entry_count--;
-	}
-
-	acpi_unmap_table(rsdt);
-
-	if (!acpi_facp) {
-		printk(KERN_ERR "ACPI: missing FACP\n");
-		return -ENODEV;
-	}
-	return 0;
-}
-
-/*
- * Unmap or destroy ACPI tables
- */
-static void acpi_destroy_tables(void)
-{
-	if (!acpi_fake_facp)
-		acpi_unmap_table((struct acpi_table*) acpi_facp);
-	else
-		kfree(acpi_facp);
-	acpi_unmap_table((struct acpi_table*) acpi_facs);
-}
-
-/*
- * Locate PIIX4 device and create a fake FACP
- */
-static int __init acpi_find_piix4(void)
-{
-	struct pci_dev *dev;
-	u32 base;
-	u16 cmd;
-	u8 pmregmisc;
-
-	dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-			      PCI_DEVICE_ID_INTEL_82371AB_3,
-			      NULL);
-	if (!dev)
-		return -ENODEV;
-	
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	if (!(cmd & PCI_COMMAND_IO))
-		return -ENODEV;
-	
-	pci_read_config_byte(dev, ACPI_PIIX4_PMREGMISC, &pmregmisc);
-	if (!(pmregmisc & ACPI_PIIX4_PMIOSE))
-		return -ENODEV;
-	
-	pci_read_config_dword(dev, 0x40, &base);
-	if (!(base & PCI_BASE_ADDRESS_SPACE_IO))
-		return -ENODEV;
-	
-	base &= PCI_BASE_ADDRESS_IO_MASK;
-	if (!base)
-		return -ENODEV;
-
-	printk(KERN_INFO "ACPI: found PIIX4 at 0x%04x\n", base);
-
-	acpi_facp = kmalloc(sizeof(struct acpi_facp), GFP_KERNEL);
-	if (!acpi_facp)
-		return -ENOMEM;
-
-	acpi_fake_facp = 1;
-	memset(acpi_facp, 0, sizeof(struct acpi_facp));
-	acpi_facp->int_model = ACPI_PIIX4_INT_MODEL;
-	acpi_facp->sci_int = ACPI_PIIX4_SCI_INT;
-	acpi_facp->smi_cmd = ACPI_PIIX4_SMI_CMD;
-	acpi_facp->acpi_enable = ACPI_PIIX4_ACPI_ENABLE;
-	acpi_facp->acpi_disable = ACPI_PIIX4_ACPI_DISABLE;
-	acpi_facp->s4bios_req = ACPI_PIIX4_S4BIOS_REQ;
-	acpi_facp->pm1a_evt = base + ACPI_PIIX4_PM1_EVT;
-	acpi_facp->pm1a_cnt = base + ACPI_PIIX4_PM1_CNT;
-	acpi_facp->pm2_cnt = ACPI_PIIX4_PM2_CNT;
-	acpi_facp->pm_tmr = base + ACPI_PIIX4_PM_TMR;
-	acpi_facp->gpe0 = base + ACPI_PIIX4_GPE0;
-	acpi_facp->pm1_evt_len = ACPI_PIIX4_PM1_EVT_LEN;
-	acpi_facp->pm1_cnt_len = ACPI_PIIX4_PM1_CNT_LEN;
-	acpi_facp->pm2_cnt_len = ACPI_PIIX4_PM2_CNT_LEN;
-	acpi_facp->pm_tm_len = ACPI_PIIX4_PM_TM_LEN;
-	acpi_facp->gpe0_len = ACPI_PIIX4_GPE0_LEN;
-	acpi_facp->p_lvl2_lat = (__u16) ACPI_INFINITE_LAT;
-	acpi_facp->p_lvl3_lat = (__u16) ACPI_INFINITE_LAT;
-
-	acpi_facp_addr = virt_to_phys(acpi_facp);
-	acpi_dsdt_addr = 0;
-
-	acpi_p_blk = base + ACPI_PIIX4_P_BLK;
-
-	return 0;
-}
-
-/*
- * Handle an ACPI SCI (fixed or general purpose event)
- */
-static void acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
-	u32 pm1_status, gpe_status, gpe_level, gpe_edge;
-	unsigned long flags;
-
-	// detect and clear fixed events
-	pm1_status = (acpi_read_pm1_status(acpi_facp)
-		      & acpi_read_pm1_enable(acpi_facp));
-	acpi_write_pm1_status(acpi_facp, pm1_status);
-	
-	// detect and handle general-purpose events
-	gpe_status = (acpi_read_gpe_status(acpi_facp)
-		      & acpi_read_gpe_enable(acpi_facp));
-	gpe_level = gpe_status & acpi_gpe_level;
-	if (gpe_level) {
-		// disable level-triggered events (re-enabled after handling)
-		acpi_write_gpe_enable(
-			acpi_facp,
-			acpi_read_gpe_enable(acpi_facp) & ~gpe_level);
-	}
-	gpe_edge = gpe_status & ~gpe_level;
-	if (gpe_edge) {
-		// clear edge-triggered events
-		while (acpi_read_gpe_status(acpi_facp) & gpe_edge)
-			acpi_write_gpe_status(acpi_facp, gpe_edge);
-	}
-
-	// notify process waiting on /dev/acpi
-	spin_lock_irqsave(&acpi_event_lock, flags);
-	acpi_pm1_status |= pm1_status;
-	acpi_gpe_status |= gpe_status;
-	spin_unlock_irqrestore(&acpi_event_lock, flags);
-	acpi_event_state = acpi_sleep_state;
-	wake_up_interruptible(&acpi_event_wait);
-}
-
-/*
- * Is ACPI enabled or not?
- */
-static inline int acpi_is_enabled(struct acpi_facp *facp)
-{
-	return ((acpi_read_pm1_control(facp) & ACPI_SCI_EN) ? 1:0);
-}
-
-/*
- * Enable SCI
- */
-static int acpi_enable(struct acpi_facp *facp)
-{
-	if (facp->smi_cmd)
-		outb(facp->acpi_enable, facp->smi_cmd);
-	return (acpi_is_enabled(facp) ? 0:-1);
-}
-
-/*
- * Disable SCI
- */
-static int acpi_disable(struct acpi_facp *facp)
-{
-	// disable and clear any pending events
-	acpi_write_gpe_enable(facp, 0);
-	while (acpi_read_gpe_status(facp))
-		acpi_write_gpe_status(facp, acpi_read_gpe_status(facp));
-	acpi_write_pm1_enable(facp, 0);
-	acpi_write_pm1_status(facp, acpi_read_pm1_status(facp));
-
-	/* writing acpi_disable to smi_cmd would be appropriate
-	 * here but this causes a nasty crash on many systems
-	 */
-
-	return 0;
-}
-
-/*
- * Idle loop (uniprocessor only)
- */
-static void acpi_idle_handler(void)
-{
-	static int sleep_level = 1;
-	u32 pm1_cnt, timer, pm2_cnt, bm_active;
-	unsigned long time, usec;
-
-	// return to C0 on bus master request (necessary for C3 only)
-	pm1_cnt = acpi_read_pm1_control(acpi_facp);
-	if (sleep_level == 3) {
-		if (!(pm1_cnt & ACPI_BM_RLD)) {
-			pm1_cnt |= ACPI_BM_RLD;
-			acpi_write_pm1_control(acpi_facp, pm1_cnt);
-		}
-	}
-	else {
-		if (pm1_cnt & ACPI_BM_RLD) {
-			pm1_cnt &= ~ACPI_BM_RLD;
-			acpi_write_pm1_control(acpi_facp, pm1_cnt);
-		}
-	}
-
-	// clear bus master activity flag
-	acpi_write_pm1_status(acpi_facp, ACPI_BM);
-
-	// get current time (fallback to CPU cycles if no PM timer)
-	timer = acpi_facp->pm_tmr;
-	if (timer)
-		time = inl(timer);
-	else
-		time = get_cycles();
-
-	// sleep
-	switch (sleep_level) {
-	case 1:
-		__asm__ __volatile__("sti ; hlt": : :"memory");
-		break;
-	case 2:
-		inb(acpi_p_blk + ACPI_P_LVL2);
-		break;
-	case 3:
-		pm2_cnt = acpi_facp->pm2_cnt;
-		if (pm2_cnt) {
-			/* Disable PCI arbitration while sleeping,
-			   to avoid DMA corruption? */
-			cli();
-			outb(inb(pm2_cnt) | ACPI_ARB_DIS, pm2_cnt);
-			inb(acpi_p_blk + ACPI_P_LVL3);
-			outb(inb(pm2_cnt) & ~ACPI_ARB_DIS, pm2_cnt);
-			sti();
-		}
-		else {
-			inb(acpi_p_blk + ACPI_P_LVL3);
-		}
-		break;
-	}
-
-	// calculate time spent sleeping (fallback to CPU cycles)
-	if (timer)
-		time = (inl(timer) - time) & ACPI_TMR_MASK;
-	else
-		time = ACPI_CPU_TO_TMR_TICKS(get_cycles() - time);
-
-	// check for bus master activity
-	bm_active = (acpi_read_pm1_status(acpi_facp) & ACPI_BM);
-
-	// record working C2/C3
-	if (sleep_level == 2 && !acpi_p_lvl2_tested) {
-		acpi_p_lvl2_tested = 1;
-		printk(KERN_INFO "ACPI: C2 works\n");
-	}
-	else if (sleep_level == 3 && !acpi_p_lvl3_tested) {
-		acpi_p_lvl3_tested = 1;
-		printk(KERN_INFO "ACPI: C3 works\n");
-	}
-
-	// pick next C-state based on time spent sleeping,
-	// C-state latencies, and bus master activity
-	sleep_level = 1;
-	if (acpi_p_blk) {
-		usec = ACPI_TMR_TICKS_TO_uS(time);
-		if (usec > acpi_p_lvl3_lat && !bm_active)
-			sleep_level = 3;
-		else if (usec > acpi_p_lvl2_lat)
-			sleep_level = 2;
-	}
-}
-
-/*
- * Put all devices into specified D-state
- */
-static int acpi_enter_dx(acpi_dstate_t state)
-{
-	int status = 0;
-	struct list_head *i = acpi_devs.next;
-
-	while (i != &acpi_devs)	{
-		struct acpi_dev *dev = list_entry(i, struct acpi_dev, entry);
-		if (dev->state != state) {
-			int dev_status = 0;
-			if (dev->info.transition)
-				dev_status = dev->info.transition(dev, state);
-			if (!dev_status) {
-				// put hardware into D-state
-				dev->state = state;
-			}
-			if (dev_status)
-				status = dev_status;
-		}
-
-		i = i->next;
-	}
-
-	return status;
-}
-
-/*
- * Update system time from real-time clock
- */
-static void acpi_update_clock(void)
-{
-	if (acpi_sleep_start) {
-		unsigned long delta;
-		struct timeval tv;
-		
-		delta = get_cmos_time() - acpi_sleep_start;
-		do_gettimeofday(&tv);
-		tv.tv_sec += delta;
-		do_settimeofday(&tv);
-		
-		acpi_sleep_start = 0;
-	}
-}
-
-
-/*
- * Enter system sleep state
- */
-static void acpi_enter_sx(acpi_sstate_t state)
-{
-	unsigned long slp_typ = acpi_slp_typ[(int) state];
-	if (slp_typ != ACPI_SLP_TYP_DISABLED) {
-		u16 typa, typb, value;
-
-		// bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb
-		typa = (slp_typ >> 8) & 0xff;
-		typb = slp_typ & 0xff;
-
-		typa = ((typa << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK);
-		typb = ((typb << ACPI_SLP_TYP_SHIFT) & ACPI_SLP_TYP_MASK);
-
-		if (state != ACPI_S0) {
-			acpi_sleep_start = get_cmos_time();
-			acpi_enter_dx(ACPI_D3);
-			acpi_sleep_state = state;
-		}
-
-		// clear wake status
-		acpi_write_pm1_status(acpi_facp, ACPI_WAK);
-
-		// set SLP_TYPa/b and SLP_EN
-		if (acpi_facp->pm1a_cnt) {
-			value = inw(acpi_facp->pm1a_cnt) & ~ACPI_SLP_TYP_MASK;
-			outw(value | typa | ACPI_SLP_EN, acpi_facp->pm1a_cnt);
-		}
-		if (acpi_facp->pm1b_cnt) {
-			value = inw(acpi_facp->pm1b_cnt) & ~ACPI_SLP_TYP_MASK;
-			outw(value | typb | ACPI_SLP_EN, acpi_facp->pm1b_cnt);
-		}
-
-		if (state == ACPI_S0) {
-			acpi_sleep_state = state;
-			acpi_enter_dx(ACPI_D0);
-			acpi_sleep_start = 0;
-		}
-		else if (state == ACPI_S1) {
-			// wait until S1 is entered
-			while (!(acpi_read_pm1_status(acpi_facp) & ACPI_WAK)) ;
-			// finished sleeping, update system time
-			acpi_update_clock();
-		}
-	}
-}
-
-/*
- * Enter soft-off (S5)
- */
-static void acpi_power_off_handler(void)
-{
-	acpi_enter_sx(ACPI_S5);
-}
-
-/*
- * Claim ACPI I/O ports
- */
-static int acpi_claim_ioports(struct acpi_facp *facp)
-{
-	// we don't get a guarantee of contiguity for any of the ACPI registers
-	if (facp->pm1a_evt)
-		request_region(facp->pm1a_evt, facp->pm1_evt_len, "acpi");
-	if (facp->pm1b_evt)
-		request_region(facp->pm1b_evt, facp->pm1_evt_len, "acpi");
-	if (facp->pm1a_cnt)
-		request_region(facp->pm1a_cnt, facp->pm1_cnt_len, "acpi");
-	if (facp->pm1b_cnt)
-		request_region(facp->pm1b_cnt, facp->pm1_cnt_len, "acpi");
-	if (facp->pm_tmr)
-		request_region(facp->pm_tmr, facp->pm_tm_len, "acpi");
-	if (facp->gpe0)
-		request_region(facp->gpe0, facp->gpe0_len, "acpi");
-	if (facp->gpe1)
-		request_region(facp->gpe1, facp->gpe1_len, "acpi");
-
-	return 0;
-}
-
-/*
- * Free ACPI I/O ports
- */
-static int acpi_release_ioports(struct acpi_facp *facp)
-{
-	// we don't get a guarantee of contiguity for any of the ACPI registers
-	if (facp->pm1a_evt)
-		release_region(facp->pm1a_evt, facp->pm1_evt_len);
-	if (facp->pm1b_evt)
-		release_region(facp->pm1b_evt, facp->pm1_evt_len);
-	if (facp->pm1a_cnt)
-		release_region(facp->pm1a_cnt, facp->pm1_cnt_len);
-	if (facp->pm1b_cnt)
-		release_region(facp->pm1b_cnt, facp->pm1_cnt_len);
-	if (facp->pm_tmr)
-		release_region(facp->pm_tmr, facp->pm_tm_len);
-	if (facp->gpe0)
-		release_region(facp->gpe0, facp->gpe0_len);
-	if (facp->gpe1)
-		release_region(facp->gpe1, facp->gpe1_len);
-
-	return 0;
-}
-
-/*
- * Examine/modify value
- */
-static int acpi_do_ulong(ctl_table *ctl,
-			 int write,
-			 struct file *file,
-			 void *buffer,
-			 size_t *len)
-{
-	char str[2 * sizeof(unsigned long) + 4], *strend;
-	unsigned long val;
-	int size;
-
-	if (!write) {
-		if (file->f_pos) {
-			*len = 0;
-			return 0;
-		}
-
-		val = *(unsigned long*) ctl->data;
-		size = sprintf(str, "0x%08lx\n", val);
-		if (*len >= size) {
-			copy_to_user(buffer, str, size);
-			*len = size;
-		}
-		else
-			*len = 0;
-	}
-	else {
-		size = sizeof(str) - 1;
-		if (size > *len)
-			size = *len;
-		copy_from_user(str, buffer, size);
-		str[size] = '\0';
-		val = simple_strtoul(str, &strend, 0);
-		if (strend == str)
-			return -EINVAL;
-		*(unsigned long*) ctl->data = val;
-	}
-
-	file->f_pos += *len;
-	return 0;
-}
-
-/*
- * Examine/modify event register
- */
-static int acpi_do_event_reg(ctl_table *ctl,
-			     int write,
-			     struct file *file,
-			     void *buffer,
-			     size_t *len)
-{
-	char str[2 * sizeof(u32) + 4], *strend;
-	u32 val, enabling;
-	int size;
-
-	if (!write) {
-		if (file->f_pos) {
-			*len = 0;
-			return 0;
-		}
-
-		val = 0;
-		switch (ctl->ctl_name) {
-		case ACPI_PM1_ENABLE:
-			val = acpi_read_pm1_enable(acpi_facp);
-			break;
-		case ACPI_GPE_ENABLE:
-			val = acpi_read_gpe_enable(acpi_facp);
-			break;
-		case ACPI_GPE_LEVEL:
-			val = acpi_gpe_level;
-			break;
-		}
-		
-		size = sprintf(str, "0x%08x\n", val);
-		if (*len >= size) {
-			copy_to_user(buffer, str, size);
-			*len = size;
-		}
-		else
-			*len = 0;
-	}
-	else
-	{
-		// fetch user value
-		size = sizeof(str) - 1;
-		if (size > *len)
-			size = *len;
-		copy_from_user(str, buffer, size);
-		str[size] = '\0';
-		val = (u32) simple_strtoul(str, &strend, 0);
-		if (strend == str)
-			return -EINVAL;
-
-		// store value in register
-		switch (ctl->ctl_name) {
-		case ACPI_PM1_ENABLE:
-			// clear previously disabled events
-			enabling = (val
-				    & ~acpi_read_pm1_enable(acpi_facp));
-			acpi_write_pm1_status(acpi_facp, enabling);
-			
-			if (val) {
-				// enable ACPI unless it is already
-				if (!acpi_is_enabled(acpi_facp))
-					acpi_enable(acpi_facp);
-			}
-			else if (!acpi_read_gpe_enable(acpi_facp)) {
-				// disable ACPI unless it is already
-				if (acpi_is_enabled(acpi_facp))
-					acpi_disable(acpi_facp);
-			}
-			
-			acpi_write_pm1_enable(acpi_facp, val);
-			break;
-		case ACPI_GPE_ENABLE:
-			// clear previously disabled events
-			enabling = (val
-				    & ~acpi_read_gpe_enable(acpi_facp));
-			while (acpi_read_gpe_status(acpi_facp) & enabling)
-				acpi_write_gpe_status(acpi_facp, enabling);
-			
-			if (val) {
-				// enable ACPI unless it is already
-				if (!acpi_is_enabled(acpi_facp))
-					acpi_enable(acpi_facp);
-			}
-			else if (!acpi_read_pm1_enable(acpi_facp)) {
-				// disable ACPI unless it is already
-				if (acpi_is_enabled(acpi_facp))
-					acpi_disable(acpi_facp);
-			}
-			
-			acpi_write_gpe_enable(acpi_facp, val);
-			break;
-		case ACPI_GPE_LEVEL:
-			acpi_gpe_level = val;
-			break;
-		}
-	}
-
-	file->f_pos += *len;
-	return 0;
-}
-
-/*
- * Wait for next event
- */
-static int acpi_do_event(ctl_table *ctl,
-			 int write,
-			 struct file *file,
-			 void *buffer,
-			 size_t *len)
-{
-	u32 pm1_status = 0, gpe_status = 0;
-	acpi_sstate_t event_state = 0;
-	char str[27];
-	int size;
-
-	if (write)
-		return -EPERM;
-	if (*len < sizeof(str)) {
-		*len = 0;
-		return 0;
-	}
-
-	for (;;) {
-		unsigned long flags;
-		
-		// we need an atomic exchange here
-		spin_lock_irqsave(&acpi_event_lock, flags);
-		pm1_status = acpi_pm1_status;
-		acpi_pm1_status = 0;
-		gpe_status = acpi_gpe_status;
-		acpi_gpe_status = 0;
-		spin_unlock_irqrestore(&acpi_event_lock, flags);
-		event_state = acpi_event_state;
-		
-		if (pm1_status || gpe_status)
-			break;
-		
-		// wait for an event to arrive
-		interruptible_sleep_on(&acpi_event_wait);
-		if (signal_pending(current))
-			return -ERESTARTSYS;
-	}
-
-	size = sprintf(str, "0x%08x 0x%08x 0x%01x\n",
-		       pm1_status,
-		       gpe_status,
-		       event_state);
-	copy_to_user(buffer, str, size);
-	*len = size;
-	file->f_pos += size;
-
-	return 0;
-}
-
-/*
- * Enter system sleep state
- */
-static int acpi_do_sleep(ctl_table *ctl,
-			 int write,
-			 struct file *file,
-			 void *buffer,
-			 size_t *len)
-{
-	if (!write) {
-		if (file->f_pos) {
-			*len = 0;
-			return 0;
-		}
-	}
-	else
-	{
-		acpi_enter_sx(ACPI_S1);
-		acpi_enter_sx(ACPI_S0);
-	}
-	file->f_pos += *len;
-	return 0;
-}
-
-/*
- * Initialize and enable ACPI
- */
-static int __init acpi_init(void)
-{
-	int pid;
-
-	if (acpi_find_tables() && acpi_find_piix4()) {
-		// no ACPI tables and not PIIX4
-		return -ENODEV;
-	}
-
-	if (acpi_facp->p_lvl2_lat
-	    && acpi_facp->p_lvl2_lat <= ACPI_MAX_P_LVL2_LAT) {
-		acpi_p_lvl2_lat = acpi_facp->p_lvl2_lat;
-	}
-	if (acpi_facp->p_lvl3_lat
-	    && acpi_facp->p_lvl3_lat <= ACPI_MAX_P_LVL3_LAT) {
-		acpi_p_lvl3_lat = acpi_facp->p_lvl3_lat;
-	}
-
-	if (acpi_facp->sci_int
-	    && request_irq(acpi_facp->sci_int,
-			   acpi_irq,
-			   SA_INTERRUPT | SA_SHIRQ,
-			   "acpi",
-			   acpi_facp)) {
-		printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n",
-		       acpi_facp->sci_int);
-		acpi_destroy_tables();
-		return -ENODEV;
-	}
-
-	acpi_claim_ioports(acpi_facp);
-	acpi_sysctl = register_sysctl_table(acpi_dir_table, 1);
-
-	pid = kernel_thread(acpi_control_thread,
-			    NULL,
-			    CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
-
-	acpi_power_off = acpi_power_off_handler;
-
-	/*
-	 * Set up the ACPI idle function. Note that we can't really
-	 * do this with multiple CPU's, we'd need a per-CPU ACPI
-	 * device..
-	 */
-#ifdef __SMP__
-	if (smp_num_cpus > 1)
-		return 0;
-#endif
-
-	acpi_idle = acpi_idle_handler;
-
-	return 0;
-}
-
-/*
- * Disable and deinitialize ACPI
- */
-static void __exit acpi_exit(void)
-{
-	acpi_idle = NULL;
-	acpi_power_off = NULL;
-
-	unregister_sysctl_table(acpi_sysctl);
-	acpi_disable(acpi_facp);
-	acpi_release_ioports(acpi_facp);
-
-	if (acpi_facp->sci_int)
-		free_irq(acpi_facp->sci_int, acpi_facp);
-
-	acpi_destroy_tables();
-}
-
-/*
- * Register a device with the ACPI subsystem
- */
-struct acpi_dev* acpi_register(struct acpi_dev_info *info, unsigned long adr)
-{
-	struct acpi_dev *dev = NULL;
-	if (info) {
-		dev = kmalloc(sizeof(struct acpi_dev), GFP_KERNEL);
-		if (dev) {
-			unsigned long flags;
-			
-			memset(dev, 0, sizeof(*dev));
-			memcpy(&dev->info, info, sizeof(dev->info));
-			dev->adr = adr;
-			
-			spin_lock_irqsave(&acpi_devs_lock, flags);
-			list_add(&dev->entry, &acpi_devs);
-			spin_unlock_irqrestore(&acpi_devs_lock, flags);
-		}
-	}
-	return dev;
-}
-
-/*
- * Unregister a device with ACPI
- */
-void acpi_unregister(struct acpi_dev *dev)
-{
-	if (dev) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&acpi_devs_lock, flags);
-		list_del(&dev->entry);
-		spin_unlock_irqrestore(&acpi_devs_lock, flags);
-
-		kfree(dev);
-	}
-}
-
-/*
- * Wake up a device
- */
-void acpi_wakeup(struct acpi_dev *dev)
-{
-	// run _PS0 or tell parent bus to wake device up
-}
-
-/*
- * Manage idle devices
- */
-static int acpi_control_thread(void *context)
-{
-	exit_mm(current);
-	exit_files(current);
-	strcpy(current->comm, "acpi");
-	
-	for(;;) {
-		interruptible_sleep_on(&acpi_control_wait);
-		if (signal_pending(current))
-			break;
-
-		// find all idle devices and set idle timer
-	}
-
-	return 0;
-}
-
-__initcall(acpi_init);
-
-/*
- * Module visible symbols
- */
-EXPORT_SYMBOL(acpi_control_wait);
-EXPORT_SYMBOL(acpi_register);
-EXPORT_SYMBOL(acpi_unregister);
-EXPORT_SYMBOL(acpi_wakeup);
diff -u --recursive --new-file v2.3.34/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
--- v2.3.34/linux/drivers/net/3c503.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/net/3c503.c	Tue Dec 21 10:17:31 1999
@@ -103,7 +103,7 @@
 
     for (addr = addrs; *addr; addr++) {
 	int i;
-	unsigned int base_bits = readb(*addr);
+	unsigned int base_bits = isa_readb(*addr);
 	/* Find first set bit. */
 	for(i = 7; i >= 0; i--, base_bits >>= 1)
 	    if (base_bits & 0x1)
@@ -251,18 +251,18 @@
 	{			/* Check the card's memory. */
 	    unsigned long mem_base = dev->mem_start;
 	    unsigned int test_val = 0xbbadf00d;
-	    writel(0xba5eba5e, mem_base);
+	    isa_writel(0xba5eba5e, mem_base);
 	    for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
-		writel(test_val, mem_base + i);
-		if (readl(mem_base) != 0xba5eba5e
-		    || readl(mem_base + i) != test_val) {
+		isa_writel(test_val, mem_base + i);
+		if (isa_readl(mem_base) != 0xba5eba5e
+		    || isa_readl(mem_base + i) != test_val) {
 		    printk("3c503: memory failure or memory address conflict.\n");
 		    dev->mem_start = 0;
 		    ei_status.name = "3c503-PIO";
 		    break;
 		}
 		test_val += 0x55555555;
-		writel(0, mem_base + i);
+		isa_writel(0, mem_base + i);
 	    }
 	}
 #endif  /* EL2MEMTEST */
diff -u --recursive --new-file v2.3.34/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.3.34/linux/drivers/net/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/drivers/net/Makefile	Mon Dec 20 22:05:10 1999
@@ -178,7 +178,6 @@
 obj-$(CONFIG_HAPPYMEAL) += sunhme.o
 obj-$(CONFIG_SUNQE) += sunqe.o
 obj-$(CONFIG_SUNBMAC) += sunbmac.o
-obj-$(CONFIG_SUNBMAC) += sunbmac.o
 obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
 obj-$(CONFIG_AT1700) += at1700.o
 obj-$(CONFIG_FMV18X) += fmv18x.o
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/Config.in linux/drivers/net/irda/Config.in
--- v2.3.34/linux/drivers/net/irda/Config.in	Sun Nov  7 16:37:34 1999
+++ linux/drivers/net/irda/Config.in	Tue Dec 21 10:17:31 1999
@@ -20,6 +20,8 @@
    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
+   dep_tristate '  Old Belkin dongle' CONFIG_OLD_BELKIN_DONGLE $CONFIG_IRDA
+   
 fi
 
 endmenu
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile
--- v2.3.34/linux/drivers/net/irda/Makefile	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/irda/Makefile	Tue Dec 21 10:17:31 1999
@@ -52,6 +52,22 @@
   endif
 endif
 
+ifeq ($(CONFIG_TOSHIBA_FIR),y)
+L_OBJS += toshoboe.o
+else
+  ifeq ($(CONFIG_TOSHIBA_FIR),m)
+  M_OBJS += toshoboe.o
+  endif
+endif
+
+ifeq ($(CONFIG_TOSHIBA_FIR),y)
+L_OBJS += toshoboe.o
+else
+  ifeq ($(CONFIG_TOSHIBA_FIR),m)
+  M_OBJS += toshoboe.o
+  endif
+endif
+
 ifeq ($(CONFIG_SMC_IRCC_FIR),y)
 L_OBJS += smc-ircc.o
 LX_OBJS += irport.o
@@ -107,6 +123,14 @@
 else
   ifeq ($(CONFIG_AIRPORT_DONGLE),m)
   M_OBJS += airport.o
+  endif
+endif
+
+ifeq ($(CONFIG_OLD_BELKIN_DONGLE),y)
+L_OBJS += old_belkin.o
+else
+  ifeq ($(CONFIG_OLD_BELKIN_DONGLE),m)
+  M_OBJS += old_belkin.o
   endif
 endif
 
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c
--- v2.3.34/linux/drivers/net/irda/actisys.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/net/irda/actisys.c	Tue Dec 21 10:17:31 1999
@@ -1,16 +1,18 @@
 /*********************************************************************
  *                
  * Filename:      actisys.c
- * Version:       0.8
+ * Version:       1.0
  * Description:   Implementation for the ACTiSYS IR-220L and IR-220L+ 
  *                dongles
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Status:        Beta.
+ * Authors:       Dag Brattli <dagb@cs.uit.no> (initially)
+ *		  Jean Tourrilhes <jt@hpl.hp.com> (new version)
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Mon Oct 18 23:37:06 1999
+ * Modified at:   Fri Dec 17 09:16:09 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 1999 Jean Tourrilhes
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -23,6 +25,16 @@
  *     
  ********************************************************************/
 
+/*
+ * Changelog
+ *
+ * 0.8 -> 0.9999 - Jean
+ *	o New initialisation procedure : much safer and correct
+ *	o New procedure the change speed : much faster and simpler
+ *	o Other cleanups & comments
+ *	Thanks to Lichen Wang @ Actisys for his excellent help...
+ */
+
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/tty.h>
@@ -33,13 +45,25 @@
 #include <net/irda/irmod.h>
 #include <net/irda/irda_device.h>
 
+/* 
+ * Define the timing of the pulses we send to the dongle (to reset it, and
+ * to toggle speeds). Basically, the limit here is the propagation speed of
+ * the signals through the serial port, the dongle being much faster.  Any
+ * serial port support 115 kb/s, so we are sure that pulses 8.5 us wide can
+ * go through cleanly . If you are on the wild side, you can try to lower
+ * this value (Actisys recommended me 2 us, and 0 us work for me on a P233!)
+ */
+#define MIN_DELAY 10	/* 10 us to be on the conservative side */
+
 static int  actisys_change_speed(struct irda_task *task);
 static int  actisys_reset(struct irda_task *task);
 static void actisys_open(dongle_t *self, struct qos_info *qos);
 static void actisys_close(dongle_t *self);
 
-/* These are the baudrates supported */
+/* These are the baudrates supported, in the order available */
+/* Note : the 220L doesn't support 38400, but we will fix that below */
 static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400 };
+#define MAX_SPEEDS 5
 
 static struct dongle_reg dongle = {
 	Q_NULL,
@@ -59,13 +83,25 @@
 	actisys_change_speed,
 };
 
+/*
+ * Function actisys_change_speed (task)
+ *
+ *	There is two model of Actisys dongle we are dealing with,
+ * the 220L and 220L+. At this point, only irattach knows with
+ * kind the user has requested (it was an argument on irattach
+ * command line).
+ *	So, we register a dongle of each sort and let irattach
+ * pick the right one...
+ */
 int __init actisys_init(void)
 {
 	int ret;
 
+	/* First, register an Actisys 220L dongle */
 	ret = irda_device_register_dongle(&dongle);
 	if (ret < 0)
 		return ret;
+	/* Now, register an Actisys 220L+ dongle */
 	ret = irda_device_register_dongle(&dongle_plus);
 	if (ret < 0) {
 		irda_device_unregister_dongle(&dongle);
@@ -76,125 +112,121 @@
 
 void actisys_cleanup(void)
 {
+	/* We have to remove both dongles */
 	irda_device_unregister_dongle(&dongle);
 	irda_device_unregister_dongle(&dongle_plus);
 }
 
 static void actisys_open(dongle_t *self, struct qos_info *qos)
 {
+	/* Power on the dongle */
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
+
+	/* Set the speeds we can accept */
 	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
 
 	/* Remove support for 38400 if this is not a 220L+ dongle */
 	if (self->issue->type == IRDA_ACTISYS_DONGLE)
 		qos->baud_rate.bits &= ~IR_38400;
 	
-	qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
+	qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
 
 	MOD_INC_USE_COUNT;
 }
 
 static void actisys_close(dongle_t *self)
 {
-	/* Power off dongle */
+	/* Power off the dongle */
 	self->set_dtr_rts(self->dev, FALSE, FALSE);
 
 	MOD_DEC_USE_COUNT;
 }
 
 /*
- * Function actisys_change_speed (tty, baud)
+ * Function actisys_change_speed (task)
  *
  *    Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles.
- *    To cycle through the available baud rates, pulse RTS low for a few
- *    ms.  
+ *    To cycle through the available baud rates, pulse RTS low for a few us.
+ *
+ *	First, we reset the dongle to always start from a known state.
+ *	Then, we cycle through the speeds by pulsing RTS low and then up.
+ *	The dongle allow us to pulse quite fast, se we can set speed in one go,
+ * which is must faster ( < 100 us) and less complex than what is found
+ * in some other dongle drivers...
+ *	Note that even if the new speed is the same as the current speed,
+ * we reassert the speed. This make sure that things are all right,
+ * and it's fast anyway...
+ *	By the way, this function will work for both type of dongles,
+ * because the additional speed is at the end of the sequence...
  */
 static int actisys_change_speed(struct irda_task *task)
 {
 	dongle_t *self = (dongle_t *) task->instance;
-	__u32 speed = (__u32) task->param;
-        __u32 current_speed;
-        int index = 0;
+	__u32 speed = (__u32) task->param;	/* Target speed */
 	int ret = 0;
-	
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
-	current_speed = self->speed;
+	int i = 0;
 
-	/* Find the correct baudrate index for the currently used baudrate */
-	while (current_speed != baud_rates[index])
-		index++;
+        IRDA_DEBUG(4, __FUNCTION__ "(), speed=%d (was %d)\n", speed, 
+		   self->speed);
 
-        IRDA_DEBUG(4, __FUNCTION__ "(), index=%d\n", index);
+	/* Go to a known state by reseting the dongle */
 
-	switch (task->state) {
-	case IRDA_TASK_INIT:
-		/* Lock dongle */
-		if (irda_lock((void *) &self->busy) == FALSE) {
-			IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
-			ret = MSECS_TO_JIFFIES(100);
+	/* Reset the dongle : set DTR low for 10 us */
+	self->set_dtr_rts(self->dev, FALSE, TRUE);
+	udelay(MIN_DELAY);
+
+	/* Go back to normal mode (we are now at 9600 b/s) */
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
+ 
+	/* 
+	 * Now, we can set the speed requested. Send RTS pulses until we
+         * reach the target speed 
+	 */
+	for (i=0; i<MAX_SPEEDS; i++) {
+		if (speed == baud_rates[i]) {
+			self->speed = baud_rates[i];
 			break;
 		}
-	
-                IRDA_DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",
-		      baud_rates[index]);
-		
-		/* Set DTR, clear RTS */
+		/* Make sure previous pulse is finished */
+		udelay(MIN_DELAY);
+
+		/* Set RTS low for 10 us */
 		self->set_dtr_rts(self->dev, TRUE, FALSE);
-		
-		irda_task_next_state(task, IRDA_TASK_WAIT1);
+		udelay(MIN_DELAY);
 
-		/* Wait at a few ms */
-		ret = MSECS_TO_JIFFIES(20);
-		break;
-	case IRDA_TASK_WAIT1:
-		/* Set DTR, Set RTS */
+		/* Set RTS high for 10 us */
 		self->set_dtr_rts(self->dev, TRUE, TRUE);
-		
-		irda_task_next_state(task, IRDA_TASK_WAIT2);
-
-		/* Wait at a few ms again */
-		ret = MSECS_TO_JIFFIES(20);
-		break;
-	case IRDA_TASK_WAIT2:
-                /* Go to next baudrate */
-		if (self->issue->type == IRDA_ACTISYS_DONGLE)
-                        index = (index+1) % 4; /* IR-220L */
-		else
-                        index = (index+1) % 5; /* IR-220L+ */
-
-                current_speed = baud_rates[index];
-
-		/* Check if we need to go some more rounds */
-		if (current_speed != speed)
-			irda_task_next_state(task, IRDA_TASK_INIT);
-		else {
-			irda_task_next_state(task, IRDA_TASK_DONE);
-			self->busy = 0;
-		}
-		break;
-	default:
-		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
-		irda_task_next_state(task, IRDA_TASK_DONE);
-		self->busy = 0;
-		ret = -1;
-		break;
-        }
+	}
 
-	self->speed = speed;
+	/* Check if life is sweet... */
+	if (i >= MAX_SPEEDS)
+		ret = -1;  /* This should not happen */
 
-	IRDA_DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", 
-	      baud_rates[index]);
+	/* Basta lavoro, on se casse d'ici... */
+	irda_task_next_state(task, IRDA_TASK_DONE);
 
 	return ret;
 }
 
 /*
- * Function actisys_reset (dev)
+ * Function actisys_reset (task)
  *
  *      Reset the Actisys type dongle. Warning, this function must only be
  *      called with a process context!
  *
- *    	1. Clear DTR for a few ms.
+ * We need to do two things in this function :
+ *	o first make sure that the dongle is in a state where it can operate
+ *	o second put the dongle in a know state
+ *
+ *	The dongle is powered of the RTS and DTR lines. In the dongle, there
+ * is a big capacitor to accomodate the current spikes. This capacitor
+ * takes a least 50 ms to be charged. In theory, the Bios set those lines
+ * up, so by the time we arrive here we should be set. It doesn't hurt
+ * to be on the conservative side, so we will wait...
+ *	Then, we set the speed to 9600 b/s to get in a known state (see in
+ * change_speed for details). It is needed because the IrDA stack
+ * has tried to set the speed immediately after our first return,
+ * so before we can be sure the dongle is up and running.
  */
 static int actisys_reset(struct irda_task *task)
 {
@@ -203,27 +235,34 @@
 
 	ASSERT(task != NULL, return -1;);
 
+	self->reset_task = task;
+
 	switch (task->state) {
 	case IRDA_TASK_INIT:
-		/* Clear DTR */
-		self->set_dtr_rts(self->dev, FALSE, TRUE);
+		/* Set both DTR & RTS to power up the dongle */
+		/* In theory redundant with power up in actisys_open() */
+		self->set_dtr_rts(self->dev, TRUE, TRUE);
 		
+		/* Sleep 50 ms to make sure capacitor is charged */
+		ret = MSECS_TO_JIFFIES(50);
 		irda_task_next_state(task, IRDA_TASK_WAIT);
-
-		/* Sleep 10-20 ms*/
-		ret = MSECS_TO_JIFFIES(20);
 		break;
 	case IRDA_TASK_WAIT:			
+		/* Reset the dongle : set DTR low for 10 us */
+		self->set_dtr_rts(self->dev, FALSE, TRUE);
+		udelay(MIN_DELAY);
+
 		/* Go back to normal mode */
 		self->set_dtr_rts(self->dev, TRUE, TRUE);
 	
 		irda_task_next_state(task, IRDA_TASK_DONE);
-
-		self->speed = 9600;
+		self->reset_task = NULL;
+		self->speed = 9600;	/* That's the default */
 		break;
 	default:
 		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
 		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->reset_task = NULL;
 		ret = -1;
 		break;
 	}
@@ -231,7 +270,7 @@
 }
 
 #ifdef MODULE
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no> - Jean Tourrilhes <jt@hpl.hp.com>");
 MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver");	
 		
 /*
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/airport.c linux/drivers/net/irda/airport.c
--- v2.3.34/linux/drivers/net/irda/airport.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/net/irda/airport.c	Tue Dec 21 10:17:31 1999
@@ -68,7 +68,7 @@
 	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;
+	qos->min_turn_time.bits = 0x07;
 
 	MOD_INC_USE_COUNT;
 }
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c
--- v2.3.34/linux/drivers/net/irda/esi.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/net/irda/esi.c	Tue Dec 21 10:17:31 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Mon Oct 18 12:35:43 1999
+ * Modified at:   Fri Dec 17 09:17:05 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, <dagb@cs.uit.no>,
@@ -68,7 +68,7 @@
 static void esi_open(dongle_t *self, struct qos_info *qos)
 {
 	qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
-	qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
+	qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
 
 	MOD_INC_USE_COUNT;
 }
@@ -93,12 +93,6 @@
 	__u32 speed = (__u32) task->param;
 	int dtr, rts;
 	
-	/* Lock dongle */
-	if (irda_lock((void *) &self->busy) == FALSE) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
-		return MSECS_TO_JIFFIES(100);
-	}
-
 	switch (speed) {
 	case 19200:
 		dtr = TRUE;
@@ -120,9 +114,6 @@
 
 	irda_task_next_state(task, IRDA_TASK_DONE);
 
-	/* Unlock */
-	self->busy = 0;
-	
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/girbil.c linux/drivers/net/irda/girbil.c
--- v2.3.34/linux/drivers/net/irda/girbil.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/net/irda/girbil.c	Tue Dec 21 10:17:31 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:   Sat Oct 30 20:25:22 1999
+ * Modified at:   Fri Dec 17 09:16:52 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -87,7 +87,7 @@
 static void girbil_open(dongle_t *self, struct qos_info *qos)
 {
 	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-	qos->min_turn_time.bits &= 0x03;
+	qos->min_turn_time.bits = 0x03;
 
 	MOD_INC_USE_COUNT;
 }
@@ -113,14 +113,10 @@
 	__u8 control[2];
 	int ret = 0;
 
+	self->speed_task = task;
+
 	switch (task->state) {
 	case IRDA_TASK_INIT:
-		/* Lock dongle */
-		if (irda_lock((void *) &self->busy) == FALSE) {
-			IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
-			return MSECS_TO_JIFFIES(100);
-		}
-
 		/* Need to reset the dongle and go to 9600 bps before
                    programming */
 		if (irda_task_execute(self, girbil_reset, NULL, task, 
@@ -170,12 +166,12 @@
 		/* Go back to normal mode */
 		self->set_dtr_rts(self->dev, TRUE, TRUE);
 		irda_task_next_state(task, IRDA_TASK_DONE);
-		self->busy = 0;
+		self->speed_task = NULL;
 		break;
 	default:
 		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
 		irda_task_next_state(task, IRDA_TASK_DONE);
-		self->busy = 0;
+		self->speed_task = NULL;
 		ret = -1;
 		break;
 	}
@@ -197,6 +193,8 @@
 	__u8 control = GIRBIL_TXEN | GIRBIL_RXEN;
 	int ret = 0;
 
+	self->reset_task = task;
+
 	switch (task->state) {
 	case IRDA_TASK_INIT:
 		/* Reset dongle */
@@ -221,10 +219,12 @@
 		/* Go back to normal mode */
 		self->set_dtr_rts(self->dev, TRUE, TRUE);
 		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->reset_task = NULL;
 		break;
 	default:
 		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
 		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->reset_task = NULL;
 		ret = -1;
 		break;
 	}
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.3.34/linux/drivers/net/irda/irport.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/irda/irport.c	Tue Dec 21 10:17:31 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:   Sat Nov 13 23:25:56 1999
+ * Modified at:   Thu Dec 16 00:47:08 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:	  serial.c by Linus Torvalds 
  * 
@@ -73,16 +73,11 @@
 static struct irport_cb *dev_self[] = { NULL, NULL, NULL, NULL};
 static char *driver_name = "irport";
 
-static int irport_open(int i, unsigned int iobase, unsigned int irq);
-static int irport_close(struct irport_cb *self);
-
 static void irport_write_wakeup(struct irport_cb *self);
 static int  irport_write(int iobase, int fifo_size, __u8 *buf, int len);
 static void irport_receive(struct irport_cb *self);
 
 static int  irport_net_init(struct net_device *dev);
-static int  irport_net_open(struct net_device *dev);
-static int  irport_net_close(struct net_device *dev);
 static int  irport_net_ioctl(struct net_device *dev, struct ifreq *rq, 
 			     int cmd);
 static int  irport_is_receiving(struct irport_cb *self);
@@ -91,7 +86,15 @@
 static struct net_device_stats *irport_net_get_stats(struct net_device *dev);
 static int irport_change_speed_complete(struct irda_task *task);
 
+EXPORT_SYMBOL(irport_open);
+EXPORT_SYMBOL(irport_close);
+EXPORT_SYMBOL(irport_start);
+EXPORT_SYMBOL(irport_stop);
+EXPORT_SYMBOL(irport_interrupt);
+EXPORT_SYMBOL(irport_hard_xmit);
 EXPORT_SYMBOL(irport_change_speed);
+EXPORT_SYMBOL(irport_net_open);
+EXPORT_SYMBOL(irport_net_close);
 
 int __init irport_init(void)
 {
@@ -101,7 +104,7 @@
  		int ioaddr = io[i];
  		if (check_region(ioaddr, IO_EXTENT))
  			continue;
- 		if (irport_open(i, io[i], irq[i]) == 0)
+ 		if (irport_open(i, io[i], irq[i]) != NULL)
  			return 0;
  	}
 	/* 
@@ -130,7 +133,8 @@
 }
 #endif /* MODULE */
 
-static int irport_open(int i, unsigned int iobase, unsigned int irq)
+struct irport_cb *
+irport_open(int i, unsigned int iobase, unsigned int irq)
 {
 	struct net_device *dev;
 	struct irport_cb *self;
@@ -146,7 +150,7 @@
 	if (!self) {
 		ERROR(__FUNCTION__ "(), can't allocate memory for "
 		      "control block!\n");
-		return -ENOMEM;
+		return NULL;
 	}
 	memset(self, 0, sizeof(struct irport_cb));
    
@@ -154,22 +158,23 @@
 
 	/* Need to store self somewhere */
 	dev_self[i] = self;
+	self->priv = self;
 
 	/* Initialize IO */
-	self->io.iobase2   = iobase;
-        self->io.irq2      = irq;
+	self->io.iobase   = iobase;
+        self->io.irq      = irq;
         self->io.io_ext    = IO_EXTENT;
         self->io.fifo_size = 16;
 
 	/* Lock the port that we need */
-	ret = check_region(self->io.iobase2, self->io.io_ext);
+	ret = check_region(self->io.iobase, self->io.io_ext);
 	if (ret < 0) { 
 		IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
-		      self->io.iobase2);
+		      self->io.iobase);
 		/* irport_cleanup(self->self);  */
-		return -ENODEV;
+		return NULL;
 	}
-	request_region(self->io.iobase2, self->io.io_ext, driver_name);
+	request_region(self->io.iobase, self->io.io_ext, driver_name);
 
 	/* Initialize QoS for this device */
 	irda_init_max_qos_capabilies(&self->qos);
@@ -191,7 +196,7 @@
 		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
 						      GFP_KERNEL);
 		if (self->rx_buff.head == NULL)
-			return -ENOMEM;
+			return NULL;
 		memset(self->rx_buff.head, 0, self->rx_buff.truesize);
 	}
 	if (self->tx_buff.truesize > 0) {
@@ -199,7 +204,7 @@
 						      GFP_KERNEL);
 		if (self->tx_buff.head == NULL) {
 			kfree(self->rx_buff.head);
-			return -ENOMEM;
+			return NULL;
 		}
 		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 	}	
@@ -211,12 +216,18 @@
 
 	if (!(dev = dev_alloc("irda%d", &err))) {
 		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
-		return -ENOMEM;
+		return NULL;
 	}
+	/* dev_alloc doesn't clear the struct */
+	memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
 
- 	dev->priv = (void *) self;
 	self->netdev = dev;
 
+	/* May be overridden by piggyback drivers */
+ 	dev->priv = (void *) self;
+	self->interrupt    = irport_interrupt;
+	self->change_speed = irport_change_speed;
+
 	/* Override the network functions we need to use */
 	dev->init            = irport_net_init;
 	dev->hard_start_xmit = irport_hard_xmit;
@@ -234,14 +245,14 @@
 	rtnl_unlock();
 	if (err) {
 		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
-		return -1;
+		return NULL;
 	}
 	MESSAGE("IrDA: Registered device %s\n", dev->name);
 
-	return 0;
+	return self;
 }
 
-static int irport_close(struct irport_cb *self)
+int irport_close(struct irport_cb *self)
 {
 	ASSERT(self != NULL, return -1;);
 
@@ -255,12 +266,14 @@
 		rtnl_lock();
 		unregister_netdevice(self->netdev);
 		rtnl_unlock();
+		/* Must free the old-style 2.2.x device */
+		kfree(self->netdev);
 	}
 
 	/* Release the IO-port that this driver is using */
 	IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
-		   self->io.iobase2);
-	release_region(self->io.iobase2, self->io.io_ext);
+		   self->io.iobase);
+	release_region(self->io.iobase, self->io.io_ext);
 
 	if (self->tx_buff.head)
 		kfree(self->tx_buff.head);
@@ -273,13 +286,16 @@
 	return 0;
 }
 
-void irport_start(struct irport_cb *self, int iobase)
+void irport_start(struct irport_cb *self)
 {
 	unsigned long flags;
+	int iobase;
+
+	iobase = self->io.iobase;
 
 	spin_lock_irqsave(&self->lock, flags);
 
-	irport_stop(self, iobase);
+	irport_stop(self);
 
 	/* Initialize UART */
 	outb(UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
@@ -291,9 +307,12 @@
 	spin_unlock_irqrestore(&self->lock, flags);
 }
 
-void irport_stop(struct irport_cb *self, int iobase)
+void irport_stop(struct irport_cb *self)
 {
 	unsigned long flags;
+	int iobase;
+
+	iobase = self->io.iobase;
 
 	spin_lock_irqsave(&self->lock, flags);
 
@@ -325,8 +344,9 @@
  *    Set speed of IrDA port to specified baudrate
  *
  */
-void __irport_change_speed(struct irport_cb *self, __u32 speed)
+void irport_change_speed(void *priv, __u32 speed)
 {
+	struct irport_cb *self = (struct irport_cb *) priv;
 	unsigned long flags;
 	int iobase; 
 	int fcr;    /* FIFO control reg */
@@ -337,7 +357,7 @@
 
 	ASSERT(self != NULL, return;);
 
-	iobase = self->io.iobase2;
+	iobase = self->io.iobase;
 	
 	/* Update accounting for new speed */
 	self->io.speed = speed;
@@ -377,12 +397,12 @@
 }
 
 /*
- * Function irport_change_speed (instance, state, param)
+ * Function __irport_change_speed (instance, state, param)
  *
  *    State machine for changing speed of the device. We do it this way since
  *    we cannot use schedule_timeout() when we are in interrupt context
  */
-int irport_change_speed(struct irda_task *task)
+int __irport_change_speed(struct irda_task *task)
 {
 	struct irport_cb *self;
 	__u32 speed = (__u32) task->param;
@@ -413,7 +433,7 @@
 		break;
 	case IRDA_TASK_CHILD_INIT:
 		/* Go to default speed */
-		__irport_change_speed(self, 9600);
+		irport_change_speed(self, 9600);
 
 		/* Change speed of dongle */
 		if (irda_task_execute(self->dongle,
@@ -436,7 +456,7 @@
 		break;
 	case IRDA_TASK_CHILD_DONE:
 		/* Finally we are ready to change the speed */
-		__irport_change_speed(self, speed);
+		irport_change_speed(self, speed);
 		
 		irda_task_next_state(task, IRDA_TASK_DONE);
 		break;
@@ -466,7 +486,7 @@
 
 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	iobase = self->io.iobase2;
+	iobase = self->io.iobase;
 
 	/* Finished with frame?  */
 	if (self->tx_buff.len > 0)  {
@@ -484,7 +504,7 @@
 		 */
 		if (self->new_speed) {
 			IRDA_DEBUG(5, __FUNCTION__ "(), Changing speed!\n");
-			irda_task_execute(self, irport_change_speed, 
+			irda_task_execute(self, __irport_change_speed, 
 					  irport_change_speed_complete, 
 					  NULL, (void *) self->new_speed);
 			self->new_speed = 0;
@@ -529,7 +549,7 @@
 	/* Tx FIFO should be empty! */
 	if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
 		IRDA_DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n");
-		return -1;
+		return 0;
 	}
         
 	/* Fill FIFO with current frame */
@@ -589,7 +609,7 @@
 	self = (struct irport_cb *) dev->priv;
 	ASSERT(self != NULL, return 0;);
 
-	iobase = self->io.iobase2;
+	iobase = self->io.iobase;
 
 	/* Lock transmit buffer */
 	if (irda_lock((void *) &dev->tbusy) == FALSE) {
@@ -598,8 +618,8 @@
 			return -EBUSY;
 
 		WARNING("%s: transmit timed out\n", dev->name);
-		irport_start(self, iobase);
-		__irport_change_speed(self, self->io.speed );
+		irport_start(self);
+		irport_change_speed(self, self->io.speed );
 
 		dev->trans_start = jiffies;
 	}
@@ -643,7 +663,7 @@
 
 	ASSERT(self != NULL, return;);
 
-	iobase = self->io.iobase2;
+	iobase = self->io.iobase;
 
 	/*  
 	 * Receive all characters in Rx FIFO, unwrap and unstuff them. 
@@ -684,7 +704,7 @@
 
 	dev->interrupt = 1;
 
-	iobase = self->io.iobase2;
+	iobase = self->io.iobase;
 
 	iir = inb(iobase+UART_IIR) & UART_IIR_ID;
 	while (iir) {
@@ -739,7 +759,7 @@
  *    Network device is taken up. Usually this is done by "ifconfig irda0 up" 
  *   
  */
-static int irport_net_open(struct net_device *dev)
+int irport_net_open(struct net_device *dev)
 {
 	struct irport_cb *self;
 	int iobase;
@@ -747,13 +767,13 @@
 	ASSERT(dev != NULL, return -1;);
 	self = (struct irport_cb *) dev->priv;
 
-	iobase = self->io.iobase2;
+	iobase = self->io.iobase;
 
-	if (request_irq(self->io.irq2, irport_interrupt, 0, dev->name, 
+	if (request_irq(self->io.irq, self->interrupt, 0, dev->name, 
 			(void *) dev))
 		return -EAGAIN;
 
-	irport_start(self, iobase);
+	irport_start(self);
 
 	/* Ready to play! */
 	dev->tbusy = 0;
@@ -779,7 +799,7 @@
  *    Network device is taken down. Usually this is done by 
  *    "ifconfig irda0 down" 
  */
-static int irport_net_close(struct net_device *dev)
+int irport_net_close(struct net_device *dev)
 {
 	struct irport_cb *self;
 	int iobase;
@@ -791,7 +811,7 @@
 
 	ASSERT(self != NULL, return -1;);
 
-	iobase = self->io.iobase2;
+	iobase = self->io.iobase;
 
 	/* Stop device */
 	dev->tbusy = 1;
@@ -802,9 +822,9 @@
 		irlap_close(self->irlap);
 	self->irlap = NULL;
 
-	irport_stop(self, iobase);
+	irport_stop(self);
 
-	free_irq(self->io.irq2, dev);
+	free_irq(self->io.irq, dev);
 
 	MOD_DEC_USE_COUNT;
 
@@ -822,7 +842,7 @@
 {
 	int iobase;
 
-	iobase = self->io.iobase2;
+	iobase = self->io.iobase;
 
 	/* Wait until Tx FIFO is empty */
 	while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
@@ -857,7 +877,7 @@
 
 	ASSERT(self != NULL, return -1;);
 
-	iobase = self->io.iobase2;
+	iobase = self->io.iobase;
 
 	if (dtr)
 		dtr = UART_MCR_DTR;
@@ -877,7 +897,7 @@
 
 	ASSERT(self != NULL, return -1;);
 
-	iobase = self->io.iobase2;
+	iobase = self->io.iobase;
 
 	/* Tx FIFO should be empty! */
 	if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
@@ -923,7 +943,7 @@
 	
 	switch (cmd) {
 	case SIOCSBANDWIDTH: /* Set bandwidth */
-		irda_task_execute(self, irport_change_speed, NULL, NULL, 
+		irda_task_execute(self, __irport_change_speed, NULL, NULL, 
 				  (void *) irq->ifr_baudrate);
 		break;
 	case SIOCSDONGLE: /* Set dongle */
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- v2.3.34/linux/drivers/net/irda/irtty.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/irda/irtty.c	Tue Dec 21 10:17:31 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:   Tue Nov 16 02:50:37 1999
+ * Modified at:   Thu Dec 16 09:37:47 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>
@@ -42,7 +42,6 @@
 #include <net/irda/irda_device.h>
 
 static hashbin_t *irtty = NULL;
-
 static struct tty_ldisc irda_ldisc;
 
 static int qos_mtt_bits = 0x03;      /* 5 ms or more */
@@ -186,7 +185,7 @@
 		tty->ldisc.flush_buffer(tty);
 	
 	self->magic = IRTTY_MAGIC;
-	self->rx_buff.state = OUTSIDE_FRAME;
+	self->mode = IRDA_IRLAP;
 
 	/* 
 	 *  Initialize QoS capabilities, we fill in all the stuff that
@@ -206,7 +205,7 @@
 	/* Specify how much memory we want */
 	self->rx_buff.truesize = 4000; 
 	self->tx_buff.truesize = 4000;
-	
+
 	/* Allocate memory if needed */
 	if (self->rx_buff.truesize > 0) {
 		self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
@@ -225,8 +224,6 @@
 		memset(self->tx_buff.head, 0, self->tx_buff.truesize);
 	}
 	
-      	self->magic = IRTTY_MAGIC;
-
 	self->rx_buff.in_frame = FALSE;
 	self->rx_buff.state = OUTSIDE_FRAME;
 	self->tx_buff.data = self->tx_buff.head;
@@ -284,18 +281,24 @@
 	tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 	tty->disc_data = 0;
 	
-	/* We are not using any dongle anymore! */
-	if (self->dongle)
-		irda_device_dongle_cleanup(self->dongle);
-	self->dongle = NULL;
-
 	/* Remove netdevice */
 	if (self->netdev) {
 		rtnl_lock();
 		unregister_netdevice(self->netdev);
 		rtnl_unlock();
+		/* Must free the old-style 2.2.x device */
+		kfree(self->netdev);
 	}
 	
+	/* We are not using any dongle anymore! */
+	if (self->dongle)
+		irda_device_dongle_cleanup(self->dongle);
+	self->dongle = NULL;
+
+	/* Remove speed changing task if any */
+	if (self->task)
+		irda_task_delete(self->task);
+
 	self->tty = NULL;
 	self->magic = 0;
 	
@@ -404,9 +407,15 @@
 	IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies); 
 
 	self = (struct irtty_cb *) task->instance;
-
 	ASSERT(self != NULL, return -1;);
 
+	/* Check if busy */
+	if (self->task && self->task != task) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+		return MSECS_TO_JIFFIES(10);
+	} else
+		self->task = task;
+
 	switch (task->state) {
 	case IRDA_TASK_INIT:
 		/* 
@@ -459,10 +468,12 @@
 		__irtty_change_speed(self, speed);
 		
 		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->task = NULL;
 		break;
 	default:
 		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
 		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->task = NULL;
 		ret = -1;
 		break;
 	}	
@@ -551,6 +562,11 @@
 {
 	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
 
+	if (!self || !self->netdev) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), not ready yet!\n");
+		return;
+	}
+
 	/* Read the characters out of the buffer */
  	while (count--) {
 		/* 
@@ -631,7 +647,7 @@
 	/* Check if we need to change the speed */
 	if ((speed = irda_get_speed(skb)) != self->io.speed)
 		self->new_speed = speed;
-	
+
 	/* Init tx buffer*/
 	self->tx_buff.data = self->tx_buff.head;
 	
@@ -768,7 +784,7 @@
 	set_fs(get_ds());
 	
 	if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
-		ERROR(__FUNCTION__ "(), error doing ioctl!\n");
+		IRDA_DEBUG(2, __FUNCTION__ "(), error doing ioctl!\n");
 	}
 	set_fs(fs);
 
@@ -987,6 +1003,9 @@
 		break;
 	case SIOCSDTRRTS:
 		irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
+		break;
+	case SIOCSMODE:
+		irtty_set_mode(dev, irq->ifr_mode);
 		break;
 	default:
 		ret = -EOPNOTSUPP;
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/litelink.c linux/drivers/net/irda/litelink.c
--- v2.3.34/linux/drivers/net/irda/litelink.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/net/irda/litelink.c	Tue Dec 21 10:17:31 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:   Sat Oct 30 20:24:58 1999
+ * Modified at:   Fri Dec 17 09:16:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -71,7 +71,7 @@
 static void litelink_open(dongle_t *self, struct qos_info *qos)
 {
 	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-	qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
+	qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
 
 	MOD_INC_USE_COUNT;
 }
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/old_belkin.c linux/drivers/net/irda/old_belkin.c
--- v2.3.34/linux/drivers/net/irda/old_belkin.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/old_belkin.c	Tue Dec 21 10:17:31 1999
@@ -0,0 +1,178 @@
+/*********************************************************************
+ *                
+ * Filename:      old_belkin.c
+ * Version:       1.1
+ * Description:   Driver for the Belkin (old) SmartBeam dongle
+ * Status:        Experimental...
+ * Author:        Jean Tourrilhes <jt@hpl.hp.com>
+ * Created at:    22/11/99
+ * Modified at:   Fri Dec 17 09:17:30 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Jean Tourrilhes, 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/module.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/irda.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irda_device.h>
+
+/*
+ * Belkin is selling a dongle called the SmartBeam.
+ * In fact, there is two hardware version of this dongle, of course with
+ * the same name and looking the exactly same (grrr...).
+ * I guess that I've got the old one, because inside I don't have
+ * a jumper for IrDA/ASK...
+ *
+ * As far as I can make it from info on their web site, the old dongle 
+ * support only 9600 b/s, which make our life much simpler as far as
+ * the driver is concerned, but you might not like it very much ;-)
+ * The new SmartBeam does 115 kb/s, and I've not tested it...
+ *
+ * Belkin claim that the correct driver for the old dongle (in Windows)
+ * is the generic Parallax 9500a driver, but the Linux LiteLink driver
+ * fails for me (probably because Linux-IrDA doesn't rate fallback),
+ * so I created this really dumb driver...
+ *
+ * In fact, this driver doesn't do much. The only thing it does is to
+ * prevent Linux-IrDA to use any other speed than 9600 b/s ;-) This
+ * driver is called "old_belkin" so that when the new SmartBeam is supported
+ * its driver can be called "belkin" instead of "new_belkin".
+ *
+ * Note : this driver was written without any info/help from Belkin,
+ * so a lot of info here might be totally wrong. Blame me ;-)
+ */
+
+/* Let's guess */
+#define MIN_DELAY 25      /* 15 us, but wait a little more to be sure */
+
+static void old_belkin_open(dongle_t *self, struct qos_info *qos);
+static void old_belkin_close(dongle_t *self);
+static int  old_belkin_change_speed(struct irda_task *task);
+static int  old_belkin_reset(struct irda_task *task);
+
+/* These are the baudrates supported */
+/* static __u32 baud_rates[] = { 9600 }; */
+
+static struct dongle_reg dongle = {
+	Q_NULL,
+	IRDA_OLD_BELKIN_DONGLE,
+	old_belkin_open,
+	old_belkin_close,
+	old_belkin_reset,
+	old_belkin_change_speed,
+};
+
+int __init old_belkin_init(void)
+{
+	return irda_device_register_dongle(&dongle);
+}
+
+void old_belkin_cleanup(void)
+{
+	irda_device_unregister_dongle(&dongle);
+}
+
+static void old_belkin_open(dongle_t *self, struct qos_info *qos)
+{
+	/* Not too fast, please... */
+	qos->baud_rate.bits &= IR_9600;
+	/* Needs at least 10 ms (totally wild guess, can do probably better) */
+	qos->min_turn_time.bits = 0x01;
+
+	MOD_INC_USE_COUNT;
+}
+
+static void old_belkin_close(dongle_t *self)
+{
+	/* Power off dongle */
+	self->set_dtr_rts(self->dev, FALSE, FALSE);
+
+	MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function old_belkin_change_speed (task)
+ *
+ *    With only one speed available, not much to do...
+ */
+static int old_belkin_change_speed(struct irda_task *task)
+{
+	irda_task_next_state(task, IRDA_TASK_DONE);
+
+	return 0;
+}
+
+/*
+ * Function old_belkin_reset (task)
+ *
+ *      Reset the Old-Belkin type dongle.
+ *
+ */
+static int old_belkin_reset(struct irda_task *task)
+{
+	dongle_t *self = (dongle_t *) task->instance;
+
+	/* Power on dongle */
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
+
+	/* Sleep a minimum of 15 us */
+	udelay(MIN_DELAY);
+
+	/* This dongles speed "defaults" to 9600 bps ;-) */
+	self->speed = 9600;
+
+	irda_task_next_state(task, IRDA_TASK_DONE);
+
+	return 0;
+}
+
+#ifdef MODULE
+MODULE_AUTHOR("Jean Tourrilhes <jt@hpl.hp.com>");
+MODULE_DESCRIPTION("Belkin (old) SmartBeam dongle driver");	
+
+/*
+ * Function init_module (void)
+ *
+ *    Initialize Old-Belkin module
+ *
+ */
+int init_module(void)
+{
+	return old_belkin_init();
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup Old-Belkin module
+ *
+ */
+void cleanup_module(void)
+{
+	old_belkin_cleanup();
+}
+#endif /* MODULE */
+
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c
--- v2.3.34/linux/drivers/net/irda/pc87108.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/irda/pc87108.c	Tue Dec 21 10:17:31 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:   Sat Nov 13 23:54:59 1999
+ * Modified at:   Thu Dec 16 00:54:27 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -36,7 +36,7 @@
  *         outb(bank, iobase+BSR);
  *
  *    If you find bugs in this file, its very likely that the same bug
- *    will also be in w83977af_ir.c since the implementations is quite
+ *    will also be in w83977af_ir.c since the implementations are quite
  *    similar.
  *     
  ********************************************************************/
@@ -121,6 +121,7 @@
 static int  pc87108_net_init(struct net_device *dev);
 static int  pc87108_net_open(struct net_device *dev);
 static int  pc87108_net_close(struct net_device *dev);
+static int  pc87108_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 
 /*
  * Function pc87108_init ()
@@ -267,6 +268,7 @@
 	dev->hard_start_xmit = pc87108_hard_xmit;
 	dev->open            = pc87108_net_open;
 	dev->stop            = pc87108_net_close;
+	dev->do_ioctl        = pc87108_net_ioctl;
 
 	rtnl_lock();
 	err = register_netdevice(dev);
@@ -304,12 +306,15 @@
 	/* Remove netdevice */
 	if (self->netdev) {
 		rtnl_lock();
-		unregister_netdev(self->netdev);
+		unregister_netdevice(self->netdev);
 		rtnl_unlock();
+		/* Must free the old-style 2.2.x device */
+		kfree(self->netdev);
 	}
 
 	/* Release the PORT that this driver is using */
-	IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", self->io.iobase);
+	IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", 
+		   self->io.iobase);
 	release_region(self->io.iobase, self->io.io_ext);
 
 	if (self->tx_buff.head)
@@ -389,7 +394,7 @@
 
 	dongle_id = pc87108_read_dongle_id(iobase);
 	IRDA_DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n", 
-	      dongle_types[dongle_id]);
+		   dongle_types[dongle_id]);
 	
 	/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
 	switch_bank(iobase, BANK0);	
@@ -550,7 +555,8 @@
 		outb(0x62, iobase+MCR);
 		break;
 	default: 
-		IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x", dongle_id);
+		IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x", 
+			   dongle_id);
 	}
 	
 	/* IRCFG1: IRSL1 and 2 are set to IrDA mode */
@@ -705,7 +711,8 @@
 		break;
 	default:
 		mcr = MCR_FIR;
-		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", 
+			   speed);
 		break;
 	}
 
@@ -856,7 +863,7 @@
 	/* Choose transmit DMA channel  */ 
 	switch_bank(iobase, BANK2);
 	outb(inb(iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, 
-	      iobase+ECR1);
+	     iobase+ECR1);
 	
 	/* Enable DMA */
  	switch_bank(iobase, BANK0);	
@@ -885,10 +892,12 @@
 
 	switch_bank(iobase, BANK0);
 	if (!(inb_p(iobase+LSR) & LSR_TXEMP)) {
-		IRDA_DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), warning, FIFO not empty yet!\n");
 
 		fifo_size -= 17;
-		IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+		IRDA_DEBUG(4, __FUNCTION__ "(), %d bytes left in tx fifo\n", 
+			   fifo_size);
 	}
 
 	/* Fill FIFO with current frame */
@@ -898,8 +907,8 @@
 	}
         
 	IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
-	      fifo_size, actual, len);
-
+		   fifo_size, actual, len);
+	
 	/* Restore bank */
 	outb(bank, iobase+BSR);
 
@@ -1189,6 +1198,14 @@
 		else { 
 			self->netdev->tbusy = 0; /* Unlock */
 			self->stats.tx_packets++;
+
+			/* Check if we need to change the speed? */
+			if (self->new_speed) {
+				IRDA_DEBUG(2, __FUNCTION__ 
+					   "(), Changing speed!\n");
+				pc87108_change_speed(self, self->new_speed);
+				self->new_speed = 0;
+			}
 			
 		        mark_bh(NET_BH);	
 
@@ -1420,7 +1437,8 @@
 	iobase = self->io.iobase;
 
 	if (request_irq(self->io.irq, pc87108_interrupt, 0, dev->name, 
-			 (void *) dev)) {
+			(void *) dev)) 
+	{
 		return -EAGAIN;
 	}
 	/*
@@ -1497,7 +1515,7 @@
 	switch_bank(iobase, BANK0);
 	outb(0, iobase+IER); 
        
-	free_irq(self->io.irq, self);
+	free_irq(self->io.irq, dev);
 	free_dma(self->io.dma);
 
 	/* Restore bank register */
@@ -1506,6 +1524,50 @@
 	MOD_DEC_USE_COUNT;
 
 	return 0;
+}
+
+/*
+ * Function pc87108_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+static int pc87108_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct pc87108 *self;
+	unsigned long flags;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		pc87108_change_speed(self, irq->ifr_baudrate);
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = pc87108_is_receiving(self);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c
--- v2.3.34/linux/drivers/net/irda/smc-ircc.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/irda/smc-ircc.c	Tue Dec 21 10:17:31 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Thomas Davis (tadavis@jps.net)
  * Created at:    
- * Modified at:   Fri Nov 12 21:08:09 1999
+ * Modified at:   Sat Dec 11 14:38:26 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Thomas Davis, All Rights Reserved.
@@ -68,12 +68,10 @@
 static int  ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
 static int  ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev);
 static void ircc_dma_write(struct ircc_cb *self, int iobase);
-static void ircc_change_speed(struct ircc_cb *self, __u32 speed);
+static void ircc_change_speed(void *priv, __u32 speed);
 static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void ircc_wait_until_sent(struct ircc_cb *self);
 static int  ircc_is_receiving(struct ircc_cb *self);
 
-static int  ircc_net_init(struct net_device *dev);
 static int  ircc_net_open(struct net_device *dev);
 static int  ircc_net_close(struct net_device *dev);
 
@@ -149,11 +147,10 @@
  */
 static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
 {
-        struct net_device *dev;
 	struct ircc_cb *self;
+        struct irport_cb *irport;
 	int config;
 	int ret;
-        int err;
 
 	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 
@@ -177,21 +174,30 @@
 	/* Need to store self somewhere */
 	dev_self[i] = self;
 
+	irport = irport_open(0, iobase2, config >> 4 & 0x0f);
+	if (!irport)
+		return -ENODEV;
+
+	/* Steal the network device from irport */
+	self->netdev = irport->netdev;
+	self->irport = irport;
+	irport->priv = self;
+
 	/* Initialize IO */
 	self->io.iobase    = iobase;
         self->io.iobase2   = iobase2; /* Used by irport */
         self->io.irq       = config >> 4 & 0x0f;
 	if (ircc_irq < 255) {
-	        printk(KERN_INFO "smc: Overriding IRQ - chip says %d, using %d\n",
-		      self->io.irq, ircc_irq);
+	        MESSAGE("smc_ircc: Overriding IRQ - chip says %d, using %d\n",
+			self->io.irq, ircc_irq);
 		self->io.irq = ircc_irq;
 	}
         self->io.io_ext    = CHIP_IO_EXTENT;
         self->io.io_ext2   = 8;       /* Used by irport */
         self->io.dma       = config & 0x0f;
 	if (ircc_dma < 255) {
-	        printk(KERN_INFO "smc: Overriding DMA - chip says %d, using %d\n",
-		      self->io.dma, ircc_dma);
+	        MESSAGE("smc: Overriding DMA - chip says %d, using %d\n",
+			self->io.dma, ircc_dma);
 		self->io.dma = ircc_dma;
 	}
         self->io.fifo_size = 16;
@@ -204,15 +210,8 @@
 		/* ircc_cleanup(self->self);  */
 		return -ENODEV;
 	}
-	ret = check_region(self->io.iobase2, self->io.io_ext2);
-	if (ret < 0) { 
-		IRDA_DEBUG(0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
-		       self->io.iobase2);
-		/* ircc_cleanup(self->self);  */
-		return -ENODEV;
-	}
+
 	request_region(self->io.iobase, self->io.io_ext, driver_name);
-        request_region(self->io.iobase2, self->io.io_ext2, driver_name);
 
 	/* Initialize QoS for this device */
 	irda_init_max_qos_capabilies(&self->qos);
@@ -227,10 +226,10 @@
 		IR_115200;
 #endif
 
-	self->qos.min_turn_time.bits = 0x07;
-	irda_qos_bits_to_value(&self->qos);
+	irport->qos.min_turn_time.bits = 0x07;
+	irda_qos_bits_to_value(&irport->qos);
 
-	self->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
+	irport->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
 	
 	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
 	self->rx_buff.truesize = 4000; 
@@ -259,31 +258,12 @@
 	self->tx_buff.data = self->tx_buff.head;
 	self->rx_buff.data = self->rx_buff.head;
 	
-	if (!(dev = dev_alloc("irda%d", &err))) {
-		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
-		return -ENOMEM;
-	}
+	/* Override the speed change function, since we must control it now */
+	irport->change_speed = &ircc_change_speed;
+	self->netdev->open  = &ircc_net_open;
+	self->netdev->stop = &ircc_net_close;
 
-	dev->priv = (void *) self;
-	self->netdev = dev;
-	
-	/* Override the network functions we need to use */
-	dev->init            = ircc_net_init;
-	dev->hard_start_xmit = ircc_hard_xmit;
-	dev->open            = ircc_net_open;
-	dev->stop            = ircc_net_close;
-
-	rtnl_lock();
-	err = register_netdevice(dev);
-	rtnl_unlock();
-	if (err) {
-		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
-		return -1;
-	}
-
-	MESSAGE("IrDA: Registered device %s\n", dev->name);
-
-	irport_start(&self->irport, iobase2);
+	irport_start(self->irport);
 
 	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
 	return 0;
@@ -306,14 +286,7 @@
 
         iobase = self->io.iobase;
 
-	irport_stop(&self->irport, self->io.iobase2);
-
-	/* Remove netdevice */
-	if (self->netdev) {
-		rtnl_lock();
-		unregister_netdev(self->netdev);
-		rtnl_unlock();
-	}
+	irport_close(self->irport);
 
 	register_bank(iobase, 0);
 	serial_out(iobase, UART_IER, 0);
@@ -331,12 +304,6 @@
 
 	release_region(self->io.iobase, self->io.io_ext);
 
-	if (self->io.iobase2) {
-		IRDA_DEBUG(ircc_debug, __FUNCTION__ ": releasing 0x%03x\n", 
-		       self->io.iobase2);
-		release_region(self->io.iobase2, self->io.io_ext2);
-	}
-
 	if (self->tx_buff.head)
 		kfree(self->tx_buff.head);
 	
@@ -394,14 +361,17 @@
  *    Change the speed of the device
  *
  */
-static void ircc_change_speed(struct ircc_cb *self, __u32 speed)
+static void ircc_change_speed(void *priv, __u32 speed)
 {
 	int iobase, ir_mode, select, fast; 
+	struct ircc_cb *self = (struct ircc_cb *) priv;
+	struct net_device *dev;
 
 	IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
 
 	ASSERT(self != NULL, return;);
 
+	dev = self->netdev;
 	iobase = self->io.iobase;
 
 	/* Update accounting for new speed */
@@ -420,8 +390,14 @@
 		serial_out(iobase, UART_IER, 0);
 		serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
 		serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
-		irport_start(&self->irport, self->io.iobase2);
-		__irport_change_speed(&self->irport, speed);
+
+		dev->hard_start_xmit = &irport_hard_xmit;
+
+		/* We must give the interrupt back to irport */
+		self->irport->interrupt = irport_interrupt;
+
+		irport_start(self->irport);
+		irport_change_speed(self->irport, speed);
 		return;
 		break;
 
@@ -429,22 +405,26 @@
 		ir_mode = UART_CFGA_IRDA_HDLC;
 		select = 0;
 		fast = 0;
-		IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 576000\n");
+		IRDA_DEBUG(ircc_debug, __FUNCTION__ 
+			   "(), handling baud of 576000\n");
 		break;
 	case 1152000:
 		ir_mode = UART_CFGA_IRDA_HDLC;
 		select = UART_1152;
 		fast = 0;
-		IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 1152000\n");
+		IRDA_DEBUG(ircc_debug, __FUNCTION__ 
+			   "(), handling baud of 1152000\n");
 		break;
 	case 4000000:
 		ir_mode = UART_CFGA_IRDA_4PPM;
 		select = 0;
 		fast = UART_LCR_A_FAST;
-		IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 4000000\n");
+		IRDA_DEBUG(ircc_debug, __FUNCTION__ 
+			   "(), handling baud of 4000000\n");
 		break;
 	default:
-		IRDA_DEBUG(0, __FUNCTION__ ": unknown baud rate of %d\n", speed);
+		IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", 
+			   speed);
 		return;
 	}
 
@@ -457,9 +437,15 @@
 	register_bank(iobase, 0);
 	serial_out(iobase, UART_IER, 0);
 	
-       	irport_stop(&self->irport, self->io.iobase2);
+       	irport_stop(self->irport);	
 
-	self->netdev->tbusy = 0;
+	/* Install FIR transmit handler */
+	dev->hard_start_xmit = &ircc_hard_xmit;
+
+	/* Need to steal the interrupt as well */
+	self->irport->interrupt = &ircc_interrupt;
+
+	dev->tbusy = 0;
 	
 	register_bank(iobase, 1);
 
@@ -493,13 +479,15 @@
  */
 static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+	struct irport_cb *irport;
 	struct ircc_cb *self;
 	int iobase;
 	int mtt;
 	__u32 speed;
 
 	IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
-	self = (struct ircc_cb *) dev->priv;
+	irport = (struct irport_cb *) dev->priv;
+	self = (struct ircc_cb *) irport->priv;
 
 	ASSERT(self != NULL, return 0;);
 
@@ -510,14 +498,7 @@
 
 	/* Check if we need to change the speed */
 	if ((speed = irda_get_speed(skb)) != self->io.speed)
-		ircc_change_speed(self, speed);
-
-	/* Use irport for SIR speeds */
-	if (self->io.speed <= 115200) {
-		IRDA_DEBUG(ircc_debug+1, __FUNCTION__ 
-			   ": calling irport_hard_xmit\n");
-		return irport_hard_xmit(skb, dev);
-	}
+		self->new_speed = speed;
 	
 	IRDA_DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len);
 
@@ -631,11 +612,17 @@
 
 	/* Check for underrrun! */
 	if (underrun) {
-		self->stats.tx_errors++;
-		self->stats.tx_fifo_errors++;		
+		self->irport->stats.tx_errors++;
+		self->irport->stats.tx_fifo_errors++;		
 	} else {
-		self->stats.tx_packets++;
-		self->stats.tx_bytes +=  self->tx_buff.len;
+		self->irport->stats.tx_packets++;
+		self->irport->stats.tx_bytes +=  self->tx_buff.len;
+	}
+
+	if (self->new_speed) {
+		ircc_change_speed(self, self->new_speed);
+		
+		self->new_speed = 0;
 	}
 
 	/* Unlock tx_buff and request another frame */
@@ -733,7 +720,7 @@
 	skb_put(skb, len);
 
 	memcpy(skb->data, self->rx_buff.data, len);
-	self->stats.rx_packets++;
+	self->irport->stats.rx_packets++;
 
 	skb->dev = self->netdev;
 	skb->mac.raw  = skb->data;
@@ -771,12 +758,6 @@
 	
 	self = (struct ircc_cb *) dev->priv;
 
-	if (self->io.speed <= 115200) {
-		IRDA_DEBUG(ircc_debug+1, __FUNCTION__ 
-		      ": routing interrupt to irport_interrupt\n");
-		return irport_interrupt(irq, dev_id, regs);
-	}
-
 	iobase = self->io.iobase;
 
 	dev->interrupt = 1;
@@ -823,23 +804,6 @@
 }
 
 /*
- * Function ircc_wait_until_sent (self)
- *
- *    This function should put the current thread to sleep until all data 
- *    have been sent, so it is safe to change the speed.
- */
-static void ircc_wait_until_sent(struct ircc_cb *self)
-{
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
-
-	/* Just delay 60 ms */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(MSECS_TO_JIFFIES(60));
-
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
-}
-
-/*
  * Function ircc_is_receiving (self)
  *
  *    Return TRUE is we are currently receiving a frame
@@ -865,26 +829,6 @@
 }
 
 /*
- * Function ircc_net_init (dev)
- *
- *    Initialize network device
- *
- */
-static int ircc_net_init(struct net_device *dev)
-{
-	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
-
-	/* Setup to be a normal IrDA network device driver */
-	irda_device_setup(dev);
-
-	/* Insert overrides below this line! */
-
-	IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
-	return 0;
-}
-
-
-/*
  * Function ircc_net_open (dev)
  *
  *    Start the device
@@ -892,22 +836,22 @@
  */
 static int ircc_net_open(struct net_device *dev)
 {
+	struct irport_cb *irport;
 	struct ircc_cb *self;
 	int iobase;
-	
+
 	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 	
 	ASSERT(dev != NULL, return -1;);
-	self = (struct ircc_cb *) dev->priv;
-	
+	irport = (struct irport_cb *) dev->priv;
+	self = (struct ircc_cb *) irport->priv;
+
 	ASSERT(self != NULL, return 0;);
 	
 	iobase = self->io.iobase;
 
-	if (request_irq(self->io.irq, ircc_interrupt, 0, dev->name, 
-			 (void *) dev)) {
-		return -EAGAIN;
-	}
+	irport_net_open(dev);
+
 	/*
 	 * Always allocate the DMA channel after the IRQ,
 	 * and clean up on failure.
@@ -916,17 +860,6 @@
 		free_irq(self->io.irq, dev);
 		return -EAGAIN;
 	}
-		
-	/* 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(dev, &self->qos);
 	
 	MOD_INC_USE_COUNT;
 
@@ -942,31 +875,24 @@
  */
 static int ircc_net_close(struct net_device *dev)
 {
+	struct irport_cb *irport;
 	struct ircc_cb *self;
 	int iobase;
 
 	IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
 	
 	ASSERT(dev != NULL, return -1;);
-	self = (struct ircc_cb *) dev->priv;
+	irport = (struct irport_cb *) dev->priv;
+	self = (struct ircc_cb *) irport->priv;
 	
 	ASSERT(self != NULL, return 0;);
 	
 	iobase = self->io.iobase;
 
-	/* Stop device */
-	dev->tbusy = 1;
-	dev->start = 0;
-
-	/* Stop and remove instance of IrLAP */
-	if (self->irlap)
-		irlap_close(self->irlap);
-	self->irlap = NULL;
+	irport_net_close(dev);
 
 	disable_dma(self->io.dma);
 
-	/* Disable interrupts */
-	free_irq(self->io.irq, dev);
 	free_dma(self->io.dma);
 
 	MOD_DEC_USE_COUNT;
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c
--- v2.3.34/linux/drivers/net/irda/tekram.c	Wed Oct 27 16:34:12 1999
+++ linux/drivers/net/irda/tekram.c	Tue Dec 21 10:17:31 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:   Mon Oct 18 23:25:44 1999
+ * Modified at:   Fri Dec 17 09:17:45 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -70,7 +70,7 @@
 	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
-	qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
+	qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */	
 	irda_qos_bits_to_value(qos);
 
 	MOD_INC_USE_COUNT;
@@ -83,6 +83,11 @@
 	/* Power off dongle */
 	self->set_dtr_rts(self->dev, FALSE, FALSE);
 
+	if (self->reset_task)
+		irda_task_delete(self->reset_task);
+	if (self->speed_task)
+		irda_task_delete(self->speed_task);
+
 	MOD_DEC_USE_COUNT;
 }
 
@@ -113,6 +118,12 @@
 
 	ASSERT(task != NULL, return -1;);
 
+	if (self->speed_task && self->speed_task != task) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+		return MSECS_TO_JIFFIES(10);
+	} else
+		self->speed_task = task;
+
 	switch (speed) {
 	default:
 	case 9600:
@@ -128,19 +139,12 @@
 		byte = TEKRAM_PW|TEKRAM_57600;
 		break;
 	case 115200:
-		byte = TEKRAM_PW|TEKRAM_115200;
+		byte = TEKRAM_115200;
 		break;
 	}
 
 	switch (task->state) {
 	case IRDA_TASK_INIT:
-		/* Lock dongle */
-		if (irda_lock((void *) &self->busy) == FALSE) {
-			IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
-			return MSECS_TO_JIFFIES(100);
-		}
-		irda_task_next_state(task, IRDA_TASK_CHILD_INIT);
-		break;
 	case IRDA_TASK_CHILD_INIT:		
 		/* 
 		 * Need to reset the dongle and go to 9600 bps before
@@ -166,7 +170,7 @@
 		self->set_dtr_rts(self->dev, TRUE, FALSE);
 	
 		/* Wait at least 7us */
-		udelay(10);
+		udelay(14);
 
 		/* Write control byte */
 		self->write(self->dev, &byte, 1);
@@ -174,19 +178,19 @@
 		irda_task_next_state(task, IRDA_TASK_WAIT);
 
 		/* Wait at least 100 ms */
-		ret = MSECS_TO_JIFFIES(100);
+		ret = MSECS_TO_JIFFIES(150);
 		break;
 	case IRDA_TASK_WAIT:
 		/* Set DTR, Set RTS */
 		self->set_dtr_rts(self->dev, TRUE, TRUE);
 
 		irda_task_next_state(task, IRDA_TASK_DONE);
-		self->busy = 0;
+		self->speed_task = NULL;
 		break;
 	default:
 		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
 		irda_task_next_state(task, IRDA_TASK_DONE);
-		self->busy = 0;
+		self->speed_task = NULL;
 		ret = -1;
 		break;
 	}
@@ -214,9 +218,16 @@
 	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(task != NULL, return -1;);
+
+	if (self->reset_task && self->reset_task != task) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+		return MSECS_TO_JIFFIES(10);
+	} else
+		self->reset_task = task;
 	
 	/* Power off dongle */
-	self->set_dtr_rts(self->dev, FALSE, FALSE);
+	//self->set_dtr_rts(self->dev, FALSE, FALSE);
+	self->set_dtr_rts(self->dev, TRUE, TRUE);
 
 	switch (task->state) {
 	case IRDA_TASK_INIT:
@@ -231,21 +242,23 @@
 
 		irda_task_next_state(task, IRDA_TASK_WAIT2);
 		
-		/* Should sleep 1 ms, but 10 should not do any harm */
-		ret = MSECS_TO_JIFFIES(10);
+		/* Should sleep 1 ms */
+		ret = MSECS_TO_JIFFIES(1);
 		break;
 	case IRDA_TASK_WAIT2:
 		/* Set DTR, Set RTS */
 		self->set_dtr_rts(self->dev, TRUE, TRUE);
 	
-		udelay(50);
+		/* Wait at least 50 us */
+		udelay(75);
 
 		irda_task_next_state(task, IRDA_TASK_DONE);
+		self->reset_task = NULL;
 		break;
 	default:
 		ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
 		irda_task_next_state(task, IRDA_TASK_DONE);		
-
+		self->reset_task = NULL;
 		ret = -1;
 	}
 	return ret;
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c
--- v2.3.34/linux/drivers/net/irda/toshoboe.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/irda/toshoboe.c	Tue Dec 21 10:17:31 1999
@@ -7,6 +7,8 @@
  * Status:        Experimental.
  * Author:        James McKenzie <james@fishsoup.dhs.org>
  * Created at:    Sat May 8  12:35:27 1999
+ * Modified:      Paul Bristow <paul.bristow@technologist.com>
+ * Modified:      Mon Nov 11 19:10:05 1999
  * 
  *     Copyright (c) 1999 James McKenzie, All Rights Reserved.
  *      
@@ -28,7 +30,7 @@
 /* an olivetti notebook which doesn't have FIR, a toshiba libretto, and */
 /* an hp printer, this works fine at 4MBPS with my HP printer */
 
-static char *rcsid = "$Id: toshoboe.c,v 1.9 1999/06/29 14:21:06 root Exp $";
+static char *rcsid = "$Id: toshoboe.c,v 1.91 1999/06/29 14:21:06 root Exp $";
 
 /* 
  * $Log: toshoboe.c,v $
@@ -65,7 +67,7 @@
 /* Toshiba's drivers do this, but it disables back to back tansfers */
 /* I think that the chip may have some problems certainly, I have */
 /* seen it jump over tasks in the taskfile->xmit with this turned on */
-#define ONETASK
+#define ONETASK 
 
 /* To adjust the number of tasks in use edit toshoboe.h */
 
@@ -84,7 +86,6 @@
 
 /* No user servicable parts below here */
 
-#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/kernel.h>
@@ -147,7 +148,7 @@
   unsigned long flags;
   IRDA_DEBUG (4, __FUNCTION__ "()\n");
 
-  printk (KERN_WARNING "ToshOboe: seting baud to %d\n", baud);
+  printk (KERN_WARNING "ToshOboe: setting baud to %d\n", baud);
 
   save_flags (flags);
   cli ();
@@ -206,6 +207,7 @@
   outb_p (0x80, OBOE_RST);
   outb_p (0x01, OBOE_REG_9);
 
+  self->io.speed = baud;
 }
 
 /* Wake the chip up and get it looking at the taskfile */
@@ -407,6 +409,7 @@
 
       if (self->new_speed) {
 	      toshoboe_setbaud(self, self->new_speed);
+
 	      self->new_speed = 0;
       }
       self->netdev->tbusy = 0; /* Unlock */
@@ -450,8 +453,6 @@
                       "(), memory squeeze, dropping frame.\n");
             }
 
-
-
           self->taskfile->recv[self->rxs].control = 0x83;
           self->taskfile->recv[self->rxs].len = 0x0;
 
@@ -486,16 +487,6 @@
 }
 
 static int
-toshoboe_is_receiving (struct toshoboe_cb *self)
-{
-  IRDA_DEBUG (4, __FUNCTION__ "()\n");
-
-/*FIXME Can't tell! */
-  return (FALSE);
-}
-
-
-static int
 toshoboe_net_init (struct net_device *dev)
 {
   IRDA_DEBUG (4, __FUNCTION__ "()\n");
@@ -625,7 +616,51 @@
 
 }
 
+/*
+ * Function toshoboe_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+static int toshoboe_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct toshoboe_cb *self;
+	unsigned long flags;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return -1;);
 
+	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		/* toshoboe_setbaud(self, irq->ifr_baudrate); */
+                /* Just change speed once - inserted by Paul Bristow */
+	        self->new_speed = irq->ifr_baudrate;
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = 0; /* Can't tell */
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
+}
 
 #ifdef MODULE
 
@@ -667,6 +702,8 @@
 	  rtnl_lock();
 	  unregister_netdevice(self->netdev);
 	  rtnl_unlock();
+	  /* Must free the old-style 2.2.x device */
+	  kfree(self->netdev);
   }
 
   kfree (self->taskfilebuf);
@@ -847,6 +884,7 @@
   dev->hard_start_xmit = toshoboe_hard_xmit;
   dev->open = toshoboe_net_open;
   dev->stop = toshoboe_net_close;
+  dev->do_ioctl = toshoboe_net_ioctl;
 
   rtnl_lock();
   err = register_netdevice(dev);
diff -u --recursive --new-file v2.3.34/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c
--- v2.3.34/linux/drivers/net/irda/w83977af_ir.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/irda/w83977af_ir.c	Tue Dec 21 10:17:31 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Wed Nov  4 11:46:16 1998
- * Modified at:   Mon Nov  8 10:05:48 1999
+ * Modified at:   Thu Dec 16 00:52:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -22,7 +22,7 @@
  *     and at no charge.
  *     
  *     If you find bugs in this file, its very likely that the same bug
- *     will also be in pc87108.c since the implementations is quite
+ *     will also be in pc87108.c since the implementations are quite
  *     similar.
  *
  *     Notice that all functions that needs to access the chip in _any_
@@ -62,22 +62,28 @@
 #include <net/irda/w83977af.h>
 #include <net/irda/w83977af_ir.h>
 
-#define CONFIG_NETWINDER                 /* Adjust to NetWinder differences */
-#undef  CONFIG_NETWINDER_TX_DMA_PROBLEMS /* Not needed */
-#define CONFIG_NETWINDER_RX_DMA_PROBLEMS /* Must have this one! */
-#undef  CONFIG_USE_INTERNAL_TIMER        /* Just cannot make that timer work */
-#define CONFIG_USE_W977_PNP              /* Currently needed */
+#ifdef  CONFIG_ARCH_VNC            /* Adjust to NetWinder differences */
+#undef  CONFIG_VNC_TX_DMA_PROBLEMS /* Not needed */
+#define CONFIG_VNC_RX_DMA_PROBLEMS /* Must have this one! */
+#endif
+#undef  CONFIG_USE_INTERNAL_TIMER  /* Just cannot make that timer work */
+#define CONFIG_USE_W977_PNP        /* Currently needed */
 #define PIO_MAX_SPEED       115200 
 
 static char *driver_name = "w83977af_ir";
-static int  qos_mtt_bits = 0x07;           /* 1 ms or more */
+static int  qos_mtt_bits = 0x07;   /* 1 ms or more */
 
 #define CHIP_IO_EXTENT 8
 
 static unsigned int io[] = { 0x180, ~0, ~0, ~0 };
+#ifdef CONFIG_ARCH_VNC             /* Adjust to NetWinder differences */
 static unsigned int irq[] = { 6, 0, 0, 0 };
-static unsigned int dma[] = 
-{ 1, 0, 0, 0 };
+#else
+static unsigned int irq[] = { 11, 0, 0, 0 };
+#endif
+static unsigned int dma[] = { 1, 0, 0, 0 };
+static unsigned int efbase[] = { W977_EFIO_BASE, W977_EFIO2_BASE };
+static unsigned int efio = W977_EFIO_BASE;
 
 static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL};
 
@@ -98,6 +104,7 @@
 static int  w83977af_net_init(struct net_device *dev);
 static int  w83977af_net_open(struct net_device *dev);
 static int  w83977af_net_close(struct net_device *dev);
+static int  w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 
 /*
  * Function w83977af_init ()
@@ -248,6 +255,7 @@
 	dev->hard_start_xmit = w83977af_hard_xmit;
 	dev->open            = w83977af_net_open;
 	dev->stop            = w83977af_net_close;
+	dev->do_ioctl        = w83977af_net_ioctl;
 
 	rtnl_lock();
 	err = register_netdev(dev);
@@ -278,21 +286,23 @@
 
 #ifdef CONFIG_USE_W977_PNP
 	/* enter PnP configuration mode */
-	w977_efm_enter();
+	w977_efm_enter(efio);
 
-	w977_select_device(W977_DEVICE_IR);
+	w977_select_device(W977_DEVICE_IR, efio);
 
 	/* Deactivate device */
-	w977_write_reg(0x30, 0x00);
+	w977_write_reg(0x30, 0x00, efio);
 
-	w977_efm_exit();
+	w977_efm_exit(efio);
 #endif /* CONFIG_USE_W977_PNP */
 
 	/* Remove netdevice */
 	if (self->netdev) {
 		rtnl_lock();
-		unregister_netdev(self->netdev);
+		unregister_netdevice(self->netdev);
 		rtnl_unlock();
+		/* Must free the old-style 2.2.x device */
+		kfree(self->netdev);
 	}
 
 	/* Release the PORT that this driver is using */
@@ -311,100 +321,103 @@
 	return 0;
 }
 
-/*
- * Function w83977af_probe (iobase, irq, dma)
- *
- *    Returns non-negative on success.
- *
- */
 int w83977af_probe( int iobase, int irq, int dma)
 {
-	int version;
-	
-	IRDA_DEBUG( 0, __FUNCTION__ "()\n");
+  	int version;
+	int i;
+  	
+ 	for (i=0; i < 2; i++) {
+ 		IRDA_DEBUG( 0, __FUNCTION__ "()\n");
 #ifdef CONFIG_USE_W977_PNP
-	/* Enter PnP configuration mode */
-	w977_efm_enter();
-
-	w977_select_device(W977_DEVICE_IR);
-
-	/* Configure PnP port, IRQ, and DMA channel */
-	w977_write_reg(0x60, (iobase >> 8) & 0xff);
-	w977_write_reg(0x61, (iobase) & 0xff);
-
-	w977_write_reg(0x70, irq);
-#ifdef CONFIG_NETWINDER
-	w977_write_reg(0x74, dma+1); /* Netwinder uses 1 higher than Linux */
+ 		/* Enter PnP configuration mode */
+		w977_efm_enter(efbase[i]);
+  
+ 		w977_select_device(W977_DEVICE_IR, efbase[i]);
+  
+ 		/* Configure PnP port, IRQ, and DMA channel */
+ 		w977_write_reg(0x60, (iobase >> 8) & 0xff, efbase[i]);
+ 		w977_write_reg(0x61, (iobase) & 0xff, efbase[i]);
+  
+ 		w977_write_reg(0x70, irq, efbase[i]);
+#ifdef CONFIG_ARCH_VNC
+		/* Netwinder uses 1 higher than Linux */
+ 		w977_write_reg(0x74, dma+1, efbase[i]);
 #else
-	w977_write_reg(0x74, dma);   
-#endif
-	w977_write_reg(0x75, 0x04);  /* Disable Tx DMA */
-	
-	/* Set append hardware CRC, enable IR bank selection */	
-	w977_write_reg(0xf0, APEDCRC|ENBNKSEL);
-
-	/* Activate device */
-	w977_write_reg(0x30, 0x01);
-
-	w977_efm_exit();
-#endif
- 	/* Disable Advanced mode */
- 	switch_bank(iobase, SET2);
- 	outb(iobase+2, 0x00);  
-
-	/* Turn on UART (global) interrupts */
-	switch_bank(iobase, SET0);
-	outb(HCR_EN_IRQ, iobase+HCR);
-	
-	/* Switch to advanced mode */
-	switch_bank(iobase, SET2);
-	outb(inb(iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1);
-
-	/* Set default IR-mode */
-	switch_bank(iobase, SET0);
-	outb(HCR_SIR, iobase+HCR);
-
-	/* Read the Advanced IR ID */
-	switch_bank(iobase, SET3);
-	version = inb(iobase+AUID);
-	
-	/* Should be 0x1? */
-	if (0x10 != (version & 0xf0)) {
-		IRDA_DEBUG( 0, __FUNCTION__ "(), Wrong chip version");	
-		return -1;
-	}
-	
-	/* Set FIFO size to 32 */
-	switch_bank(iobase, SET2);
-	outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
-	
-	/* Set FIFO threshold to TX17, RX16 */
-	switch_bank(iobase, SET0);	
-	outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO,iobase+UFR);
-
-	/* Receiver frame length */
-	switch_bank(iobase, SET4);
-	outb(2048 & 0xff, iobase+6);
-	outb((2048 >> 8) & 0x1f, iobase+7);
-
-	/* 
-	 * Init HP HSDL-1100 transceiver. 
-	 * 
-	 * Set IRX_MSL since we have 2 * receive paths IRRX, and
-	 * IRRXH. Clear IRSL0D since we want IRSL0 * to be a input pin used
-	 * for IRRXH 
-	 *
-	 *   IRRX  pin 37 connected to receiver 
-	 *   IRTX  pin 38 connected to transmitter
-	 *   FIRRX pin 39 connected to receiver      (IRSL0) 
-	 *   CIRRX pin 40 connected to pin 37
-	 */
-	switch_bank(iobase, SET7);
-	outb(0x40, iobase+7);
-		
-	IRDA_DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version);
-	
-	return 0;
+ 		w977_write_reg(0x74, dma, efbase[i]);   
+#endif /*CONFIG_ARCH_VNC */
+ 		w977_write_reg(0x75, 0x04, efbase[i]);  /* Disable Tx DMA */
+  	
+ 		/* Set append hardware CRC, enable IR bank selection */	
+ 		w977_write_reg(0xf0, APEDCRC|ENBNKSEL, efbase[i]);
+  
+ 		/* Activate device */
+ 		w977_write_reg(0x30, 0x01, efbase[i]);
+  
+ 		w977_efm_exit(efbase[i]);
+#endif /* CONFIG_USE_W977_PNP */
+  		/* Disable Advanced mode */
+  		switch_bank(iobase, SET2);
+  		outb(iobase+2, 0x00);  
+ 
+ 		/* Turn on UART (global) interrupts */
+ 		switch_bank(iobase, SET0);
+  		outb(HCR_EN_IRQ, iobase+HCR);
+  	
+  		/* Switch to advanced mode */
+  		switch_bank(iobase, SET2);
+  		outb(inb(iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1);
+  
+  		/* Set default IR-mode */
+  		switch_bank(iobase, SET0);
+  		outb(HCR_SIR, iobase+HCR);
+  
+  		/* Read the Advanced IR ID */
+  		switch_bank(iobase, SET3);
+  		version = inb(iobase+AUID);
+  	
+  		/* Should be 0x1? */
+  		if (0x10 == (version & 0xf0)) {
+ 			efio = efbase[i];
+ 
+ 			/* Set FIFO size to 32 */
+ 			switch_bank(iobase, SET2);
+ 			outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
+ 	
+ 			/* Set FIFO threshold to TX17, RX16 */
+ 			switch_bank(iobase, SET0);	
+ 			outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|
+			     UFR_EN_FIFO,iobase+UFR);
+ 
+ 			/* Receiver frame length */
+ 			switch_bank(iobase, SET4);
+			outb(2048 & 0xff, iobase+6);
+			outb((2048 >> 8) & 0x1f, iobase+7);
+
+			/* 
+			 * Init HP HSDL-1100 transceiver. 
+			 * 
+			 * Set IRX_MSL since we have 2 * receive paths IRRX, 
+			 * and IRRXH. Clear IRSL0D since we want IRSL0 * to 
+			 * be a input pin used for IRRXH 
+			 *
+			 *   IRRX  pin 37 connected to receiver 
+			 *   IRTX  pin 38 connected to transmitter
+			 *   FIRRX pin 39 connected to receiver      (IRSL0) 
+			 *   CIRRX pin 40 connected to pin 37
+			 */
+			switch_bank(iobase, SET7);
+			outb(0x40, iobase+7);
+			
+			MESSAGE("W83977AF (IR) driver loaded. "
+				"Version: 0x%02x\n", version);
+			
+			return 0;
+		} else {
+			/* Try next extented function register address */
+			IRDA_DEBUG( 0, __FUNCTION__ "(), Wrong chip version");
+		}
+  	}   	
+	return -1;
 }
 
 void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
@@ -576,7 +589,7 @@
 static void w83977af_dma_write(struct w83977af_ir *self, int iobase)
 {
 	__u8 set;
-#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
+#ifdef CONFIG_VNC_TX_DMA_PROBLEMS
 	unsigned long flags;
 	__u8 hcr;
 #endif
@@ -592,7 +605,7 @@
 	/* Choose transmit DMA channel  */ 
 	switch_bank(iobase, SET2);
 	outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1);
-#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
+#ifdef CONFIG_VNC_TX_DMA_PROBLEMS
 	save_flags(flags);
 	cli();
 
@@ -609,7 +622,7 @@
 	
 	/* Enable DMA */
  	switch_bank(iobase, SET0);
-#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
+#ifdef CONFIG_VNC_TX_DMA_PROBLEMS
 	hcr = inb(iobase+HCR);
 	outb(hcr | HCR_EN_DMA, iobase+HCR);
 	enable_dma(self->io.dma);
@@ -653,7 +666,7 @@
 	}
         
 	IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
-	       fifo_size, actual, len);
+		   fifo_size, actual, len);
 
 	/* Restore bank */
 	outb(set, iobase+SSR);
@@ -725,7 +738,7 @@
 {
 	int iobase;
 	__u8 set;
-#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
+#ifdef CONFIG_VNC_RX_DMA_PROBLEMS
 	unsigned long flags;
 	__u8 hcr;
 #endif
@@ -751,7 +764,7 @@
 	self->io.direction = IO_RECV;
 	self->rx_buff.data = self->rx_buff.head;
 
-#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
+#ifdef CONFIG_VNC_RX_DMA_PROBLEMS
 	save_flags(flags);
 	cli();
 
@@ -775,7 +788,7 @@
 	
 	/* Enable DMA */
 	switch_bank(iobase, SET0);
-#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
+#ifdef CONFIG_VNC_RX_DMA_PROBLEMS
 	hcr = inb(iobase+HCR);
 	outb(hcr | HCR_EN_DMA, iobase+HCR);
 	enable_dma(self->io.dma);
@@ -985,6 +998,14 @@
 			self->netdev->tbusy = 0; /* Unlock */
 			self->stats.tx_packets++;
 
+			/* Check if we need to change the speed? */
+			if (self->new_speed) {
+				IRDA_DEBUG(2, __FUNCTION__ 
+					   "(), Changing speed!\n");
+				w83977af_change_speed(self, self->new_speed);
+				self->new_speed = 0;
+			}
+
 			/* Schedule network layer */
 		        mark_bh(NET_BH);	
 
@@ -1207,7 +1228,7 @@
 	iobase = self->io.iobase;
 
 	if (request_irq(self->io.irq, w83977af_interrupt, 0, dev->name, 
-			 (void *) dev)) {
+			(void *) dev)) {
 		return -EAGAIN;
 	}
 	/*
@@ -1289,7 +1310,7 @@
 	switch_bank(iobase, SET0);
 	outb(0, iobase+ICR); 
 
-	free_irq(self->io.irq, self);
+	free_irq(self->io.irq, dev);
 	free_dma(self->io.dma);
 
 	/* Restore bank register */
@@ -1298,6 +1319,50 @@
 	MOD_DEC_USE_COUNT;
 
 	return 0;
+}
+
+/*
+ * Function w83977af_net_ioctl (dev, rq, cmd)
+ *
+ *    Process IOCTL commands for this device
+ *
+ */
+static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct w83977af_ir *self;
+	unsigned long flags;
+	int ret = 0;
+
+	ASSERT(dev != NULL, return -1;);
+
+	self = dev->priv;
+
+	ASSERT(self != NULL, return -1;);
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+	
+	/* Disable interrupts & save flags */
+	save_flags(flags);
+	cli();
+	
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		w83977af_change_speed(self, irq->ifr_baudrate);
+		break;
+	case SIOCSMEDIABUSY: /* Set media busy */
+		irda_device_set_media_busy(self->netdev, TRUE);
+		break;
+	case SIOCGRECEIVING: /* Check if we are receiving right now */
+		irq->ifr_receiving = w83977af_is_receiving(self);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+	}
+	
+	restore_flags(flags);
+	
+	return ret;
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.3.34/linux/drivers/net/myri_sbus.c linux/drivers/net/myri_sbus.c
--- v2.3.34/linux/drivers/net/myri_sbus.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/myri_sbus.c	Mon Dec 20 22:06:42 1999
@@ -1,10 +1,10 @@
 /* myri_sbus.h: MyriCOM MyriNET SBUS card driver.
  *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com)
  */
 
 static char *version =
-        "myri_sbus.c:v1.0 10/Dec/96 David S. Miller (davem@caipfs.rutgers.edu)\n";
+        "myri_sbus.c:v1.9 12/Sep/99 David S. Miller (davem@redhat.com)\n";
 
 #include <linux/module.h>
 
@@ -92,73 +92,79 @@
 static struct myri_eth *root_myri_dev = NULL;
 #endif
 
-static inline void myri_reset_off(struct lanai_regs *lp, struct myri_control *cregs)
+static void myri_reset_off(unsigned long lp, unsigned long cregs)
 {
-	lp->eimask = 0;			/* Clear IRQ mask.          */
-	cregs->ctrl = CONTROL_ROFF;	/* Turn RESET function off. */
+	/* Clear IRQ mask. */
+	sbus_writel(0, lp + LANAI_EIMASK);
+
+	/* Turn RESET function off. */
+	sbus_writel(CONTROL_ROFF, cregs + MYRICTRL_CTRL);
 }
 
-static inline void myri_reset_on(struct myri_control *cregs)
+static void myri_reset_on(unsigned long cregs)
 {
-	cregs->ctrl = CONTROL_RON;	/* Enable RESET function.   */
-	cregs->ctrl = CONTROL_DIRQ;	/* Disable IRQ's.           */
+	/* Enable RESET function. */
+	sbus_writel(CONTROL_RON, cregs + MYRICTRL_CTRL);
+
+	/* Disable IRQ's. */
+	sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
 }
 
-static inline void myri_disable_irq(struct lanai_regs *lp, struct myri_control *cregs)
+static void myri_disable_irq(unsigned long lp, unsigned long cregs)
 {
-	cregs->ctrl = CONTROL_DIRQ;
-	lp->eimask = 0;
-	lp->istat = ISTAT_HOST;
+	sbus_writel(CONTROL_DIRQ, cregs + MYRICTRL_CTRL);
+	sbus_writel(0, lp + LANAI_EIMASK);
+	sbus_writel(ISTAT_HOST, lp + LANAI_ISTAT);
 }
 
-static inline void myri_enable_irq(struct lanai_regs *lp, struct myri_control *cregs)
+static void myri_enable_irq(unsigned long lp, unsigned long cregs)
 {
-	cregs->ctrl = CONTROL_EIRQ;
-	lp->eimask = ISTAT_HOST;
+	sbus_writel(CONTROL_EIRQ, cregs + MYRICTRL_CTRL);
+	sbus_writel(ISTAT_HOST, lp + LANAI_EIMASK);
 }
 
 static inline void bang_the_chip(struct myri_eth *mp)
 {
 	struct myri_shmem *shmem	= mp->shmem;
-	struct myri_control *cregs	= mp->cregs;
+	unsigned long cregs		= mp->cregs;
 
-	shmem->send = 1;
-	cregs->ctrl = CONTROL_WON;
+	sbus_writel(1, &shmem->send);
+	sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
 }
 
-static inline int myri_do_handshake(struct myri_eth *mp)
+static int myri_do_handshake(struct myri_eth *mp)
 {
 	struct myri_shmem *shmem	= mp->shmem;
-	struct myri_control *cregs	= mp->cregs;
+	unsigned long cregs = mp->cregs;
 	struct myri_channel *chan	= &shmem->channel;
 	int tick 			= 0;
 
 	DET(("myri_do_handshake: "));
-	if(chan->state == STATE_READY) {
+	if (sbus_readl(&chan->state) == STATE_READY) {
 		DET(("Already STATE_READY, failed.\n"));
 		return -1;	/* We're hosed... */
 	}
 
 	myri_disable_irq(mp->lregs, cregs);
 
-	while(tick++ <= 25) {
-		unsigned int softstate;
+	while (tick++ <= 25) {
+		u32 softstate;
 
 		/* Wake it up. */
 		DET(("shakedown, CONTROL_WON, "));
-		shmem->shakedown = 1;
-		cregs->ctrl = CONTROL_WON;
+		sbus_writel(1, &shmem->shakedown);
+		sbus_writel(CONTROL_WON, cregs + MYRICTRL_CTRL);
 
-		softstate = chan->state;
+		softstate = sbus_readl(&chan->state);
 		DET(("chanstate[%08x] ", softstate));
-		if(softstate == STATE_READY) {
+		if (softstate == STATE_READY) {
 			DET(("wakeup successful, "));
 			break;
 		}
 
-		if(softstate != STATE_WFN) {
+		if (softstate != STATE_WFN) {
 			DET(("not WFN setting that, "));
-			chan->state = STATE_WFN;
+			sbus_writel(STATE_WFN, &chan->state);
 		}
 
 		udelay(20);
@@ -166,7 +172,7 @@
 
 	myri_enable_irq(mp->lregs, cregs);
 
-	if(tick > 25) {
+	if (tick > 25) {
 		DET(("25 ticks we lose, failure.\n"));
 		return -1;
 	}
@@ -174,9 +180,9 @@
 	return 0;
 }
 
-static inline int myri_load_lanai(struct myri_eth *mp)
+static int myri_load_lanai(struct myri_eth *mp)
 {
-	struct net_device		*dev = mp->dev;
+	struct net_device	*dev = mp->dev;
 	struct myri_shmem	*shmem = mp->shmem;
 	unsigned char		*rptr;
 	int 			i;
@@ -185,28 +191,30 @@
 	myri_reset_on(mp->cregs);
 
 	rptr = (unsigned char *) mp->lanai;
-	for(i = 0; i < mp->eeprom.ramsz; i++)
-		rptr[i] = 0;
+	for (i = 0; i < mp->eeprom.ramsz; i++)
+		sbus_writeb(0, &rptr[i]);
 
-	if(mp->eeprom.cpuvers >= CPUVERS_3_0)
-		mp->lregs->cval = mp->eeprom.cval;
+	if (mp->eeprom.cpuvers >= CPUVERS_3_0)
+		sbus_writel(mp->eeprom.cval, mp->lregs + LANAI_CVAL);
 
 	/* Load executable code. */
-	for(i = 0; i < sizeof(lanai4_code); i++)
-		rptr[(lanai4_code_off * 2) + i] = lanai4_code[i];
+	for (i = 0; i < sizeof(lanai4_code); i++)
+		sbus_writeb(lanai4_code[i], &rptr[(lanai4_code_off * 2) + i]);
 
 	/* Load data segment. */
-	for(i = 0; i < sizeof(lanai4_data); i++)
-		rptr[(lanai4_data_off * 2) + i] = lanai4_data[i];
+	for (i = 0; i < sizeof(lanai4_data); i++)
+		sbus_writeb(lanai4_data[i], &rptr[(lanai4_data_off * 2) + i]);
 
 	/* Set device address. */
-	shmem->addr[0] = shmem->addr[1] = 0;
-	for(i = 0; i < 6; i++)
-		shmem->addr[i + 2] = dev->dev_addr[i];
+	sbus_writeb(0, &shmem->addr[0]);
+	sbus_writeb(0, &shmem->addr[1]);
+	for (i = 0; i < 6; i++)
+		sbus_writeb(dev->dev_addr[i],
+			    &shmem->addr[i + 2]);
 
 	/* Set SBUS bursts and interrupt mask. */
-	shmem->burst = ((mp->myri_bursts & 0xf8) >> 3);
-	shmem->imask = SHMEM_IMASK_RX;
+	sbus_writel(((mp->myri_bursts & 0xf8) >> 3), &shmem->burst);
+	sbus_writel(SHMEM_IMASK_RX, &shmem->imask);
 
 	/* Release the LANAI. */
 	myri_disable_irq(mp->lregs, mp->cregs);
@@ -214,22 +222,22 @@
 	myri_disable_irq(mp->lregs, mp->cregs);
 
 	/* Wait for the reset to complete. */
-	for(i = 0; i < 5000; i++) {
-		if(shmem->channel.state != STATE_READY)
+	for (i = 0; i < 5000; i++) {
+		if (sbus_readl(&shmem->channel.state) != STATE_READY)
 			break;
 		else
 			udelay(10);
 	}
 
-	if(i == 5000)
-		printk("myricom: Chip would not reset after firmware load.\n");
+	if (i == 5000)
+		printk(KERN_ERR "myricom: Chip would not reset after firmware load.\n");
 
 	i = myri_do_handshake(mp);
-	if(i)
-		printk("myricom: Handshake with LANAI failed.\n");
+	if (i)
+		printk(KERN_ERR "myricom: Handshake with LANAI failed.\n");
 
-	if(mp->eeprom.cpuvers == CPUVERS_4_0)
-		mp->lregs->vers = 0;
+	if (mp->eeprom.cpuvers == CPUVERS_4_0)
+		sbus_writel(0, mp->lregs + LANAI_VERS);
 
 	return i;
 }
@@ -240,17 +248,31 @@
 	struct recvq *rq = mp->rq;
 	int i;
 
-	rq->tail = rq->head = 0;
-	for(i = 0; i < (RX_RING_SIZE+1); i++) {
-		if(mp->rx_skbs[i] != NULL) {
+	sbus_writel(0, &rq->tail);
+	sbus_writel(0, &rq->head);
+	for (i = 0; i < (RX_RING_SIZE+1); i++) {
+		if (mp->rx_skbs[i] != NULL) {
+			struct myri_rxd *rxd = &rq->myri_rxd[i];
+			u32 dma_addr;
+
+			dma_addr = sbus_readl(&rxd->myri_scatters[0].addr);
+			sbus_unmap_single(mp->myri_sdev, dma_addr, RX_ALLOC_SIZE);
 			dev_kfree_skb(mp->rx_skbs[i]);
 			mp->rx_skbs[i] = NULL;
 		}
 	}
 
-	mp->tx_old = sq->tail = sq->head = 0;
-	for(i = 0; i < TX_RING_SIZE; i++) {
-		if(mp->tx_skbs[i] != NULL) {
+	mp->tx_old = 0;
+	sbus_writel(0, &sq->tail);
+	sbus_writel(0, &sq->head);
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		if (mp->tx_skbs[i] != NULL) {
+			struct sk_buff *skb = mp->tx_skbs[i];
+			struct myri_txd *txd = &sq->myri_txd[i];
+			u32 dma_addr;
+
+			dma_addr = sbus_readl(&txd->myri_gathers[0].addr);
+			sbus_unmap_single(mp->myri_sdev, dma_addr, (skb->len + 3) & ~3);
 			dev_kfree_skb(mp->tx_skbs[i]);
 			mp->tx_skbs[i] = NULL;
 		}
@@ -265,25 +287,28 @@
 	int gfp_flags = GFP_KERNEL;
 	int i;
 
-	if(from_irq || in_interrupt())
+	if (from_irq || in_interrupt())
 		gfp_flags = GFP_ATOMIC;
 
 	myri_clean_rings(mp);
-	for(i = 0; i < RX_RING_SIZE; i++) {
+	for (i = 0; i < RX_RING_SIZE; i++) {
 		struct sk_buff *skb = myri_alloc_skb(RX_ALLOC_SIZE, gfp_flags);
+		u32 dma_addr;
 
-		if(!skb)
+		if (!skb)
 			continue;
 		mp->rx_skbs[i] = skb;
 		skb->dev = dev;
 		skb_put(skb, RX_ALLOC_SIZE);
-		rxd[i].myri_scatters[0].addr = sbus_dvma_addr(skb->data);
-		rxd[i].myri_scatters[0].len = RX_ALLOC_SIZE;
-		rxd[i].ctx = i;
-		rxd[i].num_sg = 1;
+
+		dma_addr = sbus_map_single(mp->myri_sdev, skb->data, RX_ALLOC_SIZE);
+		sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr);
+		sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len);
+		sbus_writel(i, &rxd[i].ctx);
+		sbus_writel(1, &rxd[i].num_sg);
 	}
-	rq->head = 0;
-	rq->tail = RX_RING_SIZE;
+	sbus_writel(0, &rq->head);
+	sbus_writel(RX_RING_SIZE, &rq->tail);
 }
 
 static int myri_init(struct myri_eth *mp, int from_irq)
@@ -323,19 +348,22 @@
 }
 #endif
 
-static inline void myri_tx(struct myri_eth *mp, struct net_device *dev)
+static void myri_tx(struct myri_eth *mp, struct net_device *dev)
 {
 	struct sendq *sq	= mp->sq;
 	int entry		= mp->tx_old;
-	int limit		= sq->head;
+	int limit		= sbus_readl(&sq->head);
 
 	DTX(("entry[%d] limit[%d] ", entry, limit));
-	if(entry == limit)
+	if (entry == limit)
 		return;
-	while(entry != limit) {
+	while (entry != limit) {
 		struct sk_buff *skb = mp->tx_skbs[entry];
+		u32 dma_addr;
 
 		DTX(("SKB[%d] ", entry));
+		dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr);
+		sbus_unmap_single(mp->myri_sdev, dma_addr, skb->len);
 		dev_kfree_skb(skb);
 		mp->tx_skbs[entry] = NULL;
 		mp->enet_stats.tx_packets++;
@@ -361,17 +389,17 @@
 	DHDR(("myri_type_trans: "));
 	dump_ehdr(eth);
 #endif
-	if(*eth->h_dest & 1) {
-		if(memcmp(eth->h_dest, dev->broadcast, ETH_ALEN)==0)
+	if (*eth->h_dest & 1) {
+		if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN)==0)
 			skb->pkt_type = PACKET_BROADCAST;
 		else
 			skb->pkt_type = PACKET_MULTICAST;
-	} else if(dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
-		if(memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
+	} else if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) {
+		if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
 			skb->pkt_type = PACKET_OTHERHOST;
 	}
 	
-	if(ntohs(eth->h_proto) >= 1536)
+	if (ntohs(eth->h_proto) >= 1536)
 		return eth->h_proto;
 		
 	rawp = skb->data;
@@ -388,36 +416,39 @@
 	return htons(ETH_P_802_2);
 }
 
-static inline void myri_rx(struct myri_eth *mp, struct net_device *dev)
+static void myri_rx(struct myri_eth *mp, struct net_device *dev)
 {
 	struct recvq *rq	= mp->rq;
 	struct recvq *rqa	= mp->rqack;
-	int entry		= rqa->head;
-	int limit		= rqa->tail;
+	int entry		= sbus_readl(&rqa->head);
+	int limit		= sbus_readl(&rqa->tail);
 	int drops;
 
 	DRX(("entry[%d] limit[%d] ", entry, limit));
-	if(entry == limit)
+	if (entry == limit)
 		return;
 	drops = 0;
 	DRX(("\n"));
-	while(entry != limit) {
+	while (entry != limit) {
 		struct myri_rxd *rxdack = &rqa->myri_rxd[entry];
-		unsigned int csum	= rxdack->csum;
-		int len			= rxdack->myri_scatters[0].len;
-		int index		= rxdack->ctx;
+		u32 csum		= sbus_readl(&rxdack->csum);
+		int len			= sbus_readl(&rxdack->myri_scatters[0].len);
+		int index		= sbus_readl(&rxdack->ctx);
 		struct myri_rxd *rxd	= &rq->myri_rxd[rq->tail];
 		struct sk_buff *skb	= mp->rx_skbs[index];
 
 		/* Ack it. */
-		rqa->head = NEXT_RX(entry);
+		sbus_writel(NEXT_RX(entry), &rqa->head);
 
 		/* Check for errors. */
 		DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum));
-		if((len < (ETH_HLEN + MYRI_PAD_LEN)) || (skb->data[0] != MYRI_PAD_LEN)) {
+		sbus_dma_sync_single(mp->myri_sdev,
+				     sbus_readl(&rxd->myri_scatters[0].addr),
+				     RX_ALLOC_SIZE);
+		if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) {
 			DRX(("ERROR["));
 			mp->enet_stats.rx_errors++;
-			if(len < (ETH_HLEN + MYRI_PAD_LEN)) {
+			if (len < (ETH_HLEN + MYRI_PAD_LEN)) {
 				DRX(("BAD_LENGTH] "));
 				mp->enet_stats.rx_length_errors++;
 			} else {
@@ -430,37 +461,38 @@
 			drops++;
 			DRX(("DROP "));
 			mp->enet_stats.rx_dropped++;
-			rxd->myri_scatters[0].addr = sbus_dvma_addr(skb->data);
-			rxd->myri_scatters[0].len = RX_ALLOC_SIZE;
-			rxd->ctx = index;
-			rxd->num_sg = 1;
-			rq->tail = NEXT_RX(rq->tail);
+			sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
+			sbus_writel(index, &rxd->ctx);
+			sbus_writel(1, &rxd->num_sg);
+			sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
 			goto next;
 		}
 
-#ifdef NEED_DMA_SYNCHRONIZATION
-		mmu_sync_dma(sbus_dvma_addr(skb->data),
-			     skb->len, mp->myri_sbus_dev->my_bus);
-#endif
-
 		DRX(("len[%d] ", len));
-		if(len > RX_COPY_THRESHOLD) {
+		if (len > RX_COPY_THRESHOLD) {
 			struct sk_buff *new_skb;
+			u32 dma_addr;
 
 			DRX(("BIGBUFF "));
 			new_skb = myri_alloc_skb(RX_ALLOC_SIZE, GFP_ATOMIC);
-			if(!new_skb) {
+			if (new_skb == NULL) {
 				DRX(("skb_alloc(FAILED) "));
 				goto drop_it;
 			}
+			sbus_unmap_single(mp->myri_sdev,
+					  sbus_readl(&rxd->myri_scatters[0].addr),
+					  RX_ALLOC_SIZE);
 			mp->rx_skbs[index] = new_skb;
 			new_skb->dev = dev;
 			skb_put(new_skb, RX_ALLOC_SIZE);
-			rxd->myri_scatters[0].addr = sbus_dvma_addr(new_skb->data);
-			rxd->myri_scatters[0].len = RX_ALLOC_SIZE;
-			rxd->ctx = index;
-			rxd->num_sg = 1;
-			rq->tail = NEXT_RX(rq->tail);
+			dma_addr = sbus_map_single(mp->myri_sdev,
+						   new_skb->data,
+						   RX_ALLOC_SIZE);
+			sbus_writel(dma_addr, &rxd->myri_scatters[0].addr);
+			sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
+			sbus_writel(index, &rxd->ctx);
+			sbus_writel(1, &rxd->num_sg);
+			sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
 
 			/* Trim the original skb for the netif. */
 			DRX(("trim(%d) ", len));
@@ -469,10 +501,11 @@
 			struct sk_buff *copy_skb = dev_alloc_skb(len);
 
 			DRX(("SMALLBUFF "));
-			if(!copy_skb) {
+			if (copy_skb == NULL) {
 				DRX(("dev_alloc_skb(FAILED) "));
 				goto drop_it;
 			}
+			/* DMA sync already done above. */
 			copy_skb->dev = dev;
 			DRX(("resv_and_put "));
 			skb_put(copy_skb, len);
@@ -480,11 +513,10 @@
 
 			/* Reuse original ring buffer. */
 			DRX(("reuse "));
-			rxd->myri_scatters[0].addr = sbus_dvma_addr(skb->data);
-			rxd->myri_scatters[0].len = RX_ALLOC_SIZE;
-			rxd->ctx = index;
-			rxd->num_sg = 1;
-			rq->tail = NEXT_RX(rq->tail);
+			sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len);
+			sbus_writel(index, &rxd->ctx);
+			sbus_writel(1, &rxd->num_sg);
+			sbus_writel(NEXT_RX(sbus_readl(&rq->tail)), &rq->tail);
 
 			skb = copy_skb;
 		}
@@ -508,28 +540,28 @@
 {
 	struct net_device *dev		= (struct net_device *) dev_id;
 	struct myri_eth *mp		= (struct myri_eth *) dev->priv;
-	struct lanai_regs *lregs	= mp->lregs;
+	unsigned long lregs		= mp->lregs;
 	struct myri_channel *chan	= &mp->shmem->channel;
-	unsigned int status;
+	u32 status;
 
-	status = lregs->istat;
+	status = sbus_readl(lregs + LANAI_ISTAT);
 	DIRQ(("myri_interrupt: status[%08x] ", status));
-	if(status & ISTAT_HOST) {
-		unsigned int softstate;
+	if (status & ISTAT_HOST) {
+		u32 softstate;
 
 		DIRQ(("IRQ_DISAB "));
 		myri_disable_irq(lregs, mp->cregs);
 		dev->interrupt = 1;
-		softstate = chan->state;
+		softstate = sbus_readl(&chan->state);
 		DIRQ(("state[%08x] ", softstate));
-		if(softstate != STATE_READY) {
+		if (softstate != STATE_READY) {
 			DIRQ(("myri_not_so_happy "));
 			myri_is_not_so_happy(mp);
 		}
 		DIRQ(("\nmyri_rx: "));
 		myri_rx(mp, dev);
 		DIRQ(("\nistat=ISTAT_HOST "));
-		lregs->istat = ISTAT_HOST;
+		sbus_writel(ISTAT_HOST, lregs + LANAI_ISTAT);
 		dev->interrupt = 0;
 		DIRQ(("IRQ_ENAB "));
 		myri_enable_irq(lregs, mp->cregs);
@@ -557,25 +589,25 @@
 	struct myri_eth *mp = (struct myri_eth *) dev->priv;
 	struct sendq *sq = mp->sq;
 	struct myri_txd *txd;
-	unsigned char *srcptr;
 	unsigned long flags;
 	unsigned int head, tail;
 	int len, entry;
+	u32 dma_addr;
 
 	DTX(("myri_start_xmit: "));
 
 	myri_tx(mp, dev);
 
-	if(dev->tbusy) {
+	if (dev->tbusy) {
 		int tickssofar = jiffies - dev->trans_start;
 
 		DTX(("tbusy tickssofar[%d] ", tickssofar));
-		if(tickssofar < 40) {
+		if (tickssofar < 40) {
 			DTX(("returning 1\n"));
 			return 1;
 		} else {
 			DTX(("resetting, return 0\n"));
-			printk("%s: transmit timed out, resetting\n", dev->name);
+			printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
 			mp->enet_stats.tx_errors++;
 			myri_init(mp, in_interrupt());
 			dev->tbusy = 0;
@@ -584,23 +616,17 @@
 		}
 	}
 
-	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
+	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
 		DTX(("tbusy, maybe a race? returning 1\n"));
 		printk("%s: Transmitter access conflict.\n", dev->name);
 		return 1;
 	}
 
-
-#ifdef NEED_DMA_SYNCHRONIZATION
-	mmu_sync_dma(sbus_dvma_addr(skb->data),
-		     skb->len, mp->myri_sbus_dev->my_bus);
-#endif
-
 	/* This is just to prevent multiple PIO reads for TX_BUFFS_AVAIL. */
-	head = sq->head;
-	tail = sq->tail;
+	head = sbus_readl(&sq->head);
+	tail = sbus_readl(&sq->tail);
 
-	if(!TX_BUFFS_AVAIL(head, tail)) {
+	if (!TX_BUFFS_AVAIL(head, tail)) {
 		DTX(("no buffs available, returning 1\n"));
 		return 1;
 	}
@@ -614,34 +640,39 @@
 
 	/* XXX Maybe this can go as well. */
 	len = skb->len;
-	if(len & 3) {
+	if (len & 3) {
 		DTX(("len&3 "));
 		len = (len + 4) & (~3);
 	}
 
-	entry = sq->tail;
+	entry = sbus_readl(&sq->tail);
 
 	txd = &sq->myri_txd[entry];
 	mp->tx_skbs[entry] = skb;
 
-	txd->myri_gathers[0].addr = sbus_dvma_addr(skb->data);
-	txd->myri_gathers[0].len = len;
-	txd->num_sg = 1;
-	txd->chan = KERNEL_CHANNEL;
-	txd->len = len;
-	txd->csum_off = ((unsigned int)-1);
-	txd->csum_field = 0;
-
-	srcptr = (((unsigned char *) skb->data) + MYRI_PAD_LEN);
-	if(srcptr[0] & 0x1) {
-		txd->addr[0] = txd->addr[1] = txd->addr[2] = txd->addr[3] = 0xffff;
+	/* Must do this before we sbus map it. */
+	if (skb->data[MYRI_PAD_LEN] & 0x1) {
+		sbus_writew(0xffff, &txd->addr[0]);
+		sbus_writew(0xffff, &txd->addr[1]);
+		sbus_writew(0xffff, &txd->addr[2]);
+		sbus_writew(0xffff, &txd->addr[3]);
 	} else {
-		txd->addr[0] = 0;
-		txd->addr[1] = (srcptr[0] << 8) | srcptr[1];
-		txd->addr[2] = (srcptr[2] << 8) | srcptr[3];
-		txd->addr[3] = (srcptr[4] << 8) | srcptr[5];
-	}
-	sq->tail = NEXT_TX(entry);
+		sbus_writew(0xffff, &txd->addr[0]);
+		sbus_writew((skb->data[0] << 8) | skb->data[1], &txd->addr[1]);
+		sbus_writew((skb->data[2] << 8) | skb->data[3], &txd->addr[2]);
+		sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]);
+	}
+
+	dma_addr = sbus_map_single(mp->myri_sdev, skb->data, len);
+	sbus_writel(dma_addr, &txd->myri_gathers[0].addr);
+	sbus_writel(len, &txd->myri_gathers[0].len);
+	sbus_writel(1, &txd->num_sg);
+	sbus_writel(KERNEL_CHANNEL, &txd->chan);
+	sbus_writel(len, &txd->len);
+	sbus_writel((u32)-1, &txd->csum_off);
+	sbus_writel(0, &txd->csum_field);
+
+	sbus_writel(NEXT_TX(entry), &sq->tail);
 	DTX(("BangTheChip "));
 	bang_the_chip(mp);
 
@@ -659,8 +690,8 @@
 static int myri_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
 		       void *daddr, void *saddr, unsigned len)
 {
-	struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
-	unsigned char *pad = (unsigned char *)skb_push(skb,MYRI_PAD_LEN);
+	struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
+	unsigned char *pad = (unsigned char *) skb_push(skb, MYRI_PAD_LEN);
 
 #ifdef DEBUG_HEADER
 	DHDR(("myri_header: pad[%02x,%02x] ", pad[0], pad[1]));
@@ -674,13 +705,13 @@
 	/* Set the protocol type. For a packet of type ETH_P_802_3 we put the length
 	 * in here instead. It is up to the 802.2 layer to carry protocol information.
 	 */
-	if(type != ETH_P_802_3) 
+	if (type != ETH_P_802_3) 
 		eth->h_proto = htons(type);
 	else
 		eth->h_proto = htons(len);
 
 	/* Set the source hardware address. */
-	if(saddr)
+	if (saddr)
 		memcpy(eth->h_source, saddr, dev->addr_len);
 	else
 		memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
@@ -688,12 +719,12 @@
 	/* Anyway, the loopback-device should never use this function... */
 	if (dev->flags & IFF_LOOPBACK) {
 		int i;
-		for(i = 0; i < dev->addr_len; i++)
+		for (i = 0; i < dev->addr_len; i++)
 			eth->h_dest[i] = 0;
 		return(dev->hard_header_len);
 	}
 	
-	if(daddr) {
+	if (daddr) {
 		memcpy(eth->h_dest, daddr, dev->addr_len);
 		return dev->hard_header_len;
 	}
@@ -706,8 +737,8 @@
  */
 static int myri_rebuild_header(struct sk_buff *skb)
 {
-	unsigned char *pad = (unsigned char *)skb->data;
-	struct ethhdr *eth = (struct ethhdr *)(pad + MYRI_PAD_LEN);
+	unsigned char *pad = (unsigned char *) skb->data;
+	struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
 	struct net_device *dev = skb->dev;
 
 #ifdef DEBUG_HEADER
@@ -742,8 +773,8 @@
 int myri_header_cache(struct neighbour *neigh, struct hh_cache *hh)
 {
 	unsigned short type = hh->hh_type;
-	unsigned char *pad = (unsigned char *)hh->hh_data;
-	struct ethhdr *eth = (struct ethhdr *)(pad + MYRI_PAD_LEN);
+	unsigned char *pad = (unsigned char *) hh->hh_data;
+	struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN);
 	struct net_device *dev = neigh->dev;
 
 	if (type == __constant_htons(ETH_P_802_3))
@@ -862,37 +893,36 @@
 }
 #endif
 
-static inline int myri_ether_init(struct net_device *dev, struct linux_sbus_device *sdev, int num)
+static int __init myri_ether_init(struct net_device *dev, struct sbus_dev *sdev, int num)
 {
 	static unsigned version_printed = 0;
 	struct myri_eth *mp;
-	unsigned char   prop_buf[32];
+	unsigned char prop_buf[32];
 	int i;
 
 	DET(("myri_ether_init(%p,%p,%d):\n", dev, sdev, num));
 	dev = init_etherdev(0, sizeof(struct myri_eth));
 
-	if(version_printed++ == 0)
+	if (version_printed++ == 0)
 		printk(version);
 
 	printk("%s: MyriCOM MyriNET Ethernet ", dev->name);
-	dev->base_addr = (long) sdev;
 
 	mp = (struct myri_eth *) dev->priv;
-	mp->myri_sbus_dev = sdev;
+	mp->myri_sdev = sdev;
 
 	/* Clean out skb arrays. */
-	for(i = 0; i < (RX_RING_SIZE + 1); i++)
+	for (i = 0; i < (RX_RING_SIZE + 1); i++)
 		mp->rx_skbs[i] = NULL;
 
-	for(i = 0; i < TX_RING_SIZE; i++)
+	for (i = 0; i < TX_RING_SIZE; i++)
 		mp->tx_skbs[i] = NULL;
 
 	/* First check for EEPROM information. */
 	i = prom_getproperty(sdev->prom_node, "myrinet-eeprom-info",
 			     (char *)&mp->eeprom, sizeof(struct myri_eeprom));
 	DET(("prom_getprop(myrinet-eeprom-info) returns %d\n", i));
-	if(i == 0 || i == -1) {
+	if (i == 0 || i == -1) {
 		/* No eeprom property, must cook up the values ourselves. */
 		DET(("No EEPROM: "));
 		mp->eeprom.bus_type = BUS_TYPE_SBUS;
@@ -901,38 +931,38 @@
 		mp->eeprom.ramsz = prom_getintdefault(sdev->prom_node,"sram_size",0);
 		DET(("cpuvers[%d] cval[%d] ramsz[%d]\n", mp->eeprom.cpuvers,
 		     mp->eeprom.cval, mp->eeprom.ramsz));
-		if(mp->eeprom.cpuvers == 0) {
+		if (mp->eeprom.cpuvers == 0) {
 			DET(("EEPROM: cpuvers was zero, setting to %04x\n",CPUVERS_2_3));
 			mp->eeprom.cpuvers = CPUVERS_2_3;
 		}
-		if(mp->eeprom.cpuvers < CPUVERS_3_0) {
+		if (mp->eeprom.cpuvers < CPUVERS_3_0) {
 			DET(("EEPROM: cpuvers < CPUVERS_3_0, clockval set to zero.\n"));
 			mp->eeprom.cval = 0;
 		}
-		if(mp->eeprom.ramsz == 0) {
+		if (mp->eeprom.ramsz == 0) {
 			DET(("EEPROM: ramsz == 0, setting to 128k\n"));
 			mp->eeprom.ramsz = (128 * 1024);
 		}
 		i = prom_getproperty(sdev->prom_node, "myrinet-board-id",
 				     &prop_buf[0], 10);
 		DET(("EEPROM: prom_getprop(myrinet-board-id) returns %d\n", i));
-		if((i != 0) && (i != -1))
+		if ((i != 0) && (i != -1))
 			memcpy(&mp->eeprom.id[0], &prop_buf[0], 6);
 		else
 			set_boardid_from_idprom(mp, num);
 		i = prom_getproperty(sdev->prom_node, "fpga_version",
 				     &mp->eeprom.fvers[0], 32);
 		DET(("EEPROM: prom_getprop(fpga_version) returns %d\n", i));
-		if(i == 0 || i == -1)
+		if (i == 0 || i == -1)
 			memset(&mp->eeprom.fvers[0], 0, 32);
 
-		if(mp->eeprom.cpuvers == CPUVERS_4_1) {
+		if (mp->eeprom.cpuvers == CPUVERS_4_1) {
 			DET(("EEPROM: cpuvers CPUVERS_4_1, "));
-			if(mp->eeprom.ramsz == (128 * 1024)) {
+			if (mp->eeprom.ramsz == (128 * 1024)) {
 				DET(("ramsize 128k, setting to 256k, "));
 				mp->eeprom.ramsz = (256 * 1024);
 			}
-			if((mp->eeprom.cval==0x40414041)||(mp->eeprom.cval==0x90449044)){
+			if ((mp->eeprom.cval==0x40414041)||(mp->eeprom.cval==0x90449044)){
 				DET(("changing cval from %08x to %08x ",
 				     mp->eeprom.cval, 0x50e450e4));
 				mp->eeprom.cval = 0x50e450e4;
@@ -944,7 +974,7 @@
 	dump_eeprom(mp);
 #endif
 
-	for(i = 0; i < 6; i++)
+	for (i = 0; i < 6; i++)
 		printk("%2.2x%c",
 		       dev->dev_addr[i] = mp->eeprom.id[i],
 		       i == 5 ? ' ' : ':');
@@ -953,45 +983,36 @@
 	determine_reg_space_size(mp);
 
 	/* Map in the MyriCOM register/localram set. */
-	prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0],
-			       sdev->num_registers, sdev);
-	if(mp->eeprom.cpuvers < CPUVERS_4_0) {
+	if (mp->eeprom.cpuvers < CPUVERS_4_0) {
 		/* XXX Makes no sense, if control reg is non-existant this
 		 * XXX driver cannot function at all... maybe pre-4.0 is
 		 * XXX only a valid version for PCI cards?  Ask feldy...
 		 */
 		DET(("Mapping regs for cpuvers < CPUVERS_4_0\n"));
-		mp->regs = (struct myri_regs *)
-			sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
-				       mp->reg_size, "MyriCOM Regs",
-				       sdev->reg_addrs[0].which_io, 0);
-		if(!mp->regs) {
+		mp->regs = sbus_ioremap(&sdev->resource[0], 0,
+					mp->reg_size, "MyriCOM Regs");
+		if (!mp->regs) {
 			printk("MyriCOM: Cannot map MyriCOM registers.\n");
 			return ENODEV;
 		}
-		mp->lanai = (unsigned short *) (((unsigned long)mp->regs) + (256*1024));
+		mp->lanai = (unsigned short *) (mp->regs + (256 * 1024));
 		mp->lanai3 = (unsigned int *) mp->lanai;
-		mp->lregs = (struct lanai_regs *) &mp->lanai[0x10000];
+		mp->lregs = (unsigned long) &mp->lanai[0x10000];
 	} else {
 		DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n"));
-		mp->cregs = (struct myri_control *)
-			sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
-				       PAGE_SIZE, "MyriCOM Control Regs",
-				       sdev->reg_addrs[0].which_io, 0);
-		mp->lregs = (struct lanai_regs *)
-			sparc_alloc_io(sdev->reg_addrs[0].phys_addr + (256 * 1024),
-				       0, PAGE_SIZE, "MyriCOM LANAI Regs",
-				       sdev->reg_addrs[0].which_io, 0);
+		mp->cregs = sbus_ioremap(&sdev->resource[0], 0,
+					 PAGE_SIZE, "MyriCOM Control Regs");
+		mp->lregs = sbus_ioremap(&sdev->resource[0], (256 * 1024),
+					 PAGE_SIZE, "MyriCOM LANAI Regs");
 		mp->lanai = (unsigned short *)
-			sparc_alloc_io(sdev->reg_addrs[0].phys_addr + (512 * 1024),
-				       0, mp->eeprom.ramsz, "MyriCOM SRAM",
-				       sdev->reg_addrs[0].which_io, 0);
+			sbus_ioremap(&sdev->resource[0], (512 * 1024),
+				     mp->eeprom.ramsz, "MyriCOM SRAM");
 		mp->lanai3 = (unsigned int *) mp->lanai;
 	}
-	DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p] lanai3[%p]\n",
+	DET(("Registers mapped: cregs[%lx] lregs[%lx] lanai[%p] lanai3[%p]\n",
 	     mp->cregs, mp->lregs, mp->lanai, mp->lanai3));
 
-	if(mp->eeprom.cpuvers >= CPUVERS_4_0)
+	if (mp->eeprom.cpuvers >= CPUVERS_4_0)
 		mp->shmem_base = 0xf000;
 	else
 		mp->shmem_base = 0x8000;
@@ -1017,22 +1038,22 @@
 	myri_reset_on(mp->cregs);
 
 	/* Get the supported DVMA burst sizes from our SBUS. */
-	mp->myri_bursts = prom_getintdefault(mp->myri_sbus_dev->my_bus->prom_node,
+	mp->myri_bursts = prom_getintdefault(mp->myri_sdev->bus->prom_node,
 					     "burst-sizes", 0x00);
 
-#if 1 /* XXX Until sun4m SBUS burst workaround is written. */
-	if(sparc_cpu_model == sun4m)
+	if (!sbus_can_burst64(sdev))
 		mp->myri_bursts &= ~(DMA_BURST64);
-#endif
+
 	DET(("MYRI bursts %02x\n", mp->myri_bursts));
 
 	/* Encode SBUS interrupt level in second control register. */
 	i = prom_getint(sdev->prom_node, "interrupts");
-	if(i == 0)
+	if (i == 0)
 		i = 4;
 	DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n",
 	     i, (1 << i)));
-	mp->cregs->irqlvl = (1 << i);
+
+	sbus_writel((1 << i), mp->cregs + MYRICTRL_IRQLVL);
 
 	mp->dev = dev;
 	dev->open = &myri_open;
@@ -1041,12 +1062,11 @@
 	dev->get_stats = &myri_get_stats;
 	dev->set_multicast_list = &myri_set_multicast;
 	dev->irq = sdev->irqs[0];
-	dev->dma = 0;
 
 	/* Register interrupt handler now. */
 	DET(("Requesting MYRIcom IRQ line.\n"));
-	if(request_irq(dev->irq, &myri_interrupt,
-		       SA_SHIRQ, "MyriCOM Ethernet", (void *) dev)) {
+	if (request_irq(dev->irq, &myri_interrupt,
+			SA_SHIRQ, "MyriCOM Ethernet", (void *) dev)) {
 		printk("MyriCOM: Cannot register interrupt handler.\n");
 		return ENODEV;
 	}
@@ -1074,31 +1094,42 @@
 	return 0;
 }
 
+static int __init myri_sbus_match(struct sbus_dev *sdev)
+{
+	char *name = sdev->prom_name;
+
+	if (!strcmp(name, "MYRICOM,mlanai") ||
+	    !strcmp(name, "myri"))
+		return 1;
+
+	return 0;
+}
+
 int __init myri_sbus_probe(void)
 {
 	struct net_device *dev = NULL;
-	struct linux_sbus *bus;
-	struct linux_sbus_device *sdev = 0;
+	struct sbus_bus *bus;
+	struct sbus_dev *sdev = 0;
 	static int called = 0;
 	int cards = 0, v;
 
-	if(called)
+	if (called)
 		return ENODEV;
 	called++;
 
 	for_each_sbus(bus) {
 		for_each_sbusdev(sdev, bus) {
-			if(cards) dev = NULL;
-			if(!strcmp(sdev->prom_name, "MYRICOM,mlanai") ||
-			   !strcmp(sdev->prom_name, "myri")) {
+			if (cards)
+				dev = NULL;
+			if (myri_sbus_match(sdev)) {
 				cards++;
 				DET(("Found myricom myrinet as %s\n", sdev->prom_name));
-				if((v = myri_ether_init(dev, sdev, (cards - 1))))
+				if ((v = myri_ether_init(dev, sdev, (cards - 1))))
 					return v;
 			}
 		}
 	}
-	if(!cards)
+	if (!cards)
 		return ENODEV;
 	return 0;
 }
@@ -1115,15 +1146,13 @@
 void
 cleanup_module(void)
 {
-	struct myri_eth *mp;
-
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_myri_dev) {
-		mp = root_myri_dev->next_module;
+		struct myri_eth *next = root_myri_dev->next_module;
 
 		unregister_netdev(root_myri_dev->dev);
 		kfree(root_myri_dev->dev);
-		root_myri_dev = mp;
+		root_myri_dev = next;
 	}
 }
 
diff -u --recursive --new-file v2.3.34/linux/drivers/net/myri_sbus.h linux/drivers/net/myri_sbus.h
--- v2.3.34/linux/drivers/net/myri_sbus.h	Wed Aug 18 11:36:45 1999
+++ linux/drivers/net/myri_sbus.h	Mon Dec 20 22:06:42 1999
@@ -6,52 +6,52 @@
 #ifndef _MYRI_SBUS_H
 #define _MYRI_SBUS_H
 
-struct lanai_regs {
-	volatile unsigned int	ipf0;		/* Context zero state registers.*/
-	volatile unsigned int	cur0;
-	volatile unsigned int	prev0;
-	volatile unsigned int	data0;
-	volatile unsigned int	dpf0;
-	volatile unsigned int	ipf1;		/* Context one state registers.	*/
-	volatile unsigned int	cur1;
-	volatile unsigned int	prev1;
-	volatile unsigned int	data1;
-	volatile unsigned int	dpf1;
-	volatile unsigned int	istat;		/* Interrupt status.		*/
-	volatile unsigned int	eimask;		/* External IRQ mask.		*/
-	volatile unsigned int	itimer;		/* IRQ timer.			*/
-	volatile unsigned int	rtc;		/* Real Time Clock		*/
-	volatile unsigned int	csum;		/* Checksum.			*/
-	volatile unsigned int	dma_xaddr;	/* SBUS DMA external address.	*/
-	volatile unsigned int	dma_laddr;	/* SBUS DMA local address.	*/
-	volatile unsigned int	dma_ctr;	/* SBUS DMA counter.		*/
-	volatile unsigned int	rx_dmaptr;	/* Receive DMA pointer.		*/
-	volatile unsigned int	rx_dmalim;	/* Receive DMA limit.		*/
-	volatile unsigned int	tx_dmaptr;	/* Transmit DMA pointer.	*/
-	volatile unsigned int	tx_dmalim;	/* Transmit DMA limit.		*/
-	volatile unsigned int	tx_dmalimt;	/* Transmit DMA limit w/tail.	*/
-	unsigned int	_unused0;
-	volatile unsigned char	rbyte;		/* Receive byte.		*/
-	unsigned char	_unused1[3];
-	volatile unsigned short	rhalf;		/* Receive half-word.		*/
-	unsigned char	_unused2[2];
-	volatile unsigned int	rword;		/* Receive word.		*/
-	volatile unsigned int	salign;		/* Send align.			*/
-	volatile unsigned int	ss_sendbyte;	/* SingleSend send-byte.	*/
-	volatile unsigned int	ss_sendhalf;	/* SingleSend send-halfword.	*/
-	volatile unsigned int	ss_sendword;	/* SingleSend send-word.	*/
-	volatile unsigned int	ss_sendt;	/* SingleSend special.		*/
-	volatile unsigned int	dma_dir;	/* DMA direction.		*/
-	volatile unsigned int	dma_stat;	/* DMA status.			*/
-	volatile unsigned int	timeo;		/* Timeout register.		*/
-	volatile unsigned int	myrinet;	/* XXX MAGIC myricom thing	*/
-	volatile unsigned int	hwdebug;	/* Hardware debugging reg.	*/
-	volatile unsigned int	leds;		/* LED control.			*/
-	volatile unsigned int	vers;		/* Version register.		*/
-	volatile unsigned int	link_on;	/* Link activation reg.		*/
-	unsigned int _unused3[0x17];
-	volatile unsigned int	cval;		/* Clock value register.	*/
-};
+/* LANAI Registers */
+#define LANAI_IPF0	0x00UL		/* Context zero state registers.*/
+#define LANAI_CUR0	0x04UL
+#define LANAI_PREV0	0x08UL
+#define LANAI_DATA0	0x0cUL
+#define LANAI_DPF0	0x10UL
+#define LANAI_IPF1	0x14UL		/* Context one state registers.	*/
+#define LANAI_CUR1	0x18UL
+#define LANAI_PREV1	0x1cUL
+#define LANAI_DATA1	0x20UL
+#define LANAI_DPF1	0x24UL
+#define LANAI_ISTAT	0x28UL		/* Interrupt status.		*/
+#define LANAI_EIMASK	0x2cUL		/* External IRQ mask.		*/
+#define LANAI_ITIMER	0x30UL		/* IRQ timer.			*/
+#define LANAI_RTC	0x34UL		/* Real Time Clock		*/
+#define LANAI_CSUM	0x38UL		/* Checksum.			*/
+#define LANAI_DMAXADDR	0x3cUL		/* SBUS DMA external address.	*/
+#define LANAI_DMALADDR	0x40UL		/* SBUS DMA local address.	*/
+#define LANAI_DMACTR	0x44UL		/* SBUS DMA counter.		*/
+#define LANAI_RXDMAPTR	0x48UL		/* Receive DMA pointer.		*/
+#define LANAI_RXDMALIM	0x4cUL		/* Receive DMA limit.		*/
+#define LANAI_TXDMAPTR	0x50UL		/* Transmit DMA pointer.	*/
+#define LANAI_TXDMALIM	0x54UL		/* Transmit DMA limit.		*/
+#define LANAI_TXDMALIMT	0x58UL		/* Transmit DMA limit w/tail.	*/
+	/* 0x5cUL, reserved */
+#define LANAI_RBYTE	0x60UL		/* Receive byte.		*/
+	/* 0x64-->0x6c, reserved */
+#define LANAI_RHALF	0x70UL		/* Receive half-word.		*/
+	/* 0x72UL, reserved */
+#define LANAI_RWORD	0x74UL		/* Receive word.		*/
+#define LANAI_SALIGN	0x78UL		/* Send align.			*/
+#define LANAI_SBYTE	0x7cUL		/* SingleSend send-byte.	*/
+#define LANAI_SHALF	0x80UL		/* SingleSend send-halfword.	*/
+#define LANAI_SWORD	0x84UL		/* SingleSend send-word.	*/
+#define LANAI_SSENDT	0x88UL		/* SingleSend special.		*/
+#define LANAI_DMADIR	0x8cUL		/* DMA direction.		*/
+#define LANAI_DMASTAT	0x90UL		/* DMA status.			*/
+#define LANAI_TIMEO	0x94UL		/* Timeout register.		*/
+#define LANAI_MYRINET	0x98UL		/* XXX MAGIC myricom thing	*/
+#define LANAI_HWDEBUG	0x9cUL		/* Hardware debugging reg.	*/
+#define LANAI_LEDS	0xa0UL		/* LED control.			*/
+#define LANAI_VERS	0xa4UL		/* Version register.		*/
+#define LANAI_LINKON	0xa8UL		/* Link activation reg.		*/
+	/* 0xac-->0x104, reserved */
+#define LANAI_CVAL	0x108UL		/* Clock value register.	*/
+#define LANAI_REG_SIZE	0x10cUL
 
 /* Interrupt status bits. */
 #define ISTAT_DEBUG	0x80000000
@@ -82,17 +82,17 @@
 #define ISTAT_RECV	0x00000002
 #define ISTAT_BRDY	0x00000001
 
-struct myri_regs {
-	volatile unsigned int	reset_off;
-	volatile unsigned int	reset_on;
-	volatile unsigned int	irq_off;
-	volatile unsigned int	irq_on;
-	volatile unsigned int	wakeup_off;
-	volatile unsigned int	wakeup_on;
-	volatile unsigned int	irq_read;
-	unsigned int _unused[0xfff9];
-	volatile unsigned short	local_mem[0x10800];
-};
+/* MYRI Registers */
+#define MYRI_RESETOFF	0x00UL
+#define MYRI_RESETON	0x04UL
+#define MYRI_IRQOFF	0x08UL
+#define MYRI_IRQON	0x0cUL
+#define MYRI_WAKEUPOFF	0x10UL
+#define MYRI_WAKEUPON	0x14UL
+#define MYRI_IRQREAD	0x18UL
+	/* 0x1c-->0x3ffc, reserved */
+#define MYRI_LOCALMEM	0x4000UL
+#define MYRI_REG_SIZE	0x25000UL
 
 /* Shared memory interrupt mask. */
 #define SHMEM_IMASK_RX		0x00000002
@@ -131,10 +131,10 @@
 #define CPUVERS_4_2		0x0402
 #define CPUVERS_5_0		0x0500
 
-struct myri_control {
-	volatile unsigned short	ctrl;
-	volatile unsigned short	irqlvl;
-};
+/* MYRI Control Registers */
+#define MYRICTRL_CTRL		0x00UL
+#define MYRICTRL_IRQLVL		0x02UL
+#define MYRICTRL_REG_SIZE	0x04UL
 
 /* Global control register defines. */
 #define CONTROL_ROFF		0x8000	/* Reset OFF.		*/
@@ -147,25 +147,25 @@
 #define MYRI_GATHER_ENTRIES	16
 
 struct myri_sglist {
-	unsigned int addr;
-	unsigned int len;
+	u32 addr;
+	u32 len;
 };
 
 struct myri_rxd {
 	struct myri_sglist myri_scatters[MYRI_SCATTER_ENTRIES];	/* DMA scatter list.*/
-	unsigned int csum;				/* HW computed checksum.    */
-	unsigned int ctx;
-	unsigned int num_sg;				/* Total scatter entries.   */
+	u32 csum;	/* HW computed checksum.    */
+	u32 ctx;
+	u32 num_sg;	/* Total scatter entries.   */
 };
 
 struct myri_txd {
 	struct myri_sglist myri_gathers[MYRI_GATHER_ENTRIES]; /* DMA scatter list.  */
-	unsigned int num_sg;				/* Total scatter entries.   */
-	unsigned short addr[4];				/* XXX address              */
-	unsigned int chan;
-	unsigned int len;				/* Total length of packet.  */
-	unsigned int csum_off;				/* Where data to csum is.   */
-	unsigned int csum_field;			/* Where csum goes in pkt.  */
+	u32 num_sg;	/* Total scatter entries.   */
+	u16 addr[4];	/* XXX address              */
+	u32 chan;
+	u32 len;	/* Total length of packet.  */
+	u32 csum_off;	/* Where data to csum is.   */
+	u32 csum_field;	/* Where csum goes in pkt.  */
 };
 
 #define MYRINET_MTU        8432
@@ -185,6 +185,7 @@
 /* GRRR... */
 static __inline__ int NEXT_RX(int num)
 {
+	/* XXX >=??? */
 	if(++num > RX_RING_SIZE)
 		num = 0;
 	return num;
@@ -206,44 +207,44 @@
 	 (head) - (tail) - 1)
 
 struct sendq {
-	unsigned int	tail;
-	unsigned int	head;
-	unsigned int	hdebug;
-	unsigned int	mdebug;
+	u32	tail;
+	u32	head;
+	u32	hdebug;
+	u32	mdebug;
 	struct myri_txd	myri_txd[TX_RING_MAXSIZE];
 };
 
 struct recvq {
-	unsigned int	head;
-	unsigned int	tail;
-	unsigned int	hdebug;
-	unsigned int	mdebug;
+	u32	head;
+	u32	tail;
+	u32	hdebug;
+	u32	mdebug;
 	struct myri_rxd	myri_rxd[RX_RING_MAXSIZE + 1];
 };
 
 #define MYRI_MLIST_SIZE 8
 
 struct mclist {
-	unsigned int maxlen;
-	unsigned int len;
-	unsigned int cache;
+	u32 maxlen;
+	u32 len;
+	u32 cache;
 	struct pair {
-		unsigned char addr[8];
-		unsigned int  val;
+		u8 addr[8];
+		u32 val;
 	} mc_pairs[MYRI_MLIST_SIZE];
-	unsigned char bcast_addr[8];
+	u8 bcast_addr[8];
 };
 
 struct myri_channel {
-	unsigned int	state;		/* State of the channel.	*/
-	unsigned int	busy;		/* Channel is busy.		*/
+	u32		state;		/* State of the channel.	*/
+	u32		busy;		/* Channel is busy.		*/
 	struct sendq	sendq;		/* Device tx queue.		*/
 	struct recvq	recvq;		/* Device rx queue.		*/
 	struct recvq	recvqa;		/* Device rx queue acked.	*/
-	unsigned int	rbytes;		/* Receive bytes.		*/
-	unsigned int	sbytes;		/* Send bytes.			*/
-	unsigned int	rmsgs;		/* Receive messages.		*/
-	unsigned int	smsgs;		/* Send messages.		*/
+	u32		rbytes;		/* Receive bytes.		*/
+	u32		sbytes;		/* Send bytes.			*/
+	u32		rmsgs;		/* Receive messages.		*/
+	u32		smsgs;		/* Send messages.		*/
 	struct mclist	mclist;		/* Device multicast list.	*/
 };
 
@@ -253,14 +254,14 @@
 #define STATE_READY	2		/* Ready.			*/
 
 struct myri_shmem {
-	unsigned char	addr[8];	/* Board's address.		*/
-	unsigned int	nchan;		/* Number of channels.		*/
-	unsigned int	burst;		/* SBUS dma burst enable.	*/
-	unsigned int	shakedown;	/* DarkkkkStarrr Crashesss...	*/
-	unsigned int	send;		/* Send wanted.			*/
-	unsigned int	imask;		/* Interrupt enable mask.	*/
-	unsigned int	mlevel;		/* Map level.			*/
-	unsigned int	debug[4];	/* Misc. debug areas.		*/
+	u8	addr[8];		/* Board's address.		*/
+	u32	nchan;			/* Number of channels.		*/
+	u32	burst;			/* SBUS dma burst enable.	*/
+	u32	shakedown;		/* DarkkkkStarrr Crashesss...	*/
+	u32	send;			/* Send wanted.			*/
+	u32	imask;			/* Interrupt enable mask.	*/
+	u32	mlevel;			/* Map level.			*/
+	u32	debug[4];		/* Misc. debug areas.		*/
 	struct myri_channel channel;	/* Only one channel on a host.	*/
 };
 
@@ -269,26 +270,26 @@
 	 * to obtain good cache hit rates.
 	 */
 	struct myri_shmem		*shmem;		/* Shared data structures.    */
-	struct myri_control		*cregs;		/* Control register space.    */
+	unsigned long			cregs;		/* Control register space.    */
 	struct recvq			*rqack;		/* Where we ack rx's.         */
 	struct recvq			*rq;		/* Where we put buffers.      */
 	struct sendq			*sq;		/* Where we stuff tx's.       */
-	struct net_device			*dev;		/* Linux/NET dev struct.      */
+	struct net_device		*dev;		/* Linux/NET dev struct.      */
 	int				tx_old;		/* To speed up tx cleaning.   */
-	struct lanai_regs		*lregs;		/* Quick ptr to LANAI regs.   */
+	unsigned long			lregs;		/* Quick ptr to LANAI regs.   */
 	struct sk_buff	       *rx_skbs[RX_RING_SIZE+1];/* RX skb's                   */
 	struct sk_buff	       *tx_skbs[TX_RING_SIZE];  /* TX skb's                   */
 	struct net_device_stats		enet_stats;	/* Interface stats.           */
 
 	/* These are less frequently accessed. */
-	struct myri_regs		*regs;          /* MyriCOM register space.    */
+	unsigned long			regs;          /* MyriCOM register space.    */
 	unsigned short			*lanai;		/* View 2 of register space.  */
 	unsigned int			*lanai3;	/* View 3 of register space.  */
 	unsigned int			myri_bursts;	/* SBUS bursts.               */
 	struct myri_eeprom		eeprom;		/* Local copy of EEPROM.      */
 	unsigned int			reg_size;	/* Size of register space.    */
 	unsigned int			shmem_base;	/* Offset to shared ram.      */
-	struct linux_sbus_device	*myri_sbus_dev;	/* Our SBUS device struct.    */
+	struct sbus_dev			*myri_sdev;	/* Our SBUS device struct.    */
 	struct myri_eth			*next_module;	/* Next in adapter chain.     */
 };
 
diff -u --recursive --new-file v2.3.34/linux/drivers/net/ptifddi.c linux/drivers/net/ptifddi.c
--- v2.3.34/linux/drivers/net/ptifddi.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/net/ptifddi.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: ptifddi.c,v 1.9 1999/08/20 00:31:07 davem Exp $
+/* $Id: ptifddi.c,v 1.11 1999/10/25 01:50:16 zaitcev Exp $
  * ptifddi.c: Network driver for Performance Technologies single-attach
  *            and dual-attach FDDI sbus cards.
  *
@@ -149,7 +149,7 @@
 {
 }
 
-static inline int pti_fddi_init(struct net_device *dev, struct linux_sbus_device *sdev, int num)
+static inline int pti_fddi_init(struct net_device *dev, struct sbus_dev *sdev, int num)
 {
 	static unsigned version_printed = 0;
 	struct ptifddi *pp;
@@ -160,34 +160,25 @@
 	if(version_printed++ == 0)
 		printk(version);
 
-	prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0],
-			       sdev->num_registers, sdev);
-
 	/* Register 0 mapping contains DPRAM. */
-	pp->dpram = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
-				   sdev->reg_addrs[0].reg_size,
-				   "PTI FDDI DPRAM",
-				   sdev->reg_addrs[0].which_io, 0);
+	pp->dpram = (struct dfddi_ram *) sbus_ioremap(
+	    &sdep->resource[0], 0, sizeof(sturct dfddi_ram), "PTI FDDI DPRAM");
 	if(!pp->dpram) {
 		printk("ptiFDDI: Cannot map DPRAM I/O area.\n");
 		return ENODEV;
 	}
 
 	/* Next, register 1 contains reset byte. */
-	pp->reset = sparc_alloc_io(sdev->reg_addrs[1].phys_addr, 0,
-				   sdev->reg_addrs[1].reg_size,
-				   "PTI FDDI RESET Byte",
-				   sdev->reg_addrs[1].which_io, 0);
+	pp->reset = (unsigned char *) sbus_ioremap(
+	    &sdep->resource[1], 0, 1, "PTI FDDI RESET Byte");
 	if(!pp->reset) {
 		printk("ptiFDDI: Cannot map RESET byte.\n");
 		return ENODEV;
 	}
 
 	/* Register 2 contains unreset byte. */
-	pp->unreset = sparc_alloc_io(sdev->reg_addrs[2].phys_addr, 0,
-				     sdev->reg_addrs[2].reg_size,
-				     "PTI FDDI UNRESET Byte",
-				     sdev->reg_addrs[2].which_io, 0);
+	pp->unreset = (unsigned char *) sbus_ioremap(
+	    &sdep->resource[2], 0, 1, "PTI FDDI UNRESET Byte");
 	if(!pp->unreset) {
 		printk("ptiFDDI: Cannot map UNRESET byte.\n");
 		return ENODEV;
@@ -215,8 +206,8 @@
 
 int __init ptifddi_sbus_probe(struct net_device *dev)
 {
-	struct linux_sbus *bus;
-	struct linux_sbus_device *sdev = 0;
+	struct sbus_bus *bus;
+	struct sbus_dev *sdev = 0;
 	static int called = 0;
 	int cards = 0, v;
 
diff -u --recursive --new-file v2.3.34/linux/drivers/net/sis900.c linux/drivers/net/sis900.c
--- v2.3.34/linux/drivers/net/sis900.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/net/sis900.c	Sat Dec 25 11:21:15 1999
@@ -1,6 +1,6 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
-   Silicon Integrated System Corporation 
-   Revision:	1.05	Aug 7 1999
+   Copyright 1999 Silicon Integrated System Corporation 
+   Revision:	1.06.03	Dec 23 1999
    
    Modified from the driver which is originally written by Donald Becker. 
    
@@ -18,6 +18,9 @@
    preliminary Rev. 1.0 Jan. 18, 1998
    http://www.sis.com.tw/support/databook.htm
    
+   Rev 1.06.03 Dec. 23 1999 Ollie Lho Third release
+   Rev 1.06.02 Nov. 23 1999 Ollie Lho bug in mac probing fixed 
+   Rev 1.06.01 Nov. 16 1999 Ollie Lho CRC calculation provide by Joseph Zbiciak (im14u2c@primenet.com)
    Rev 1.06 Nov. 4 1999 Ollie Lho (ollie@sis.com.tw) Second release
    Rev 1.05.05 Oct. 29 1999 Ollie Lho (ollie@sis.com.tw) Single buffer Tx/Rx  
    Chin-Shan Li (lcs@sis.com.tw) Added AMD Am79c901 HomePNA PHY support
@@ -47,7 +50,7 @@
 #include "sis900.h"
 
 static const char *version =
-"sis900.c: v1.06  11/04/99\n";
+"sis900.c: v1.06.03  12/23/99\n";
 
 static int max_interrupt_work = 20;
 #define sis900_debug debug
@@ -221,6 +224,8 @@
 	if (did_version++ == 0)
 		printk(KERN_INFO "%s", version);
 
+	if ((net_dev = init_etherdev(net_dev, 0)) == NULL)
+		return NULL;
 	/* check to see if we have sane EEPROM */
 	signature = (u16) read_eeprom(ioaddr, EEPROMSignature);    
 	if (signature == 0xffff || signature == 0x0000) {
@@ -229,9 +234,6 @@
 		return NULL;
 	}
 
-	if ((net_dev = init_etherdev(net_dev, 0)) == NULL)
-		return NULL;
-
 	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", net_dev->name, mac->name,
 	       ioaddr, irq);
 
@@ -509,7 +511,7 @@
 	net_dev->start = 1;
 
 	/* Enable all known interrupts by setting the interrupt mask. */
-	outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxOK), ioaddr + imr);
+	outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
 	outl(RxENA, ioaddr + cr);
 	outl(IE, ioaddr + ier);
 
@@ -787,6 +789,7 @@
 {
 	struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
 	long ioaddr = net_dev->base_addr;
+	int i;
 
 	printk(KERN_INFO "%s: Transmit timeout, status %8.8x %8.8x \n",
 	       net_dev->name, inl(ioaddr + cr), inl(ioaddr + isr));
@@ -794,14 +797,26 @@
 	/* Disable interrupts by clearing the interrupt mask. */
 	outl(0x0000, ioaddr + imr);
 
-	sis_priv->cur_rx = 0;
+	/* discard unsent packets, should this code section be protected by
+	   cli(), sti() ?? */
+	sis_priv->dirty_tx = sis_priv->cur_tx = 0;
+	for (i = 0; i < NUM_TX_DESC; i++) {
+		if (sis_priv->tx_skbuff[i] != NULL) {
+			dev_kfree_skb(sis_priv->tx_skbuff[i]);
+			sis_priv->tx_skbuff[i] = 0;
+			sis_priv->tx_ring[i].cmdsts = 0;
+			sis_priv->tx_ring[i].bufptr = 0;
+			sis_priv->stats.tx_dropped++;
+		}
+	}
+
 	net_dev->trans_start = jiffies;
-	sis_priv->stats.tx_errors++;
+	net_dev->tbusy = sis_priv->tx_full = 0;
 
 	/* FIXME: Should we restart the transmission thread here  ?? */
 
 	/* Enable all known interrupts by setting the interrupt mask. */
-	outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxOK), ioaddr + imr);
+	outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
 	return;
 }
 
@@ -876,13 +891,7 @@
 	do {
 		status = inl(ioaddr + isr);
 		
-		if (sis900_debug > 3)
-			printk(KERN_INFO "%s: entering interrupt, "
-			       "original status = %#8.8x, "
-			       "new status = %#8.8x.\n",
-			       net_dev->name, status, inl(ioaddr + isr));
-
-		if ((status & (HIBERR|TxURN|TxERR|TxOK|RxORN|RxERR|RxOK)) == 0)
+		if ((status & (HIBERR|TxURN|TxERR|TxIDLE|RxORN|RxERR|RxOK)) == 0)
 			/* nothing intresting happened */
 			break;
 
@@ -891,7 +900,7 @@
 			/* Rx interrupt */
 			sis900_rx(net_dev);
 
-		if (status & (TxURN | TxERR | TxOK))
+		if (status & (TxURN | TxERR | TxIDLE))
 			/* Tx interrupt */
 			sis900_finish_xmit(net_dev);
 
@@ -961,6 +970,9 @@
 		} else {
 			struct sk_buff * skb;
 			
+			/* This situation should never happen, but due to
+			   some unknow bugs, it is possible that
+			   we are working on NULL sk_buff :-( */			
 			if (sis_priv->rx_skbuff[entry] == NULL) {
 				printk(KERN_INFO "%s: NULL pointer " 
 				       "encountered in Rx ring, skipping\n",
@@ -1033,7 +1045,9 @@
 		tx_status = sis_priv->tx_ring[entry].cmdsts;
 		
 		if (tx_status & OWN) {
-			/* The packet is not transmited yet (owned by hardware) ! */
+			/* The packet is not transmited yet (owned by hardware) !
+			   Note: the interrupt is generated only when Tx Machine
+			   is idle, so this is an almost impossible case */
 			break;
 		}
 		
@@ -1054,8 +1068,6 @@
 				sis_priv->stats.tx_window_errors++;
 		} else {
 			/* packet successfully transmited */
-			if (sis900_debug > 3)
-				printk(KERN_INFO "Tx Transmit OK\n");
 			sis_priv->stats.collisions += (tx_status & COLCNT) >> 16;
 			sis_priv->stats.tx_bytes += tx_status & DSIZE;
 			sis_priv->stats.tx_packets++;
@@ -1069,8 +1081,8 @@
 	
 	if (sis_priv->tx_full && net_dev->tbusy && 
 	    sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) {
-		/* The ring is no longer full, clear tbusy, tx_full and schedule 
-		   more transmission by marking NET_BH */
+		/* The ring is no longer full, clear tbusy, tx_full and
+		   schedule more transmission by marking NET_BH */
 		sis_priv->tx_full = 0;
 		clear_bit(0, (void *)&net_dev->tbusy);
 		mark_bh(NET_BH);
@@ -1153,11 +1165,13 @@
 {
 
 /* what is the correct value of the POLYNOMIAL ??
-   Donald Becker use 0x04C11DB7U */
-#define POLYNOMIAL 0x04C11DB6L
+   Donald Becker use 0x04C11DB7U
+   Joseph Zbiciak im14u2c@primenet.com gives me the
+   correct answer, thank you Joe !! */
+#define POLYNOMIAL 0x04C11DB7L
 	u32 crc = 0xffffffff, msb;
 	int  i, j;
-	u8  byte;
+	u32  byte;
 
 	for (i = 0; i < 6; i++) {
 		byte = *addr++;
@@ -1166,7 +1180,6 @@
 			crc <<= 1;
 			if (msb ^ (byte & 1)) {
 				crc ^= POLYNOMIAL;
-				crc |= 1;
 			}
 			byte >>= 1;
 		}
@@ -1208,7 +1221,7 @@
 
 	/* update Multicast Hash Table in Receive Filter */
 	for (i = 0; i < 8; i++) {
-		/* why plus 0x04 ??, I don't know, UNDOCUMENT FEATURE ?? */
++               /* why plus 0x04 ??, That makes the correct value for hash table. */
 		outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr);
 		outl(mc_filter[i], ioaddr + rfdr);
 	}
diff -u --recursive --new-file v2.3.34/linux/drivers/net/sis900.h linux/drivers/net/sis900.h
--- v2.3.34/linux/drivers/net/sis900.h	Sun Nov  7 16:37:34 1999
+++ linux/drivers/net/sis900.h	Sat Dec 25 11:21:15 1999
@@ -92,8 +92,8 @@
 
 /* recevie FIFO thresholds */
 #define RxDRNT_shift     1
-#define RxDRNT_100	24	/* 3/4 FIFO size */
-#define RxDRNT_10		16 	/* 1/2 FIFO size */
+#define RxDRNT_100	16	/* 1/2 FIFO size */
+#define RxDRNT_10		24 	/* 3/4 FIFO size */
 
 enum sis900_reveive_config_register_bits {
 	RxAEP  = 0x80000000, RxARP = 0x40000000, RxATX = 0x10000000,
diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunbmac.c linux/drivers/net/sunbmac.c
--- v2.3.34/linux/drivers/net/sunbmac.c	Thu Nov 11 20:11:42 1999
+++ linux/drivers/net/sunbmac.c	Mon Dec 20 22:06:42 1999
@@ -1,10 +1,11 @@
-/* sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters.
+/* $Id: sunbmac.c,v 1.12 1999/12/15 14:07:58 davem Exp $
+ * sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters.
  *
- * Copyright (C) 1997, 1998 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
  */
 
 static char *version =
-        "sunbmac.c:v1.1 8/Dec/98 David S. Miller (davem@caipfs.rutgers.edu)\n";
+        "sunbmac.c:v1.9 11/Sep/99 David S. Miller (davem@redhat.com)\n";
 
 #include <linux/module.h>
 
@@ -70,84 +71,87 @@
 
 #define QEC_RESET_TRIES 200
 
-static inline int qec_global_reset(struct qe_globreg *gregs)
+static int qec_global_reset(unsigned long gregs)
 {
 	int tries = QEC_RESET_TRIES;
 
-	gregs->ctrl = GLOB_CTRL_RESET;
-	while(--tries) {
-		if(gregs->ctrl & GLOB_CTRL_RESET) {
+	sbus_writel(GLOB_CTRL_RESET, gregs + GLOB_CTRL);
+	while (--tries) {
+		if (sbus_readl(gregs + GLOB_CTRL) & GLOB_CTRL_RESET) {
 			udelay(20);
 			continue;
 		}
 		break;
 	}
-	if(tries)
+	if (tries)
 		return 0;
-	printk("BigMAC: Cannot reset the QEC.\n");
+	printk(KERN_ERR "BigMAC: Cannot reset the QEC.\n");
 	return -1;
 }
 
 static void qec_init(struct bigmac *bp)
 {
-	struct qe_globreg *gregs = bp->gregs;
-	struct linux_sbus_device *qec_sdev = bp->qec_sbus_dev;
-	unsigned char bsizes = bp->bigmac_bursts;
-	unsigned int regval;
+	unsigned long gregs = bp->gregs;
+	struct sbus_dev *qec_sdev = bp->qec_sdev;
+	u8 bsizes = bp->bigmac_bursts;
+	u32 regval;
 
 	/* 64byte bursts do not work at the moment, do
 	 * not even try to enable them.  -DaveM
 	 */
-	if(bsizes & DMA_BURST32)
+	if (bsizes & DMA_BURST32)
 		regval = GLOB_CTRL_B32;
 	else
 		regval = GLOB_CTRL_B16;
-	gregs->ctrl = regval | GLOB_CTRL_BMODE;
-
-	gregs->psize = GLOB_PSIZE_2048;
+	sbus_writel(regval | GLOB_CTRL_BMODE, gregs + GLOB_CTRL);
+	sbus_writel(GLOB_PSIZE_2048, gregs + GLOB_PSIZE);
 
 	/* All of memsize is given to bigmac. */
-	gregs->msize = qec_sdev->reg_addrs[1].reg_size;
+	sbus_writel(qec_sdev->reg_addrs[1].reg_size,
+		    gregs + GLOB_MSIZE);
 
 	/* Half to the transmitter, half to the receiver. */
-	gregs->rsize = gregs->tsize = qec_sdev->reg_addrs[1].reg_size >> 1;
+	sbus_writel(qec_sdev->reg_addrs[1].reg_size >> 1,
+		    gregs + GLOB_TSIZE);
+	sbus_writel(qec_sdev->reg_addrs[1].reg_size >> 1,
+		    gregs + GLOB_RSIZE);
 }
 
-/* XXX auto negotiation on these things might not be pleasant... */
-
 #define TX_RESET_TRIES     32
 #define RX_RESET_TRIES     32
 
-static inline void bigmac_tx_reset(struct BIG_MAC_regs *bregs)
+static void bigmac_tx_reset(unsigned long bregs)
 {
 	int tries = TX_RESET_TRIES;
 
-	bregs->tx_cfg = 0;
+	sbus_writel(0, bregs + BMAC_TXCFG);
 
 	/* The fifo threshold bit is read-only and does
 	 * not clear.  -DaveM
 	 */
-	while((bregs->tx_cfg & ~(BIGMAC_TXCFG_FIFO)) != 0 &&
-	      --tries != 0)
+	while ((sbus_readl(bregs + BMAC_TXCFG) & ~(BIGMAC_TXCFG_FIFO)) != 0 &&
+	       --tries != 0)
 		udelay(20);
 
-	if(!tries) {
-		printk("BIGMAC: Transmitter will not reset.\n");
-		printk("BIGMAC: tx_cfg is %08x\n", bregs->tx_cfg);
+	if (!tries) {
+		printk(KERN_ERR "BIGMAC: Transmitter will not reset.\n");
+		printk(KERN_ERR "BIGMAC: tx_cfg is %08x\n",
+		       sbus_readl(bregs + BMAC_TXCFG));
 	}
 }
 
-static inline void bigmac_rx_reset(struct BIG_MAC_regs *bregs)
+static void bigmac_rx_reset(unsigned long bregs)
 {
 	int tries = RX_RESET_TRIES;
 
-	bregs->rx_cfg = 0;
-	while((bregs->rx_cfg) && --tries)
+	sbus_writel(0, bregs + BMAC_RXCFG);
+	while (sbus_readl(bregs + BMAC_RXCFG) && --tries)
 		udelay(20);
 
-	if(!tries) {
-		printk("BIGMAC: Receiver will not reset.\n");
-		printk("BIGMAC: rx_cfg is %08x\n", bregs->rx_cfg);
+	if (!tries) {
+		printk(KERN_ERR "BIGMAC: Receiver will not reset.\n");
+		printk(KERN_ERR "BIGMAC: rx_cfg is %08x\n",
+		       sbus_readl(bregs + BMAC_RXCFG));
 	}
 }
 
@@ -158,38 +162,41 @@
 	bigmac_rx_reset(bp->bregs);
 }
 
-static void bigmac_get_counters(struct bigmac *bp, struct BIG_MAC_regs *bregs)
+static void bigmac_get_counters(struct bigmac *bp, unsigned long bregs)
 {
 	struct enet_statistics *stats = &bp->enet_stats;
 
-	stats->rx_crc_errors += bregs->rcrce_ctr;
-	bregs->rcrce_ctr = 0;
+	stats->rx_crc_errors += sbus_readl(bregs + BMAC_RCRCECTR);
+	sbus_writel(0, bregs + BMAC_RCRCECTR);
 
-	stats->rx_frame_errors += bregs->unale_ctr;
-	bregs->unale_ctr = 0;
+	stats->rx_frame_errors += sbus_readl(bregs + BMAC_UNALECTR);
+	sbus_writel(0, bregs + BMAC_UNALECTR);
 
-	stats->rx_length_errors += bregs->gle_ctr;
-	bregs->gle_ctr = 0;
+	stats->rx_length_errors += sbus_readl(bregs + BMAC_GLECTR);
+	sbus_writel(0, bregs + BMAC_GLECTR);
 
-	stats->tx_aborted_errors += bregs->ex_ctr;
+	stats->tx_aborted_errors += sbus_readl(bregs + BMAC_EXCTR);
 
-	stats->collisions += (bregs->ex_ctr + bregs->lt_ctr);
-	bregs->ex_ctr = bregs->lt_ctr = 0;
+	stats->collisions +=
+		(sbus_readl(bregs + BMAC_EXCTR) +
+		 sbus_readl(bregs + BMAC_LTCTR));
+	sbus_writel(0, bregs + BMAC_EXCTR);
+	sbus_writel(0, bregs + BMAC_LTCTR);
 }
 
-static inline void bigmac_clean_rings(struct bigmac *bp)
+static void bigmac_clean_rings(struct bigmac *bp)
 {
 	int i;
 
-	for(i = 0; i < RX_RING_SIZE; i++) {
-		if(bp->rx_skbs[i] != NULL) {
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		if (bp->rx_skbs[i] != NULL) {
 			dev_kfree_skb(bp->rx_skbs[i]);
 			bp->rx_skbs[i] = NULL;
 		}
 	}
 
-	for(i = 0; i < TX_RING_SIZE; i++) {
-		if(bp->tx_skbs[i] != NULL) {
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		if (bp->tx_skbs[i] != NULL) {
 			dev_kfree_skb(bp->tx_skbs[i]);
 			bp->tx_skbs[i] = NULL;
 		}
@@ -202,7 +209,7 @@
 	struct net_device *dev = bp->dev;
 	int i, gfp_flags = GFP_KERNEL;
 
-	if(from_irq || in_interrupt())
+	if (from_irq || in_interrupt())
 		gfp_flags = GFP_ATOMIC;
 
 	bp->rx_new = bp->rx_old = bp->tx_new = bp->tx_old = 0;
@@ -210,12 +217,12 @@
 	/* Free any skippy bufs left around in the rings. */
 	bigmac_clean_rings(bp);
 
-	/* Now get new skippy bufs for the receive ring. */
-	for(i = 0; i < RX_RING_SIZE; i++) {
+	/* Now get new skbufs for the receive ring. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
 		struct sk_buff *skb;
 
 		skb = big_mac_alloc_skb(RX_BUF_ALLOC_SIZE, gfp_flags);
-		if(!skb)
+		if (!skb)
 			continue;
 
 		bp->rx_skbs[i] = skb;
@@ -225,125 +232,103 @@
 		skb_put(skb, ETH_FRAME_LEN);
 		skb_reserve(skb, 34);
 
-		bb->be_rxd[i].rx_addr = sbus_dvma_addr(skb->data);
+		bb->be_rxd[i].rx_addr =
+			sbus_map_single(bp->bigmac_sdev, skb->data,
+					RX_BUF_ALLOC_SIZE - 34);
 		bb->be_rxd[i].rx_flags =
 			(RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH));
 	}
 
-	for(i = 0; i < TX_RING_SIZE; i++)
+	for (i = 0; i < TX_RING_SIZE; i++)
 		bb->be_txd[i].tx_flags = bb->be_txd[i].tx_addr = 0;
 }
 
-#ifndef __sparc_v9__
-static void sun4c_bigmac_init_rings(struct bigmac *bp)
-{
-	struct bmac_init_block *bb = bp->bmac_block;
-	__u32 bbufs_dvma = bp->s4c_buf_dvma;
-	int i;
-
-	bp->rx_new = bp->rx_old = bp->tx_new = bp->tx_old = 0;
-
-	for(i = 0; i < RX_RING_SIZE; i++) {
-		bb->be_rxd[i].rx_addr = bbufs_dvma + bbuf_offset(rx_buf, i);
-		bb->be_rxd[i].rx_flags =
-			(RXD_OWN | (SUN4C_RX_BUFF_SIZE & RXD_LENGTH));
-	}
-
-	for(i = 0; i < TX_RING_SIZE; i++)
-		bb->be_txd[i].tx_flags = bb->be_txd[i].tx_addr = 0;
-}
-#endif
-
 #define MGMT_CLKON  (MGMT_PAL_INT_MDIO|MGMT_PAL_EXT_MDIO|MGMT_PAL_OENAB|MGMT_PAL_DCLOCK)
 #define MGMT_CLKOFF (MGMT_PAL_INT_MDIO|MGMT_PAL_EXT_MDIO|MGMT_PAL_OENAB)
 
-static inline void idle_transceiver(struct bmac_tcvr *tregs)
+static void idle_transceiver(unsigned long tregs)
 {
-	volatile unsigned int garbage;
 	int i = 20;
 
-	while(i--) {
-		tregs->mgmt_pal = MGMT_CLKOFF;
-		garbage = tregs->mgmt_pal;
-		tregs->mgmt_pal = MGMT_CLKON;
-		garbage = tregs->mgmt_pal;
+	while (i--) {
+		sbus_writel(MGMT_CLKOFF, tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
+		sbus_writel(MGMT_CLKON, tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
 	}
 }
 
-static void write_tcvr_bit(struct bigmac *bp, struct bmac_tcvr *tregs, int bit)
+static void write_tcvr_bit(struct bigmac *bp, unsigned long tregs, int bit)
 {
-	volatile unsigned int garbage;
-
-	if(bp->tcvr_type == internal) {
+	if (bp->tcvr_type == internal) {
 		bit = (bit & 1) << 3;
-		tregs->mgmt_pal = bit | (MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO);
-		garbage = tregs->mgmt_pal;
-		tregs->mgmt_pal = bit | (MGMT_PAL_OENAB |
-					 MGMT_PAL_EXT_MDIO |
-					 MGMT_PAL_DCLOCK);
-		garbage = tregs->mgmt_pal;
-	} else if(bp->tcvr_type == external) {
+		sbus_writel(bit | (MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO),
+			    tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
+		sbus_writel(bit | MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK,
+			    tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
+	} else if (bp->tcvr_type == external) {
 		bit = (bit & 1) << 2;
-		tregs->mgmt_pal = bit | (MGMT_PAL_INT_MDIO | MGMT_PAL_OENAB);
-		garbage = tregs->mgmt_pal;
-		tregs->mgmt_pal = bit | (MGMT_PAL_INT_MDIO |
-					 MGMT_PAL_OENAB |
-					 MGMT_PAL_DCLOCK);
-		garbage = tregs->mgmt_pal;
+		sbus_writel(bit | MGMT_PAL_INT_MDIO | MGMT_PAL_OENAB,
+			    tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
+		sbus_writel(bit | MGMT_PAL_INT_MDIO | MGMT_PAL_OENAB | MGMT_PAL_DCLOCK,
+			    tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
 	} else {
-		printk("write_tcvr_bit: No transceiver type known!\n");
+		printk(KERN_ERR "write_tcvr_bit: No transceiver type known!\n");
 	}
 }
 
-static int read_tcvr_bit(struct bigmac *bp, struct bmac_tcvr *tregs)
+static int read_tcvr_bit(struct bigmac *bp, unsigned long tregs)
 {
-	volatile unsigned int garbage;
 	int retval = 0;
 
-	if(bp->tcvr_type == internal) {
-		tregs->mgmt_pal = MGMT_PAL_EXT_MDIO;
-		garbage = tregs->mgmt_pal;
-		tregs->mgmt_pal = MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK;
-		garbage = tregs->mgmt_pal;
-		retval = (tregs->mgmt_pal & MGMT_PAL_INT_MDIO) >> 3;
-	} else if(bp->tcvr_type == external) {
-		tregs->mgmt_pal = MGMT_PAL_INT_MDIO;
-		garbage = tregs->mgmt_pal;
-		tregs->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK;
-		garbage = tregs->mgmt_pal;
-		retval = (tregs->mgmt_pal & MGMT_PAL_EXT_MDIO) >> 2;
+	if (bp->tcvr_type == internal) {
+		sbus_writel(MGMT_PAL_EXT_MDIO, tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
+		sbus_writel(MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK,
+			    tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
+		retval = (sbus_readl(tregs + TCVR_MPAL) & MGMT_PAL_INT_MDIO) >> 3;
+	} else if (bp->tcvr_type == external) {
+		sbus_writel(MGMT_PAL_INT_MDIO, tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
+		sbus_writel(MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK, tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
+		retval = (sbus_readl(tregs + TCVR_MPAL) & MGMT_PAL_EXT_MDIO) >> 2;
 	} else {
-		printk("read_tcvr_bit: No transceiver type known!\n");
+		printk(KERN_ERR "read_tcvr_bit: No transceiver type known!\n");
 	}
 	return retval;
 }
 
-static int read_tcvr_bit2(struct bigmac *bp, struct bmac_tcvr *tregs)
+static int read_tcvr_bit2(struct bigmac *bp, unsigned long tregs)
 {
-	volatile unsigned int garbage;
 	int retval = 0;
 
-	if(bp->tcvr_type == internal) {
-		tregs->mgmt_pal = MGMT_PAL_EXT_MDIO;
-		garbage = tregs->mgmt_pal;
-		retval = (tregs->mgmt_pal & MGMT_PAL_INT_MDIO) >> 3;
-		tregs->mgmt_pal = (MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK);
-		garbage = tregs->mgmt_pal;
-	} else if(bp->tcvr_type == external) {
-		tregs->mgmt_pal = MGMT_PAL_INT_MDIO;
-		garbage = tregs->mgmt_pal;
-		retval = (tregs->mgmt_pal & MGMT_PAL_EXT_MDIO) >> 2;
-		tregs->mgmt_pal = (MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK);
-		garbage = tregs->mgmt_pal;
+	if (bp->tcvr_type == internal) {
+		sbus_writel(MGMT_PAL_EXT_MDIO, tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
+		retval = (sbus_readl(tregs + TCVR_MPAL) & MGMT_PAL_INT_MDIO) >> 3;
+		sbus_writel(MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK, tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
+	} else if (bp->tcvr_type == external) {
+		sbus_writel(MGMT_PAL_INT_MDIO, tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
+		retval = (sbus_readl(tregs + TCVR_MPAL) & MGMT_PAL_EXT_MDIO) >> 2;
+		sbus_writel(MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK, tregs + TCVR_MPAL);
+		sbus_readl(tregs + TCVR_MPAL);
 	} else {
-		printk("read_tcvr_bit2: No transceiver type known!\n");
+		printk(KERN_ERR "read_tcvr_bit2: No transceiver type known!\n");
 	}
 	return retval;
 }
 
-static inline void put_tcvr_byte(struct bigmac *bp,
-				 struct bmac_tcvr *tregs,
-				 unsigned int byte)
+static void put_tcvr_byte(struct bigmac *bp,
+			  unsigned long tregs,
+			  unsigned int byte)
 {
 	int shift = 4;
 
@@ -353,7 +338,7 @@
 	} while (shift >= 0);
 }
 
-static void bigmac_tcvr_write(struct bigmac *bp, struct bmac_tcvr *tregs,
+static void bigmac_tcvr_write(struct bigmac *bp, unsigned long tregs,
 			      int reg, unsigned short val)
 {
 	int shift;
@@ -366,7 +351,7 @@
 		break;
 
 	default:
-		printk("bigmac_tcvr_read: Whoops, no known transceiver type.\n");
+		printk(KERN_ERR "bigmac_tcvr_read: Whoops, no known transceiver type.\n");
 		return;
 	};
 
@@ -389,11 +374,11 @@
 	do {
 		write_tcvr_bit(bp, tregs, (val >> shift) & 1);
 		shift -= 1;
-	} while(shift >= 0);
+	} while (shift >= 0);
 }
 
 static unsigned short bigmac_tcvr_read(struct bigmac *bp,
-				       struct bmac_tcvr *tregs,
+				       unsigned long tregs,
 				       int reg)
 {
 	unsigned short retval = 0;
@@ -405,7 +390,7 @@
 		break;
 
 	default:
-		printk("bigmac_tcvr_read: Whoops, no known transceiver type.\n");
+		printk(KERN_ERR "bigmac_tcvr_read: Whoops, no known transceiver type.\n");
 		return 0xffff;
 	};
 
@@ -421,7 +406,7 @@
 
 	put_tcvr_byte(bp, tregs, reg);
 
-	if(bp->tcvr_type == external) {
+	if (bp->tcvr_type == external) {
 		int shift = 15;
 
 		(void) read_tcvr_bit2(bp, tregs);
@@ -433,7 +418,7 @@
 			tmp = read_tcvr_bit2(bp, tregs);
 			retval |= ((tmp & 1) << shift);
 			shift -= 1;
-		} while(shift >= 0);
+		} while (shift >= 0);
 
 		(void) read_tcvr_bit2(bp, tregs);
 		(void) read_tcvr_bit2(bp, tregs);
@@ -450,7 +435,7 @@
 			tmp = read_tcvr_bit(bp, tregs);
 			retval |= ((tmp & 1) << shift);
 			shift -= 1;
-		} while(shift >= 0);
+		} while (shift >= 0);
 
 		(void) read_tcvr_bit(bp, tregs);
 		(void) read_tcvr_bit(bp, tregs);
@@ -461,49 +446,47 @@
 
 static void bigmac_tcvr_init(struct bigmac *bp)
 {
-	volatile unsigned int garbage;
-	struct bmac_tcvr *tregs = bp->tregs;
+	unsigned long tregs = bp->tregs;
+	u32 mpal;
 
 	idle_transceiver(tregs);
-	tregs->mgmt_pal = (MGMT_PAL_INT_MDIO |
-			   MGMT_PAL_EXT_MDIO |
-			   MGMT_PAL_DCLOCK);
-	garbage = tregs->mgmt_pal;
+	sbus_writel(MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK,
+		    tregs + TCVR_MPAL);
+	sbus_readl(tregs + TCVR_MPAL);
 
 	/* Only the bit for the present transceiver (internal or
 	 * external) will stick, set them both and see what stays.
 	 */
-	tregs->mgmt_pal = (MGMT_PAL_INT_MDIO |
-			   MGMT_PAL_EXT_MDIO);
-	garbage = tregs->mgmt_pal;
+	sbus_writel(MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO, tregs + TCVR_MPAL);
+	sbus_readl(tregs + TCVR_MPAL);
 	udelay(20);
 
-	if(tregs->mgmt_pal & MGMT_PAL_EXT_MDIO) {
+	mpal = sbus_readl(tregs + TCVR_MPAL);
+	if (mpal & MGMT_PAL_EXT_MDIO) {
 		bp->tcvr_type = external;
-		tregs->tcvr_pal = ~(TCVR_PAL_EXTLBACK |
-				    TCVR_PAL_MSENSE |
-				    TCVR_PAL_LTENABLE);
-		garbage = tregs->tcvr_pal;
-	} else if(tregs->mgmt_pal & MGMT_PAL_INT_MDIO) {
+		sbus_writel(~(TCVR_PAL_EXTLBACK | TCVR_PAL_MSENSE | TCVR_PAL_LTENABLE),
+			    tregs + TCVR_TPAL);
+		sbus_readl(tregs + TCVR_TPAL);
+	} else if (mpal & MGMT_PAL_INT_MDIO) {
 		bp->tcvr_type = internal;
-		tregs->tcvr_pal = ~(TCVR_PAL_SERIAL |
-				    TCVR_PAL_EXTLBACK |
-				    TCVR_PAL_MSENSE |
-				    TCVR_PAL_LTENABLE);
-		garbage = tregs->tcvr_pal;
+		sbus_writel(~(TCVR_PAL_SERIAL | TCVR_PAL_EXTLBACK |
+			      TCVR_PAL_MSENSE | TCVR_PAL_LTENABLE),
+			    tregs + TCVR_TPAL);
+		sbus_readl(tregs + TCVR_TPAL);
 	} else {
-		printk("BIGMAC: AIEEE, neither internal nor "
+		printk(KERN_ERR "BIGMAC: AIEEE, neither internal nor "
 		       "external MDIO available!\n");
-		printk("BIGMAC: mgmt_pal[%08x] tcvr_pal[%08x]\n",
-		       tregs->mgmt_pal, tregs->tcvr_pal);
+		printk(KERN_ERR "BIGMAC: mgmt_pal[%08x] tcvr_pal[%08x]\n",
+		       sbus_readl(tregs + TCVR_MPAL),
+		       sbus_readl(tregs + TCVR_TPAL));
 	}
 }
 
 static int bigmac_init(struct bigmac *, int);
 
-static int try_next_permutation(struct bigmac *bp, struct bmac_tcvr *tregs)
+static int try_next_permutation(struct bigmac *bp, unsigned long tregs)
 {
-	if(bp->sw_bmcr & BMCR_SPEED100) {
+	if (bp->sw_bmcr & BMCR_SPEED100) {
 		int timeout;
 
 		/* Reset the PHY. */
@@ -513,14 +496,14 @@
 		bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
 
 		timeout = 64;
-		while(--timeout) {
+		while (--timeout) {
 			bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
-			if((bp->sw_bmcr & BMCR_RESET) == 0)
+			if ((bp->sw_bmcr & BMCR_RESET) == 0)
 				break;
 			udelay(20);
 		}
-		if(timeout == 0)
-			printk("%s: PHY reset failed.\n", bp->dev->name);
+		if (timeout == 0)
+			printk(KERN_ERR "%s: PHY reset failed.\n", bp->dev->name);
 
 		bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
 
@@ -537,31 +520,31 @@
 static void bigmac_timer(unsigned long data)
 {
 	struct bigmac *bp = (struct bigmac *) data;
-	struct bmac_tcvr *tregs = bp->tregs;
+	unsigned long tregs = bp->tregs;
 	int restart_timer = 0;
 
 	bp->timer_ticks++;
-	if(bp->timer_state == ltrywait) {
+	if (bp->timer_state == ltrywait) {
 		bp->sw_bmsr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMSR);
 		bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
-		if(bp->sw_bmsr & BMSR_LSTATUS) {
-			printk("%s: Link is now up at %s.\n",
+		if (bp->sw_bmsr & BMSR_LSTATUS) {
+			printk(KERN_INFO "%s: Link is now up at %s.\n",
 			       bp->dev->name,
 			       (bp->sw_bmcr & BMCR_SPEED100) ?
 			       "100baseT" : "10baseT");
 			bp->timer_state = asleep;
 			restart_timer = 0;
 		} else {
-			if(bp->timer_ticks >= 4) {
+			if (bp->timer_ticks >= 4) {
 				int ret;
 
 				ret = try_next_permutation(bp, tregs);
-				if(ret == -1) {
-					printk("%s: Link down, cable problem?\n",
+				if (ret == -1) {
+					printk(KERN_ERR "%s: Link down, cable problem?\n",
 					       bp->dev->name);
 					ret = bigmac_init(bp, 0);
-					if(ret) {
-						printk("%s: Error, cannot re-init the "
+					if (ret) {
+						printk(KERN_ERR "%s: Error, cannot re-init the "
 						       "BigMAC.\n", bp->dev->name);
 					}
 					return;
@@ -574,14 +557,14 @@
 		}
 	} else {
 		/* Can't happens.... */
-		printk("%s: Aieee, link timer is asleep but we got one anyways!\n",
+		printk(KERN_ERR "%s: Aieee, link timer is asleep but we got one anyways!\n",
 		       bp->dev->name);
 		restart_timer = 0;
 		bp->timer_ticks = 0;
 		bp->timer_state = asleep; /* foo on you */
 	}
 
-	if(restart_timer != 0) {
+	if (restart_timer != 0) {
 		bp->bigmac_timer.expires = jiffies + ((12 * HZ)/10); /* 1.2 sec. */
 		add_timer(&bp->bigmac_timer);
 	}
@@ -592,7 +575,7 @@
  */
 static void bigmac_begin_auto_negotiation(struct bigmac *bp)
 {
-	struct bmac_tcvr *tregs = bp->tregs;
+	unsigned long tregs = bp->tregs;
 	int timeout;
 
 	/* Grab new software copies of PHY registers. */
@@ -606,14 +589,14 @@
 	bigmac_tcvr_write(bp, tregs, BIGMAC_BMCR, bp->sw_bmcr);
 
 	timeout = 64;
-	while(--timeout) {
+	while (--timeout) {
 		bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
-		if((bp->sw_bmcr & BMCR_RESET) == 0)
+		if ((bp->sw_bmcr & BMCR_RESET) == 0)
 			break;
 		udelay(20);
 	}
-	if(timeout == 0)
-		printk("%s: PHY reset failed.\n", bp->dev->name);
+	if (timeout == 0)
+		printk(KERN_ERR "%s: PHY reset failed.\n", bp->dev->name);
 
 	bp->sw_bmcr = bigmac_tcvr_read(bp, tregs, BIGMAC_BMCR);
 
@@ -631,9 +614,9 @@
 
 static int bigmac_init(struct bigmac *bp, int from_irq)
 {
-	struct qe_globreg    *gregs        = bp->gregs;
-	struct qe_creg       *cregs        = bp->creg;
-	struct BIG_MAC_regs  *bregs        = bp->bregs;
+	unsigned long gregs        = bp->gregs;
+	unsigned long cregs        = bp->creg;
+	unsigned long bregs        = bp->bregs;
 	unsigned char *e = &bp->dev->dev_addr[0];
 
 	/* Latch current counters into statistics. */
@@ -646,12 +629,7 @@
 	qec_init(bp);
 
 	/* Alloc and reset the tx/rx descriptor chains. */
-#ifndef __sparc_v9__
-	if(sparc_cpu_model == sun4c)
-		sun4c_bigmac_init_rings(bp);
-	else
-#endif
-		bigmac_init_rings(bp, from_irq);
+	bigmac_init_rings(bp, from_irq);
 
 	/* Initialize the PHY. */
 	bigmac_tcvr_init(bp);
@@ -660,56 +638,67 @@
 	bigmac_stop(bp);
 
 	/* Set hardware ethernet address. */
-	bregs->mac_addr2 = ((e[4] << 8) | e[5]);
-	bregs->mac_addr1 = ((e[2] << 8) | e[3]);
-	bregs->mac_addr0 = ((e[0] << 8) | e[1]);
+	sbus_writel(((e[4] << 8) | e[5]), bregs + BMAC_MACADDR2);
+	sbus_writel(((e[2] << 8) | e[3]), bregs + BMAC_MACADDR1);
+	sbus_writel(((e[0] << 8) | e[1]), bregs + BMAC_MACADDR0);
 
 	/* Clear the hash table until mc upload occurs. */
-	bregs->htable3 = 0;
-	bregs->htable2 = 0;
-	bregs->htable1 = 0;
-	bregs->htable0 = 0;
+	sbus_writel(0, bregs + BMAC_HTABLE3);
+	sbus_writel(0, bregs + BMAC_HTABLE2);
+	sbus_writel(0, bregs + BMAC_HTABLE1);
+	sbus_writel(0, bregs + BMAC_HTABLE0);
 
 	/* Enable Big Mac hash table filter. */
-	bregs->rx_cfg = (BIGMAC_RXCFG_HENABLE | BIGMAC_RXCFG_FIFO);
-
+	sbus_writel(BIGMAC_RXCFG_HENABLE | BIGMAC_RXCFG_FIFO,
+		    bregs + BMAC_RXCFG);
 	udelay(20);
 
 	/* Ok, configure the Big Mac transmitter. */
-	bregs->tx_cfg = BIGMAC_TXCFG_FIFO;
+	sbus_writel(BIGMAC_TXCFG_FIFO, bregs + BMAC_TXCFG);
 
 	/* The HME docs recommend to use the 10LSB of our MAC here. */
-	bregs->rand_seed = ((e[5] | e[4] << 8) & 0x3ff);
+	sbus_writel(((e[5] | e[4] << 8) & 0x3ff),
+		    bregs + BMAC_RSEED);
 
 	/* Enable the output drivers no matter what. */
-	bregs->xif_cfg = (BIGMAC_XCFG_ODENABLE | BIGMAC_XCFG_RESV);
+	sbus_writel(BIGMAC_XCFG_ODENABLE | BIGMAC_XCFG_RESV,
+		    bregs + BMAC_XIFCFG);
 
 	/* Tell the QEC where the ring descriptors are. */
-	cregs->rxds = bp->bblock_dvma + bib_offset(be_rxd, 0);
-	cregs->txds = bp->bblock_dvma + bib_offset(be_txd, 0);
+	sbus_writel(bp->bblock_dvma + bib_offset(be_rxd, 0),
+		    cregs + CREG_RXDS);
+	sbus_writel(bp->bblock_dvma + bib_offset(be_txd, 0),
+		    cregs + CREG_TXDS);
 
 	/* Setup the FIFO pointers into QEC local memory. */
-	cregs->rxwbufptr = cregs->rxrbufptr = 0;
-	cregs->txwbufptr = cregs->txrbufptr = gregs->rsize;
+	sbus_writel(0, cregs + CREG_RXRBUFPTR);
+	sbus_writel(0, cregs + CREG_RXWBUFPTR);
+	sbus_writel(sbus_readl(gregs + GLOB_RSIZE),
+		    cregs + CREG_TXRBUFPTR);
+	sbus_writel(sbus_readl(gregs + GLOB_RSIZE),
+		    cregs + CREG_TXWBUFPTR);
 
 	/* Tell bigmac what interrupts we don't want to hear about. */
-	bregs->imask = (BIGMAC_IMASK_GOTFRAME | BIGMAC_IMASK_SENTFRAME);
+	sbus_writel(BIGMAC_IMASK_GOTFRAME | BIGMAC_IMASK_SENTFRAME,
+		    bregs + BMAC_IMASK);
 
 	/* Enable the various other irq's. */
-	cregs->rimask = 0;
-	cregs->timask = 0;
-	cregs->qmask = 0;
-	cregs->bmask = 0;
+	sbus_writel(0, cregs + CREG_RIMASK);
+	sbus_writel(0, cregs + CREG_TIMASK);
+	sbus_writel(0, cregs + CREG_QMASK);
+	sbus_writel(0, cregs + CREG_BMASK);
 
 	/* Set jam size to a reasonable default. */
-	bregs->jsize     = DEFAULT_JAMSIZE;
+	sbus_writel(DEFAULT_JAMSIZE, bregs + BMAC_JSIZE);
 
 	/* Clear collision counter. */
-	cregs->ccnt = 0;
+	sbus_writel(0, cregs + CREG_CCNT);
 
 	/* Enable transmitter and receiver. */
-	bregs->tx_cfg |= BIGMAC_TXCFG_ENABLE;
-	bregs->rx_cfg |= BIGMAC_RXCFG_ENABLE;
+	sbus_writel(sbus_readl(bregs + BMAC_TXCFG) | BIGMAC_TXCFG_ENABLE,
+		    bregs + BMAC_TXCFG);
+	sbus_writel(sbus_readl(bregs + BMAC_RXCFG) | BIGMAC_RXCFG_ENABLE,
+		    bregs + BMAC_RXCFG);
 
 	/* Ok, start detecting link speed/duplex. */
 	bigmac_begin_auto_negotiation(bp);
@@ -719,39 +708,37 @@
 }
 
 /* Error interrupts get sent here. */
-static void bigmac_is_medium_rare(struct bigmac *bp,
-				  unsigned int qec_status,
-				  unsigned int bmac_status)
-{
-	printk("bigmac_is_medium_rare: ");
-	if(qec_status & (GLOB_STAT_ER | GLOB_STAT_BM)) {
-		if(qec_status & GLOB_STAT_ER)
+static void bigmac_is_medium_rare(struct bigmac *bp, u32 qec_status, u32 bmac_status)
+{
+	printk(KERN_ERR "bigmac_is_medium_rare: ");
+	if (qec_status & (GLOB_STAT_ER | GLOB_STAT_BM)) {
+		if (qec_status & GLOB_STAT_ER)
 			printk("QEC_ERROR, ");
-		if(qec_status & GLOB_STAT_BM)
+		if (qec_status & GLOB_STAT_BM)
 			printk("QEC_BMAC_ERROR, ");
 	}
-	if(bmac_status & CREG_STAT_ERRORS) {
-		if(bmac_status & CREG_STAT_BERROR)
+	if (bmac_status & CREG_STAT_ERRORS) {
+		if (bmac_status & CREG_STAT_BERROR)
 			printk("BMAC_ERROR, ");
-		if(bmac_status & CREG_STAT_TXDERROR)
+		if (bmac_status & CREG_STAT_TXDERROR)
 			printk("TXD_ERROR, ");
-		if(bmac_status & CREG_STAT_TXLERR)
+		if (bmac_status & CREG_STAT_TXLERR)
 			printk("TX_LATE_ERROR, ");
-		if(bmac_status & CREG_STAT_TXPERR)
+		if (bmac_status & CREG_STAT_TXPERR)
 			printk("TX_PARITY_ERROR, ");
-		if(bmac_status & CREG_STAT_TXSERR)
+		if (bmac_status & CREG_STAT_TXSERR)
 			printk("TX_SBUS_ERROR, ");
 
-		if(bmac_status & CREG_STAT_RXDROP)
+		if (bmac_status & CREG_STAT_RXDROP)
 			printk("RX_DROP_ERROR, ");
 
-		if(bmac_status & CREG_STAT_RXSMALL)
+		if (bmac_status & CREG_STAT_RXSMALL)
 			printk("RX_SMALL_ERROR, ");
-		if(bmac_status & CREG_STAT_RXLERR)
+		if (bmac_status & CREG_STAT_RXLERR)
 			printk("RX_LATE_ERROR, ");
-		if(bmac_status & CREG_STAT_RXPERR)
+		if (bmac_status & CREG_STAT_RXPERR)
 			printk("RX_PARITY_ERROR, ");
-		if(bmac_status & CREG_STAT_RXSERR)
+		if (bmac_status & CREG_STAT_RXSERR)
 			printk("RX_SBUS_ERROR, ");
 	}
 
@@ -760,106 +747,83 @@
 }
 
 /* BigMAC transmit complete service routines. */
-static inline void bigmac_tx(struct bigmac *bp)
+static void bigmac_tx(struct bigmac *bp)
 {
 	struct be_txd *txbase = &bp->bmac_block->be_txd[0];
-	struct be_txd *this;
 	int elem = bp->tx_old;
 
 	DTX(("bigmac_tx: tx_old[%d] ", elem));
-	while(elem != bp->tx_new) {
+	while (elem != bp->tx_new) {
 		struct sk_buff *skb;
-
-		this = &txbase[elem];
+		struct be_txd *this = &txbase[elem];
 
 		DTX(("this(%p) [flags(%08x)addr(%08x)]",
 		     this, this->tx_flags, this->tx_addr));
 
-		if(this->tx_flags & TXD_OWN)
+		if (this->tx_flags & TXD_OWN)
 			break;
 		skb = bp->tx_skbs[elem];
+		bp->enet_stats.tx_packets++;
+		bp->enet_stats.tx_bytes += skb->len;
+		sbus_unmap_single(bp->bigmac_sdev,
+				  this->tx_addr, skb->len);
+
 		DTX(("skb(%p) ", skb));
 		bp->tx_skbs[elem] = NULL;
 		dev_kfree_skb(skb);
 
-		bp->enet_stats.tx_packets++;
 		elem = NEXT_TX(elem);
 	}
 	DTX((" DONE, tx_old=%d\n", elem));
 	bp->tx_old = elem;
 }
 
-#ifndef __sparc_v9__
-static inline void sun4c_bigmac_tx(struct bigmac *bp)
-{
-	struct be_txd *txbase = &bp->bmac_block->be_txd[0];
-	struct be_txd *this;
-	int elem = bp->tx_old;
-
-	while(elem != bp->tx_new) {
-		this = &txbase[elem];
-		if(this->tx_flags & TXD_OWN)
-			break;
-		bp->enet_stats.tx_packets++;
-		elem = NEXT_TX(elem);
-	}
-	bp->tx_old = elem;
-}
-#endif
-
 /* BigMAC receive complete service routines. */
-static inline void bigmac_rx(struct bigmac *bp)
+static void bigmac_rx(struct bigmac *bp)
 {
 	struct be_rxd *rxbase = &bp->bmac_block->be_rxd[0];
 	struct be_rxd *this;
 	int elem = bp->rx_new, drops = 0;
+	u32 flags;
 
 	this = &rxbase[elem];
-	while(!(this->rx_flags & RXD_OWN)) {
+	while (!((flags = this->rx_flags) & RXD_OWN)) {
 		struct sk_buff *skb;
-		unsigned int flags = this->rx_flags;
 		int len = (flags & RXD_LENGTH); /* FCS not included */
 
 		/* Check for errors. */
-		if(len < ETH_ZLEN) {
+		if (len < ETH_ZLEN) {
 			bp->enet_stats.rx_errors++;
 			bp->enet_stats.rx_length_errors++;
 
 	drop_it:
 			/* Return it to the BigMAC. */
 			bp->enet_stats.rx_dropped++;
-			this->rx_addr = sbus_dvma_addr(bp->rx_skbs[elem]->data);
 			this->rx_flags =
-				(RXD_OWN | (RX_BUF_ALLOC_SIZE & RXD_LENGTH));
+				(RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH));
 			goto next;
 		}
 		skb = bp->rx_skbs[elem];
-#ifdef NEED_DMA_SYNCHRONIZATION
-#ifdef __sparc_v9__
-		if ((unsigned long) (skb->data + skb->len) >= MAX_DMA_ADDRESS) {
-			printk("sunbmac: Bogus DMA buffer address "
-			       "[%016lx]\n", ((unsigned long) skb->data));
-			panic("DMA address too large, tell DaveM");
-		}
-#endif
-		mmu_sync_dma(sbus_dvma_addr(skb->data),
-			     skb->len, bp->bigmac_sbus_dev->my_bus);
-#endif
-		if(len > RX_COPY_THRESHOLD) {
+		if (len > RX_COPY_THRESHOLD) {
 			struct sk_buff *new_skb;
 
 			/* Now refill the entry, if we can. */
 			new_skb = big_mac_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC);
-			if(!new_skb) {
+			if (new_skb == NULL) {
 				drops++;
 				goto drop_it;
 			}
+			sbus_unmap_single(bp->bigmac_sdev,
+					  this->rx_addr,
+					  RX_BUF_ALLOC_SIZE - 34);
 			bp->rx_skbs[elem] = new_skb;
 			new_skb->dev = bp->dev;
 			skb_put(new_skb, ETH_FRAME_LEN);
 			skb_reserve(new_skb, 34);
-			rxbase[elem].rx_addr = sbus_dvma_addr(new_skb->data);
-			rxbase[elem].rx_flags =
+			this->rx_addr = sbus_map_single(bp->bigmac_sdev,
+							new_skb->data,
+							RX_BUF_ALLOC_SIZE - 34);
+			this->rx_flags =
 				(RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH));
 
 			/* Trim the original skb for the netif. */
@@ -867,18 +831,19 @@
 		} else {
 			struct sk_buff *copy_skb = dev_alloc_skb(len + 2);
 
-			if(!copy_skb) {
+			if (copy_skb == NULL) {
 				drops++;
 				goto drop_it;
 			}
 			copy_skb->dev = bp->dev;
 			skb_reserve(copy_skb, 2);
 			skb_put(copy_skb, len);
+			sbus_dma_sync_single(bp->bigmac_sdev,
+					     this->rx_addr, len);
 			eth_copy_and_sum(copy_skb, (unsigned char *)skb->data, len, 0);
 
-			/* Reuse otiginal ring buffer. */
-			rxbase[elem].rx_addr = sbus_dvma_addr(skb->data);
-			rxbase[elem].rx_flags =
+			/* Reuse original ring buffer. */
+			this->rx_flags =
 				(RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH));
 
 			skb = copy_skb;
@@ -888,94 +853,41 @@
 		skb->protocol = eth_type_trans(skb, bp->dev);
 		netif_rx(skb);
 		bp->enet_stats.rx_packets++;
+		bp->enet_stats.rx_bytes += len;
 	next:
 		elem = NEXT_RX(elem);
 		this = &rxbase[elem];
 	}
 	bp->rx_new = elem;
-	if(drops)
-		printk("%s: Memory squeeze, deferring packet.\n", bp->dev->name);
-}
-
-#ifndef __sparc_v9__
-static inline void sun4c_bigmac_rx(struct bigmac *bp)
-{
-	struct be_rxd *rxbase = &bp->bmac_block->be_rxd[0];
-	struct be_rxd *this;
-	struct bigmac_buffers *bbufs = bp->sun4c_buffers;
-	__u32 bbufs_dvma = bp->s4c_buf_dvma;
-	int elem = bp->rx_new, drops = 0;
-
-	this = &rxbase[elem];
-	while(!(this->rx_flags & RXD_OWN)) {
-		struct sk_buff *skb;
-		unsigned char *this_bbuf =
-			bbufs->rx_buf[elem & (SUN4C_RX_RING_SIZE - 1)];
-		__u32 this_bbuf_dvma = bbufs_dvma +
-			bbuf_offset(rx_buf, (elem & (SUN4C_RX_RING_SIZE - 1)));
-		struct be_rxd *end_rxd =
-			&rxbase[(elem+SUN4C_RX_RING_SIZE)&(RX_RING_SIZE-1)];
-		unsigned int flags = this->rx_flags;
-		int len = (flags & RXD_LENGTH) - 4; /* FCS not included */
-
-		/* Check for errors. */
-		if(len < ETH_ZLEN) {
-			bp->enet_stats.rx_errors++;
-			bp->enet_stats.rx_length_errors++;
-			bp->enet_stats.rx_dropped++;
-		} else {
-			skb = dev_alloc_skb(len + 2);
-			if(skb == 0) {
-				drops++;
-				bp->enet_stats.rx_dropped++;
-			} else {
-				skb->dev = bp->dev;
-				skb_reserve(skb, 2);
-				skb_put(skb, len);
-				eth_copy_and_sum(skb, (unsigned char *)this_bbuf,
-						 len, 0);
-				skb->protocol = eth_type_trans(skb, bp->dev);
-				netif_rx(skb);
-				bp->enet_stats.rx_packets++;
-			}
-		}
-		end_rxd->rx_addr = this_bbuf_dvma;
-		end_rxd->rx_flags = (RXD_OWN | (SUN4C_RX_BUFF_SIZE & RXD_LENGTH));
-		
-		elem = NEXT_RX(elem);
-		this = &rxbase[elem];
-	}
-	bp->rx_new = elem;
-	if(drops)
-		printk("%s: Memory squeeze, deferring packet.\n", bp->dev->name);
+	if (drops)
+		printk(KERN_NOTICE "%s: Memory squeeze, deferring packet.\n", bp->dev->name);
 }
-#endif
 
 static void bigmac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct bigmac *bp = (struct bigmac *) dev_id;
-	unsigned int qec_status, bmac_status;
+	u32 qec_status, bmac_status;
 
 	DIRQ(("bigmac_interrupt: "));
 
 	/* Latch status registers now. */
-	bmac_status = bp->creg->stat;
-	qec_status = bp->gregs->stat;
+	bmac_status = sbus_readl(bp->creg + CREG_STAT);
+	qec_status = sbus_readl(bp->gregs + GLOB_STAT);
 
 	bp->dev->interrupt = 1;
 
 	DIRQ(("qec_status=%08x bmac_status=%08x\n", qec_status, bmac_status));
-	if((qec_status & (GLOB_STAT_ER | GLOB_STAT_BM)) ||
+	if ((qec_status & (GLOB_STAT_ER | GLOB_STAT_BM)) ||
 	   (bmac_status & CREG_STAT_ERRORS))
 		bigmac_is_medium_rare(bp, qec_status, bmac_status);
 
-	if(bmac_status & CREG_STAT_TXIRQ)
+	if (bmac_status & CREG_STAT_TXIRQ)
 		bigmac_tx(bp);
 
-	if(bmac_status & CREG_STAT_RXIRQ)
+	if (bmac_status & CREG_STAT_RXIRQ)
 		bigmac_rx(bp);
 
-	if(bp->dev->tbusy && (TX_BUFFS_AVAIL(bp) >= 0)) {
+	if (bp->dev->tbusy && (TX_BUFFS_AVAIL(bp) > 0)) {
 		bp->dev->tbusy = 0;
 		mark_bh(NET_BH);
 	}
@@ -983,59 +895,19 @@
 	bp->dev->interrupt = 0;
 }
 
-#ifndef __sparc_v9__
-static void sun4c_bigmac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct bigmac *bp = (struct bigmac *) dev_id;
-	unsigned int qec_status, bmac_status;
-
-	/* Latch status registers now. */
-	bmac_status = bp->creg->stat;
-	qec_status = bp->gregs->stat;
-
-	bp->dev->interrupt = 1;
-
-	if(qec_status & (GLOB_STAT_ER | GLOB_STAT_BM) ||
-	   (bmac_status & CREG_STAT_ERRORS))
-		bigmac_is_medium_rare(bp, qec_status, bmac_status);
-
-	if(bmac_status & CREG_STAT_TXIRQ)
-		sun4c_bigmac_tx(bp);
-
-	if(bmac_status & CREG_STAT_RXIRQ)
-		sun4c_bigmac_rx(bp);
-
-	if(bp->dev->tbusy && (SUN4C_TX_BUFFS_AVAIL(bp) >= 0)) {
-		bp->dev->tbusy = 0;
-		mark_bh(NET_BH);
-	}
-
-	bp->dev->interrupt = 0;
-}
-#endif
-
 static int bigmac_open(struct net_device *dev)
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
 	int res;
 
-#ifndef __sparc_v9__
-	if(sparc_cpu_model == sun4c) {
-		if(request_irq(dev->irq, &sun4c_bigmac_interrupt,
-			       SA_SHIRQ, "BIG MAC", (void *) bp)) {
-			printk("BIGMAC: Can't order irq %d to go.\n", dev->irq);
-			return -EAGAIN;
-		}
-	} else
-#endif
-	if(request_irq(dev->irq, &bigmac_interrupt,
-		       SA_SHIRQ, "BIG MAC", (void *) bp)) {
-		printk("BIGMAC: Can't order irq %d to go.\n", dev->irq);
+	if (request_irq(dev->irq, &bigmac_interrupt,
+			SA_SHIRQ, "BIG MAC", (void *) bp)) {
+		printk(KERN_ERR "BIGMAC: Can't order irq %d to go.\n", dev->irq);
 		return -EAGAIN;
 	}
 	init_timer(&bp->bigmac_timer);
 	res = bigmac_init(bp, 0);
-	if(!res) {
+	if (!res) {
 		MOD_INC_USE_COUNT;
 	}
 	return res;
@@ -1062,13 +934,13 @@
 	struct bigmac *bp = (struct bigmac *) dev->priv;
 	int len, entry;
 
-	if(dev->tbusy) {
+	if (dev->tbusy) {
 		int tickssofar = jiffies - dev->trans_start;
 	    
 		if (tickssofar < 40) {
 			return 1;
 		} else {
-			printk ("%s: transmit timed out, resetting\n", dev->name);
+			printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
 			bp->enet_stats.tx_errors++;
 			bigmac_init(bp, 0);
 			dev->tbusy = 0;
@@ -1078,110 +950,37 @@
 		}
 	}
 
-	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		printk("%s: Transmitter access conflict.\n", dev->name);
+	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
+		printk(KERN_ERR "%s: Transmitter access conflict.\n", dev->name);
 		return 1;
 	}
 
-	if(!TX_BUFFS_AVAIL(bp))
+	if (!TX_BUFFS_AVAIL(bp))
 		return 1;
 
-#ifdef NEED_DMA_SYNCHRONIZATION
-#ifdef __sparc_v9__
-	if ((unsigned long) (skb->data + skb->len) >= MAX_DMA_ADDRESS) {
-		struct sk_buff *new_skb = skb_copy(skb, GFP_DMA | GFP_ATOMIC);
-		if(!new_skb)
-			return 1;
-		dev_kfree_skb(skb);
-		skb = new_skb;
-	}
-#endif
-	mmu_sync_dma(sbus_dvma_addr(skb->data),
-		     skb->len, bp->bigmac_sbus_dev->my_bus);
-#endif
 	len = skb->len;
 	entry = bp->tx_new;
 	DTX(("bigmac_start_xmit: len(%d) entry(%d)\n", len, entry));
 
 	/* Avoid a race... */
 	bp->bmac_block->be_txd[entry].tx_flags = TXD_UPDATE;
-
 	bp->tx_skbs[entry] = skb;
-	bp->bmac_block->be_txd[entry].tx_addr = sbus_dvma_addr(skb->data);
+	bp->bmac_block->be_txd[entry].tx_addr =
+		sbus_map_single(bp->bigmac_sdev, skb->data, len);
 	bp->bmac_block->be_txd[entry].tx_flags =
 		(TXD_OWN | TXD_SOP | TXD_EOP | (len & TXD_LENGTH));
 	dev->trans_start = jiffies;
 	bp->tx_new = NEXT_TX(entry);
 
 	/* Get it going. */
-	bp->creg->ctrl = CREG_CTRL_TWAKEUP;
+	sbus_writel(CREG_CTRL_TWAKEUP, bp->creg + CREG_CTRL);
 
-	if(TX_BUFFS_AVAIL(bp))
+	if (TX_BUFFS_AVAIL(bp))
 		dev->tbusy = 0;
 
 	return 0;
 }
 
-#ifndef __sparc_v9__
-static int sun4c_bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct bigmac *bp = (struct bigmac *) dev->priv;
-	struct bigmac_buffers *bbufs = bp->sun4c_buffers;
-	__u32 txbuf_dvma, bbufs_dvma = bp->s4c_buf_dvma;
-	unsigned char *txbuf;
-	int len, entry;
-
-	if(dev->tbusy) {
-		int tickssofar = jiffies - dev->trans_start;
-	    
-		if (tickssofar < 40) {
-			return 1;
-		} else {
-			printk ("%s: transmit timed out, resetting\n", dev->name);
-			bp->enet_stats.tx_errors++;
-			bigmac_init(bp, 0);
-			dev->tbusy = 0;
-			dev->trans_start = jiffies;
-			return 0;
-		}
-	}
-
-	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		printk("%s: Transmitter access conflict.\n", dev->name);
-		return 1;
-	}
-
-	if(!SUN4C_TX_BUFFS_AVAIL(bp))
-		return 1;
-
-	len = skb->len;
-	entry = bp->tx_new;
-
-	txbuf = &bbufs->tx_buf[entry][0];
-	txbuf_dvma = bbufs_dvma + bbuf_offset(tx_buf, entry);
-	memcpy(txbuf, skb->data, len);
-
-	/* Avoid a race... */
-	bp->bmac_block->be_txd[entry].tx_flags = TXD_UPDATE;
-
-	bp->bmac_block->be_txd[entry].tx_addr = txbuf_dvma;
-	bp->bmac_block->be_txd[entry].tx_flags =
-		(TXD_OWN | TXD_SOP | TXD_EOP | (len & TXD_LENGTH));
-	bp->tx_new = NEXT_TX(entry);
-
-	/* Get it going. */
-	dev->trans_start = jiffies;
-	bp->creg->ctrl = CREG_CTRL_TWAKEUP;
-
-	dev_kfree_skb(skb);
-
-	if(SUN4C_TX_BUFFS_AVAIL(bp))
-		dev->tbusy = 0;
-
-	return 0;
-}
-#endif
-
 static struct enet_statistics *bigmac_get_stats(struct net_device *dev)
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
@@ -1196,175 +995,140 @@
 static void bigmac_set_multicast(struct net_device *dev)
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
-	struct BIG_MAC_regs *bregs = bp->bregs;
+	unsigned long bregs = bp->bregs;
 	struct dev_mc_list *dmi = dev->mc_list;
 	char *addrs;
 	int i, j, bit, byte;
-	u32 crc, poly = CRC_POLYNOMIAL_LE;
+	u32 tmp, crc, poly = CRC_POLYNOMIAL_LE;
 
 	/* Disable the receiver.  The bit self-clears when
 	 * the operation is complete.
 	 */
-	bregs->rx_cfg &= ~(BIGMAC_RXCFG_ENABLE);
-	while((bregs->rx_cfg & BIGMAC_RXCFG_ENABLE) != 0)
+	tmp = sbus_readl(bregs + BMAC_RXCFG);
+	tmp &= ~(BIGMAC_RXCFG_ENABLE);
+	sbus_writel(tmp, bregs + BMAC_RXCFG);
+	while ((sbus_readl(bregs + BMAC_RXCFG) & BIGMAC_RXCFG_ENABLE) != 0)
 		udelay(20);
 
-	if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
-		bregs->htable0 = 0xffff;
-		bregs->htable1 = 0xffff;
-		bregs->htable2 = 0xffff;
-		bregs->htable3 = 0xffff;
-	} else if(dev->flags & IFF_PROMISC) {
-		bregs->rx_cfg |= BIGMAC_RXCFG_PMISC;
+	if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
+		sbus_writel(0xffff, bregs + BMAC_HTABLE0);
+		sbus_writel(0xffff, bregs + BMAC_HTABLE1);
+		sbus_writel(0xffff, bregs + BMAC_HTABLE2);
+		sbus_writel(0xffff, bregs + BMAC_HTABLE3);
+	} else if (dev->flags & IFF_PROMISC) {
+		tmp = sbus_readl(bregs + BMAC_RXCFG);
+		tmp |= BIGMAC_RXCFG_PMISC;
+		sbus_writel(tmp, bregs + BMAC_RXCFG);
 	} else {
 		u16 hash_table[4];
 
-		for(i = 0; i < 4; i++)
+		for (i = 0; i < 4; i++)
 			hash_table[i] = 0;
 
-		for(i = 0; i < dev->mc_count; i++) {
+		for (i = 0; i < dev->mc_count; i++) {
 			addrs = dmi->dmi_addr;
 			dmi = dmi->next;
 
-			if(!(*addrs & 1))
+			if (!(*addrs & 1))
 				continue;
 
 			crc = 0xffffffffU;
-			for(byte = 0; byte < 6; byte++) {
-				for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
+			for (byte = 0; byte < 6; byte++) {
+				for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
 					int test;
 
 					test = ((bit ^ crc) & 0x01);
 					crc >>= 1;
-					if(test)
+					if (test)
 						crc = crc ^ poly;
 				}
 			}
 			crc >>= 26;
 			hash_table[crc >> 4] |= 1 << (crc & 0xf);
 		}
-		bregs->htable0 = hash_table[0];
-		bregs->htable1 = hash_table[1];
-		bregs->htable2 = hash_table[2];
-		bregs->htable3 = hash_table[3];
+		sbus_writel(hash_table[0], bregs + BMAC_HTABLE0);
+		sbus_writel(hash_table[1], bregs + BMAC_HTABLE1);
+		sbus_writel(hash_table[2], bregs + BMAC_HTABLE2);
+		sbus_writel(hash_table[3], bregs + BMAC_HTABLE3);
 	}
 
 	/* Re-enable the receiver. */
-	bregs->rx_cfg |= BIGMAC_RXCFG_ENABLE;
+	tmp = sbus_readl(bregs + BMAC_RXCFG);
+	tmp |= BIGMAC_RXCFG_ENABLE;
+	sbus_writel(tmp, bregs + BMAC_RXCFG);
 }
 
-static int __init bigmac_ether_init(struct net_device *dev, struct linux_sbus_device *qec_sdev)
+static int __init bigmac_ether_init(struct net_device *dev, struct sbus_dev *qec_sdev)
 {
-	static unsigned version_printed = 0;
+	static int version_printed = 0;
 	struct bigmac *bp = 0;
-	unsigned char bsizes, bsizes_more;
-	int i, j, num_qranges, res = ENOMEM;
-	struct linux_prom_ranges qranges[8];
+	u8 bsizes, bsizes_more;
+	int i, res = ENOMEM;
 
 	/* Get a new device struct for this interface. */
 	dev = init_etherdev(0, sizeof(struct bigmac));
 
-	if(version_printed++ == 0)
-		printk(version);
+	if (version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
 
 	/* Report what we have found to the user. */
-	printk("%s: BigMAC 100baseT Ethernet ", dev->name);
+	printk(KERN_INFO "%s: BigMAC 100baseT Ethernet ", dev->name);
 	dev->base_addr = (long) qec_sdev;
-	for(i = 0; i < 6; i++)
+	for (i = 0; i < 6; i++)
 		printk("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i],
 		       i == 5 ? ' ' : ':');
 	printk("\n");
 
 	/* Setup softc, with backpointers to QEC and BigMAC SBUS device structs. */
 	bp = (struct bigmac *) dev->priv;
-	bp->qec_sbus_dev = qec_sdev;
-	bp->bigmac_sbus_dev = qec_sdev->child;
+	bp->qec_sdev = qec_sdev;
+	bp->bigmac_sdev = qec_sdev->child;
 
 	/* All further failures we find return this. */
 	res = ENODEV;
 
 	/* Verify the registers we expect, are actually there. */
-	if((bp->bigmac_sbus_dev->num_registers != 3) ||
-	   (bp->qec_sbus_dev->num_registers != 2)) {
-		printk("BIGMAC: Device does not have 2 and 3 regs, it has %d and %d.\n",
-		       bp->qec_sbus_dev->num_registers,
-		       bp->bigmac_sbus_dev->num_registers);
-		printk("BIGMAC: Would you like that for here or to go?\n");
+	if ((bp->bigmac_sdev->num_registers != 3) ||
+	   (bp->qec_sdev->num_registers != 2)) {
+		printk(KERN_ERR "BIGMAC: Device does not have 2 and 3 regs, it has %d and %d.\n",
+		       bp->qec_sdev->num_registers,
+		       bp->bigmac_sdev->num_registers);
+		printk(KERN_ERR "BIGMAC: Would you like that for here or to go?\n");
 		goto fail_and_cleanup;
 	}
 
-	/* Fun with QEC ranges... */
-	if(bp->bigmac_sbus_dev->ranges_applied == 0) {
-		i = prom_getproperty(bp->qec_sbus_dev->prom_node, "ranges",
-				     (char *)&qranges[0], sizeof(qranges));
-		num_qranges = (i / sizeof(struct linux_prom_ranges));
-
-		/* Now, apply all the ranges for the BigMAC. */
-		for(j = 0; j < bp->bigmac_sbus_dev->num_registers; j++) {
-			int k;
-
-			for(k = 0; k < num_qranges; k++)
-				if(bp->bigmac_sbus_dev->reg_addrs[j].which_io ==
-				   qranges[k].ot_child_space)
-					break;
-			if(k >= num_qranges) {
-				printk("BigMAC: Aieee, bogus QEC range for space %08x\n",
-				       bp->bigmac_sbus_dev->reg_addrs[j].which_io);
-				goto fail_and_cleanup;
-			}
-			bp->bigmac_sbus_dev->reg_addrs[j].which_io = qranges[k].ot_parent_space;
-			bp->bigmac_sbus_dev->reg_addrs[j].phys_addr += qranges[k].ot_parent_base;
-		}
-
-		/* Next, apply SBUS ranges on top of what we just changed. */
-		prom_apply_sbus_ranges(bp->bigmac_sbus_dev->my_bus,
-				       &bp->bigmac_sbus_dev->reg_addrs[0],
-				       bp->bigmac_sbus_dev->num_registers,
-				       bp->bigmac_sbus_dev);
-	}
-
-	/* Apply SBUS ranges for the QEC parent. */
-	prom_apply_sbus_ranges(bp->qec_sbus_dev->my_bus,
-			       &bp->qec_sbus_dev->reg_addrs[0],
-			       bp->qec_sbus_dev->num_registers,
-			       bp->qec_sbus_dev);
-
 	/* Map in QEC global control registers. */
-	bp->gregs = sparc_alloc_io(bp->qec_sbus_dev->reg_addrs[0].phys_addr,
-				   0,
-				   sizeof(struct qe_globreg),
-				   "BigMAC QEC Global Regs",
-				   bp->qec_sbus_dev->reg_addrs[0].which_io,
-				   0);
-	if(!bp->gregs) {
-		printk("BIGMAC: Cannot map QEC global registers.\n");
+	bp->gregs = sbus_ioremap(&bp->qec_sdev->resource[0], 0,
+				 GLOB_REG_SIZE, "BigMAC QEC GLobal Regs");
+	if (!bp->gregs) {
+		printk(KERN_ERR "BIGMAC: Cannot map QEC global registers.\n");
 		goto fail_and_cleanup;
 	}
 
 	/* Make sure QEC is in BigMAC mode. */
-	if((bp->gregs->ctrl & 0xf0000000) != GLOB_CTRL_BMODE) {
-		printk("BigMAC: AIEEE, QEC is not in BigMAC mode!\n");
+	if ((sbus_readl(bp->gregs + GLOB_CTRL) & 0xf0000000) != GLOB_CTRL_BMODE) {
+		printk(KERN_ERR "BigMAC: AIEEE, QEC is not in BigMAC mode!\n");
 		goto fail_and_cleanup;
 	}
 
 	/* Reset the QEC. */
-	if(qec_global_reset(bp->gregs))
+	if (qec_global_reset(bp->gregs))
 		goto fail_and_cleanup;
 
 	/* Get supported SBUS burst sizes. */
-	bsizes = prom_getintdefault(bp->qec_sbus_dev->prom_node,
+	bsizes = prom_getintdefault(bp->qec_sdev->prom_node,
 				    "burst-sizes",
 				    0xff);
 
-	bsizes_more = prom_getintdefault(bp->qec_sbus_dev->my_bus->prom_node,
+	bsizes_more = prom_getintdefault(bp->qec_sdev->bus->prom_node,
 					 "burst-sizes",
 					 0xff);
 
 	bsizes &= 0xff;
-	if(bsizes_more != 0xff)
+	if (bsizes_more != 0xff)
 		bsizes &= bsizes_more;
-	if(bsizes == 0xff || (bsizes & DMA_BURST16) == 0 ||
-	   (bsizes & DMA_BURST32) == 0)
+	if (bsizes == 0xff || (bsizes & DMA_BURST16) == 0 ||
+	    (bsizes & DMA_BURST32) == 0)
 		bsizes = (DMA_BURST32 - 1);
 	bp->bigmac_bursts = bsizes;
 
@@ -1372,40 +1136,28 @@
 	qec_init(bp);
 
 	/* Map in the BigMAC channel registers. */
-	bp->creg = sparc_alloc_io(bp->bigmac_sbus_dev->reg_addrs[0].phys_addr,
-				  0,
-				  sizeof(struct qe_creg),
-				  "BigMAC QEC Channel Regs",
-				  bp->bigmac_sbus_dev->reg_addrs[0].which_io,
-				  0);
-	if(!bp->creg) {
-		printk("BIGMAC: Cannot map QEC channel registers.\n");
+	bp->creg = sbus_ioremap(&bp->bigmac_sdev->resource[0], 0,
+				CREG_REG_SIZE, "BigMAC QEC Channel Regs");
+	if (!bp->creg) {
+		printk(KERN_ERR "BIGMAC: Cannot map QEC channel registers.\n");
 		goto fail_and_cleanup;
 	}
 
 	/* Map in the BigMAC control registers. */
-	bp->bregs = sparc_alloc_io(bp->bigmac_sbus_dev->reg_addrs[1].phys_addr,
-				   0,
-				   sizeof(struct BIG_MAC_regs),
-				   "BigMAC Primary Regs",
-				   bp->bigmac_sbus_dev->reg_addrs[1].which_io,
-				   0);
-	if(!bp->bregs) {
-		printk("BIGMAC: Cannot map BigMAC primary registers.\n");
+	bp->bregs = sbus_ioremap(&bp->bigmac_sdev->resource[1], 0,
+				 BMAC_REG_SIZE, "BigMAC Primary Regs");
+	if (!bp->bregs) {
+		printk(KERN_ERR "BIGMAC: Cannot map BigMAC primary registers.\n");
 		goto fail_and_cleanup;
 	}
 
 	/* Map in the BigMAC transceiver registers, this is how you poke at
 	 * the BigMAC's PHY.
 	 */
-	bp->tregs = sparc_alloc_io(bp->bigmac_sbus_dev->reg_addrs[2].phys_addr,
-				   0,
-				   sizeof(struct bmac_tcvr),
-				   "BigMAC Transceiver Regs",
-				   bp->bigmac_sbus_dev->reg_addrs[2].which_io,
-				   0);
-	if(!bp->tregs) {
-		printk("BIGMAC: Cannot map BigMAC transceiver registers.\n");
+	bp->tregs = sbus_ioremap(&bp->bigmac_sdev->resource[2], 0,
+				 TCVR_REG_SIZE, "BigMAC Transceiver Regs");
+	if (!bp->tregs) {
+		printk(KERN_ERR "BIGMAC: Cannot map BigMAC transceiver registers.\n");
 		goto fail_and_cleanup;
 	}
 
@@ -1413,27 +1165,18 @@
 	bigmac_stop(bp);
 
 	/* Allocate transmit/receive descriptor DVMA block. */
-	bp->bmac_block = (struct bmac_init_block *)
-		sparc_dvma_malloc(PAGE_SIZE, "BigMAC Init Block",
-				  &bp->bblock_dvma);
+	bp->bmac_block = sbus_alloc_consistant(bp->bigmac_sdev,
+					       PAGE_SIZE,
+					       &bp->bblock_dvma);
+	if (bp->bmac_block == NULL || bp->bblock_dvma == 0) {
+		printk(KERN_ERR "BIGMAC: Cannot allocate consistant DMA.\n");
+		goto fail_and_cleanup;
+	}
 
 	/* Get the board revision of this BigMAC. */
-	bp->board_rev = prom_getintdefault(bp->bigmac_sbus_dev->prom_node,
+	bp->board_rev = prom_getintdefault(bp->bigmac_sdev->prom_node,
 					   "board-version", 1);
 
-	/* If on sun4c, we use a static buffer pool, on sun4m we DMA directly
-	 * in and out of sk_buffs instead for speed and one copy to userspace.
-	 */
-#ifndef __sparc_v9__
-	if(sparc_cpu_model == sun4c)
-		bp->sun4c_buffers = (struct bigmac_buffers *)
-			sparc_dvma_malloc(sizeof(struct bigmac_buffers),
-					  "BigMAC Bufs",
-					  &bp->s4c_buf_dvma);
-	else
-#endif
-		bp->sun4c_buffers = 0;
-
 	/* Init auto-negotiation timer state. */
 	init_timer(&bp->bigmac_timer);
 	bp->timer_state = asleep;
@@ -1445,21 +1188,14 @@
 	/* Set links to our BigMAC open and close routines. */
 	dev->open = &bigmac_open;
 	dev->stop = &bigmac_close;
-
-	/* Choose transmit routine based upon buffering scheme. */
-#ifndef __sparc_v9__
-	if(sparc_cpu_model == sun4c)
-		dev->hard_start_xmit = &sun4c_bigmac_start_xmit;
-	else
-#endif
-		dev->hard_start_xmit = &bigmac_start_xmit;
+	dev->hard_start_xmit = &bigmac_start_xmit;
 
 	/* Set links to BigMAC statistic and multi-cast loading code. */
 	dev->get_stats = &bigmac_get_stats;
 	dev->set_multicast_list = &bigmac_set_multicast;
 
 	/* Finish net device registration. */
-	dev->irq = bp->bigmac_sbus_dev->irqs[0];
+	dev->irq = bp->bigmac_sdev->irqs[0];
 	dev->dma = 0;
 	ether_setup(dev);
 
@@ -1472,18 +1208,22 @@
 
 fail_and_cleanup:
 	/* Something went wrong, undo whatever we did so far. */
-	if(bp) {
+	if (bp) {
 		/* Free register mappings if any. */
-		if(bp->gregs)
-			sparc_free_io(bp->gregs, sizeof(struct qe_globreg));
-		if(bp->creg)
-			sparc_free_io(bp->creg, sizeof(struct qe_creg));
-		if(bp->bregs)
-			sparc_free_io(bp->bregs, sizeof(struct BIG_MAC_regs));
-		if(bp->tregs)
-			sparc_free_io(bp->tregs, sizeof(struct bmac_tcvr));
-
-		/* XXX todo, bmac_block and sun4c_buffers */
+		if (bp->gregs)
+			sbus_iounmap(bp->gregs, GLOB_REG_SIZE);
+		if (bp->creg)
+			sbus_iounmap(bp->creg, CREG_REG_SIZE);
+		if (bp->bregs)
+			sbus_iounmap(bp->bregs, BMAC_REG_SIZE);
+		if (bp->tregs)
+			sbus_iounmap(bp->tregs, TCVR_REG_SIZE);
+
+		if (bp->bmac_block)
+			sbus_free_consistant(bp->bigmac_sdev,
+					     PAGE_SIZE,
+					     bp->bmac_block,
+					     bp->bblock_dvma);
 
 		/* Free the BigMAC softc. */
 		kfree(bp);
@@ -1492,34 +1232,50 @@
 	return res;	/* Return error code. */
 }
 
+/* QEC can be the parent of either QuadEthernet or
+ * a BigMAC.  We want the latter.
+ */
+static int __init bigmac_match(struct sbus_dev *sdev)
+{
+	struct sbus_dev *child = sdev->child;
+
+	if (strcmp(sdev->prom_name, "qec") != 0)
+		return 0;
+
+	if (child == NULL)
+		return 0;
+
+	if (strcmp(child->prom_name, "be") != 0)
+		return 0;
+
+	return 1;
+}
+
 int __init bigmac_probe(void)
 {
 	struct net_device *dev = NULL;
-	struct linux_sbus *bus;
-	struct linux_sbus_device *sdev = 0;
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev = 0;
 	static int called = 0;
 	int cards = 0, v;
 
-	if(called)
+	if (called)
 		return ENODEV;
 	called++;
 
-	for_each_sbus(bus) {
-		for_each_sbusdev(sdev, bus) {
-			if(cards) dev = NULL;
-
-			/* QEC can be the parent of either QuadEthernet or
-			 * a BigMAC.  We want the latter.
-			 */
-			if(!strcmp(sdev->prom_name, "qec") && sdev->child &&
-			   !strcmp(sdev->child->prom_name, "be")) {
+	for_each_sbus(sbus) {
+		for_each_sbusdev(sdev, sbus) {
+			if (cards)
+				dev = NULL;
+
+			if (bigmac_match(sdev)) {
 				cards++;
-				if((v = bigmac_ether_init(dev, sdev)))
-				   return v;
+				if ((v = bigmac_ether_init(dev, sdev)))
+					return v;
 			}
 		}
 	}
-	if(!cards)
+	if (!cards)
 		return ENODEV;
 	return 0;
 }
@@ -1541,12 +1297,14 @@
 		struct bigmac *bp = root_bigmac_dev;
 		struct bigmac *bp_nxt = root_bigmac_dev->next_module;
 
-		sparc_free_io(bp->gregs, sizeof(struct qe_globreg));
-		sparc_free_io(bp->creg, sizeof(struct qe_creg));
-		sparc_free_io(bp->bregs, sizeof(struct BIG_MAC_regs));
-		sparc_free_io(bp->tregs, sizeof(struct bmac_tcvr));
-
-		/* XXX todo, bmac_block and sun4c_buffers */
+		sbus_iounmap(bp->gregs, GLOB_REG_SIZE);
+		sbus_iounmap(bp->creg, CREG_REG_SIZE);
+		sbus_iounmap(bp->bregs, BMAC_REG_SIZE);
+		sbus_iounmap(bp->tregs, TCVR_REG_SIZE);
+		sbus_free_consistant(bp->bigmac_sdev,
+				     PAGE_SIZE,
+				     bp->bmac_block,
+				     bp->bblock_dvma);
 
 		unregister_netdev(bp->dev);
 		kfree(bp->dev);
diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunbmac.h linux/drivers/net/sunbmac.h
--- v2.3.34/linux/drivers/net/sunbmac.h	Wed Aug 18 11:36:45 1999
+++ linux/drivers/net/sunbmac.h	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,5 @@
-/* sunbmac.h: Defines for the Sun "Big MAC" 100baseT ethernet cards.
+/* $Id: sunbmac.h,v 1.5 1999/09/21 14:36:26 davem Exp $
+ * sunbmac.h: Defines for the Sun "Big MAC" 100baseT ethernet cards.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  */
@@ -7,14 +8,13 @@
 #define _SUNBMAC_H
 
 /* QEC global registers. */
-struct qe_globreg {
-	volatile unsigned int ctrl;      /* Control                  */
-	volatile unsigned int stat;      /* Status                   */
-	volatile unsigned int psize;     /* Packet Size              */
-	volatile unsigned int msize;     /* Local-mem size (64K)     */
-	volatile unsigned int rsize;     /* Receive partition size   */
-	volatile unsigned int tsize;     /* Transmit partition size  */
-};
+#define GLOB_CTRL	0x00UL	/* Control                  */
+#define GLOB_STAT	0x04UL	/* Status                   */
+#define GLOB_PSIZE	0x08UL	/* Packet Size              */
+#define GLOB_MSIZE	0x0cUL	/* Local-mem size (64K)     */
+#define GLOB_RSIZE	0x10UL	/* Receive partition size   */
+#define GLOB_TSIZE	0x14UL	/* Transmit partition size  */
+#define GLOB_REG_SIZE	0x18UL
 
 #define GLOB_CTRL_MMODE       0x40000000 /* MACE qec mode            */
 #define GLOB_CTRL_BMODE       0x10000000 /* BigMAC qec mode          */
@@ -36,21 +36,20 @@
 #define GLOB_PSIZE_8192       0x11       /* 8k packet size           */
 
 /* QEC BigMAC channel registers. */
-struct qe_creg {
-	volatile unsigned int ctrl;       /* Control                     */
-	volatile unsigned int stat;       /* Status                      */
-	volatile unsigned int rxds;       /* RX descriptor ring ptr      */
-	volatile unsigned int txds;       /* TX descriptor ring ptr      */
-	volatile unsigned int rimask;     /* RX Interrupt Mask           */
-	volatile unsigned int timask;     /* TX Interrupt Mask           */
-	volatile unsigned int qmask;      /* QEC Error Interrupt Mask    */
-	volatile unsigned int bmask;      /* BigMAC Error Interrupt Mask */
-	volatile unsigned int rxwbufptr;  /* Local memory rx write ptr   */
-	volatile unsigned int rxrbufptr;  /* Local memory rx read ptr    */
-	volatile unsigned int txwbufptr;  /* Local memory tx write ptr   */
-	volatile unsigned int txrbufptr;  /* Local memory tx read ptr    */
-	volatile unsigned int ccnt;       /* Collision Counter           */
-};
+#define CREG_CTRL	0x00UL	/* Control                   */
+#define CREG_STAT	0x04UL	/* Status                    */
+#define CREG_RXDS	0x08UL	/* RX descriptor ring ptr    */
+#define CREG_TXDS	0x0cUL	/* TX descriptor ring ptr    */
+#define CREG_RIMASK	0x10UL	/* RX Interrupt Mask         */
+#define CREG_TIMASK	0x14UL	/* TX Interrupt Mask         */
+#define CREG_QMASK	0x18UL	/* QEC Error Interrupt Mask  */
+#define CREG_BMASK	0x1cUL	/* BigMAC Error Interrupt Mask*/
+#define CREG_RXWBUFPTR	0x20UL	/* Local memory rx write ptr */
+#define CREG_RXRBUFPTR	0x24UL	/* Local memory rx read ptr  */
+#define CREG_TXWBUFPTR	0x28UL	/* Local memory tx write ptr */
+#define CREG_TXRBUFPTR	0x2cUL	/* Local memory tx read ptr  */
+#define CREG_CCNT	0x30UL	/* Collision Counter         */
+#define CREG_REG_SIZE	0x34UL
 
 #define CREG_CTRL_TWAKEUP     0x00000001  /* Transmitter Wakeup, 'go'. */
 
@@ -82,56 +81,56 @@
 #define CREG_QMASK_RXPERR     0x00000002  /* RX parity error           */
 #define CREG_QMASK_RXSERR     0x00000001  /* RX sbus error ack         */
 
-struct BIG_MAC_regs {
-	volatile unsigned int xif_cfg;		/* XIF config register                */
-	volatile unsigned int _unused[63];	/* Reserved...                        */
-	volatile unsigned int status;		/* Status register, clear on read     */
-	volatile unsigned int imask;		/* Interrupt mask register            */
-	volatile unsigned int _unused2[64];	/* Reserved...                        */
-	volatile unsigned int tx_swreset;	/* Transmitter software reset         */
-	volatile unsigned int tx_cfg;           /* Transmitter config register        */
-	volatile unsigned int ipkt_gap1;	/* Inter-packet gap 1                 */
-	volatile unsigned int ipkt_gap2;	/* Inter-packet gap 2                 */
-	volatile unsigned int attempt_limit;	/* Transmit attempt limit             */
-	volatile unsigned int stime;		/* Transmit slot time                 */
-	volatile unsigned int preamble_len;	/* Size of transmit preamble          */
-	volatile unsigned int preamble_pattern;	/* Pattern for transmit preamble      */
-	volatile unsigned int tx_sframe_delim;	/* Transmit delimiter                 */
-	volatile unsigned int jsize;		/* Toe jam...                         */
-	volatile unsigned int tx_pkt_max;	/* Transmit max pkt size              */
-	volatile unsigned int tx_pkt_min;	/* Transmit min pkt size              */
-	volatile unsigned int peak_attempt;	/* Count of transmit peak attempts    */
-	volatile unsigned int dt_ctr;		/* Transmit defer timer               */
-	volatile unsigned int nc_ctr;           /* Transmit normal-collision counter  */
-	volatile unsigned int fc_ctr;           /* Transmit first-collision counter   */
-	volatile unsigned int ex_ctr;           /* Transmit excess-collision counter  */
-	volatile unsigned int lt_ctr;           /* Transmit late-collision counter    */
-	volatile unsigned int rand_seed;        /* Transmit random number seed        */
-	volatile unsigned int tx_smachine;      /* Transmit state machine             */
-	volatile unsigned int _unused3[44];     /* Reserved                           */
-	volatile unsigned int rx_swreset;       /* Receiver software reset            */
-	volatile unsigned int rx_cfg;           /* Receiver config register           */
-	volatile unsigned int rx_pkt_max;       /* Receive max pkt size               */
-	volatile unsigned int rx_pkt_min;       /* Receive min pkt size               */
-	volatile unsigned int mac_addr2;        /* Ether address register 2           */
-	volatile unsigned int mac_addr1;        /* Ether address register 1           */
-	volatile unsigned int mac_addr0;        /* Ether address register 0           */
-	volatile unsigned int fr_ctr;           /* Receive frame receive counter      */
-	volatile unsigned int gle_ctr;          /* Receive giant-length error counter */
-	volatile unsigned int unale_ctr;        /* Receive unaligned error counter    */
-	volatile unsigned int rcrce_ctr;        /* Receive CRC error counter          */
-	volatile unsigned int rx_smachine;      /* Receiver state machine             */
-	volatile unsigned int rx_cvalid;        /* Receiver code violation            */
-	volatile unsigned int _unused4;         /* Reserved...                        */
-	volatile unsigned int htable3;          /* Hash table 3                       */
-	volatile unsigned int htable2;          /* Hash table 2                       */
-	volatile unsigned int htable1;          /* Hash table 1                       */
-	volatile unsigned int htable0;          /* Hash table 0                       */
-	volatile unsigned int afilter2;         /* Address filter 2                   */
-	volatile unsigned int afilter1;         /* Address filter 1                   */
-	volatile unsigned int afilter0;         /* Address filter 0                   */
-	volatile unsigned int afilter_mask;     /* Address filter mask                */
-};
+/* BIGMAC core registers */
+#define BMAC_XIFCFG	0x000UL	/* XIF config register                */
+	/* 0x004-->0x0fc, reserved */
+#define BMAC_STATUS	0x100UL	/* Status register, clear on read     */
+#define BMAC_IMASK	0x104UL	/* Interrupt mask register            */
+	/* 0x108-->0x204, reserved */
+#define BMAC_TXSWRESET	0x208UL	/* Transmitter software reset         */
+#define BMAC_TXCFG	0x20cUL	/* Transmitter config register        */
+#define BMAC_IGAP1	0x210UL	/* Inter-packet gap 1                 */
+#define BMAC_IGAP2	0x214UL	/* Inter-packet gap 2                 */
+#define BMAC_ALIMIT	0x218UL	/* Transmit attempt limit             */
+#define BMAC_STIME	0x21cUL	/* Transmit slot time                 */
+#define BMAC_PLEN	0x220UL	/* Size of transmit preamble          */
+#define BMAC_PPAT	0x224UL	/* Pattern for transmit preamble      */
+#define BMAC_TXDELIM	0x228UL	/* Transmit delimiter                 */
+#define BMAC_JSIZE	0x22cUL	/* Toe jam...                         */
+#define BMAC_TXPMAX	0x230UL	/* Transmit max pkt size              */
+#define BMAC_TXPMIN	0x234UL	/* Transmit min pkt size              */
+#define BMAC_PATTEMPT	0x238UL	/* Count of transmit peak attempts    */
+#define BMAC_DTCTR	0x23cUL	/* Transmit defer timer               */
+#define BMAC_NCCTR	0x240UL	/* Transmit normal-collision counter  */
+#define BMAC_FCCTR	0x244UL	/* Transmit first-collision counter   */
+#define BMAC_EXCTR	0x248UL	/* Transmit excess-collision counter  */
+#define BMAC_LTCTR	0x24cUL	/* Transmit late-collision counter    */
+#define BMAC_RSEED	0x250UL	/* Transmit random number seed        */
+#define BMAC_TXSMACHINE	0x254UL /* Transmit state machine             */
+	/* 0x258-->0x304, reserved */
+#define BMAC_RXSWRESET	0x308UL	/* Receiver software reset            */
+#define BMAC_RXCFG	0x30cUL	/* Receiver config register           */
+#define BMAC_RXPMAX	0x310UL	/* Receive max pkt size               */
+#define BMAC_RXPMIN	0x314UL	/* Receive min pkt size               */
+#define BMAC_MACADDR2	0x318UL	/* Ether address register 2           */
+#define BMAC_MACADDR1	0x31cUL	/* Ether address register 1           */
+#define BMAC_MACADDR0	0x320UL	/* Ether address register 0           */
+#define BMAC_FRCTR	0x324UL	/* Receive frame receive counter      */
+#define BMAC_GLECTR	0x328UL	/* Receive giant-length error counter */
+#define BMAC_UNALECTR	0x32cUL	/* Receive unaligned error counter    */
+#define BMAC_RCRCECTR	0x330UL	/* Receive CRC error counter          */
+#define BMAC_RXSMACHINE	0x334UL	/* Receiver state machine             */
+#define BMAC_RXCVALID	0x338UL	/* Receiver code violation            */
+	/* 0x33c, reserved */
+#define BMAC_HTABLE3	0x340UL	/* Hash table 3                       */
+#define BMAC_HTABLE2	0x344UL	/* Hash table 2                       */
+#define BMAC_HTABLE1	0x348UL	/* Hash table 1                       */
+#define BMAC_HTABLE0	0x34cUL	/* Hash table 0                       */
+#define BMAC_AFILTER2	0x350UL	/* Address filter 2                   */
+#define BMAC_AFILTER1	0x354UL	/* Address filter 1                   */
+#define BMAC_AFILTER0	0x358UL	/* Address filter 0                   */
+#define BMAC_AFMASK	0x35cUL	/* Address filter mask                */
+#define BMAC_REG_SIZE	0x360UL
 
 /* BigMac XIF config register. */
 #define BIGMAC_XCFG_ODENABLE   0x00000001 /* Output driver enable                     */
@@ -197,10 +196,9 @@
 /* The BigMAC PHY transceiver.  Not nearly as sophisticated as the happy meal
  * one.  But it does have the "bit banger", oh baby.
  */
-struct bmac_tcvr {
-	unsigned int	tcvr_pal;
-	unsigned int    mgmt_pal;
-};
+#define TCVR_TPAL	0x00UL
+#define TCVR_MPAL	0x04UL
+#define TCVR_REG_SIZE	0x08UL
 
 /* Frame commands. */
 #define FRAME_WRITE           0x50020000
@@ -244,8 +242,8 @@
 
 /* Ring descriptors and such, same as Quad Ethernet. */
 struct be_rxd {
-	unsigned int rx_flags;
-	unsigned int rx_addr;
+	u32 rx_flags;
+	u32 rx_addr;
 };
 
 #define RXD_OWN      0x80000000 /* Ownership.      */
@@ -253,8 +251,8 @@
 #define RXD_LENGTH   0x000007ff /* Packet Length.  */
 
 struct be_txd {
-	unsigned int tx_flags;
-	unsigned int tx_addr;
+	u32 tx_flags;
+	u32 tx_addr;
 };
 
 #define TXD_OWN      0x80000000 /* Ownership.      */
@@ -280,13 +278,7 @@
 			    (bp)->tx_old - (bp)->tx_new - 1)
 
 
-#define SUN4C_TX_BUFFS_AVAIL(bp)                                    \
-        (((bp)->tx_old <= (bp)->tx_new) ?                           \
-	  (bp)->tx_old + (SUN4C_TX_RING_SIZE - 1) - (bp)->tx_new :  \
-	  (bp)->tx_old - (bp)->tx_new - (TX_RING_SIZE - SUN4C_TX_RING_SIZE))
-
-
-#define RX_COPY_THRESHOLD  128
+#define RX_COPY_THRESHOLD  256
 #define RX_BUF_ALLOC_SIZE  (ETH_FRAME_LEN + (64 * 3))
 
 struct bmac_init_block {
@@ -297,22 +289,6 @@
 #define bib_offset(mem, elem) \
 ((__u32)((unsigned long)(&(((struct bmac_init_block *)0)->mem[elem]))))
 
-#define SUN4C_PKT_BUF_SZ	1546
-#define SUN4C_RX_BUFF_SIZE	SUN4C_PKT_BUF_SZ
-#define SUN4C_TX_BUFF_SIZE	SUN4C_PKT_BUF_SZ
-
-#define SUN4C_RX_RING_SIZE	16
-#define SUN4C_TX_RING_SIZE	16
-
-struct bigmac_buffers {
-	char	tx_buf[SUN4C_TX_RING_SIZE][SUN4C_TX_BUFF_SIZE];
-	char	pad[2];		/* Align rx_buf for copy_and_sum(). */
-	char	rx_buf[SUN4C_RX_RING_SIZE][SUN4C_RX_BUFF_SIZE];
-};
-
-#define bbuf_offset(mem, elem) \
-((__u32)((unsigned long)(&(((struct bigmac_buffers *)0)->mem[elem][0]))))
-
 /* Now software state stuff. */
 enum bigmac_transceiver {
 	external = 0,
@@ -327,21 +303,18 @@
 };
 
 struct bigmac {
-	struct qe_globreg	*gregs;		/* QEC Global Registers               */
-	struct qe_creg		*creg;		/* QEC BigMAC Channel Registers       */
-	struct BIG_MAC_regs	*bregs;         /* BigMAC Registers                   */
-	struct bmac_tcvr	*tregs;         /* BigMAC Transceiver                 */
-	struct bmac_init_block	*bmac_block;	/* RX and TX descriptors              */
-	__u32			 bblock_dvma;	/* RX and TX descriptors              */
+	unsigned long	gregs;	/* QEC Global Registers               */
+	unsigned long	creg;	/* QEC BigMAC Channel Registers       */
+	unsigned long	bregs;	/* BigMAC Registers                   */
+	unsigned long	tregs;	/* BigMAC Transceiver                 */
+	struct bmac_init_block	*bmac_block;	/* RX and TX descriptors */
+	__u32			 bblock_dvma;	/* RX and TX descriptors */
 
 	struct sk_buff		*rx_skbs[RX_RING_SIZE];
 	struct sk_buff		*tx_skbs[TX_RING_SIZE];
 
 	int rx_new, tx_new, rx_old, tx_old;
 
-	struct bigmac_buffers	*sun4c_buffers;
-	__u32			 s4c_buf_dvma;
-
 	int board_rev;				/* BigMAC board revision.             */
 
 	enum bigmac_transceiver	tcvr_type;
@@ -353,11 +326,11 @@
 	enum bigmac_timer_state	timer_state;
 	unsigned int		timer_ticks;
 
-	struct enet_statistics		enet_stats;
-	struct linux_sbus_device	*qec_sbus_dev;
-	struct linux_sbus_device	*bigmac_sbus_dev;
-	struct net_device			*dev;
-	struct bigmac			*next_module;
+	struct enet_statistics	enet_stats;
+	struct sbus_dev		*qec_sdev;
+	struct sbus_dev		*bigmac_sdev;
+	struct net_device	*dev;
+	struct bigmac		*next_module;
 };
 
 /* We use this to acquire receive skb's that we can DMA directly into. */
diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.3.34/linux/drivers/net/sunhme.c	Thu Nov 11 20:11:42 1999
+++ linux/drivers/net/sunhme.c	Mon Dec 20 22:06:42 1999
@@ -1,12 +1,13 @@
-/* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
+/* $Id: sunhme.c,v 1.84 1999/12/15 14:08:03 davem Exp $
+ * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
  *           auto carrier detecting ethernet driver.  Also known as the
  *           "Happy Meal Ethernet" found on SunSwift SBUS cards.
  *
- * Copyright (C) 1996, 1998 David S. Miller (davem@caipfs.rutgers.edu)
+ * Copyright (C) 1996, 1998, 1999 David S. Miller (davem@redhat.com)
  */
 
 static char *version =
-        "sunhme.c:v1.10 27/Jan/99 David S. Miller (davem@caipfs.rutgers.edu)\n";
+        "sunhme.c:v1.99 12/Sep/99 David S. Miller (davem@redhat.com)\n";
 
 #include <linux/module.h>
 
@@ -103,7 +104,7 @@
 	int i, this;
 
 	this = txlog_cur_entry;
-	for(i = 0; i < TX_LOG_LEN; i++) {
+	for (i = 0; i < TX_LOG_LEN; i++) {
 		printk("TXLOG[%d]: j[%08x] tx[N(%d)O(%d)] action[%08x] stat[%08x]\n", i,
 		       tx_log[this].tstamp,
 		       tx_log[this].tx_new, tx_log[this].tx_old,
@@ -117,7 +118,7 @@
 	struct happy_meal_txd *tp = &hb->happy_meal_txd[0];
 	int i;
 
-	for(i = 0; i < TX_RING_SIZE; i+=4) {
+	for (i = 0; i < TX_RING_SIZE; i+=4) {
 		printk("TXD[%d..%d]: [%08x:%08x] [%08x:%08x] [%08x:%08x] [%08x:%08x]\n",
 		       i, i + 4,
 		       le32_to_cpu(tp[i].tx_flags), le32_to_cpu(tp[i].tx_addr),
@@ -151,53 +152,225 @@
 #define DEFAULT_IPG2       4 /* For all modes */
 #define DEFAULT_JAMSIZE    4 /* Toe jam */
 
-/* Oh yes, the MIF BitBang is mighty fun to program.  BitBucket is more like it. */
-#define BB_PUT_BIT(hp, tregs, bit)						\
-do {	hme_write32(hp, &(tregs)->bb_data, (bit));				\
-	hme_write32(hp, &(tregs)->bb_clock, 0);					\
-	hme_write32(hp, &(tregs)->bb_clock, 1);					\
+#if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
+static void sbus_hme_write32(unsigned long reg, u32 val)
+{
+	sbus_writel(val, reg);
+}
+
+static u32 sbus_hme_read32(unsigned long reg)
+{
+	return sbus_readl(reg);
+}
+
+static void sbus_hme_write_rxd(struct happy_meal_rxd *rxd, u32 flags, u32 addr)
+{
+	rxd->rx_addr = addr;
+	rxd->rx_flags = flags;
+}
+
+static void sbus_hme_write_txd(struct happy_meal_txd *txd, u32 flags, u32 addr)
+{
+	txd->tx_flags = flags;
+	txd->tx_addr = addr;
+}
+
+static u32 sbus_hme_read_desc32(u32 *p)
+{
+	return *p;
+}
+
+static void pci_hme_write32(unsigned long reg, u32 val)
+{
+	writel(val, reg);
+}
+
+static u32 pci_hme_read32(unsigned long reg)
+{
+	return readl(reg);
+}
+
+static void pci_hme_write_rxd(struct happy_meal_rxd *rxd, u32 flags, u32 addr)
+{
+	rxd->rx_addr = cpu_to_le32(addr);
+	rxd->rx_flags = cpu_to_le32(flags);
+}
+
+static void pci_hme_write_txd(struct happy_meal_txd *txd, u32 flags, u32 addr)
+{
+	txd->tx_flags = cpu_to_le32(flags);
+	txd->tx_addr = cpu_to_le32(addr);
+}
+
+static u32 pci_hme_read_desc32(u32 *p)
+{
+	return cpu_to_le32(*p);
+}
+
+/* XXX Convert these to direct function hookup once new
+ * XXX PCI dvma interfaces are propagated and in use everywhere.
+ */
+static u32 pci_hme_dma_map(void *device, void *ptr, long size)
+{
+#if 1
+	return virt_to_bus(ptr);
+#else
+	struct pci_dev *pdev = device;
+
+	return pci_map_single(pdev, ptr, size);
+#endif
+}
+
+static void pci_hme_dma_unmap(void *device, u32 dma_addr, long size)
+{
+#if 1
+	return;
+#else
+	struct pci_dev *pdev = device;
+
+	pci_unmap_single(pdev, dma_addr, size);
+#endif
+}
+
+static void pci_hme_dma_sync(void *device, u32 dma_addr, long size)
+{
+#if 1
+	return;
+#else
+	struct pci_dev *pdev = device;
+
+	pci_dma_sync_single(pdev, dma_addr, size);
+#endif
+}
+
+#define hme_write32(__hp, __reg, __val) \
+	((__hp)->write32((__reg), (__val)))
+#define hme_read32(__hp, __reg) \
+	((__hp)->read32(__reg))
+#define hme_write_rxd(__hp, __rxd, __flags, __addr) \
+	((__hp)->write_rxd((__rxd), (__flags), (__addr)))
+#define hme_write_txd(__hp, __txd, __flags, __addr) \
+	((__hp)->write_txd((__txd), (__flags), (__addr)))
+#define hme_read_desc32(__hp, __p) \
+	((__hp)->read_desc32(__p))
+#define hme_dma_map(__hp, __ptr, __size) \
+	((__hp)->dma_map((__hp)->happy_dev, (__ptr), (__size)))
+#define hme_dma_unmap(__hp, __addr, __size) \
+	((__hp)->dma_unmap((__hp)->happy_dev, (__addr), (__size)))
+#define hme_dma_sync(__hp, __addr, __size) \
+	((__hp)->dma_sync((__hp)->happy_dev, (__addr), (__size)))
+#else
+#ifdef CONFIG_SBUS
+/* SBUS only compilation */
+#define hme_write32(__hp, __reg, __val) \
+	sbus_writel((__val), (__reg))
+#define hme_read32(__hp, __reg) \
+	sbus_readl(__reg)
+#define hme_write_rxd(__hp, __rxd, __flags, __addr) \
+do {	(__rxd)->rx_addr = (__addr); \
+	(__rxd)->rx_flags = (__flags); \
+} while(0)
+#define hme_write_txd(__hp, __txd, __flags, __addr) \
+do {	(__txd)->tx_addr = (__addr); \
+	(__txd)->tx_flags = (__flags); \
 } while(0)
+#define hme_read_desc32(__hp, __p)	(*(__p))
+#define hme_dma_map(__hp, __ptr, __size) \
+	sbus_map_single((__hp)->happy_dev, (__ptr), (__size))
+#define hme_dma_unmap(__hp, __addr, __size) \
+	sbus_unmap_single((__hp)->happy_dev, (__addr), (__size))
+#define hme_dma_sync(__hp, __addr, __size) \
+	sbus_dma_sync_single((__hp)->happy_dev, (__addr), (__size))
+#else
+/* PCI only compilation */
+#define hme_write32(__hp, __reg, __val) \
+	writel((__val), (__reg))
+#define hme_read32(__hp, __reg) \
+	readl(__reg)
+#define hme_write_rxd(__hp, __rxd, __flags, __addr) \
+do {	(__rxd)->rx_addr = cpu_to_le32(__addr); \
+	(__rxd)->rx_flags = cpu_to_le32(__flags); \
+} while(0)
+#define hme_write_txd(__hp, __txd, __flags, __addr) \
+do {	(__txd)->tx_addr = cpu_to_le32(__addr); \
+	(__txd)->tx_flags = cpu_to_le32(__flags); \
+} while(0)
+#define hme_read_desc32(__hp, __p)	cpu_to_le32(*(__p))
+#if 0 /* XXX Once new PCI interfaces are in place... XXX */
+#define hme_dma_map(__hp, __ptr, __size) \
+	pci_map_single((__hp)->happy_dev, (__ptr), (__size))
+#define hme_dma_unmap(__hp, __addr, __size) \
+	pci_unmap_single((__hp)->happy_dev, (__addr), (__size))
+#define hme_dma_sync(__hp, __addr, __size) \
+	pci_dma_sync_single((__hp)->happy_dev, (__addr), (__size))
+#else
+#define hme_dma_map(__hp, __ptr, __size) \
+	(virt_to_bus(__ptr))
+#define hme_dma_unmap(__hp, __addr, __size) \
+	do { } while(0)
+#define hme_dma_sync(__hp, __addr, __size) \
+	do { } while(0)
+#endif
+#endif
+#endif
+
+/* Oh yes, the MIF BitBang is mighty fun to program.  BitBucket is more like it. */
+static void BB_PUT_BIT(struct happy_meal *hp, unsigned long tregs, int bit)
+{
+	hme_write32(hp, tregs + TCVR_BBDATA, bit);
+	hme_write32(hp, tregs + TCVR_BBCLOCK, 0);
+	hme_write32(hp, tregs + TCVR_BBCLOCK, 1);
+}
+
+#if 0
+static u32 BB_GET_BIT(struct happy_meal *hp, unsigned long tregs, int internal)
+{
+	u32 ret;
+
+	hme_write32(hp, tregs + TCVR_BBCLOCK, 0);
+	hme_write32(hp, tregs + TCVR_BBCLOCK, 1);
+	ret = hme_read32(hp, tregs + TCVR_CFG);
+	if (internal)
+		ret &= TCV_CFG_MDIO0;
+	else
+		ret &= TCV_CFG_MDIO1;
+
+	return ret;
+}
+#endif
+
+static u32 BB_GET_BIT2(struct happy_meal *hp, unsigned long tregs, int internal)
+{
+	u32 retval;
 
-#define BB_GET_BIT(hp, tregs, internal)						\
-({										\
-	hme_write32(hp, &(tregs)->bb_clock, 0);					\
-	hme_write32(hp, &(tregs)->bb_clock, 1);					\
-	if(internal)								\
-		hme_read32(hp, &(tregs)->cfg) & TCV_CFG_MDIO0;			\
-	else									\
-		hme_read32(hp, &(tregs)->cfg) & TCV_CFG_MDIO1;			\
-})
-
-#define BB_GET_BIT2(hp, tregs, internal)					\
-({										\
-	int retval;								\
-	hme_write32(hp, &(tregs)->bb_clock, 0);					\
-	udelay(1);								\
-	if(internal)								\
-		retval = hme_read32(hp, &(tregs)->cfg) & TCV_CFG_MDIO0;		\
-	else									\
-		retval = hme_read32(hp, &(tregs)->cfg) & TCV_CFG_MDIO1;		\
-	hme_write32(hp, &(tregs)->bb_clock, 1);					\
-	retval;									\
-})
+	hme_write32(hp, tregs + TCVR_BBCLOCK, 0);
+	udelay(1);
+	retval = hme_read32(hp, tregs + TCVR_CFG);
+	if (internal)
+		retval &= TCV_CFG_MDIO0;
+	else
+		retval &= TCV_CFG_MDIO1;
+	hme_write32(hp, tregs + TCVR_BBCLOCK, 1);
+
+	return retval;
+}
 
 #define TCVR_FAILURE      0x80000000     /* Impossible MIF read value */
 
-static inline int happy_meal_bb_read(struct happy_meal *hp,
-				     struct hmeal_tcvregs *tregs, int reg)
+static int happy_meal_bb_read(struct happy_meal *hp,
+			      unsigned long tregs, int reg)
 {
-	volatile int unused;
-	unsigned long tmp;
+	u32 tmp;
 	int retval = 0;
 	int i;
 
 	ASD(("happy_meal_bb_read: reg=%d ", reg));
 
 	/* Enable the MIF BitBang outputs. */
-	hme_write32(hp, &tregs->bb_oenab, 1);
+	hme_write32(hp, tregs + TCVR_BBOENAB, 1);
 
 	/* Force BitBang into the idle state. */
-	for(i = 0; i < 32; i++)
+	for (i = 0; i < 32; i++)
 		BB_PUT_BIT(hp, tregs, 1);
 
 	/* Give it the read sequence. */
@@ -208,42 +381,42 @@
 
 	/* Give it the PHY address. */
 	tmp = hp->paddr & 0xff;
-	for(i = 4; i >= 0; i--)
+	for (i = 4; i >= 0; i--)
 		BB_PUT_BIT(hp, tregs, ((tmp >> i) & 1));
 
 	/* Tell it what register we want to read. */
 	tmp = (reg & 0xff);
-	for(i = 4; i >= 0; i--)
+	for (i = 4; i >= 0; i--)
 		BB_PUT_BIT(hp, tregs, ((tmp >> i) & 1));
 
 	/* Close down the MIF BitBang outputs. */
-	hme_write32(hp, &tregs->bb_oenab, 0);
+	hme_write32(hp, tregs + TCVR_BBOENAB, 0);
 
 	/* Now read in the value. */
-	unused = BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
-	for(i = 15; i >= 0; i--)
+	(void) BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
+	for (i = 15; i >= 0; i--)
 		retval |= BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
-	unused = BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
-	unused = BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
-	unused = BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
+	(void) BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
+	(void) BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
+	(void) BB_GET_BIT2(hp, tregs, (hp->tcvr_type == internal));
 	ASD(("value=%x\n", retval));
 	return retval;
 }
 
-static inline void happy_meal_bb_write(struct happy_meal *hp,
-				       struct hmeal_tcvregs *tregs, int reg,
-				       unsigned short value)
+static void happy_meal_bb_write(struct happy_meal *hp,
+				unsigned long tregs, int reg,
+				unsigned short value)
 {
-	unsigned long tmp;
+	u32 tmp;
 	int i;
 
 	ASD(("happy_meal_bb_write: reg=%d value=%x\n", reg, value));
 
 	/* Enable the MIF BitBang outputs. */
-	hme_write32(hp, &tregs->bb_oenab, 1);
+	hme_write32(hp, tregs + TCVR_BBOENAB, 1);
 
 	/* Force BitBang into the idle state. */
-	for(i = 0; i < 32; i++)
+	for (i = 0; i < 32; i++)
 		BB_PUT_BIT(hp, tregs, 1);
 
 	/* Give it write sequence. */
@@ -254,81 +427,81 @@
 
 	/* Give it the PHY address. */
 	tmp = (hp->paddr & 0xff);
-	for(i = 4; i >= 0; i--)
+	for (i = 4; i >= 0; i--)
 		BB_PUT_BIT(hp, tregs, ((tmp >> i) & 1));
 
 	/* Tell it what register we will be writing. */
 	tmp = (reg & 0xff);
-	for(i = 4; i >= 0; i--)
+	for (i = 4; i >= 0; i--)
 		BB_PUT_BIT(hp, tregs, ((tmp >> i) & 1));
 
 	/* Tell it to become ready for the bits. */
 	BB_PUT_BIT(hp, tregs, 1);
 	BB_PUT_BIT(hp, tregs, 0);
 
-	for(i = 15; i >= 0; i--)
+	for (i = 15; i >= 0; i--)
 		BB_PUT_BIT(hp, tregs, ((value >> i) & 1));
 
 	/* Close down the MIF BitBang outputs. */
-	hme_write32(hp, &tregs->bb_oenab, 0);
+	hme_write32(hp, tregs + TCVR_BBOENAB, 0);
 }
 
 #define TCVR_READ_TRIES   16
 
-static inline int happy_meal_tcvr_read(struct happy_meal *hp,
-				       struct hmeal_tcvregs *tregs, int reg)
+static int happy_meal_tcvr_read(struct happy_meal *hp,
+				unsigned long tregs, int reg)
 {
 	int tries = TCVR_READ_TRIES;
 	int retval;
 
 	ASD(("happy_meal_tcvr_read: reg=0x%02x ", reg));
-	if(hp->tcvr_type == none) {
+	if (hp->tcvr_type == none) {
 		ASD(("no transceiver, value=TCVR_FAILURE\n"));
 		return TCVR_FAILURE;
 	}
 
-	if(!(hp->happy_flags & HFLAG_FENABLE)) {
+	if (!(hp->happy_flags & HFLAG_FENABLE)) {
 		ASD(("doing bit bang\n"));
 		return happy_meal_bb_read(hp, tregs, reg);
 	}
 
-	hme_write32(hp, &tregs->frame,
+	hme_write32(hp, tregs + TCVR_FRAME,
 		    (FRAME_READ | (hp->paddr << 23) | ((reg & 0xff) << 18)));
-	while(!(hme_read32(hp, &tregs->frame) & 0x10000) && --tries)
+	while (!(hme_read32(hp, tregs + TCVR_FRAME) & 0x10000) && --tries)
 		udelay(20);
-	if(!tries) {
-		printk("happy meal: Aieee, transceiver MIF read bolixed\n");
+	if (!tries) {
+		printk(KERN_ERR "happy meal: Aieee, transceiver MIF read bolixed\n");
 		return TCVR_FAILURE;
 	}
-	retval = hme_read32(hp, &tregs->frame) & 0xffff;
+	retval = hme_read32(hp, tregs + TCVR_FRAME) & 0xffff;
 	ASD(("value=%04x\n", retval));
 	return retval;
 }
 
 #define TCVR_WRITE_TRIES  16
 
-static inline void happy_meal_tcvr_write(struct happy_meal *hp,
-					 struct hmeal_tcvregs *tregs, int reg,
-					 unsigned short value)
+static void happy_meal_tcvr_write(struct happy_meal *hp,
+				  unsigned long tregs, int reg,
+				  unsigned short value)
 {
 	int tries = TCVR_WRITE_TRIES;
 	
 	ASD(("happy_meal_tcvr_write: reg=0x%02x value=%04x\n", reg, value));
 
 	/* Welcome to Sun Microsystems, can I take your order please? */
-	if(!hp->happy_flags & HFLAG_FENABLE)
+	if (!hp->happy_flags & HFLAG_FENABLE)
 		return happy_meal_bb_write(hp, tregs, reg, value);
 
 	/* Would you like fries with that? */
-	hme_write32(hp, &tregs->frame,
+	hme_write32(hp, tregs + TCVR_FRAME,
 		    (FRAME_WRITE | (hp->paddr << 23) |
 		     ((reg & 0xff) << 18) | (value & 0xffff)));
-	while(!(hme_read32(hp, &tregs->frame) & 0x10000) && --tries)
+	while (!(hme_read32(hp, tregs + TCVR_FRAME) & 0x10000) && --tries)
 		udelay(20);
 
 	/* Anything else? */
-	if(!tries)
-		printk("happy meal: Aieee, transceiver MIF write bolixed\n");
+	if (!tries)
+		printk(KERN_ERR "happy meal: Aieee, transceiver MIF write bolixed\n");
 
 	/* Fifty-two cents is your change, have a nice day. */
 }
@@ -365,21 +538,21 @@
  * service routine, and the chip is reset, or the link is ifconfig'd down
  * and then back up, this entire process repeats itself all over again.
  */
-static int try_next_permutation(struct happy_meal *hp, struct hmeal_tcvregs *tregs)
+static int try_next_permutation(struct happy_meal *hp, unsigned long tregs)
 {
 	hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
 
 	/* Downgrade from full to half duplex.  Only possible
 	 * via ethtool.
 	 */
-	if(hp->sw_bmcr & BMCR_FULLDPLX) {
+	if (hp->sw_bmcr & BMCR_FULLDPLX) {
 		hp->sw_bmcr &= ~(BMCR_FULLDPLX);
 		happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
 		return 0;
 	}
 
 	/* Downgrade from 100 to 10. */
-	if(hp->sw_bmcr & BMCR_SPEED100) {
+	if (hp->sw_bmcr & BMCR_SPEED100) {
 		hp->sw_bmcr &= ~(BMCR_SPEED100);
 		happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
 		return 0;
@@ -389,70 +562,70 @@
 	return -1;
 }
 
-static void display_link_mode(struct happy_meal *hp, struct hmeal_tcvregs *tregs)
+static void display_link_mode(struct happy_meal *hp, unsigned long tregs)
 {
-	printk("%s: Link is up using ", hp->dev->name);
-	if(hp->tcvr_type == external)
+	printk(KERN_INFO "%s: Link is up using ", hp->dev->name);
+	if (hp->tcvr_type == external)
 		printk("external ");
 	else
 		printk("internal ");
 	printk("transceiver at ");
 	hp->sw_lpa = happy_meal_tcvr_read(hp, tregs, DP83840_LPA);
-	if(hp->sw_lpa & (LPA_100HALF | LPA_100FULL)) {
-		if(hp->sw_lpa & LPA_100FULL)
+	if (hp->sw_lpa & (LPA_100HALF | LPA_100FULL)) {
+		if (hp->sw_lpa & LPA_100FULL)
 			printk("100Mb/s, Full Duplex.\n");
 		else
 			printk("100Mb/s, Half Duplex.\n");
 	} else {
-		if(hp->sw_lpa & LPA_10FULL)
+		if (hp->sw_lpa & LPA_10FULL)
 			printk("10Mb/s, Full Duplex.\n");
 		else
 			printk("10Mb/s, Half Duplex.\n");
 	}
 }
 
-static void display_forced_link_mode(struct happy_meal *hp, struct hmeal_tcvregs *tregs)
+static void display_forced_link_mode(struct happy_meal *hp, unsigned long tregs)
 {
-	printk("%s: Link has been forced up using ", hp->dev->name);
-	if(hp->tcvr_type == external)
+	printk(KERN_INFO "%s: Link has been forced up using ", hp->dev->name);
+	if (hp->tcvr_type == external)
 		printk("external ");
 	else
 		printk("internal ");
 	printk("transceiver at ");
 	hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
-	if(hp->sw_bmcr & BMCR_SPEED100)
+	if (hp->sw_bmcr & BMCR_SPEED100)
 		printk("100Mb/s, ");
 	else
 		printk("10Mb/s, ");
-	if(hp->sw_bmcr & BMCR_FULLDPLX)
+	if (hp->sw_bmcr & BMCR_FULLDPLX)
 		printk("Full Duplex.\n");
 	else
 		printk("Half Duplex.\n");
 }
 
-static int set_happy_link_modes(struct happy_meal *hp, struct hmeal_tcvregs *tregs)
+static int set_happy_link_modes(struct happy_meal *hp, unsigned long tregs)
 {
 	int full;
 
 	/* All we care about is making sure the bigmac tx_cfg has a
 	 * proper duplex setting.
 	 */
-	if(hp->timer_state == arbwait) {
+	if (hp->timer_state == arbwait) {
 		hp->sw_lpa = happy_meal_tcvr_read(hp, tregs, DP83840_LPA);
-		if(!(hp->sw_lpa & (LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL)))
+		if (!(hp->sw_lpa & (LPA_10HALF | LPA_10FULL | LPA_100HALF | LPA_100FULL)))
 			goto no_response;
-		if(hp->sw_lpa & LPA_100FULL)
+		if (hp->sw_lpa & LPA_100FULL)
 			full = 1;
-		else if(hp->sw_lpa & LPA_100HALF)
+		else if (hp->sw_lpa & LPA_100HALF)
 			full = 0;
-		else if(hp->sw_lpa & LPA_10FULL)
+		else if (hp->sw_lpa & LPA_10FULL)
 			full = 1;
 		else
 			full = 0;
 	} else {
 		/* Forcing a link mode. */
 		hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
-		if(hp->sw_bmcr & BMCR_FULLDPLX)
+		if (hp->sw_bmcr & BMCR_FULLDPLX)
 			full = 1;
 		else
 			full = 0;
@@ -466,24 +639,24 @@
 	 * 3) Make TX configuration changes
 	 * 4) Set Enable once more
 	 */
-	hme_write32(hp, &hp->bigmacregs->tx_cfg,
-		    hme_read32(hp, &hp->bigmacregs->tx_cfg) &
+	hme_write32(hp, hp->bigmacregs + BMAC_TXCFG,
+		    hme_read32(hp, hp->bigmacregs + BMAC_TXCFG) &
 		    ~(BIGMAC_TXCFG_ENABLE));
-	while(hme_read32(hp, &hp->bigmacregs->tx_cfg) & BIGMAC_TXCFG_ENABLE)
+	while (hme_read32(hp, hp->bigmacregs + BMAC_TXCFG) & BIGMAC_TXCFG_ENABLE)
 		barrier();
-	if(full) {
+	if (full) {
 		hp->happy_flags |= HFLAG_FULL;
-		hme_write32(hp, &hp->bigmacregs->tx_cfg,
-			    hme_read32(hp, &hp->bigmacregs->tx_cfg) |
+		hme_write32(hp, hp->bigmacregs + BMAC_TXCFG,
+			    hme_read32(hp, hp->bigmacregs + BMAC_TXCFG) |
 			    BIGMAC_TXCFG_FULLDPLX);
 	} else {
 		hp->happy_flags &= ~(HFLAG_FULL);
-		hme_write32(hp, &hp->bigmacregs->tx_cfg,
-			    hme_read32(hp, &hp->bigmacregs->tx_cfg) &
+		hme_write32(hp, hp->bigmacregs + BMAC_TXCFG,
+			    hme_read32(hp, hp->bigmacregs + BMAC_TXCFG) &
 			    ~(BIGMAC_TXCFG_FULLDPLX));
 	}
-	hme_write32(hp, &hp->bigmacregs->tx_cfg,
-		    hme_read32(hp, &hp->bigmacregs->tx_cfg) |
+	hme_write32(hp, hp->bigmacregs + BMAC_TXCFG,
+		    hme_read32(hp, hp->bigmacregs + BMAC_TXCFG) |
 		    BIGMAC_TXCFG_ENABLE);
 	return 0;
 no_response:
@@ -492,10 +665,29 @@
 
 static int happy_meal_init(struct happy_meal *hp, int from_irq);
 
+static int is_lucent_phy(struct happy_meal *hp)
+{
+	unsigned long tregs = hp->tcvregs;
+	unsigned short mr2, mr3;
+	int ret = 0;
+
+	mr2 = happy_meal_tcvr_read(hp, tregs, 2);
+	mr3 = happy_meal_tcvr_read(hp, tregs, 3);
+	if ((mr2 & 0xffff) == 0x0180 &&
+	    ((mr3 & 0xffff) >> 10) == 0x1d) {
+#if 0
+		printk("HMEDEBUG: Lucent PHY detected.\n");
+#endif
+		ret = 1;
+	}
+
+	return ret;
+}
+
 static void happy_meal_timer(unsigned long data)
 {
 	struct happy_meal *hp = (struct happy_meal *) data;
-	struct hmeal_tcvregs *tregs = hp->tcvregs;
+	unsigned long tregs = hp->tcvregs;
 	int restart_timer = 0;
 
 	hp->timer_ticks++;
@@ -504,35 +696,36 @@
 		/* Only allow for 5 ticks, thats 10 seconds and much too
 		 * long to wait for arbitration to complete.
 		 */
-		if(hp->timer_ticks >= 10) {
+		if (hp->timer_ticks >= 10) {
 			/* Enter force mode. */
 	do_force_mode:
 			hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
-			printk("%s: Auto-Negotiation unsuccessful, trying force link mode\n",
+			printk(KERN_NOTICE "%s: Auto-Negotiation unsuccessful, trying force link mode\n",
 			       hp->dev->name);
 			hp->sw_bmcr = BMCR_SPEED100;
 			happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
 
-			/* OK, seems we need do disable the transceiver for the first
-			 * tick to make sure we get an accurate link state at the
-			 * second tick.
-			 */
-			hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG);
-			hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB);
-			happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig);
-
+			if (!is_lucent_phy(hp)) {
+				/* OK, seems we need do disable the transceiver for the first
+				 * tick to make sure we get an accurate link state at the
+				 * second tick.
+				 */
+				hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG);
+				hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB);
+				happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig);
+			}
 			hp->timer_state = ltrywait;
 			hp->timer_ticks = 0;
 			restart_timer = 1;
 		} else {
 			/* Anything interesting happen? */
 			hp->sw_bmsr = happy_meal_tcvr_read(hp, tregs, DP83840_BMSR);
-			if(hp->sw_bmsr & BMSR_ANEGCOMPLETE) {
+			if (hp->sw_bmsr & BMSR_ANEGCOMPLETE) {
 				int ret;
 
 				/* Just what we've been waiting for... */
 				ret = set_happy_link_modes(hp, tregs);
-				if(ret) {
+				if (ret) {
 					/* Ooops, something bad happened, go to force
 					 * mode.
 					 *
@@ -558,7 +751,7 @@
 		 * a message to the user at 10 second intervals.
 		 */
 		hp->sw_bmsr = happy_meal_tcvr_read(hp, tregs, DP83840_BMSR);
-		if(hp->sw_bmsr & BMSR_LSTATUS) {
+		if (hp->sw_bmsr & BMSR_LSTATUS) {
 			/* Wheee, it's up, display the link mode in use and put
 			 * the timer to sleep.
 			 */
@@ -566,8 +759,8 @@
 			hp->timer_state = asleep;
 			restart_timer = 0;
 		} else {
-			if(hp->timer_ticks >= 10) {
-				printk("%s: Auto negotiation successful, link still "
+			if (hp->timer_ticks >= 10) {
+				printk(KERN_NOTICE "%s: Auto negotiation successful, link still "
 				       "not completely up.\n", hp->dev->name);
 				hp->timer_ticks = 0;
 				restart_timer = 1;
@@ -585,51 +778,62 @@
 		 */
 		hp->sw_bmsr = happy_meal_tcvr_read(hp, tregs, DP83840_BMSR);
 		hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG);
-		if(hp->timer_ticks == 1) {
-			/* Re-enable transceiver, we'll re-enable the transceiver next
-			 * tick, then check link state on the following tick. */
-			hp->sw_csconfig |= CSCONFIG_TCVDISAB;
-			happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig);
+		if (hp->timer_ticks == 1) {
+			if (!is_lucent_phy(hp)) {
+				/* Re-enable transceiver, we'll re-enable the transceiver next
+				 * tick, then check link state on the following tick.
+				 */
+				hp->sw_csconfig |= CSCONFIG_TCVDISAB;
+				happy_meal_tcvr_write(hp, tregs,
+						      DP83840_CSCONFIG, hp->sw_csconfig);
+			}
 			restart_timer = 1;
 			break;
 		}
-		if(hp->timer_ticks == 2) {
-			hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB);
-			happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig);
+		if (hp->timer_ticks == 2) {
+			if (!is_lucent_phy(hp)) {
+				hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB);
+				happy_meal_tcvr_write(hp, tregs,
+						      DP83840_CSCONFIG, hp->sw_csconfig);
+			}
 			restart_timer = 1;
 			break;
 		}
-		if(hp->sw_bmsr & BMSR_LSTATUS) {
+		if (hp->sw_bmsr & BMSR_LSTATUS) {
 			/* Force mode selection success. */
 			display_forced_link_mode(hp, tregs);
 			set_happy_link_modes(hp, tregs); /* XXX error? then what? */
 			hp->timer_state = asleep;
 			restart_timer = 0;
 		} else {
-			if(hp->timer_ticks >= 4) { /* 6 seconds or so... */
+			if (hp->timer_ticks >= 4) { /* 6 seconds or so... */
 				int ret;
 
 				ret = try_next_permutation(hp, tregs);
-				if(ret == -1) {
+				if (ret == -1) {
 					/* Aieee, tried them all, reset the
 					 * chip and try all over again.
 					 */
 
 					/* Let the user know... */
-					printk("%s: Link down, cable problem?\n",
+					printk(KERN_NOTICE "%s: Link down, cable problem?\n",
 					       hp->dev->name);
 
 					ret = happy_meal_init(hp, 0);
-					if(ret) {
+					if (ret) {
 						/* ho hum... */
-						printk("%s: Error, cannot re-init the "
+						printk(KERN_ERR "%s: Error, cannot re-init the "
 						       "Happy Meal.\n", hp->dev->name);
 					}
 					return;
 				}
-				hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG);
-				hp->sw_csconfig |= CSCONFIG_TCVDISAB;
-				happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, hp->sw_csconfig);
+				if (!is_lucent_phy(hp)) {
+					hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs,
+									       DP83840_CSCONFIG);
+					hp->sw_csconfig |= CSCONFIG_TCVDISAB;
+					happy_meal_tcvr_write(hp, tregs,
+							      DP83840_CSCONFIG, hp->sw_csconfig);
+				}
 				hp->timer_ticks = 0;
 				restart_timer = 1;
 			} else {
@@ -641,7 +845,7 @@
 	case asleep:
 	default:
 		/* Can't happens.... */
-		printk("%s: Aieee, link timer is asleep but we got one anyways!\n",
+		printk(KERN_ERR "%s: Aieee, link timer is asleep but we got one anyways!\n",
 		       hp->dev->name);
 		restart_timer = 0;
 		hp->timer_ticks = 0;
@@ -649,7 +853,7 @@
 		break;
 	};
 
-	if(restart_timer) {
+	if (restart_timer) {
 		hp->happy_timer.expires = jiffies + ((12 * HZ)/10); /* 1.2 sec. */
 		add_timer(&hp->happy_timer);
 	}
@@ -658,41 +862,39 @@
 #define TX_RESET_TRIES     32
 #define RX_RESET_TRIES     32
 
-static inline void happy_meal_tx_reset(struct happy_meal *hp,
-				       struct hmeal_bigmacregs *bregs)
+static void happy_meal_tx_reset(struct happy_meal *hp, unsigned long bregs)
 {
 	int tries = TX_RESET_TRIES;
 
 	HMD(("happy_meal_tx_reset: reset, "));
 
 	/* Would you like to try our SMCC Delux? */
-	hme_write32(hp, &bregs->tx_swreset, 0);
-	while((hme_read32(hp, &bregs->tx_swreset) & 1) && --tries)
+	hme_write32(hp, bregs + BMAC_TXSWRESET, 0);
+	while ((hme_read32(hp, bregs + BMAC_TXSWRESET) & 1) && --tries)
 		udelay(20);
 
 	/* Lettuce, tomato, buggy hardware (no extra charge)? */
-	if(!tries)
-		printk("happy meal: Transceiver BigMac ATTACK!");
+	if (!tries)
+		printk(KERN_ERR "happy meal: Transceiver BigMac ATTACK!");
 
 	/* Take care. */
 	HMD(("done\n"));
 }
 
-static inline void happy_meal_rx_reset(struct happy_meal *hp,
-				       struct hmeal_bigmacregs *bregs)
+static void happy_meal_rx_reset(struct happy_meal *hp, unsigned long bregs)
 {
 	int tries = RX_RESET_TRIES;
 
 	HMD(("happy_meal_rx_reset: reset, "));
 
 	/* We have a special on GNU/Viking hardware bugs today. */
-	hme_write32(hp, &bregs->rx_swreset, 0);
-	while((hme_read32(hp, &bregs->rx_swreset) & 1) && --tries)
+	hme_write32(hp, bregs + BMAC_RXSWRESET, 0);
+	while ((hme_read32(hp, bregs + BMAC_RXSWRESET) & 1) && --tries)
 		udelay(20);
 
 	/* Will that be all? */
-	if(!tries)
-		printk("happy meal: Receiver BigMac ATTACK!");
+	if (!tries)
+		printk(KERN_ERR "happy meal: Receiver BigMac ATTACK!");
 
 	/* Don't forget your vik_1137125_wa.  Have a nice day. */
 	HMD(("done\n"));
@@ -700,69 +902,67 @@
 
 #define STOP_TRIES         16
 
-static inline void happy_meal_stop(struct happy_meal *hp,
-				   struct hmeal_gregs *gregs)
+static void happy_meal_stop(struct happy_meal *hp, unsigned long gregs)
 {
 	int tries = STOP_TRIES;
 
 	HMD(("happy_meal_stop: reset, "));
 
 	/* We're consolidating our STB products, it's your lucky day. */
-	hme_write32(hp, &gregs->sw_reset, GREG_RESET_ALL);
-	while(hme_read32(hp, &gregs->sw_reset) && --tries)
+	hme_write32(hp, gregs + GREG_SWRESET, GREG_RESET_ALL);
+	while (hme_read32(hp, gregs + GREG_SWRESET) && --tries)
 		udelay(20);
 
 	/* Come back next week when we are "Sun Microelectronics". */
-	if(!tries)
-		printk("happy meal: Fry guys.");
+	if (!tries)
+		printk(KERN_ERR "happy meal: Fry guys.");
 
 	/* Remember: "Different name, same old buggy as shit hardware." */
 	HMD(("done\n"));
 }
 
-static void happy_meal_get_counters(struct happy_meal *hp,
-				    struct hmeal_bigmacregs *bregs)
+static void happy_meal_get_counters(struct happy_meal *hp, unsigned long bregs)
 {
 	struct net_device_stats *stats = &hp->net_stats;
 
-	stats->rx_crc_errors += hme_read32(hp, &bregs->rcrce_ctr);
-	hme_write32(hp, &bregs->rcrce_ctr, 0);
+	stats->rx_crc_errors += hme_read32(hp, bregs + BMAC_RCRCECTR);
+	hme_write32(hp, bregs + BMAC_RCRCECTR, 0);
 
-	stats->rx_frame_errors += hme_read32(hp, &bregs->unale_ctr);
-	hme_write32(hp, &bregs->unale_ctr, 0);
+	stats->rx_frame_errors += hme_read32(hp, bregs + BMAC_UNALECTR);
+	hme_write32(hp, bregs + BMAC_UNALECTR, 0);
 
-	stats->rx_length_errors += hme_read32(hp, &bregs->gle_ctr);
-	hme_write32(hp, &bregs->gle_ctr, 0);
+	stats->rx_length_errors += hme_read32(hp, bregs + BMAC_GLECTR);
+	hme_write32(hp, bregs + BMAC_GLECTR, 0);
 
-	stats->tx_aborted_errors += hme_read32(hp, &bregs->ex_ctr);
+	stats->tx_aborted_errors += hme_read32(hp, bregs + BMAC_EXCTR);
 
 	stats->collisions +=
-		(hme_read32(hp, &bregs->ex_ctr) +
-		 hme_read32(hp, &bregs->lt_ctr));
-	hme_write32(hp, &bregs->ex_ctr, 0);
-	hme_write32(hp, &bregs->lt_ctr, 0);
+		(hme_read32(hp, bregs + BMAC_EXCTR) +
+		 hme_read32(hp, bregs + BMAC_LTCTR));
+	hme_write32(hp, bregs + BMAC_EXCTR, 0);
+	hme_write32(hp, bregs + BMAC_LTCTR, 0);
 }
 
-static inline void happy_meal_poll_start(struct happy_meal *hp,
-					 struct hmeal_tcvregs *tregs)
+#if 0
+static void happy_meal_poll_start(struct happy_meal *hp, unsigned long tregs)
 {
-	unsigned long tmp;
+	u32 tmp;
 	int speed;
 
 	ASD(("happy_meal_poll_start: "));
-	if(!(hp->happy_flags & HFLAG_POLLENABLE)) {
+	if (!(hp->happy_flags & HFLAG_POLLENABLE)) {
 		HMD(("polling disabled, return\n"));
 		return;
 	}
 
 	/* Start the MIF polling on the external transceiver. */
 	ASD(("polling on, "));
-	tmp = hme_read32(hp, &tregs->cfg);
+	tmp = hme_read32(hp, tregs + TCVR_CFG);
 	tmp &= ~(TCV_CFG_PDADDR | TCV_CFG_PREGADDR);
 	tmp |= ((hp->paddr & 0x1f) << 10);
 	tmp |= (TCV_PADDR_ETX << 3);
 	tmp |= TCV_CFG_PENABLE;
-	hme_write32(hp, &tregs->cfg, tmp);
+	hme_write32(hp, tregs + TCVR_CFG, tmp);
 
 	/* Let the bits set. */
 	udelay(200);
@@ -773,29 +973,29 @@
 
 	/* Clear the poll flags, get the basic status as of now. */
 	hp->poll_flag = 0;
-	hp->poll_data = tregs->status >> 16;
+	hp->poll_data = hme_read32(hp, tregs + TCVR_STATUS) >> 16;
 
-	if(hp->happy_flags & HFLAG_AUTO)
+	if (hp->happy_flags & HFLAG_AUTO)
 		speed = hp->auto_speed;
 	else
 		speed = hp->forced_speed;
 
 	/* Listen only for the MIF interrupts we want to hear. */
 	ASD(("mif ints on, "));
-	if(speed == 100)
-		hme_write32(hp, &tregs->int_mask, 0xfffb);
+	if (speed == 100)
+		hme_write32(hp, tregs + TCVR_IMASK, 0xfffb);
 	else
-		hme_write32(hp, &tregs->int_mask, 0xfff9);
+		hme_write32(hp, tregs + TCVR_IMASK, 0xfff9);
 	ASD(("done\n"));
 }
+#endif
 
-static inline void happy_meal_poll_stop(struct happy_meal *hp,
-					struct hmeal_tcvregs *tregs)
+static void happy_meal_poll_stop(struct happy_meal *hp, unsigned long tregs)
 {
 	ASD(("happy_meal_poll_stop: "));
 
 	/* If polling disabled or not polling already, nothing to do. */
-	if((hp->happy_flags & (HFLAG_POLLENABLE | HFLAG_POLL)) !=
+	if ((hp->happy_flags & (HFLAG_POLLENABLE | HFLAG_POLL)) !=
 	   (HFLAG_POLLENABLE | HFLAG_POLL)) {
 		HMD(("not polling, return\n"));
 		return;
@@ -803,12 +1003,12 @@
 
 	/* Shut up the MIF. */
 	ASD(("were polling, mif ints off, "));
-	hme_write32(hp, &tregs->int_mask, 0xffff);
+	hme_write32(hp, tregs + TCVR_IMASK, 0xffff);
 
 	/* Turn off polling. */
 	ASD(("polling off, "));
-	hme_write32(hp, &tregs->cfg,
-		    hme_read32(hp, &tregs->cfg) & ~(TCV_CFG_PENABLE));
+	hme_write32(hp, tregs + TCVR_CFG,
+		    hme_read32(hp, tregs + TCVR_CFG) & ~(TCV_CFG_PENABLE));
 
 	/* We are no longer polling. */
 	hp->happy_flags &= ~(HFLAG_POLL);
@@ -824,45 +1024,44 @@
 #define TCVR_RESET_TRIES       16 /* It should reset quickly        */
 #define TCVR_UNISOLATE_TRIES   32 /* Dis-isolation can take longer. */
 
-static int happy_meal_tcvr_reset(struct happy_meal *hp,
-				 struct hmeal_tcvregs *tregs)
+static int happy_meal_tcvr_reset(struct happy_meal *hp, unsigned long tregs)
 {
-	unsigned long tconfig;
+	u32 tconfig;
 	int result, tries = TCVR_RESET_TRIES;
 
-	tconfig = hme_read32(hp, &tregs->cfg);
+	tconfig = hme_read32(hp, tregs + TCVR_CFG);
 	ASD(("happy_meal_tcvr_reset: tcfg<%08lx> ", tconfig));
-	if(hp->tcvr_type == external) {
+	if (hp->tcvr_type == external) {
 		ASD(("external<"));
-		hme_write32(hp, &tregs->cfg, tconfig & ~(TCV_CFG_PSELECT));
+		hme_write32(hp, tregs + TCVR_CFG, tconfig & ~(TCV_CFG_PSELECT));
 		hp->tcvr_type = internal;
 		hp->paddr = TCV_PADDR_ITX;
 		ASD(("ISOLATE,"));
 		happy_meal_tcvr_write(hp, tregs, DP83840_BMCR,
 				      (BMCR_LOOPBACK|BMCR_PDOWN|BMCR_ISOLATE));
 		result = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
-		if(result == TCVR_FAILURE) {
+		if (result == TCVR_FAILURE) {
 			ASD(("phyread_fail>\n"));
 			return -1;
 		}
 		ASD(("phyread_ok,PSELECT>"));
-		hme_write32(hp, &tregs->cfg, tconfig | TCV_CFG_PSELECT);
+		hme_write32(hp, tregs + TCVR_CFG, tconfig | TCV_CFG_PSELECT);
 		hp->tcvr_type = external;
 		hp->paddr = TCV_PADDR_ETX;
 	} else {
-		if(tconfig & TCV_CFG_MDIO1) {
+		if (tconfig & TCV_CFG_MDIO1) {
 			ASD(("internal<PSELECT,"));
-			hme_write32(hp, &tregs->cfg, (tconfig | TCV_CFG_PSELECT));
+			hme_write32(hp, tregs + TCVR_CFG, (tconfig | TCV_CFG_PSELECT));
 			ASD(("ISOLATE,"));
 			happy_meal_tcvr_write(hp, tregs, DP83840_BMCR,
 					      (BMCR_LOOPBACK|BMCR_PDOWN|BMCR_ISOLATE));
 			result = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
-			if(result == TCVR_FAILURE) {
+			if (result == TCVR_FAILURE) {
 				ASD(("phyread_fail>\n"));
 				return -1;
 			}
 			ASD(("phyread_ok,~PSELECT>"));
-			hme_write32(hp, &tregs->cfg, (tconfig & ~(TCV_CFG_PSELECT)));
+			hme_write32(hp, tregs + TCVR_CFG, (tconfig & ~(TCV_CFG_PSELECT)));
 			hp->tcvr_type = internal;
 			hp->paddr = TCV_PADDR_ITX;
 		}
@@ -871,16 +1070,16 @@
 	ASD(("BMCR_RESET "));
 	happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, BMCR_RESET);
 
-	while(--tries) {
+	while (--tries) {
 		result = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
-		if(result == TCVR_FAILURE)
+		if (result == TCVR_FAILURE)
 			return -1;
 		hp->sw_bmcr = result;
-		if(!(result & BMCR_RESET))
+		if (!(result & BMCR_RESET))
 			break;
 		udelay(20);
 	}
-	if(!tries) {
+	if (!tries) {
 		ASD(("BMCR RESET FAILED!\n"));
 		return -1;
 	}
@@ -897,36 +1096,39 @@
 	happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
 
 	tries = TCVR_UNISOLATE_TRIES;
-	while(--tries) {
+	while (--tries) {
 		result = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
-		if(result == TCVR_FAILURE)
+		if (result == TCVR_FAILURE)
 			return -1;
-		if(!(result & BMCR_ISOLATE))
+		if (!(result & BMCR_ISOLATE))
 			break;
 		udelay(20);
 	}
-	if(!tries) {
+	if (!tries) {
 		ASD((" FAILED!\n"));
 		return -1;
 	}
 	ASD((" SUCCESS and CSCONFIG_DFBYPASS\n"));
-	result = happy_meal_tcvr_read(hp, tregs, DP83840_CSCONFIG);
-	happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG, (result | CSCONFIG_DFBYPASS));
+	if (!is_lucent_phy(hp)) {
+		result = happy_meal_tcvr_read(hp, tregs,
+					      DP83840_CSCONFIG);
+		happy_meal_tcvr_write(hp, tregs,
+				      DP83840_CSCONFIG, (result | CSCONFIG_DFBYPASS));
+	}
 	return 0;
 }
 
 /* Figure out whether we have an internal or external transceiver. */
-static void happy_meal_transceiver_check(struct happy_meal *hp,
-					 struct hmeal_tcvregs *tregs)
+static void happy_meal_transceiver_check(struct happy_meal *hp, unsigned long tregs)
 {
-	unsigned long tconfig = hme_read32(hp, &tregs->cfg);
+	unsigned long tconfig = hme_read32(hp, tregs + TCVR_CFG);
 
 	ASD(("happy_meal_transceiver_check: tcfg=%08lx ", tconfig));
-	if(hp->happy_flags & HFLAG_POLL) {
+	if (hp->happy_flags & HFLAG_POLL) {
 		/* If we are polling, we must stop to get the transceiver type. */
 		ASD(("<polling> "));
-		if(hp->tcvr_type == internal) {
-			if(tconfig & TCV_CFG_MDIO1) {
+		if (hp->tcvr_type == internal) {
+			if (tconfig & TCV_CFG_MDIO1) {
 				ASD(("<internal> <poll stop> "));
 				happy_meal_poll_stop(hp, tregs);
 				hp->paddr = TCV_PADDR_ETX;
@@ -934,19 +1136,19 @@
 				ASD(("<external>\n"));
 				tconfig &= ~(TCV_CFG_PENABLE);
 				tconfig |= TCV_CFG_PSELECT;
-				hme_write32(hp, &tregs->cfg, tconfig);
+				hme_write32(hp, tregs + TCVR_CFG, tconfig);
 			}
 		} else {
-			if(hp->tcvr_type == external) {
+			if (hp->tcvr_type == external) {
 				ASD(("<external> "));
-				if(!(hme_read32(hp, &tregs->status) >> 16)) {
+				if (!(hme_read32(hp, tregs + TCVR_STATUS) >> 16)) {
 					ASD(("<poll stop> "));
 					happy_meal_poll_stop(hp, tregs);
 					hp->paddr = TCV_PADDR_ITX;
 					hp->tcvr_type = internal;
 					ASD(("<internal>\n"));
-					hme_write32(hp, &tregs->cfg,
-						    hme_read32(hp, &tregs->cfg) &
+					hme_write32(hp, tregs + TCVR_CFG,
+						    hme_read32(hp, tregs + TCVR_CFG) &
 						    ~(TCV_CFG_PSELECT));
 				}
 				ASD(("\n"));
@@ -955,24 +1157,24 @@
 			}
 		}
 	} else {
-		unsigned long reread = hme_read32(hp, &tregs->cfg);
+		u32 reread = hme_read32(hp, tregs + TCVR_CFG);
 
 		/* Else we can just work off of the MDIO bits. */
 		ASD(("<not polling> "));
-		if(reread & TCV_CFG_MDIO1) {
-			hme_write32(hp, &tregs->cfg, tconfig | TCV_CFG_PSELECT);
+		if (reread & TCV_CFG_MDIO1) {
+			hme_write32(hp, tregs + TCVR_CFG, tconfig | TCV_CFG_PSELECT);
 			hp->paddr = TCV_PADDR_ETX;
 			hp->tcvr_type = external;
 			ASD(("<external>\n"));
 		} else {
-			if(reread & TCV_CFG_MDIO0) {
-				hme_write32(hp, &tregs->cfg,
+			if (reread & TCV_CFG_MDIO0) {
+				hme_write32(hp, tregs + TCVR_CFG,
 					    tconfig & ~(TCV_CFG_PSELECT));
 				hp->paddr = TCV_PADDR_ITX;
 				hp->tcvr_type = internal;
 				ASD(("<internal>\n"));
 			} else {
-				printk("happy meal: Transceiver and a coke please.");
+				printk(KERN_ERR "happy meal: Transceiver and a coke please.");
 				hp->tcvr_type = none; /* Grrr... */
 				ASD(("<none>\n"));
 			}
@@ -1024,20 +1226,34 @@
  *
  * before sending off the skb to the protocols, and we are good as gold.
  */
-static inline void happy_meal_clean_rings(struct happy_meal *hp)
+static void happy_meal_clean_rings(struct happy_meal *hp)
 {
 	int i;
 
-	for(i = 0; i < RX_RING_SIZE; i++) {
-		if(hp->rx_skbs[i] != NULL) {
-			dev_kfree_skb(hp->rx_skbs[i]);
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		if (hp->rx_skbs[i] != NULL) {
+			struct sk_buff *skb = hp->rx_skbs[i];
+			struct happy_meal_rxd *rxd;
+			u32 dma_addr;
+
+			rxd = &hp->happy_block->happy_meal_rxd[i];
+			dma_addr = hme_read_desc32(hp, &rxd->rx_addr);
+			hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE);
+			dev_kfree_skb(skb);
 			hp->rx_skbs[i] = NULL;
 		}
 	}
 
-	for(i = 0; i < TX_RING_SIZE; i++) {
-		if(hp->tx_skbs[i] != NULL) {
-			dev_kfree_skb(hp->tx_skbs[i]);
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		if (hp->tx_skbs[i] != NULL) {
+			struct sk_buff *skb = hp->tx_skbs[i];
+			struct happy_meal_txd *txd;
+			u32 dma_addr;
+
+			txd = &hp->happy_block->happy_meal_txd[i];
+			dma_addr = hme_read_desc32(hp, &txd->tx_addr);
+			hme_dma_unmap(hp, dma_addr, skb->len);
+			dev_kfree_skb(skb);
 			hp->tx_skbs[i] = NULL;
 		}
 	}
@@ -1049,7 +1265,7 @@
 	struct net_device *dev = hp->dev;
 	int i, gfp_flags = GFP_KERNEL;
 
-	if(from_irq || in_interrupt())
+	if (from_irq || in_interrupt())
 		gfp_flags = GFP_ATOMIC;
 
 	HMD(("happy_meal_init_rings: counters to zero, "));
@@ -1061,76 +1277,34 @@
 
 	/* Now get new skippy bufs for the receive ring. */
 	HMD(("init rxring, "));
-	for(i = 0; i < RX_RING_SIZE; i++) {
+	for (i = 0; i < RX_RING_SIZE; i++) {
 		struct sk_buff *skb;
 
-		skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, gfp_flags | GFP_DMA);
-		if(!skb)
+		skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, gfp_flags);
+		if (!skb) {
+			hme_write_rxd(hp, &hb->happy_meal_rxd[i], 0, 0);
 			continue;
+		}
 		hp->rx_skbs[i] = skb;
 		skb->dev = dev;
 
 		/* Because we reserve afterwards. */
 		skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET));
-
-#ifdef CONFIG_PCI
-		if(hp->happy_flags & HFLAG_PCI) {
-			pcihme_write_rxd(&hb->happy_meal_rxd[i],
-					 (RXFLAG_OWN |
-					  ((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
-					 (u32)virt_to_bus((volatile void *)skb->data));
-		} else
-#endif
-#ifndef __sparc_v9__
-		if (sparc_cpu_model == sun4d) {
-			__u32 va = (__u32)hp->sun4d_buffers + i * PAGE_SIZE;
-
-			hb->happy_meal_rxd[i].rx_addr =
-				iounit_map_dma_page(va, skb->data, hp->happy_sbus_dev->my_bus);
-			hb->happy_meal_rxd[i].rx_flags =
-				(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
-		} else
-#endif
-		{
-			hb->happy_meal_rxd[i].rx_addr = sbus_dvma_addr(skb->data);
-			hb->happy_meal_rxd[i].rx_flags =
-				(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
-		}
+		hme_write_rxd(hp, &hb->happy_meal_rxd[i],
+			      (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)),
+			      hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE));
 		skb_reserve(skb, RX_OFFSET);
 	}
 
 	HMD(("init txring, "));
-	for(i = 0; i < TX_RING_SIZE; i++)
-		hb->happy_meal_txd[i].tx_flags = 0;
-	HMD(("done\n"));
-}
-
-#ifndef __sparc_v9__
-static void sun4c_happy_meal_init_rings(struct happy_meal *hp)
-{
-	struct hmeal_init_block *hb = hp->happy_block;
-	__u32 hbufs = hp->s4c_buf_dvma;
-	int i;
-
-	HMD(("happy_meal_init_rings: counters to zero, "));
-	hp->rx_new = hp->rx_old = hp->tx_new = hp->tx_old = 0;
-
-	HMD(("init rxring, "));
-	for(i = 0; i < RX_RING_SIZE; i++) {
-		hb->happy_meal_rxd[i].rx_addr = hbufs + hbuf_offset(rx_buf, i);
-		hb->happy_meal_rxd[i].rx_flags =
-			(RXFLAG_OWN | ((SUN4C_RX_BUFF_SIZE - RX_OFFSET) << 16));
-	}
+	for (i = 0; i < TX_RING_SIZE; i++)
+		hme_write_txd(hp, &hb->happy_meal_txd[i], 0, 0);
 
-	HMD(("init txring, "));
-	for(i = 0; i < TX_RING_SIZE; i++)
-		hb->happy_meal_txd[i].tx_flags = 0;
 	HMD(("done\n"));
 }
-#endif
 
 static void happy_meal_begin_auto_negotiation(struct happy_meal *hp,
-					      struct hmeal_tcvregs *tregs,
+					      unsigned long tregs,
 					      struct ethtool_cmd *ep)
 {
 	int timeout;
@@ -1144,22 +1318,22 @@
 	/* XXX Check BMSR_ANEGCAPABLE, should not be necessary though. */
 
 	hp->sw_advertise = happy_meal_tcvr_read(hp, tregs, DP83840_ADVERTISE);
-	if(ep == NULL || ep->autoneg == AUTONEG_ENABLE) {
+	if (ep == NULL || ep->autoneg == AUTONEG_ENABLE) {
 		/* Advertise everything we can support. */
-		if(hp->sw_bmsr & BMSR_10HALF)
+		if (hp->sw_bmsr & BMSR_10HALF)
 			hp->sw_advertise |= (ADVERTISE_10HALF);
 		else
 			hp->sw_advertise &= ~(ADVERTISE_10HALF);
 
-		if(hp->sw_bmsr & BMSR_10FULL)
+		if (hp->sw_bmsr & BMSR_10FULL)
 			hp->sw_advertise |= (ADVERTISE_10FULL);
 		else
 			hp->sw_advertise &= ~(ADVERTISE_10FULL);
-		if(hp->sw_bmsr & BMSR_100HALF)
+		if (hp->sw_bmsr & BMSR_100HALF)
 			hp->sw_advertise |= (ADVERTISE_100HALF);
 		else
 			hp->sw_advertise &= ~(ADVERTISE_100HALF);
-		if(hp->sw_bmsr & BMSR_100FULL)
+		if (hp->sw_bmsr & BMSR_100FULL)
 			hp->sw_advertise |= (ADVERTISE_100FULL);
 		else
 			hp->sw_advertise &= ~(ADVERTISE_100FULL);
@@ -1173,13 +1347,13 @@
 
 #ifdef AUTO_SWITCH_DEBUG
 		ASD(("%s: Advertising [ ", hp->dev->name));
-		if(hp->sw_advertise & ADVERTISE_10HALF)
+		if (hp->sw_advertise & ADVERTISE_10HALF)
 			ASD(("10H "));
-		if(hp->sw_advertise & ADVERTISE_10FULL)
+		if (hp->sw_advertise & ADVERTISE_10FULL)
 			ASD(("10F "));
-		if(hp->sw_advertise & ADVERTISE_100HALF)
+		if (hp->sw_advertise & ADVERTISE_100HALF)
 			ASD(("100H "));
-		if(hp->sw_advertise & ADVERTISE_100FULL)
+		if (hp->sw_advertise & ADVERTISE_100FULL)
 			ASD(("100F "));
 #endif
 
@@ -1194,16 +1368,16 @@
 		/* BMCR_ANRESTART self clears when the process has begun. */
 
 		timeout = 64;  /* More than enough. */
-		while(--timeout) {
+		while (--timeout) {
 			hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
-			if(!(hp->sw_bmcr & BMCR_ANRESTART))
+			if (!(hp->sw_bmcr & BMCR_ANRESTART))
 				break; /* got it. */
 			udelay(10);
 		}
-		if(!timeout) {
-			printk("%s: Happy Meal would not start auto negotiation "
+		if (!timeout) {
+			printk(KERN_ERR "%s: Happy Meal would not start auto negotiation "
 			       "BMCR=0x%04x\n", hp->dev->name, hp->sw_bmcr);
-			printk("%s: Performing force link detection.\n",
+			printk(KERN_NOTICE "%s: Performing force link detection.\n",
 			       hp->dev->name);
 			goto force_link;
 		} else {
@@ -1219,28 +1393,29 @@
 		/* Disable auto-negotiation in BMCR, enable the duplex and
 		 * speed setting, init the timer state machine, and fire it off.
 		 */
-		if(ep == NULL || ep->autoneg == AUTONEG_ENABLE) {
+		if (ep == NULL || ep->autoneg == AUTONEG_ENABLE) {
 			hp->sw_bmcr = BMCR_SPEED100;
 		} else {
-			if(ep->speed == SPEED_100)
+			if (ep->speed == SPEED_100)
 				hp->sw_bmcr = BMCR_SPEED100;
 			else
 				hp->sw_bmcr = 0;
-			if(ep->duplex == DUPLEX_FULL)
+			if (ep->duplex == DUPLEX_FULL)
 				hp->sw_bmcr |= BMCR_FULLDPLX;
 		}
 		happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
 
-		/* OK, seems we need do disable the transceiver for the first
-		 * tick to make sure we get an accurate link state at the
-		 * second tick.
-		 */
-		hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs,
-						       DP83840_CSCONFIG);
-		hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB);
-		happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG,
-				      hp->sw_csconfig);
-
+		if (!is_lucent_phy(hp)) {
+			/* OK, seems we need do disable the transceiver for the first
+			 * tick to make sure we get an accurate link state at the
+			 * second tick.
+			 */
+			hp->sw_csconfig = happy_meal_tcvr_read(hp, tregs,
+							       DP83840_CSCONFIG);
+			hp->sw_csconfig &= ~(CSCONFIG_TCVDISAB);
+			happy_meal_tcvr_write(hp, tregs, DP83840_CSCONFIG,
+					      hp->sw_csconfig);
+		}
 		hp->timer_state = ltrywait;
 	}
 
@@ -1256,12 +1431,12 @@
 
 static int happy_meal_init(struct happy_meal *hp, int from_irq)
 {
-	struct hmeal_gregs   *gregs        = hp->gregs;
-	struct hmeal_etxregs *etxregs      = hp->etxregs;
-	struct hmeal_erxregs *erxregs      = hp->erxregs;
-	struct hmeal_bigmacregs *bregs     = hp->bigmacregs;
-	struct hmeal_tcvregs *tregs        = hp->tcvregs;
-	unsigned long regtmp, rxcfg;
+	unsigned long gregs        = hp->gregs;
+	unsigned long etxregs      = hp->etxregs;
+	unsigned long erxregs      = hp->erxregs;
+	unsigned long bregs        = hp->bigmacregs;
+	unsigned long tregs        = hp->tcvregs;
+	u32 regtmp, rxcfg;
 	unsigned char *e = &hp->dev->dev_addr[0];
 
 	/* If auto-negotiation timer is running, kill it. */
@@ -1269,7 +1444,7 @@
 
 	HMD(("happy_meal_init: happy_flags[%08x] ",
 	     hp->happy_flags));
-	if(!(hp->happy_flags & HFLAG_INIT)) {
+	if (!(hp->happy_flags & HFLAG_INIT)) {
 		HMD(("set HFLAG_INIT, "));
 		hp->happy_flags |= HFLAG_INIT;
 		happy_meal_get_counters(hp, bregs);
@@ -1285,29 +1460,24 @@
 
 	/* Alloc and reset the tx/rx descriptor chains. */
 	HMD(("happy_meal_init: to happy_meal_init_rings\n"));
-#ifndef __sparc_v9__	
-	if(sparc_cpu_model == sun4c)
-		sun4c_happy_meal_init_rings(hp);
-	else
-#endif	
-		happy_meal_init_rings(hp, from_irq);
+	happy_meal_init_rings(hp, from_irq);
 
 	/* Shut up the MIF. */
 	HMD(("happy_meal_init: Disable all MIF irqs (old[%08x]), ",
 	     hme_read32(hp, &tregs->int_mask)));
-	hme_write32(hp, &tregs->int_mask, 0xffff);
+	hme_write32(hp, tregs + TCVR_IMASK, 0xffff);
 
 	/* See if we can enable the MIF frame on this card to speak to the DP83840. */
-	if(hp->happy_flags & HFLAG_FENABLE) {
+	if (hp->happy_flags & HFLAG_FENABLE) {
 		HMD(("use frame old[%08x], ",
 		     hme_read32(hp, &tregs->cfg)));
-		hme_write32(hp, &tregs->cfg,
-			    hme_read32(hp, &tregs->cfg) & ~(TCV_CFG_BENABLE));
+		hme_write32(hp, tregs + TCVR_CFG,
+			    hme_read32(hp, tregs + TCVR_CFG) & ~(TCV_CFG_BENABLE));
 	} else {
 		HMD(("use bitbang old[%08x], ",
 		     hme_read32(hp, &tregs->cfg)));
-		hme_write32(hp, &tregs->cfg,
-			    hme_read32(hp, &tregs->cfg) | TCV_CFG_BENABLE);
+		hme_write32(hp, tregs + TCVR_CFG,
+			    hme_read32(hp, tregs + TCVR_CFG) | TCV_CFG_BENABLE);
 	}
 
 	/* Check the state of the transceiver. */
@@ -1325,17 +1495,17 @@
 	case internal:
 		/* Using the MII buffers. */
 		HMD(("internal, using MII, "));
-		hme_write32(hp, &bregs->xif_cfg, 0);
+		hme_write32(hp, bregs + BMAC_XIFCFG, 0);
 		break;
 
 	case external:
 		/* Not using the MII, disable it. */
 		HMD(("external, disable MII, "));
-		hme_write32(hp, &bregs->xif_cfg, BIGMAC_XCFG_MIIDISAB);
+		hme_write32(hp, bregs + BMAC_XIFCFG, BIGMAC_XCFG_MIIDISAB);
 		break;
 	};
 
-	if(happy_meal_tcvr_reset(hp, tregs))
+	if (happy_meal_tcvr_reset(hp, tregs))
 		return -EAGAIN;
 
 	/* Reset the Happy Meal Big Mac transceiver and the receiver. */
@@ -1345,128 +1515,132 @@
 
 	/* Set jam size and inter-packet gaps to reasonable defaults. */
 	HMD(("jsize/ipg1/ipg2, "));
-	hme_write32(hp, &bregs->jsize, DEFAULT_JAMSIZE);
-	hme_write32(hp, &bregs->ipkt_gap1, DEFAULT_IPG1);
-	hme_write32(hp, &bregs->ipkt_gap2, DEFAULT_IPG2);
+	hme_write32(hp, bregs + BMAC_JSIZE, DEFAULT_JAMSIZE);
+	hme_write32(hp, bregs + BMAC_IGAP1, DEFAULT_IPG1);
+	hme_write32(hp, bregs + BMAC_IGAP2, DEFAULT_IPG2);
 
 	/* Load up the MAC address and random seed. */
 	HMD(("rseed/macaddr, "));
 
 	/* The docs recommend to use the 10LSB of our MAC here. */
-	hme_write32(hp, &bregs->rand_seed, ((e[5] | e[4]<<8)&0x3ff));
+	hme_write32(hp, bregs + BMAC_RSEED, ((e[5] | e[4]<<8)&0x3ff));
 
-	hme_write32(hp, &bregs->mac_addr2, ((e[4] << 8) | e[5]));
-	hme_write32(hp, &bregs->mac_addr1, ((e[2] << 8) | e[3]));
-	hme_write32(hp, &bregs->mac_addr0, ((e[0] << 8) | e[1]));
+	hme_write32(hp, bregs + BMAC_MACADDR2, ((e[4] << 8) | e[5]));
+	hme_write32(hp, bregs + BMAC_MACADDR1, ((e[2] << 8) | e[3]));
+	hme_write32(hp, bregs + BMAC_MACADDR0, ((e[0] << 8) | e[1]));
 
 	HMD(("htable, "));
-	if((hp->dev->flags & IFF_ALLMULTI) ||
-	   (hp->dev->mc_count > 64)) {
-		hme_write32(hp, &bregs->htable0, 0xffff);
-		hme_write32(hp, &bregs->htable1, 0xffff);
-		hme_write32(hp, &bregs->htable2, 0xffff);
-		hme_write32(hp, &bregs->htable3, 0xffff);
-	} else if((hp->dev->flags & IFF_PROMISC) == 0) {
+	if ((hp->dev->flags & IFF_ALLMULTI) ||
+	    (hp->dev->mc_count > 64)) {
+		hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff);
+		hme_write32(hp, bregs + BMAC_HTABLE1, 0xffff);
+		hme_write32(hp, bregs + BMAC_HTABLE2, 0xffff);
+		hme_write32(hp, bregs + BMAC_HTABLE3, 0xffff);
+	} else if ((hp->dev->flags & IFF_PROMISC) == 0) {
 		u16 hash_table[4];
 		struct dev_mc_list *dmi = hp->dev->mc_list;
 		char *addrs;
 		int i, j, bit, byte;
 		u32 crc, poly = CRC_POLYNOMIAL_LE;
 
-		for(i = 0; i < 4; i++)
+		for (i = 0; i < 4; i++)
 			hash_table[i] = 0;
 
-		for(i = 0; i < hp->dev->mc_count; i++) {
+		for (i = 0; i < hp->dev->mc_count; i++) {
 			addrs = dmi->dmi_addr;
 			dmi = dmi->next;
 
-			if(!(*addrs & 1))
+			if (!(*addrs & 1))
 				continue;
 
 			crc = 0xffffffffU;
-			for(byte = 0; byte < 6; byte++) {
-				for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
+			for (byte = 0; byte < 6; byte++) {
+				for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
 					int test;
 
 					test = ((bit ^ crc) & 0x01);
 					crc >>= 1;
-					if(test)
+					if (test)
 						crc = crc ^ poly;
 				}
 			}
 			crc >>= 26;
 			hash_table[crc >> 4] |= 1 << (crc & 0xf);
 		}
-		hme_write32(hp, &bregs->htable0, hash_table[0]);
-		hme_write32(hp, &bregs->htable1, hash_table[1]);
-		hme_write32(hp, &bregs->htable2, hash_table[2]);
-		hme_write32(hp, &bregs->htable3, hash_table[3]);
+		hme_write32(hp, bregs + BMAC_HTABLE0, hash_table[0]);
+		hme_write32(hp, bregs + BMAC_HTABLE1, hash_table[1]);
+		hme_write32(hp, bregs + BMAC_HTABLE2, hash_table[2]);
+		hme_write32(hp, bregs + BMAC_HTABLE3, hash_table[3]);
 	} else {
-		hme_write32(hp, &bregs->htable3, 0);
-		hme_write32(hp, &bregs->htable2, 0);
-		hme_write32(hp, &bregs->htable1, 0);
-		hme_write32(hp, &bregs->htable0, 0);
+		hme_write32(hp, bregs + BMAC_HTABLE3, 0);
+		hme_write32(hp, bregs + BMAC_HTABLE2, 0);
+		hme_write32(hp, bregs + BMAC_HTABLE1, 0);
+		hme_write32(hp, bregs + BMAC_HTABLE0, 0);
 	}
 
 	/* Set the RX and TX ring ptrs. */
 	HMD(("ring ptrs rxr[%08x] txr[%08x]\n",
 	     (hp->hblock_dvma + hblock_offset(happy_meal_rxd, 0)),
 	     (hp->hblock_dvma + hblock_offset(happy_meal_txd, 0))));
-	hme_write32(hp, &erxregs->rx_ring,
+	hme_write32(hp, erxregs + ERX_RING,
 		    (hp->hblock_dvma + hblock_offset(happy_meal_rxd, 0)));
-	hme_write32(hp, &etxregs->tx_ring,
+	hme_write32(hp, etxregs + ETX_RING,
 		    (hp->hblock_dvma + hblock_offset(happy_meal_txd, 0)));
 
 	/* Set the supported burst sizes. */
 	HMD(("happy_meal_init: old[%08x] bursts<",
-	     hme_read32(hp, &gregs->cfg)));
+	     hme_read32(hp, gregs + GREG_CFG)));
 
-#ifdef __sparc_v9__
-	/* XXX Can sun4d do these too? */
-	if(hp->happy_bursts & DMA_BURST64) {
+	if ((hp->happy_bursts & DMA_BURST64) &&
+	    ((hp->happy_flags & HFLAG_PCI) != 0
+#ifdef CONFIG_SBUS
+	     || sbus_can_burst64(hp->happy_dev)
+#endif
+	     || 0)) {
 		u32 gcfg = GREG_CFG_BURST64;
 
 		/* I have no idea if I should set the extended
 		 * transfer mode bit for Cheerio, so for now I
 		 * do not.  -DaveM
 		 */
-		if((hp->happy_flags & HFLAG_PCI) == 0) {
-			mmu_set_sbus64(hp->happy_sbus_dev,
-				       hp->happy_bursts);
+#ifdef CONFIG_SBUS
+		if ((hp->happy_flags & HFLAG_PCI) == 0 &&
+		    sbus_can_dma_64bit(hp->happy_dev)) {
+			sbus_set_sbus64(hp->happy_dev,
+					hp->happy_bursts);
 			gcfg |= GREG_CFG_64BIT;
 		}
+#endif
 
 		HMD(("64>"));
-		hme_write32(hp, &gregs->cfg, gcfg);
-	} else
-#endif
-	if(hp->happy_bursts & DMA_BURST32) {
+		hme_write32(hp, gregs + GREG_CFG, gcfg);
+	} else if (hp->happy_bursts & DMA_BURST32) {
 		HMD(("32>"));
-		hme_write32(hp, &gregs->cfg, GREG_CFG_BURST32);
-	} else if(hp->happy_bursts & DMA_BURST16) {
+		hme_write32(hp, gregs + GREG_CFG, GREG_CFG_BURST32);
+	} else if (hp->happy_bursts & DMA_BURST16) {
 		HMD(("16>"));
-		hme_write32(hp, &gregs->cfg, GREG_CFG_BURST16);
+		hme_write32(hp, gregs + GREG_CFG, GREG_CFG_BURST16);
 	} else {
 		HMD(("XXX>"));
-		hme_write32(hp, &gregs->cfg, 0);
+		hme_write32(hp, gregs + GREG_CFG, 0);
 	}
 
 	/* Turn off interrupts we do not want to hear. */
 	HMD((", enable global interrupts, "));
-	hme_write32(hp, &gregs->imask,
+	hme_write32(hp, gregs + GREG_IMASK,
 		    (GREG_IMASK_GOTFRAME | GREG_IMASK_RCNTEXP |
 		     GREG_IMASK_SENTFRAME | GREG_IMASK_TXPERR));
 
 	/* Set the transmit ring buffer size. */
 	HMD(("tx rsize=%d oreg[%08x], ", (int)TX_RING_SIZE,
-	     hme_read32(hp, &etxregs->tx_rsize)));
-	hme_write32(hp, &etxregs->tx_rsize, (TX_RING_SIZE >> ETX_RSIZE_SHIFT) - 1);
+	     hme_read32(hp, etxregs + ETX_RSIZE)));
+	hme_write32(hp, etxregs + ETX_RSIZE, (TX_RING_SIZE >> ETX_RSIZE_SHIFT) - 1);
 
 	/* Enable transmitter DVMA. */
 	HMD(("tx dma enable old[%08x], ",
-	     hme_read32(hp, &etxregs->cfg)));
-	hme_write32(hp, &etxregs->cfg,
-		    hme_read32(hp, &etxregs->cfg) | ETX_CFG_DMAENABLE);
+	     hme_read32(hp, etxregs + ETX_CFG)));
+	hme_write32(hp, etxregs + ETX_CFG,
+		    hme_read32(hp, etxregs + ETX_CFG) | ETX_CFG_DMAENABLE);
 
 	/* This chip really rots, for the receiver sometimes when you
 	 * write to it's control registers not all the bits get there
@@ -1474,24 +1648,24 @@
 	 * coverage for this hardware bug yet.
 	 */
 	HMD(("erx regs bug old[%08x]\n",
-	     hme_read32(hp, &erxregs->cfg)));
-	hme_write32(hp, &erxregs->cfg, ERX_CFG_DEFAULT(RX_OFFSET));
-	regtmp = hme_read32(hp, &erxregs->cfg);
-	hme_write32(hp, &erxregs->cfg, ERX_CFG_DEFAULT(RX_OFFSET));
-	if(hme_read32(hp, &erxregs->cfg) != ERX_CFG_DEFAULT(RX_OFFSET)) {
-		printk("happy meal: Eieee, rx config register gets greasy fries.\n");
-		printk("happy meal: Trying to set %08x, reread gives %08lx\n",
+	     hme_read32(hp, erxregs + ERX_CFG)));
+	hme_write32(hp, erxregs + ERX_CFG, ERX_CFG_DEFAULT(RX_OFFSET));
+	regtmp = hme_read32(hp, erxregs + ERX_CFG);
+	hme_write32(hp, erxregs + ERX_CFG, ERX_CFG_DEFAULT(RX_OFFSET));
+	if (hme_read32(hp, erxregs + ERX_CFG) != ERX_CFG_DEFAULT(RX_OFFSET)) {
+		printk(KERN_ERR "happy meal: Eieee, rx config register gets greasy fries.\n");
+		printk(KERN_ERR "happy meal: Trying to set %08x, reread gives %08x\n",
 		       ERX_CFG_DEFAULT(RX_OFFSET), regtmp);
 		/* XXX Should return failure here... */
 	}
 
 	/* Enable Big Mac hash table filter. */
 	HMD(("happy_meal_init: enable hash rx_cfg_old[%08x], ",
-	     hme_read32(hp, &bregs->rx_cfg)));
+	     hme_read32(hp, bregs + BMAC_RXCFG)));
 	rxcfg = BIGMAC_RXCFG_HENABLE;
-	if(hp->dev->flags & IFF_PROMISC)
+	if (hp->dev->flags & IFF_PROMISC)
 		rxcfg |= BIGMAC_RXCFG_PMISC;
-	hme_write32(hp, &bregs->rx_cfg, rxcfg);
+	hme_write32(hp, bregs + BMAC_RXCFG, rxcfg);
 
 	/* Let the bits settle in the chip. */
 	udelay(10);
@@ -1499,33 +1673,33 @@
 	/* Ok, configure the Big Mac transmitter. */
 	HMD(("BIGMAC init, "));
 	regtmp = 0;
-	if(hp->happy_flags & HFLAG_FULL)
+	if (hp->happy_flags & HFLAG_FULL)
 		regtmp |= BIGMAC_TXCFG_FULLDPLX;
-	hme_write32(hp, &bregs->tx_cfg, regtmp | BIGMAC_TXCFG_DGIVEUP);
+	hme_write32(hp, bregs + BMAC_TXCFG, regtmp | BIGMAC_TXCFG_DGIVEUP);
 
 	/* Enable the output drivers no matter what. */
 	regtmp = BIGMAC_XCFG_ODENABLE;
 
 	/* If card can do lance mode, enable it. */
-	if(hp->happy_flags & HFLAG_LANCE)
+	if (hp->happy_flags & HFLAG_LANCE)
 		regtmp |= (DEFAULT_IPG0 << 5) | BIGMAC_XCFG_LANCE;
 
 	/* Disable the MII buffers if using external transceiver. */
-	if(hp->tcvr_type == external)
+	if (hp->tcvr_type == external)
 		regtmp |= BIGMAC_XCFG_MIIDISAB;
 
 	HMD(("XIF config old[%08x], ",
-	     hme_read32(hp, &bregs->xif_cfg)));
-	hme_write32(hp, &bregs->xif_cfg, regtmp);
+	     hme_read32(hp, bregs + BMAC_XIFCFG)));
+	hme_write32(hp, bregs + BMAC_XIFCFG, regtmp);
 
 	/* Start things up. */
 	HMD(("tx old[%08x] and rx [%08x] ON!\n",
-	     hme_read32(hp, &bregs->tx_cfg),
-	     hme_read32(hp, &bregs->rx_cfg)));
-	hme_write32(hp, &bregs->tx_cfg,
-		    hme_read32(hp, &bregs->tx_cfg) | BIGMAC_TXCFG_ENABLE);
-	hme_write32(hp, &bregs->rx_cfg,
-		    hme_read32(hp, &bregs->rx_cfg) | BIGMAC_RXCFG_ENABLE);
+	     hme_read32(hp, bregs + BMAC_TXCFG),
+	     hme_read32(hp, bregs + BMAC_RXCFG)));
+	hme_write32(hp, bregs + BMAC_TXCFG,
+		    hme_read32(hp, bregs + BMAC_TXCFG) | BIGMAC_TXCFG_ENABLE);
+	hme_write32(hp, bregs + BMAC_RXCFG,
+		    hme_read32(hp, bregs + BMAC_RXCFG) | BIGMAC_RXCFG_ENABLE);
 
 	/* Get the autonegotiation started, and the watch timer ticking. */
 	happy_meal_begin_auto_negotiation(hp, tregs, NULL);
@@ -1536,30 +1710,30 @@
 
 static void happy_meal_set_initial_advertisement(struct happy_meal *hp)
 {
-	struct hmeal_tcvregs *tregs	= hp->tcvregs;
-	struct hmeal_bigmacregs *bregs	= hp->bigmacregs;
-	struct hmeal_gregs *gregs	= hp->gregs;
+	unsigned long tregs	= hp->tcvregs;
+	unsigned long bregs	= hp->bigmacregs;
+	unsigned long gregs	= hp->gregs;
 
 	happy_meal_stop(hp, gregs);
-	hme_write32(hp, &tregs->int_mask, 0xffff);
-	if(hp->happy_flags & HFLAG_FENABLE)
-		hme_write32(hp, &tregs->cfg,
-			    hme_read32(hp, &tregs->cfg) & ~(TCV_CFG_BENABLE));
+	hme_write32(hp, tregs + TCVR_IMASK, 0xffff);
+	if (hp->happy_flags & HFLAG_FENABLE)
+		hme_write32(hp, tregs + TCVR_CFG,
+			    hme_read32(hp, tregs + TCVR_CFG) & ~(TCV_CFG_BENABLE));
 	else
-		hme_write32(hp, &tregs->cfg,
-			    hme_read32(hp, &tregs->cfg) | TCV_CFG_BENABLE);
+		hme_write32(hp, tregs + TCVR_CFG,
+			    hme_read32(hp, tregs + TCVR_CFG) | TCV_CFG_BENABLE);
 	happy_meal_transceiver_check(hp, tregs);
 	switch(hp->tcvr_type) {
 	case none:
 		return;
 	case internal:
-		hme_write32(hp, &bregs->xif_cfg, 0);
+		hme_write32(hp, bregs + BMAC_XIFCFG, 0);
 		break;
 	case external:
-		hme_write32(hp, &bregs->xif_cfg, BIGMAC_XCFG_MIIDISAB);
+		hme_write32(hp, bregs + BMAC_XIFCFG, BIGMAC_XCFG_MIIDISAB);
 		break;
 	};
-	if(happy_meal_tcvr_reset(hp, tregs))
+	if (happy_meal_tcvr_reset(hp, tregs))
 		return;
 
 	/* Latch PHY registers as of now. */
@@ -1567,20 +1741,20 @@
 	hp->sw_advertise = happy_meal_tcvr_read(hp, tregs, DP83840_ADVERTISE);
 
 	/* Advertise everything we can support. */
-	if(hp->sw_bmsr & BMSR_10HALF)
+	if (hp->sw_bmsr & BMSR_10HALF)
 		hp->sw_advertise |= (ADVERTISE_10HALF);
 	else
 		hp->sw_advertise &= ~(ADVERTISE_10HALF);
 
-	if(hp->sw_bmsr & BMSR_10FULL)
+	if (hp->sw_bmsr & BMSR_10FULL)
 		hp->sw_advertise |= (ADVERTISE_10FULL);
 	else
 		hp->sw_advertise &= ~(ADVERTISE_10FULL);
-	if(hp->sw_bmsr & BMSR_100HALF)
+	if (hp->sw_bmsr & BMSR_100HALF)
 		hp->sw_advertise |= (ADVERTISE_100HALF);
 	else
 		hp->sw_advertise &= ~(ADVERTISE_100HALF);
-	if(hp->sw_bmsr & BMSR_100FULL)
+	if (hp->sw_bmsr & BMSR_100FULL)
 		hp->sw_advertise |= (ADVERTISE_100FULL);
 	else
 		hp->sw_advertise &= ~(ADVERTISE_100FULL);
@@ -1592,50 +1766,48 @@
 /* Once status is latched (by happy_meal_interrupt) it is cleared by
  * the hardware, so we cannot re-read it and get a correct value.
  */
-static int happy_meal_is_not_so_happy(struct happy_meal *hp,
-				      struct hmeal_gregs *gregs,
-				      unsigned long status)
+static int happy_meal_is_not_so_happy(struct happy_meal *hp, u32 status)
 {
 	int reset = 0;
 	
 	/* Only print messages for non-counter related interrupts. */
-	if(status & (GREG_STAT_STSTERR | GREG_STAT_TFIFO_UND |
-		     GREG_STAT_MAXPKTERR | GREG_STAT_RXERR |
-		     GREG_STAT_RXPERR | GREG_STAT_RXTERR | GREG_STAT_EOPERR |
-		     GREG_STAT_MIFIRQ | GREG_STAT_TXEACK | GREG_STAT_TXLERR |
-		     GREG_STAT_TXPERR | GREG_STAT_TXTERR | GREG_STAT_SLVERR |
-		     GREG_STAT_SLVPERR))
-		printk("%s: Error interrupt for happy meal, status = %08lx\n",
+	if (status & (GREG_STAT_STSTERR | GREG_STAT_TFIFO_UND |
+		      GREG_STAT_MAXPKTERR | GREG_STAT_RXERR |
+		      GREG_STAT_RXPERR | GREG_STAT_RXTERR | GREG_STAT_EOPERR |
+		      GREG_STAT_MIFIRQ | GREG_STAT_TXEACK | GREG_STAT_TXLERR |
+		      GREG_STAT_TXPERR | GREG_STAT_TXTERR | GREG_STAT_SLVERR |
+		      GREG_STAT_SLVPERR))
+		printk(KERN_ERR "%s: Error interrupt for happy meal, status = %08x\n",
 		       hp->dev->name, status);
 
-	if(status & GREG_STAT_RFIFOVF) {
+	if (status & GREG_STAT_RFIFOVF) {
 		/* Receive FIFO overflow is harmless and the hardware will take
 		   care of it, just some packets are lost. Who cares. */
 		printk(KERN_DEBUG "%s: Happy Meal receive FIFO overflow.\n", hp->dev->name);
 	}
 
-	if(status & GREG_STAT_STSTERR) {
+	if (status & GREG_STAT_STSTERR) {
 		/* BigMAC SQE link test failed. */
-		printk("%s: Happy Meal BigMAC SQE test failed.\n", hp->dev->name);
+		printk(KERN_ERR "%s: Happy Meal BigMAC SQE test failed.\n", hp->dev->name);
 		reset = 1;
 	}
 
-	if(status & GREG_STAT_TFIFO_UND) {
+	if (status & GREG_STAT_TFIFO_UND) {
 		/* Transmit FIFO underrun, again DMA error likely. */
-		printk("%s: Happy Meal transmitter FIFO underrun, DMA error.\n",
+		printk(KERN_ERR "%s: Happy Meal transmitter FIFO underrun, DMA error.\n",
 		       hp->dev->name);
 		reset = 1;
 	}
 
-	if(status & GREG_STAT_MAXPKTERR) {
+	if (status & GREG_STAT_MAXPKTERR) {
 		/* Driver error, tried to transmit something larger
 		 * than ethernet max mtu.
 		 */
-		printk("%s: Happy Meal MAX Packet size error.\n", hp->dev->name);
+		printk(KERN_ERR "%s: Happy Meal MAX Packet size error.\n", hp->dev->name);
 		reset = 1;
 	}
 
-	if(status & GREG_STAT_NORXD) {
+	if (status & GREG_STAT_NORXD) {
 		/* This is harmless, it just means the system is
 		 * quite loaded and the incomming packet rate was
 		 * faster than the interrupt handler could keep up
@@ -1646,87 +1818,87 @@
 		       hp->dev->name);
 	}
 
-	if(status & (GREG_STAT_RXERR|GREG_STAT_RXPERR|GREG_STAT_RXTERR)) {
+	if (status & (GREG_STAT_RXERR|GREG_STAT_RXPERR|GREG_STAT_RXTERR)) {
 		/* All sorts of DMA receive errors. */
-		printk("%s: Happy Meal rx DMA errors [ ", hp->dev->name);
-		if(status & GREG_STAT_RXERR)
+		printk(KERN_ERR "%s: Happy Meal rx DMA errors [ ", hp->dev->name);
+		if (status & GREG_STAT_RXERR)
 			printk("GenericError ");
-		if(status & GREG_STAT_RXPERR)
+		if (status & GREG_STAT_RXPERR)
 			printk("ParityError ");
-		if(status & GREG_STAT_RXTERR)
+		if (status & GREG_STAT_RXTERR)
 			printk("RxTagBotch ");
 		printk("]\n");
 		reset = 1;
 	}
 
-	if(status & GREG_STAT_EOPERR) {
+	if (status & GREG_STAT_EOPERR) {
 		/* Driver bug, didn't set EOP bit in tx descriptor given
 		 * to the happy meal.
 		 */
-		printk("%s: EOP not set in happy meal transmit descriptor!\n",
+		printk(KERN_ERR "%s: EOP not set in happy meal transmit descriptor!\n",
 		       hp->dev->name);
 		reset = 1;
 	}
 
-	if(status & GREG_STAT_MIFIRQ) {
+	if (status & GREG_STAT_MIFIRQ) {
 		/* MIF signalled an interrupt, were we polling it? */
-		printk("%s: Happy Meal MIF interrupt.\n", hp->dev->name);
+		printk(KERN_ERR "%s: Happy Meal MIF interrupt.\n", hp->dev->name);
 	}
 
-	if(status &
-	   (GREG_STAT_TXEACK|GREG_STAT_TXLERR|GREG_STAT_TXPERR|GREG_STAT_TXTERR)) {
+	if (status &
+	    (GREG_STAT_TXEACK|GREG_STAT_TXLERR|GREG_STAT_TXPERR|GREG_STAT_TXTERR)) {
 		/* All sorts of transmit DMA errors. */
-		printk("%s: Happy Meal tx DMA errors [ ", hp->dev->name);
-		if(status & GREG_STAT_TXEACK)
+		printk(KERN_ERR "%s: Happy Meal tx DMA errors [ ", hp->dev->name);
+		if (status & GREG_STAT_TXEACK)
 			printk("GenericError ");
-		if(status & GREG_STAT_TXLERR)
+		if (status & GREG_STAT_TXLERR)
 			printk("LateError ");
-		if(status & GREG_STAT_TXPERR)
+		if (status & GREG_STAT_TXPERR)
 			printk("ParityErro ");
-		if(status & GREG_STAT_TXTERR)
+		if (status & GREG_STAT_TXTERR)
 			printk("TagBotch ");
 		printk("]\n");
 		reset = 1;
 	}
 
-	if(status & (GREG_STAT_SLVERR|GREG_STAT_SLVPERR)) {
+	if (status & (GREG_STAT_SLVERR|GREG_STAT_SLVPERR)) {
 		/* Bus or parity error when cpu accessed happy meal registers
 		 * or it's internal FIFO's.  Should never see this.
 		 */
-		printk("%s: Happy Meal register access SBUS slave (%s) error.\n",
+		printk(KERN_ERR "%s: Happy Meal register access SBUS slave (%s) error.\n",
 		       hp->dev->name,
 		       (status & GREG_STAT_SLVPERR) ? "parity" : "generic");
 		reset = 1;
 	}
 
-	if(reset) {
-		printk("%s: Resetting...\n", hp->dev->name);
+	if (reset) {
+		printk(KERN_NOTICE "%s: Resetting...\n", hp->dev->name);
 		happy_meal_init(hp, 1);
 		return 1;
 	}
 	return 0;
 }
 
-static inline void happy_meal_mif_interrupt(struct happy_meal *hp,
-					    struct hmeal_gregs *gregs,
-					    struct hmeal_tcvregs *tregs)
+static void happy_meal_mif_interrupt(struct happy_meal *hp)
 {
-	printk("%s: Link status change.\n", hp->dev->name);
+	unsigned long tregs = hp->tcvregs;
+
+	printk(KERN_INFO "%s: Link status change.\n", hp->dev->name);
 	hp->sw_bmcr = happy_meal_tcvr_read(hp, tregs, DP83840_BMCR);
 	hp->sw_lpa = happy_meal_tcvr_read(hp, tregs, DP83840_LPA);
 
 	/* Use the fastest transmission protocol possible. */
-	if(hp->sw_lpa & LPA_100FULL) {
-		printk("%s: Switching to 100Mbps at full duplex.", hp->dev->name);
+	if (hp->sw_lpa & LPA_100FULL) {
+		printk(KERN_INFO "%s: Switching to 100Mbps at full duplex.", hp->dev->name);
 		hp->sw_bmcr |= (BMCR_FULLDPLX | BMCR_SPEED100);
-	} else if(hp->sw_lpa & LPA_100HALF) {
-		printk("%s: Switching to 100MBps at half duplex.", hp->dev->name);
+	} else if (hp->sw_lpa & LPA_100HALF) {
+		printk(KERN_INFO "%s: Switching to 100MBps at half duplex.", hp->dev->name);
 		hp->sw_bmcr |= BMCR_SPEED100;
-	} else if(hp->sw_lpa & LPA_10FULL) {
-		printk("%s: Switching to 10MBps at full duplex.", hp->dev->name);
+	} else if (hp->sw_lpa & LPA_10FULL) {
+		printk(KERN_INFO "%s: Switching to 10MBps at full duplex.", hp->dev->name);
 		hp->sw_bmcr |= BMCR_FULLDPLX;
 	} else {
-		printk("%s: Using 10Mbps at half duplex.", hp->dev->name);
+		printk(KERN_INFO "%s: Using 10Mbps at half duplex.", hp->dev->name);
 	}
 	happy_meal_tcvr_write(hp, tregs, DP83840_BMCR, hp->sw_bmcr);
 
@@ -1740,60 +1912,28 @@
 #define TXD(x)
 #endif
 
-static inline void happy_meal_tx(struct happy_meal *hp)
+static void happy_meal_tx(struct happy_meal *hp)
 {
 	struct happy_meal_txd *txbase = &hp->happy_block->happy_meal_txd[0];
 	struct happy_meal_txd *this;
 	int elem = hp->tx_old;
 
 	TXD(("TX<"));
-	while(elem != hp->tx_new) {
+	while (elem != hp->tx_new) {
 		struct sk_buff *skb;
+		u32 flags, dma_addr;
 
 		TXD(("[%d]", elem));
 		this = &txbase[elem];
-		if(this->tx_flags & TXFLAG_OWN)
+		flags = hme_read_desc32(hp, &this->tx_flags);
+		if (flags & TXFLAG_OWN)
 			break;
+		dma_addr = hme_read_desc32(hp, &this->tx_addr);
 		skb = hp->tx_skbs[elem];
+		hme_dma_unmap(hp, dma_addr, skb->len);
 		hp->tx_skbs[elem] = NULL;
-		hp->net_stats.tx_bytes+=skb->len;
-		
-		dev_kfree_skb(skb);
-
-		hp->net_stats.tx_packets++;
-		elem = NEXT_TX(elem);
-	}
-	hp->tx_old = elem;
-	TXD((">"));
-}
-
-#ifdef CONFIG_PCI
-static inline void pci_happy_meal_tx(struct happy_meal *hp)
-{
-	struct happy_meal_txd *txbase = &hp->happy_block->happy_meal_txd[0];
-	struct happy_meal_txd *this;
-	int elem = hp->tx_old;
+		hp->net_stats.tx_bytes += skb->len;
 
-	TXD(("TX<"));
-	while(elem != hp->tx_new) {
-		struct sk_buff *skb;
-		unsigned int flags;
-
-		TXD(("[%d]", elem));
-		this = &txbase[elem];
-#ifdef  __sparc_v9__
-		__asm__ __volatile__("lduwa [%1] %2, %0"
-				     : "=r" (flags)
-				     : "r" (&this->tx_flags), "i" (ASI_PL));
-#else
-		flags = flip_dword(this->tx_flags);
-#endif
-		if(flags & TXFLAG_OWN)
-			break;
-		skb = hp->tx_skbs[elem];
-		hp->tx_skbs[elem] = NULL;
-		hp->net_stats.tx_bytes+=skb->len;
-		
 		dev_kfree_skb(skb);
 
 		hp->net_stats.tx_packets++;
@@ -1802,31 +1942,6 @@
 	hp->tx_old = elem;
 	TXD((">"));
 }
-#endif
-
-#ifndef __sparc_v9__
-static inline void sun4c_happy_meal_tx(struct happy_meal *hp)
-{
-	struct happy_meal_txd *txbase = &hp->happy_block->happy_meal_txd[0];
-	struct happy_meal_txd *this;
-	int elem = hp->tx_old;
-
-	TXD(("TX<"));
-	while(elem != hp->tx_new) {
-		TXD(("[%d]", elem));
-
-		this = &txbase[elem];
-
-		if(this->tx_flags & TXFLAG_OWN)
-			break;
-
-		hp->net_stats.tx_packets++;
-		elem = NEXT_TX(elem);
-	}
-	hp->tx_old = elem;
-	TXD((">"));
-}
-#endif
 
 #ifdef RXDEBUG
 #define RXD(x) printk x
@@ -1841,30 +1956,30 @@
  * ring when we cannot get a new skb and give them all back to the happy meal,
  * maybe things will be "happier" now.
  */
-static inline void happy_meal_rx(struct happy_meal *hp, struct net_device *dev,
-				 struct hmeal_gregs *gregs)
+static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
 {
 	struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0];
 	struct happy_meal_rxd *this;
 	int elem = hp->rx_new, drops = 0;
+	u32 flags;
 
 	RXD(("RX<"));
 	this = &rxbase[elem];
-	while(!(this->rx_flags & RXFLAG_OWN)) {
+	while (!((flags = hme_read_desc32(hp, &this->rx_flags)) & RXFLAG_OWN)) {
 		struct sk_buff *skb;
-		unsigned int flags = this->rx_flags;
 		int len = flags >> 16;
 		u16 csum = flags & RXFLAG_CSUM;
+		u32 dma_addr = hme_read_desc32(hp, &this->rx_addr);
 
 		RXD(("[%d ", elem));
 
 		/* Check for errors. */
-		if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
+		if ((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
 			RXD(("ERR(%08x)]", flags));
 			hp->net_stats.rx_errors++;
-			if(len < ETH_ZLEN)
+			if (len < ETH_ZLEN)
 				hp->net_stats.rx_length_errors++;
-			if(len & (RXFLAG_OVERFLOW >> 16)) {
+			if (len & (RXFLAG_OVERFLOW >> 16)) {
 				hp->net_stats.rx_over_errors++;
 				hp->net_stats.rx_fifo_errors++;
 			}
@@ -1872,41 +1987,36 @@
 			/* Return it to the Happy meal. */
 	drop_it:
 			hp->net_stats.rx_dropped++;
-			this->rx_addr = kva_to_hva(hp, hp->rx_skbs[elem]->data);
-			this->rx_flags =
-				(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
+			hme_write_rxd(hp, this,
+				      (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
+				      dma_addr);
 			goto next;
 		}
 		skb = hp->rx_skbs[elem];
-#ifdef NEED_DMA_SYNCHRONIZATION
-		mmu_sync_dma(kva_to_hva(hp, skb->data),
-			     skb->len, hp->happy_sbus_dev->my_bus);
-#endif
-		if(len > RX_COPY_THRESHOLD) {
+		if (len > RX_COPY_THRESHOLD) {
 			struct sk_buff *new_skb;
 
 			/* Now refill the entry, if we can. */
-			new_skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE,
-						       (GFP_DMA|GFP_ATOMIC));
-			if(!new_skb) {
+			new_skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC);
+			if (new_skb == NULL) {
 				drops++;
 				goto drop_it;
 			}
-
+			hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE);
 			hp->rx_skbs[elem] = new_skb;
 			new_skb->dev = dev;
 			skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET));
-			rxbase[elem].rx_addr = kva_to_hva(hp, new_skb->data);
+			hme_write_rxd(hp, this,
+				      (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
+				      hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE));
 			skb_reserve(new_skb, RX_OFFSET);
-			rxbase[elem].rx_flags =
-				(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
 
 			/* Trim the original skb for the netif. */
 			skb_trim(skb, len);
 		} else {
 			struct sk_buff *copy_skb = dev_alloc_skb(len + 2);
 
-			if(!copy_skb) {
+			if (copy_skb == NULL) {
 				drops++;
 				goto drop_it;
 			}
@@ -1914,18 +2024,19 @@
 			copy_skb->dev = dev;
 			skb_reserve(copy_skb, 2);
 			skb_put(copy_skb, len);
+			hme_dma_sync(hp, dma_addr, len);
 			memcpy(copy_skb->data, skb->data, len);
 
 			/* Reuse original ring buffer. */
-			rxbase[elem].rx_addr = kva_to_hva(hp, skb->data);
-			rxbase[elem].rx_flags =
-				(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
+			hme_write_rxd(hp, this,
+				      (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
+				      dma_addr);
 
 			skb = copy_skb;
 		}
 
 		/* This card is _fucking_ hot... */
-		if(!(csum ^ 0xffff))
+		if (!(csum ^ 0xffff))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 		else
 			skb->ip_summed = CHECKSUM_NONE;
@@ -1935,535 +2046,107 @@
 		netif_rx(skb);
 
 		hp->net_stats.rx_packets++;
-		hp->net_stats.rx_bytes+=len;
+		hp->net_stats.rx_bytes += len;
 	next:
 		elem = NEXT_RX(elem);
 		this = &rxbase[elem];
 	}
 	hp->rx_new = elem;
-	if(drops)
-		printk("%s: Memory squeeze, deferring packet.\n", hp->dev->name);
+	if (drops)
+		printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n", hp->dev->name);
 	RXD((">"));
 }
 
-#ifdef CONFIG_PCI
-static inline void pci_happy_meal_rx(struct happy_meal *hp, struct net_device *dev,
-				     struct hmeal_gregs *gregs)
+static void happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0];
-	struct happy_meal_rxd *this;
-	unsigned int flags;
-	int elem = hp->rx_new, drops = 0;
-
-	RXD(("RX<"));
-	this = &rxbase[elem];
-#ifdef  __sparc_v9__
-	__asm__ __volatile__("lduwa [%1] %2, %0"
-			     : "=r" (flags)
-			     : "r" (&this->rx_flags), "i" (ASI_PL));
-#else
-	flags = flip_dword(this->rx_flags); /* FIXME */
-#endif
-	while(!(flags & RXFLAG_OWN)) {
-		struct sk_buff *skb;
-		int len;
-		u16 csum;
-
-		RXD(("[%d ", elem));
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct happy_meal *hp  = (struct happy_meal *) dev->priv;
+	u32 happy_status       = hme_read32(hp, hp->gregs + GREG_STAT);
 
-		len = flags >> 16;
-		csum = flags & RXFLAG_CSUM;
+	HMD(("happy_meal_interrupt: status=%08x ", happy_status));
 
-		/* Check for errors. */
-		if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
-			RXD(("ERR(%08x)]", flags));
-			hp->net_stats.rx_errors++;
-			if(len < ETH_ZLEN)
-				hp->net_stats.rx_length_errors++;
-			if(len & (RXFLAG_OVERFLOW >> 16)) {
-				hp->net_stats.rx_over_errors++;
-				hp->net_stats.rx_fifo_errors++;
-			}
+	dev->interrupt = 1;
 
-			/* Return it to the Happy meal. */
-	drop_it:
-			hp->net_stats.rx_dropped++;
-			pcihme_write_rxd(this,
-				 (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
-				 (u32) virt_to_bus((volatile void *)hp->rx_skbs[elem]->data));
-			goto next;
+	if (happy_status & GREG_STAT_ERRORS) {
+		HMD(("ERRORS "));
+		if (happy_meal_is_not_so_happy(hp, /* un- */ happy_status)) {
+			dev->interrupt = 0;
+			return;
 		}
-		skb = hp->rx_skbs[elem];
-		if(len > RX_COPY_THRESHOLD) {
-			struct sk_buff *new_skb;
-
-			/* Now refill the entry, if we can. */
-			new_skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE,
-						       (GFP_DMA|GFP_ATOMIC));
-			if(!new_skb) {
-				drops++;
-				goto drop_it;
-			}
+	}
 
-			hp->rx_skbs[elem] = new_skb;
-			new_skb->dev = dev;
-			skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET));
-			pcihme_write_rxd(&rxbase[elem],
-				 (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
-				  (u32)virt_to_bus((volatile void *)new_skb->data));
-			skb_reserve(new_skb, RX_OFFSET);
+	if (happy_status & GREG_STAT_MIFIRQ) {
+		HMD(("MIFIRQ "));
+		happy_meal_mif_interrupt(hp);
+	}
 
-			/* Trim the original skb for the netif. */
-			skb_trim(skb, len);
-		} else {
-			struct sk_buff *copy_skb = dev_alloc_skb(len + 2);
+	if (happy_status & GREG_STAT_TXALL) {
+		HMD(("TXALL "));
+		happy_meal_tx(hp);
+	}
 
-			if(!copy_skb) {
-				drops++;
-				goto drop_it;
-			}
+	if (happy_status & GREG_STAT_RXTOHOST) {
+		HMD(("RXTOHOST "));
+		happy_meal_rx(hp, dev);
+	}
 
-			copy_skb->dev = dev;
-			skb_reserve(copy_skb, 2);
-			skb_put(copy_skb, len);
-			memcpy(copy_skb->data, skb->data, len);
+	if (dev->tbusy && (TX_BUFFS_AVAIL(hp) > 0)) {
+		hp->dev->tbusy = 0;
+		mark_bh(NET_BH);
+	}
 
-			/* Reuse original ring buffer. */
-			pcihme_write_rxd(&rxbase[elem],
-				 (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
-				 (u32)virt_to_bus((volatile void *)skb->data));
-
-			skb = copy_skb;
-		}
-
-		/* This card is _fucking_ hot... */
-		if(!~(csum))
-			skb->ip_summed = CHECKSUM_UNNECESSARY;
-		else
-			skb->ip_summed = CHECKSUM_NONE;
-
-		RXD(("len=%d csum=%4x]", len, csum));
-		skb->protocol = eth_type_trans(skb, dev);
-		netif_rx(skb);
-
-		hp->net_stats.rx_packets++;
-		hp->net_stats.rx_bytes+=len;
-	next:
-		elem = NEXT_RX(elem);
-		this = &rxbase[elem];
-#ifdef __sparc_v9__ 
-		__asm__ __volatile__("lduwa [%1] %2, %0"
-				     : "=r" (flags)
-				     : "r" (&this->rx_flags), "i" (ASI_PL));
-#else
-		flags = flip_dword(this->rx_flags); /* FIXME */
-#endif
-	}
-	hp->rx_new = elem;
-	if(drops)
-		printk("%s: Memory squeeze, deferring packet.\n", hp->dev->name);
-	RXD((">"));
-}
-#endif
-
-#ifndef __sparc_v9__
-static inline void sun4c_happy_meal_rx(struct happy_meal *hp, struct net_device *dev,
-				       struct hmeal_gregs *gregs)
-{
-	struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0];
-	struct happy_meal_rxd *this;
-	struct hmeal_buffers *hbufs = hp->sun4c_buffers;
-	__u32 hbufs_dvma = hp->s4c_buf_dvma;
-	int elem = hp->rx_new, drops = 0;
-
-	RXD(("RX<"));
-	this = &rxbase[elem];
-	while(!(this->rx_flags & RXFLAG_OWN)) {
-		struct sk_buff *skb;
-		unsigned int flags = this->rx_flags;
-		unsigned char *thisbuf = &hbufs->rx_buf[elem][0];
-		__u32 thisbuf_dvma = hbufs_dvma + hbuf_offset(rx_buf, elem);
-		int len = flags >> 16;
-
-		RXD(("[%d ", elem));
-
-		/* Check for errors. */
-		if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
-			RXD(("ERR(%08x)]", flags));
-			hp->net_stats.rx_errors++;
-			if(len < ETH_ZLEN)
-				hp->net_stats.rx_length_errors++;
-			if(len & (RXFLAG_OVERFLOW >> 16)) {
-				hp->net_stats.rx_over_errors++;
-				hp->net_stats.rx_fifo_errors++;
-			}
-
-			hp->net_stats.rx_dropped++;
-		} else {
-			skb = dev_alloc_skb(len + 2);
-			if(skb == 0) {
-				drops++;
-				hp->net_stats.rx_dropped++;
-			} else {
-				RXD(("len=%d]", len));
-				skb->dev = hp->dev;
-				skb_reserve(skb, 2);
-				skb_put(skb, len);
-				eth_copy_and_sum(skb, (thisbuf+2), len, 0);
-				skb->protocol = eth_type_trans(skb, dev);
-				netif_rx(skb);
-				hp->net_stats.rx_packets++;
-				hp->net_stats.rx_bytes+=len;
-			}
-		}
-		/* Return the buffer to the Happy Meal. */
-		this->rx_addr = thisbuf_dvma;
-		this->rx_flags =
-			(RXFLAG_OWN | ((SUN4C_RX_BUFF_SIZE - RX_OFFSET) << 16));
-
-		elem = NEXT_RX(elem);
-		this = &rxbase[elem];
-	}
-	hp->rx_new = elem;
-	if(drops)
-		printk("%s: Memory squeeze, deferring packet.\n", hp->dev->name);
-	RXD((">"));
-}
-
-static inline void sun4d_happy_meal_rx(struct happy_meal *hp, struct net_device *dev,
-				       struct hmeal_gregs *gregs)
-{
-	struct happy_meal_rxd *rxbase = &hp->happy_block->happy_meal_rxd[0];
-	struct happy_meal_rxd *this;
-	int elem = hp->rx_new, drops = 0;
-	__u32 va;
-
-	RXD(("RX<"));
-	this = &rxbase[elem];
-	while(!(this->rx_flags & RXFLAG_OWN)) {
-		struct sk_buff *skb;
-		unsigned int flags = this->rx_flags;
-		int len = flags >> 16;
-		u16 csum = flags & RXFLAG_CSUM;
-
-		RXD(("[%d ", elem));
-
-		/* Check for errors. */
-		if((len < ETH_ZLEN) || (flags & RXFLAG_OVERFLOW)) {
-			RXD(("ERR(%08x)]", flags));
-			hp->net_stats.rx_errors++;
-			if(len < ETH_ZLEN)
-				hp->net_stats.rx_length_errors++;
-			if(len & (RXFLAG_OVERFLOW >> 16)) {
-				hp->net_stats.rx_over_errors++;
-				hp->net_stats.rx_fifo_errors++;
-			}
-
-			/* Return it to the Happy meal. */
-	drop_it:
-			hp->net_stats.rx_dropped++;
-			va = (__u32)hp->sun4d_buffers + elem * PAGE_SIZE;
-			this->rx_addr = iounit_map_dma_page(va, hp->rx_skbs[elem]->data,
-							    hp->happy_sbus_dev->my_bus);
-			this->rx_flags =
-				(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
-			goto next;
-		}
-		skb = hp->rx_skbs[elem];
-		if(len > RX_COPY_THRESHOLD) {
-			struct sk_buff *new_skb;
-
-			/* Now refill the entry, if we can. */
-			new_skb = happy_meal_alloc_skb(RX_BUF_ALLOC_SIZE,
-						       (GFP_DMA | GFP_ATOMIC));
-			if(!new_skb) {
-				drops++;
-				goto drop_it;
-			}
-
-			hp->rx_skbs[elem] = new_skb;
-			new_skb->dev = dev;
-			skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET));
-			va = (__u32)hp->sun4d_buffers + elem * PAGE_SIZE;
-			rxbase[elem].rx_addr = iounit_map_dma_page(va, new_skb->data,
-								hp->happy_sbus_dev->my_bus);
-
-			skb_reserve(new_skb, RX_OFFSET);
-			rxbase[elem].rx_flags =
-				(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
-
-			/* Trim the original skb for the netif. */
-			skb_trim(skb, len);
-		} else {
-			struct sk_buff *copy_skb = dev_alloc_skb(len + 2);
-
-			if(!copy_skb) {
-				drops++;
-				goto drop_it;
-			}
-
-			copy_skb->dev = dev;
-			skb_reserve(copy_skb, 2);
-			skb_put(copy_skb, len);
-			memcpy(copy_skb->data, skb->data, len);
-
-			/* Reuse original ring buffer. */
-			va = (__u32)hp->sun4d_buffers + elem * PAGE_SIZE;
-			rxbase[elem].rx_addr = iounit_map_dma_page(va, skb->data,
-								hp->happy_sbus_dev->my_bus);
-			rxbase[elem].rx_flags =
-				(RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16));
-
-			skb = copy_skb;
-		}
-
-		/* This card is _fucking_ hot... */
-		if(!(csum ^ 0xffff))
-			skb->ip_summed = CHECKSUM_UNNECESSARY;
-		else
-			skb->ip_summed = CHECKSUM_NONE;
-
-		RXD(("len=%d csum=%4x]", len, csum));
-		skb->protocol = eth_type_trans(skb, dev);
-		netif_rx(skb);
-
-		hp->net_stats.rx_packets++;
-		hp->net_stats.rx_bytes+=len;
-	next:
-		elem = NEXT_RX(elem);
-		this = &rxbase[elem];
-	}
-	hp->rx_new = elem;
-	if(drops)
-		printk("%s: Memory squeeze, deferring packet.\n", hp->dev->name);
-	RXD((">"));
-}
-#endif
-
-static void happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev            = (struct net_device *) dev_id;
-	struct happy_meal *hp         = (struct happy_meal *) dev->priv;
-	struct hmeal_gregs *gregs     = hp->gregs;
-	struct hmeal_tcvregs *tregs   = hp->tcvregs;
-	unsigned int happy_status    = hme_read32(hp, &gregs->stat);
-
-	HMD(("happy_meal_interrupt: status=%08x ", happy_status));
-
-	dev->interrupt = 1;
-
-	if(happy_status & GREG_STAT_ERRORS) {
-		HMD(("ERRORS "));
-		if(happy_meal_is_not_so_happy(hp, gregs, /* un- */ happy_status)) {
-			dev->interrupt = 0;
-			return;
-		}
-	}
-
-	if(happy_status & GREG_STAT_MIFIRQ) {
-		HMD(("MIFIRQ "));
-		happy_meal_mif_interrupt(hp, gregs, tregs);
-	}
-
-	if(happy_status & GREG_STAT_TXALL) {
-		HMD(("TXALL "));
-		happy_meal_tx(hp);
-	}
-
-	if(happy_status & GREG_STAT_RXTOHOST) {
-		HMD(("RXTOHOST "));
-		happy_meal_rx(hp, dev, gregs);
-	}
-
-	if(dev->tbusy && (TX_BUFFS_AVAIL(hp) >= 0)) {
-		hp->dev->tbusy = 0;
-		mark_bh(NET_BH);
-	}
-
-	dev->interrupt = 0;
-	HMD(("done\n"));
-}
-
-#ifdef CONFIG_PCI
-static void pci_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev            = (struct net_device *) dev_id;
-	struct happy_meal *hp         = (struct happy_meal *) dev->priv;
-	struct hmeal_gregs *gregs     = hp->gregs;
-	struct hmeal_tcvregs *tregs   = hp->tcvregs;
-	unsigned int happy_status     = readl((unsigned long)&gregs->stat);
-
-	HMD(("happy_meal_interrupt: status=%08x ", happy_status));
-
-	dev->interrupt = 1;
-
-	if(happy_status & GREG_STAT_ERRORS) {
-		HMD(("ERRORS "));
-		if(happy_meal_is_not_so_happy(hp, gregs, /* un- */ happy_status)) {
-			dev->interrupt = 0;
-			return;
-		}
-	}
-
-	if(happy_status & GREG_STAT_MIFIRQ) {
-		HMD(("MIFIRQ "));
-		happy_meal_mif_interrupt(hp, gregs, tregs);
-	}
-
-	if(happy_status & GREG_STAT_TXALL) {
-		HMD(("TXALL "));
-		pci_happy_meal_tx(hp);
-	}
-
-	if(happy_status & GREG_STAT_RXTOHOST) {
-		HMD(("RXTOHOST "));
-		pci_happy_meal_rx(hp, dev, gregs);
-	}
-
-	if(dev->tbusy && (TX_BUFFS_AVAIL(hp) >= 0)) {
-		hp->dev->tbusy = 0;
-		mark_bh(NET_BH);
-	}
-	tx_add_log(hp, TXLOG_ACTION_IRQ, happy_status);
-	dev->interrupt = 0;
-	HMD(("done\n"));
-}
-#endif
-
-#ifndef __sparc_v9__
-static void sun4c_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev            = (struct net_device *) dev_id;
-	struct happy_meal *hp         = (struct happy_meal *) dev->priv;
-	struct hmeal_gregs *gregs     = hp->gregs;
-	struct hmeal_tcvregs *tregs   = hp->tcvregs;
-	unsigned int happy_status    = hme_read32(hp, &gregs->stat);
-
-	HMD(("happy_meal_interrupt: status=%08x ", happy_status));
-
-	dev->interrupt = 1;
-
-	if(happy_status & GREG_STAT_ERRORS) {
-		HMD(("ERRORS "));
-		if(happy_meal_is_not_so_happy(hp, gregs, /* un- */ happy_status)) {
-			dev->interrupt = 0;
-			return;
-		}
-	}
-
-	if(happy_status & GREG_STAT_MIFIRQ) {
-		HMD(("MIFIRQ "));
-		happy_meal_mif_interrupt(hp, gregs, tregs);
-	}
-
-	if(happy_status & GREG_STAT_TXALL) {
-		HMD(("TXALL "));
-		sun4c_happy_meal_tx(hp);
-	}
-
-	if(happy_status & GREG_STAT_RXTOHOST) {
-		HMD(("RXTOHOST "));
-		sun4c_happy_meal_rx(hp, dev, gregs);
-	}
-
-	if(dev->tbusy && (TX_BUFFS_AVAIL(hp) >= 0)) {
-		hp->dev->tbusy = 0;
-		mark_bh(NET_BH);
-	}
-
-	dev->interrupt = 0;
-	HMD(("done\n"));
-}
-
-static void sun4d_happy_meal_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev            = (struct net_device *) dev_id;
-	struct happy_meal *hp         = (struct happy_meal *) dev->priv;
-	struct hmeal_gregs *gregs     = hp->gregs;
-	struct hmeal_tcvregs *tregs   = hp->tcvregs;
-	unsigned int happy_status    = hme_read32(hp, &gregs->stat);
-
-	HMD(("happy_meal_interrupt: status=%08x ", happy_status));
-
-	dev->interrupt = 1;
-
-	if(happy_status & GREG_STAT_ERRORS) {
-		HMD(("ERRORS "));
-		if(happy_meal_is_not_so_happy(hp, gregs, /* un- */ happy_status)) {
-			dev->interrupt = 0;
-			return;
-		}
-	}
-
-	if(happy_status & GREG_STAT_MIFIRQ) {
-		HMD(("MIFIRQ "));
-		happy_meal_mif_interrupt(hp, gregs, tregs);
-	}
-
-	if(happy_status & GREG_STAT_TXALL) {
-		HMD(("TXALL "));
-		happy_meal_tx(hp);
-	}
-
-	if(happy_status & GREG_STAT_RXTOHOST) {
-		HMD(("RXTOHOST "));
-		sun4d_happy_meal_rx(hp, dev, gregs);
-	}
-
-	if(dev->tbusy && (TX_BUFFS_AVAIL(hp) >= 0)) {
-		hp->dev->tbusy = 0;
-		mark_bh(NET_BH);
-	}
-
-	dev->interrupt = 0;
-	HMD(("done\n"));
-}
-#endif
+	dev->interrupt = 0;
+	HMD(("done\n"));
+}
 
 static void quattro_sbus_interrupt(int irq, void *cookie, struct pt_regs *ptregs)
 {
-	struct quattro *qp = (struct quattro *)cookie;
+	struct quattro *qp = (struct quattro *) cookie;
 	int i;
 
-	for(i = 0; i < 4; i++) {
+	for (i = 0; i < 4; i++) {
 		struct net_device *dev = qp->happy_meals[i];
-		struct happy_meal *hp = (struct happy_meal *) dev->priv;
-		struct hmeal_gregs *gregs = hp->gregs;
-		struct hmeal_tcvregs *tregs = hp->tcvregs;
-		unsigned int happy_status = hme_read32(hp, &gregs->stat);
+		struct happy_meal *hp  = (struct happy_meal *) dev->priv;
+		u32 happy_status       = hme_read32(hp, hp->gregs + GREG_STAT);
 
-		HMD(("quattro_interrupt: status=%08x ",happy_status));
+		HMD(("quattro_interrupt: status=%08x ", happy_status));
 
-		dev->interrupt=1;
+		if (!(happy_status & (GREG_STAT_ERRORS |
+				      GREG_STAT_MIFIRQ |
+				      GREG_STAT_TXALL |
+				      GREG_STAT_RXTOHOST)))
+			continue;
+
+		dev->interrupt = 1;
 
-		if(happy_status & GREG_STAT_ERRORS) {
+		if (happy_status & GREG_STAT_ERRORS) {
 			HMD(("ERRORS "));
-			if(happy_meal_is_not_so_happy(hp, gregs, happy_status)) {
+			if (happy_meal_is_not_so_happy(hp, happy_status)) {
 				dev->interrupt=0;
 				break;
 			}
 		}
 
-		if(happy_status & GREG_STAT_MIFIRQ) {
+		if (happy_status & GREG_STAT_MIFIRQ) {
 			HMD(("MIFIRQ "));
-			happy_meal_mif_interrupt(hp, gregs, tregs);
+			happy_meal_mif_interrupt(hp);
 		}
 
-		if(happy_status & GREG_STAT_TXALL) {
+		if (happy_status & GREG_STAT_TXALL) {
 			HMD(("TXALL "));
 			happy_meal_tx(hp);
 		}
 
-		if(happy_status & GREG_STAT_RXTOHOST) {
+		if (happy_status & GREG_STAT_RXTOHOST) {
 			HMD(("RXTOHOST "));
-			happy_meal_rx(hp, dev, gregs);
+			happy_meal_rx(hp, dev);
 		}
 
-		if(dev->tbusy && (TX_BUFFS_AVAIL(hp) >= 0)) {
+		if (dev->tbusy && (TX_BUFFS_AVAIL(hp) > 0)) {
 			hp->dev->tbusy = 0;
 			mark_bh(NET_BH);
 		}
-		dev->interrupt=0;
+		dev->interrupt = 0;
 	}
 	HMD(("done\n"));
 }
@@ -2478,51 +2161,19 @@
 	/* On SBUS Quattro QFE cards, all hme interrupts are concentrated
 	 * into a single source which we register handling at probe time.
 	 */
-	if((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) == HFLAG_QUATTRO) {
-		hp->qfe_parent->irq_status[hp->qfe_ent] = &hp->gregs->stat;
-		goto after_request_irq;
-	}
-#ifndef __sparc_v9__
-	if(sparc_cpu_model == sun4c) {
-		if(request_irq(dev->irq, &sun4c_happy_meal_interrupt,
-			       SA_SHIRQ, "HAPPY MEAL", (void *) dev)) {
+	if ((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO) {
+		if (request_irq(dev->irq, &happy_meal_interrupt,
+				SA_SHIRQ, "HAPPY MEAL", (void *)dev)) {
 			HMD(("EAGAIN\n"));
-			printk("happy meal: Can't order irq %d to go.\n", dev->irq);
-			return -EAGAIN;
-		}
-	} else if (sparc_cpu_model == sun4d) {
-		if(request_irq(dev->irq, &sun4d_happy_meal_interrupt,
-			       SA_SHIRQ, "HAPPY MEAL", (void *) dev)) {
-			HMD(("EAGAIN\n"));
-			printk("happy_meal(SBUS): Can't order irq %s to go.\n",
+			printk(KERN_ERR "happy_meal(SBUS): Can't order irq %s to go.\n",
 			       __irq_itoa(dev->irq));
 			return -EAGAIN;
 		}
-	} else
-#endif
-#ifdef CONFIG_PCI
-	if(hp->happy_flags & HFLAG_PCI) {
-		if(request_irq(dev->irq, &pci_happy_meal_interrupt,
-			       SA_SHIRQ, "HAPPY MEAL (PCI)", dev)) {
-		HMD(("EAGAIN\n"));
-		printk("happy_meal(PCI: Can't order irq %s to go.\n",
-		       __irq_itoa(dev->irq));
-			return -EAGAIN;
-		}
-	} else
-#endif
-	if(request_irq(dev->irq, &happy_meal_interrupt,
-		       SA_SHIRQ, "HAPPY MEAL", (void *)dev)) {
-		HMD(("EAGAIN\n"));
-		printk("happy_meal(SBUS): Can't order irq %s to go.\n",
-		       __irq_itoa(dev->irq));
-		return -EAGAIN;
 	}
 
-after_request_irq:
 	HMD(("to happy_meal_init\n"));
 	res = happy_meal_init(hp, 0);
-	if(!res) {
+	if (!res) {
 		MOD_INC_USE_COUNT;
 	}
 	return res;
@@ -2542,12 +2193,8 @@
 	 * into a single source which we register handling at probe
 	 * time and never unregister.
 	 */
-	if((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO) {
+	if ((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO)
 		free_irq(dev->irq, (void *)dev);
-	} else {
-		/* Zap the status register pointer. */
-		hp->qfe_parent->irq_status[hp->qfe_ent] = NULL;
-	}
 
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -2564,83 +2211,17 @@
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
 	int len, entry;
 
-	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
+	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
 		int tickssofar = jiffies - dev->trans_start;
 	    
 		if (tickssofar >= 40) {
-			printk ("%s: transmit timed out, resetting\n", dev->name);
+			printk (KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
 			hp->net_stats.tx_errors++;
 			tx_dump_log();
-			printk ("%s: Happy Status %08x TX[%08x:%08x]\n", dev->name,
-				hme_read32(hp, &hp->gregs->stat),
-				hme_read32(hp, &hp->etxregs->cfg),
-				hme_read32(hp, &hp->bigmacregs->tx_cfg));
-			happy_meal_init(hp, 0);
-			dev->tbusy = 0;
-			dev->trans_start = jiffies;
-		} else
-			tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_TBUSY, 0);
-		return 1;
-	}
-
-	if(!TX_BUFFS_AVAIL(hp)) {
-		tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_NBUFS, 0);
-		return 1;
-	}
-#ifdef __sparc_v9__
-	if ((unsigned long)(skb->data + skb->len) >= MAX_DMA_ADDRESS) {
-		struct sk_buff *new_skb = skb_copy(skb, GFP_DMA | GFP_ATOMIC);
-		if (!new_skb)
-			return 1;
-		dev_kfree_skb(skb);
-		skb = new_skb;
-	}
-#endif
-	len = skb->len;
-	entry = hp->tx_new;
-
-	SXD(("SX<l[%d]e[%d]>", len, entry));
-#ifdef NEED_DMA_SYNCHRONIZATION
-	mmu_sync_dma(kva_to_hva(hp, skb->data),
-		     skb->len, hp->happy_sbus_dev->my_bus);
-#endif
-	hp->tx_skbs[entry] = skb;
-	hp->happy_block->happy_meal_txd[entry].tx_addr = kva_to_hva(hp, skb->data);
-	hp->happy_block->happy_meal_txd[entry].tx_flags =
-		(TXFLAG_OWN | TXFLAG_SOP | TXFLAG_EOP | (len & TXFLAG_SIZE));
-	hp->tx_new = NEXT_TX(entry);
-
-	/* Get it going. */
-	dev->trans_start = jiffies;
-	hme_write32(hp, &hp->etxregs->tx_pnding, ETX_TP_DMAWAKEUP);
-
-	if(TX_BUFFS_AVAIL(hp))
-		dev->tbusy = 0;
-
-	tx_add_log(hp, TXLOG_ACTION_TXMIT, 0);
-	return 0;
-}
-
-#ifdef CONFIG_PCI
-static int pci_happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct happy_meal *hp = (struct happy_meal *) dev->priv;
-	int len, entry;
-
-	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		int tickssofar = jiffies - dev->trans_start;
-	    
-		if (tickssofar >= 40) {
-			unsigned long flags;
-
-			printk ("%s: transmit timed out, resetting\n", dev->name);
-
-			save_and_cli(flags);
-			tx_dump_log();
-			tx_dump_ring(hp);
-			restore_flags(flags);
-
-			hp->net_stats.tx_errors++;
+			printk (KERN_ERR "%s: Happy Status %08x TX[%08x:%08x]\n", dev->name,
+				hme_read32(hp, hp->gregs + GREG_STAT),
+				hme_read32(hp, hp->etxregs + ETX_CFG),
+				hme_read32(hp, hp->bigmacregs + BMAC_TXCFG));
 			happy_meal_init(hp, 0);
 			dev->tbusy = 0;
 			dev->trans_start = jiffies;
@@ -2649,7 +2230,7 @@
 		return 1;
 	}
 
-	if(!TX_BUFFS_AVAIL(hp)) {
+	if (!TX_BUFFS_AVAIL(hp)) {
 		tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_NBUFS, 0);
 		return 1;
 	}
@@ -2658,132 +2239,21 @@
 
 	SXD(("SX<l[%d]e[%d]>", len, entry));
 	hp->tx_skbs[entry] = skb;
-	pcihme_write_txd(&hp->happy_block->happy_meal_txd[entry],
-			 (TXFLAG_OWN|TXFLAG_SOP|TXFLAG_EOP|(len & TXFLAG_SIZE)),
-			 (u32) virt_to_bus((volatile void *)skb->data));
+	hme_write_txd(hp, &hp->happy_block->happy_meal_txd[entry],
+		      (TXFLAG_OWN | TXFLAG_SOP | TXFLAG_EOP | (len & TXFLAG_SIZE)),
+		      hme_dma_map(hp, skb->data, len));
 	hp->tx_new = NEXT_TX(entry);
 
 	/* Get it going. */
 	dev->trans_start = jiffies;
-	writel(ETX_TP_DMAWAKEUP, (unsigned long)&hp->etxregs->tx_pnding);
+	hme_write32(hp, hp->etxregs + ETX_PENDING, ETX_TP_DMAWAKEUP);
 
-	if(TX_BUFFS_AVAIL(hp))
+	if (TX_BUFFS_AVAIL(hp))
 		dev->tbusy = 0;
 
 	tx_add_log(hp, TXLOG_ACTION_TXMIT, 0);
 	return 0;
 }
-#endif
-
-#ifndef __sparc_v9__
-static int sun4c_happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct happy_meal *hp = (struct happy_meal *) dev->priv;
-	struct hmeal_buffers *hbufs = hp->sun4c_buffers;
-	__u32 txbuf_dvma, hbufs_dvma = hp->s4c_buf_dvma;
-	unsigned char *txbuf;
-	int len, entry;
-
-	if(dev->tbusy) {
-		int tickssofar = jiffies - dev->trans_start;
-	    
-		if (tickssofar < 40) {
-			return 1;
-		} else {
-			printk ("%s: transmit timed out, resetting\n", dev->name);
-			hp->net_stats.tx_errors++;
-			happy_meal_init(hp, 0);
-			dev->tbusy = 0;
-			dev->trans_start = jiffies;
-			return 0;
-		}
-	}
-
-	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		printk("happy meal: Transmitter access conflict.\n");
-		return 1;
-	}
-
-	if(!TX_BUFFS_AVAIL(hp))
-		return 1;
-
-	len = skb->len;
-	entry = hp->tx_new;
-
-	txbuf = &hbufs->tx_buf[entry][0];
-	memcpy(txbuf, skb->data, len);
-
-	SXD(("SX<l[%d]e[%d]>", len, entry));
-	txbuf_dvma = hbufs_dvma + hbuf_offset(tx_buf, entry);
-	hp->happy_block->happy_meal_txd[entry].tx_addr = txbuf_dvma;
-	hp->happy_block->happy_meal_txd[entry].tx_flags =
-		(TXFLAG_OWN | TXFLAG_SOP | TXFLAG_EOP | (len & TXFLAG_SIZE));
-	hp->tx_new = NEXT_TX(entry);
-
-	/* Get it going. */
-	dev->trans_start = jiffies;
-	hp->etxregs->tx_pnding = ETX_TP_DMAWAKEUP;
-
-	dev_kfree_skb(skb);
-
-	if(TX_BUFFS_AVAIL(hp))
-		dev->tbusy = 0;
-
-	return 0;
-}
-
-static int sun4d_happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct happy_meal *hp = (struct happy_meal *) dev->priv;
-	int len, entry;
-	__u32 va;
-
-	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		int tickssofar = jiffies - dev->trans_start;
-	    
-		if (tickssofar >= 40) {
-			printk ("%s: transmit timed out, resetting\n", dev->name);
-			hp->net_stats.tx_errors++;
-			tx_dump_log();
-			printk ("%s: Happy Status %08x TX[%08x:%08x]\n", dev->name,
-				hme_read32(hp, &hp->gregs->stat),
-				hme_read32(hp, &hp->etxregs->cfg),
-				hme_read32(hp, &hp->bigmacregs->tx_cfg));
-			happy_meal_init(hp, 0);
-			dev->tbusy = 0;
-			dev->trans_start = jiffies;
-		} else
-			tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_TBUSY, 0);
-		return 1;
-	}
-
-	if(!TX_BUFFS_AVAIL(hp)) {
-		tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_NBUFS, 0);
-		return 1;
-	}
-	len = skb->len;
-	entry = hp->tx_new;
-
-	SXD(("SX<l[%d]e[%d]>", len, entry));
-	hp->tx_skbs[entry] = skb;
-	va = (__u32)hp->sun4d_buffers + (RX_RING_SIZE + entry) * PAGE_SIZE;
-	hp->happy_block->happy_meal_txd[entry].tx_addr = 
-		iounit_map_dma_page(va, skb->data, hp->happy_sbus_dev->my_bus);
-	hp->happy_block->happy_meal_txd[entry].tx_flags =
-		(TXFLAG_OWN | TXFLAG_SOP | TXFLAG_EOP | (len & TXFLAG_SIZE));
-	hp->tx_new = NEXT_TX(entry);
-
-	/* Get it going. */
-	dev->trans_start = jiffies;
-	hme_write32(hp, &hp->etxregs->tx_pnding, ETX_TP_DMAWAKEUP);
-
-	if(TX_BUFFS_AVAIL(hp))
-		dev->tbusy = 0;
-
-	tx_add_log(hp, TXLOG_ACTION_TXMIT, 0);
-	return 0;
-}
-#endif
 
 static struct net_device_stats *happy_meal_get_stats(struct net_device *dev)
 {
@@ -2796,7 +2266,7 @@
 static void happy_meal_set_multicast(struct net_device *dev)
 {
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
-	struct hmeal_bigmacregs *bregs = hp->bigmacregs;
+	unsigned long bregs = hp->bigmacregs;
 	struct dev_mc_list *dmi = dev->mc_list;
 	char *addrs;
 	int i, j, bit, byte;
@@ -2805,45 +2275,45 @@
 	/* Lock out others. */
 	set_bit(0, (void *) &dev->tbusy);
 
-	if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
-		hme_write32(hp, &bregs->htable0, 0xffff);
-		hme_write32(hp, &bregs->htable1, 0xffff);
-		hme_write32(hp, &bregs->htable2, 0xffff);
-		hme_write32(hp, &bregs->htable3, 0xffff);
-	} else if(dev->flags & IFF_PROMISC) {
-		hme_write32(hp, &bregs->rx_cfg,
-			    hme_read32(hp, &bregs->rx_cfg) | BIGMAC_RXCFG_PMISC);
+	if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
+		hme_write32(hp, bregs + BMAC_HTABLE0, 0xffff);
+		hme_write32(hp, bregs + BMAC_HTABLE1, 0xffff);
+		hme_write32(hp, bregs + BMAC_HTABLE2, 0xffff);
+		hme_write32(hp, bregs + BMAC_HTABLE3, 0xffff);
+	} else if (dev->flags & IFF_PROMISC) {
+		hme_write32(hp, bregs + BMAC_RXCFG,
+			    hme_read32(hp, bregs + BMAC_RXCFG) | BIGMAC_RXCFG_PMISC);
 	} else {
 		u16 hash_table[4];
 
-		for(i = 0; i < 4; i++)
+		for (i = 0; i < 4; i++)
 			hash_table[i] = 0;
 
-		for(i = 0; i < dev->mc_count; i++) {
+		for (i = 0; i < dev->mc_count; i++) {
 			addrs = dmi->dmi_addr;
 			dmi = dmi->next;
 
-			if(!(*addrs & 1))
+			if (!(*addrs & 1))
 				continue;
 
 			crc = 0xffffffffU;
-			for(byte = 0; byte < 6; byte++) {
-				for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
+			for (byte = 0; byte < 6; byte++) {
+				for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
 					int test;
 
 					test = ((bit ^ crc) & 0x01);
 					crc >>= 1;
-					if(test)
+					if (test)
 						crc = crc ^ poly;
 				}
 			}
 			crc >>= 26;
 			hash_table[crc >> 4] |= 1 << (crc & 0xf);
 		}
-		hme_write32(hp, &bregs->htable0, hash_table[0]);
-		hme_write32(hp, &bregs->htable1, hash_table[1]);
-		hme_write32(hp, &bregs->htable2, hash_table[2]);
-		hme_write32(hp, &bregs->htable3, hash_table[3]);
+		hme_write32(hp, bregs + BMAC_HTABLE0, hash_table[0]);
+		hme_write32(hp, bregs + BMAC_HTABLE1, hash_table[1]);
+		hme_write32(hp, bregs + BMAC_HTABLE2, hash_table[2]);
+		hme_write32(hp, bregs + BMAC_HTABLE3, hash_table[3]);
 	}
 
 	/* Let us get going again. */
@@ -2858,12 +2328,12 @@
 	struct ethtool_cmd *ep_user = (struct ethtool_cmd *) rq->ifr_data;
 	struct ethtool_cmd ecmd;
 
-	if(cmd != SIOCETHTOOL)
+	if (cmd != SIOCETHTOOL)
 		return -EOPNOTSUPP;
-	if(copy_from_user(&ecmd, ep_user, sizeof(ecmd)))
+	if (copy_from_user(&ecmd, ep_user, sizeof(ecmd)))
 		return -EFAULT;
 
-	if(ecmd.cmd == SPARC_ETH_GSET) {
+	if (ecmd.cmd == SPARC_ETH_GSET) {
 		ecmd.supported =
 			(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
 			 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
@@ -2877,12 +2347,12 @@
 		/* Record PHY settings. */
 		hp->sw_bmcr = happy_meal_tcvr_read(hp, hp->tcvregs, DP83840_BMCR);
 		hp->sw_lpa = happy_meal_tcvr_read(hp, hp->tcvregs, DP83840_LPA);
-		if(hp->sw_bmcr & BMCR_ANENABLE) {
+		if (hp->sw_bmcr & BMCR_ANENABLE) {
 			ecmd.autoneg = AUTONEG_ENABLE;
 			ecmd.speed =
 				(hp->sw_lpa & (LPA_100HALF | LPA_100FULL)) ?
 				SPEED_100 : SPEED_10;
-			if(ecmd.speed == SPEED_100)
+			if (ecmd.speed == SPEED_100)
 				ecmd.duplex =
 					(hp->sw_lpa & (LPA_100FULL)) ?
 					DUPLEX_FULL : DUPLEX_HALF;
@@ -2899,22 +2369,22 @@
 				(hp->sw_bmcr & BMCR_FULLDPLX) ?
 				DUPLEX_FULL : DUPLEX_HALF;
 		}
-		if(copy_to_user(ep_user, &ecmd, sizeof(ecmd)))
+		if (copy_to_user(ep_user, &ecmd, sizeof(ecmd)))
 			return -EFAULT;
 		return 0;
-	} else if(ecmd.cmd == SPARC_ETH_SSET) {
-		if(!capable(CAP_NET_ADMIN))
+	} else if (ecmd.cmd == SPARC_ETH_SSET) {
+		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 
 		/* Verify the settings we care about. */
-		if(ecmd.autoneg != AUTONEG_ENABLE &&
-		   ecmd.autoneg != AUTONEG_DISABLE)
+		if (ecmd.autoneg != AUTONEG_ENABLE &&
+		    ecmd.autoneg != AUTONEG_DISABLE)
 			return -EINVAL;
-		if(ecmd.autoneg == AUTONEG_DISABLE &&
-		   ((ecmd.speed != SPEED_100 &&
-		     ecmd.speed != SPEED_10) ||
-		    (ecmd.duplex != DUPLEX_HALF &&
-		     ecmd.duplex != DUPLEX_FULL)))
+		if (ecmd.autoneg == AUTONEG_DISABLE &&
+		    ((ecmd.speed != SPEED_100 &&
+		      ecmd.speed != SPEED_10) ||
+		     (ecmd.duplex != DUPLEX_HALF &&
+		      ecmd.duplex != DUPLEX_FULL)))
 			return -EINVAL;
 
 		/* Ok, do it to it. */
@@ -2928,15 +2398,19 @@
 		return -EOPNOTSUPP;
 }
 
+static int hme_version_printed = 0;
+
+#ifdef CONFIG_SBUS
 void __init quattro_get_ranges(struct quattro *qp)
 {
+	struct sbus_dev *sdev = qp->quattro_dev;
 	int err;
 
-	err = prom_getproperty(qp->quattro_sbus_dev->prom_node,
+	err = prom_getproperty(sdev->prom_node,
 			       "ranges",
 			       (char *)&qp->ranges[0],
 			       sizeof(qp->ranges));
-	if(err == 0 || err == -1) {
+	if (err == 0 || err == -1) {
 		qp->nranges = 0;
 		return;
 	}
@@ -2945,19 +2419,19 @@
 
 static void __init quattro_apply_ranges(struct quattro *qp, struct happy_meal *hp)
 {
-	struct linux_sbus_device *sdev = hp->happy_sbus_dev;
+	struct sbus_dev *sdev = hp->happy_dev;
 	int rng;
 
-	for(rng = 0; rng < qp->nranges; rng++) {
+	for (rng = 0; rng < qp->nranges; rng++) {
 		struct linux_prom_ranges *rngp = &qp->ranges[rng];
 		int reg;
 
-		for(reg = 0; reg < 5; reg++) {
-			if(sdev->reg_addrs[reg].which_io ==
-			   rngp->ot_child_space)
+		for (reg = 0; reg < 5; reg++) {
+			if (sdev->reg_addrs[reg].which_io ==
+			    rngp->ot_child_space)
 				break;
 		}
-		if(reg == 5)
+		if (reg == 5)
 			continue;
 
 		sdev->reg_addrs[reg].which_io = rngp->ot_parent_space;
@@ -2970,30 +2444,30 @@
  *
  * Return NULL on failure.
  */
-static struct quattro * __init quattro_sbus_find(struct linux_sbus_device *goal_sdev)
+static struct quattro * __init quattro_sbus_find(struct sbus_dev *goal_sdev)
 {
-	struct linux_sbus *sbus;
-	struct linux_sbus_device *sdev;
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev;
 	struct quattro *qp;
 
-	if(qfe_sbus_list == NULL)
+	if (qfe_sbus_list == NULL)
 		goto found;
 
-	for(qp = qfe_sbus_list; qp != NULL; qp = qp->next) {
-		for(sdev = qp->quattro_sbus_dev;
-		    sdev != NULL;
-		    sdev = sdev->next) {
-			if(sdev == goal_sdev)
+	for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) {
+		for (sdev = qp->quattro_dev;
+		     sdev != NULL;
+		     sdev = sdev->next) {
+			if (sdev == goal_sdev)
 				return qp;
 		}
 	}
 	for_each_sbus(sbus) {
 		for_each_sbusdev(sdev, sbus) {
-			if(sdev->child != NULL) {
-				struct linux_sbus_device *p;
+			if (sdev->child != NULL) {
+				struct sbus_dev *p;
 
-				for(p = sdev->child; p != NULL; p = p->next)
-					if(p == goal_sdev)
+				for (p = sdev->child; p != NULL; p = p->next)
+					if (p == goal_sdev)
 						goto found;
 			}
 		}
@@ -3004,18 +2478,13 @@
 
 found:
 	qp = kmalloc(sizeof(struct quattro), GFP_KERNEL);
-	if(qp != NULL) {
+	if (qp != NULL) {
 		int i;
 
-		for(i = 0; i < 4; i++) {
-			qp->irq_status[i] = NULL;
+		for (i = 0; i < 4; i++)
 			qp->happy_meals[i] = NULL;
-		}
-		qp->handler = NULL;
-		qp->quattro_sbus_dev = goal_sdev;
-#ifdef CONFIG_PCI
-		qp->quattro_pci_dev = NULL;
-#endif
+
+		qp->quattro_dev = goal_sdev;
 		qp->next = qfe_sbus_list;
 		qfe_sbus_list = qp;
 		quattro_get_ranges(qp);
@@ -3023,6 +2492,29 @@
 	return qp;
 }
 
+/* After all quattro cards have been probed, we call these functions
+ * to register the IRQ handlers.
+ */
+static void __init quattro_sbus_register_irqs(void)
+{
+	struct quattro *qp;
+
+	for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) {
+		struct sbus_dev *sdev = qp->quattro_dev;
+		int err;
+
+		err = request_irq(sdev->irqs[0],
+				  quattro_sbus_interrupt,
+				  SA_SHIRQ, "Quattro",
+				  qp);
+		if (err != 0) {
+			printk(KERN_ERR "Quattro: Fatal IRQ registery error %d.\n", err);
+			panic("QFE request irq");
+		}
+	}
+}
+#endif /* CONFIG_SBUS */
+
 #ifdef CONFIG_PCI
 static struct quattro * __init quattro_pci_find(struct pci_dev *pdev)
 {
@@ -3030,21 +2522,20 @@
 	struct quattro *qp;
 
 	if (!bdev) return NULL;
-	for(qp = qfe_pci_list; qp != NULL; qp = qp->next) {
-		if(qp->quattro_pci_dev == bdev)
+	for (qp = qfe_pci_list; qp != NULL; qp = qp->next) {
+		struct pci_dev *qpdev = qp->quattro_dev;
+
+		if (qpdev == bdev)
 			return qp;
 	}
 	qp = kmalloc(sizeof(struct quattro), GFP_KERNEL);
-	if(qp != NULL) {
+	if (qp != NULL) {
 		int i;
 
-		for(i = 0; i < 4; i++) {
-			qp->irq_status[i] = NULL;
+		for (i = 0; i < 4; i++)
 			qp->happy_meals[i] = NULL;
-		}
-		qp->handler = NULL;
-		qp->quattro_sbus_dev = NULL;
-		qp->quattro_pci_dev = bdev;
+
+		qp->quattro_dev = bdev;
 		qp->next = qfe_pci_list;
 		qfe_pci_list = qp;
 
@@ -3053,88 +2544,50 @@
 	}
 	return qp;
 }
-#endif
-
-/* After all quattro cards have been probed, we call these functions
- * to register the IRQ handlers.
- */
-static void __init quattro_sbus_register_irqs(void)
-{
-	struct quattro *qp;
-
-	for(qp = qfe_sbus_list; qp != NULL; qp = qp->next) {
-		int err;
-
-		/* Set the handler. */
-#ifndef __sparc_v9__
-		if(sparc_cpu_model == sun4c)
-			qp->handler = sun4c_happy_meal_interrupt;
-		else if(sparc_cpu_model == sun4d)
-			qp->handler = sun4d_happy_meal_interrupt;
-		else
-#endif
-#ifdef CONFIG_PCI
-		if(qp->quattro_pci_dev != NULL)
-			panic("QFE: PCI qfe in sbus_register_irqs!");
-		else
-#endif
-			qp->handler = happy_meal_interrupt;
-
-		err = request_irq(qp->quattro_sbus_dev->irqs[0],
-				  quattro_sbus_interrupt,
-				  SA_SHIRQ, "Quattro",
-				  qp);
-		if(err != 0) {
-			printk("Quattro: Fatal IRQ registery error %d.\n", err);
-			panic("QFE request irq");
-		}
-	}
-}
+#endif /* CONFIG_PCI */
 
-static unsigned hme_version_printed = 0;
-
-static int __init happy_meal_ether_init(struct net_device *dev, struct linux_sbus_device *sdev, int is_qfe)
+#ifdef CONFIG_SBUS
+static int __init happy_meal_sbus_init(struct net_device *dev,
+				       struct sbus_dev *sdev,
+				       int is_qfe)
 {
 	struct quattro *qp = NULL;
 	struct happy_meal *hp;
 	int i, qfe_slot = -1;
 
-	if(is_qfe) {
+	if (is_qfe) {
 		qp = quattro_sbus_find(sdev);
-		if(qp == NULL)
+		if (qp == NULL)
 			return ENODEV;
-		for(qfe_slot = 0; qfe_slot < 4; qfe_slot++)
-			if(qp->happy_meals[qfe_slot] == NULL)
+		for (qfe_slot = 0; qfe_slot < 4; qfe_slot++)
+			if (qp->happy_meals[qfe_slot] == NULL)
 				break;
-		if(qfe_slot == 4)
+		if (qfe_slot == 4)
 			return ENODEV;
 	}
-	if(dev == NULL) {
+	if (dev == NULL) {
 		dev = init_etherdev(0, sizeof(struct happy_meal));
 	} else {
 		dev->priv = kmalloc(sizeof(struct happy_meal), GFP_KERNEL);
-		if(dev->priv == NULL)
+		if (dev->priv == NULL)
 			return -ENOMEM;
 	}
-	if(hme_version_printed++ == 0)
-		printk(version);
+	if (hme_version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
 
-	if(qfe_slot != -1)
-		printk("%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ",
+	if (qfe_slot != -1)
+		printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ",
 		       dev->name, qfe_slot);
 	else
-		printk("%s: HAPPY MEAL (SBUS) 10/100baseT Ethernet ",
+		printk(KERN_INFO "%s: HAPPY MEAL (SBUS) 10/100baseT Ethernet ",
 		       dev->name);
 
-	dev->base_addr = (long) sdev;
-
-	/* XXX Check for local-mac-address property on Quattro... -DaveM */
 	/* Quattro local-mac-address... */
-	if(qfe_slot != -1 && prom_getproplen(sdev->prom_node,"local-mac-address")==6)
+	if (qfe_slot != -1 && prom_getproplen(sdev->prom_node,"local-mac-address")==6)
 		prom_getproperty(sdev->prom_node,"local-mac-address",dev->dev_addr,6);
 	else
 		memcpy(dev->dev_addr,idprom->id_ethaddr,6);
-	for(i = 0; i < 6; i++)
+	for (i = 0; i < 6; i++)
 		printk("%2.2x%c",
 		       dev->dev_addr[i], i == 5 ? ' ' : ':');
 	printk("\n");
@@ -3142,105 +2595,77 @@
 	hp = (struct happy_meal *) dev->priv;
 	memset(hp, 0, sizeof(*hp));
 
-	hp->happy_sbus_dev = sdev;
-#ifdef CONFIG_PCI
-	hp->happy_pci_dev = NULL;
-#endif
+	hp->happy_dev = sdev;
 
-	if(sdev->num_registers != 5) {
-		printk("happymeal: Device does not have 5 regs, it has %d.\n",
+	if (sdev->num_registers != 5) {
+		printk(KERN_ERR "happymeal: Device does not have 5 regs, it has %d.\n",
 		       sdev->num_registers);
-		printk("happymeal: Would you like that for here or to go?\n");
+		printk(KERN_ERR "happymeal: Would you like that for here or to go?\n");
 		return ENODEV;
 	}
 
-	if(qp != NULL) {
+	if (qp != NULL) {
 		hp->qfe_parent = qp;
 		hp->qfe_ent = qfe_slot;
 		qp->happy_meals[qfe_slot] = dev;
 		quattro_apply_ranges(qp, hp);
 	}
 
-	prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0],
-			       sdev->num_registers, sdev);
-	hp->gregs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
-				   sizeof(struct hmeal_gregs),
-				   "Happy Meal Global Regs",
-				   sdev->reg_addrs[0].which_io, 0);
-	if(!hp->gregs) {
-		printk("happymeal: Cannot map Happy Meal global registers.\n");
+	hp->gregs = sbus_ioremap(&sdev->resource[0], 0,
+				 GREG_REG_SIZE, "HME Global Regs");
+	if (!hp->gregs) {
+		printk(KERN_ERR "happymeal: Cannot map Happy Meal global registers.\n");
 		return ENODEV;
 	}
 
-	hp->etxregs = sparc_alloc_io(sdev->reg_addrs[1].phys_addr, 0,
-				     sizeof(struct hmeal_etxregs),
-				     "Happy Meal MAC TX Regs",
-				     sdev->reg_addrs[1].which_io, 0);
-	if(!hp->etxregs) {
-		printk("happymeal: Cannot map Happy Meal MAC Transmit registers.\n");
+	hp->etxregs = sbus_ioremap(&sdev->resource[1], 0,
+				   ETX_REG_SIZE, "HME TX Regs");
+	if (!hp->etxregs) {
+		printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Transmit registers.\n");
 		return ENODEV;
 	}
 
-	hp->erxregs = sparc_alloc_io(sdev->reg_addrs[2].phys_addr, 0,
-				     sizeof(struct hmeal_erxregs),
-				     "Happy Meal MAC RX Regs",
-				     sdev->reg_addrs[2].which_io, 0);
-	if(!hp->erxregs) {
-		printk("happymeal: Cannot map Happy Meal MAC Receive registers.\n");
+	hp->erxregs = sbus_ioremap(&sdev->resource[2], 0,
+				   ERX_REG_SIZE, "HME RX Regs");
+	if (!hp->erxregs) {
+		printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Receive registers.\n");
 		return ENODEV;
 	}
 
-	hp->bigmacregs = sparc_alloc_io(sdev->reg_addrs[3].phys_addr, 0,
-					sizeof(struct hmeal_bigmacregs),
-					"Happy Meal BIGMAC Regs",
-					sdev->reg_addrs[3].which_io, 0);
-	if(!hp->bigmacregs) {
-		printk("happymeal: Cannot map Happy Meal BIGMAC registers.\n");
+	hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0,
+				      BMAC_REG_SIZE, "HME BIGMAC Regs");
+	if (!hp->bigmacregs) {
+		printk(KERN_ERR "happymeal: Cannot map Happy Meal BIGMAC registers.\n");
 		return ENODEV;
 	}
 
-	hp->tcvregs = sparc_alloc_io(sdev->reg_addrs[4].phys_addr, 0,
-				     sizeof(struct hmeal_tcvregs),
-				     "Happy Meal Tranceiver Regs",
-				     sdev->reg_addrs[4].which_io, 0);
-	if(!hp->tcvregs) {
-		printk("happymeal: Cannot map Happy Meal Tranceiver registers.\n");
+	hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0,
+				   TCVR_REG_SIZE, "HME Tranceiver Regs");
+	if (!hp->tcvregs) {
+		printk(KERN_ERR "happymeal: Cannot map Happy Meal Tranceiver registers.\n");
 		return ENODEV;
 	}
 
 	hp->hm_revision = prom_getintdefault(sdev->prom_node, "hm-rev", 0xff);
-	if(hp->hm_revision == 0xff)
+	if (hp->hm_revision == 0xff)
 		hp->hm_revision = 0xa0;
 
 	/* Now enable the feature flags we can. */
-	if(hp->hm_revision == 0x20 || hp->hm_revision == 0x21)
+	if (hp->hm_revision == 0x20 || hp->hm_revision == 0x21)
 		hp->happy_flags = HFLAG_20_21;
-	else if(hp->hm_revision != 0xa0)
+	else if (hp->hm_revision != 0xa0)
 		hp->happy_flags = HFLAG_NOT_A0;
 
-	if(qp != NULL)
+	if (qp != NULL)
 		hp->happy_flags |= HFLAG_QUATTRO;
 
 	/* Get the supported DVMA burst sizes from our Happy SBUS. */
-	hp->happy_bursts = prom_getintdefault(hp->happy_sbus_dev->my_bus->prom_node,
+	hp->happy_bursts = prom_getintdefault(sdev->bus->prom_node,
 					      "burst-sizes", 0x00);
 
-	hp->happy_block = (struct hmeal_init_block *)
-		sparc_dvma_malloc(PAGE_SIZE, "Happy Meal Init Block",
-				  &hp->hblock_dvma);
-
-#ifndef __sparc_v9__
-	if(sparc_cpu_model == sun4c)
-		hp->sun4c_buffers = (struct hmeal_buffers *)
-		    sparc_dvma_malloc(sizeof(struct hmeal_buffers), "Happy Meal Bufs",
-				      &hp->s4c_buf_dvma);
-	else if (sparc_cpu_model == sun4d)
-		hp->sun4d_buffers = (struct hmeal_buffers *)
-		    iounit_map_dma_init(hp->happy_sbus_dev->my_bus,
-		    			(RX_RING_SIZE + TX_RING_SIZE) * PAGE_SIZE);
-	else
-#endif
-		hp->sun4c_buffers = 0;
+	hp->happy_block = sbus_alloc_consistant(hp->happy_dev,
+						PAGE_SIZE,
+						&hp->hblock_dvma);
 
 	/* Force check of the link first time we are brought up. */
 	hp->linkcheck = 0;
@@ -3249,30 +2674,35 @@
 	hp->timer_state = asleep;
 	hp->timer_ticks = 0;
 
-	/* Grrr, Happy Meal comes up by default not advertising
-	 * full duplex 100baseT capabilities, fix this.
-	 */
-	happy_meal_set_initial_advertisement(hp);
-
 	init_timer(&hp->happy_timer);
 
 	hp->dev = dev;
 	dev->open = &happy_meal_open;
 	dev->stop = &happy_meal_close;
-#ifndef __sparc_v9__	
-	if(sparc_cpu_model == sun4c)
-		dev->hard_start_xmit = &sun4c_happy_meal_start_xmit;
-	else if (sparc_cpu_model == sun4d)
-		dev->hard_start_xmit = &sun4d_happy_meal_start_xmit;
-	else
-#endif
-		dev->hard_start_xmit = &happy_meal_start_xmit;
+	dev->hard_start_xmit = &happy_meal_start_xmit;
 	dev->get_stats = &happy_meal_get_stats;
 	dev->set_multicast_list = &happy_meal_set_multicast;
 	dev->do_ioctl = &happy_meal_ioctl;
 
 	dev->irq = sdev->irqs[0];
-	dev->dma = 0;
+
+#if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
+	/* Hook up PCI register/dma accessors. */
+	hp->read_desc32 = sbus_hme_read_desc32;
+	hp->write_txd = sbus_hme_write_txd;
+	hp->write_rxd = sbus_hme_write_rxd;
+	hp->dma_map = (u32 (*)(void *, void *, long))sbus_map_single;
+	hp->dma_unmap = (void (*)(void *, u32, long))sbus_unmap_single;
+	hp->dma_sync = (void (*)(void *, u32, long))sbus_dma_sync_single;
+	hp->read32 = sbus_hme_read32;
+	hp->write32 = sbus_hme_write32;
+#endif
+
+	/* Grrr, Happy Meal comes up by default not advertising
+	 * full duplex 100baseT capabilities, fix this.
+	 */
+	happy_meal_set_initial_advertisement(hp);
+
 	ether_setup(dev);
 #ifdef MODULE
 	/* We are home free at this point, link us in to the happy
@@ -3284,6 +2714,7 @@
 #endif
 	return 0;
 }
+#endif
 
 #ifdef CONFIG_PCI
 static int __init happy_meal_pci_init(struct net_device *dev, struct pci_dev *pdev)
@@ -3298,8 +2729,8 @@
 
 	/* Now make sure pci_dev cookie is there. */
 	pcp = pdev->sysdata;
-	if(pcp == NULL || pcp->prom_node == -1) {
-		printk("happymeal(PCI): Some PCI device info missing\n");
+	if (pcp == NULL || pcp->prom_node == -1) {
+		printk(KERN_ERR "happymeal(PCI): Some PCI device info missing\n");
 		return ENODEV;
 	}
 	node = pcp->prom_node;
@@ -3307,43 +2738,45 @@
 	prom_getstring(node, "name", prom_name, sizeof(prom_name));
 	if (!strcmp(prom_name, "SUNW,qfe") || !strcmp(prom_name, "qfe")) {
 		qp = quattro_pci_find(pdev);
-		if(qp == NULL)
+		if (qp == NULL)
 			return ENODEV;
-		for(qfe_slot = 0; qfe_slot < 4; qfe_slot++)
-			if(qp->happy_meals[qfe_slot] == NULL)
+		for (qfe_slot = 0; qfe_slot < 4; qfe_slot++)
+			if (qp->happy_meals[qfe_slot] == NULL)
 				break;
-		if(qfe_slot == 4)
+		if (qfe_slot == 4)
 			return ENODEV;
 	}
-	if(dev == NULL) {
+	if (dev == NULL) {
 		dev = init_etherdev(0, sizeof(struct happy_meal));
 	} else {
 		dev->priv = kmalloc(sizeof(struct happy_meal), GFP_KERNEL);
-		if(dev->priv == NULL)
+		if (dev->priv == NULL)
 			return -ENOMEM;
 	}
-	if(hme_version_printed++ == 0)
-		printk(version);
+	if (hme_version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
 
 	if (!qfe_slot) {
+		struct pci_dev *qpdev = qp->quattro_dev;
+
 		prom_name[0] = 0;
 		if (!strncmp(dev->name, "eth", 3)) {
 			int i = simple_strtoul(dev->name + 3, NULL, 10);
 			sprintf(prom_name, "-%d", i + 3);
 		}
-		printk("%s%s: Quattro HME (PCI/CheerIO) 10/100baseT Ethernet ", dev->name, prom_name);
-		if (qp->quattro_pci_dev->vendor == PCI_VENDOR_ID_DEC &&
-		    qp->quattro_pci_dev->device == PCI_DEVICE_ID_DEC_21153)
+		printk(KERN_INFO "%s%s: Quattro HME (PCI/CheerIO) 10/100baseT Ethernet ", dev->name, prom_name);
+		if (qpdev->vendor == PCI_VENDOR_ID_DEC &&
+		    qpdev->device == PCI_DEVICE_ID_DEC_21153)
 			printk("DEC 21153 PCI Bridge\n");
 		else
 			printk("unknown bridge %04x.%04x\n", 
-				qp->quattro_pci_dev->vendor, qp->quattro_pci_dev->device);
+				qpdev->vendor, qpdev->device);
 	}
-	if(qfe_slot != -1)
-		printk("%s: Quattro HME slot %d (PCI/CheerIO) 10/100baseT Ethernet ",
+	if (qfe_slot != -1)
+		printk(KERN_INFO "%s: Quattro HME slot %d (PCI/CheerIO) 10/100baseT Ethernet ",
 		       dev->name, qfe_slot);
 	else
-		printk("%s: HAPPY MEAL (PCI/CheerIO) 10/100BaseT Ethernet ",
+		printk(KERN_INFO "%s: HAPPY MEAL (PCI/CheerIO) 10/100BaseT Ethernet ",
 		       dev->name);
 
 	dev->base_addr = (long) pdev;
@@ -3351,10 +2784,9 @@
 	hp = (struct happy_meal *)dev->priv;
 	memset(hp, 0, sizeof(*hp));
 
-	hp->happy_sbus_dev = NULL;
-	hp->happy_pci_dev = pdev;
+	hp->happy_dev = pdev;
 
-	if(qp != NULL) {
+	if (qp != NULL) {
 		hp->qfe_parent = qp;
 		hp->qfe_ent = qfe_slot;
 		qp->happy_meals[qfe_slot] = dev;
@@ -3362,37 +2794,39 @@
 
 	hpreg_base = pdev->resource[0].start;
 	if ((pdev->resource[0].flags & IORESOURCE_IO) != 0) {
-		printk("happymeal(PCI): Cannot find proper PCI device base address.\n");
+		printk(KERN_ERR "happymeal(PCI): Cannot find proper PCI device base address.\n");
 		return ENODEV;
 	}
+	hpreg_base &= PCI_BASE_ADDRESS_MEM_MASK;
+	hpreg_base = (unsigned long) ioremap(hpreg_base, 0x8000);
 
 	if (qfe_slot != -1 && prom_getproplen(node, "local-mac-address") == 6)
 		prom_getproperty(node, "local-mac-address", dev->dev_addr, 6);
 	else
 		memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
-	for(i = 0; i < 6; i++)
+	for (i = 0; i < 6; i++)
 		printk("%2.2x%c", dev->dev_addr[i], i == 5 ? ' ' : ':');
 
 	printk("\n");
 
 	/* Layout registers. */
-	hp->gregs      = (struct hmeal_gregs *)		(hpreg_base + 0x0000);
-	hp->etxregs    = (struct hmeal_etxregs *)	(hpreg_base + 0x2000);
-	hp->erxregs    = (struct hmeal_erxregs *)	(hpreg_base + 0x4000);
-	hp->bigmacregs = (struct hmeal_bigmacregs *)	(hpreg_base + 0x6000);
-	hp->tcvregs    = (struct hmeal_tcvregs *)	(hpreg_base + 0x7000);
+	hp->gregs      = (hpreg_base + 0x0000UL);
+	hp->etxregs    = (hpreg_base + 0x2000UL);
+	hp->erxregs    = (hpreg_base + 0x4000UL);
+	hp->bigmacregs = (hpreg_base + 0x6000UL);
+	hp->tcvregs    = (hpreg_base + 0x7000UL);
 
 	hp->hm_revision = prom_getintdefault(node, "hm-rev", 0xff);
-	if(hp->hm_revision == 0xff)
+	if (hp->hm_revision == 0xff)
 		hp->hm_revision = 0xa0;
 
 	/* Now enable the feature flags we can. */
-	if(hp->hm_revision == 0x20 || hp->hm_revision == 0x21)
+	if (hp->hm_revision == 0x20 || hp->hm_revision == 0x21)
 		hp->happy_flags = HFLAG_20_21;
-	else if(hp->hm_revision != 0xa0)
+	else if (hp->hm_revision != 0xa0)
 		hp->happy_flags = HFLAG_NOT_A0;
 
-	if(qp != NULL)
+	if (qp != NULL)
 		hp->happy_flags |= HFLAG_QUATTRO;
 
 	/* And of course, indicate this is PCI. */
@@ -3401,36 +2835,53 @@
 	/* Assume PCI happy meals can handle all burst sizes. */
 	hp->happy_bursts = DMA_BURSTBITS;
 
-	hp->happy_block = (struct hmeal_init_block *) get_free_page(GFP_DMA);
-	if(!hp->happy_block) {
-		printk("happymeal(PCI): Cannot get hme init block.\n");
+	hp->happy_block = (struct hmeal_init_block *) get_free_page(GFP_ATOMIC);
+	if (!hp->happy_block) {
+		printk(KERN_ERR "happymeal(PCI): Cannot get hme init block.\n");
 		return ENODEV;
 	}
 
 	hp->hblock_dvma = (u32) virt_to_bus(hp->happy_block);
 #ifndef __sparc_v9__
-	/* This case we currently need to use 'sparc_alloc_io' */
-	hp->happy_block = sparc_alloc_io (hp->hblock_dvma, NULL, 
-					  PAGE_SIZE, "sunhme", 0, 0);
+	/*
+	 * P3: Dirty trick to get uncacheable memory as we have no dma_sync.
+	 */
+	hp->happy_block = ioremap(virt_to_phys(hp->happy_block), PAGE_SIZE);
 #endif
-	hp->sun4c_buffers = 0;
 
 	hp->linkcheck = 0;
 	hp->timer_state = asleep;
 	hp->timer_ticks = 0;
-	happy_meal_set_initial_advertisement(hp);
 
 	init_timer(&hp->happy_timer);
 
 	hp->dev = dev;
 	dev->open = &happy_meal_open;
 	dev->stop = &happy_meal_close;
-	dev->hard_start_xmit = &pci_happy_meal_start_xmit;
+	dev->hard_start_xmit = &happy_meal_start_xmit;
 	dev->get_stats = &happy_meal_get_stats;
 	dev->set_multicast_list = &happy_meal_set_multicast;
 	dev->do_ioctl = &happy_meal_ioctl;
 	dev->irq = pdev->irq;
 	dev->dma = 0;
+
+#if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
+	/* Hook up PCI register/dma accessors. */
+	hp->read_desc32 = pci_hme_read_desc32;
+	hp->write_txd = pci_hme_write_txd;
+	hp->write_rxd = pci_hme_write_rxd;
+	hp->dma_map = pci_hme_dma_map;
+	hp->dma_unmap = pci_hme_dma_unmap;
+	hp->dma_sync = pci_hme_dma_sync;
+	hp->read32 = pci_hme_read32;
+	hp->write32 = pci_hme_write32;
+#endif
+
+	/* Grrr, Happy Meal comes up by default not advertising
+	 * full duplex 100baseT capabilities, fix this.
+	 */
+	happy_meal_set_initial_advertisement(hp);
+
 	ether_setup(dev);
 
 	/* If we don't do this, nothing works. */
@@ -3459,55 +2910,79 @@
 }
 #endif
 
-int __init happy_meal_probe(void)
+#ifdef CONFIG_SBUS
+static int __init happy_meal_sbus_probe(struct net_device *dev)
 {
-	struct net_device *dev = NULL;
-	struct linux_sbus *bus;
-	struct linux_sbus_device *sdev = 0;
-	static int called = 0;
-	int cards = 0, v;
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev;
+	int cards = 0;
 
-	if(called)
-		return ENODEV;
-	called++;
+	for_each_sbus(sbus) {
+		for_each_sbusdev(sdev, sbus) {
+			char *name = sdev->prom_name;
 
-	for_each_sbus(bus) {
-		for_each_sbusdev(sdev, bus) {
-			if(cards)
+			if (cards)
 				dev = NULL;
-			if(!strcmp(sdev->prom_name, "SUNW,hme")) {
+			if (!strcmp(name, "SUNW,hme")) {
 				cards++;
-				if((v = happy_meal_ether_init(dev, sdev, 0)))
-					return v;
-			} else if(!strcmp(sdev->prom_name, "qfe") ||
-				  !strcmp(sdev->prom_name, "SUNW,qfe")) {
+				happy_meal_sbus_init(dev, sdev, 0);
+			} else if (!strcmp(name, "qfe") ||
+				   !strcmp(name, "SUNW,qfe")) {
 				cards++;
-				if((v = happy_meal_ether_init(dev, sdev, 1)))
-					return v;
+				happy_meal_sbus_init(dev, sdev, 1);
 			}
 		}
 	}
-	if(cards != 0)
+	if (cards != 0)
 		quattro_sbus_register_irqs();
+	return cards;
+}
+#endif
+
 #ifdef CONFIG_PCI
-	if(pci_present()) {
+static int __init happy_meal_pci_probe(struct net_device *dev)
+{
+	int cards = 0;
+
+	if (pci_present()) {
 		struct pci_dev *pdev;
 
 		pdev = pci_find_device(PCI_VENDOR_ID_SUN,
 				       PCI_DEVICE_ID_SUN_HAPPYMEAL, 0);
-		while (pdev) {
-			if(cards)
+		while (pdev != NULL) {
+			if (cards)
 				dev = NULL;
 			cards++;
-			if((v = happy_meal_pci_init(dev, pdev)))
-				return v;
+			happy_meal_pci_init(dev, pdev);
 			pdev = pci_find_device(PCI_VENDOR_ID_SUN,
 					       PCI_DEVICE_ID_SUN_HAPPYMEAL,
 					       pdev);
 		}
 	}
+	return cards;
+}
 #endif
-	if(!cards)
+
+int __init happy_meal_probe(void)
+{
+	struct net_device *dev = NULL;
+	static int called = 0;
+	int cards;
+
+	if (called)
+		return ENODEV;
+	called++;
+
+	cards = 0;
+#ifdef CONFIG_SBUS
+	cards += happy_meal_sbus_probe(dev);
+	if (cards != 0)
+		dev = NULL;
+#endif
+#ifdef CONFIG_PCI
+	cards += happy_meal_pci_probe(dev);
+#endif
+	if (!cards)
 		return ENODEV;
 	return 0;
 }
@@ -3518,32 +2993,33 @@
 init_module(void)
 {
 	root_happy_dev = NULL;
-	return happy_meal_probe(NULL);
+	return happy_meal_probe();
 }
 
 void
 cleanup_module(void)
 {
-	struct happy_meal *sunshine;
-
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_happy_dev) {
 		struct happy_meal *hp = root_happy_dev;
-		sunshine = root_happy_dev->next_module;
+		struct happy_meal *next = root_happy_dev->next_module;
 
-		sparc_free_io(hp->gregs, sizeof(struct hmeal_gregs));
-		sparc_free_io(hp->etxregs, sizeof(struct hmeal_etxregs));
-		sparc_free_io(hp->erxregs, sizeof(struct hmeal_erxregs));
-		sparc_free_io(hp->bigmacregs, sizeof(struct hmeal_bigmacregs));
-		sparc_free_io(hp->tcvregs, sizeof(struct hmeal_tcvregs));
-#ifndef __sparc_v9__
-		if (sparc_cpu_model == sun4d)
-			iounit_map_dma_finish(hp->happy_sbus_dev->my_bus,
-					      (__u32)hp->sun4d_buffers, (RX_RING_SIZE + TX_RING_SIZE) * PAGE_SIZE);
-#endif		
+#ifdef CONFIG_SBUS
+		if (!(hp->happy_flags & HFLAG_PCI)) {
+			sbus_iounmap(hp->gregs, GREG_REG_SIZE);
+			sbus_iounmap(hp->etxregs, ETX_REG_SIZE);
+			sbus_iounmap(hp->erxregs, ERX_REG_SIZE);
+			sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE);
+			sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE);
+			sbus_free_consistant(hp->happy_dev,
+					     PAGE_SIZE,
+					     hp->happy_block,
+					     hp->hblock_dvma);
+		}
+#endif
 		unregister_netdev(hp->dev);
 		kfree(hp->dev);
-		root_happy_dev = sunshine;
+		root_happy_dev = next;
 	}
 }
 
diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunhme.h linux/drivers/net/sunhme.h
--- v2.3.34/linux/drivers/net/sunhme.h	Wed Aug 18 11:36:45 1999
+++ linux/drivers/net/sunhme.h	Mon Dec 20 22:06:42 1999
@@ -1,7 +1,8 @@
-/* sunhme.h: Definitions for Sparc HME/BigMac 10/100baseT ethernet driver.
+/* $Id: sunhme.h,v 1.28 1999/09/21 14:36:34 davem Exp $
+ * sunhme.h: Definitions for Sparc HME/BigMac 10/100baseT ethernet driver.
  *           Also known as the "Happy Meal".
  *
- * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
+ * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com)
  */
 
 #ifndef _SUNHME_H
@@ -10,13 +11,11 @@
 #include <linux/config.h>
 
 /* Happy Meal global registers. */
-struct hmeal_gregs {
-	volatile unsigned int sw_reset;      /* Software Reset  */
-	volatile unsigned int cfg;           /* Config Register */
-	volatile unsigned int _padding[62];  /* Unused          */
-	volatile unsigned int stat;          /* Status          */
-	volatile unsigned int imask;         /* Interrupt Mask  */
-};
+#define GREG_SWRESET	0x000UL	/* Software Reset  */
+#define GREG_CFG	0x004UL	/* Config Register */
+#define GREG_STAT	0x108UL	/* Status          */
+#define GREG_IMASK	0x10cUL	/* Interrupt Mask  */
+#define GREG_REG_SIZE	0x110UL
 
 /* Global reset register. */
 #define GREG_RESET_ETX         0x01
@@ -104,21 +103,20 @@
 #define GREG_IMASK_SLVPERR     0x80000000 /* PIO access got a parity error            */
 
 /* Happy Meal external transmitter registers. */
-struct hmeal_etxregs {
-	volatile unsigned int tx_pnding;     /* Transmit pending/wakeup register */
-	volatile unsigned int cfg;           /* Transmit config register         */
-	volatile unsigned int tx_ring;       /* Transmit ring pointer            */
-	volatile unsigned int tx_bbase;      /* Transmit buffer base             */
-	volatile unsigned int tx_bdisp;      /* Transmit buffer displacement     */
-	volatile unsigned int tx_fifo_wptr;  /* FIFO write ptr                   */
-	volatile unsigned int tx_fifo_swptr; /* FIFO write ptr (shadow register) */
-	volatile unsigned int tx_fifo_rptr;  /* FIFO read ptr                    */
-	volatile unsigned int tx_fifo_srptr; /* FIFO read ptr (shadow register)  */
-	volatile unsigned int tx_fifo_pcnt;  /* FIFO packet counter              */
-	volatile unsigned int smachine;      /* Transmitter state machine        */
-	volatile unsigned int tx_rsize;      /* Ring descriptor size             */
-	volatile unsigned int tx_bptr;       /* Transmit data buffer ptr         */
-};
+#define ETX_PENDING	0x00UL	/* Transmit pending/wakeup register */
+#define ETX_CFG		0x04UL	/* Transmit config register         */
+#define ETX_RING	0x08UL	/* Transmit ring pointer            */
+#define ETX_BBASE	0x0cUL	/* Transmit buffer base             */
+#define ETX_BDISP	0x10UL	/* Transmit buffer displacement     */
+#define ETX_FIFOWPTR	0x14UL	/* FIFO write ptr                   */
+#define ETX_FIFOSWPTR	0x18UL	/* FIFO write ptr (shadow register) */
+#define ETX_FIFORPTR	0x1cUL	/* FIFO read ptr                    */
+#define ETX_FIFOSRPTR	0x20UL	/* FIFO read ptr (shadow register)  */
+#define ETX_FIFOPCNT	0x24UL	/* FIFO packet counter              */
+#define ETX_SMACHINE	0x28UL	/* Transmitter state machine        */
+#define ETX_RSIZE	0x2cUL	/* Ring descriptor size             */
+#define ETX_BPTR	0x30UL	/* Transmit data buffer ptr         */
+#define ETX_REG_SIZE	0x34UL
 
 /* ETX transmit pending register. */
 #define ETX_TP_DMAWAKEUP         0x00000001 /* Restart transmit dma             */
@@ -132,16 +130,15 @@
 #define ETX_RSIZE_SHIFT          4
 
 /* Happy Meal external receiver registers. */
-struct hmeal_erxregs {
-	volatile unsigned int cfg;           /* Receiver config register         */
-	volatile unsigned int rx_ring;       /* Receiver ring ptr                */
-	volatile unsigned int rx_bptr;       /* Receiver buffer ptr              */
-	volatile unsigned int rx_fifo_wptr;  /* FIFO write ptr                   */
-	volatile unsigned int rx_fifo_swptr; /* FIFO write ptr (shadow register) */
-	volatile unsigned int rx_fifo_rptr;  /* FIFO read ptr                    */
-	volatile unsigned int rx_fifo_srptr; /* FIFO read ptr (shadow register)  */
-	volatile unsigned int smachine;      /* Receiver state machine           */
-};
+#define ERX_CFG		0x00UL	/* Receiver config register         */
+#define ERX_RING	0x04UL	/* Receiver ring ptr                */
+#define ERX_BPTR	0x08UL	/* Receiver buffer ptr              */
+#define ERX_FIFOWPTR	0x0cUL	/* FIFO write ptr                   */
+#define ERX_FIFOSWPTR	0x10UL	/* FIFO write ptr (shadow register) */
+#define ERX_FIFORPTR	0x14UL	/* FIFO read ptr                    */
+#define ERX_FIFOSRPTR	0x18UL	/* FIFO read ptr (shadow register)  */
+#define ERX_SMACHINE	0x1cUL	/* Receiver state machine           */
+#define ERX_REG_SIZE	0x20UL
 
 /* ERX config register. */
 #define ERX_CFG_DMAENABLE    0x00000001 /* Enable receive DMA        */
@@ -156,54 +153,52 @@
 #define ERX_CFG_CSUMSTART    0x007f0000 /* Offset of checksum start  */
 
 /* I'd like a Big Mac, small fries, small coke, and SparcLinux please. */
-struct hmeal_bigmacregs {
-	volatile unsigned int xif_cfg;          /* XIF config register                */
-	volatile unsigned int _unused[129];     /* Reserved...                        */
-	volatile unsigned int tx_swreset;       /* Transmitter software reset         */
-	volatile unsigned int tx_cfg;           /* Transmitter config register        */
-	volatile unsigned int ipkt_gap1;        /* Inter-packet gap 1                 */
-	volatile unsigned int ipkt_gap2;        /* Inter-packet gap 2                 */
-	volatile unsigned int attempt_limit;    /* Transmit attempt limit             */
-	volatile unsigned int stime;            /* Transmit slot time                 */
-	volatile unsigned int preamble_len;     /* Size of transmit preamble          */
-	volatile unsigned int preamble_pattern; /* Pattern for transmit preamble      */
-	volatile unsigned int tx_sframe_delim;  /* Transmit delimiter                 */
-	volatile unsigned int jsize;            /* Jam size                           */
-	volatile unsigned int tx_pkt_max;       /* Transmit max pkt size              */
-	volatile unsigned int tx_pkt_min;       /* Transmit min pkt size              */
-	volatile unsigned int peak_attempt;     /* Count of transmit peak attempts    */
-	volatile unsigned int dt_ctr;           /* Transmit defer timer               */
-	volatile unsigned int nc_ctr;           /* Transmit normal-collision counter  */
-	volatile unsigned int fc_ctr;           /* Transmit first-collision counter   */
-	volatile unsigned int ex_ctr;           /* Transmit excess-collision counter  */
-	volatile unsigned int lt_ctr;           /* Transmit late-collision counter    */
-	volatile unsigned int rand_seed;        /* Transmit random number seed        */
-	volatile unsigned int tx_smachine;      /* Transmit state machine             */
-	volatile unsigned int _unused2[44];     /* Reserved                           */
-	volatile unsigned int rx_swreset;       /* Receiver software reset            */
-	volatile unsigned int rx_cfg;           /* Receiver config register           */
-	volatile unsigned int rx_pkt_max;       /* Receive max pkt size               */
-	volatile unsigned int rx_pkt_min;       /* Receive min pkt size               */
-	volatile unsigned int mac_addr2;        /* Ether address register 2           */
-	volatile unsigned int mac_addr1;        /* Ether address register 1           */
-	volatile unsigned int mac_addr0;        /* Ether address register 0           */
-	volatile unsigned int fr_ctr;           /* Receive frame receive counter      */
-	volatile unsigned int gle_ctr;          /* Receive giant-length error counter */
-	volatile unsigned int unale_ctr;        /* Receive unaligned error counter    */
-	volatile unsigned int rcrce_ctr;        /* Receive CRC error counter          */
-	volatile unsigned int rx_smachine;      /* Receiver state machine             */
-	volatile unsigned int rx_cvalid;        /* Receiver code violation            */
-	volatile unsigned int _unused3;         /* Reserved...                        */
-	volatile unsigned int htable3;          /* Hash table 3                       */
-	volatile unsigned int htable2;          /* Hash table 2                       */
-	volatile unsigned int htable1;          /* Hash table 1                       */
-	volatile unsigned int htable0;          /* Hash table 0                       */
-	volatile unsigned int afilter2;         /* Address filter 2                   */
-	volatile unsigned int afilter1;         /* Address filter 1                   */
-	volatile unsigned int afilter0;         /* Address filter 0                   */
-	volatile unsigned int afilter_mask;     /* Address filter mask                */
-
-};
+#define BMAC_XIFCFG	0x0000UL	/* XIF config register                */
+	/* 0x4-->0x204, reserved */
+#define BMAC_TXSWRESET	0x208UL	/* Transmitter software reset         */
+#define BMAC_TXCFG	0x20cUL	/* Transmitter config register        */
+#define BMAC_IGAP1	0x210UL	/* Inter-packet gap 1                 */
+#define BMAC_IGAP2	0x214UL	/* Inter-packet gap 2                 */
+#define BMAC_ALIMIT	0x218UL	/* Transmit attempt limit             */
+#define BMAC_STIME	0x21cUL	/* Transmit slot time                 */
+#define BMAC_PLEN	0x220UL	/* Size of transmit preamble          */
+#define BMAC_PPAT	0x224UL	/* Pattern for transmit preamble      */
+#define BMAC_TXSDELIM	0x228UL	/* Transmit delimiter                 */
+#define BMAC_JSIZE	0x22cUL	/* Jam size                           */
+#define BMAC_TXMAX	0x230UL	/* Transmit max pkt size              */
+#define BMAC_TXMIN	0x234UL	/* Transmit min pkt size              */
+#define BMAC_PATTEMPT	0x238UL	/* Count of transmit peak attempts    */
+#define BMAC_DTCTR	0x23cUL	/* Transmit defer timer               */
+#define BMAC_NCCTR	0x240UL	/* Transmit normal-collision counter  */
+#define BMAC_FCCTR	0x244UL	/* Transmit first-collision counter   */
+#define BMAC_EXCTR	0x248UL	/* Transmit excess-collision counter  */
+#define BMAC_LTCTR	0x24cUL	/* Transmit late-collision counter    */
+#define BMAC_RSEED	0x250UL	/* Transmit random number seed        */
+#define BMAC_TXSMACHINE	0x254UL	/* Transmit state machine             */
+	/* 0x258-->0x304, reserved */
+#define BMAC_RXSWRESET	0x308UL	/* Receiver software reset            */
+#define BMAC_RXCFG	0x30cUL	/* Receiver config register           */
+#define BMAC_RXMAX	0x310UL	/* Receive max pkt size               */
+#define BMAC_RXMIN	0x314UL	/* Receive min pkt size               */
+#define BMAC_MACADDR2	0x318UL	/* Ether address register 2           */
+#define BMAC_MACADDR1	0x31cUL	/* Ether address register 1           */
+#define BMAC_MACADDR0	0x320UL	/* Ether address register 0           */
+#define BMAC_FRCTR	0x324UL	/* Receive frame receive counter      */
+#define BMAC_GLECTR	0x328UL	/* Receive giant-length error counter */
+#define BMAC_UNALECTR	0x32cUL	/* Receive unaligned error counter    */
+#define BMAC_RCRCECTR	0x330UL	/* Receive CRC error counter          */
+#define BMAC_RXSMACHINE	0x334UL	/* Receiver state machine             */
+#define BMAC_RXCVALID	0x338UL	/* Receiver code violation            */
+	/* 0x33c, reserved */
+#define BMAC_HTABLE3	0x340UL	/* Hash table 3                       */
+#define BMAC_HTABLE2	0x344UL	/* Hash table 2                       */
+#define BMAC_HTABLE1	0x348UL	/* Hash table 1                       */
+#define BMAC_HTABLE0	0x34cUL	/* Hash table 0                       */
+#define BMAC_AFILTER2	0x350UL	/* Address filter 2                   */
+#define BMAC_AFILTER1	0x354UL	/* Address filter 1                   */
+#define BMAC_AFILTER0	0x358UL	/* Address filter 0                   */
+#define BMAC_AFMASK	0x35cUL	/* Address filter mask                */
+#define BMAC_REG_SIZE	0x360UL
 
 /* BigMac XIF config register. */
 #define BIGMAC_XCFG_ODENABLE  0x00000001 /* Output driver enable         */
@@ -236,16 +231,15 @@
 #define BIGMAC_RXCFG_AENABLE  0x00001000 /* Enable the address filter       */
 
 /* These are the "Management Interface" (ie. MIF) registers of the transceiver. */
-struct hmeal_tcvregs {
-	volatile unsigned int bb_clock; /* Bit bang clock register          */
-	volatile unsigned int bb_data;  /* Bit bang data register           */
-	volatile unsigned int bb_oenab; /* Bit bang output enable           */
-	volatile unsigned int frame;    /* Frame control/data register      */
-	volatile unsigned int cfg;      /* MIF config register              */
-	volatile unsigned int int_mask; /* MIF interrupt mask               */
-	volatile unsigned int status;   /* MIF status                       */
-	volatile unsigned int smachine; /* MIF state machine                */
-};
+#define TCVR_BBCLOCK	0x00UL	/* Bit bang clock register          */
+#define TCVR_BBDATA	0x04UL	/* Bit bang data register           */
+#define TCVR_BBOENAB	0x08UL	/* Bit bang output enable           */
+#define TCVR_FRAME	0x0cUL	/* Frame control/data register      */
+#define TCVR_CFG	0x10UL	/* MIF config register              */
+#define TCVR_IMASK	0x14UL	/* MIF interrupt mask               */
+#define TCVR_STATUS	0x18UL	/* MIF status                       */
+#define TCVR_SMACHINE	0x1cUL	/* MIF state machine                */
+#define TCVR_REG_SIZE	0x20UL
 
 /* Frame commands. */
 #define FRAME_WRITE           0x50020000
@@ -421,10 +415,12 @@
 /* Happy Meal descriptor rings and such.
  * All descriptor rings must be aligned on a 2K boundry.
  * All receive buffers must be 64 byte aligned.
+ * Always write the address first before setting the ownership
+ * bits to avoid races with the hardware scanning the ring.
  */
 struct happy_meal_rxd {
-	unsigned int rx_flags;
-	unsigned int rx_addr;
+	u32 rx_flags;
+	u32 rx_addr;
 };
 
 #define RXFLAG_OWN         0x80000000 /* 1 = hardware, 0 = software */
@@ -433,8 +429,8 @@
 #define RXFLAG_CSUM        0x0000ffff /* HW computed checksum       */
 
 struct happy_meal_txd {
-	unsigned int tx_flags;
-	unsigned int tx_addr;
+	u32 tx_flags;
+	u32 tx_addr;
 };
 
 #define TXFLAG_OWN         0x80000000 /* 1 = hardware, 0 = software */
@@ -480,18 +476,6 @@
 #define hblock_offset(mem, elem) \
 ((__u32)((unsigned long)(&(((struct hmeal_init_block *)0)->mem[elem]))))
 
-#define SUN4C_PKT_BUF_SZ	1546
-#define SUN4C_RX_BUFF_SIZE	SUN4C_PKT_BUF_SZ
-#define SUN4C_TX_BUFF_SIZE	SUN4C_PKT_BUF_SZ
-
-struct hmeal_buffers {
-	char	tx_buf[TX_RING_SIZE][SUN4C_TX_BUFF_SIZE];
-	char	rx_buf[RX_RING_SIZE][SUN4C_RX_BUFF_SIZE];
-};
-
-#define hbuf_offset(mem, elem) \
-((__u32)((unsigned long)(&(((struct hmeal_buffers *)0)->mem[elem][0]))))
-
 /* Now software state stuff. */
 enum happy_transceiver {
 	external = 0,
@@ -511,25 +495,39 @@
 
 /* Happy happy, joy joy! */
 struct happy_meal {
-	struct hmeal_gregs       *gregs;          /* Happy meal global registers       */
-	struct hmeal_etxregs     *etxregs;        /* External transmitter regs         */
-	struct hmeal_erxregs     *erxregs;        /* External receiver regs            */
-	struct hmeal_bigmacregs  *bigmacregs;     /* I said NO SOLARIS with my bigmac! */
-	struct hmeal_tcvregs     *tcvregs;        /* MIF transceiver regs              */
+	unsigned long	gregs;			/* Happy meal global registers       */
+	struct hmeal_init_block  *happy_block;	/* RX and TX descriptors (CPU addr)  */
 
-	struct hmeal_init_block  *happy_block;    /* RX and TX descriptors (CPU addr)  */
-	__u32                     hblock_dvma;    /* DVMA visible address happy block  */
+#if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
+	u32 (*read_desc32)(u32 *);
+	void (*write_txd)(struct happy_meal_txd *, u32, u32);
+	void (*write_rxd)(struct happy_meal_rxd *, u32, u32);
+	u32 (*dma_map)(void *, void *, long);
+	void (*dma_unmap)(void *, u32, long);
+	void (*dma_sync)(void *, u32, long);
+#endif
+
+	/* This is either a sbus_dev or a pci_dev. */
+	void			  *happy_dev;
 
 	struct sk_buff           *rx_skbs[RX_RING_SIZE];
 	struct sk_buff           *tx_skbs[TX_RING_SIZE];
 
 	int rx_new, tx_new, rx_old, tx_old;
 
-	/* We may use this for Ultra as well, will have to see, maybe not. */
-	struct hmeal_buffers     *sun4c_buffers;  /* CPU visible address.              */
-#define	sun4d_buffers		  sun4c_buffers	  /* No need to make this a separate.  */
-	__u32                     s4c_buf_dvma;   /* DVMA visible address.             */
+	struct net_device_stats	  net_stats;      /* Statistical counters              */
+
+#if defined(CONFIG_SBUS) && defined(CONFIG_PCI)
+	u32 (*read32)(unsigned long);
+	void (*write32)(unsigned long, u32);
+#endif
+
+	unsigned long	etxregs;        /* External transmitter regs         */
+	unsigned long	erxregs;        /* External receiver regs            */
+	unsigned long	bigmacregs;     /* BIGMAC core regs		     */
+	unsigned long	tcvregs;        /* MIF transceiver regs              */
 
+	__u32                     hblock_dvma;    /* DVMA visible address happy block  */
 	unsigned int              happy_flags;    /* Driver state flags                */
 	enum happy_transceiver    tcvr_type;      /* Kind of transceiver in use        */
 	unsigned int              happy_bursts;   /* Get your mind out of the gutter   */
@@ -555,15 +553,10 @@
 	enum happy_timer_state    timer_state;    /* State of the auto-neg timer.      */
 	unsigned int              timer_ticks;    /* Number of clicks at each state.   */
 
-	struct net_device_stats	  net_stats;      /* Statistical counters              */
-	struct linux_sbus_device *happy_sbus_dev; /* ;-)                               */
-#ifdef CONFIG_PCI
-	struct pci_dev		 *happy_pci_dev;
-#endif
-	struct net_device            *dev;            /* Backpointer                       */
-	struct quattro		 *qfe_parent;	  /* For Quattro cards                 */
-	int			  qfe_ent;	  /* Which instance on quattro         */
-	struct happy_meal        *next_module;
+	struct net_device	 *dev;		/* Backpointer                       */
+	struct quattro		 *qfe_parent;	/* For Quattro cards                 */
+	int			  qfe_ent;	/* Which instance on quattro         */
+	struct happy_meal         *next_module;
 };
 
 /* Here are the happy flags. */
@@ -586,15 +579,12 @@
 
 /* Support for QFE/Quattro cards. */
 struct quattro {
-	volatile u32		 *irq_status[4];
-	struct net_device		 *happy_meals[4];
-	void (*handler)(int, void *, struct pt_regs *);
-
-	struct linux_sbus_device *quattro_sbus_dev;
-#ifdef CONFIG_PCI
-	struct pci_dev		 *quattro_pci_dev;
-#endif
-	struct quattro		 *next;
+	struct net_device	*happy_meals[4];
+
+	/* This is either a sbus_dev or a pci_dev. */
+	void			*quattro_dev;
+
+	struct quattro		*next;
 
 	/* PROM ranges, if any. */
 	struct linux_prom_ranges  ranges[8];
@@ -603,78 +593,16 @@
 
 /* We use this to acquire receive skb's that we can DMA directly into. */
 #define ALIGNED_RX_SKB_ADDR(addr) \
-        ((((unsigned long)(addr) + (64 - 1)) & ~(64 - 1)) - (unsigned long)(addr))
+        ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr))
 #define happy_meal_alloc_skb(__length, __gfp_flags) \
 ({	struct sk_buff *__skb; \
 	__skb = alloc_skb((__length) + 64, (__gfp_flags)); \
 	if(__skb) { \
-		int __offset = ALIGNED_RX_SKB_ADDR(__skb->data); \
+		int __offset = (int) ALIGNED_RX_SKB_ADDR(__skb->data); \
 		if(__offset) \
 			skb_reserve(__skb, __offset); \
 	} \
 	__skb; \
 })
-
-/* Register/DMA access stuff, used to cope with differences between
- * PCI and SBUS happy meals.
- */
-#if defined(CONFIG_PCI)
-#define kva_to_hva(__hp, __addr) \
-({	u32 __ret; \
-	if ((__hp)->happy_flags & HFLAG_PCI) \
-		(__ret) = (u32) virt_to_bus((volatile void *)(__addr)); \
-	else \
-		(__ret) = sbus_dvma_addr(__addr); \
-	__ret; \
-})
-#define hme_read32(__hp, __reg) \
-({	unsigned int __ret; \
-	if ((__hp)->happy_flags & HFLAG_PCI) \
-		__ret = readl((unsigned long)(__reg)); \
-	else \
-		__ret = *(__reg); \
-	__ret; \
-})
-#define hme_write32(__hp, __reg, __val) \
-do {	if ((__hp)->happy_flags & HFLAG_PCI) \
-		writel((__val), (unsigned long)(__reg)); \
-	else \
-		*(__reg) = (__val); \
-} while(0)
-#else
-#define kva_to_hva(__hp, __addr) ((u32)sbus_dvma_addr(__addr))
-#define hme_read32(__hp, __reg)	(*(__reg))
-#define hme_write32(__hp, __reg, __val)	((*(__reg)) = (__val))
-#endif
-
-#ifdef CONFIG_PCI
-#ifdef __sparc_v9__
-#define pcihme_write_rxd(__rp, __flags, __addr) \
-	__asm__ __volatile__("stwa	%3, [%0] %2\n\t" \
-			     "stwa	%4, [%1] %2" \
-			     : /* no outputs */ \
-			     : "r" (&(__rp)->rx_addr), "r" (&(__rp)->rx_flags), \
-			       "i" (ASI_PL), "r" (__addr), "r" (__flags))
-
-#define pcihme_write_txd(__tp, __flags, __addr) \
-	__asm__ __volatile__("stwa	%3, [%0] %2\n\t" \
-			     "stwa	%4, [%1] %2" \
-			     : /* no outputs */ \
-			     : "r" (&(__tp)->tx_addr), "r" (&(__tp)->tx_flags), \
-			       "i" (ASI_PL), "r" (__addr), "r" (__flags))
-#else
-
-#define pcihme_write_rxd(__rp, __flags, __addr) \
-do {	(__rp)->rx_addr = flip_dword(__addr); \
-	(__rp)->rx_flags = flip_dword(__flags); \
-} while(0)
-	
-#define pcihme_write_txd(__tp, __flags, __addr) \
-do {	(__tp)->tx_addr = flip_dword(__addr); \
-	(__tp)->tx_flags = flip_dword(__flags); \
-} while(0)
-	
-#endif  /* def __sparc_v9__ */
-#endif  /* def CONFIG_PCI */
 
 #endif /* !(_SUNHME_H) */
diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c
--- v2.3.34/linux/drivers/net/sunlance.c	Thu Nov 11 20:11:42 1999
+++ linux/drivers/net/sunlance.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.88 1999/08/20 00:31:45 davem Exp $
+/* $Id: sunlance.c,v 1.92 1999/12/15 14:08:09 davem Exp $
  * lance.c: Linux/Sparc/Lance driver
  *
  *	Written 1995, 1996 by Miguel de Icaza
@@ -60,15 +60,16 @@
  * 1.12:
  * 	 11/3/99: Fixed SMP race in lance_start_xmit found by davem.
  * 	          Anton Blanchard (anton@progsoc.uts.edu.au)
+ * 2.00: 11/9/99: Massive overhaul and port to new SBUS driver interfaces.
+ *		  David S. Miller (davem@redhat.com)
  */
 
 #undef DEBUG_DRIVER
 
 static char *version =
-	"sunlance.c:v1.12 11/Mar/99 Miguel de Icaza (miguel@nuclecu.unam.mx)\n";
+	"sunlance.c:v2.00 11/Sep/99 Miguel de Icaza (miguel@nuclecu.unam.mx)\n";
 
 static char *lancestr = "LANCE";
-static char *lancedma = "LANCE DMA";
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -177,53 +178,55 @@
 #define TX_RING_SIZE			(1 << (LANCE_LOG_TX_BUFFERS))
 #define TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
 #define TX_RING_LEN_BITS		((LANCE_LOG_TX_BUFFERS) << 29)
+#define TX_NEXT(__x)			(((__x)+1) & TX_RING_MOD_MASK)
 
 #define RX_RING_SIZE			(1 << (LANCE_LOG_RX_BUFFERS))
 #define RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
 #define RX_RING_LEN_BITS		((LANCE_LOG_RX_BUFFERS) << 29)
+#define RX_NEXT(__x)			(((__x)+1) & RX_RING_MOD_MASK)
 
 #define PKT_BUF_SZ		1544
 #define RX_BUFF_SIZE            PKT_BUF_SZ
 #define TX_BUFF_SIZE            PKT_BUF_SZ
 
 struct lance_rx_desc {
-	unsigned short rmd0;        /* low address of packet */
-	unsigned char  rmd1_bits;   /* descriptor bits */
-	unsigned char  rmd1_hadr;   /* high address of packet */
-	short    length;    	    /* This length is 2s complement (negative)!
-				     * Buffer length
-				     */
-	unsigned short mblength;    /* This is the actual number of bytes received */
+	u16	rmd0;		/* low address of packet */
+	u8	rmd1_bits;	/* descriptor bits */
+	u8	rmd1_hadr;	/* high address of packet */
+	s16	length;		/* This length is 2s complement (negative)!
+				 * Buffer length
+				 */
+	u16	mblength;	/* This is the actual number of bytes received */
 };
 
 struct lance_tx_desc {
-	unsigned short tmd0;        /* low address of packet */
-	unsigned char  tmd1_bits;   /* descriptor bits */
-	unsigned char  tmd1_hadr;   /* high address of packet */
-	short length;          	    /* Length is 2s complement (negative)! */
-	unsigned short misc;
+	u16	tmd0;		/* low address of packet */
+	u8 	tmd1_bits;	/* descriptor bits */
+	u8 	tmd1_hadr;	/* high address of packet */
+	s16 	length;		/* Length is 2s complement (negative)! */
+	u16 	misc;
 };
 		
 /* The LANCE initialization block, described in databook. */
 /* On the Sparc, this block should be on a DMA region     */
 struct lance_init_block {
-	unsigned short mode;		/* Pre-set mode (reg. 15) */
-	unsigned char phys_addr[6];     /* Physical ethernet address */
-	unsigned filter[2];		/* Multicast filter. */
+	u16	mode;		/* Pre-set mode (reg. 15) */
+	u8	phys_addr[6];	/* Physical ethernet address */
+	u32	filter[2];	/* Multicast filter. */
 
 	/* Receive and transmit ring base, along with extra bits. */
-	unsigned short rx_ptr;		/* receive descriptor addr */
-	unsigned short rx_len;		/* receive len and high addr */
-	unsigned short tx_ptr;		/* transmit descriptor addr */
-	unsigned short tx_len;		/* transmit len and high addr */
+	u16	rx_ptr;		/* receive descriptor addr */
+	u16	rx_len;		/* receive len and high addr */
+	u16	tx_ptr;		/* transmit descriptor addr */
+	u16	tx_len;		/* transmit len and high addr */
     
 	/* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
 	struct lance_rx_desc brx_ring[RX_RING_SIZE];
 	struct lance_tx_desc btx_ring[TX_RING_SIZE];
     
-	char   tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
-	char   pad[2];			/* align rx_buf for copy_and_sum(). */
-	char   rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
+	u8	tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
+	u8	pad[2];		/* align rx_buf for copy_and_sum(). */
+	u8	rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
 };
 
 #define libdesc_offset(rt, elem) \
@@ -233,40 +236,48 @@
 ((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem][0])))))
 
 struct lance_private {
-	char *name;
-	volatile struct lance_regs *ll;
+	unsigned long	lregs;		/* Lance RAP/RDP regs.		*/
+	unsigned long	dregs;		/* DMA controller regs.		*/
 	volatile struct lance_init_block *init_block;
-	__u32 init_block_dvma;
     
-	int rx_new, tx_new;
-	int rx_old, tx_old;
+	int		rx_new, tx_new;
+	int		rx_old, tx_old;
     
 	struct net_device_stats	stats;
-	struct Linux_SBus_DMA *ledma; /* If set this points to ledma    */
-				      /* and arch = sun4m		*/
-
-	int tpe;		      /* cable-selection is TPE		*/
-	int auto_select;	      /* cable-selection by carrier	*/
-	int burst_sizes;	      /* ledma SBus burst sizes		*/
-
-	unsigned short busmaster_regval;
-	unsigned short pio_buffer;
-
-	struct net_device		 *dev;		  /* Backpointer	*/
-	struct lance_private	 *next_module;
-	struct linux_sbus        *sbus;
-	struct timer_list         multicast_timer;
+	struct sbus_dma *ledma;	/* If set this points to ledma	*/
+	char		tpe;		/* cable-selection is TPE	*/
+	char		auto_select;	/* cable-selection by carrier	*/
+	char		burst_sizes;	/* ledma SBus burst sizes	*/
+	char		pio_buffer;	/* init block in PIO space?	*/
+
+	unsigned short	busmaster_regval;
+
+	void (*init_ring)(struct net_device *);
+	void (*rx)(struct net_device *);
+	void (*tx)(struct net_device *);
+
+	char	       	       *name;
+	__u32			init_block_dvma;
+	struct net_device      *dev;		  /* Backpointer	*/
+	struct lance_private   *next_module;
+	struct sbus_dev	       *sdev;
+	struct timer_list       multicast_timer;
 };
 
 #define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
 			lp->tx_old+TX_RING_MOD_MASK-lp->tx_new:\
 			lp->tx_old - lp->tx_new-1)
 
-/* On the sparc, the lance control ports are memory mapped */
-struct lance_regs {
-	unsigned short rdp;			/* register data port */
-	unsigned short rap;			/* register address port */
-};
+/* Lance registers. */
+#define RDP		0x00UL		/* register data port		*/
+#define RAP		0x02UL		/* register address port	*/
+#define LANCE_REG_SIZE	0x04UL
+
+#define STOP_LANCE(__lp) \
+do {	unsigned long __base = (__lp)->lregs; \
+	sbus_writew(LE_CSR0,	__base + RAP); \
+	sbus_writew(LE_C0_STOP,	__base + RDP); \
+} while (0)
 
 int sparc_lance_debug = 2;
 
@@ -275,7 +286,7 @@
 /* On the Sun4m we have to instruct the ledma to provide them    */
 /* Even worse, on scsi/ether SBUS cards, the init block and the
  * transmit/receive buffers are addresses as offsets from absolute
- * zero on the lebuffer PIO area. -davem
+ * zero on the lebuffer PIO area. -DaveM
  */
 
 #define LANCE_ADDR(x) ((long)(x) & ~0xff000000)
@@ -285,46 +296,36 @@
 #endif
 
 /* Load the CSR registers */
-static void load_csrs (struct lance_private *lp)
+static void load_csrs(struct lance_private *lp)
 {
-	volatile struct lance_regs *ll = lp->ll;
-	__u32 ib_dvma = lp->init_block_dvma;
-	int leptr;
+	u32 leptr;
 
-	/* This is right now because when we are using a PIO buffered
-	 * init block, init_block_dvma is set to zero. -DaveM
-	 */
-	leptr = LANCE_ADDR (ib_dvma);
-
-	ll->rap = LE_CSR1;
-	ll->rdp = (leptr & 0xFFFF);
-	ll->rap = LE_CSR2;
-	ll->rdp = leptr >> 16;
-	ll->rap = LE_CSR3;
-	ll->rdp = lp->busmaster_regval;
+	if (lp->pio_buffer)
+		leptr = 0;
+	else
+		leptr = LANCE_ADDR(lp->init_block_dvma);
+
+	sbus_writew(LE_CSR1,		  lp->lregs + RAP);
+	sbus_writew(leptr & 0xffff,	  lp->lregs + RDP);
+	sbus_writew(LE_CSR2,		  lp->lregs + RAP);
+	sbus_writew(leptr >> 16,	  lp->lregs + RDP);
+	sbus_writew(LE_CSR3,		  lp->lregs + RAP);
+	sbus_writew(lp->busmaster_regval, lp->lregs + RDP);
 
 	/* Point back to csr0 */
-	ll->rap = LE_CSR0;
+	sbus_writew(LE_CSR0, lp->lregs + RAP);
 }
 
-#define ZERO 0
-
 /* Setup the Lance Rx and Tx rings */
 /* Sets dev->tbusy */
-static void lance_init_ring (struct net_device *dev)
+static void lance_init_ring_dvma(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
-	__u32 ib_dvma = lp->init_block_dvma;
-	__u32 aib; /* for LANCE_ADDR computations */
-	int leptr;
+	__u32 aib = lp->init_block_dvma;
+	__u32 leptr;
 	int i;
     
-	/* This is right now because when we are using a PIO buffered
-	 * init block, init_block_dvma is set to zero. -DaveM
-	 */
-	aib = ib_dvma;
-
 	/* Lock out other processes while setting up hardware */
 	dev->tbusy = 1;
 	lp->rx_new = lp->tx_new = 0;
@@ -332,7 +333,6 @@
 
 	/* Copy the ethernet address to the lance init block
 	 * Note that on the sparc you need to swap the ethernet address.
-	 * Note also we want the CPU ptr of the init_block here.
 	 */
 	ib->phys_addr [0] = dev->dev_addr [1];
 	ib->phys_addr [1] = dev->dev_addr [0];
@@ -341,9 +341,6 @@
 	ib->phys_addr [4] = dev->dev_addr [5];
 	ib->phys_addr [5] = dev->dev_addr [4];
 
-	if (ZERO)
-		printk ("TX rings:\n");
-    
 	/* Setup the Tx ring entries */
 	for (i = 0; i <= TX_RING_SIZE; i++) {
 		leptr = LANCE_ADDR(aib + libbuff_offset(tx_buf, i));
@@ -352,13 +349,9 @@
 		ib->btx_ring [i].tmd1_bits = 0;
 		ib->btx_ring [i].length    = 0xf000; /* The ones required by tmd2 */
 		ib->btx_ring [i].misc      = 0;
-		if (i < 3)
-			if (ZERO) printk ("%d: 0x%8.8x\n", i, leptr);
 	}
 
 	/* Setup the Rx ring entries */
-	if (ZERO)
-		printk ("RX rings:\n");
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		leptr = LANCE_ADDR(aib + libbuff_offset(rx_buf, i));
 
@@ -367,8 +360,6 @@
 		ib->brx_ring [i].rmd1_bits = LE_R1_OWN;
 		ib->brx_ring [i].length    = -RX_BUFF_SIZE | 0xf000;
 		ib->brx_ring [i].mblength  = 0;
-		if (i < 3 && ZERO)
-			printk ("%d: 0x%8.8x\n", i, leptr);
 	}
 
 	/* Setup the initialization block */
@@ -377,98 +368,155 @@
 	leptr = LANCE_ADDR(aib + libdesc_offset(brx_ring, 0));
 	ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16);
 	ib->rx_ptr = leptr;
-	if (ZERO)
-		printk ("RX ptr: %8.8x\n", leptr);
     
 	/* Setup tx descriptor pointer */
 	leptr = LANCE_ADDR(aib + libdesc_offset(btx_ring, 0));
 	ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16);
 	ib->tx_ptr = leptr;
-	if (ZERO)
-		printk ("TX ptr: %8.8x\n", leptr);
 }
 
-static int init_restart_lance (struct lance_private *lp)
+static void lance_init_ring_pio(struct net_device *dev)
 {
-	volatile struct lance_regs *ll = lp->ll;
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_init_block *ib = lp->init_block;
+	u32 leptr;
 	int i;
+    
+	/* Lock out other processes while setting up hardware */
+	dev->tbusy = 1;
+	lp->rx_new = lp->tx_new = 0;
+	lp->rx_old = lp->tx_old = 0;
 
-	if (lp->ledma) {
-		struct sparc_dma_registers *dregs = lp->ledma->regs;
-		unsigned long creg;
-
-		if (!(dregs->cond_reg & DMA_HNDL_ERROR)) {
-			/* E-Cache draining */
-			while (dregs->cond_reg & DMA_FIFO_ISDRAIN)
-				barrier();
-		}
+	/* Copy the ethernet address to the lance init block
+	 * Note that on the sparc you need to swap the ethernet address.
+	 */
+	sbus_writeb(dev->dev_addr[1], &ib->phys_addr[0]);
+	sbus_writeb(dev->dev_addr[0], &ib->phys_addr[1]);
+	sbus_writeb(dev->dev_addr[3], &ib->phys_addr[2]);
+	sbus_writeb(dev->dev_addr[2], &ib->phys_addr[3]);
+	sbus_writeb(dev->dev_addr[5], &ib->phys_addr[4]);
+	sbus_writeb(dev->dev_addr[4], &ib->phys_addr[5]);
 
-		creg = dregs->cond_reg;
-		if (lp->burst_sizes & DMA_BURST32)
-			creg |= DMA_E_BURST8;
-		else
-			creg &= ~DMA_E_BURST8;
+	/* Setup the Tx ring entries */
+	for (i = 0; i <= TX_RING_SIZE; i++) {
+		leptr = libbuff_offset(tx_buf, i);
+		sbus_writew(leptr,	&ib->btx_ring [i].tmd0);
+		sbus_writeb(leptr >> 16,&ib->btx_ring [i].tmd1_hadr);
+		sbus_writeb(0,		&ib->btx_ring [i].tmd1_bits);
+
+		/* The ones required by tmd2 */
+		sbus_writew(0xf000,	&ib->btx_ring [i].length);
+		sbus_writew(0,		&ib->btx_ring [i].misc);
+	}
 
-		creg |= (DMA_DSBL_RD_DRN | DMA_DSBL_WR_INV | DMA_FIFO_INV);
+	/* Setup the Rx ring entries */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		leptr = libbuff_offset(rx_buf, i);
 
-		if (lp->tpe)
-			creg |= DMA_EN_ENETAUI;
-		else
-			creg &= ~DMA_EN_ENETAUI;
-		udelay(20);
-		dregs->cond_reg = creg;
-		udelay(200);
+		sbus_writew(leptr,	&ib->brx_ring [i].rmd0);
+		sbus_writeb(leptr >> 16,&ib->brx_ring [i].rmd1_hadr);
+		sbus_writeb(LE_R1_OWN,	&ib->brx_ring [i].rmd1_bits);
+		sbus_writew(-RX_BUFF_SIZE|0xf000,
+			    &ib->brx_ring [i].length);
+		sbus_writew(0,		&ib->brx_ring [i].mblength);
 	}
 
-	ll->rap = LE_CSR0;
-	ll->rdp = LE_C0_INIT;
+	/* Setup the initialization block */
+    
+	/* Setup rx descriptor pointer */
+	leptr = libdesc_offset(brx_ring, 0);
+	sbus_writew((LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16),
+		    &ib->rx_len);
+	sbus_writew(leptr, &ib->rx_ptr);
+    
+	/* Setup tx descriptor pointer */
+	leptr = libdesc_offset(btx_ring, 0);
+	sbus_writew((LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16),
+		    &ib->tx_len);
+	sbus_writew(leptr, &ib->tx_ptr);
+}
+
+static void init_restart_ledma(struct lance_private *lp)
+{
+	u32 csr = sbus_readl(lp->dregs + DMA_CSR);
+
+	if (!(csr & DMA_HNDL_ERROR)) {
+		/* E-Cache draining */
+		while (sbus_readl(lp->dregs + DMA_CSR) & DMA_FIFO_ISDRAIN)
+			barrier();
+	}
+
+	csr = sbus_readl(lp->dregs + DMA_CSR);
+	csr &= ~DMA_E_BURSTS;
+	if (lp->burst_sizes & DMA_BURST32)
+		csr |= DMA_E_BURST32;
+	else
+		csr |= DMA_E_BURST16;
+
+	csr |= (DMA_DSBL_RD_DRN | DMA_DSBL_WR_INV | DMA_FIFO_INV);
+
+	if (lp->tpe)
+		csr |= DMA_EN_ENETAUI;
+	else
+		csr &= ~DMA_EN_ENETAUI;
+	udelay(20);
+	sbus_writel(csr, lp->dregs + DMA_CSR);
+	udelay(200);
+}
+
+static int init_restart_lance(struct lance_private *lp)
+{
+	u16 regval = 0;
+	int i;
+
+	if (lp->dregs)
+		init_restart_ledma(lp);
+
+	sbus_writew(LE_CSR0,	lp->lregs + RAP);
+	sbus_writew(LE_C0_INIT,	lp->lregs + RDP);
 
 	/* Wait for the lance to complete initialization */
-	for (i = 0; (i < 100) && !(ll->rdp & (LE_C0_ERR | LE_C0_IDON)); i++)
+	for (i = 0; i < 100; i++) {
+		regval = sbus_readw(lp->lregs + RDP);
+
+		if (regval & (LE_C0_ERR | LE_C0_IDON))
+			break;
 		barrier();
-	if ((i == 100) || (ll->rdp & LE_C0_ERR)) {
-		printk ("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp);
-		if (lp->ledma)
-			printk ("dcsr=%8.8x\n",
-				(unsigned int) lp->ledma->regs->cond_reg);
+	}
+	if (i == 100 || (regval & LE_C0_ERR)) {
+		printk(KERN_ERR "LANCE unopened after %d ticks, csr0=%4.4x.\n",
+		       i, regval);
+		if (lp->dregs)
+			printk("dcsr=%8.8x\n", sbus_readl(lp->dregs + DMA_CSR));
 		return -1;
 	}
 
 	/* Clear IDON by writing a "1", enable interrupts and start lance */
-	ll->rdp = LE_C0_IDON;
-	ll->rdp = LE_C0_INEA | LE_C0_STRT;
+	sbus_writew(LE_C0_IDON,			lp->lregs + RDP);
+	sbus_writew(LE_C0_INEA | LE_C0_STRT,	lp->lregs + RDP);
 
-	if (lp->ledma)
-		lp->ledma->regs->cond_reg |= DMA_INT_ENAB;
+	if (lp->dregs) {
+		u32 csr = sbus_readl(lp->dregs + DMA_CSR);
+
+		csr |= DMA_INT_ENAB;
+		sbus_writel(csr, lp->dregs + DMA_CSR);
+	}
 
 	return 0;
 }
 
-static int lance_rx (struct net_device *dev)
+static void lance_rx_dvma(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
 	volatile struct lance_rx_desc *rd;
-	unsigned char bits;
-	int len;
+	u8 bits;
+	int len, entry = lp->rx_new;
 	struct sk_buff *skb;
 
-#ifdef TEST_HITS
-	printk ("[");
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		if (i == lp->rx_new)
-			printk ("%s",
-				ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "_" : "X");
-		else
-			printk ("%s",
-				ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "." : "1");
-	}
-	printk ("]");
-#endif
-    
-	for (rd = &ib->brx_ring [lp->rx_new];
+	for (rd = &ib->brx_ring [entry];
 	     !((bits = rd->rmd1_bits) & LE_R1_OWN);
-	     rd = &ib->brx_ring [lp->rx_new]) {
+	     rd = &ib->brx_ring [entry]) {
 
 		/* We got an incomplete frame? */
 		if ((bits & LE_R1_POK) != LE_R1_POK) {
@@ -485,58 +533,57 @@
 			if (bits & LE_R1_EOP) lp->stats.rx_errors++;
 		} else {
 			len = (rd->mblength & 0xfff) - 4;
-			skb = dev_alloc_skb (len+2);
+			skb = dev_alloc_skb(len + 2);
 
-			if (skb == 0) {
-				printk ("%s: Memory squeeze, deferring packet.\n",
-					dev->name);
+			if (skb == NULL) {
+				printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
+				       dev->name);
 				lp->stats.rx_dropped++;
 				rd->mblength = 0;
 				rd->rmd1_bits = LE_R1_OWN;
-				lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK;
-				return 0;
+				lp->rx_new = RX_NEXT(entry);
+				return;
 			}
 	    
 			lp->stats.rx_bytes += len;
 
 			skb->dev = dev;
-			skb_reserve (skb, 2);		/* 16 byte align */
-			skb_put (skb, len);		/* make room */
+			skb_reserve(skb, 2);		/* 16 byte align */
+			skb_put(skb, len);		/* make room */
 			eth_copy_and_sum(skb,
-					 (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
+					 (unsigned char *)&(ib->rx_buf [entry][0]),
 					 len, 0);
-			skb->protocol = eth_type_trans (skb, dev);
-			netif_rx (skb);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
 			lp->stats.rx_packets++;
 		}
 
 		/* Return the packet to the pool */
 		rd->mblength = 0;
 		rd->rmd1_bits = LE_R1_OWN;
-		lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK;
+		entry = RX_NEXT(entry);
 	}
-	return 0;
+
+	lp->rx_new = entry;
 }
 
-static int lance_tx (struct net_device *dev)
+static void lance_tx_dvma(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
-	volatile struct lance_regs *ll = lp->ll;
-	volatile struct lance_tx_desc *td;
 	int i, j;
-	int status;
 
 	j = lp->tx_old;
 	for (i = j; i != lp->tx_new; i = j) {
-		td = &ib->btx_ring [i];
+		volatile struct lance_tx_desc *td = &ib->btx_ring [i];
+		u8 bits = td->tmd1_bits;
 
 		/* If we hit a packet not owned by us, stop */
-		if (td->tmd1_bits & LE_T1_OWN)
+		if (bits & LE_T1_OWN)
 			break;
 		
-		if (td->tmd1_bits & LE_T1_ERR) {
-			status = td->misc;
+		if (bits & LE_T1_ERR) {
+			u16 status = td->misc;
 	    
 			lp->stats.tx_errors++;
 			if (status & LE_T3_RTY)  lp->stats.tx_aborted_errors++;
@@ -546,15 +593,13 @@
 				lp->stats.tx_carrier_errors++;
 				if (lp->auto_select) {
 					lp->tpe = 1 - lp->tpe;
-					printk("%s: Carrier Lost, trying %s\n",
+					printk(KERN_NOTICE "%s: Carrier Lost, trying %s\n",
 					       dev->name, lp->tpe?"TPE":"AUI");
-					/* Stop the lance */
-					ll->rap = LE_CSR0;
-					ll->rdp = LE_C0_STOP;
-					lance_init_ring (dev);
-					load_csrs (lp);
-					init_restart_lance (lp);
-					return 0;
+					STOP_LANCE(lp);
+					lp->init_ring(dev);
+					load_csrs(lp);
+					init_restart_lance(lp);
+					return;
 				}
 			}
 
@@ -564,72 +609,233 @@
 			if (status & (LE_T3_BUF|LE_T3_UFL)) {
 				lp->stats.tx_fifo_errors++;
 
-				printk ("%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
-					dev->name);
-				/* Stop the lance */
-				ll->rap = LE_CSR0;
-				ll->rdp = LE_C0_STOP;
-				lance_init_ring (dev);
-				load_csrs (lp);
-				init_restart_lance (lp);
-				return 0;
+				printk(KERN_ERR "%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
+				       dev->name);
+				STOP_LANCE(lp);
+				lp->init_ring(dev);
+				load_csrs(lp);
+				init_restart_lance(lp);
+				return;
 			}
-		} else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
+		} else if ((bits & LE_T1_POK) == LE_T1_POK) {
 			/*
 			 * So we don't count the packet more than once.
 			 */
-			td->tmd1_bits &= ~(LE_T1_POK);
+			td->tmd1_bits = bits & ~(LE_T1_POK);
 
 			/* One collision before packet was sent. */
-			if (td->tmd1_bits & LE_T1_EONE)
+			if (bits & LE_T1_EONE)
 				lp->stats.collisions++;
 
 			/* More than one collision, be optimistic. */
-			if (td->tmd1_bits & LE_T1_EMORE)
+			if (bits & LE_T1_EMORE)
 				lp->stats.collisions += 2;
 
 			lp->stats.tx_packets++;
 		}
 	
-		j = (j + 1) & TX_RING_MOD_MASK;
+		j = TX_NEXT(j);
 	}
 	lp->tx_old = j;
-	return 0;
 }
 
-static void lance_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+static void lance_piocopy_to_skb(struct sk_buff *skb, volatile void *piobuf, int len)
+{
+	u16 *p16 = (u16 *) skb->data;
+	u32 *p32;
+	u8 *p8;
+	unsigned long pbuf = (unsigned long) piobuf;
+
+	/* We know here that both src and dest are on a 16bit boundry. */
+	*p16++ = sbus_readw(pbuf);
+	p32 = (u32 *) p16;
+	pbuf += 2;
+	len -= 2;
+
+	while (len >= 4) {
+		*p32++ = sbus_readl(pbuf);
+		pbuf += 4;
+		len -= 4;
+	}
+	p8 = (u8 *) p32;
+	if (len >= 2) {
+		p16 = (u16 *) p32;
+		*p16++ = sbus_readw(pbuf);
+		pbuf += 2;
+		len -= 2;
+		p8 = (u8 *) p16;
+	}
+	if (len >= 1)
+		*p8 = sbus_readb(pbuf);
+}
+
+static void lance_rx_pio(struct net_device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_init_block *ib = lp->init_block;
+	volatile struct lance_rx_desc *rd;
+	unsigned char bits;
+	int len, entry;
+	struct sk_buff *skb;
+
+	entry = lp->rx_new;
+	for (rd = &ib->brx_ring [entry];
+	     !((bits = sbus_readb(&rd->rmd1_bits)) & LE_R1_OWN);
+	     rd = &ib->brx_ring [entry]) {
+
+		/* We got an incomplete frame? */
+		if ((bits & LE_R1_POK) != LE_R1_POK) {
+			lp->stats.rx_over_errors++;
+			lp->stats.rx_errors++;
+		} else if (bits & LE_R1_ERR) {
+			/* Count only the end frame as a rx error,
+			 * not the beginning
+			 */
+			if (bits & LE_R1_BUF) lp->stats.rx_fifo_errors++;
+			if (bits & LE_R1_CRC) lp->stats.rx_crc_errors++;
+			if (bits & LE_R1_OFL) lp->stats.rx_over_errors++;
+			if (bits & LE_R1_FRA) lp->stats.rx_frame_errors++;
+			if (bits & LE_R1_EOP) lp->stats.rx_errors++;
+		} else {
+			len = (sbus_readw(&rd->mblength) & 0xfff) - 4;
+			skb = dev_alloc_skb(len + 2);
+
+			if (skb == NULL) {
+				printk(KERN_INFO "%s: Memory squeeze, deferring packet.\n",
+				       dev->name);
+				lp->stats.rx_dropped++;
+				sbus_writew(0, &rd->mblength);
+				sbus_writeb(LE_R1_OWN, &rd->rmd1_bits);
+				lp->rx_new = RX_NEXT(entry);
+				return;
+			}
+	    
+			lp->stats.rx_bytes += len;
+
+			skb->dev = dev;
+			skb_reserve (skb, 2);		/* 16 byte align */
+			skb_put(skb, len);		/* make room */
+			lance_piocopy_to_skb(skb, &(ib->rx_buf[entry][0]), len);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			lp->stats.rx_packets++;
+		}
+
+		/* Return the packet to the pool */
+		sbus_writew(0, &rd->mblength);
+		sbus_writeb(LE_R1_OWN, &rd->rmd1_bits);
+		entry = RX_NEXT(entry);
+	}
+
+	lp->rx_new = entry;
+}
+
+static void lance_tx_pio(struct net_device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_init_block *ib = lp->init_block;
+	int i, j;
+
+	j = lp->tx_old;
+	for (i = j; i != lp->tx_new; i = j) {
+		volatile struct lance_tx_desc *td = &ib->btx_ring [i];
+		u8 bits = sbus_readb(&td->tmd1_bits);
+
+		/* If we hit a packet not owned by us, stop */
+		if (bits & LE_T1_OWN)
+			break;
+		
+		if (bits & LE_T1_ERR) {
+			u16 status = sbus_readw(&td->misc);
+	    
+			lp->stats.tx_errors++;
+			if (status & LE_T3_RTY)  lp->stats.tx_aborted_errors++;
+			if (status & LE_T3_LCOL) lp->stats.tx_window_errors++;
+
+			if (status & LE_T3_CLOS) {
+				lp->stats.tx_carrier_errors++;
+				if (lp->auto_select) {
+					lp->tpe = 1 - lp->tpe;
+					printk(KERN_NOTICE "%s: Carrier Lost, trying %s\n",
+					       dev->name, lp->tpe?"TPE":"AUI");
+					STOP_LANCE(lp);
+					lp->init_ring(dev);
+					load_csrs(lp);
+					init_restart_lance(lp);
+					return;
+				}
+			}
+
+			/* Buffer errors and underflows turn off the
+			 * transmitter, restart the adapter.
+			 */
+			if (status & (LE_T3_BUF|LE_T3_UFL)) {
+				lp->stats.tx_fifo_errors++;
+
+				printk(KERN_ERR "%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
+				       dev->name);
+				STOP_LANCE(lp);
+				lp->init_ring(dev);
+				load_csrs(lp);
+				init_restart_lance(lp);
+				return;
+			}
+		} else if ((bits & LE_T1_POK) == LE_T1_POK) {
+			/*
+			 * So we don't count the packet more than once.
+			 */
+			sbus_writeb(bits & ~(LE_T1_POK), &td->tmd1_bits);
+
+			/* One collision before packet was sent. */
+			if (bits & LE_T1_EONE)
+				lp->stats.collisions++;
+
+			/* More than one collision, be optimistic. */
+			if (bits & LE_T1_EMORE)
+				lp->stats.collisions += 2;
+
+			lp->stats.tx_packets++;
+		}
+	
+		j = TX_NEXT(j);
+	}
+	lp->tx_old = j;
+}
+
+static void lance_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
 	struct lance_private *lp = (struct lance_private *)dev->priv;
-	volatile struct lance_regs *ll = lp->ll;
 	int csr0;
     
 	if (dev->interrupt)
-		printk ("%s: again", dev->name);
+		printk(KERN_ERR "%s: again", dev->name);
     
 	dev->interrupt = 1;
 
-	ll->rap = LE_CSR0;
-	csr0 = ll->rdp;
+	sbus_writew(LE_CSR0, lp->lregs + RAP);
+	csr0 = sbus_readw(lp->lregs + RDP);
 
 	/* Acknowledge all the interrupt sources ASAP */
-	ll->rdp = csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT);
+	sbus_writew(csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT),
+		    lp->lregs + RDP);
     
-	if ((csr0 & LE_C0_ERR)) {
+	if ((csr0 & LE_C0_ERR) != 0) {
 		/* Clear the error condition */
-		ll->rdp = LE_C0_BABL | LE_C0_ERR | LE_C0_MISS |
-			  LE_C0_CERR | LE_C0_MERR;
+		sbus_writew((LE_C0_BABL | LE_C0_ERR | LE_C0_MISS |
+			     LE_C0_CERR | LE_C0_MERR),
+			    lp->lregs + RDP);
 	}
     
 	if (csr0 & LE_C0_RINT)
-		lance_rx (dev);
+		lp->rx(dev);
     
 	if (csr0 & LE_C0_TINT)
-		lance_tx (dev);
+		lp->tx(dev);
     
-	if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) {
+	if ((TX_BUFFS_AVAIL > 0) && dev->tbusy) {
 		dev->tbusy = 0;
-		mark_bh (NET_BH);
+		mark_bh(NET_BH);
 	}
 
 	if (csr0 & LE_C0_BABL)
@@ -639,103 +845,122 @@
 		lp->stats.rx_errors++;
 
 	if (csr0 & LE_C0_MERR) {
-		struct sparc_dma_registers *dregs = lp->ledma->regs;
-		unsigned long tst = (unsigned long)dregs->st_addr;
+		if (lp->dregs) {
+			u32 addr = sbus_readl(lp->dregs + DMA_ADDR);
+
+			printk(KERN_ERR "%s: Memory error, status %04x, addr %06x\n",
+			       dev->name, csr0, addr & 0xffffff);
+		} else {
+			printk(KERN_ERR "%s: Memory error, status %04x\n",
+			       dev->name, csr0);
+		}
 
-		printk ("%s: Memory error, status %04x, addr %06lx\n",
-			dev->name, csr0, tst & 0xffffff);
+		sbus_writew(LE_C0_STOP, lp->lregs + RDP);
 
-		ll->rdp = LE_C0_STOP;
+		if (lp->dregs) {
+			u32 dma_csr = sbus_readl(lp->dregs + DMA_CSR);
 
-		if (lp->ledma)
-			lp->ledma->regs->cond_reg |= DMA_FIFO_INV;
+			dma_csr |= DMA_FIFO_INV;
+			sbus_writel(dma_csr, lp->dregs + DMA_CSR);
+		}
 
-		lance_init_ring (dev);
-		load_csrs (lp);
-		init_restart_lance (lp);
+		lp->init_ring(dev);
+		load_csrs(lp);
+		init_restart_lance(lp);
 		dev->tbusy = 0;
 	}
 
-	ll->rdp = LE_C0_INEA;
+	sbus_writew(LE_C0_INEA, lp->lregs + RDP);
 	dev->interrupt = 0;
 }
 
+/* Build a fake network packet and send it to ourselves. */
+static void build_fake_packet(struct lance_private *lp)
+{
+	struct net_device *dev = lp->dev;
+	volatile struct lance_init_block *ib = lp->init_block;
+	u16 *packet;
+	struct ethhdr *eth;
+	int i, entry;
+
+	entry = lp->tx_new & TX_RING_MOD_MASK;
+	packet = (u16 *) &(ib->tx_buf[entry][0]);
+	eth = (struct ethhdr *) packet;
+	if (lp->pio_buffer) {
+		for (i = 0; i < (ETH_ZLEN / sizeof(u16)); i++)
+			sbus_writew(0, &packet[i]);
+		for (i = 0; i < 6; i++) {
+			sbus_writeb(dev->dev_addr[i], &eth->h_dest[i]);
+			sbus_writeb(dev->dev_addr[i], &eth->h_source[i]);
+		}
+		sbus_writew((-ETH_ZLEN) | 0xf000, &ib->btx_ring[entry].length);
+		sbus_writew(0, &ib->btx_ring[entry].misc);
+		sbus_writeb(LE_T1_POK|LE_T1_OWN, &ib->btx_ring[entry].tmd1_bits);
+	} else {
+		memset(packet, 0, ETH_ZLEN);
+		for (i = 0; i < 6; i++) {
+			eth->h_dest[i] = dev->dev_addr[i];
+			eth->h_source[i] = dev->dev_addr[i];
+		}
+		ib->btx_ring[entry].length = (-ETH_ZLEN) | 0xf000;
+		ib->btx_ring[entry].misc = 0;
+		ib->btx_ring[entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
+	}
+	lp->tx_new = TX_NEXT(entry);
+}
+
 struct net_device *last_dev = 0;
 
-static int lance_open (struct net_device *dev)
+static int lance_open(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
-	volatile struct lance_regs *ll = lp->ll;
 	volatile struct lance_init_block *ib = lp->init_block;
 	int status = 0;
 
 	last_dev = dev;
 
-	if (request_irq (dev->irq, &lance_interrupt, SA_SHIRQ,
-			 lancestr, (void *) dev)) {
-		printk ("Lance: Can't get irq %s\n", __irq_itoa(dev->irq));
+	if (request_irq(dev->irq, &lance_interrupt, SA_SHIRQ,
+			lancestr, (void *) dev)) {
+		printk(KERN_ERR "Lance: Can't get irq %s\n", __irq_itoa(dev->irq));
 		return -EAGAIN;
 	}
 
-	/* Stop the Lance */
-	ll->rap = LE_CSR0;
-	ll->rdp = LE_C0_STOP;
+	STOP_LANCE(lp);
 
 	/* On the 4m, setup the ledma to provide the upper bits for buffers */
-	if (lp->ledma)
-		lp->ledma->regs->dma_test = ((__u32) lp->init_block_dvma) & 0xff000000;
+	if (lp->dregs) {
+		u32 regval = lp->init_block_dvma & 0xff000000;
 
-	/* Set mode and clear multicast filter only at device open,
-	   so that lance_init_ring() called at any error will not
-	   forget multicast filters.
+		sbus_writel(regval, lp->dregs + DMA_TEST);
+	}
 
-	   BTW it is common bug in all lance drivers! --ANK
+	/* Set mode and clear multicast filter only at device open,
+	 * so that lance_init_ring() called at any error will not
+	 * forget multicast filters.
+	 *
+	 * BTW it is common bug in all lance drivers! --ANK
 	 */
-	ib->mode = 0;
-	ib->filter [0] = 0;
-	ib->filter [1] = 0;
+	if (lp->pio_buffer) {
+		sbus_writew(0, &ib->mode);
+		sbus_writel(0, &ib->filter[0]);
+		sbus_writel(0, &ib->filter[1]);
+	} else {
+		ib->mode = 0;
+		ib->filter [0] = 0;
+		ib->filter [1] = 0;
+	}
 
-	lance_init_ring (dev);
-	load_csrs (lp);
+	lp->init_ring(dev);
+	load_csrs(lp);
 
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
 
-	status = init_restart_lance (lp);
-#if 0
-	/* To emulate SunOS, we add a route to the local network */
-	rt_add (RTF_UP,
-		dev->pa_addr & ip_get_mask (dev->pa_addr),
-		ip_get_mask (dev->pa_addr),
-		0, dev, dev->mtu, 0, 0);
-#endif
+	status = init_restart_lance(lp);
 	if (!status && lp->auto_select) {
-		/*
-		 * Build a fake network packet and send it to ourselfs.
-		 */
-		volatile struct lance_init_block *ib = lp->init_block;
-		volatile unsigned long flush;
-		unsigned char packet[ETH_ZLEN];
-		struct ethhdr *eth = (struct ethhdr *)packet;
-		int i, entry;
-
-		memset(packet, 0, ETH_ZLEN);
-		for (i = 0; i < 6; i++) {
-			eth->h_dest[i] = dev->dev_addr[i];
-			eth->h_source[i] = dev->dev_addr[i];
-		}
-
-		entry = lp->tx_new & TX_RING_MOD_MASK;
-		ib->btx_ring[entry].length = (-ETH_ZLEN) | 0xf000;
-		ib->btx_ring[entry].misc = 0;
-
-		memcpy((char *)&ib->tx_buf[entry][0], packet, ETH_ZLEN);
-		ib->btx_ring[entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
-		lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK;
-
-		ll->rdp = LE_C0_INEA | LE_C0_TDMD;
-		flush = ll->rdp;
+		build_fake_packet(lp);
+		sbus_writew(LE_C0_INEA | LE_C0_TDMD, lp->lregs + RDP);
 	}
 
 	if (!status)
@@ -744,74 +969,162 @@
 	return status;
 }
 
-static int lance_close (struct net_device *dev)
+static int lance_close(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
-	volatile struct lance_regs *ll = lp->ll;
 
 	dev->start = 0;
 	dev->tbusy = 1;
 	del_timer(&lp->multicast_timer);
 
-	/* Stop the card */
-	ll->rap = LE_CSR0;
-	ll->rdp = LE_C0_STOP;
+	STOP_LANCE(lp);
 
-	free_irq (dev->irq, (void *) dev);
+	free_irq(dev->irq, (void *) dev);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
-static inline int lance_reset (struct net_device *dev)
+static int lance_reset(struct net_device *dev)
 {
-	struct lance_private *lp = (struct lance_private *)dev->priv;
-	volatile struct lance_regs *ll = lp->ll;
+	struct lance_private *lp = (struct lance_private *) dev->priv;
 	int status;
     
-	/* Stop the lance */
-	ll->rap = LE_CSR0;
-	ll->rdp = LE_C0_STOP;
+	STOP_LANCE(lp);
 
 	/* On the 4m, reset the dma too */
-	if (lp->ledma) {
-		printk ("resetting ledma\n");
-		lp->ledma->regs->cond_reg |= DMA_RST_ENET;
-		udelay (200);
-		lp->ledma->regs->cond_reg &= ~DMA_RST_ENET;
-		lp->ledma->regs->dma_test = ((__u32) lp->init_block_dvma) & 0xff000000;
+	if (lp->dregs) {
+		u32 csr, addr;
+
+		printk(KERN_ERR "resetting ledma\n");
+		csr = sbus_readl(lp->dregs + DMA_CSR);
+		sbus_writel(csr | DMA_RST_ENET, lp->dregs + DMA_CSR);
+		udelay(200);
+		sbus_writel(csr & ~DMA_RST_ENET, lp->dregs + DMA_CSR);
+
+		addr = lp->init_block_dvma & 0xff000000;
+		sbus_writel(addr, lp->dregs + DMA_TEST);
 	}
-	lance_init_ring (dev);
-	load_csrs (lp);
+	lp->init_ring(dev);
+	load_csrs(lp);
 	dev->trans_start = jiffies;
 	dev->interrupt = 0;
 	dev->start = 1;
 	dev->tbusy = 0;
-	status = init_restart_lance (lp);
-#ifdef DEBUG_DRIVER
-	printk ("Lance restart=%d\n", status);
-#endif
+	status = init_restart_lance(lp);
 	return status;
 }
 
-static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
+static void lance_piocopy_from_skb(volatile void *dest, char *src, int len)
 {
-	struct lance_private *lp = (struct lance_private *)dev->priv;
-	volatile struct lance_regs *ll = lp->ll;
+	unsigned long piobuf = (unsigned long) dest;
+	u32 *p32;
+	u16 *p16;
+	u8 *p8;
+
+	switch ((unsigned long)src & 0x3) {
+	case 0:
+		p32 = (u32 *) src;
+		while (len >= 4) {
+			sbus_writel(*p32, piobuf);
+			p32++;
+			piobuf += 4;
+			len -= 4;
+		}
+		src = (char *) p32;
+		break;
+	case 1:
+	case 3:
+		p8 = (u8 *) src;
+		while (len >= 4) {
+			u32 val;
+
+			val  = p8[0] << 24;
+			val |= p8[1] << 16;
+			val |= p8[2] << 8;
+			val |= p8[3];
+			sbus_writel(val, piobuf);
+			p8 += 4;
+			piobuf += 4;
+			len -= 4;
+		}
+		src = (char *) p8;
+		break;
+	case 2:
+		p16 = (u16 *) src;
+		while (len >= 4) {
+			u32 val = p16[0]<<16 | p16[1];
+			sbus_writel(val, piobuf);
+			p16 += 2;
+			piobuf += 4;
+			len -= 4;
+		}
+		src = (char *) p16;
+		break;
+	};
+	if (len >= 2) {
+		u16 val = src[0] << 8 | src[1];
+		sbus_writew(val, piobuf);
+		src += 2;
+		piobuf += 2;
+		len -= 2;
+	}
+	if (len >= 1)
+		sbus_writeb(src[0], piobuf);
+}
+
+static void lance_piozero(volatile void *dest, int len)
+{
+	unsigned long piobuf = (unsigned long) dest;
+
+	if (piobuf & 1) {
+		sbus_writeb(0, piobuf);
+		piobuf += 1;
+		len -= 1;
+		if (len == 0)
+			return;
+	}
+	if (len == 1) {
+		sbus_writeb(0, piobuf);
+		return;
+	}
+	if (piobuf & 2) {
+		sbus_writew(0, piobuf);
+		piobuf += 2;
+		len -= 2;
+		if (len == 0)
+			return;
+	}
+	while (len >= 4) {
+		sbus_writel(0, piobuf);
+		piobuf += 4;
+		len -= 4;
+	}
+	if (len >= 2) {
+		sbus_writew(0, piobuf);
+		piobuf += 2;
+		len -= 2;
+	}
+	if (len >= 1)
+		sbus_writeb(0, piobuf);
+}
+
+static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
-	volatile unsigned long flush;
 	unsigned long flags;
 	int entry, skblen, len;
 
-	if (test_and_set_bit (0, (void *) &dev->tbusy) != 0) {
+	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
 		int tickssofar = jiffies - dev->trans_start;
 
 		if (tickssofar < 100)
 			return 1;
 
-		printk ("%s: transmit timed out, status %04x, reset\n",
-			dev->name, ll->rdp);
+		printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
+		       dev->name, sbus_readw(lp->lregs + RDP));
 		lp->stats.tx_errors++;
-		lance_reset (dev);
+		lance_reset(dev);
 
 		return 1;
 	}
@@ -830,38 +1143,43 @@
 	lp->stats.tx_bytes += len;
 
 	entry = lp->tx_new & TX_RING_MOD_MASK;
-	ib->btx_ring [entry].length = (-len) | 0xf000;
-	ib->btx_ring [entry].misc = 0;
-    
-	memcpy ((char *)&ib->tx_buf [entry][0], skb->data, skblen);
+	if (lp->pio_buffer) {
+		sbus_writew((-len) | 0xf000, &ib->btx_ring[entry].length);
+		sbus_writew(0, &ib->btx_ring[entry].misc);
+		lance_piocopy_from_skb(&ib->tx_buf[entry][0], skb->data, skblen);
+		if (len != skblen)
+			lance_piozero(&ib->tx_buf[entry][skblen], len - skblen);
+		sbus_writeb(LE_T1_POK | LE_T1_OWN, &ib->btx_ring[entry].tmd1_bits);
+	} else {
+		ib->btx_ring [entry].length = (-len) | 0xf000;
+		ib->btx_ring [entry].misc = 0;
+		memcpy((char *)&ib->tx_buf [entry][0], skb->data, skblen);
+		if (len != skblen)
+			memset((char *) &ib->tx_buf [entry][skblen], 0, len - skblen);
+		ib->btx_ring [entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN);
+	}
 
-	/* Clear the slack of the packet, do I need this? */
-	/* For a firewall its a good idea - AC */
-	if (len != skblen)
-		memset ((char *) &ib->tx_buf [entry][skblen], 0, len - skblen);
-    
-	/* Now, give the packet to the lance */
-	ib->btx_ring [entry].tmd1_bits = (LE_T1_POK|LE_T1_OWN);
-	lp->tx_new = (lp->tx_new+1) & TX_RING_MOD_MASK;
+	lp->tx_new = TX_NEXT(entry);
 
 	/* Kick the lance: transmit now */
-	ll->rdp = LE_C0_INEA | LE_C0_TDMD;
+	sbus_writew(LE_C0_INEA | LE_C0_TDMD, lp->lregs + RDP);
 	dev->trans_start = jiffies;
-	dev_kfree_skb (skb);
+	dev_kfree_skb(skb);
     
 	if (TX_BUFFS_AVAIL)
 		dev->tbusy = 0;
 
 	/* Read back CSR to invalidate the E-Cache.
-	 * This is needed, because DMA_DSBL_WR_INV is set. */
-	if (lp->ledma)
-		flush = ll->rdp;
+	 * This is needed, because DMA_DSBL_WR_INV is set.
+	 */
+	if (lp->dregs)
+		sbus_readw(lp->lregs + RDP);
 
 	restore_flags(flags);
 	return 0;
 }
 
-static struct net_device_stats *lance_get_stats (struct net_device *dev)
+static struct net_device_stats *lance_get_stats(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 
@@ -869,25 +1187,35 @@
 }
 
 /* taken from the depca driver */
-static void lance_load_multicast (struct net_device *dev)
+static void lance_load_multicast(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
-	volatile u16 *mcast_table = (u16 *)&ib->filter;
-	struct dev_mc_list *dmi=dev->mc_list;
+	volatile u16 *mcast_table = (u16 *) &ib->filter;
+	struct dev_mc_list *dmi = dev->mc_list;
 	char *addrs;
 	int i, j, bit, byte;
 	u32 crc, poly = CRC_POLYNOMIAL_LE;
 	
 	/* set all multicast bits */
 	if (dev->flags & IFF_ALLMULTI) {
-		ib->filter [0] = 0xffffffff;
-		ib->filter [1] = 0xffffffff;
+		if (lp->pio_buffer) {
+			sbus_writel(0xffffffff, &ib->filter[0]);
+			sbus_writel(0xffffffff, &ib->filter[1]);
+		} else {
+			ib->filter [0] = 0xffffffff;
+			ib->filter [1] = 0xffffffff;
+		}
 		return;
 	}
 	/* clear the multicast filter */
-	ib->filter [0] = 0;
-	ib->filter [1] = 0;
+	if (lp->pio_buffer) {
+		sbus_writel(0, &ib->filter[0]);
+		sbus_writel(0, &ib->filter[1]);
+	} else {
+		ib->filter [0] = 0;
+		ib->filter [1] = 0;
+	}
 
 	/* Add addresses */
 	for (i = 0; i < dev->mc_count; i++) {
@@ -911,37 +1239,29 @@
 			}
 		}
 		crc = crc >> 26;
-		mcast_table [crc >> 4] |= 1 << (crc & 0xf);
+		if (lp->pio_buffer) {
+			u16 tmp = sbus_readw(&mcast_table[crc>>4]);
+			tmp |= 1 << (crc & 0xf);
+			sbus_writew(tmp, &mcast_table[crc>>4]);
+		} else {
+			mcast_table [crc >> 4] |= 1 << (crc & 0xf);
+		}
 	}
 }
 
-static void lance_set_multicast (struct net_device *dev)
+static void lance_set_multicast(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
-	volatile struct lance_regs *ll = lp->ll;
+	u16 mode;
 
 	if (!dev->start)
 		return;
 
-	if (dev->tbusy) {
+	if (test_and_set_bit(0, (void *)&dev->tbusy)) {
 		mod_timer(&lp->multicast_timer, jiffies + 2);
 		return;
 	}
-	/* This CANNOT be correct. Chip is running
-	   and dev->tbusy may change any moment.
-	   It is useless to set it.
-
-	   Generally, usage of dev->tbusy in this driver is completely
-	   wrong.
-
-	   I protected calls to this function
-	   with start_bh_atomic, so that set_multicast_list
-	   and hard_start_xmit are serialized now by top level. --ANK
-
-	   The same is true about a2065.
-	 */
-	set_bit (0, (void *) &dev->tbusy);
 
 	if (lp->tx_old != lp->tx_new) {
 		mod_timer(&lp->multicast_timer, jiffies + 4);
@@ -949,93 +1269,130 @@
 		return;
 	}
 
-	ll->rap = LE_CSR0;
-	ll->rdp = LE_C0_STOP;
-	lance_init_ring (dev);
+	STOP_LANCE(lp);
+	lp->init_ring(dev);
 
+	if (lp->pio_buffer)
+		mode = sbus_readw(&ib->mode);
+	else
+		mode = ib->mode;
 	if (dev->flags & IFF_PROMISC) {
-		ib->mode |= LE_MO_PROM;
+		mode |= LE_MO_PROM;
+		if (lp->pio_buffer)
+			sbus_writew(mode, &ib->mode);
+		else
+			ib->mode = mode;
 	} else {
-		ib->mode &= ~LE_MO_PROM;
-		lance_load_multicast (dev);
+		mode &= ~LE_MO_PROM;
+		if (lp->pio_buffer)
+			sbus_writew(mode, &ib->mode);
+		else
+			ib->mode = mode;
+		lance_load_multicast(dev);
 	}
-	load_csrs (lp);
-	init_restart_lance (lp);
+	load_csrs(lp);
+	init_restart_lance(lp);
 	dev->tbusy = 0;
 	mark_bh(NET_BH);
 }
 
-static int __init 
-sparc_lance_init (struct net_device *dev, struct linux_sbus_device *sdev,
-		  struct Linux_SBus_DMA *ledma,
-		  struct linux_sbus_device *lebuffer)
+static void lance_free_hwresources(struct lance_private *lp)
+{
+	if (lp->lregs)
+		sbus_iounmap(lp->lregs, LANCE_REG_SIZE);
+	if (lp->init_block != NULL) {
+		if (lp->pio_buffer) {
+			sbus_iounmap((unsigned long)lp->init_block,
+				     sizeof(struct lance_init_block));
+		} else {
+			sbus_free_consistant(lp->sdev,
+					     sizeof(struct lance_init_block),
+					     (void *)lp->init_block,
+					     lp->init_block_dvma);
+		}
+	}
+}
+
+static int __init sparc_lance_init(struct net_device *dev,
+				   struct sbus_dev *sdev,
+				   struct sbus_dma *ledma,
+				   struct sbus_dev *lebuffer)
 {
 	static unsigned version_printed = 0;
+	struct lance_private *lp = NULL;
 	int    i;
-	struct lance_private *lp;
-	volatile struct lance_regs *ll;
 
 	if (dev == NULL) {
 		dev = init_etherdev (0, sizeof (struct lance_private) + 8);
 	} else {
-		dev->priv = kmalloc (sizeof (struct lance_private) + 8,
-				     GFP_KERNEL);
+		dev->priv = kmalloc(sizeof (struct lance_private) + 8,
+				    GFP_KERNEL);
 		if (dev->priv == NULL)
 			return -ENOMEM;
 		memset(dev->priv, 0, sizeof (struct lance_private) + 8);
 	}
 	if (sparc_lance_debug && version_printed++ == 0)
-		printk (version);
+		printk (KERN_INFO "%s", version);
+
+	printk(KERN_INFO "%s: LANCE ", dev->name);
 
-	printk ("%s: LANCE ", dev->name);
-	/* Fill the dev fields */
-	dev->base_addr = (long) sdev;
+	/* Make certain the data structures used by the LANCE are aligned. */
+	dev->priv = (void *)(((unsigned long)dev->priv + 7) & ~7);
+	lp = (struct lance_private *) dev->priv;
 
 	/* Copy the IDPROM ethernet address to the device structure, later we
 	 * will copy the address in the device structure to the lance
 	 * initialization block.
 	 */
 	for (i = 0; i < 6; i++)
-		printk ("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i],
-			i == 5 ? ' ': ':');
+		printk("%2.2x%c", dev->dev_addr[i] = idprom->id_ethaddr[i],
+		       i == 5 ? ' ': ':');
 	printk("\n");
 
 	/* Get the IO region */
-	prom_apply_sbus_ranges (sdev->my_bus, &sdev->reg_addrs [0],
-				sdev->num_registers, sdev);
-	ll = sparc_alloc_io (sdev->reg_addrs [0].phys_addr, 0,
-			     sizeof (struct lance_regs), lancestr,
-			     sdev->reg_addrs[0].which_io, 0x0);
+	lp->lregs = sbus_ioremap(&sdev->resource[0], 0,
+				 LANCE_REG_SIZE, lancestr);
+	if (lp->lregs == 0UL) {
+		printk(KERN_ERR "%s: Cannot map SunLance registers.\n",
+		       dev->name);
+		goto fail;
+	}
 
-	/* Make certain the data structures used by the LANCE are aligned. */
-	dev->priv = (void *)(((unsigned long)dev->priv + 7) & ~7);
-	lp = (struct lance_private *) dev->priv;
-	lp->sbus = sdev->my_bus;
-	if (lebuffer){
-		prom_apply_sbus_ranges (lebuffer->my_bus,
-					&lebuffer->reg_addrs [0],
-					lebuffer->num_registers,
-					lebuffer);
-
-		lp->init_block = (void *)
-			sparc_alloc_io (lebuffer->reg_addrs [0].phys_addr, 0,
-				sizeof (struct lance_init_block), "lebuffer", 
-				lebuffer->reg_addrs [0].which_io, 0);
+	lp->sdev = sdev;
+	if (lebuffer) {
+		lp->init_block = (volatile struct lance_init_block *)
+			sbus_ioremap(&lebuffer->resource[0], 0,
+				     sizeof(struct lance_init_block), "lebuffer");
+		if (lp->init_block == NULL) {
+			printk(KERN_ERR "%s: Cannot map SunLance PIO buffer.\n",
+			       dev->name);
+			goto fail;
+		}
 		lp->init_block_dvma = 0;
-
 		lp->pio_buffer = 1;
+		lp->init_ring = lance_init_ring_pio;
+		lp->rx = lance_rx_pio;
+		lp->tx = lance_tx_pio;
 	} else {
-		lp->init_block = (void *)
-			sparc_dvma_malloc (sizeof (struct lance_init_block),
-					   lancedma, &lp->init_block_dvma);
+		lp->init_block = (volatile struct lance_init_block *)
+			sbus_alloc_consistant(sdev, sizeof(struct lance_init_block),
+					      &lp->init_block_dvma);
+		if (lp->init_block == NULL ||
+		    lp->init_block_dvma == 0) {
+			printk(KERN_ERR "%s: Cannot allocate consistant DMA memory.\n",
+			       dev->name);
+			goto fail;
+		}
 		lp->pio_buffer = 0;
+		lp->init_ring = lance_init_ring_dvma;
+		lp->rx = lance_rx_dvma;
+		lp->tx = lance_tx_dvma;
 	}
 	lp->busmaster_regval = prom_getintdefault(sdev->prom_node,
 						  "busmaster-regval",
 						  (LE_C3_BSWP | LE_C3_ACON |
 						   LE_C3_BCON));
 
-	lp->ll = ll;
 	lp->name = lancestr;
 	lp->ledma = ledma;
 
@@ -1043,24 +1400,25 @@
 	if (lp->ledma) {
 		char prop[6];
 		unsigned int sbmask;
+		u32 csr;
 
 		/* Find burst-size property for ledma */
-		lp->burst_sizes = prom_getintdefault(ledma->SBus_dev->prom_node,
+		lp->burst_sizes = prom_getintdefault(ledma->sdev->prom_node,
 						     "burst-sizes", 0);
 
 		/* ledma may be capable of fast bursts, but sbus may not. */
-		sbmask = prom_getintdefault(ledma->SBus_dev->my_bus->prom_node,
+		sbmask = prom_getintdefault(ledma->sdev->bus->prom_node,
 					    "burst-sizes", DMA_BURSTBITS);
 		lp->burst_sizes &= sbmask;
 
 		/* Get the cable-selection property */
 		memset(prop, 0, sizeof(prop));
-		prom_getstring(ledma->SBus_dev->prom_node, "cable-selection",
+		prom_getstring(ledma->sdev->prom_node, "cable-selection",
 			       prop, sizeof(prop));
 		if (prop[0] == 0) {
 			int topnd, nd;
 
-			printk("%s: using auto-carrier-detection.\n",
+			printk(KERN_INFO "%s: using auto-carrier-detection.\n",
 			       dev->name);
 
 			/* Is this found at /options .attributes in all
@@ -1080,9 +1438,9 @@
 				       sizeof(prop));
 
 			if (strcmp(prop, "true")) {
-				printk("%s: warning: overriding option "
+				printk(KERN_NOTICE "%s: warning: overriding option "
 				       "'tpe-link-test?'\n", dev->name);
-				printk("%s: warning: mail any problems "
+				printk(KERN_NOTICE "%s: warning: mail any problems "
 				       "to ecd@skynet.be\n", dev->name);
 				set_auxio(AUXIO_LINK_TEST, 0);
 			}
@@ -1097,17 +1455,21 @@
 			lp->tpe = 1;
 		}
 
+		lp->dregs = ledma->regs;
+
 		/* Reset ledma */
-		lp->ledma->regs->cond_reg |= DMA_RST_ENET;
-		udelay (200);
-		lp->ledma->regs->cond_reg &= ~DMA_RST_ENET;
-	}
+		csr = sbus_readl(lp->dregs + DMA_CSR);
+		sbus_writel(csr | DMA_RST_ENET, lp->dregs + DMA_CSR);
+		udelay(200);
+		sbus_writel(csr & ~DMA_RST_ENET, lp->dregs + DMA_CSR);
+	} else
+		lp->dregs = 0;
 
 	/* This should never happen. */
 	if ((unsigned long)(lp->init_block->brx_ring) & 0x07) {
-		printk("%s: ERROR: Rx and Tx rings not on even boundary.\n",
+		printk(KERN_ERR "%s: ERROR: Rx and Tx rings not on even boundary.\n",
 		       dev->name);
-		return ENODEV;
+		goto fail;
 	}
 
 	lp->dev = dev;
@@ -1120,7 +1482,7 @@
 	dev->irq = sdev->irqs[0];
 
 	dev->dma = 0;
-	ether_setup (dev);
+	ether_setup(dev);
 
 	/* We cannot sleep if the chip is busy during a
 	 * multicast list update event, because such events
@@ -1138,18 +1500,23 @@
 	root_lance_dev = lp;
 #endif
 	return 0;
+
+fail:
+	if (lp != NULL)
+		lance_free_hwresources(lp);
+	return ENODEV;
 }
 
 /* On 4m, find the associated dma for the lance chip */
-static inline struct Linux_SBus_DMA *
-find_ledma (struct linux_sbus_device *dev)
+static inline struct sbus_dma *find_ledma(struct sbus_dev *sdev)
 {
-	struct Linux_SBus_DMA *p;
+	struct sbus_dma *p;
 
-	for_each_dvma(p)
-		if (p->SBus_dev == dev)
+	for_each_dvma(p) {
+		if (p->sdev == sdev)
 			return p;
-	return 0;
+	}
+	return NULL;
 }
 
 #ifdef CONFIG_SUN4
@@ -1159,16 +1526,16 @@
 /* Find all the lance cards on the system and initialize them */
 int __init sparc_lance_probe(void)
 {
-	static struct linux_sbus_device sdev;
+	static struct sbus_dev sdev;
 	static int called = 0;
 
-	if(called)
+	if (called)
 		return ENODEV;
 	called++;
 
 	if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) ||
 	    (idprom->id_machtype == (SM_SUN4|SM_4_470))) {
-		memset (&sdev, 0, sizeof(sdev));
+		memset(&sdev, 0, sizeof(sdev));
 		sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr;
 		sdev.irqs[0] = 6;
 		return sparc_lance_init(NULL, &sdev, 0, 0);
@@ -1179,37 +1546,38 @@
 #else /* !CONFIG_SUN4 */
 
 /* Find all the lance cards on the system and initialize them */
-int __init sparc_lance_probe (void)
+int __init sparc_lance_probe(void)
 {
-	struct linux_sbus *bus;
-	struct linux_sbus_device *sdev = 0;
+	struct sbus_bus *bus;
+	struct sbus_dev *sdev = 0;
 	struct net_device *dev = NULL;
-	struct Linux_SBus_DMA *ledma = 0;
+	struct sbus_dma *ledma = 0;
 	static int called = 0;
 	int cards = 0, v;
 
-	if(called)
+	if (called)
 		return ENODEV;
 	called++;
 
 	for_each_sbus (bus) {
 		for_each_sbusdev (sdev, bus) {
-			if (cards) dev = NULL;
-			if (strcmp (sdev->prom_name, "le") == 0) {
+			if (cards)
+				dev = NULL;
+			if (strcmp(sdev->prom_name, "le") == 0) {
 				cards++;
 				if ((v = sparc_lance_init(dev, sdev, 0, 0)))
 					return v;
 				continue;
 			}
-			if (strcmp (sdev->prom_name, "ledma") == 0) {
+			if (strcmp(sdev->prom_name, "ledma") == 0) {
 				cards++;
-				ledma = find_ledma (sdev);
+				ledma = find_ledma(sdev);
 				if ((v = sparc_lance_init(dev, sdev->child,
 							  ledma, 0)))
 					return v;
 				continue;
 			}
-			if (strcmp (sdev->prom_name, "lebuffer") == 0){
+			if (strcmp(sdev->prom_name, "lebuffer") == 0){
 				cards++;
 				if ((v = sparc_lance_init(dev, sdev->child,
 							  0, sdev)))
@@ -1242,6 +1610,7 @@
 		lp = root_lance_dev->next_module;
 
 		unregister_netdev(root_lance_dev->dev);
+		lance_free_hwresources(root_lance_dev);
 		kfree(root_lance_dev->dev);
 		root_lance_dev = lp;
 	}
diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunqe.c linux/drivers/net/sunqe.c
--- v2.3.34/linux/drivers/net/sunqe.c	Thu Nov 11 20:11:42 1999
+++ linux/drivers/net/sunqe.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,5 @@
-/* sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver.
+/* $Id: sunqe.c,v 1.40 1999/12/15 14:08:13 davem Exp $
+ * sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver.
  *          Once again I am out to prove that every ethernet
  *          controller out there can be most efficiently programmed
  *          if you make it look like a LANCE.
@@ -7,7 +8,7 @@
  */
 
 static char *version =
-        "sunqe.c:v2.0 9/9/99 David S. Miller (davem@redhat.com)\n";
+        "sunqe.c:v2.9 9/11/99 David S. Miller (davem@redhat.com)\n";
 
 #include <linux/module.h>
 
@@ -53,21 +54,22 @@
 
 #define QEC_RESET_TRIES 200
 
-static inline int qec_global_reset(struct qe_globreg *gregs)
+static inline int qec_global_reset(unsigned long gregs)
 {
 	int tries = QEC_RESET_TRIES;
 
-	gregs->ctrl = GLOB_CTRL_RESET;
-	while(--tries) {
-		if(gregs->ctrl & GLOB_CTRL_RESET) {
+	sbus_writel(GLOB_CTRL_RESET, gregs + GLOB_CTRL);
+	while (--tries) {
+		u32 tmp = sbus_readl(gregs + GLOB_CTRL);
+		if (tmp & GLOB_CTRL_RESET) {
 			udelay(20);
 			continue;
 		}
 		break;
 	}
-	if(tries)
+	if (tries)
 		return 0;
-	printk("QuadEther: AIEEE cannot reset the QEC!\n");
+	printk(KERN_ERR "QuadEther: AIEEE cannot reset the QEC!\n");
 	return -1;
 }
 
@@ -76,36 +78,38 @@
 
 static inline int qe_stop(struct sunqe *qep)
 {
-	struct qe_creg *cregs = qep->qcregs;
-	struct qe_mregs *mregs = qep->mregs;
+	unsigned long cregs = qep->qcregs;
+	unsigned long mregs = qep->mregs;
 	int tries;
 
 	/* Reset the MACE, then the QEC channel. */
-	mregs->bconfig = MREGS_BCONFIG_RESET;
+	sbus_writeb(MREGS_BCONFIG_RESET, mregs + MREGS_BCONFIG);
 	tries = MACE_RESET_RETRIES;
-	while(--tries) {
-		if(mregs->bconfig & MREGS_BCONFIG_RESET) {
+	while (--tries) {
+		u8 tmp = sbus_readb(mregs + MREGS_BCONFIG);
+		if (tmp & MREGS_BCONFIG_RESET) {
 			udelay(20);
 			continue;
 		}
 		break;
 	}
-	if(!tries) {
-		printk("QuadEther: AIEEE cannot reset the MACE!\n");
+	if (!tries) {
+		printk(KERN_ERR "QuadEther: AIEEE cannot reset the MACE!\n");
 		return -1;
 	}
 
-	cregs->ctrl = CREG_CTRL_RESET;
+	sbus_writel(CREG_CTRL_RESET, cregs + CREG_CTRL);
 	tries = QE_RESET_RETRIES;
-	while(--tries) {
-		if(cregs->ctrl & CREG_CTRL_RESET) {
+	while (--tries) {
+		u32 tmp = sbus_readl(cregs + CREG_CTRL);
+		if (tmp & CREG_CTRL_RESET) {
 			udelay(20);
 			continue;
 		}
 		break;
 	}
-	if(!tries) {
-		printk("QuadEther: Cannot reset QE channel!\n");
+	if (!tries) {
+		printk(KERN_ERR "QuadEther: Cannot reset QE channel!\n");
 		return -1;
 	}
 	return 0;
@@ -121,7 +125,7 @@
 	qep->rx_new = qep->rx_old = qep->tx_new = qep->tx_old = 0;
 	memset(qb, 0, sizeof(struct qe_init_block));
 	memset(qbufs, 0, sizeof(struct sunqe_buffers));
-	for(i = 0; i < RX_RING_SIZE; i++) {
+	for (i = 0; i < RX_RING_SIZE; i++) {
 		qb->qe_rxd[i].rx_addr = qbufs_dvma + qebuf_offset(rx_buf, i);
 		qb->qe_rxd[i].rx_flags =
 			(RXD_OWN | ((RXD_PKT_SZ) & RXD_LENGTH));
@@ -131,99 +135,110 @@
 static int qe_init(struct sunqe *qep, int from_irq)
 {
 	struct sunqec *qecp = qep->parent;
-	struct qe_creg *cregs = qep->qcregs;
-	struct qe_mregs *mregs = qep->mregs;
-	struct qe_globreg *gregs = qecp->gregs;
+	unsigned long cregs = qep->qcregs;
+	unsigned long mregs = qep->mregs;
+	unsigned long gregs = qecp->gregs;
 	unsigned char *e = &qep->dev->dev_addr[0];
-	volatile unsigned char garbage;
+	u32 tmp;
 	int i;
 
 	/* Shut it up. */
-	if(qe_stop(qep))
+	if (qe_stop(qep))
 		return -EAGAIN;
 
 	/* Setup initial rx/tx init block pointers. */
-	cregs->rxds = qep->qblock_dvma + qib_offset(qe_rxd, 0);
-	cregs->txds = qep->qblock_dvma + qib_offset(qe_txd, 0);
+	sbus_writel(qep->qblock_dvma + qib_offset(qe_rxd, 0), cregs + CREG_RXDS);
+	sbus_writel(qep->qblock_dvma + qib_offset(qe_txd, 0), cregs + CREG_TXDS);
 
 	/* Enable/mask the various irq's. */
-	cregs->rimask = 0;
-	cregs->timask = 1;
+	sbus_writel(0, cregs + CREG_RIMASK);
+	sbus_writel(1, cregs + CREG_TIMASK);
 
-	cregs->qmask = 0;
-	cregs->mmask = CREG_MMASK_RXCOLL;
+	sbus_writel(0, cregs + CREG_QMASK);
+	sbus_writel(CREG_MMASK_RXCOLL, cregs + CREG_MMASK);
 
 	/* Setup the FIFO pointers into QEC local memory. */
-	cregs->rxwbufptr = cregs->rxrbufptr = qep->channel * gregs->msize;
-	cregs->txwbufptr = cregs->txrbufptr = cregs->rxrbufptr + gregs->rsize;
+	tmp = qep->channel * sbus_readl(gregs + GLOB_MSIZE);
+	sbus_writel(tmp, cregs + CREG_RXRBUFPTR);
+	sbus_writel(tmp, cregs + CREG_RXWBUFPTR);
+
+	tmp = sbus_readl(cregs + CREG_RXRBUFPTR) +
+		sbus_readl(gregs + GLOB_RSIZE);
+	sbus_writel(tmp, cregs + CREG_TXRBUFPTR);
+	sbus_writel(tmp, cregs + CREG_TXWBUFPTR);
 
 	/* Clear the channel collision counter. */
-	cregs->ccnt = 0;
+	sbus_writel(0, cregs + CREG_CCNT);
 
 	/* For 10baseT, inter frame space nor throttle seems to be necessary. */
-	cregs->pipg = 0;
+	sbus_writel(0, cregs + CREG_PIPG);
 
 	/* Now dork with the AMD MACE. */
-	mregs->phyconfig = MREGS_PHYCONFIG_AUTO;
-	mregs->txfcntl = MREGS_TXFCNTL_AUTOPAD; /* Save us some tx work. */
-	mregs->rxfcntl = 0;
+	sbus_writeb(MREGS_PHYCONFIG_AUTO, mregs + MREGS_PHYCONFIG);
+	sbus_writeb(MREGS_TXFCNTL_AUTOPAD, mregs + MREGS_TXFCNTL);
+	sbus_writeb(0, mregs + MREGS_RXFCNTL);
 
 	/* The QEC dma's the rx'd packets from local memory out to main memory,
 	 * and therefore it interrupts when the packet reception is "complete".
 	 * So don't listen for the MACE talking about it.
 	 */
-	mregs->imask = (MREGS_IMASK_COLL | MREGS_IMASK_RXIRQ);
-
-	mregs->bconfig = (MREGS_BCONFIG_BSWAP | MREGS_BCONFIG_64TS);
-	mregs->fconfig = (MREGS_FCONFIG_TXF16 | MREGS_FCONFIG_RXF32 |
-			  MREGS_FCONFIG_RFWU | MREGS_FCONFIG_TFWU);
+	sbus_writeb(MREGS_IMASK_COLL | MREGS_IMASK_RXIRQ, mregs + MREGS_IMASK);
+	sbus_writeb(MREGS_BCONFIG_BSWAP | MREGS_BCONFIG_64TS, mregs + MREGS_BCONFIG);
+	sbus_writeb((MREGS_FCONFIG_TXF16 | MREGS_FCONFIG_RXF32 |
+		     MREGS_FCONFIG_RFWU | MREGS_FCONFIG_TFWU),
+		    mregs + MREGS_FCONFIG);
 
 	/* Only usable interface on QuadEther is twisted pair. */
-	mregs->plsconfig = (MREGS_PLSCONFIG_TP);
+	sbus_writeb(MREGS_PLSCONFIG_TP, mregs + MREGS_PLSCONFIG);
 
 	/* Tell MACE we are changing the ether address. */
-	mregs->iaconfig = (MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_PARESET);
-	while ((mregs->iaconfig & MREGS_IACONFIG_ACHNGE) != 0)
+	sbus_writeb(MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_PARESET,
+		    mregs + MREGS_IACONFIG);
+	while ((sbus_readb(mregs + MREGS_IACONFIG) & MREGS_IACONFIG_ACHNGE) != 0)
 		barrier();
-	mregs->ethaddr = e[0];
-	mregs->ethaddr = e[1];
-	mregs->ethaddr = e[2];
-	mregs->ethaddr = e[3];
-	mregs->ethaddr = e[4];
-	mregs->ethaddr = e[5];
+	sbus_writeb(e[0], mregs + MREGS_ETHADDR);
+	sbus_writeb(e[1], mregs + MREGS_ETHADDR);
+	sbus_writeb(e[2], mregs + MREGS_ETHADDR);
+	sbus_writeb(e[3], mregs + MREGS_ETHADDR);
+	sbus_writeb(e[4], mregs + MREGS_ETHADDR);
+	sbus_writeb(e[5], mregs + MREGS_ETHADDR);
 
 	/* Clear out the address filter. */
-	mregs->iaconfig = (MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET);
-	while ((mregs->iaconfig & MREGS_IACONFIG_ACHNGE) != 0)
+	sbus_writeb(MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET,
+		    mregs + MREGS_IACONFIG);
+	while ((sbus_readb(mregs + MREGS_IACONFIG) & MREGS_IACONFIG_ACHNGE) != 0)
 		barrier();
-	for(i = 0; i < 8; i++)
-		mregs->filter = 0;
+	for (i = 0; i < 8; i++)
+		sbus_writeb(0, mregs + MREGS_FILTER);
 
 	/* Address changes are now complete. */
-	mregs->iaconfig = 0;
+	sbus_writeb(0, mregs + MREGS_IACONFIG);
 
 	qe_init_rings(qep);
 
 	/* Wait a little bit for the link to come up... */
 	mdelay(5);
-	if(!(mregs->phyconfig & MREGS_PHYCONFIG_LTESTDIS)) {
+	if (!(sbus_readb(mregs + MREGS_PHYCONFIG) & MREGS_PHYCONFIG_LTESTDIS)) {
 		int tries = 50;
 
 		while (tries--) {
+			u8 tmp;
+
 			mdelay(5);
 			barrier();
-			if((mregs->phyconfig & MREGS_PHYCONFIG_LSTAT) != 0)
+			tmp = sbus_readb(mregs + MREGS_PHYCONFIG);
+			if ((tmp & MREGS_PHYCONFIG_LSTAT) != 0)
 				break;
 		}
 		if (tries == 0)
-			printk("%s: Warning, link state is down.\n", qep->dev->name);
+			printk(KERN_NOTICE "%s: Warning, link state is down.\n", qep->dev->name);
 	}
 
 	/* Missed packet counter is cleared on a read. */
-	garbage = mregs->mpcnt;
+	sbus_readb(mregs + MREGS_MPCNT);
 
 	/* Reload multicast information, this will enable the receiver
-	 * and transmitter.  But set the base mconfig value right now.
+	 * and transmitter.
 	 */
 	qe_set_multicast(qep->dev);
 
@@ -234,152 +249,152 @@
 /* Grrr, certain error conditions completely lock up the AMD MACE,
  * so when we get these we _must_ reset the chip.
  */
-static int qe_is_bolixed(struct sunqe *qep, unsigned int qe_status)
+static int qe_is_bolixed(struct sunqe *qep, u32 qe_status)
 {
 	struct net_device *dev = qep->dev;
 	int mace_hwbug_workaround = 0;
 
-	if(qe_status & CREG_STAT_EDEFER) {
-		printk("%s: Excessive transmit defers.\n", dev->name);
+	if (qe_status & CREG_STAT_EDEFER) {
+		printk(KERN_ERR "%s: Excessive transmit defers.\n", dev->name);
 		qep->net_stats.tx_errors++;
 	}
 
-	if(qe_status & CREG_STAT_CLOSS) {
-		printk("%s: Carrier lost, link down?\n", dev->name);
+	if (qe_status & CREG_STAT_CLOSS) {
+		printk(KERN_ERR "%s: Carrier lost, link down?\n", dev->name);
 		qep->net_stats.tx_errors++;
 		qep->net_stats.tx_carrier_errors++;
 	}
 
-	if(qe_status & CREG_STAT_ERETRIES) {
-		printk("%s: Excessive transmit retries (more than 16).\n", dev->name);
+	if (qe_status & CREG_STAT_ERETRIES) {
+		printk(KERN_ERR "%s: Excessive transmit retries (more than 16).\n", dev->name);
 		qep->net_stats.tx_errors++;
 		mace_hwbug_workaround = 1;
 	}
 
-	if(qe_status & CREG_STAT_LCOLL) {
-		printk("%s: Late transmit collision.\n", dev->name);
+	if (qe_status & CREG_STAT_LCOLL) {
+		printk(KERN_ERR "%s: Late transmit collision.\n", dev->name);
 		qep->net_stats.tx_errors++;
 		qep->net_stats.collisions++;
 		mace_hwbug_workaround = 1;
 	}
 
-	if(qe_status & CREG_STAT_FUFLOW) {
-		printk("%s: Transmit fifo underflow, driver bug.\n", dev->name);
+	if (qe_status & CREG_STAT_FUFLOW) {
+		printk(KERN_ERR "%s: Transmit fifo underflow, driver bug.\n", dev->name);
 		qep->net_stats.tx_errors++;
 		mace_hwbug_workaround = 1;
 	}
 
-	if(qe_status & CREG_STAT_JERROR) {
-		printk("%s: Jabber error.\n", dev->name);
+	if (qe_status & CREG_STAT_JERROR) {
+		printk(KERN_ERR "%s: Jabber error.\n", dev->name);
 	}
 
-	if(qe_status & CREG_STAT_BERROR) {
-		printk("%s: Babble error.\n", dev->name);
+	if (qe_status & CREG_STAT_BERROR) {
+		printk(KERN_ERR "%s: Babble error.\n", dev->name);
 	}
 
-	if(qe_status & CREG_STAT_CCOFLOW) {
+	if (qe_status & CREG_STAT_CCOFLOW) {
 		qep->net_stats.tx_errors += 256;
 		qep->net_stats.collisions += 256;
 	}
 
-	if(qe_status & CREG_STAT_TXDERROR) {
-		printk("%s: Transmit descriptor is bogus, driver bug.\n", dev->name);
+	if (qe_status & CREG_STAT_TXDERROR) {
+		printk(KERN_ERR "%s: Transmit descriptor is bogus, driver bug.\n", dev->name);
 		qep->net_stats.tx_errors++;
 		qep->net_stats.tx_aborted_errors++;
 		mace_hwbug_workaround = 1;
 	}
 
-	if(qe_status & CREG_STAT_TXLERR) {
-		printk("%s: Transmit late error.\n", dev->name);
+	if (qe_status & CREG_STAT_TXLERR) {
+		printk(KERN_ERR "%s: Transmit late error.\n", dev->name);
 		qep->net_stats.tx_errors++;
 		mace_hwbug_workaround = 1;
 	}
 
-	if(qe_status & CREG_STAT_TXPERR) {
-		printk("%s: Transmit DMA parity error.\n", dev->name);
+	if (qe_status & CREG_STAT_TXPERR) {
+		printk(KERN_ERR "%s: Transmit DMA parity error.\n", dev->name);
 		qep->net_stats.tx_errors++;
 		qep->net_stats.tx_aborted_errors++;
 		mace_hwbug_workaround = 1;
 	}
 
-	if(qe_status & CREG_STAT_TXSERR) {
-		printk("%s: Transmit DMA sbus error ack.\n", dev->name);
+	if (qe_status & CREG_STAT_TXSERR) {
+		printk(KERN_ERR "%s: Transmit DMA sbus error ack.\n", dev->name);
 		qep->net_stats.tx_errors++;
 		qep->net_stats.tx_aborted_errors++;
 		mace_hwbug_workaround = 1;
 	}
 
-	if(qe_status & CREG_STAT_RCCOFLOW) {
+	if (qe_status & CREG_STAT_RCCOFLOW) {
 		qep->net_stats.rx_errors += 256;
 		qep->net_stats.collisions += 256;
 	}
 
-	if(qe_status & CREG_STAT_RUOFLOW) {
+	if (qe_status & CREG_STAT_RUOFLOW) {
 		qep->net_stats.rx_errors += 256;
 		qep->net_stats.rx_over_errors += 256;
 	}
 
-	if(qe_status & CREG_STAT_MCOFLOW) {
+	if (qe_status & CREG_STAT_MCOFLOW) {
 		qep->net_stats.rx_errors += 256;
 		qep->net_stats.rx_missed_errors += 256;
 	}
 
-	if(qe_status & CREG_STAT_RXFOFLOW) {
-		printk("%s: Receive fifo overflow.\n", dev->name);
+	if (qe_status & CREG_STAT_RXFOFLOW) {
+		printk(KERN_ERR "%s: Receive fifo overflow.\n", dev->name);
 		qep->net_stats.rx_errors++;
 		qep->net_stats.rx_over_errors++;
 	}
 
-	if(qe_status & CREG_STAT_RLCOLL) {
-		printk("%s: Late receive collision.\n", dev->name);
+	if (qe_status & CREG_STAT_RLCOLL) {
+		printk(KERN_ERR "%s: Late receive collision.\n", dev->name);
 		qep->net_stats.rx_errors++;
 		qep->net_stats.collisions++;
 	}
 
-	if(qe_status & CREG_STAT_FCOFLOW) {
+	if (qe_status & CREG_STAT_FCOFLOW) {
 		qep->net_stats.rx_errors += 256;
 		qep->net_stats.rx_frame_errors += 256;
 	}
 
-	if(qe_status & CREG_STAT_CECOFLOW) {
+	if (qe_status & CREG_STAT_CECOFLOW) {
 		qep->net_stats.rx_errors += 256;
 		qep->net_stats.rx_crc_errors += 256;
 	}
 
-	if(qe_status & CREG_STAT_RXDROP) {
-		printk("%s: Receive packet dropped.\n", dev->name);
+	if (qe_status & CREG_STAT_RXDROP) {
+		printk(KERN_ERR "%s: Receive packet dropped.\n", dev->name);
 		qep->net_stats.rx_errors++;
 		qep->net_stats.rx_dropped++;
 		qep->net_stats.rx_missed_errors++;
 	}
 
-	if(qe_status & CREG_STAT_RXSMALL) {
-		printk("%s: Receive buffer too small, driver bug.\n", dev->name);
+	if (qe_status & CREG_STAT_RXSMALL) {
+		printk(KERN_ERR "%s: Receive buffer too small, driver bug.\n", dev->name);
 		qep->net_stats.rx_errors++;
 		qep->net_stats.rx_length_errors++;
 	}
 
-	if(qe_status & CREG_STAT_RXLERR) {
-		printk("%s: Receive late error.\n", dev->name);
+	if (qe_status & CREG_STAT_RXLERR) {
+		printk(KERN_ERR "%s: Receive late error.\n", dev->name);
 		qep->net_stats.rx_errors++;
 		mace_hwbug_workaround = 1;
 	}
 
-	if(qe_status & CREG_STAT_RXPERR) {
-		printk("%s: Receive DMA parity error.\n", dev->name);
+	if (qe_status & CREG_STAT_RXPERR) {
+		printk(KERN_ERR "%s: Receive DMA parity error.\n", dev->name);
 		qep->net_stats.rx_errors++;
 		qep->net_stats.rx_missed_errors++;
 		mace_hwbug_workaround = 1;
 	}
 
-	if(qe_status & CREG_STAT_RXSERR) {
-		printk("%s: Receive DMA sbus error ack.\n", dev->name);
+	if (qe_status & CREG_STAT_RXSERR) {
+		printk(KERN_ERR "%s: Receive DMA sbus error ack.\n", dev->name);
 		qep->net_stats.rx_errors++;
 		qep->net_stats.rx_missed_errors++;
 		mace_hwbug_workaround = 1;
 	}
 
-	if(mace_hwbug_workaround)
+	if (mace_hwbug_workaround)
 		qe_init(qep, 1);
 	return mace_hwbug_workaround;
 }
@@ -394,10 +409,10 @@
 	struct sunqe_buffers *qbufs = qep->buffers;
 	__u32 qbufs_dvma = qep->buffers_dvma;
 	int elem = qep->rx_new, drops = 0;
-	unsigned int flags;
+	u32 flags;
 
 	this = &rxbase[elem];
-	while(!((flags = this->rx_flags) & RXD_OWN)) {
+	while (!((flags = this->rx_flags) & RXD_OWN)) {
 		struct sk_buff *skb;
 		unsigned char *this_qbuf =
 			&qbufs->rx_buf[elem & (RX_RING_SIZE - 1)][0];
@@ -408,25 +423,25 @@
 		int len = (flags & RXD_LENGTH) - 4;  /* QE adds ether FCS size to len */
 
 		/* Check for errors. */
-		if(len < ETH_ZLEN) {
+		if (len < ETH_ZLEN) {
 			qep->net_stats.rx_errors++;
 			qep->net_stats.rx_length_errors++;
 			qep->net_stats.rx_dropped++;
 		} else {
 			skb = dev_alloc_skb(len + 2);
-			if(skb == 0) {
+			if (skb == NULL) {
 				drops++;
 				qep->net_stats.rx_dropped++;
 			} else {
 				skb->dev = qep->dev;
 				skb_reserve(skb, 2);
 				skb_put(skb, len);
-				eth_copy_and_sum(skb, (unsigned char *)this_qbuf,
+				eth_copy_and_sum(skb, (unsigned char *) this_qbuf,
 						 len, 0);
 				skb->protocol = eth_type_trans(skb, qep->dev);
 				netif_rx(skb);
 				qep->net_stats.rx_packets++;
-				qep->net_stats.rx_bytes+=len;
+				qep->net_stats.rx_bytes += len;
 			}
 		}
 		end_rxd->rx_addr = this_qbuf_dvma;
@@ -436,8 +451,8 @@
 		this = &rxbase[elem];
 	}
 	qep->rx_new = elem;
-	if(drops)
-		printk("%s: Memory squeeze, deferring packet.\n", qep->dev->name);
+	if (drops)
+		printk(KERN_NOTICE "%s: Memory squeeze, deferring packet.\n", qep->dev->name);
 }
 
 /* Interrupts for all QE's get filtered out via the QEC master controller,
@@ -447,25 +462,25 @@
 static void qec_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct sunqec *qecp = (struct sunqec *) dev_id;
-	unsigned int qec_status;
+	u32 qec_status;
 	int channel = 0;
 
 	/* Latch the status now. */
-	qec_status = qecp->gregs->stat;
-	while(channel < 4) {
-		if(qec_status & 0xf) {
+	qec_status = sbus_readl(qecp->gregs + GLOB_STAT);
+	while (channel < 4) {
+		if (qec_status & 0xf) {
 			struct sunqe *qep = qecp->qes[channel];
 			struct net_device *dev = qep->dev;
-			unsigned int qe_status;
+			u32 qe_status;
 
 			dev->interrupt = 1;
 
-			qe_status = qep->qcregs->stat;
-			if(qe_status & CREG_STAT_ERRORS)
-				if(qe_is_bolixed(qep, qe_status))
+			qe_status = sbus_readl(qep->qcregs + CREG_STAT);
+			if (qe_status & CREG_STAT_ERRORS) {
+				if (qe_is_bolixed(qep, qe_status))
 					goto next;
-
-			if(qe_status & CREG_STAT_RXIRQ)
+			}
+			if (qe_status & CREG_STAT_RXIRQ)
 				qe_rx(qep);
 	next:
 			dev->interrupt = 0;
@@ -484,7 +499,7 @@
 			MREGS_MCONFIG_RXENAB |
 			MREGS_MCONFIG_MBAENAB);
 	res = qe_init(qep, 0);
-	if(!res)
+	if (!res)
 		MOD_INC_USE_COUNT;
 
 	return res;
@@ -506,18 +521,16 @@
 	struct net_device *dev = qep->dev;
 	int elem = qep->tx_old;
 
-	while(elem != qep->tx_new) {
-		unsigned int flags = txbase[elem].tx_flags;
+	while (elem != qep->tx_new) {
+		u32 flags = txbase[elem].tx_flags;
 
 		if (flags & TXD_OWN)
 			break;
-		qep->net_stats.tx_packets++;
-		qep->net_stats.tx_bytes+=(flags & TXD_LENGTH);
 		elem = NEXT_TX(elem);
 	}
 	qep->tx_old = elem;
 
-	if(dev->tbusy && (TX_BUFFS_AVAIL(qep) > 0)) {
+	if (dev->tbusy && (TX_BUFFS_AVAIL(qep) > 0)) {
 		dev->tbusy = 0;
 		mark_bh(NET_BH);
 	}
@@ -534,11 +547,11 @@
 
 	qe_tx_reclaim(qep);
 
-	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
+	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
 		long tickssofar = jiffies - dev->trans_start;
 
 		if (tickssofar >= 40) {
-			printk("%s: transmit timed out, resetting\n", dev->name);
+			printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
 			qe_init(qep, 1);
 			dev->tbusy = 0;
 			dev->trans_start = jiffies;
@@ -546,9 +559,6 @@
 		return 1;
 	}
 
-	if(!TX_BUFFS_AVAIL(qep))
-		return 1;
-
 	len = skb->len;
 	entry = qep->tx_new;
 
@@ -568,11 +578,14 @@
 
 	/* Get it going. */
 	dev->trans_start = jiffies;
-	qep->qcregs->ctrl = CREG_CTRL_TWAKEUP;
+	sbus_writel(CREG_CTRL_TWAKEUP, qep->qcregs + CREG_CTRL);
+
+	qep->net_stats.tx_packets++;
+	qep->net_stats.tx_bytes += len;
 
 	dev_kfree_skb(skb);
 
-	if(TX_BUFFS_AVAIL(qep))
+	if (TX_BUFFS_AVAIL(qep))
 		dev->tbusy = 0;
 
 	return 0;
@@ -592,7 +605,7 @@
 {
 	struct sunqe *qep = (struct sunqe *) dev->priv;
 	struct dev_mc_list *dmi = dev->mc_list;
-	unsigned char new_mconfig = qep->mconfig;
+	u8 new_mconfig = qep->mconfig;
 	char *addrs;
 	int i, j, bit, byte;
 	u32 crc, poly = CRC_POLYNOMIAL_LE;
@@ -600,37 +613,38 @@
 	/* Lock out others. */
 	set_bit(0, (void *) &dev->tbusy);
 
-	if((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
-		qep->mregs->iaconfig = MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET;
-		while ((qep->mregs->iaconfig & MREGS_IACONFIG_ACHNGE) != 0)
+	if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 64)) {
+		sbus_writeb(MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET,
+			    qep->mregs + MREGS_IACONFIG);
+		while ((sbus_readb(qep->mregs + MREGS_IACONFIG) & MREGS_IACONFIG_ACHNGE) != 0)
 			barrier();
-		for(i = 0; i < 8; i++)
-			qep->mregs->filter = 0xff;
-		qep->mregs->iaconfig = 0;
-	} else if(dev->flags & IFF_PROMISC) {
+		for (i = 0; i < 8; i++)
+			sbus_writeb(0xff, qep->mregs + MREGS_FILTER);
+		sbus_writeb(0, qep->mregs + MREGS_IACONFIG);
+	} else if (dev->flags & IFF_PROMISC) {
 		new_mconfig |= MREGS_MCONFIG_PROMISC;
 	} else {
 		u16 hash_table[4];
-		unsigned char *hbytes = (unsigned char *) &hash_table[0];
+		u8 *hbytes = (unsigned char *) &hash_table[0];
 
-		for(i = 0; i < 4; i++)
+		for (i = 0; i < 4; i++)
 			hash_table[i] = 0;
 
-		for(i = 0; i < dev->mc_count; i++) {
+		for (i = 0; i < dev->mc_count; i++) {
 			addrs = dmi->dmi_addr;
 			dmi = dmi->next;
 
-			if(!(*addrs & 1))
+			if (!(*addrs & 1))
 				continue;
 
 			crc = 0xffffffffU;
-			for(byte = 0; byte < 6; byte++) {
-				for(bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
+			for (byte = 0; byte < 6; byte++) {
+				for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
 					int test;
 
 					test = ((bit ^ crc) & 0x01);
 					crc >>= 1;
-					if(test)
+					if (test)
 						crc = crc ^ poly;
 				}
 			}
@@ -638,12 +652,15 @@
 			hash_table[crc >> 4] |= 1 << (crc & 0xf);
 		}
 		/* Program the qe with the new filter value. */
-		qep->mregs->iaconfig = MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET;
-		while ((qep->mregs->iaconfig & MREGS_IACONFIG_ACHNGE) != 0)
+		sbus_writeb(MREGS_IACONFIG_ACHNGE | MREGS_IACONFIG_LARESET,
+			    qep->mregs + MREGS_IACONFIG);
+		while ((sbus_readb(qep->mregs + MREGS_IACONFIG) & MREGS_IACONFIG_ACHNGE) != 0)
 			barrier();
-		for(i = 0; i < 8; i++)
-			qep->mregs->filter = *hbytes++;
-		qep->mregs->iaconfig = 0;
+		for (i = 0; i < 8; i++) {
+			u8 tmp = *hbytes++;
+			sbus_writeb(tmp, qep->mregs + MREGS_FILTER);
+		}
+		sbus_writeb(0, qep->mregs + MREGS_IACONFIG);
 	}
 
 	/* Any change of the logical address filter, the physical address,
@@ -653,82 +670,80 @@
 	 * me a day or two to find this bug.
 	 */
 	qep->mconfig = new_mconfig;
-	qep->mregs->mconfig = qep->mconfig;
+	sbus_writeb(qep->mconfig, qep->mregs + MREGS_MCONFIG);
 
 	/* Let us get going again. */
 	dev->tbusy = 0;
 }
 
 /* This is only called once at boot time for each card probed. */
-static inline void qec_init_once(struct sunqec *qecp, struct linux_sbus_device *qsdev)
+static inline void qec_init_once(struct sunqec *qecp, struct sbus_dev *qsdev)
 {
-	unsigned char bsizes = qecp->qec_bursts;
+	u8 bsizes = qecp->qec_bursts;
 
-#ifdef __sparc_v9__
-	if (bsizes & DMA_BURST64) {
-		qecp->gregs->ctrl = GLOB_CTRL_B64;
-	} else
-#endif
-	if(bsizes & DMA_BURST32) {
-		qecp->gregs->ctrl = GLOB_CTRL_B32;
+	if (sbus_can_burst64(qsdev) && (bsizes & DMA_BURST64)) {
+		sbus_writel(GLOB_CTRL_B64, qecp->gregs + GLOB_CTRL);
+	} else if (bsizes & DMA_BURST32) {
+		sbus_writel(GLOB_CTRL_B32, qecp->gregs + GLOB_CTRL);
 	} else {
-		qecp->gregs->ctrl = GLOB_CTRL_B16;
+		sbus_writel(GLOB_CTRL_B16, qecp->gregs + GLOB_CTRL);
 	}
 
 	/* Packetsize only used in 100baseT BigMAC configurations,
 	 * set it to zero just to be on the safe side.
 	 */
-	qecp->gregs->psize = 0;
+	sbus_writel(GLOB_PSIZE_2048, qecp->gregs + GLOB_PSIZE);
 
 	/* Set the local memsize register, divided up to one piece per QE channel. */
-	qecp->gregs->msize = (qsdev->reg_addrs[1].reg_size >> 2);
+	sbus_writel((qsdev->reg_addrs[1].reg_size >> 2),
+		    qecp->gregs + GLOB_MSIZE);
 
 	/* Divide up the local QEC memory amongst the 4 QE receiver and
 	 * transmitter FIFOs.  Basically it is (total / 2 / num_channels).
 	 */
-	qecp->gregs->rsize = qecp->gregs->tsize =
-		(qsdev->reg_addrs[1].reg_size >> 2) >> 1;
-
+	sbus_writel((qsdev->reg_addrs[1].reg_size >> 2) >> 1,
+		    qecp->gregs + GLOB_TSIZE);
+	sbus_writel((qsdev->reg_addrs[1].reg_size >> 2) >> 1,
+		    qecp->gregs + GLOB_RSIZE);
 }
 
 /* Four QE's per QEC card. */
-static inline int qec_ether_init(struct net_device *dev, struct linux_sbus_device *sdev)
+static int __init qec_ether_init(struct net_device *dev, struct sbus_dev *sdev)
 {
 	static unsigned version_printed = 0;
 	struct net_device *qe_devs[4];
 	struct sunqe *qeps[4];
-	struct linux_sbus_device *qesdevs[4];
-	struct sunqec *qecp;
-	struct linux_prom_ranges qranges[8];
-	unsigned char bsizes, bsizes_more, num_qranges;
+	struct sbus_dev *qesdevs[4];
+	struct sunqec *qecp = NULL;
+	u8 bsizes, bsizes_more;
 	int i, j, res = ENOMEM;
 
 	dev = init_etherdev(0, sizeof(struct sunqe));
 	qe_devs[0] = dev;
 	qeps[0] = (struct sunqe *) dev->priv;
 	qeps[0]->channel = 0;
-	for(j = 0; j < 6; j++)
+	for (j = 0; j < 6; j++)
 		qe_devs[0]->dev_addr[j] = idprom->id_ethaddr[j];
 
-	if(version_printed++ == 0)
-		printk(version);
+	if (version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
 
 	qe_devs[1] = qe_devs[2] = qe_devs[3] = NULL;
-	for(i = 1; i < 4; i++) {
+	for (i = 1; i < 4; i++) {
 		qe_devs[i] = init_etherdev(0, sizeof(struct sunqe));
-		if(qe_devs[i] == NULL || qe_devs[i]->priv == NULL)
+		if (qe_devs[i] == NULL || qe_devs[i]->priv == NULL)
 			goto qec_free_devs;
 		qeps[i] = (struct sunqe *) qe_devs[i]->priv;
-		for(j = 0; j < 6; j++)
+		for (j = 0; j < 6; j++)
 			qe_devs[i]->dev_addr[j] = idprom->id_ethaddr[j];
 		qeps[i]->channel = i;
 	}
 	qecp = kmalloc(sizeof(struct sunqec), GFP_KERNEL);
-	if(qecp == NULL)
+	if (qecp == NULL)
 		goto qec_free_devs;
-	qecp->qec_sbus_dev = sdev;
+	qecp->qec_sdev = sdev;
 
-	for(i = 0; i < 4; i++) {
+	for (i = 0; i < 4; i++) {
 		qecp->qes[i] = qeps[i];
 		qeps[i]->dev = qe_devs[i];
 		qeps[i]->parent = qecp;
@@ -736,80 +751,45 @@
 
 	/* Link in channel 0. */
 	i = prom_getintdefault(sdev->child->prom_node, "channel#", -1);
-	if(i == -1) { res=ENODEV; goto qec_free_devs; }
+	if (i == -1) { res=ENODEV; goto qec_free_devs; }
 	qesdevs[i] = sdev->child;
-	qe_devs[i]->base_addr = (long) qesdevs[i];
 
 	/* Link in channel 1. */
 	i = prom_getintdefault(sdev->child->next->prom_node, "channel#", -1);
-	if(i == -1) { res=ENODEV; goto qec_free_devs; }
+	if (i == -1) { res=ENODEV; goto qec_free_devs; }
 	qesdevs[i] = sdev->child->next;
-	qe_devs[i]->base_addr = (long) qesdevs[i];
 
 	/* Link in channel 2. */
 	i = prom_getintdefault(sdev->child->next->next->prom_node, "channel#", -1);
-	if(i == -1) { res=ENODEV; goto qec_free_devs; }
+	if (i == -1) { res=ENODEV; goto qec_free_devs; }
 	qesdevs[i] = sdev->child->next->next;
-	qe_devs[i]->base_addr = (long) qesdevs[i];
 
 	/* Link in channel 3. */
 	i = prom_getintdefault(sdev->child->next->next->next->prom_node, "channel#", -1);
-	if(i == -1) { res=ENODEV; goto qec_free_devs; }
+	if (i == -1) { res=ENODEV; goto qec_free_devs; }
 	qesdevs[i] = sdev->child->next->next->next;
-	qe_devs[i]->base_addr = (long) qesdevs[i];
 
-	for(i = 0; i < 4; i++)
-		qeps[i]->qe_sbusdev = qesdevs[i];
-
-	/* This is a bit of fun, get QEC ranges. */
-	i = prom_getproperty(sdev->prom_node, "ranges",
-			     (char *) &qranges[0], sizeof(qranges));
-	num_qranges = (i / sizeof(struct linux_prom_ranges));
-
-	/* Now, apply all the ranges, QEC ranges then the SBUS ones for each QE. */
-	if (sdev->ranges_applied == 0) {
-		for(i = 0; i < 4; i++) {
-			for(j = 0; j < 2; j++) {
-				int k;
-
-				for(k = 0; k < num_qranges; k++)
-					if(qesdevs[i]->reg_addrs[j].which_io ==
-					   qranges[k].ot_child_space)
-						break;
-				if(k >= num_qranges)
-					printk("QuadEther: Aieee, bogus QEC range for "
-					       "space %08x\n",qesdevs[i]->reg_addrs[j].which_io);
-				qesdevs[i]->reg_addrs[j].which_io = qranges[k].ot_parent_space;
-				qesdevs[i]->reg_addrs[j].phys_addr += qranges[k].ot_parent_base;
-			}
-
-			prom_apply_sbus_ranges(qesdevs[i]->my_bus, &qesdevs[i]->reg_addrs[0],
-					       2, qesdevs[i]);
-		}
-		prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0],
-				       sdev->num_registers, sdev);
-	}
+	for (i = 0; i < 4; i++)
+		qeps[i]->qe_sdev = qesdevs[i];
 
 	/* Now map in the registers, QEC globals first. */
-	qecp->gregs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
-				     sizeof(struct qe_globreg),
-				     "QEC Global Registers",
-				     sdev->reg_addrs[0].which_io, 0);
-	if(!qecp->gregs) {
-		printk("QuadEther: Cannot map QEC global registers.\n");
+	qecp->gregs = sbus_ioremap(&sdev->resource[0], 0,
+				   GLOB_REG_SIZE, "QEC Global Registers");
+	if (!qecp->gregs) {
+		printk(KERN_ERR "QuadEther: Cannot map QEC global registers.\n");
 		res = ENODEV;
 		goto qec_free_devs;
 	}
 
 	/* Make sure the QEC is in MACE mode. */
-	if((qecp->gregs->ctrl & 0xf0000000) != GLOB_CTRL_MMODE) {
-		printk("QuadEther: AIEEE, QEC is not in MACE mode!\n");
+	if ((sbus_readl(qecp->gregs + GLOB_CTRL) & 0xf0000000) != GLOB_CTRL_MMODE) {
+		printk(KERN_ERR "QuadEther: AIEEE, QEC is not in MACE mode!\n");
 		res = ENODEV;
 		goto qec_free_devs;
 	}
 
 	/* Reset the QEC. */
-	if(qec_global_reset(qecp->gregs)) {
+	if (qec_global_reset(qecp->gregs)) {
 		res = ENODEV;
 		goto qec_free_devs;
 	}
@@ -819,11 +799,11 @@
 	 */
 	bsizes = prom_getintdefault(sdev->prom_node, "burst-sizes", 0xff);
 	bsizes &= 0xff;
-	bsizes_more = prom_getintdefault(sdev->my_bus->prom_node, "burst-sizes", 0xff);
+	bsizes_more = prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff);
 
-	if(bsizes_more != 0xff)
+	if (bsizes_more != 0xff)
 		bsizes &= bsizes_more;
-	if(bsizes == 0xff || (bsizes & DMA_BURST16) == 0 ||
+	if (bsizes == 0xff || (bsizes & DMA_BURST16) == 0 ||
 	   (bsizes & DMA_BURST32)==0)
 		bsizes = (DMA_BURST32 - 1);
 
@@ -834,43 +814,44 @@
 	 */
 	qec_init_once(qecp, sdev);
 
-	for(i = 0; i < 4; i++) {
+	for (i = 0; i < 4; i++) {
 		/* Map in QEC per-channel control registers. */
-		qeps[i]->qcregs = sparc_alloc_io(qesdevs[i]->reg_addrs[0].phys_addr, 0,
-						 sizeof(struct qe_creg),
-						 "QEC Per-Channel Registers",
-						 qesdevs[i]->reg_addrs[0].which_io, 0);
-		if(!qeps[i]->qcregs) {
-			printk("QuadEther: Cannot map QE %d's channel registers.\n", i);
+		qeps[i]->qcregs = sbus_ioremap(&qesdevs[i]->resource[0], 0,
+					       CREG_REG_SIZE, "QEC Channel Registers");
+		if (!qeps[i]->qcregs) {
+			printk(KERN_ERR "QuadEther: Cannot map QE %d's channel registers.\n", i);
 			res = ENODEV;
 			goto qec_free_devs;
 		}
 
 		/* Map in per-channel AMD MACE registers. */
-		qeps[i]->mregs = sparc_alloc_io(qesdevs[i]->reg_addrs[1].phys_addr, 0,
-						sizeof(struct qe_mregs),
-						"QE MACE Registers",
-						qesdevs[i]->reg_addrs[1].which_io, 0);
-		if(!qeps[i]->mregs) {
-			printk("QuadEther: Cannot map QE %d's MACE registers.\n", i);
+		qeps[i]->mregs = sbus_ioremap(&qesdevs[i]->resource[1], 0,
+					      MREGS_REG_SIZE, "QE MACE Registers");
+		if (!qeps[i]->mregs) {
+			printk(KERN_ERR "QuadEther: Cannot map QE %d's MACE registers.\n", i);
 			res = ENODEV;
 			goto qec_free_devs;
 		}
 
-		qeps[i]->qe_block = (struct qe_init_block *)
-			sparc_dvma_malloc(PAGE_SIZE, "QE Init Block",
-					  &qeps[i]->qblock_dvma);
-
-		qeps[i]->buffers = (struct sunqe_buffers *)
-			sparc_dvma_malloc(sizeof(struct sunqe_buffers),
-					  "QE RX/TX Buffers",
-					  &qeps[i]->buffers_dvma);
+		qeps[i]->qe_block = sbus_alloc_consistant(qesdevs[i],
+							  PAGE_SIZE,
+							  &qeps[i]->qblock_dvma);
+		qeps[i]->buffers = sbus_alloc_consistant(qesdevs[i],
+							 sizeof(struct sunqe_buffers),
+							 &qeps[i]->buffers_dvma);
+		if (qeps[i]->qe_block == NULL ||
+		    qeps[i]->qblock_dvma == 0 ||
+		    qeps[i]->buffers == NULL ||
+		    qeps[i]->buffers_dvma == 0) {
+			res = ENODEV;
+			goto qec_free_devs;
+		}
 
 		/* Stop this QE. */
 		qe_stop(qeps[i]);
 	}
 
-	for(i = 0; i < 4; i++) {
+	for (i = 0; i < 4; i++) {
 		qe_devs[i]->open = qe_open;
 		qe_devs[i]->stop = qe_close;
 		qe_devs[i]->hard_start_xmit = qe_start_xmit;
@@ -886,17 +867,17 @@
 	 * interrupt for all QE channels we register the IRQ handler
 	 * for it now.
 	 */
-	if(request_irq(sdev->irqs[0], &qec_interrupt,
-		       SA_SHIRQ, "QuadEther", (void *) qecp)) {
-		printk("QuadEther: Can't register QEC master irq handler.\n");
+	if (request_irq(sdev->irqs[0], &qec_interrupt,
+			SA_SHIRQ, "QuadEther", (void *) qecp)) {
+		printk(KERN_ERR "QuadEther: Can't register QEC master irq handler.\n");
 		res = EAGAIN;
 		goto qec_free_devs;
 	}
 
 	/* Report the QE channels. */
-	for(i = 0; i < 4; i++) {
-		printk("%s: QuadEthernet channel[%d] ", qe_devs[i]->name, i);
-		for(j = 0; j < 6; j++)
+	for (i = 0; i < 4; i++) {
+		printk(KERN_INFO "%s: QuadEthernet channel[%d] ", qe_devs[i]->name, i);
+		for (j = 0; j < 6; j++)
 			printk ("%2.2x%c",
 				qe_devs[i]->dev_addr[j],
 				j == 5 ? ' ': ':');
@@ -907,7 +888,7 @@
 	/* We are home free at this point, link the qe's into
 	 * the master list for later module unloading.
 	 */
-	for(i = 0; i < 4; i++)
+	for (i = 0; i < 4; i++)
 		qe_devs[i]->ifindex = dev_new_index();
 	qecp->next_module = root_qec_dev;
 	root_qec_dev = qecp;
@@ -916,50 +897,87 @@
 	return 0;
 
 qec_free_devs:
-	for(i = 0; i < 4; i++) {
-		if(qe_devs[i]) {
-			if(qe_devs[i]->priv)
+	for (i = 0; i < 4; i++) {
+		if (qe_devs[i] != NULL) {
+			if (qe_devs[i]->priv) {
+				struct sunqe *qe = (struct sunqe *)qe_devs[i]->priv;
+
+				if (qe->qcregs)
+					sbus_iounmap(qe->qcregs, CREG_REG_SIZE);
+				if (qe->mregs)
+					sbus_iounmap(qe->mregs, MREGS_REG_SIZE);
+				if (qe->qe_block != NULL)
+					sbus_free_consistant(qe->qe_sdev,
+							     PAGE_SIZE,
+							     qe->qe_block,
+							     qe->qblock_dvma);
+				if (qe->buffers != NULL)
+					sbus_free_consistant(qe->qe_sdev,
+							     sizeof(struct sunqe_buffers),
+							     qe->buffers,
+							     qe->buffers_dvma);
 				kfree(qe_devs[i]->priv);
+			}
 			kfree(qe_devs[i]);
 		}
 	}
+	if (qecp != NULL) {
+		if (qecp->gregs)
+			sbus_iounmap(qecp->gregs, GLOB_REG_SIZE);
+		kfree(qecp);
+	}
 	return res;
 }
 
+static int __init qec_match(struct sbus_dev *sdev)
+{
+	struct sbus_dev *sibling;
+	int i;
+
+	if (strcmp(sdev->prom_name, "qec") != 0)
+		return 0;
+
+	/* QEC can be parent of either QuadEthernet or BigMAC
+	 * children.  Do not confuse this with qfe/SUNW,qfe
+	 * which is a quad-happymeal card and handled by
+	 * a different driver.
+	 */
+	sibling = sdev->child;
+	for (i = 0; i < 4; i++) {
+		if (sibling == NULL)
+			return 0;
+		if (strcmp(sibling->prom_name, "qe") != 0)
+			return 0;
+		sibling = sibling->next;
+	}
+	return 1;
+}
+
 int __init qec_probe(void)
 {
 	struct net_device *dev = NULL;
-	struct linux_sbus *bus;
-	struct linux_sbus_device *sdev = 0;
+	struct sbus_bus *bus;
+	struct sbus_dev *sdev = 0;
 	static int called = 0;
 	int cards = 0, v;
 
-	if(called)
+	if (called)
 		return ENODEV;
 	called++;
 
 	for_each_sbus(bus) {
 		for_each_sbusdev(sdev, bus) {
-			if(cards) dev = NULL;
+			if (cards)
+				dev = NULL;
 
-			/* QEC can be parent of either QuadEthernet or BigMAC
-			 * children.
-			 */
-			if(!strcmp(sdev->prom_name, "qec") && sdev->child &&
-			   !strcmp(sdev->child->prom_name, "qe") &&
-			   sdev->child->next &&
-			   !strcmp(sdev->child->next->prom_name, "qe") &&
-			   sdev->child->next->next &&
-			   !strcmp(sdev->child->next->next->prom_name, "qe") &&
-			   sdev->child->next->next->next &&
-			   !strcmp(sdev->child->next->next->next->prom_name, "qe")) {
+			if (qec_match(sdev)) {
 				cards++;
-				if((v = qec_ether_init(dev, sdev)))
+				if ((v = qec_ether_init(dev, sdev)))
 					return v;
 			}
 		}
 	}
-	if(!cards)
+	if (!cards)
 		return ENODEV;
 	return 0;
 }
@@ -984,14 +1002,22 @@
 		next_qec = root_qec_dev->next_module;
 
 		/* Release all four QE channels, then the QEC itself. */
-		for(i = 0; i < 4; i++) {
+		for (i = 0; i < 4; i++) {
 			unregister_netdev(root_qec_dev->qes[i]->dev);
-			sparc_free_io(root_qec_dev->qes[i]->qcregs, sizeof(struct qe_creg));
-			sparc_free_io(root_qec_dev->qes[i]->mregs, sizeof(struct qe_mregs));
+			sbus_iounmap(root_qec_dev->qes[i]->qcregs, CREG_REG_SIZE);
+			sbus_iounmap(root_qec_dev->qes[i]->mregs, MREGS_REG_SIZE);
+			sbus_free_consistant(root_qec_dev->qes[i]->qe_sdev,
+					     PAGE_SIZE,
+					     root_qec_dev->qes[i]->qe_block,
+					     root_qec_dev->qes[i]->qblock_dvma);
+			sbus_free_consistant(root_qec_dev->qes[i]->qe_sdev,
+					     sizeof(struct sunqe_buffers),
+					     root_qec_dev->qes[i]->buffers,
+					     root_qec_dev->qes[i]->buffers_dvma);
 			kfree(root_qec_dev->qes[i]->dev);
 		}
-		free_irq(root_qec_dev->qec_sbus_dev->irqs[0], (void *)root_qec_dev);
-		sparc_free_io(root_qec_dev->gregs, sizeof(struct qe_globreg));
+		free_irq(root_qec_dev->qec_sdev->irqs[0], (void *)root_qec_dev);
+		sbus_iounmap(root_qec_dev->gregs, GLOB_REG_SIZE);
 		kfree(root_qec_dev);
 		root_qec_dev = next_qec;
 	}
diff -u --recursive --new-file v2.3.34/linux/drivers/net/sunqe.h linux/drivers/net/sunqe.h
--- v2.3.34/linux/drivers/net/sunqe.h	Fri Sep 10 23:57:30 1999
+++ linux/drivers/net/sunqe.h	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,5 @@
-/* sunqe.h: Definitions for the Sun QuadEthernet driver.
+/* $Id: sunqe.h,v 1.12 1999/09/21 14:36:44 davem Exp $
+ * sunqe.h: Definitions for the Sun QuadEthernet driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
@@ -7,14 +8,13 @@
 #define _SUNQE_H
 
 /* QEC global registers. */
-struct qe_globreg {
-	volatile unsigned int ctrl;      /* Control                  */
-	volatile unsigned int stat;      /* Status                   */
-	volatile unsigned int psize;     /* Packet Size              */
-	volatile unsigned int msize;     /* Local-mem size (64K)     */
-	volatile unsigned int rsize;     /* Receive partition size   */
-	volatile unsigned int tsize;     /* Transmit partition size  */
-};
+#define GLOB_CTRL	0x00UL		/* Control			*/
+#define GLOB_STAT	0x04UL		/* Status			*/
+#define GLOB_PSIZE	0x08UL		/* Packet Size			*/
+#define GLOB_MSIZE	0x0cUL		/* Local-memory Size		*/
+#define GLOB_RSIZE	0x10UL		/* Receive partition size	*/
+#define GLOB_TSIZE	0x14UL		/* Transmit partition size	*/
+#define GLOB_REG_SIZE	0x18UL
 
 #define GLOB_CTRL_MMODE       0x40000000 /* MACE qec mode            */
 #define GLOB_CTRL_BMODE       0x10000000 /* BigMAC qec mode          */
@@ -42,22 +42,21 @@
 #define GLOB_STAT_PER_QE(status, channel) (((status) >> ((channel) * 4)) & 0xf)
 
 /* The following registers are for per-qe channel information/status. */
-struct qe_creg {
-	volatile unsigned int ctrl;       /* Control                   */
-	volatile unsigned int stat;       /* Status                    */
-	volatile unsigned int rxds;       /* RX descriptor ring ptr    */
-	volatile unsigned int txds;       /* TX descriptor ring ptr    */
-	volatile unsigned int rimask;     /* RX Interrupt Mask         */
-	volatile unsigned int timask;     /* TX Interrupt Mask         */
-	volatile unsigned int qmask;      /* QEC Error Interrupt Mask  */
-	volatile unsigned int mmask;      /* MACE Error Interrupt Mask */
-	volatile unsigned int rxwbufptr;  /* Local memory rx write ptr */
-	volatile unsigned int rxrbufptr;  /* Local memory rx read ptr  */
-	volatile unsigned int txwbufptr;  /* Local memory tx write ptr */
-	volatile unsigned int txrbufptr;  /* Local memory tx read ptr  */
-	volatile unsigned int ccnt;       /* Collision Counter         */
-	volatile unsigned int pipg;       /* Inter-Frame Gap           */
-};
+#define CREG_CTRL	0x00UL	/* Control                   */
+#define CREG_STAT	0x04UL	/* Status                    */
+#define CREG_RXDS	0x08UL	/* RX descriptor ring ptr    */
+#define CREG_TXDS	0x0cUL	/* TX descriptor ring ptr    */
+#define CREG_RIMASK	0x10UL	/* RX Interrupt Mask         */
+#define CREG_TIMASK	0x14UL	/* TX Interrupt Mask         */
+#define CREG_QMASK	0x18UL	/* QEC Error Interrupt Mask  */
+#define CREG_MMASK	0x1cUL	/* MACE Error Interrupt Mask */
+#define CREG_RXWBUFPTR	0x20UL	/* Local memory rx write ptr */
+#define CREG_RXRBUFPTR	0x24UL	/* Local memory rx read ptr  */
+#define CREG_TXWBUFPTR	0x28UL	/* Local memory tx write ptr */
+#define CREG_TXRBUFPTR	0x2cUL	/* Local memory tx read ptr  */
+#define CREG_CCNT	0x30UL	/* Collision Counter         */
+#define CREG_PIPG	0x34UL	/* Inter-Frame Gap           */
+#define CREG_REG_SIZE	0x38UL
 
 #define CREG_CTRL_RXOFF       0x00000004  /* Disable this qe's receiver*/
 #define CREG_CTRL_RESET       0x00000002  /* Reset this qe channel     */
@@ -127,40 +126,39 @@
 #define CREG_PIPG_WMASK       0x0000000f  /* SBUS Wait Mask            */
 
 /* Per-channel AMD 79C940 MACE registers. */
-struct qe_mregs {
-	volatile unsigned char rxfifo;   /* Receive FIFO                   */
-	volatile unsigned char txfifo;   /* Transmit FIFO                  */
-	volatile unsigned char txfcntl;  /* Transmit Frame Control         */
-	volatile unsigned char txfstat;  /* Transmit Frame Status          */
-	volatile unsigned char txrcnt;   /* Transmit Retry Count           */
-	volatile unsigned char rxfcntl;  /* Receive Frame Control          */
-	volatile unsigned char rxfstat;  /* Receive Frame Status           */
-	volatile unsigned char ffcnt;    /* FIFO Frame Count               */
-	volatile unsigned char ireg;     /* Interrupt Register             */
-	volatile unsigned char imask;    /* Interrupt Mask                 */
-	volatile unsigned char poll;     /* POLL Register                  */
-	volatile unsigned char bconfig;  /* BIU Config                     */
-	volatile unsigned char fconfig;  /* FIFO Config                    */
-	volatile unsigned char mconfig;  /* MAC Config                     */
-	volatile unsigned char plsconfig;/* PLS Config                     */
-	volatile unsigned char phyconfig;/* PHY Config                     */
-	volatile unsigned char chipid1;  /* Chip-ID, low bits              */
-	volatile unsigned char chipid2;  /* Chip-ID, high bits             */
-	volatile unsigned char iaconfig; /* Internal Address Config        */
-	volatile unsigned char _unused0; /* Reserved...                    */
-	volatile unsigned char filter;   /* Logical Address Filter         */
-	volatile unsigned char ethaddr;  /* Our Ethernet Address           */
-	volatile unsigned char _unused1; /* Reserved...                    */
-	volatile unsigned char _unused2; /* Reserved...                    */
-	volatile unsigned char mpcnt;    /* Missed Packet Count            */
-	volatile unsigned char _unused3; /* Reserved...                    */
-	volatile unsigned char rpcnt;    /* Runt Packet Count              */
-	volatile unsigned char rccnt;    /* RX Collision Count             */
-	volatile unsigned char _unused4; /* Reserved...                    */
-	volatile unsigned char utest;    /* User Test                      */
-	volatile unsigned char rtest1;   /* Reserved Test 1                */
-	volatile unsigned char rtest2;   /* Reserved Test 2                */
-};
+#define MREGS_RXFIFO	0x00UL	/* Receive FIFO                   */
+#define MREGS_TXFIFO	0x01UL	/* Transmit FIFO                  */
+#define MREGS_TXFCNTL	0x02UL	/* Transmit Frame Control         */
+#define MREGS_TXFSTAT	0x03UL	/* Transmit Frame Status          */
+#define MREGS_TXRCNT	0x04UL	/* Transmit Retry Count           */
+#define MREGS_RXFCNTL	0x05UL	/* Receive Frame Control          */
+#define MREGS_RXFSTAT	0x06UL	/* Receive Frame Status           */
+#define MREGS_FFCNT	0x07UL	/* FIFO Frame Count               */
+#define MREGS_IREG	0x08UL	/* Interrupt Register             */
+#define MREGS_IMASK	0x09UL	/* Interrupt Mask                 */
+#define MREGS_POLL	0x0aUL	/* POLL Register                  */
+#define MREGS_BCONFIG	0x0bUL	/* BIU Config                     */
+#define MREGS_FCONFIG	0x0cUL	/* FIFO Config                    */
+#define MREGS_MCONFIG	0x0dUL	/* MAC Config                     */
+#define MREGS_PLSCONFIG	0x0eUL	/* PLS Config                     */
+#define MREGS_PHYCONFIG	0x0fUL	/* PHY Config                     */
+#define MREGS_CHIPID1	0x10UL	/* Chip-ID, low bits              */
+#define MREGS_CHIPID2	0x11UL	/* Chip-ID, high bits             */
+#define MREGS_IACONFIG	0x12UL	/* Internal Address Config        */
+	/* 0x13UL, reserved */
+#define MREGS_FILTER	0x14UL	/* Logical Address Filter         */
+#define MREGS_ETHADDR	0x15UL	/* Our Ethernet Address           */
+	/* 0x16UL, reserved */
+	/* 0x17UL, reserved */
+#define MREGS_MPCNT	0x18UL	/* Missed Packet Count            */
+	/* 0x19UL, reserved */
+#define MREGS_RPCNT	0x1aUL	/* Runt Packet Count              */
+#define MREGS_RCCNT	0x1bUL	/* RX Collision Count             */
+	/* 0x1cUL, reserved */
+#define MREGS_UTEST	0x1dUL	/* User Test                      */
+#define MREGS_RTEST1	0x1eUL	/* Reserved Test 1                */
+#define MREGS_RTEST2	0x1fUL	/* Reserved Test 2                */
+#define MREGS_REG_SIZE	0x20UL
 
 #define MREGS_TXFCNTL_DRETRY        0x80 /* Retry disable                  */
 #define MREGS_TXFCNTL_DFCS          0x08 /* Disable TX FCS                 */
@@ -267,8 +265,8 @@
 #define MREGS_UTEST_NOLOOP          0x00 /* No loopback                    */
 
 struct qe_rxd {
-	unsigned int rx_flags;
-	unsigned int rx_addr;
+	u32 rx_flags;
+	u32 rx_addr;
 };
 
 #define RXD_OWN      0x80000000 /* Ownership.      */
@@ -276,8 +274,8 @@
 #define RXD_LENGTH   0x000007ff /* Packet Length.  */
 
 struct qe_txd {
-	unsigned int tx_flags;
-	unsigned int tx_addr;
+	u32 tx_flags;
+	u32 tx_addr;
 };
 
 #define TXD_OWN      0x80000000 /* Ownership.      */
@@ -313,40 +311,40 @@
 struct sunqe;
 
 struct sunqec {
-	struct qe_globreg         *gregs;             /* QEC Global Registers         */
-	struct sunqe              *qes[4];	      /* Each child MACE              */
-	unsigned int               qec_bursts;	      /* Support burst sizes          */
-	struct linux_sbus_device  *qec_sbus_dev;      /* QEC's SBUS device            */
-	struct sunqec             *next_module;	      /* List of all QECs in system   */
+	unsigned long		gregs;		/* QEC Global Registers         */
+	struct sunqe		*qes[4];	/* Each child MACE              */
+	unsigned int            qec_bursts;	/* Support burst sizes          */
+	struct sbus_dev		*qec_sdev;	/* QEC's SBUS device            */
+	struct sunqec		*next_module;	/* List of all QECs in system   */
 };
 
 #define PKT_BUF_SZ	1664
 #define RXD_PKT_SZ	1664
 
 struct sunqe_buffers {
-	char	tx_buf[TX_RING_SIZE][PKT_BUF_SZ];
-	char	__pad[2];
-	char	rx_buf[RX_RING_SIZE][PKT_BUF_SZ];
+	u8	tx_buf[TX_RING_SIZE][PKT_BUF_SZ];
+	u8	__pad[2];
+	u8	rx_buf[RX_RING_SIZE][PKT_BUF_SZ];
 };
 
 #define qebuf_offset(mem, elem) \
 ((__u32)((unsigned long)(&(((struct sunqe_buffers *)0)->mem[elem][0]))))
 
 struct sunqe {
-	struct qe_creg            *qcregs;           /* QEC per-channel Registers      */
-	struct qe_mregs           *mregs;            /* Per-channel MACE Registers     */
-	struct qe_init_block      *qe_block;         /* RX and TX descriptors          */
-	__u32                      qblock_dvma;      /* RX and TX descriptors          */
-	int                        rx_new, rx_old;   /* RX ring extents		       */
-	int			   tx_new, tx_old;   /* TX ring extents		       */
-	struct sunqe_buffers      *buffers;	     /* CPU visible address.           */
-	__u32                      buffers_dvma;     /* DVMA visible address.          */
-	struct sunqec             *parent;
-	unsigned char		   mconfig;	     /* Base MACE mconfig value        */
-	struct net_device_stats    net_stats;        /* Statistical counters           */
-	struct linux_sbus_device  *qe_sbusdev;       /* QE's SBUS device struct        */
-	struct net_device         *dev;              /* QE's netdevice struct          */
-	int                        channel;          /* Who am I?                      */
+	unsigned long			qcregs;		/* QEC per-channel Registers   */
+	unsigned long			mregs;		/* Per-channel MACE Registers  */
+	struct qe_init_block      	*qe_block;	/* RX and TX descriptors       */
+	__u32                      	qblock_dvma;	/* RX and TX descriptors       */
+	int                        	rx_new, rx_old;	/* RX ring extents	       */
+	int			   	tx_new, tx_old;	/* TX ring extents	       */
+	struct sunqe_buffers		*buffers;	/* CPU visible address.        */
+	__u32				buffers_dvma;	/* DVMA visible address.       */
+	struct sunqec			*parent;
+	u8				mconfig;	/* Base MACE mconfig value     */
+	struct net_device_stats		net_stats;	/* Statistical counters        */
+	struct sbus_dev			*qe_sdev;	/* QE's SBUS device struct     */
+	struct net_device		*dev;		/* QE's netdevice struct       */
+	int				channel;	/* Who am I?                   */
 };
 
 #endif /* !(_SUNQE_H) */
diff -u --recursive --new-file v2.3.34/linux/drivers/parport/parport_sunbpp.c linux/drivers/parport/parport_sunbpp.c
--- v2.3.34/linux/drivers/parport/parport_sunbpp.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/parport/parport_sunbpp.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: parport_sunbpp.c,v 1.7 1999/09/02 11:59:31 davem Exp $
+/* $Id: parport_sunbpp.c,v 1.9 1999/10/14 05:59:43 ecd Exp $
  * Parallel-port routines for Sun architecture
  * 
  * Author: Derrick J. Brashear <shadow@dementia.org>
@@ -32,7 +32,7 @@
 
 #include <asm/io.h>
 #include <asm/oplib.h>           /* OpenProm Library */
-#include <asm/sbus.h>            /* struct linux_sbus *SBus_chain */
+#include <asm/sbus.h>
 #include <asm/dma.h>             /* BPP uses LSI 64854 for DMA */
 #include <asm/irq.h>
 #include <asm/sunbpp.h>
@@ -52,22 +52,28 @@
 static void parport_sunbpp_disable_irq(struct parport *p)
 {
 	struct bpp_regs *regs = (struct bpp_regs *)p->base;
+	u32 tmp;
 
-	regs->p_csr &= ~(DMA_INT_ENAB);
+	tmp = sbus_readl(&regs->p_csr);
+	tmp &= ~DMA_INT_ENAB;
+	sbus_writel(tmp, &regs->p_csr);
 }
 
 static void parport_sunbpp_enable_irq(struct parport *p)
 {
 	struct bpp_regs *regs = (struct bpp_regs *)p->base;
+	u32 tmp;
 
-	regs->p_csr |= DMA_INT_ENAB;
+	tmp = sbus_readl(&regs->p_csr);
+	tmp |= DMA_INT_ENAB;
+	sbus_writel(tmp, &regs->p_csr);
 }
 
 static void parport_sunbpp_write_data(struct parport *p, unsigned char d)
 {
 	struct bpp_regs *regs = (struct bpp_regs *)p->base;
 
-	regs->p_dr = d;
+	sbus_writeb(d, &regs->p_dr);
 	dprintk(("wrote 0x%x\n", d));
 }
 
@@ -75,14 +81,15 @@
 {
 	struct bpp_regs *regs = (struct bpp_regs *)p->base;
 
-	return regs->p_dr;
+	return sbus_readb(&regs->p_dr);
 }
 
+#if 0
 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;
+	unsigned char value_tcr = sbus_readb(&regs->p_tcr);
+	unsigned char value_or = sbus_readb(&regs->p_or);
 
 	if (status & PARPORT_CONTROL_STROBE) 
 		value_tcr |= P_TCR_DS;
@@ -93,16 +100,17 @@
 	if (status & PARPORT_CONTROL_SELECT) 
 		value_or |= P_OR_SLCT_IN;
 
-	regs->p_or = value_or;
-	regs->p_tcr = value_tcr;
+	sbus_writeb(value_or, &regs->p_or);
+	sbus_writeb(value_tcr, &regs->p_tcr);
 }
+#endif
 
 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;
+	unsigned char value_tcr = sbus_readb(&regs->p_tcr);
+	unsigned char value_ir = sbus_readb(&regs->p_ir);
 
 	if (!(value_ir & P_IR_ERR))
 		bits |= PARPORT_STATUS_ERROR;
@@ -124,8 +132,8 @@
 {
 	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;
+	unsigned char value_tcr = sbus_readb(&regs->p_tcr);
+	unsigned char value_or = sbus_readb(&regs->p_or);
 
 	if (!(value_tcr & P_TCR_DS))
 		bits |= PARPORT_CONTROL_STROBE;
@@ -151,8 +159,8 @@
 						 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;
+	unsigned char value_tcr = sbus_readb(&regs->p_tcr);
+	unsigned char value_or = sbus_readb(&regs->p_or);
 
 	dprintk(("frob1: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
 	if (mask & PARPORT_CONTROL_STROBE) {
@@ -184,8 +192,8 @@
 		}
 	}
 
-	regs->p_or = value_or;
-	regs->p_tcr = value_tcr;
+	sbus_writeb(value_or, &regs->p_or);
+	sbus_writeb(value_tcr, &regs->p_tcr);
 	dprintk(("frob2: tcr 0x%x or 0x%x\n", regs->p_tcr, regs->p_or));
 	return parport_sunbpp_read_control(p);
 }
@@ -208,20 +216,21 @@
 static void parport_sunbpp_data_forward (struct parport *p)
 {
 	struct bpp_regs *regs = (struct bpp_regs *)p->base;
-	unsigned char value_tcr = regs->p_tcr;
+	unsigned char value_tcr = sbus_readb(&regs->p_tcr);
 
 	dprintk(("forward\n"));
-	value_tcr = regs->p_tcr;
 	value_tcr &= ~P_TCR_DIR;
-	regs->p_tcr = value_tcr;
+	sbus_writeb(value_tcr, &regs->p_tcr);
 }
 
 static void parport_sunbpp_data_reverse (struct parport *p)
 {
 	struct bpp_regs *regs = (struct bpp_regs *)p->base;
+	u8 val = sbus_readb(&regs->p_tcr);
 
 	dprintk(("reverse\n"));
-	regs->p_tcr |= P_TCR_DIR;
+	val |= P_TCR_DIR;
+	sbus_writeb(val, &regs->p_tcr);
 }
 
 static void parport_sunbpp_init_state(struct pardevice *dev, struct parport_state *s)
@@ -292,38 +301,37 @@
         parport_ieee1284_read_byte,
 };
 
-static int __init init_one_port(struct linux_sbus_device *sdev)
+static int __init init_one_port(struct sbus_dev *sdev)
 {
 	struct parport *p;
 	/* at least in theory there may be a "we don't dma" case */
 	struct parport_operations *ops;
-	char *base;
+	unsigned long base;
 	int irq, dma, err, size;
 	struct bpp_regs *regs;
 	unsigned char value_tcr;
 
 	dprintk(("init_one_port(%p): ranges, alloc_io, ", sdev));
 	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);
+	base = sbus_ioremap(&sdev->resource[0], 0,
+			    sdev->reg_addrs[0].reg_size, 
+			    "sunbpp");
 	size = sdev->reg_addrs[0].reg_size;
 	dma = PARPORT_DMA_NONE;
 
 	dprintk(("alloc(ppops), "));
 	ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
         if (!ops) {
-		sparc_free_io(base, size);
+		sbus_iounmap(base, size);
 		return 0;
         }
 
         memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations));
 
 	dprintk(("register_port, "));
-	if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) {
+	if (!(p = parport_register_port(base, irq, dma, ops))) {
 		kfree(ops);
-		sparc_free_io(base, size);
+		sbus_iounmap(base, size);
 		return 0;
 	}
 
@@ -334,7 +342,7 @@
 		dprintk(("ERROR %d\n", err));
 		parport_unregister_port(p);
 		kfree(ops);
-		sparc_free_io(base, size);
+		sbus_iounmap(base, size);
 		return err;
 	} else {
 		dprintk(("OK\n"));
@@ -343,9 +351,9 @@
 
 	regs = (struct bpp_regs *)p->base;
 	dprintk(("forward\n"));
-	value_tcr = regs->p_tcr;
+	value_tcr = sbus_readb(&regs->p_tcr);
 	value_tcr &= ~P_TCR_DIR;
-	regs->p_tcr = value_tcr;
+	sbus_writeb(value_tcr, &regs->p_tcr);
 
 	printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base);
 	parport_proc_register(p);
@@ -362,8 +370,8 @@
 int __init parport_sunbpp_init(void)
 #endif
 {
-        struct linux_sbus *sbus;
-        struct linux_sbus_device *sdev;
+        struct sbus_bus *sbus;
+        struct sbus_dev *sdev;
 	int count = 0;
 
 	for_each_sbus(sbus) {
@@ -383,21 +391,24 @@
 void
 cleanup_module(void)
 {
-	struct parport *p = parport_enumerate(), *tmp;
+	struct parport *p = parport_enumerate();
+
 	while (p) {
-		tmp = p->next;
+		struct parport *next = 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);
+			struct parport_operations *ops = p->ops;
+
+			if (p->irq != PARPORT_IRQ_NONE) {
+				parport_sunbpp_disable_irq(p);
+				free_irq(p->irq, p);
+			}
+			sbus_iounmap(p->base, p->size);
+			parport_proc_unregister(p);
+			parport_unregister_port(p);
+			kfree (ops);
 		}
-		p = tmp;
+		p = next;
 	}
 }
 #endif
diff -u --recursive --new-file v2.3.34/linux/drivers/pci/Makefile linux/drivers/pci/Makefile
--- v2.3.34/linux/drivers/pci/Makefile	Wed Dec  8 14:11:26 1999
+++ linux/drivers/pci/Makefile	Tue Dec 21 10:12:53 1999
@@ -11,21 +11,20 @@
 
 L_TARGET := pci.a
 
-# Nasty trick as nobody references pcisyms.o, but we still want it linked.
-ifeq ($(CONFIG_MODULES),y)
-O_TARGET = pci_syms.o
-OX_OBJS  = pcisyms.o
-O_OBJS   = pci.o
-L_OBJS   := pci_syms.o
-else
-L_OBJS   := pci.o
+# Nasty trick as we need to link files with no references from the outside.
+O_TARGET := pci_core.o
+L_OBJS	 := pci_core.o
+O_OBJS   := pci.o quirks.o
+
+ifdef CONFIG_MODULES
+OX_OBJS  += pcisyms.o
 endif
 
 ifdef CONFIG_PROC_FS
-L_OBJS   += proc.o
+O_OBJS   += proc.o
 endif
 
-L_OBJS   += compat.o quirks.o names.o helper.o
+L_OBJS   += compat.o names.o helper.o
 
 ifndef CONFIG_X86
 L_OBJS   += syscall.o setup.o
diff -u --recursive --new-file v2.3.34/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.3.34/linux/drivers/pci/pci.c	Wed Dec  8 14:11:26 1999
+++ linux/drivers/pci/pci.c	Mon Dec 27 11:08:29 1999
@@ -30,7 +30,6 @@
 struct pci_bus *pci_root;
 struct pci_dev *pci_devices = NULL;
 static struct pci_dev **pci_last_dev_p = &pci_devices;
-static int pci_reverse __initdata = 0;
 
 struct pci_dev *
 pci_find_slot(unsigned int bus, unsigned int devfn)
@@ -270,7 +269,7 @@
 	return IORESOURCE_MEM;
 }
 
-void __init pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
+static void __init pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
 {
 	unsigned int pos, reg, next;
 	u32 l, sz, tmp;
@@ -413,91 +412,264 @@
 	}
 }
 
-static unsigned int __init pci_do_scan_bus(struct pci_bus *bus)
+static struct pci_bus * __init pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
 {
-	unsigned int devfn, l, max, class;
-	unsigned char irq, hdr_type, is_multi = 0;
-	struct pci_dev *dev, **bus_last;
 	struct pci_bus *child;
-	struct pci_dev *dev_cache = NULL;
 
-	DBG("pci_do_scan_bus for bus %d\n", bus->number);
-	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 (!dev_cache) {
-			dev_cache = kmalloc(sizeof(*dev), GFP_KERNEL);
-			if (!dev_cache)
-				continue;
-		}
-		dev = dev_cache;
-		memset(dev, 0, sizeof(*dev));
-		dev->bus = bus;
-		dev->sysdata = bus->sysdata;
-		dev->devfn  = devfn;
+	/*
+	 * Allocate a new bus, and inherit stuff from the parent..
+	 */
+	child = kmalloc(sizeof(*child), GFP_KERNEL);
+	memset(child, 0, sizeof(*child));
 
-		if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type))
-			continue;
-		if (!PCI_FUNC(devfn))
-			is_multi = hdr_type & 0x80;
+	child->next = parent->children;
+	parent->children = child;
+	child->self = dev;
+	dev->subordinate = child;
+	child->parent = parent;
+	child->ops = parent->ops;
+	child->sysdata = parent->sysdata;
+
+	/*
+	 * Set up the primary, secondary and subordinate
+	 * bus numbers.
+	 */
+	child->number = child->secondary = busnr;
+	child->primary = parent->secondary;
+	child->subordinate = 0xff;
+
+	return child;
+}
+
+/*
+ * A CardBus bridge is basically the same as a regular PCI bridge,
+ * except we don't scan behind it because it will be changing.
+ */
+static int __init pci_scan_cardbus(struct pci_bus *bus, struct pci_dev *dev, int busnr)
+{
+	unsigned short cr;
+	unsigned int buses;
+	struct pci_bus *child;
+
+	/*
+	 * Insert it into the tree of buses.
+	 */
+	child = pci_add_new_bus(bus, dev, ++busnr);
+	child->subordinate = busnr;
+	sprintf(child->name, "PCI CardBus #%02x", child->number);
+
+	/*
+	 * Clear all status bits and turn off memory,
+	 * I/O and master enables.
+	 */
+	pci_read_config_word(dev, PCI_COMMAND, &cr);
+	pci_write_config_word(dev, PCI_COMMAND, 0x0000);
+	pci_write_config_word(dev, PCI_STATUS, 0xffff);
+
+	/*
+	 * Read the existing primary/secondary/subordinate bus
+	 * number configuration to determine if the bridge
+	 * has already been configured by the system.  If so,
+	 * do not modify the configuration, merely note it.
+	 */
+	pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
+	if ((buses & 0xFFFFFF) != 0 && ! pcibios_assign_all_busses()) {
+		child->primary = buses & 0xFF;
+		child->secondary = (buses >> 8) & 0xFF;
+		child->subordinate = (buses >> 16) & 0xFF;
+		child->number = child->secondary;
+		if (child->subordinate > busnr)
+			busnr = child->subordinate;
+	} 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));
+		pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
+	}
+	pci_write_config_word(dev, PCI_COMMAND, cr);
+	return busnr;
+}
+
+static unsigned int __init pci_do_scan_bus(struct pci_bus *bus);
+
+/*
+ * If it's a bridge, scan the bus behind it.
+ */
+static int __init pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max)
+{
+	unsigned int buses;
+	unsigned short cr;
+	struct pci_bus *child;
+
+	/*
+	 * Insert it into the tree of buses.
+	 */
+	child = pci_add_new_bus(bus, dev, ++max);
+	sprintf(child->name, "PCI Bus #%02x", child->number);
+
+	/*
+	 * Clear all status bits and turn off memory,
+	 * I/O and master enables.
+	 */
+	pci_read_config_word(dev, PCI_COMMAND, &cr);
+	pci_write_config_word(dev, PCI_COMMAND, 0x0000);
+	pci_write_config_word(dev, 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.
+	 */
+	pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
+	if ((buses & 0xFFFFFF) != 0 && ! pcibios_assign_all_busses()) {
+		unsigned int cmax;
+		child->primary = buses & 0xFF;
+		child->secondary = (buses >> 8) & 0xFF;
+		child->subordinate = (buses >> 16) & 0xFF;
+		child->number = child->secondary;
+		cmax = pci_do_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));
+		pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
+		/*
+		 * Now we can scan all subordinate buses:
+		 */
+		max = pci_do_scan_bus(child);
+		/*
+		 * Set the subordinate bus number to its real
+		 * value:
+		 */
+		child->subordinate = max;
+		buses = (buses & 0xff00ffff)
+			| ((unsigned int)(child->subordinate) << 16);
+		pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
+	}
+	pci_write_config_word(dev, PCI_COMMAND, cr);
+	return max;
+}
 
-		if (pci_read_config_dword(dev, PCI_VENDOR_ID, &l) ||
-		    /* some broken boards return 0 if a slot is empty: */
-		    l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000)
+/*
+ * Read interrupt line and base address registers.
+ * The architecture-dependent code can tweak these, of course.
+ */
+static void __init pci_read_irq(struct pci_dev *dev)
+{
+	unsigned char irq;
+
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq);
+	if (irq)
+		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+	dev->irq = irq;
+}
+
+/*
+ * Read the config data for a PCI device, sanity-check it
+ * and fill in the dev structure...
+ */
+static struct pci_dev * __init pci_scan_device(struct pci_dev *temp)
+{
+	struct pci_dev *dev;
+	u32 l, class;
+
+	if (pci_read_config_dword(temp, PCI_VENDOR_ID, &l))
+		return NULL;
+
+	/* some broken boards return 0 or ~0 if a slot is empty: */
+	if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000)
+		return NULL;
+
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	memcpy(dev, temp, sizeof(*dev));
+	dev->vendor = l & 0xffff;
+	dev->device = (l >> 16) & 0xffff;
+	sprintf(dev->slot_name, "%02x:%02x.%d", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+	pci_name_device(dev);
+
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
+	class >>= 8;				    /* upper 3 bytes */
+	dev->class = class;
+	class >>= 8;
+
+	switch (dev->hdr_type) {		    /* header type */
+	case PCI_HEADER_TYPE_NORMAL:		    /* standard header */
+		if (class == PCI_CLASS_BRIDGE_PCI)
+			goto bad;
+		pci_read_irq(dev);
+		pci_read_bases(dev, 6, PCI_ROM_ADDRESS);
+		pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
+		pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device);
+		break;
+
+	case PCI_HEADER_TYPE_BRIDGE:		    /* bridge header */
+		if (class != PCI_CLASS_BRIDGE_PCI)
+			goto bad;
+		pci_read_bases(dev, 2, PCI_ROM_ADDRESS1);
+		break;
+
+	case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */
+		if (class != PCI_CLASS_BRIDGE_CARDBUS)
+			goto bad;
+		pci_read_irq(dev);
+		pci_read_bases(dev, 1, 0);
+		pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
+		pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);
+		break;
+
+	default:				    /* unknown header */
+		printk(KERN_ERR "PCI: device %s has unknown header type %02x, ignoring.\n",
+			dev->slot_name, dev->hdr_type);
+		kfree(dev);
+		return NULL;
+
+	bad:
+		printk(KERN_ERR "PCI: %s: class %x doesn't match header type %02x. Ignoring class.\n",
+		       dev->slot_name, class, dev->hdr_type);
+		dev->class = PCI_CLASS_NOT_DEFINED;
+	}
+
+	/* We found a fine healthy device, go go go... */
+	return dev;
+}
+
+struct pci_dev * __init pci_scan_slot(struct pci_dev *temp)
+{
+	struct pci_bus *bus = temp->bus;
+	struct pci_dev *dev;
+	struct pci_dev *first_dev = NULL;
+	int func = 0;
+	int is_multi = 0;
+	u8 hdr_type;
+
+	for (func = 0; func < 8; func++, temp->devfn++) {
+		if (func && !is_multi)		/* not a multi-function device */
+			continue;
+		if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type))
 			continue;
+		temp->hdr_type = hdr_type & 0x7f;
 
-		dev_cache = NULL;
-		dev->vendor = l & 0xffff;
-		dev->device = (l >> 16) & 0xffff;
-		sprintf(dev->slot_name, "%02x:%02x.%d", bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
-		pci_name_device(dev);
-
-		pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
-		class >>= 8;				    /* upper 3 bytes */
-		dev->class = class;
-		class >>= 8;
-		dev->hdr_type = hdr_type & 0x7f;
-
-		switch (dev->hdr_type) {		    /* header type */
-		case PCI_HEADER_TYPE_NORMAL:		    /* standard header */
-			if (class == PCI_CLASS_BRIDGE_PCI)
-				goto bad;
-			/*
-			 * Read interrupt line and base address registers.
-			 * The architecture-dependent code can tweak these, of course.
-			 */
-			pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq);
-			if (irq)
-				pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
-			dev->irq = irq;
-			pci_read_bases(dev, 6, PCI_ROM_ADDRESS);
-			pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
-			pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device);
-			break;
-		case PCI_HEADER_TYPE_BRIDGE:		    /* bridge header */
-			if (class != PCI_CLASS_BRIDGE_PCI)
-				goto bad;
-			pci_read_bases(dev, 2, PCI_ROM_ADDRESS1);
-			break;
-		case PCI_HEADER_TYPE_CARDBUS:		    /* CardBus bridge header */
-			if (class != PCI_CLASS_BRIDGE_CARDBUS)
-				goto bad;
-			pci_read_bases(dev, 1, 0);
-			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
-			pci_read_config_word(dev, PCI_CB_SUBSYSTEM_ID, &dev->subsystem_device);
-			break;
-		default:				    /* unknown header */
-			printk(KERN_ERR "PCI: device %s has unknown header type %02x, ignoring.\n",
-				dev->slot_name, hdr_type);
+		dev = pci_scan_device(temp);
+		if (!dev)
 			continue;
-		bad:
-			printk(KERN_ERR "PCI: %s: class %x doesn't match header type %02x. Ignoring class.\n",
-			       dev->slot_name, class, hdr_type);
-			dev->class = PCI_CLASS_NOT_DEFINED;
+		if (!func) {
+			is_multi = hdr_type & 0x80;
+			first_dev = dev;
 		}
 
 		DBG("PCI: %02x:%02x [%04x/%04x] %06x %02x\n", bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type);
@@ -506,122 +678,57 @@
 		 * 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;
-		}
+		*pci_last_dev_p = dev;
+		pci_last_dev_p = &dev->next;
 
 		/*
 		 * Now insert it into the list of devices held
 		 * by the parent bus.
 		 */
-		*bus_last = dev;
-		bus_last = &dev->sibling;
+		*bus->last_dev_p = dev;
+		bus->last_dev_p = &dev->sibling;
 
 		/* Fix up broken headers */
 		pci_fixup_device(PCI_FIXUP_HEADER, dev);
+	}
+	return first_dev;
+}
 
-#if 0
-		/*
-		 * Setting of latency timer in case it was less than 32 was
-		 * a great idea, but it confused several broken devices. Grrr.
-		 */
-		pci_read_config_byte(dev, PCI_LATENCY_TIMER, &tmp);
-		if (tmp < 32)
-			pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32);
-#endif
+static unsigned int __init pci_do_scan_bus(struct pci_bus *bus)
+{
+	unsigned int devfn, max;
+	struct pci_dev *dev, dev0;
+
+	DBG("pci_do_scan_bus for bus %d\n", bus->number);
+	bus->last_dev_p = &bus->devices;
+	max = bus->secondary;
+
+	/* Create a device template */
+	memset(&dev0, 0, sizeof(dev0));
+	dev0.bus = bus;
+	dev0.sysdata = bus->sysdata;
+
+	/* Go find them, Rover! */
+	for (devfn = 0; devfn < 0x100; devfn += 8) {
+		dev0.devfn = devfn;
+		pci_scan_slot(&dev0);
 	}
-	if (dev_cache)
-		kfree(dev_cache);
 
 	/*
 	 * 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 short cr;
-
-			/*
-			 * Insert it into the tree of buses.
-			 */
-			child = kmalloc(sizeof(*child), GFP_KERNEL);
-			memset(child, 0, sizeof(*child));
-			child->next = bus->children;
-			bus->children = child;
-			child->self = dev;
-			child->parent = bus;
-			child->ops = bus->ops;
-			child->sysdata = bus->sysdata;
-
-			/*
-			 * Set up the primary, secondary and subordinate
-			 * 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);
-			/*
-			 * Clear all status bits and turn off memory,
-			 * I/O and master enables.
-			 */
-			pci_read_config_word(dev, PCI_COMMAND, &cr);
-			pci_write_config_word(dev, PCI_COMMAND, 0x0000);
-			pci_write_config_word(dev, 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.
-			 */
-			pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);
-			if ((buses & 0xFFFFFF) != 0
-			    && ! pcibios_assign_all_busses())
-			  {
-			    unsigned int cmax;
-
-			    child->primary = buses & 0xFF;
-			    child->secondary = (buses >> 8) & 0xFF;
-			    child->subordinate = (buses >> 16) & 0xFF;
-			    child->number = child->secondary;
-			    cmax = pci_do_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));
-			    pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
-			    /*
-			     * Now we can scan all subordinate buses:
-			     */
-			    max = pci_do_scan_bus(child);
-			    /*
-			     * Set the subordinate bus number to its real
-			     * value:
-			     */
-			    child->subordinate = max;
-			    buses = (buses & 0xff00ffff)
-			      | ((unsigned int)(child->subordinate) << 16);
-			    pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
-			  }
-			pci_write_config_word(dev, PCI_COMMAND, cr);
+	for (dev = bus->devices; dev; dev = dev->sibling) {
+		switch (dev->class >> 8) {
+		case PCI_CLASS_BRIDGE_PCI:
+			max = pci_scan_bridge(bus, dev, max);
+			break;
+		case PCI_CLASS_BRIDGE_CARDBUS:
+			max = pci_scan_cardbus(bus, dev, max);
+			break;
 		}
+	}
 
 	/*
 	 * We've scanned the bus and so we know all about what's on
@@ -646,7 +753,7 @@
 	return 0;
 }
 
-struct pci_bus * __init pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata)
+struct pci_bus * __init pci_alloc_primary_bus(int bus)
 {
 	struct pci_bus *b, **r;
 
@@ -666,11 +773,19 @@
 	*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;
+}
+
+struct pci_bus * __init pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata)
+{
+	struct pci_bus *b = pci_alloc_primary_bus(bus);
+	if (b) {
+		b->sysdata = sysdata;
+		b->ops = ops;
+		b->subordinate = pci_do_scan_bus(b);
+	}
 	return b;
 }
 
@@ -691,9 +806,8 @@
 		if (k)
 			*k++ = 0;
 		if (*str && (str = pcibios_setup(str)) && *str) {
-			if (!strcmp(str, "reverse"))
-				pci_reverse = 1;
-			else printk(KERN_ERR "PCI: Unknown option `%s'\n", str);
+			/* PCI layer options should be handled here */
+			printk(KERN_ERR "PCI: Unknown option `%s'\n", str);
 		}
 		str = k;
 	}
diff -u --recursive --new-file v2.3.34/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids
--- v2.3.34/linux/drivers/pci/pci.ids	Mon Dec 20 18:48:21 1999
+++ linux/drivers/pci/pci.ids	Sun Dec 26 19:34:04 1999
@@ -2150,7 +2150,7 @@
 	1948  Solo?
 	1968  ES1968 Maestro 2
 	1969  ES1969 Solo-1 Audiodrive
-	1978  ES1978 Maestro Audiodrive
+	1978  ES1978 Maestro 2E
 	2808  ES336H Fax Modem (Later Model)
 	2898  ES2898 Modem
 125e  Specialvideo Engineering SRL
@@ -2216,7 +2216,7 @@
 	e886  IT8330G
 1284  Sahara Networks, Inc.
 1285  Platform Technologies, Inc.
-	0100  PT-201C-O-P AGOGO-XP sound chip
+	0100  AGOGO sound chip (aka ESS Maestro 1)
 1286  Mazet GmbH
 1287  M-Pact, Inc.
 	001e  LS220D DVD Decoder
diff -u --recursive --new-file v2.3.34/linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c
--- v2.3.34/linux/drivers/pci/pcisyms.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/pci/pcisyms.c	Sun Dec 26 10:39:19 1999
@@ -25,6 +25,8 @@
 EXPORT_SYMBOL(pci_find_slot);
 EXPORT_SYMBOL(pci_set_master);
 EXPORT_SYMBOL(pci_simple_probe);
+EXPORT_SYMBOL(pci_set_power_state);
+EXPORT_SYMBOL(pci_assign_resource);
 #ifdef	CONFIG_PROC_FS
 EXPORT_SYMBOL(pci_proc_attach_device);
 EXPORT_SYMBOL(pci_proc_detach_device);
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/Config.in linux/drivers/pcmcia/Config.in
--- v2.3.34/linux/drivers/pcmcia/Config.in	Fri Oct 22 13:21:49 1999
+++ linux/drivers/pcmcia/Config.in	Wed Dec 22 10:52:08 1999
@@ -8,8 +8,9 @@
 if [ "$CONFIG_PCMCIA" != "n" ]; then
    if [ "$CONFIG_PCI" != "n" ]; then
       bool '  CardBus support' CONFIG_CARDBUS
+      dep_tristate '  Yenta Cardbus support' CONFIG_YENTA $CONFIG_CARDBUS
    fi
-   bool '  i82365/Yenta compatible bridge support' CONFIG_I82365
+   bool '  i82365 compatible bridge support' CONFIG_I82365
    bool '  Databook TCIC host bridge support' CONFIG_TCIC
 fi
 
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/Makefile linux/drivers/pcmcia/Makefile
--- v2.3.34/linux/drivers/pcmcia/Makefile	Fri Oct 22 13:21:49 1999
+++ linux/drivers/pcmcia/Makefile	Wed Dec 22 10:54:26 1999
@@ -24,6 +24,9 @@
   ifeq ($(CONFIG_TCIC),y)
     O_OBJS += tcic.o
   endif
+  ifeq ($(CONFIG_YENTA),y)
+    OX_OBJS += yenta.o pci_socket.o
+  endif
   ifeq ($(CONFIG_CARDBUS),y)
     O_OBJS += cardbus.o
     OX_OBJS += cb_enabler.o
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/bulkmem.c linux/drivers/pcmcia/bulkmem.c
--- v2.3.34/linux/drivers/pcmcia/bulkmem.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/pcmcia/bulkmem.c	Tue Dec 21 11:41:41 1999
@@ -257,7 +257,7 @@
 	win->ctl.flags |= MAP_ATTRIB;
     win->ctl.speed = req->AccessSpeed;
     win->ctl.card_start = req->CardOffset;
-    win->sock->ss_entry(win->sock->sock, SS_SetMemMap, &win->ctl);
+    win->sock->ss_entry->set_mem_map(win->sock->sock, &win->ctl);
     return CS_SUCCESS;
 }
 
@@ -270,7 +270,7 @@
 	return CS_BAD_VPP;
     s = SOCKET(handle);
     s->socket.Vpp = req->Vpp1;
-    if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
+    if (s->ss_entry->set_socket(s->sock, &s->socket))
 	return CS_BAD_VPP;
     return CS_SUCCESS;
 }
@@ -285,7 +285,7 @@
 	s->socket.csc_mask |= SS_READY;
     else
 	s->socket.csc_mask &= ~SS_READY;
-    if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
+    if (s->ss_entry->set_socket(s->sock, &s->socket))
 	return CS_GENERAL_FAILURE;
     return CS_SUCCESS;
 }
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/cardbus.c linux/drivers/pcmcia/cardbus.c
--- v2.3.34/linux/drivers/pcmcia/cardbus.c	Thu Nov 11 20:11:42 1999
+++ linux/drivers/pcmcia/cardbus.c	Tue Dec 28 17:31:24 1999
@@ -203,7 +203,7 @@
     pci_writeb(s->cap.cardbus, 0, PCI_COMMAND, PCI_COMMAND_MEMORY);
     m->map = 0; m->flags = MAP_ACTIVE;
     m->start = base; m->stop = base+sz-1;
-    s->ss_entry(s->sock, SS_SetBridge, m);
+    s->ss_entry->set_bridge(s->sock, m);
     if ((space == 7) && (check_rom(s->cb_cis_virt, sz) == 0)) {
 	printk(KERN_NOTICE "cs: no valid ROM images found!\n");
 	return CS_READ_FAILURE;
@@ -227,7 +227,7 @@
 	br = (s->cb_cis_space == 7) ?
 	    CB_ROM_BASE : CB_BAR(s->cb_cis_space-1);
 	m->map = 0; m->flags = 0;
-	s->ss_entry(s->sock, SS_SetBridge, m);
+	s->ss_entry->set_bridge(s->sock, m);
 	pci_writeb(s->cap.cardbus, 0, PCI_COMMAND, 0);
 	pci_writel(s->cap.cardbus, 0, br, 0);
 	release_mem_region(m->start, m->stop - m->start + 1);
@@ -283,20 +283,21 @@
     u_char i, hdr, fn, bus = s->cap.cardbus;
     cb_config_t *c;
 
+    memset(&tmp, 0, sizeof(tmp));
     tmp.bus = s->cap.cb_bus; tmp.devfn = 0;
-    tmp.next = pci_devices; pci_devices = &tmp;
 
-    pci_readw(bus, 0, PCI_VENDOR_ID, &vend);
-    pci_readw(bus, 0, PCI_DEVICE_ID, &dev);
+
+    pci_read_config_word(&tmp, PCI_VENDOR_ID, &vend);
+    pci_read_config_word(&tmp, PCI_DEVICE_ID, &dev);
     printk(KERN_INFO "cs: cb_alloc(bus %d): vendor 0x%04x, "
 	   "device 0x%04x\n", bus, vend, dev);
 
-    pci_readb(bus, 0, PCI_HEADER_TYPE, &hdr);
+    pci_read_config_byte(&tmp, PCI_HEADER_TYPE, &hdr);
     if (hdr & 0x80) {
 	/* Count functions */
 	for (fn = 0; fn < 8; fn++) {
 	    tmp.devfn = fn;
-	    pci_readw(bus, fn, PCI_VENDOR_ID, &v);
+	    pci_read_config_word(&tmp, PCI_VENDOR_ID, &v);
 	    if (v != vend) break;
 	}
     } else fn = 1;
@@ -307,7 +308,6 @@
     memset(c, 0, fn * sizeof(struct cb_config_t));
     s->cb_config = c;
 
-    pci_devices = tmp.next;
     for (i = 0; i < fn; i++) {
 	c[i].dev.bus = s->cap.cb_bus;
 	c[i].dev.devfn = i;
@@ -317,7 +317,7 @@
     }
     s->cap.cb_bus->devices = &c[0].dev;
     /* Link into PCI device chain */
-    c[s->functions-1].dev.next = pci_devices;
+    c[fn-1].dev.next = pci_devices;
     pci_devices = &c[0].dev;
     for (i = 0; i < fn; i++) {
 	c[i].dev.vendor = vend;
@@ -338,17 +338,20 @@
     cb_config_t *c = s->cb_config;
 
     if (c) {
-	struct pci_dev **p, *q;
+	struct pci_dev **p;
 	/* Unlink from PCI device chain */
-	for (p = &pci_devices; *p; p = &((*p)->next))
-	    if (*p == &c[0].dev) break;
-	for (q = *p; q; q = q->next) {
-	    if (q->bus != (*p)->bus) break;
+	p = &pci_devices;
+	while (*p) {
+	    struct pci_dev * dev = *p;
+	    if (dev->bus != s->cap.cb_bus) {
+	    	p = &dev->next;
+		continue;
+	    }
+	    *p = dev->next;
 #ifdef CONFIG_PROC_FS
-	    pci_proc_detach_device(q);
+	    pci_proc_detach_device(dev);
 #endif
 	}
-	if (*p) *p = q;
 	s->cap.cb_bus->devices = NULL;
 	kfree(s->cb_config);
 	s->cb_config = NULL;
@@ -584,7 +587,7 @@
 	DEBUG(0, "  bridge %s map %d (flags 0x%x): 0x%x-0x%x\n",
 	      (m.flags & MAP_IOSPACE) ? "io" : "mem",
 	      m.map, m.flags, m.start, m.stop);
-	s->ss_entry(s->sock, SS_SetBridge, &m);
+	s->ss_entry->set_bridge(s->sock, &m);
     }
 
     /* Set up base address registers */
@@ -609,7 +612,7 @@
 	    pci_writeb(bus, i, PCI_INTERRUPT_LINE,
 		       s->irq.AssignedIRQ);
 	s->socket.io_irq = s->irq.AssignedIRQ;
-	s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+	s->ss_entry->set_socket(s->sock, &s->socket);
     }
 }
 
@@ -638,6 +641,6 @@
 	case B_M1: m.map = m.flags = 0; break;
 	case B_M2: m.map = 1; m.flags = 0; break;
 	}
-	s->ss_entry(s->sock, SS_SetBridge, &m);
+	s->ss_entry->set_bridge(s->sock, &m);
     }
 }
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/cistpl.c linux/drivers/pcmcia/cistpl.c
--- v2.3.34/linux/drivers/pcmcia/cistpl.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/pcmcia/cistpl.c	Tue Dec 21 11:43:21 1999
@@ -101,7 +101,7 @@
     mem->card_start = addr & ~(s->cap.map_size-1);
 
     for (; len > 0; sys = s->cis_virt) {
-	s->ss_entry(s->sock, SS_SetMemMap, mem);
+	s->ss_entry->set_mem_map(s->sock, mem);
 	DEBUG(3,  "cs:  %#2.2x %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
 	      bus_readb(s->cap.bus, sys),
 	      bus_readb(s->cap.bus, sys+inc),
@@ -131,7 +131,7 @@
     mem->card_start = addr & ~(s->cap.map_size-1);
     
     for (; len > 0; sys = s->cis_virt) {
-	s->ss_entry(s->sock, SS_SetMemMap, mem);
+	s->ss_entry->set_mem_map(s->sock, mem);
 	for ( ; len > 0; len--, ((u_char *)ptr)++, sys += inc) {
 	    if (sys == s->cis_virt+s->cap.map_size) break;
 	    bus_writeb(s->cap.bus, *(u_char *)ptr, sys);
@@ -181,7 +181,7 @@
     vs->cis_virt = bus_ioremap(vs->cap.bus, base, vs->cap.map_size);
     vs->cis_mem.card_start = 0;
     vs->cis_mem.flags = MAP_ACTIVE;
-    vs->ss_entry(vs->sock, SS_SetMemMap, &vs->cis_mem);
+    vs->ss_entry->set_mem_map(vs->sock, &vs->cis_mem);
     /* Don't bother checking every word... */
     a = 0; b = -1;
     for (i = 0; i < vs->cap.map_size; i += 44) {
@@ -223,7 +223,7 @@
 {
     if (s->cis_mem.sys_start != 0) {
 	s->cis_mem.flags &= ~MAP_ACTIVE;
-	s->ss_entry(s->sock, SS_SetMemMap, &s->cis_mem);
+	s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
 	release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
 	bus_iounmap(s->cap.bus, s->cis_virt);
 	s->cis_mem.sys_start = 0;
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- v2.3.34/linux/drivers/pcmcia/cs.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/pcmcia/cs.c	Tue Dec 21 21:18:54 1999
@@ -242,6 +242,42 @@
 
 /*======================================================================
 
+ These functions are just shorthand for the actual low-level drivers
+
+======================================================================*/
+
+static int register_callback(socket_info_t *s, void (*handler)(void *, unsigned int), void * info)
+{
+	return s->ss_entry->register_callback(s->sock, handler, info);
+}
+
+static int get_socket_status(socket_info_t *s, int *val)
+{
+	return s->ss_entry->get_status(s->sock, val);
+}
+
+static int set_socket(socket_info_t *s, socket_state_t *state)
+{
+	return s->ss_entry->set_socket(s->sock, state);
+}
+
+static int get_io_map(socket_info_t *s, struct pccard_io_map *io)
+{
+	return s->ss_entry->get_io_map(s->sock, io);
+}
+
+static int set_io_map(socket_info_t *s, struct pccard_io_map *io)
+{
+	return s->ss_entry->set_io_map(s->sock, io);
+}
+
+static int set_mem_map(socket_info_t *s, struct pccard_mem_map *mem)
+{
+	return s->ss_entry->set_mem_map(s->sock, mem);
+}
+
+/*======================================================================
+
     Reset a socket to the default state
     
 ======================================================================*/
@@ -254,14 +290,14 @@
 
     mem.sys_stop = s->cap.map_size;
     s->socket = dead_socket;
-    s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+    set_socket(s, &s->socket);
     for (i = 0; i < 2; i++) {
 	io.map = i;
-	s->ss_entry(s->sock, SS_SetIOMap, &io);
+	set_io_map(s, &io);
     }
     for (i = 0; i < 5; i++) {
 	mem.map = i;
-	s->ss_entry(s->sock, SS_SetMemMap, &mem);
+	set_mem_map(s, &mem);
     }
 }
 
@@ -295,7 +331,7 @@
 static void unreset_socket(u_long i);
 static void parse_events(void *info, u_int events);
 
-int register_ss_entry(int nsock, ss_entry_t ss_entry)
+int register_ss_entry(int nsock, struct pccard_operations * ss_entry)
 {
     int i, ns;
     socket_info_t *s;
@@ -324,7 +360,7 @@
 	if (i == sockets) sockets++;
 
 	init_socket(s);
-	ss_entry(ns, SS_InquireSocket, &s->cap);
+	ss_entry->inquire_socket(ns, &s->cap);
 #ifdef CONFIG_PROC_FS
 	if (proc_pccard) {
 	    char name[3];
@@ -333,7 +369,7 @@
 #ifdef PCMCIA_DEBUG
 	    create_proc_read_entry("clients",0,s->proc,proc_read_clients,s);
 #endif
-	    ss_entry(ns, SS_ProcSetup, s->proc);
+	    ss_entry->proc_setup(ns, s->proc);
 	}
 #endif
     }
@@ -343,7 +379,7 @@
 
 /*====================================================================*/
 
-void unregister_ss_entry(ss_entry_t ss_entry)
+void unregister_ss_entry(struct pccard_operations * ss_entry)
 {
     int i, j;
     socket_info_t *s = NULL;
@@ -454,7 +490,7 @@
     int val;
     socket_info_t *s = socket_table[i];
 
-    s->ss_entry(s->sock, SS_GetStatus, &val);
+    get_socket_status(s, &val);
     if (val & SS_DETECT) {
 	DEBUG(1, "cs: setup_socket(%ld): applying power\n", i);
 	s->state |= SOCKET_PRESENT;
@@ -474,7 +510,7 @@
 	    printk(KERN_NOTICE "cs: unsupported card type detected!\n");
 #endif
 	}
-	s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+	set_socket(s, &s->socket);
 	s->setup.function = &reset_socket;
 	s->setup.expires = jiffies + vcc_settle;
 	add_timer(&s->setup);
@@ -497,10 +533,10 @@
 
     DEBUG(1, "cs: resetting socket %ld\n", i);
     s->socket.flags |= SS_OUTPUT_ENA | SS_RESET;
-    s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+    set_socket(s, &s->socket);
     udelay((long)reset_time);
     s->socket.flags &= ~SS_RESET;
-    s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+    set_socket(s, &s->socket);
     s->unreset_timeout = 0;
     s->setup.expires = jiffies + unreset_delay;
     s->setup.function = &unreset_socket;
@@ -515,7 +551,7 @@
     socket_info_t *s = socket_table[i];
     int val;
 
-    s->ss_entry(s->sock, SS_GetStatus, &val);
+    get_socket_status(s, &val);
     if (val & SS_READY) {
 	DEBUG(1, "cs: reset done on socket %ld\n", i);
 	if (s->state & SOCKET_SUSPEND) {
@@ -607,7 +643,7 @@
 	int status;
 	u_long flags;
 	spin_lock_irqsave(&s->lock, flags);
-	s->ss_entry(s->sock, SS_GetStatus, &status);
+	get_socket_status(s, &status);
 	if ((s->state & SOCKET_PRESENT) &&
 	    (!(s->state & SOCKET_SUSPEND) ||
 	     !(status & SS_DETECT)))
@@ -668,7 +704,7 @@
 	    if ((s->state & SOCKET_PRESENT) &&
 		!(s->state & SOCKET_SUSPEND)){
 		send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
-		s->ss_entry(s->sock, SS_SetSocket, &dead_socket);
+		set_socket(s, &dead_socket);
 		s->state |= SOCKET_SUSPEND;
 	    }
 	}
@@ -685,7 +721,7 @@
 	    s = socket_table[i];
 	    /* Do this just to reinitialize the socket */
 	    init_socket(s);
-	    s->ss_entry(s->sock, SS_GetStatus, &stat);
+	    get_socket_status(s, &stat);
 	    /* If there was or is a card here, we need to do something
 	       about it... but parse_events will sort it all out. */
        	    if ((s->state & SOCKET_PRESENT) || (stat & SS_DETECT))
@@ -939,7 +975,7 @@
     }
 
     if (--s->real_clients == 0)
-	s->ss_entry(sn, SS_RegisterCallback, NULL);
+        register_callback(s, NULL, NULL);
     
     return CS_SUCCESS;
 } /* deregister_client */
@@ -1134,7 +1170,7 @@
     if (CHECK_HANDLE(handle))
 	return CS_BAD_HANDLE;
     s = SOCKET(handle);
-    s->ss_entry(s->sock, SS_GetStatus, &val);
+    get_socket_status(s, &val);
     status->CardState = status->SocketState = 0;
     status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
     status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
@@ -1213,7 +1249,7 @@
 	return CS_BAD_PAGE;
     s = win->sock;
     win->ctl.card_start = req->CardOffset;
-    if (s->ss_entry(s->sock, SS_SetMemMap, &win->ctl) != 0)
+    if (set_mem_map(s, &win->ctl) != 0)
 	return CS_BAD_OFFSET;
     return CS_SUCCESS;
 } /* map_mem_page */
@@ -1246,7 +1282,7 @@
 	    c->Attributes &= ~CONF_ENABLE_IRQ;
 	    s->socket.io_irq = 0;
 	}
-	s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+	set_socket(s, &s->socket);
     }
 
     if (mod->Attributes & CONF_VCC_CHANGE_VALID)
@@ -1258,7 +1294,7 @@
 	if (mod->Vpp1 != mod->Vpp2)
 	    return CS_BAD_VPP;
 	c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1;
-	if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
+	if (set_socket(s, &s->socket))
 	    return CS_BAD_VPP;
     } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
 	       (mod->Attributes & CONF_VPP2_CHANGE_VALID))
@@ -1288,7 +1324,7 @@
     if (req->Attributes & WIN_USE_WAIT)
 	win->ctl.flags |= MAP_USE_WAIT;
     win->ctl.speed = req->AccessSpeed;
-    win->sock->ss_entry(win->sock->sock, SS_SetMemMap, &win->ctl);
+    set_mem_map(win->sock, &win->ctl);
     
     return CS_SUCCESS;
 } /* modify_window */
@@ -1324,12 +1360,9 @@
 
     s = socket_table[ns];
     if (++s->real_clients == 1) {
-	ss_callback_t call;
 	int status;
-	call.handler = &parse_events;
-	call.info = s;
-	s->ss_entry(ns, SS_RegisterCallback, &call);
-	s->ss_entry(ns, SS_GetStatus, &status);
+	register_callback(s, &parse_events, s);
+	get_socket_status(s, &status);
 	if ((status & SS_DETECT) &&
 	    !(s->state & SOCKET_SETUP_PENDING)) {
 	    s->state |= SOCKET_SETUP_PENDING;
@@ -1405,7 +1438,7 @@
 	    s->socket.flags = SS_OUTPUT_ENA;
 	    s->socket.Vpp = 0;
 	    s->socket.io_irq = 0;
-	    s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+	    set_socket(s, &s->socket);
 	}
 	if (c->state & CONFIG_IO_REQ)
 	    for (i = 0; i < MAX_IO_WIN; i++) {
@@ -1415,9 +1448,9 @@
 		if (s->io[i].Config != 0)
 		    continue;
 		io.map = i;
-		s->ss_entry(s->sock, SS_GetIOMap, &io);
+		get_io_map(s, &io);
 		io.flags &= ~MAP_ACTIVE;
-		s->ss_entry(s->sock, SS_SetIOMap, &io);
+		set_io_map(s, &io);
 	    }
 	c->state &= ~CONFIG_LOCKED;
     }
@@ -1520,7 +1553,7 @@
 
     /* Shut down memory window */
     win->ctl.flags &= ~MAP_ACTIVE;
-    s->ss_entry(s->sock, SS_SetMemMap, &win->ctl);
+    set_mem_map(s, &win->ctl);
     s->state &= ~SOCKET_WIN_REQ(win->index);
 
     /* Release system memory */
@@ -1574,7 +1607,7 @@
     if (req->Vpp1 != req->Vpp2)
 	return CS_BAD_VPP;
     s->socket.Vpp = req->Vpp1;
-    if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
+    if (set_socket(s, &s->socket))
 	return CS_BAD_VPP;
     
     c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
@@ -1592,7 +1625,7 @@
 	s->socket.io_irq = s->irq.AssignedIRQ;
     else
 	s->socket.io_irq = 0;
-    s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+    set_socket(s, &s->socket);
     s->lock_count++;
     
     /* Set up CIS configuration registers */
@@ -1655,7 +1688,7 @@
 		}
 		iomap.start = s->io[i].BasePort;
 		iomap.stop = iomap.start + s->io[i].NumPorts - 1;
-		s->ss_entry(s->sock, SS_SetIOMap, &iomap);
+		set_io_map(s, &iomap);
 		s->io[i].Config++;
 	    }
     }
@@ -1871,7 +1904,7 @@
     win->ctl.sys_start = req->Base;
     win->ctl.sys_stop = req->Base + req->Size-1;
     win->ctl.card_start = 0;
-    if (s->ss_entry(s->sock, SS_SetMemMap, &win->ctl) != 0)
+    if (set_mem_map(s, &win->ctl) != 0)
 	return CS_BAD_ARGS;
     s->state |= SOCKET_WIN_REQ(w);
 
@@ -1939,7 +1972,7 @@
 
     DEBUG(1, "cs: suspending socket %d\n", i);
     send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
-    s->ss_entry(s->sock, SS_SetSocket, &dead_socket);
+    set_socket(s, &dead_socket);
     s->state |= SOCKET_SUSPEND;
 
     return CS_SUCCESS;
@@ -2014,7 +2047,7 @@
     if (!(s->state & SOCKET_SETUP_PENDING)) {
 	s->state |= SOCKET_SETUP_PENDING;
 	spin_unlock_irqrestore(&s->lock, flags);
-	s->ss_entry(i, SS_GetStatus, &status);
+	get_socket_status(s, &status);
 	if (status & SS_DETECT)
 	    setup_socket(i);
 	else {
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/cs_internal.h linux/drivers/pcmcia/cs_internal.h
--- v2.3.34/linux/drivers/pcmcia/cs_internal.h	Thu Nov 18 20:25:37 1999
+++ linux/drivers/pcmcia/cs_internal.h	Tue Dec 28 17:43:36 1999
@@ -120,7 +120,7 @@
 
 typedef struct socket_info_t {
     spinlock_t			lock;
-    ss_entry_t			ss_entry;
+    struct pccard_operations *	ss_entry;
     u_int			sock;
     socket_state_t		socket;
     socket_cap_t		cap;
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c
--- v2.3.34/linux/drivers/pcmcia/i82365.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/pcmcia/i82365.c	Sun Dec 26 12:33:09 1999
@@ -66,7 +66,7 @@
 #include "o2micro.h"
 
 /* PCI-bus controllers */
-#include "yenta.h"
+#include "old-yenta.h"
 #include "ti113x.h"
 #include "smc34c90.h"
 #include "topic.h"
@@ -159,8 +159,6 @@
 #ifdef CONFIG_PCI
 /* Scan PCI bus? */
 static int do_pci_probe = 1;
-/* Default memory base address for CardBus controllers */
-static u_int cb_mem_base[] = { 0x68000000, 0xf8000000 };
 static int fast_pci = -1;
 static int hold_time = -1;
 /* Override BIOS interrupt routing mode? */
@@ -173,7 +171,6 @@
 static int cb_bus_step = 2;
 static int cb_write_post = -1;
 MODULE_PARM(do_pci_probe, "i");
-MODULE_PARM(cb_mem_base, "i");
 MODULE_PARM(fast_pci, "i");
 MODULE_PARM(hold_time, "i");
 MODULE_PARM(irq_mode, "i");
@@ -249,11 +246,11 @@
     struct proc_dir_entry *proc;
 #endif
 #ifdef CONFIG_PCI
-    u_short		vendor, device;
-    u_char		revision, bus, devfn;
+    struct pci_dev	*pdev;
+    u_char		revision;
     u_short		bcr;
     u_char		pci_lat, cb_lat, sub_bus;
-    u_char		cache, pmcs;
+    u_char		cache;
     u_int		cb_phys;
     char		*cb_virt;
 #endif
@@ -294,24 +291,10 @@
 
 /*====================================================================*/
 
-#ifdef CONFIG_PCI
-
-#ifndef PCI_VENDOR_ID_INTEL
-#define PCI_VENDOR_ID_INTEL		0x8086
-#endif
-#ifndef PCI_VENDOR_ID_OMEGA
-#define PCI_VENDOR_ID_OMEGA		0x119b
-#endif
-#ifndef PCI_DEVICE_ID_OMEGA_PCMCIA
-#define PCI_DEVICE_ID_OMEGA_PCMCIA	0x1221
-#endif
-
 /* Default settings for PCI command configuration register */
 #define CMD_DFLT (PCI_COMMAND_IO|PCI_COMMAND_MEMORY| \
 		  PCI_COMMAND_MASTER|PCI_COMMAND_WAIT)
 
-#endif
-
 /* These definitions must match the pcic table! */
 typedef enum pcic_id {
 #ifdef CONFIG_ISA
@@ -379,9 +362,9 @@
     { "O2Micro OZ6730", IS_O2MICRO|IS_PCI|IS_VG_PWR,
       PCI_VENDOR_ID_O2, PCI_DEVICE_ID_O2_6730 },
     { "Intel 82092AA", IS_PCI,
-      PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_OMEGA_PCMCIA },
+      PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82092AA_0 },
     { "Omega Micro 82C092G", IS_PCI,
-      PCI_VENDOR_ID_OMEGA, PCI_DEVICE_ID_OMEGA_PCMCIA },
+      PCI_VENDOR_ID_OMEGA, PCI_DEVICE_ID_OMEGA_82C092G },
     { "Cirrus PD6832", IS_CIRRUS|IS_CARDBUS,
       PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832 },
     { "O2Micro OZ6832/OZ6833", IS_O2MICRO|IS_CARDBUS|IS_VG_PWR,
@@ -443,12 +426,12 @@
 
 /* Some PCI shortcuts */
 
-#define pci_readb		pcibios_read_config_byte
-#define pci_writeb		pcibios_write_config_byte
-#define pci_readw		pcibios_read_config_word
-#define pci_writew		pcibios_write_config_word
-#define pci_readl		pcibios_read_config_dword
-#define pci_writel		pcibios_write_config_dword
+#define config_readb(sock, r, v)	pci_read_config_byte((sock)->pdev, r, v)
+#define config_readw(sock, r, v)	pci_read_config_word((sock)->pdev, r, v)
+#define config_readl(sock, r, v)	pci_read_config_dword((sock)->pdev, r, v)
+#define config_writeb(sock, r, v)	pci_write_config_byte((sock)->pdev, r, v)
+#define config_writew(sock, r, v)	pci_write_config_word((sock)->pdev, r, v)
+#define config_writel(sock, r, v)	pci_write_config_dword((sock)->pdev, r, v)
 
 #define cb_readb(s, r)		readb(socket[s].cb_virt + (r))
 #define cb_readl(s, r)		readl(socket[s].cb_virt + (r))
@@ -701,21 +684,21 @@
 {
     socket_info_t *t = &socket[s];
     ti113x_state_t *p = &socket[s].state.ti113x;
-    pci_readl(t->bus, t->devfn, TI113X_SYSTEM_CONTROL, &p->sysctl);
-    pci_readb(t->bus, t->devfn, TI113X_CARD_CONTROL, &p->cardctl);
-    pci_readb(t->bus, t->devfn, TI113X_DEVICE_CONTROL, &p->devctl);
-    pci_readb(t->bus, t->devfn, TI1250_DIAGNOSTIC, &p->diag);
+    config_readl(t, TI113X_SYSTEM_CONTROL, &p->sysctl);
+    config_readb(t, TI113X_CARD_CONTROL, &p->cardctl);
+    config_readb(t, TI113X_DEVICE_CONTROL, &p->devctl);
+    config_readb(t, TI1250_DIAGNOSTIC, &p->diag);
 }
 
 static void ti113x_set_state(u_short s)
 {
     socket_info_t *t = &socket[s];
     ti113x_state_t *p = &socket[s].state.ti113x;
-    pci_writel(t->bus, t->devfn, TI113X_SYSTEM_CONTROL, p->sysctl);
-    pci_writeb(t->bus, t->devfn, TI113X_CARD_CONTROL, p->cardctl);
-    pci_writeb(t->bus, t->devfn, TI113X_DEVICE_CONTROL, p->devctl);
-    pci_writeb(t->bus, t->devfn, TI1250_MULTIMEDIA_CTL, 0);
-    pci_writeb(t->bus, t->devfn, TI1250_DIAGNOSTIC, p->diag);
+    config_writel(t, TI113X_SYSTEM_CONTROL, p->sysctl);
+    config_writeb(t, TI113X_CARD_CONTROL, p->cardctl);
+    config_writeb(t, TI113X_DEVICE_CONTROL, p->devctl);
+    config_writeb(t, TI1250_MULTIMEDIA_CTL, 0);
+    config_writeb(t, TI1250_DIAGNOSTIC, p->diag);
     i365_set_pair(s, TI113X_IO_OFFSET(0), 0);
     i365_set_pair(s, TI113X_IO_OFFSET(1), 0);
 }
@@ -822,20 +805,20 @@
 {
     socket_info_t *t = &socket[s];
     rl5c4xx_state_t *p = &socket[s].state.rl5c4xx;
-    pci_readw(t->bus, t->devfn, RL5C4XX_MISC, &p->misc);
-    pci_readw(t->bus, t->devfn, RL5C4XX_16BIT_CTL, &p->ctl);
-    pci_readw(t->bus, t->devfn, RL5C4XX_16BIT_IO_0, &p->io);
-    pci_readw(t->bus, t->devfn, RL5C4XX_16BIT_MEM_0, &p->mem);
+    config_readw(t, RL5C4XX_MISC, &p->misc);
+    config_readw(t, RL5C4XX_16BIT_CTL, &p->ctl);
+    config_readw(t, RL5C4XX_16BIT_IO_0, &p->io);
+    config_readw(t, RL5C4XX_16BIT_MEM_0, &p->mem);
 }
 
 static void rl5c4xx_set_state(u_short s)
 {
     socket_info_t *t = &socket[s];
     rl5c4xx_state_t *p = &socket[s].state.rl5c4xx;
-    pci_writew(t->bus, t->devfn, RL5C4XX_MISC, p->misc);
-    pci_writew(t->bus, t->devfn, RL5C4XX_16BIT_CTL, p->ctl);
-    pci_writew(t->bus, t->devfn, RL5C4XX_16BIT_IO_0, p->io);
-    pci_writew(t->bus, t->devfn, RL5C4XX_16BIT_MEM_0, p->mem);
+    config_writew(t, RL5C4XX_MISC, p->misc);
+    config_writew(t, RL5C4XX_16BIT_CTL, p->ctl);
+    config_writew(t, RL5C4XX_16BIT_IO_0, p->io);
+    config_writew(t, RL5C4XX_16BIT_MEM_0, p->mem);
 }
 
 static u_int __init rl5c4xx_set_opts(u_short s, char *buf)
@@ -986,20 +969,20 @@
 {
     socket_info_t *t = &socket[s];
     topic_state_t *p = &socket[s].state.topic;
-    pci_readb(t->bus, t->devfn, TOPIC_SLOT_CONTROL, &p->slot);
-    pci_readb(t->bus, t->devfn, TOPIC_CARD_CONTROL, &p->ccr);
-    pci_readb(t->bus, t->devfn, TOPIC_CARD_DETECT, &p->cdr);
-    pci_readl(t->bus, t->devfn, TOPIC_REGISTER_CONTROL, &p->rcr);
+    config_readb(t, TOPIC_SLOT_CONTROL, &p->slot);
+    config_readb(t, TOPIC_CARD_CONTROL, &p->ccr);
+    config_readb(t, TOPIC_CARD_DETECT, &p->cdr);
+    config_readl(t, TOPIC_REGISTER_CONTROL, &p->rcr);
 }
 
 static void topic_set_state(u_short s)
 {
     socket_info_t *t = &socket[s];
     topic_state_t *p = &socket[s].state.topic;
-    pci_writeb(t->bus, t->devfn, TOPIC_SLOT_CONTROL, p->slot);
-    pci_writeb(t->bus, t->devfn, TOPIC_CARD_CONTROL, p->ccr);
-    pci_writeb(t->bus, t->devfn, TOPIC_CARD_DETECT, p->cdr);
-    pci_writel(t->bus, t->devfn, TOPIC_REGISTER_CONTROL, p->rcr);
+    config_writeb(t, TOPIC_SLOT_CONTROL, p->slot);
+    config_writeb(t, TOPIC_CARD_CONTROL, p->ccr);
+    config_writeb(t, TOPIC_CARD_DETECT, p->cdr);
+    config_writel(t, TOPIC_REGISTER_CONTROL, p->rcr);
 }
 
 static int topic_set_irq_mode(u_short s, int pcsc, int pint)
@@ -1040,33 +1023,28 @@
 {
     socket_info_t *t = &socket[s];
     
-    pci_readb(t->bus, t->devfn, PCI_CACHE_LINE_SIZE, &t->cache);
-    pci_readb(t->bus, t->devfn, PCI_LATENCY_TIMER, &t->pci_lat);
-    pci_readb(t->bus, t->devfn, CB_LATENCY_TIMER, &t->cb_lat);
-    pci_readb(t->bus, t->devfn, CB_CARDBUS_BUS, &t->cap.cardbus);
-    pci_readb(t->bus, t->devfn, CB_SUBORD_BUS, &t->sub_bus);
-    pci_readw(t->bus, t->devfn, CB_BRIDGE_CONTROL, &t->bcr);
-    {
-	struct pci_dev *pdev = pci_find_slot(t->bus, t->devfn);
-	t->cap.pci_irq = (pdev) ? pdev->irq : 0;
-    }
-    if (t->cap.pci_irq >= NR_IRQS) t->cap.pci_irq = 0;
+    config_readb(t, PCI_CACHE_LINE_SIZE, &t->cache);
+    config_readb(t, PCI_LATENCY_TIMER, &t->pci_lat);
+    config_readb(t, CB_LATENCY_TIMER, &t->cb_lat);
+    config_readb(t, CB_CARDBUS_BUS, &t->cap.cardbus);
+    config_readb(t, CB_SUBORD_BUS, &t->sub_bus);
+    config_readw(t, CB_BRIDGE_CONTROL, &t->bcr);
+    t->cap.pci_irq = t->pdev->irq;
 }
 
 static void cb_set_state(u_short s)
 {
     socket_info_t *t = &socket[s];
-    if (t->pmcs)
-	pci_writew(t->bus, t->devfn, t->pmcs, PCI_PMCS_PWR_STATE_D0);
-    pci_writel(t->bus, t->devfn, CB_LEGACY_MODE_BASE, 0);
-    pci_writel(t->bus, t->devfn, PCI_BASE_ADDRESS_0, t->cb_phys);
-    pci_writew(t->bus, t->devfn, PCI_COMMAND, CMD_DFLT);
-    pci_writeb(t->bus, t->devfn, PCI_CACHE_LINE_SIZE, t->cache);
-    pci_writeb(t->bus, t->devfn, PCI_LATENCY_TIMER, t->pci_lat);
-    pci_writeb(t->bus, t->devfn, CB_LATENCY_TIMER, t->cb_lat);
-    pci_writeb(t->bus, t->devfn, CB_CARDBUS_BUS, t->cap.cardbus);
-    pci_writeb(t->bus, t->devfn, CB_SUBORD_BUS, t->sub_bus);
-    pci_writew(t->bus, t->devfn, CB_BRIDGE_CONTROL, t->bcr);
+    pci_set_power_state(t->pdev, 0);	/* FIXME: Do we really need all of this? */
+    config_writel(t, CB_LEGACY_MODE_BASE, 0);
+    config_writel(t, PCI_BASE_ADDRESS_0, t->cb_phys);
+    config_writew(t, PCI_COMMAND, CMD_DFLT);
+    config_writeb(t, PCI_CACHE_LINE_SIZE, t->cache);
+    config_writeb(t, PCI_LATENCY_TIMER, t->pci_lat);
+    config_writeb(t, CB_LATENCY_TIMER, t->cb_lat);
+    config_writeb(t, CB_CARDBUS_BUS, t->cap.cardbus);
+    config_writeb(t, CB_SUBORD_BUS, t->sub_bus);
+    config_writew(t, CB_BRIDGE_CONTROL, t->bcr);
 }
 
 static int cb_get_irq_mode(u_short s)
@@ -1500,13 +1478,11 @@
     printk(KERN_INFO "  %s", pcic[type].name);
 #ifdef CONFIG_PCI
     if (t->flags & IS_UNKNOWN)
-	printk(" [0x%04x 0x%04x]", t->vendor, t->device);
+	printk(" [0x%04x 0x%04x]", t->pdev->vendor, t->pdev->device);
     if (t->flags & IS_CARDBUS)
-	printk(" PCI-to-CardBus at bus %d slot %d, mem 0x%08x",
-	       t->bus, PCI_SLOT(t->devfn), t->cb_phys);
+	printk(" PCI-to-CardBus at %s, mem 0x%08x", t->pdev->slot_name, t->cb_phys);
     else if (t->flags & IS_PCI)
-	printk(" PCI-to-PCMCIA at bus %d slot %d, port %#x",
-	       t->bus, PCI_SLOT(t->devfn), t->ioaddr);
+	printk(" PCI-to-PCMCIA at %s, port %#x", t->pdev->slot_name, t->ioaddr);
     else
 #endif
 	printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
@@ -1596,107 +1572,50 @@
 
 #ifdef CONFIG_PCI
 
-typedef struct pci_dev *pci_id_t;
-static int __init pci_lookup(u_int class, pci_id_t *id,
-			     u_char *bus, u_char *devfn)
-{
-    if ((*id = pci_find_class(class<<8, *id)) != NULL) {
-	*bus = (*id)->bus->number;
-	*devfn = (*id)->devfn;
-	return 0;
-    } else return -1;
-}
-
-static void __init add_pci_bridge(int type, u_char bus, u_char devfn,
-				  u_short v, u_short d)
+static void __init add_pci_bridge(int type, struct pci_dev *dev)
 {
     socket_info_t *s = &socket[sockets];
     u_short i, ns;
-    u_int addr;
+    u32 addr = dev->resource[0].start;
 
     if (type == PCIC_COUNT) type = IS_UNK_PCI;
-    pci_readl(bus, devfn, PCI_BASE_ADDRESS_0, &addr);
-    addr &= ~0x1;
-    pci_writew(bus, devfn, PCI_COMMAND, CMD_DFLT);
+    pci_write_config_word(dev, PCI_COMMAND, CMD_DFLT);
     for (i = ns = 0; i < ((type == IS_I82092AA) ? 4 : 2); i++) {
-	s->bus = bus; s->devfn = devfn;
-	s->vendor = v; s->device = d;
+	s->pdev = dev;
 	add_socket(addr, i, type);
 	ns++; s++;
     }
     add_pcic(ns, type);
 }
 
-static void __init add_cb_bridge(int type, u_char bus, u_char devfn,
-				 u_short v, u_short d0)
+static void __init add_cb_bridge(int type, struct pci_dev *dev0)
 {
     socket_info_t *s = &socket[sockets];
-    u_short d, ns, i;
-    u_char a, b, r, max;
+    u_short i, ns;
+    u_char a, b;
     
-    /* PCI bus enumeration is broken on some systems */
-    for (ns = 0; ns < sockets; ns++)
-	if ((socket[ns].bus == bus) && (socket[ns].devfn == devfn))
-	    return;
-    
-    if (type == PCIC_COUNT) type = IS_UNK_CARDBUS;
-    pci_readb(bus, devfn, PCI_HEADER_TYPE, &a);
-    pci_readb(bus, devfn, PCI_CLASS_REVISION, &r);
-    max = (a & 0x80) ? 8 : 1;
-    for (ns = 0; ns < max; ns++, s++, devfn++) {
-	if (pci_readw(bus, devfn, PCI_DEVICE_ID, &d) || (d != d0))
-	    break;
-	s->bus = bus; s->devfn = devfn;
-	s->vendor = v; s->device = d; s->revision = r;
-	
-	/* Check for power management capabilities */
-	pci_readb(bus, devfn, PCI_STATUS, &a);
-	if (a & PCI_STATUS_CAPLIST) {
-	    pci_readb(bus, devfn, PCI_CB_CAPABILITY_POINTER, &b);
-	    while (b != 0) {
-		pci_readb(bus, devfn, b+PCI_CAPABILITY_ID, &a);
-		if (a == PCI_CAPABILITY_PM) {
-		    s->pmcs = b + PCI_PM_CONTROL_STATUS;
-		    break;
-		}
-		pci_readb(bus, devfn, b+PCI_NEXT_CAPABILITY, &b);
-	    }
-	}
-	/* If capability exists, make sure we're in D0 state */
-	if (s->pmcs)
-	    pci_writew(bus, devfn, s->pmcs, PCI_PMCS_PWR_STATE_D0);
-	
-	/* Map CardBus registers if they are not already mapped */
-	pci_writel(bus, devfn, CB_LEGACY_MODE_BASE, 0);
-	pci_readl(bus, devfn, PCI_BASE_ADDRESS_0, &s->cb_phys);
-	if (s->cb_phys == 0) {
-	    pci_writew(bus, devfn, PCI_COMMAND, CMD_DFLT);
-	    for (i = 0; i < sizeof(cb_mem_base)/sizeof(u_int); i++) {
-		s->cb_phys = cb_mem_base[i];
-		s->cb_virt = ioremap(s->cb_phys, 0x1000);
-		pci_writel(bus, devfn, PCI_BASE_ADDRESS_0, s->cb_phys);
-		/* Simple sanity checks */
-		if (!(readb(s->cb_virt+0x800+I365_IDENT) & 0x70) &&
-		    !(readb(s->cb_virt+0x800+I365_CSC) &&
-		      readb(s->cb_virt+0x800+I365_CSC) &&
-		      readb(s->cb_virt+0x800+I365_CSC)))
-		    break;
-		iounmap(s->cb_virt);
-	    }
-	    if (i == sizeof(cb_mem_base)/sizeof(u_int)) {
-		pci_writel(bus, devfn, PCI_BASE_ADDRESS_0, 0);
-		s->cb_phys = 0; s->cb_virt = NULL;
-		printk("\n");
-		printk(KERN_NOTICE "  Bridge register mapping failed:"
-		       " check cb_mem_base setting\n");
+    if (type == PCIC_COUNT)
+    	type = IS_UNK_CARDBUS;
+
+    for (ns = 0; ns < 8; ns++, s++) {
+	struct pci_dev *dev;
+
+	dev = pci_find_slot(dev0->bus->number, dev0->devfn + ns);
+	if (!dev)
 		break;
-	    }
-	    cb_mem_base[0] = cb_mem_base[i] + PAGE_SIZE;
-	} else {
-	    s->cb_virt = ioremap(s->cb_phys, 0x1000);
+	s->pdev = dev;
+	pci_read_config_byte(dev, PCI_CLASS_REVISION, &s->revision);
+
+	/* Map CardBus registers if they are not already mapped */
+	pci_write_config_dword(dev, CB_LEGACY_MODE_BASE, 0);
+	s->cb_phys = dev->resource[0].start;
+	if (!s->cb_phys || !(s->cb_virt = ioremap(s->cb_phys, 0x1000))) {
+	    printk("\n");
+	    printk(KERN_ERR "  No control registers found!\n");
+	    break;
 	}
-	
 	request_mem_region(s->cb_phys, 0x1000, "i82365");
+	s->cap.cb_bus = dev->subordinate;
 	add_socket(0, 0, type);
     }
     if (ns == 0) return;
@@ -1704,11 +1623,11 @@
     s -= ns;
     if (ns == 2) {
 	/* Nasty special check for bad bus mapping */
-	pci_readb(bus, s[0].devfn, CB_CARDBUS_BUS, &a);
-	pci_readb(bus, s[1].devfn, CB_CARDBUS_BUS, &b);
+	config_readb(&s[0], CB_CARDBUS_BUS, &a);
+	config_readb(&s[1], CB_CARDBUS_BUS, &b);
 	if (a == b) {
-	    pci_writeb(bus, s[0].devfn, CB_CARDBUS_BUS, 0);
-	    pci_writeb(bus, s[1].devfn, CB_CARDBUS_BUS, 0);
+	    config_writeb(&s[0], CB_CARDBUS_BUS, 0);
+	    config_writeb(&s[1], CB_CARDBUS_BUS, 0);
 	}
     }
     add_pcic(ns, type);
@@ -1728,43 +1647,19 @@
     if (i == 200)
 	printk(KERN_NOTICE "i82365: card voltage interrogation"
 	       " timed out!\n");
-
-    /* Set up PCI bus bridge structures if needed */
-    for (a = 0; a < ns; a++) {
-	struct pci_dev *self = pci_find_slot(bus, s[a].devfn);
-	struct pci_bus *child, *parent = self->bus;
-	for (child = parent->children; child; child = child->next)
-	    if (child->number == s[a].cap.cardbus) break;
-	if (!child) {
-	    child = kmalloc(sizeof(struct pci_bus), GFP_KERNEL);
-	    memset(child, 0, sizeof(struct pci_bus));
-	    child->self = self;
-	    child->primary = bus;
-	    child->number = child->secondary = s[a].cap.cardbus;
-	    child->subordinate = s[a].sub_bus;
-	    child->parent = parent;
-	    child->ops = parent->ops;
-	    child->next = parent->children;
-	}
-	s[a].cap.cb_bus = parent->children = child;
-    }
 }
 
-static void __init pci_probe(u_int class, void (add_fn)
-			     (int, u_char, u_char, u_short, u_short))
-{
-    u_short i, v, d;
-    u_char bus, devfn;
-    pci_id_t id;
-    
-    id = 0;
-    while (pci_lookup(class, &id, &bus, &devfn) == 0) {
-	if (PCI_FUNC(devfn) != 0) continue;
-	pci_readw(bus, devfn, PCI_VENDOR_ID, &v);
-	pci_readw(bus, devfn, PCI_DEVICE_ID, &d);
+static void __init pci_probe(u_int class, void (add_fn)(int, struct pci_dev *))
+{
+    struct pci_dev *dev = NULL;
+    u_short i;
+
+    while ((dev = pci_find_class(class << 8, dev))) {
+	pci_enable_device(dev);
+	if (PCI_FUNC(dev->devfn) != 0) continue;
 	for (i = 0; i < PCIC_COUNT; i++)
-	    if ((pcic[i].vendor == v) && (pcic[i].device == d)) break;
-	add_fn(i, bus, devfn, v, d);
+	    if ((pcic[i].vendor == dev->vendor) && (pcic[i].device == dev->device)) break;
+	add_fn(i, dev);
     }
 }
 
@@ -1887,22 +1782,21 @@
 
 /*====================================================================*/
 
-static int pcic_register_callback(u_short sock, ss_callback_t *call)
+static int pcic_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
 {
-    if (call == NULL) {
-	socket[sock].handler = NULL;
+    socket[sock].handler = handler;
+    socket[sock].info = info;
+    if (handler == NULL) {
 	MOD_DEC_USE_COUNT;
     } else {
 	MOD_INC_USE_COUNT;
-	socket[sock].handler = call->handler;
-	socket[sock].info = call->info;
     }
     return 0;
 } /* pcic_register_callback */
 
 /*====================================================================*/
 
-static int pcic_inquire_socket(u_short sock, socket_cap_t *cap)
+static int pcic_inquire_socket(unsigned int sock, socket_cap_t *cap)
 {
     *cap = socket[sock].cap;
     return 0;
@@ -2398,7 +2292,7 @@
     u_short bcr;
 
     cb_get_power(sock, state);
-    pci_readw(s->bus, s->devfn, CB_BRIDGE_CONTROL, &bcr);
+    config_readw(s, CB_BRIDGE_CONTROL, &bcr);
     state->flags |= (bcr & CB_BCR_CB_RESET) ? SS_RESET : 0;
     if (cb_get_irq_mode(sock) != 0)
 	state->io_irq = s->cap.pci_irq;
@@ -2414,7 +2308,7 @@
 {
     socket_info_t *s = &socket[sock];
     u_int reg;
-    
+
     DEBUG(1, "yenta: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
 	  "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
 	  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
@@ -2455,15 +2349,15 @@
     if (map > 1) return -EINVAL;
     m->flags &= MAP_IOSPACE;
     map += (m->flags & MAP_IOSPACE) ? 2 : 0;
-    pci_readl(s->bus, s->devfn, CB_MEM_BASE(map), &m->start);
-    pci_readl(s->bus, s->devfn, CB_MEM_LIMIT(map), &m->stop);
+    config_readl(s, CB_MEM_BASE(map), &m->start);
+    config_readl(s, CB_MEM_LIMIT(map), &m->stop);
     if (m->start || m->stop) {
 	m->flags |= MAP_ACTIVE;
 	m->stop |= (map > 1) ? 3 : 0x0fff;
     }
     if (map > 1) {
 	u_short bcr;
-	pci_readw(s->bus, s->devfn, CB_BRIDGE_CONTROL, &bcr);
+	config_readw(s, CB_BRIDGE_CONTROL, &bcr);
 	m->flags |= (bcr & CB_BCR_PREFETCH(map)) ? MAP_PREFETCH : 0;
     }
     DEBUG(1, "yenta: GetBridge(%d, %d) = %#2.2x, %#4.4x-%#4.4x\n",
@@ -2490,17 +2384,17 @@
 	u_short bcr;
 	if ((m->start & 0x0fff) || ((m->stop & 0x0fff) != 0x0fff))
 	    return -EINVAL;
-	pci_readw(s->bus, s->devfn, CB_BRIDGE_CONTROL, &bcr);
+	config_readw(s, CB_BRIDGE_CONTROL, &bcr);
 	bcr &= ~CB_BCR_PREFETCH(map);
 	bcr |= (m->flags & MAP_PREFETCH) ? CB_BCR_PREFETCH(map) : 0;
-	pci_writew(s->bus, s->devfn, CB_BRIDGE_CONTROL, bcr);
+	config_writew(s, CB_BRIDGE_CONTROL, bcr);
     }
     if (m->flags & MAP_ACTIVE) {
-	pci_writel(s->bus, s->devfn, CB_MEM_BASE(map), m->start);
-	pci_writel(s->bus, s->devfn, CB_MEM_LIMIT(map), m->stop);
+	config_writel(s, CB_MEM_BASE(map), m->start);
+	config_writel(s, CB_MEM_LIMIT(map), m->stop);
     } else {
-	pci_writel(s->bus, s->devfn, CB_IO_BASE(map), 0);
-	pci_writel(s->bus, s->devfn, CB_IO_LIMIT(map), 0);
+	config_writel(s, CB_MEM_BASE(map), 0);
+	config_writel(s, CB_MEM_LIMIT(map), 0);
     }
     return 0;
 }
@@ -2526,7 +2420,7 @@
 #ifdef CONFIG_PCI
     if (s->flags & (IS_PCI|IS_CARDBUS))
 	p += sprintf(p, "bus:      %02x\ndevfn:    %02x.%1x\n",
-		     s->bus, PCI_SLOT(s->devfn), PCI_FUNC(s->devfn));
+		     s->pdev->bus->number, PCI_SLOT(s->pdev->devfn), PCI_FUNC(s->pdev->devfn));
     if (s->flags & IS_CARDBUS)
 	p += sprintf(p, "cardbus:  %02x\n", s->cap.cardbus);
 #endif
@@ -2566,16 +2460,15 @@
 			 int count, int *eof, void *data)
 {
     socket_info_t *s = data;
-    u_char bus = s->bus, devfn = s->devfn;
     char *p = buf;
     u_int a, b, c, d;
     int i;
     
     for (i = 0; i < 0xc0; i += 0x10) {
-	pci_readl(bus, devfn, i, &a);
-	pci_readl(bus, devfn, i+4, &b);
-	pci_readl(bus, devfn, i+8, &c);
-	pci_readl(bus, devfn, i+12, &d);
+	config_readl(s, i, &a);
+	config_readl(s, i+4, &b);
+	config_readl(s, i+8, &c);
+	config_readl(s, i+12, &d);
 	p += sprintf(p, "%08x %08x %08x %08x\n", a, b, c, d);
     }
     return (p - buf);
@@ -2599,9 +2492,14 @@
 }
 #endif
 
-static void pcic_proc_setup(u_short sock, struct proc_dir_entry *base)
+static void pcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
 {
+#ifdef CONFIG_PROC_FS
     socket_info_t *s = &socket[sock];
+
+    if (s->flags & IS_ALIVE)
+    	return;
+
     create_proc_read_entry("info", 0, base, proc_read_info, s);
     create_proc_read_entry("exca", 0, base, proc_read_exca, s);
 #ifdef CONFIG_PCI
@@ -2613,6 +2511,7 @@
 	create_proc_read_entry("cardbus", 0, base, proc_read_cardbus, s);
 #endif
     s->proc = base;
+#endif
 }
 
 static void pcic_proc_remove(u_short sock)
@@ -2635,68 +2534,150 @@
 
 /*====================================================================*/
 
-typedef int (*subfn_t)(u_short, void *);
+/*
+ * This looks like a lot of duplication, and it is. What we should REALLY
+ * have is separate functions for the separate cases, instead of having
+ * duplicate tests in them - and then have the test in the place that sets
+ * up the ss_entry function pointer table instead!
+ *
+ * For example, the IS_CARDBUS thing is something we know _statically_,
+ * and as such it is a waste of time and space to test it dynamically.
+ *
+ * Much of this goes away by splitting off the cases. One small step at a
+ * time..
+ */
 
-static subfn_t pcic_service_table[] = {
-    (subfn_t)&pcic_register_callback,
-    (subfn_t)&pcic_inquire_socket,
-    (subfn_t)&i365_get_status,
-    (subfn_t)&i365_get_socket,
-    (subfn_t)&i365_set_socket,
-    (subfn_t)&i365_get_io_map,
-    (subfn_t)&i365_set_io_map,
-    (subfn_t)&i365_get_mem_map,
-    (subfn_t)&i365_set_mem_map,
 #ifdef CONFIG_CARDBUS
-    (subfn_t)&cb_get_bridge,
-    (subfn_t)&cb_set_bridge,
+#define is_cardbus(sock) ((socket[(sock)].flags & IS_CARDBUS) && (cb_readl((sock), CB_SOCKET_STATE) & CB_SS_32BIT))
+#endif
+
+/*
+ * The locking is rather broken. Why do we only lock for ISA, not for
+ * all other cases? If there are reasons to lock, we should lock. Not
+ * this silly conditional.
+ *
+ * Plan: make it bug-for-bug compatible with the old stuff, and clean
+ * it up when the infrastructure is done.
+ */
+#ifdef CONFIG_ISA
+#define LOCKED(x) do { \
+	if (socket[(sock)].flags & IS_CARDBUS) return x; \
+	do { \
+		int retval; \
+		unsigned long flags; \
+		spin_lock_irqsave(&isa_lock, flags); \
+		retval = x; \
+		spin_unlock_irqrestore(&isa_lock, flags); \
+		return retval; \
+	} while (0); \
+} while (0)
 #else
-    NULL, NULL,
+#define LOCKED(x) return x
 #endif
-#ifdef CONFIG_PROC_FS
-    (subfn_t)&pcic_proc_setup
+	
+
+static int pcic_get_status(unsigned int sock, u_int *value)
+{
+	if (socket[sock].flags & IS_ALIVE) {
+		*value = 0;
+		return -EINVAL;
+	}
+
+#ifdef CONFIG_CARDBUS
+	if (is_cardbus(sock))
+		return cb_get_status(sock, value);
 #endif
-};
+	LOCKED(i365_get_status(sock, value));
+}
+
+static int pcic_get_socket(unsigned int sock, socket_state_t *state)
+{
+	if (socket[sock].flags & IS_ALIVE)
+		return -EINVAL;
 
-#define NFUNC (sizeof(pcic_service_table)/sizeof(subfn_t))
+#ifdef CONFIG_CARDBUS
+	if (is_cardbus(sock))
+		return cb_get_socket(sock, state);
+#endif
+	LOCKED(i365_get_socket(sock, state));
+}
 
-static int pcic_service(u_int sock, u_int cmd, void *arg)
+static int pcic_set_socket(unsigned int sock, socket_state_t *state)
 {
-    subfn_t fn;
-    int ret;
-#ifdef CONFIG_ISA
-    u_long flags = 0;
+	if (socket[sock].flags & IS_ALIVE)
+		return -EINVAL;
+
+#ifdef CONFIG_CARDBUS
+	if (is_cardbus(sock))
+		return cb_set_socket(sock, state);
 #endif
-    
-    DEBUG(2, "pcic_ioctl(%d, %d, 0x%p)\n", sock, cmd, arg);
+	LOCKED(i365_set_socket(sock, state));
+}
 
-    if (cmd >= NFUNC)
-	return -EINVAL;
+static int pcic_get_io_map(unsigned int sock, struct pccard_io_map *io)
+{
+	if (socket[sock].flags & IS_ALIVE)
+		return -EINVAL;
+
+	LOCKED(i365_get_io_map(sock, io));
+}
+
+static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io)
+{
+	if (socket[sock].flags & IS_ALIVE)
+		return -EINVAL;
+
+	LOCKED(i365_set_io_map(sock, io));
+}
+
+static int pcic_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+{
+	if (socket[sock].flags & IS_ALIVE)
+		return -EINVAL;
+
+	LOCKED(i365_get_mem_map(sock, mem));
+}
+
+static int pcic_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+{
+	if (socket[sock].flags & IS_ALIVE)
+		return -EINVAL;
+
+	LOCKED(i365_set_mem_map(sock, mem));
+}
 
-    if (socket[sock].flags & IS_ALIVE) {
-	if (cmd == SS_GetStatus)
-	    *(u_int *)arg = 0;
+static int pcic_get_bridge(unsigned int sock, struct cb_bridge_map *m)
+{
+#ifdef CONFIG_CARDBUS
+	return cb_get_bridge(sock, m);
+#else
 	return -EINVAL;
-    }
-    
-    fn = pcic_service_table[cmd];
+#endif
+}
+
+static int pcic_set_bridge(unsigned int sock, struct cb_bridge_map *m)
+{
 #ifdef CONFIG_CARDBUS
-    if ((socket[sock].flags & IS_CARDBUS) &&
-	(cb_readl(sock, CB_SOCKET_STATE) & CB_SS_32BIT)) {
-	if (cmd == SS_GetStatus)
-	    fn = (subfn_t)&cb_get_status;
-	else if (cmd == SS_GetSocket)
-	    fn = (subfn_t)&cb_get_socket;
-	else if (cmd == SS_SetSocket)
-	    fn = (subfn_t)&cb_set_socket;
-    }
+	return cb_set_bridge(sock, m);
+#else
+	return -EINVAL;
 #endif
+}
 
-    ISA_LOCK(sock, flags);
-    ret = (fn == NULL) ? -EINVAL : fn(sock, arg);
-    ISA_UNLOCK(sock, flags);
-    return ret;
-} /* pcic_service */
+static struct pccard_operations pcic_operations = {
+	pcic_register_callback,
+	pcic_inquire_socket,
+	pcic_get_status,
+	pcic_get_socket,
+	pcic_set_socket,
+	pcic_get_io_map,
+	pcic_set_io_map,
+	pcic_get_mem_map,
+	pcic_set_mem_map,
+	pcic_get_bridge,
+	pcic_set_bridge,
+	pcic_proc_setup
+};
 
 /*====================================================================*/
 
@@ -2714,7 +2695,7 @@
     sockets = 0;
 
 #ifdef CONFIG_PCI
-    if (do_pci_probe && pcibios_present()) {
+    if (do_pci_probe) {
 	pci_probe(PCI_CLASS_BRIDGE_CARDBUS, add_cb_bridge);
 	pci_probe(PCI_CLASS_BRIDGE_PCMCIA, add_pci_bridge);
     }
@@ -2746,7 +2727,7 @@
     }
 #endif
     
-    if (register_ss_entry(sockets, &pcic_service) != 0)
+    if (register_ss_entry(sockets, &pcic_operations) != 0)
 	printk(KERN_NOTICE "i82365: register_ss_entry() failed\n");
 
     /* Finally, schedule a polling interrupt */
@@ -2768,7 +2749,7 @@
 #ifdef CONFIG_PROC_FS
     for (i = 0; i < sockets; i++) pcic_proc_remove(i);
 #endif
-    unregister_ss_entry(&pcic_service);
+    unregister_ss_entry(&pcic_operations);
     if (poll_interval != 0)
 	del_timer(&poll_timer);
 #ifdef CONFIG_ISA
@@ -2805,4 +2786,3 @@
 module_exit(exit_i82365);
 
 /*====================================================================*/
-
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/old-yenta.h linux/drivers/pcmcia/old-yenta.h
--- v2.3.34/linux/drivers/pcmcia/old-yenta.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pcmcia/old-yenta.h	Thu Nov 11 16:03:37 1999
@@ -0,0 +1,153 @@
+/*
+ * yenta.h 1.16 1999/10/25 20:03:34
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License. 
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU Public License version 2 (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of the
+ * above.  If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use
+ * your version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL.  If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#ifndef _LINUX_YENTA_H
+#define _LINUX_YENTA_H
+
+/* PCI Configuration Registers */
+
+#define PCI_STATUS_CAPLIST		0x10
+#define PCI_CB_CAPABILITY_POINTER	0x14	/* 8 bit */
+#define PCI_CAPABILITY_ID		0x00	/* 8 bit */
+#define  PCI_CAPABILITY_PM		0x01
+#define PCI_NEXT_CAPABILITY		0x01	/* 8 bit */
+#define PCI_PM_CAPABILITIES		0x02	/* 16 bit */
+#define  PCI_PMCAP_PME_D3COLD		0x8000
+#define  PCI_PMCAP_PME_D3HOT		0x4000
+#define  PCI_PMCAP_PME_D2		0x2000
+#define  PCI_PMCAP_PME_D1		0x1000
+#define  PCI_PMCAP_PME_D0		0x0800
+#define  PCI_PMCAP_D2_CAP		0x0400
+#define  PCI_PMCAP_D1_CAP		0x0200
+#define  PCI_PMCAP_DYN_DATA		0x0100
+#define  PCI_PMCAP_DSI			0x0020
+#define  PCI_PMCAP_AUX_PWR		0x0010
+#define  PCI_PMCAP_PMECLK		0x0008
+#define  PCI_PMCAP_VERSION_MASK		0x0007
+#define PCI_PM_CONTROL_STATUS		0x04	/* 16 bit */
+#define  PCI_PMCS_PME_STATUS		0x8000
+#define  PCI_PMCS_DATASCALE_MASK	0x6000
+#define  PCI_PMCS_DATASCALE_SHIFT	13
+#define  PCI_PMCS_DATASEL_MASK		0x1e00
+#define  PCI_PMCS_DATASEL_SHIFT		9
+#define  PCI_PMCS_PME_ENABLE		0x0100
+#define  PCI_PMCS_PWR_STATE_MASK	0x0003
+#define  PCI_PMCS_PWR_STATE_D0		0x0000
+#define  PCI_PMCS_PWR_STATE_D1		0x0001
+#define  PCI_PMCS_PWR_STATE_D2		0x0002
+#define  PCI_PMCS_PWR_STATE_D3		0x0003
+#define PCI_PM_BRIDGE_EXT		0x06	/* 8 bit */
+#define PCI_PM_DATA			0x07	/* 8 bit */
+
+#define CB_PRIMARY_BUS			0x18	/* 8 bit */
+#define CB_CARDBUS_BUS			0x19	/* 8 bit */
+#define CB_SUBORD_BUS			0x1a	/* 8 bit */
+#define CB_LATENCY_TIMER		0x1b	/* 8 bit */
+
+#define CB_MEM_BASE(m)			(0x1c + 8*(m))
+#define CB_MEM_LIMIT(m)			(0x20 + 8*(m))
+#define CB_IO_BASE(m)			(0x2c + 8*(m))
+#define CB_IO_LIMIT(m)			(0x30 + 8*(m))
+
+#define CB_BRIDGE_CONTROL		0x3e	/* 16 bit */
+#define  CB_BCR_PARITY_ENA		0x0001
+#define  CB_BCR_SERR_ENA		0x0002
+#define  CB_BCR_ISA_ENA			0x0004
+#define  CB_BCR_VGA_ENA			0x0008
+#define  CB_BCR_MABORT			0x0020
+#define  CB_BCR_CB_RESET		0x0040
+#define  CB_BCR_ISA_IRQ			0x0080
+#define  CB_BCR_PREFETCH(m)		(0x0100 << (m))
+#define  CB_BCR_WRITE_POST		0x0400
+
+#define CB_LEGACY_MODE_BASE		0x44
+
+/* Memory mapped registers */
+
+#define CB_SOCKET_EVENT			0x0000
+#define  CB_SE_CSTSCHG			0x00000001
+#define  CB_SE_CCD1			0x00000002
+#define  CB_SE_CCD2			0x00000004
+#define  CB_SE_PWRCYCLE			0x00000008
+
+#define CB_SOCKET_MASK			0x0004
+#define  CB_SM_CSTSCHG			0x00000001
+#define  CB_SM_CCD			0x00000006
+#define  CB_SM_PWRCYCLE			0x00000008
+
+#define CB_SOCKET_STATE			0x0008
+#define  CB_SS_CSTSCHG			0x00000001
+#define  CB_SS_CCD1			0x00000002
+#define  CB_SS_CCD2			0x00000004
+#define  CB_SS_PWRCYCLE			0x00000008
+#define  CB_SS_16BIT			0x00000010
+#define  CB_SS_32BIT			0x00000020
+#define  CB_SS_CINT			0x00000040
+#define  CB_SS_BADCARD			0x00000080
+#define  CB_SS_DATALOST			0x00000100
+#define  CB_SS_BADVCC			0x00000200
+#define  CB_SS_5VCARD			0x00000400
+#define  CB_SS_3VCARD			0x00000800
+#define  CB_SS_XVCARD			0x00001000
+#define  CB_SS_YVCARD			0x00002000
+#define  CB_SS_5VSOCKET			0x10000000
+#define  CB_SS_3VSOCKET			0x20000000
+#define  CB_SS_XVSOCKET			0x40000000
+#define  CB_SS_YVSOCKET			0x80000000
+
+#define CB_SOCKET_FORCE			0x000c
+#define  CB_SF_CVSTEST			0x00004000
+
+#define CB_SOCKET_CONTROL		0x0010
+#define  CB_SC_VPP_MASK			0x00000007
+#define   CB_SC_VPP_OFF			0x00000000
+#define   CB_SC_VPP_12V			0x00000001
+#define   CB_SC_VPP_5V			0x00000002
+#define   CB_SC_VPP_3V			0x00000003
+#define   CB_SC_VPP_XV			0x00000004
+#define   CB_SC_VPP_YV			0x00000005
+#define  CB_SC_VCC_MASK			0x00000070
+#define   CB_SC_VCC_OFF			0x00000000
+#define   CB_SC_VCC_5V			0x00000020
+#define   CB_SC_VCC_3V			0x00000030
+#define   CB_SC_VCC_XV			0x00000040
+#define   CB_SC_VCC_YV			0x00000050
+#define  CB_SC_CCLK_STOP		0x00000080
+
+#define CB_SOCKET_POWER			0x0020
+#define  CB_SP_CLK_CTRL			0x00000001
+#define  CB_SP_CLK_CTRL_ENA		0x00010000
+#define  CB_SP_CLK_MODE			0x01000000
+#define  CB_SP_ACCESS			0x02000000
+
+/* Address bits 31..24 for memory windows for 16-bit cards,
+   accessable only by memory mapping the 16-bit register set */
+#define CB_MEM_PAGE(map)		(0x40 + (map))
+
+#endif /* _LINUX_YENTA_H */
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/pci_socket.c linux/drivers/pcmcia/pci_socket.c
--- v2.3.34/linux/drivers/pcmcia/pci_socket.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pcmcia/pci_socket.c	Thu Dec 23 00:07:09 1999
@@ -0,0 +1,212 @@
+/*
+ * Generic PCI pccard driver interface.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * This implements the common parts of PCI pccard drivers,
+ * notably detection and infrastructure conversion (ie change
+ * from socket index to "struct pci_dev" etc)
+ *
+ * This does NOT implement the actual low-level driver details,
+ * and this has on purpose been left generic enough that it can
+ * be used to set up a PCI PCMCIA controller (ie non-cardbus),
+ * or to set up a controller.
+ *
+ * See for example the "yenta" driver for PCI cardbus controllers
+ * conforming to the yenta cardbus specifications.
+ */
+#include <linux/module.h>
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/io.h>
+
+#include "pci_socket.h"
+
+static struct pci_simple_probe_entry controller_list[] = {
+	{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1225, 0, 0, &yenta_operations },
+	{ 0x1180, 0x0475, 0, 0, &yenta_operations },
+	{ 0, 0, 0, 0, NULL }
+};
+
+
+/*
+ * Arbitrary define. This is the array of active cardbus
+ * entries.
+ */
+#define MAX_SOCKETS (8)
+static pci_socket_t pci_socket_array[MAX_SOCKETS];
+
+/*
+ * Work in progress. I need to distill the _real_ differences in
+ * carbus drivers, and change the cardbus "op" list to match. This
+ * is just a direct 1:1 mapping of the pccard operations.
+ */
+static int pci_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
+{
+	pci_socket_t *socket = pci_socket_array + sock;
+
+	socket->handler = handler;
+	socket->info = info;
+	if (handler)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int pci_inquire_socket(unsigned int sock, socket_cap_t *cap)
+{
+	pci_socket_t *socket = pci_socket_array + sock;
+
+	if (socket->op && socket->op->inquire)
+		return socket->op->inquire(socket, cap);
+	return -EINVAL;
+}
+
+static int pci_get_status(unsigned int sock, unsigned int *value)
+{
+	pci_socket_t *socket = pci_socket_array + sock;
+
+	if (socket->op && socket->op->get_status)
+		return socket->op->get_status(socket, value);
+	*value = 0;
+	return -EINVAL;
+}
+
+static int pci_get_socket(unsigned int sock, socket_state_t *state)
+{
+	pci_socket_t *socket = pci_socket_array + sock;
+
+	if (socket->op && socket->op->get_socket)
+		return socket->op->get_socket(socket, state);
+	return -EINVAL;
+}
+
+static int pci_set_socket(unsigned int sock, socket_state_t *state)
+{
+	pci_socket_t *socket = pci_socket_array + sock;
+
+	if (socket->op && socket->op->set_socket)
+		return socket->op->set_socket(socket, state);
+	return -EINVAL;
+}
+
+static int pci_get_io_map(unsigned int sock, struct pccard_io_map *io)
+{
+	pci_socket_t *socket = pci_socket_array + sock;
+
+	if (socket->op && socket->op->get_io_map)
+		return socket->op->get_io_map(socket, io);
+	return -EINVAL;
+}
+
+static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io)
+{
+	pci_socket_t *socket = pci_socket_array + sock;
+
+	if (socket->op && socket->op->set_io_map)
+		return socket->op->set_io_map(socket, io);
+	return -EINVAL;
+}
+
+static int pci_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+{
+	pci_socket_t *socket = pci_socket_array + sock;
+
+	if (socket->op && socket->op->get_mem_map)
+		return socket->op->get_mem_map(socket, mem);
+	return -EINVAL;
+}
+
+static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+{
+	pci_socket_t *socket = pci_socket_array + sock;
+
+	if (socket->op && socket->op->set_mem_map)
+		return socket->op->set_mem_map(socket, mem);
+	return -EINVAL;
+}
+
+static int pci_get_bridge(unsigned int sock, struct cb_bridge_map *m)
+{
+	pci_socket_t *socket = pci_socket_array + sock;
+
+	if (socket->op && socket->op->get_bridge)
+		return socket->op->get_bridge(socket, m);
+	return -EINVAL;
+}
+
+static int pci_set_bridge(unsigned int sock, struct cb_bridge_map *m)
+{
+	pci_socket_t *socket = pci_socket_array + sock;
+
+	if (socket->op && socket->op->set_bridge)
+		return socket->op->set_bridge(socket, m);
+	return -EINVAL;
+}
+
+static void pci_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+{
+	pci_socket_t *socket = pci_socket_array + sock;
+
+	if (socket->op && socket->op->proc_setup)
+		socket->op->proc_setup(socket, base);
+}
+
+static struct pccard_operations pci_socket_operations = {
+	pci_register_callback,
+	pci_inquire_socket,
+	pci_get_status,
+	pci_get_socket,
+	pci_set_socket,
+	pci_get_io_map,
+	pci_set_io_map,
+	pci_get_mem_map,
+	pci_set_mem_map,
+	pci_get_bridge,
+	pci_set_bridge,
+	pci_proc_setup
+};
+
+static int __init pci_socket_probe(struct pci_dev *dev, int nr, const struct pci_simple_probe_entry * entry, void *data)
+{
+	pci_socket_t *socket = nr + pci_socket_array;
+
+	printk("Found controller %d: %s\n", nr, dev->name);
+	socket->dev = dev;
+	socket->op = entry->dev_data;
+	socket->op->open(socket);
+	return 0;
+}
+
+static int __init pci_socket_init(void)
+{
+	int sockets = pci_simple_probe(controller_list, MAX_SOCKETS, pci_socket_probe, NULL);
+
+	if (sockets <= 0)
+		return -1;
+	register_ss_entry(sockets, &pci_socket_operations);
+	return 0;
+}
+
+static void __exit pci_socket_exit(void)
+{
+	int i;
+
+	unregister_ss_entry(&pci_socket_operations);
+	for (i = 0; i < MAX_SOCKETS; i++) {
+		pci_socket_t *socket = pci_socket_array + i;
+
+		if (socket->op && socket->op->close)
+			socket->op->close(socket);
+	}
+}
+
+module_init(pci_socket_init);
+module_exit(pci_socket_exit);
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/pci_socket.h linux/drivers/pcmcia/pci_socket.h
--- v2.3.34/linux/drivers/pcmcia/pci_socket.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pcmcia/pci_socket.h	Thu Dec 23 14:55:39 1999
@@ -0,0 +1,36 @@
+/*
+ * drivers/pcmcia/pci_socket.h
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ */
+
+struct pci_socket_ops;
+
+typedef struct pci_socket {
+	struct pci_dev *dev;
+	int cb_irq, io_irq;
+	void *base;
+	void (*handler)(void *, unsigned int);
+	void *info;
+	struct pci_socket_ops *op;
+	socket_cap_t cap;
+} pci_socket_t;
+
+struct pci_socket_ops {
+	int (*open)(struct pci_socket *);
+	void (*close)(struct pci_socket *);
+
+	int (*inquire)(struct pci_socket *, socket_cap_t *cap);
+	int (*get_status)(struct pci_socket *, unsigned int *);
+	int (*get_socket)(struct pci_socket *, socket_state_t *);
+	int (*set_socket)(struct pci_socket *, socket_state_t *);
+	int (*get_io_map)(struct pci_socket *, struct pccard_io_map *);
+	int (*set_io_map)(struct pci_socket *, struct pccard_io_map *);
+	int (*get_mem_map)(struct pci_socket *, struct pccard_mem_map *);
+	int (*set_mem_map)(struct pci_socket *, struct pccard_mem_map *);
+	int (*get_bridge)(struct pci_socket *, struct cb_bridge_map *);
+	int (*set_bridge)(struct pci_socket *, struct cb_bridge_map *);
+	void (*proc_setup)(struct pci_socket *, struct proc_dir_entry *base);
+};
+
+extern struct pci_socket_ops yenta_operations;
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/tcic.c linux/drivers/pcmcia/tcic.c
--- v2.3.34/linux/drivers/pcmcia/tcic.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/pcmcia/tcic.c	Tue Dec 21 22:02:15 1999
@@ -109,7 +109,7 @@
 
 static void tcic_interrupt(int irq, void *dev, struct pt_regs *regs);
 static void tcic_timer(u_long data);
-static int tcic_service(u_int sock, u_int cmd, void *arg);
+static struct pccard_operations tcic_operations;
 
 typedef struct socket_info_t {
     u_short	psock;
@@ -494,7 +494,7 @@
     /* jump start interrupt handler, if needed */
     tcic_interrupt(0, NULL, NULL);
 
-    if (register_ss_entry(sockets, &tcic_service) != 0) {
+    if (register_ss_entry(sockets, &tcic_operations) != 0) {
 	printk(KERN_NOTICE "tcic: register_ss_entry() failed\n");
 	release_region(tcic_base, 16);
 	if (cs_irq != 0)
@@ -511,7 +511,7 @@
 static void __exit exit_tcic(void)
 {
     u_long flags;
-    unregister_ss_entry(&tcic_service);
+    unregister_ss_entry(&tcic_operations);
     save_flags(flags);
     cli();
     if (cs_irq != 0) {
@@ -589,22 +589,21 @@
 
 /*====================================================================*/
 
-static int tcic_register_callback(u_short lsock, ss_callback_t *call)
+static int tcic_register_callback(unsigned int lsock, void (*handler)(void *, unsigned int), void * info)
 {
-    if (call == NULL) {
-	socket_table[lsock].handler = NULL;
+    socket_table[lsock].handler = handler;
+    socket_table[lsock].info = info;
+    if (handler == NULL) {
 	MOD_DEC_USE_COUNT;
     } else {
 	MOD_INC_USE_COUNT;
-	socket_table[lsock].handler = call->handler;
-	socket_table[lsock].info = call->info;
     }
     return 0;
 } /* tcic_register_callback */
 
 /*====================================================================*/
 
-static int tcic_get_status(u_short lsock, u_int *value)
+static int tcic_get_status(unsigned int lsock, u_int *value)
 {
     u_short psock = socket_table[lsock].psock;
     u_char reg;
@@ -630,7 +629,7 @@
   
 /*====================================================================*/
 
-static int tcic_inquire_socket(u_short lsock, socket_cap_t *cap)
+static int tcic_inquire_socket(unsigned int lsock, socket_cap_t *cap)
 {
     *cap = tcic_cap;
     return 0;
@@ -638,7 +637,7 @@
 
 /*====================================================================*/
 
-static int tcic_get_socket(u_short lsock, socket_state_t *state)
+static int tcic_get_socket(unsigned int lsock, socket_state_t *state)
 {
     u_short psock = socket_table[lsock].psock;
     u_char reg;
@@ -691,7 +690,7 @@
 
 /*====================================================================*/
 
-static int tcic_set_socket(u_short lsock, socket_state_t *state)
+static int tcic_set_socket(unsigned int lsock, socket_state_t *state)
 {
     u_short psock = socket_table[lsock].psock;
     u_char reg;
@@ -766,7 +765,7 @@
   
 /*====================================================================*/
 
-static int tcic_get_io_map(u_short lsock, struct pccard_io_map *io)
+static int tcic_get_io_map(unsigned int lsock, struct pccard_io_map *io)
 {
     u_short psock = socket_table[lsock].psock;
     u_short base, ioctl;
@@ -804,7 +803,7 @@
 
 /*====================================================================*/
 
-static int tcic_set_io_map(u_short lsock, struct pccard_io_map *io)
+static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io)
 {
     u_short psock = socket_table[lsock].psock;
     u_int addr;
@@ -841,7 +840,7 @@
 
 /*====================================================================*/
 
-static int tcic_get_mem_map(u_short lsock, struct pccard_mem_map *mem)
+static int tcic_get_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
 {
     u_short psock = socket_table[lsock].psock;
     u_short addr, ctl;
@@ -886,7 +885,7 @@
 
 /*====================================================================*/
   
-static int tcic_set_mem_map(u_short lsock, struct pccard_mem_map *mem)
+static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
 {
     u_short psock = socket_table[lsock].psock;
     u_short addr, ctl;
@@ -930,35 +929,31 @@
 
 /*====================================================================*/
 
-typedef int (*subfn_t)(u_short, void *);
-    
-static subfn_t service_table[] = {
-    (subfn_t)&tcic_register_callback,
-    (subfn_t)&tcic_inquire_socket,
-    (subfn_t)&tcic_get_status,
-    (subfn_t)&tcic_get_socket,
-    (subfn_t)&tcic_set_socket,
-    (subfn_t)&tcic_get_io_map,
-    (subfn_t)&tcic_set_io_map,
-    (subfn_t)&tcic_get_mem_map,
-    (subfn_t)&tcic_set_mem_map,
-};
-
-#define NFUNC (sizeof(service_table)/sizeof(subfn_t))
-
-static int tcic_service(u_int lsock, u_int cmd, void *arg)
+int tcic_get_bridge(unsigned int sock, struct cb_bridge_map *m)
 {
-    int err;
+	return -EINVAL;
+}
 
-    DEBUG(2, "tcic_service(%d, %d, 0x%p)\n", lsock, cmd, arg);
+#define tcic_set_bridge tcic_get_bridge
 
-    if (cmd < NFUNC)
-	err = service_table[cmd](lsock, arg);
-    else
-	err = -EINVAL;
+void tcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+{
+}
 
-    return err;
-} /* tcic_service */
+static struct pccard_operations tcic_operations = {
+	tcic_register_callback,
+	tcic_inquire_socket,
+	tcic_get_status,
+	tcic_get_socket,
+	tcic_set_socket,
+	tcic_get_io_map,
+	tcic_set_io_map,
+	tcic_get_mem_map,
+	tcic_set_mem_map,
+	tcic_get_bridge,
+	tcic_set_bridge,
+	tcic_proc_setup
+};
 
 /*====================================================================*/
 
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c
--- v2.3.34/linux/drivers/pcmcia/yenta.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pcmcia/yenta.c	Tue Dec 28 16:11:31 1999
@@ -0,0 +1,534 @@
+/*
+ * Regular lowlevel cardbus driver ("yenta")
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/io.h>
+
+#include "yenta.h"
+#include "i82365.h"
+
+/* Don't ask.. */
+#define to_cycles(ns)	((ns)/120)
+#define to_ns(cycles)	((cycles)*120)
+
+static int yenta_inquire(pci_socket_t *socket, socket_cap_t *cap)
+{
+	*cap = socket->cap;
+	return 0;
+}
+
+/*
+ * Silly interface. We convert the cardbus status to a internal status,
+ * and we probably really should keep it in cardbus status form and
+ * only convert for old-style 16-bit PCMCIA cards..
+ */
+static int yenta_get_status(pci_socket_t *socket, unsigned int *value)
+{
+	u32 state = cb_readl(socket, CB_SOCKET_STATE);
+	u8 status;
+	unsigned int val;
+
+	/* Convert from Yenta status to old-style status */
+	val  = (state & CB_CARDSTS) ? SS_STSCHG : 0;
+	val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT;
+	val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0;
+	val |= (state & CB_CBCARD) ? SS_CARDBUS : 0;
+	val |= (state & CB_3VCARD) ? SS_3VCARD : 0;
+	val |= (state & CB_XVCARD) ? SS_XVCARD : 0;
+
+	/* Get the old compatibility status too.. */
+	status = exca_readb(socket, I365_STATUS);
+	val |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
+	val |= (status & I365_CS_READY) ? SS_READY : 0;
+	val |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
+
+printk("yenta_get_status(%p)= %x\n", socket, val);
+
+	*value = val;
+	return 0;
+}
+
+static int yenta_Vcc_power(u32 control)
+{
+	switch ((control >> CB_VCCCTRL) & CB_PWRBITS) {
+	case CB_PWR5V: return 50;
+	case CB_PWR3V: return 33;
+	default: return 0;
+	}
+}
+
+static int yenta_Vpp_power(u32 control)
+{
+	switch ((control >> CB_VPPCTRL) & CB_PWRBITS) {
+	case CB_PWR12V: return 120;
+	case CB_PWR5V: return 50;
+	case CB_PWR3V: return 33;
+	default: return 0;
+	}
+}
+
+static int yenta_get_socket(pci_socket_t *socket, socket_state_t *state)
+{
+	u32 control = cb_readl(socket, CB_SOCKET_CONTROL);
+	u8 reg;
+
+	state->Vcc = yenta_Vcc_power(control);
+	state->Vpp = yenta_Vpp_power(control);
+	state->io_irq = socket->io_irq;
+
+	reg = exca_readb(socket, I365_POWER);
+	state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
+	state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
+
+	reg = exca_readb(socket, I365_INTCTL);
+	state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
+	state->flags |= (reg & I365_PC_IOCARD) ? SS_IOCARD : 0;
+
+	reg = exca_readb(socket, I365_CSCINT);
+	state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
+	if (state->flags & SS_IOCARD) {
+		state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
+	} else {
+		state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
+		state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
+		state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
+	}
+
+printk("yenta_get_socket(%p) = %d, %d\n", socket, state->Vcc, state->Vpp);
+
+	return 0;
+}
+
+static int yenta_set_socket(pci_socket_t *socket, socket_state_t *state)
+{
+	u8 reg;
+	u16 bridge;
+	u32 control;
+
+printk("yenta_set_socket(%p, %d, %d, %x)\n", socket, state->Vcc, state->Vpp, state->flags);
+
+	bridge = config_readw(socket, CB_BRIDGE_CONTROL);
+	bridge &= ~CB_BRIDGE_CRST;
+	bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0;
+	config_writew(socket, CB_BRIDGE_CONTROL, bridge);
+
+	/* Set the IO interrupt and socket state */
+	reg = state->io_irq;
+	reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
+	reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
+	exca_writeb(socket, I365_INTCTL, reg);
+
+	/* Set host interrupt and CSC mask state */
+	reg = socket->cb_irq << 4;
+	reg |= (state->csc_mask & SS_DETECT) ? I365_CSC_DETECT : 0;
+	if (state->flags & SS_IOCARD) {
+		reg |= (state->csc_mask & SS_STSCHG) ? I365_CSC_STSCHG : 0;
+	} else {
+		reg |= (state->csc_mask & SS_BATDEAD) ? I365_CSC_BVD1 : 0;
+		reg |= (state->csc_mask & SS_BATWARN) ? I365_CSC_BVD2 : 0;
+		reg |= (state->csc_mask & SS_READY) ? I365_CSC_READY : 0;
+	}
+	exca_writeb(socket, I365_CSCINT, reg);
+	exca_readb(socket, I365_CSC);
+
+	/*
+	 * Set power state..
+	 *
+	 * I wonder if we could do the Vcc/Vpp part through the
+	 * CB interface only..
+	 */
+	reg = I365_PWR_NORESET;
+	reg |= (state->flags & SS_PWR_AUTO) ? I365_PWR_AUTO : 0;
+	reg |= (state->flags & SS_OUTPUT_ENA) ? I365_PWR_OUT : 0;
+
+	control = CB_STOPCLK;
+	switch (state->Vcc) {
+	case 33:
+		control |= CB_PWR3V << CB_VCCCTRL;
+		reg |= I365_VCC_5V;
+		break;
+	case 50:
+		control |= CB_PWR5V << CB_VCCCTRL;
+		reg |= I365_VCC_5V;
+		break;
+	}
+	switch (state->Vpp) {
+	case 33:
+		control |= CB_PWR3V << CB_VPPCTRL;
+		reg |= I365_VPP1_5V;
+		break;
+	case 50:
+		control |= CB_PWR5V << CB_VPPCTRL;
+		reg |= I365_VPP1_5V;
+		break;
+	case 120:
+		control |= CB_PWR12V << CB_VPPCTRL;
+		reg |= I365_VPP1_12V;
+		break;
+	}
+	exca_writeb(socket, I365_POWER, reg);
+	cb_writel(socket, CB_SOCKET_CONTROL, control);
+
+	return 0;
+}
+
+static int yenta_get_io_map(pci_socket_t *socket, struct pccard_io_map *io)
+{
+	int map;
+	unsigned char ioctl, addr;
+
+	map = io->map;
+	if (map > 1)
+		return -EINVAL;
+
+	io->start = exca_readw(socket, I365_IO(map)+I365_W_START);
+	io->stop = exca_readw(socket, I365_IO(map)+I365_W_STOP);
+
+	ioctl = exca_readb(socket, I365_IOCTL);
+	addr = exca_readb(socket, I365_ADDRWIN);
+	io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0;
+	io->flags  = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0;
+	io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0;
+	io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0;
+	io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0;
+
+printk("yenta_get_io_map(%d) = %x, %x, %x\n", map, io->start, io->stop, io->flags);
+
+	return 0;
+}
+
+static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io)
+{
+	int map;
+	unsigned char ioctl, addr, enable;
+
+	map = io->map;
+
+printk("yenta_set_io_map(%d, %x, %x, %x)\n", map, io->start, io->stop, io->flags);
+
+	if (map > 1)
+		return -EINVAL;
+
+	enable = I365_ENA_IO(map);
+	addr = exca_readb(socket, I365_ADDRWIN);
+
+	/* Disable the window before changing it.. */
+	if (addr & enable) {
+		addr &= ~enable;
+		exca_writeb(socket, I365_ADDRWIN, addr);
+	}
+
+	exca_writew(socket, I365_IO(map)+I365_W_START, io->start);
+	exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop);
+
+	ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map);
+	if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
+	if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
+	if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
+	exca_writeb(socket, I365_IOCTL, ioctl);
+
+	if (io->flags & MAP_ACTIVE)
+		exca_writeb(socket, I365_ADDRWIN, addr | enable);
+	return 0;
+}
+
+static int yenta_get_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem)
+{
+	int map;
+	unsigned char addr;
+	unsigned int start, stop, page, offset;
+
+	map = mem->map;
+	if (map > 4)
+		return -EINVAL;
+
+	addr = exca_readb(socket, I365_ADDRWIN);
+	mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0;
+
+	start = exca_readw(socket, I365_MEM(map) + I365_W_START);
+	mem->flags |= (start & I365_MEM_16BIT) ? MAP_16BIT : 0;
+	mem->flags |= (start & I365_MEM_0WS) ? MAP_0WS : 0;
+	start = (start & 0x0fff) << 12;
+
+	stop = exca_readw(socket, I365_MEM(map) + I365_W_STOP);
+	mem->speed  = (stop & I365_MEM_WS0) ? 1 : 0;
+	mem->speed += (stop & I365_MEM_WS1) ? 2 : 0;
+	mem->speed = to_ns(mem->speed);
+	stop = ((stop & 0x0fff) << 12) + 0x0fff;
+
+	offset = exca_readw(socket, I365_MEM(map) + I365_W_OFF);
+	mem->flags |= (offset & I365_MEM_WRPROT) ? MAP_WRPROT : 0;
+	mem->flags |= (offset & I365_MEM_REG) ? MAP_ATTRIB : 0;
+	offset = ((offset & 0x3fff) << 12) + start;
+	mem->card_start = offset & 0x3ffffff;
+
+	page = exca_readb(socket, CB_MEM_PAGE(map)) << 24;
+	mem->sys_start = start + page;
+	mem->sys_stop = start + page;
+
+printk("yenta_get_map(%d) = %lx, %lx, %x\n", map, mem->sys_start, mem->sys_stop, mem->card_start);
+
+	return 0;
+}
+
+static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem)
+{
+	int map;
+	unsigned char addr, enable;
+	unsigned int start, stop, card_start;
+	unsigned short word;
+
+	map = mem->map;
+	start = mem->sys_start;
+	stop = mem->sys_stop;
+	card_start = mem->card_start;
+
+printk("yenta_set_map(%d, %x, %x, %x)\n", map, start, stop, card_start);
+
+	if (map > 4 || start > stop || ((start ^ stop) >> 24) || (card_start >> 26) || mem->speed > 1000)
+		return -EINVAL;
+
+	enable = I365_ENA_MEM(map);
+	addr = exca_readb(socket, I365_ADDRWIN);
+	if (addr & enable) {
+		addr &= ~enable;
+		exca_writeb(socket, I365_ADDRWIN, addr);
+	}
+
+	exca_writeb(socket, CB_MEM_PAGE(map), start >> 24);
+
+	word = (start >> 12) & 0x0fff;
+	if (mem->flags & MAP_16BIT)
+		word |= I365_MEM_16BIT;
+	if (mem->flags & MAP_0WS)
+		word |= I365_MEM_0WS;
+	exca_writew(socket, I365_MEM(map) + I365_W_START, word);
+
+	word = (stop >> 12) & 0x0fff;
+	switch (to_cycles(mem->speed)) {
+		case 0: break;
+		case 1:  word |= I365_MEM_WS0; break;
+		case 2:  word |= I365_MEM_WS1; break;
+		default: word |= I365_MEM_WS1 | I365_MEM_WS0; break;
+	}
+	exca_writew(socket, I365_MEM(map) + I365_W_STOP, word);
+
+	word = ((card_start - start) >> 12) & 0x3fff;
+	if (mem->flags & MAP_WRPROT)
+		word |= I365_MEM_WRPROT;
+	if (mem->flags & MAP_ATTRIB)
+		word |= I365_MEM_REG;
+	exca_writew(socket, I365_MEM(map) + I365_W_OFF, word);
+
+	if (mem->flags & MAP_ACTIVE)
+		exca_writeb(socket, I365_ADDRWIN, addr | enable);
+	return 0;
+}
+
+static int yenta_get_bridge(pci_socket_t *socket, struct cb_bridge_map *m)
+{
+	unsigned map;
+	
+	map = m->map;
+	if (map > 1)
+		return -EINVAL;
+
+	m->flags &= MAP_IOSPACE;
+	map += (m->flags & MAP_IOSPACE) ? 2 : 0;
+	m->start = config_readl(socket, CB_BRIDGE_BASE(map));
+	m->stop = config_readl(socket, CB_BRIDGE_LIMIT(map));
+	if (m->start || m->stop) {
+		m->flags |= MAP_ACTIVE;
+		m->stop |= (map > 1) ? 3 : 0x0fff;
+	}
+
+	/* Get prefetch state for memory mappings */
+	if (map < 2) {
+		u16 ctrl, prefetch_mask = CB_BRIDGE_PREFETCH0 << map;
+
+		ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
+		m->flags |= (ctrl & prefetch_mask) ? MAP_PREFETCH : 0;
+	}
+	return 0;
+}
+
+static int yenta_set_bridge(pci_socket_t *socket, struct cb_bridge_map *m)
+{
+	unsigned map;
+	u32 start, end;
+	
+	map = m->map;
+	if (map > 1 || m->stop < m->start)
+		return -EINVAL;
+
+	if (m->flags & MAP_IOSPACE) {
+		if ((m->stop > 0xffff) || (m->start & 3) ||
+		    ((m->stop & 3) != 3))
+			return -EINVAL;
+		map += 2;
+	} else {
+		u16 ctrl, prefetch_mask = CB_BRIDGE_PREFETCH0 << map;
+
+		if ((m->start & 0x0fff) || ((m->stop & 0x0fff) != 0x0fff))
+			return -EINVAL;
+		ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
+		ctrl &= ~prefetch_mask;
+		ctrl |= (m->flags & MAP_PREFETCH) ? prefetch_mask : 0;
+		config_writew(socket, CB_BRIDGE_CONTROL, ctrl);
+	}
+
+	start = 0;
+	end = 0;
+	if (m->flags & MAP_ACTIVE) {
+		start = m->start;
+		end = m->stop;
+	}
+	config_writel(socket, CB_BRIDGE_BASE(map), start);
+	config_writel(socket, CB_BRIDGE_LIMIT(map), end);
+	return 0;
+}
+
+static void yenta_proc_setup(pci_socket_t *socket, struct proc_dir_entry *base)
+{
+	/* Not done yet */
+}
+
+static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u8 csc;
+	u32 cb_event;
+	unsigned int events;
+	pci_socket_t *socket = (pci_socket_t *) dev_id;
+
+	/* Clear interrupt status for the event */
+	cb_event = cb_readl(socket, CB_SOCKET_EVENT);
+	cb_writel(socket, CB_SOCKET_EVENT, cb_event);
+
+	csc = exca_readb(socket, I365_CSC);
+
+	events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ;
+	events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
+	if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) {
+		events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
+	} else {
+		events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
+		events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
+		events |= (csc & I365_CSC_READY) ? SS_READY : 0;
+	}
+
+	printk("Socket interrupt event %08x (%08x %02x)\n", events, cb_event, csc);
+
+	if (events && socket->handler)
+		socket->handler(socket->info, events);
+}
+
+static unsigned int yenta_probe_irq(pci_socket_t *socket)
+{
+	int i;
+	unsigned long val;
+
+	cb_writel(socket, CB_SOCKET_EVENT, -1);
+	cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
+	val = probe_irq_on();
+	for (i = 1; i < 16; i++) {
+		exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG | (i << 4));
+		cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS);
+		udelay(100);
+		cb_writel(socket, CB_SOCKET_EVENT, -1);
+	}
+	cb_writel(socket, CB_SOCKET_MASK, 0);
+	return probe_irq_mask(val);
+}
+
+static void yenta_get_socket_capabilities(pci_socket_t *socket)
+{
+	socket->cap.features = SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS;
+	socket->cap.irq_mask = yenta_probe_irq(socket);
+	if (socket->cb_irq && socket->cb_irq < 16)
+		socket->cap.irq_mask |= 1 << socket->cb_irq;
+	socket->cap.map_size = 0x1000;
+	socket->cap.pci_irq = socket->cb_irq;
+	socket->cap.cardbus = config_readb(socket, PCI_CB_CARD_BUS);
+	socket->cap.cb_bus = socket->dev->subordinate;
+	socket->cap.bus = NULL;
+
+	printk("Yenta IRQ list %04x\n", socket->cap.irq_mask);
+}
+
+/*
+ * Initialize a cardbus controller. Make sure we have a usable
+ * interrupt, and that we can map the cardbus area. Fill in the
+ * socket information structure..
+ */
+static int yenta_open(pci_socket_t *socket)
+{
+	struct pci_dev *dev = socket->dev;
+
+	/*
+	 * Do some basic sanity checking..
+	 */
+	if (pci_enable_device(dev)) {
+		printk("Unable to enable device\n");
+		return -1;
+	}
+	if (!dev->resource[0].start) {
+		printk("No cardbus resource!\n");
+		return -1;
+	}
+
+	/*
+	 * Ok, start setup.. Map the cardbus registers,
+	 * and request the IRQ.
+	 */
+	socket->base = ioremap(dev->resource[0].start, 0x1000);
+	if (!socket->base)
+		return -1;
+
+	if (dev->irq && !request_irq(dev->irq, yenta_interrupt, SA_SHIRQ, dev->name, socket))
+		socket->cb_irq = dev->irq;
+
+	/* Figure out what the dang thing can do.. */
+	yenta_get_socket_capabilities(socket);
+
+	/* Enable all events */
+	writel(0x0f, socket->base + 4);
+
+	printk("Socket status: %08x\n", readl(socket->base + 8));
+	return 0;
+}
+
+/*
+ * Close it down - release our resources and go home..
+ */
+static void yenta_close(pci_socket_t *sock)
+{
+	if (sock->cb_irq)
+		free_irq(sock->cb_irq, sock);
+	if (sock->base)
+		iounmap(sock->base);
+}
+
+struct pci_socket_ops yenta_operations = {
+	yenta_open,
+	yenta_close,
+	yenta_inquire,
+	yenta_get_status,
+	yenta_get_socket,
+	yenta_set_socket,
+	yenta_get_io_map,
+	yenta_set_io_map,
+	yenta_get_mem_map,
+	yenta_set_mem_map,
+	yenta_get_bridge,
+	yenta_set_bridge,
+	yenta_proc_setup
+};
diff -u --recursive --new-file v2.3.34/linux/drivers/pcmcia/yenta.h linux/drivers/pcmcia/yenta.h
--- v2.3.34/linux/drivers/pcmcia/yenta.h	Thu Nov 11 20:11:43 1999
+++ linux/drivers/pcmcia/yenta.h	Tue Dec 28 17:43:37 1999
@@ -1,153 +1,124 @@
+#ifndef __YENTA_H
+#define __YENTA_H
+
+#include <asm/io.h>
+#include "pci_socket.h"
+
 /*
- * yenta.h 1.16 1999/10/25 20:03:34
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License. 
- *
- * The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>.  Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the MPL or the GPL.
+ * Generate easy-to-use ways of reading a cardbus sockets
+ * regular memory space ("cb_xxx"), configuration space
+ * ("config_xxx") and compatibility space ("exca_xxxx")
  */
 
-#ifndef _LINUX_YENTA_H
-#define _LINUX_YENTA_H
+#define cb_readb(sock,reg)		readb((sock)->base + (reg))
+#define cb_readw(sock,reg)		readw((sock)->base + (reg))
+#define cb_readl(sock,reg)		readl((sock)->base + (reg))
+#define cb_writeb(sock,reg,val)		writeb((val), (sock)->base + (reg))
+#define cb_writew(sock,reg,val)		writew((val), (sock)->base + (reg))
+#define cb_writel(sock,reg,val)		writel((val), (sock)->base + (reg))
+
+#define config_readb(sock,offset)	({ __u8 __val; pci_read_config_byte((sock)->dev, (offset), &__val); __val; })
+#define config_readw(sock,offset)	({ __u16 __val; pci_read_config_word((sock)->dev, (offset), &__val); __val; })
+#define config_readl(sock,offset)	({ __u32 __val; pci_read_config_dword((sock)->dev, (offset), &__val); __val; })
+
+#define config_writeb(sock,offset,val)	pci_write_config_byte((sock)->dev, (offset), (val))
+#define config_writew(sock,offset,val)	pci_write_config_word((sock)->dev, (offset), (val))
+#define config_writel(sock,offset,val)	pci_write_config_dword((sock)->dev, (offset), (val))
+
+#define exca_readb(sock,reg)		cb_readb((sock),(reg)+0x0800)
+#define exca_readw(sock,reg)		cb_readw((sock),(reg)+0x0800)
+#define exca_readl(sock,reg)		cb_readl((sock),(reg)+0x0800)
+
+#define exca_writeb(sock,reg,val)	cb_writeb((sock),(reg)+0x0800,(val))
+#define exca_writew(sock,reg,val)	cb_writew((sock),(reg)+0x0800,(val))
+#define exca_writel(sock,reg,val)	cb_writel((sock),(reg)+0x0800,(val))
+
+#define CB_SOCKET_EVENT		0x00
+#define    CB_CSTSEVENT		0x00000001	/* Card status event */
+#define    CB_CD1EVENT		0x00000002	/* Card detect 1 change event */
+#define    CB_CD2EVENT		0x00000004	/* Card detect 2 change event */
+#define    CB_PWREVENT		0x00000008	/* PWRCYCLE change event */
+
+#define CB_SOCKET_MASK		0x04
+#define    CB_CSTSMASK		0x00000001	/* Card status mask */
+#define    CB_CDMASK		0x00000006	/* Card detect 1&2 mask */
+#define    CB_PWRMASK		0x00000008	/* PWRCYCLE change mask */
+
+#define CB_SOCKET_STATE		0x08
+#define    CB_CARDSTS		0x00000001	/* CSTSCHG status */
+#define    CB_CDETECT1		0x00000002	/* Card detect status 1 */
+#define    CB_CDETECT2		0x00000004	/* Card detect status 2 */
+#define    CB_PWRCYCLE		0x00000008	/* Socket powered */
+#define    CB_16BITCARD		0x00000010	/* 16-bit card detected */
+#define    CB_CBCARD		0x00000020	/* CardBus card detected */
+#define    CB_IREQCINT		0x00000040	/* READY(xIRQ)/xCINT high */
+#define    CB_NOTACARD		0x00000080	/* Unrecognizable PC card detected */
+#define    CB_DATALOST		0x00000100	/* Potential data loss due to card removal */
+#define    CB_BADVCCREQ		0x00000200	/* Invalid Vcc request by host software */
+#define    CB_5VCARD		0x00000400	/* Card Vcc at 5.0 volts? */
+#define    CB_3VCARD		0x00000800	/* Card Vcc at 3.3 volts? */
+#define    CB_XVCARD		0x00001000	/* Card Vcc at X.X volts? */
+#define    CB_YVCARD		0x00002000	/* Card Vcc at Y.Y volts? */
+#define    CB_5VSOCKET		0x10000000	/* Socket Vcc at 5.0 volts? */
+#define    CB_3VSOCKET		0x20000000	/* Socket Vcc at 3.3 volts? */
+#define    CB_XVSOCKET		0x40000000	/* Socket Vcc at X.X volts? */
+#define    CB_YVSOCKET		0x80000000	/* Socket Vcc at Y.Y volts? */
+
+#define CB_SOCKET_FORCE		0x0C
+#define    CB_FCARDSTS		0x00000001	/* Force CSTSCHG */
+#define    CB_FCDETECT1		0x00000002	/* Force CD1EVENT */
+#define    CB_FCDETECT2		0x00000004	/* Force CD2EVENT */
+#define    CB_FPWRCYCLE		0x00000008	/* Force PWREVENT */
+#define    CB_F16BITCARD	0x00000010	/* Force 16-bit PCMCIA card */
+#define    CB_FCBCARD		0x00000020	/* Force CardBus line */
+#define    CB_FNOTACARD		0x00000080	/* Force NOTACARD */
+#define    CB_FDATALOST		0x00000100	/* Force data lost */
+#define    CB_FBADVCCREQ	0x00000200	/* Force bad Vcc request */
+#define    CB_F5VCARD		0x00000400	/* Force 5.0 volt card */
+#define    CB_F3VCARD		0x00000800	/* Force 3.3 volt card */
+#define    CB_FXVCARD		0x00001000	/* Force X.X volt card */
+#define    CB_FYVCARD		0x00002000	/* Force Y.Y volt card */
+#define    CB_CVSTEST		0x00004000	/* Card VS test */
+
+#define CB_SOCKET_CONTROL	0x10
+#define    CB_VPPCTRL		0		/* Shift for Vpp */
+#define    CB_VCCCTRL		4		/* Shift for Vcc */
+#define    CB_STOPCLK		0x00000080	/* CLKRUN can slow CB clock when idle */
+
+#define    CB_PWRBITS		0x7
+#define    CB_PWROFF		0x0
+#define    CB_PWR12V		0x1	/* Only valid for Vpp */
+#define    CB_PWR5V		0x2
+#define    CB_PWR3V		0x3
+#define    CB_PWRXV		0x4
+#define    CB_PWRYV		0x5
+
+#define CB_SOCKET_POWER		0x20
+#define    CB_SKTACCES		0x02000000	/* A PC card access has occurred (clear on read) */
+#define    CB_SKTMODE		0x01000000	/* Clock frequency has changed (clear on read) */
+#define    CB_CLKCTRLEN		0x00010000	/* Clock control enabled (RW) */
+#define    CB_CLKCTRL		0x00000001	/* Stop(0) or slow(1) CB clock (RW) */
 
-/* PCI Configuration Registers */
+/*
+ * Cardbus configuration space
+ */
+#define CB_BRIDGE_BASE(m)	(0x1c + 8*(m))
+#define CB_BRIDGE_LIMIT(m)	(0x20 + 8*(m))
+#define CB_BRIDGE_CONTROL	0x3e
+#define   CB_BRIDGE_CPERREN	0x00000001
+#define   CB_BRIDGE_CSERREN	0x00000002
+#define   CB_BRIDGE_ISAEN	0x00000004
+#define   CB_BRIDGE_VGAEN	0x00000008
+#define   CB_BRIDGE_MABTMODE	0x00000020
+#define   CB_BRIDGE_CRST	0x00000040
+#define   CB_BRIDGE_INTR	0x00000080
+#define   CB_BRIDGE_PREFETCH0	0x00000100
+#define   CB_BRIDGE_PREFETCH1	0x00000200
+#define   CB_BRIDGE_POSTEN	0x00000400
 
-#define PCI_STATUS_CAPLIST		0x10
-#define PCI_CB_CAPABILITY_POINTER	0x14	/* 8 bit */
-#define PCI_CAPABILITY_ID		0x00	/* 8 bit */
-#define  PCI_CAPABILITY_PM		0x01
-#define PCI_NEXT_CAPABILITY		0x01	/* 8 bit */
-#define PCI_PM_CAPABILITIES		0x02	/* 16 bit */
-#define  PCI_PMCAP_PME_D3COLD		0x8000
-#define  PCI_PMCAP_PME_D3HOT		0x4000
-#define  PCI_PMCAP_PME_D2		0x2000
-#define  PCI_PMCAP_PME_D1		0x1000
-#define  PCI_PMCAP_PME_D0		0x0800
-#define  PCI_PMCAP_D2_CAP		0x0400
-#define  PCI_PMCAP_D1_CAP		0x0200
-#define  PCI_PMCAP_DYN_DATA		0x0100
-#define  PCI_PMCAP_DSI			0x0020
-#define  PCI_PMCAP_AUX_PWR		0x0010
-#define  PCI_PMCAP_PMECLK		0x0008
-#define  PCI_PMCAP_VERSION_MASK		0x0007
-#define PCI_PM_CONTROL_STATUS		0x04	/* 16 bit */
-#define  PCI_PMCS_PME_STATUS		0x8000
-#define  PCI_PMCS_DATASCALE_MASK	0x6000
-#define  PCI_PMCS_DATASCALE_SHIFT	13
-#define  PCI_PMCS_DATASEL_MASK		0x1e00
-#define  PCI_PMCS_DATASEL_SHIFT		9
-#define  PCI_PMCS_PME_ENABLE		0x0100
-#define  PCI_PMCS_PWR_STATE_MASK	0x0003
-#define  PCI_PMCS_PWR_STATE_D0		0x0000
-#define  PCI_PMCS_PWR_STATE_D1		0x0001
-#define  PCI_PMCS_PWR_STATE_D2		0x0002
-#define  PCI_PMCS_PWR_STATE_D3		0x0003
-#define PCI_PM_BRIDGE_EXT		0x06	/* 8 bit */
-#define PCI_PM_DATA			0x07	/* 8 bit */
-
-#define CB_PRIMARY_BUS			0x18	/* 8 bit */
-#define CB_CARDBUS_BUS			0x19	/* 8 bit */
-#define CB_SUBORD_BUS			0x1a	/* 8 bit */
-#define CB_LATENCY_TIMER		0x1b	/* 8 bit */
-
-#define CB_MEM_BASE(m)			(0x1c + 8*(m))
-#define CB_MEM_LIMIT(m)			(0x20 + 8*(m))
-#define CB_IO_BASE(m)			(0x2c + 8*(m))
-#define CB_IO_LIMIT(m)			(0x30 + 8*(m))
-
-#define CB_BRIDGE_CONTROL		0x3e	/* 16 bit */
-#define  CB_BCR_PARITY_ENA		0x0001
-#define  CB_BCR_SERR_ENA		0x0002
-#define  CB_BCR_ISA_ENA			0x0004
-#define  CB_BCR_VGA_ENA			0x0008
-#define  CB_BCR_MABORT			0x0020
-#define  CB_BCR_CB_RESET		0x0040
-#define  CB_BCR_ISA_IRQ			0x0080
-#define  CB_BCR_PREFETCH(m)		(0x0100 << (m))
-#define  CB_BCR_WRITE_POST		0x0400
-
-#define CB_LEGACY_MODE_BASE		0x44
-
-/* Memory mapped registers */
-
-#define CB_SOCKET_EVENT			0x0000
-#define  CB_SE_CSTSCHG			0x00000001
-#define  CB_SE_CCD1			0x00000002
-#define  CB_SE_CCD2			0x00000004
-#define  CB_SE_PWRCYCLE			0x00000008
-
-#define CB_SOCKET_MASK			0x0004
-#define  CB_SM_CSTSCHG			0x00000001
-#define  CB_SM_CCD			0x00000006
-#define  CB_SM_PWRCYCLE			0x00000008
-
-#define CB_SOCKET_STATE			0x0008
-#define  CB_SS_CSTSCHG			0x00000001
-#define  CB_SS_CCD1			0x00000002
-#define  CB_SS_CCD2			0x00000004
-#define  CB_SS_PWRCYCLE			0x00000008
-#define  CB_SS_16BIT			0x00000010
-#define  CB_SS_32BIT			0x00000020
-#define  CB_SS_CINT			0x00000040
-#define  CB_SS_BADCARD			0x00000080
-#define  CB_SS_DATALOST			0x00000100
-#define  CB_SS_BADVCC			0x00000200
-#define  CB_SS_5VCARD			0x00000400
-#define  CB_SS_3VCARD			0x00000800
-#define  CB_SS_XVCARD			0x00001000
-#define  CB_SS_YVCARD			0x00002000
-#define  CB_SS_5VSOCKET			0x10000000
-#define  CB_SS_3VSOCKET			0x20000000
-#define  CB_SS_XVSOCKET			0x40000000
-#define  CB_SS_YVSOCKET			0x80000000
-
-#define CB_SOCKET_FORCE			0x000c
-#define  CB_SF_CVSTEST			0x00004000
-
-#define CB_SOCKET_CONTROL		0x0010
-#define  CB_SC_VPP_MASK			0x00000007
-#define   CB_SC_VPP_OFF			0x00000000
-#define   CB_SC_VPP_12V			0x00000001
-#define   CB_SC_VPP_5V			0x00000002
-#define   CB_SC_VPP_3V			0x00000003
-#define   CB_SC_VPP_XV			0x00000004
-#define   CB_SC_VPP_YV			0x00000005
-#define  CB_SC_VCC_MASK			0x00000070
-#define   CB_SC_VCC_OFF			0x00000000
-#define   CB_SC_VCC_5V			0x00000020
-#define   CB_SC_VCC_3V			0x00000030
-#define   CB_SC_VCC_XV			0x00000040
-#define   CB_SC_VCC_YV			0x00000050
-#define  CB_SC_CCLK_STOP		0x00000080
-
-#define CB_SOCKET_POWER			0x0020
-#define  CB_SP_CLK_CTRL			0x00000001
-#define  CB_SP_CLK_CTRL_ENA		0x00010000
-#define  CB_SP_CLK_MODE			0x01000000
-#define  CB_SP_ACCESS			0x02000000
-
-/* Address bits 31..24 for memory windows for 16-bit cards,
-   accessable only by memory mapping the 16-bit register set */
-#define CB_MEM_PAGE(map)		(0x40 + (map))
+/*
+ * ExCA area extensions in Yenta
+ */
+#define CB_MEM_PAGE(map)	(0x40 + (map))
 
-#endif /* _LINUX_YENTA_H */
+#endif
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/amd7930.c linux/drivers/sbus/audio/amd7930.c
--- v2.3.34/linux/drivers/sbus/audio/amd7930.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/sbus/audio/amd7930.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/*
+/* $Id: amd7930.c,v 1.23 1999/11/19 09:55:58 davem Exp $
  * drivers/sbus/audio/amd7930.c
  *
  * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu)
@@ -132,31 +132,30 @@
 
 struct amd7930_channel {
 	/* Channel status */
-	unsigned char channel_status;
+	u8 channel_status;
 
 	/* Current buffer that the driver is playing on channel */
 	volatile __u8 * output_ptr;
-	volatile unsigned long output_count;
-	unsigned char xmit_idle_char;
+	volatile u32 output_count;
+	u8 xmit_idle_char;
 
 	/* Callback routine (and argument) when output is done on */
-	void (*output_callback)();
+	void (*output_callback)(void *, unsigned char);
 	void * output_callback_arg;
 
 	/* Current buffer that the driver is recording on channel */
 	volatile __u8 * input_ptr;
-	volatile unsigned long input_count;
-	volatile unsigned long input_limit;
+	volatile u32 input_count;
+	volatile u32 input_limit;
 
 	/* Callback routine (and argument) when input is done on */
-	void (*input_callback)();
+	void (*input_callback)(void *, unsigned char, unsigned long);
 	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;
@@ -171,7 +170,7 @@
 	struct amd7930_channel *Bisdn[2];
 
 	/* Device registers information. */
-	struct amd7930 *regs;
+	unsigned long regs;
 	unsigned long regs_size;
 	struct amd7930_map map;
 
@@ -185,21 +184,20 @@
 	/* Format type */
 	int format_type;
 
-
 	/* Someone to signal when the ISDN LIU state changes */
 	int liu_state;
 	void (*liu_callback)(void *);
 	void *liu_callback_arg;
 };
 
-
-
 /* Output a 16-bit quantity in the order that the amd7930 expects. */
-#define amd7930_out16(regs,v) ({ regs->dr = v & 0xFF; regs->dr = (v >> 8) & 0xFF; })
-
+static __inline__ void amd7930_out16(unsigned long regs, u16 val)
+{
+	sbus_writeb(val & 0xff, regs + DR);
+	sbus_writeb(val >> 8, regs + DR);
+}
 
-/*
- * gx, gr & stg gains.  this table must contain 256 elements with
+/* gx, gr & stg gains.  this table must contain 256 elements with
  * the 0th being "infinity" (the magic value 9008).  The remaining
  * elements match sun's gain curve (but with higher resolution):
  * -18 to 0dB in .16dB steps then 0 to 12dB in .08dB steps.
@@ -265,80 +263,76 @@
 #define NR_GER_COEFFS (sizeof(ger_coeff) / sizeof(ger_coeff[0]))
 
 /* Enable amd7930 interrupts atomically. */
-static __inline__ void amd7930_enable_ints(struct amd7930_info *info)
+static void amd7930_enable_ints(struct amd7930_info *info)
 {
-	register unsigned long flags;
-
-	if (info->ints_on)
-		return;
+	unsigned long flags;
 
 	save_and_cli(flags);
-	info->regs->cr = AMR_INIT;
-	info->regs->dr = AM_INIT_ACTIVE;
+	if (!info->ints_on) {
+		sbus_writeb(AMR_INIT, info->regs + CR);
+		sbus_writeb(AM_INIT_ACTIVE, info->regs + DR);
+		info->ints_on = 1;
+	}
 	restore_flags(flags);
-
-	info->ints_on = 1;
 }
 
 /* Disable amd7930 interrupts atomically. */
 static __inline__ void amd7930_disable_ints(struct amd7930_info *info)
 {
-	register unsigned long flags;
-
-	if (!info->ints_on)
-		return;
+	unsigned long flags;
 
 	save_and_cli(flags);
-	info->regs->cr = AMR_INIT;
-	info->regs->dr = AM_INIT_ACTIVE | AM_INIT_DISABLE_INTS;
+	if (info->ints_on) {
+		sbus_writeb(AMR_INIT, info->regs + CR);
+		sbus_writeb(AM_INIT_ACTIVE | AM_INIT_DISABLE_INTS,
+			    info->regs + DR);
+		info->ints_on = 0;
+	}
 	restore_flags(flags);
 
-	info->ints_on = 0;
 }  
 
 /* Idle amd7930 (no interrupts, no audio, no data) */
 static __inline__ void amd7930_idle(struct amd7930_info *info)
 {
-	register unsigned long flags;
-
-	if (!info->ints_on)
-		return;
+	unsigned long flags;
 
 	save_and_cli(flags);
-	info->regs->cr = AMR_INIT;
-	info->regs->dr = 0;
+	if (info->ints_on) {
+		sbus_writeb(AMR_INIT, info->regs + CR);
+		sbus_writeb(0, info->regs + DR);
+		info->ints_on = 0;
+	}
 	restore_flags(flags);
-
-	info->ints_on = 0;
 }  
 
 /* Commit the local copy of the MAP registers to the amd7930. */
 static void amd7930_write_map(struct sparcaudio_driver *drv)
 {
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
-	struct amd7930      *regs = info->regs;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
+	unsigned long        regs = info->regs;
 	struct amd7930_map  *map  = &info->map;
 	unsigned long flags;
 
 	save_and_cli(flags);
 
-	regs->cr = AMR_MAP_GX;
+	sbus_writeb(AMR_MAP_GX, regs + CR);
 	amd7930_out16(regs, map->gx);
 
-	regs->cr = AMR_MAP_GR;
+	sbus_writeb(AMR_MAP_GR, regs + CR);
 	amd7930_out16(regs, map->gr);
 
-	regs->cr = AMR_MAP_STGR;
+	sbus_writeb(AMR_MAP_STGR, regs + CR);
 	amd7930_out16(regs, map->stgr);
 
-	regs->cr = AMR_MAP_GER;
+	sbus_writeb(AMR_MAP_GER, regs + CR);
 	amd7930_out16(regs, map->ger);
 
-	regs->cr = AMR_MAP_MMR1;
-	regs->dr = map->mmr1;
+	sbus_writeb(AMR_MAP_MMR1, regs + CR);
+	sbus_writeb(map->mmr1, regs + DR);
 
-	regs->cr = AMR_MAP_MMR2;
-	regs->dr = map->mmr2;
+	sbus_writeb(AMR_MAP_MMR2, regs + CR);
+	sbus_writeb(map->mmr2, regs + DR);
 
 	restore_flags(flags);
 }
@@ -346,7 +340,7 @@
 /* Update the MAP registers with new settings. */
 static void amd7930_update_map(struct sparcaudio_driver *drv)
 {
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 	struct amd7930_map  *map  = &info->map;
 	int level;
 
@@ -380,14 +374,17 @@
 
 #ifdef L2FRAME_DEBUG
 
-inline void debug_info(struct amd7930_info *info, char c) {
+inline void debug_info(struct amd7930_info *info, char c)
+{
 	struct IsdnCardState *cs;
 
-	if (!info || !info->D.output_callback_arg) return;
+	if (!info || !info->D.output_callback_arg)
+		return;
 
-	cs = (struct IsdnCardState *)info->D.output_callback_arg;
+	cs = (struct IsdnCardState *) info->D.output_callback_arg;
 
-	if (!cs || !cs->status_write) return;
+	if (!cs || !cs->status_write)
+		return;
 
 	if (cs->debug & L1_DEB_INTSTAT) {
 		*(cs->status_write++) = c;
@@ -402,15 +399,15 @@
 
 #endif
 
-
 static void fill_D_xmit_fifo(struct amd7930_info *info)
 {
 	/* Send next byte(s) of outgoing data. */
 	while (info->D.output_ptr && info->D.output_count > 0 &&
-               (info->regs->dsr2 & AMR_DSR2_TBE)) {
+               (sbus_readb(info->regs + DSR2) & AMR_DSR2_TBE)) {
+		u8 byte = *(info->D.output_ptr);
 
 		/* Send the next byte and advance buffer pointer. */
-		info->regs->dctb = *(info->D.output_ptr);
+		sbus_writeb(byte, info->regs + DCTB);
 		info->D.output_ptr++;
 		info->D.output_count--;
 
@@ -437,51 +434,40 @@
 		if (info->D.output_callback)
 			(*info->D.output_callback)
 				(info->D.output_callback_arg,
-				 info->regs->der);
-				 /* info->regs->der & D_XMIT_ERRORS); */
+				 sbus_readb(info->regs + DER));
+				 /* sbus_readb(info->regs + DER) & D_XMIT_ERRORS); */
 	}
 
 	/* Read the next byte(s) of incoming data. */
 
-	while (info->regs->dsr2 & AMR_DSR2_RBA) {
-
+	while (sbus_readb(info->regs + DSR2) & AMR_DSR2_RBA) {
 		if (info->D.input_ptr &&
 		    (info->D.input_count < info->D.input_limit)) {
-
 			/* Get the next byte and advance buffer pointer. */
-
-			*(info->D.input_ptr) = info->regs->dcrb;
+			*(info->D.input_ptr) = sbus_readb(info->regs + DCRB);
 			info->D.input_ptr++;
 			info->D.input_count++;
-
 		} else {
-
 			/* Overflow - should be detected by chip via RBLR
 			 * so we'll just consume data until we see LBRP
 			 */
-
-			dummy = info->regs->dcrb;
-
+			dummy = sbus_readb(info->regs + DCRB);
 		}
 
 		debug_info(info, '<');
 
-		if (info->regs->dsr2 & AMR_DSR2_LBRP) {
-
-			/* End of recv packet? Notify the midlevel driver. */
-
+		if (sbus_readb(info->regs + DSR2) & AMR_DSR2_LBRP) {
 			__u8 der;
 
+			/* End of recv packet? Notify the midlevel driver. */
 			debug_info(info, '!');
-
 			info->D.input_ptr = NULL;
-
-			der = info->regs->der & D_RECV_ERRORS;
+			der = sbus_readb(info->regs + DER) & D_RECV_ERRORS;
 
 			/* Read receive byte count - advances FIFOs */
-			info->regs->cr = AMR_DLC_DRCR;
-			dummy = info->regs->dr;
-			dummy = info->regs->dr;
+			sbus_writeb(AMR_DLC_DRCR, info->regs + CR);
+			dummy = sbus_readb(info->regs + DR);
+			dummy = sbus_readb(info->regs + DR);
 
 			if (info->D.input_callback)
 				(*info->D.input_callback)
@@ -492,26 +478,33 @@
 	}
 }
 
-long amd7930_xmit_idles=0;
+long amd7930_xmit_idles = 0;
 
 static void transceive_Bchannel(struct amd7930_channel *channel,
-	__volatile__ __u8 *io_reg)
+				unsigned long reg)
 {
 	/* Send the next byte of outgoing data. */
 	if (channel->output_ptr && channel->output_count > 0) {
+		u8 byte;
 
 		/* Send the next byte and advance buffer pointer. */
 		switch(channel->output_format) {
 		case AUDIO_ENCODING_ULAW:
 		case AUDIO_ENCODING_ALAW:
-			*io_reg = *(channel->output_ptr);
+			byte = *(channel->output_ptr);
+			sbus_writeb(byte, reg);
 			break;
 		case AUDIO_ENCODING_LINEAR8:
-			*io_reg = bilinear2mulaw(*(channel->output_ptr));
+			byte = bilinear2mulaw(*(channel->output_ptr));
+			sbus_writeb(byte, reg);
 			break;
 		case AUDIO_ENCODING_LINEAR:
 			if (channel->output_count >= 2) {
-				*io_reg = linear2mulaw(*((__u16*)(channel->output_ptr)));
+				u16 val = channel->output_ptr[0] << 8;
+
+				val |= channel->output_ptr[1];
+				byte = linear2mulaw(val);
+				sbus_writeb(byte, reg);
 				channel->output_ptr++;
 				channel->output_count--;
 			};
@@ -529,28 +522,31 @@
 					(channel->output_callback_arg,1);
 		}
 	} else {
-		*io_reg = channel->xmit_idle_char;
+		sbus_writeb(channel->xmit_idle_char, reg);
 		amd7930_xmit_idles++;
         }
 
 	/* Read the next byte of incoming data. */
 	if (channel->input_ptr && channel->input_count > 0) {
-
 		/* Get the next byte and advance buffer pointer. */
 		switch(channel->input_format) {
 		case AUDIO_ENCODING_ULAW:
 		case AUDIO_ENCODING_ALAW:
-			*(channel->input_ptr) = *io_reg;
+			*(channel->input_ptr) = sbus_readb(reg);
 			break;
 		case AUDIO_ENCODING_LINEAR8:
-			*(channel->input_ptr) = mulaw2bilinear(*io_reg);
+			*(channel->input_ptr) = mulaw2bilinear(sbus_readb(reg));
 			break;
 		case AUDIO_ENCODING_LINEAR:
 			if (channel->input_count >= 2) {
-				*((__u16*)(channel->input_ptr)) = mulaw2linear(*io_reg);
+				u16 val = mulaw2linear(sbus_readb(reg));
+				channel->input_ptr[0] = val >> 8;
+				channel->input_ptr[1] = val & 0xff;
 				channel->input_ptr++;
 				channel->input_count--;
-			} else *(channel->input_ptr) = 0;
+			} else {
+				*(channel->input_ptr) = 0;
+			}
 		};
 		channel->input_ptr++;
 		channel->input_count--;
@@ -561,7 +557,7 @@
 			channel->input_count = 0;
 			if (channel->input_callback)
 				(*channel->input_callback)
-					(channel->input_callback_arg, 1);
+					(channel->input_callback_arg, 1, 0);
 		}
 	}
 }
@@ -569,20 +565,19 @@
 /* Interrupt handler (The chip takes only one byte per interrupt. Grrr!) */
 static void amd7930_interrupt(int irq, void *dev_id, struct pt_regs *intr_regs)
 {
-	struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id;
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
-	struct amd7930 *regs = info->regs;
+	struct sparcaudio_driver *drv = (struct sparcaudio_driver *) dev_id;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
+	unsigned long regs = info->regs;
 	__u8 ir;
-	__u8 lsr;
 
 	/* Clear the interrupt. */
-	ir = regs->ir;
+	ir = sbus_readb(regs + IR);
 
 	if (ir & AMR_IR_BBUF) {
 		if (info->Bb.channel_status == CHANNEL_INUSE)
-			transceive_Bchannel(&info->Bb, &info->regs->bbtb);
+			transceive_Bchannel(&info->Bb, info->regs + BBTB);
 		if (info->Bc.channel_status == CHANNEL_INUSE)
-			transceive_Bchannel(&info->Bc, &info->regs->bctb);
+			transceive_Bchannel(&info->Bc, info->regs + BCTB);
 	}
 
 	if (ir & (AMR_IR_DRTHRSH | AMR_IR_DTTHRSH | AMR_IR_DSRI)) {
@@ -592,21 +587,22 @@
 	}
 
 	if (ir & AMR_IR_LSRI) {
-		regs->cr = AMR_LIU_LSR;
-		lsr = regs->dr;
+		__u8 lsr;
 
-                info->liu_state = (lsr&0x7) + 2;
+		sbus_writeb(AMR_LIU_LSR, regs + CR);
+		lsr = sbus_readb(regs + DR);
+
+                info->liu_state = (lsr & 0x7) + 2;
 
                 if (info->liu_callback)
 			(*info->liu_callback)(info->liu_callback_arg);
         }
 }
 
-
 static int amd7930_open(struct inode * inode, struct file * file,
 			struct sparcaudio_driver *drv)
 {
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
 	switch(MINOR(inode->i_rdev) & 0xf) {
 	case SPARCAUDIO_AUDIO_MINOR:
@@ -634,31 +630,29 @@
 static void request_Baudio(struct amd7930_info *info)
 {
 	if (info->Bb.channel_status == CHANNEL_AVAILABLE) {
-
 		info->Bb.channel_status = CHANNEL_INUSE;
 		info->Baudio = &info->Bb;
 
 		/* Multiplexor map - audio (Ba) to Bb */
-		info->regs->cr = AMR_MUX_MCR1;
-		info->regs->dr = AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bb << 4);
+		sbus_writeb(AMR_MUX_MCR1, info->regs + CR);
+		sbus_writeb(AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bb << 4),
+			    info->regs + DR);
 
 		/* Enable B channel interrupts */
-		info->regs->cr = AMR_MUX_MCR4;
-		info->regs->dr = AM_MUX_MCR4_ENABLE_INTS;
-
+		sbus_writeb(AMR_MUX_MCR4, info->regs + CR);
+		sbus_writeb(AM_MUX_MCR4_ENABLE_INTS, info->regs + DR);
 	} else if (info->Bc.channel_status == CHANNEL_AVAILABLE) {
-
 		info->Bc.channel_status = CHANNEL_INUSE;
 		info->Baudio = &info->Bc;
 
 		/* Multiplexor map - audio (Ba) to Bc */
-		info->regs->cr = AMR_MUX_MCR1;
-		info->regs->dr = AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bc << 4);
+		sbus_writeb(AMR_MUX_MCR1, info->regs + CR);
+		sbus_writeb(AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bc << 4),
+			    info->regs + DR);
 
 		/* Enable B channel interrupts */
-		info->regs->cr = AMR_MUX_MCR4;
-		info->regs->dr = AM_MUX_MCR4_ENABLE_INTS;
-
+		sbus_writeb(AMR_MUX_MCR4, info->regs + CR);
+		sbus_writeb(AM_MUX_MCR4_ENABLE_INTS, info->regs + DR);
 	}
 }
 
@@ -666,16 +660,15 @@
 {
 	if (info->Baudio) {
 		info->Baudio->channel_status = CHANNEL_AVAILABLE;
-		info->regs->cr = AMR_MUX_MCR1;
-		info->regs->dr = 0;
+		sbus_writeb(AMR_MUX_MCR1, info->regs + CR);
+		sbus_writeb(0, info->regs + DR);
 		info->Baudio = NULL;
 
 		if (info->Bb.channel_status == CHANNEL_AVAILABLE &&
 		    info->Bc.channel_status == CHANNEL_AVAILABLE) {
-
 			/* Disable B channel interrupts */
-			info->regs->cr = AMR_MUX_MCR4;
-			info->regs->dr = 0;
+			sbus_writeb(AMR_MUX_MCR4, info->regs + CR);
+			sbus_writeb(0, info->regs + DR);
 		}
 	}
 }
@@ -683,25 +676,24 @@
 static void amd7930_start_output(struct sparcaudio_driver *drv,
 				 __u8 * buffer, unsigned long count)
 {
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
-	if (! info->Baudio) {
+	if (! info->Baudio)
 		request_Baudio(info);
-	}
 
 	if (info->Baudio) {
 		info->Baudio->output_ptr = buffer;
 		info->Baudio->output_count = count;
 		info->Baudio->output_format = info->format_type;
-       	info->Baudio->output_callback = (void *) &sparcaudio_output_done;
-        info->Baudio->output_callback_arg = (void *) drv;
+		info->Baudio->output_callback = (void *) &sparcaudio_output_done;
+		info->Baudio->output_callback_arg = (void *) drv;
 		info->Baudio->xmit_idle_char = 0;
 	}
 }
 
 static void amd7930_stop_output(struct sparcaudio_driver *drv)
 {
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
 	if (info->Baudio) {
 		info->Baudio->output_ptr = NULL;
@@ -714,11 +706,10 @@
 static void amd7930_start_input(struct sparcaudio_driver *drv,
 				__u8 * buffer, unsigned long count)
 {
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
-	if (! info->Baudio) {
+	if (! info->Baudio)
 		request_Baudio(info);
-	}
 
 	if (info->Baudio) {
 		info->Baudio->input_ptr = buffer;
@@ -731,7 +722,7 @@
 
 static void amd7930_stop_input(struct sparcaudio_driver *drv)
 {
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
 	if (info->Baudio) {
 		info->Baudio->input_ptr = NULL;
@@ -772,7 +763,7 @@
 
 static int amd7930_set_output_volume(struct sparcaudio_driver *drv, int vol)
 {
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
 	info->pgain = vol;
 	amd7930_update_map(drv);
@@ -781,14 +772,14 @@
 
 static int amd7930_get_output_volume(struct sparcaudio_driver *drv)
 {
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
 	return info->pgain;
 }
 
 static int amd7930_set_input_volume(struct sparcaudio_driver *drv, int vol)
 {
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
 	info->rgain = vol;
 	amd7930_update_map(drv);
@@ -797,14 +788,14 @@
 
 static int amd7930_get_input_volume(struct sparcaudio_driver *drv)
 {
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
 	return info->rgain;
 }
 
 static int amd7930_set_monitor_volume(struct sparcaudio_driver *drv, int vol)
 {
-	struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
 	info->mgain = vol;
 	amd7930_update_map(drv);
@@ -813,7 +804,7 @@
 
 static int amd7930_get_monitor_volume(struct sparcaudio_driver *drv)
 {
-      struct amd7930_info *info = (struct amd7930_info *)drv->private;
+      struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
       return info->mgain;
 }
@@ -848,7 +839,7 @@
 static int 
 amd7930_set_input_channels(struct sparcaudio_driver *drv, int value)
 {
-  return (value == AUDIO_MIN_REC_CHANNELS) ? 0 : -EINVAL;
+	return (value == AUDIO_MIN_REC_CHANNELS) ? 0 : -EINVAL;
 }
 
 static int amd7930_get_output_precision(struct sparcaudio_driver *drv)
@@ -859,7 +850,7 @@
 static int 
 amd7930_set_output_precision(struct sparcaudio_driver *drv, int value)
 {
-  return (value == AUDIO_MIN_PLAY_PRECISION) ? 0 : -EINVAL;
+	return (value == AUDIO_MIN_PLAY_PRECISION) ? 0 : -EINVAL;
 }
 
 static int amd7930_get_input_precision(struct sparcaudio_driver *drv)
@@ -870,32 +861,36 @@
 static int 
 amd7930_set_input_precision(struct sparcaudio_driver *drv, int value)
 {
-  return (value == AUDIO_MIN_REC_PRECISION) ? 0 : -EINVAL;
+	return (value == AUDIO_MIN_REC_PRECISION) ? 0 : -EINVAL;
 }
 
 static int amd7930_get_output_port(struct sparcaudio_driver *drv)
 {
-  struct amd7930_info *info = (struct amd7930_info *)drv->private;
-  if (info->map.mmr2 & AM_MAP_MMR2_LS)
-    return AUDIO_SPEAKER; 
-  return AUDIO_HEADPHONE;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
+
+	if (info->map.mmr2 & AM_MAP_MMR2_LS)
+		return AUDIO_SPEAKER; 
+
+	return AUDIO_HEADPHONE;
 }
 
 static int amd7930_set_output_port(struct sparcaudio_driver *drv, int value)
 {
-  struct amd7930_info *info = (struct amd7930_info *)drv->private;
-  switch (value) {
-  case AUDIO_HEADPHONE:
-    info->map.mmr2 &= ~AM_MAP_MMR2_LS;
-    break;
-  case AUDIO_SPEAKER:
-    info->map.mmr2 |= AM_MAP_MMR2_LS;
-    break;
-  default:
-    return -EINVAL;
-  }
-  amd7930_update_map(drv);
-  return 0;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
+
+	switch (value) {
+	case AUDIO_HEADPHONE:
+		info->map.mmr2 &= ~AM_MAP_MMR2_LS;
+		break;
+	case AUDIO_SPEAKER:
+		info->map.mmr2 |= AM_MAP_MMR2_LS;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	amd7930_update_map(drv);
+	return 0;
 }
 
 /* Only a microphone here, so no troubles */
@@ -906,36 +901,37 @@
 
 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) && 
-      (info->format_type == AUDIO_ENCODING_ALAW))
-    return AUDIO_ENCODING_ALAW;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
+
+	if ((info->map.mmr1 & AM_MAP_MMR1_ALAW) && 
+	    (info->format_type == AUDIO_ENCODING_ALAW))
+		return AUDIO_ENCODING_ALAW;
 
-  return info->format_type;
+	return info->format_type;
 }
 
 static int 
 amd7930_set_encoding(struct sparcaudio_driver *drv, int value)
 {
-  struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
-  switch (value) {
-  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;
-  };
+	switch (value) {
+	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;
+	info->format_type = value;
 
-  amd7930_update_map(drv);
-  return 0;
+	amd7930_update_map(drv);
+	return 0;
 }
 
 /* This is what you get. Take it or leave it */
@@ -947,7 +943,7 @@
 static int 
 amd7930_set_output_rate(struct sparcaudio_driver *drv, int value)
 {
-  return (value == AMD7930_RATE) ? 0 : -EINVAL;
+	return (value == AMD7930_RATE) ? 0 : -EINVAL;
 }
 
 static int amd7930_get_input_rate(struct sparcaudio_driver *drv)
@@ -958,7 +954,7 @@
 static int
 amd7930_set_input_rate(struct sparcaudio_driver *drv, int value)
 {
-  return (value == AMD7930_RATE) ? 0 : -EINVAL;
+	return (value == AMD7930_RATE) ? 0 : -EINVAL;
 }
 
 static int amd7930_get_output_muted(struct sparcaudio_driver *drv)
@@ -968,31 +964,30 @@
 
 static void amd7930_loopback(struct sparcaudio_driver *drv, unsigned int value)
 {
-  struct amd7930_info *info = (struct amd7930_info *)drv->private;
+	struct amd7930_info *info = (struct amd7930_info *) drv->private;
 
-  if (value)
-    info->map.mmr1 |= AM_MAP_MMR1_LOOPBACK;
-  else
-    info->map.mmr1 &= ~AM_MAP_MMR1_LOOPBACK;
-  amd7930_update_map(drv);
-  return;
+	if (value)
+		info->map.mmr1 |= AM_MAP_MMR1_LOOPBACK;
+	else
+		info->map.mmr1 &= ~AM_MAP_MMR1_LOOPBACK;
+	amd7930_update_map(drv);
 }
 
 static int amd7930_ioctl(struct inode * inode, struct file * file,
                          unsigned int cmd, unsigned long arg, 
                          struct sparcaudio_driver *drv)
 {
-  int retval = 0;
+	int retval = 0;
   
-  switch (cmd) {
-  case AUDIO_DIAG_LOOPBACK:
-    amd7930_loopback(drv, (unsigned int)arg);
-    break;
-  default:
-    retval = -EINVAL;
-  }
+	switch (cmd) {
+	case AUDIO_DIAG_LOOPBACK:
+		amd7930_loopback(drv, (unsigned int)arg);
+		break;
+	default:
+		retval = -EINVAL;
+	};
 
-  return retval;
+	return retval;
 }
 
 
@@ -1141,9 +1136,8 @@
 {
 	struct amd7930_info *info;
 
-	if (dev > num_drivers) {
+	if (dev > num_drivers)
 		return(0);
-	}
 
 	info = (struct amd7930_info *) drivers[dev].private;
 
@@ -1154,9 +1148,8 @@
 {
 	struct amd7930_info *info;
 
-	if (dev > num_drivers) {
+	if (dev > num_drivers)
 		return(0);
-	}
 
 	info = (struct amd7930_info *) drivers[dev].private;
 
@@ -1166,11 +1159,10 @@
 static void amd7930_liu_init(int dev, void (*callback)(), void *callback_arg)
 {
 	struct amd7930_info *info;
-	register unsigned long flags;
+	unsigned long flags;
 
-	if (dev > num_drivers) {
+	if (dev > num_drivers)
 		return;
-	}
 
 	info = (struct amd7930_info *) drivers[dev].private;
 
@@ -1181,19 +1173,21 @@
 	info->liu_callback_arg = callback_arg;
 
 	/* De-activate the ISDN Line Interface Unit (LIU) */
-	info->regs->cr = AMR_LIU_LMR1;
-	info->regs->dr = 0;
+	sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
+	sbus_writeb(0, info->regs + DR);
 
 	/* Request interrupt when LIU changes state from/to F3/F7/F8 */
-	info->regs->cr = AMR_LIU_LMR2;
-	info->regs->dr = AM_LIU_LMR2_EN_F3_INT |
-          AM_LIU_LMR2_EN_F7_INT | AM_LIU_LMR2_EN_F8_INT;
+	sbus_writeb(AMR_LIU_LMR2, info->regs + CR);
+	sbus_writeb(AM_LIU_LMR2_EN_F3_INT |
+		    AM_LIU_LMR2_EN_F7_INT |
+		    AM_LIU_LMR2_EN_F8_INT,
+		    info->regs + DR);
 
 	/* amd7930_enable_ints(info); */
 
 	/* Activate the ISDN Line Interface Unit (LIU) */
-	info->regs->cr = AMR_LIU_LMR1;
-	info->regs->dr = AM_LIU_LMR1_LIU_ENABL;
+	sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
+	sbus_writeb(AM_LIU_LMR1_LIU_ENABL, info->regs + DR);
 
 	restore_flags(flags);
 }
@@ -1201,11 +1195,10 @@
 static void amd7930_liu_activate(int dev, int priority)
 {
 	struct amd7930_info *info;
-	register unsigned long flags;
+	unsigned long flags;
 
-	if (dev > num_drivers) {
+	if (dev > num_drivers)
 		return;
-	}
 
 	info = (struct amd7930_info *) drivers[dev].private;
 
@@ -1218,14 +1211,13 @@
          *
          * Priority 0 is eight 1s; priority 1 is ten 1s; etc
          */
-
-        info->regs->cr = AMR_LIU_LPR;
-        info->regs->dr = priority & 0x0f;
+        sbus_writeb(AMR_LIU_LPR, info->regs + CR);
+        sbus_writeb(priority & 0x0f, info->regs + DR);
 
 	/* request LIU activation */
-
-	info->regs->cr = AMR_LIU_LMR1;
-	info->regs->dr = AM_LIU_LMR1_LIU_ENABL | AM_LIU_LMR1_REQ_ACTIV;
+	sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
+	sbus_writeb(AM_LIU_LMR1_LIU_ENABL | AM_LIU_LMR1_REQ_ACTIV,
+		    info->regs + DR);
 
 	restore_flags(flags);
 }
@@ -1233,20 +1225,18 @@
 static void amd7930_liu_deactivate(int dev)
 {
 	struct amd7930_info *info;
-	register unsigned long flags;
+	unsigned long flags;
 
-	if (dev > num_drivers) {
+	if (dev > num_drivers)
 		return;
-	}
 
 	info = (struct amd7930_info *) drivers[dev].private;
 
 	save_and_cli(flags);
 
 	/* deactivate LIU */
-
-	info->regs->cr = AMR_LIU_LMR1;
-	info->regs->dr = 0;
+	sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
+	sbus_writeb(0, info->regs + DR);
 
 	restore_flags(flags);
 }
@@ -1255,12 +1245,11 @@
 			  void (*callback)(void *, int), void *callback_arg)
 {
 	struct amd7930_info *info;
-	register unsigned long flags;
+	unsigned long flags;
 	__u8 dmr1;
 
-	if (dev > num_drivers) {
+	if (dev > num_drivers)
 		return;
-	}
 
 	info = (struct amd7930_info *) drivers[dev].private;
 
@@ -1278,16 +1267,16 @@
 	info->D.output_callback_arg = callback_arg;
 
 	/* Enable D-channel Transmit Threshold interrupt; disable addressing */
-	info->regs->cr = AMR_DLC_DMR1;
-	dmr1 = info->regs->dr;
+	sbus_writeb(AMR_DLC_DMR1, info->regs + CR);
+	dmr1 = sbus_readb(info->regs + DR);
 	dmr1 |= AMR_DLC_DMR1_DTTHRSH_INT;
 	dmr1 &= ~AMR_DLC_DMR1_EN_ADDRS;
-	info->regs->dr = dmr1;
+	sbus_writeb(dmr1, info->regs + DR);
 
 	/* Begin xmit by setting D-channel Transmit Byte Count Reg (DTCR) */
-	info->regs->cr = AMR_DLC_DTCR;
-	info->regs->dr = count & 0xff;
-	info->regs->dr = (count >> 8) & 0xff;
+	sbus_writeb(AMR_DLC_DTCR, info->regs + CR);
+	sbus_writeb(count & 0xff, info->regs + DR);
+	sbus_writeb((count >> 8) & 0xff, info->regs + DR);
 
 	/* Prime xmit FIFO */
 	/* fill_D_xmit_fifo(info); */
@@ -1301,12 +1290,11 @@
 			  void *callback_arg)
 {
 	struct amd7930_info *info;
-	register unsigned long flags;
+	unsigned long flags;
 	__u8 dmr1;
 
-	if (dev > num_drivers) {
+	if (dev > num_drivers)
 		return;
-	}
 
 	info = (struct amd7930_info *) drivers[dev].private;
 
@@ -1328,16 +1316,16 @@
 	 * Enable D-channel End of Receive Packet interrupt;
 	 * Disable address recognition
 	 */
-	info->regs->cr = AMR_DLC_DMR1;
-	dmr1 = info->regs->dr;
+	sbus_writeb(AMR_DLC_DMR1, info->regs + CR);
+	dmr1 = sbus_readb(info->regs + DR);
 	dmr1 |= AMR_DLC_DMR1_DRTHRSH_INT | AMR_DLC_DMR1_EORP_INT;
 	dmr1 &= ~AMR_DLC_DMR1_EN_ADDRS;
-	info->regs->dr = dmr1;
+	sbus_writeb(dmr1, info->regs + DR);
 
 	/* Set D-channel Receive Byte Count Limit Register */
-	info->regs->cr = AMR_DLC_DRCR;
-	info->regs->dr = size & 0xff;
-	info->regs->dr = (size >> 8) & 0xff;
+	sbus_writeb(AMR_DLC_DRCR, info->regs + CR);
+	sbus_writeb(size & 0xff, info->regs + DR);
+	sbus_writeb((size >> 8) & 0xff, info->regs + DR);
 
 	restore_flags(flags);
 }
@@ -1346,54 +1334,56 @@
                          int mode, u_char xmit_idle_char)
 {
 	struct amd7930_info *info;
-	register unsigned long flags;
+	unsigned long flags;
+	u8 tmp;
 
-	if (dev > num_drivers || chan<0 || chan>1) {
+	if (dev > num_drivers || chan<0 || chan>1)
 		return -1;
-	}
 
-         if (mode == L1_MODE_HDLC) {
-                 return -1;
-         }
+	if (mode == L1_MODE_HDLC)
+		return -1;
  
 	info = (struct amd7930_info *) drivers[dev].private;
 
 	save_and_cli(flags);
 
 	if (info->Bb.channel_status == CHANNEL_AVAILABLE) {
-
 		info->Bb.channel_status = CHANNEL_INUSE;
 		info->Bb.xmit_idle_char = xmit_idle_char;
 		info->Bisdn[chan] = &info->Bb;
 
 		/* Multiplexor map - isdn (B1/2) to Bb */
-		info->regs->cr = AMR_MUX_MCR2 + chan;
-		info->regs->dr = (AM_MUX_CHANNEL_B1 + chan) |
-				 (AM_MUX_CHANNEL_Bb << 4);
-
+		sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR);
+		sbus_writeb((AM_MUX_CHANNEL_B1 + chan) |
+			    (AM_MUX_CHANNEL_Bb << 4),
+			    info->regs + DR);
 	} else if (info->Bc.channel_status == CHANNEL_AVAILABLE) {
-
 		info->Bc.channel_status = CHANNEL_INUSE;
 		info->Bc.xmit_idle_char = xmit_idle_char;
 		info->Bisdn[chan] = &info->Bc;
 
 		/* Multiplexor map - isdn (B1/2) to Bc */
-		info->regs->cr = AMR_MUX_MCR2 + chan;
-		info->regs->dr = (AM_MUX_CHANNEL_B1 + chan) |
-				 (AM_MUX_CHANNEL_Bc << 4);
-
+		sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR);
+		sbus_writeb((AM_MUX_CHANNEL_B1 + chan) |
+			    (AM_MUX_CHANNEL_Bc << 4),
+			    info->regs + DR);
 	} else {
 		restore_flags(flags);
 		return (-1);
 	}
 
 	/* Enable B channel transmit */
-	info->regs->cr = AMR_LIU_LMR1;
-	info->regs->dr |= AM_LIU_LMR1_B1_ENABL + chan;
+	sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
+	tmp = sbus_readb(info->regs + DR);
+	tmp |= AM_LIU_LMR1_B1_ENBL + chan;
+	sbus_writeb(tmp, info->regs + DR);
 
 	/* Enable B channel interrupts */
-	info->regs->cr = AMR_MUX_MCR4;
-	info->regs->dr = AM_MUX_MCR4_ENABLE_INTS | AM_MUX_MCR4_REVERSE_Bb | AM_MUX_MCR4_REVERSE_Bc;
+	sbus_writeb(AMR_MUX_MCR4, info->regs + CR);
+	sbus_writeb(AM_MUX_MCR4_ENABLE_INTS |
+		    AM_MUX_MCR4_REVERSE_Bb |
+		    AM_MUX_MCR4_REVERSE_Bc,
+		    info->regs + DR);
 
 	restore_flags(flags);
 	return 0;
@@ -1402,32 +1392,36 @@
 static void amd7930_bclose(int dev, unsigned int chan)
 {
 	struct amd7930_info *info;
-	register unsigned long flags;
+	unsigned long flags;
 
-	if (dev > num_drivers || chan<0 || chan>1) {
+	if (dev > num_drivers || chan<0 || chan>1)
 		return;
-	}
 
 	info = (struct amd7930_info *) drivers[dev].private;
 
 	save_and_cli(flags);
 
 	if (info->Bisdn[chan]) {
+		u8 tmp;
+
 		info->Bisdn[chan]->channel_status = CHANNEL_AVAILABLE;
-		info->regs->cr = AMR_MUX_MCR2 + chan;
-		info->regs->dr = 0;
+
+		sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR);
+		sbus_writeb(0, info->regs + DR);
+
 		info->Bisdn[chan] = NULL;
 
 		/* Disable B channel transmit */
-		info->regs->cr = AMR_LIU_LMR1;
-		info->regs->dr &= ~(AM_LIU_LMR1_B1_ENABL + chan);
+		sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
+		tmp = sbus_readb(info->regs + DR);
+		tmp &= ~(AM_LIU_LMR1_B1_ENABL + chan);
+		sbus_writeb(tmp, info->regs + DR);
 
 		if (info->Bb.channel_status == CHANNEL_AVAILABLE &&
 		    info->Bc.channel_status == CHANNEL_AVAILABLE) {
-
 			/* Disable B channel interrupts */
-			info->regs->cr = AMR_MUX_MCR4;
-			info->regs->dr = 0;
+			sbus_writeb(AMR_MUX_MCR4, info->regs + CR);
+			sbus_writeb(0, info->regs + DR);
 		}
 	}
 
@@ -1440,11 +1434,10 @@
 {
 	struct amd7930_info *info;
 	struct amd7930_channel *Bchan;
-	register unsigned long flags;
+	unsigned long flags;
 
-	if (dev > num_drivers) {
+	if (dev > num_drivers)
 		return;
-	}
 
 	info = (struct amd7930_info *) drivers[dev].private;
 	Bchan = info->Bisdn[chan];
@@ -1469,11 +1462,10 @@
 {
 	struct amd7930_info *info;
 	struct amd7930_channel *Bchan;
-	register unsigned long flags;
+	unsigned long flags;
 
-	if (dev > num_drivers) {
+	if (dev > num_drivers)
 		return;
-	}
 
 	info = (struct amd7930_info *) drivers[dev].private;
 	Bchan = info->Bisdn[chan];
@@ -1573,16 +1565,17 @@
 
 /* Attach to an amd7930 chip given its PROM node. */
 static int amd7930_attach(struct sparcaudio_driver *drv, int node,
-			  struct linux_sbus *sbus, struct linux_sbus_device *sdev)
+			  struct sbus_bus *sbus, struct sbus_dev *sdev)
 {
 	struct linux_prom_registers regs;
 	struct linux_prom_irqs irq;
+	struct resource res, *resp;
 	struct amd7930_info *info;
 	int err;
 
 	/* Allocate our private information structure. */
 	drv->private = kmalloc(sizeof(struct amd7930_info), GFP_KERNEL);
-	if (!drv->private)
+	if (drv->private == NULL)
 		return -ENOMEM;
 
 	/* Point at the information structure and initialize it. */
@@ -1595,13 +1588,18 @@
 
 	/* Map the registers into memory. */
 	prom_getproperty(node, "reg", (char *)&regs, sizeof(regs));
-	if (sbus && sdev)
-		prom_apply_sbus_ranges(sbus, &regs, 1, sdev);
+	if (sbus && sdev) {
+		resp = &sdev->resource[0];
+	} else {
+		resp = &res;
+		res.start = regs.phys_addr;
+		res.end = res.start + regs.reg_size - 1;
+		res.flags = IORESOURCE_IO | (regs.which_io & 0xff);
+	}
 	info->regs_size = regs.reg_size;
-	info->regs = sparc_alloc_io(regs.phys_addr, 0, regs.reg_size,
-					   "amd7930", regs.which_io, 0);
+	info->regs = sbus_ioremap(resp, 0, regs.reg_size, "amd7930");
 	if (!info->regs) {
-		printk(KERN_ERR "amd7930: could not allocate registers\n");
+		printk(KERN_ERR "amd7930: could not remap registers\n");
 		kfree(drv->private);
 		return -EIO;
 	}
@@ -1610,10 +1608,11 @@
 	amd7930_idle(info);
 
 	/* Enable extended FIFO operation on D-channel */
-	info->regs->cr = AMR_DLC_EFCR;
-	info->regs->dr = AMR_DLC_EFCR_EXTEND_FIFO;
-	info->regs->cr = AMR_DLC_DMR4;
-	info->regs->dr = /* AMR_DLC_DMR4_RCV_30 | */ AMR_DLC_DMR4_XMT_14;
+	sbus_writeb(AMR_DLC_EFCR, info->regs + CR);
+	sbus_writeb(AMR_DLC_EFCR_EXTEND_FIFO, info->regs + DR);
+	sbus_writeb(AMR_DLC_DMR4, info->regs + CR);
+	sbus_writeb(/* AMR_DLC_DMR4_RCV_30 | */ AMR_DLC_DMR4_XMT_14,
+		    info->regs + DR);
 
 	/* Attach the interrupt handler to the audio interrupt. */
 	prom_getproperty(node, "intr", (char *)&irq, sizeof(irq));
@@ -1625,8 +1624,8 @@
 
 	/* Initalize the local copy of the MAP registers. */
 	memset(&info->map, 0, sizeof(info->map));
-	info->map.mmr1 = AM_MAP_MMR1_GX | AM_MAP_MMR1_GER
-			 | AM_MAP_MMR1_GR | AM_MAP_MMR1_STG;
+	info->map.mmr1 = AM_MAP_MMR1_GX | AM_MAP_MMR1_GER |
+			 AM_MAP_MMR1_GR | AM_MAP_MMR1_STG;
         /* Start out with speaker, microphone */
         info->map.mmr2 |= (AM_MAP_MMR2_LS | AM_MAP_MMR2_AINB);
 
@@ -1647,14 +1646,14 @@
 		printk(KERN_ERR "amd7930: unable to register\n");
 		disable_irq(info->irq);
 		free_irq(info->irq, drv);
-		sparc_free_io(info->regs, info->regs_size);
+		sbus_iounmap(info->regs, info->regs_size);
 		kfree(drv->private);
 		return -EIO;
 	}
 
 	/* Announce the hardware to the user. */
-	printk(KERN_INFO "amd7930 at 0x%lx irq %d\n",
-		(unsigned long)info->regs, info->irq);
+	printk(KERN_INFO "amd7930 at %lx irq %d\n",
+	       info->regs, info->irq);
 
 	/* Success! */
 	return 0;
@@ -1670,7 +1669,7 @@
 	amd7930_idle(info);
 	disable_irq(info->irq);
 	free_irq(info->irq, drv);
-	sparc_free_io(info->regs, info->regs_size);
+	sbus_iounmap(info->regs, info->regs_size);
 	kfree(drv->private);
 }
 #endif
@@ -1682,8 +1681,8 @@
 int __init amd7930_init(void)
 #endif
 {
-	struct linux_sbus *bus;
-	struct linux_sbus_device *sdev;
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev;
 	int node;
 
 	/* Try to find the sun4c "audio" node first. */
@@ -1695,7 +1694,7 @@
 		num_drivers = 0;
 
 	/* Probe each SBUS for amd7930 chips. */
-	for_all_sbusdev(sdev,bus) {
+	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "audio")) {
 			/* Don't go over the max number of drivers. */
 			if (num_drivers >= MAX_DRIVERS)
@@ -1769,7 +1768,6 @@
 {
 	return ulaw[data];
 }
-
 
 static unsigned char linear[] = {
      0,    0,    0,    0,    0,    0,    0,    1,
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/amd7930.h linux/drivers/sbus/audio/amd7930.h
--- v2.3.34/linux/drivers/sbus/audio/amd7930.h	Wed Nov 18 09:06:05 1998
+++ linux/drivers/sbus/audio/amd7930.h	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/*
+/* $Id: amd7930.h,v 1.8 1999/09/21 14:37:10 davem Exp $
  * drivers/sbus/audio/amd7930.h
  *
  * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
@@ -17,22 +17,18 @@
 #include <linux/version.h>
 
 /* Register interface presented to the CPU by the amd7930. */
-struct amd7930
-{
-	__volatile__ __u8 cr;		/* Command Register (W) */
-#define ir cr				/* Interrupt Register (R) */
-	__volatile__ __u8 dr;		/* Data Register (R/W) */
-	__volatile__ __u8 dsr1;		/* D-channel Status Register 1 (R) */
-	__volatile__ __u8 der;		/* D-channel Error Register (R) */
-	__volatile__ __u8 dctb;		/* D-channel Transmit Buffer (W) */
-#define dcrb dctb			/* D-channel Receive Buffer (R) */
-	__volatile__ __u8 bbtb;		/* Bb-channel Transmit Buffer (W) */
-#define bbrb bbtb			/* Bb-channel Receive Buffer (R) */
-	__volatile__ __u8 bctb;		/* Bc-channel Transmit Buffer (W) */
-#define bcrb bctb			/* Bc-channel Receive Buffer (R) */
-	__volatile__ __u8 dsr2;		/* D-channel Status Register 2 (R) */
-};
-
+#define CR	0x00UL		/* Command Register (W) */
+#define IR	CR		/* Interrupt Register (R) */
+#define DR	0x01UL		/* Data Register (R/W) */
+#define DSR1	0x02UL		/* D-channel Status Register 1 (R) */
+#define DER	0x03UL		/* D-channel Error Register (R) */
+#define DCTB	0x04UL		/* D-channel Transmit Buffer (W) */
+#define DCRB	DCTB		/* D-channel Receive Buffer (R) */
+#define BBTB	0x05UL		/* Bb-channel Transmit Buffer (W) */
+#define BBRB	BBTB		/* Bb-channel Receive Buffer (R) */
+#define BCTB	0x06UL		/* Bc-channel Transmit Buffer (W) */
+#define BCRB	BCTB		/* Bc-channel Receive Buffer (R) */
+#define DSR2	0x07UL		/* D-channel Status Register 2 (R) */
 
 /* Indirect registers in the Main Audio Processor. */
 struct amd7930_map {
@@ -270,4 +266,5 @@
 
 /* Give this chip a "default" sample rate */
 #define AMD7930_RATE                    (8000)
-#endif
+
+#endif /* _AMD7930_H_ */
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c
--- v2.3.34/linux/drivers/sbus/audio/audio.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/sbus/audio/audio.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/*
+/* $Id: audio.c,v 1.47 1999/12/15 22:30:16 davem Exp $
  * drivers/sbus/audio/audio.c
  *
  * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
@@ -97,14 +97,13 @@
 
 	/* If we've used up SPARCAUDIO_MAX_DEVICES, fail */
 	for (dev = 0; dev < SPARCAUDIO_MAX_DEVICES; dev++) {
-	  if (drivers[dev] == NULL) {
-	    break;
-	  }
-	}
-	if (drivers[dev]) {
-	  return -EIO;
+                if (drivers[dev] == NULL)
+                        break;
 	}
 
+	if (drivers[dev])
+                return -EIO;
+
 	/* Ensure that the driver has a proper operations structure. */
 	if (!drv->ops || !drv->ops->start_output || !drv->ops->stop_output ||
 	    !drv->ops->start_input || !drv->ops->stop_input)
@@ -146,17 +145,18 @@
         drv->output_notify = kmalloc(drv->num_output_buffers * 
 				    sizeof(char), GFP_KERNEL);
         if (!drv->output_buffers || !drv->output_sizes || !drv->output_notify)
-	  goto kmalloc_failed1;
+                goto kmalloc_failed1;
 
 	drv->output_buffer = kmalloc((drv->output_buffer_size * 
-					       drv->num_output_buffers),
-					      (GFP_DMA | GFP_KERNEL));
-	if (!drv->output_buffer) goto kmalloc_failed2;
+                                      drv->num_output_buffers),
+                                     GFP_KERNEL);
+	if (!drv->output_buffer)
+                goto kmalloc_failed2;
 
         /* Allocate the pages for each output buffer. */
         for (i = 0; i < drv->num_output_buffers; i++) {
 	        drv->output_buffers[i] = (void *)(drv->output_buffer + 
-					  (i * drv->output_buffer_size));
+                                                  (i * drv->output_buffer_size));
 		drv->output_sizes[i] = 0;
 		drv->output_notify[i] = 0;
         }
@@ -174,31 +174,32 @@
         drv->input_buffers = kmalloc(drv->num_input_buffers * sizeof(__u8 *),
 				     GFP_KERNEL);
         drv->input_sizes = kmalloc(drv->num_input_buffers * 
-				    sizeof(size_t), GFP_KERNEL);
-        if (!drv->input_buffers || !drv->input_sizes) goto kmalloc_failed3;
+                                   sizeof(size_t), GFP_KERNEL);
+        if (!drv->input_buffers || !drv->input_sizes)
+                goto kmalloc_failed3;
 
         /* Allocate the pages for each input buffer. */
 	if (duplex == 1) {
-	  drv->input_buffer = kmalloc((drv->input_buffer_size * 
-						drv->num_input_buffers), 
-					       (GFP_DMA | GFP_KERNEL));
-	  if (!drv->input_buffer) goto kmalloc_failed4;
-
-	  for (i = 0; i < drv->num_input_buffers; i++) {
-	    drv->input_buffers[i] = (void *)(drv->input_buffer + 
-					      (i * drv->input_buffer_size));
-	  }
+                drv->input_buffer = kmalloc((drv->input_buffer_size * 
+                                             drv->num_input_buffers), 
+                                            GFP_DMA);
+                if (!drv->input_buffer)
+                        goto kmalloc_failed4;
+
+                for (i = 0; i < drv->num_input_buffers; i++)
+                        drv->input_buffers[i] = (void *)(drv->input_buffer + 
+                                                         (i * drv->input_buffer_size));
 	} else {
-	  if (duplex == 2) {
-	    drv->input_buffer = drv->output_buffer;
-	    drv->input_buffer_size = drv->output_buffer_size;
-	    drv->num_input_buffers = drv->num_output_buffers;
-	    for (i = 0; i < drv->num_input_buffers; i++) 
-	      drv->input_buffers[i] = drv->output_buffers[i];
-	  } else {
-	    for (i = 0; i < drv->num_input_buffers; i++) 
-	      drv->input_buffers[i] = NULL;
-	  }
+                if (duplex == 2) {
+                        drv->input_buffer = drv->output_buffer;
+                        drv->input_buffer_size = drv->output_buffer_size;
+                        drv->num_input_buffers = drv->num_output_buffers;
+                        for (i = 0; i < drv->num_input_buffers; i++) 
+                                drv->input_buffers[i] = drv->output_buffers[i];
+                } else {
+                        for (i = 0; i < drv->num_input_buffers; i++) 
+                                drv->input_buffers[i] = NULL;
+                }
 	}
 
 	/* Take note of our duplexity */
@@ -253,13 +254,13 @@
 
 	/* Deallocate the queue of input buffers. */
 	if (duplex == 1) {
-	  kfree(drv->input_buffer);
-	  kfree(drv->input_sizes);
+                kfree(drv->input_buffer);
+                kfree(drv->input_sizes);
 	}
 	kfree(drv->input_buffers);
 
 	if (&(drv->sd_siglist) != NULL)
-	  lis_free_elist( &(drv->sd_siglist) );
+                lis_free_elist( &(drv->sd_siglist) );
 
 	MOD_DEC_USE_COUNT;
 
@@ -271,123 +272,122 @@
 
 void sparcaudio_output_done(struct sparcaudio_driver * drv, int status)
 {
-  /* 
-   * If !status, just restart current output.
-   * If status & 1, a buffer is finished; make it available again.
-   * 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) 
-      drv->playing_count--;
-    else {
-      drv->output_count--;
-      drv->output_size -= drv->output_sizes[drv->output_front];
-      if (drv->output_notify[drv->output_front] == 1) {
-	drv->output_eof++;
-	drv->output_notify[drv->output_front] = 0;
-	kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
-      }
-      drv->output_front = (drv->output_front + 1) % 
-	drv->num_output_buffers;
-    }
-  }
+        /* If !status, just restart current output.
+         * If status & 1, a buffer is finished; make it available again.
+         * 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) {
+                        drv->playing_count--;
+                } else {
+                        drv->output_count--;
+                        drv->output_size -= drv->output_sizes[drv->output_front];
+                        if (drv->output_notify[drv->output_front] == 1) {
+                                drv->output_eof++;
+                                drv->output_notify[drv->output_front] = 0;
+                                kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
+                        }
+                        drv->output_front = (drv->output_front + 1) % 
+                                drv->num_output_buffers;
+                }
+        }
     
-  if (status & 2) {
-    drv->output_count--;
-    drv->playing_count++;
-    drv->output_size -= drv->output_sizes[drv->output_front];
-    if (drv->output_notify[drv->output_front] == 1) {
-      drv->output_eof++;
-      drv->output_notify[drv->output_front] = 0;
-      kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
-    }
-    drv->output_front = (drv->output_front + 1) % 
-      drv->num_output_buffers;
-  }
+        if (status & 2) {
+                drv->output_count--;
+                drv->playing_count++;
+                drv->output_size -= drv->output_sizes[drv->output_front];
+                if (drv->output_notify[drv->output_front] == 1) {
+                        drv->output_eof++;
+                        drv->output_notify[drv->output_front] = 0;
+                        kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
+                }
+                drv->output_front = (drv->output_front + 1) % 
+                        drv->num_output_buffers;
+        }
 
-  /* If we've played everything go inactive. */
-  if ((drv->output_count < 1) && (drv->playing_count < 1)) 
-    drv->output_active = 0;
-
-  /* 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)) {
-    wake_up_interruptible(&drv->output_write_wait);
-  }
+        /* If we've played everything go inactive. */
+        if ((drv->output_count < 1) && (drv->playing_count < 1)) 
+                drv->output_active = 0;
+
+        /* 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)) {
+                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); Should not be necessary  -- DJB 5/25/98 */
-    drv->output_active = 0;
+        /* 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); Should not be necessary  -- DJB 5/25/98 */
+                drv->output_active = 0;
 		  
-    /* Wake up any waiting writers or syncers and return. */
-    wake_up_interruptible(&drv->output_write_wait);
-    wake_up_interruptible(&drv->output_drain_wait);
-    return;
-  }
+                /* Wake up any waiting writers or syncers and return. */
+                wake_up_interruptible(&drv->output_write_wait);
+                wake_up_interruptible(&drv->output_drain_wait);
+                return;
+        }
 
-  /* Start next block of output if we have it */
-  if (drv->output_count > 0) {
-    drv->ops->start_output(drv, drv->output_buffers[drv->output_front],
-			   drv->output_sizes[drv->output_front]);
-    drv->output_active = 1;
-  } else 
-    drv->output_active = 0;
+        /* Start next block of output if we have it */
+        if (drv->output_count > 0) {
+                drv->ops->start_output(drv, drv->output_buffers[drv->output_front],
+                                       drv->output_sizes[drv->output_front]);
+                drv->output_active = 1;
+        } else {
+                drv->output_active = 0;
+        }
 }
 
 void sparcaudio_input_done(struct sparcaudio_driver * drv, int status)
 {
-  /* Deal with the weird case here */
-  if (drv->duplex == 2) {
-    if (drv->input_count < drv->num_input_buffers)
-      drv->input_count++;
-    drv->ops->start_input(drv, drv->input_buffers[drv->input_front],
-			  drv->input_buffer_size);
-    wake_up_interruptible(&drv->input_read_wait);
-    return;
-  } 
-
-  /* 
-   * If status % 2, they filled a buffer for us. 
-   * If status & 2, they took a buffer from us.
-   */
-
-  if ((status % 2) == 1) {
-    drv->input_count++;
-    drv->recording_count--;
-    drv->input_size+=drv->input_buffer_size;
-  }
+        /* Deal with the weird case here */
+        if (drv->duplex == 2) {
+                if (drv->input_count < drv->num_input_buffers)
+                        drv->input_count++;
+                drv->ops->start_input(drv, drv->input_buffers[drv->input_front],
+                                      drv->input_buffer_size);
+                wake_up_interruptible(&drv->input_read_wait);
+                return;
+        } 
 
-  if (status > 1) {
-    drv->recording_count++;
-    drv->input_front = (drv->input_front + 1) % drv->num_input_buffers;
-  }
-
-  dprintk(("f%d r%d c%d u%d\n", drv->input_front, drv->input_rear, drv->input_count, drv->recording_count));
-  /* If the input queue is full, shutdown the driver. */
-  if ((drv->input_count + drv->recording_count) == drv->num_input_buffers) {
-    kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
-
-    /* Stop the lowlevel driver from inputing. */
-    drv->ops->stop_input(drv);
-    drv->input_active = 0;
-  } else {
-    /* Otherwise, give the driver the next buffer. */
-    drv->ops->start_input(drv, drv->input_buffers[drv->input_front],
-			  drv->input_buffer_size);
-  }
+        /* If status % 2, they filled a buffer for us. 
+         * If status & 2, they took a buffer from us.
+         */
+        if ((status % 2) == 1) {
+                drv->input_count++;
+                drv->recording_count--;
+                drv->input_size+=drv->input_buffer_size;
+        }
 
-  /* Wake up any tasks that are waiting. */
-  wake_up_interruptible(&drv->input_read_wait);
-}
+        if (status > 1) {
+                drv->recording_count++;
+                drv->input_front = (drv->input_front + 1) % drv->num_input_buffers;
+        }
 
+        dprintk(("f%d r%d c%d u%d\n",
+                 drv->input_front, drv->input_rear,
+                 drv->input_count, drv->recording_count));
+
+        /* If the input queue is full, shutdown the driver. */
+        if ((drv->input_count + drv->recording_count) == drv->num_input_buffers) {
+                kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
+
+                /* Stop the lowlevel driver from inputing. */
+                drv->ops->stop_input(drv);
+                drv->input_active = 0;
+        } else {
+                /* Otherwise, give the driver the next buffer. */
+                drv->ops->start_input(drv, drv->input_buffers[drv->input_front],
+                                      drv->input_buffer_size);
+        }
 
+        /* Wake up any tasks that are waiting. */
+        wake_up_interruptible(&drv->input_read_wait);
+}
 
 /*
  *	VFS layer interface
@@ -397,49 +397,50 @@
 static int sparcaudio_select(struct inode * inode, struct file * file,
 			    int sel_type, select_table * wait)
 {
-  struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
-					   SPARCAUDIO_DEVICE_SHIFT)];
+        struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
+                                                 SPARCAUDIO_DEVICE_SHIFT)];
   
-  switch (sel_type) {
-  case SEL_IN:
-    if (((!file->f_flags & O_NONBLOCK) && drv->input_count) ||
-	(drv->input_size > drv->buffer_size)) {
-      dprintk(("read ready: c%d o%d\n", drv->input_count, drv->input_offset));
-      return 1;
-    }
-    select_wait(&drv->input_read_wait, wait);
-    break;
-  case SEL_OUT:
-    dprintk(("sel out: c%d o%d p%d\n", drv->output_count, drv->output_offset, drv->playing_count));
-    if ((drv->output_count + drv->playing_count) < (drv->num_output_buffers)) {
-      return 1;
-    }
-    select_wait(&drv->output_write_wait, wait);
-    break;
-  case SEL_EX:
-    break;
-  }
+        switch (sel_type) {
+        case SEL_IN:
+                if (((!file->f_flags & O_NONBLOCK) && drv->input_count) ||
+                    (drv->input_size > drv->buffer_size)) {
+                        dprintk(("read ready: c%d o%d\n",
+                                 drv->input_count, drv->input_offset));
+                        return 1;
+                }
+                select_wait(&drv->input_read_wait, wait);
+                break;
+        case SEL_OUT:
+                dprintk(("sel out: c%d o%d p%d\n",
+                         drv->output_count, drv->output_offset, drv->playing_count));
+                if ((drv->output_count + drv->playing_count) < (drv->num_output_buffers))
+                        return 1;
+                select_wait(&drv->output_write_wait, wait);
+                break;
+        case SEL_EX:
+                break;
+        };
 
-  return 0;
+        return 0;
 }
 #else
 static unsigned int sparcaudio_poll(struct file *file, poll_table * wait)
 {
-  unsigned int mask = 0;
-  struct inode *inode = file->f_dentry->d_inode;
-  struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
-                                           SPARCAUDIO_DEVICE_SHIFT)];
-
-  poll_wait(file, &drv->input_read_wait, wait);
-  poll_wait(file, &drv->output_write_wait, wait);
-  if (((!file->f_flags & O_NONBLOCK) && drv->input_count) ||
-      (drv->input_size > drv->buffer_size)) {
-    mask |= POLLIN | POLLRDNORM;
-  }
-  if ((drv->output_count + drv->playing_count) < (drv->num_output_buffers)) {
-    mask |= POLLOUT | POLLWRNORM;
-  }
-  return mask;
+        unsigned int mask = 0;
+        struct inode *inode = file->f_dentry->d_inode;
+        struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
+                                                 SPARCAUDIO_DEVICE_SHIFT)];
+
+        poll_wait(file, &drv->input_read_wait, wait);
+        poll_wait(file, &drv->output_write_wait, wait);
+        if (((!file->f_flags & O_NONBLOCK) && drv->input_count) ||
+            (drv->input_size > drv->buffer_size)) {
+                mask |= POLLIN | POLLRDNORM;
+        }
+        if ((drv->output_count + drv->playing_count) < (drv->num_output_buffers)) {
+                mask |= POLLOUT | POLLWRNORM;
+        }
+        return mask;
 }
 #endif
 
@@ -462,78 +463,77 @@
 #endif
 {
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
-  struct inode *inode = file->f_dentry->d_inode;
+        struct inode *inode = file->f_dentry->d_inode;
 #endif
-  struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
-					   SPARCAUDIO_DEVICE_SHIFT)];
-  int bytes_to_copy, bytes_read = 0, err;
+        struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
+                                                 SPARCAUDIO_DEVICE_SHIFT)];
+        int bytes_to_copy, bytes_read = 0, err;
 
-  if (! file->f_mode & FMODE_READ)
-    return -EINVAL;
+        if (! (file->f_mode & FMODE_READ))
+                return -EINVAL;
 
-  if ((file->f_flags & O_NONBLOCK) && (drv->input_size < count))
-    return -EAGAIN;
+        if ((file->f_flags & O_NONBLOCK) && (drv->input_size < count))
+                return -EAGAIN;
     
-  while (count > 0) {
-    if (drv->input_count == 0) {
-      /* This *should* never happen. */
-      if (file->f_flags & O_NONBLOCK) {
-	printk("Warning: audio input leak!\n");
-	return -EAGAIN;
-      }
-      interruptible_sleep_on(&drv->input_read_wait);
-      if (signal_pending(current))
-	return -EINTR;
-    }
+        while (count > 0) {
+                if (drv->input_count == 0) {
+                        /* This *should* never happen. */
+                        if (file->f_flags & O_NONBLOCK) {
+                                printk("Warning: audio input leak!\n");
+                                return -EAGAIN;
+                        }
+                        interruptible_sleep_on(&drv->input_read_wait);
+                        if (signal_pending(current))
+                                return -EINTR;
+                }
   
-    bytes_to_copy = drv->input_buffer_size - drv->input_offset;
-    
-    if (bytes_to_copy > count)
-      bytes_to_copy = count;
+                bytes_to_copy = drv->input_buffer_size - drv->input_offset;
+                if (bytes_to_copy > count)
+                        bytes_to_copy = count;
+
+                err = verify_area(VERIFY_WRITE, buf, bytes_to_copy);
+                if (err)
+                        return err;
+
+                copy_to_user(buf, drv->input_buffers[drv->input_rear]+drv->input_offset, 
+                             bytes_to_copy);
+
+                drv->input_offset += bytes_to_copy;
+                drv->input_size -= bytes_to_copy;
+                buf += bytes_to_copy;
+                count -= bytes_to_copy;
+                bytes_read += bytes_to_copy;
+
+                if (drv->input_offset >= drv->input_buffer_size) {
+                        drv->input_rear = (drv->input_rear + 1) % 
+                                drv->num_input_buffers;
+                        drv->input_count--;
+                        drv->input_offset = 0;
+                }
 
-    err = verify_area(VERIFY_WRITE, buf, bytes_to_copy);
-    if (err)
-      return err;
-
-    copy_to_user(buf, drv->input_buffers[drv->input_rear]+drv->input_offset, 
-                 bytes_to_copy);
-
-    drv->input_offset += bytes_to_copy;
-    drv->input_size -= bytes_to_copy;
-    buf += bytes_to_copy;
-    count -= bytes_to_copy;
-    bytes_read += bytes_to_copy;
-
-    if (drv->input_offset >= drv->input_buffer_size) {
-      drv->input_rear = (drv->input_rear + 1) % 
-	drv->num_input_buffers;
-      drv->input_count--;
-      drv->input_offset = 0;
-    }
-    /* If we're in "loop audio" mode, try waking up the other side
-     * in case they're waiting for us to eat a block. 
-     */
-    if (drv->duplex == 2) {
-      wake_up_interruptible(&drv->output_write_wait);
-    }
-  }
+                /* If we're in "loop audio" mode, try waking up the other side
+                 * in case they're waiting for us to eat a block. 
+                 */
+                if (drv->duplex == 2)
+                        wake_up_interruptible(&drv->output_write_wait);
+        }
 
-  return bytes_read;
+        return bytes_read;
 }
 
 static void sparcaudio_sync_output(struct sparcaudio_driver * drv)
 {
-  unsigned long flags;
+        unsigned long flags;
 
-  /* If the low-level driver is not active, activate it. */
-  save_and_cli(flags);
-  if ((!drv->output_active) && (drv->output_count > 0)) {
-    drv->ops->start_output(drv, 
-			   drv->output_buffers[drv->output_front],
-			   drv->output_sizes[drv->output_front]);
-    drv->output_active = 1;
-  }
-  restore_flags(flags);
+        /* If the low-level driver is not active, activate it. */
+        save_and_cli(flags);
+        if ((!drv->output_active) && (drv->output_count > 0)) {
+                drv->ops->start_output(drv, 
+                                       drv->output_buffers[drv->output_front],
+                                       drv->output_sizes[drv->output_front]);
+                drv->output_active = 1;
+        }
+        restore_flags(flags);
 }
 
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100
@@ -545,317 +545,319 @@
 #endif
 {
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
-  struct inode *inode = file->f_dentry->d_inode;
+        struct inode *inode = file->f_dentry->d_inode;
 #endif
-  struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
-					   SPARCAUDIO_DEVICE_SHIFT)];
-  int bytes_written = 0, bytes_to_copy, err;
+        struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
+                                                 SPARCAUDIO_DEVICE_SHIFT)];
+        int bytes_written = 0, bytes_to_copy, err;
   
-  if (! file->f_mode & FMODE_WRITE)
-    return -EINVAL;
+        if (! (file->f_mode & FMODE_WRITE))
+                return -EINVAL;
 
-  /* 
-   * A signal they want notification when this is processed. Too bad
-   * sys_write doesn't tell us unless you patch it, in 2.0 kernels.
-   */
-  if (count == 0) {
+        /* A signal they want notification when this is processed. Too bad
+         * sys_write doesn't tell us unless you patch it, in 2.0 kernels.
+         */
+        if (count == 0) {
 #ifndef notdef
-    drv->output_eof++;
-    kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
+                drv->output_eof++;
+                kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
 #else
-    /* Nice code, but the world isn't ready yet... */
-    drv->output_notify[drv->output_rear] = 1;
+                /* Nice code, but the world isn't ready yet... */
+                drv->output_notify[drv->output_rear] = 1;
 #endif
-  }
+        }
 
-  /* Loop until all output is written to device. */
-  while (count > 0) {
-    /* Check to make sure that an output buffer is available. */
-    if (drv->num_output_buffers == (drv->output_count + drv->playing_count)) {
-      /* We need buffers, so... */
-      sparcaudio_sync_output(drv);
-      if (file->f_flags & O_NONBLOCK) {
-	return -EAGAIN;
-      }
-      interruptible_sleep_on(&drv->output_write_wait);
-      if (signal_pending(current))
-	return bytes_written > 0 ? bytes_written : -EINTR;
-    }
-
-    /* No buffers were freed. Go back to sleep */
-    if (drv->num_output_buffers == (drv->output_count + drv->playing_count)) 
-      continue;
-
-    /* Deal with the weird case of a reader in the write area by trying to
-     * let them keep ahead of us... Go to sleep until they start servicing.
-     */
-    if ((drv->duplex == 2) && (drv->flags & SDF_OPEN_READ) &&
-	(drv->output_rear == drv->input_rear) && (drv->input_count > 0)) {
-      if (file->f_flags & O_NONBLOCK) {
-	return -EAGAIN;
-      }
-      interruptible_sleep_on(&drv->output_write_wait);
-      if (signal_pending(current))
-	return bytes_written > 0 ? bytes_written : -EINTR;
-    }
-
-    /* Determine how much we can copy in this iteration. */
-    bytes_to_copy = count;
-    if (bytes_to_copy > drv->output_buffer_size - drv->output_offset)
-      bytes_to_copy = drv->output_buffer_size - drv->output_offset;
+        /* Loop until all output is written to device. */
+        while (count > 0) {
+                /* Check to make sure that an output buffer is available. */
+                if (drv->num_output_buffers == (drv->output_count+drv->playing_count)) {
+                        /* We need buffers, so... */
+                        sparcaudio_sync_output(drv);
+                        if (file->f_flags & O_NONBLOCK)
+                                return -EAGAIN;
+
+                        interruptible_sleep_on(&drv->output_write_wait);
+                        if (signal_pending(current))
+                                return bytes_written > 0 ? bytes_written : -EINTR;
+                }
+
+                /* No buffers were freed. Go back to sleep */
+                if (drv->num_output_buffers == (drv->output_count+drv->playing_count)) 
+                        continue;
+
+                /* Deal with the weird case of a reader in the write area by trying to
+                 * let them keep ahead of us... Go to sleep until they start servicing.
+                 */
+                if ((drv->duplex == 2) && (drv->flags & SDF_OPEN_READ) &&
+                    (drv->output_rear == drv->input_rear) && (drv->input_count > 0)) {
+                        if (file->f_flags & O_NONBLOCK)
+                                return -EAGAIN;
+
+                        interruptible_sleep_on(&drv->output_write_wait);
+                        if (signal_pending(current))
+                                return bytes_written > 0 ? bytes_written : -EINTR;
+                }
+
+                /* Determine how much we can copy in this iteration. */
+                bytes_to_copy = count;
+                if (bytes_to_copy > drv->output_buffer_size - drv->output_offset)
+                        bytes_to_copy = drv->output_buffer_size - drv->output_offset;
     
-    err = verify_area(VERIFY_READ, buf, bytes_to_copy);
-    if (err)
-      return err;
+                err = verify_area(VERIFY_READ, buf, bytes_to_copy);
+                if (err)
+                        return err;
 
-    copy_from_user(drv->output_buffers[drv->output_rear]+drv->output_offset, buf, bytes_to_copy);
+                copy_from_user(drv->output_buffers[drv->output_rear]+drv->output_offset,
+                               buf, bytes_to_copy);
     
-    /* Update the queue pointers. */
-    buf += bytes_to_copy;
-    count -= bytes_to_copy;
-    bytes_written += bytes_to_copy;
-
-    /* A block can get orphaned in a flush and not cleaned up. */
-    if (drv->output_offset)
-      drv->output_sizes[drv->output_rear] += bytes_to_copy;
-    else
-      drv->output_sizes[drv->output_rear] = bytes_to_copy;
-
-    drv->output_notify[drv->output_rear] = 0;
-
-    if (drv->output_sizes[drv->output_rear] == drv->output_buffer_size) {
-      drv->output_rear = (drv->output_rear + 1) 
-	% drv->num_output_buffers;
-      drv->output_count++;
-      drv->output_offset = 0;
-    } else
-      drv->output_offset += bytes_to_copy;
+                /* Update the queue pointers. */
+                buf += bytes_to_copy;
+                count -= bytes_to_copy;
+                bytes_written += bytes_to_copy;
+
+                /* A block can get orphaned in a flush and not cleaned up. */
+                if (drv->output_offset)
+                        drv->output_sizes[drv->output_rear] += bytes_to_copy;
+                else
+                        drv->output_sizes[drv->output_rear] = bytes_to_copy;
+
+                drv->output_notify[drv->output_rear] = 0;
+
+                if (drv->output_sizes[drv->output_rear] == drv->output_buffer_size) {
+                        drv->output_rear = (drv->output_rear + 1) 
+                                % drv->num_output_buffers;
+                        drv->output_count++;
+                        drv->output_offset = 0;
+                } else {
+                        drv->output_offset += bytes_to_copy;
+                }
 
-    drv->output_size+=bytes_to_copy;
-  }
+                drv->output_size += bytes_to_copy;
+        }
 
-  sparcaudio_sync_output(drv);
+        sparcaudio_sync_output(drv);
   
-  /* Return the number of bytes written to the caller. */
-  return bytes_written;
+        /* Return the number of bytes written to the caller. */
+        return bytes_written;
 }
 
 /* Add these in as new devices are supported. Belongs in audioio.h, actually */
 #define MONO_DEVICES (SOUND_MASK_SPEAKER | SOUND_MASK_MIC)
 
 static int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file,
-			    unsigned int cmd, unsigned int *arg)
+                                  unsigned int cmd, unsigned int *arg)
 {
-  struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
-					   SPARCAUDIO_DEVICE_SHIFT)];
-  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;
-          mixer_info info;
-          int retval = -EINVAL;
-
-          if(drv->ops->sunaudio_getdev) {
-                  drv->ops->sunaudio_getdev(drv, &tmp);
-                  memset(&info, 0, sizeof(info));
-                  strncpy(info.id, tmp.name, sizeof(info.id));
-                  strncpy(info.name, "Sparc Audio", sizeof(info.name));
-                  info.modify_counter = drv->mixer_modify_counter;
-
-                  if(copy_to_user((char *)arg, &info, sizeof(info)))
-                          retval = -EFAULT;
-                  else
-                          retval = 0;
-          }
-          return retval;
+        struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
+                                                 SPARCAUDIO_DEVICE_SHIFT)];
+        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;
+                mixer_info info;
+                int retval = -EINVAL;
+
+                if(drv->ops->sunaudio_getdev) {
+                        drv->ops->sunaudio_getdev(drv, &tmp);
+                        memset(&info, 0, sizeof(info));
+                        strncpy(info.id, tmp.name, sizeof(info.id));
+                        strncpy(info.name, "Sparc Audio", sizeof(info.name));
+                        info.modify_counter = drv->mixer_modify_counter;
+
+                        if(copy_to_user((char *)arg, &info, sizeof(info)))
+                                retval = -EFAULT;
+                        else
+                                retval = 0;
+                }
+                return retval;
   }
 
-  switch (cmd) {
-  case SOUND_MIXER_WRITE_RECLEV:
-    if(COPY_IN(arg, k))
-      return -EFAULT;
-  iretry:
-    oprintk(("setting input volume (0x%x)", k));
-    if (drv->ops->get_input_channels)
-      j = drv->ops->get_input_channels(drv);
-    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_VOLUME:
-    if(COPY_IN(arg, k))
-	return -EFAULT;
-    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 (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_CD) j = SOUND_MASK_CD;
-    if (i & AUDIO_LINE_IN) j = SOUND_MASK_LINE;
-    if (i & AUDIO_MICROPHONE) j = SOUND_MASK_MIC;
+        switch (cmd) {
+        case SOUND_MIXER_WRITE_RECLEV:
+                if(COPY_IN(arg, k))
+                        return -EFAULT;
+        iretry:
+                oprintk(("setting input volume (0x%x)", k));
+                if (drv->ops->get_input_channels)
+                        j = drv->ops->get_input_channels(drv);
+                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_VOLUME:
+                if(COPY_IN(arg, k))
+                        return -EFAULT;
+                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 (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_CD) j = SOUND_MASK_CD;
+                if (i & AUDIO_LINE_IN) j = SOUND_MASK_LINE;
+                if (i & AUDIO_MICROPHONE) j = SOUND_MASK_MIC;
     
-    return COPY_OUT(arg, j);
+                return COPY_OUT(arg, j);
   case SOUND_MIXER_WRITE_RECSRC: 
-    if (!drv->ops->set_input_port)
-      return -EINVAL;
-    if(COPY_IN(arg, k))
-      return -EFAULT;
-    /* only one should ever be selected */
-    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;
-    oprintk(("setting inport to %d\n", j));
-    i = drv->ops->set_input_port(drv, j);
+          if (!drv->ops->set_input_port)
+                  return -EINVAL;
+          if(COPY_IN(arg, k))
+                  return -EFAULT;
+
+          /* only one should ever be selected */
+          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;
+          oprintk(("setting inport to %d\n", j));
+          i = drv->ops->set_input_port(drv, j);
     
-    return COPY_OUT(arg, i);
-  case SOUND_MIXER_READ_RECMASK: 
-    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;
+          return COPY_OUT(arg, i);
+        case SOUND_MIXER_READ_RECMASK: 
+                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;
     
-    return COPY_OUT(arg, j);
-  case SOUND_MIXER_READ_CAPS: /* mixer capabilities */
-    i = SOUND_CAP_EXCL_INPUT;
-    return COPY_OUT(arg, i);
-
-  case SOUND_MIXER_READ_DEVMASK: /* all supported devices */
-    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;
+                return COPY_OUT(arg, j);
+        case SOUND_MIXER_READ_CAPS: /* mixer capabilities */
+                i = SOUND_CAP_EXCL_INPUT;
+                return COPY_OUT(arg, i);
+
+        case SOUND_MIXER_READ_DEVMASK: /* all supported devices */
+                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 (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_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);
-  default:
-    return -EINVAL;
-  }
+                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_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);
+        default:
+                return -EINVAL;
+        };
 }
 
 /* AUDIO_SETINFO uses these to set values if possible. */
@@ -865,12 +867,12 @@
 		       int (*get_function)(struct sparcaudio_driver *), 
 		       unsigned int value)
 {
-  if (set_function && Modify(value))
-    return (int)set_function(drv, value);
-  else if (get_function)
-    return (int)get_function(drv);
-  else 
-    return 0;
+        if (set_function && Modify(value))
+                return (int) set_function(drv, value);
+        else if (get_function)
+                return (int) get_function(drv);
+        else 
+                return 0;
 }
 
 static __inline__ int 
@@ -879,12 +881,12 @@
 			int (*get_function)(struct sparcaudio_driver *), 
 			unsigned char value)
 {
-  if (set_function && Modifyc(value))
-    return (char)set_function(drv, (int)value);
-  else if (get_function)
-    return (char)get_function(drv);
-  else 
-    return 0;
+        if (set_function && Modifyc(value))
+                return (char) set_function(drv, (int)value);
+        else if (get_function)
+                return (char) get_function(drv);
+        else 
+                return 0;
 }
 
 /* I_FLUSH, I_{G,S}ETSIG, I_NREAD provided for SunOS compatibility
@@ -892,7 +894,6 @@
  * I must admit I'm quite ashamed of the state of the ioctl handling,
  * but I do have several optimizations which I'm planning. -- DJB
  */
-
 static int sparcaudio_ioctl(struct inode * inode, struct file * file,
 			    unsigned int cmd, unsigned long arg)
 {
@@ -902,1043 +903,1081 @@
 	audio_buf_info binfo;
 	count_info cinfo;
 	struct sparcaudio_driver *drv = 
-	  drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)];
+                drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)];
 
 	switch (minor & 0xf) {
 	case SPARCAUDIO_MIXER_MINOR:
-	  return sparcaudio_mixer_ioctl(inode, file, cmd, (unsigned int *)arg);
+                return sparcaudio_mixer_ioctl(inode, file, cmd, (unsigned int *)arg);
 	case SPARCAUDIO_DSP16_MINOR:
         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:
-	    j = (int)lis_get_elist_ent(drv->sd_siglist,current->pid);
-	    COPY_OUT(arg, j);
-	    retval = drv->input_count;
-	    break;
-
-	  case I_SETSIG:
-	  case I_SETSIG_SOLARIS:
-	    if ((minor & 0xf) == SPARCAUDIO_AUDIOCTL_MINOR) {
-	      if (!arg){
-		if (lis_del_from_elist(&(drv->sd_siglist),current->pid,S_ALL))
-		  retval = -EINVAL;
-		else 
-		  if (!drv->sd_siglist)
-		    drv->sd_sigflags=0;
-	      }
-	      else 
-		if (lis_add_to_elist(&(drv->sd_siglist),current->pid,
-				     (short)arg))
-		  retval = -EAGAIN;
-		else
-		  ((drv->sd_sigflags) |= (arg));
-	    }
-	    break;
-	  case I_NREAD:
-	  case I_NREAD_SOLARIS:
-	    /* According to the Solaris man page, this copies out
-	     * the size of the first streams buffer and returns 
-             * the number of streams messages on the read queue as
-	     * as its retval. (streamio(7I)) This should work. */
-             
-	    j = (drv->input_count > 0) ? drv->input_buffer_size : 0;
-	    COPY_OUT(arg, j);
-	    retval = drv->input_count;
-	    break;
-	    /*
-	     * A poor substitute until we do true resizable buffers.
-	     */
-	  case SNDCTL_DSP_GETISPACE:
-	    binfo.fragstotal = drv->num_input_buffers;
-	    binfo.fragments = drv->num_input_buffers - 
-	      (drv->input_count + drv->recording_count);
-	    binfo.fragsize = drv->input_buffer_size;
-	    binfo.bytes = binfo.fragments*binfo.fragsize;
+                /* 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:
+                        j = (int) lis_get_elist_ent(drv->sd_siglist,current->pid);
+                        COPY_OUT(arg, j);
+                        retval = drv->input_count;
+                        break;
+
+                case I_SETSIG:
+                case I_SETSIG_SOLARIS:
+                        if ((minor & 0xf) == SPARCAUDIO_AUDIOCTL_MINOR) {
+                                if (!arg) {
+                                        if (lis_del_from_elist(&(drv->sd_siglist),
+                                                               current->pid,S_ALL)) {
+                                                retval = -EINVAL;
+                                        } else if (!drv->sd_siglist) {
+                                                drv->sd_sigflags=0;
+                                        }
+                                } else if (lis_add_to_elist(&(drv->sd_siglist),
+                                                            current->pid,
+                                                            (short)arg)) {
+                                        retval = -EAGAIN;
+                                } else {
+                                        ((drv->sd_sigflags) |= (arg));
+                                }
+                        }
+                        break;
+                case I_NREAD:
+                case I_NREAD_SOLARIS:
+                        /* According to the Solaris man page, this copies out
+                         * the size of the first streams buffer and returns 
+                         * the number of streams messages on the read queue as
+                         * as its retval. (streamio(7I)) This should work.
+                         */
+                        j = (drv->input_count > 0) ? drv->input_buffer_size : 0;
+                        COPY_OUT(arg, j);
+                        retval = drv->input_count;
+                        break;
+
+                        /* A poor substitute until we do true resizable buffers. */
+                case SNDCTL_DSP_GETISPACE:
+                        binfo.fragstotal = drv->num_input_buffers;
+                        binfo.fragments = drv->num_input_buffers - 
+                                (drv->input_count + drv->recording_count);
+                        binfo.fragsize = drv->input_buffer_size;
+                        binfo.bytes = binfo.fragments*binfo.fragsize;
 	    
-	    retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(binfo));
-	    if (retval) break; 
-	    copy_to_user(&((char *)arg)[0], (char *)&binfo, sizeof(binfo));
-	    break;
-	  case SNDCTL_DSP_GETOSPACE:
-	    binfo.fragstotal = drv->num_output_buffers;
-	    binfo.fragments = drv->num_output_buffers - 
-	      (drv->output_count + drv->playing_count + 
-	       (drv->output_offset ? 1 : 0));
-	    binfo.fragsize = drv->output_buffer_size;
-	    binfo.bytes = binfo.fragments*binfo.fragsize + 
-	      (drv->output_buffer_size - drv->output_offset);
+                        retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(binfo));
+                        if (retval)
+                                break;
+                        copy_to_user(&((char *)arg)[0], (char *)&binfo, sizeof(binfo));
+                        break;
+                case SNDCTL_DSP_GETOSPACE:
+                        binfo.fragstotal = drv->num_output_buffers;
+                        binfo.fragments = drv->num_output_buffers - 
+                                (drv->output_count + drv->playing_count + 
+                                 (drv->output_offset ? 1 : 0));
+                        binfo.fragsize = drv->output_buffer_size;
+                        binfo.bytes = binfo.fragments*binfo.fragsize + 
+                                (drv->output_buffer_size - drv->output_offset);
 	    
-	    retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(binfo));
-	    if (retval) break; 
-	    copy_to_user(&((char *)arg)[0], (char *)&binfo, sizeof(binfo));
-	    break;
-	  case SNDCTL_DSP_GETIPTR:
-	  case SNDCTL_DSP_GETOPTR:
-	    /*
-	     * int bytes (number of bytes read/written since last)
-             * int blocks (number of frags read/wrote since last call)
-             * int ptr (current position of dma in buffer)
-	     */
-	    retval = 0;
-	    cinfo.bytes = 0;
-	    cinfo.ptr = 0;
-	    cinfo.blocks = 0;
-	    cinfo.bytes += cinfo.ptr;
+                        retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(binfo));
+                        if (retval)
+                                break;
+                        copy_to_user(&((char *)arg)[0], (char *)&binfo, sizeof(binfo));
+                        break;
+                case SNDCTL_DSP_GETIPTR:
+                case SNDCTL_DSP_GETOPTR:
+                        /* int bytes (number of bytes read/written since last)
+                         * int blocks (number of frags read/wrote since last call)
+                         * int ptr (current position of dma in buffer)
+                         */
+                        retval = 0;
+                        cinfo.bytes = 0;
+                        cinfo.ptr = 0;
+                        cinfo.blocks = 0;
+                        cinfo.bytes += cinfo.ptr;
 	    
-	    retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(cinfo));
-	    if (retval) break; 
-	    copy_to_user(&((char *)arg)[0], (char *)&cinfo, sizeof(cinfo));
-	    break;
-	  case SNDCTL_DSP_SETFRAGMENT:
-            /* XXX Small hack to get ESD/Enlightenment to work.  --DaveM */
-            retval = 0;
-            break;
-
-	  case SNDCTL_DSP_SUBDIVIDE:
-	    /*
-	     * I don't understand what I need to do yet.
-	     */
-	    retval = -EINVAL;
-	    break;
-	  case SNDCTL_DSP_SETTRIGGER:
-	    /* This may not be 100% correct */
-	    if ((arg & PCM_ENABLE_INPUT) && drv->ops->get_input_pause &&
-		drv->ops->set_input_pause) {
-	      if (drv->ops->get_input_pause(drv))
-		drv->ops->set_input_pause(drv, 0);
-	    } else {
-	      if (!drv->ops->get_input_pause(drv))
-		drv->ops->set_input_pause(drv, 1);
-	    }
-	    if ((arg & PCM_ENABLE_OUTPUT) && drv->ops->get_output_pause &&
-		drv->ops->set_output_pause) {
-	      if (drv->ops->get_output_pause(drv))
-		drv->ops->set_output_pause(drv, 0);
-	    } else {
-	      if (!drv->ops->get_output_pause(drv))
-		drv->ops->set_output_pause(drv, 1);
-	    }
-	    break;
-	  case SNDCTL_DSP_GETTRIGGER:
-            j = 0;
-	    if (drv->ops->get_input_pause)
-	      if (drv->ops->get_input_pause(drv))
-		j = PCM_ENABLE_INPUT;
-	    if (drv->ops->get_output_pause)
-	      if (drv->ops->get_output_pause(drv))
-		j |= PCM_ENABLE_OUTPUT;
-	    COPY_OUT(arg, j);
-	    break;
-	  case SNDCTL_DSP_GETBLKSIZE:
-	    j = drv->input_buffer_size;
-	    COPY_OUT(arg, j);
-	    break;
-	  case SNDCTL_DSP_SPEED:
-	    if ((!drv->ops->set_output_rate) && 
-		(!drv->ops->set_input_rate)) {
-	      retval = -EINVAL;
-	      break;
-	    }
-	    COPY_IN(arg, i);
-	    tprintk(("setting speed to %d\n", i));
-	    drv->ops->set_input_rate(drv, i);
-	    drv->ops->set_output_rate(drv, i);
-	    j = drv->ops->get_output_rate(drv);
-	    COPY_OUT(arg, j);
-	    break;
-	  case SNDCTL_DSP_GETCAPS:
-	    /* 
-	     * All Sparc audio hardware is full duplex.
-	     * 4231 supports DMA pointer reading, 7930 is byte at a time.
-             * Pause functionality emulates trigger
-             */
-	    j = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER | DSP_CAP_REALTIME;
-	    COPY_OUT(arg, j);
-	    break;
-	  case SNDCTL_DSP_GETFMTS:
-	    if (drv->ops->get_formats) {
-	      j = drv->ops->get_formats(drv);
-	      COPY_OUT(arg, j);
-	    } else
-	      retval = -EINVAL;
-	    break;
-	  case SNDCTL_DSP_SETFMT:
-	    /* need to decode into encoding, precision */
-	    COPY_IN(arg, i);
+                        retval = verify_area(VERIFY_WRITE, (int *)arg, sizeof(cinfo));
+                        if (retval)
+                                break;
+                        copy_to_user(&((char *)arg)[0], (char *)&cinfo, sizeof(cinfo));
+                        break;
+                case SNDCTL_DSP_SETFRAGMENT:
+                        /* XXX Small hack to get ESD/Enlightenment to work.  --DaveM */
+                        retval = 0;
+                        break;
+
+                case SNDCTL_DSP_SUBDIVIDE:
+                        /* I don't understand what I need to do yet. */
+                        retval = -EINVAL;
+                        break;
+                case SNDCTL_DSP_SETTRIGGER:
+                        /* This may not be 100% correct */
+                        if ((arg & PCM_ENABLE_INPUT) && drv->ops->get_input_pause &&
+                            drv->ops->set_input_pause) {
+                                if (drv->ops->get_input_pause(drv))
+                                        drv->ops->set_input_pause(drv, 0);
+                        } else {
+                                if (!drv->ops->get_input_pause(drv))
+                                        drv->ops->set_input_pause(drv, 1);
+                        }
+                        if ((arg & PCM_ENABLE_OUTPUT) && drv->ops->get_output_pause &&
+                            drv->ops->set_output_pause) {
+                                if (drv->ops->get_output_pause(drv))
+                                        drv->ops->set_output_pause(drv, 0);
+                        } else {
+                                if (!drv->ops->get_output_pause(drv))
+                                        drv->ops->set_output_pause(drv, 1);
+                        }
+                        break;
+                case SNDCTL_DSP_GETTRIGGER:
+                        j = 0;
+                        if (drv->ops->get_input_pause) {
+                                if (drv->ops->get_input_pause(drv))
+                                        j = PCM_ENABLE_INPUT;
+                        }
+                        if (drv->ops->get_output_pause) {
+                                if (drv->ops->get_output_pause(drv))
+                                        j |= PCM_ENABLE_OUTPUT;
+                        }
+                        COPY_OUT(arg, j);
+                        break;
+                case SNDCTL_DSP_GETBLKSIZE:
+                        j = drv->input_buffer_size;
+                        COPY_OUT(arg, j);
+                        break;
+                case SNDCTL_DSP_SPEED:
+                        if ((!drv->ops->set_output_rate) && 
+                            (!drv->ops->set_input_rate)) {
+                                retval = -EINVAL;
+                                break;
+                        }
+                        COPY_IN(arg, i);
+                        tprintk(("setting speed to %d\n", i));
+                        drv->ops->set_input_rate(drv, i);
+                        drv->ops->set_output_rate(drv, i);
+                        j = drv->ops->get_output_rate(drv);
+                        COPY_OUT(arg, j);
+                        break;
+                case SNDCTL_DSP_GETCAPS:
+                        /* All Sparc audio hardware is full duplex.
+                         * 4231 supports DMA pointer reading, 7930 is byte at a time.
+                         * Pause functionality emulates trigger
+                         */
+                        j = DSP_CAP_DUPLEX | DSP_CAP_TRIGGER | DSP_CAP_REALTIME;
+                        COPY_OUT(arg, j);
+                        break;
+                case SNDCTL_DSP_GETFMTS:
+                        if (drv->ops->get_formats) {
+                                j = drv->ops->get_formats(drv);
+                                COPY_OUT(arg, j);
+                        } else {
+                                retval = -EINVAL;
+                        }
+                        break;
+                case SNDCTL_DSP_SETFMT:
+                        /* need to decode into encoding, precision */
+                        COPY_IN(arg, i);
 	    
-	    /* handle special case here */
-	    if (i == AFMT_QUERY) {
-	      j = drv->ops->get_output_encoding(drv);
-	      k = drv->ops->get_output_precision(drv);
-	      if (j == AUDIO_ENCODING_DVI)
-                i = AFMT_IMA_ADPCM;
-	      else if (k == 8) {
-		switch (j) {
-		case AUDIO_ENCODING_ULAW:
-		  i = AFMT_MU_LAW;
-		  break;
-		case AUDIO_ENCODING_ALAW:
-		  i = AFMT_A_LAW;
-		  break;
-		case AUDIO_ENCODING_LINEAR8:
-		  i = AFMT_U8;
-		  break;
-		}
-	      } else if (k == 16) {
-		switch (j) {
-		case AUDIO_ENCODING_LINEAR:
-		  i = AFMT_S16_BE;
-		  break;
-		case AUDIO_ENCODING_LINEARLE:
-		  i = AFMT_S16_LE;
-		  break;
-                }
-	      } 
-	      COPY_OUT(arg, i);
-	      break;
-	    }
-
-            /* Without these there's no point in trying */
-            if (!drv->ops->set_input_precision ||
-                !drv->ops->set_input_encoding ||
-                !drv->ops->set_output_precision ||
-                !drv->ops->set_output_encoding) {
-	      eprintk(("missing set routines: failed\n"));
-	      retval = -EINVAL;
-	      break;
-            }
-
-	    if (drv->ops->get_formats)
-	      if (!(drv->ops->get_formats(drv) & i)) {
-		dprintk(("format not supported\n"));
-		return -EINVAL;
-	      }
-
-            switch (i) {
-            case AFMT_S16_LE:
-              ainfo.record.precision = ainfo.play.precision = 16;
-              ainfo.record.encoding = ainfo.play.encoding =
-		AUDIO_ENCODING_LINEARLE;
-              break;
-            case AFMT_S16_BE:
-              ainfo.record.precision = ainfo.play.precision = 16;
-              ainfo.record.encoding = ainfo.play.encoding =
-		AUDIO_ENCODING_LINEAR;
-              break;
-            case AFMT_MU_LAW:
-              ainfo.record.precision = ainfo.play.precision = 8;
-              ainfo.record.encoding = ainfo.play.encoding =
-		AUDIO_ENCODING_ULAW;
-              break;
-            case AFMT_A_LAW:
-              ainfo.record.precision = ainfo.play.precision = 8;
-              ainfo.record.encoding = ainfo.play.encoding =
-		AUDIO_ENCODING_ALAW;
-              break;
-            case AFMT_U8:
-              ainfo.record.precision = ainfo.play.precision = 8;
-              ainfo.record.encoding = ainfo.play.encoding =
-		AUDIO_ENCODING_LINEAR8;
-              break;
-            }
-	    tprintk(("setting fmt to enc %d pr %d\n", ainfo.play.encoding,
-		     ainfo.play.precision));
-            if ((drv->ops->set_input_precision(drv,
-						  ainfo.record.precision) 
-		 < 0) ||
-                (drv->ops->set_output_precision(drv,
-						   ainfo.play.precision)  
-		 < 0) ||
-                (drv->ops->set_input_encoding(drv,
-						 ainfo.record.encoding)
-		 < 0) ||
-                (drv->ops->set_output_encoding(drv,
-						  ainfo.play.encoding)
-		 < 0)) {
-	      dprintk(("setting format: failed\n"));
-	      return -EINVAL;
-            }
-	    COPY_OUT(arg, i);
-            break;
-	  case SNDCTL_DSP_CHANNELS:
-	    if ((!drv->ops->set_output_channels) && 
-		(!drv->ops->set_input_channels)) {
-	      retval = -EINVAL;
-	      break;
-	    }
-	    COPY_IN(arg, i);
-	    drv->ops->set_input_channels(drv, i);
-	    drv->ops->set_output_channels(drv, i);
-	    i = drv->ops->get_output_channels(drv);
-	    COPY_OUT(arg, i);
-	    break;
-	  case SNDCTL_DSP_STEREO:
-	    if ((!drv->ops->set_output_channels) && 
-		(!drv->ops->set_input_channels)) {
-	      retval = -EINVAL;
-	      break;
-	    }
-	    COPY_IN(arg, i);
-	    drv->ops->set_input_channels(drv, (i + 1));
-	    drv->ops->set_output_channels(drv, (i + 1));
-	    i = ((drv->ops->get_output_channels(drv)) - 1);
-	    COPY_OUT(arg, i);
-	    break;
-	  case SNDCTL_DSP_POST:
-	  case SNDCTL_DSP_SYNC:
-	  case AUDIO_DRAIN:
-	    /* Deal with weirdness so we can fill buffers */
-	    if (drv->output_offset) {
-	      drv->output_offset = 0;
-	      drv->output_rear = (drv->output_rear + 1)
-		% drv->num_output_buffers;
-	      drv->output_count++;
-	    }
-	    if (drv->output_count > 0) {
-	      sparcaudio_sync_output(drv);
-	      /* Only pause for DRAIN/SYNC, not POST */
-	      if (cmd != SNDCTL_DSP_POST) {
-		interruptible_sleep_on(&drv->output_drain_wait);
-		retval = (signal_pending(current)) ? -EINTR : 0;
-	      }
-	    }
-	    break;
-	  case I_FLUSH:
-	  case I_FLUSH_SOLARIS:
-	    if (((unsigned int)arg == FLUSHW) || 
-		((unsigned int)arg == FLUSHRW)) {
-	      if (file->f_mode & FMODE_WRITE) {
-		sparcaudio_sync_output(drv);
-		if (drv->output_active) {
-		  wake_up_interruptible(&drv->output_write_wait);
-		  drv->ops->stop_output(drv);
-		}
-		drv->output_offset = 0;
-		drv->output_active = 0;
-		drv->output_front = 0;
-		drv->output_rear = 0;
-		drv->output_count = 0;
-		drv->output_size = 0;
-		drv->playing_count = 0;
-		drv->output_eof = 0;
-	      }
-	    }
-	    if (((unsigned int)arg == FLUSHR) || 
-		((unsigned int)arg == FLUSHRW)) {
-	      if (drv->input_active && (file->f_mode & FMODE_READ)) {
-		wake_up_interruptible(&drv->input_read_wait);
-		drv->ops->stop_input(drv);
-		drv->input_active = 0;
-		drv->input_front = 0;
-		drv->input_rear = 0;
-		drv->input_count = 0;
-		drv->input_size = 0;
-		drv->input_offset = 0;
-		drv->recording_count = 0;
-	      }
-	      if ((file->f_mode & FMODE_READ) && 
-		  (drv->flags & SDF_OPEN_READ)) {
-		if (drv->duplex == 2)
-		  drv->input_count = drv->output_count;
-		drv->ops->start_input(drv, 
-					 drv->input_buffers[drv->input_front],
-					 drv->input_buffer_size);
-		drv->input_active = 1;
-	      }
-	    }
-	    if (((unsigned int)arg == FLUSHW) || 
-		((unsigned int)arg == FLUSHRW)) {
-	      if ((file->f_mode & FMODE_WRITE) && 
-		  !(drv->flags & SDF_OPEN_WRITE)) {
-		kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
-		sparcaudio_sync_output(drv);
-	      }
-	    }
-	    break;
-	  case SNDCTL_DSP_RESET:
-	  case AUDIO_FLUSH:
-	    if (drv->output_active && (file->f_mode & FMODE_WRITE)) {
-	      wake_up_interruptible(&drv->output_write_wait);
-	      drv->ops->stop_output(drv);
-	      drv->output_active = 0;
-	      drv->output_front = 0;
-	      drv->output_rear = 0;
-	      drv->output_count = 0;
-	      drv->output_size = 0;
-	      drv->playing_count = 0;
-	      drv->output_offset = 0;
-	      drv->output_eof = 0;
-	    }
-	    if (drv->input_active && (file->f_mode & FMODE_READ)) {
-	      wake_up_interruptible(&drv->input_read_wait);
-	      drv->ops->stop_input(drv);
-	      drv->input_active = 0;
-	      drv->input_front = 0;
-	      drv->input_rear = 0;
-	      drv->input_count = 0;
-	      drv->input_size = 0;
-	      drv->input_offset = 0;
-	      drv->recording_count = 0;
-	    }
-	    if ((file->f_mode & FMODE_READ) && 
-		!(drv->flags & SDF_OPEN_READ)) {
-	      drv->ops->start_input(drv, 
-				       drv->input_buffers[drv->input_front],
-				       drv->input_buffer_size);
-	      drv->input_active = 1;
-	    }
-	    if ((file->f_mode & FMODE_WRITE) && 
-		!(drv->flags & SDF_OPEN_WRITE)) {
-	      sparcaudio_sync_output(drv);
-	    }
-	    break;
-	  case AUDIO_GETDEV:
-	    if (drv->ops->sunaudio_getdev) {
-	      audio_device_t tmp;
+                        /* handle special case here */
+                        if (i == AFMT_QUERY) {
+                                j = drv->ops->get_output_encoding(drv);
+                                k = drv->ops->get_output_precision(drv);
+                                if (j == AUDIO_ENCODING_DVI) {
+                                        i = AFMT_IMA_ADPCM;
+                                } else if (k == 8) {
+                                        switch (j) {
+                                        case AUDIO_ENCODING_ULAW:
+                                                i = AFMT_MU_LAW;
+                                                break;
+                                        case AUDIO_ENCODING_ALAW:
+                                                i = AFMT_A_LAW;
+                                                break;
+                                        case AUDIO_ENCODING_LINEAR8:
+                                                i = AFMT_U8;
+                                                break;
+                                        };
+                                } else if (k == 16) {
+                                        switch (j) {
+                                        case AUDIO_ENCODING_LINEAR:
+                                                i = AFMT_S16_BE;
+                                                break;
+                                        case AUDIO_ENCODING_LINEARLE:
+                                                i = AFMT_S16_LE;
+                                                break;
+                                        };
+                                } 
+                                COPY_OUT(arg, i);
+                                break;
+                        }
+
+                        /* Without these there's no point in trying */
+                        if (!drv->ops->set_input_precision ||
+                            !drv->ops->set_input_encoding ||
+                            !drv->ops->set_output_precision ||
+                            !drv->ops->set_output_encoding) {
+                                eprintk(("missing set routines: failed\n"));
+                                retval = -EINVAL;
+                                break;
+                        }
+
+                        if (drv->ops->get_formats) {
+                                if (!(drv->ops->get_formats(drv) & i)) {
+                                        dprintk(("format not supported\n"));
+                                        return -EINVAL;
+                                }
+                        }
+                        switch (i) {
+                        case AFMT_S16_LE:
+                                ainfo.record.precision = ainfo.play.precision = 16;
+                                ainfo.record.encoding = ainfo.play.encoding =
+                                        AUDIO_ENCODING_LINEARLE;
+                                break;
+                        case AFMT_S16_BE:
+                                ainfo.record.precision = ainfo.play.precision = 16;
+                                ainfo.record.encoding = ainfo.play.encoding =
+                                        AUDIO_ENCODING_LINEAR;
+                                break;
+                        case AFMT_MU_LAW:
+                                ainfo.record.precision = ainfo.play.precision = 8;
+                                ainfo.record.encoding = ainfo.play.encoding =
+                                        AUDIO_ENCODING_ULAW;
+                                break;
+                        case AFMT_A_LAW:
+                                ainfo.record.precision = ainfo.play.precision = 8;
+                                ainfo.record.encoding = ainfo.play.encoding =
+                                        AUDIO_ENCODING_ALAW;
+                                break;
+                        case AFMT_U8:
+                                ainfo.record.precision = ainfo.play.precision = 8;
+                                ainfo.record.encoding = ainfo.play.encoding =
+                                        AUDIO_ENCODING_LINEAR8;
+                                break;
+                        };
+                        tprintk(("setting fmt to enc %d pr %d\n",
+                                 ainfo.play.encoding,
+                                 ainfo.play.precision));
+                        if ((drv->ops->set_input_precision(drv,
+                                                           ainfo.record.precision) 
+                             < 0) ||
+                            (drv->ops->set_output_precision(drv,
+                                                            ainfo.play.precision)  
+                             < 0) ||
+                            (drv->ops->set_input_encoding(drv,
+                                                          ainfo.record.encoding)
+                             < 0) ||
+                            (drv->ops->set_output_encoding(drv,
+                                                           ainfo.play.encoding)
+                             < 0)) {
+                                dprintk(("setting format: failed\n"));
+                                return -EINVAL;
+                        }
+                        COPY_OUT(arg, i);
+                        break;
+                case SNDCTL_DSP_CHANNELS:
+                        if ((!drv->ops->set_output_channels) && 
+                            (!drv->ops->set_input_channels)) {
+                                retval = -EINVAL;
+                                break;
+                        }
+                        COPY_IN(arg, i);
+                        drv->ops->set_input_channels(drv, i);
+                        drv->ops->set_output_channels(drv, i);
+                        i = drv->ops->get_output_channels(drv);
+                        COPY_OUT(arg, i);
+                        break;
+                case SNDCTL_DSP_STEREO:
+                        if ((!drv->ops->set_output_channels) && 
+                            (!drv->ops->set_input_channels)) {
+                                retval = -EINVAL;
+                                break;
+                        }
+                        COPY_IN(arg, i);
+                        drv->ops->set_input_channels(drv, (i + 1));
+                        drv->ops->set_output_channels(drv, (i + 1));
+                        i = ((drv->ops->get_output_channels(drv)) - 1);
+                        COPY_OUT(arg, i);
+                        break;
+                case SNDCTL_DSP_POST:
+                case SNDCTL_DSP_SYNC:
+                case AUDIO_DRAIN:
+                        /* Deal with weirdness so we can fill buffers */
+                        if (drv->output_offset) {
+                                drv->output_offset = 0;
+                                drv->output_rear = (drv->output_rear + 1)
+                                        % drv->num_output_buffers;
+                                drv->output_count++;
+                        }
+                        if (drv->output_count > 0) {
+                                sparcaudio_sync_output(drv);
+                                /* Only pause for DRAIN/SYNC, not POST */
+                                if (cmd != SNDCTL_DSP_POST) {
+                                        interruptible_sleep_on(&drv->output_drain_wait);
+                                        retval = (signal_pending(current)) ? -EINTR : 0;
+                                }
+                        }
+                        break;
+                case I_FLUSH:
+                case I_FLUSH_SOLARIS:
+                        if (((unsigned int)arg == FLUSHW) || 
+                            ((unsigned int)arg == FLUSHRW)) {
+                                if (file->f_mode & FMODE_WRITE) {
+                                        sparcaudio_sync_output(drv);
+                                        if (drv->output_active) {
+                                                wake_up_interruptible(&drv->output_write_wait);
+                                                drv->ops->stop_output(drv);
+                                        }
+                                        drv->output_offset = 0;
+                                        drv->output_active = 0;
+                                        drv->output_front = 0;
+                                        drv->output_rear = 0;
+                                        drv->output_count = 0;
+                                        drv->output_size = 0;
+                                        drv->playing_count = 0;
+                                        drv->output_eof = 0;
+                                }
+                        }
+                        if (((unsigned int)arg == FLUSHR) || 
+                            ((unsigned int)arg == FLUSHRW)) {
+                                if (drv->input_active && (file->f_mode & FMODE_READ)) {
+                                        wake_up_interruptible(&drv->input_read_wait);
+                                        drv->ops->stop_input(drv);
+                                        drv->input_active = 0;
+                                        drv->input_front = 0;
+                                        drv->input_rear = 0;
+                                        drv->input_count = 0;
+                                        drv->input_size = 0;
+                                        drv->input_offset = 0;
+                                        drv->recording_count = 0;
+                                }
+                                if ((file->f_mode & FMODE_READ) && 
+                                    (drv->flags & SDF_OPEN_READ)) {
+                                        if (drv->duplex == 2)
+                                                drv->input_count = drv->output_count;
+                                        drv->ops->start_input(drv, 
+                                                              drv->input_buffers[drv->input_front],
+                                                              drv->input_buffer_size);
+                                        drv->input_active = 1;
+                                }
+                        }
+                        if (((unsigned int)arg == FLUSHW) || 
+                            ((unsigned int)arg == FLUSHRW)) {
+                                if ((file->f_mode & FMODE_WRITE) && 
+                                    !(drv->flags & SDF_OPEN_WRITE)) {
+                                        kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
+                                        sparcaudio_sync_output(drv);
+                                }
+                        }
+                        break;
+                case SNDCTL_DSP_RESET:
+                case AUDIO_FLUSH:
+                        if (drv->output_active && (file->f_mode & FMODE_WRITE)) {
+                                wake_up_interruptible(&drv->output_write_wait);
+                                drv->ops->stop_output(drv);
+                                drv->output_active = 0;
+                                drv->output_front = 0;
+                                drv->output_rear = 0;
+                                drv->output_count = 0;
+                                drv->output_size = 0;
+                                drv->playing_count = 0;
+                                drv->output_offset = 0;
+                                drv->output_eof = 0;
+                        }
+                        if (drv->input_active && (file->f_mode & FMODE_READ)) {
+                                wake_up_interruptible(&drv->input_read_wait);
+                                drv->ops->stop_input(drv);
+                                drv->input_active = 0;
+                                drv->input_front = 0;
+                                drv->input_rear = 0;
+                                drv->input_count = 0;
+                                drv->input_size = 0;
+                                drv->input_offset = 0;
+                                drv->recording_count = 0;
+                        }
+                        if ((file->f_mode & FMODE_READ) && 
+                            !(drv->flags & SDF_OPEN_READ)) {
+                                drv->ops->start_input(drv, 
+                                                      drv->input_buffers[drv->input_front],
+                                                      drv->input_buffer_size);
+                                drv->input_active = 1;
+                        }
+                        if ((file->f_mode & FMODE_WRITE) && 
+                            !(drv->flags & SDF_OPEN_WRITE)) {
+                                sparcaudio_sync_output(drv);
+                        }
+                        break;
+                case AUDIO_GETDEV:
+                        if (drv->ops->sunaudio_getdev) {
+                                audio_device_t tmp;
 	      
-	      retval = verify_area(VERIFY_WRITE, (void *)arg, 
-				   sizeof(audio_device_t));
-	      if (!retval)
-		drv->ops->sunaudio_getdev(drv, &tmp);
-	      copy_to_user((audio_device_t *)arg, &tmp, sizeof(tmp));
-	    } else
-	      retval = -EINVAL;
-	    break;
-	  case AUDIO_GETDEV_SUNOS:
-	    if (drv->ops->sunaudio_getdev_sunos) {
-	      int tmp = drv->ops->sunaudio_getdev_sunos(drv);
-	      
-	      retval = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
-	      if (!retval)
-		copy_to_user((int *)arg, &tmp, sizeof(tmp));
-	    } else
-	      retval = -EINVAL;
-	    break;
-	  case AUDIO_GETINFO:
-	    AUDIO_INITINFO(&ainfo);
-
-	    if (drv->ops->get_input_rate)
-	      ainfo.record.sample_rate =
-		drv->ops->get_input_rate(drv);
-	    else
-	      ainfo.record.sample_rate = (8000);
-	    if (drv->ops->get_input_channels)
-	      ainfo.record.channels =
-		drv->ops->get_input_channels(drv);
-	    else
-	      ainfo.record.channels = (1);
-	    if (drv->ops->get_input_precision)
-	      ainfo.record.precision =
-		drv->ops->get_input_precision(drv);
-	    else
-	      ainfo.record.precision = (8);
-	    if (drv->ops->get_input_encoding)
-	      ainfo.record.encoding =
-		drv->ops->get_input_encoding(drv);
-	    else
-	      ainfo.record.encoding = (AUDIO_ENCODING_ULAW);
-	    if (drv->ops->get_input_volume)
-	      ainfo.record.gain =
-		drv->ops->get_input_volume(drv);
-	    else
-	      ainfo.record.gain = (0);
-	    if (drv->ops->get_input_port)
-	      ainfo.record.port =
-		drv->ops->get_input_port(drv);
-	    else
-	      ainfo.record.port = (0);
-	    if (drv->ops->get_input_ports)
-	      ainfo.record.avail_ports = 
-		drv->ops->get_input_ports(drv);
-	    else
-	      ainfo.record.avail_ports = (0);
-	    /* To make e.g. vat happy, we let them think they control this */
-	    ainfo.record.buffer_size = drv->buffer_size;
-	    if (drv->ops->get_input_samples)
-	      ainfo.record.samples = drv->ops->get_input_samples(drv);
-	    else
-	      ainfo.record.samples = 0;
-	    /* This is undefined in the record context in Solaris */
-	    ainfo.record.eof = 0;
-	    if (drv->ops->get_input_pause)
-	      ainfo.record.pause =
-		drv->ops->get_input_pause(drv);
-	    else
-	      ainfo.record.pause = 0;
-	    if (drv->ops->get_input_error)
-	      ainfo.record.error = 
-		(unsigned char)drv->ops->get_input_error(drv);
-	    else
-	      ainfo.record.error = 0;
-	    ainfo.record.waiting = 0;
-	    if (drv->ops->get_input_balance)
-	      ainfo.record.balance =
-		(unsigned char)drv->ops->get_input_balance(drv);
-	    else
-	      ainfo.record.balance = (unsigned char)(AUDIO_MID_BALANCE);
-	    ainfo.record.minordev = 4 + (minor << SPARCAUDIO_DEVICE_SHIFT);
-	    ainfo.record.open = (drv->flags & SDF_OPEN_READ);
-	    ainfo.record.active = 0;
-
-	    if (drv->ops->get_output_rate)
-	      ainfo.play.sample_rate =
-		drv->ops->get_output_rate(drv);
-	    else
-	      ainfo.play.sample_rate = (8000);
-	    if (drv->ops->get_output_channels)
-	      ainfo.play.channels =
-		drv->ops->get_output_channels(drv);
-	    else
-	      ainfo.play.channels = (1);
-	    if (drv->ops->get_output_precision)
-	      ainfo.play.precision =
-		drv->ops->get_output_precision(drv);
-	    else
-	      ainfo.play.precision = (8);
-	    if (drv->ops->get_output_encoding)
-	      ainfo.play.encoding =
-		drv->ops->get_output_encoding(drv);
-	    else
-	      ainfo.play.encoding = (AUDIO_ENCODING_ULAW);
-	    if (drv->ops->get_output_volume)
-	      ainfo.play.gain =
-		drv->ops->get_output_volume(drv);
-	    else
-	      ainfo.play.gain = (0);
-	    if (drv->ops->get_output_port)
-	      ainfo.play.port =
-		drv->ops->get_output_port(drv);
-	    else
-	      ainfo.play.port = (0);
-	    if (drv->ops->get_output_ports)
-	      ainfo.play.avail_ports = 
-		drv->ops->get_output_ports(drv);
-	    else
-	      ainfo.play.avail_ports = (0);
-	    /* This is not defined in the play context in Solaris */
-	    ainfo.play.buffer_size = 0;
-	    if (drv->ops->get_output_samples)
-	      ainfo.play.samples = drv->ops->get_output_samples(drv);
-	    else
-	      ainfo.play.samples = 0;
-	    ainfo.play.eof = drv->output_eof;
-	    if (drv->ops->get_output_pause)
-	      ainfo.play.pause =
-		drv->ops->get_output_pause(drv);
-	    else
-	      ainfo.play.pause = 0;
-	    if (drv->ops->get_output_error)
-	      ainfo.play.error =
-		(unsigned char)drv->ops->get_output_error(drv);
-	    else
-	      ainfo.play.error = 0;
-	    ainfo.play.waiting = waitqueue_active(&drv->open_wait);
-	    if (drv->ops->get_output_balance)
-	      ainfo.play.balance =
-		(unsigned char)drv->ops->get_output_balance(drv);
-	    else
-	      ainfo.play.balance = (unsigned char)(AUDIO_MID_BALANCE);
-	    ainfo.play.minordev = 4 + (minor << SPARCAUDIO_DEVICE_SHIFT);
-	    ainfo.play.open = (drv->flags & SDF_OPEN_WRITE);
-	    ainfo.play.active = drv->output_active;
-	    
-	    if (drv->ops->get_monitor_volume)
-	      ainfo.monitor_gain =
-		drv->ops->get_monitor_volume(drv);
-	    else
-	      ainfo.monitor_gain = (0);
-
-	    if (drv->ops->get_output_muted)
-	      ainfo.output_muted = 
-		(unsigned char)drv->ops->get_output_muted(drv);
-	    else
-	      ainfo.output_muted = (unsigned char)(0);
-
-	    retval = verify_area(VERIFY_WRITE, (void *)arg,
-				 sizeof(struct audio_info));
-	    if (retval < 0)
-	      break;
-
-	    copy_to_user((struct audio_info *)arg, &ainfo, sizeof(ainfo));
+                                retval = verify_area(VERIFY_WRITE, (void *)arg, 
+                                                     sizeof(audio_device_t));
+                                if (!retval)
+                                        drv->ops->sunaudio_getdev(drv, &tmp);
+                                copy_to_user((audio_device_t *)arg, &tmp, sizeof(tmp));
+                        } else {
+                                retval = -EINVAL;
+                        }
+                        break;
+                case AUDIO_GETDEV_SUNOS:
+                        if (drv->ops->sunaudio_getdev_sunos) {
+                                int tmp = drv->ops->sunaudio_getdev_sunos(drv);
+
+                                retval = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
+                                if (!retval)
+                                        copy_to_user((int *)arg, &tmp, sizeof(tmp));
+                        } else {
+                                retval = -EINVAL;
+                        }
+                        break;
+                case AUDIO_GETINFO:
+                        AUDIO_INITINFO(&ainfo);
+
+                        if (drv->ops->get_input_rate)
+                                ainfo.record.sample_rate =
+                                        drv->ops->get_input_rate(drv);
+                        else
+                                ainfo.record.sample_rate = (8000);
+                        if (drv->ops->get_input_channels)
+                                ainfo.record.channels =
+                                        drv->ops->get_input_channels(drv);
+                        else
+                                ainfo.record.channels = (1);
+                        if (drv->ops->get_input_precision)
+                                ainfo.record.precision =
+                                        drv->ops->get_input_precision(drv);
+                        else
+                                ainfo.record.precision = (8);
+                        if (drv->ops->get_input_encoding)
+                                ainfo.record.encoding =
+                                        drv->ops->get_input_encoding(drv);
+                        else
+                                ainfo.record.encoding = (AUDIO_ENCODING_ULAW);
+                        if (drv->ops->get_input_volume)
+                                ainfo.record.gain =
+                                        drv->ops->get_input_volume(drv);
+                        else
+                                ainfo.record.gain = (0);
+                        if (drv->ops->get_input_port)
+                                ainfo.record.port =
+                                        drv->ops->get_input_port(drv);
+                        else
+                                ainfo.record.port = (0);
+                        if (drv->ops->get_input_ports)
+                                ainfo.record.avail_ports = 
+                                        drv->ops->get_input_ports(drv);
+                        else
+                                ainfo.record.avail_ports = (0);
+
+                        /* To make e.g. vat happy, we let them think they control this */
+                        ainfo.record.buffer_size = drv->buffer_size;
+                        if (drv->ops->get_input_samples)
+                                ainfo.record.samples = drv->ops->get_input_samples(drv);
+                        else
+                                ainfo.record.samples = 0;
+
+                        /* This is undefined in the record context in Solaris */
+                        ainfo.record.eof = 0;
+                        if (drv->ops->get_input_pause)
+                                ainfo.record.pause =
+                                        drv->ops->get_input_pause(drv);
+                        else
+                                ainfo.record.pause = 0;
+                        if (drv->ops->get_input_error)
+                                ainfo.record.error = 
+                                        (unsigned char) drv->ops->get_input_error(drv);
+                        else
+                                ainfo.record.error = 0;
+                        ainfo.record.waiting = 0;
+                        if (drv->ops->get_input_balance)
+                                ainfo.record.balance =
+                                        (unsigned char) drv->ops->get_input_balance(drv);
+                        else
+                                ainfo.record.balance = (unsigned char)(AUDIO_MID_BALANCE);
+                        ainfo.record.minordev = 4 + (minor << SPARCAUDIO_DEVICE_SHIFT);
+                        ainfo.record.open = (drv->flags & SDF_OPEN_READ);
+                        ainfo.record.active = 0;
+
+                        if (drv->ops->get_output_rate)
+                                ainfo.play.sample_rate =
+                                        drv->ops->get_output_rate(drv);
+                        else
+                                ainfo.play.sample_rate = (8000);
+                        if (drv->ops->get_output_channels)
+                                ainfo.play.channels =
+                                        drv->ops->get_output_channels(drv);
+                        else
+                                ainfo.play.channels = (1);
+                        if (drv->ops->get_output_precision)
+                                ainfo.play.precision =
+                                        drv->ops->get_output_precision(drv);
+                        else
+                                ainfo.play.precision = (8);
+                        if (drv->ops->get_output_encoding)
+                                ainfo.play.encoding =
+                                        drv->ops->get_output_encoding(drv);
+                        else
+                                ainfo.play.encoding = (AUDIO_ENCODING_ULAW);
+                        if (drv->ops->get_output_volume)
+                                ainfo.play.gain =
+                                        drv->ops->get_output_volume(drv);
+                        else
+                                ainfo.play.gain = (0);
+                        if (drv->ops->get_output_port)
+                                ainfo.play.port =
+                                        drv->ops->get_output_port(drv);
+                        else
+                                ainfo.play.port = (0);
+                        if (drv->ops->get_output_ports)
+                                ainfo.play.avail_ports = 
+                                        drv->ops->get_output_ports(drv);
+                        else
+                                ainfo.play.avail_ports = (0);
+
+                        /* This is not defined in the play context in Solaris */
+                        ainfo.play.buffer_size = 0;
+                        if (drv->ops->get_output_samples)
+                                ainfo.play.samples = drv->ops->get_output_samples(drv);
+                        else
+                                ainfo.play.samples = 0;
+                        ainfo.play.eof = drv->output_eof;
+                        if (drv->ops->get_output_pause)
+                                ainfo.play.pause =
+                                        drv->ops->get_output_pause(drv);
+                        else
+                                ainfo.play.pause = 0;
+                        if (drv->ops->get_output_error)
+                                ainfo.play.error =
+                                        (unsigned char)drv->ops->get_output_error(drv);
+                        else
+                                ainfo.play.error = 0;
+                        ainfo.play.waiting = waitqueue_active(&drv->open_wait);
+                        if (drv->ops->get_output_balance)
+                                ainfo.play.balance =
+                                        (unsigned char)drv->ops->get_output_balance(drv);
+                        else
+                                ainfo.play.balance = (unsigned char)(AUDIO_MID_BALANCE);
+                        ainfo.play.minordev = 4 + (minor << SPARCAUDIO_DEVICE_SHIFT);
+                        ainfo.play.open = (drv->flags & SDF_OPEN_WRITE);
+                        ainfo.play.active = drv->output_active;
 	    
-	    break;
-	  case AUDIO_SETINFO:
-	    {
-	      audio_info_t curinfo, newinfo;
+                        if (drv->ops->get_monitor_volume)
+                                ainfo.monitor_gain =
+                                        drv->ops->get_monitor_volume(drv);
+                        else
+                                ainfo.monitor_gain = (0);
+
+                        if (drv->ops->get_output_muted)
+                                ainfo.output_muted = 
+                                        (unsigned char)drv->ops->get_output_muted(drv);
+                        else
+                                ainfo.output_muted = (unsigned char)(0);
+
+                        retval = verify_area(VERIFY_WRITE, (void *)arg,
+                                             sizeof(struct audio_info));
+                        if (retval < 0)
+                                break;
+
+                        copy_to_user((struct audio_info *)arg, &ainfo, sizeof(ainfo));
+                        break;
+                case AUDIO_SETINFO:
+                {
+                        audio_info_t curinfo, newinfo;
 	      
-	      if (verify_area(VERIFY_READ, (audio_info_t *)arg, 
-			      sizeof(audio_info_t))) {
-		dprintk(("verify_area failed\n"));
-		return -EINVAL;
-	      }
-	      copy_from_user(&ainfo, (audio_info_t *)arg, sizeof(audio_info_t));
-
-	      /* Without these there's no point in trying */
-	      if (!drv->ops->get_input_precision ||
-		  !drv->ops->get_input_channels ||
-		  !drv->ops->get_input_rate ||
-		  !drv->ops->get_input_encoding ||
-		  !drv->ops->get_output_precision ||
-		  !drv->ops->get_output_channels ||
-		  !drv->ops->get_output_rate ||
-		  !drv->ops->get_output_encoding) 
-		{
-		  eprintk(("missing get routines: failed\n"));
-		  retval = -EINVAL;
-		  break;
-		}
-
-	      /* Do bounds checking for things which always apply.
-	       * Follow with enforcement of basic tenets of certain
-	       * encodings. Everything over and above generic is
-	       * enforced by the driver, which can assume that
-	       * Martian cases are taken care of here. */
-	      if (Modify(ainfo.play.gain) && 
-		  ((ainfo.play.gain > AUDIO_MAX_GAIN) || 
-		   (ainfo.play.gain < AUDIO_MIN_GAIN))) {
-		/* Need to differentiate this from e.g. the above error */
-		eprintk(("play gain bounds: failed %d\n", ainfo.play.gain));
-		retval = -EINVAL;
-		break;
-	      }
-	      if (Modify(ainfo.record.gain) &&
-		  ((ainfo.record.gain > AUDIO_MAX_GAIN) ||
-		   (ainfo.record.gain < AUDIO_MIN_GAIN))) {
-		eprintk(("rec gain bounds: failed %d\n", ainfo.record.gain));
-		retval = -EINVAL;
-		break;
-	      }
-	      if (Modify(ainfo.monitor_gain) &&
-		  ((ainfo.monitor_gain > AUDIO_MAX_GAIN) ||
-		   (ainfo.monitor_gain < AUDIO_MIN_GAIN))) {
-		eprintk(("monitor gain bounds: failed\n"));
-		retval = -EINVAL;
-		break;
-	      }
-	      /* Don't need to check less than zero on these */
-	      if (Modifyc(ainfo.play.balance) &&
-		  (ainfo.play.balance > AUDIO_RIGHT_BALANCE)) {
-		eprintk(("play balance bounds: %d failed\n", 
-			 (int)ainfo.play.balance));
-		retval = -EINVAL;
-		break;
-	      }
-	      if (Modifyc(ainfo.record.balance) &&
-		  (ainfo.record.balance > AUDIO_RIGHT_BALANCE)) {
-		eprintk(("rec balance bounds: failed\n"));
-		retval = -EINVAL;
-		break;
-	      }
+                        if (verify_area(VERIFY_READ, (audio_info_t *)arg, 
+                                        sizeof(audio_info_t))) {
+                                dprintk(("verify_area failed\n"));
+                                return -EINVAL;
+                        }
+                        copy_from_user(&ainfo, (audio_info_t *)arg, sizeof(audio_info_t));
+
+                        /* Without these there's no point in trying */
+                        if (!drv->ops->get_input_precision ||
+                            !drv->ops->get_input_channels ||
+                            !drv->ops->get_input_rate ||
+                            !drv->ops->get_input_encoding ||
+                            !drv->ops->get_output_precision ||
+                            !drv->ops->get_output_channels ||
+                            !drv->ops->get_output_rate ||
+                            !drv->ops->get_output_encoding) {
+                                eprintk(("missing get routines: failed\n"));
+                                retval = -EINVAL;
+                                break;
+                        }
+
+                        /* Do bounds checking for things which always apply.
+                         * Follow with enforcement of basic tenets of certain
+                         * encodings. Everything over and above generic is
+                         * enforced by the driver, which can assume that
+                         * Martian cases are taken care of here.
+                         */
+                        if (Modify(ainfo.play.gain) && 
+                            ((ainfo.play.gain > AUDIO_MAX_GAIN) || 
+                             (ainfo.play.gain < AUDIO_MIN_GAIN))) {
+                                /* Need to differentiate this from e.g. the above error */
+                                eprintk(("play gain bounds: failed %d\n", ainfo.play.gain));
+                                retval = -EINVAL;
+                                break;
+                        }
+                        if (Modify(ainfo.record.gain) &&
+                            ((ainfo.record.gain > AUDIO_MAX_GAIN) ||
+                             (ainfo.record.gain < AUDIO_MIN_GAIN))) {
+                                eprintk(("rec gain bounds: failed %d\n", ainfo.record.gain));
+                                retval = -EINVAL;
+                                break;
+                        }
+                        if (Modify(ainfo.monitor_gain) &&
+                            ((ainfo.monitor_gain > AUDIO_MAX_GAIN) ||
+                             (ainfo.monitor_gain < AUDIO_MIN_GAIN))) {
+                                eprintk(("monitor gain bounds: failed\n"));
+                                retval = -EINVAL;
+                                break;
+                        }
+
+                        /* Don't need to check less than zero on these */
+                        if (Modifyc(ainfo.play.balance) &&
+                            (ainfo.play.balance > AUDIO_RIGHT_BALANCE)) {
+                                eprintk(("play balance bounds: %d failed\n", 
+                                         (int)ainfo.play.balance));
+                                retval = -EINVAL;
+                                break;
+                        }
+                        if (Modifyc(ainfo.record.balance) &&
+                            (ainfo.record.balance > AUDIO_RIGHT_BALANCE)) {
+                                eprintk(("rec balance bounds: failed\n"));
+                                retval = -EINVAL;
+                                break;
+                        }
 	      
-	      /* If any of these changed, record them all, then make
-	       * changes atomically. If something fails, back it all out. */
-	      if (Modify(ainfo.record.precision) || 
-		  Modify(ainfo.record.sample_rate) ||
-		  Modify(ainfo.record.channels) ||
-		  Modify(ainfo.record.encoding) || 
-		  Modify(ainfo.play.precision) || 
-		  Modify(ainfo.play.sample_rate) ||
-		  Modify(ainfo.play.channels) ||
-		  Modify(ainfo.play.encoding)) 
-		{
-		  /* If they're trying to change something we
-		   * have no routine for, they lose */
-		  if ((!drv->ops->set_input_encoding && 
-		       Modify(ainfo.record.encoding)) ||
-		      (!drv->ops->set_input_rate && 
-		       Modify(ainfo.record.sample_rate)) ||
-		      (!drv->ops->set_input_precision && 
-		       Modify(ainfo.record.precision)) ||
-		      (!drv->ops->set_input_channels && 
-		       Modify(ainfo.record.channels))) {
-		    eprintk(("rec set no routines: failed\n"));
-		    retval = -EINVAL;
-		    break;
-		  }		  
+                        /* If any of these changed, record them all, then make
+                         * changes atomically. If something fails, back it all out.
+                         */
+                        if (Modify(ainfo.record.precision) || 
+                            Modify(ainfo.record.sample_rate) ||
+                            Modify(ainfo.record.channels) ||
+                            Modify(ainfo.record.encoding) || 
+                            Modify(ainfo.play.precision) || 
+                            Modify(ainfo.play.sample_rate) ||
+                            Modify(ainfo.play.channels) ||
+                            Modify(ainfo.play.encoding)) {
+                                /* If they're trying to change something we
+                                 * have no routine for, they lose.
+                                 */
+                                if ((!drv->ops->set_input_encoding && 
+                                     Modify(ainfo.record.encoding)) ||
+                                    (!drv->ops->set_input_rate && 
+                                     Modify(ainfo.record.sample_rate)) ||
+                                    (!drv->ops->set_input_precision && 
+                                     Modify(ainfo.record.precision)) ||
+                                    (!drv->ops->set_input_channels && 
+                                     Modify(ainfo.record.channels))) {
+                                        eprintk(("rec set no routines: failed\n"));
+                                        retval = -EINVAL;
+                                        break;
+                                }		  
 		  
-		  curinfo.record.encoding = 
-		    drv->ops->get_input_encoding(drv);
-		  curinfo.record.sample_rate = 
-		    drv->ops->get_input_rate(drv);	   
-		  curinfo.record.precision = 
-		    drv->ops->get_input_precision(drv);	   
-		  curinfo.record.channels = 
-		    drv->ops->get_input_channels(drv);	   
-		  newinfo.record.encoding = Modify(ainfo.record.encoding) ? 
-		    ainfo.record.encoding : curinfo.record.encoding;
-		  newinfo.record.sample_rate =
-		    Modify(ainfo.record.sample_rate)?
-		    ainfo.record.sample_rate : curinfo.record.sample_rate;
-		  newinfo.record.precision = Modify(ainfo.record.precision) ? 
-		    ainfo.record.precision : curinfo.record.precision;
-		  newinfo.record.channels = Modify(ainfo.record.channels) ? 
-		    ainfo.record.channels : curinfo.record.channels;
+                                curinfo.record.encoding = 
+                                        drv->ops->get_input_encoding(drv);
+                                curinfo.record.sample_rate = 
+                                        drv->ops->get_input_rate(drv);	   
+                                curinfo.record.precision = 
+                                        drv->ops->get_input_precision(drv);	   
+                                curinfo.record.channels = 
+                                        drv->ops->get_input_channels(drv);	   
+                                newinfo.record.encoding =
+                                        Modify(ainfo.record.encoding) ? 
+                                        ainfo.record.encoding :
+                                        curinfo.record.encoding;
+                                newinfo.record.sample_rate =
+                                        Modify(ainfo.record.sample_rate) ?
+                                        ainfo.record.sample_rate :
+                                        curinfo.record.sample_rate;
+                                newinfo.record.precision =
+                                        Modify(ainfo.record.precision) ? 
+                                        ainfo.record.precision :
+                                        curinfo.record.precision;
+                                newinfo.record.channels =
+                                        Modify(ainfo.record.channels) ? 
+                                        ainfo.record.channels :
+                                        curinfo.record.channels;
 		    
-		  switch (newinfo.record.encoding) {
-		  case AUDIO_ENCODING_ALAW:
-		  case AUDIO_ENCODING_ULAW:
-		    if (newinfo.record.precision != 8) {
-		      eprintk(("rec law precision bounds: failed\n"));
-		      retval = -EINVAL;
-		      break;
-		    }
-		    if (newinfo.record.channels != 1) {
-		      eprintk(("rec law channel bounds: failed\n"));
-		      retval = -EINVAL;
-		      break;
-		    }
-		    break;
-		  case AUDIO_ENCODING_LINEAR:
-		  case AUDIO_ENCODING_LINEARLE:
-		    if (newinfo.record.precision != 16) {
-		      eprintk(("rec lin precision bounds: failed\n"));
-		      retval = -EINVAL;
-		      break;
-		    }
-		    if (newinfo.record.channels != 1 && 
-			newinfo.record.channels != 2) 
-		      {
-			eprintk(("rec lin channel bounds: failed\n"));
-			retval = -EINVAL;
-			break;
-		      }
-		    break;
-		  case AUDIO_ENCODING_LINEAR8:
-		    if (newinfo.record.precision != 8) {
-		      eprintk(("rec lin8 precision bounds: failed\n"));
-		      retval = -EINVAL;
-		      break;
-		    }
-		    if (newinfo.record.channels != 1 && 
-			newinfo.record.channels != 2)
-		      {
-			eprintk(("rec lin8 channel bounds: failed\n"));
-			retval = -EINVAL;
-			break;
-		      }
-		  }
+                                switch (newinfo.record.encoding) {
+                                case AUDIO_ENCODING_ALAW:
+                                case AUDIO_ENCODING_ULAW:
+                                        if (newinfo.record.precision != 8) {
+                                                eprintk(("rec law precision bounds: "
+                                                         "failed\n"));
+                                                retval = -EINVAL;
+                                                break;
+                                        }
+                                        if (newinfo.record.channels != 1) {
+                                                eprintk(("rec law channel bounds: "
+                                                         "failed\n"));
+                                                retval = -EINVAL;
+                                                break;
+                                        }
+                                        break;
+                                case AUDIO_ENCODING_LINEAR:
+                                case AUDIO_ENCODING_LINEARLE:
+                                        if (newinfo.record.precision != 16) {
+                                                eprintk(("rec lin precision bounds: "
+                                                         "failed\n"));
+                                                retval = -EINVAL;
+                                                break;
+                                        }
+                                        if (newinfo.record.channels != 1 &&
+                                            newinfo.record.channels != 2) {
+                                                eprintk(("rec lin channel bounds: "
+                                                         "failed\n"));
+                                                retval = -EINVAL;
+                                                break;
+                                        }
+                                        break;
+                                case AUDIO_ENCODING_LINEAR8:
+                                        if (newinfo.record.precision != 8) {
+                                                eprintk(("rec lin8 precision bounds: "
+                                                         "failed\n"));
+                                                retval = -EINVAL;
+                                                break;
+                                        }
+                                        if (newinfo.record.channels != 1 && 
+                                            newinfo.record.channels != 2) {
+                                                eprintk(("rec lin8 channel bounds: "
+                                                         "failed\n"));
+                                                retval = -EINVAL;
+                                                break;
+                                        }
+                                };
 		  
-		  if (retval < 0)
-		    break;
+                                if (retval < 0)
+                                        break;
 		  
-		  /* If they're trying to change something we
-		   * have no routine for, they lose */
-		  if ((!drv->ops->set_output_encoding && 
-		       Modify(ainfo.play.encoding)) ||
-		      (!drv->ops->set_output_rate && 
-		       Modify(ainfo.play.sample_rate)) ||
-		      (!drv->ops->set_output_precision && 
-		       Modify(ainfo.play.precision)) ||
-		      (!drv->ops->set_output_channels && 
-		       Modify(ainfo.play.channels))) {
-		    eprintk(("play set no routine: failed\n"));
-		    retval = -EINVAL;
-		    break;
-		  }		  
+                                /* If they're trying to change something we
+                                 * have no routine for, they lose.
+                                 */
+                                if ((!drv->ops->set_output_encoding && 
+                                     Modify(ainfo.play.encoding)) ||
+                                    (!drv->ops->set_output_rate && 
+                                     Modify(ainfo.play.sample_rate)) ||
+                                    (!drv->ops->set_output_precision && 
+                                     Modify(ainfo.play.precision)) ||
+                                    (!drv->ops->set_output_channels && 
+                                     Modify(ainfo.play.channels))) {
+                                        eprintk(("play set no routine: failed\n"));
+                                        retval = -EINVAL;
+                                        break;
+                                }		  
 		  
-		  curinfo.play.encoding = 
-		    drv->ops->get_output_encoding(drv);
-		  curinfo.play.sample_rate = 
-		    drv->ops->get_output_rate(drv);	   
-		  curinfo.play.precision = 
-		    drv->ops->get_output_precision(drv);	   
-		  curinfo.play.channels = 
-		    drv->ops->get_output_channels(drv);	   
-		  newinfo.play.encoding = Modify(ainfo.play.encoding) ? 
-		    ainfo.play.encoding : curinfo.play.encoding;
-		  newinfo.play.sample_rate = Modify(ainfo.play.sample_rate) ? 
-		    ainfo.play.sample_rate : curinfo.play.sample_rate;
-		  newinfo.play.precision = Modify(ainfo.play.precision) ? 
-		    ainfo.play.precision : curinfo.play.precision;
-		  newinfo.play.channels = Modify(ainfo.play.channels) ? 
-		    ainfo.play.channels : curinfo.play.channels;
+                                curinfo.play.encoding = 
+                                        drv->ops->get_output_encoding(drv);
+                                curinfo.play.sample_rate = 
+                                        drv->ops->get_output_rate(drv);	   
+                                curinfo.play.precision = 
+                                        drv->ops->get_output_precision(drv);	   
+                                curinfo.play.channels = 
+                                        drv->ops->get_output_channels(drv);	   
+                                newinfo.play.encoding =
+                                        Modify(ainfo.play.encoding) ? 
+                                        ainfo.play.encoding :
+                                                curinfo.play.encoding;
+                                newinfo.play.sample_rate =
+                                        Modify(ainfo.play.sample_rate) ? 
+                                        ainfo.play.sample_rate :
+                                                curinfo.play.sample_rate;
+                                newinfo.play.precision =
+                                        Modify(ainfo.play.precision) ? 
+                                        ainfo.play.precision :
+                                                curinfo.play.precision;
+                                newinfo.play.channels =
+                                        Modify(ainfo.play.channels) ? 
+                                        ainfo.play.channels :
+                                                curinfo.play.channels;
 		  
-		  switch (newinfo.play.encoding) {
-		  case AUDIO_ENCODING_ALAW:
-		  case AUDIO_ENCODING_ULAW:
-		    if (newinfo.play.precision != 8) {
-		      eprintk(("play law precision bounds: failed\n"));
-		      retval = -EINVAL;
-		      break;
-		    }
-		    if (newinfo.play.channels != 1) {
-		      eprintk(("play law channel bounds: failed\n"));
-		      retval = -EINVAL;
-		      break;
-		    }
-		    break;
-		  case AUDIO_ENCODING_LINEAR:
-		  case AUDIO_ENCODING_LINEARLE:
-		    if (newinfo.play.precision != 16) {
-		      eprintk(("play lin precision bounds: failed\n"));
-		      retval = -EINVAL;
-		      break;
-		    }
-		    if (newinfo.play.channels != 1 && 
-			newinfo.play.channels != 2) 
-		      {
-			eprintk(("play lin channel bounds: failed\n"));
-			retval = -EINVAL;
-			break;
-		      }
-		    break;
-		  case AUDIO_ENCODING_LINEAR8:
-		    if (newinfo.play.precision != 8) {
-		      eprintk(("play lin8 precision bounds: failed\n"));
-		      retval = -EINVAL;
-		      break;
-		    }
-		    if (newinfo.play.channels != 1 && 
-			newinfo.play.channels != 2) 
-		      {
-			eprintk(("play lin8 channel bounds: failed\n"));
-			retval = -EINVAL;
-			break;
-		      }
-		  }
+                                switch (newinfo.play.encoding) {
+                                case AUDIO_ENCODING_ALAW:
+                                case AUDIO_ENCODING_ULAW:
+                                        if (newinfo.play.precision != 8) {
+                                                eprintk(("play law precision bounds: "
+                                                         "failed\n"));
+                                                retval = -EINVAL;
+                                                break;
+                                        }
+                                        if (newinfo.play.channels != 1) {
+                                                eprintk(("play law channel bounds: "
+                                                         "failed\n"));
+                                                retval = -EINVAL;
+                                                break;
+                                        }
+                                        break;
+                                case AUDIO_ENCODING_LINEAR:
+                                case AUDIO_ENCODING_LINEARLE:
+                                        if (newinfo.play.precision != 16) {
+                                                eprintk(("play lin precision bounds: "
+                                                         "failed\n"));
+                                                retval = -EINVAL;
+                                                break;
+                                        }
+                                        if (newinfo.play.channels != 1 && 
+                                            newinfo.play.channels != 2) {
+                                                eprintk(("play lin channel bounds: "
+                                                         "failed\n"));
+                                                retval = -EINVAL;
+                                                break;
+                                        }
+                                        break;
+                                case AUDIO_ENCODING_LINEAR8:
+                                        if (newinfo.play.precision != 8) {
+                                                eprintk(("play lin8 precision bounds: "
+                                                         "failed\n"));
+                                                retval = -EINVAL;
+                                                break;
+                                        }
+                                        if (newinfo.play.channels != 1 && 
+                                            newinfo.play.channels != 2) {
+                                                eprintk(("play lin8 channel bounds: "
+                                                         "failed\n"));
+                                                retval = -EINVAL;
+                                                break;
+                                        }
+                                };
 		  
-		  if (retval < 0)
-		    break;
+                                if (retval < 0)
+                                        break;
 		  
-		  /* If we got this far, we're at least sane with
-		   * respect to generics. Try the changes. */
-		  if ((drv->ops->set_input_channels &&
-		      (drv->ops->set_input_channels(drv, 
-						    newinfo.record.channels)
-		       < 0)) ||
-		      (drv->ops->set_output_channels &&
-		       (drv->ops->set_output_channels(drv, 
-						      newinfo.play.channels)
-			< 0)) ||
-		      (drv->ops->set_input_rate &&
-		       (drv->ops->set_input_rate(drv, 
-						 newinfo.record.sample_rate) 
-			< 0)) ||
-		      (drv->ops->set_output_rate &&
-		       (drv->ops->set_output_rate(drv, 
-						  newinfo.play.sample_rate) 
-			< 0)) ||
-		      (drv->ops->set_input_precision &&
-		       (drv->ops->set_input_precision(drv, 
-						      newinfo.record.precision)
-			< 0)) ||
-		      (drv->ops->set_output_precision &&
-		       (drv->ops->set_output_precision(drv, 
-						       newinfo.play.precision)
-			< 0)) ||
-		      (drv->ops->set_input_encoding &&
-		       (drv->ops->set_input_encoding(drv, 
-						     newinfo.record.encoding)
-			< 0)) ||
-		      (drv->ops->set_output_encoding &&
-		       (drv->ops->set_output_encoding(drv, 
-						      newinfo.play.encoding)
-			< 0))) 
-		    {
-		      dprintk(("setting format: failed\n"));
-		      /* Pray we can set it all back. If not, uh... */
-		      if (drv->ops->set_input_channels)
-			drv->ops->set_input_channels(drv, 
+                                /* If we got this far, we're at least sane with
+                                 * respect to generics. Try the changes.
+                                 */
+                                if ((drv->ops->set_input_channels &&
+                                     (drv->ops->set_input_channels(drv, 
+                                                                   newinfo.record.channels)
+                                      < 0)) ||
+                                    (drv->ops->set_output_channels &&
+                                     (drv->ops->set_output_channels(drv, 
+                                                                    newinfo.play.channels)
+                                      < 0)) ||
+                                    (drv->ops->set_input_rate &&
+                                     (drv->ops->set_input_rate(drv, 
+                                                               newinfo.record.sample_rate) 
+                                      < 0)) ||
+                                    (drv->ops->set_output_rate &&
+                                     (drv->ops->set_output_rate(drv, 
+                                                                newinfo.play.sample_rate) 
+                                      < 0)) ||
+                                    (drv->ops->set_input_precision &&
+                                     (drv->ops->set_input_precision(drv, 
+                                                                    newinfo.record.precision)
+                                      < 0)) ||
+                                    (drv->ops->set_output_precision &&
+                                     (drv->ops->set_output_precision(drv, 
+                                                                     newinfo.play.precision)
+                                      < 0)) ||
+                                    (drv->ops->set_input_encoding &&
+                                     (drv->ops->set_input_encoding(drv, 
+                                                                   newinfo.record.encoding)
+                                      < 0)) ||
+                                    (drv->ops->set_output_encoding &&
+                                     (drv->ops->set_output_encoding(drv, 
+                                                                    newinfo.play.encoding)
+                                      < 0))) 
+                                {
+                                        dprintk(("setting format: failed\n"));
+                                        /* Pray we can set it all back. If not, uh... */
+                                        if (drv->ops->set_input_channels)
+                                                drv->ops->set_input_channels(drv, 
 						     curinfo.record.channels);
-		      if (drv->ops->set_output_channels)
-			drv->ops->set_output_channels(drv, 
-						      curinfo.play.channels);
-		      if (drv->ops->set_input_rate)
-			drv->ops->set_input_rate(drv, 
-						 curinfo.record.sample_rate);
-		      if (drv->ops->set_output_rate)
-			drv->ops->set_output_rate(drv, 
-						  curinfo.play.sample_rate);
-		      if (drv->ops->set_input_precision)
-			drv->ops->set_input_precision(drv, 
-						      curinfo.record.precision);
-		      if (drv->ops->set_output_precision)
-			drv->ops->set_output_precision(drv, 
-						       curinfo.play.precision);
-		      if (drv->ops->set_input_encoding)
-			drv->ops->set_input_encoding(drv, 
-						     curinfo.record.encoding);
-		      if (drv->ops->set_output_encoding)
-			drv->ops->set_output_encoding(drv, 
-						      curinfo.play.encoding);
-		      retval = -EINVAL;
-		      break;
-		    }
-		}
-	      
-	      if (retval < 0)
-		break;
+                                        if (drv->ops->set_output_channels)
+                                                drv->ops->set_output_channels(drv, 
+                                                                              curinfo.play.channels);
+                                        if (drv->ops->set_input_rate)
+                                                drv->ops->set_input_rate(drv, 
+                                                                         curinfo.record.sample_rate);
+                                        if (drv->ops->set_output_rate)
+                                                drv->ops->set_output_rate(drv, 
+                                                                          curinfo.play.sample_rate);
+                                        if (drv->ops->set_input_precision)
+                                                drv->ops->set_input_precision(drv, 
+                                                                              curinfo.record.precision);
+                                        if (drv->ops->set_output_precision)
+                                                drv->ops->set_output_precision(drv, 
+                                                                               curinfo.play.precision);
+                                        if (drv->ops->set_input_encoding)
+                                                drv->ops->set_input_encoding(drv, 
+                                                                             curinfo.record.encoding);
+                                        if (drv->ops->set_output_encoding)
+                                                drv->ops->set_output_encoding(drv, 
+                                                                              curinfo.play.encoding);
+                                        retval = -EINVAL;
+                                        break;
+                                }
+                        }
+                        
+                        if (retval < 0)
+                                break;
+                        
+                        newinfo.record.balance =
+                                __sparcaudio_if_setc_do(drv, 
+                                                        drv->ops->set_input_balance, 
+                                                        drv->ops->get_input_balance,
+                                                        ainfo.record.balance);
+                        newinfo.play.balance =
+                                __sparcaudio_if_setc_do(drv, 
+                                                        drv->ops->set_output_balance, 
+                                                        drv->ops->get_output_balance,
+                                                        ainfo.play.balance);
+                        newinfo.record.error =
+                                __sparcaudio_if_setc_do(drv, 
+                                                        drv->ops->set_input_error, 
+                                                        drv->ops->get_input_error,
+                                                        ainfo.record.error);
+                        newinfo.play.error =
+                                __sparcaudio_if_setc_do(drv, 
+                                                        drv->ops->set_output_error, 
+                                                        drv->ops->get_output_error,
+                                                        ainfo.play.error);
+                        newinfo.output_muted =
+                                __sparcaudio_if_setc_do(drv, 
+                                                        drv->ops->set_output_muted, 
+                                                        drv->ops->get_output_muted,
+                                                        ainfo.output_muted);
+                        newinfo.record.gain =
+                                __sparcaudio_if_set_do(drv, 
+                                                       drv->ops->set_input_volume, 
+                                                       drv->ops->get_input_volume,
+                                                       ainfo.record.gain);
+                        newinfo.play.gain =
+                                __sparcaudio_if_set_do(drv, 
+                                                       drv->ops->set_output_volume, 
+                                                       drv->ops->get_output_volume,
+                                                       ainfo.play.gain);
+                        newinfo.record.port =
+                                __sparcaudio_if_set_do(drv, 
+                                                       drv->ops->set_input_port, 
+                                                       drv->ops->get_input_port,
+                                                       ainfo.record.port);
+                        newinfo.play.port =
+                                __sparcaudio_if_set_do(drv, 
+                                                       drv->ops->set_output_port, 
+                                                       drv->ops->get_output_port,
+                                                       ainfo.play.port);
+                        newinfo.record.samples =
+                                __sparcaudio_if_set_do(drv, 
+                                                       drv->ops->set_input_samples, 
+                                                       drv->ops->get_input_samples,
+                                                       ainfo.record.samples);
+                        newinfo.play.samples =
+                                __sparcaudio_if_set_do(drv, 
+                                                       drv->ops->set_output_samples, 
+                                                       drv->ops->get_output_samples,
+                                                       ainfo.play.samples);
+                        newinfo.monitor_gain =
+                                __sparcaudio_if_set_do(drv, 
+                                                       drv->ops->set_monitor_volume, 
+                                                       drv->ops->get_monitor_volume,
+                                                       ainfo.monitor_gain);
+
+                        if (Modify(ainfo.record.buffer_size)) {
+                                /* Should sanity check this */
+                                newinfo.record.buffer_size = ainfo.record.buffer_size;
+                                drv->buffer_size = ainfo.record.buffer_size;
+                        } else {
+                                newinfo.record.buffer_size = drv->buffer_size;
+                        }
+
+                        if (Modify(ainfo.play.eof)) {
+                                ainfo.play.eof = newinfo.play.eof;
+                                newinfo.play.eof = drv->output_eof;
+                                drv->output_eof = ainfo.play.eof;
+                        } else {
+                                newinfo.play.eof = drv->output_eof;
+                        }		
+
+                        if (drv->flags & SDF_OPEN_READ) {
+                                newinfo.record.pause =
+                                        __sparcaudio_if_setc_do(drv, 
+                                                                drv->ops->set_input_pause, 
+                                                                drv->ops->get_input_pause,
+                                                                ainfo.record.pause);
+                        } else if (drv->ops->get_input_pause) {
+                                newinfo.record.pause = drv->ops->get_input_pause(drv);
+                        } else {
+                                newinfo.record.pause = 0;
+                        }
+
+                        if (drv->flags & SDF_OPEN_WRITE) {
+                                newinfo.play.pause =
+                                        __sparcaudio_if_setc_do(drv, 
+                                                                drv->ops->set_output_pause, 
+                                                                drv->ops->get_output_pause,
+                                                                ainfo.play.pause);
+                        } else if (drv->ops->get_output_pause) {
+                                newinfo.play.pause = drv->ops->get_output_pause(drv);
+                        } else {
+                                newinfo.play.pause = 0;
+                        }
 	      
-	      newinfo.record.balance =
-		__sparcaudio_if_setc_do(drv, 
-					drv->ops->set_input_balance, 
-					drv->ops->get_input_balance,
-					ainfo.record.balance);
-	      newinfo.play.balance =
-		__sparcaudio_if_setc_do(drv, 
-					drv->ops->set_output_balance, 
-					drv->ops->get_output_balance,
-					ainfo.play.balance);
-	      newinfo.record.error =
-		__sparcaudio_if_setc_do(drv, 
-					drv->ops->set_input_error, 
-					drv->ops->get_input_error,
-					ainfo.record.error);
-	      newinfo.play.error =
-		__sparcaudio_if_setc_do(drv, 
-					drv->ops->set_output_error, 
-					drv->ops->get_output_error,
-					ainfo.play.error);
-	      newinfo.output_muted =
-		__sparcaudio_if_setc_do(drv, 
-					drv->ops->set_output_muted, 
-					drv->ops->get_output_muted,
-					ainfo.output_muted);
-	      newinfo.record.gain =
-		__sparcaudio_if_set_do(drv, 
-					drv->ops->set_input_volume, 
-					drv->ops->get_input_volume,
-					ainfo.record.gain);
-	      newinfo.play.gain =
-		__sparcaudio_if_set_do(drv, 
-					drv->ops->set_output_volume, 
-					drv->ops->get_output_volume,
-					ainfo.play.gain);
-	      newinfo.record.port =
-		__sparcaudio_if_set_do(drv, 
-					drv->ops->set_input_port, 
-					drv->ops->get_input_port,
-					ainfo.record.port);
-	      newinfo.play.port =
-		__sparcaudio_if_set_do(drv, 
-					drv->ops->set_output_port, 
-					drv->ops->get_output_port,
-					ainfo.play.port);
-	      newinfo.record.samples =
-		__sparcaudio_if_set_do(drv, 
-					drv->ops->set_input_samples, 
-					drv->ops->get_input_samples,
-					ainfo.record.samples);
-	      newinfo.play.samples =
-		__sparcaudio_if_set_do(drv, 
-					drv->ops->set_output_samples, 
-					drv->ops->get_output_samples,
-					ainfo.play.samples);
-	      newinfo.monitor_gain =
-		__sparcaudio_if_set_do(drv, 
-					drv->ops->set_monitor_volume, 
-					drv->ops->get_monitor_volume,
-					ainfo.monitor_gain);
-
-	      if (Modify(ainfo.record.buffer_size)) {
-		/* Should sanity check this */
-		newinfo.record.buffer_size = ainfo.record.buffer_size;
-		drv->buffer_size = ainfo.record.buffer_size;
-	      } else 
-		newinfo.record.buffer_size = drv->buffer_size;
-
-
-	      if (Modify(ainfo.play.eof)) {
-		ainfo.play.eof = newinfo.play.eof;
-		newinfo.play.eof = drv->output_eof;
-		drv->output_eof = ainfo.play.eof;
-	      } else
-		newinfo.play.eof = drv->output_eof;
-		
-	      if (drv->flags & SDF_OPEN_READ) {
-		newinfo.record.pause =
-		  __sparcaudio_if_setc_do(drv, 
-					  drv->ops->set_input_pause, 
-					  drv->ops->get_input_pause,
-					  ainfo.record.pause);
-	      } else if (drv->ops->get_input_pause) {
-		newinfo.record.pause = drv->ops->get_input_pause(drv);
-	      } else newinfo.record.pause = 0;
-
-	      if (drv->flags & SDF_OPEN_WRITE) {
-		newinfo.play.pause =
-		  __sparcaudio_if_setc_do(drv, 
-					  drv->ops->set_output_pause, 
-					  drv->ops->get_output_pause,
-					  ainfo.play.pause);
-	      } else if (drv->ops->get_output_pause) {
-		newinfo.play.pause = drv->ops->get_output_pause(drv);
-	      } else newinfo.play.pause = 0;
-	      
-	      retval = verify_area(VERIFY_WRITE, (void *)arg,
-				   sizeof(struct audio_info));
+                        retval = verify_area(VERIFY_WRITE, (void *)arg,
+                                             sizeof(struct audio_info));
 
-	      /* Even if we fail, if we made changes let's try notification */
-	      if (!retval) 
-		copy_to_user((struct audio_info *)arg, &newinfo, 
-			     sizeof(newinfo));
+                        /* Even if we fail, if we made changes let's try notification */
+                        if (!retval) 
+                                copy_to_user((struct audio_info *)arg, &newinfo, 
+                                             sizeof(newinfo));
 	    
 #ifdef REAL_AUDIO_SIGNALS
-	      kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
+                        kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
 #endif
-
-	      break;
-	    }
+                        break;
+                }
 	  
-	  default:
-	    if (drv->ops->ioctl)
-	      retval = drv->ops->ioctl(inode,file,cmd,arg,drv);
-	    else
-	      retval = -EINVAL;
-	  }
-	  break;
+                default:
+                        if (drv->ops->ioctl)
+                                retval = drv->ops->ioctl(inode,file,cmd,arg,drv);
+                        else
+                                retval = -EINVAL;
+                };
+                break;
 	case SPARCAUDIO_STATUS_MINOR:
-	  eprintk(("status minor not yet implemented\n"));
-	  retval = -EINVAL;
+                eprintk(("status minor not yet implemented\n"));
+                retval = -EINVAL;
 	default:
-	  eprintk(("unknown minor device number\n"));
-	  retval = -EINVAL;
-	}
+                eprintk(("unknown minor device number\n"));
+                retval = -EINVAL;
+	};
 	
 	return retval;
 }
 
 static int sparcaudioctl_release_ret(struct inode * inode, struct file * file)
 {
-      MOD_DEC_USE_COUNT;
-      return 0;
+        MOD_DEC_USE_COUNT;
+        return 0;
 }
 
 /* For 2.0 kernels */
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100
 static void sparcaudioctl_release(struct inode * inode, struct file * file)
 {
-  sparcaudioctl_release_ret(inode, file);
+        sparcaudioctl_release_ret(inode, file);
 }
 #endif
 
 static struct file_operations sparcaudioctl_fops = {
-      NULL,
-      NULL,
-      NULL,
-      NULL,                   /* sparcaudio_readdir */
-      sparcaudio_select,
-      sparcaudio_ioctl,
-      NULL,                   /* sparcaudio_mmap */
-      NULL,
+        NULL,
+        NULL,
+        NULL,
+        NULL,                   /* sparcaudio_readdir */
+        sparcaudio_select,
+        sparcaudio_ioctl,
+        NULL,                   /* sparcaudio_mmap */
+        NULL,
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
-      NULL,                   /* sparcaudio_flush */
+        NULL,                   /* sparcaudio_flush */
 #endif
-      sparcaudioctl_release,
+        sparcaudioctl_release,
 };
 
 static int sparcaudio_open(struct inode * inode, struct file * file)
 {
         int minor = MINOR(inode->i_rdev);
 	struct sparcaudio_driver *drv = 
-	  drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)];
+                drivers[(minor >> SPARCAUDIO_DEVICE_SHIFT)];
 	int err;
 
 	/* A low-level audio driver must exist. */
@@ -1952,84 +1991,87 @@
 
 	switch (minor & 0xf) {
 	case SPARCAUDIO_AUDIOCTL_MINOR:
-	  file->f_op = &sparcaudioctl_fops;
-	  break;
+                file->f_op = &sparcaudioctl_fops;
+                break;
 	case SPARCAUDIO_DSP16_MINOR:
 	case SPARCAUDIO_DSP_MINOR:
 	case SPARCAUDIO_AUDIO_MINOR:
-	  /* If the driver is busy, then wait to get through. */
-	  retry_open:
-	  if (file->f_mode & FMODE_READ && drv->flags & SDF_OPEN_READ) {
-	    if (file->f_flags & O_NONBLOCK)
-	      return -EBUSY;
-
-	    /* If something is now waiting, signal control device */
-	    kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
-
-	    interruptible_sleep_on(&drv->open_wait);
-            if (signal_pending(current))
-	      return -EINTR;
-	    goto retry_open;
-	  }
-	  if (file->f_mode & FMODE_WRITE && drv->flags & SDF_OPEN_WRITE) {
-	    if (file->f_flags & O_NONBLOCK)
-	      return -EBUSY;
+                /* If the driver is busy, then wait to get through. */
+        retry_open:
+        	if (file->f_mode & FMODE_READ && drv->flags & SDF_OPEN_READ) {
+                        if (file->f_flags & O_NONBLOCK)
+                                return -EBUSY;
+
+                        /* If something is now waiting, signal control device */
+                        kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
+
+                        interruptible_sleep_on(&drv->open_wait);
+                        if (signal_pending(current))
+                                return -EINTR;
+                        goto retry_open;
+                }
+                if (file->f_mode & FMODE_WRITE && drv->flags & SDF_OPEN_WRITE) {
+                        if (file->f_flags & O_NONBLOCK)
+                                return -EBUSY;
 	    
-	    /* If something is now waiting, signal control device */
-	    kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
+                        /* If something is now waiting, signal control device */
+                        kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
+
+                        interruptible_sleep_on(&drv->open_wait);
+                        if (signal_pending(current))
+                                return -EINTR;
+                        goto retry_open;
+                }
+
+                /* Allow the low-level driver to initialize itself. */
+                if (drv->ops->open) {
+                        err = drv->ops->open(inode,file,drv);
+                        if (err < 0)
+                                return err;
+                }
 
-	    interruptible_sleep_on(&drv->open_wait);
-            if (signal_pending(current))
-	      return -EINTR;
-	    goto retry_open;
-	  }
-
-	  /* Allow the low-level driver to initialize itself. */
-	  if (drv->ops->open) {
-	    err = drv->ops->open(inode,file,drv);
-	    if (err < 0)
-	      return err;
-	  }
-
-	  /* Mark the driver as locked for read and/or write. */
-	  if (file->f_mode & FMODE_READ) {
-	    drv->input_offset = 0;
-	    drv->input_front = 0;
-	    drv->input_rear = 0;
-	    drv->input_count = 0;
-	    drv->input_size = 0;
-	    drv->recording_count = 0;
-	    /* Clear pause */
-	    if (drv->ops->set_input_pause)
-	      drv->ops->set_input_pause(drv, 0); 
-	    drv->ops->start_input(drv, drv->input_buffers[drv->input_front],
-				     drv->input_buffer_size);
-	    drv->input_active = 1;
-	    drv->flags |= SDF_OPEN_READ;
-	  }
-	  if (file->f_mode & FMODE_WRITE) {
-	    drv->output_offset = 0;
-	    drv->output_eof = 0;
-	    drv->playing_count = 0;
-	    drv->output_size = 0;
-	    drv->output_front = 0;
-	    drv->output_rear = 0;
-	    drv->output_count = 0;
-	    drv->output_active = 0;
-	    /* Clear pause */
-	    if (drv->ops->set_output_pause)
-	      drv->ops->set_output_pause(drv, 0); 
-	    drv->flags |= SDF_OPEN_WRITE;
-	  }  
+                /* Mark the driver as locked for read and/or write. */
+                if (file->f_mode & FMODE_READ) {
+                        drv->input_offset = 0;
+                        drv->input_front = 0;
+                        drv->input_rear = 0;
+                        drv->input_count = 0;
+                        drv->input_size = 0;
+                        drv->recording_count = 0;
+
+                        /* Clear pause */
+                        if (drv->ops->set_input_pause)
+                                drv->ops->set_input_pause(drv, 0); 
+                        drv->ops->start_input(drv, drv->input_buffers[drv->input_front],
+                                              drv->input_buffer_size);
+                        drv->input_active = 1;
+                        drv->flags |= SDF_OPEN_READ;
+                }
+
+                if (file->f_mode & FMODE_WRITE) {
+                        drv->output_offset = 0;
+                        drv->output_eof = 0;
+                        drv->playing_count = 0;
+                        drv->output_size = 0;
+                        drv->output_front = 0;
+                        drv->output_rear = 0;
+                        drv->output_count = 0;
+                        drv->output_active = 0;
+
+                        /* Clear pause */
+                        if (drv->ops->set_output_pause)
+                                drv->ops->set_output_pause(drv, 0); 
+                        drv->flags |= SDF_OPEN_WRITE;
+                }  
 
-	  break;
+                break;
 	case SPARCAUDIO_MIXER_MINOR:     
-	  file->f_op = &sparcaudioctl_fops;
-	  break;
+                file->f_op = &sparcaudioctl_fops;
+                break;
 
 	default:
-	  return -ENXIO;
-	}
+                return -ENXIO;
+	};
 
         /* From the dbri driver:
          * SunOS 5.5.1 audio(7I) man page says:
@@ -2042,23 +2084,23 @@
          */
 
 	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);
-          }          
+                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;
@@ -2069,62 +2111,61 @@
 
 static int sparcaudio_release_ret(struct inode * inode, struct file * file)
 {
-  struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
-                                           SPARCAUDIO_DEVICE_SHIFT)];
+        struct sparcaudio_driver *drv = drivers[(MINOR(inode->i_rdev) >>
+                                                 SPARCAUDIO_DEVICE_SHIFT)];
 
-  if (file->f_mode & FMODE_READ) {
-    /* Stop input */
-    drv->ops->stop_input(drv);
-    drv->input_active = 0;
-  }
+        if (file->f_mode & FMODE_READ) {
+                /* Stop input */
+                drv->ops->stop_input(drv);
+                drv->input_active = 0;
+        }
 
-  if (file->f_mode & FMODE_WRITE) {
-    /* Anything in the queue? */
-    if (drv->output_offset) {
-      drv->output_offset = 0;
-      drv->output_rear = (drv->output_rear + 1)
-	% drv->num_output_buffers;
-      drv->output_count++;
-    }
-    sparcaudio_sync_output(drv);
-
-    /* Wait for any output still in the queue to be played. */
-    if ((drv->output_count > 0) || (drv->playing_count > 0))
-      interruptible_sleep_on(&drv->output_drain_wait);
-
-    /* Force any output to be stopped. */
-    drv->ops->stop_output(drv);
-    drv->output_active = 0;
-    drv->playing_count = 0;
-    drv->output_eof = 0;
+        if (file->f_mode & FMODE_WRITE) {
+                /* Anything in the queue? */
+                if (drv->output_offset) {
+                        drv->output_offset = 0;
+                        drv->output_rear = (drv->output_rear + 1)
+                                % drv->num_output_buffers;
+                        drv->output_count++;
+                }
+                sparcaudio_sync_output(drv);
 
-  }
+                /* Wait for any output still in the queue to be played. */
+                if ((drv->output_count > 0) || (drv->playing_count > 0))
+                        interruptible_sleep_on(&drv->output_drain_wait);
+
+                /* Force any output to be stopped. */
+                drv->ops->stop_output(drv);
+                drv->output_active = 0;
+                drv->playing_count = 0;
+                drv->output_eof = 0;
+        }
 
-  /* Let the low-level driver do any release processing. */
-  if (drv->ops->release)
-    drv->ops->release(inode,file,drv);
+        /* Let the low-level driver do any release processing. */
+        if (drv->ops->release)
+                drv->ops->release(inode,file,drv);
 
-  if (file->f_mode & FMODE_READ)
-    drv->flags &= ~(SDF_OPEN_READ);
+        if (file->f_mode & FMODE_READ)
+                drv->flags &= ~(SDF_OPEN_READ);
 
-  if (file->f_mode & FMODE_WRITE) 
-    drv->flags &= ~(SDF_OPEN_WRITE);
+        if (file->f_mode & FMODE_WRITE) 
+                drv->flags &= ~(SDF_OPEN_WRITE);
 
-  /* Status changed. Signal control device */
-  kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
+        /* Status changed. Signal control device */
+        kill_procs(drv->sd_siglist,SIGPOLL,S_MSG);
 
-  MOD_DEC_USE_COUNT;
+        MOD_DEC_USE_COUNT;
 
-  wake_up_interruptible(&drv->open_wait);
+        wake_up_interruptible(&drv->open_wait);
 
-  return 0;
+        return 0;
 }
 
 /* For 2.0 kernels */
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100
 static void sparcaudio_release(struct inode * inode, struct file * file)
 {
-  sparcaudio_release_ret(inode, file);
+        sparcaudio_release_ret(inode, file);
 }
 #endif
 
@@ -2138,7 +2179,7 @@
 	NULL,			/* sparcaudio_mmap */
 	sparcaudio_open,
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
-      NULL,                   /* sparcaudio_flush */
+        NULL,                   /* sparcaudio_flush */
 #endif
 	sparcaudio_release
 };
@@ -2207,136 +2248,139 @@
 static int
 lis_add_to_elist( strevent_t **list, pid_t pid, short events )
 {
-    strevent_t *ev = NULL;
+        strevent_t *ev = NULL;
 
-    if (*list != NULL)
-      {
-        for (ev=(*list)->se_next;
-             ev != *list && ev->se_pid < pid;
-             ev=ev->se_next
-            );    
-      }
-
-    if (ev == NULL || ev == *list)              /* no slot for pid in list */
-      {
-        if ((ev = (strevent_t*)kmalloc(sizeof(strevent_t),GFP_KERNEL))==NULL)
-            return(-ENOMEM);
-
-        if (!*list)                     /* create dummy head node */
-	  {
-            strevent_t *hd;
-            if ((hd = (strevent_t*)kmalloc(sizeof(strevent_t),GFP_KERNEL)
-                                         )==NULL)
-	      {
-                kfree(ev);
-                return(-ENOMEM);
-	      }
-            (*list=hd)->se_pid=0;
-            hd->se_next=hd->se_prev=hd;         /* empty list */
-	  }
-
-        /* link node last in the list */
-        ev->se_prev=(*list)->se_prev;
-        (*list)->se_prev->se_next=ev;
-        ((*list)->se_prev=ev)->se_next=*list;
-
-        ev->se_pid=pid;
-        ev->se_evs=0;
-      }
-    else if (ev->se_pid!=pid){  /* link node in the middle of the list */
-        strevent_t *new;
-        if ((new = (strevent_t*)kmalloc(sizeof(strevent_t),GFP_KERNEL))==NULL){
-            return(-ENOMEM);
-        }
-        new->se_prev=ev->se_prev;
-        new->se_next=ev;
-        ev->se_prev->se_next=new;
-        ev->se_prev=new;
-        ev = new ;                              /* use new element */
-        ev->se_pid=pid;
-        ev->se_evs=0;
-    }
-    ev->se_evs|=events;
-    return(0);
+        if (*list != NULL) {
+                for (ev = (*list)->se_next;
+                     ev != *list && ev->se_pid < pid;
+                     ev = ev->se_next)
+                        ;
+        }
+
+        if (ev == NULL || ev == *list) {             /* no slot for pid in list */
+                ev = (strevent_t *) kmalloc(sizeof(strevent_t), GFP_KERNEL);
+                if (ev == NULL)
+                        return(-ENOMEM);
+
+                if (!*list) {                   /* create dummy head node */
+                        strevent_t *hd;
+
+                        hd = (strevent_t *) kmalloc(sizeof(strevent_t), GFP_KERNEL);
+                        if (hd == NULL) {
+                                kfree(ev);
+                                return(-ENOMEM);
+                        }
+                        (*list = hd)->se_pid = 0;
+                        hd->se_next = hd->se_prev = hd;         /* empty list */
+                }
+
+                /* link node last in the list */
+                ev->se_prev = (*list)->se_prev;
+                (*list)->se_prev->se_next = ev;
+                ((*list)->se_prev = ev)->se_next = *list;
+
+                ev->se_pid = pid;
+                ev->se_evs = 0;
+        } else if (ev->se_pid != pid) {  /* link node in the middle of the list */
+                strevent_t *new;
+
+                new = (strevent_t *) kmalloc(sizeof(strevent_t), GFP_KERNEL);
+                if (new == NULL)
+                        return -ENOMEM;
+
+                new->se_prev = ev->se_prev;
+                new->se_next = ev;
+                ev->se_prev->se_next = new;
+                ev->se_prev = new;
+                ev = new;                              /* use new element */
+                ev->se_pid = pid;
+                ev->se_evs = 0;
+        }
+
+        ev->se_evs |= events;
+        return 0;
 }
 
 static int
 lis_del_from_elist( strevent_t **list, pid_t pid, short events )
 {
-    strevent_t *ev = NULL;     
+        strevent_t *ev = NULL;     
+
+        if (*list != NULL) {
+                for (ev = (*list)->se_next;
+                     ev != *list && ev->se_pid < pid;
+                     ev = ev->se_next)
+                        ;
+        }
+
+        if (ev == NULL || ev == *list || ev->se_pid != pid)
+                return 1;
 
-    if (*list != NULL)
-      {
-        for (ev=(*list)->se_next;
-             ev != *list && ev->se_pid < pid;
-             ev=ev->se_next
-            );    
-      }
-
-    if (ev == NULL || ev == *list || ev->se_pid != pid )
-        return(1);
-
-    if ( (ev->se_evs &= ~events) == 0 ){        /* unlink */
-        if (ev->se_next)                        /* should always be true */
-            ev->se_next->se_prev=ev->se_prev;
-        if (ev->se_prev)                        /* should always be true */
-            ev->se_prev->se_next=ev->se_next;
-        kfree(ev);
-    }
-    return(0);
+        if ((ev->se_evs &= ~events) == 0) {        /* unlink */
+                if (ev->se_next)                        /* should always be true */
+                        ev->se_next->se_prev = ev->se_prev;
+                if (ev->se_prev)                        /* should always be true */
+                        ev->se_prev->se_next = ev->se_next;
+                kfree(ev);
+        }
+        return 0;
 }
 
 static void
 lis_free_elist( strevent_t **list )
 {
-    strevent_t  *ev;     
-    strevent_t  *nxt ;
+        strevent_t  *ev;     
+        strevent_t  *nxt;
 
-    for (ev = *list; ev != NULL; )
-      {
-        nxt = ev->se_next ;
-        kfree(ev) ;
-        ev = nxt ;
-        if (ev == *list) break ;                /* all done */
-      }
+        for (ev = *list; ev != NULL; ) {
+                nxt = ev->se_next;
+                kfree(ev);
+                ev = nxt;
+                if (ev == *list)
+                        break;                /* all done */
+        }
 
-    *list = NULL ;
+        *list = NULL;
 }
 
 static short
 lis_get_elist_ent( strevent_t *list, pid_t pid )
 {
-    strevent_t *ev = NULL;
+        strevent_t *ev = NULL;
 
-    if (list == NULL) return(0) ;
+        if (list == NULL)
+                return 0;
 
-    for(ev = list->se_next ; ev != list && ev->se_pid < pid; ev=ev->se_next )
-        ;
-    if (ev != list && ev->se_pid == pid)
-        return(ev->se_evs);
-    else
-        return(0);
+        for(ev = list->se_next ; ev != list && ev->se_pid < pid; ev = ev->se_next)
+                ;
+        if (ev != list && ev->se_pid == pid)
+                return ev->se_evs;
+        else
+                return 0;
 }
 
 static void 
 kill_procs( struct strevent *elist, int sig, short e)
 {
-  strevent_t *ev;
-  int res;
+        strevent_t *ev;
+        int res;
 
-  (void) sig ;
-  if (elist) {
-    for(ev = elist->se_next ; ev != elist; ev=ev->se_next )
-      if ((ev->se_evs & e) != 0){
-	if ((res=kill_proc(ev->se_pid,SIGPOLL,1))<0) {
-	  if (res == -3) {
-	    lis_del_from_elist(&elist, ev->se_pid, S_ALL);
-	    continue;
-	  }
-	  dprintk(("kill_proc: errno %d\n",res));
-	}
-      }
-  }
+        if (elist) {
+                for(ev = elist->se_next ; ev != elist; ev = ev->se_next)
+                        if ((ev->se_evs & e) != 0) {
+                                res = kill_proc(ev->se_pid, SIGPOLL, 1);
+
+                                if (res < 0) {
+                                        if (res == -3) {
+                                                lis_del_from_elist(&elist,
+                                                                   ev->se_pid,
+                                                                   S_ALL);
+                                                continue;
+                                        }
+                                        dprintk(("kill_proc: errno %d\n",res));
+                                }
+                        }
+        }
 }
 
 /*
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/cs4215.h linux/drivers/sbus/audio/cs4215.h
--- v2.3.34/linux/drivers/sbus/audio/cs4215.h	Thu Jun 17 01:08:50 1999
+++ linux/drivers/sbus/audio/cs4215.h	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/*
+/* $Id: cs4215.h,v 1.7 1999/09/21 14:37:19 davem Exp $
  * drivers/sbus/audio/cs4215.h
  *
  * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
@@ -117,4 +117,4 @@
 #define CS4215_RG(v)	v	/* Right Gain Setting 0xf: 22.5 dB */
 #define CS4215_MA(v)	(v<<4)	/* Monitor Path Attenuation 0xf: mute */
 
-#endif
+#endif /* _CS4215_H_ */
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c
--- v2.3.34/linux/drivers/sbus/audio/cs4231.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/sbus/audio/cs4231.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/*
+/* $Id: cs4231.c,v 1.41 1999/12/19 23:28:03 davem Exp $
  * drivers/sbus/audio/cs4231.c
  *
  * Copyright 1996, 1997, 1998, 1999 Derrick J Brashear (shadow@andrew.cmu.edu)
@@ -84,418 +84,399 @@
 static void eb4231_pollinput(struct sparcaudio_driver *drv);
 #endif
 
-#define CHIP_READY udelay(100); cs4231_ready(drv); udelay(1000);
+/* Serveral shorthands save typing... */
+#define CHIP_READY() \
+do { udelay(100); cs4231_ready(drv); udelay(1000); } while(0)
+#define WRITE_IAR(__VAL) \
+	CS4231_WRITE8(cs4231_chip, cs4231_chip->regs + IAR, __VAL)
+#define WRITE_IDR(__VAL) \
+	CS4231_WRITE8(cs4231_chip, cs4231_chip->regs + IDR, __VAL)
+#define READ_IAR() \
+	CS4231_READ8(cs4231_chip, cs4231_chip->regs + IAR)
+#define READ_IDR() \
+	CS4231_READ8(cs4231_chip, cs4231_chip->regs + IDR)
 
 /* Enable cs4231 interrupts atomically. */
-static __inline__ void cs4231_enable_interrupts(struct sparcaudio_driver *drv)
+static void cs4231_enable_interrupts(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  register unsigned long flags;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        unsigned long flags;
 
-  if (cs4231_chip->status & CS_STATUS_INTS_ON)
-    return;
-
-  tprintk(("enabling interrupts\n"));
-  save_flags(flags);
-  cli();
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0xa);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), INTR_ON);
-  restore_flags(flags);
-
-  cs4231_chip->status |= CS_STATUS_INTS_ON;
+        tprintk(("enabling interrupts\n"));
+        save_flags(flags);
+        cli();
+        if ((cs4231_chip->status & CS_STATUS_INTS_ON) == 0) {
+                WRITE_IAR(0xa);
+                WRITE_IDR(INTR_ON);
+                cs4231_chip->status |= CS_STATUS_INTS_ON;
+        }
+        restore_flags(flags);
 }
 
 /* Disable cs4231 interrupts atomically. */
-static __inline__ void cs4231_disable_interrupts(struct sparcaudio_driver *drv)
+static void cs4231_disable_interrupts(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  register unsigned long flags;
-
-  if (!(cs4231_chip->status & CS_STATUS_INTS_ON))
-    return;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        unsigned long flags;
 
-  tprintk(("disabling interrupts\n"));
-  save_flags(flags);
-  cli();
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0xa);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), INTR_OFF);
-  restore_flags(flags);
-
-  cs4231_chip->status &= ~CS_STATUS_INTS_ON;
+        tprintk(("disabling interrupts\n"));
+        save_flags(flags);
+        cli();
+        if ((cs4231_chip->status & CS_STATUS_INTS_ON) != 0) {
+                WRITE_IAR(0xa);
+                WRITE_IDR(INTR_OFF);
+                cs4231_chip->status &= ~CS_STATUS_INTS_ON;
+        }
+        restore_flags(flags);
 }
 
-static __inline__ void cs4231_enable_play(struct sparcaudio_driver *drv)
+static void cs4231_enable_play(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  register unsigned long flags;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        unsigned long flags;
 
-  tprintk(("enabling play\n"));
-  save_flags(flags);
-  cli();
-  
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x9);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | PEN_ENABLE));
-  restore_flags(flags);
+        tprintk(("enabling play\n"));
+        save_flags(flags);
+        cli();
+        WRITE_IAR(0x9);
+        WRITE_IDR(READ_IDR() | PEN_ENABLE);
+        restore_flags(flags);
 }
 
-static __inline__ void cs4231_disable_play(struct sparcaudio_driver *drv)
+static void cs4231_disable_play(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  register unsigned long flags;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        unsigned long flags;
 
-  tprintk(("disabling play\n"));
-  save_flags(flags);
-  cli();
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x9);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & PEN_DISABLE));
-  restore_flags(flags);
+        tprintk(("disabling play\n"));
+        save_flags(flags);
+        cli();
+        WRITE_IAR(0x9);
+        WRITE_IDR(READ_IDR() & PEN_DISABLE);
+        restore_flags(flags);
 }
 
-static __inline__ void cs4231_enable_rec(struct sparcaudio_driver *drv)
+static void cs4231_enable_rec(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  register unsigned long flags;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        unsigned long flags;
 
-  tprintk(("enabling rec\n"));
-  save_flags(flags);
-  cli();
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x9);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | CEN_ENABLE));
-  restore_flags(flags);
+        tprintk(("enabling rec\n"));
+        save_flags(flags);
+        cli();
+        WRITE_IAR(0x9);
+        WRITE_IDR(READ_IDR() | CEN_ENABLE);
+        restore_flags(flags);
 }
 
-static __inline__ void cs4231_disable_rec(struct sparcaudio_driver *drv)
+static void cs4231_disable_rec(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  register unsigned long flags;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        unsigned long flags;
 
-  tprintk(("disabling rec\n"));
-  save_flags(flags);
-  cli();
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x9);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & CEN_DISABLE));
-  restore_flags(flags);
+        tprintk(("disabling rec\n"));
+        save_flags(flags);
+        cli();
+        WRITE_IAR(0x9);
+        WRITE_IDR(READ_IDR() & CEN_DISABLE);
+        restore_flags(flags);
 }
 
 static struct cs4231_rates {
-  int speed, bits;
+        int speed, bits;
 } cs4231_rate_table[] = {
-  { 5512, CS4231_DFR_5512 },
-  { 6615, CS4231_DFR_6615 },
-  { 8000, CS4231_DFR_8000 },
-  { 9600, CS4231_DFR_9600 },
-  { 11025, CS4231_DFR_11025 },
-  { 16000, CS4231_DFR_16000 },
-  { 18900, CS4231_DFR_18900 },
-  { 22050, CS4231_DFR_22050 },
-  { 27429, CS4231_DFR_27429 },
-  { 32000, CS4231_DFR_32000 },
-  { 33075, CS4231_DFR_33075 },
-  { 37800, CS4231_DFR_37800 },
-  { 44100, CS4231_DFR_44100 },
-  { 48000, CS4231_DFR_48000 }
+        { 5512, CS4231_DFR_5512 },
+        { 6615, CS4231_DFR_6615 },
+        { 8000, CS4231_DFR_8000 },
+        { 9600, CS4231_DFR_9600 },
+        { 11025, CS4231_DFR_11025 },
+        { 16000, CS4231_DFR_16000 },
+        { 18900, CS4231_DFR_18900 },
+        { 22050, CS4231_DFR_22050 },
+        { 27429, CS4231_DFR_27429 },
+        { 32000, CS4231_DFR_32000 },
+        { 33075, CS4231_DFR_33075 },
+        { 37800, CS4231_DFR_37800 },
+        { 44100, CS4231_DFR_44100 },
+        { 48000, CS4231_DFR_48000 }
 };
 
 #define NUM_RATES	(sizeof(cs4231_rate_table) / sizeof(struct cs4231_rates))
 
-static int 
-cs4231_rate_to_bits(struct sparcaudio_driver *drv, int *value)
-{
-  struct cs4231_rates *p = &cs4231_rate_table[0];
-  int i, wanted = *value;
-
-  /* We try to be nice and approximate what the user asks for. */
-  if(wanted < 5512)
-    wanted = 5512;
-  if(wanted > 48000)
-    wanted = 48000;
-
-  for(i = 0; i < NUM_RATES; i++, p++) {
-    /* Exact match? */
-    if(wanted == p->speed)
-      break;
-
-    /* If we're inbetween two entries, and neither is exact,
-     * pick the closest one.
-     */
-    if(wanted == p[1].speed)
-      continue;
-    if(wanted > p->speed &&
-       wanted < p[1].speed) {
-      int diff1, diff2;
-
-      diff1 = wanted - p->speed;
-      diff2 = p[1].speed - wanted;
-      if(diff2 < diff1)
-        p++;
-      break;
-    }
-  }
-  *value = p->speed;
-  return p->bits;
-}
-
-static int 
-cs4231_encoding_to_bits(struct sparcaudio_driver *drv, int value)
-{
-  int set_bits;
-  
-  switch (value) {
-  case AUDIO_ENCODING_ULAW:
-    set_bits = CS4231_DFR_ULAW;
-    break;
-  case AUDIO_ENCODING_ALAW:
-    set_bits = CS4231_DFR_ALAW;
-    break;
-  case AUDIO_ENCODING_DVI:
-    set_bits = CS4231_DFR_ADPCM;
-    break;
-  case AUDIO_ENCODING_LINEARLE:
-    set_bits = CS4231_DFR_LINEARLE;
-    break;
-  case AUDIO_ENCODING_LINEAR:
-    set_bits = CS4231_DFR_LINEARBE;
-    break;
-  case AUDIO_ENCODING_LINEAR8:
-    set_bits = CS4231_DFR_LINEAR8;
-    break;
-  default:
-    set_bits = -(EINVAL);
-    break;
-  }
-  
-  return set_bits;
-}
-
-static int
-cs4231_set_output_encoding(struct sparcaudio_driver *drv, int value)
+static int cs4231_rate_to_bits(struct sparcaudio_driver *drv, int *value)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int tmp_bits, set_bits;
+        struct cs4231_rates *p = &cs4231_rate_table[0];
+        int i, wanted = *value;
 
-  tprintk(("output encoding %d\n", value));
-  if (value != 0) {
-    set_bits = cs4231_encoding_to_bits(drv, value);
-    if (set_bits >= 0) {
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-        CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x8);
-        tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-        CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                      CHANGE_ENCODING(tmp_bits, set_bits));
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-    
-        CHIP_READY
-
-        cs4231_chip->perchip_info.play.encoding = value;
-        return 0;
-    }
-  }
-  dprintk(("output enc failed\n"));
-  return -EINVAL;
+        /* We try to be nice and approximate what the user asks for. */
+        if (wanted < 5512)
+                wanted = 5512;
+        if (wanted > 48000)
+                wanted = 48000;
+
+        for (i = 0; i < NUM_RATES; i++, p++) {
+                /* Exact match? */
+                if (wanted == p->speed)
+                        break;
+
+                /* If we're inbetween two entries, and neither is exact,
+                 * pick the closest one.
+                 */
+                if (wanted == p[1].speed)
+                        continue;
+                if (wanted > p->speed && wanted < p[1].speed) {
+                        int diff1, diff2;
+
+                        diff1 = wanted - p->speed;
+                        diff2 = p[1].speed - wanted;
+                        if (diff2 < diff1)
+                                p++;
+                        break;
+                }
+        }
+        *value = p->speed;
+        return p->bits;
+}
+
+static int cs4231_encoding_to_bits(struct sparcaudio_driver *drv, int value)
+{
+        int set_bits;
+  
+        switch (value) {
+        case AUDIO_ENCODING_ULAW:
+                set_bits = CS4231_DFR_ULAW;
+                break;
+        case AUDIO_ENCODING_ALAW:
+                set_bits = CS4231_DFR_ALAW;
+                break;
+        case AUDIO_ENCODING_DVI:
+                set_bits = CS4231_DFR_ADPCM;
+                break;
+        case AUDIO_ENCODING_LINEARLE:
+                set_bits = CS4231_DFR_LINEARLE;
+                break;
+        case AUDIO_ENCODING_LINEAR:
+                set_bits = CS4231_DFR_LINEARBE;
+                break;
+        case AUDIO_ENCODING_LINEAR8:
+                set_bits = CS4231_DFR_LINEAR8;
+                break;
+        default:
+                set_bits = -EINVAL;
+                break;
+        };
+  
+        return set_bits;
+}
+
+static int cs4231_set_output_encoding(struct sparcaudio_driver *drv, int value)
+{
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int tmp_bits, set_bits;
+
+        tprintk(("output encoding %d\n", value));
+        if (value != 0) {
+                set_bits = cs4231_encoding_to_bits(drv, value);
+                if (set_bits >= 0) {
+                        READ_IDR();
+                        READ_IDR();
+                        WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x8);
+                        tmp_bits = READ_IDR();
+                        WRITE_IDR(CHANGE_ENCODING(tmp_bits, set_bits));
+                        READ_IDR();
+                        READ_IDR();
+                        CHIP_READY();
+                        cs4231_chip->perchip_info.play.encoding = value;
+                        return 0;
+                }
+        }
+        dprintk(("output enc failed\n"));
+        return -EINVAL;
 }
 
 static int cs4231_get_output_encoding(struct sparcaudio_driver *drv)
 {
-      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
       return cs4231_chip->perchip_info.play.encoding;
 }
 
-static int
-cs4231_set_input_encoding(struct sparcaudio_driver *drv, int value)
+static int cs4231_set_input_encoding(struct sparcaudio_driver *drv, int value)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int tmp_bits, set_bits;
-
-  tprintk(("input encoding %d\n", value));
-  if (value != 0) {
-    set_bits = cs4231_encoding_to_bits(drv, value);
-    if (set_bits >= 0) {
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-        CS4231_READ8(cs4231_chip, &(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));
-        CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                      CHANGE_ENCODING(tmp_bits, set_bits));
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int tmp_bits, set_bits;
 
-        CHIP_READY
-
-        cs4231_chip->perchip_info.record.encoding = value;
-        return 0;
-    }
-  }
-  dprintk(("input enc failed\n"));
-  return -EINVAL;
+        tprintk(("input encoding %d\n", value));
+        if (value != 0) {
+                set_bits = cs4231_encoding_to_bits(drv, value);
+                if (set_bits >= 0) {
+                        READ_IDR();
+                        READ_IDR();
+                        WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x1c);
+                        tmp_bits = READ_IDR();
+                        WRITE_IDR(CHANGE_ENCODING(tmp_bits, set_bits));
+                        READ_IDR();
+                        READ_IDR();
+                        CHIP_READY();
+
+                        cs4231_chip->perchip_info.record.encoding = value;
+                        return 0;
+                }
+        }
+        dprintk(("input enc failed\n"));
+        return -EINVAL;
 }
 
 static int cs4231_get_input_encoding(struct sparcaudio_driver *drv)
 {
-      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
       return cs4231_chip->perchip_info.record.encoding;
 }
 
-static int
-cs4231_set_output_rate(struct sparcaudio_driver *drv, int value)
+static int cs4231_set_output_rate(struct sparcaudio_driver *drv, int value)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int tmp_bits, set_bits;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int tmp_bits, set_bits;
 
-  tprintk(("output rate %d\n", value));
-  if (value != 0) {
-    set_bits = cs4231_rate_to_bits(drv, &value);
-    if (set_bits >= 0) {
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-        CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x8);
-        tmp_bits = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-        CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                      CHANGE_DFR(tmp_bits, set_bits));
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-
-        CHIP_READY
-
-        cs4231_chip->perchip_info.play.sample_rate = value;
-        tprintk(("tmp_bits[%02x] set_bits[%02x] CHANGE_DFR[%02x]\n",
-                 tmp_bits, set_bits, CHANGE_DFR(tmp_bits, set_bits)));
-        return 0;
-    }
-  }
-  dprintk(("output rate failed\n"));
-  return -EINVAL;
+        tprintk(("output rate %d\n", value));
+        if (value != 0) {
+                set_bits = cs4231_rate_to_bits(drv, &value);
+                if (set_bits >= 0) {
+                        READ_IDR();
+                        READ_IDR();
+                        WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x8);
+                        tmp_bits = READ_IDR();
+                        WRITE_IDR(CHANGE_DFR(tmp_bits, set_bits));
+                        READ_IDR();
+                        READ_IDR();
+                        CHIP_READY();
+
+                        cs4231_chip->perchip_info.play.sample_rate = value;
+                        tprintk(("tmp_bits[%02x] set_bits[%02x] CHANGE_DFR[%02x]\n",
+                                 tmp_bits, set_bits, CHANGE_DFR(tmp_bits, set_bits)));
+                        return 0;
+                }
+        }
+        dprintk(("output rate failed\n"));
+        return -EINVAL;
 }
 
 static int cs4231_get_output_rate(struct sparcaudio_driver *drv)
 {
-      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
       return cs4231_chip->perchip_info.play.sample_rate;
 }
 
-static int
-cs4231_set_input_rate(struct sparcaudio_driver *drv, int value)
+static int cs4231_set_input_rate(struct sparcaudio_driver *drv, int value)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int tmp_bits, set_bits;
-
-  tprintk(("input rate %d\n", value));
-  if (value != 0) {
-    set_bits = cs4231_rate_to_bits(drv, &value);
-    if (set_bits >= 0) {
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-        CS4231_READ8(cs4231_chip, &(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));
-        CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                      CHANGE_DFR(tmp_bits, set_bits));
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-        CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-      
-        CHIP_READY
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int tmp_bits, set_bits;
 
-        cs4231_chip->perchip_info.record.sample_rate = value;
-        return 0;
-    }
-  }
-  dprintk(("input rate failed\n"));
-  return -EINVAL;
+        tprintk(("input rate %d\n", value));
+        if (value != 0) {
+                set_bits = cs4231_rate_to_bits(drv, &value);
+                if (set_bits >= 0) {
+                        READ_IDR();
+                        READ_IDR();
+                        WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x1c);
+                        tmp_bits = READ_IDR();
+                        WRITE_IDR(CHANGE_DFR(tmp_bits, set_bits));
+                        READ_IDR();
+                        READ_IDR();
+                        CHIP_READY();
+
+                        cs4231_chip->perchip_info.record.sample_rate = value;
+                        return 0;
+                }
+        }
+        dprintk(("input rate failed\n"));
+        return -EINVAL;
 }
 
 static int cs4231_get_input_rate(struct sparcaudio_driver *drv)
 {
-      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
       return cs4231_chip->perchip_info.record.sample_rate;
 }
 
 /* Generically we support 4 channels. This hardware does 2 */
-static int
-cs4231_set_input_channels(struct sparcaudio_driver *drv, int value)
+static int cs4231_set_input_channels(struct sparcaudio_driver *drv, int value)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int tmp_bits;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int tmp_bits;
 
-  tprintk(("input channels %d\n", value));
-  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));
-      break;
-  case 2:
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), CS4231_STEREO_ON(tmp_bits));
-      break;
-  default:
-      dprintk(("input chan failed\n"));
-      return -(EINVAL);
-  }  
+        tprintk(("input channels %d\n", value));
+        WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x1c);
+        tmp_bits = READ_IDR();
+        switch (value) {
+        case 1:
+                WRITE_IDR(CS4231_MONO_ON(tmp_bits));
+                break;
+        case 2:
+                WRITE_IDR(CS4231_STEREO_ON(tmp_bits));
+                break;
+        default:
+                dprintk(("input chan failed\n"));
+                return -EINVAL;
+        };
+        CHIP_READY();
 
-  CHIP_READY
-
-  cs4231_chip->perchip_info.record.channels = value;
-  return 0;
+        cs4231_chip->perchip_info.record.channels = value;
+        return 0;
 }
 
 static int cs4231_get_input_channels(struct sparcaudio_driver *drv)
 {
-      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
       return cs4231_chip->perchip_info.record.channels;
 }
 
 /* Generically we support 4 channels. This hardware does 2 */
-static int
-cs4231_set_output_channels(struct sparcaudio_driver *drv, int value)
+static int cs4231_set_output_channels(struct sparcaudio_driver *drv, int value)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int tmp_bits;
-
-  tprintk(("output channels %d\n", value));
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x8);
-  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));
-      break;
-  case 2:
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), CS4231_STEREO_ON(tmp_bits));
-      break;
-  default:
-      dprintk(("output chan failed\n"));
-      return -(EINVAL);
-  }  
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int tmp_bits;
 
-  CHIP_READY
+        tprintk(("output channels %d\n", value));
+        WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x8);
+        tmp_bits = READ_IDR();
+        switch (value) {
+        case 1:
+                WRITE_IDR(CS4231_MONO_ON(tmp_bits));
+                break;
+        case 2:
+                WRITE_IDR(CS4231_STEREO_ON(tmp_bits));
+                break;
+        default:
+                dprintk(("output chan failed\n"));
+                return -EINVAL;
+        };
+        CHIP_READY();
     
-  cs4231_chip->perchip_info.play.channels = value;
-  return 0;
+	cs4231_chip->perchip_info.play.channels = value;
+        return 0;
 }
 
 static int cs4231_get_output_channels(struct sparcaudio_driver *drv)
 {
-      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
       return cs4231_chip->perchip_info.play.channels;
 }
 
 static int cs4231_get_input_precision(struct sparcaudio_driver *drv)
 {
-      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
       return cs4231_chip->perchip_info.record.precision;
 }
 
 static int cs4231_get_output_precision(struct sparcaudio_driver *drv)
 {
-      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
       return cs4231_chip->perchip_info.play.precision;
 }
 
 static int cs4231_set_input_precision(struct sparcaudio_driver *drv, int val)
 {
-      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
       cs4231_chip->perchip_info.record.precision = val;
 
@@ -504,7 +485,7 @@
 
 static int cs4231_set_output_precision(struct sparcaudio_driver *drv, int val)
 {
-      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private; 
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private; 
 
       cs4231_chip->perchip_info.play.precision = val;
 
@@ -512,253 +493,238 @@
 }
 
 /* Wait until the auto calibration process has finished */
-static void
-cs4231_ready(struct sparcaudio_driver *drv) 
+static void cs4231_ready(struct sparcaudio_driver *drv) 
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  unsigned int x = 0;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        unsigned int x;
 
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_END);
-  while (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) == IAR_NOT_READY &&
-         x <= CS_TIMEOUT) {
-    x++;
-  }
-
-  x = 0;
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0b);
-  while (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) == AUTOCAL_IN_PROGRESS &&
-         x <= CS_TIMEOUT) {
-    x++;
-  }
+        WRITE_IAR(IAR_AUTOCAL_END);
+        x = 0;
+        do {
+                if (READ_IDR() != IAR_NOT_READY)
+                        break;
+                x++;
+        } while (x <= CS_TIMEOUT);
+
+        WRITE_IAR(0x0b);
+        x = 0;
+        do {
+                if (READ_IDR() != AUTOCAL_IN_PROGRESS)
+                        break;
+                x++;
+        } while (x <= CS_TIMEOUT);
 }
 
 /* Set output mute */
 static int cs4231_output_muted(struct sparcaudio_driver *drv, int value)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  tprintk(("in cs4231_output_muted: %d\n", value));
-  if (!value) {
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x7);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & OUTCR_UNMUTE));
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x6);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & OUTCR_UNMUTE));
-      cs4231_chip->perchip_info.output_muted = 0;
-  } else {
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x7);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | OUTCR_MUTE));
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x6);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | OUTCR_MUTE));
-      cs4231_chip->perchip_info.output_muted = 1;
-  }
-  return 0;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        tprintk(("in cs4231_output_muted: %d\n", value));
+        if (!value) {
+                WRITE_IAR(0x7);
+                WRITE_IDR(READ_IDR() & OUTCR_UNMUTE);
+                WRITE_IAR(0x6);
+                WRITE_IDR(READ_IDR() & OUTCR_UNMUTE);
+                cs4231_chip->perchip_info.output_muted = 0;
+        } else {
+                WRITE_IAR(0x7);
+                WRITE_IDR(READ_IDR() | OUTCR_MUTE);
+                WRITE_IAR(0x6);
+                WRITE_IDR(READ_IDR() | OUTCR_MUTE);
+                cs4231_chip->perchip_info.output_muted = 1;
+        }
+        return 0;
 }
 
 static int cs4231_get_output_muted(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  return cs4231_chip->perchip_info.output_muted;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        return cs4231_chip->perchip_info.output_muted;
 }
 
 static int cs4231_get_formats(struct sparcaudio_driver *drv)
 {
-      return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_U8 | AFMT_IMA_ADPCM | 
-              AFMT_S16_LE | AFMT_S16_BE);
+        return (AFMT_MU_LAW | AFMT_A_LAW |
+                AFMT_U8 | AFMT_IMA_ADPCM | 
+                AFMT_S16_LE | AFMT_S16_BE);
 }
 
 static int cs4231_get_output_ports(struct sparcaudio_driver *drv)
 {
-      return (AUDIO_LINE_OUT | AUDIO_SPEAKER | AUDIO_HEADPHONE);
+        return (AUDIO_LINE_OUT | AUDIO_SPEAKER | AUDIO_HEADPHONE);
 }
 
 static int cs4231_get_input_ports(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-  /* This apparently applies only to APC ultras, not ebus ultras */
-  if (cs4231_chip->status & CS_STATUS_IS_ULTRA)
-    return (AUDIO_LINE_IN | AUDIO_MICROPHONE | AUDIO_ANALOG_LOOPBACK);
-  else
-    return (AUDIO_INTERNAL_CD_IN | AUDIO_LINE_IN | AUDIO_MICROPHONE | 
-	    AUDIO_ANALOG_LOOPBACK);
+        /* This apparently applies only to APC ultras, not ebus ultras */
+        if (cs4231_chip->status & CS_STATUS_IS_ULTRA)
+                return (AUDIO_LINE_IN | AUDIO_MICROPHONE | AUDIO_ANALOG_LOOPBACK);
+        else
+                return (AUDIO_INTERNAL_CD_IN | AUDIO_LINE_IN |
+                        AUDIO_MICROPHONE | AUDIO_ANALOG_LOOPBACK);
 }
 
 /* Set chip "output" port */
 static int cs4231_set_output_port(struct sparcaudio_driver *drv, int value)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int retval = 0;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int retval = 0;
 
-  tprintk(("output port: %d\n", value));
-  /* Aaaaaah! It's all coming so fast! Turn it all off, then selectively
-   * enable things.
-   */
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1a);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | MONO_IOCR_MUTE));
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0a);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | PINCR_LINE_MUTE));
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) | PINCR_HDPH_MUTE));
-
-  if (value & AUDIO_SPEAKER) {
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1a);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & ~MONO_IOCR_MUTE));
-      retval |= AUDIO_SPEAKER;
-  }
-
-  if (value & AUDIO_HEADPHONE) {
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0a);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & ~PINCR_HDPH_MUTE));
-      retval |= AUDIO_HEADPHONE;
-  }
-
-  if (value & AUDIO_LINE_OUT) {
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0a);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & ~PINCR_LINE_MUTE));
-      retval |= AUDIO_LINE_OUT;
-  }
+        tprintk(("output port: %d\n", value));
+        /* Aaaaaah! It's all coming so fast! Turn it all off, then selectively
+         * enable things.
+         */
+        WRITE_IAR(0x1a);
+        WRITE_IDR(READ_IDR() | MONO_IOCR_MUTE);
+        WRITE_IAR(0x0a);
+        WRITE_IDR(READ_IDR() | PINCR_LINE_MUTE);
+        WRITE_IDR(READ_IDR() | PINCR_HDPH_MUTE);
+
+        if (value & AUDIO_SPEAKER) {
+                WRITE_IAR(0x1a);
+                WRITE_IDR(READ_IDR() & ~MONO_IOCR_MUTE);
+                retval |= AUDIO_SPEAKER;
+        }
+
+        if (value & AUDIO_HEADPHONE) {
+                WRITE_IAR(0x0a);
+                WRITE_IDR(READ_IDR() & ~PINCR_HDPH_MUTE);
+                retval |= AUDIO_HEADPHONE;
+        }
+
+        if (value & AUDIO_LINE_OUT) {
+                WRITE_IAR(0x0a);
+                WRITE_IDR(READ_IDR() & ~PINCR_LINE_MUTE);
+                retval |= AUDIO_LINE_OUT;
+        }
   
-  cs4231_chip->perchip_info.play.port = retval;
+        cs4231_chip->perchip_info.play.port = retval;
 
-  return (retval);
+        return (retval);
 }
 
 static int cs4231_get_output_port(struct sparcaudio_driver *drv)
 {
-      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-      return cs4231_chip->perchip_info.play.port;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        return cs4231_chip->perchip_info.play.port;
 }
 
 /* Set chip "input" port */
 static int cs4231_set_input_port(struct sparcaudio_driver *drv, int value)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int retval = 0;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int retval = 0;
 
-  tprintk(("input port: %d\n", value));
+        tprintk(("input port: %d\n", value));
 
-  /* You can have one and only one. This is probably wrong, but
-   * appears to be how SunOS is doing it. Should be able to mix.
-   * More work to be done. CD input mixable, analog loopback may be.
-   */
-
-  /* Ultra systems do not support AUDIO_INTERNAL_CD_IN */
-  /* This apparently applies only to APC ultras, not ebus ultras */
-  if (!(cs4231_chip->status & CS_STATUS_IS_ULTRA)) {
-    if (value & AUDIO_INTERNAL_CD_IN) {
-        CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1);
-        CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                      CDROM_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr))));
-        CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0);
-        CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                      CDROM_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr))));
-        retval = AUDIO_INTERNAL_CD_IN;
-    }
-  }
-  if ((value & AUDIO_LINE_IN)) {
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    LINE_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr))));
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    LINE_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr))));
-      retval = AUDIO_LINE_IN;
-  } else if (value & AUDIO_MICROPHONE) {
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    MIC_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr))));
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    MIC_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr))));
-      retval = AUDIO_MICROPHONE;
-  } else if (value & AUDIO_ANALOG_LOOPBACK) {
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    OUTPUTLOOP_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr))));
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0);
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                    OUTPUTLOOP_ENABLE(CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr))));
-      retval = AUDIO_ANALOG_LOOPBACK;
-  }
+        /* You can have one and only one. This is probably wrong, but
+         * appears to be how SunOS is doing it. Should be able to mix.
+         * More work to be done. CD input mixable, analog loopback may be.
+         */
+
+        /* Ultra systems do not support AUDIO_INTERNAL_CD_IN */
+        /* This apparently applies only to APC ultras, not ebus ultras */
+        if (!(cs4231_chip->status & CS_STATUS_IS_ULTRA)) {
+                if (value & AUDIO_INTERNAL_CD_IN) {
+                        WRITE_IAR(0x1);
+                        WRITE_IDR(CDROM_ENABLE(READ_IDR()));
+                        WRITE_IAR(0x0);
+                        WRITE_IDR(CDROM_ENABLE(READ_IDR()));
+                        retval = AUDIO_INTERNAL_CD_IN;
+                }
+        }
+        if ((value & AUDIO_LINE_IN)) {
+                WRITE_IAR(0x1);
+                WRITE_IDR(LINE_ENABLE(READ_IDR()));
+                WRITE_IAR(0x0);
+                WRITE_IDR(LINE_ENABLE(READ_IDR()));
+                retval = AUDIO_LINE_IN;
+        } else if (value & AUDIO_MICROPHONE) {
+                WRITE_IAR(0x1);
+                WRITE_IDR(MIC_ENABLE(READ_IDR()));
+                WRITE_IAR(0x0);
+                WRITE_IDR(MIC_ENABLE(READ_IDR()));
+                retval = AUDIO_MICROPHONE;
+        } else if (value & AUDIO_ANALOG_LOOPBACK) {
+                WRITE_IAR(0x1);
+                WRITE_IDR(OUTPUTLOOP_ENABLE(READ_IDR()));
+                WRITE_IAR(0x0);
+                WRITE_IDR(OUTPUTLOOP_ENABLE(READ_IDR()));
+                retval = AUDIO_ANALOG_LOOPBACK;
+        }
 
-  cs4231_chip->perchip_info.record.port = retval;
+        cs4231_chip->perchip_info.record.port = retval;
 
-  return (retval);
+        return retval;
 }
 
 static int cs4231_get_input_port(struct sparcaudio_driver *drv)
 {
-      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-      return cs4231_chip->perchip_info.record.port;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        return cs4231_chip->perchip_info.record.port;
 }
 
 /* Set chip "monitor" gain */
 static int cs4231_set_monitor_volume(struct sparcaudio_driver *drv, int value)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int a = 0;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int a = 0;
 
-  tprintk(("monitor gain: %d\n", value));
+        tprintk(("monitor gain: %d\n", value));
 
-  /* This interpolation really sucks. The question is, be compatible 
-   * with ScumOS/Sloaris or not?
-   */
-  a = CS4231_MON_MAX_ATEN - (value * (CS4231_MON_MAX_ATEN + 1) / 
-                             (AUDIO_MAX_GAIN + 1));
-
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0d);
-  if (a >= CS4231_MON_MAX_ATEN) 
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), LOOPB_OFF);
-  else 
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), ((a << 2) | LOOPB_ON));
-
-  if (value == AUDIO_MAX_GAIN) 
-    CS4231_WRITE8(cs4231_chip, &(cs4231_chip->perchip_info.monitor_gain), AUDIO_MAX_GAIN);
-  else 
-    CS4231_WRITE8(cs4231_chip, &(cs4231_chip->perchip_info.monitor_gain),
-                  ((CS4231_MAX_DEV_ATEN - a) * 
-                   (AUDIO_MAX_GAIN + 1) / 
-                   (CS4231_MAX_DEV_ATEN + 1)));
+        /* This interpolation really sucks. The question is, be compatible 
+         * with ScumOS/Sloaris or not?
+         */
+        a = CS4231_MON_MAX_ATEN - (value * (CS4231_MON_MAX_ATEN + 1) / 
+                                   (AUDIO_MAX_GAIN + 1));
+
+        WRITE_IAR(0x0d);
+        if (a >= CS4231_MON_MAX_ATEN) 
+                WRITE_IDR(LOOPB_OFF);
+        else 
+                WRITE_IDR((a << 2) | LOOPB_ON);
+
+        if (value == AUDIO_MAX_GAIN) 
+                cs4231_chip->perchip_info.monitor_gain = AUDIO_MAX_GAIN;
+        else 
+                cs4231_chip->perchip_info.monitor_gain =
+                        ((CS4231_MAX_DEV_ATEN - a) * 
+                         (AUDIO_MAX_GAIN + 1) / 
+                         (CS4231_MAX_DEV_ATEN + 1));
 
-  return 0;
+        return 0;
 }
 
 static int cs4231_get_monitor_volume(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-        return (int)cs4231_chip->perchip_info.monitor_gain;
+        return (int) cs4231_chip->perchip_info.monitor_gain;
 }
 
 static int cs4231_get_output_error(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-        return (int)cs4231_chip->perchip_info.play.error;
+        return (int) cs4231_chip->perchip_info.play.error;
 }
 
 static int cs4231_get_input_error(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-        return (int)cs4231_chip->perchip_info.record.error;
+        return (int) cs4231_chip->perchip_info.record.error;
 }
 
 #ifdef EB4231_SUPPORT
 static int eb4231_get_output_samples(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-        int count = 
-          cs4231_length_to_samplecount(&cs4231_chip->perchip_info.play, 
-                                       readl(&cs4231_chip->eb2p->dbcr));
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 dbcr = readl(cs4231_chip->eb2p + EBDMA_COUNT);
+        int count =
+                cs4231_length_to_samplecount(&cs4231_chip->perchip_info.play, dbcr);
 
         return (cs4231_chip->perchip_info.play.samples - 
                 ((count > cs4231_chip->perchip_info.play.samples) 
@@ -767,10 +733,10 @@
 
 static int eb4231_get_input_samples(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-        int count = 
-          cs4231_length_to_samplecount(&cs4231_chip->perchip_info.record, 
-                                       readl(&cs4231_chip->eb2c->dbcr));
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 dbcr = readl(cs4231_chip->eb2c + EBDMA_COUNT);
+        int count =
+                cs4231_length_to_samplecount(&cs4231_chip->perchip_info.record, dbcr);
 
         return (cs4231_chip->perchip_info.record.samples - 
                 ((count > cs4231_chip->perchip_info.record.samples) ?
@@ -780,10 +746,10 @@
 
 static int cs4231_get_output_samples(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 dmapc = sbus_readl(cs4231_chip->regs + APCPC);
         int count = 
-          cs4231_length_to_samplecount(&cs4231_chip->perchip_info.play, 
-                                       cs4231_chip->regs->dmapc);
+          cs4231_length_to_samplecount(&cs4231_chip->perchip_info.play, dmapc);
 
         return (cs4231_chip->perchip_info.play.samples - 
                 ((count > cs4231_chip->perchip_info.play.samples) 
@@ -792,10 +758,10 @@
 
 static int cs4231_get_input_samples(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 dmacc = sbus_readl(cs4231_chip->regs + APCCC);
         int count = 
-          cs4231_length_to_samplecount(&cs4231_chip->perchip_info.record, 
-                                       cs4231_chip->regs->dmacc);
+          cs4231_length_to_samplecount(&cs4231_chip->perchip_info.record, dmacc);
 
         return (cs4231_chip->perchip_info.record.samples - 
                 ((count > cs4231_chip->perchip_info.record.samples) ?
@@ -804,23 +770,24 @@
 
 static int cs4231_get_output_pause(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-        return (int)cs4231_chip->perchip_info.play.pause;
+        return (int) cs4231_chip->perchip_info.play.pause;
 }
 
 static int cs4231_get_input_pause(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-        return (int)cs4231_chip->perchip_info.record.pause;
+        return (int) cs4231_chip->perchip_info.record.pause;
 }
 
 /* But for play/record we have these cheesy jacket routines because of 
- * how this crap gets set */
+ * how this crap gets set.
+ */
 static int cs4231_set_input_volume(struct sparcaudio_driver *drv, int value)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
 	cs4231_record_gain(drv, value, 
                            cs4231_chip->perchip_info.record.balance);
@@ -830,14 +797,14 @@
 
 static int cs4231_get_input_volume(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-        return (int)cs4231_chip->perchip_info.record.gain;
+        return (int) cs4231_chip->perchip_info.record.gain;
 }
 
 static int cs4231_set_output_volume(struct sparcaudio_driver *drv, int value)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
 	cs4231_play_gain(drv, value, cs4231_chip->perchip_info.play.balance);
 	
@@ -846,7 +813,7 @@
 
 static int cs4231_get_output_volume(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
         return cs4231_chip->perchip_info.play.gain;
 }
@@ -854,7 +821,7 @@
 /* Likewise for balance */
 static int cs4231_set_input_balance(struct sparcaudio_driver *drv, int value)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
 	cs4231_chip->perchip_info.record.balance = value;
 	cs4231_record_gain(drv, cs4231_chip->perchip_info.record.gain, 
@@ -865,14 +832,14 @@
 
 static int cs4231_get_input_balance(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-        return (int)cs4231_chip->perchip_info.record.balance;
+        return (int) cs4231_chip->perchip_info.record.balance;
 }
 
 static int cs4231_set_output_balance(struct sparcaudio_driver *drv, int value)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
 	cs4231_chip->perchip_info.play.balance = value;
 	cs4231_play_gain(drv, cs4231_chip->perchip_info.play.gain, 
@@ -883,561 +850,602 @@
 
 static int cs4231_get_output_balance(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-        return (int)cs4231_chip->perchip_info.play.balance;
+        return (int) cs4231_chip->perchip_info.play.balance;
 }
 
 /* Set chip record gain */
-static int cs4231_record_gain(struct sparcaudio_driver *drv, int value, unsigned char balance)
+static int cs4231_record_gain(struct sparcaudio_driver *drv, int value,
+                              unsigned char balance)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int tmp = 0, r, l, r_adj, l_adj;
-  unsigned char old_gain;
-
-  r = l = value;
-
-  if (balance < AUDIO_MID_BALANCE) {
-    r = (int)(value - ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT));
-    if (r < 0) r = 0;
-  } else if (balance > AUDIO_MID_BALANCE) {
-    l = (int)(value - ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT));
-    if (l < 0) l = 0;
-  }
-
-  l_adj = l * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1);
-  r_adj = r * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1);
-  
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0);
-  old_gain = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), RECGAIN_SET(old_gain, l_adj));
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x1);
-  old_gain = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), RECGAIN_SET(old_gain, r_adj));
-  
-  if (l == value) {
-    (l == 0) ? (tmp = 0) : (tmp = ((l_adj + 1) * AUDIO_MAX_GAIN) / 
-                            (CS4231_MAX_GAIN + 1));
-  } else if (r == value) {
-    (r == 0) ? (tmp = 0) : (tmp = ((r_adj + 1) * AUDIO_MAX_GAIN) / 
-                            (CS4231_MAX_GAIN + 1));
-  }
-  cs4231_chip->perchip_info.record.gain = tmp;
-  return 0;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int tmp = 0, r, l, r_adj, l_adj;
+        unsigned char old_gain;
+
+        r = l = value;
+
+        if (balance < AUDIO_MID_BALANCE) {
+                r = (int) (value -
+                           ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT));
+
+                if (r < 0)
+                        r = 0;
+        } else if (balance > AUDIO_MID_BALANCE) {
+                l = (int) (value -
+                           ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT));
+
+                if (l < 0)
+                        l = 0;
+        }
+
+        l_adj = l * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1);
+        r_adj = r * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1);
+  
+        WRITE_IAR(0x0);
+        old_gain = READ_IDR();
+        WRITE_IDR(RECGAIN_SET(old_gain, l_adj));
+        WRITE_IAR(0x1);
+        old_gain = READ_IDR();
+        WRITE_IDR(RECGAIN_SET(old_gain, r_adj));
+  
+        if (l == value) {
+                (l == 0) ? (tmp = 0) : (tmp = ((l_adj + 1) * AUDIO_MAX_GAIN) / 
+                                        (CS4231_MAX_GAIN + 1));
+        } else if (r == value) {
+                (r == 0) ? (tmp = 0) : (tmp = ((r_adj + 1) * AUDIO_MAX_GAIN) / 
+                                        (CS4231_MAX_GAIN + 1));
+        }
+        cs4231_chip->perchip_info.record.gain = tmp;
+        return 0;
 }
 
 /* Set chip play gain */
-static int cs4231_play_gain(struct sparcaudio_driver *drv, int value, unsigned char balance)
+static int cs4231_play_gain(struct sparcaudio_driver *drv, int value,
+                            unsigned char balance)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int tmp = 0, r, l, r_adj, l_adj;
-  unsigned char old_gain;
-
-  tprintk(("in play_gain: %d %c\n", value, balance));
-  r = l = value;
-  if (balance < AUDIO_MID_BALANCE) {
-    r = (int)(value - ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT));
-    if (r < 0) r = 0;
-  } else if (balance > AUDIO_MID_BALANCE) {
-    l = (int)(value - ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT));
-    if (l < 0) l = 0;
-  }
-
-  (l == 0) ? (l_adj = CS4231_MAX_DEV_ATEN) : (l_adj = CS4231_MAX_ATEN - 
-                                              (l * (CS4231_MAX_ATEN + 1) / 
-                                               (AUDIO_MAX_GAIN + 1)));
-  (r == 0) ? (r_adj = CS4231_MAX_DEV_ATEN) : (r_adj = CS4231_MAX_ATEN -
-                                              (r * (CS4231_MAX_ATEN + 1) /
-                                               (AUDIO_MAX_GAIN + 1)));
-  
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x6);
-  old_gain = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), GAIN_SET(old_gain, l_adj));
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x7);
-  old_gain = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), GAIN_SET(old_gain, r_adj));
-  
-  if ((value == 0) || (value == AUDIO_MAX_GAIN)) {
-    tmp = value;
-  } else {
-    if (value == l)
-      tmp = ((CS4231_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / 
-             (CS4231_MAX_ATEN + 1));
-    else if (value == r)
-      tmp = ((CS4231_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / 
-             (CS4231_MAX_ATEN + 1));
-  }
-  cs4231_chip->perchip_info.play.gain = tmp;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int tmp = 0, r, l, r_adj, l_adj;
+        unsigned char old_gain;
+
+        tprintk(("in play_gain: %d %c\n", value, balance));
+        r = l = value;
+        if (balance < AUDIO_MID_BALANCE) {
+                r = (int) (value -
+                           ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT));
+
+                if (r < 0)
+                        r = 0;
+        } else if (balance > AUDIO_MID_BALANCE) {
+                l = (int) (value -
+                           ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT));
+
+                if (l < 0)
+                        l = 0;
+        }
+
+        (l == 0) ? (l_adj = CS4231_MAX_DEV_ATEN) : (l_adj = CS4231_MAX_ATEN - 
+                                                    (l * (CS4231_MAX_ATEN + 1) / 
+                                                     (AUDIO_MAX_GAIN + 1)));
+        (r == 0) ? (r_adj = CS4231_MAX_DEV_ATEN) : (r_adj = CS4231_MAX_ATEN -
+                                                    (r * (CS4231_MAX_ATEN + 1) /
+                                                     (AUDIO_MAX_GAIN + 1)));
+  
+        WRITE_IAR(0x6);
+        old_gain = READ_IDR();
+        WRITE_IDR(GAIN_SET(old_gain, l_adj));
+        WRITE_IAR(0x7);
+        old_gain = READ_IDR();
+        WRITE_IDR(GAIN_SET(old_gain, r_adj));
+  
+        if ((value == 0) || (value == AUDIO_MAX_GAIN)) {
+                tmp = value;
+        } else {
+                if (value == l) {
+                        tmp = ((CS4231_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / 
+                               (CS4231_MAX_ATEN + 1));
+                } else if (value == r) {
+                        tmp = ((CS4231_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / 
+                               (CS4231_MAX_ATEN + 1));
+                }
+        }
+        cs4231_chip->perchip_info.play.gain = tmp;
 
-  return 0;
+        return 0;
 }
 
 /* Reset the audio chip to a sane state. */
 static void cs4231_chip_reset(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  unsigned char vers;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        unsigned char vers;
 
-  tprintk(("in cs4231_chip_reset\n"));
+        tprintk(("in cs4231_chip_reset\n"));
 
-  if (cs4231_chip->status & CS_STATUS_IS_EBUS) {
+        if (cs4231_chip->status & CS_STATUS_IS_EBUS) {
 #ifdef EB4231_SUPPORT
-    writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2p->dcsr));
-    writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2c->dcsr));
-    writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2p->dcsr));
-    writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2c->dcsr));
+                writel(EBUS_DCSR_RESET, cs4231_chip->eb2p + EBDMA_CSR);
+                writel(EBUS_DCSR_RESET, cs4231_chip->eb2c + EBDMA_CSR);
+                writel(EBUS_DCSR_BURST_SZ_16, cs4231_chip->eb2p + EBDMA_CSR);
+                writel(EBUS_DCSR_BURST_SZ_16, cs4231_chip->eb2c + EBDMA_CSR);
 #endif
-  } else {
-    cs4231_chip->regs->dmacsr = APC_CHIP_RESET;
-    cs4231_chip->regs->dmacsr = 0x00;
-    cs4231_chip->regs->dmacsr |= APC_CDC_RESET;
-  
-    udelay(20);
-  
-    cs4231_chip->regs->dmacsr &= ~(APC_CDC_RESET);
-  }
-
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar),
-                (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->iar)) | IAR_AUTOCAL_BEGIN));
-  
-  CHIP_READY
-    
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x0c);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), MISC_IR_MODE2);
-
-  /* This is the equivalent of DEFAULT_DATA_FMAT */
-  cs4231_set_input_encoding(drv, AUDIO_ENCODING_ULAW);
-  cs4231_set_input_rate(drv, CS4231_RATE);
-  cs4231_set_input_channels(drv, CS4231_CHANNELS);
-  cs4231_set_input_precision(drv, CS4231_PRECISION);
+        } else {
+                u32 tmp;
 
-  cs4231_set_output_encoding(drv, AUDIO_ENCODING_ULAW);
-  cs4231_set_output_rate(drv, CS4231_RATE);
-  cs4231_set_output_channels(drv, CS4231_CHANNELS);
-  cs4231_set_output_precision(drv, CS4231_PRECISION);
+                sbus_writel(APC_CHIP_RESET, cs4231_chip->regs + APCCSR);
+                sbus_writel(0x00, cs4231_chip->regs + APCCSR);
+                tmp = sbus_readl(cs4231_chip->regs + APCCSR);
+                tmp |= APC_CDC_RESET;
+                sbus_writel(tmp, cs4231_chip->regs + APCCSR);
+  
+                udelay(20);
+  
+                tmp = sbus_readl(cs4231_chip->regs + APCCSR);
+                tmp &= ~(APC_CDC_RESET);
+                sbus_writel(tmp, cs4231_chip->regs + APCCSR);
+        }
 
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x19);
+        WRITE_IAR(READ_IAR() | IAR_AUTOCAL_BEGIN);
+        CHIP_READY();
+    
+        WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x0c);
+        WRITE_IDR(MISC_IR_MODE2);
 
-  /* see what we can turn on */
-  vers = CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr));
-  if (vers & CS4231A) {
-    tprintk(("This is a CS4231A\n"));
-    cs4231_chip->status |= CS_STATUS_REV_A;
-  } else
-    cs4231_chip->status &= ~CS_STATUS_REV_A;
+        /* This is the equivalent of DEFAULT_DATA_FMAT */
+        cs4231_set_input_encoding(drv, AUDIO_ENCODING_ULAW);
+        cs4231_set_input_rate(drv, CS4231_RATE);
+        cs4231_set_input_channels(drv, CS4231_CHANNELS);
+        cs4231_set_input_precision(drv, CS4231_PRECISION);
+
+        cs4231_set_output_encoding(drv, AUDIO_ENCODING_ULAW);
+        cs4231_set_output_rate(drv, CS4231_RATE);
+        cs4231_set_output_channels(drv, CS4231_CHANNELS);
+        cs4231_set_output_precision(drv, CS4231_PRECISION);
+
+        WRITE_IAR(0x19);
+
+        /* see what we can turn on */
+        vers = READ_IDR();
+        if (vers & CS4231A) {
+                tprintk(("This is a CS4231A\n"));
+                cs4231_chip->status |= CS_STATUS_REV_A;
+        } else {
+                cs4231_chip->status &= ~CS_STATUS_REV_A;
+        }
   
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x10);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), OLB_ENABLE);
+        WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x10);
+        WRITE_IDR(OLB_ENABLE);
   
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x11);
-  if (cs4231_chip->status & CS_STATUS_REV_A)
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), (HPF_ON | XTALE_ON));
-  else
-      CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), HPF_ON);
+        WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x11);
+        if (cs4231_chip->status & CS_STATUS_REV_A)
+                WRITE_IDR(HPF_ON | XTALE_ON);
+        else
+                WRITE_IDR(HPF_ON);
   
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x1a);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), 0x00);
+        WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x1a);
+        WRITE_IDR(0x00);
   
-  /* Now set things up for defaults */
-  cs4231_set_input_balance(drv, AUDIO_MID_BALANCE);
-  cs4231_set_output_balance(drv, AUDIO_MID_BALANCE);
+        /* Now set things up for defaults */
+        cs4231_set_input_balance(drv, AUDIO_MID_BALANCE);
+        cs4231_set_output_balance(drv, AUDIO_MID_BALANCE);
 
-  cs4231_set_input_volume(drv, CS4231_DEFAULT_RECGAIN);
-  cs4231_set_output_volume(drv, CS4231_DEFAULT_PLAYGAIN);
+        cs4231_set_input_volume(drv, CS4231_DEFAULT_RECGAIN);
+        cs4231_set_output_volume(drv, CS4231_DEFAULT_PLAYGAIN);
 
-  cs4231_set_input_port(drv, AUDIO_MICROPHONE);
-  cs4231_set_output_port(drv, AUDIO_SPEAKER);
+        cs4231_set_input_port(drv, AUDIO_MICROPHONE);
+        cs4231_set_output_port(drv, AUDIO_SPEAKER);
 
-  cs4231_set_monitor_volume(drv, LOOPB_OFF);
+        cs4231_set_monitor_volume(drv, LOOPB_OFF);
   
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_END);
+        WRITE_IAR(IAR_AUTOCAL_END);
   
-  cs4231_ready(drv);
+        cs4231_ready(drv);
   
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_BEGIN | 0x09);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr),
-                (CS4231_READ8(cs4231_chip, &(cs4231_chip->regs->idr)) & ACAL_DISABLE));
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), IAR_AUTOCAL_END);
+        WRITE_IAR(IAR_AUTOCAL_BEGIN | 0x09);
+        WRITE_IDR(READ_IDR() & ACAL_DISABLE);
+        WRITE_IAR(IAR_AUTOCAL_END);
   
-  cs4231_ready(drv);
+        cs4231_ready(drv);
 
-  cs4231_output_muted(drv, 0);
+        cs4231_output_muted(drv, 0);
 
-  cs4231_chip->recording_count = 0;
-  cs4231_chip->input_next_dma_handle = 0;
-  cs4231_chip->input_dma_handle = 0;
-  cs4231_chip->input_next_dma_size = 0;
-  cs4231_chip->input_dma_size = 0;
+        cs4231_chip->recording_count = 0;
+        cs4231_chip->input_next_dma_handle = 0;
+        cs4231_chip->input_dma_handle = 0;
+        cs4231_chip->input_next_dma_size = 0;
+        cs4231_chip->input_dma_size = 0;
 
-  cs4231_chip->playing_count = 0;
-  cs4231_chip->output_next_dma_handle = 0;
-  cs4231_chip->output_dma_handle = 0;
-  cs4231_chip->output_next_dma_size = 0;
-  cs4231_chip->output_dma_size = 0;
+        cs4231_chip->playing_count = 0;
+        cs4231_chip->output_next_dma_handle = 0;
+        cs4231_chip->output_dma_handle = 0;
+        cs4231_chip->output_next_dma_size = 0;
+        cs4231_chip->output_dma_size = 0;
 }
 
-static int 
+static int
 cs4231_length_to_samplecount(struct audio_prinfo *thisdir, unsigned int length)
 {
-  unsigned int count;
+        unsigned int count;
 
-  if (thisdir->channels == 2)
-    count = (length/2);
-  else 
-    count = length;
-  
-  if (thisdir->encoding == AUDIO_ENCODING_LINEAR)
-    count = (count/2);
-  else if (thisdir->encoding == AUDIO_ENCODING_DVI)
-    count = (count/4);
+        if (thisdir->channels == 2)
+                count = (length / 2);
+        else 
+                count = length;
+  
+        if (thisdir->encoding == AUDIO_ENCODING_LINEAR)
+                count = (count / 2);
+        else if (thisdir->encoding == AUDIO_ENCODING_DVI)
+                count = (count / 4);
   
-  return count;
+        return count;
 }
 
 #ifdef EB4231_SUPPORT
-static void eb4231_getsamplecount(struct sparcaudio_driver *drv, unsigned int length, unsigned int direction)
-{
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  struct audio_prinfo *thisdir;
-  unsigned int count, curcount, nextcount, dbcr;
-
-  if(direction == 1) {
-    thisdir = &cs4231_chip->perchip_info.record;
-    dbcr = readl(&(cs4231_chip->eb2c->dbcr));
-    nextcount = cs4231_chip->input_next_dma_size;
-  } else {
-    thisdir = &cs4231_chip->perchip_info.play;
-    dbcr = readl(&(cs4231_chip->eb2p->dbcr));
-    nextcount = cs4231_chip->output_next_dma_size;
-  }
-  curcount = cs4231_length_to_samplecount(thisdir, dbcr);
-  count = thisdir->samples;
-  length = cs4231_length_to_samplecount(thisdir, length);
-  /* normalize for where we are. */
-  thisdir->samples = ((count - nextcount) + (length - curcount));
+static void eb4231_getsamplecount(struct sparcaudio_driver *drv,
+                                  unsigned int length,
+                                  unsigned int direction)
+{
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        struct audio_prinfo *thisdir;
+        unsigned int count, curcount, nextcount, dbcr;
+
+        if(direction == 1) {
+                thisdir = &cs4231_chip->perchip_info.record;
+                dbcr = readl(cs4231_chip->eb2c + EBDMA_COUNT);
+                nextcount = cs4231_chip->input_next_dma_size;
+        } else {
+                thisdir = &cs4231_chip->perchip_info.play;
+                dbcr = readl(cs4231_chip->eb2p + EBDMA_COUNT);
+                nextcount = cs4231_chip->output_next_dma_size;
+        }
+        curcount = cs4231_length_to_samplecount(thisdir, dbcr);
+        count = thisdir->samples;
+        length = cs4231_length_to_samplecount(thisdir, length);
+        /* normalize for where we are. */
+        thisdir->samples = ((count - nextcount) + (length - curcount));
 }
 #endif
 
-static void cs4231_getsamplecount(struct sparcaudio_driver *drv, unsigned int length, unsigned int direction)
-{
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  struct audio_prinfo *thisdir;
-  unsigned int count, nextcount, curcount;
-
-  if (direction == 1) /* record */ 
-    {
-      thisdir = &cs4231_chip->perchip_info.record;
-      curcount = 
-	cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmacc);
-      nextcount = 
-	cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmacnc);
-    }
-  else /* play */
-    {
-      thisdir = &cs4231_chip->perchip_info.play;
-      curcount = 
-	cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmapc);
-      nextcount = 
-	cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmapnc);
-    }
-  count = thisdir->samples;
-  length = cs4231_length_to_samplecount(thisdir, length);
-  /* normalize for where we are. */
-  thisdir->samples = ((count - nextcount) + (length - curcount));
+static void cs4231_getsamplecount(struct sparcaudio_driver *drv,
+                                  unsigned int length,
+                                  unsigned int direction)
+{
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        struct audio_prinfo *thisdir;
+        unsigned int count, nextcount, curcount;
+        u32 tmp;
+
+        if (direction == 1) {
+                /* record */ 
+                thisdir = &cs4231_chip->perchip_info.record;
+                tmp = sbus_readl(cs4231_chip->regs + APCCC);
+                curcount = cs4231_length_to_samplecount(thisdir, tmp);
+                tmp = sbus_readl(cs4231_chip->regs + APCCNC);
+                nextcount = cs4231_length_to_samplecount(thisdir, tmp);
+        } else {
+                /* play */
+                thisdir = &cs4231_chip->perchip_info.play;
+                tmp = sbus_readl(cs4231_chip->regs + APCPC);
+                curcount = cs4231_length_to_samplecount(thisdir, tmp);
+                tmp = sbus_readl(cs4231_chip->regs + APCPNC);
+                nextcount = cs4231_length_to_samplecount(thisdir, tmp);
+        }
+        count = thisdir->samples;
+        length = cs4231_length_to_samplecount(thisdir, length);
+
+        /* normalize for where we are. */
+        thisdir->samples = ((count - nextcount) + (length - curcount));
 }
 
 static int cs4231_open(struct inode * inode, struct file * file, struct sparcaudio_driver *drv)
 {	
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-  /* Set the default audio parameters if not already in use. */
-  if (file->f_mode & FMODE_WRITE) {
-    if (!(drv->flags & SDF_OPEN_WRITE) && 
-	(cs4231_chip->perchip_info.play.active == 0)) {
-      cs4231_chip->perchip_info.play.open = 1;
-      cs4231_chip->perchip_info.play.samples =
-        cs4231_chip->perchip_info.play.error = 0;
-    }
-  }
-
-  if (file->f_mode & FMODE_READ) {
-    if (!(drv->flags & SDF_OPEN_READ) && 
-	(cs4231_chip->perchip_info.record.active == 0)) {
-      cs4231_chip->perchip_info.record.open = 1;
-      cs4231_chip->perchip_info.record.samples = 
-        cs4231_chip->perchip_info.record.error = 0;
-    }
-  }  
+        /* Set the default audio parameters if not already in use. */
+        if (file->f_mode & FMODE_WRITE) {
+                if (!(drv->flags & SDF_OPEN_WRITE) && 
+                    (cs4231_chip->perchip_info.play.active == 0)) {
+                        cs4231_chip->perchip_info.play.open = 1;
+                        cs4231_chip->perchip_info.play.samples =
+                                cs4231_chip->perchip_info.play.error = 0;
+                }
+        }
+
+        if (file->f_mode & FMODE_READ) {
+                if (!(drv->flags & SDF_OPEN_READ) && 
+                    (cs4231_chip->perchip_info.record.active == 0)) {
+                        cs4231_chip->perchip_info.record.open = 1;
+                        cs4231_chip->perchip_info.record.samples = 
+                                cs4231_chip->perchip_info.record.error = 0;
+                }
+        }  
 
-  cs4231_ready(drv);
-  
-  CHIP_READY
+        cs4231_ready(drv);
+        CHIP_READY();
     
-  MOD_INC_USE_COUNT;
+        MOD_INC_USE_COUNT;
   
-  return 0;
+        return 0;
 }
 
 static void cs4231_release(struct inode * inode, struct file * file, struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-
-  /* zero out any info about what data we have as well */
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
 
-  if (file->f_mode & FMODE_READ) {
-    /* stop capture here or midlevel? */
-    cs4231_chip->perchip_info.record.open = 0;
-    if (cs4231_chip->input_dma_handle) {
-      if(!(cs4231_chip->status & CS_STATUS_IS_EBUS))
-              mmu_release_scsi_one(cs4231_chip->input_dma_handle,
-                                   cs4231_chip->input_dma_size, drv->dev->my_bus);
-      cs4231_chip->input_dma_handle = 0;
-      cs4231_chip->input_dma_size = 0;
-    }
-    if (cs4231_chip->input_next_dma_handle) {
-      if(!(cs4231_chip->status & CS_STATUS_IS_EBUS))
-              mmu_release_scsi_one(cs4231_chip->input_next_dma_handle,
-                                   cs4231_chip->input_next_dma_size, drv->dev->my_bus);
-      cs4231_chip->input_next_dma_handle = 0;
-      cs4231_chip->input_next_dma_size = 0;
-    }
-  }
-
-  if (file->f_mode & FMODE_WRITE) {
-    cs4231_chip->perchip_info.play.active =
-      cs4231_chip->perchip_info.play.open = 0;
-    if (cs4231_chip->output_dma_handle) {
-      if(!(cs4231_chip->status & CS_STATUS_IS_EBUS))
-              mmu_release_scsi_one(cs4231_chip->output_dma_handle,
-                                   cs4231_chip->output_dma_size, drv->dev->my_bus);
-      cs4231_chip->output_dma_handle = 0;
-      cs4231_chip->output_dma_size = 0;
-    }
-    if (cs4231_chip->output_next_dma_handle) {
-      if(!(cs4231_chip->status & CS_STATUS_IS_EBUS))
-              mmu_release_scsi_one(cs4231_chip->output_next_dma_handle,
-                                   cs4231_chip->output_next_dma_size, 
-                                   drv->dev->my_bus);
-      cs4231_chip->output_next_dma_handle = 0;
-      cs4231_chip->output_next_dma_size = 0;
-    }
-  }
-
-  if (!cs4231_chip->perchip_info.play.open && 
-      !cs4231_chip->perchip_info.record.open && 
-      (cs4231_chip->status & CS_STATUS_INIT_ON_CLOSE)) {
-    cs4231_chip_reset(drv);
-    cs4231_chip->status &= ~CS_STATUS_INIT_ON_CLOSE;
-  }
+        /* zero out any info about what data we have as well */
+        if (file->f_mode & FMODE_READ) {
+                /* stop capture here or midlevel? */
+                cs4231_chip->perchip_info.record.open = 0;
+                if (cs4231_chip->input_dma_handle) {
+                        if(!(cs4231_chip->status & CS_STATUS_IS_EBUS))
+                                sbus_unmap_single(drv->dev,
+                                                  cs4231_chip->input_dma_handle,
+                                                  cs4231_chip->input_dma_size);
+                        cs4231_chip->input_dma_handle = 0;
+                        cs4231_chip->input_dma_size = 0;
+                }
+                if (cs4231_chip->input_next_dma_handle) {
+                        if(!(cs4231_chip->status & CS_STATUS_IS_EBUS))
+                                sbus_unmap_single(drv->dev,
+                                                  cs4231_chip->input_next_dma_handle,
+                                                  cs4231_chip->input_next_dma_size);
+                        cs4231_chip->input_next_dma_handle = 0;
+                        cs4231_chip->input_next_dma_size = 0;
+                }
+        }
+
+        if (file->f_mode & FMODE_WRITE) {
+                cs4231_chip->perchip_info.play.active =
+                        cs4231_chip->perchip_info.play.open = 0;
+                if (cs4231_chip->output_dma_handle) {
+                        if(!(cs4231_chip->status & CS_STATUS_IS_EBUS))
+                                sbus_unmap_single(drv->dev,
+                                                  cs4231_chip->output_dma_handle,
+                                                  cs4231_chip->output_dma_size);
+                        cs4231_chip->output_dma_handle = 0;
+                        cs4231_chip->output_dma_size = 0;
+                }
+                if (cs4231_chip->output_next_dma_handle) {
+                        if(!(cs4231_chip->status & CS_STATUS_IS_EBUS))
+                                sbus_unmap_single(drv->dev,
+                                                  cs4231_chip->output_next_dma_handle,
+                                                  cs4231_chip->output_next_dma_size);
+                        cs4231_chip->output_next_dma_handle = 0;
+                        cs4231_chip->output_next_dma_size = 0;
+                }
+        }
+
+        if (!cs4231_chip->perchip_info.play.open && 
+            !cs4231_chip->perchip_info.record.open && 
+            (cs4231_chip->status & CS_STATUS_INIT_ON_CLOSE)) {
+                cs4231_chip_reset(drv);
+                cs4231_chip->status &= ~CS_STATUS_INIT_ON_CLOSE;
+        }
 
-  MOD_DEC_USE_COUNT;
+        MOD_DEC_USE_COUNT;
 }
 
 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;
-
-  if (cs4231_chip->output_dma_handle) {
-    mmu_release_scsi_one(cs4231_chip->output_dma_handle, 
-                         cs4231_chip->output_dma_size, drv->dev->my_bus);
-    cs4231_chip->output_dma_handle = 0;
-    cs4231_chip->output_dma_size = 0;
-    cs4231_chip->playing_count--;
-    status++;
-  }
-  if (cs4231_chip->output_next_dma_handle) {
-    cs4231_chip->output_dma_handle = cs4231_chip->output_next_dma_handle;
-    cs4231_chip->output_dma_size = cs4231_chip->output_next_dma_size;
-    cs4231_chip->output_next_dma_size = 0;
-    cs4231_chip->output_next_dma_handle = 0;
-  }
-
-  if ((cs4231_chip->output_ptr && cs4231_chip->output_size > 0) && 
-      !(cs4231_chip->perchip_info.play.pause)) {
-    cs4231_chip->output_next_dma_handle =
-      mmu_get_scsi_one((char *) cs4231_chip->output_ptr, 
-                       cs4231_chip->output_size, drv->dev->my_bus);
-    cs4231_chip->regs->dmapnva = cs4231_chip->output_next_dma_handle;
-    cs4231_chip->output_next_dma_size = cs4231_chip->regs->dmapnc = 
-      cs4231_chip->output_size;
-    cs4231_chip->output_size = 0;
-    cs4231_chip->output_ptr = NULL;
-    cs4231_chip->playing_count++;
-    status += 2;
-  } else {
-    cs4231_chip->regs->dmapnva = 0;
-    cs4231_chip->regs->dmapnc = 0;
-  }
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int status = 0;
 
-  sparcaudio_output_done(drv, status);
+        if (!push) {
+                if (!cs4231_chip->perchip_info.play.active) {
+                        sbus_writel(cs4231_chip->output_next_dma_handle,
+                                    cs4231_chip->regs + APCPNVA);
+                        sbus_writel(cs4231_chip->output_next_dma_size,
+                                    cs4231_chip->regs + APCPNC);
+                }
+                sparcaudio_output_done(drv, 0);
+                return;
+        }
+
+        if (cs4231_chip->playlen == 0 && cs4231_chip->output_size > 0) 
+                cs4231_chip->playlen = cs4231_chip->output_size;
+
+        if (cs4231_chip->output_dma_handle) {
+                sbus_unmap_single(drv->dev,
+                                  cs4231_chip->output_dma_handle,
+                                  cs4231_chip->output_dma_size);
+                cs4231_chip->output_dma_handle = 0;
+                cs4231_chip->output_dma_size = 0;
+                cs4231_chip->playing_count--;
+                status++;
+        }
+
+        if (cs4231_chip->output_next_dma_handle) {
+                cs4231_chip->output_dma_handle = cs4231_chip->output_next_dma_handle;
+                cs4231_chip->output_dma_size = cs4231_chip->output_next_dma_size;
+                cs4231_chip->output_next_dma_size = 0;
+                cs4231_chip->output_next_dma_handle = 0;
+        }
+
+        if ((cs4231_chip->output_ptr && cs4231_chip->output_size > 0) && 
+            !(cs4231_chip->perchip_info.play.pause)) {
+                cs4231_chip->output_next_dma_handle =
+                        sbus_map_single(drv->dev,
+                                        (char *)cs4231_chip->output_ptr,
+                                        cs4231_chip->output_size);
+                cs4231_chip->output_next_dma_size = cs4231_chip->output_size;
+                sbus_writel(cs4231_chip->output_next_dma_handle,
+                            cs4231_chip->regs + APCPNVA);
+                sbus_writel(cs4231_chip->output_next_dma_size,
+                            cs4231_chip->regs + APCPNC);
+                cs4231_chip->output_size = 0;
+                cs4231_chip->output_ptr = NULL;
+                cs4231_chip->playing_count++;
+                status += 2;
+        } else {
+                sbus_writel(0, cs4231_chip->regs + APCPNVA);
+                sbus_writel(0, cs4231_chip->regs + APCPNC);
+        }
 
-  return;
+        sparcaudio_output_done(drv, status);
 }
 
 #ifdef EB4231_SUPPORT
 static void eb4231_playintr(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int status = 0;
-
-  if (cs4231_chip->playlen == 0 && cs4231_chip->output_size > 0) 
-    cs4231_chip->playlen = cs4231_chip->output_size;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int status = 0;
 
-  if (cs4231_chip->output_dma_handle) {
-    cs4231_chip->output_dma_handle = 0;
-    cs4231_chip->output_dma_size = 0;
-    cs4231_chip->playing_count--;
-    status++;
-  }
-  if(cs4231_chip->output_next_dma_handle) {
-    cs4231_chip->output_dma_handle = cs4231_chip->output_next_dma_handle;
-    cs4231_chip->output_dma_size = cs4231_chip->output_next_dma_size;
-    cs4231_chip->output_next_dma_handle = 0;
-    cs4231_chip->output_next_dma_size = 0;
-  }
-
-  if ((cs4231_chip->output_ptr && cs4231_chip->output_size > 0) && 
-      !(cs4231_chip->perchip_info.play.pause)) {
-    cs4231_chip->output_next_dma_handle = virt_to_bus(cs4231_chip->output_ptr);
-    cs4231_chip->output_next_dma_size = cs4231_chip->output_size;
-
-    writel(cs4231_chip->output_next_dma_size, &(cs4231_chip->eb2p->dbcr));
-    writel(cs4231_chip->output_next_dma_handle, &(cs4231_chip->eb2p->dacr));
-    cs4231_chip->output_size = 0;
-    cs4231_chip->output_ptr = NULL;
-    cs4231_chip->playing_count++;
-    status += 2;
-  }
+        if (cs4231_chip->playlen == 0 && cs4231_chip->output_size > 0) 
+                cs4231_chip->playlen = cs4231_chip->output_size;
 
-  sparcaudio_output_done(drv, status);
+        if (cs4231_chip->output_dma_handle) {
+                cs4231_chip->output_dma_handle = 0;
+                cs4231_chip->output_dma_size = 0;
+                cs4231_chip->playing_count--;
+                status++;
+        }
+
+        if(cs4231_chip->output_next_dma_handle) {
+                cs4231_chip->output_dma_handle = cs4231_chip->output_next_dma_handle;
+                cs4231_chip->output_dma_size = cs4231_chip->output_next_dma_size;
+                cs4231_chip->output_next_dma_handle = 0;
+                cs4231_chip->output_next_dma_size = 0;
+        }
+
+        if ((cs4231_chip->output_ptr && cs4231_chip->output_size > 0) && 
+            !(cs4231_chip->perchip_info.play.pause)) {
+                cs4231_chip->output_next_dma_handle =
+                        virt_to_bus(cs4231_chip->output_ptr);
+                cs4231_chip->output_next_dma_size = cs4231_chip->output_size;
+
+                writel(cs4231_chip->output_next_dma_size,
+                       cs4231_chip->eb2p + EBDMA_COUNT);
+                writel(cs4231_chip->output_next_dma_handle,
+                       cs4231_chip->eb2p + EBDMA_ADDR);
+                cs4231_chip->output_size = 0;
+                cs4231_chip->output_ptr = NULL;
+                cs4231_chip->playing_count++;
+                status += 2;
+        }
 
-  return;
+        sparcaudio_output_done(drv, status);
 }
 #endif
 
 static void cs4231_recclear(int fmt, char *dmabuf, int length)
 {
-  switch (fmt) {
-  case AUDIO_ENCODING_LINEAR:
-    memset(dmabuf, 0x00, length);
-    break;
-  case AUDIO_ENCODING_ALAW:
-    memset(dmabuf, 0xd5, length);
-    break;
-  case AUDIO_ENCODING_ULAW:
-    memset(dmabuf, 0xff, length);
-    break;
-  }
+        switch (fmt) {
+        case AUDIO_ENCODING_LINEAR:
+                memset(dmabuf, 0x00, length);
+                break;
+        case AUDIO_ENCODING_ALAW:
+                memset(dmabuf, 0xd5, length);
+                break;
+        case AUDIO_ENCODING_ULAW:
+                memset(dmabuf, 0xff, length);
+                break;
+        }
 }
 
 static int cs4231_recintr(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int status = 0;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int status = 0;
 
-  if (cs4231_chip->perchip_info.record.active == 0) {
-    dprintk(("going inactive\n"));
-    cs4231_pollinput(drv);
-    cs4231_disable_rec(drv);    
-  } 
-
-  if (cs4231_chip->input_dma_handle) {
-    mmu_release_scsi_one(cs4231_chip->input_dma_handle, 
-                         cs4231_chip->input_dma_size, drv->dev->my_bus);
-    cs4231_chip->input_dma_handle = 0;
-    cs4231_chip->input_dma_size = 0;
-    cs4231_chip->recording_count--;
-    status++;
-  }
-  if (cs4231_chip->input_next_dma_handle) {
-    cs4231_chip->input_dma_handle = cs4231_chip->input_next_dma_handle;
-    cs4231_chip->input_dma_size = cs4231_chip->input_next_dma_size;
-    cs4231_chip->input_next_dma_size = 0;
-    cs4231_chip->input_next_dma_handle = 0;
-  }
-
-  if ((cs4231_chip->input_ptr && cs4231_chip->input_size > 0) && 
-      !(cs4231_chip->perchip_info.record.pause)) {
-    cs4231_recclear(cs4231_chip->perchip_info.record.encoding, 
-                    (char *)cs4231_chip->input_ptr, cs4231_chip->input_size);
-    cs4231_chip->input_next_dma_handle =
-      mmu_get_scsi_one((char *) cs4231_chip->input_ptr, 
-                       cs4231_chip->input_size, drv->dev->my_bus);
-    cs4231_chip->regs->dmacnva = cs4231_chip->input_next_dma_handle;
-    cs4231_chip->input_next_dma_size = cs4231_chip->regs->dmacnc = 
-      cs4231_chip->input_size;
-    cs4231_chip->input_size = 0;
-    cs4231_chip->input_ptr = NULL;
-    cs4231_chip->recording_count++;
-    status += 2;
-  } else {
-    cs4231_chip->regs->dmacnva = 0;
-    cs4231_chip->regs->dmacnc = 0;
-  }
-
-  sparcaudio_input_done(drv, status);
+        if (cs4231_chip->perchip_info.record.active == 0) {
+                dprintk(("going inactive\n"));
+                cs4231_pollinput(drv);
+                cs4231_disable_rec(drv);    
+        } 
+
+        if (cs4231_chip->input_dma_handle) {
+                sbus_unmap_single(drv->dev,
+                                  cs4231_chip->input_dma_handle,
+                                  cs4231_chip->input_dma_size);
+                cs4231_chip->input_dma_handle = 0;
+                cs4231_chip->input_dma_size = 0;
+                cs4231_chip->recording_count--;
+                status++;
+        }
+
+        if (cs4231_chip->input_next_dma_handle) {
+                cs4231_chip->input_dma_handle = cs4231_chip->input_next_dma_handle;
+                cs4231_chip->input_dma_size = cs4231_chip->input_next_dma_size;
+                cs4231_chip->input_next_dma_size = 0;
+                cs4231_chip->input_next_dma_handle = 0;
+        }
+
+        if ((cs4231_chip->input_ptr && cs4231_chip->input_size > 0) && 
+            !(cs4231_chip->perchip_info.record.pause)) {
+                cs4231_recclear(cs4231_chip->perchip_info.record.encoding, 
+                                (char *)cs4231_chip->input_ptr,
+                                cs4231_chip->input_size);
+                cs4231_chip->input_next_dma_handle =
+                        sbus_map_single(drv->dev,
+                                        (char *)cs4231_chip->input_ptr,
+                                        cs4231_chip->input_size);
+                cs4231_chip->input_next_dma_size = cs4231_chip->input_size;
+                sbus_writel(cs4231_chip->input_next_dma_handle,
+                            cs4231_chip->regs + APCCNVA);
+                sbus_writel(cs4231_chip->input_next_dma_size,
+                            cs4231_chip->regs + APCCNC);
+                cs4231_chip->input_size = 0;
+                cs4231_chip->input_ptr = NULL;
+                cs4231_chip->recording_count++;
+                status += 2;
+        } else {
+                sbus_writel(0, cs4231_chip->regs + APCCNVA);
+                sbus_writel(0, cs4231_chip->regs + APCCNC);
+        }
 
-  return 1;
+        sparcaudio_input_done(drv, status);
+        return 1;
 }
 
 #ifdef EB4231_SUPPORT
 static int eb4231_recintr(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int status = 0;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int status = 0;
 
-  if (cs4231_chip->perchip_info.record.active == 0) {
-    dprintk(("going inactive\n"));
-    eb4231_pollinput(drv);
-    cs4231_disable_rec(drv);    
-  } 
-
-  if (cs4231_chip->input_dma_handle) {
-    cs4231_chip->input_dma_handle = 0;
-    cs4231_chip->input_dma_size = 0;
-    cs4231_chip->recording_count--;
-    status++;
-  }
-  if (cs4231_chip->input_next_dma_handle) {
-    cs4231_chip->input_dma_handle = cs4231_chip->input_next_dma_handle;
-    cs4231_chip->input_dma_size = cs4231_chip->input_next_dma_size;
-    cs4231_chip->input_next_dma_size = 0;
-    cs4231_chip->input_next_dma_handle = 0;
-  }
-
-  if ((cs4231_chip->input_ptr && cs4231_chip->input_size > 0) && 
-      !(cs4231_chip->perchip_info.record.pause)) {
-    cs4231_recclear(cs4231_chip->perchip_info.record.encoding, 
-                    (char *)cs4231_chip->input_ptr, cs4231_chip->input_size);
-
-    cs4231_chip->input_next_dma_handle = virt_to_bus(cs4231_chip->input_ptr);
-    cs4231_chip->input_next_dma_size = cs4231_chip->input_size;
-
-    writel(cs4231_chip->input_next_dma_size, &(cs4231_chip->eb2c->dbcr));
-    writel(cs4231_chip->input_next_dma_handle, &(cs4231_chip->eb2c->dacr));
-
-    cs4231_chip->input_size = 0;
-    cs4231_chip->input_ptr = NULL;
-    cs4231_chip->recording_count++;
-    status += 2;
-  }
+        if (cs4231_chip->perchip_info.record.active == 0) {
+                dprintk(("going inactive\n"));
+                eb4231_pollinput(drv);
+                cs4231_disable_rec(drv);    
+        } 
+
+        if (cs4231_chip->input_dma_handle) {
+                cs4231_chip->input_dma_handle = 0;
+                cs4231_chip->input_dma_size = 0;
+                cs4231_chip->recording_count--;
+                status++;
+        }
+
+        if (cs4231_chip->input_next_dma_handle) {
+                cs4231_chip->input_dma_handle = cs4231_chip->input_next_dma_handle;
+                cs4231_chip->input_dma_size = cs4231_chip->input_next_dma_size;
+                cs4231_chip->input_next_dma_size = 0;
+                cs4231_chip->input_next_dma_handle = 0;
+        }
+
+        if ((cs4231_chip->input_ptr && cs4231_chip->input_size > 0) && 
+            !(cs4231_chip->perchip_info.record.pause)) {
+                cs4231_recclear(cs4231_chip->perchip_info.record.encoding, 
+                                (char *)cs4231_chip->input_ptr,
+                                cs4231_chip->input_size);
+
+                cs4231_chip->input_next_dma_handle =
+                        virt_to_bus(cs4231_chip->input_ptr);
+                cs4231_chip->input_next_dma_size = cs4231_chip->input_size;
+
+                writel(cs4231_chip->input_next_dma_size,
+                       cs4231_chip->eb2c + EBDMA_COUNT);
+                writel(cs4231_chip->input_next_dma_handle,
+                       cs4231_chip->eb2c + EBDMA_ADDR);
+
+                cs4231_chip->input_size = 0;
+                cs4231_chip->input_ptr = NULL;
+                cs4231_chip->recording_count++;
+                status += 2;
+        }
 
-  sparcaudio_input_done(drv, status);
-
-  return 1;
+        sparcaudio_input_done(drv, status);
+        return 1;
 }
 #endif
 
@@ -1445,335 +1453,380 @@
 static void eb4231_start_output(struct sparcaudio_driver *drv, __u8 * buffer,
                                 unsigned long count)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  unsigned int dcsr;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 dcsr;
 
-  cs4231_chip->output_ptr = buffer;
-  cs4231_chip->output_size = count;
+        cs4231_chip->output_ptr = buffer;
+        cs4231_chip->output_size = count;
 
-  if (cs4231_chip->perchip_info.play.active || 
-      (cs4231_chip->perchip_info.play.pause))
-    return;
+        if (cs4231_chip->perchip_info.play.active || 
+            (cs4231_chip->perchip_info.play.pause))
+                return;
 
-  cs4231_ready(drv);
+        cs4231_ready(drv);
 
-  cs4231_chip->perchip_info.play.active = 1;
-  cs4231_chip->playing_count = 0;
+        cs4231_chip->perchip_info.play.active = 1;
+        cs4231_chip->playing_count = 0;
 
-  dcsr = readl(&cs4231_chip->eb2p->dcsr);
-  if (!(dcsr & EBUS_DCSR_EN_DMA)) {
-    writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2p->dcsr));
-    writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2p->dcsr));
+        dcsr = readl(cs4231_chip->eb2p + EBDMA_CSR);
+        if (!(dcsr & EBUS_DCSR_EN_DMA)) {
+                writel(EBUS_DCSR_RESET, cs4231_chip->eb2p + EBDMA_CSR);
+                writel(EBUS_DCSR_BURST_SZ_16, cs4231_chip->eb2p + EBDMA_CSR);
 
-    eb4231_playintr(drv);
+                eb4231_playintr(drv);
 
-    writel(EBUS_DCSR_BURST_SZ_16 |
-           (EBUS_DCSR_EN_DMA | EBUS_DCSR_INT_EN | EBUS_DCSR_EN_CNT | EBUS_DCSR_EN_NEXT),
-           &(cs4231_chip->eb2p->dcsr));
+                writel(EBUS_DCSR_BURST_SZ_16 |
+                       (EBUS_DCSR_EN_DMA | EBUS_DCSR_INT_EN |
+                        EBUS_DCSR_EN_CNT | EBUS_DCSR_EN_NEXT),
+                       cs4231_chip->eb2p + EBDMA_CSR);
 
-    cs4231_enable_play(drv);
+                cs4231_enable_play(drv);
 
-    cs4231_ready(drv);
-  } else {
-    eb4231_playintr(drv);
-  }
+                cs4231_ready(drv);
+        } else {
+                eb4231_playintr(drv);
+        }
 }
 #endif
 
 static void cs4231_start_output(struct sparcaudio_driver *drv, __u8 * buffer,
                                 unsigned long count)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-
-  tprintk(("in 4231 start output\n"));
-  cs4231_chip->output_ptr = buffer;
-  cs4231_chip->output_size = count;
-
-  if (cs4231_chip->perchip_info.play.active || 
-      (cs4231_chip->perchip_info.play.pause))
-    return;
-
-  cs4231_ready(drv);
-
-  cs4231_chip->perchip_info.play.active = 1;
-  cs4231_chip->playing_count = 0;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 csr;
 
-  if ((cs4231_chip->regs->dmacsr & APC_PPAUSE) || 
-      !(cs4231_chip->regs->dmacsr & APC_PDMA_READY)) {
-    cs4231_chip->regs->dmacsr &= ~APC_XINT_PLAY;
-    cs4231_chip->regs->dmacsr &= ~APC_PPAUSE;
+        tprintk(("in 4231 start output\n"));
+        cs4231_chip->output_ptr = buffer;
+        cs4231_chip->output_size = count;
+
+        if (cs4231_chip->perchip_info.play.active || 
+            (cs4231_chip->perchip_info.play.pause))
+                return;
+
+        cs4231_ready(drv);
+
+        cs4231_chip->perchip_info.play.active = 1;
+        cs4231_chip->playing_count = 0;
+
+        csr = sbus_readl(cs4231_chip->regs + APCCSR);
+        if ((csr & APC_PPAUSE) || !(csr & APC_PDMA_READY)) {
+                u32 pnva;
+
+                csr &= ~APC_XINT_PLAY;
+                sbus_writel(csr, cs4231_chip->regs + APCCSR);
+                csr &= ~APC_PPAUSE;
+                sbus_writel(csr, cs4231_chip->regs + APCCSR);
     
-    cs4231_playintr(drv, cs4231_chip->regs->dmapnva == 0 ? 1 : 0);
+                pnva = sbus_readl(cs4231_chip->regs + APCPNVA);
+                cs4231_playintr(drv, (pnva == 0) ? 1 : 0);
 
-    cs4231_chip->regs->dmacsr |= APC_PLAY_SETUP;
-    cs4231_enable_play(drv);
+                csr |= APC_PLAY_SETUP;
+                sbus_writel(csr, cs4231_chip->regs + APCCSR);
+                cs4231_enable_play(drv);
 
-    cs4231_ready(drv);
-  }
+                cs4231_ready(drv);
+        }
 }
 
 #ifdef EB4231_SUPPORT
 static void eb4231_stop_output(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  unsigned int dcsr;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 dcsr;
 
-  dprintk(("eb4231_stop_output: dcsr 0x%x dacr 0x%x dbcr %d\n",
-           readl(&cs4231_chip->eb2p->dcsr),
-           readl(&cs4231_chip->eb2p->dacr),
-           readl(&cs4231_chip->eb2p->dbcr)));
-  cs4231_chip->output_ptr = NULL;
-  cs4231_chip->output_size = 0;
-  if (cs4231_chip->output_dma_handle) {
-    cs4231_chip->output_dma_handle = 0;
-    cs4231_chip->output_dma_size = 0;
-  }
-  if (cs4231_chip->output_next_dma_handle) {
-    cs4231_chip->output_next_dma_handle = 0;
-    cs4231_chip->output_next_dma_size = 0;
-  }
-  dcsr = readl(&(cs4231_chip->eb2p->dcsr));
-  if(dcsr & EBUS_DCSR_EN_DMA)
-    writel(dcsr & ~EBUS_DCSR_EN_DMA, &(cs4231_chip->eb2p->dcsr));
+        dprintk(("eb4231_stop_output: dcsr 0x%x dacr 0x%x dbcr %d\n",
+                 readl(cs4231_chip->eb2p + EBDMA_CSR),
+                 readl(cs4231_chip->eb2p + EBDMA_ADDR),
+                 readl(cs4231_chip->eb2p + EBDMA_COUNT)));
+
+        cs4231_chip->output_ptr = NULL;
+        cs4231_chip->output_size = 0;
+
+        if (cs4231_chip->output_dma_handle) {
+                cs4231_chip->output_dma_handle = 0;
+                cs4231_chip->output_dma_size = 0;
+        }
+
+        if (cs4231_chip->output_next_dma_handle) {
+                cs4231_chip->output_next_dma_handle = 0;
+                cs4231_chip->output_next_dma_size = 0;
+        }
+        dcsr = readl(cs4231_chip->eb2p + EBDMA_CSR);
+        if(dcsr & EBUS_DCSR_EN_DMA)
+                writel(dcsr & ~EBUS_DCSR_EN_DMA,
+                       cs4231_chip->eb2p + EBDMA_CSR);
 
-  /* Else subsequent speed setting changes are ignored by the chip. */
-  cs4231_disable_play(drv);
+        /* Else subsequent speed setting changes are ignored by the chip. */
+        cs4231_disable_play(drv);
 }
 #endif
 
 static void cs4231_stop_output(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-  tprintk(("in cs4231_stop_output\n"));
-  cs4231_chip->output_ptr = NULL;
-  cs4231_chip->output_size = 0;
-  if (cs4231_chip->output_dma_handle) {
-    mmu_release_scsi_one(cs4231_chip->output_dma_handle,
-                         cs4231_chip->output_dma_size, drv->dev->my_bus);
-    cs4231_chip->output_dma_handle = 0;
-    cs4231_chip->output_dma_size = 0;
-  }
-  if (cs4231_chip->output_next_dma_handle) {
-    mmu_release_scsi_one(cs4231_chip->output_next_dma_handle,
-                         cs4231_chip->output_next_dma_size, drv->dev->my_bus);
-    cs4231_chip->output_next_dma_handle = 0;
-    cs4231_chip->output_next_dma_size = 0;
-  }
+        tprintk(("in cs4231_stop_output\n"));
+        cs4231_chip->output_ptr = NULL;
+        cs4231_chip->output_size = 0;
+
+        if (cs4231_chip->output_dma_handle) {
+                sbus_unmap_single(drv->dev,
+                                  cs4231_chip->output_dma_handle,
+                                  cs4231_chip->output_dma_size);
+                cs4231_chip->output_dma_handle = 0;
+                cs4231_chip->output_dma_size = 0;
+        }
+
+        if (cs4231_chip->output_next_dma_handle) {
+                sbus_unmap_single(drv->dev,
+                                  cs4231_chip->output_next_dma_handle,
+                                  cs4231_chip->output_next_dma_size);
+                cs4231_chip->output_next_dma_handle = 0;
+                cs4231_chip->output_next_dma_size = 0;
+        }
 #if 0 /* Not safe without shutting off the DMA controller as well. -DaveM */
-  /* Else subsequent speed setting changes are ignored by the chip. */
-  cs4231_disable_play(drv);
+        /* Else subsequent speed setting changes are ignored by the chip. */
+        cs4231_disable_play(drv);
 #endif
 }
 
 #ifdef EB4231_SUPPORT
 static void eb4231_pollinput(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int x = 0, dcsr;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int x;
+        u32 dcsr;
+
+        x = 0;
+        do {
+                dcsr = readl(cs4231_chip->eb2c + EBDMA_CSR);
+                if (dcsr & EBUS_DCSR_TC)
+                        break;
+                x++;
+        } while (x <= CS_TIMEOUT);
 
-  while (!((dcsr = readl(&(cs4231_chip->eb2c->dcsr))) & EBUS_DCSR_TC) &&
-         x <= CS_TIMEOUT) {
-    x++;
-  }
-
-  writel(dcsr | EBUS_DCSR_TC, &(cs4231_chip->eb2c->dcsr));
+        writel(dcsr | EBUS_DCSR_TC,
+               cs4231_chip->eb2c + EBDMA_CSR);
 }
 #endif
 
 static void cs4231_pollinput(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int x = 0;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int x;
+        u32 csr;
+
+        x = 0;
+        do {
+                csr = sbus_readl(cs4231_chip->regs + APCCSR);
+                if (csr & APC_XINT_COVF)
+                        break;
+                x++;
+        } while (x <= CS_TIMEOUT);
 
-  while (!(cs4231_chip->regs->dmacsr & APC_XINT_COVF) && x <= CS_TIMEOUT) {
-    x++;
-  }
-  cs4231_chip->regs->dmacsr |= APC_XINT_CEMP;
+        sbus_writel(csr | APC_XINT_CEMP,
+                    cs4231_chip->regs + APCCSR);
 }
 
 static void cs4231_start_input(struct sparcaudio_driver *drv, __u8 * buffer, 
                                unsigned long count)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 csr;
 
-  cs4231_chip->input_ptr = buffer;
-  cs4231_chip->input_size = count;
+        cs4231_chip->input_ptr = buffer;
+        cs4231_chip->input_size = count;
 
-  if (cs4231_chip->perchip_info.record.active || 
-      (cs4231_chip->perchip_info.record.pause))
-    return;
+        if (cs4231_chip->perchip_info.record.active || 
+            (cs4231_chip->perchip_info.record.pause))
+                return;
 
-  cs4231_ready(drv);
+        cs4231_ready(drv);
 
-  cs4231_chip->perchip_info.record.active = 1;
-  cs4231_chip->recording_count = 0;
+        cs4231_chip->perchip_info.record.active = 1;
+        cs4231_chip->recording_count = 0;
 
-  if ((cs4231_chip->regs->dmacsr & APC_CPAUSE) || 
-      !(cs4231_chip->regs->dmacsr & APC_CDMA_READY)) {
-    cs4231_chip->regs->dmacsr &= ~APC_XINT_CAPT;
-    cs4231_chip->regs->dmacsr &= ~APC_CPAUSE;
+        csr = sbus_readl(cs4231_chip->regs + APCCSR);
+        if ((csr & APC_CPAUSE) || !(csr & APC_CDMA_READY)) {
+                csr &= ~APC_XINT_CAPT;
+                sbus_writel(csr, cs4231_chip->regs + APCCSR);
+                csr &= ~APC_CPAUSE;
+                sbus_writel(csr, cs4231_chip->regs + APCCSR);
 
-    cs4231_recintr(drv);
+                cs4231_recintr(drv);
 
-    cs4231_chip->regs->dmacsr |= APC_CAPT_SETUP;
-    cs4231_enable_rec(drv);
+                csr |= APC_CAPT_SETUP;
+                sbus_writel(csr, cs4231_chip->regs + APCCSR);
 
-    cs4231_ready(drv);
-  } else
-    cs4231_recintr(drv);
+                cs4231_enable_rec(drv);
+                cs4231_ready(drv);
+        } else {
+                cs4231_recintr(drv);
+        }
 }
 
 static void cs4231_stop_input(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 csr;
+
+        cs4231_chip->perchip_info.record.active = 0;
 
-  cs4231_chip->perchip_info.record.active = 0;
-  cs4231_chip->regs->dmacsr |= (APC_CPAUSE);
+        csr = sbus_readl(cs4231_chip->regs + APCCSR);
+        csr |= APC_CPAUSE;
+        sbus_writel(csr, cs4231_chip->regs + APCCSR);
+
+        cs4231_chip->input_ptr = NULL;
+        cs4231_chip->input_size = 0;
+
+        if (cs4231_chip->input_dma_handle) {
+                sbus_unmap_single(drv->dev,
+                                  cs4231_chip->input_dma_handle,
+                                  cs4231_chip->input_dma_size);
+                cs4231_chip->input_dma_handle = 0;
+                cs4231_chip->input_dma_size = 0;
+        }
+
+        if (cs4231_chip->input_next_dma_handle) {
+                sbus_unmap_single(drv->dev,
+                                  cs4231_chip->input_next_dma_handle,
+                                  cs4231_chip->input_next_dma_size);
+                cs4231_chip->input_next_dma_handle = 0;
+                cs4231_chip->input_next_dma_size = 0;
+        }
 
-  cs4231_chip->input_ptr = NULL;
-  cs4231_chip->input_size = 0;
-  if (cs4231_chip->input_dma_handle) {
-    mmu_release_scsi_one(cs4231_chip->input_dma_handle,
-                         cs4231_chip->input_dma_size, drv->dev->my_bus);
-    cs4231_chip->input_dma_handle = 0;
-    cs4231_chip->input_dma_size = 0;
-  }
-  if (cs4231_chip->input_next_dma_handle) {
-    mmu_release_scsi_one(cs4231_chip->input_next_dma_handle,
-                         cs4231_chip->input_next_dma_size, drv->dev->my_bus);
-    cs4231_chip->input_next_dma_handle = 0;
-    cs4231_chip->input_next_dma_size = 0;
-  }
-  cs4231_pollinput(drv);
+        cs4231_pollinput(drv);
 }
 
 #ifdef EB4231_SUPPORT
 static void eb4231_start_input(struct sparcaudio_driver *drv, __u8 * buffer, 
                                unsigned long count)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  unsigned int dcsr;
-
-  cs4231_chip->input_ptr = buffer;
-  cs4231_chip->input_size = count;
-
-  if (cs4231_chip->perchip_info.record.active || 
-      (cs4231_chip->perchip_info.record.pause))
-    return;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 dcsr;
 
-  cs4231_ready(drv);
+        cs4231_chip->input_ptr = buffer;
+        cs4231_chip->input_size = count;
 
-  cs4231_chip->perchip_info.record.active = 1;
-  cs4231_chip->recording_count = 0;
+        if (cs4231_chip->perchip_info.record.active || 
+            (cs4231_chip->perchip_info.record.pause))
+                return;
+
+        cs4231_ready(drv);
+        cs4231_chip->perchip_info.record.active = 1;
+        cs4231_chip->recording_count = 0;
+
+        dcsr = readl(cs4231_chip->eb2c + EBDMA_CSR);
+        if (!(dcsr & EBUS_DCSR_EN_DMA)) {
+                writel(EBUS_DCSR_RESET, cs4231_chip->eb2c + EBDMA_CSR);
+                writel(EBUS_DCSR_BURST_SZ_16, cs4231_chip->eb2c + EBDMA_CSR);
+
+                eb4231_recintr(drv);
+
+                writel(EBUS_DCSR_BURST_SZ_16 |
+                       (EBUS_DCSR_EN_DMA | EBUS_DCSR_INT_EN |
+                        EBUS_DCSR_EN_CNT | EBUS_DCSR_EN_NEXT),
+                       cs4231_chip->eb2c + EBDMA_CSR);
 
-  dcsr = readl(&cs4231_chip->eb2c->dcsr);
-  if (!(dcsr & EBUS_DCSR_EN_DMA)) {
-    writel(EBUS_DCSR_RESET, &(cs4231_chip->eb2c->dcsr));
-    writel(EBUS_DCSR_BURST_SZ_16, &(cs4231_chip->eb2c->dcsr));
-
-    eb4231_recintr(drv);
-
-    writel(EBUS_DCSR_BURST_SZ_16 |
-           (EBUS_DCSR_EN_DMA | EBUS_DCSR_INT_EN | EBUS_DCSR_EN_CNT | EBUS_DCSR_EN_NEXT),
-           &(cs4231_chip->eb2c->dcsr));
-
-    cs4231_enable_rec(drv);
-    cs4231_ready(drv);
-  } else
-    eb4231_recintr(drv);
+                cs4231_enable_rec(drv);
+                cs4231_ready(drv);
+        } else {
+                eb4231_recintr(drv);
+        }
 }
 
 static void eb4231_stop_input(struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  unsigned int dcsr;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 dcsr;
 
-  cs4231_chip->perchip_info.record.active = 0;
+        cs4231_chip->perchip_info.record.active = 0;
 
-  cs4231_chip->input_ptr = NULL;
-  cs4231_chip->input_size = 0;
-  if (cs4231_chip->input_dma_handle) {
-    cs4231_chip->input_dma_handle = 0;
-    cs4231_chip->input_dma_size = 0;
-  }
-  if (cs4231_chip->input_next_dma_handle) {
-    cs4231_chip->input_next_dma_handle = 0;
-    cs4231_chip->input_next_dma_size = 0;
-  }
-
-  dcsr = readl(&(cs4231_chip->eb2c->dcsr));
-  if (dcsr & EBUS_DCSR_EN_DMA)
-    writel(dcsr & ~EBUS_DCSR_EN_DMA, &(cs4231_chip->eb2c->dcsr));
+        cs4231_chip->input_ptr = NULL;
+        cs4231_chip->input_size = 0;
 
-  cs4231_disable_rec(drv);
+        if (cs4231_chip->input_dma_handle) {
+                cs4231_chip->input_dma_handle = 0;
+                cs4231_chip->input_dma_size = 0;
+        }
+
+        if (cs4231_chip->input_next_dma_handle) {
+                cs4231_chip->input_next_dma_handle = 0;
+                cs4231_chip->input_next_dma_size = 0;
+        }
+
+        dcsr = readl(cs4231_chip->eb2c + EBDMA_CSR);
+        if (dcsr & EBUS_DCSR_EN_DMA)
+                writel(dcsr & ~EBUS_DCSR_EN_DMA, cs4231_chip->eb2c + EBDMA_CSR);
+
+        cs4231_disable_rec(drv);
 }
 #endif
 
 static int cs4231_set_output_pause(struct sparcaudio_driver *drv, int value)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
         cs4231_chip->perchip_info.play.pause = value;
 
         if (!value)
-          sparcaudio_output_done(drv, 0);
+                sparcaudio_output_done(drv, 0);
 
         return value;
 }
 
 static int cs4231_set_output_error(struct sparcaudio_driver *drv, int value)
 {
-  int i;
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int i;
   
-  i = cs4231_chip->perchip_info.play.error;
-  cs4231_chip->perchip_info.play.error = value;
+        i = cs4231_chip->perchip_info.play.error;
+        cs4231_chip->perchip_info.play.error = value;
   
-  return i;
+        return i;
 }
 
 static int cs4231_set_input_error(struct sparcaudio_driver *drv, int value)
 {
-  int i;
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int i;
   
-  i = cs4231_chip->perchip_info.record.error;
-  cs4231_chip->perchip_info.record.error = value;
+        i = cs4231_chip->perchip_info.record.error;
+        cs4231_chip->perchip_info.record.error = value;
   
-  return i;
+        return i;
 }
 
 static int cs4231_set_output_samples(struct sparcaudio_driver *drv, int value)
 {
-  int i;
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        int i;
   
-  i = cs4231_chip->perchip_info.play.samples;
-  cs4231_chip->perchip_info.play.samples = value;
+        i = cs4231_chip->perchip_info.play.samples;
+        cs4231_chip->perchip_info.play.samples = value;
   
-  return i;
+        return i;
 }
 
 static int cs4231_set_input_samples(struct sparcaudio_driver *drv, int value)
 {
-  int i;
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  
-  i = cs4231_chip->perchip_info.record.samples;
-  cs4231_chip->perchip_info.record.samples = value;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int i;
   
-  return i;
+        i = cs4231_chip->perchip_info.record.samples;
+        cs4231_chip->perchip_info.record.samples = value;
+
+        return i;
 }
 
 static int cs4231_set_input_pause(struct sparcaudio_driver *drv, int value)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
         cs4231_chip->perchip_info.record.pause = value;
 	
         if (value)
-          cs4231_stop_input(drv);
+                cs4231_stop_input(drv);
 	
         return value;
 }
@@ -1781,182 +1834,181 @@
 static void cs4231_audio_getdev(struct sparcaudio_driver *drv,
                                  audio_device_t * audinfo)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-  strncpy(audinfo->name, "SUNW,CS4231", sizeof(audinfo->name) - 1);
-  /* versions */
-  /* a: SPARCstation 4/5          b: Ultra 1/2 (electron)       */
-  /* c: Ultra 1/2 PCI? (positron) d: ppc                        */
-  /* e: x86                       f: Ultra Enterprise? (tazmo)  */
-  /* g: Ultra 30? (quark)         h: Ultra 5/10? (darwin)       */
-  /* apparently Ultra 1, Ultra 2 don't have internal CD input */
-  if (cs4231_chip->status & CS_STATUS_IS_ULTRA)
-    strncpy(audinfo->version, "b", sizeof(audinfo->version) - 1);
-  else
-    strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1);
-  strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1);
+        strncpy(audinfo->name, "SUNW,CS4231", sizeof(audinfo->name) - 1);
+        /* versions */
+        /* a: SPARCstation 4/5          b: Ultra 1/2 (electron)       */
+        /* c: Ultra 1/2 PCI? (positron) d: ppc                        */
+        /* e: x86                       f: Ultra Enterprise? (tazmo)  */
+        /* g: Ultra 30? (quark)         h: Ultra 5/10? (darwin)       */
+        /* apparently Ultra 1, Ultra 2 don't have internal CD input */
+        if (cs4231_chip->status & CS_STATUS_IS_ULTRA)
+                strncpy(audinfo->version, "b", sizeof(audinfo->version) - 1);
+        else
+                strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1);
+        strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1);
 }
 
 
 static int cs4231_audio_getdev_sunos(struct sparcaudio_driver *drv)
 {
-  return AUDIO_DEV_CS4231;
+        return AUDIO_DEV_CS4231;
 }
 
 static void cs4231_loopback(struct sparcaudio_driver *drv, unsigned int value)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->iar), 0x0d);
-  CS4231_WRITE8(cs4231_chip, &(cs4231_chip->regs->idr), (value ? LOOPB_ON : 0));
+        WRITE_IAR(0x0d);
+        WRITE_IDR(value ? LOOPB_ON : 0);
 }
 
 static int cs4231_ioctl(struct inode * inode, struct file * file,
 			unsigned int cmd, unsigned long arg, 
 			struct sparcaudio_driver *drv)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int retval = 0;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        int retval = 0;
   
-  switch (cmd) {
-  case AUDIO_DIAG_LOOPBACK:
-    cs4231_chip->status |= CS_STATUS_INIT_ON_CLOSE;
-    cs4231_loopback(drv, (unsigned int)arg);
-    break;
-  default:
-    retval = -EINVAL;
-  }
+        switch (cmd) {
+        case AUDIO_DIAG_LOOPBACK:
+                cs4231_chip->status |= CS_STATUS_INIT_ON_CLOSE;
+                cs4231_loopback(drv, (unsigned int)arg);
+                break;
+        default:
+                retval = -EINVAL;
+        };
 
-  return retval;
+        return retval;
 }
 
 #ifdef EB4231_SUPPORT
 /* ebus audio capture interrupt handler. */
 void eb4231_cinterrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-  struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id;
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int dummy;
-  
-  /* Clear the interrupt. */
-  dummy = readl(&(cs4231_chip->eb2c->dcsr));
-  writel(dummy, &(cs4231_chip->eb2c->dcsr));
-
-  if ((dummy & EBUS_DCSR_TC) != 0
-      /*&& (dummy & EBUS_DCSR_A_LOADED) != 0*/) {
-    cs4231_chip->perchip_info.record.samples += 
-      cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), 
-                                   cs4231_chip->reclen);
-    eb4231_recintr(drv);
-  }
-
-  if ((dummy & EBUS_DCSR_A_LOADED) == 0) {
-    cs4231_chip->perchip_info.record.active = 0;
-    eb4231_recintr(drv);
-#if 1
-    eb4231_getsamplecount(drv, cs4231_chip->reclen, 1);
-#endif
-  }
+        struct sparcaudio_driver *drv = (struct sparcaudio_driver *) dev_id;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 dummy;
+  
+        /* Clear the interrupt. */
+        dummy = readl(cs4231_chip->eb2c + EBDMA_CSR);
+        writel(dummy, cs4231_chip->eb2c + EBDMA_CSR);
+
+        if ((dummy & EBUS_DCSR_TC) != 0
+            /*&& (dummy & EBUS_DCSR_A_LOADED) != 0*/) {
+                cs4231_chip->perchip_info.record.samples += 
+                    cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), 
+                                                 cs4231_chip->reclen);
+                eb4231_recintr(drv);
+        }
+
+        if ((dummy & EBUS_DCSR_A_LOADED) == 0) {
+                cs4231_chip->perchip_info.record.active = 0;
+                eb4231_recintr(drv);
+                eb4231_getsamplecount(drv, cs4231_chip->reclen, 1);
+        }
 }
 
 /* ebus audio play interrupt handler. */
 void eb4231_pinterrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-  struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id;
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  unsigned int dummy;
-  
-  /* Clear the interrupt.  Bleh, when not using the next-address
-   * feature, TC can only be cleared by a reset.
-   */
-  dummy = readl(&(cs4231_chip->eb2p->dcsr));
-  writel(dummy, &(cs4231_chip->eb2p->dcsr));
-
-  /* If we get a terminal count and address loaded condition,
-   * this means the DNAR was copied into DACR.
-   */
-  if((dummy & EBUS_DCSR_TC) != 0
-     /*&& (dummy & EBUS_DCSR_A_LOADED) != 0*/) {
-    cs4231_chip->perchip_info.play.samples += 
-      cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), 
-                                   cs4231_chip->playlen); 
-    eb4231_playintr(drv);
-  }
-
-  if((dummy & EBUS_DCSR_A_LOADED) == 0) {
-    cs4231_chip->perchip_info.play.active = 0;
-    eb4231_playintr(drv);
-
-    eb4231_getsamplecount(drv, cs4231_chip->playlen, 0);
-  }
+        struct sparcaudio_driver *drv = (struct sparcaudio_driver *) dev_id;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        u32 dummy;
+  
+        /* Clear the interrupt.  Bleh, when not using the next-address
+         * feature, TC can only be cleared by a reset.
+         */
+        dummy = readl(cs4231_chip->eb2p + EBDMA_CSR);
+        writel(dummy, cs4231_chip->eb2p + EBDMA_CSR);
+
+        /* If we get a terminal count and address loaded condition,
+         * this means the DNAR was copied into DACR.
+         */
+        if((dummy & EBUS_DCSR_TC) != 0
+           /*&& (dummy & EBUS_DCSR_A_LOADED) != 0*/) {
+                cs4231_chip->perchip_info.play.samples += 
+                        cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), 
+                                                     cs4231_chip->playlen); 
+                eb4231_playintr(drv);
+        }
+
+        if((dummy & EBUS_DCSR_A_LOADED) == 0) {
+                cs4231_chip->perchip_info.play.active = 0;
+                eb4231_playintr(drv);
+                eb4231_getsamplecount(drv, cs4231_chip->playlen, 0);
+        }
 }
 #endif
 
 /* Audio interrupt handler. */
 void cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-  struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id;
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  __u32 dummy;
-  
-  dprintk(("in cs4231_interrupt\n"));
-
-  /* Clear the interrupt. */
-  dummy = cs4231_chip->regs->dmacsr;
-  cs4231_chip->regs->dmacsr = dummy;
-
-  /* now go through and figure out what gets to claim the interrupt 
-   * if anything since we may be doing shared interrupts 
-   */
-
-  if (dummy & 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); 
-      if (!(dummy & APC_XINT_EMPT))
-        cs4231_playintr(drv, 1);
-    } 
-    /* Any other conditions we need worry about? */
-  }
-
-  if (dummy & APC_CAPT_INT) {
-    if (dummy & APC_XINT_CNVA) {
-      cs4231_chip->perchip_info.record.samples += 
-	cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), 
-				     cs4231_chip->reclen);
-      cs4231_recintr(drv);
-    }
-    /* Any other conditions we need worry about? */
-  }
-
-  
-  if (dummy & APC_XINT_CEMP) {
-    if (cs4231_chip->perchip_info.record.active == 0) {
-      /* Fix me */
-      cs4231_chip->perchip_info.record.active = 0;
-      cs4231_chip->perchip_info.record.error = 1;
-      cs4231_recintr(drv);
-    }
-  }
-
-  if (dummy & APC_XINT_EMPT) {
-    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, 0);
-
-    cs4231_getsamplecount(drv, cs4231_chip->playlen, 0);
-  }
-
-  if (dummy & APC_GENL_INT) {
-    /* If we get here we must be sharing an interrupt, but I haven't code 
-       to handle this right now */
-  }
-
+        struct sparcaudio_driver *drv = (struct sparcaudio_driver *) dev_id;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
+        __u32 dummy;
+  
+        dprintk(("in cs4231_interrupt\n"));
+
+        /* Clear the interrupt. */
+        dummy = sbus_readl(cs4231_chip->regs + APCCSR);
+        sbus_writel(dummy, cs4231_chip->regs + APCCSR);
+
+        /* now go through and figure out what gets to claim the interrupt 
+         * if anything since we may be doing shared interrupts 
+         */
+        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); 
+                        if (!(dummy & APC_XINT_EMPT))
+                                cs4231_playintr(drv, 1);
+                } 
+                /* Any other conditions we need worry about? */
+        }
+
+        if (dummy & APC_CAPT_INT) {
+                if (dummy & APC_XINT_CNVA) {
+                  cs4231_chip->perchip_info.record.samples += 
+                    cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), 
+                                                 cs4231_chip->reclen);
+                  cs4231_recintr(drv);
+                }
+                /* Any other conditions we need worry about? */
+        }
+
+  
+        if (dummy & APC_XINT_CEMP) {
+                if (cs4231_chip->perchip_info.record.active == 0) {
+                        /* Fix me */
+                        cs4231_chip->perchip_info.record.active = 0;
+                        cs4231_chip->perchip_info.record.error = 1;
+                        cs4231_recintr(drv);
+                }
+        }
+
+        if (dummy & APC_XINT_EMPT) {
+                if (!cs4231_chip->output_next_dma_handle) {
+                        u32 csr = sbus_readl(cs4231_chip->regs + APCCSR);
+
+                        csr |= APC_PPAUSE;
+                        sbus_writel(csr, cs4231_chip->regs + APCCSR);
+                        cs4231_disable_play(drv);
+                        cs4231_chip->perchip_info.play.error = 1;
+                }
+                cs4231_chip->perchip_info.play.active = 0;
+                cs4231_playintr(drv, 0);
+
+                cs4231_getsamplecount(drv, cs4231_chip->playlen, 0);
+        }
+
+        if (dummy & APC_GENL_INT) {
+                /* If we get here we must be sharing an interrupt, but I haven't code 
+                 * to handle this right now.
+                 */
+        }
 }
 
 static struct sparcaudio_operations cs4231_ops = {
@@ -2081,118 +2133,86 @@
 
 /* Attach to an cs4231 chip given its PROM node. */
 static int cs4231_attach(struct sparcaudio_driver *drv, 
-			 struct linux_sbus_device *sdev)
+			 struct sbus_dev *sdev)
 {
 #if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100
-  struct linux_prom_irqs irq;
-#endif
-  struct linux_sbus *sbus = sdev->my_bus;
-  struct cs4231_chip *cs4231_chip;
-  int err;
-
-  /* Allocate our private information structure. */
-  drv->private = kmalloc(sizeof(struct cs4231_chip), GFP_KERNEL);
-  if (!drv->private)
-    return -ENOMEM;
-
-  /* Point at the information structure and initialize it. */
-  drv->ops = &cs4231_ops;
-  cs4231_chip = (struct cs4231_chip *)drv->private;
-  cs4231_chip->input_ptr = cs4231_chip->output_ptr = NULL;
-  cs4231_chip->input_size = cs4231_chip->output_size = 0;
-  cs4231_chip->status = 0;
-
-  drv->dev = sdev;
-
-  /* Map the registers into memory. */
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100
-  prom_apply_sbus_ranges(sbus, &sdev->reg_addrs[0], 
-			 sdev->num_registers, sdev);
-#else
-  prom_apply_sbus_ranges(sbus, sdev->reg_addrs, 1, sdev);
-#endif
-
-  cs4231_chip->regs_size = sdev->reg_addrs[0].reg_size;
-
-  cs4231_chip->regs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
-				     sdev->reg_addrs[0].reg_size, 
-				     "cs4231", sdev->reg_addrs[0].which_io, 
-				     0);
-
-  if (!cs4231_chip->regs) {
-    printk(KERN_ERR "cs4231: could not allocate registers\n");
-    kfree(drv->private);
-    return -EIO;
-  }
-
-  /* Attach the interrupt handler to the audio interrupt. */
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100
-  prom_getproperty(sdev->prom_node, "intr", (char *)&irq, sizeof(irq));
-
-  if (irq.pri < 0) {
-    sparc_free_io(cs4231_chip->regs, cs4231_chip->regs_size);
-    kfree(drv->private);
-    return -EIO;
-  }
-
-  cs4231_chip->irq = irq.pri;
-
-#else
-  cs4231_chip->irq = sdev->irqs[0];
+        struct linux_prom_irqs irq;
 #endif
+        struct cs4231_chip *cs4231_chip;
+        int err;
 
-  request_irq(cs4231_chip->irq, cs4231_interrupt, SA_SHIRQ, "cs4231", drv);
-
-  enable_irq(cs4231_chip->irq);
-
-  cs4231_chip->nirqs = 1;
-
-  cs4231_enable_interrupts(drv);
-
-  /* Reset the audio chip. */
-  cs4231_chip_reset(drv);
-
-  /* Register ourselves with the midlevel audio driver. */
-  err = register_sparcaudio_driver(drv, 1);
-
-  if (err < 0) {
-    printk(KERN_ERR "cs4231: unable to register\n");
-    cs4231_disable_interrupts(drv);
-    disable_irq(cs4231_chip->irq);
-    free_irq(cs4231_chip->irq, drv);
-    sparc_free_io(cs4231_chip->regs, cs4231_chip->regs_size);
-    kfree(drv->private);
-    return -EIO;
-  }
-
-  cs4231_chip->perchip_info.play.active = 
-    cs4231_chip->perchip_info.play.pause = 0;
-
-  cs4231_chip->perchip_info.record.active = 
-    cs4231_chip->perchip_info.record.pause = 0;
-
-  cs4231_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE |
-						AUDIO_SPEAKER |
-						AUDIO_LINE_OUT);
-
-  cs4231_chip->perchip_info.record.avail_ports = (AUDIO_INTERNAL_CD_IN |
-						  AUDIO_LINE_IN | 
-						  AUDIO_MICROPHONE |
-						  AUDIO_ANALOG_LOOPBACK);
-
-  /* Announce the hardware to the user. */
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100
-  printk(KERN_INFO "audio%d: cs4231%c at 0x%x irq %d\n",
-         drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ', 
-	 (unsigned long)cs4231_chip->regs, cs4231_chip->irq);
-#else	 
-  printk(KERN_INFO "audio%d: cs4231%c at %p irq %s\n",
-         drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ', 
-	 cs4231_chip->regs, __irq_itoa(cs4231_chip->irq));
-#endif
+        /* Allocate our private information structure. */
+        drv->private = kmalloc(sizeof(struct cs4231_chip), GFP_KERNEL);
+        if (drv->private == NULL)
+                return -ENOMEM;
+
+        /* Point at the information structure and initialize it. */
+        drv->ops = &cs4231_ops;
+        cs4231_chip = (struct cs4231_chip *) drv->private;
+        cs4231_chip->input_ptr = cs4231_chip->output_ptr = NULL;
+        cs4231_chip->input_size = cs4231_chip->output_size = 0;
+        cs4231_chip->status = 0;
+
+        drv->dev = sdev;
+
+        /* Map the registers into memory. */
+        cs4231_chip->regs_size = sdev->reg_addrs[0].reg_size;
+        cs4231_chip->regs = sbus_ioremap(&sdev->resource[0], 0,
+                                         sdev->reg_addrs[0].reg_size,
+                                         "cs4231");
+
+        if (!cs4231_chip->regs) {
+                printk(KERN_ERR "cs4231: could not remap registers\n");
+                kfree(drv->private);
+                return -EIO;
+        }
+
+        /* Attach the interrupt handler to the audio interrupt. */
+        cs4231_chip->irq = sdev->irqs[0];
+        request_irq(cs4231_chip->irq, cs4231_interrupt, SA_SHIRQ, "cs4231", drv);
+        enable_irq(cs4231_chip->irq);
+
+        cs4231_chip->nirqs = 1;
+        cs4231_enable_interrupts(drv);
+
+        /* Reset the audio chip. */
+        cs4231_chip_reset(drv);
+
+        /* Register ourselves with the midlevel audio driver. */
+        err = register_sparcaudio_driver(drv, 1);
+
+        if (err < 0) {
+                printk(KERN_ERR "cs4231: unable to register\n");
+                cs4231_disable_interrupts(drv);
+                disable_irq(cs4231_chip->irq);
+                free_irq(cs4231_chip->irq, drv);
+                sbus_iounmap(cs4231_chip->regs, cs4231_chip->regs_size);
+                kfree(drv->private);
+                return -EIO;
+        }
+
+        cs4231_chip->perchip_info.play.active = 
+                cs4231_chip->perchip_info.play.pause = 0;
+
+        cs4231_chip->perchip_info.record.active = 
+                cs4231_chip->perchip_info.record.pause = 0;
+
+        cs4231_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE |
+                                                      AUDIO_SPEAKER |
+                                                      AUDIO_LINE_OUT);
+
+        cs4231_chip->perchip_info.record.avail_ports = (AUDIO_INTERNAL_CD_IN |
+                                                        AUDIO_LINE_IN | 
+                                                        AUDIO_MICROPHONE |
+                                                        AUDIO_ANALOG_LOOPBACK);
+
+        /* Announce the hardware to the user. */
+        printk(KERN_INFO "audio%d: cs4231%c at %lx irq %s\n",
+               drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ', 
+               cs4231_chip->regs, __irq_itoa(cs4231_chip->irq));
   
-  /* Success! */
-  return 0;
+        /* Success! */
+        return 0;
 }
 
 #ifdef EB4231_SUPPORT
@@ -2200,89 +2220,86 @@
 static int eb4231_attach(struct sparcaudio_driver *drv, 
 			 struct linux_ebus_device *edev)
 {
-  struct cs4231_chip *cs4231_chip;
-  int len, err, nregs;
-  struct linux_prom_registers regs[4];
-
-  /* Allocate our private information structure. */
-  drv->private = kmalloc(sizeof(struct cs4231_chip), GFP_KERNEL);
-  if (!drv->private)
-    return -ENOMEM;
-
-  /* Point at the information structure and initialize it. */
-  drv->ops = &eb4231_ops;
-  cs4231_chip = (struct cs4231_chip *)drv->private;
-  cs4231_chip->input_ptr = cs4231_chip->output_ptr = NULL;
-  cs4231_chip->input_size = cs4231_chip->output_size = 0;
-  cs4231_chip->status = 0;
-
-  len = prom_getproperty(edev->prom_node, "reg", (void *)regs, sizeof(regs));
-
-  if ((len % sizeof(regs[0])) != 0) {
-    printk("eb4231: Strange reg property size %d\n", len);
-    return -ENODEV;
-  }
-
-  nregs = len / sizeof(regs[0]);
-
-  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;
-
-  /* Attach the interrupt handler to the audio interrupt. */
-  cs4231_chip->irq = edev->irqs[0];
-  cs4231_chip->irq2 = edev->irqs[1];
-
-  if(request_irq(cs4231_chip->irq, eb4231_cinterrupt, SA_SHIRQ, "cs4231", drv) ||
-     request_irq(cs4231_chip->irq2, eb4231_pinterrupt, SA_SHIRQ, "cs4231", drv))
-          goto bail;
-
-  cs4231_chip->nirqs = 2;
-
-  cs4231_enable_interrupts(drv);
-
-  /* Reset the audio chip. */
-  cs4231_chip_reset(drv);
-
-  /* Register ourselves with the midlevel audio driver. */
-  err = register_sparcaudio_driver(drv, 1);
-
-  if (err < 0) {
-  bail:
-    printk(KERN_ERR "cs4231: unable to register\n");
-    cs4231_disable_interrupts(drv);
-    disable_irq(cs4231_chip->irq);
-    free_irq(cs4231_chip->irq, drv);
-    disable_irq(cs4231_chip->irq2);
-    free_irq(cs4231_chip->irq2, drv);
-    kfree(drv->private);
-    return -EIO;
-  }
-
-  cs4231_chip->perchip_info.play.active = 
-    cs4231_chip->perchip_info.play.pause = 0;
-
-  cs4231_chip->perchip_info.record.active = 
-    cs4231_chip->perchip_info.record.pause = 0;
-
-  cs4231_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE |
-						AUDIO_SPEAKER |
-						AUDIO_LINE_OUT);
-
-  cs4231_chip->perchip_info.record.avail_ports = (AUDIO_INTERNAL_CD_IN |
-						  AUDIO_LINE_IN | 
-						  AUDIO_MICROPHONE |
-						  AUDIO_ANALOG_LOOPBACK);
-
-  /* Announce the hardware to the user. */
-  printk(KERN_INFO "audio%d: cs4231%c(eb2) at %p irq %s\n",
-         drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ', 
-	 cs4231_chip->regs, __irq_itoa(cs4231_chip->irq));
+        struct cs4231_chip *cs4231_chip;
+        int len, err, nregs;
+        struct linux_prom_registers regs[4];
+
+        /* Allocate our private information structure. */
+        drv->private = kmalloc(sizeof(struct cs4231_chip), GFP_KERNEL);
+        if (drv->private == NULL)
+                return -ENOMEM;
+
+        /* Point at the information structure and initialize it. */
+        drv->ops = &eb4231_ops;
+        cs4231_chip = (struct cs4231_chip *) drv->private;
+        cs4231_chip->input_ptr = cs4231_chip->output_ptr = NULL;
+        cs4231_chip->input_size = cs4231_chip->output_size = 0;
+        cs4231_chip->status = 0;
+
+        len = prom_getproperty(edev->prom_node, "reg", (void *)regs, sizeof(regs));
+        if ((len % sizeof(regs[0])) != 0) {
+                printk("eb4231: Strange reg property size %d\n", len);
+                return -ENODEV;
+        }
+
+        nregs = len / sizeof(regs[0]);
+        cs4231_chip->regs = (unsigned long)ioremap(edev->resource[0].start, 0x10);
+        cs4231_chip->eb2p = (unsigned long)ioremap(edev->resource[1].start, 0x10);
+        cs4231_chip->eb2c = (unsigned long)ioremap(edev->resource[2].start, 0x10);
+
+        cs4231_chip->status |= CS_STATUS_IS_EBUS;
+
+        /* Attach the interrupt handler to the audio interrupt. */
+        cs4231_chip->irq = edev->irqs[0];
+        cs4231_chip->irq2 = edev->irqs[1];
+
+        if(request_irq(cs4231_chip->irq, eb4231_cinterrupt, SA_SHIRQ, "cs4231", drv) ||
+           request_irq(cs4231_chip->irq2, eb4231_pinterrupt, SA_SHIRQ, "cs4231", drv))
+                goto bail;
+
+        cs4231_chip->nirqs = 2;
+        cs4231_enable_interrupts(drv);
+
+        /* Reset the audio chip. */
+        cs4231_chip_reset(drv);
+
+        /* Register ourselves with the midlevel audio driver. */
+        err = register_sparcaudio_driver(drv, 1);
+
+        if (err < 0) {
+        bail:
+                printk(KERN_ERR "cs4231: unable to register\n");
+                cs4231_disable_interrupts(drv);
+                disable_irq(cs4231_chip->irq);
+                free_irq(cs4231_chip->irq, drv);
+                disable_irq(cs4231_chip->irq2);
+                free_irq(cs4231_chip->irq2, drv);
+                kfree(drv->private);
+                return -EIO;
+        }
+
+        cs4231_chip->perchip_info.play.active = 
+                cs4231_chip->perchip_info.play.pause = 0;
+
+        cs4231_chip->perchip_info.record.active = 
+                cs4231_chip->perchip_info.record.pause = 0;
+
+        cs4231_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE |
+                                                      AUDIO_SPEAKER |
+                                                      AUDIO_LINE_OUT);
+
+        cs4231_chip->perchip_info.record.avail_ports = (AUDIO_INTERNAL_CD_IN |
+                                                        AUDIO_LINE_IN | 
+                                                        AUDIO_MICROPHONE |
+                                                        AUDIO_ANALOG_LOOPBACK);
+
+        /* Announce the hardware to the user. */
+        printk(KERN_INFO "audio%d: cs4231%c(eb2) at %lx irq %s\n",
+               drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ', 
+               cs4231_chip->regs, __irq_itoa(cs4231_chip->irq));
   
-  /* Success! */
-  return 0;
+        /* Success! */
+        return 0;
 }
 #endif
 
@@ -2293,62 +2310,65 @@
 int __init cs4231_init(void)
 #endif
 {
-  struct linux_sbus *sbus;
-  struct linux_sbus_device *sdev;
+        struct sbus_bus *sbus;
+        struct sbus_dev *sdev;
 #ifdef EB4231_SUPPORT
-  struct linux_ebus *ebus;
-  struct linux_ebus_device *edev;
+        struct linux_ebus *ebus;
+        struct linux_ebus_device *edev;
 #endif
 
-  num_drivers = 0;
+        num_drivers = 0;
   
-  /* Probe each SBUS for cs4231 chips. */
-  for_all_sbusdev(sdev,sbus) {
-    if (!strcmp(sdev->prom_name, "SUNW,CS4231")) {
-      /* Don't go over the max number of drivers. */
-      if (num_drivers >= MAX_DRIVERS)
-	continue;
+        /* Probe each SBUS for cs4231 chips. */
+        for_all_sbusdev(sdev, sbus) {
+                if (!strcmp(sdev->prom_name, "SUNW,CS4231")) {
+                        /* Don't go over the max number of drivers. */
+                        if (num_drivers >= MAX_DRIVERS)
+                                continue;
       
-      if (cs4231_attach(&drivers[num_drivers], sdev) == 0)
-	num_drivers++;
-    }
-  }
+                        if (cs4231_attach(&drivers[num_drivers], sdev) == 0)
+                                num_drivers++;
+                }
+        }
   
 #ifdef EB4231_SUPPORT
-  for_each_ebus(ebus) {
-    for_each_ebusdev(edev, ebus) {
-      if (!strcmp(edev->prom_name, "SUNW,CS4231")) {
-        /* Don't go over the max number of drivers. */
-        if (num_drivers >= MAX_DRIVERS)
-          continue;
+        for_each_ebus(ebus) {
+                for_each_ebusdev(edev, ebus) {
+                        if (!strcmp(edev->prom_name, "SUNW,CS4231")) {
+                                /* Don't go over the max number of drivers. */
+                                if (num_drivers >= MAX_DRIVERS)
+                                        continue;
       
-        if (eb4231_attach(&drivers[num_drivers], edev) == 0)
-          num_drivers++;
-      }
-    }
-  }
+                                if (eb4231_attach(&drivers[num_drivers], edev) == 0)
+                                        num_drivers++;
+                        }
+                }
+        }
 #endif
 
-  /* Only return success if we found some cs4231 chips. */
-  return (num_drivers > 0) ? 0 : -EIO;
+        /* Only return success if we found some cs4231 chips. */
+        return (num_drivers > 0) ? 0 : -EIO;
 }
 
 #ifdef MODULE
 /* Detach from an cs4231 chip given the device structure. */
 static void cs4231_detach(struct sparcaudio_driver *drv)
 {
-        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *) drv->private;
 
 	cs4231_disable_interrupts(drv);
         unregister_sparcaudio_driver(drv, 1);
         disable_irq(cs4231_chip->irq);
         free_irq(cs4231_chip->irq, drv);
         if (!(cs4231_chip->status & CS_STATUS_IS_EBUS)) {
-          sparc_free_io(cs4231_chip->regs, cs4231_chip->regs_size);
+                sbus_iounmap(cs4231_chip->regs, cs4231_chip->regs_size);
         } else {
 #ifdef EB4231_SUPPORT
-          disable_irq(cs4231_chip->irq2);
-          free_irq(cs4231_chip->irq2, drv);
+                iounmap(cs4231_chip->regs);
+                iounmap(cs4231_chip->eb2p);
+                iounmap(cs4231_chip->eb2c);
+                disable_irq(cs4231_chip->irq2);
+                free_irq(cs4231_chip->irq2, drv);
 #endif
         }
         kfree(drv->private);
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/cs4231.h linux/drivers/sbus/audio/cs4231.h
--- v2.3.34/linux/drivers/sbus/audio/cs4231.h	Tue Aug 31 17:29:14 1999
+++ linux/drivers/sbus/audio/cs4231.h	Mon Dec 20 22:06:42 1999
@@ -1,8 +1,9 @@
-/*
+/* $Id: cs4231.h,v 1.13 1999/09/21 14:37:27 davem Exp $
  * drivers/sbus/audio/cs4231.h
  *
  * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
  * Copyright (C) 1997 Derrick J. Brashear (shadow@dementia.org)
+ * Copyright (C) 1999 David S. Miller (davem@redhat.com)
  */
 
 #ifndef _CS4231_H_
@@ -11,78 +12,78 @@
 #include <linux/types.h>
 
 /* According to the CS4231A data provided on CS web site and sun's includes */
-
-struct cs4231_regs {
-  __volatile__ __u8 iar;            /* Index Address Register */
-  __volatile__ __u8 pad0[3];         
-  __volatile__ __u8 idr;            /* Indexed Data Register */
-  __volatile__ __u8 pad1[3];        
-  __volatile__ __u8 statr;          /* Status Register */
-  __volatile__ __u8 pad2[3];        
-  __volatile__ __u8 piodr;          /* PIO Data Register */
-  __volatile__ __u8 pad3[3];        
-  __volatile__ __u32 dmacsr;         /* APC CSR */
-  __volatile__ __u32 dmapad[3];        
-  __volatile__ __u32 dmacva;         /* Capture Virtual Address */
-  __volatile__ __u32 dmacc;          /* Capture Count */
-  __volatile__ __u32 dmacnva;        /* Capture Next Virtual Address */
-  __volatile__ __u32 dmacnc;         /* Capture Next Count */
-  __volatile__ __u32 dmapva;         /* Playback Virtual Address */
-  __volatile__ __u32 dmapc;          /* Playback Count */
-  __volatile__ __u32 dmapnva;        /* Playback Next Virtual Address */
-  __volatile__ __u32 dmapnc;         /* Playback Next Count */
-};
+#define IAR	0x00UL	/* Index Address Register */
+#define IDR	0x04UL	/* Index Data Register */
+#define STAT	0x08UL	/* Status Register */
+#define PIOD	0x0cUL	/* PIO Data Register */
+#define APCCSR	0x10UL	/* APC DMA CSR */
+#define APCCVA	0x20UL	/* APC Capture DMA Address */
+#define APCCC	0x24UL	/* APC Capture Count */
+#define APCCNVA	0x28UL	/* APC Capture DMA Next Address */
+#define APCCNC	0x2cUL	/* APC Capture Next Count */
+#define APCPVA	0x30UL	/* APC Play DMA Address */
+#define APCPC	0x34UL	/* APC Play Count */
+#define APCPNVA	0x38UL	/* APC Play DMA Next Address */
+#define APCPNC	0x3cUL	/* APC Play Next Count */
+
+/* EBUS DMA Registers */
+#define EBDMA_CSR	0x00UL	/* Control/Status */
+#define EBDMA_ADDR	0x04UL	/* DMA Address */
+#define EBDMA_COUNT	0x08UL	/* DMA Count */
 
 /* Our structure for each chip */
-
 struct cs4231_chip {
-  struct cs4231_regs *regs;
-  struct linux_ebus_dma *eb2c;
-  struct linux_ebus_dma *eb2p;
-  struct audio_info perchip_info;
-  unsigned int playlen, reclen;
-  int irq, irq2, nirqs;
-  unsigned long regs_size;
+	unsigned long regs;
+	unsigned long eb2c;
+	unsigned long eb2p;
+	struct audio_info perchip_info;
+	unsigned int playlen, reclen;
+	int irq, irq2, nirqs;
+	unsigned long regs_size;
   
-  /* Keep track of various info */
-  volatile unsigned int status;
+	/* Keep track of various info */
+	volatile unsigned int status;
   
-  /* Current buffer that the driver is playing. */
-  volatile __u8 * output_ptr;
-  volatile unsigned long output_size;
-  volatile __u32 output_dma_handle, output_next_dma_handle;
-  volatile unsigned long output_dma_size, output_next_dma_size;
-
-  /* Current record buffer. */
-  volatile __u8 * input_ptr;
-  volatile unsigned long input_size;
-  volatile __u32 input_dma_handle, input_next_dma_handle;
-  volatile unsigned long input_dma_size, input_next_dma_size;
-
-  /* Number of buffers in the pipe. */
-  volatile unsigned long playing_count;
-  volatile unsigned long recording_count;
+	/* Current buffer that the driver is playing. */
+	volatile __u8 * output_ptr;
+	volatile __u32 output_size;
+	volatile __u32 output_dma_handle, output_next_dma_handle;
+	volatile __u32 output_dma_size, output_next_dma_size;
+
+	/* Current record buffer. */
+	volatile __u8 * input_ptr;
+	volatile __u32 input_size;
+	volatile __u32 input_dma_handle, input_next_dma_handle;
+	volatile __u32 input_dma_size, input_next_dma_size;
+
+	/* Number of buffers in the pipe. */
+	volatile __u32 playing_count;
+	volatile __u32 recording_count;
 };
 
 #ifdef EB4231_SUPPORT
-#define CS4231_READ32(__C, __REG) \
-	(((__C)->status & CS_STATUS_IS_EBUS) ? readl((unsigned long)(__REG)) : (*(__REG)))
+#define CS4231_READ32(__C, __REG)		\
+	(((__C)->status & CS_STATUS_IS_EBUS) ?	\
+	readl((__REG)) :			\
+	sbus_readl((__REG)))
 #define CS4231_READ8(__C, __REG) \
-	(((__C)->status & CS_STATUS_IS_EBUS) ? readb((unsigned long)(__REG)) : (*(__REG)))
-#define CS4231_WRITE32(__C, __REG, __VAL) \
-	(((__C)->status & CS_STATUS_IS_EBUS) ? \
-         writel((__VAL), (unsigned long)(__REG)) : \
-         (*(__REG) = (__VAL)))
-#define CS4231_WRITE8(__C, __REG, __VAL) \
-	(((__C)->status & CS_STATUS_IS_EBUS) ? \
-         writeb((__VAL), (unsigned long)(__REG)) : \
-         (*(__REG) = (__VAL)))
+	(((__C)->status & CS_STATUS_IS_EBUS) ?	\
+	readb((__REG)) :			\
+	sbus_readb((__REG)))
+#define CS4231_WRITE32(__C, __REG, __VAL)	\
+	(((__C)->status & CS_STATUS_IS_EBUS) ?	\
+         writel((__VAL), (__REG)) :		\
+         sbus_writel((__VAL), (__REG)))
+#define CS4231_WRITE8(__C, __REG, __VAL)	\
+	(((__C)->status & CS_STATUS_IS_EBUS) ?	\
+         writeb((__VAL), (__REG)) :		\
+         sbus_writeb((__VAL), (__REG)))
 #else
 /* We can assume all is SBUS in this case. */
-#define CS4231_READ32(__C, __REG) (*(__REG))
-#define CS4231_READ8(__C, __REG) (*(__REG))
-#define CS4231_WRITE32(__C, __REG, __VAL) (*(__REG) = (__VAL))
-#define CS4231_WRITE8(__C, __REG, __VAL) (*(__REG) = (__VAL))
+#define CS4231_READ32(__C, __REG) sbus_readl((__REG))
+#define CS4231_READ8(__C, __REG) sbus_readb((__REG))
+#define CS4231_WRITE32(__C, __REG, __VAL) sbus_writel((__VAL), (__REG))
+#define CS4231_WRITE8(__C, __REG, __VAL) sbus_writeb((__VAL), (__REG))
 #endif
 
 /* Local status bits */
@@ -270,18 +271,26 @@
 #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) 
-
-#define APC_PLAY_SETUP  (APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | APC_XINT_PLAY | APC_XINT_EMPT | APC_XINT_GENL | APC_XINT_PENA | APC_PDMA_READY)
-
-#define APC_CAPT_SETUP  (APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL | APC_CDMA_READY)
+#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) 
+
+#define APC_PLAY_SETUP  (APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | \
+			 APC_XINT_PLAY | APC_XINT_EMPT | APC_XINT_GENL | \
+			 APC_XINT_PENA | APC_PDMA_READY)
+
+#define APC_CAPT_SETUP  (APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | \
+			 APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL | \
+			 APC_CDMA_READY)
 
 /* Following are EB2 CSR register definitions for the Sparc */
 
 /* asm/ebus.h has the base settings */
 
-#define EB2_PLAY_SETUP (EBUS_DCSR_BURST_SZ_8|EBUS_DCSR_INT_EN|EBUS_DCSR_EN_DMA|EBUS_DCSR_EN_CNT|EBUS_DCSR_TC)
-#define EB2_CAPT_SETUP (EBUS_DCSR_BURST_SZ_8|EBUS_DCSR_INT_EN|EBUS_DCSR_EN_DMA|EBUS_DCSR_EN_CNT|EBUS_DCSR_TC|EBUS_DCSR_WRITE)
+#define EB2_PLAY_SETUP (EBUS_DCSR_BURST_SZ_8 | EBUS_DCSR_INT_EN | EBUS_DCSR_EN_DMA | \
+			EBUS_DCSR_EN_CNT | EBUS_DCSR_TC)
+#define EB2_CAPT_SETUP (EBUS_DCSR_BURST_SZ_8 | EBUS_DCSR_INT_EN | EBUS_DCSR_EN_DMA| \
+			EBUS_DCSR_EN_CNT | EBUS_DCSR_TC | EBUS_DCSR_WRITE)
 
 #define CS4231_MIN_ATEN     (0)
 #define CS4231_MAX_ATEN     (31)
@@ -301,4 +310,4 @@
 
 #define CS4231_RATE   (8000)                /* default sample rate */
 
-#endif
+#endif /* _CS4231_H_ */
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/dbri.c linux/drivers/sbus/audio/dbri.c
--- v2.3.34/linux/drivers/sbus/audio/dbri.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/sbus/audio/dbri.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/*
+/* $Id: dbri.c,v 1.16 1999/11/19 09:56:05 davem Exp $
  * drivers/sbus/audio/dbri.c
  *
  * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
@@ -42,8 +42,6 @@
  * connected.
  */
 
-
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -151,42 +149,44 @@
 
 static int dbri_locked = 0;
 
-static volatile int * dbri_cmdlock(struct dbri *dbri)
+static volatile s32 *dbri_cmdlock(struct dbri *dbri)
 {
-        if (dbri_locked) {
+        if (dbri_locked)
                 printk("DBRI: Command buffer locked! (bug in driver)\n");
-        }
-        dbri_locked ++;
-        return dbri->dma->cmd;
+
+        dbri_locked++;
+        return &dbri->dma->cmd[0];
 }
 
 static void dbri_process_interrupt_buffer(struct dbri *);
 
-static void dbri_cmdsend(struct dbri *dbri, volatile int * cmd)
+static void dbri_cmdsend(struct dbri *dbri, volatile s32 *cmd)
 {
 	int MAXLOOPS = 1000000;
 	int maxloops = MAXLOOPS;
-	unsigned int flags;
-	volatile int * ptr;
+	unsigned long flags;
+	volatile s32 *ptr;
 
-	for (ptr = dbri->dma->cmd; ptr < cmd; ptr ++) {
-		dprintk(D_CMD, ("DBRI cmd: %08x:%08x\n",
-				(unsigned int) ptr, *ptr));
+	for (ptr = &dbri->dma->cmd[0]; ptr < cmd; ptr++) {
+		dprintk(D_CMD, ("DBRI cmd: %lx:%08x\n",
+				(unsigned long) ptr, *ptr));
 	}
 
 	save_and_cli(flags);
 
-        dbri_locked --;
+        dbri_locked--;
         if (dbri_locked != 0) {
                 printk("DBRI: Command buffer improperly locked! (bug in driver)\n");
-        } else if ((cmd - dbri->dma->cmd) >= DBRI_NO_CMDS-1) {
+        } else if ((cmd - &dbri->dma->cmd[0]) >= DBRI_NO_CMDS-1) {
                 printk("DBRI: Command buffer overflow! (bug in driver)\n");
         } else {
                 *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
 		*(cmd++) = DBRI_CMD(D_WAIT, 1, 0);
 		dbri->wait_seen = 0;
-                dbri->regs->reg8 = (int)dbri->dma_dvma->cmd;
-		while ((--maxloops) > 0 && (dbri->regs->reg0 & D_P));
+                sbus_writel(dbri->dma_dvma, dbri->regs + REG8);
+		while ((--maxloops) > 0 &&
+                       (sbus_readl(dbri->regs + REG0) & D_P))
+                        barrier();
 		if (maxloops == 0) {
 			printk("DBRI: Chip never completed command buffer\n");
 		} else {
@@ -195,7 +195,8 @@
 			if (maxloops == 0) {
 				printk("DBRI: Chip never acked WAIT\n");
 			} else {
-				dprintk(D_INT, ("DBRI: Chip completed command buffer (%d)\n",
+				dprintk(D_INT, ("DBRI: Chip completed command "
+                                                "buffer (%d)\n",
 						MAXLOOPS - maxloops));
 			}
 		}
@@ -209,11 +210,13 @@
 	int i;
 
 	dprintk(D_GEN, ("DBRI: reset 0:%x 2:%x 8:%x 9:%x\n",
-		dbri->regs->reg0, dbri->regs->reg2,
-		dbri->regs->reg8, dbri->regs->reg9)); 
+                        sbus_readl(dbri->regs + REG0),
+                        sbus_readl(dbri->regs + REG2),
+                        sbus_readl(dbri->regs + REG8),
+                        sbus_readl(dbri->regs + REG9)));
 
-	dbri->regs->reg0 = D_R; /* Soft Reset */
-	for(i = 0; (dbri->regs->reg0 & D_R) && i < 10; i++)
+	sbus_writel(D_R, dbri->regs + REG0); /* Soft Reset */
+	for(i = 0; (sbus_readl(dbri->regs + REG0) & D_R) && i < 64; i++)
 		udelay(10);
 }
 
@@ -221,42 +224,48 @@
 {
 	dbri_reset(dbri);
         free_irq(dbri->irq, dbri);
-        sparc_free_io(dbri->regs, dbri->regs_size);
-	release_region((unsigned long) dbri->dma, sizeof(struct dbri_dma));
+        sbus_iounmap(dbri->regs, dbri->regs_size);
+        sbus_free_consistant(dbri->sdev, sizeof(struct dbri_dma),
+                             dbri->dma, dbry->dma_dvma);
         kfree(dbri);
 }
 
-
 static void dbri_initialize(struct dbri *dbri)
 {
+	volatile s32 *cmd;
+        u32 dma_addr, tmp;
         int n;
-	volatile int *cmd;
 
         dbri_reset(dbri);
 
-	dprintk(D_GEN, ("DBRI: init: cmd: %x, int: %x\n",
-			(int)dbri->dma->cmd, (int)dbri->dma->intr));
+	dprintk(D_GEN, ("DBRI: init: cmd: %p, int: %p\n",
+			&dbri->dma->cmd[0], &dbri->dma->intr[0]));
 
 	/*
 	 * Initialize the interrupt ringbuffer.
 	 */
-	for(n = 0; n < DBRI_NO_INTS-1; n++)
-		dbri->dma->intr[n * DBRI_INT_BLK] = 
-                        (int)(&dbri->dma_dvma->intr[(n+1)*DBRI_INT_BLK]);
-	dbri->dma->intr[n * DBRI_INT_BLK] = (int)(dbri->dma_dvma->intr);
+	for(n = 0; n < DBRI_NO_INTS-1; n++) {
+                dma_addr = dbri->dma_dvma;
+                dma_addr += dbri_dma_off(intr, ((n+1) & DBRI_INT_BLK));
+		dbri->dma->intr[n * DBRI_INT_BLK] = dma_addr;
+        }
+        dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0);
+	dbri->dma->intr[n * DBRI_INT_BLK] = dma_addr;
 	dbri->dbri_irqp = 1;
 
         /* We should query the openprom to see what burst sizes this
          * SBus supports.  For now, just disable all SBus bursts */
-        dbri->regs->reg0 &= ~(D_G|D_S|D_E);
+        tmp = sbus_readl(dbri->regs + REG0);
+        tmp &= ~(D_G | D_S | D_E);
+        sbus_writel(tmp, dbri->regs + REG0);
 
 	/*
 	 * Set up the interrupt queue
 	 */
 	cmd = dbri_cmdlock(dbri);
-
+        dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0);
 	*(cmd++) = DBRI_CMD(D_IIQ, 0, 0);
-	*(cmd++) = (int)(dbri->dma_dvma->intr);
+	*(cmd++) = dma_addr;
 
         dbri_cmdsend(dbri, cmd);
 }
@@ -302,7 +311,8 @@
                 break;
         default:
                 printk("DBRI reverse_bytes: unsupported length\n");
-	}
+	};
+
 	return b;
 }
 
@@ -329,7 +339,6 @@
 	td = dbri->pipes[pipe].desc;
 
 	while (td >= 0) {
-
                 if (td >= DBRI_NO_DESCS) {
                         printk("DBRI: invalid td on pipe %d\n", pipe);
                         return;
@@ -344,11 +353,10 @@
 		dprintk(D_INT, ("DBRI: TD %d, status 0x%02x\n", td, status));
 
                 buffer = dbri->descs[td].buffer;
-                if (buffer) {
-                        mmu_release_scsi_one(sbus_dvma_addr(buffer),
-                                             dbri->descs[td].len,
-                                             dbri->sdev->my_bus);
-                }
+                if (buffer)
+                        sbus_unmap_single(dbri->sdev,
+                                          dbri->descs[td].buffer_dvma,
+                                          dbri->descs[td].len);
 
                 callback = dbri->descs[td].output_callback;
 		callback_arg = dbri->descs[td].output_callback_arg;
@@ -358,16 +366,15 @@
 		td = dbri->descs[td].next;
 		dbri->pipes[pipe].desc = td;
 
-		if (callback != NULL) {
+		if (callback != NULL)
 			callback(callback_arg, status & 0xe);
-		}
         }
 }
 
 static void reception_complete_intr(struct dbri *dbri, int pipe)
 {
         int rd = dbri->pipes[pipe].desc;
-        int status;
+        s32 status;
         void *buffer;
         void (*callback)(void *, int, unsigned int);
 
@@ -381,18 +388,16 @@
         status = dbri->dma->desc[rd].word1;
 
         buffer = dbri->descs[rd].buffer;
-        if (buffer) {
-                mmu_release_scsi_one(sbus_dvma_addr(buffer),
-                                     dbri->descs[rd].len,
-                                     dbri->sdev->my_bus);
-        }
+        if (buffer)
+                sbus_unmap_single(dbri->sdev,
+                                  dbri->descs[rd].buffer_dvma,
+                                  dbri->descs[rd].len);
 
         callback = dbri->descs[rd].input_callback;
-        if (callback != NULL) {
+        if (callback != NULL)
                 callback(dbri->descs[rd].input_callback_arg,
                          DBRI_RD_STATUS(status),
                          DBRI_RD_CNT(status)-2);
-        }
 
 	dprintk(D_INT, ("DBRI: Recv RD %d, status 0x%02x, len %d\n",
 			rd, DBRI_RD_STATUS(status), DBRI_RD_CNT(status)));
@@ -414,35 +419,29 @@
 			       channel, code, rval));
 	}
 
-	if (channel == D_INTR_CMD && command == D_WAIT) {
-		dbri->wait_seen ++;
-	}
+	if (channel == D_INTR_CMD && command == D_WAIT)
+		dbri->wait_seen++;
 
 	if (code == D_INTR_SBRI) {
-
 		/* SBRI - BRI status change */
+		const int liu_states[] = {1, 0, 8, 3, 4, 5, 6, 7};
 
-		int liu_states[] = {1, 0, 8, 3, 4, 5, 6, 7};
 		dbri->liu_state = liu_states[val & 0x7];
 		if (dbri->liu_callback)
 			dbri->liu_callback(dbri->liu_callback_arg);
 	}
 
-	if (code == D_INTR_BRDY) {
+	if (code == D_INTR_BRDY)
 		reception_complete_intr(dbri, channel);
-	}
 
-	if (code == D_INTR_XCMP) {
+	if (code == D_INTR_XCMP)
 		transmission_complete_intr(dbri, channel);
-	}
 
 	if (code == D_INTR_UNDR) {
-
 		/* UNDR - Transmission underrun
 		 * resend SDP command with clear pipe bit (C) set
 		 */
-
-		volatile int *cmd;
+		volatile s32 *cmd;
 		int pipe = channel;
 		int td = dbri->pipes[pipe].desc;
 
@@ -452,21 +451,17 @@
 		*(cmd++) = DBRI_CMD(D_SDP, 0,
 				    dbri->pipes[pipe].sdp
 				    | D_SDP_P | D_SDP_C | D_SDP_2SAME);
-		*(cmd++) = (int) & dbri->dma_dvma->desc[td];
+                *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, td);
 		dbri_cmdsend(dbri, cmd);
 	}
 
 	if (code == D_INTR_FXDT) {
-
 		/* FXDT - Fixed data change */
-
-		if (dbri->pipes[channel].sdp & D_SDP_MSB) {
+		if (dbri->pipes[channel].sdp & D_SDP_MSB)
 			val = reverse_bytes(val, dbri->pipes[channel].length);
-                }
 
-		if (dbri->pipes[channel].recv_fixed_ptr) {
-			* dbri->pipes[channel].recv_fixed_ptr = val;
-		}
+		if (dbri->pipes[channel].recv_fixed_ptr)
+			*(dbri->pipes[channel].recv_fixed_ptr) = val;
 	}
 }
 
@@ -477,15 +472,12 @@
  * order is important since we might recurse back into this function
  * and need to make sure the pointer has been advanced first.
  */
-
 static void dbri_process_interrupt_buffer(struct dbri *dbri)
 {
-	int x;
+	s32 x;
 
 	while ((x = dbri->dma->intr[dbri->dbri_irqp]) != 0) {
-
 		dbri->dma->intr[dbri->dbri_irqp] = 0;
-
 		dbri->dbri_irqp++;
 		if (dbri->dbri_irqp == (DBRI_NO_INTS * DBRI_INT_BLK))
 			dbri->dbri_irqp = 1;
@@ -498,17 +490,18 @@
 
 static void dbri_intr(int irq, void *opaque, struct pt_regs *regs)
 {
-	struct dbri *dbri = (struct dbri *)opaque;
+	struct dbri *dbri = (struct dbri *) opaque;
 	int x;
 	
 	/*
 	 * Read it, so the interrupt goes away.
 	 */
-	x = dbri->regs->reg1;
+	x = sbus_readl(dbri->regs + REG1);
 
 	dprintk(D_INT, ("DBRI: Interrupt!  (reg1=0x%08x)\n", x));
 
-	if ( x & (D_MRR|D_MLE|D_LBG|D_MBE) ) {
+	if (x & (D_MRR|D_MLE|D_LBG|D_MBE)) {
+                u32 tmp;
 
 		if(x & D_MRR) printk("DBRI: Multiple Error Ack on SBus\n");
 		if(x & D_MLE) printk("DBRI: Multiple Late Error on SBus\n");
@@ -524,8 +517,9 @@
 		 * If these things persist, we should probably reset
 		 * and re-init the chip.
 		 */
-
-		dbri->regs->reg0 &= ~D_D;
+                tmp = sbus_readl(dbri->regs + REG0);
+                tmp &= ~(D_D);
+                sbus_writel(tmp, dbri->regs + REG0);
 	}
 
 #if 0
@@ -551,7 +545,6 @@
 here interface closely with the transmit and receive interrupt code.
 
 */
-
 static int pipe_active(struct dbri *dbri, int pipe)
 {
 	return (dbri->pipes[pipe].desc != -1);
@@ -562,7 +555,6 @@
  *
  * Called on an in-use pipe to clear anything being transmitted or received
  */
-
 static void reset_pipe(struct dbri *dbri, int pipe)
 {
         int sdp;
@@ -597,21 +589,19 @@
 		void *input_callback_arg
 			= dbri->descs[desc].input_callback_arg;
 
-		if (buffer) {
-			mmu_release_scsi_one(sbus_dvma_addr(buffer),
-					     dbri->descs[desc].len,
-					     dbri->sdev->my_bus);
-		}
+		if (buffer)
+                        sbus_unmap_single(dbri->sdev,
+                                          dbri->descs[desc].buffer_dvma,
+                                          dbri->descs[desc].len);
 
 		dbri->descs[desc].inuse = 0;
 		desc = dbri->descs[desc].next;
 
-		if (output_callback) {
+		if (output_callback)
 			output_callback(output_callback_arg, -1);
-		}
-		if (input_callback) {
+
+		if (input_callback)
 			input_callback(input_callback_arg, -1, 0);
-		}
 	}
 
         dbri->pipes[pipe].desc = -1;
@@ -632,10 +622,8 @@
 	/* If this is a fixed receive pipe, arrange for an interrupt
 	 * every time its data changes
 	 */
-
-	if (D_SDP_MODE(sdp) == D_SDP_FIXED && ! (sdp & D_SDP_TO_SER)) {
+	if (D_SDP_MODE(sdp) == D_SDP_FIXED && ! (sdp & D_SDP_TO_SER))
 		sdp |= D_SDP_CHANGE;
-	}
 
         sdp |= D_PIPE(pipe);
         dbri->pipes[pipe].sdp = sdp;
@@ -648,7 +636,7 @@
 			   enum in_or_out direction, int basepipe,
 			   int length, int cycle)
 {
-        volatile int *cmd;
+        volatile s32 *cmd;
         int val;
 	int prevpipe;
 	int nextpipe;
@@ -668,23 +656,19 @@
 	 *  (where n = # of bit times per frame...) must be used."
 	 *                  - DBRI data sheet, page 11
 	 */
-
-	if (basepipe == 16 && direction == PIPEoutput && cycle == 0) {
+	if (basepipe == 16 && direction == PIPEoutput && cycle == 0)
 		cycle = dbri->chi_bpf;
-	}
 
 	if (basepipe == pipe) {
 		prevpipe = pipe;
 		nextpipe = pipe;
         } else {
-
 		/* We're not initializing a new linked list (basepipe != pipe),
 		 * so run through the linked list and find where this pipe
 		 * should be sloted in, based on its cycle.  CHI confuses
 		 * things a bit, since it has a single anchor for both its
 		 * transmit and receive lists.
                  */
-
 		if (basepipe == 16) {
 			if (direction == PIPEinput) {
 				prevpipe = dbri->chi_in_pipe;
@@ -736,12 +720,11 @@
 }
 
 /* I don't use this function, so it's basically untested. */
-
 static void unlink_time_slot(struct dbri *dbri, int pipe,
 			     enum in_or_out direction, int prevpipe,
 			     int nextpipe)
 {
-        volatile int *cmd;
+        volatile s32 *cmd;
         int val;
 
         if (pipe < 0 || pipe > 31 || prevpipe < 0 || prevpipe > 31) {
@@ -780,10 +763,9 @@
  * in the low-order 8 bits, filled either MSB-first or LSB-first,
  * depending on the settings passed to setup_pipe()
  */
-
 static void xmit_fixed(struct dbri *dbri, int pipe, unsigned int data)
 {
-        volatile int *cmd;
+        volatile s32 *cmd;
 
         if (pipe < 16 || pipe > 31) {
 		printk("DBRI: xmit_fixed: Illegal pipe number\n");
@@ -800,16 +782,15 @@
                 return;
         }
 
-        if (! dbri->pipes[pipe].sdp & D_SDP_TO_SER) {
+        if (! (dbri->pipes[pipe].sdp & D_SDP_TO_SER)) {
 		printk("DBRI: xmit_fixed: Called on receive pipe %d\n", pipe);
                 return;
         }
 
         /* DBRI short pipes always transmit LSB first */
 
-        if (dbri->pipes[pipe].sdp & D_SDP_MSB) {
+        if (dbri->pipes[pipe].sdp & D_SDP_MSB)
                 data = reverse_bytes(data, dbri->pipes[pipe].length);
-        }
 
         cmd = dbri_cmdlock(dbri);
 
@@ -855,17 +836,16 @@
  * data buffers.  Buffers too large for a single descriptor will
  * be spread across multiple descriptors.
  */
-
 static void xmit_on_pipe(struct dbri *dbri, int pipe,
                          void * buffer, unsigned int len,
                          void (*callback)(void *, int), void * callback_arg)
 {
-        volatile int *cmd;
-	register unsigned int flags;
+        volatile s32 *cmd;
+	unsigned long flags;
         int td = 0;
         int first_td = -1;
 	int last_td = -1;
-        __u32 dvma_buffer;
+        __u32 dvma_buffer, dvma_buffer_base;
 
         if (pipe < 0 || pipe > 15) {
 		printk("DBRI: xmit_on_pipe: Illegal pipe number\n");
@@ -877,26 +857,26 @@
                 return;
         }
 
-        if (! dbri->pipes[pipe].sdp & D_SDP_TO_SER) {
+        if (! (dbri->pipes[pipe].sdp & D_SDP_TO_SER)) {
 		printk("DBRI: xmit_on_pipe: Called on receive pipe %d\n",
 		       pipe);
                 return;
         }
 
-        dvma_buffer = mmu_get_scsi_one(buffer, len, dbri->sdev->my_bus);
-
+        dvma_buffer_base = dvma_buffer = sbus_map_single(dbri->sdev, buffer, len);
         while (len > 0) {
                 int mylen;
 
 		for (; td < DBRI_NO_DESCS; td ++) {
-                        if (! dbri->descs[td].inuse) break;
+                        if (! dbri->descs[td].inuse)
+                                break;
                 }
                 if (td == DBRI_NO_DESCS) {
 			printk("DBRI: xmit_on_pipe: No descriptors\n");
                         break;
                 }
 
-                if (len > (1 << 13) - 1) {
+                if (len > ((1 << 13) - 1)) {
                         mylen = (1 << 13) - 1;
                 } else {
                         mylen = len;
@@ -918,7 +898,7 @@
                 } else {
                         dbri->descs[last_td].next = td;
                         dbri->dma->desc[last_td].nda =
-                                (int) & dbri->dma_dvma->desc[td];
+                                dbri->dma_dvma + dbri_dma_off(desc, td);
                 }
 
                 last_td = td;
@@ -933,6 +913,7 @@
         dbri->dma->desc[last_td].word1 |= DBRI_TD_I | DBRI_TD_F | DBRI_TD_B;
 
         dbri->descs[last_td].buffer = buffer;
+        dbri->descs[last_td].buffer_dvma = dvma_buffer_base;
         dbri->descs[last_td].len = len;
         dbri->descs[last_td].output_callback = callback;
         dbri->descs[last_td].output_callback_arg = callback_arg;
@@ -949,39 +930,32 @@
 	save_and_cli(flags);
 
 	if (pipe_active(dbri, pipe)) {
-
 		/* Pipe is already active - find last TD in use
 		 * and link our first TD onto its end.  Then issue
 		 * a CDP command to let the DBRI know there's more data.
 		 */
-
 		last_td = dbri->pipes[pipe].desc;
 		while (dbri->descs[last_td].next != -1)
 			last_td = dbri->descs[last_td].next;
 
 		dbri->descs[last_td].next = first_td;
 		dbri->dma->desc[last_td].nda =
-			(int) & dbri->dma_dvma->desc[first_td];
+                        dbri->dma_dvma + dbri_dma_off(desc, first_td);
 
 		cmd = dbri_cmdlock(dbri);
 		*(cmd++) = DBRI_CMD(D_CDP, 0, pipe);
 		dbri_cmdsend(dbri,cmd);
-
 	} else {
-
 		/* Pipe isn't active - issue an SDP command to start
 		 * our chain of TDs running.
 		 */
-
 		dbri->pipes[pipe].desc = first_td;
-
 		cmd = dbri_cmdlock(dbri);
 		*(cmd++) = DBRI_CMD(D_SDP, 0,
 				    dbri->pipes[pipe].sdp
 				    | D_SDP_P | D_SDP_EVERY | D_SDP_C);
-		*(cmd++) = (int) & dbri->dma_dvma->desc[first_td];
+                *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td);
 		dbri_cmdsend(dbri, cmd);
-
 	}
 
 	restore_flags(flags);
@@ -992,11 +966,11 @@
                          void (*callback)(void *, int, unsigned int),
                          void * callback_arg)
 {
-        volatile int *cmd;
+        volatile s32 *cmd;
 	int first_rd = -1;
 	int last_rd = -1;
         int rd;
-	__u32 bus_buffer;
+	__u32 bus_buffer, bus_buffer_base;
 
         if (pipe < 0 || pipe > 15) {
 		printk("DBRI: recv_on_pipe: Illegal pipe number\n");
@@ -1017,7 +991,6 @@
         /* XXX Fix this XXX
 	 * Should be able to queue multiple buffers to receive on a pipe
          */
-
         if (dbri->pipes[pipe].desc != -1) {
 		printk("DBRI: recv_on_pipe: Called on active pipe %d\n", pipe);
                 return;
@@ -1026,20 +999,20 @@
         /* Make sure buffer size is multiple of four */
         len &= ~3;
 
-	bus_buffer = mmu_get_scsi_one(buffer, len, dbri->sdev->my_bus);
+        buf_buffer_base = buf_buffer = sbus_map_single(dbri->sdev, buffer, len);
 
 	while (len > 0) {
-		int rd;
-		int mylen;
+		int rd, mylen;
 
-		if (len > (1 << 13) - 4) {
+		if (len > ((1 << 13) - 4)) {
 			mylen = (1 << 13) - 4;
 		} else {
 			mylen = len;
 		}
 
 		for (rd = 0; rd < DBRI_NO_DESCS; rd ++) {
-			if (! dbri->descs[rd].inuse) break;
+			if (! dbri->descs[rd].inuse)
+                                break;
 		}
 		if (rd == DBRI_NO_DESCS) {
 			printk("DBRI recv_on_pipe: No descriptors\n");
@@ -1061,7 +1034,7 @@
 		if (first_rd == -1) first_rd = rd;
 		if (last_rd != -1) {
 			dbri->dma->desc[last_rd].nda =
-				(int) & dbri->dma_dvma->desc[rd];
+                                dbri->dma_dvma + dbri_dma_off(desc, rd);
 			dbri->descs[last_rd].next = rd;
 		}
 		last_rd = rd;
@@ -1070,9 +1043,8 @@
 		len -= mylen;
         }
 
-	if (last_rd == -1 || first_rd == -1) {
+	if (last_rd == -1 || first_rd == -1)
                 return;
-        }
 
 	for (rd=first_rd; rd != -1; rd = dbri->descs[rd].next) {
 		dprintk(D_DESC, ("DBRI RD %d: %08x %08x %08x %08x\n",
@@ -1084,6 +1056,7 @@
 	}
 
 	dbri->descs[last_rd].buffer = buffer;
+        dbri->descs[last_rd].buffer_dvma = bus_buffer_base;
 	dbri->descs[last_rd].len = len;
 	dbri->descs[last_rd].input_callback = callback;
 	dbri->descs[last_rd].input_callback_arg = callback_arg;
@@ -1093,7 +1066,7 @@
         cmd = dbri_cmdlock(dbri);
 
 	*(cmd++) = DBRI_CMD(D_SDP, 0, dbri->pipes[pipe].sdp | D_SDP_P | D_SDP_C);
-	*(cmd++) = (int) & dbri->dma_dvma->desc[first_rd];
+        *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_rd);
 
         dbri_cmdsend(dbri, cmd);
 }
@@ -1115,9 +1088,9 @@
 static void reset_chi(struct dbri *dbri, enum master_or_slave master_or_slave,
 		      int bits_per_frame)
 {
-	volatile int *cmd;
+	volatile s32 *cmd;
 	int val;
-	static int chi_initialized=0;
+	static int chi_initialized = 0;
 
 	if (!chi_initialized) {
 
@@ -1163,7 +1136,6 @@
 		dbri->chi_out_pipe = 16;
 
 		cmd = dbri_cmdlock(dbri);
-
 	}
 
 	if (master_or_slave == CHIslave) {
@@ -1181,13 +1153,11 @@
 		 * 12.288 MHz / CHICM_divisor	= clock rate
 		 * FD  =  1 - drive CHIFS on rising edge of CHICK
 		 */
-
 		int clockrate = bits_per_frame * 8;
 		int divisor   = 12288 / clockrate;
 
-		if (divisor > 255 || divisor * clockrate != 12288) {
+		if (divisor > 255 || divisor * clockrate != 12288)
 			printk("DBRI: illegal bits_per_frame in setup_chi\n");
-		}
 
 		*(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD
 				    | D_CHI_BPF(bits_per_frame));
@@ -1204,7 +1174,6 @@
 	 */
 
 	*(cmd++) = DBRI_CMD(D_PAUSE, 0, 0);
-
 	*(cmd++) = DBRI_CMD(D_CDM, 0, D_CDM_XCE|D_CDM_XEN|D_CDM_REN);
 
 	dbri_cmdsend(dbri, cmd);
@@ -1219,8 +1188,6 @@
 to the DBRI via the CHI interface and few of the DBRI's PIO pins.
 
 */
-
-
 static void mmcodec_default(struct cs4215 *mm)
 {
 	/*
@@ -1312,6 +1279,7 @@
 static void mmcodec_init_data(struct dbri *dbri)
 {
 	int data_width;
+        u32 tmp;
 
 	/*
 	 * Data mode:
@@ -1326,13 +1294,14 @@
          * bits.  The CS4215, it seems, observes TSIN (the delayed signal)
          * even if it's the CHI master.  Don't ask me...
 	 */
-
-
-	dbri->regs->reg0 &= ~D_C;	/* Disable CHI */
+        tmp = sbus_readl(dbri->regs + REG0);
+        tmp &= ~(D_C);	/* Disable CHI */
+        sbus_writel(tmp, dbri->regs + REG0);
 
         /* Switch CS4215 to data mode - set PIO3 to 1 */
-	dbri->regs->reg2 = D_ENPIO | D_PIO1 | D_PIO3 |
-				(dbri->mm.onboard ? D_PIO0 : D_PIO2);
+        sbus_writel(D_ENPIO | D_PIO1 | D_PIO3 |
+                    (dbri->mm.onboard ? D_PIO0 : D_PIO2),
+                    dbri->regs + REG2);
 
 	reset_chi(dbri, CHIslave, 128);
 
@@ -1357,16 +1326,18 @@
 
 	mmcodec_setgain(dbri, 0);
 
-	dbri->regs->reg0 |= D_C;	/* Enable CHI */
+        tmp = sbus_readl(dbri->regs + REG0);
+	tmp |= D_C;	/* Enable CHI */
+        sbus_writel(tmp, dbri->regs + REG0);
 }
 
-
 /*
  * Send the control information (i.e. audio format)
  */
 static int mmcodec_setctrl(struct dbri *dbri)
 {
 	int i, val;
+        u32 tmp;
 
 	/* XXX - let the CPU do something useful during these delays */
 
@@ -1382,7 +1353,7 @@
 	 * 12 cycles <= 12/(5512.5*64) sec = 34.01 usec
 	 */
 	val = D_ENPIO | D_PIO1 | (dbri->mm.onboard ? D_PIO0 : D_PIO2);
-	dbri->regs->reg2 = val;
+	sbus_writel(val, dbri->regs + REG2);
 	udelay(34);
 
         /* In Control mode, the CS4215 is a slave device, so the DBRI must
@@ -1403,8 +1374,9 @@
          * done in hardware by a TI 248 that delays the DBRI->4215
          * frame sync signal by eight clock cycles.  Anybody know why?
          */
-
-	dbri->regs->reg0 &= ~D_C;	/* Disable CHI */
+        tmp = sbus_readl(dbri->regs + REG0);
+	tmp &= ~D_C;	/* Disable CHI */
+        sbus_writel(tmp, dbri->regs + REG0);
 
         reset_chi(dbri, CHImaster, 128);
 
@@ -1427,10 +1399,13 @@
 	dbri->mm.ctrl[0] &= ~CS4215_CLB;
         xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl);
 
-	dbri->regs->reg0 |= D_C;	/* Enable CHI */
-
-	i = 10;
-	while (((dbri->mm.status & 0xe4) != 0x20) && --i) udelay(125);
+        tmp = sbus_readl(dbri->regs + REG0);
+        tmp |= D_C;	/* Enable CHI */
+        sbus_writel(tmp, dbri->regs + REG0);
+
+	i = 64;
+	while (((dbri->mm.status & 0xe4) != 0x20) && --i)
+                udelay(125);
         if (i == 0) {
 		dprintk(D_MM, ("DBRI: CS4215 didn't respond to CLB (0x%02x)\n",
 			       dbri->mm.status));
@@ -1440,7 +1415,6 @@
         /* Terminate CS4215 control mode - data sheet says
          * "Set CLB=1 and send two more frames of valid control info"
          */
-
 	dbri->mm.ctrl[0] |= CS4215_CLB;
         xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl);
 
@@ -1454,9 +1428,8 @@
 
 static int mmcodec_init(struct sparcaudio_driver *drv)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
-	int reg2 = dbri->regs->reg2;
-
+	struct dbri *dbri = (struct dbri *) drv->private;
+	u32 reg2 = sbus_readl(dbri->regs + REG2);
 
 	/* Look for the cs4215 chips */
 	if(reg2 & D_PIO2) {
@@ -1472,10 +1445,11 @@
 	/* Using the Speakerbox, if both are attached.  */
 	if((reg2 & D_PIO2) && (reg2 & D_PIO0)) {
 		printk("DBRI: Using speakerbox / ignoring onboard mmcodec.\n");
-		dbri->regs->reg2 = D_ENPIO2;
+		sbus_writel(D_ENPIO2, dbri->regs + REG2);
 		dbri->mm.onboard = 0;
 	}
-	if( !(reg2 & (D_PIO0|D_PIO2)) ) {
+
+	if(!(reg2 & (D_PIO0|D_PIO2))) {
 		printk("DBRI: no mmcodec found.\n");
 		return -EIO;
 	}
@@ -1519,27 +1493,23 @@
 */
 
 /******************* sparcaudio midlevel - audio output *******************/
-
-
 static void dbri_audio_output_callback(void * callback_arg, int status)
 {
         struct sparcaudio_driver *drv = callback_arg;
 
-	if (status != -1) {
+	if (status != -1)
 		sparcaudio_output_done(drv, 1);
-	}
 }
 
 static void dbri_start_output(struct sparcaudio_driver *drv,
                               __u8 * buffer, unsigned long count)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
-	dprintk(D_USR, ("DBRI: start audio output buf=%lx/%ld\n",
-			(unsigned long) buffer, count));
+	dprintk(D_USR, ("DBRI: start audio output buf=%p/%ld\n",
+			buffer, count));
 
         /* Pipe 4 is audio transmit */
-
 	xmit_on_pipe(dbri, 4, buffer, count,
 		     &dbri_audio_output_callback, drv);
 
@@ -1559,12 +1529,11 @@
 
 	sparcaudio_output_done(drv, 2);
 #endif
-
 }
 
 static void dbri_stop_output(struct sparcaudio_driver *drv)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
         reset_pipe(dbri, 4);
 }
@@ -1577,26 +1546,25 @@
 	struct sparcaudio_driver * drv =
 		(struct sparcaudio_driver *) callback_arg;
 
-	if (status != -1) {
+	if (status != -1)
 		sparcaudio_input_done(drv, 3);
-	}
 }
 
 static void dbri_start_input(struct sparcaudio_driver *drv,
                              __u8 * buffer, unsigned long len)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	/* Pipe 6 is audio receive */
 	recv_on_pipe(dbri, 6, buffer, len,
 		     &dbri_audio_input_callback, (void *)drv);
-	dprintk(D_USR, ("DBRI: start audio input buf=%lx/%ld\n",
-			(unsigned long) buffer, len));
+	dprintk(D_USR, ("DBRI: start audio input buf=%p/%ld\n",
+			buffer, len));
 }
 
 static void dbri_stop_input(struct sparcaudio_driver *drv)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	reset_pipe(dbri, 6);
 }
@@ -1605,7 +1573,7 @@
 
 static int dbri_set_output_volume(struct sparcaudio_driver *drv, int volume)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	dbri->perchip_info.play.gain = volume;
 	mmcodec_setgain(dbri, 0);
@@ -1615,7 +1583,7 @@
 
 static int dbri_get_output_volume(struct sparcaudio_driver *drv)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	return dbri->perchip_info.play.gain;
 }
@@ -1642,7 +1610,7 @@
 
 static int dbri_set_output_balance(struct sparcaudio_driver *drv, int balance)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	dbri->perchip_info.play.balance = balance;
 	mmcodec_setgain(dbri, 0);
@@ -1652,7 +1620,7 @@
 
 static int dbri_get_output_balance(struct sparcaudio_driver *drv)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	return dbri->perchip_info.play.balance;
 }
@@ -1669,7 +1637,7 @@
 
 static int dbri_set_output_muted(struct sparcaudio_driver *drv, int mute)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	dbri->perchip_info.output_muted = mute;
 
@@ -1678,7 +1646,7 @@
 
 static int dbri_get_output_muted(struct sparcaudio_driver *drv)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	return dbri->perchip_info.output_muted;
 }
@@ -1687,7 +1655,7 @@
 
 static int dbri_set_output_channels(struct sparcaudio_driver *drv, int chan)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	switch (chan) {
 	case 0:
@@ -1710,7 +1678,7 @@
 
 static int dbri_get_output_channels(struct sparcaudio_driver *drv)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	return dbri->perchip_info.play.channels;
 }
@@ -1732,7 +1700,7 @@
 
 static int dbri_get_output_precision(struct sparcaudio_driver *drv)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	return dbri->perchip_info.play.precision;
 }
@@ -1744,14 +1712,14 @@
 
 static int dbri_get_input_precision(struct sparcaudio_driver *drv)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	return dbri->perchip_info.play.precision;
 }
 
 static int dbri_set_output_encoding(struct sparcaudio_driver *drv, int enc)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	/* For ULAW and ALAW, audio.c enforces precision = 8,
 	 * for LINEAR, precision must be 16
@@ -1780,7 +1748,8 @@
 		break;
 	default:
 		return -1;
-	}
+	};
+
 	mmcodec_setctrl(dbri);
 	mmcodec_init_data(dbri);
         return 0;
@@ -1788,7 +1757,7 @@
 
 static int dbri_get_output_encoding(struct sparcaudio_driver *drv)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	return dbri->perchip_info.play.encoding;
 }
@@ -1805,19 +1774,19 @@
 
 static int dbri_set_output_rate(struct sparcaudio_driver *drv, int rate)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 	int i;
 
-	if (rate == 0) {
+	if (rate == 0)
 		return 0;
-	}
 
 	for (i=0; CS4215_FREQ[i].freq; i++) {
-		if (CS4215_FREQ[i].freq == rate) break;
+		if (CS4215_FREQ[i].freq == rate)
+                        break;
 	}
-	if (CS4215_FREQ[i].freq == 0) {
+
+	if (CS4215_FREQ[i].freq == 0)
 		return -1;
-	}
 
 	dbri->mm.ctrl[1] &= ~ 0x38;
 	dbri->mm.ctrl[1] |= CS4215_FREQ[i].csval;
@@ -1833,7 +1802,7 @@
 
 static int dbri_get_output_rate(struct sparcaudio_driver *drv)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	return dbri->perchip_info.play.sample_rate;
 }
@@ -1885,7 +1854,7 @@
 static void dbri_audio_getdev(struct sparcaudio_driver *drv,
 			      audio_device_t *audinfo)
 {
-	struct dbri *dbri = (struct dbri *)drv->private;
+	struct dbri *dbri = (struct dbri *) drv->private;
 
 	strncpy(audinfo->name, "SUNW,DBRI", sizeof(audinfo->name) - 1);
 
@@ -1907,13 +1876,11 @@
 {
 	MOD_INC_USE_COUNT;
 
-        /*
-	 * I've 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_balance(drv, AUDIO_MID_BALANCE);
-	dbri_set_output_volume(drv, AUDIO_MAX_GAIN/2);
+	dbri_set_output_volume(drv, AUDIO_MAX_GAIN / 2);
 
 	return 0;
 }
@@ -1985,8 +1952,6 @@
 ************************** ISDN (Hisax) Interface **************************
 ****************************************************************************
 */
-
-
 void dbri_isdn_init(struct dbri *dbri)
 {
         /* Pipe  0: Receive D channel
@@ -2018,9 +1983,8 @@
 {
        struct dbri *dbri;
 
-       if (dev >= num_drivers) {
+       if (dev >= num_drivers)
                return(0);
-       }
 
        dbri = (struct dbri *) drivers[dev].private;
 
@@ -2034,9 +1998,8 @@
 {
        struct dbri *dbri;
 
-       if (dev >= num_drivers) {
+       if (dev >= num_drivers)
                return(0);
-       }
 
        dbri = (struct dbri *) drivers[dev].private;
 
@@ -2051,9 +2014,8 @@
 {
        struct dbri *dbri;
 
-       if (dev >= num_drivers) {
+       if (dev >= num_drivers)
                return;
-       }
 
        dbri = (struct dbri *) drivers[dev].private;
 
@@ -2071,17 +2033,17 @@
 {
        struct dbri *dbri;
        int val;
-       volatile int *cmd;
+       volatile s32 *cmd;
 
-       if (dev >= num_drivers) {
+       if (dev >= num_drivers)
                return;
-       }
 
        dbri = (struct dbri *) drivers[dev].private;
 
        tprintk(("dbri_liu_activate()\n"));
 
        if (dbri->liu_state <= 3) {
+               u32 tmp;
 
 	       cmd = dbri_cmdlock(dbri);
 
@@ -2095,38 +2057,41 @@
 	       dbri_cmdsend(dbri, cmd);
 
 	       /* Activate the interface */
-	       dbri->regs->reg0 |= D_T;
+               tmp = sbus_readl(dbri->regs + REG0);
+               tmp |= D_T;
+               sbus_writel(tmp, dbri->regs + REG0);
        }
 }
 
 void dbri_liu_deactivate(int dev)
 {
        struct dbri *dbri;
+       u32 tmp;
 
-       if (dev >= num_drivers) {
+       if (dev >= num_drivers)
                return;
-       }
 
        dbri = (struct dbri *) drivers[dev].private;
 
        tprintk(("dbri_liu_deactivate()\n"));
 
 #if 0
-        /* Turn off the ISDN TE interface */
-        dbri->regs->reg0 &= ~D_T;
+       /* Turn off the ISDN TE interface */
+       tmp = sbus_readl(dbri->regs + REG0);
+       tmp &= ~D_T;
+       sbus_writel(tmp, dbri->regs + REG0);
 
-	dbri->liu_state = 0;
+       dbri->liu_state = 0;
 #endif
 }
 
 void dbri_dxmit(int dev, __u8 *buffer, unsigned int count,
-                       void (*callback)(void *, int), void *callback_arg)
+                void (*callback)(void *, int), void *callback_arg)
 {
        struct dbri *dbri;
 
-       if (dev >= num_drivers) {
+       if (dev >= num_drivers)
                return;
-       }
 
        dbri = (struct dbri *) drivers[dev].private;
 
@@ -2135,14 +2100,13 @@
 }
 
 void dbri_drecv(int dev, __u8 *buffer, unsigned int size,
-                       void (*callback)(void *, int, unsigned int),
-                       void *callback_arg)
+                void (*callback)(void *, int, unsigned int),
+                void *callback_arg)
 {
        struct dbri *dbri;
 
-       if (dev >= num_drivers) {
+       if (dev >= num_drivers)
                return;
-       }
 
        dbri = (struct dbri *) drivers[dev].private;
 
@@ -2155,14 +2119,12 @@
 {
        struct dbri *dbri;
 
-       if (dev >= num_drivers || chan > 1) {
+       if (dev >= num_drivers || chan > 1)
                return -1;
-       }
 
        dbri = (struct dbri *) drivers[dev].private;
 
        if (hdlcmode) {
-
                /* return -1; */
 
                /* Pipe 8/9: receive B1/B2 channel */
@@ -2170,15 +2132,12 @@
 
                /* Pipe 10/11: transmit B1/B2 channel */
                setup_pipe(dbri,10+chan, D_SDP_HDLC | D_SDP_TO_SER | D_SDP_LSB);
-
        } else {        /* !hdlcmode means transparent */
-
                /* Pipe 8/9: receive B1/B2 channel */
                setup_pipe(dbri, 8+chan, D_SDP_MEM | D_SDP_FROM_SER|D_SDP_LSB);
 
                /* Pipe 10/11: transmit B1/B2 channel */
                setup_pipe(dbri,10+chan, D_SDP_MEM | D_SDP_TO_SER | D_SDP_LSB);
-
        }
        return 0;
 }
@@ -2187,9 +2146,8 @@
 {
        struct dbri *dbri;
 
-       if (dev >= num_drivers || chan > 1) {
+       if (dev >= num_drivers || chan > 1)
                return;
-       }
 
        dbri = (struct dbri *) drivers[dev].private;
 
@@ -2198,15 +2156,14 @@
 }
 
 void dbri_bxmit(int dev, unsigned int chan,
-                       __u8 *buffer, unsigned long count,
-                       void (*callback)(void *, int),
-                       void *callback_arg)
+                __u8 *buffer, unsigned long count,
+                void (*callback)(void *, int),
+                void *callback_arg)
 {
        struct dbri *dbri;
 
-       if (dev >= num_drivers || chan > 1) {
+       if (dev >= num_drivers || chan > 1)
                return;
-       }
 
        dbri = (struct dbri *) drivers[dev].private;
 
@@ -2215,15 +2172,14 @@
 }
 
 void dbri_brecv(int dev, unsigned int chan,
-                       __u8 *buffer, unsigned long size,
-                       void (*callback)(void *, int, unsigned int),
-                       void *callback_arg)
+                __u8 *buffer, unsigned long size,
+                void (*callback)(void *, int, unsigned int),
+                void *callback_arg)
 {
        struct dbri *dbri;
 
-       if (dev >= num_drivers || chan > 1) {
+       if (dev >= num_drivers || chan > 1)
                return;
-       }
 
        dbri = (struct dbri *) drivers[dev].private;
 
@@ -2255,7 +2211,7 @@
 */
 
 static int dbri_attach(struct sparcaudio_driver *drv, 
-			 struct linux_sbus_device *sdev)
+                       struct sbus_dev *sdev)
 {
 	struct dbri *dbri;
 	struct linux_prom_irqs irq;
@@ -2270,36 +2226,33 @@
 
 	drv->ops = &dbri_ops;
 	drv->private = kmalloc(sizeof(struct dbri), GFP_KERNEL);
-	if (!drv->private)
+	if (drv->private == NULL)
 		return -ENOMEM;
-	dbri = (struct dbri *)drv->private;
 
+	dbri = (struct dbri *) drv->private;
         memset(dbri, 0, sizeof(*dbri));
 
-        /* sparc_dvma_malloc() will halt the kernel if the malloc fails */
-        dbri->dma = sparc_dvma_malloc (sizeof (struct dbri_dma),
-                                       "DBRI DMA Cmd Block", &dma_dvma);
-        dbri->dma_dvma = (struct dbri_dma *) dma_dvma;
+        dbri->dma = sbus_alloc_consistant(sdev,
+                                          sizeof(struct dbri_dma),
+                                          &dbri->dma_dvma);
 
 	memset((void *) dbri->dma, 0, sizeof(struct dbri_dma));
 
-	dprintk(D_GEN, ("DBRI: DMA Cmd Block 0x%08x (0x%08x)\n",
-			(int)dbri->dma, (int)dbri->dma_dvma));
+	dprintk(D_GEN, ("DBRI: DMA Cmd Block 0x%p (0x%08x)\n",
+			dbri->dma, dbri->dma_dvma));
 
 	dbri->dbri_version = sdev->prom_name[9];
         dbri->sdev = sdev;
 
 	/* Map the registers into memory. */
-	prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], 
-		sdev->num_registers, sdev);
 	dbri->regs_size = sdev->reg_addrs[0].reg_size;
-	dbri->regs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
-		sdev->reg_addrs[0].reg_size, 
-		"DBRI Registers", sdev->reg_addrs[0].which_io, 0);
+        dbri->regs = sbus_ioremap(&sdev->resource[0], 0,
+                                  sdev->reg_addrs[0].reg_size,
+                                  "DBRI Registers");
 	if (!dbri->regs) {
 		printk(KERN_ERR "DBRI: could not allocate registers\n");
-		release_region((unsigned long) dbri->dma,
-			       sizeof(struct dbri_dma));
+                sbus_free_consistant(sdev, sizeof(struct dbri_dma),
+                                     dbri->dma, dbri->dma_dvma);
 		kfree(drv->private);
 		return -EIO;
 	}
@@ -2311,9 +2264,9 @@
                           "DBRI audio/ISDN", dbri);
 	if (err) {
 		printk(KERN_ERR "DBRI: Can't get irq %d\n", dbri->irq);
-		sparc_free_io(dbri->regs, dbri->regs_size);
-		release_region((unsigned long) dbri->dma,
-			       sizeof(struct dbri_dma));
+                sbus_iounmap(dbri->regs, dbri->regs_size);
+                sbus_free_consistant(sdev, sizeof(struct dbri_dma),
+                                     dbri->dma, dbri->dma_dvma);
 		kfree(drv->private);
 		return err;
 	}
@@ -2337,7 +2290,7 @@
 	dbri->perchip_info.record.active = dbri->perchip_info.record.pause = 0;
 
 	printk(KERN_INFO "audio%d at 0x%lx (irq %d) is DBRI(%c)+CS4215(%d)\n",
-	       num_drivers, (unsigned long)dbri->regs,
+	       num_drivers, dbri->regs,
 	       dbri->irq, dbri->dbri_version, dbri->mm.version);
 	
 	return 0;
@@ -2350,13 +2303,13 @@
 int __init dbri_init(void)
 #endif
 {
-	struct linux_sbus *bus;
-	struct linux_sbus_device *sdev;
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev;
   
 	num_drivers = 0;
   
 	/* Probe each SBUS for the DBRI chip(s). */
-	for_all_sbusdev(sdev,bus) {
+	for_all_sbusdev(sdev, sbus) {
 		/*
 		 * The version is coded in the last character
 		 */
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/dbri.h linux/drivers/sbus/audio/dbri.h
--- v2.3.34/linux/drivers/sbus/audio/dbri.h	Thu Jun 17 01:08:50 1999
+++ linux/drivers/sbus/audio/dbri.h	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/*
+/* $Id: dbri.h,v 1.12 1999/09/21 14:37:34 davem Exp $
  * drivers/sbus/audio/cs4231.h
  *
  * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
@@ -9,15 +9,13 @@
 
 #include <linux/types.h>
 
-struct dbri_regs {
-  __volatile__ __u32 reg0;		/* Status & Control */
-  __volatile__ __u32 reg1;		/* Mode & Interrupt */
-  __volatile__ __u32 reg2;		/* Parallel IO */
-  __volatile__ __u32 reg3;		/* Test */
-  __volatile__ __u32 unused[4];
-  __volatile__ __u32 reg8;		/* Command Queue Pointer */
-  __volatile__ __u32 reg9;		/* Interrupt Queue Pointer */
-};
+/* DBRI main registers */
+#define REG0	0x00UL		/* Status and Control */
+#define REG1	0x04UL		/* Mode and Interrupt */
+#define REG2	0x08UL		/* Parallel IO */
+#define REG3	0x0cUL		/* Test */
+#define REG8	0x20UL		/* Command Queue Pointer */
+#define REG9	0x24UL		/* Interrupt Queue Pointer */
 
 #define DBRI_NO_CMDS	64
 #define DBRI_NO_INTS	2
@@ -28,10 +26,10 @@
 #define DBRI_MM_SB	2
 
 struct dbri_mem {
-	__u32	word1;
-	__u32	ba;			/* Transmit/Receive Buffer Address */
-	__u32	nda;			/* Next Descriptor Address */
-	__u32	word4;
+	volatile __u32	word1;
+	volatile __u32	ba;			/* Transmit/Receive Buffer Address */
+	volatile __u32	nda;			/* Next Descriptor Address */
+	volatile __u32	word4;
 };
 
 #include "cs4215.h"
@@ -39,13 +37,16 @@
 /* This structure is in a DMA region where it can accessed by both
  * the CPU and the DBRI
  */
-
 struct dbri_dma {
-  int cmd[DBRI_NO_CMDS];			/* Place for commands */
-  int intr[DBRI_NO_INTS * DBRI_INT_BLK];	/* Interrupt field */
-  struct dbri_mem desc[DBRI_NO_DESCS];		/* Xmit/receive descriptors */
+	volatile s32 cmd[DBRI_NO_CMDS];			/* Place for commands */
+	volatile s32 intr[DBRI_NO_INTS * DBRI_INT_BLK];	/* Interrupt field */
+	struct dbri_mem desc[DBRI_NO_DESCS];		/* Xmit/receive descriptors */
 };
 
+#define dbri_dma_off(member, elem)	\
+	((u32)(unsigned long)		\
+	 (&(((struct dbri_dma *)0)->member[elem])))
+
 enum in_or_out { PIPEinput, PIPEoutput };
 
 enum direction { in, out };
@@ -64,7 +65,8 @@
 struct dbri_desc {
         int inuse;				/* Boolean flag */
         int next;				/* Index of next desc, or -1 */
-        void *buffer;
+        void *buffer;				/* CPU view of buffer */
+	u32 buffer_dvma;			/* Device view */
         unsigned int len;
         void (*output_callback)(void *, int);
         void *output_callback_arg;
@@ -75,37 +77,37 @@
 /* This structure holds the information for both chips (DBRI & CS4215) */
 
 struct dbri {
-  int regs_size, irq;				/* Needed for unload */
-  struct linux_sbus_device *sdev;
+	int regs_size, irq;		/* Needed for unload */
+	struct sbus_dev *sdev;		/* SBUS device info */
 
-  volatile struct dbri_dma *dma;		/* Pointer to our DMA block */
-  struct dbri_dma *dma_dvma;			/* DBRI visible DMA address */
+	volatile struct dbri_dma *dma;	/* Pointer to our DMA block */
+	u32 dma_dvma;			/* DBRI visible DMA address */
 
-  struct dbri_regs *regs;			/* dbri HW regs */
-  int dbri_version;				/* 'e' and up is OK */
-  int dbri_irqp;				/* intr queue pointer */
-  int wait_seen;
+	unsigned long regs;		/* dbri HW regs */
+	int dbri_version;		/* 'e' and up is OK */
+	int dbri_irqp;			/* intr queue pointer */
+	int wait_seen;
 
-  struct dbri_pipe pipes[32];			/* DBRI's 32 data pipes */
-  struct dbri_desc descs[DBRI_NO_DESCS];
+	struct dbri_pipe pipes[32];	/* DBRI's 32 data pipes */
+	struct dbri_desc descs[DBRI_NO_DESCS];
 
-  int chi_in_pipe;
-  int chi_out_pipe;
-  int chi_bpf;
+	int chi_in_pipe;
+	int chi_out_pipe;
+	int chi_bpf;
 
-  struct cs4215 mm;				/* mmcodec special info */
+	struct cs4215 mm;		/* mmcodec special info */
 
 #if 0
-  wait_queue_head_t wait, int_wait;		/* Where to sleep if busy */
+	/* Where to sleep if busy */
+	wait_queue_head_t wait, int_wait;
 #endif
-  struct audio_info perchip_info;
+	struct audio_info perchip_info;
 
-  /* Track ISDN LIU and notify changes */
-  int liu_state;
-  void (*liu_callback)(void *);
-  void *liu_callback_arg;
+	/* Track ISDN LIU and notify changes */
+	int liu_state;
+	void (*liu_callback)(void *);
+	void *liu_callback_arg;
 };
-
 
 /* DBRI Reg0 - Status Control Register - defines. (Page 17) */
 #define D_P		(1<<15)	/* Program command & queue pointer valid */
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/dmy.c linux/drivers/sbus/audio/dmy.c
--- v2.3.34/linux/drivers/sbus/audio/dmy.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/sbus/audio/dmy.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/*
+/* $Id: dmy.c,v 1.5 1999/09/21 14:37:37 davem Exp $
  * drivers/sbus/audio/dummy.c
  *
  * Copyright 1998 Derrick J Brashear (shadow@andrew.cmu.edu)
@@ -41,543 +41,614 @@
 static int
 dummy_set_output_encoding(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  if (value != 0) {
-    dummy_chip->perchip_info.play.encoding = value;
-    return 0;
-  }
-  return -EINVAL;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        if (value != 0) {
+                dummy_chip->perchip_info.play.encoding = value;
+                return 0;
+        }
+        return -EINVAL;
 }
 
 static int
 dummy_set_input_encoding(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  if (value != 0) {
-    dummy_chip->perchip_info.record.encoding = value;
-    return 0;
-  }
-  return -EINVAL;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        if (value != 0) {
+                dummy_chip->perchip_info.record.encoding = value;
+                return 0;
+        }
+        return -EINVAL;
 }
 
 static int dummy_get_output_encoding(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.play.encoding;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.play.encoding;
 }
 
 static int dummy_get_input_encoding(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.record.encoding;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.record.encoding;
 }
 
 static int
 dummy_set_output_rate(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  if (value != 0) {
-    dummy_chip->perchip_info.play.sample_rate = value;
-    return 0;
-  }
-  return -EINVAL;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        if (value != 0) {
+                dummy_chip->perchip_info.play.sample_rate = value;
+                return 0;
+        }
+        return -EINVAL;
 }
 
 static int
 dummy_set_input_rate(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  if (value != 0) {
-    dummy_chip->perchip_info.record.sample_rate = value;
-    return 0;
-  }
-  return -EINVAL;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        if (value != 0) {
+                dummy_chip->perchip_info.record.sample_rate = value;
+                return 0;
+        }
+        return -EINVAL;
 }
 
 static int dummy_get_output_rate(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.play.sample_rate;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.play.sample_rate;
 }
 
 static int dummy_get_input_rate(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.record.sample_rate;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.record.sample_rate;
 }
 
 /* Generically we support 4 channels. This does 2 */
 static int
 dummy_set_output_channels(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  switch (value) {
-  case 1:
-  case 2:
-    break;
-  default:
-    return -(EINVAL);
-  }  
-  dummy_chip->perchip_info.play.channels = value;
-  return 0;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        switch (value) {
+        case 1:
+        case 2:
+                break;
+        default:
+                return -(EINVAL);
+        };
+
+        dummy_chip->perchip_info.play.channels = value;
+        return 0;
 }
 
 /* Generically we support 4 channels. This does 2 */
 static int
 dummy_set_input_channels(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  switch (value) {
-  case 1:
-  case 2:
-    break;
-  default:
-    return -(EINVAL);
-  }  
-  dummy_chip->perchip_info.record.channels = value;
-  return 0;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        switch (value) {
+        case 1:
+        case 2:
+                break;
+        default:
+                return -(EINVAL);
+        };
+
+        dummy_chip->perchip_info.record.channels = value;
+        return 0;
 }
 
 static int dummy_get_input_channels(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.record.channels;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.record.channels;
 }
 
 static int dummy_get_output_channels(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.play.channels;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.play.channels;
 }
 
 static int dummy_get_output_precision(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.play.precision;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.play.precision;
 }
 
 static int dummy_get_input_precision(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.record.precision;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.record.precision;
 }
 
 static int dummy_set_output_precision(struct sparcaudio_driver *drv, int val)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; 
-  dummy_chip->perchip_info.play.precision = val;
-  return dummy_chip->perchip_info.play.precision;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; 
+
+        dummy_chip->perchip_info.play.precision = val;
+        return dummy_chip->perchip_info.play.precision;
 }
 
 static int dummy_set_input_precision(struct sparcaudio_driver *drv, int val)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private; 
-  dummy_chip->perchip_info.record.precision = val;
-  return dummy_chip->perchip_info.record.precision;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private; 
+
+        dummy_chip->perchip_info.record.precision = val;
+        return dummy_chip->perchip_info.record.precision;
 }
 
 /* Set output mute */
 static int dummy_output_muted(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  if (!value) 
-    dummy_chip->perchip_info.output_muted = 0;
-  else
-    dummy_chip->perchip_info.output_muted = 1;
-  return 0;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        if (!value) 
+                dummy_chip->perchip_info.output_muted = 0;
+        else
+                dummy_chip->perchip_info.output_muted = 1;
+
+        return 0;
 }
 
 static int dummy_get_output_muted(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.output_muted;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.output_muted;
 }
 
 static int dummy_get_formats(struct sparcaudio_driver *drv)
 {
-  return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_U8 | AFMT_IMA_ADPCM | 
-          AFMT_S16_LE | AFMT_S16_BE);
+        return (AFMT_MU_LAW | AFMT_A_LAW |
+                AFMT_U8 | AFMT_IMA_ADPCM | 
+                AFMT_S16_LE | AFMT_S16_BE);
 }
 
 static int dummy_get_output_ports(struct sparcaudio_driver *drv)
 {
-  return (AUDIO_LINE_OUT | AUDIO_SPEAKER | AUDIO_HEADPHONE);
+        return (AUDIO_LINE_OUT | AUDIO_SPEAKER | AUDIO_HEADPHONE);
 }
 
 static int dummy_get_input_ports(struct sparcaudio_driver *drv)
 {
-  return (AUDIO_ANALOG_LOOPBACK);
+        return (AUDIO_ANALOG_LOOPBACK);
 }
 
 /* Set chip "output" port */
 static int dummy_set_output_port(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  dummy_chip->perchip_info.play.port = value;
-  return (value);
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        dummy_chip->perchip_info.play.port = value;
+        return value;
 }
 
 static int dummy_set_input_port(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  dummy_chip->perchip_info.record.port = value;
-  return (value);
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        dummy_chip->perchip_info.record.port = value;
+        return value;
 }
 
 static int dummy_get_output_port(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.play.port;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.play.port;
 }
 
 static int dummy_get_input_port(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.record.port;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.record.port;
 }
 
 static int dummy_get_output_error(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return (int)dummy_chip->perchip_info.play.error;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return (int) dummy_chip->perchip_info.play.error;
 }
 
 static int dummy_get_input_error(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return (int)dummy_chip->perchip_info.record.error;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return (int) dummy_chip->perchip_info.record.error;
 }
 
 static int dummy_get_output_samples(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.play.samples;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.play.samples;
 }
 
 static int dummy_get_output_pause(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return (int)dummy_chip->perchip_info.play.pause;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return (int) dummy_chip->perchip_info.play.pause;
 }
 
 static int dummy_set_output_volume(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  dummy_play_gain(drv, value, dummy_chip->perchip_info.play.balance);
-  return 0;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        dummy_play_gain(drv, value, dummy_chip->perchip_info.play.balance);
+        return 0;
 }
 
 static int dummy_get_output_volume(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.play.gain;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.play.gain;
 }
 
 static int dummy_set_output_balance(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  dummy_chip->perchip_info.play.balance = value;
-  dummy_play_gain(drv, dummy_chip->perchip_info.play.gain, 
-                  dummy_chip->perchip_info.play.balance);
-  return 0;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        dummy_chip->perchip_info.play.balance = value;
+        dummy_play_gain(drv, dummy_chip->perchip_info.play.gain, 
+                        dummy_chip->perchip_info.play.balance);
+        return 0;
 }
 
 static int dummy_get_output_balance(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return (int)dummy_chip->perchip_info.play.balance;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return (int) dummy_chip->perchip_info.play.balance;
 }
 
 /* Set chip play gain */
-static int dummy_play_gain(struct sparcaudio_driver *drv, int value, unsigned char balance)
+static int dummy_play_gain(struct sparcaudio_driver *drv,
+                           int value, unsigned char balance)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  int tmp = 0, r, l, r_adj, l_adj;
-  r = l = value;
-  if (balance < AUDIO_MID_BALANCE) {
-    r = (int)(value - ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT));
-    if (r < 0) r = 0;
-  } else if (balance > AUDIO_MID_BALANCE) {
-    l = (int)(value - ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT));
-    if (l < 0) l = 0;
-  }
-  (l == 0) ? (l_adj = DUMMY_MAX_DEV_ATEN) : (l_adj = DUMMY_MAX_ATEN - 
-                                             (l * (DUMMY_MAX_ATEN + 1) / 
-                                              (AUDIO_MAX_GAIN + 1)));
-  (r == 0) ? (r_adj = DUMMY_MAX_DEV_ATEN) : (r_adj = DUMMY_MAX_ATEN -
-                                             (r * (DUMMY_MAX_ATEN + 1) /
-                                              (AUDIO_MAX_GAIN + 1)));
-  if ((value == 0) || (value == AUDIO_MAX_GAIN)) {
-    tmp = value;
-  } else {
-    if (value == l)
-      tmp = ((DUMMY_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / 
-             (DUMMY_MAX_ATEN + 1));
-    else if (value == r)
-      tmp = ((DUMMY_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / 
-             (DUMMY_MAX_ATEN + 1));
-  }
-  dummy_chip->perchip_info.play.gain = tmp;
-  return 0;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+        int tmp = 0, r, l, r_adj, l_adj;
+
+        r = l = value;
+        if (balance < AUDIO_MID_BALANCE) {
+                r = (int) (value -
+                           ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT));
+
+                if (r < 0)
+                        r = 0;
+        } else if (balance > AUDIO_MID_BALANCE) {
+                l = (int) (value -
+                           ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT));
+
+                if (l < 0)
+                        l = 0;
+        }
+        (l == 0) ? (l_adj = DUMMY_MAX_DEV_ATEN) : (l_adj = DUMMY_MAX_ATEN - 
+                                                   (l * (DUMMY_MAX_ATEN + 1) / 
+                                                    (AUDIO_MAX_GAIN + 1)));
+        (r == 0) ? (r_adj = DUMMY_MAX_DEV_ATEN) : (r_adj = DUMMY_MAX_ATEN -
+                                                   (r * (DUMMY_MAX_ATEN + 1) /
+                                                    (AUDIO_MAX_GAIN + 1)));
+        if ((value == 0) || (value == AUDIO_MAX_GAIN)) {
+                tmp = value;
+        } else {
+                if (value == l) {
+                        tmp = ((DUMMY_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / 
+                               (DUMMY_MAX_ATEN + 1));
+                } else if (value == r) {
+                        tmp = ((DUMMY_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / 
+                               (DUMMY_MAX_ATEN + 1));
+                }
+        }
+        dummy_chip->perchip_info.play.gain = tmp;
+        return 0;
 }
 
 static int dummy_get_input_samples(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.record.samples;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.record.samples;
 }
 
 static int dummy_get_input_pause(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return (int)dummy_chip->perchip_info.record.pause;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return (int) dummy_chip->perchip_info.record.pause;
 }
 
 static int dummy_set_monitor_volume(struct sparcaudio_driver *drv, int value)
 {
-  return 0;
+        return 0;
 }
 
 static int dummy_get_monitor_volume(struct sparcaudio_driver *drv)
 {
-  return 0;
+        return 0;
 }
 
 static int dummy_set_input_volume(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  dummy_record_gain(drv, value, dummy_chip->perchip_info.record.balance);
-  return 0;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        dummy_record_gain(drv, value, dummy_chip->perchip_info.record.balance);
+        return 0;
 }
 
 static int dummy_get_input_volume(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return dummy_chip->perchip_info.record.gain;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return dummy_chip->perchip_info.record.gain;
 }
 
 static int dummy_set_input_balance(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  dummy_chip->perchip_info.record.balance = value;
-  dummy_record_gain(drv, dummy_chip->perchip_info.record.gain, 
-                  dummy_chip->perchip_info.play.balance);
-  return 0;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        dummy_chip->perchip_info.record.balance = value;
+        dummy_record_gain(drv, dummy_chip->perchip_info.record.gain, 
+                          dummy_chip->perchip_info.play.balance);
+        return 0;
 }
 
 static int dummy_get_input_balance(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  return (int)dummy_chip->perchip_info.record.balance;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        return (int) dummy_chip->perchip_info.record.balance;
 }
 
-static int dummy_record_gain(struct sparcaudio_driver *drv, int value, unsigned char balance)
+static int dummy_record_gain(struct sparcaudio_driver *drv,
+                             int value, unsigned char balance)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  int tmp = 0, r, l, r_adj, l_adj;
-  r = l = value;
-  if (balance < AUDIO_MID_BALANCE) {
-    r = (int)(value - ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT));
-    if (r < 0) r = 0;
-  } else if (balance > AUDIO_MID_BALANCE) {
-    l = (int)(value - ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT));
-    if (l < 0) l = 0;
-  }
-  (l == 0) ? (l_adj = DUMMY_MAX_DEV_ATEN) : (l_adj = DUMMY_MAX_ATEN - 
-                                             (l * (DUMMY_MAX_ATEN + 1) / 
-                                              (AUDIO_MAX_GAIN + 1)));
-  (r == 0) ? (r_adj = DUMMY_MAX_DEV_ATEN) : (r_adj = DUMMY_MAX_ATEN -
-                                             (r * (DUMMY_MAX_ATEN + 1) /
-                                              (AUDIO_MAX_GAIN + 1)));
-  if ((value == 0) || (value == AUDIO_MAX_GAIN)) {
-    tmp = value;
-  } else {
-    if (value == l)
-      tmp = ((DUMMY_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / 
-             (DUMMY_MAX_ATEN + 1));
-    else if (value == r)
-      tmp = ((DUMMY_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / 
-             (DUMMY_MAX_ATEN + 1));
-  }
-  dummy_chip->perchip_info.record.gain = tmp;
-  return 0;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+        int tmp = 0, r, l, r_adj, l_adj;
+
+        r = l = value;
+        if (balance < AUDIO_MID_BALANCE) {
+                r = (int) (value -
+                           ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT));
+
+                if (r < 0)
+                        r = 0;
+        } else if (balance > AUDIO_MID_BALANCE) {
+                l = (int) (value -
+                           ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT));
+
+                if (l < 0)
+                        l = 0;
+        }
+        (l == 0) ? (l_adj = DUMMY_MAX_DEV_ATEN) : (l_adj = DUMMY_MAX_ATEN - 
+                                                   (l * (DUMMY_MAX_ATEN + 1) / 
+                                                    (AUDIO_MAX_GAIN + 1)));
+        (r == 0) ? (r_adj = DUMMY_MAX_DEV_ATEN) : (r_adj = DUMMY_MAX_ATEN -
+                                                   (r * (DUMMY_MAX_ATEN + 1) /
+                                                    (AUDIO_MAX_GAIN + 1)));
+        if ((value == 0) || (value == AUDIO_MAX_GAIN)) {
+                tmp = value;
+        } else {
+                if (value == l) {
+                        tmp = ((DUMMY_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / 
+                               (DUMMY_MAX_ATEN + 1));
+                } else if (value == r) {
+                        tmp = ((DUMMY_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / 
+                               (DUMMY_MAX_ATEN + 1));
+                }
+        }
+        dummy_chip->perchip_info.record.gain = tmp;
+        return 0;
 }
 
 /* Reset the audio chip to a sane state. */
 static void dummy_chip_reset(struct sparcaudio_driver *drv)
 {
-  dummy_set_output_encoding(drv, AUDIO_ENCODING_ULAW);
-  dummy_set_output_rate(drv, DUMMY_RATE);
-  dummy_set_output_channels(drv, DUMMY_CHANNELS);
-  dummy_set_output_precision(drv, DUMMY_PRECISION);
-  dummy_set_output_balance(drv, AUDIO_MID_BALANCE);
-  dummy_set_output_volume(drv, DUMMY_DEFAULT_PLAYGAIN);
-  dummy_set_output_port(drv, AUDIO_SPEAKER);
-  dummy_output_muted(drv, 0);
-  dummy_set_input_encoding(drv, AUDIO_ENCODING_ULAW);
-  dummy_set_input_rate(drv, DUMMY_RATE);
-  dummy_set_input_channels(drv, DUMMY_CHANNELS);
-  dummy_set_input_precision(drv, DUMMY_PRECISION);
-  dummy_set_input_balance(drv, AUDIO_MID_BALANCE);
-  dummy_set_input_volume(drv, DUMMY_DEFAULT_PLAYGAIN);
-  dummy_set_input_port(drv, AUDIO_SPEAKER);
+        dummy_set_output_encoding(drv, AUDIO_ENCODING_ULAW);
+        dummy_set_output_rate(drv, DUMMY_RATE);
+        dummy_set_output_channels(drv, DUMMY_CHANNELS);
+        dummy_set_output_precision(drv, DUMMY_PRECISION);
+        dummy_set_output_balance(drv, AUDIO_MID_BALANCE);
+        dummy_set_output_volume(drv, DUMMY_DEFAULT_PLAYGAIN);
+        dummy_set_output_port(drv, AUDIO_SPEAKER);
+        dummy_output_muted(drv, 0);
+        dummy_set_input_encoding(drv, AUDIO_ENCODING_ULAW);
+        dummy_set_input_rate(drv, DUMMY_RATE);
+        dummy_set_input_channels(drv, DUMMY_CHANNELS);
+        dummy_set_input_precision(drv, DUMMY_PRECISION);
+        dummy_set_input_balance(drv, AUDIO_MID_BALANCE);
+        dummy_set_input_volume(drv, DUMMY_DEFAULT_PLAYGAIN);
+        dummy_set_input_port(drv, AUDIO_SPEAKER);
 }
 
 static int dummy_open(struct inode * inode, struct file * file, struct sparcaudio_driver *drv)
 {	
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  /* Set the default audio parameters if not already in use. */
-  if (file->f_mode & FMODE_WRITE) {
-    if (!(drv->flags & SDF_OPEN_WRITE) && 
-	(dummy_chip->perchip_info.play.active == 0)) {
-      dummy_chip->perchip_info.play.open = 1;
-      dummy_chip->perchip_info.play.samples =
-        dummy_chip->perchip_info.play.error = 0;
-    }
-  }
-  if (file->f_mode & FMODE_READ) {
-    if (!(drv->flags & SDF_OPEN_READ) && 
-	(dummy_chip->perchip_info.record.active == 0)) {
-      dummy_chip->perchip_info.record.open = 1;
-      dummy_chip->perchip_info.record.samples =
-        dummy_chip->perchip_info.record.error = 0;
-    }
-  }
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        /* Set the default audio parameters if not already in use. */
+        if (file->f_mode & FMODE_WRITE) {
+                if (!(drv->flags & SDF_OPEN_WRITE) && 
+                    (dummy_chip->perchip_info.play.active == 0)) {
+                        dummy_chip->perchip_info.play.open = 1;
+                        dummy_chip->perchip_info.play.samples =
+                                dummy_chip->perchip_info.play.error = 0;
+                }
+        }
+
+        if (file->f_mode & FMODE_READ) {
+                if (!(drv->flags & SDF_OPEN_READ) && 
+                    (dummy_chip->perchip_info.record.active == 0)) {
+                        dummy_chip->perchip_info.record.open = 1;
+                        dummy_chip->perchip_info.record.samples =
+                                dummy_chip->perchip_info.record.error = 0;
+                }
+        }
 
-  MOD_INC_USE_COUNT;
+        MOD_INC_USE_COUNT;
 
-  return 0;
+        return 0;
 }
 
 static void dummy_release(struct inode * inode, struct file * file, struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  if (file->f_mode & FMODE_WRITE) {
-    dummy_chip->perchip_info.play.active =
-      dummy_chip->perchip_info.play.open = 0;
-  }
-  if (file->f_mode & FMODE_READ) {
-    dummy_chip->perchip_info.record.active =
-      dummy_chip->perchip_info.record.open = 0;
-  }
-  MOD_DEC_USE_COUNT;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        if (file->f_mode & FMODE_WRITE) {
+                dummy_chip->perchip_info.play.active =
+                        dummy_chip->perchip_info.play.open = 0;
+        }
+
+        if (file->f_mode & FMODE_READ) {
+                dummy_chip->perchip_info.record.active =
+                        dummy_chip->perchip_info.record.open = 0;
+        }
+
+        MOD_DEC_USE_COUNT;
 }
 
 static void dummy_output_done_task(void * arg)
 {
-  struct sparcaudio_driver *drv = (struct sparcaudio_driver *)arg;
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
+        struct sparcaudio_driver *drv = (struct sparcaudio_driver *) arg;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
 
-  sparcaudio_output_done(drv, 1);
-  if (dummy_chip->perchip_info.record.active)
-    sparcaudio_input_done(drv, 1);
+        sparcaudio_output_done(drv, 1);
+        if (dummy_chip->perchip_info.record.active)
+                sparcaudio_input_done(drv, 1);
 }
 
 static void dummy_start_output(struct sparcaudio_driver *drv, __u8 * buffer,
-                                unsigned long count)
+                               unsigned long count)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
 
-  if (dummy_chip->perchip_info.play.pause || !count) 
-    return;
+        if (dummy_chip->perchip_info.play.pause || !count) 
+                return;
 
-  dummy_chip->perchip_info.play.active = 1;
+        dummy_chip->perchip_info.play.active = 1;
 
-  /* fake an "interrupt" to deal with this block */
-  dummy_chip->tqueue.next = NULL;
-  dummy_chip->tqueue.sync = 0;
-  dummy_chip->tqueue.routine = dummy_output_done_task;
-  dummy_chip->tqueue.data = drv;
+        /* fake an "interrupt" to deal with this block */
+        dummy_chip->tqueue.next = NULL;
+        dummy_chip->tqueue.sync = 0;
+        dummy_chip->tqueue.routine = dummy_output_done_task;
+        dummy_chip->tqueue.data = drv;
 
-  queue_task(&dummy_chip->tqueue, &tq_immediate);
-  mark_bh(IMMEDIATE_BH);
+        queue_task(&dummy_chip->tqueue, &tq_immediate);
+        mark_bh(IMMEDIATE_BH);
 }
 
 static void dummy_start_input(struct sparcaudio_driver *drv, __u8 * buffer,
-                                unsigned long count)
+                              unsigned long count)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  dummy_chip->perchip_info.record.active = 1;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        dummy_chip->perchip_info.record.active = 1;
 }
 
 static void dummy_stop_output(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  dummy_chip->perchip_info.play.active = 0;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        dummy_chip->perchip_info.play.active = 0;
 }
 
 static void dummy_stop_input(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  dummy_chip->perchip_info.record.active = 0;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        dummy_chip->perchip_info.record.active = 0;
 }
 
 static int dummy_set_output_pause(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  dummy_chip->perchip_info.play.pause = value;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        dummy_chip->perchip_info.play.pause = value;
 
-  if (!value)
-    sparcaudio_output_done(drv, 0);
+        if (!value)
+                sparcaudio_output_done(drv, 0);
 
-  return value;
+        return value;
 }
 
 static int dummy_set_input_pause(struct sparcaudio_driver *drv, int value)
 {
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  dummy_chip->perchip_info.record.pause = value;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+
+        dummy_chip->perchip_info.record.pause = value;
 
-  /* This should probably cause play pause. */
+        /* This should probably cause play pause. */
 
-  return value;
+        return value;
 }
 
 static int dummy_set_input_error(struct sparcaudio_driver *drv, int value)
 {
-  return 0;
+        return 0;
 }
 
 static int dummy_set_output_error(struct sparcaudio_driver *drv, int value)
 {
-  int i;
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  i = dummy_chip->perchip_info.play.error;
-  dummy_chip->perchip_info.play.error = value;
-  return i;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+        int i;
+
+        i = dummy_chip->perchip_info.play.error;
+        dummy_chip->perchip_info.play.error = value;
+        return i;
 }
 
 static int dummy_set_output_samples(struct sparcaudio_driver *drv, int value)
 {
-  int i;
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  i = dummy_chip->perchip_info.play.samples;
-  dummy_chip->perchip_info.play.samples = value;
-  return i;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+        int i;
+
+        i = dummy_chip->perchip_info.play.samples;
+        dummy_chip->perchip_info.play.samples = value;
+        return i;
 }
 
 static int dummy_set_input_samples(struct sparcaudio_driver *drv, int value)
 {
-  int i;
-  struct dummy_chip *dummy_chip = (struct dummy_chip *)drv->private;
-  i = dummy_chip->perchip_info.play.samples;
-  dummy_chip->perchip_info.record.samples = value;
-  return i;
+        struct dummy_chip *dummy_chip = (struct dummy_chip *) drv->private;
+        int i;
+
+        i = dummy_chip->perchip_info.play.samples;
+        dummy_chip->perchip_info.record.samples = value;
+        return i;
 }
 
 /* In order to fake things which care out, play we're a 4231 */
 static void dummy_audio_getdev(struct sparcaudio_driver *drv,
-                                 audio_device_t * audinfo)
+                               audio_device_t * audinfo)
 {
-  strncpy(audinfo->name, "SUNW,cs4231", sizeof(audinfo->name) - 1);
-  strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1);
-  strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1);
+        strncpy(audinfo->name, "SUNW,cs4231", sizeof(audinfo->name) - 1);
+        strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1);
+        strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1);
 }
 
 
 static int dummy_audio_getdev_sunos(struct sparcaudio_driver *drv)
 {
-  return (5); 
+        return 5; 
 }
 
 static struct sparcaudio_operations dummy_ops = {
@@ -646,73 +717,73 @@
 int __init dummy_init(void)
 #endif
 {
-  num_drivers = 0;
+        num_drivers = 0;
       
-  /* Add support here for specifying multiple dummies to attach at once. */
-  if (dummy_attach(&drivers[num_drivers]) == 0)
-    num_drivers++;
+        /* Add support here for specifying multiple dummies to attach at once. */
+        if (dummy_attach(&drivers[num_drivers]) == 0)
+                num_drivers++;
   
-  /* Only return success if we found some dummy chips. */
-  return (num_drivers > 0) ? 0 : -EIO;
+        /* Only return success if we found some dummy chips. */
+        return (num_drivers > 0) ? 0 : -EIO;
 }
 
 /* Attach to an dummy chip given its PROM node. */
 static int dummy_attach(struct sparcaudio_driver *drv)
 {
-  struct dummy_chip *dummy_chip;
-  int err;
+        struct dummy_chip *dummy_chip;
+        int err;
 
-  /* Allocate our private information structure. */
-  drv->private = kmalloc(sizeof(struct dummy_chip), GFP_KERNEL);
-  if (!drv->private)
-    return -ENOMEM;
-
-  /* Point at the information structure and initialize it. */
-  drv->ops = &dummy_ops;
-  dummy_chip = (struct dummy_chip *)drv->private;
-
-  /* Reset parameters. */
-  dummy_chip_reset(drv);
-
-  /* Register ourselves with the midlevel audio driver. */
-  err = register_sparcaudio_driver(drv, 2);
-
-  if (err < 0) {
-    printk(KERN_ERR "dummy: unable to register\n");
-    kfree(drv->private);
-    return -EIO;
-  }
-
-  dummy_chip->perchip_info.play.active = 
-    dummy_chip->perchip_info.play.pause = 0;
-
-  dummy_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE |
-						AUDIO_SPEAKER |
-						AUDIO_LINE_OUT);
+        /* Allocate our private information structure. */
+        drv->private = kmalloc(sizeof(struct dummy_chip), GFP_KERNEL);
+        if (drv->private == NULL)
+                return -ENOMEM;
+
+        /* Point at the information structure and initialize it. */
+        drv->ops = &dummy_ops;
+        dummy_chip = (struct dummy_chip *) drv->private;
+
+        /* Reset parameters. */
+        dummy_chip_reset(drv);
+
+        /* Register ourselves with the midlevel audio driver. */
+        err = register_sparcaudio_driver(drv, 2);
+
+        if (err < 0) {
+                printk(KERN_ERR "dummy: unable to register\n");
+                kfree(drv->private);
+                return -EIO;
+        }
+
+        dummy_chip->perchip_info.play.active = 
+                dummy_chip->perchip_info.play.pause = 0;
+
+        dummy_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE |
+                                                     AUDIO_SPEAKER |
+                                                     AUDIO_LINE_OUT);
 
-  /* Announce the hardware to the user. */
-  printk(KERN_INFO "audio%d: dummy at 0x0 irq 0\n", drv->index);
+        /* Announce the hardware to the user. */
+        printk(KERN_INFO "audio%d: dummy at 0x0 irq 0\n", drv->index);
   
-  /* Success! */
-  return 0;
+        /* Success! */
+        return 0;
 }
 
 #ifdef MODULE
 /* Detach from an dummy chip given the device structure. */
 static void dummy_detach(struct sparcaudio_driver *drv)
 {
-  unregister_sparcaudio_driver(drv, 2);
-  kfree(drv->private);
+        unregister_sparcaudio_driver(drv, 2);
+        kfree(drv->private);
 }
 
 void cleanup_module(void)
 {
-  register int i;
+        int i;
 
-  for (i = 0; i < num_drivers; i++) {
-    dummy_detach(&drivers[i]);
-    num_drivers--;
-  }
+        for (i = 0; i < num_drivers; i++) {
+                dummy_detach(&drivers[i]);
+                num_drivers--;
+        }
 }
 #endif
 
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/audio/dummy.h linux/drivers/sbus/audio/dummy.h
--- v2.3.34/linux/drivers/sbus/audio/dummy.h	Mon Mar 15 16:11:30 1999
+++ linux/drivers/sbus/audio/dummy.h	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/*
+/* $Id: dummy.h,v 1.3 1999/09/21 14:37:41 davem Exp $
  * drivers/sbus/audio/dummy.h
  *
  * Copyright (C) 1998 Derrick J. Brashear (shadow@dementia.org)
@@ -15,9 +15,9 @@
 /* Our structure for each chip */
 
 struct dummy_chip {
-  struct audio_info perchip_info;
-  unsigned int playlen;
-  struct tq_struct tqueue;
+	struct audio_info perchip_info;
+	unsigned int playlen;
+	struct tq_struct tqueue;
 };
 
 #define DUMMY_MIN_ATEN     (0)
@@ -38,4 +38,4 @@
 
 #define DUMMY_RATE   (8000)                /* default sample rate */
 
-#endif
+#endif /* _DUMMY_H_ */
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/Config.in linux/drivers/sbus/char/Config.in
--- v2.3.34/linux/drivers/sbus/char/Config.in	Mon Nov  1 13:56:26 1999
+++ linux/drivers/sbus/char/Config.in	Mon Dec 20 22:06:42 1999
@@ -14,6 +14,7 @@
    tristate 'Aurora Multiboard 1600se (EXPERIMENTAL)' CONFIG_SUN_AURORA
    tristate 'Tadpole TS102 Microcontroller support (EXPERIMENTAL)' CONFIG_TADPOLE_TS102_UCTRL
 
+   tristate 'JavaStation OS Flash SIMM (EXPERIMENTAL)' CONFIG_SUN_JSFLASH
    # XXX Why don't we do "source drivers/char/Config.in" somewhere?
    if [ "$CONFIG_PCI" = "y" ]; then
       define_bool CONFIG_APM_RTC_IS_GMT y		# no shit
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c
--- v2.3.34/linux/drivers/sbus/char/aurora.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/sbus/char/aurora.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/*
+/*	$Id: aurora.c,v 1.7 1999/09/21 14:37:46 davem Exp $
  *	linux/drivers/sbus/char/aurora.c -- Aurora multiport driver
  *
  *	Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro)
@@ -69,7 +69,7 @@
 
 unsigned char irqs[4] = {
 	0, 0, 0, 0
-	};
+};
 
 #ifdef AURORA_INT_DEBUG
 int irqhit=0;
@@ -108,7 +108,7 @@
 static unsigned long baud_table[] =  {
         0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
         9600, 19200, 38400, 57600, 115200, 0,
-        };
+};
 
 static inline int aurora_paranoia_check(struct Aurora_port const * port,
 				    kdev_t device, const char *routine)
@@ -165,7 +165,7 @@
 #endif
 	/* FIXME: need something more descriptive than 100000 :) */
 	for (delay = 100000; delay; delay--) 
-		if (!r->r[CD180_CCR])
+		if (!sbus_readb(&r->r[CD180_CCR]))
 			return;
 	printk(KERN_DEBUG "aurora: Timeout waiting for CCR.\n");
 }
@@ -178,12 +178,13 @@
 extern inline void aurora_long_delay(unsigned long delay)
 {
 	unsigned long i;
+
 #ifdef AURORA_DEBUG
-printk("aurora_long_delay: start\n");
+	printk("aurora_long_delay: start\n");
 #endif
 	for (i = jiffies + delay; i > jiffies; ) ;
 #ifdef AURORA_DEBUG
-printk("aurora_long_delay: end\n");
+	printk("aurora_long_delay: end\n");
 #endif
 }
 
@@ -194,51 +195,68 @@
 	int id;
 	
 #ifdef AURORA_DEBUG
-printk("aurora_init_CD180: start %d:%d\n",board_No(bp),chip);
+	printk("aurora_init_CD180: start %d:%d\n",
+	       board_No(bp), chip);
 #endif
 	save_flags(flags); cli();
-	bp->r[chip]->r[CD180_CAR]=0;
-	bp->r[chip]->r[CD180_GSVR]=0;
-	aurora_wait_CCR(bp->r[chip]);			/* Wait for CCR ready        */
-	bp->r[chip]->r[CD180_CCR]=CCR_HARDRESET;      /* Reset CD180 chip          */
+	sbus_writeb(0, &bp->r[chip]->r[CD180_CAR]);
+	sbus_writeb(0, &bp->r[chip]->r[CD180_GSVR]);
+
+	/* Wait for CCR ready        */
+	aurora_wait_CCR(bp->r[chip]);
+
+	/* Reset CD180 chip          */
+	sbus_writeb(CCR_HARDRESET, &bp->r[chip]->r[CD180_CCR]);
 	udelay(1);
 	sti();
 	id=1000;
-	while((--id)&&(bp->r[chip]->r[CD180_GSVR]!=0xff))udelay(100);
+	while((--id) &&
+	      (sbus_readb(&bp->r[chip]->r[CD180_GSVR])!=0xff))udelay(100);
 	if(!id) {
-		printk(KERN_ERR "aurora%d: Chip %d failed init.\n",board_No(bp),chip);
+		printk(KERN_ERR "aurora%d: Chip %d failed init.\n",
+		       board_No(bp), chip);
 		restore_flags(flags);
 		return(-1);
-		}
+	}
 	cli();
-	bp->r[chip]->r[CD180_GSVR]=(board_No(bp)<<5)|((chip+1)<<3); /* Set ID for this chip      */
-	bp->r[chip]->r[CD180_MSMR]=0x80|bp->ACK_MINT;      /* Prio for modem intr       */
-	bp->r[chip]->r[CD180_TSMR]=0x80|bp->ACK_TINT;      /* Prio for transmitter intr */
-	bp->r[chip]->r[CD180_RSMR]=0x80|bp->ACK_RINT;      /* Prio for receiver intr    */
+	sbus_writeb((board_No(bp)<<5)|((chip+1)<<3),
+		    &bp->r[chip]->r[CD180_GSVR]); /* Set ID for this chip      */
+	sbus_writeb(0x80|bp->ACK_MINT,
+		    &bp->r[chip]->r[CD180_MSMR]); /* Prio for modem intr       */
+	sbus_writeb(0x80|bp->ACK_TINT,
+		    &bp->r[chip]->r[CD180_TSMR]); /* Prio for transmitter intr */
+	sbus_writeb(0x80|bp->ACK_RINT,
+		    &bp->r[chip]->r[CD180_RSMR]); /* Prio for receiver intr    */
 	/* Setting up prescaler. We need 4 tick per 1 ms */
-	bp->r[chip]->r[CD180_PPRH]=(bp->oscfreq/(1000000/AURORA_TPS)) >> 8;
-	bp->r[chip]->r[CD180_PPRL]=(bp->oscfreq/(1000000/AURORA_TPS)) & 0xff;
-
-	bp->r[chip]->r[CD180_SRCR]=SRCR_AUTOPRI|SRCR_GLOBPRI;
-
-	id=bp->r[chip]->r[CD180_GFRCR];
-	printk(KERN_INFO "aurora%d: Chip %d id %02x: ",board_No(bp),chip,id);
-	if(bp->r[chip]->r[CD180_SRCR]&128)
-		switch(id){
+	sbus_writeb((bp->oscfreq/(1000000/AURORA_TPS)) >> 8,
+		    &bp->r[chip]->r[CD180_PPRH]);
+	sbus_writeb((bp->oscfreq/(1000000/AURORA_TPS)) & 0xff,
+		    &bp->r[chip]->r[CD180_PPRL]);
+
+	sbus_writeb(SRCR_AUTOPRI|SRCR_GLOBPRI,
+		    &bp->r[chip]->r[CD180_SRCR]);
+
+	id = sbus_readb(&bp->r[chip]->r[CD180_GFRCR]);
+	printk(KERN_INFO "aurora%d: Chip %d id %02x: ",
+	       board_No(bp), chip,id);
+	if(sbus_readb(&bp->r[chip]->r[CD180_SRCR]) & 128) {
+		switch (id) {
 			case 0x82:printk("CL-CD1864 rev A\n");break;
 			case 0x83:printk("CL-CD1865 rev A\n");break;
 			case 0x84:printk("CL-CD1865 rev B\n");break;
 			case 0x85:printk("CL-CD1865 rev C\n");break;
 			default:printk("Unknown.\n");
-		}else
-		switch(id){
+		};
+	} else {
+		switch (id) {
 			case 0x81:printk("CL-CD180 rev B\n");break;
 			case 0x82:printk("CL-CD180 rev C\n");break;
 			default:printk("Unknown.\n");
 		};
+	}
 	restore_flags(flags);
 #ifdef AURORA_DEBUG
-printk("aurora_init_CD180: end\n");
+	printk("aurora_init_CD180: end\n");
 #endif
 	return 0;
 }
@@ -254,70 +272,85 @@
 static void aurora_interrupt(int irq, void * dev_id, struct pt_regs * regs);
 
 /* Main probing routine, also sets irq. */
-static int aurora_probe(void) {
-	struct linux_sbus *sbus;
-	struct linux_sbus_device *sdev;
+static int aurora_probe(void)
+{
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev;
 	int grrr;
 	char buf[30];
-	int bn=0;
+	int bn = 0;
 	struct Aurora_board *bp;
 
 	for_each_sbus(sbus) {
 		for_each_sbusdev(sdev, sbus) {
 /*			printk("Try: %x %s\n",sdev,sdev->prom_name);*/
 			if (!strcmp(sdev->prom_name, "sio16")) {
-				#ifdef AURORA_DEBUG
+#ifdef AURORA_DEBUG
 				printk(KERN_INFO "aurora: sio16 at %p\n",sdev);
-				#endif
-				prom_apply_sbus_ranges(sdev->my_bus, sdev->reg_addrs, sdev->num_registers, sdev);
-				if((sdev->reg_addrs[0].reg_size!=1)&&(sdev->reg_addrs[1].reg_size!=128)&&
-				   (sdev->reg_addrs[2].reg_size!=128)&&(sdev->reg_addrs[3].reg_size!=4)){
-				   	printk(KERN_ERR "aurora%d: registers' sizes do not match.\n",bn);
+#endif
+				if((sdev->reg_addrs[0].reg_size!=1) &&
+				   (sdev->reg_addrs[1].reg_size!=128) &&
+				   (sdev->reg_addrs[2].reg_size!=128) &&
+				   (sdev->reg_addrs[3].reg_size!=4)) {
+				   	printk(KERN_ERR "aurora%d: registers' sizes "
+					       "do not match.\n", bn);
 				   	break;
-				   	}
-				bp=&aurora_board[bn];
-				bp->r0 = (struct aurora_reg1 *) sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
-					sdev->reg_addrs[0].reg_size, "sio16",sdev->reg_addrs[0].which_io, 0x0);
-				if (!bp->r0) {
-					printk(KERN_ERR "aurora%d: can't map reg_addrs[0]\n",bn);
+				}
+				bp = &aurora_board[bn];
+				bp->r0 = (struct aurora_reg1 *)
+					sbus_ioremap(&sdev->resource[0], 0,
+						     sdev->reg_addrs[0].reg_size,
+						     "sio16");
+				if (bp->r0 == NULL) {
+					printk(KERN_ERR "aurora%d: can't map "
+					       "reg_addrs[0]\n", bn);
 					break;
 				}
-				#ifdef AURORA_DEBUG
-				printk("Map reg 0: %x\n",bp->r0);
-				#endif
-				bp->r[0] = (struct aurora_reg128 *) sparc_alloc_io(sdev->reg_addrs[1].phys_addr, 0,
-					sdev->reg_addrs[1].reg_size, "sio16", sdev->reg_addrs[1].which_io, 0x0);
-				if (!bp->r[0]) {
-					printk(KERN_ERR "aurora%d: can't map reg_addrs[1]\n",bn);
+#ifdef AURORA_DEBUG
+				printk("Map reg 0: %p\n", bp->r0);
+#endif
+				bp->r[0] = (struct aurora_reg128 *)
+					sbus_ioremap(&sdev->resource[1], 0,
+						     sdev->reg_addrs[1].reg_size,
+						     "sio16");
+				if (bp->r[0] == NULL) {
+					printk(KERN_ERR "aurora%d: can't map "
+					       "reg_addrs[1]\n", bn);
 					break;
 				}
-				#ifdef AURORA_DEBUG
-				printk("Map reg 1: %x\n",bp->r[0]);
-				#endif
-				bp->r[1] = (struct aurora_reg128 *) sparc_alloc_io(sdev->reg_addrs[2].phys_addr, 0,
-					sdev->reg_addrs[2].reg_size, "sio16", sdev->reg_addrs[2].which_io, 0x0);
-				if (!bp->r[1]) {
-					printk(KERN_ERR "aurora%d: can't map reg_addrs[2]\n",bn);
+#ifdef AURORA_DEBUG
+				printk("Map reg 1: %p\n", bp->r[0]);
+#endif
+				bp->r[1] = (struct aurora_reg128 *)
+					sbus_ioremap(&sdev->resource[2], 0,
+						     sdev->reg_addrs[2].reg_size,
+						     "sio16");
+				if (bp->r[1] == NULL) {
+					printk(KERN_ERR "aurora%d: can't map "
+					       "reg_addrs[2]\n", bn);
 					break;
 				}
-				#ifdef AURORA_DEBUG
-				printk("Map reg 2: %x\n",bp->r[1]);
-				#endif
-				bp->r3 = (struct aurora_reg4 *) sparc_alloc_io(sdev->reg_addrs[3].phys_addr, 0,
-					sdev->reg_addrs[3].reg_size, "sio16", sdev->reg_addrs[3].which_io, 0x0);
-				if (!bp->r3) {
-					printk(KERN_ERR "aurora%d: can't map reg_addrs[3]\n",bn);
+#ifdef AURORA_DEBUG
+				printk("Map reg 2: %p\n", bp->r[1]);
+#endif
+				bp->r3 = (struct aurora_reg4 *)
+					sbus_ioremap(&sdev->resource[3], 0,
+						     sdev->reg_addrs[3].reg_size,
+						     "sio16");
+				if (bp->r3 == NULL) {
+					printk(KERN_ERR "aurora%d: can't map "
+					       "reg_addrs[3]\n", bn);
 					break;
 				}
-				#ifdef AURORA_DEBUG
-				printk("Map reg 3: %x\n",bp->r3);
-				#endif
+#ifdef AURORA_DEBUG
+				printk("Map reg 3: %p\n", bp->r3);
+#endif
 				/* Variables setup */
 				bp->flags = 0;
-				#ifdef AURORA_DEBUG
+#ifdef AURORA_DEBUG
 				grrr=prom_getint(sdev->prom_node,"intr");
-				printk("intr pri %d\n",grrr);
-				#endif
+				printk("intr pri %d\n", grrr);
+#endif
 				if ((bp->irq=irqs[bn]) && valid_irq(bp->irq) &&
 				    !request_irq(bp->irq|0x30, aurora_interrupt, SA_SHIRQ, "sio16", bp)) {
 					free_irq(bp->irq|0x30, bp);
@@ -395,42 +428,44 @@
 
 static void aurora_release_io_range(struct Aurora_board *bp)
 {
-sparc_free_io(bp->r0,1);
-sparc_free_io(bp->r[0],128);
-sparc_free_io(bp->r[1],128);
-sparc_free_io(bp->r3,4);
+	sbus_iounmap((unsigned long)bp->r0, 1);
+	sbus_iounmap((unsigned long)bp->r[0], 128);
+	sbus_iounmap((unsigned long)bp->r[1], 128);
+	sbus_iounmap((unsigned long)bp->r3, 4);
 }
 
 extern inline void aurora_mark_event(struct Aurora_port * port, int event)
 {
 #ifdef AURORA_DEBUG
-printk("aurora_mark_event: start\n");
+	printk("aurora_mark_event: start\n");
 #endif
 	set_bit(event, &port->event);
 	queue_task(&port->tqueue, &tq_aurora);
 	mark_bh(AURORA_BH);
 #ifdef AURORA_DEBUG
-printk("aurora_mark_event: end\n");
+	printk("aurora_mark_event: end\n");
 #endif
 }
 
-extern inline struct Aurora_port * aurora_get_port(struct Aurora_board const * bp,
-					int chip, unsigned char const * what)
+static __inline__ struct Aurora_port * aurora_get_port(struct Aurora_board const * bp,
+						       int chip,
+						       unsigned char const *what)
 {
 	unsigned char channel;
 	struct Aurora_port * port;
 
-	channel = (chip<<3)|((bp->r[chip]->r[CD180_GSCR]&GSCR_CHAN)>>GSCR_CHAN_OFF);
+	channel = ((chip << 3) |
+		   ((sbus_readb(&bp->r[chip]->r[CD180_GSCR]) & GSCR_CHAN) >> GSCR_CHAN_OFF));
 	port = &aurora_port[board_No(bp) * AURORA_NPORT * AURORA_NCD180 + channel];
-	if (port->flags & ASYNC_INITIALIZED)  {
+	if (port->flags & ASYNC_INITIALIZED)
 		return port;
-	}
+
 	printk(KERN_DEBUG "aurora%d: %s interrupt from invalid port %d\n",
 	       board_No(bp), what, channel);
 	return NULL;
 }
 
-extern inline void aurora_receive_exc(struct Aurora_board const * bp, int chip)
+static void aurora_receive_exc(struct Aurora_board const * bp, int chip)
 {
 	struct Aurora_port *port;
 	struct tty_struct *tty;
@@ -442,15 +477,15 @@
 
 	tty = port->tty;
 	if (tty->flip.count >= TTY_FLIPBUF_SIZE)  {
-	#ifdef AURORA_INTNORM
+#ifdef AURORA_INTNORM
 		printk("aurora%d: port %d: Working around flip buffer overflow.\n",
 		       board_No(bp), port_No(port));
-	#endif
+#endif
 		return;
 	}
 	
 #ifdef AURORA_REPORT_OVERRUN	
-	status = bp->r[chip]->r[CD180_RCSR];
+	status = sbus_readb(&bp->r[chip]->r[CD180_RCSR]);
 	if (status & RCSR_OE)  {
 		port->overrun++;
 #if 1
@@ -460,12 +495,12 @@
 	}
 	status &= port->mark_mask;
 #else	
-	status = bp->r[chip]->r[CD180_RCSR] & port->mark_mask;
+	status = sbus_readb(&bp->r[chip]->r[CD180_RCSR]) & port->mark_mask;
 #endif	
-	ch = bp->r[chip]->r[CD180_RDR];
-	if (!status)  {
+	ch = sbus_readb(&bp->r[chip]->r[CD180_RDR]);
+	if (!status)
 		return;
-	}
+
 	if (status & RCSR_TOUT)  {
 /*		printk("aurora%d: port %d: Receiver timeout. Hardware problems ?\n",
 		       board_No(bp), port_No(port));*/
@@ -495,7 +530,7 @@
 	queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-extern inline void aurora_receive(struct Aurora_board const * bp, int chip)
+static void aurora_receive(struct Aurora_board const * bp, int chip)
 {
 	struct Aurora_port *port;
 	struct tty_struct *tty;
@@ -506,7 +541,7 @@
 	
 	tty = port->tty;
 	
-	count = bp->r[chip]->r[CD180_RDCR];
+	count = sbus_readb(&bp->r[chip]->r[CD180_RDCR]);
 
 #ifdef AURORA_REPORT_FIFO
 	port->hits[count > 8 ? 9 : count]++;
@@ -514,13 +549,13 @@
 
 	while (count--)  {
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE)  {
-		#ifdef AURORA_INTNORM
+#ifdef AURORA_INTNORM
 			printk("aurora%d: port %d: Working around flip buffer overflow.\n",
 			       board_No(bp), port_No(port));
-		#endif
+#endif
 			break;
 		}
-		cnt=bp->r[chip]->r[CD180_RDR];
+		cnt = sbus_readb(&bp->r[chip]->r[CD180_RDR]);
 		*tty->flip.char_buf_ptr++ = cnt;
 		*tty->flip.flag_buf_ptr++ = 0;
 		tty->flip.count++;
@@ -528,13 +563,12 @@
 	queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-extern inline void aurora_transmit(struct Aurora_board const * bp, int chip)
+static void aurora_transmit(struct Aurora_board const * bp, int chip)
 {
 	struct Aurora_port *port;
 	struct tty_struct *tty;
 	unsigned char count;
 	
-	
 	if (!(port = aurora_get_port(bp, chip, "Transmit")))
 		return;
 		
@@ -542,41 +576,53 @@
 	
 	if (port->SRER & SRER_TXEMPTY)  {
 		/* FIFO drained */
-		bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+		sbus_writeb(port_No(port) & 7,
+			    &bp->r[chip]->r[CD180_CAR]);
 		udelay(1);
 		port->SRER &= ~SRER_TXEMPTY;
-		bp->r[chip]->r[CD180_SRER]=port->SRER;
+		sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
 		return;
 	}
 	
 	if ((port->xmit_cnt <= 0 && !port->break_length)
 	    || tty->stopped || tty->hw_stopped)  {
-		bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+		sbus_writeb(port_No(port) & 7,
+			    &bp->r[chip]->r[CD180_CAR]);
 		udelay(1);
 		port->SRER &= ~SRER_TXRDY;
-		bp->r[chip]->r[CD180_SRER]=port->SRER;
+		sbus_writeb(port->SRER,
+			    &bp->r[chip]->r[CD180_SRER]);
 		return;
 	}
 	
 	if (port->break_length)  {
 		if (port->break_length > 0)  {
 			if (port->COR2 & COR2_ETC)  {
-				bp->r[chip]->r[CD180_TDR]=CD180_C_ESC;
-				bp->r[chip]->r[CD180_TDR]=CD180_C_SBRK;
+				sbus_writeb(CD180_C_ESC,
+					    &bp->r[chip]->r[CD180_TDR]);
+				sbus_writeb(CD180_C_SBRK,
+					    &bp->r[chip]->r[CD180_TDR]);
 				port->COR2 &= ~COR2_ETC;
 			}
 			count = MIN(port->break_length, 0xff);
-			bp->r[chip]->r[CD180_TDR]=CD180_C_ESC;
-			bp->r[chip]->r[CD180_TDR]=CD180_C_DELAY;
-			bp->r[chip]->r[CD180_TDR]=count;
+			sbus_writeb(CD180_C_ESC,
+				    &bp->r[chip]->r[CD180_TDR]);
+			sbus_writeb(CD180_C_DELAY,
+				    &bp->r[chip]->r[CD180_TDR]);
+			sbus_writeb(count,
+				    &bp->r[chip]->r[CD180_TDR]);
 			if (!(port->break_length -= count))
 				port->break_length--;
 		} else  {
-			bp->r[chip]->r[CD180_TDR]=CD180_C_ESC;
-			bp->r[chip]->r[CD180_TDR]=CD180_C_EBRK;
-			bp->r[chip]->r[CD180_COR2]=port->COR2;
+			sbus_writeb(CD180_C_ESC,
+				    &bp->r[chip]->r[CD180_TDR]);
+			sbus_writeb(CD180_C_EBRK,
+				    &bp->r[chip]->r[CD180_TDR]);
+			sbus_writeb(port->COR2,
+				    &bp->r[chip]->r[CD180_COR2]);
 			aurora_wait_CCR(bp->r[chip]);
-			bp->r[chip]->r[CD180_CCR]=CCR_CORCHG2;
+			sbus_writeb(CCR_CORCHG2,
+				    &bp->r[chip]->r[CD180_CCR]);
 			port->break_length = 0;
 		}
 		return;
@@ -584,23 +630,27 @@
 	
 	count = CD180_NFIFO;
 	do {
-		bp->r[chip]->r[CD180_TDR]=port->xmit_buf[port->xmit_tail++];
+		u8 byte = port->xmit_buf[port->xmit_tail++];
+
+		sbus_writeb(byte, &bp->r[chip]->r[CD180_TDR]);
 		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
 		if (--port->xmit_cnt <= 0)
 			break;
 	} while (--count > 0);
 	
 	if (port->xmit_cnt <= 0)  {
-		bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+		sbus_writeb(port_No(port) & 7,
+			    &bp->r[chip]->r[CD180_CAR]);
 		udelay(1);
 		port->SRER &= ~SRER_TXRDY;
-		bp->r[chip]->r[CD180_SRER]=port->SRER;
+		sbus_writeb(port->SRER,
+			    &bp->r[chip]->r[CD180_SRER]);
 	}
 	if (port->xmit_cnt <= port->wakeup_chars)
 		aurora_mark_event(port, RS_EVENT_WRITE_WAKEUP);
 }
 
-extern inline void aurora_check_modem(struct Aurora_board const * bp, int chip)
+static void aurora_check_modem(struct Aurora_board const * bp, int chip)
 {
 	struct Aurora_port *port;
 	struct tty_struct *tty;
@@ -611,9 +661,9 @@
 		
 	tty = port->tty;
 	
-	mcr = bp->r[chip]->r[CD180_MCR];
+	mcr = sbus_readb(&bp->r[chip]->r[CD180_MCR]);
 	if (mcr & MCR_CDCHG)  {
-		if (bp->r[chip]->r[CD180_MSVR] & MSVR_CD) 
+		if (sbus_readb(&bp->r[chip]->r[CD180_MSVR]) & MSVR_CD) 
 			wake_up_interruptible(&port->open_wait);
 		else if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
 			   (port->flags & ASYNC_CALLOUT_NOHUP)))
@@ -635,7 +685,7 @@
 			tty->hw_stopped = 1;
 			port->SRER &= ~SRER_TXRDY;
 		}
-		bp->r[chip]->r[CD180_SRER, port->SRER);
+		sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
 	}
 	if (mcr & MCR_DSRCHG)  {
 		if (aurora_in(bp, CD180_MSVR) & MSVR_DSR)  {
@@ -647,12 +697,12 @@
 			tty->hw_stopped = 1;
 			port->SRER &= ~SRER_TXRDY;
 		}
-		bp->r[chip]->r[CD180_SRER, port->SRER);
+		sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
 	}
 #endif AURORA_BRAIN_DAMAGED_CTS */
 	
 	/* Clear change bits */
-	bp->r[chip]->r[CD180_MCR]=0;
+	sbus_writeb(0, &bp->r[chip]->r[CD180_MCR]);
 }
 
 /* The main interrupt processing routine */
@@ -661,178 +711,177 @@
 	unsigned char status;
 	unsigned char ack,chip/*,chip_id*/;
 	struct Aurora_board * bp = (struct Aurora_board *) dev_id;
-	unsigned long loop=0;
+	unsigned long loop = 0;
 
-	#ifdef AURORA_INT_DEBUG
+#ifdef AURORA_INT_DEBUG
 	printk("IRQ%d %d\n",irq,++irqhit);
-	#ifdef AURORA_FLOODPRO
+#ifdef AURORA_FLOODPRO
 	if (irqhit>=AURORA_FLOODPRO)
-		bp->r0->r=8;
-	#endif
-	#endif
+		sbus_writeb(8, &bp->r0->r);
+#endif
+#endif
 	
 /* old	bp = IRQ_to_board[irq&0x0f];*/
 	
-	if (!bp || !(bp->flags & AURORA_BOARD_ACTIVE))  {
+	if (!bp || !(bp->flags & AURORA_BOARD_ACTIVE))
 		return;
-	}
 
 /*	The while() below takes care of this.
-	status=bp->r[0]->r[CD180_SRSR];
-	#ifdef AURORA_INT_DEBUG
-	printk("mumu: %02x\n",status);
-	#endif
-	if (!(status&SRSR_ANYINT)) return; * Nobody has anything to say, so exit *
+	status = sbus_readb(&bp->r[0]->r[CD180_SRSR]);
+#ifdef AURORA_INT_DEBUG
+	printk("mumu: %02x\n", status);
+#endif
+	if (!(status&SRSR_ANYINT))
+		return; * Nobody has anything to say, so exit *
 */
-	while ((loop++ < 48)&&(status=bp->r[0]->r[CD180_SRSR]&SRSR_ANYINT)){
-		#ifdef AURORA_INT_DEBUG
-		printk("SRSR: %02x\n",status);
-		#endif
-		if (status&SRSR_REXT) {
-			ack=bp->r3->r[bp->ACK_RINT];
-			#ifdef AURORA_INT_DEBUG
-			printk("R-ACK %02x\n",ack);
-			#endif
-			if ((ack>>5)==board_No(bp)) {
+	while ((loop++ < 48) &&
+	       (status = sbus_readb(&bp->r[0]->r[CD180_SRSR]) & SRSR_ANYINT)){
+#ifdef AURORA_INT_DEBUG
+		printk("SRSR: %02x\n", status);
+#endif
+		if (status & SRSR_REXT) {
+			ack = sbus_readb(&bp->r3->r[bp->ACK_RINT]);
+#ifdef AURORA_INT_DEBUG
+			printk("R-ACK %02x\n", ack);
+#endif
+			if ((ack >> 5) == board_No(bp)) {
 				if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) {
 					if ((ack&GSVR_ITMASK)==GSVR_IT_RGD) {
 						aurora_receive(bp,chip);
-						bp->r[chip]->r[CD180_EOSRR]=0;
-					} else
-					if ((ack&GSVR_ITMASK)==GSVR_IT_REXC) {
+						sbus_writeb(0,
+							 &bp->r[chip]->r[CD180_EOSRR]);
+					} else if ((ack & GSVR_ITMASK) == GSVR_IT_REXC) {
 						aurora_receive_exc(bp,chip);
-						bp->r[chip]->r[CD180_EOSRR]=0;
+						sbus_writeb(0,
+							 &bp->r[chip]->r[CD180_EOSRR]);
 					}
 				}
 			}
-		} else
-		if (status&SRSR_TEXT) {
-			ack=bp->r3->r[bp->ACK_TINT];
-			#ifdef AURORA_INT_DEBUG
-			printk("T-ACK %02x\n",ack);
-			#endif
-			if ((ack>>5)==board_No(bp)) {
+		} else if (status & SRSR_TEXT) {
+			ack = sbus_readb(&bp->r3->r[bp->ACK_TINT]);
+#ifdef AURORA_INT_DEBUG
+			printk("T-ACK %02x\n", ack);
+#endif
+			if ((ack >> 5) == board_No(bp)) {
 				if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) {
 					if ((ack&GSVR_ITMASK)==GSVR_IT_TX) {
 						aurora_transmit(bp,chip);
-						bp->r[chip]->r[CD180_EOSRR]=0;
+						sbus_writeb(0,
+							 &bp->r[chip]->r[CD180_EOSRR]);
 					}
 				}
 			}
-		} else
-		if (status&SRSR_MEXT) {
-			ack=bp->r3->r[bp->ACK_MINT];
-			#ifdef AURORA_INT_DEBUG
-			printk("M-ACK %02x\n",ack);
-			#endif
-			if ((ack>>5)==board_No(bp)) {
-				if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) {
+		} else if (status & SRSR_MEXT) {
+			ack = sbus_readb(&bp->r3->r[bp->ACK_MINT]);
+#ifdef AURORA_INT_DEBUG
+			printk("M-ACK %02x\n", ack);
+#endif
+			if ((ack >> 5) == board_No(bp)) {
+				if ((chip = ((ack>>3)&3)-1) < AURORA_NCD180) {
 					if ((ack&GSVR_ITMASK)==GSVR_IT_MDM) {
 						aurora_check_modem(bp,chip);
-						bp->r[chip]->r[CD180_EOSRR]=0;
+						sbus_writeb(0,
+							 &bp->r[chip]->r[CD180_EOSRR]);
 					}
 				}
 			}
 		}
 	}
-/* I guess this faster code can be used with CD1865, using AUROPRI and GLOBPRI.
+/* I guess this faster code can be used with CD1865, using AUROPRI and GLOBPRI. */
+#if 0
 	while ((loop++ < 48)&&(status=bp->r[0]->r[CD180_SRSR]&SRSR_ANYINT)){
-		#ifdef AURORA_INT_DEBUG
+#ifdef AURORA_INT_DEBUG
 		printk("SRSR: %02x\n",status);
-		#endif
-		ack=bp->r3->r[0];
-		#ifdef AURORA_INT_DEBUG
+#endif
+		ack = sbus_readb(&bp->r3->r[0]);
+#ifdef AURORA_INT_DEBUG
 		printk("ACK: %02x\n",ack);
-		#endif
+#endif
 		if ((ack>>5)==board_No(bp)) {
 			if ((chip=((ack>>3)&3)-1) < AURORA_NCD180) {
 				ack&=GSVR_ITMASK;
 				if (ack==GSVR_IT_RGD) {
 					aurora_receive(bp,chip);
-					bp->r[chip]->r[CD180_EOSRR]=0;
-				} else
-				if (ack==GSVR_IT_REXC) {
+					sbus_writeb(0,
+						    &bp->r[chip]->r[CD180_EOSRR]);
+				} else if (ack==GSVR_IT_REXC) {
 					aurora_receive_exc(bp,chip);
-					bp->r[chip]->r[CD180_EOSRR]=0;
-				} else
-				if (ack==GSVR_IT_TX) {
+					sbus_writeb(0,
+						    &bp->r[chip]->r[CD180_EOSRR]);
+				} else if (ack==GSVR_IT_TX) {
 					aurora_transmit(bp,chip);
-					bp->r[chip]->r[CD180_EOSRR]=0;
-				} else
-				if (ack==GSVR_IT_MDM) {
+					sbus_writeb(0,
+						    &bp->r[chip]->r[CD180_EOSRR]);
+				} else if (ack==GSVR_IT_MDM) {
 					aurora_check_modem(bp,chip);
-					bp->r[chip]->r[CD180_EOSRR]=0;
+					sbus_writeb(0,
+						    &bp->r[chip]->r[CD180_EOSRR]);
 				}
 			}
 		}
 	}
-*/
-/* This is the old handling routine, used in riscom8 for only one CD180. I keep it here for reference.
-for(chip=0;chip<AURORA_NCD180;chip++){
-	chip_id=(board_No(bp)<<5)|((chip+1)<<3);
-	loop=0;
-	while ((loop++ < 1) && ((status = bp->r[chip]->r[CD180_SRSR]) &
-			 (SRSR_TEXT | SRSR_MEXT | SRSR_REXT))) {
+#endif
 
-		if (status & SRSR_REXT) {
-			ack = bp->r3->r[bp->ACK_RINT];
-			if (ack == (chip_id | GSVR_IT_RGD)){
-				#ifdef AURORA_INTMSG
-				printk("RX ACK\n");
-				#endif
-				aurora_receive(bp,chip);
-				}
-			else if (ack == (chip_id | GSVR_IT_REXC)){
-				#ifdef AURORA_INTMSG
-				printk("RXC ACK\n");
-				#endif
-				aurora_receive_exc(bp,chip);
+/* This is the old handling routine, used in riscom8 for only one CD180. I keep it here for reference. */
+#if 0
+	for(chip=0;chip<AURORA_NCD180;chip++){
+		chip_id=(board_No(bp)<<5)|((chip+1)<<3);
+		loop=0;
+		while ((loop++ < 1) &&
+		       ((status = sbus_readb(&bp->r[chip]->r[CD180_SRSR])) &
+			(SRSR_TEXT | SRSR_MEXT | SRSR_REXT))) {
+
+			if (status & SRSR_REXT) {
+				ack = sbus_readb(&bp->r3->r[bp->ACK_RINT]);
+				if (ack == (chip_id | GSVR_IT_RGD)) {
+#ifdef AURORA_INTMSG
+					printk("RX ACK\n");
+#endif
+					aurora_receive(bp,chip);
+				} else if (ack == (chip_id | GSVR_IT_REXC)) {
+#ifdef AURORA_INTMSG
+					printk("RXC ACK\n");
+#endif
+					aurora_receive_exc(bp,chip);
+				} else {
+#ifdef AURORA_INTNORM
+					printk("aurora%d-%d: Bad receive ack 0x%02x.\n",
+					       board_No(bp), chip, ack);
+#endif
 				}
-			else
-				#ifdef AURORA_INTNORM
-				printk("aurora%d-%d: Bad receive ack 0x%02x.\n",
-				       board_No(bp), chip, ack)
-				#endif
-				;
-
-		} else if (status & SRSR_TEXT) {
-			ack = bp->r3->r[bp->ACK_TINT];
-			if (ack == (chip_id | GSVR_IT_TX)){
-				#ifdef AURORA_INTMSG
-				printk("TX ACK\n");
-				#endif
-				aurora_transmit(bp,chip);
+			} else if (status & SRSR_TEXT) {
+				ack = sbus_readb(&bp->r3->r[bp->ACK_TINT]);
+				if (ack == (chip_id | GSVR_IT_TX)){
+#ifdef AURORA_INTMSG
+					printk("TX ACK\n");
+#endif
+					aurora_transmit(bp,chip);
+				} else {
+#ifdef AURORA_INTNORM
+					printk("aurora%d-%d: Bad transmit ack 0x%02x.\n",
+					       board_No(bp), chip, ack);
+#endif
 				}
-			else{
-				#ifdef AURORA_INTNORM
-				printk("aurora%d-%d: Bad transmit ack 0x%02x.\n",
-				       board_No(bp), chip, ack);
-				#endif
-				       }
-
-		} else  if (status & SRSR_MEXT)  {
-			ack = bp->r3->r[bp->ACK_MINT];
-			if (ack == (chip_id | GSVR_IT_MDM)){
-				#ifdef AURORA_INTMSG
-				printk("MDM ACK\n");
-				#endif
-				aurora_check_modem(bp,chip);
+			} else  if (status & SRSR_MEXT)  {
+				ack = sbus_readb(&bp->r3->r[bp->ACK_MINT]);
+				if (ack == (chip_id | GSVR_IT_MDM)){
+#ifdef AURORA_INTMSG
+					printk("MDM ACK\n");
+#endif
+					aurora_check_modem(bp,chip);
+				} else {
+#ifdef AURORA_INTNORM
+					printk("aurora%d-%d: Bad modem ack 0x%02x.\n",
+					       board_No(bp), chip, ack);
+#endif
 				}
-			else
-				#ifdef AURORA_INTNORM
-				printk("aurora%d-%d: Bad modem ack 0x%02x.\n",
-				       board_No(bp), chip, ack)
-				#endif
-				;
-		
+			}
+			sbus_writeb(0, &bp->r[chip]->r[CD180_EOSRR]);
 		}
-		bp->r[chip]->r[CD180_EOSRR]=0;
 	}
-    }
-*/
+#endif
 }
 
-
 #ifdef AURORA_INT_DEBUG
 static void aurora_timer (unsigned long ignored);
 
@@ -847,12 +896,15 @@
 
 	save_flags(flags); cli();
 
-printk("SRSR: %02x,%02x - ",aurora_board[0].r[0]->r[CD180_SRSR],aurora_board[0].r[1]->r[CD180_SRSR]);
-for(i=0;i<4;i++){
-	udelay(1);
-	printk("%02x ",aurora_board[0].r3->r[i]);
+	printk("SRSR: %02x,%02x - ",
+	       sbus_readb(&aurora_board[0].r[0]->r[CD180_SRSR]),
+	       sbus_readb(&aurora_board[0].r[1]->r[CD180_SRSR]));
+	for (i = 0; i < 4; i++) {
+		udelay(1);
+		printk("%02x ",
+		       sbus_readb(&aurora_board[0].r3->r[i]));
 	}
-printk("\n");
+	printk("\n");
 
 	aurora_poll_timer.expires = jiffies + 300;
 	add_timer (&aurora_poll_timer);
@@ -866,59 +918,63 @@
  */
 
 /* Called with disabled interrupts */
-extern inline int aurora_setup_board(struct Aurora_board * bp)
+static int aurora_setup_board(struct Aurora_board * bp)
 {
 	int error;
 	
 #ifdef AURORA_ALLIRQ
 	int i;
-	for(i=0;i<AURORA_ALLIRQ;i++){
-		error = request_irq(allirq[i]|0x30, aurora_interrupt, SA_SHIRQ, "sio16", bp);
-		if (error){
-			printk(KERN_ERR "IRQ%d request error %d\n",allirq[i],error);
-		}
+	for (i = 0; i < AURORA_ALLIRQ; i++) {
+		error = request_irq(allirq[i]|0x30, aurora_interrupt, SA_SHIRQ,
+				    "sio16", bp);
+		if (error)
+			printk(KERN_ERR "IRQ%d request error %d\n",
+			       allirq[i], error);
 	}
 #else
-	error = request_irq(bp->irq|0x30, aurora_interrupt, SA_SHIRQ, "sio16", bp);
-	if (error){
-		printk(KERN_ERR "IRQ request error %d\n",error);
+	error = request_irq(bp->irq|0x30, aurora_interrupt, SA_SHIRQ,
+			    "sio16", bp);
+	if (error) {
+		printk(KERN_ERR "IRQ request error %d\n", error);
 		return error;
 	}
 #endif
 	/* Board reset */
-	bp->r0->r=0;
+	sbus_writeb(0, &bp->r0->r);
 	udelay(1);
-	if(bp->flags&AURORA_BOARD_TYPE_2){
+	if (bp->flags & AURORA_BOARD_TYPE_2) {
 		/* unknown yet */
 	} else {
-		bp->r0->r=AURORA_CFG_ENABLE_IO|AURORA_CFG_ENABLE_IRQ|(((bp->irq)&0x0f)>>2);
+		sbus_writeb((AURORA_CFG_ENABLE_IO | AURORA_CFG_ENABLE_IRQ |
+			     (((bp->irq)&0x0f)>>2)),
+			    &bp->r0->r);
 	}
 	udelay(10000);
 
 	if (aurora_init_CD180(bp,0))error=1;error=0;
 	if (aurora_init_CD180(bp,1))error++;
-	if (error==AURORA_NCD180) {
+	if (error == AURORA_NCD180) {
 		printk(KERN_ERR "Both chips failed initialisation.\n");
 		return -EIO;
-		}
+	}
 
 #ifdef AURORA_INT_DEBUG
-	aurora_poll_timer.expires=jiffies+1;
+	aurora_poll_timer.expires= jiffies + 1;
 	add_timer(&aurora_poll_timer);
 #endif
 #ifdef AURORA_DEBUG
-printk("aurora_setup_board: end\n");
+	printk("aurora_setup_board: end\n");
 #endif
 	return 0;
 }
 
 /* Called with disabled interrupts */
-extern inline void aurora_shutdown_board(struct Aurora_board *bp)
+static void aurora_shutdown_board(struct Aurora_board *bp)
 {
 	int i;
 
 #ifdef AURORA_DEBUG
-printk("aurora_shutdown_board: start\n");
+	printk("aurora_shutdown_board: start\n");
 #endif
 
 #ifdef AURORA_INT_DEBUG
@@ -926,9 +982,9 @@
 #endif
 
 #ifdef AURORA_ALLIRQ
-for(i=0;i<AURORA_ALLIRQ;i++){
-	free_irq(allirq[i]|0x30, bp);
-/*	IRQ_to_board[allirq[i]&0xf] = NULL;*/
+	for(i=0;i<AURORA_ALLIRQ;i++){
+		free_irq(allirq[i]|0x30, bp);
+/*		IRQ_to_board[allirq[i]&0xf] = NULL;*/
 	}
 #else
 	free_irq(bp->irq|0x30, bp);
@@ -936,21 +992,20 @@
 #endif	
 	/* Drop all DTR's */
 	for(i=0;i<16;i++){
-		bp->r[i>>3]->r[CD180_CAR]=i&7;
+		sbus_writeb(i & 7, &bp->r[i>>3]->r[CD180_CAR]);
 		udelay(1);
-		bp->r[i>>3]->r[CD180_MSVR]=0;
+		sbus_writeb(0, &bp->r[i>>3]->r[CD180_MSVR]);
 		udelay(1);
-		}
+	}
 	/* Board shutdown */
-	bp->r0->r=0;
+	sbus_writeb(0, &bp->r0->r);
 
 #ifdef AURORA_DEBUG
-printk("aurora_shutdown_board: end\n");
+	printk("aurora_shutdown_board: end\n");
 #endif
 }
 
-/*
- * Setting up port characteristics. 
+/* Setting up port characteristics. 
  * Must be called with disabled interrupts
  */
 static void aurora_change_speed(struct Aurora_board *bp, struct Aurora_port *port)
@@ -962,12 +1017,12 @@
 	unsigned char mcor1 = 0, mcor2 = 0,chip;
 	
 #ifdef AURORA_DEBUG
-printk("aurora_change_speed: start\n");
+	printk("aurora_change_speed: start\n");
 #endif
 	if (!(tty = port->tty) || !tty->termios)
 		return;
 		
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 
 	port->SRER  = 0;
 	port->COR2 = 0;
@@ -990,25 +1045,26 @@
 	}
 	
 	/* Select port on the board */
-	bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+	sbus_writeb(port_No(port) & 7,
+		    &bp->r[chip]->r[CD180_CAR]);
 	udelay(1);
 	
 	if (!baud_table[baud])  {
 		/* Drop DTR & exit */
 		port->MSVR &= ~(bp->DTR|bp->RTS);
-		bp->r[chip]->r[CD180_MSVR]=port->MSVR;
+		sbus_writeb(port->MSVR,
+			    &bp->r[chip]->r[CD180_MSVR]);
 		return;
 	} else  {
 		/* Set DTR on */
 		port->MSVR |= bp->DTR;
-		bp->r[chip]->r[CD180_MSVR]=port->MSVR;
+		sbus_writeb(port->MSVR,
+			    &bp->r[chip]->r[CD180_MSVR]);
 	}
 	
-	/*
-	 * Now we must calculate some speed depended things 
-	 */
+	/* Now we must calculate some speed dependant things. */
 	
-	/* Set baud rate for port */
+	/* Set baud rate for port. */
 	tmp = (((bp->oscfreq + baud_table[baud]/2) / baud_table[baud] +
 		CD180_TPC/2) / CD180_TPC);
 
@@ -1016,10 +1072,12 @@
 	if((tmp%10)>4)tmp=tmp/10+1;else tmp=tmp/10;*/
 /*	printk("Prescaler period: %d\n",tmp);*/
 
-	bp->r[chip]->r[CD180_RBPRH]=(tmp >> 8) & 0xff;
-	bp->r[chip]->r[CD180_TBPRH]=(tmp >> 8) & 0xff;
-	bp->r[chip]->r[CD180_RBPRL]=tmp & 0xff;
-	bp->r[chip]->r[CD180_TBPRL]=tmp & 0xff;
+	sbus_writeb((tmp >> 8) & 0xff,
+		    &bp->r[chip]->r[CD180_RBPRH]);
+	sbus_writeb((tmp >> 8) & 0xff,
+		    &bp->r[chip]->r[CD180_TBPRH]);
+	sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_RBPRL]);
+	sbus_writeb(tmp & 0xff, &bp->r[chip]->r[CD180_TBPRL]);
 	
 	baud = (baud_table[baud] + 5) / 10;   /* Estimated CPS */
 	
@@ -1031,7 +1089,7 @@
 	/* Receiver timeout will be transmission time for 1.5 chars */
 	tmp = (AURORA_TPS + AURORA_TPS/2 + baud/2) / baud;
 	tmp = (tmp > 0xff) ? 0xff : tmp;
-	bp->r[chip]->r[CD180_RTPR]=tmp;
+	sbus_writeb(tmp, &bp->r[chip]->r[CD180_RTPR]);
 	
 	switch (C_CSIZE(tty))  {
 	 case CS5:
@@ -1094,10 +1152,14 @@
 		cor3 |= (COR3_FCT | COR3_SCDE);
 		if (I_IXANY(tty))
 			port->COR2 |= COR2_IXM;
-		bp->r[chip]->r[CD180_SCHR1]=START_CHAR(tty);
-		bp->r[chip]->r[CD180_SCHR2]=STOP_CHAR(tty);
-		bp->r[chip]->r[CD180_SCHR3]=START_CHAR(tty);
-		bp->r[chip]->r[CD180_SCHR4]=STOP_CHAR(tty);
+		sbus_writeb(START_CHAR(tty),
+			    &bp->r[chip]->r[CD180_SCHR1]);
+		sbus_writeb(STOP_CHAR(tty),
+			    &bp->r[chip]->r[CD180_SCHR2]);
+		sbus_writeb(START_CHAR(tty),
+			    &bp->r[chip]->r[CD180_SCHR3]);
+		sbus_writeb(STOP_CHAR(tty),
+			    &bp->r[chip]->r[CD180_SCHR4]);
 	}
 	if (!C_CLOCAL(tty))  {
 		/* Enable CD check */
@@ -1113,24 +1175,25 @@
 	/* Set input FIFO size (1-8 bytes) */
 	cor3 |= AURORA_RXFIFO; 
 	/* Setting up CD180 channel registers */
-	bp->r[chip]->r[CD180_COR1]=cor1;
-	bp->r[chip]->r[CD180_COR2]=port->COR2;
-	bp->r[chip]->r[CD180_COR3]=cor3;
+	sbus_writeb(cor1, &bp->r[chip]->r[CD180_COR1]);
+	sbus_writeb(port->COR2, &bp->r[chip]->r[CD180_COR2]);
+	sbus_writeb(cor3, &bp->r[chip]->r[CD180_COR3]);
 	/* Make CD180 know about registers change */
 	aurora_wait_CCR(bp->r[chip]);
-	bp->r[chip]->r[CD180_CCR]=CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3;
+	sbus_writeb(CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3,
+		    &bp->r[chip]->r[CD180_CCR]);
 	/* Setting up modem option registers */
-	bp->r[chip]->r[CD180_MCOR1]=mcor1;
-	bp->r[chip]->r[CD180_MCOR2]=mcor2;
+	sbus_writeb(mcor1, &bp->r[chip]->r[CD180_MCOR1]);
+	sbus_writeb(mcor2, &bp->r[chip]->r[CD180_MCOR2]);
 	/* Enable CD180 transmitter & receiver */
 	aurora_wait_CCR(bp->r[chip]);
-	bp->r[chip]->r[CD180_CCR]=CCR_TXEN | CCR_RXEN;
+	sbus_writeb(CCR_TXEN | CCR_RXEN, &bp->r[chip]->r[CD180_CCR]);
 	/* Enable interrupts */
-	bp->r[chip]->r[CD180_SRER]=port->SRER;
+	sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
 	/* And finally set RTS on */
-	bp->r[chip]->r[CD180_MSVR]=port->MSVR;
+	sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]);
 #ifdef AURORA_DEBUG
-printk("aurora_change_speed: end\n");
+	printk("aurora_change_speed: end\n");
 #endif
 }
 
@@ -1140,7 +1203,7 @@
 	unsigned long flags;
 	
 #ifdef AURORA_DEBUG
-printk("aurora_setup_port: start %d\n",port_No(port));
+	printk("aurora_setup_port: start %d\n",port_No(port));
 #endif
 	if (port->flags & ASYNC_INITIALIZED)
 		return 0;
@@ -1167,8 +1230,8 @@
 #ifdef MODULE
 	if (port->count == 1) {
 		MOD_INC_USE_COUNT;
-		if((++bp->count)==1)
-			bp->flags|=AURORA_BOARD_ACTIVE;
+		if((++bp->count) == 1)
+			bp->flags |= AURORA_BOARD_ACTIVE;
 	}
 #endif
 
@@ -1178,7 +1241,7 @@
 		
 	restore_flags(flags);
 #ifdef AURORA_DEBUG
-printk("aurora_setup_port: end\n");
+	printk("aurora_setup_port: end\n");
 #endif
 	return 0;
 }
@@ -1190,12 +1253,12 @@
 	unsigned char chip;
 
 #ifdef AURORA_DEBUG
-printk("aurora_shutdown_port: start\n");
+	printk("aurora_shutdown_port: start\n");
 #endif
 	if (!(port->flags & ASYNC_INITIALIZED)) 
 		return;
 	
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 	
 #ifdef AURORA_REPORT_OVERRUN
 	printk("aurora%d: port %d: Total %ld overruns were detected.\n",
@@ -1221,18 +1284,22 @@
 	if (!(tty = port->tty) || C_HUPCL(tty))  {
 		/* Drop DTR */
 		port->MSVR &= ~(bp->DTR|bp->RTS);
-		bp->r[chip]->r[CD180_MSVR]=port->MSVR;
+		sbus_writeb(port->MSVR,
+			    &bp->r[chip]->r[CD180_MSVR]);
 	}
 	
         /* Select port */
-	bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+	sbus_writeb(port_No(port) & 7,
+		    &bp->r[chip]->r[CD180_CAR]);
 	udelay(1);
+
 	/* Reset port */
 	aurora_wait_CCR(bp->r[chip]);
-	bp->r[chip]->r[CD180_CCR]=CCR_SOFTRESET;
+	sbus_writeb(CCR_SOFTRESET, &bp->r[chip]->r[CD180_CCR]);
+
 	/* Disable all interrupts from this port */
 	port->SRER = 0;
-	bp->r[chip]->r[CD180_SRER]=port->SRER;
+	sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
 	
 	if (tty)  
 		set_bit(TTY_IO_ERROR, &tty->flags);
@@ -1240,18 +1307,19 @@
 
 #ifdef MODULE
 	if (--bp->count < 0)  {
-		printk(KERN_DEBUG "aurora%d: aurora_shutdown_port: bad board count: %d\n",
+		printk(KERN_DEBUG "aurora%d: aurora_shutdown_port: "
+		       "bad board count: %d\n",
 		       board_No(bp), bp->count);
 		bp->count = 0;
 	}
 	
 	MOD_DEC_USE_COUNT;
 	if (!bp->count)
-		bp->flags&=~AURORA_BOARD_ACTIVE;
+		bp->flags &= ~AURORA_BOARD_ACTIVE;
 #endif
 
 #ifdef AURORA_DEBUG
-printk("aurora_shutdown_port: end\n");
+	printk("aurora_shutdown_port: end\n");
 #endif
 }
 
@@ -1267,12 +1335,11 @@
 	unsigned char chip;
 	
 #ifdef AURORA_DEBUG
-printk("block_til_ready: start\n");
+	printk("block_til_ready: start\n");
 #endif
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 
-	/*
-	 * If the device is in the middle of being closed, then block
+	/* If the device is in the middle of being closed, then block
 	 * until it's done, and then try again.
 	 */
 	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
@@ -1283,8 +1350,7 @@
 			return -ERESTARTSYS;
 	}
 
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
+	/* 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) ||
@@ -1302,9 +1368,8 @@
 		if (C_CLOCAL(tty))  
 			do_clocal = 1;
 	}
-	
-	/*
-	 * Block waiting for the carrier detect and the line to become
+
+	/* Block waiting for the carrier detect and the line to become
 	 * free (i.e., not in use by the callout).  While we are in
 	 * this loop, info->count is dropped by one, so that
 	 * rs_close() knows when to free things.  We restore it upon
@@ -1319,12 +1384,16 @@
 	port->blocked_open++;
 	while (1) {
 		cli();
-		bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+		sbus_writeb(port_No(port) & 7,
+			    &bp->r[chip]->r[CD180_CAR]);
 		udelay(1);
-		CD = bp->r[chip]->r[CD180_MSVR] & MSVR_CD;
+		CD = sbus_readb(&bp->r[chip]->r[CD180_MSVR]) & MSVR_CD;
 		if (!(port->flags & ASYNC_CALLOUT_ACTIVE))  {
 			port->MSVR=bp->RTS;
-			bp->r[chip]->r[CD180_MSVR]=port->MSVR;/* auto drops DTR */
+
+			/* auto drops DTR */
+			sbus_writeb(port->MSVR,
+				    &bp->r[chip]->r[CD180_MSVR]);
 		}
 		sti();
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -1356,7 +1425,7 @@
 	
 	port->flags |= ASYNC_NORMAL_ACTIVE;
 #ifdef AURORA_DEBUG
-printk("block_til_ready: end\n");
+	printk("block_til_ready: end\n");
 #endif
 	return 0;
 }	
@@ -1369,44 +1438,46 @@
 	struct Aurora_board * bp;
 	unsigned long flags;
 	
-	#ifdef AURORA_DEBUG
+#ifdef AURORA_DEBUG
 	printk("aurora_open: start\n");
-	#endif
+#endif
 	
 	board = AURORA_BOARD(MINOR(tty->device));
-	if (board > AURORA_NBOARD || !(aurora_board[board].flags & AURORA_BOARD_PRESENT)){
-		#ifdef AURORA_DEBUG
-		printk("aurora_open: error board %d present %d\n",board,aurora_board[board].flags &AURORA_BOARD_PRESENT);
-		#endif
+	if (board > AURORA_NBOARD ||
+	    !(aurora_board[board].flags & AURORA_BOARD_PRESENT)) {
+#ifdef AURORA_DEBUG
+		printk("aurora_open: error board %d present %d\n",
+		       board, aurora_board[board].flags & AURORA_BOARD_PRESENT);
+#endif
 		return -ENODEV;
-		}
+	}
 	
 	bp = &aurora_board[board];
 	port = aurora_port + board * AURORA_NPORT * AURORA_NCD180 + AURORA_PORT(MINOR(tty->device));
-	if (aurora_paranoia_check(port, tty->device, "aurora_open")){
-		#ifdef AURORA_DEBUG
+	if (aurora_paranoia_check(port, tty->device, "aurora_open")) {
+#ifdef AURORA_DEBUG
 		printk("aurora_open: error paranoia check\n");
-		#endif
+#endif
 		return -ENODEV;
-		}
+	}
 	
 	port->count++;
 	tty->driver_data = port;
 	port->tty = tty;
 	
 	if ((error = aurora_setup_port(bp, port))) {
-		#ifdef AURORA_DEBUG
+#ifdef AURORA_DEBUG
 		printk("aurora_open: error aurora_setup_port ret %d\n",error);
-		#endif
+#endif
 		return error;
-		}
+	}
 
-	if ((error = block_til_ready(tty, filp, port))){
-		#ifdef AURORA_DEBUG
+	if ((error = block_til_ready(tty, filp, port))) {
+#ifdef AURORA_DEBUG
 		printk("aurora_open: error block_til_ready ret %d\n",error);
-		#endif
+#endif
 		return error;
-		}
+	}
 	
 	if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) {
 		*tty->termios = port->normal_termios;
@@ -1417,9 +1488,9 @@
 
 	port->session = current->session;
 	port->pgrp = current->pgrp;
-	#ifdef AURORA_DEBUG
+#ifdef AURORA_DEBUG
 	printk("aurora_open: end\n");
-	#endif
+#endif
 	return 0;
 }
 
@@ -1431,14 +1502,14 @@
 	unsigned long timeout;
 	unsigned char chip;
 	
-	#ifdef AURORA_DEBUG
+#ifdef AURORA_DEBUG
 	printk("aurora_close: start\n");
-	#endif
+#endif
 	
 	if (!port || aurora_paranoia_check(port, tty->device, "close"))
 		return;
 	
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 
 	save_flags(flags); cli();
 	if (tty_hung_up_p(filp))  {
@@ -1448,12 +1519,14 @@
 	
 	bp = port_Board(port);
 	if ((tty->count == 1) && (port->count != 1))  {
-		printk(KERN_DEBUG "aurora%d: aurora_close: bad port count; tty->count is 1, port count is %d\n",
+		printk(KERN_DEBUG "aurora%d: aurora_close: bad port count; "
+		       "tty->count is 1, port count is %d\n",
 		       board_No(bp), port->count);
 		port->count = 1;
 	}
 	if (--port->count < 0)  {
-		printk(KERN_DEBUG "aurora%d: aurora_close: bad port count for tty%d: %d\n",
+		printk(KERN_DEBUG "aurora%d: aurora_close: bad port "
+		       "count for tty%d: %d\n",
 		       board_No(bp), port_No(port), port->count);
 		port->count = 0;
 	}
@@ -1462,27 +1535,27 @@
 		return;
 	}
 	port->flags |= ASYNC_CLOSING;
-	/*
-	 * Save the termios structure, since this port may have
+
+	/* Save the termios structure, since this port may have
 	 * separate termios for callout and dialin.
 	 */
 	if (port->flags & ASYNC_NORMAL_ACTIVE)
 		port->normal_termios = *tty->termios;
 /*	if (port->flags & ASYNC_CALLOUT_ACTIVE)
 		port->callout_termios = *tty->termios;*/
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify 
+
+	/* 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 (port->closing_wait != ASYNC_CLOSING_WAIT_NONE){
-		#ifdef AURORA_DEBUG
+#ifdef AURORA_DEBUG
 		printk("aurora_close: waiting to flush...\n");
-		#endif
+#endif
 		tty_wait_until_sent(tty, port->closing_wait);
-		}
-	/*
-	 * At this point we stop accepting input.  To do this, we
+	}
+
+	/* At this point we stop accepting input.  To do this, we
 	 * disable the receive line status interrupts, and tell the
 	 * interrupt driver to stop checking the data ready bit in the
 	 * line status register.
@@ -1491,9 +1564,10 @@
 	if (port->flags & ASYNC_INITIALIZED) {
 		port->SRER &= ~SRER_TXRDY;
 		port->SRER |= SRER_TXEMPTY;
-		bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+		sbus_writeb(port_No(port) & 7,
+			    &bp->r[chip]->r[CD180_CAR]);
 		udelay(1);
-		bp->r[chip]->r[CD180_SRER]=port->SRER;
+		sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
 		/*
 		 * Before we drop DTR, make sure the UART transmitter
 		 * has completely drained; this is especially
@@ -1507,9 +1581,9 @@
 				break;
 		}
 	}
-	#ifdef AURORA_DEBUG
+#ifdef AURORA_DEBUG
 	printk("aurora_close: shutdown_port\n");
-	#endif
+#endif
 	aurora_shutdown_port(bp, port);
 	if (tty->driver.flush_buffer)
 		tty->driver.flush_buffer(tty);
@@ -1529,27 +1603,27 @@
 			 ASYNC_CLOSING);
 	wake_up_interruptible(&port->close_wait);
 	restore_flags(flags);
-	#ifdef AURORA_DEBUG
+#ifdef AURORA_DEBUG
 	printk("aurora_close: end\n");
-	#endif
+#endif
 }
 
 static int aurora_write(struct tty_struct * tty, int from_user, 
-		    const unsigned char *buf, int count)
+			const unsigned char *buf, int count)
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	struct Aurora_board *bp;
 	int c, total = 0;
 	unsigned long flags;
 	unsigned char chip;
 
 #ifdef AURORA_DEBUG
-printk("aurora_write: start %d\n",count);
+	printk("aurora_write: start %d\n",count);
 #endif
 	if (aurora_paranoia_check(port, tty->device, "aurora_write"))
 		return 0;
 		
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 	
 	bp = port_Board(port);
 
@@ -1586,24 +1660,25 @@
 	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
 	    !(port->SRER & SRER_TXRDY)) {
 		port->SRER |= SRER_TXRDY;
-		bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+		sbus_writeb(port_No(port) & 7,
+			    &bp->r[chip]->r[CD180_CAR]);
 		udelay(1);
-		bp->r[chip]->r[CD180_SRER]=port->SRER;
+		sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
 	}
 	restore_flags(flags);
 #ifdef AURORA_DEBUG
-printk("aurora_write: end %d\n",total);
+	printk("aurora_write: end %d\n",total);
 #endif
 	return total;
 }
 
 static void aurora_put_char(struct tty_struct * tty, unsigned char ch)
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	unsigned long flags;
 
 #ifdef AURORA_DEBUG
-printk("aurora_put_char: start %c\n",ch);
+	printk("aurora_put_char: start %c\n",ch);
 #endif
 	if (aurora_paranoia_check(port, tty->device, "aurora_put_char"))
 		return;
@@ -1623,23 +1698,23 @@
 	port->xmit_cnt++;
 	restore_flags(flags);
 #ifdef AURORA_DEBUG
-printk("aurora_put_char: end\n");
+	printk("aurora_put_char: end\n");
 #endif
 }
 
 static void aurora_flush_chars(struct tty_struct * tty)
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	unsigned long flags;
 	unsigned char chip;
 
 /*#ifdef AURORA_DEBUG
-printk("aurora_flush_chars: start\n");
+	printk("aurora_flush_chars: start\n");
 #endif*/
 	if (aurora_paranoia_check(port, tty->device, "aurora_flush_chars"))
 		return;
 		
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 	
 	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
 	    !port->xmit_buf)
@@ -1647,22 +1722,24 @@
 
 	save_flags(flags); cli();
 	port->SRER |= SRER_TXRDY;
-	port_Board(port)->r[chip]->r[CD180_CAR]=port_No(port)&7;
+	sbus_writeb(port_No(port) & 7,
+		    &port_Board(port)->r[chip]->r[CD180_CAR]);
 	udelay(1);
-	port_Board(port)->r[chip]->r[CD180_SRER]=port->SRER;
+	sbus_writeb(port->SRER,
+		    &port_Board(port)->r[chip]->r[CD180_SRER]);
 	restore_flags(flags);
 /*#ifdef AURORA_DEBUG
-printk("aurora_flush_chars: end\n");
+	printk("aurora_flush_chars: end\n");
 #endif*/
 }
 
 static int aurora_write_room(struct tty_struct * tty)
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	int	ret;
 
 #ifdef AURORA_DEBUG
-printk("aurora_write_room: start\n");
+	printk("aurora_write_room: start\n");
 #endif
 	if (aurora_paranoia_check(port, tty->device, "aurora_write_room"))
 		return 0;
@@ -1671,14 +1748,14 @@
 	if (ret < 0)
 		ret = 0;
 #ifdef AURORA_DEBUG
-printk("aurora_write_room: end\n");
+	printk("aurora_write_room: end\n");
 #endif
 	return ret;
 }
 
 static int aurora_chars_in_buffer(struct tty_struct *tty)
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 				
 	if (aurora_paranoia_check(port, tty->device, "aurora_chars_in_buffer"))
 		return 0;
@@ -1688,11 +1765,11 @@
 
 static void aurora_flush_buffer(struct tty_struct *tty)
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	unsigned long flags;
 
 #ifdef AURORA_DEBUG
-printk("aurora_flush_buffer: start\n");
+	printk("aurora_flush_buffer: start\n");
 #endif
 	if (aurora_paranoia_check(port, tty->device, "aurora_flush_buffer"))
 		return;
@@ -1706,7 +1783,7 @@
 	    tty->ldisc.write_wakeup)
 		(tty->ldisc.write_wakeup)(tty);
 #ifdef AURORA_DEBUG
-printk("aurora_flush_buffer: end\n");
+	printk("aurora_flush_buffer: end\n");
 #endif
 }
 
@@ -1718,31 +1795,37 @@
 	unsigned long flags;
 
 #ifdef AURORA_DEBUG
-printk("aurora_get_modem_info: start\n");
+	printk("aurora_get_modem_info: start\n");
 #endif
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 
 	bp = port_Board(port);
+
 	save_flags(flags); cli();
-	bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+
+	sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]);
 	udelay(1);
-	status = bp->r[chip]->r[CD180_MSVR];
+
+	status = sbus_readb(&bp->r[chip]->r[CD180_MSVR]);
 	result = 0/*bp->r[chip]->r[AURORA_RI] & (1u << port_No(port)) ? 0 : TIOCM_RNG*/;
+
 	restore_flags(flags);
+
 	result |= ((status & bp->RTS) ? TIOCM_RTS : 0)
 		| ((status & bp->DTR) ? TIOCM_DTR : 0)
 		| ((status & MSVR_CD)  ? TIOCM_CAR : 0)
 		| ((status & MSVR_DSR) ? TIOCM_DSR : 0)
 		| ((status & MSVR_CTS) ? TIOCM_CTS : 0);
+
 	put_user(result,(unsigned long *) value);
 #ifdef AURORA_DEBUG
-printk("aurora_get_modem_info: end\n");
+	printk("aurora_get_modem_info: end\n");
 #endif
 	return 0;
 }
 
 static int aurora_set_modem_info(struct Aurora_port * port, unsigned int cmd,
-			     unsigned int *value)
+				 unsigned int *value)
 {
 	int error;
 	unsigned int arg;
@@ -1751,12 +1834,12 @@
 	unsigned char chip;
 
 #ifdef AURORA_DEBUG
-printk("aurora_set_modem_info: start\n");
+	printk("aurora_set_modem_info: start\n");
 #endif
 	error = get_user(arg, value);
 	if (error) 
 		return error;
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 	switch (cmd) {
 	 case TIOCMBIS: 
 		if (arg & TIOCM_RTS) 
@@ -1778,48 +1861,56 @@
 		break;
 	 default:
 		return -EINVAL;
-	}
+	};
+
 	save_flags(flags); cli();
-	bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+
+	sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]);
 	udelay(1);
-	bp->r[chip]->r[CD180_MSVR]=port->MSVR;
+
+	sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]);
+
 	restore_flags(flags);
 #ifdef AURORA_DEBUG
-printk("aurora_set_modem_info: end\n");
+	printk("aurora_set_modem_info: end\n");
 #endif
 	return 0;
 }
 
-extern inline void aurora_send_break(struct Aurora_port * port, unsigned long length)
+static void aurora_send_break(struct Aurora_port * port, unsigned long length)
 {
 	struct Aurora_board *bp = port_Board(port);
 	unsigned long flags;
 	unsigned char chip;
 	
 #ifdef AURORA_DEBUG
-printk("aurora_send_break: start\n");
+	printk("aurora_send_break: start\n");
 #endif
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 	
 	save_flags(flags); cli();
+
 	port->break_length = AURORA_TPS / HZ * length;
 	port->COR2 |= COR2_ETC;
 	port->SRER  |= SRER_TXRDY;
-	bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+	sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]);
 	udelay(1);
-	bp->r[chip]->r[CD180_COR2]=port->COR2;
-	bp->r[chip]->r[CD180_SRER]=port->SRER;
+
+	sbus_writeb(port->COR2, &bp->r[chip]->r[CD180_COR2]);
+	sbus_writeb(port->SRER, &bp->r[chip]->r[CD180_SRER]);
 	aurora_wait_CCR(bp->r[chip]);
-	bp->r[chip]->r[CD180_CCR]=CCR_CORCHG2;
+
+	sbus_writeb(CCR_CORCHG2, &bp->r[chip]->r[CD180_CCR]);
 	aurora_wait_CCR(bp->r[chip]);
+
 	restore_flags(flags);
 #ifdef AURORA_DEBUG
-printk("aurora_send_break: end\n");
+	printk("aurora_send_break: end\n");
 #endif
 }
 
-extern inline int aurora_set_serial_info(struct Aurora_port * port,
-				     struct serial_struct * newinfo)
+static int aurora_set_serial_info(struct Aurora_port * port,
+				  struct serial_struct * newinfo)
 {
 	struct serial_struct tmp;
 	struct Aurora_board *bp = port_Board(port);
@@ -1828,7 +1919,7 @@
 	int error;
 
 #ifdef AURORA_DEBUG
-printk("aurora_set_serial_info: start\n");
+	printk("aurora_set_serial_info: start\n");
 #endif
 	error = verify_area(VERIFY_READ, (void *) newinfo, sizeof(tmp));
 	if (error)
@@ -1869,20 +1960,20 @@
 		restore_flags(flags);
 	}
 #ifdef AURORA_DEBUG
-printk("aurora_set_serial_info: end\n");
+	printk("aurora_set_serial_info: end\n");
 #endif
 	return 0;
 }
 
-extern inline int aurora_get_serial_info(struct Aurora_port * port,
-				     struct serial_struct * retinfo)
+extern int aurora_get_serial_info(struct Aurora_port * port,
+				  struct serial_struct * retinfo)
 {
 	struct serial_struct tmp;
 	struct Aurora_board *bp = port_Board(port);
 	int error;
 	
 #ifdef AURORA_DEBUG
-printk("aurora_get_serial_info: start\n");
+	printk("aurora_get_serial_info: start\n");
 #endif
 	error = verify_area(VERIFY_WRITE, (void *) retinfo, sizeof(tmp));
 	if (error)
@@ -1909,18 +2000,18 @@
 		    unsigned int cmd, unsigned long arg)
 		    
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	int error;
 	int retval;
 
 #ifdef AURORA_DEBUG
-printk("aurora_ioctl: start\n");
+	printk("aurora_ioctl: start\n");
 #endif
 	if (aurora_paranoia_check(port, tty->device, "aurora_ioctl"))
 		return -ENODEV;
 	
 	switch (cmd) {
-	 case TCSBRK:	/* SVID version: non-zero arg --> no break */
+	case TCSBRK:	/* SVID version: non-zero arg --> no break */
 		retval = tty_check_change(tty);
 		if (retval)
 			return retval;
@@ -1928,171 +2019,177 @@
 		if (!arg)
 			aurora_send_break(port, HZ/4);	/* 1/4 second */
 		return 0;
-	 case TCSBRKP:	/* support for POSIX tcsendbreak() */
+	case TCSBRKP:	/* support for POSIX tcsendbreak() */
 		retval = tty_check_change(tty);
 		if (retval)
 			return retval;
 		tty_wait_until_sent(tty, 0);
 		aurora_send_break(port, arg ? arg*(HZ/10) : HZ/4);
 		return 0;
-	 case TIOCGSOFTCAR:
+	case TIOCGSOFTCAR:
 		error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
 		if (error)
 			return error;
 		put_user(C_CLOCAL(tty) ? 1 : 0,
-			    (unsigned long *) arg);
+			 (unsigned long *) arg);
 		return 0;
-	 case TIOCSSOFTCAR:
+	case TIOCSSOFTCAR:
 		retval = get_user(arg,(unsigned long *) arg);
 		if (retval)
 			return retval;
 		tty->termios->c_cflag =
 			((tty->termios->c_cflag & ~CLOCAL) |
-			(arg ? CLOCAL : 0));
+			 (arg ? CLOCAL : 0));
 		return 0;
-	 case TIOCMGET:
+	case TIOCMGET:
 		error = verify_area(VERIFY_WRITE, (void *) arg,
 				    sizeof(unsigned int));
 		if (error)
 			return error;
 		return aurora_get_modem_info(port, (unsigned int *) arg);
-	 case TIOCMBIS:
-	 case TIOCMBIC:
-	 case TIOCMSET:
+	case TIOCMBIS:
+	case TIOCMBIC:
+	case TIOCMSET:
 		return aurora_set_modem_info(port, cmd, (unsigned int *) arg);
-	 case TIOCGSERIAL:	
+	case TIOCGSERIAL:	
 		return aurora_get_serial_info(port, (struct serial_struct *) arg);
-	 case TIOCSSERIAL:	
+	case TIOCSSERIAL:	
 		return aurora_set_serial_info(port, (struct serial_struct *) arg);
-	 default:
+	default:
 		return -ENOIOCTLCMD;
-	}
+	};
 #ifdef AURORA_DEBUG
-printk("aurora_ioctl: end\n");
+	printk("aurora_ioctl: end\n");
 #endif
 	return 0;
 }
 
 static void aurora_throttle(struct tty_struct * tty)
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	struct Aurora_board *bp;
 	unsigned long flags;
 	unsigned char chip;
 
 #ifdef AURORA_DEBUG
-printk("aurora_throttle: start\n");
+	printk("aurora_throttle: start\n");
 #endif
 	if (aurora_paranoia_check(port, tty->device, "aurora_throttle"))
 		return;
 	
 	bp = port_Board(port);
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 	
 	save_flags(flags); cli();
 	port->MSVR &= ~bp->RTS;
-	bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+	sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]);
 	udelay(1);
 	if (I_IXOFF(tty))  {
 		aurora_wait_CCR(bp->r[chip]);
-		bp->r[chip]->r[CD180_CCR]=CCR_SSCH2;
+		sbus_writeb(CCR_SSCH2, &bp->r[chip]->r[CD180_CCR]);
 		aurora_wait_CCR(bp->r[chip]);
 	}
-	bp->r[chip]->r[CD180_MSVR]=port->MSVR;
+	sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]);
 	restore_flags(flags);
 #ifdef AURORA_DEBUG
-printk("aurora_throttle: end\n");
+	printk("aurora_throttle: end\n");
 #endif
 }
 
 static void aurora_unthrottle(struct tty_struct * tty)
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	struct Aurora_board *bp;
 	unsigned long flags;
 	unsigned char chip;
 
 #ifdef AURORA_DEBUG
-printk("aurora_unthrottle: start\n");
+	printk("aurora_unthrottle: start\n");
 #endif
 	if (aurora_paranoia_check(port, tty->device, "aurora_unthrottle"))
 		return;
 	
 	bp = port_Board(port);
 	
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 	
 	save_flags(flags); cli();
 	port->MSVR |= bp->RTS;
-	bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+	sbus_writeb(port_No(port) & 7,
+		    &bp->r[chip]->r[CD180_CAR]);
 	udelay(1);
 	if (I_IXOFF(tty))  {
 		aurora_wait_CCR(bp->r[chip]);
-		bp->r[chip]->r[CD180_CCR]=CCR_SSCH1;
+		sbus_writeb(CCR_SSCH1,
+			    &bp->r[chip]->r[CD180_CCR]);
 		aurora_wait_CCR(bp->r[chip]);
 	}
-	bp->r[chip]->r[CD180_MSVR]=port->MSVR;
+	sbus_writeb(port->MSVR, &bp->r[chip]->r[CD180_MSVR]);
 	restore_flags(flags);
 #ifdef AURORA_DEBUG
-printk("aurora_unthrottle: end\n");
+	printk("aurora_unthrottle: end\n");
 #endif
 }
 
 static void aurora_stop(struct tty_struct * tty)
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	struct Aurora_board *bp;
 	unsigned long flags;
 	unsigned char chip;
 
 #ifdef AURORA_DEBUG
-printk("aurora_stop: start\n");
+	printk("aurora_stop: start\n");
 #endif
 	if (aurora_paranoia_check(port, tty->device, "aurora_stop"))
 		return;
 	
 	bp = port_Board(port);
 	
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 	
 	save_flags(flags); cli();
 	port->SRER &= ~SRER_TXRDY;
-	bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+	sbus_writeb(port_No(port) & 7,
+		    &bp->r[chip]->r[CD180_CAR]);
 	udelay(1);
-	bp->r[chip]->r[CD180_SRER]=port->SRER;
+	sbus_writeb(port->SRER,
+		    &bp->r[chip]->r[CD180_SRER]);
 	restore_flags(flags);
 #ifdef AURORA_DEBUG
-printk("aurora_stop: end\n");
+	printk("aurora_stop: end\n");
 #endif
 }
 
 static void aurora_start(struct tty_struct * tty)
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	struct Aurora_board *bp;
 	unsigned long flags;
 	unsigned char chip;
 
 #ifdef AURORA_DEBUG
-printk("aurora_start: start\n");
+	printk("aurora_start: start\n");
 #endif
 	if (aurora_paranoia_check(port, tty->device, "aurora_start"))
 		return;
 	
 	bp = port_Board(port);
 	
-	chip=AURORA_CD180(port_No(port));
+	chip = AURORA_CD180(port_No(port));
 	
 	save_flags(flags); cli();
 	if (port->xmit_cnt && port->xmit_buf && !(port->SRER & SRER_TXRDY))  {
 		port->SRER |= SRER_TXRDY;
-		bp->r[chip]->r[CD180_CAR]=port_No(port)&7;
+		sbus_writeb(port_No(port) & 7,
+			    &bp->r[chip]->r[CD180_CAR]);
 		udelay(1);
-		bp->r[chip]->r[CD180_SRER]=port->SRER;
+		sbus_writeb(port->SRER,
+			    &bp->r[chip]->r[CD180_SRER]);
 	}
 	restore_flags(flags);
 #ifdef AURORA_DEBUG
-printk("aurora_start: end\n");
+	printk("aurora_start: end\n");
 #endif
 }
 
@@ -2111,25 +2208,25 @@
 	struct tty_struct	*tty;
 
 #ifdef AURORA_DEBUG
-printk("do_aurora_hangup: start\n");
+	printk("do_aurora_hangup: start\n");
 #endif
 	tty = port->tty;
-	if (!tty)
+	if (tty == NULL)
 		return;
 
 	tty_hangup(tty);
 #ifdef AURORA_DEBUG
-printk("do_aurora_hangup: end\n");
+	printk("do_aurora_hangup: end\n");
 #endif
 }
 
 static void aurora_hangup(struct tty_struct * tty)
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	struct Aurora_board *bp;
 				
 #ifdef AURORA_DEBUG
-printk("aurora_hangup: start\n");
+	printk("aurora_hangup: start\n");
 #endif
 	if (aurora_paranoia_check(port, tty->device, "aurora_hangup"))
 		return;
@@ -2143,17 +2240,17 @@
 	port->tty = 0;
 	wake_up_interruptible(&port->open_wait);
 #ifdef AURORA_DEBUG
-printk("aurora_hangup: end\n");
+	printk("aurora_hangup: end\n");
 #endif
 }
 
 static void aurora_set_termios(struct tty_struct * tty, struct termios * old_termios)
 {
-	struct Aurora_port *port = (struct Aurora_port *)tty->driver_data;
+	struct Aurora_port *port = (struct Aurora_port *) tty->driver_data;
 	unsigned long flags;
 
 #ifdef AURORA_DEBUG
-printk("aurora_set_termios: start\n");
+	printk("aurora_set_termios: start\n");
 #endif
 	if (aurora_paranoia_check(port, tty->device, "aurora_set_termios"))
 		return;
@@ -2172,7 +2269,7 @@
 		aurora_start(tty);
 	}
 #ifdef AURORA_DEBUG
-printk("aurora_set_termios: end\n");
+	printk("aurora_set_termios: end\n");
 #endif
 }
 
@@ -2187,9 +2284,10 @@
 	struct tty_struct	*tty;
 
 #ifdef AURORA_DEBUG
-printk("do_softint: start\n");
+	printk("do_softint: start\n");
 #endif
-	if(!(tty = port->tty)) 
+	tty = port->tty;
+	if (tty == NULL)
 		return;
 
 	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
@@ -2199,7 +2297,7 @@
 		wake_up_interruptible(&tty->write_wait);
 	}
 #ifdef AURORA_DEBUG
-printk("do_softint: end\n");
+	printk("do_softint: end\n");
 #endif
 }
 
@@ -2209,9 +2307,10 @@
 	int i;
 
 #ifdef AURORA_DEBUG
-printk("aurora_init_drivers: start\n");
+	printk("aurora_init_drivers: start\n");
 #endif
-	if (!(tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL))) {
+	tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL);
+	if (tmp_buf == NULL) {
 		printk(KERN_ERR "aurora: Couldn't get free page.\n");
 		return 1;
 	}
@@ -2249,8 +2348,9 @@
 	aurora_driver.start = aurora_start;
 	aurora_driver.hangup = aurora_hangup;
 
-	if ((error = tty_register_driver(&aurora_driver)))  {
-		free_page((unsigned long)tmp_buf);
+	error = tty_register_driver(&aurora_driver);
+	if (error) {
+		free_page((unsigned long) tmp_buf);
 		printk(KERN_ERR "aurora: Couldn't register aurora driver, error = %d\n",
 		       error);
 		return 1;
@@ -2270,7 +2370,7 @@
 		init_waitqueue_head(&aurora_port[i].close_wait);
 	}
 #ifdef AURORA_DEBUG
-printk("aurora_init_drivers: end\n");
+	printk("aurora_init_drivers: end\n");
 #endif
 	return 0;
 }
@@ -2278,12 +2378,12 @@
 static void aurora_release_drivers(void)
 {
 #ifdef AURORA_DEBUG
-printk("aurora_release_drivers: start\n");
+	printk("aurora_release_drivers: start\n");
 #endif
 	free_page((unsigned long)tmp_buf);
 	tty_unregister_driver(&aurora_driver);
 #ifdef AURORA_DEBUG
-printk("aurora_release_drivers: end\n");
+	printk("aurora_release_drivers: end\n");
 #endif
 }
 
@@ -2297,7 +2397,7 @@
  * addresses in this case.
  *
  */
-__init_func(void aurora_setup(char *str, int *ints))
+void __init aurora_setup(char *str, int *ints)
 {
 	int i;
 
@@ -2306,33 +2406,37 @@
 		}
 }
 
-__init_func(int aurora_init(void))
+int __init aurora_init(void)
 #else
 int aurora_init(void)
 #endif
 {
-int found;
-int grrr,i;
+	int found;
+	int i;
 
-printk(KERN_INFO "aurora: Driver starting.\n");
-if(aurora_init_drivers())return -EIO;
-found=aurora_probe();
-if(!found){
-  aurora_release_drivers();
-  printk(KERN_INFO "aurora: No Aurora Multiport boards detected.\n");
-  return -EIO;
-  } else {
-  printk(KERN_INFO "aurora: %d boards found.\n",found);
-  }
-for(i=0;i<found;i++){
-	if ((grrr = aurora_setup_board(&aurora_board[i]))) {
-		#ifdef AURORA_DEBUG
-		printk(KERN_ERR "aurora_init: error aurora_setup_board ret %d\n",grrr);
-		#endif
-		return grrr;
+	printk(KERN_INFO "aurora: Driver starting.\n");
+	if(aurora_init_drivers())
+		return -EIO;
+	found = aurora_probe();
+	if(!found) {
+		aurora_release_drivers();
+		printk(KERN_INFO "aurora: No Aurora Multiport boards detected.\n");
+		return -EIO;
+	} else {
+		printk(KERN_INFO "aurora: %d boards found.\n", found);
 	}
-}
-return 0;
+	for (i = 0; i < found; i++) {
+		int ret = aurora_setup_board(&aurora_board[i]);
+
+		if (ret) {
+#ifdef AURORA_DEBUG
+			printk(KERN_ERR "aurora_init: error aurora_setup_board ret %d\n",
+			       ret);
+#endif
+			return ret;
+		}
+	}
+	return 0;
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/aurora.h linux/drivers/sbus/char/aurora.h
--- v2.3.34/linux/drivers/sbus/char/aurora.h	Mon May 31 22:08:10 1999
+++ linux/drivers/sbus/char/aurora.h	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/*
+/*	$Id: aurora.h,v 1.5 1999/12/02 09:55:16 davem Exp $
  *	linux/drivers/sbus/char/aurora.h -- Aurora multiport driver
  *
  *	Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro)
@@ -63,6 +63,7 @@
 #define __LINUX_AURORA_H
 
 #include <linux/serial.h>
+#include <linux/serialP.h>
 
 #ifdef __KERNEL__
 
@@ -88,7 +89,7 @@
 #define TYPE_1_IRQS 4
 unsigned char type_1_irq[TYPE_1_IRQS] = {
 	3, 5, 9, 13
-	};
+};
 /* I know something about another method of interrupt setting, but not enough.
  * Also, this is for another type of board, so I first have to learn how to
  * detect it.
@@ -166,15 +167,15 @@
 
 struct aurora_reg1 {
 	__volatile__ unsigned char r;
-	};
+};
 
 struct aurora_reg128 {
 	__volatile__ unsigned char r[128];
-	};
+};
 	
 struct aurora_reg4 {
 	__volatile__ unsigned char r[4];
-	};
+};
 
 struct Aurora_board {
 	unsigned long		flags;
@@ -197,7 +198,7 @@
 	unsigned char		MSVDTR;
 	unsigned char		MSVRTS;
 	/* Values for hardware acknowledge. */
-	unsigned char		ACK_MINT,ACK_TINT,ACK_RINT;
+	unsigned char		ACK_MINT, ACK_TINT, ACK_RINT;
 };
 
 /* Board configuration register */
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c
--- v2.3.34/linux/drivers/sbus/char/bpp.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/sbus/char/bpp.c	Mon Dec 20 22:06:42 1999
@@ -33,7 +33,7 @@
 # include <linux/delay.h>         /* udelay() */
 
 # include <asm/oplib.h>           /* OpenProm Library */
-# include <asm/sbus.h>            /* struct linux_sbus *SBus_chain */
+# include <asm/sbus.h>
 #endif
 
 #include <asm/bpp.h>
@@ -146,23 +146,22 @@
 /*
  * Register block
  */
-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) */
+#define BPP_CSR      0x00
+#define BPP_ADDR     0x04
+#define BPP_BCNT     0x08
+#define BPP_TST_CSR  0x0C
       /* 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 */
-};
+#define BPP_HCR      0x10
+#define BPP_OCR      0x12
+#define BPP_DR       0x14
+#define BPP_TCR      0x15
+#define BPP_OR       0x16
+#define BPP_IR       0x17
+#define BPP_ICR      0x18
+#define BPP_SIZE     0x1A
 
-/* P_CSR.  Bits of type RW1 are cleared with writting '1'. */
+/* BPP_CSR.  Bits of type RW1 are cleared with writting '1'. */
 #define P_DEV_ID_MASK   0xf0000000      /* R   */
 #define P_DEV_ID_ZEBRA  0x40000000
 #define P_DEV_ID_L64854 0xa0000000      /*      == NCR 89C100+89C105. Pity. */
@@ -190,12 +189,12 @@
 #define P_ERR_PEND      0x00000002      /* R    */
 #define P_INT_PEND      0x00000001      /* R    */
 
-/* P_HCR. Time is in increments of SBus clock. */
+/* BPP_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. */
+/* BPP_OCR. */
 #define P_OCR_MEM_CLR   0x8000
 #define P_OCR_DATA_SRC  0x4000      /* )                  */
 #define P_OCR_DS_DSEL   0x2000      /* )  Bidirectional      */
@@ -209,13 +208,13 @@
 #define P_OCR_V_ILCK    0x0002      /* Versatec faded. Zebra only. */
 #define P_OCR_EN_VER    0x0001      /* Enable Versatec (0 - enable). Zebra only. */
 
-/* P_TCR */
+/* BPP_TCR */
 #define P_TCR_DIR       0x08
 #define P_TCR_BUSY      0x04
 #define P_TCR_ACK       0x02
 #define P_TCR_DS        0x01        /* Strobe */
 
-/* P_OR */
+/* BPP_OR */
 #define P_OR_V3         0x20        /* )                 */
 #define P_OR_V2         0x10        /* ) on Zebra only   */
 #define P_OR_V1         0x08        /* )                 */
@@ -223,12 +222,12 @@
 #define P_OR_AFXN       0x02        /* Auto Feed */
 #define P_OR_SLCT_IN    0x01
 
-/* P_IR */
+/* BPP_IR */
 #define P_IR_PE         0x04
 #define P_IR_SLCT       0x02
 #define P_IR_ERR        0x01
 
-/* P_ICR */
+/* BPP_ICR */
 #define P_DS_IRQ        0x8000      /* RW1  */
 #define P_ACK_IRQ       0x4000      /* RW1  */
 #define P_BUSY_IRQ      0x2000      /* RW1  */
@@ -246,22 +245,15 @@
 #define P_ERR_IRP       0x0002      /* RW1  1= rising edge */
 #define P_ERR_IRQ_EN    0x0001      /* RW   */
 
-volatile struct bpp_regs *base_addrs[BPP_NO];
-
-static inline void bpp_outb_p(__u8 data, volatile struct bpp_regs *base){
-      base->p_dr = data;
-}
-
-#define bpp_inb_p(base)  bpp_inb(base)
-
-static inline __u8 bpp_inb(volatile struct bpp_regs *base){
-      return base->p_dr;
-}
+unsigned long base_addrs[BPP_NO];
 
+#define bpp_outb_p(data, base)	sbus_writeb(data, (base) + BPP_DR)
+#define bpp_inb_p(base)		sbus_readb((base) + BPP_DR)
+#define bpp_inb(base)		sbus_readb((base) + BPP_DR)
 
 static void set_pins(unsigned short pins, unsigned minor)
 {
-      volatile struct bpp_regs *base = base_addrs[minor];
+      unsigned long base = base_addrs[minor];
       unsigned char bits_tcr = 0, bits_or = 0;
 
       if (instances[minor].direction & 0x20) bits_tcr |= P_TCR_DIR;
@@ -271,8 +263,8 @@
       if (! (pins & BPP_PP_nInit))           bits_or |= P_OR_INIT;
       if (! (pins & BPP_PP_nSelectIn))       bits_or |= P_OR_SLCT_IN;
 
-      base->p_or = bits_or;
-      base->p_tcr = bits_tcr;
+      sbus_writeb(bits_or, base + BPP_OR);
+      sbus_writeb(bits_tcr, base + BPP_TCR);
 }
 
 /*
@@ -282,11 +274,11 @@
  */
 static unsigned short get_pins(unsigned minor)
 {
-      volatile struct bpp_regs *base = base_addrs[minor];
+      unsigned long base = base_addrs[minor];
       unsigned short bits = 0;
-      unsigned value_tcr = base->p_tcr;
-      unsigned value_ir = base->p_ir;
-      unsigned value_or = base->p_or;
+      unsigned value_tcr = sbus_readb(base + BPP_TCR);
+      unsigned value_ir = sbus_readb(base + BPP_IR);
+      unsigned value_or = sbus_readb(base + BPP_OR);
 
       if (value_tcr & P_TCR_DS)         bits |= BPP_PP_nStrobe;
       if (value_or & P_OR_AFXN)         bits |= BPP_PP_nAutoFd;
@@ -302,15 +294,6 @@
       return bits;
 }
 
-#if 0
-/* P3 */
-static inline void bpp_snap(const char *msg, unsigned minor)
-{
-	volatile struct bpp_regs *r = base_addrs[minor];
-	printk("bpp.%s: c=%02x o=%02x i=%02x\n", msg, r->p_tcr, r->p_or, r->p_ir);
-}
-#endif
-
 #endif /* __sparc__ */
 
 static void bpp_wake_up(unsigned long val)
@@ -940,34 +923,15 @@
 
 #if defined(__sparc__)
 
-static volatile struct bpp_regs *map_bpp(struct linux_sbus_device *dev, int idx)
+static unsigned long map_bpp(struct sbus_dev *dev, int idx)
 {
-      volatile struct bpp_regs *regs;
-
-      /*
-       * PROM reports different numbers on Zebra and on DMA2.
-       * We need to figure out when to apply parent ranges.
-       * printk will show this on different machines.
-       */
-
-      /* IPC Zebra   1.fa200000[1c] i=2  */
-      prom_apply_sbus_ranges(dev->my_bus, &dev->reg_addrs[0],
-			     dev->num_registers, dev);
-
-      regs = sparc_alloc_io(dev->reg_addrs[0].phys_addr, 0,
-			    dev->reg_addrs[0].reg_size, "bpp",
-			    dev->reg_addrs[0].which_io, 0x0);
-      printk("bpp%d.map_bpp: 0x%x.%p[0x%x] i=%d\n", idx,
-	     dev->reg_addrs[0].which_io, dev->reg_addrs[0].phys_addr,
-	     dev->reg_addrs[0].reg_size, dev->irqs[0]);
-
-      return regs;
+      return sbus_ioremap(&dev->resource[0], 0, BPP_SIZE, "bpp");
 }
 
 static int collectLptPorts(void)
 {
-	struct linux_sbus *bus;
-	struct linux_sbus_device *dev;
+	struct sbus_bus *bus;
+	struct sbus_dev *dev;
 	int count;
 
 	count = 0;
@@ -988,7 +952,7 @@
 
 static void probeLptPort(unsigned idx)
 {
-      volatile struct bpp_regs *rp = base_addrs[idx];
+      unsigned long rp = base_addrs[idx];
       __u32 csr;
       char *brand;
 
@@ -1007,20 +971,23 @@
       instances[idx].present = 1;
       instances[idx].enhanced = 1;   /* Sure */
 
-      if (((csr = rp->p_csr) & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) {
+      csr = sbus_readl(rp + BPP_CSR);
+      if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) {
             udelay(20);
-            csr = rp->p_csr;
+            csr = sbus_readl(rp + BPP_CSR);
             if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) {
                   printk("bpp%d: DRAINING still active (0x%08x)\n", idx, csr);
             }
       }
       printk("bpp%d: reset with 0x%08x ..", idx, csr);
-      rp->p_csr = (csr | P_RESET) & ~P_INT_EN;
+      sbus_writel((csr | P_RESET) & ~P_INT_EN, rp + BPP_CSR);
       udelay(500);
-      rp->p_csr &= ~P_RESET;
-      printk(" done with csr=0x%08x ocr=0x%04x\n", rp->p_csr, rp->p_ocr);
+      sbus_writel(sbus_readl(rp + BPP_CSR) & ~P_RESET, rp + BPP_CSR);
+      csr = sbus_readl(rp + BPP_CSR);
+      printk(" done with csr=0x%08x ocr=0x%04x\n",
+         csr, sbus_readw(rp + BPP_OCR));
 
-      switch (rp->p_csr & P_DEV_ID_MASK) {
+      switch (csr & P_DEV_ID_MASK) {
       case P_DEV_ID_ZEBRA:
             brand = "Zebra";
             break;
@@ -1030,7 +997,7 @@
       default:
             brand = "Unknown";
       }
-      printk("bpp%d: %s at 0x%p\n", idx, brand, rp);
+      printk("bpp%d: %s at 0x%lx\n", idx, brand, rp);
 
       /*
        * Leave the port in compat idle mode.
@@ -1042,7 +1009,7 @@
 
 static inline void freeLptPort(int idx)
 {
-      sparc_free_io ((void *)base_addrs[idx], sizeof(struct bpp_regs));
+      sbus_iounmap(base_addrs[idx], BPP_SIZE);
 }
 
 #endif
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/envctrl.c linux/drivers/sbus/char/envctrl.c
--- v2.3.34/linux/drivers/sbus/char/envctrl.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/sbus/char/envctrl.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: envctrl.c,v 1.12 1999/08/31 06:58:04 davem Exp $
+/* $Id: envctrl.c,v 1.13 1999/12/19 23:28:07 davem Exp $
  * envctrl.c: Temperature and Fan monitoring on Machines providing it.
  *
  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
@@ -78,6 +78,7 @@
 /* PCF8584 register offsets */
 #define I2C_DATA	0x00UL
 #define I2C_CSR		0x01UL
+#define I2C_REG_SIZE	0x02UL
 
 struct i2c_device {
 	unsigned char		addr;
@@ -1565,7 +1566,7 @@
 		return -ENODEV;
 	}
 
-	i2c_regs = edev->resource[0].start;
+	i2c_regs = (unsigned long) ioremap(edev->resource[0].start, I2C_REG_SIZE);
 	writeb(CONTROL_PIN, i2c_regs + I2C_CSR);
 	writeb(PCF8584_ADDRESS >> 1, i2c_regs + I2C_DATA);
 	writeb(CONTROL_PIN | CONTROL_ES1, i2c_regs + I2C_CSR);
@@ -1625,6 +1626,7 @@
 {
 	envctrl_stop();
 	i2c_free_devices();
+	iounmap(i2c_regs);
 	misc_deregister(&envctrl_dev);
 }
 #endif
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c
--- v2.3.34/linux/drivers/sbus/char/flash.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/sbus/char/flash.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: flash.c,v 1.13 1999/08/31 06:58:06 davem Exp $
+/* $Id: flash.c,v 1.15 1999/12/09 00:44:22 davem Exp $
  * flash.c: Allow mmap access to the OBP Flash, for OBP updates.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -55,13 +55,12 @@
 			return -ENXIO;
 	}
 
-	if (vma->vm_pgoff > (size >> PAGE_SHIFT))
+	if ((vma->vm_pgoff << PAGE_SHIFT) > size)
 		return -ENXIO;
-	off = vma->vm_pgoff << PAGE_SHIFT;
-	addr += off;
+	addr += (vma->vm_pgoff << PAGE_SHIFT);
 
-	if (vma->vm_end - (vma->vm_start + off) > size)
-		size = vma->vm_end - (vma->vm_start + off);
+	if (vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)) > size)
+		size = vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT));
 
 	pgprot_val(vma->vm_page_prot) &= ~(_PAGE_CACHE);
 	pgprot_val(vma->vm_page_prot) |= _PAGE_E;
@@ -153,8 +152,8 @@
 int __init flash_init(void)
 #endif
 {
-	struct linux_sbus *sbus;
-	struct linux_sbus_device *sdev = 0;
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev = 0;
 	struct linux_ebus *ebus;
 	struct linux_ebus_device *edev = 0;
 	struct linux_prom_registers regs[2];
@@ -162,8 +161,6 @@
 
 	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "flashprom")) {
-			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)sdev->reg_addrs[0].phys_addr) |
 					(((unsigned long)sdev->reg_addrs[0].which_io)<<32UL);
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/jsflash.c linux/drivers/sbus/char/jsflash.c
--- v2.3.34/linux/drivers/sbus/char/jsflash.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sbus/char/jsflash.c	Mon Dec 20 22:06:42 1999
@@ -0,0 +1,415 @@
+/*
+ * drivers/sbus/char/jsflash.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds	(drivers/char/mem.c)
+ *  Copyright (C) 1997  Eddie C. Dost		(drivers/sbus/char/flash.c)
+ *  Copyright (C) 1999  Pete Zaitcev
+ *
+ * This driver is used to program OS into a Flash SIMM on
+ * Krups and Espresso platforms.
+ *
+ * It is anticipated that programming an OS Flash will be a routine
+ * procedure. In the same time it is exeedingly dangerous because
+ * a user can program its OBP flash with OS image and effectively
+ * kill the machine.
+ *
+ * This driver uses an interface different from Eddie's flash.c
+ * as a silly safeguard.
+ *
+ * XXX The flash.c manipulates page caching characteristics in a certain
+ * dubious way; also it assumes that remap_page_range() can remap
+ * PCI bus locations, which may be false. ioremap() must be used
+ * instead. We should discuss this.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+#include <linux/fcntl.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#if 0	/* P3 from mem.c */
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/mman.h>
+#include <linux/random.h>
+#include <linux/raw.h>
+#include <linux/capability.h>
+#endif
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#if 0	/* P3 from mem.c */
+#include <asm/system.h>
+#include <asm/sbus.h>
+#include <asm/ebus.h>
+#endif
+
+#include <asm/jsflash.h>		/* ioctl arguments. <linux/> ?? */
+#define JSFIDSZ		(sizeof(struct jsflash_ident_arg))
+#define JSFPRGSZ	(sizeof(struct jsflash_program_arg))
+
+/*
+ * Our device numbers have no business in system headers.
+ * The only thing a user knows is the device name /dev/jsflash.
+ */
+#define JSF_MINOR	178
+
+/*
+ * Access functions.
+ * We could ioremap(), but it's easier this way.
+ */
+static unsigned int jsf_inl(unsigned long addr)
+{
+	unsigned long retval;
+
+	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
+				"=r" (retval) :
+				"r" (addr), "i" (ASI_M_BYPASS));
+        return retval;
+}
+
+static void jsf_outl(unsigned long addr, __u32 data)
+{
+
+	__asm__ __volatile__("sta %0, [%1] %2\n\t" : :
+				"r" (data), "r" (addr), "i" (ASI_M_BYPASS) :
+				"memory");
+}
+
+/*
+ * soft carrier
+ */
+struct jsflash {
+	unsigned long base;
+	unsigned long size;
+	unsigned long busy;		/* In use? */
+	struct jsflash_ident_arg id;
+};
+
+/*
+ * We do not map normal memory or obio as a safety precaution.
+ * But offsets are real, for ease of userland programming.
+ */
+#define JSF_BASE_TOP	0x30000000
+#define JSF_BASE_ALL	0x20000000
+
+#define JSF_BASE_JK	0x20400000
+
+/*
+ * Let's pretend we may have several of these...
+ */
+static struct jsflash jsf0;
+
+/*
+ * Wait for AMD to finish its embedded algorithm.
+ * We use the Toggle bit DQ6 (0x40) because it does not
+ * depend on the data value as /DATA bit DQ7 does.
+ *
+ * XXX Do we need any timeout here?
+ */
+static void jsf_wait(unsigned long p) {
+	unsigned int x1, x2;
+
+	for (;;) {
+		x1 = jsf_inl(p);
+		x2 = jsf_inl(p);
+		if ((x1 & 0x40404040) == (x2 & 0x40404040)) return;
+	}
+}
+
+/*
+ * Programming will only work if Flash is clean,
+ * we leave it to the programmer application.
+ *
+ * AMD must be programmed one byte at a time;
+ * thus, Simple Tech SIMM must be written 4 bytes at a time.
+ *
+ * Write waits for the chip to become ready after the write
+ * was finished. This is done so that application would read
+ * consistent data after the write is done.
+ */
+static void jsf_write4(unsigned long fa, u32 data) {
+
+	jsf_outl(fa, 0xAAAAAAAA);		/* Unlock 1 Write 1 */
+	jsf_outl(fa, 0x55555555);		/* Unlock 1 Write 2 */
+	jsf_outl(fa, 0xA0A0A0A0);		/* Byte Program */
+	jsf_outl(fa, data);
+
+	jsf_wait(fa);
+}
+
+/*
+ * The memory devices use the full 32/64 bits of the offset, and so we cannot
+ * check against negative addresses: they are ok. The return value is weird,
+ * though, in that case (0).
+ *
+ * also note that seeking relative to the "end of file" isn't supported:
+ * it has no meaning, so it returns -EINVAL.
+ */
+static loff_t jsf_lseek(struct file * file, loff_t offset, int orig)
+{
+	switch (orig) {
+		case 0:
+			file->f_pos = offset;
+			return file->f_pos;
+		case 1:
+			file->f_pos += offset;
+			return file->f_pos;
+		default:
+			return -EINVAL;
+	}
+}
+
+/*
+ * P3: OS SIMM Cannot be read in other size but a 32bits word.
+ */
+static ssize_t jsf_read(struct file * file, char * buf, 
+    size_t togo, loff_t *ppos)
+{
+	unsigned long p = *ppos;
+	char *tmp = buf;
+
+	union byte4 {
+		char s[4];
+		unsigned int n;
+	} b;
+
+	if (verify_area(VERIFY_WRITE, buf, togo))
+		return -EFAULT; 
+
+	if (p < JSF_BASE_ALL || p >= JSF_BASE_TOP) {
+		return 0;
+	}
+
+	if ((p + togo) < p	/* wrap */
+	   || (p + togo) >= JSF_BASE_TOP) {
+		togo = JSF_BASE_TOP - p;
+	}
+
+	if (p < JSF_BASE_ALL && togo != 0) {
+		size_t x = JSF_BASE_ALL - p;
+		if (x > togo) x = togo;
+		clear_user(tmp, x);
+		tmp += x;
+		p += x;
+		togo -= x;
+	}
+
+	while (togo >= 4) {
+		togo -= 4;
+		b.n = jsf_inl(p);
+		copy_to_user(tmp, b.s, 4);
+		tmp += 4;
+		p += 4;
+	}
+
+	/*
+	 * XXX Small togo may remain if 1 byte is ordered.
+	 * It would be nice if we did a word size read and unpacked it.
+	 */
+
+	*ppos = p;
+	return tmp-buf;
+}
+
+static ssize_t jsf_write(struct file * file, const char * buf,
+    size_t count, loff_t *ppos)
+{
+	return -ENOSPC;
+}
+
+/*
+ */
+static int jsf_ioctl_erase(unsigned long arg)
+{
+	unsigned long p;
+
+	/* p = jsf0.base;	hits wrong bank */
+	p = 0x20400000;
+
+	jsf_outl(p, 0xAAAAAAAA);		/* Unlock 1 Write 1 */
+	jsf_outl(p, 0x55555555);		/* Unlock 1 Write 2 */
+	jsf_outl(p, 0x80808080);		/* Erase setup */
+	jsf_outl(p, 0xAAAAAAAA);		/* Unlock 2 Write 1 */
+	jsf_outl(p, 0x55555555);		/* Unlock 2 Write 2 */
+	jsf_outl(p, 0x10101010);		/* Chip erase */
+
+#if 0
+	/*
+	 * This code is ok, except that counter based timeout
+	 * has no place in this world. Let's just drop timeouts...
+	 */
+	{
+		int i;
+		__u32 x;
+		for (i = 0; i < 1000000; i++) {
+			x = jsf_inl(p);
+			if ((x & 0x80808080) == 0x80808080) break;
+		}
+		if ((x & 0x80808080) != 0x80808080) {
+			printk("jsf0: erase timeout with 0x%08x\n", x);
+		} else {
+			printk("jsf0: erase done with 0x%08x\n", x);
+		}
+	}
+#else
+	jsf_wait(p);
+#endif
+
+	return 0;
+}
+
+/*
+ * Program a block of flash.
+ * Very simple because we can do it byte by byte anyway.
+ */
+static int jsf_ioctl_program(unsigned long arg)
+{
+	struct jsflash_program_arg abuf;
+	char *uptr;
+	unsigned long p;
+	unsigned int togo;
+	union {
+		unsigned int n;
+		char s[4];
+	} b;
+
+	if (verify_area(VERIFY_READ, (void *)arg, JSFPRGSZ))
+		return -EFAULT; 
+	copy_from_user(&abuf, (char *)arg, JSFPRGSZ);
+	p = abuf.off;
+	togo = abuf.size;
+	if ((togo & 3) || (p & 3)) return -EINVAL;
+
+	uptr = (char *) abuf.data;
+	if (verify_area(VERIFY_READ, uptr, togo))
+		return -EFAULT;
+	while (togo != 0) {
+		--togo;
+		copy_from_user(&b.s[0], uptr, 4);
+		jsf_write4(p, b.n);
+		p += 4;
+		uptr += 4;
+	}
+
+	return 0;
+}
+
+static int jsf_ioctl(struct inode *inode, struct file *f, unsigned int cmd,
+    unsigned long arg)
+{
+	int error = -ENOTTY;
+
+	switch (cmd) {
+	case JSFLASH_IDENT:
+		if (verify_area(VERIFY_WRITE, (void *)arg, JSFIDSZ))
+			return -EFAULT; 
+		copy_to_user(arg, &jsf0.id, JSFIDSZ);
+		error = 0;
+		break;
+	case JSFLASH_ERASE:
+		error = jsf_ioctl_erase(arg);
+		break;
+	case JSFLASH_PROGRAM:
+		error = jsf_ioctl_program(arg);
+		break;
+	}
+
+	return error;
+}
+
+static int jsf_mmap(struct file * file, struct vm_area_struct * vma)
+{
+	return -ENXIO;
+}
+
+static int jsf_open(struct inode * inode, struct file * filp)
+{
+
+	if (jsf0.base == 0) return -ENXIO;
+	if (test_and_set_bit(0, (void *)&jsf0.busy) != 0)
+		return -EBUSY;
+
+	MOD_INC_USE_COUNT;
+	return 0;	/* XXX What security? */
+}
+
+static int jsf_release(struct inode *inode, struct file *file)
+{
+
+	MOD_DEC_USE_COUNT;
+
+	jsf0.busy = 0;
+	return 0;
+}
+
+static struct file_operations jsf_fops = {
+	jsf_lseek,
+	jsf_read,
+	jsf_write,
+	NULL,		/* readdir */
+	NULL,		/* poll */
+	jsf_ioctl,
+	jsf_mmap,
+	jsf_open,
+	NULL,		/* flush */
+	jsf_release,
+	NULL		/* fsync */
+};
+
+static struct miscdevice jsf_dev = { JSF_MINOR, "jsflash", &jsf_fops };
+
+EXPORT_NO_SYMBOLS;
+
+#ifdef MODULE
+int init_module(void)
+#else
+int /* __init */ jsflash_init(void)
+#endif
+{
+	int rc;
+
+	/* extern enum sparc_cpu sparc_cpu_model; */ /* in <asm/system.h> */
+	if (sparc_cpu_model == sun4m && jsf0.base == 0) {
+		/* XXX Autodetect */
+		/*
+		 * We do not want to use PROM properties;
+		 * They are faked by PROLL anyways.
+		 */
+		jsf0.base = JSF_BASE_JK;
+		jsf0.size = 0x00800000;		/* 8M */
+
+		jsf0.id.off = JSF_BASE_ALL;
+		jsf0.id.size = 0x01000000;	/* 16M - all segments */
+		strcpy(jsf0.id.name, "Krups_all");
+
+		printk("Espresso Flash @0x%lx\n", jsf0.base);
+	}
+
+	if ((rc = misc_register(&jsf_dev)) != 0) {
+		printk(KERN_ERR "jsf: unable to get misc minor %d\n",
+		    JSF_MINOR);
+		jsf0.base = 0;
+		return rc;
+	}
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+
+	/* for (all probed units) {  } */
+	if (jsf0.busy)
+		printk("jsf0: cleaning busy unit\n");
+	jsf0.base = 0;
+	jsf0.busy = 0;
+
+	misc_deregister(&jsf_dev);
+}
+#endif
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/openprom.c linux/drivers/sbus/char/openprom.c
--- v2.3.34/linux/drivers/sbus/char/openprom.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/sbus/char/openprom.c	Mon Dec 20 22:06:42 1999
@@ -31,6 +31,7 @@
 
 #define PROMLIB_INTERNAL
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -43,7 +44,10 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/openpromio.h>
-
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#include <asm/pbm.h>
+#endif
 
 /* Private data kept by the driver for each descriptor. */
 typedef struct openprom_private_data
@@ -71,9 +75,15 @@
 
 	get_user_ret(bufsize, &info->oprom_size, -EFAULT);
 
-	if (bufsize == 0 || bufsize > OPROMMAXPARAM)
+	if (bufsize == 0)
 		return -EINVAL;
 
+	/* If the bufsize is too large, just limit it.
+	 * Fix from Jason Rappleye.
+	 */
+	if (bufsize > OPROMMAXPARAM)
+		bufsize = OPROMMAXPARAM;
+
 	if (!(*opp_p = kmalloc(sizeof(int) + bufsize + 1, GFP_KERNEL)))
 		return -ENOMEM;
 	memset(*opp_p, 0, sizeof(int) + bufsize + 1);
@@ -138,6 +148,7 @@
 	unsigned long flags;
 	int bufsize, len, error = 0;
 	extern char saved_command_line[];
+	static int cnt;
 
 	if (cmd == OPROMSETOPT)
 		bufsize = getstrings((void *)arg, &opp);
@@ -194,20 +205,18 @@
 		buf = opp->oprom_array + strlen(opp->oprom_array) + 1;
 		len = opp->oprom_array + bufsize - buf;
 
-		printk(KERN_DEBUG "OPROMSETOPT%s %s='%s'\n",
-		       (cmd == OPROMSETOPT) ? "" : "2", opp->oprom_array, buf);
-
 		save_and_cli(flags);
 		error = prom_setprop(options_node, opp->oprom_array,
 				     buf, len);
 		restore_flags(flags);
 
-		if (error <= 0)
+		if (error < 0)
 			error = -EINVAL;
 		break;
 
 	case OPROMNEXT:
 	case OPROMCHILD:
+	case OPROMSETCUR:
 		if (bufsize < sizeof(int)) {
 			error = -EINVAL;
 			break;
@@ -216,10 +225,11 @@
 		node = *((int *) opp->oprom_array);
 
 		save_and_cli(flags);
-		if (cmd == OPROMNEXT)
-			node = __prom_getsibling(node);
-		else
-			node = __prom_getchild(node);
+		switch (cmd) {
+		case OPROMNEXT: node = __prom_getsibling(node); break;
+		case OPROMCHILD: node = __prom_getchild(node); break;
+		case OPROMSETCUR: break;
+		}
 		restore_flags(flags);
 
 		data->current_node = node;
@@ -229,6 +239,39 @@
 		error = copyout((void *)arg, opp, bufsize + sizeof(int));
 		break;
 
+	case OPROMPCI2NODE:
+		error = -EINVAL;
+
+		if (bufsize >= 2*sizeof(int)) {
+#ifdef CONFIG_PCI
+			struct pci_dev *pdev;
+			struct pcidev_cookie *pcp;
+			pdev = pci_find_slot (((int *) opp->oprom_array)[0],
+					      ((int *) opp->oprom_array)[1]);
+
+			pcp = pdev->sysdata;
+			if (pcp != NULL && pcp->prom_node != -1 && pcp->prom_node) {
+				node = pcp->prom_node;
+				data->current_node = node;
+				*((int *)opp->oprom_array) = node;
+				opp->oprom_size = sizeof(int);
+				error = copyout((void *)arg, opp, bufsize + sizeof(int));
+			}
+#endif
+		}
+		break;
+
+	case OPROMPATH2NODE:
+		save_and_cli(flags);
+		node = prom_finddevice(opp->oprom_array);
+		restore_flags(flags);
+		data->current_node = node;
+		*((int *)opp->oprom_array) = node;
+		opp->oprom_size = sizeof(int);
+
+		error = copyout((void *)arg, opp, bufsize + sizeof(int));
+		break;
+
 	case OPROMGETBOOTARGS:
 		buf = saved_command_line;
 
@@ -248,11 +291,13 @@
 	case OPROMU2P:
 	case OPROMGETCONS:
 	case OPROMGETFBNAME:
-		printk(KERN_INFO "openprom_sunos_ioctl: unimplemented ioctl\n");
+		if (cnt++ < 10)
+			printk(KERN_INFO "openprom_sunos_ioctl: unimplemented ioctl\n");
 		error = -EINVAL;
 		break;
 	default:
-		printk(KERN_INFO "openprom_sunos_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg);
+		if (cnt++ < 10)
+			printk(KERN_INFO "openprom_sunos_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg);
 		error = -EINVAL;
 		break;
 	}
@@ -315,6 +360,7 @@
 	int error, node, len;
 	char *str, *tmp;
 	char buffer[64];
+	static int cnt;
 
 	switch (cmd) {
 	case OPIOCGET:
@@ -459,7 +505,8 @@
 		return 0;
 
 	default:
-		printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd);
+		if (cnt++ < 10)
+			printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd);
 		return -EINVAL;
 
 	}
@@ -473,6 +520,7 @@
 			  unsigned int cmd, unsigned long arg)
 {
 	DATA *data = (DATA *) file->private_data;
+	static int cnt;
 
 	switch (cmd) {
 	case OPROMGETOPT:
@@ -502,6 +550,9 @@
 	case OPROMGETCONS:
 	case OPROMGETFBNAME:
 	case OPROMGETBOOTARGS:
+	case OPROMSETCUR:
+	case OPROMPCI2NODE:
+	case OPROMPATH2NODE:
 		if ((file->f_mode & FMODE_READ) == 0)
 			return -EPERM;
 		return openprom_sunos_ioctl(inode, file, cmd, arg, 0);
@@ -521,7 +572,8 @@
 		return openprom_bsd_ioctl(inode,file,cmd,arg);
 
 	default:
-		printk("openprom_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg);
+		if (cnt++ < 10)
+			printk("openprom_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg);
 		return -EINVAL;
 	}
 }
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.3.34/linux/drivers/sbus/char/pcikbd.c	Mon Oct 11 15:38:15 1999
+++ linux/drivers/sbus/char/pcikbd.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.35 1999/09/01 08:09:26 davem Exp $
+/* $Id: pcikbd.c,v 1.40 1999/12/01 10:45:53 davem Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -67,8 +67,10 @@
 extern void pci_setledstate(struct kbd_struct *, unsigned int);
 extern unsigned char pci_getledstate(void);
 
-#ifdef __sparc_v9__
+#define pcikbd_inb(x)     inb(x)
+#define pcikbd_outb(v,x)  outb(v,x)
 
+#if 0 /* deadwood */
 static __inline__ unsigned char pcikbd_inb(unsigned long port)
 {
 	return inb(port);
@@ -78,19 +80,6 @@
 {
 	outb(val, port);
 }
-
-#else
-
-static __inline__ unsigned char pcikbd_inb(unsigned long port)
-{
-	return *(volatile unsigned char *)port;
-}
-
-static __inline__ void pcikbd_outb(unsigned char val, unsigned long port)
-{
-	*(volatile unsigned char *)port = val;
-}
-
 #endif
 
 static inline void kb_wait(void)
@@ -487,8 +476,7 @@
 	char *msg;
 
 	if (pcikbd_mrcoffee) {
-		if ((pcikbd_iobase = (unsigned long) sparc_alloc_io(0x71300060,
-		    0, 8, "ps2kbd-regs", 0x0, 0)) == 0) {
+		if ((pcikbd_iobase = (unsigned long) ioremap(0x71300060, 8)) == 0) {
 			prom_printf("pcikbd_init_hw: cannot map\n");
 			return;
 		}
@@ -498,7 +486,7 @@
 			printk("8042: cannot register IRQ %x\n", pcikbd_irq);
 			return;
 		}
-		printk("8042(kbd): iobase[%08x] irq[%x]\n",
+		printk("8042(kbd): iobase[%x] irq[%x]\n",
 		    (unsigned)pcikbd_iobase, pcikbd_irq);
 	} else {
 		for_each_ebus(ebus) {
@@ -588,7 +576,10 @@
 static int aux_count = 0;
 static int aux_present = 0;
 
-#ifdef __sparc_v9__
+#define pcimouse_inb(x)     inb(x)
+#define pcimouse_outb(v,x)  outb(v,x)
+
+#if 0
 
 static __inline__ unsigned char pcimouse_inb(unsigned long port)
 {
@@ -600,18 +591,6 @@
 	outb(val, port);
 }
 
-#else
-
-static __inline__ unsigned char pcimouse_inb(unsigned long port)
-{
-	return *(volatile unsigned char *)port;
-}
-
-static __inline__ void pcimouse_outb(unsigned char val, unsigned long port)
-{
-	*(volatile unsigned char *)port = val;
-}
-
 #endif
 
 /*
@@ -924,10 +903,34 @@
 	aux_fasync,
 };
 
+static int aux_no_open(struct inode *inode, struct file *file)
+{
+	return -ENODEV;
+}
+
+struct file_operations psaux_no_fops = {
+	NULL,		/* seek */
+	NULL,
+	NULL,
+	NULL, 		/* readdir */
+	NULL,
+	NULL, 		/* ioctl */
+	NULL,		/* mmap */
+	aux_no_open,
+	NULL,		/* flush */
+	NULL,
+	NULL,
+	NULL,
+};
+
 static struct miscdevice psaux_mouse = {
 	PSMOUSE_MINOR, "ps2aux", &psaux_fops
 };
 
+static struct miscdevice psaux_no_mouse = {
+	PSMOUSE_MINOR, "ps2aux", &psaux_no_fops
+};
+
 int __init pcimouse_init(void)
 {
 	struct linux_ebus *ebus;
@@ -937,7 +940,7 @@
 	if (pcikbd_mrcoffee) {
 		if ((pcimouse_iobase = pcikbd_iobase) == 0) {
 			printk("pcimouse_init: no 8042 given\n");
-			return -ENODEV;
+			goto do_enodev;
 		}
 		pcimouse_irq = pcikbd_irq;
 	} else {
@@ -953,7 +956,7 @@
 			}
 		}
 		printk("pcimouse_init: no 8042 found\n");
-		return -ENODEV;
+		goto do_enodev;
 
 found:
 		pcimouse_iobase = child->resource[0].start;
@@ -973,7 +976,7 @@
 		        SA_SHIRQ, "mouse", (void *)pcimouse_iobase)) {
 		printk("8042: Cannot register IRQ %s\n",
 		       __irq_itoa(pcimouse_irq));
-		return -ENODEV;
+		goto do_enodev;
 	}
 
 	printk("8042(mouse) at %lx (irq %s)\n", pcimouse_iobase,
@@ -1002,10 +1005,19 @@
 	aux_end_atomic();
 
 	return 0;
+
+do_enodev:
+	misc_register(&psaux_no_mouse);
+	return -ENODEV;
 }
 
+int __init pcimouse_no_init(void)
+{
+	misc_register(&psaux_no_mouse);
+	return -ENODEV;
+}
 
-int __init ps2kbd_probe(unsigned long *memory_start)
+int __init ps2kbd_probe(void)
 {
 	int pnode, enode, node, dnode, xnode;
 	int kbnode = 0, msnode = 0, bnode = 0;
@@ -1020,7 +1032,7 @@
 	len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
 	if (len < 0) {
 		printk("ps2kbd_probe: no name of root node\n");
-		return -ENODEV;
+		goto do_enodev;
 	}
 	if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
 		pcikbd_mrcoffee = 1;	/* Brain damage detected */
@@ -1033,7 +1045,7 @@
         node = prom_getchild(prom_root_node);
 	node = prom_searchsiblings(node, "aliases");
 	if (!node)
-		return -ENODEV;
+		goto do_enodev;
 
 	len = prom_getproperty(node, "keyboard", prop, sizeof(prop));
 	if (len > 0) {
@@ -1041,7 +1053,7 @@
 		kbnode = prom_finddevice(prop);
 	}
 	if (!kbnode)
-		return -ENODEV;
+		goto do_enodev;
 
 	len = prom_getproperty(node, "mouse", prop, sizeof(prop));
 	if (len > 0) {
@@ -1049,7 +1061,7 @@
 		msnode = prom_finddevice(prop);
 	}
 	if (!msnode)
-		return -ENODEV;
+		goto do_enodev;
 
 	/*
 	 * Find matching EBus nodes...
@@ -1119,11 +1131,13 @@
 		pnode = prom_getsibling(pnode);
 		pnode = prom_searchsiblings(pnode, "pci");
 	}
+do_enodev:
+	sunkbd_setinitfunc(pcimouse_no_init);
 	return -ENODEV;
 
 found:
-        sunkbd_setinitfunc(memory_start, pcimouse_init);
-        sunkbd_setinitfunc(memory_start, pcikbd_init);
+        sunkbd_setinitfunc(pcimouse_init);
+        sunkbd_setinitfunc(pcikbd_init);
 	kbd_ops.compute_shiftstate = pci_compute_shiftstate;
 	kbd_ops.setledstate = pci_setledstate;
 	kbd_ops.getledstate = pci_getledstate;
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c
--- v2.3.34/linux/drivers/sbus/char/sab82532.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/sbus/char/sab82532.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.35 1999/09/01 08:09:29 davem Exp $
+/* $Id: sab82532.c,v 1.40 1999/12/19 23:28:08 davem Exp $
  * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -15,6 +15,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
+#include <linux/serialP.h>
 #include <linux/serial_reg.h>
 #include <linux/console.h>
 #include <linux/major.h>
@@ -36,6 +37,12 @@
 
 static DECLARE_TASK_QUEUE(tq_serial);
 
+/* This is (one of many) a special gross hack to allow SU and
+ * SAB serials to co-exist on the same machine. -DaveM
+ */
+#undef SERIAL_BH
+#define SERIAL_BH	AURORA_BH
+
 static struct tty_driver serial_driver, callout_driver;
 static int sab82532_refcount;
 
@@ -252,6 +259,9 @@
 {
 	unsigned char saved_rfc, tmp;
 
+	if (!stop_a_enabled)
+		return;
+
 	/* If we are doing kadb, we call the debugger
 	 * else we just drop into the boot monitor.
 	 * Note that we must flush the user windows
@@ -2129,7 +2139,7 @@
 		}
 		memset(sab, 0, sizeof(struct sab82532));
 
-		sab->regs = (union sab82532_async_regs *)(regs + offset);
+		sab->regs = ioremap(regs + offset, sizeof(union sab82532_async_regs));
 		sab->irq = edev->irqs[0];
 		sab->line = 1 - i;
 		sab->xmit_fifo_size = 32;
@@ -2153,7 +2163,7 @@
 
 static inline void __init show_serial_version(void)
 {
-	char *revision = "$Revision: 1.35 $";
+	char *revision = "$Revision: 1.40 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2163,6 +2173,8 @@
 	printk("SAB82532 serial driver version %s\n", serial_version);
 }
 
+extern int su_num_ports;
+
 /*
  * The serial driver boot-time initialization code!
  */
@@ -2186,7 +2198,7 @@
 	serial_driver.driver_name = "serial";
 	serial_driver.name = "ttyS";
 	serial_driver.major = TTY_MAJOR;
-	serial_driver.minor_start = 64;
+	serial_driver.minor_start = 64 + su_num_ports;
 	serial_driver.num = NR_PORTS;
 	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
 	serial_driver.subtype = SERIAL_TYPE_NORMAL;
@@ -2284,7 +2296,7 @@
 	
 		printk(KERN_INFO
 		       "ttyS%02d at 0x%lx (irq = %s) is a SAB82532 %s\n",
-		       info->line, (unsigned long)info->regs,
+		       info->line + su_num_ports, (unsigned long)info->regs,
 		       __irq_itoa(info->irq), sab82532_version[info->type]);
 	}
 
@@ -2294,7 +2306,7 @@
 	return 0;
 }
 
-int __init sab82532_probe(unsigned long *memory_start)
+int __init sab82532_probe(void)
 {
 	int node, enode, snode;
 	char model[32];
@@ -2338,9 +2350,9 @@
 
 found:
 #ifdef CONFIG_SERIAL_CONSOLE
-	sunserial_setinitfunc(memory_start, sab82532_console_init);
+	sunserial_setinitfunc(sab82532_console_init);
 #endif
-	sunserial_setinitfunc(memory_start, sab82532_init);
+	sunserial_setinitfunc(sab82532_init);
 	rs_ops.rs_kgdb_hook = sab82532_kgdb_hook;
 	return 0;
 }
@@ -2356,6 +2368,7 @@
 
 void cleanup_module(void) 
 {
+	struct sab82532 *sab;
 	unsigned long flags;
 	int e1, e2;
 
@@ -2378,6 +2391,8 @@
 		free_page((unsigned long) tmp_buf);
 		tmp_buf = NULL;
 	}
+	for (sab = sab82532_chain; sab; sab = sab->next)
+		iounmap(sab->regs);
 }
 #endif /* MODULE */
 
@@ -2575,8 +2590,9 @@
 int __init sab82532_console_init(void)
 {
 	extern int con_is_present(void);
+	extern int su_console_registered;
 
-	if (con_is_present())
+	if (con_is_present() || su_console_registered)
 		return 0;
 
 	if (!sab82532_chain) {
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c
--- v2.3.34/linux/drivers/sbus/char/su.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/sbus/char/su.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.28 1999/09/01 08:09:32 davem Exp $
+/* $Id: su.c,v 1.34 1999/12/02 09:55:21 davem Exp $
  * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -54,6 +54,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
+#include <linux/serialP.h>
 #include <linux/serial_reg.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
@@ -62,6 +63,7 @@
 #include <linux/mm.h>
 #include <linux/malloc.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 #include <linux/delay.h>
 #ifdef CONFIG_SERIAL_CONSOLE
 #include <linux/console.h>
@@ -113,6 +115,7 @@
 	int		 cflag;
 
 	enum su_type	 port_type;	/* Hookup type: e.g. mouse */
+	int		 is_console;
 	int		 port_node;
 
 	char		 name[16];
@@ -341,7 +344,7 @@
 }
 
 static __inline__ void
-receive_kbd_ms_chars(struct su_struct *info, struct pt_regs *regs)
+receive_kbd_ms_chars(struct su_struct *info, struct pt_regs *regs, int is_brk)
 {
 	unsigned char status = 0;
 	unsigned char ch;
@@ -368,7 +371,7 @@
                 	}
                 	sunkbd_inchar(ch, regs);
 		} else {
-			sun_mouse_inbyte(ch);
+			sun_mouse_inbyte(ch, is_brk);
 		}
 
 		status = su_inb(info, UART_LSR);
@@ -380,12 +383,15 @@
 {
 	struct tty_struct *tty = info->tty;
 	unsigned char ch;
-	int ignored = 0;
+	int ignored = 0, saw_console_brk = 0;
 	struct	async_icount *icount;
 
 	icount = &info->icount;
 	do {
 		ch = serial_inp(info, UART_RX);
+		if (info->is_console &&
+		    (ch == 0 || (*status &UART_LSR_BI)))
+			saw_console_brk = 1;
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 			break;
 		*tty->flip.char_buf_ptr = ch;
@@ -461,6 +467,8 @@
 	printk("E%02x.R%d", *status, tty->flip.count);
 #endif
 	tty_flip_buffer_push(tty);
+	if (saw_console_brk != 0)
+		batten_down_hatches();
 }
 
 static __inline__ void
@@ -598,8 +606,9 @@
 #ifdef SERIAL_DEBUG_INTR
 	printk("status = %x...", status);
 #endif
-	if (status & UART_LSR_DR)
-		receive_kbd_ms_chars(info, regs);
+	if ((status & UART_LSR_DR) || (status & UART_LSR_BI))
+		receive_kbd_ms_chars(info, regs,
+				     (status & UART_LSR_BI) != 0);
 
 #ifdef SERIAL_DEBUG_INTR
 	printk("end.\n");
@@ -2214,7 +2223,7 @@
  */
 static __inline__ void __init show_su_version(void)
 {
-	char *revision = "$Revision: 1.28 $";
+	char *revision = "$Revision: 1.34 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2273,8 +2282,13 @@
 		return;
 	}
 	prom_apply_obio_ranges(&reg0, 1);
-	if ((info->port = (unsigned long) sparc_alloc_io(reg0.phys_addr,
-	    0, reg0.reg_size, "su-regs", reg0.which_io, 0)) == 0) {
+	if (reg0.which_io != 0) {	/* Just in case... */
+		prom_printf("su: bus number nonzero: 0x%x:%x\n",
+		    reg0.which_io, reg0.phys_addr);
+		return;
+	}
+	if ((info->port = (unsigned long) ioremap(reg0.phys_addr,
+	    reg0.reg_size)) == 0) {
 		prom_printf("su: cannot map\n");
 		return;
 	}
@@ -2407,6 +2421,11 @@
 	restore_flags(flags);
 }
 
+/* This is used by the SAB driver to adjust where its minor
+ * numbers start, we always are probed for first.
+ */
+int su_num_ports = 0;
+
 /*
  * The serial driver boot-time initialization code!
  */
@@ -2505,6 +2524,13 @@
 		       uart_config[info->type].name);
 	}
 
+	for (i = 0, info = su_table; i < NR_PORTS; i++, info++)
+		if (info->type == PORT_UNKNOWN)
+			break;
+
+	su_num_ports = i;
+	serial_driver.num = callout_driver.num = i;
+
 	return 0;
 }
 
@@ -2574,6 +2600,7 @@
 			} else {
 				info->port_type = SU_PORT_PORT;
 			}
+			info->is_console = 0;
 			info->port_node = sunode;
 			++t->devices;
 		} else {
@@ -2582,7 +2609,7 @@
 	}
 }
 
-int __init su_probe (unsigned long *memory_start)
+int __init su_probe(void)
 {
 	int node;
 	int len;
@@ -2630,20 +2657,22 @@
 	 */
 	if (scan.msx != -1 && scan.kbx != -1) {
 		su_table[0].port_type = SU_PORT_MS;
+		su_table[0].is_console = 0;
 		su_table[0].port_node = scan.msnode;
 		su_table[1].port_type = SU_PORT_KBD;
+		su_table[1].is_console = 0;
 		su_table[1].port_node = scan.kbnode;
 
-        	sunserial_setinitfunc(memory_start, su_kbd_ms_init);
+        	sunserial_setinitfunc(su_kbd_ms_init);
         	rs_ops.rs_change_mouse_baud = su_change_mouse_baud;
-		sunkbd_setinitfunc(memory_start, sun_kbd_init);
+		sunkbd_setinitfunc(sun_kbd_init);
 		kbd_ops.compute_shiftstate = sun_compute_shiftstate;
 		kbd_ops.setledstate = sun_setledstate;
 		kbd_ops.getledstate = sun_getledstate;
 		kbd_ops.setkeycode = sun_setkeycode;
 		kbd_ops.getkeycode = sun_getkeycode;
 #ifdef CONFIG_PCI
-		sunkbd_install_keymaps(memory_start, sun_key_maps,
+		sunkbd_install_keymaps(sun_key_maps,
 		    sun_keymap_count, sun_func_buf, sun_func_table,
 		    sun_funcbufsize, sun_funcbufleft,
 		    sun_accent_table, sun_accent_table_size);
@@ -2663,9 +2692,9 @@
 	 * Console must be initiated after the generic initialization.
 	 * sunserial_setinitfunc inverts order, so call this before next one.
 	 */
-	sunserial_setinitfunc(memory_start, su_serial_console_init);
+	sunserial_setinitfunc(su_serial_console_init);
 #endif
-       	sunserial_setinitfunc(memory_start, su_serial_init);
+       	sunserial_setinitfunc(su_serial_init);
 	return 0;
 }
 
@@ -2887,6 +2916,8 @@
 	if (su_inb(info, UART_LSR) == 0xff)
 		return -1;
 
+	info->is_console = 1;
+
 	return 0;
 }
 
@@ -2904,6 +2935,8 @@
 	NULL
 };
 
+int su_console_registered = 0;
+
 /*
  *	Register console.
  */
@@ -2919,6 +2952,7 @@
 		return 0;
 	sercons.index = 0;
 	register_console(&sercons);
+	su_console_registered = 1;
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c
--- v2.3.34/linux/drivers/sbus/char/sunkbd.c	Mon Oct 11 15:38:15 1999
+++ linux/drivers/sbus/char/sunkbd.c	Mon Dec 20 22:06:42 1999
@@ -172,6 +172,9 @@
 static struct pt_regs * pt_regs;
 
 #ifdef CONFIG_MAGIC_SYSRQ
+#ifndef CONFIG_PCI
+int sysrq_enabled = 1;
+#endif
 unsigned char sun_sysrq_xlate[128] =
 	"\0\0\0\0\0\201\202\212\203\213\204\214\205\0\206\0"	/* 0x00 - 0x0f */
 	"\207\210\211\0\0\0\0\0\0\0\0\0\0\03312"		/* 0x10 - 0x1f */
@@ -545,7 +548,7 @@
 
 #ifdef CONFIG_MAGIC_SYSRQ			/* Handle the SysRq hack */
 	if (l1a_state.l1_down) {
-		if (!up_flag)
+		if (!up_flag && sysrq_enabled)
 			handle_sysrq(sun_sysrq_xlate[keycode], pt_regs, kbd, tty);
 		goto out;
 	}
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunkeymap.c linux/drivers/sbus/char/sunkeymap.c
--- v2.3.34/linux/drivers/sbus/char/sunkeymap.c	Mon Jan 27 00:42:54 1997
+++ linux/drivers/sbus/char/sunkeymap.c	Mon Dec 20 22:06:42 1999
@@ -1,3 +1,4 @@
+
 /* Do not edit this file! It was automatically generated by   */
 /*    loadkeys --mktable defkeymap.map > defkeymap.c          */
 
@@ -30,7 +31,7 @@
 	0xf110,	0xf111,	0xf112,	0xf703,	0xf603,	0xf11d,	0xf200,	0xf203,
 	0xf601,	0xf200,	0xf200,	0xf600,	0xf602,	0xf01b,	0xf021,	0xf040,
 	0xf023,	0xf024,	0xf025,	0xf05e,	0xf026,	0xf02a,	0xf028,	0xf029,
-	0xf05f,	0xf02b,	0xf07e,	0xf07f,	0xf115,	0xf200,	0xf30d,	0xf30c,
+	0xf05f,	0xf02b,	0xf07e,	0xf07f,	0xf115,	0xf03d,	0xf30d,	0xf30c,
 	0xf200,	0xf200,	0xf310,	0xf200,	0xf114,	0xf009,	0xfb51,	0xfb57,
 	0xfb45,	0xfb52,	0xfb54,	0xfb59,	0xfb55,	0xfb49,	0xfb4f,	0xfb50,
 	0xf07b,	0xf07d,	0xf07f,	0xf20e,	0xf307,	0xf308,	0xf309,	0xf30b,
@@ -38,7 +39,7 @@
 	0xfb46,	0xfb47,	0xfb48,	0xfb4a,	0xfb4b,	0xfb4c,	0xf03a,	0xf022,
 	0xf07c,	0xf201,	0xf30e,	0xf304,	0xf305,	0xf306,	0xf300,	0xf200,
 	0xf20b,	0xf200,	0xf208,	0xf700,	0xfb5a,	0xfb58,	0xfb43,	0xfb56,
-	0xfb42,	0xfb4e,	0xfb4d,	0xf03c,	0xf03e,	0xf03f,	0xf700,	0xf200,
+	0xfb42,	0xfb4e,	0xfb4d,	0xf03c,	0xf03e,	0xf03f,	0xf700,	0xf00a,
 	0xf301,	0xf302,	0xf303,	0xf200,	0xf200,	0xf200,	0xf11b,	0xf207,
 	0xf200,	0xf020,	0xf200,	0xf20a,	0xf200,	0xf30a,	0xf200,	0xf200,
 };
@@ -49,7 +50,7 @@
 	0xf512,	0xf513,	0xf514,	0xf703,	0xf603,	0xf11d,	0xf200,	0xf202,
 	0xf601,	0xf200,	0xf200,	0xf600,	0xf602,	0xf200,	0xf200,	0xf040,
 	0xf200,	0xf024,	0xf200,	0xf200,	0xf07b,	0xf05b,	0xf05d,	0xf07d,
-	0xf05c,	0xf200,	0xf200,	0xf200,	0xf115,	0xf200,	0xf30d,	0xf30c,
+	0xf05c,	0xf200,	0xf200,	0xf200,	0xf115,	0xf03d,	0xf30d,	0xf30c,
 	0xf200,	0xf200,	0xf310,	0xf200,	0xf114,	0xf200,	0xfb71,	0xfb77,
 	0xf918,	0xfb72,	0xfb74,	0xfb79,	0xfb75,	0xfb69,	0xfb6f,	0xfb70,
 	0xf200,	0xf07e,	0xf200,	0xf20e,	0xf911,	0xf912,	0xf913,	0xf30b,
@@ -57,7 +58,7 @@
 	0xf919,	0xfb67,	0xfb68,	0xfb6a,	0xfb6b,	0xfb6c,	0xf200,	0xf200,
 	0xf200,	0xf201,	0xf30e,	0xf90e,	0xf90f,	0xf910,	0xf90a,	0xf200,
 	0xf118,	0xf200,	0xf208,	0xf700,	0xfb7a,	0xfb78,	0xf916,	0xfb76,
-	0xf915,	0xfb6e,	0xfb6d,	0xf200,	0xf200,	0xf200,	0xf700,	0xf200,
+	0xf915,	0xfb6e,	0xfb6d,	0xf200,	0xf200,	0xf200,	0xf700,	0xf00a,
 	0xf90b,	0xf90c,	0xf90d,	0xf200,	0xf200,	0xf200,	0xf11b,	0xf207,
 	0xf200,	0xf200,	0xf200,	0xf119,	0xf200,	0xf30a,	0xf200,	0xf200,
 };
@@ -68,7 +69,7 @@
 	0xf106,	0xf107,	0xf108,	0xf703,	0xf603,	0xf11d,	0xf200,	0xf204,
 	0xf601,	0xf200,	0xf200,	0xf600,	0xf602,	0xf200,	0xf200,	0xf000,
 	0xf01b,	0xf01c,	0xf01d,	0xf01e,	0xf01f,	0xf07f,	0xf200,	0xf200,
-	0xf01f,	0xf200,	0xf000,	0xf008,	0xf115,	0xf200,	0xf30d,	0xf30c,
+	0xf01f,	0xf200,	0xf000,	0xf008,	0xf115,	0xf03d,	0xf30d,	0xf30c,
 	0xf200,	0xf200,	0xf310,	0xf200,	0xf114,	0xf200,	0xf011,	0xf017,
 	0xf005,	0xf012,	0xf014,	0xf019,	0xf015,	0xf009,	0xf00f,	0xf010,
 	0xf01b,	0xf01d,	0xf008,	0xf20e,	0xf307,	0xf308,	0xf309,	0xf30b,
@@ -76,7 +77,7 @@
 	0xf006,	0xf007,	0xf008,	0xf00a,	0xf00b,	0xf00c,	0xf200,	0xf007,
 	0xf01c,	0xf201,	0xf30e,	0xf304,	0xf305,	0xf306,	0xf300,	0xf200,
 	0xf118,	0xf200,	0xf208,	0xf700,	0xf01a,	0xf018,	0xf003,	0xf016,
-	0xf002,	0xf00e,	0xf00d,	0xf200,	0xf20e,	0xf07f,	0xf700,	0xf200,
+	0xf002,	0xf00e,	0xf00d,	0xf200,	0xf20e,	0xf07f,	0xf700,	0xf00a,
 	0xf301,	0xf302,	0xf303,	0xf200,	0xf200,	0xf200,	0xf11b,	0xf207,
 	0xf200,	0xf000,	0xf200,	0xf119,	0xf200,	0xf30a,	0xf200,	0xf200,
 };
@@ -87,7 +88,7 @@
 	0xf200,	0xf200,	0xf200,	0xf703,	0xf603,	0xf11d,	0xf200,	0xf200,
 	0xf601,	0xf200,	0xf200,	0xf600,	0xf602,	0xf200,	0xf200,	0xf000,
 	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
-	0xf01f,	0xf200,	0xf200,	0xf200,	0xf115,	0xf200,	0xf30d,	0xf30c,
+	0xf01f,	0xf200,	0xf200,	0xf200,	0xf115,	0xf03d,	0xf30d,	0xf30c,
 	0xf200,	0xf200,	0xf310,	0xf200,	0xf114,	0xf200,	0xf011,	0xf017,
 	0xf005,	0xf012,	0xf014,	0xf019,	0xf015,	0xf009,	0xf00f,	0xf010,
 	0xf200,	0xf200,	0xf200,	0xf20e,	0xf307,	0xf308,	0xf309,	0xf30b,
@@ -95,7 +96,7 @@
 	0xf006,	0xf007,	0xf008,	0xf00a,	0xf00b,	0xf00c,	0xf200,	0xf200,
 	0xf200,	0xf201,	0xf30e,	0xf304,	0xf305,	0xf306,	0xf300,	0xf200,
 	0xf118,	0xf200,	0xf208,	0xf700,	0xf01a,	0xf018,	0xf003,	0xf016,
-	0xf002,	0xf00e,	0xf00d,	0xf200,	0xf200,	0xf200,	0xf700,	0xf200,
+	0xf002,	0xf00e,	0xf00d,	0xf200,	0xf200,	0xf200,	0xf700,	0xf00a,
 	0xf301,	0xf302,	0xf303,	0xf200,	0xf200,	0xf200,	0xf11b,	0xf207,
 	0xf200,	0xf200,	0xf200,	0xf119,	0xf200,	0xf30a,	0xf200,	0xf200,
 };
@@ -106,15 +107,15 @@
 	0xf506,	0xf507,	0xf508,	0xf703,	0xf603,	0xf11d,	0xf200,	0xf209,
 	0xf210,	0xf200,	0xf200,	0xf600,	0xf211,	0xf81b,	0xf831,	0xf832,
 	0xf833,	0xf834,	0xf835,	0xf836,	0xf837,	0xf838,	0xf839,	0xf830,
-	0xf82d,	0xf83d,	0xf860,	0xf87f,	0xf115,	0xf200,	0xf30d,	0xf30c,
+	0xf82d,	0xf83d,	0xf860,	0xf87f,	0xf115,	0xf03d,	0xf30d,	0xf30c,
 	0xf200,	0xf200,	0xf310,	0xf200,	0xf114,	0xf809,	0xf871,	0xf877,
 	0xf865,	0xf872,	0xf874,	0xf879,	0xf875,	0xf869,	0xf86f,	0xf870,
-	0xf85b,	0xf85d,	0xf200,	0xf87f,	0xf907,	0xf908,	0xf909,	0xf30b,
+	0xf85b,	0xf85d,	0xf87f,	0xf20e,	0xf907,	0xf908,	0xf909,	0xf30b,
 	0xf200,	0xf200,	0xf117,	0xf200,	0xf702,	0xf861,	0xf873,	0xf864,
 	0xf866,	0xf867,	0xf868,	0xf86a,	0xf86b,	0xf86c,	0xf83b,	0xf827,
 	0xf85c,	0xf80d,	0xf30e,	0xf904,	0xf905,	0xf906,	0xf900,	0xf200,
 	0xf118,	0xf200,	0xf208,	0xf700,	0xf87a,	0xf878,	0xf863,	0xf876,
-	0xf862,	0xf86e,	0xf86d,	0xf82c,	0xf82e,	0xf82f,	0xf700,	0xf200,
+	0xf862,	0xf86e,	0xf86d,	0xf82c,	0xf82e,	0xf82f,	0xf700,	0xf00a,
 	0xf901,	0xf902,	0xf903,	0xf200,	0xf200,	0xf200,	0xf11b,	0xf207,
 	0xf200,	0xf820,	0xf200,	0xf119,	0xf200,	0xf30a,	0xf200,	0xf200,
 };
@@ -125,7 +126,7 @@
 	0xf506,	0xf507,	0xf508,	0xf703,	0xf603,	0xf11d,	0xf200,	0xf200,
 	0xf601,	0xf200,	0xf200,	0xf600,	0xf602,	0xf200,	0xf200,	0xf200,
 	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,	0xf200,
-	0xf200,	0xf200,	0xf200,	0xf200,	0xf115,	0xf200,	0xf30d,	0xf30c,
+	0xf200,	0xf200,	0xf200,	0xf200,	0xf115,	0xf03d,	0xf30d,	0xf30c,
 	0xf200,	0xf200,	0xf20c,	0xf200,	0xf114,	0xf200,	0xf811,	0xf817,
 	0xf805,	0xf812,	0xf814,	0xf819,	0xf815,	0xf809,	0xf80f,	0xf810,
 	0xf200,	0xf200,	0xf20c,	0xf20e,	0xf307,	0xf308,	0xf309,	0xf30b,
@@ -133,7 +134,7 @@
 	0xf806,	0xf807,	0xf808,	0xf80a,	0xf80b,	0xf80c,	0xf200,	0xf200,
 	0xf200,	0xf201,	0xf30e,	0xf304,	0xf305,	0xf306,	0xf300,	0xf200,
 	0xf118,	0xf200,	0xf208,	0xf700,	0xf81a,	0xf818,	0xf803,	0xf816,
-	0xf802,	0xf80e,	0xf80d,	0xf200,	0xf200,	0xf200,	0xf700,	0xf200,
+	0xf802,	0xf80e,	0xf80d,	0xf200,	0xf200,	0xf200,	0xf700,	0xf00a,
 	0xf301,	0xf302,	0xf303,	0xf200,	0xf200,	0xf200,	0xf11b,	0xf207,
 	0xf200,	0xf200,	0xf200,	0xf119,	0xf200,	0xf30a,	0xf200,	0xf200,
 };
@@ -147,6 +148,7 @@
 
 unsigned int keymap_count = 7;
 
+
 /*
  * Philosophy: most people do not define more strings, but they who do
  * often want quite a lot of string space. So, we statically allocate
@@ -183,6 +185,7 @@
 	'\033', '[', 'M', 0, 
 	'\033', '[', 'P', 0, 
 };
+
 
 char *funcbufptr = func_buf;
 int funcbufsize = sizeof(func_buf);
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunkeymap.map linux/drivers/sbus/char/sunkeymap.map
--- v2.3.34/linux/drivers/sbus/char/sunkeymap.map	Mon Jan 27 00:42:54 1997
+++ linux/drivers/sbus/char/sunkeymap.map	Mon Dec 20 22:06:42 1999
@@ -160,7 +160,7 @@
 	alt	keycode				0x41 = Meta_bracketright
 keycode 0x42 = Delete		Delete
 	control	keycode				0x42 = BackSpace
-	alt	keycode				0x43 = Meta_Delete
+	alt	keycode				0x42 = Meta_Delete
 	control	alt	keycode			0x42 = Boot
 keycode 0x43 = Compose
 keycode 0x44 = KP_7
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunmouse.c linux/drivers/sbus/char/sunmouse.c
--- v2.3.34/linux/drivers/sbus/char/sunmouse.c	Mon Oct 11 15:38:15 1999
+++ linux/drivers/sbus/char/sunmouse.c	Mon Dec 20 22:06:42 1999
@@ -81,7 +81,7 @@
 	unsigned int tail;
 	union {
 		char stream [STREAM_SIZE];
-		Firm_event ev [0];
+		Firm_event ev [EV_SIZE];
 	} queue;
 };
 
@@ -142,8 +142,6 @@
 }
 
 /* Auto baud rate "detection".  ;-) */
-static int mouse_bogon_bytes = 0;
-static int mouse_baud_changing = 0;	/* For reporting things to the user. */
 static int mouse_baud = 4800;		/* Initial rate set by zilog driver. */
 
 /* Change the baud rate after receiving too many "bogon bytes". */
@@ -161,81 +159,112 @@
 		mouse_baud = 1200;
 
 	rs_change_mouse_baud(mouse_baud);
-	mouse_baud_changing = 1;
 }
 
-void mouse_baud_detection(unsigned char c)
+/* This tries to monitor the mouse state so that it
+ * can automatically adjust to the correct baud rate.
+ * The mouse spits out BRKs when the baud rate is
+ * incorrect.
+ *
+ * It returns non-zero if we should ignore this byte.
+ */
+int mouse_baud_detection(unsigned char c, int is_break)
 {
-	static int wait_for_synchron = 1;
+	static int mouse_got_break = 0;
 	static int ctr = 0;
 
-	if(wait_for_synchron) {
-		if((c & ~0x0f) != 0x80)
-			mouse_bogon_bytes++;
-		else {
-		        if (c & 8) {
-				ctr = 2;
-				wait_for_synchron = 0;
-			} else {
-				ctr = 0;
-				wait_for_synchron = 0;
-			}
-		}
-	} else {
+	if (is_break) {
+		/* Let a few normal bytes go by before
+		 * we jump the gun and say we need to
+		 * try another baud rate.
+		 */
+		if (mouse_got_break && ctr < 8)
+			return 1;
+
+		/* OK, we need to try another baud rate. */
+		sun_mouse_change_baud();
+		ctr = 0;
+		mouse_got_break = 1;
+		return 1;
+	}
+	if (mouse_got_break) {
 		ctr++;
-		if(ctr >= 4) {
-			ctr = 0;
-			wait_for_synchron = 1;
-			if(mouse_baud_changing == 1) {
-				printk(KERN_DEBUG "sunmouse: Successfully adjusted to %d baud.\n",
-				       mouse_baud);
-				mouse_baud_changing = 0;
-			}
+		if (c == 0x87) {
+			printk(KERN_INFO "sunmouse: Successfully "
+			       "adjusted to %d baud.\n", mouse_baud);
+			mouse_got_break = 0;
 		}
+		return 1;
 	}
-	if(mouse_bogon_bytes > 12) {
-		sun_mouse_change_baud();
-		mouse_bogon_bytes = 0;
-		wait_for_synchron = 1;
-	}
+
+	return 0;
 }
 
-/* The following is called from the zs driver when bytes are received on
- * the Mouse zs8530 channel.
+/* You ask me, why does this cap the lower bound at -127 and not
+ * -128?  Because the xf86 mouse code is crap and treats -128
+ * as an illegal value and resets it's protocol state machine
+ * when it sees this value.
+ */
+#define CLIP(__X)	(((__X) > 127) ? 127 : (((__X) < -127) ? -127 : (__X)))
+
+/* The following is called from the serial driver when bytes/breaks
+ * are received on the Mouse line.
  */
 void
-sun_mouse_inbyte(unsigned char byte)
+sun_mouse_inbyte(unsigned char byte, int is_break)
 {
 	signed char mvalue;
 	int d, pushed = 0;
 	Firm_event ev;
 
 	add_mouse_randomness (byte);
+#if 0
+	{
+		static int xxx = 0;
+		printk("mouse(%02x:%d) ",
+		       byte, is_break);
+		if (byte == 0x87) {
+			xxx = 0;
+			printk("\n");
+		}
+	}
+#endif
+	if (mouse_baud_detection(byte, is_break))
+		return;
+
 	if(!sunmouse.active)
 		return;
 
-	mouse_baud_detection(byte);
+	/* Ignore this if it is garbage. */
+	if (sunmouse.byte == 69) {
+		if (byte != 0x87)
+			return;
 
-	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;
+		/* Ok, we've begun the state machine. */
+		sunmouse.byte = 0;
 	}
-
+#if 0
 	/* If the mouse sends us a byte from 0x80 to 0x87
 	 * we are starting at byte zero in the transaction
 	 * protocol.
 	 */
 	if((byte & ~0x0f) == 0x80) 
 		sunmouse.byte = 0;
+#endif
 
 	mvalue = (signed char) byte;
 	switch(sunmouse.byte) {
 	case 0:
+		/* If we get a bogus button byte, just skip it.
+		 * When we get here the baud detection code has
+		 * passed, so the only other things which can
+		 * cause this are dropped serial characters and
+		 * confused mouse.  We check this because otherwise
+		 * begin posting erroneous mouse events.
+		 */
+		if ((byte & 0xf0) != 0x80)
+			return;
+
 		/* Button state */
 		sunmouse.button_state = (~byte) & 0x7;
 #ifdef SMOUSE_DEBUG
@@ -274,6 +303,7 @@
 		printk("DX2<%d>", mvalue);
 #endif
 		sunmouse.delta_x += mvalue;
+		sunmouse.delta_x = CLIP(sunmouse.delta_x);
 		sunmouse.byte++;
 		return;
 	case 4:
@@ -282,7 +312,8 @@
 		printk("DY2<%d>", mvalue);
 #endif
 		sunmouse.delta_y += mvalue;
-		sunmouse.byte = 69;  /* Some ridiculous value */
+		sunmouse.delta_y = CLIP(sunmouse.delta_y);
+		sunmouse.byte = 0;  /* Back to button state */
 		break;
 	case 69:
 		/* Until we get the (0x80 -> 0x87) value we aren't
@@ -295,6 +326,12 @@
 		sunmouse.byte = 69;  /* What could cause this? */
 		return;
 	};
+	if (!gen_events){
+		push_char (~sunmouse.button_state & 0x87);
+		push_char (sunmouse.delta_x);
+		push_char (sunmouse.delta_y);
+		return;
+	}
 	d = bstate ^ pstate;
 	pstate = bstate;
 	if (d){
@@ -405,6 +442,10 @@
 			if (current->thread.flags & SPARC_FLAG_32BIT) {
 				Firm_event *q = get_from_queue();
 				
+				if ((end - p) <
+				    ((sizeof(Firm_event) - sizeof(struct timeval) +
+				      (sizeof(u32) * 2))))
+					break;
 				copy_to_user_ret((Firm_event *)p, q, 
 						 sizeof(Firm_event)-sizeof(struct timeval),
 						 -EFAULT);
@@ -416,6 +457,8 @@
 			} else
 #endif	
 			{	
+				if ((end - p) < sizeof(Firm_event))
+					break;
 				copy_to_user_ret((Firm_event *)p, get_from_queue(),
 				     		 sizeof(Firm_event), -EFAULT);
 				p += sizeof (Firm_event);
@@ -425,16 +468,25 @@
 		file->f_dentry->d_inode->i_atime = CURRENT_TIME;
 		return p-buffer;
 	} else {
-		int c;
-		
-		for (c = count; !queue_empty() && c; c--){
-			put_user_ret(sunmouse.queue.stream[sunmouse.tail], buffer, -EFAULT);
+		int c, limit = 3;
+
+		if (count < limit)
+			limit = count;
+		for (c = 0; c < limit; c++) {
+			put_user(sunmouse.queue.stream[sunmouse.tail], buffer);
 			buffer++;
 			sunmouse.tail = (sunmouse.tail + 1) % STREAM_SIZE;
 		}
+		while (c < count) {
+			if (c >= 5)
+				break;
+			put_user(0, buffer);
+			buffer++;
+			c++;
+		}
 		sunmouse.ready = !queue_empty();
 		file->f_dentry->d_inode->i_atime = CURRENT_TIME;
-		return count-c;
+		return c;
 	}
 	/* Only called if nothing was sent */
 	if (signal_pending(current))
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunmouse.h linux/drivers/sbus/char/sunmouse.h
--- v2.3.34/linux/drivers/sbus/char/sunmouse.h	Thu Sep  4 12:54:49 1997
+++ linux/drivers/sbus/char/sunmouse.h	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: sunmouse.h,v 1.1 1997/08/28 02:23:38 ecd Exp $
+/* $Id: sunmouse.h,v 1.2 1999/11/19 09:56:34 davem Exp $
  * sunmouse.h: Interface to the SUN mouse driver.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -8,6 +8,6 @@
 #define _SPARC_SUNMOUSE_H 1
 
 extern void sun_mouse_zsinit(void);
-extern void sun_mouse_inbyte(unsigned char);
+extern void sun_mouse_inbyte(unsigned char, int);
 
 #endif /* !(_SPARC_SUNMOUSE_H) */
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c
--- v2.3.34/linux/drivers/sbus/char/sunserial.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/sbus/char/sunserial.c	Mon Dec 20 22:06:42 1999
@@ -1,24 +1,29 @@
-/* $Id: sunserial.c,v 1.70 1999/09/04 20:28:17 davem Exp $
+/* $Id: sunserial.c,v 1.74 1999/12/15 22:30:23 davem Exp $
  * serial.c: Serial port driver infrastructure for the Sparc.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
  */
 
 #include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
 #include <linux/serial.h>
+#include <linux/serialP.h>
 #include <linux/string.h>
 #include <linux/kbd_diacr.h>
 #include <linux/version.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 
 #include <asm/oplib.h>
 
 #include "sunserial.h"
 
 int serial_console;
+int stop_a_enabled = 1;
 
 int __init con_is_present(void)
 {
@@ -67,9 +72,9 @@
 	rs_ops.rs_kgdb_hook(channel);
 }
 
-long __init serial_console_init(long kmem_start, long kmem_end)
+void __init serial_console_init(void)
 {
-	return kmem_start;
+	return;
 }
 
 void rs_change_mouse_baud(int baud)
@@ -168,14 +173,27 @@
 	return kbd_ops.getkeycode(scancode);
 }
 
+void * __init sunserial_alloc_bootmem(unsigned long size)
+{
+	void *ret;
+
+	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+	if (ret != NULL)
+		memset(ret, 0, size);
+
+	return ret;
+}
+
 void
-sunserial_setinitfunc(unsigned long *memory_start, int (*init) (void))
+sunserial_setinitfunc(int (*init) (void))
 {
 	struct initfunc *rs_init;
 
-	*memory_start = (*memory_start + 7) & ~(7);
-	rs_init = (struct initfunc *) *memory_start;
-	*memory_start += sizeof(struct initfunc);
+	rs_init = sunserial_alloc_bootmem(sizeof(struct initfunc));
+	if (rs_init == NULL) {
+		prom_printf("sunserial_setinitfunc: Cannot alloc initfunc.\n");
+		prom_halt();
+	}
 
 	rs_init->init = init;
 	rs_init->next = rs_ops.rs_init;
@@ -291,13 +309,15 @@
 }
 
 void
-sunkbd_setinitfunc(unsigned long *memory_start, int (*init) (void))
+sunkbd_setinitfunc(int (*init) (void))
 {
 	struct initfunc *kbd_init;
 
-	*memory_start = (*memory_start + 7) & ~(7);
-	kbd_init = (struct initfunc *) *memory_start;
-	*memory_start += sizeof(struct initfunc);
+	kbd_init = sunserial_alloc_bootmem(sizeof(struct initfunc));
+	if (kbd_init == NULL) {
+		prom_printf("sunkbd_setinitfunc: Cannot alloc initfunc.\n");
+		prom_halt();
+	}
 
 	kbd_init->init = init;
 	kbd_init->next = kbd_ops.kbd_init;
@@ -306,8 +326,7 @@
 
 #ifdef CONFIG_PCI
 void
-sunkbd_install_keymaps(unsigned long *memory_start,
-		       ushort **src_key_maps, unsigned int src_keymap_count,
+sunkbd_install_keymaps(ushort **src_key_maps, unsigned int src_keymap_count,
 		       char *src_func_buf, char **src_func_table,
 		       int src_funcbufsize, int src_funcbufleft,
 		       struct kbdiacr *src_accent_table,
@@ -319,8 +338,13 @@
 	for (i = 0; i < MAX_NR_KEYMAPS; i++) {
 		if (src_key_maps[i]) {
 			if (!key_maps[i]) {
-				key_maps[i] = (ushort *)*memory_start;
-				*memory_start += NR_KEYS * sizeof(ushort);
+				key_maps[i] = (ushort *)
+					sunserial_alloc_bootmem(NR_KEYS * sizeof(ushort));
+				if (key_maps[i] == NULL) {
+					prom_printf("sunkbd_install_keymaps: "
+						    "Cannot alloc key_map(%d).\n", i);
+					prom_halt();
+				}
 			}
 			for (j = 0; j < NR_KEYS; j++)
 				key_maps[i][j] = src_key_maps[i][j];
@@ -341,16 +365,16 @@
 }
 #endif
 
-extern int su_probe(unsigned long *);
-extern int zs_probe(unsigned long *);
+extern int su_probe(void);
+extern int zs_probe(void);
 #ifdef CONFIG_SAB82532
-extern int sab82532_probe(unsigned long *);
+extern int sab82532_probe(void);
 #endif
 #ifdef CONFIG_PCI
-extern int ps2kbd_probe(unsigned long *);
+extern int ps2kbd_probe(void);
 #endif
 
-unsigned long __init sun_serial_setup(unsigned long memory_start)
+void __init sun_serial_setup(void)
 {
 	int ret = 1;
 	
@@ -362,16 +386,16 @@
 	 * get console on MrCoffee with fine but disconnected zs.
 	 */
 	if (!serial_console)
-		ps2kbd_probe(&memory_start);
-	if (su_probe(&memory_start) == 0)
-		return memory_start;
+		ps2kbd_probe();
+	if (su_probe() == 0)
+		return;
 #endif
 
-	if (zs_probe(&memory_start) == 0)
-		return memory_start;
+	if (zs_probe() == 0)
+		return;
 		
 #ifdef CONFIG_SAB82532
-	ret = sab82532_probe(&memory_start);
+	ret = sab82532_probe();
 #endif
 
 #if defined(CONFIG_PCI) && defined(__sparc_v9__)
@@ -387,23 +411,22 @@
 	 * serial console.
 	 */
 	if (!serial_console)
-		ps2kbd_probe(&memory_start);
-	if (su_probe(&memory_start) == 0)
-		return memory_start;
+		ps2kbd_probe();
+	if (su_probe() == 0)
+		return;
 #endif
 
 	if (!ret)
-		return memory_start;
+		return;
 		
 #ifdef __sparc_v9__
 	{	extern int this_is_starfire;
 		/* Hello, Starfire. Pleased to meet you :) */
 		if(this_is_starfire != 0)
-			return memory_start;
+			return;
 	}
 #endif
 
 	prom_printf("No serial devices found, bailing out.\n");
 	prom_halt();
-	return memory_start;
 }
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/sunserial.h linux/drivers/sbus/char/sunserial.h
--- v2.3.34/linux/drivers/sbus/char/sunserial.h	Mon Jan 12 15:15:45 1998
+++ linux/drivers/sbus/char/sunserial.h	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: sunserial.h,v 1.17 1997/12/19 07:33:12 ecd Exp $
+/* $Id: sunserial.h,v 1.19 1999/12/01 10:45:59 davem Exp $
  * sunserial.h: SUN serial driver infrastructure (including keyboards).
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -37,15 +37,17 @@
 extern struct sunserial_operations rs_ops;
 extern struct sunkbd_operations kbd_ops;
 
-extern void sunserial_setinitfunc(unsigned long *, int (*) (void));
-extern void sunkbd_setinitfunc(unsigned long *, int (*) (void));
+extern void sunserial_setinitfunc(int (*) (void));
+extern void sunkbd_setinitfunc(int (*) (void));
 
 extern int serial_console;
+extern int stop_a_enabled;
 extern void sunserial_console_termios(struct console *);
 
 #ifdef CONFIG_PCI
-extern void sunkbd_install_keymaps(unsigned long *, ushort **, unsigned int, char *,
-				   char **, int, int, struct kbdiacr *, unsigned int);
+extern void sunkbd_install_keymaps(ushort **, unsigned int, char *,
+				   char **, int, int, struct kbdiacr *,
+				   unsigned int);
 #endif
 
 #endif /* !(_SPARC_SUNSERIAL_H) */
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/uctrl.c linux/drivers/sbus/char/uctrl.c
--- v2.3.34/linux/drivers/sbus/char/uctrl.c	Thu Nov 18 20:25:37 1999
+++ linux/drivers/sbus/char/uctrl.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: uctrl.c,v 1.2 1999/09/07 23:11:08 shadow Exp $
+/* $Id: uctrl.c,v 1.5 1999/12/15 15:48:24 davem Exp $
  * uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3
  *
  * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
@@ -25,13 +25,179 @@
 
 #define UCTRL_MINOR	174
 
+#define DEBUG 1
+#ifdef DEBUG
+#define dprintk(x) printk x
+#else
+#define dprintk(x)
+#endif
+
+struct uctrl_regs {
+	volatile u32 uctrl_intr;
+	volatile u32 uctrl_data;
+	volatile u32 uctrl_stat;
+	volatile u32 uctrl_xxx[5];
+};
+
+struct ts102_regs {
+	volatile u32 card_a_intr;
+	volatile u32 card_a_stat;
+	volatile u32 card_a_ctrl;
+	volatile u32 card_a_xxx;
+	volatile u32 card_b_intr;
+	volatile u32 card_b_stat;
+	volatile u32 card_b_ctrl;
+	volatile u32 card_b_xxx;
+	volatile u32 uctrl_intr;
+	volatile u32 uctrl_data;
+	volatile u32 uctrl_stat;
+	volatile u32 uctrl_xxx;
+	volatile u32 ts102_xxx[4];
+};
+
+/* Bits for uctrl_intr register */
+#define UCTRL_INTR_TXE_REQ         0x01    /* transmit FIFO empty int req */
+#define UCTRL_INTR_TXNF_REQ        0x02    /* transmit FIFO not full int req */
+#define UCTRL_INTR_RXNE_REQ        0x04    /* receive FIFO not empty int req */
+#define UCTRL_INTR_RXO_REQ         0x08    /* receive FIFO overflow int req */
+#define UCTRL_INTR_TXE_MSK         0x10    /* transmit FIFO empty mask */
+#define UCTRL_INTR_TXNF_MSK        0x20    /* transmit FIFO not full mask */
+#define UCTRL_INTR_RXNE_MSK        0x40    /* receive FIFO not empty mask */
+#define UCTRL_INTR_RXO_MSK         0x80    /* receive FIFO overflow mask */
+
+/* Bits for uctrl_stat register */
+#define UCTRL_STAT_TXE_STA         0x01    /* transmit FIFO empty status */
+#define UCTRL_STAT_TXNF_STA        0x02    /* transmit FIFO not full status */
+#define UCTRL_STAT_RXNE_STA        0x04    /* receive FIFO not empty status */
+#define UCTRL_STAT_RXO_STA         0x08    /* receive FIFO overflow status */
+
+static const char *uctrl_extstatus[16] = {
+        "main power available",
+        "internal battery attached",
+        "external battery attached",
+        "external VGA attached",
+        "external keyboard attached",
+        "external mouse attached",
+        "lid down",
+        "internal battery currently charging",
+        "external battery currently charging",
+        "internal battery currently discharging",
+        "external battery currently discharging",
+};
+
+/* Everything required for one transaction with the uctrl */
+struct uctrl_txn {
+	u8 opcode;
+	u8 inbits;
+	u8 outbits;
+	u8 *inbuf;
+	u8 *outbuf;
+};
+
+struct uctrl_status {
+	u8 current_temp; /* 0x07 */
+	u8 reset_status; /* 0x0b */
+	u16 event_status; /* 0x0c */
+	u16 error_status; /* 0x10 */
+	u16 external_status; /* 0x11, 0x1b */
+	u8 internal_charge; /* 0x18 */
+	u8 external_charge; /* 0x19 */
+	u16 control_lcd; /* 0x20 */
+	u8 control_bitport; /* 0x21 */
+	u8 speaker_volume; /* 0x23 */
+	u8 control_tft_brightness; /* 0x24 */
+	u8 control_kbd_repeat_delay; /* 0x28 */
+	u8 control_kbd_repeat_rate; /* 0x29 */
+	u8 control_screen_contrast; /* 0x2F */
+};
+
+enum uctrl_opcode {
+  READ_SERIAL_NUMBER=0x1,
+  READ_ETHERNET_ADDRESS=0x2,
+  READ_HARDWARE_VERSION=0x3,
+  READ_MICROCONTROLLER_VERSION=0x4,
+  READ_MAX_TEMPERATURE=0x5,
+  READ_MIN_TEMPERATURE=0x6,
+  READ_CURRENT_TEMPERATURE=0x7,
+  READ_SYSTEM_VARIANT=0x8,
+  READ_POWERON_CYCLES=0x9,
+  READ_POWERON_SECONDS=0xA,
+  READ_RESET_STATUS=0xB,
+  READ_EVENT_STATUS=0xC,
+  READ_REAL_TIME_CLOCK=0xD,
+  READ_EXTERNAL_VGA_PORT=0xE,
+  READ_MICROCONTROLLER_ROM_CHECKSUM=0xF,
+  READ_ERROR_STATUS=0x10,
+  READ_EXTERNAL_STATUS=0x11,
+  READ_USER_CONFIGURATION_AREA=0x12,
+  READ_MICROCONTROLLER_VOLTAGE=0x13,
+  READ_INTERNAL_BATTERY_VOLTAGE=0x14,
+  READ_DCIN_VOLTAGE=0x15,
+  READ_HORIZONTAL_POINTER_VOLTAGE=0x16,
+  READ_VERTICAL_POINTER_VOLTAGE=0x17,
+  READ_INTERNAL_BATTERY_CHARGE_LEVEL=0x18,
+  READ_EXTERNAL_BATTERY_CHARGE_LEVEL=0x19,
+  READ_REAL_TIME_CLOCK_ALARM=0x1A,
+  READ_EVENT_STATUS_NO_RESET=0x1B,
+  READ_INTERNAL_KEYBOARD_LAYOUT=0x1C,
+  READ_EXTERNAL_KEYBOARD_LAYOUT=0x1D,
+  READ_EEPROM_STATUS=0x1E,
+  CONTROL_LCD=0x20,
+  CONTROL_BITPORT=0x21,
+  SPEAKER_VOLUME=0x23,
+  CONTROL_TFT_BRIGHTNESS=0x24,
+  CONTROL_WATCHDOG=0x25,
+  CONTROL_FACTORY_EEPROM_AREA=0x26,
+  CONTROL_KBD_TIME_UNTIL_REPEAT=0x28,
+  CONTROL_KBD_TIME_BETWEEN_REPEATS=0x29,
+  CONTROL_TIMEZONE=0x2A,
+  CONTROL_MARK_SPACE_RATIO=0x2B,
+  CONTROL_DIAGNOSTIC_MODE=0x2E,
+  CONTROL_SCREEN_CONTRAST=0x2F,
+  RING_BELL=0x30,
+  SET_DIAGNOSTIC_STATUS=0x32,
+  CLEAR_KEY_COMBINATION_TABLE=0x33,
+  PERFORM_SOFTWARE_RESET=0x34,
+  SET_REAL_TIME_CLOCK=0x35,
+  RECALIBRATE_POINTING_STICK=0x36,
+  SET_BELL_FREQUENCY=0x37,
+  SET_INTERNAL_BATTERY_CHARGE_RATE=0x39,
+  SET_EXTERNAL_BATTERY_CHARGE_RATE=0x3A,
+  SET_REAL_TIME_CLOCK_ALARM=0x3B,
+  READ_EEPROM=0x40,
+  WRITE_EEPROM=0x41,
+  WRITE_TO_STATUS_DISPLAY=0x42,
+  DEFINE_SPECIAL_CHARACTER=0x43,
+  DEFINE_KEY_COMBINATION_ENTRY=0x50,
+  DEFINE_STRING_TABLE_ENTRY=0x51,
+  DEFINE_STATUS_SCREEN_DISPLAY=0x52,
+  PERFORM_EMU_COMMANDS=0x64,
+  READ_EMU_REGISTER=0x65,
+  WRITE_EMU_REGISTER=0x66,
+  READ_EMU_RAM=0x67,
+  WRITE_EMU_RAM=0x68,
+  READ_BQ_REGISTER=0x69,
+  WRITE_BQ_REGISTER=0x6A,
+  SET_USER_PASSWORD=0x70,
+  VERIFY_USER_PASSWORD=0x71,
+  GET_SYSTEM_PASSWORD_KEY=0x72,
+  VERIFY_SYSTEM_PASSWORD=0x73,
+  POWER_OFF=0x82,
+  POWER_RESTART=0x83,
+};
+
 struct uctrl_driver {
-	volatile u32 *regs;
+	struct uctrl_regs *regs;
 	int irq;
+	int pending;
+	struct uctrl_status status;
 };
 
 static struct uctrl_driver drv;
 
+void uctrl_get_event_status(void);
+void uctrl_get_external_status(void);
+
 static loff_t
 uctrl_llseek(struct file *file, loff_t offset, int type)
 {
@@ -53,6 +219,8 @@
 uctrl_open(struct inode *inode, struct file *file)
 {
 	MOD_INC_USE_COUNT;
+	uctrl_get_event_status();
+	uctrl_get_external_status();
 	return 0;
 }
 
@@ -88,6 +256,127 @@
 	&uctrl_fops
 };
 
+/* Wait for space to write, then write to it */
+#define WRITEUCTLDATA(value) \
+{ \
+  unsigned int i; \
+  for (i = 0; i < 10000; i++) { \
+    if (UCTRL_STAT_TXNF_STA & driver->regs->uctrl_stat) \
+      break; \
+  } \
+  dprintk(("write data 0x%02x\n", value)); \
+  driver->regs->uctrl_data = value; \
+}
+
+/* Wait for something to read, read it, then clear the bit */
+#define READUCTLDATA(value) \
+{ \
+  unsigned int i; \
+  value = 0; \
+  for (i = 0; i < 10000; i++) { \
+    if ((UCTRL_STAT_RXNE_STA & driver->regs->uctrl_stat) == 0) \
+      break; \
+    udelay(1); \
+  } \
+  value = driver->regs->uctrl_data; \
+  dprintk(("read data 0x%02x\n", value)); \
+  driver->regs->uctrl_stat = UCTRL_STAT_RXNE_STA; \
+}
+
+void uctrl_set_video(int status)
+{
+	struct uctrl_driver *driver = &drv;
+	
+}
+
+static void uctrl_do_txn(struct uctrl_txn *txn)
+{
+	struct uctrl_driver *driver = &drv;
+	int stat, incnt, outcnt, bytecnt, intr;
+	u32 byte;
+
+	stat = driver->regs->uctrl_stat;
+	intr = driver->regs->uctrl_intr;
+	driver->regs->uctrl_stat = stat;
+
+	dprintk(("interrupt stat 0x%x int 0x%x\n", stat, intr));
+
+	incnt = txn->inbits;
+	outcnt = txn->outbits;
+	byte = (txn->opcode << 8);
+	WRITEUCTLDATA(byte);
+
+	bytecnt = 0;
+	while (incnt > 0) {
+		byte = (txn->inbuf[bytecnt] << 8);
+		WRITEUCTLDATA(byte);
+		incnt--;
+		bytecnt++;
+	}
+
+	/* Get the ack */
+	READUCTLDATA(byte);
+	dprintk(("ack was %x\n", (byte >> 8)));
+
+	bytecnt = 0;
+	while (outcnt > 0) {
+		READUCTLDATA(byte);
+		txn->outbuf[bytecnt] = (byte >> 8);
+		dprintk(("set byte to %02x\n", byte));
+		outcnt--;
+		bytecnt++;
+	}
+}
+
+void uctrl_get_event_status()
+{
+	struct uctrl_driver *driver = &drv;
+	struct uctrl_txn txn;
+	u8 outbits[2];
+
+	txn.opcode = READ_EVENT_STATUS;
+	txn.inbits = 0;
+	txn.outbits = 2;
+	txn.inbuf = 0;
+	txn.outbuf = outbits;
+
+	uctrl_do_txn(&txn);
+
+	dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff)));
+	driver->status.event_status = 
+		((outbits[0] & 0xff) << 8) | (outbits[1] & 0xff);
+	dprintk(("ev is %x\n", driver->status.event_status));
+}
+
+void uctrl_get_external_status()
+{
+	struct uctrl_driver *driver = &drv;
+	struct uctrl_txn txn;
+	u8 outbits[2];
+	int i, v;
+
+	txn.opcode = READ_EXTERNAL_STATUS;
+	txn.inbits = 0;
+	txn.outbits = 2;
+	txn.inbuf = 0;
+	txn.outbuf = outbits;
+
+	uctrl_do_txn(&txn);
+
+	dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff)));
+	driver->status.external_status = 
+		((outbits[0] * 256) + (outbits[1]));
+	dprintk(("ex is %x\n", driver->status.external_status));
+	v = driver->status.external_status;
+	for (i = 0; v != 0; i++, v >>= 1) {
+		if (v & 1) {
+			dprintk(("%s%s", " ", uctrl_extstatus[i]));
+		}
+	}
+	dprintk(("\n"));
+	
+}
+
 #ifdef MODULE
 int init_module(void)
 #else
@@ -95,7 +384,7 @@
 #endif
 {
 	struct uctrl_driver *driver = &drv;
-	int len;
+	int len, i;
 	struct linux_prom_irqs tmp_irq[2];
         unsigned int vaddr[2] = { 0, 0 };
 	int tmpnode, uctrlnode = prom_getchild(prom_root_node);
@@ -113,10 +402,14 @@
 	/* the prom mapped it for us */
 	len = prom_getproperty(uctrlnode, "address", (void *) vaddr,
 			       sizeof(vaddr));
-	driver->regs = vaddr[0];
+	driver->regs = (struct uctrl_regs *)vaddr[0];
 
 	len = prom_getproperty(uctrlnode, "intr", (char *) tmp_irq,
 			       sizeof(tmp_irq));
+
+	/* Flush device */
+	READUCTLDATA(len);
+
 	if(!driver->irq) 
 		driver->irq = tmp_irq[0].pri;
 
@@ -133,7 +426,10 @@
 		return -ENODEV;
 	}
 
-	printk(KERN_INFO, "uctrl: 0x%x (irq %d)\n", driver->regs, __irq_itoa(driver->irq));
+	driver->regs->uctrl_intr = UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK;
+	printk("uctrl: 0x%x (irq %s)\n", driver->regs, __irq_itoa(driver->irq));
+	uctrl_get_event_status();
+	uctrl_get_external_status();
         return 0;
 }
 
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/vfc_dev.c linux/drivers/sbus/char/vfc_dev.c
--- v2.3.34/linux/drivers/sbus/char/vfc_dev.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/sbus/char/vfc_dev.c	Mon Dec 20 22:06:42 1999
@@ -43,17 +43,20 @@
 
 struct vfc_dev **vfc_dev_lst;
 static char vfcstr[]="vfc";
-static unsigned char saa9051_init_array[VFC_SAA9051_NR]=
-{ 0x00, 0x64, 0x72, 0x52,
-  0x36, 0x18, 0xff, 0x20,
-  0xfc, 0x77, 0xe3, 0x50,
-  0x3e};
+static unsigned char saa9051_init_array[VFC_SAA9051_NR] = {
+	0x00, 0x64, 0x72, 0x52,
+	0x36, 0x18, 0xff, 0x20,
+	0xfc, 0x77, 0xe3, 0x50,
+	0x3e
+};
 
-void vfc_lock_device(struct vfc_dev *dev) {
+void vfc_lock_device(struct vfc_dev *dev)
+{
 	down(&dev->device_lock_sem);
 }
 
-void vfc_unlock_device(struct vfc_dev *dev) {
+void vfc_unlock_device(struct vfc_dev *dev)
+{
 	up(&dev->device_lock_sem);
 }
 
@@ -61,41 +64,39 @@
 void vfc_captstat_reset(struct vfc_dev *dev) 
 {
 	dev->control_reg |= VFC_CONTROL_CAPTRESET;
-	dev->regs->control=dev->control_reg;
+	sbus_writel(dev->control_reg, &dev->regs->control);
 	dev->control_reg &= ~VFC_CONTROL_CAPTRESET;
-	dev->regs->control=dev->control_reg;
+	sbus_writel(dev->control_reg, &dev->regs->control);
 	dev->control_reg |= VFC_CONTROL_CAPTRESET;
-	dev->regs->control=dev->control_reg;
-	return;
+	sbus_writel(dev->control_reg, &dev->regs->control);
 }
 
 void vfc_memptr_reset(struct vfc_dev *dev) 
 {
 	dev->control_reg |= VFC_CONTROL_MEMPTR;
-	dev->regs->control = dev->control_reg; 
+	sbus_writel(dev->control_reg, &dev->regs->control);
 	dev->control_reg &= ~VFC_CONTROL_MEMPTR;
-	dev->regs->control = dev->control_reg; 
+	sbus_writel(dev->control_reg, &dev->regs->control);
 	dev->control_reg |= VFC_CONTROL_MEMPTR; 
-	dev->regs->control = dev->control_reg; 
-	return;
+	sbus_writel(dev->control_reg, &dev->regs->control);
 }
 
 int vfc_csr_init(struct vfc_dev *dev)
 {
 	dev->control_reg = 0x80000000;
-	dev->regs->control = dev->control_reg;
+	sbus_writel(dev->control_reg, &dev->regs->control);
 	udelay(200); 
 	dev->control_reg &= ~0x80000000;
-	dev->regs->control = dev->control_reg;
+	sbus_writel(dev->control_reg, &dev->regs->control);
 	udelay(100); 
-	dev->regs->i2c_magic2 = 0x0f000000; 
+	sbus_writel(0x0f000000, &dev->regs->i2c_magic2);
 
 	vfc_memptr_reset(dev);
 
 	dev->control_reg &= ~VFC_CONTROL_DIAGMODE;
 	dev->control_reg &= ~VFC_CONTROL_CAPTURE;
 	dev->control_reg |= 0x40000000;
-	dev->regs->control=dev->control_reg; 
+	sbus_writel(dev->control_reg, &dev->regs->control);
 
 	vfc_captstat_reset(dev);
 
@@ -105,9 +106,10 @@
 int vfc_saa9051_init(struct vfc_dev *dev)
 {
 	int i;
-	for(i=0;i<VFC_SAA9051_NR;i++) {
-		dev->saa9051_state_array[i]=saa9051_init_array[i];
-	}
+
+	for (i = 0; i < VFC_SAA9051_NR; i++)
+		dev->saa9051_state_array[i] = saa9051_init_array[i];
+
 	vfc_i2c_sendbuf(dev,VFC_SAA9051_ADDR,
 			dev->saa9051_state_array, VFC_SAA9051_NR);
 	return 0;
@@ -136,27 +138,29 @@
 	return 0;
 }
 
-int init_vfc_device(struct linux_sbus_device *sdev,struct vfc_dev *dev,
-		    int instance) {
-	if(!dev) {
+int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance)
+{
+	if(dev == NULL) {
 		printk(KERN_ERR "VFC: Bogus pointer passed\n");
 		return -ENOMEM;
 	}
 	printk("Initializing vfc%d\n",instance);
-	dev->regs=NULL;
-	prom_apply_sbus_ranges(sdev->my_bus, &sdev->reg_addrs[0], sdev->num_registers, sdev);
-	dev->regs=sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
-				 sizeof(struct vfc_regs), vfcstr, 
-				 sdev->reg_addrs[0].which_io, 0x0);
-	dev->which_io=sdev->reg_addrs[0].which_io;
-	dev->phys_regs=(struct vfc_regs *)sdev->reg_addrs[0].phys_addr;
-	if(!dev->regs) return -EIO;
+	dev->regs = NULL;
+	dev->regs = (volatile struct vfc_regs *)
+		sbus_ioremap(&sdev->resource[0], 0,
+			     sizeof(struct vfc_regs), vfcstr);
+	dev->which_io = sdev->reg_addrs[0].which_io;
+	dev->phys_regs = (struct vfc_regs *) sdev->reg_addrs[0].phys_addr;
+	if (dev->regs == NULL)
+		return -EIO;
 
 	printk("vfc%d: registers mapped at phys_addr: 0x%lx\n    virt_addr: 0x%lx\n",
 	       instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs);
 
-	if(init_vfc_devstruct(dev,instance)) return -EINVAL;
-	if(init_vfc_hw(dev)) return -EIO;
+	if (init_vfc_devstruct(dev, instance))
+		return -EINVAL;
+	if (init_vfc_hw(dev))
+		return -EIO;
 
 	return 0;
 }
@@ -170,10 +174,14 @@
 static int vfc_open(struct inode *inode, struct file *file) 
 {
 	struct vfc_dev *dev;
-	dev=vfc_get_dev_ptr(MINOR(inode->i_rdev));
-	if(!dev) return -ENODEV;
-	if(dev->busy) return -EBUSY;
-	dev->busy=1;
+
+	dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
+	if (dev == NULL)
+		return -ENODEV;
+	if (dev->busy)
+		return -EBUSY;
+
+	dev->busy = 1;
 	MOD_INC_USE_COUNT;
 	vfc_lock_device(dev);
 	
@@ -191,12 +199,14 @@
 static void vfc_release(struct inode *inode,struct file *file) 
 {
 	struct vfc_dev *dev;
-	dev=vfc_get_dev_ptr(MINOR(inode->i_rdev));
-	if(!dev) return;
-	if(!dev->busy) return;
-	dev->busy=0;
+
+	dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
+	if (dev == NULL)
+		return;
+	if (!dev->busy)
+		return;
+	dev->busy = 0;
 	MOD_DEC_USE_COUNT;
-	return;
 }
 
 static int vfc_debug(struct vfc_dev *dev, int cmd, unsigned long arg) 
@@ -204,21 +214,21 @@
 	struct vfc_debug_inout inout;
 	unsigned char *buffer;
 
-	if(!capable(CAP_SYS_ADMIN)) return -EPERM;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
 
 	switch(cmd) {
 	case VFC_I2C_SEND:
-		if(copy_from_user(&inout, (void *)arg, sizeof(inout))) {
+		if(copy_from_user(&inout, (void *)arg, sizeof(inout)))
 			return -EFAULT;
-		}
 
 		buffer = kmalloc(inout.len*sizeof(char), GFP_KERNEL);
-		if (!buffer)
+		if (buffer == NULL)
 			return -ENOMEM;
 
 		if(copy_from_user(buffer, inout.buffer, 
 				  inout.len*sizeof(char))) {
-			kfree_s(buffer,inout.len*sizeof(char));
+			kfree_s(buffer, inout.len * sizeof(char));
 			return -EFAULT;
 		}
 		
@@ -236,13 +246,13 @@
 
 		break;
 	case VFC_I2C_RECV:
-		if (copy_from_user(&inout, (void *)arg, sizeof(inout))) {
+		if (copy_from_user(&inout, (void *)arg, sizeof(inout)))
 			return -EFAULT;
-		}
 
 		buffer = kmalloc(inout.len, GFP_KERNEL);
-		if (!buffer)
+		if (buffer == NULL)
 			return -ENOMEM;
+
 		memset(buffer,0,inout.len*sizeof(char));
 		vfc_lock_device(dev);
 		inout.ret=
@@ -262,14 +272,15 @@
 		break;
 	default:
 		return -EINVAL;
-	}
+	};
+
 	return 0;
 }
 
 int vfc_capture_start(struct vfc_dev *dev) 
 {
 	vfc_captstat_reset(dev);
-	dev->control_reg=dev->regs->control;
+	dev->control_reg = sbus_readl(&dev->regs->control);
 	if((dev->control_reg & VFC_STATUS_CAPTURE)) {
 		printk(KERN_ERR "vfc%d: vfc capture status not reset\n",
 		       dev->instance);
@@ -278,11 +289,11 @@
 
 	vfc_lock_device(dev);
 	dev->control_reg &= ~VFC_CONTROL_CAPTURE;
-	dev->regs->control=dev->control_reg;
+	sbus_writel(dev->control_reg, &dev->regs->control);
 	dev->control_reg |= VFC_CONTROL_CAPTURE;
-	dev->regs->control=dev->control_reg;
+	sbus_writel(dev->control_reg, &dev->regs->control);
 	dev->control_reg &= ~VFC_CONTROL_CAPTURE;
-	dev->regs->control=dev->control_reg;
+	sbus_writel(dev->control_reg, &dev->regs->control);
 	vfc_unlock_device(dev);
 
 	return 0;
@@ -290,13 +301,16 @@
 
 int vfc_capture_poll(struct vfc_dev *dev) 
 {
-	int timeout=1000;
-	while(!timeout--) {
-		if((dev->regs->control & VFC_STATUS_CAPTURE)) break;
-		vfc_i2c_delay_no_busy(dev,100);
+	int timeout = 1000;
+
+	while (!timeout--) {
+		if (dev->regs->control & VFC_STATUS_CAPTURE)
+			break;
+		vfc_i2c_delay_no_busy(dev, 100);
 	}
 	if(!timeout) {
-		printk(KERN_WARNING "vfc%d: capture timed out\n", dev->instance);
+		printk(KERN_WARNING "vfc%d: capture timed out\n",
+		       dev->instance);
 		return -ETIMEDOUT;
 	}
 	return 0;
@@ -307,11 +321,14 @@
 static int vfc_set_control_ioctl(struct inode *inode, struct file *file, 
 			  struct vfc_dev *dev, unsigned long arg) 
 {
-	int setcmd,ret=0;
+	int setcmd, ret = 0;
+
 	if (copy_from_user(&setcmd,(void *)arg,sizeof(unsigned int)))
 		return -EFAULT;
+
 	VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n",
 				dev->instance,setcmd));
+
 	switch(setcmd) {
 	case MEMPRST:
 		vfc_lock_device(dev);
@@ -327,29 +344,33 @@
 		if(suser()) {
 			vfc_lock_device(dev);
 			dev->control_reg |= VFC_CONTROL_DIAGMODE;
-			dev->regs->control = dev->control_reg;
+			sbus_writel(dev->control_reg, &dev->regs->control);
 			vfc_unlock_device(dev);
-			ret=0;
-		} else ret=-EPERM; 
+			ret = 0;
+		} else {
+			ret = -EPERM; 
+		}
 		break;
 	case NORMMODE:
 		vfc_lock_device(dev);
 		dev->control_reg &= ~VFC_CONTROL_DIAGMODE;
-		dev->regs->control = dev->control_reg;
+		sbus_writel(dev->control_reg, &dev->regs->control);
 		vfc_unlock_device(dev);
-		ret=0;
+		ret = 0;
 		break;
 	case CAPTRSTR:
 		vfc_capture_start(dev);
-		ret=0;
+		ret = 0;
 		break;
 	case CAPTRWAIT:
 		vfc_capture_poll(dev);
-		ret=0;
+		ret = 0;
 		break;
 	default:
-		ret=-EINVAL;
-	}
+		ret = -EINVAL;
+		break;
+	};
+
 	return ret;
 }
 
@@ -357,17 +378,18 @@
 int vfc_port_change_ioctl(struct inode *inode, struct file *file, 
 			  struct vfc_dev *dev, unsigned long arg) 
 {
-	int ret=0;
+	int ret = 0;
 	int cmd;
 
 	if(copy_from_user(&cmd, (void *)arg, sizeof(unsigned int))) {
 		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to "
-				  "vfc_port_change_ioctl\n",dev->instance));
+					"vfc_port_change_ioctl\n",
+					dev->instance));
 		return -EFAULT;
 	}
 	
 	VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%x\n",
-			  dev->instance,cmd));
+				dev->instance, cmd));
 
 	switch(cmd) {
 	case 1:
@@ -385,29 +407,33 @@
 		VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x17;
 		VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0xfa;
 		VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0xde;
-		VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = VFC_SAA9051_BY | VFC_SAA9051_PF | VFC_SAA9051_BP2;
+		VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) =
+			VFC_SAA9051_BY | VFC_SAA9051_PF | VFC_SAA9051_BP2;
 		VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_YC;
 		VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0;
-		VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
+		VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &=
+			~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
 		break;
 	default:
-		ret=-EINVAL;
+		ret = -EINVAL;
 		return ret;
 		break;
 	}
 
 	switch(cmd) {
 	case 1:
-		VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= VFC_SAA9051_SS0 | VFC_SAA9051_SS1;
+		VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |=
+			(VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
 		break;
 	case 2:
-		VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
+		VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &=
+			~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1);
 		VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= VFC_SAA9051_SS0; 
 		break;
 	case 3:
 		break;
 	default:
-		ret=-EINVAL;
+		ret = -EINVAL;
 		return ret;
 		break;
 	}
@@ -422,23 +448,24 @@
 int vfc_set_video_ioctl(struct inode *inode, struct file *file, 
 			struct vfc_dev *dev, unsigned long arg) 
 {
-	int ret=0;
+	int ret = 0;
 	int cmd;
+
 	if(copy_from_user(&cmd, (void *)arg, sizeof(unsigned int))) {
 		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to "
-				  "vfc_set_video_ioctl\n",dev->instance));
+					"vfc_set_video_ioctl\n",
+					dev->instance));
 		return ret;
 	}
 	
 	VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%x\n",
-			  dev->instance,cmd));
+				dev->instance, cmd));
 	switch(cmd) {
-
 	case STD_NTSC:
 		VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~VFC_SAA9051_ALT;
 		VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_YPN | 
 			VFC_SAA9051_CCFR0 | VFC_SAA9051_CCFR1 | VFC_SAA9051_FS;
-		ret=vfc_update_saa9051(dev);
+		ret = vfc_update_saa9051(dev);
 		break;
 	case STD_PAL:
 		VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_YPN | 
@@ -446,35 +473,39 @@
 							VFC_SAA9051_CCFR0 |
 							VFC_SAA9051_FS);
 		VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_ALT;
-		ret=vfc_update_saa9051(dev);
+		ret = vfc_update_saa9051(dev);
 		break;
 
 	case COLOR_ON:
 		VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_CO;
-		VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) &= ~(VFC_SAA9051_BY | VFC_SAA9051_PF);
-		ret=vfc_update_saa9051(dev);
+		VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) &=
+			~(VFC_SAA9051_BY | VFC_SAA9051_PF);
+		ret = vfc_update_saa9051(dev);
 		break;
 	case MONO:
 		VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_CO);
-		VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) |= VFC_SAA9051_BY | VFC_SAA9051_PF;
-		ret=vfc_update_saa9051(dev);
+		VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) |=
+			(VFC_SAA9051_BY | VFC_SAA9051_PF);
+		ret = vfc_update_saa9051(dev);
 		break;
 	default:
-		ret=-EINVAL;
+		ret = -EINVAL;
 		break;
-	}
+	};
+
 	return ret;
 }
 
 int vfc_get_video_ioctl(struct inode *inode, struct file *file, 
 			struct vfc_dev *dev, unsigned long arg) 
 {
-	int ret=0;
-	unsigned int status=NO_LOCK;
+	int ret = 0;
+	unsigned int status = NO_LOCK;
 	unsigned char buf[1];
 
-	if(vfc_i2c_recvbuf(dev,VFC_SAA9051_ADDR,buf,1)) {
-		printk(KERN_ERR "vfc%d: Unable to get status\n",dev->instance);
+	if(vfc_i2c_recvbuf(dev, VFC_SAA9051_ADDR, buf, 1)) {
+		printk(KERN_ERR "vfc%d: Unable to get status\n",
+		       dev->instance);
 		return -EIO;
 	}
 
@@ -482,20 +513,22 @@
 		status = NO_LOCK;
 	} else if(buf[0] & VFC_SAA9051_FD) {
 		if(buf[0] & VFC_SAA9051_CD)
-			status=NTSC_COLOR;
+			status = NTSC_COLOR;
 		else
-			status=NTSC_NOCOLOR;
+			status = NTSC_NOCOLOR;
 	} else {
 		if(buf[0] & VFC_SAA9051_CD)
-			status=PAL_COLOR;
+			status = PAL_COLOR;
 		else
-			status=PAL_NOCOLOR;
+			status = PAL_NOCOLOR;
 	}
-	VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; buf[0]=%x\n",dev->instance,
-			  status,buf[0]));
+	VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; "
+				"buf[0]=%x\n", dev->instance, status, buf[0]));
+
 	if (copy_to_user((void *)arg,&status,sizeof(unsigned int))) {
 		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to "
-				 "vfc_get_video_ioctl\n",dev->instance));
+					"vfc_get_video_ioctl\n",
+					dev->instance));
 		return ret;
 	}
 	return ret;
@@ -504,77 +537,81 @@
 static int vfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	      unsigned long arg) 
 {
-	int ret=0;
+	int ret = 0;
 	unsigned int tmp;
 	struct vfc_dev *dev;
 
-	dev=vfc_get_dev_ptr(MINOR(inode->i_rdev));
-	if(!dev) return -ENODEV;
+	dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
+	if(dev == NULL)
+		return -ENODEV;
 	
 	switch(cmd & 0x0000ffff) {
 	case VFCGCTRL:
 #if 0
-		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n",dev->instance));
+		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n", dev->instance));
 #endif
-		tmp=dev->regs->control;
-		if(copy_to_user((void *)arg,&tmp, sizeof(unsigned int))) {
-			ret=-EFAULT;
+		tmp = sbus_readl(&dev->regs->control);
+		if(copy_to_user((void *)arg, &tmp, sizeof(unsigned int))) {
+			ret = -EFAULT;
 			break;
 		}
-		ret=0;
+		ret = 0;
 		break;
 	case VFCSCTRL:
-		ret=vfc_set_control_ioctl(inode, file, dev, arg);
+		ret = vfc_set_control_ioctl(inode, file, dev, arg);
 		break;
 	case VFCGVID:
-		ret=vfc_get_video_ioctl(inode,file,dev,arg);
+		ret = vfc_get_video_ioctl(inode, file, dev, arg);
 		break;
 	case VFCSVID:
-		ret=vfc_set_video_ioctl(inode,file,dev,arg);
+		ret = vfc_set_video_ioctl(inode, file, dev, arg);
 		break;
 	case VFCHUE:
-		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n",dev->instance));
+		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n", dev->instance));
 		if(copy_from_user(&tmp,(void *)arg,sizeof(unsigned int))) {
 			VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer "
-					  "to IOCTL(VFCHUE)",dev->instance));
-			ret=-EFAULT;
+						"to IOCTL(VFCHUE)", dev->instance));
+			ret = -EFAULT;
 		} else {
-			VFC_SAA9051_SA(dev,VFC_SAA9051_HUE)=tmp;
+			VFC_SAA9051_SA(dev,VFC_SAA9051_HUE) = tmp;
 			vfc_update_saa9051(dev);
-			ret=0;
+			ret = 0;
 		}
 		break;
 	case VFCPORTCHG:
-		ret=vfc_port_change_ioctl(inode, file, dev, arg);
+		ret = vfc_port_change_ioctl(inode, file, dev, arg);
 		break;
 	case VFCRDINFO:
-		ret=-EINVAL;
-		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n",dev->instance));
+		ret = -EINVAL;
+		VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n", dev->instance));
 		break;
 	default:
-		ret=vfc_debug(vfc_get_dev_ptr(MINOR(inode->i_rdev)),
-			      cmd,arg);
+		ret = vfc_debug(vfc_get_dev_ptr(MINOR(inode->i_rdev)),
+				cmd, arg);
 		break;
-	}
+	};
+
 	return ret;
 }
 
 static int vfc_mmap(struct inode *inode, struct file *file, 
-	     struct vm_area_struct *vma) 
+		    struct vm_area_struct *vma) 
 {
-	unsigned int map_size,ret,map_offset;
+	unsigned int map_size, ret, map_offset;
 	struct vfc_dev *dev;
 	
-	dev=vfc_get_dev_ptr(MINOR(inode->i_rdev));
-	if(!dev) return -ENODEV;
+	dev = vfc_get_dev_ptr(MINOR(inode->i_rdev));
+	if(dev == NULL)
+		return -ENODEV;
 	
-	map_size=vma->vm_end - vma->vm_start;
+	map_size = vma->vm_end - vma->vm_start;
 	if(map_size > sizeof(struct vfc_regs)) 
-		map_size=sizeof(struct vfc_regs);
+		map_size = sizeof(struct vfc_regs);
 
-	vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO | VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE;
-	map_offset=(unsigned int)dev->phys_regs;
-	ret = io_remap_page_range(vma->vm_start,map_offset,map_size, 
+	vma->vm_flags |=
+		(VM_SHM | VM_LOCKED | VM_IO | VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE);
+	map_offset = (unsigned int) (long)dev->phys_regs;
+	ret = io_remap_page_range(vma->vm_start, map_offset, map_size, 
 				  vma->vm_page_prot, dev->which_io);
 	if(ret)
 		return -EAGAIN;
@@ -584,13 +621,13 @@
 
 
 static int vfc_lseek(struct inode *inode, struct file *file, 
-	      off_t offset, int origin) 
+		     off_t offset, int origin) 
 {
 	return -ESPIPE;
 }
 
 static struct file_operations vfc_fops = {
-	vfc_lseek,        /* vfc_lseek */
+	vfc_lseek,   /* vfc_lseek */
 	NULL,        /* vfc_write */
 	NULL,        /* vfc_read */
 	NULL,        /* vfc_readdir */
@@ -598,19 +635,19 @@
 	vfc_ioctl,   
 	vfc_mmap, 
 	vfc_open,
-	NULL,		/* flush */
+	NULL,	     /* flush */
 	vfc_release,
 };
 
 static int vfc_probe(void)
 {
-	struct linux_sbus *bus;
-	struct linux_sbus_device *sdev = NULL;
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev = NULL;
 	int ret;
-	int instance=0,cards=0;
+	int instance = 0, cards = 0;
 
-	for_all_sbusdev(sdev,bus) {
-		if (strcmp(sdev->prom_name,"vfc") == 0) {
+	for_all_sbusdev(sdev, sbus) {
+		if (strcmp(sdev->prom_name, "vfc") == 0) {
 			cards++;
 			continue;
 		}
@@ -619,33 +656,35 @@
 	if (!cards)
 		return -ENODEV;
 
-	vfc_dev_lst=(struct vfc_dev **)kmalloc(sizeof(struct vfc_dev *)*
-					       (cards+1),
-					       GFP_KERNEL);
-	if(!vfc_dev_lst)
+	vfc_dev_lst = (struct vfc_dev **)kmalloc(sizeof(struct vfc_dev *) *
+						 (cards+1),
+						 GFP_KERNEL);
+	if (vfc_dev_lst == NULL)
 		return -ENOMEM;
-	memset(vfc_dev_lst,0,sizeof(struct vfc_dev *)*(cards+1));
-	vfc_dev_lst[cards]=NULL;
+	memset(vfc_dev_lst, 0, sizeof(struct vfc_dev *) * (cards + 1));
+	vfc_dev_lst[cards] = NULL;
 
-	ret=register_chrdev(VFC_MAJOR,vfcstr,&vfc_fops);
+	ret = register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops);
 	if(ret) {
-		printk(KERN_ERR "Unable to get major number %d\n",VFC_MAJOR);
+		printk(KERN_ERR "Unable to get major number %d\n", VFC_MAJOR);
 		kfree(vfc_dev_lst);
 		return -EIO;
 	}
 
-	instance=0;
-	for_all_sbusdev(sdev,bus) {
-		if (strcmp(sdev->prom_name,"vfc") == 0) {
+	instance = 0;
+	for_all_sbusdev(sdev, sbus) {
+		if (strcmp(sdev->prom_name, "vfc") == 0) {
 			vfc_dev_lst[instance]=(struct vfc_dev *)
 				kmalloc(sizeof(struct vfc_dev), GFP_KERNEL);
-			if(vfc_dev_lst[instance] == NULL) return -ENOMEM;
-			ret=init_vfc_device(sdev,
-					    vfc_dev_lst[instance],
-					    instance);
+			if (vfc_dev_lst[instance] == NULL)
+				return -ENOMEM;
+			ret = init_vfc_device(sdev,
+					      vfc_dev_lst[instance],
+					      instance);
 			if(ret) {
 				printk(KERN_ERR "Unable to initialize"
-				       " vfc%d device\n",instance);
+				       " vfc%d device\n",
+				       instance);
 			} else {
 			}
 		
@@ -669,18 +708,21 @@
 #ifdef MODULE
 static void deinit_vfc_device(struct vfc_dev *dev)
 {
-	if(!dev) return;
-	sparc_free_io((void *)dev->regs,sizeof(struct vfc_regs));
+	if(dev == NULL)
+		return;
+	sbus_iounmap((unsigned long)dev->regs, sizeof(struct vfc_regs));
 	kfree(dev);
 }
 
 void cleanup_module(void)
 {
 	struct vfc_dev **devp;
+
 	unregister_chrdev(VFC_MAJOR,vfcstr);
-	for(devp=vfc_dev_lst;*devp;devp++) {
+
+	for (devp = vfc_dev_lst; *devp; devp++)
 		deinit_vfc_device(*devp);
-	}
+
 	kfree(vfc_dev_lst);
 	return;
 }
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/vfc_i2c.c linux/drivers/sbus/char/vfc_i2c.c
--- v2.3.34/linux/drivers/sbus/char/vfc_i2c.c	Thu Jan  7 09:21:53 1999
+++ linux/drivers/sbus/char/vfc_i2c.c	Mon Dec 20 22:06:42 1999
@@ -38,6 +38,11 @@
 #include "vfc.h"
 #include "vfc_i2c.h"
 
+#define WRITE_S1(__val) \
+	sbus_writel(__val, &dev->regs->i2c_s1)
+#define WRITE_REG(__val) \
+	sbus_writel(__val, &dev->regs->i2c_reg)
+
 #define VFC_I2C_READ (0x1)
 #define VFC_I2C_WRITE (0x0)
      
@@ -52,20 +57,24 @@
 
 int vfc_pcf8584_init(struct vfc_dev *dev) 
 {
-	dev->regs->i2c_s1=RESET;        /* This will also choose
-					   register S0_OWN so we can set it*/
+	/* This will also choose register S0_OWN so we can set it. */
+	WRITE_S1(RESET);
 
-	dev->regs->i2c_reg=0x55000000;  /* the pcf8584 shifts this
-					   value left one bit and uses
-					   it as its i2c bus address */
-	dev->regs->i2c_s1=SELECT(S2);
-	dev->regs->i2c_reg=0x14000000;  /* this will set the i2c bus at
-					   the same speed sun uses,
-					   and set another magic bit */
+	/* The pcf8584 shifts this value left one bit and uses
+	 * it as its i2c bus address.
+	 */
+	WRITE_REG(0x55000000);
+
+	/* This will set the i2c bus at the same speed sun uses,
+	 * and set another magic bit.
+	 */
+	WRITE_S1(SELECT(S2));
+	WRITE_REG(0x14000000);
 	
-	dev->regs->i2c_s1=CLEAR_I2C_BUS;   /* enable the serial port,
-					   idle the i2c bus and set
-					   the data reg to s0 */
+	/* Enable the serial port, idle the i2c bus and set
+	 * the data reg to s0.
+	 */
+	WRITE_S1(CLEAR_I2C_BUS);
 	udelay(100);
 	return 0;
 }
@@ -73,11 +82,11 @@
 void vfc_i2c_delay_wakeup(struct vfc_dev *dev) 
 {
 	/* Used to profile code and eliminate too many delays */
-	VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n",dev->instance));
+	VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n", dev->instance));
 	wake_up(&dev->poll_wait);
 }
 
-void vfc_i2c_delay_no_busy(struct vfc_dev *dev,unsigned long usecs) 
+void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) 
 {
 	dev->poll_timer.next = NULL;
 	dev->poll_timer.prev = NULL;
@@ -92,12 +101,12 @@
 
 void inline vfc_i2c_delay(struct vfc_dev *dev) 
 { 
-	vfc_i2c_delay_no_busy(dev,100);
+	vfc_i2c_delay_no_busy(dev, 100);
 }
 
 int vfc_init_i2c_bus(struct vfc_dev *dev)
 {
-	dev->regs->i2c_s1= ENABLE_SERIAL | SELECT(S0) | ACK;
+	WRITE_S1(ENABLE_SERIAL | SELECT(S0) | ACK);
 	vfc_i2c_reset_bus(dev);
 	return 0;
 }
@@ -105,24 +114,28 @@
 int vfc_i2c_reset_bus(struct vfc_dev *dev) 
 {
 	VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n",
-			  dev->instance));
-	if(!dev) return -EINVAL;
-	if(!dev->regs) return -EINVAL;
-	dev->regs->i2c_s1=SEND_I2C_STOP;
-	dev->regs->i2c_s1=SEND_I2C_STOP | ACK;
+			      dev->instance));
+	if(dev == NULl)
+		return -EINVAL;
+	if(dev->regs == NULL)
+		return -EINVAL;
+	WRITE_S1(SEND_I2C_STOP);
+	WRITE_S1(SEND_I2C_STOP | ACK);
 	vfc_i2c_delay(dev);
-	dev->regs->i2c_s1=CLEAR_I2C_BUS;
+	WRITE_S1(CLEAR_I2C_BUS);
 	VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n",
-			  dev->instance, dev->regs->i2c_s1));
+			      dev->instance,
+			      sbus_readl(&dev->regs->i2c_s1)));
 	return 0;
 }
 
 int vfc_i2c_wait_for_bus(struct vfc_dev *dev) 
 {
-	int timeout=1000; 
+	int timeout = 1000; 
 
-	while(!(dev->regs->i2c_s1 & BB)) {
-		if(!(timeout--)) return -ETIMEDOUT;
+	while(!(sbus_readl(&dev->regs->i2c_s1) & BB)) {
+		if(!(timeout--))
+			return -ETIMEDOUT;
 		vfc_i2c_delay(dev);
 	}
 	return 0;
@@ -130,15 +143,17 @@
 
 int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack)
 {
-	int timeout=1000; 
+	int timeout = 1000; 
 	int s1;
 
-	while((s1=dev->regs->i2c_s1) & PIN) {
-		if(!(timeout--)) return -ETIMEDOUT;
+	while ((s1 = sbus_readl(&dev->regs->i2c_s1)) & PIN) {
+		if (!(timeout--))
+			return -ETIMEDOUT;
 		vfc_i2c_delay(dev);
 	}
-	if(ack==VFC_I2C_ACK_CHECK) {
-		if(s1 & LRB) return -EIO; 
+	if (ack == VFC_I2C_ACK_CHECK) {
+		if(s1 & LRB)
+			return -EIO; 
 	}
 	return 0;
 }
@@ -146,47 +161,50 @@
 #define SHIFT(a) ((a) << 24)
 int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, char mode) 
 { 
-	int ret,raddr;
+	int ret, raddr;
 #if 1
-	dev->regs->i2c_s1=SEND_I2C_STOP | ACK;
-	dev->regs->i2c_s1=SELECT(S0) | ENABLE_SERIAL;
+	WRITE_S1(SEND_I2C_STOP | ACK);
+	WRITE_S1(SELECT(S0) | ENABLE_SERIAL);
 	vfc_i2c_delay(dev);
 #endif
 
 	switch(mode) {
 	case VFC_I2C_READ:
-		dev->regs->i2c_reg=raddr=SHIFT((unsigned int)addr | 0x1);
+		raddr = SHIFT(((unsigned int)addr | 0x1));
+		WRITE_REG(raddr);
 		VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n",
-				  dev->instance,addr | 0x1));
+				      dev->instance, addr | 0x1));
 		break;
 	case VFC_I2C_WRITE:
-		dev->regs->i2c_reg=raddr=SHIFT((unsigned int)addr & ~0x1);
+		raddr = SHIFT((unsigned int)addr & ~0x1);
+		WRITE_REG(raddr);
 		VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n",
-				  dev->instance,addr & ~0x1));
+				      dev->instance, addr & ~0x1));
 		break;
 	default:
 		return -EINVAL;
-	}
-	dev->regs->i2c_s1 = SEND_I2C_START;
+	};
+
+	WRITE_S1(SEND_I2C_START);
 	vfc_i2c_delay(dev);
-	ret=vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait
-							    for the
-							    i2c send
-							    to finish
-							    here but
-							    Sun
-							    doesn't,
-							    hmm */
-	if(ret) {
+	ret = vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait
+							      for the
+							      i2c send
+							      to finish
+							      here but
+							      Sun
+							      doesn't,
+							      hmm */
+	if (ret) {
 		printk(KERN_ERR "vfc%d: VFC xmit addr timed out or no ack\n",
 		       dev->instance);
 		return ret;
-	} else if(mode == VFC_I2C_READ) {
-		if((ret=dev->regs->i2c_reg & 0xff000000) != raddr) {
+	} else if (mode == VFC_I2C_READ) {
+		if ((ret = sbus_readl(&dev->regs->i2c_reg) & 0xff000000) != raddr) {
 			printk(KERN_WARNING 
 			       "vfc%d: returned slave address "
 			       "mismatch(%x,%x)\n",
-			       dev->instance,raddr,ret);
+			       dev->instance, raddr, ret);
 		}
 	}	
 	return 0;
@@ -195,75 +213,81 @@
 int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte) 
 {
 	int ret;
-	dev->regs->i2c_reg=SHIFT((unsigned int)*byte);
+	u32 val = SHIFT((unsigned int)*byte);
+
+	WRITE_REG(val);
 
-	ret=vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); 
+	ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_ACK_CHECK); 
 	switch(ret) {
 	case -ETIMEDOUT: 
 		printk(KERN_ERR "vfc%d: VFC xmit byte timed out or no ack\n",
 		       dev->instance);
 		break;
 	case -EIO:
-		ret=XMIT_LAST_BYTE;
+		ret = XMIT_LAST_BYTE;
 		break;
 	default:
 		break;
-	}
+	};
+
 	return ret;
 }
 
 int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte, int last) 
 {
 	int ret;
-	if(last) {
-		dev->regs->i2c_reg=NEGATIVE_ACK;
+
+	if (last) {
+		WRITE_REG(NEGATIVE_ACK);
 		VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n",
-				  dev->instance));
+				      dev->instance));
 	} else {
-		dev->regs->i2c_s1=ACK;
+		WRITE_S1(ACK);
 	}
 
-	ret=vfc_i2c_wait_for_pin(dev,VFC_I2C_NO_ACK_CHECK);
+	ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_NO_ACK_CHECK);
 	if(ret) {
 		printk(KERN_ERR "vfc%d: "
-		       "VFC recv byte timed out\n",dev->instance);
+		       "VFC recv byte timed out\n",
+		       dev->instance);
 	}
-	*byte=(dev->regs->i2c_reg) >> 24;
+	*byte = (sbus_readl(&dev->regs->i2c_reg)) >> 24;
 	return ret;
 }
 
 int vfc_i2c_recvbuf(struct vfc_dev *dev, unsigned char addr,
 		    char *buf, int count)
 {
-	int ret,last;
+	int ret, last;
 
-	if(!(count && buf && dev && dev->regs) ) return -EINVAL;
+	if(!(count && buf && dev && dev->regs) )
+		return -EINVAL;
 
-	if((ret=vfc_i2c_wait_for_bus(dev))) {
-		printk(KERN_ERR "vfc%d: VFC I2C bus busy\n",dev->instance);
+	if ((ret = vfc_i2c_wait_for_bus(dev))) {
+		printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance);
 		return ret;
 	}
 
-	if((ret=vfc_i2c_xmit_addr(dev,addr,VFC_I2C_READ))) {
-		dev->regs->i2c_s1=SEND_I2C_STOP;
+	if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_READ))) {
+		WRITE_S1(SEND_I2C_STOP);
 		vfc_i2c_delay(dev);
 		return ret;
 	}
 	
-	last=0;
-	while(count--) {
-		if(!count) last=1;
-		if((ret=vfc_i2c_recv_byte(dev,buf,last))) {
+	last = 0;
+	while (count--) {
+		if (!count)
+			last = 1;
+		if ((ret = vfc_i2c_recv_byte(dev, buf, last))) {
 			printk(KERN_ERR "vfc%d: "
 			       "VFC error while receiving byte\n",
 			       dev->instance);
-			dev->regs->i2c_s1=SEND_I2C_STOP;
-			ret=-EINVAL;
+			WRITE_S1(SEND_I2C_STOP);
+			ret = -EINVAL;
 		}
 		buf++;
 	}
-	
-	dev->regs->i2c_s1=SEND_I2C_STOP | ACK;
+	WRITE_S1(SEND_I2C_STOP | ACK);
 	vfc_i2c_delay(dev);
 	return ret;
 }
@@ -273,42 +297,43 @@
 {
 	int ret;
 	
-	if(!(buf && dev && dev->regs) ) return -EINVAL;
+	if (!(buf && dev && dev->regs))
+		return -EINVAL;
 	
-	if((ret=vfc_i2c_wait_for_bus(dev))) {
-		printk(KERN_ERR "vfc%d: VFC I2C bus busy\n",dev->instance);
+	if ((ret = vfc_i2c_wait_for_bus(dev))) {
+		printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance);
 		return ret;
 	}
 	
-	if((ret=vfc_i2c_xmit_addr(dev,addr,VFC_I2C_WRITE))) {
-		dev->regs->i2c_s1=SEND_I2C_STOP;
+	if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_WRITE))) {
+		WRITE_S1(SEND_I2C_STOP);
 		vfc_i2c_delay(dev);
 		return ret;
 	}
 	
 	while(count--) {
-		ret=vfc_i2c_xmit_byte(dev,buf);
+		ret = vfc_i2c_xmit_byte(dev, buf);
 		switch(ret) {
 		case XMIT_LAST_BYTE:
 			VFC_I2C_DEBUG_PRINTK(("vfc%d: "
-					  "Reciever ended transmission with "
-					  " %d bytes remaining\n",
-					  dev->instance,count));
-			ret=0;
+					      "Reciever ended transmission with "
+					      " %d bytes remaining\n",
+					      dev->instance, count));
+			ret = 0;
 			goto done;
 			break;
 		case 0:
 			break;
 		default:
 			printk(KERN_ERR "vfc%d: "
-			       "VFC error while sending byte\n",dev->instance);
+			       "VFC error while sending byte\n", dev->instance);
 			break;
-		}
+		};
+
 		buf++;
 	}
 done:
-	dev->regs->i2c_s1=SEND_I2C_STOP | ACK;
-	
+	WRITE_S1(SEND_I2C_STOP | ACK);
 	vfc_i2c_delay(dev);
 	return ret;
 }
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c
--- v2.3.34/linux/drivers/sbus/char/zs.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/sbus/char/zs.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.45 1999/09/01 08:09:35 davem Exp $
+/* $Id: zs.c,v 1.52 1999/12/15 14:29:20 davem Exp $
  * zs.c: Zilog serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -23,6 +23,7 @@
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 #include <linux/sysrq.h>
 
 #include <asm/io.h>
@@ -32,6 +33,8 @@
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/kdebug.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
 
 #include <asm/sbus.h>
 #ifdef __sparc_v9__
@@ -65,8 +68,8 @@
 #else
 #define ZSDELAY()
 #define ZSDELAY_LONG()
-#define ZS_WSYNC(channel) \
-	((void) *((volatile unsigned char *)(&((channel)->control))))
+#define ZS_WSYNC(__channel) \
+	sbus_readb(&((__channel)->control))
 #endif
 
 struct sun_zslayout **zs_chips;
@@ -164,6 +167,47 @@
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 #endif
 
+#undef ZS_LOG
+#ifdef ZS_LOG
+struct zs_logent {
+	u8 reg, val;
+	u8 write, __pad;
+#define REGIRQ	0xff
+#define REGDATA	0xfe
+#define REGCTRL	0xfd
+};
+struct zs_logent zslog[32];
+int zs_curlog = 0;
+#define ZSLOG(__reg, __val, __write) \
+do{	int index = zs_curlog; \
+	zslog[index].reg = (__reg); \
+	zslog[index].val = (__val); \
+	zslog[index].write = (__write); \
+	zs_curlog = (index + 1) & (32 - 1); \
+}while(0)
+int zs_dumplog(char *buffer)
+{
+	int len = 0;
+	int i;
+
+	for (i = 0; i < 32; i++) {
+		u8 reg, val, write;
+
+		reg = zslog[i].reg;
+		val = zslog[i].val;
+		write = zslog[i].write;
+		len += sprintf(buffer + len,
+			       "ZSLOG[%2d]: reg %2x val %2x %s\n",
+			       i, reg, val, write ? "write" : "read");
+	}
+	len += sprintf(buffer + len, "ZS current log index %d\n",
+		       zs_curlog);
+	return len;
+}
+#else
+#define ZSLOG(x,y,z)	do { } while (0)
+#endif
+
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
  * lock it in case the memcpy_fromfs blocks while swapping in a page,
@@ -197,15 +241,13 @@
 	return 0;
 }
 
-/*
- * This is used to figure out the divisor speeds and the timeouts
- */
+/* This is used to figure out the divisor speeds and the timeouts. */
 static int baud_table[] = {
 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 76800, 0 };
+	9600, 19200, 38400, 76800, 0
+};
 
-/* 
- * Reading and writing Zilog8530 registers.  The delays are to make this
+/* Reading and writing Zilog8530 registers.  The delays are to make this
  * driver work on the Sun4 which needs a settling delay after each chip
  * register access, other machines handle this in hardware via auxiliary
  * flip-flops which implement the settle time we do in software.
@@ -215,26 +257,28 @@
 {
 	unsigned char retval;
 
-	channel->control = reg;
+	sbus_writeb(reg, &channel->control);
 	ZSDELAY();
-	retval = channel->control;
+	retval = sbus_readb(&channel->control);
 	ZSDELAY();
+	ZSLOG(reg, retval, 0);
 	return retval;
 }
 
 static inline void write_zsreg(struct sun_zschannel *channel,
 			       unsigned char reg, unsigned char value)
 {
-	channel->control = reg;
+	ZSLOG(reg, value, 1);
+	sbus_writeb(reg, &channel->control);
 	ZSDELAY();
-	channel->control = value;
+	sbus_writeb(value, &channel->control);
 	ZSDELAY();
 }
 
 static inline void load_zsregs(struct sun_serial *info, unsigned char *regs)
 {
-	unsigned long flags;
 	struct sun_zschannel *channel = info->zs_channel;
+	unsigned long flags;
 	unsigned char stat;
 	int i;
 
@@ -287,12 +331,18 @@
 	 * a timed polling loop and on sparc64 ZSDELAY
 	 * is a nop.  -DaveM
 	 */
-	while((channel->control & Tx_BUF_EMP) == 0 && --loops)
+	do {
+		u8 val = sbus_readb(&channel->control);
+		ZSLOG(REGCTRL, val, 0);
+		if (val & Tx_BUF_EMP)
+			break;
 		udelay(5);
+	} while (--loops);
 
-	channel->data = ch;
+	sbus_writeb(ch, &channel->data);
 	ZSDELAY();
 	ZS_WSYNC(channel);
+	ZSLOG(REGDATA, ch, 1);
 }
 
 /* Sets or clears DTR/RTS on the requested line */
@@ -339,7 +389,7 @@
  */
 static void zs_stop(struct tty_struct *tty)
 {
-	struct sun_serial *info = (struct sun_serial *)tty->driver_data;
+	struct sun_serial *info = (struct sun_serial *) tty->driver_data;
 	unsigned long flags;
 
 	if (serial_paranoia_check(info, tty->device, "zs_stop"))
@@ -355,7 +405,7 @@
 
 static void zs_start(struct tty_struct *tty)
 {
-	struct sun_serial *info = (struct sun_serial *)tty->driver_data;
+	struct sun_serial *info = (struct sun_serial *) tty->driver_data;
 	unsigned long flags;
 	
 	if (serial_paranoia_check(info, tty->device, "zs_start"))
@@ -374,6 +424,8 @@
  */
 void batten_down_hatches(void)
 {
+	if (!stop_a_enabled)
+		return;
 	/* If we are doing kadb, we call the debugger
 	 * else we just drop into the boot monitor.
 	 * Note that we must flush the user windows
@@ -424,7 +476,7 @@
  * processing in the software interrupt portion of the driver.
  */
 static _INLINE_ void zs_sched_event(struct sun_serial *info,
-				  int event)
+				    int event)
 {
 	info->event |= 1 << event;
 	queue_task(&info->tqueue, &tq_serial);
@@ -439,9 +491,12 @@
 {
 	struct tty_struct *tty = info->tty;
 	unsigned char ch, stat;
+	int do_queue_task = 1;
 
 	do {
-		ch = (info->zs_channel->data) & info->parity_mask;
+		ch = sbus_readb(&info->zs_channel->data);
+		ZSLOG(REGDATA, ch, 0);
+		ch &= info->parity_mask;
 		ZSDELAY();
 
 		/* If this is the console keyboard, we need to handle
@@ -466,14 +521,16 @@
 				return;
 			}
 			sunkbd_inchar(ch, regs);
-			return;
+			do_queue_task = 0;
+			goto next_char;
 		}
 		if(info->cons_mouse) {
-			sun_mouse_inbyte(ch);
-			return;
+			sun_mouse_inbyte(ch, 0);
+			do_queue_task = 0;
+			goto next_char;
 		}
 		if(info->is_cons) {
-			if(ch==0) {
+			if(ch == 0) {
 				/* whee, break received */
 				batten_down_hatches();
 				/* Continue execution... */
@@ -502,9 +559,11 @@
 		*tty->flip.flag_buf_ptr++ = 0;
 		*tty->flip.char_buf_ptr++ = ch;
 
+	next_char:
 		/* Check if we have another character... */
-		stat = info->zs_channel->control;
+		stat = sbus_readb(&info->zs_channel->control);
 		ZSDELAY();
+		ZSLOG(REGCTRL, stat, 0);
 		if (!(stat & Rx_CH_AV))
 			break;
 
@@ -512,7 +571,8 @@
 		stat = read_zsreg(info->zs_channel, R1);
 	} while (!(stat & (PAR_ERR | Rx_OVR | CRC_ERR)));
 
-	queue_task(&tty->flip.tqueue, &tq_timer);
+	if (do_queue_task != 0)
+		queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
 static _INLINE_ void transmit_chars(struct sun_serial *info)
@@ -528,9 +588,10 @@
 
 	if((info->xmit_cnt <= 0) || (tty != 0 && tty->stopped)) {
 		/* That's peculiar... */
-		info->zs_channel->control = RES_Tx_P;
+		sbus_writeb(RES_Tx_P, &info->zs_channel->control);
 		ZSDELAY();
 		ZS_WSYNC(info->zs_channel);
+		ZSLOG(REGCTRL, RES_Tx_P, 1);
 		return;
 	}
 
@@ -543,9 +604,10 @@
 		zs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
 
 	if(info->xmit_cnt <= 0) {
-		info->zs_channel->control = RES_Tx_P;
+		sbus_writeb(RES_Tx_P, &info->zs_channel->control);
 		ZSDELAY();
 		ZS_WSYNC(info->zs_channel);
+		ZSLOG(REGCTRL, RES_Tx_P, 1);
 	}
 }
 
@@ -554,13 +616,14 @@
 	unsigned char status;
 
 	/* Get status from Read Register 0 */
-	status = info->zs_channel->control;
+	status = sbus_readb(&info->zs_channel->control);
 	ZSDELAY();
+	ZSLOG(REGCTRL, status, 0);
 	/* Clear status condition... */
-	info->zs_channel->control = RES_EXT_INT;
+	sbus_writeb(RES_EXT_INT, &info->zs_channel->control);
 	ZSDELAY();
 	ZS_WSYNC(info->zs_channel);
-
+	ZSLOG(REGCTRL, RES_EXT_INT, 1);
 #if 0
 	if(status & DCD) {
 		if((info->tty->termios->c_cflag & CRTSCTS) &&
@@ -579,8 +642,12 @@
 	 * 'break asserted' status change interrupt, call
 	 * the boot prom.
 	 */
-	if((status & BRK_ABRT) && info->break_abort)
-		batten_down_hatches();
+	if(status & BRK_ABRT) {
+		if (info->break_abort)
+			batten_down_hatches();
+		if (info->cons_mouse)
+			sun_mouse_inbyte(0, 1);
+	}
 
 	/* XXX Whee, put in a buffer somewhere, the status information
 	 * XXX whee whee whee... Where does the information go...
@@ -595,8 +662,9 @@
 
 	stat = read_zsreg(info->zs_channel, R1);
 	if (stat & (PAR_ERR | Rx_OVR | CRC_ERR)) {
-		ch = info->zs_channel->data;
+		ch = sbus_readb(&info->zs_channel->data);
 		ZSDELAY();
+		ZSLOG(REGDATA, ch, 0);
 	}
 
 	if (!tty)
@@ -616,9 +684,10 @@
 done:
 	queue_task(&tty->flip.tqueue, &tq_timer);
 clear:
-	info->zs_channel->control = ERR_RES;
+	sbus_writeb(ERR_RES, &info->zs_channel->control);
 	ZSDELAY();
 	ZS_WSYNC(info->zs_channel);
+	ZSLOG(REGCTRL, ERR_RES, 1);
 }
 
 
@@ -632,6 +701,7 @@
 	int i;
 
 	info = (struct sun_serial *)dev_id;
+	ZSLOG(REGIRQ, 0, 0);
 	for (i = 0; i < NUM_SERIAL; i++) {
 		zs_intreg = read_zsreg(info->zs_next->zs_channel, 2);
 		zs_intreg &= STATUS_MASK;
@@ -797,13 +867,15 @@
 	/*
 	 * Clear the interrupt registers.
 	 */
-	info->zs_channel->control = ERR_RES;
+	sbus_writeb(ERR_RES, &info->zs_channel->control);
 	ZSDELAY();
 	ZS_WSYNC(info->zs_channel);
+	ZSLOG(REGCTRL, ERR_RES, 1);
 
-	info->zs_channel->control = RES_H_IUS;
+	sbus_writeb(RES_H_IUS, &info->zs_channel->control);
 	ZSDELAY();
 	ZS_WSYNC(info->zs_channel);
+	ZSLOG(REGCTRL, RES_H_IUS, 1);
 
 	/*
 	 * Now, initialize the Zilog
@@ -826,13 +898,15 @@
 	/*
 	 * And clear the interrupt registers again for luck.
 	 */
-	info->zs_channel->control = ERR_RES;
+	sbus_writeb(ERR_RES, &info->zs_channel->control);
 	ZSDELAY();
 	ZS_WSYNC(info->zs_channel);
+	ZSLOG(REGCTRL, ERR_RES, 1);
 
-	info->zs_channel->control = RES_H_IUS;
+	sbus_writeb(RES_H_IUS, &info->zs_channel->control);
 	ZSDELAY();
 	ZS_WSYNC(info->zs_channel);
+	ZSLOG(REGCTRL, RES_H_IUS, 1);
 
 	if (info->tty)
 		clear_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -1035,24 +1109,32 @@
 {
 	struct sun_zschannel *chan = zs_kgdbchan;
 
-	while((chan->control & Tx_BUF_EMP)==0)
+	while((sbus_readb(&chan->control) & Tx_BUF_EMP)==0)
 		udelay(5);
-	chan->data = kgdb_char;
+	sbus_writeb(kgdb_char, &chan->data);
 	ZS_WSYNC(chan);
+	ZSLOG(REGDATA, kgdb_char, 1);
 }
 
 char getDebugChar(void)
 {
 	struct sun_zschannel *chan = zs_kgdbchan;
+	u8 val;
 
-	while((chan->control & Rx_CH_AV)==0)
+	do {
+		val = sbus_readb(&chan->control);
+		ZSLOG(REGCTRL, val, 0);
 		udelay(5);
-	return chan->data;
+	} while ((val & Rx_CH_AV) == 0);
+
+	val = sbus_readb(&chan->data);
+	ZSLOG(REGDATA, val, 0);
+	return val;
 }
 
 static void zs_flush_chars(struct tty_struct *tty)
 {
-	struct sun_serial *info = (struct sun_serial *)tty->driver_data;
+	struct sun_serial *info = (struct sun_serial *) tty->driver_data;
 	unsigned long flags;
 
 	if (serial_paranoia_check(info, tty->device, "zs_flush_chars"))
@@ -1087,9 +1169,9 @@
 static int zs_write(struct tty_struct * tty, int from_user,
 		    const unsigned char *buf, int count)
 {
-	int	c, total = 0;
-	struct sun_serial *info = (struct sun_serial *)tty->driver_data;
+	struct sun_serial *info = (struct sun_serial *) tty->driver_data;
 	unsigned long flags;
+	int c, total = 0;
 
 	if (serial_paranoia_check(info, tty->device, "zs_write"))
 		return 0;
@@ -1143,8 +1225,8 @@
 
 static int zs_write_room(struct tty_struct *tty)
 {
-	struct sun_serial *info = (struct sun_serial *)tty->driver_data;
-	int	ret;
+	struct sun_serial *info = (struct sun_serial *) tty->driver_data;
+	int ret;
 
 	if (serial_paranoia_check(info, tty->device, "zs_write_room"))
 		return 0;
@@ -1156,7 +1238,7 @@
 
 static int zs_chars_in_buffer(struct tty_struct *tty)
 {
-	struct sun_serial *info = (struct sun_serial *)tty->driver_data;
+	struct sun_serial *info = (struct sun_serial *) tty->driver_data;
 
 	if (serial_paranoia_check(info, tty->device, "zs_chars_in_buffer"))
 		return 0;
@@ -1165,7 +1247,7 @@
 
 static void zs_flush_buffer(struct tty_struct *tty)
 {
-	struct sun_serial *info = (struct sun_serial *)tty->driver_data;
+	struct sun_serial *info = (struct sun_serial *) tty->driver_data;
 
 	if (serial_paranoia_check(info, tty->device, "zs_flush_buffer"))
 		return;
@@ -1188,7 +1270,7 @@
  */
 static void zs_throttle(struct tty_struct * tty)
 {
-	struct sun_serial *info = (struct sun_serial *)tty->driver_data;
+	struct sun_serial *info = (struct sun_serial *) tty->driver_data;
 #ifdef SERIAL_DEBUG_THROTTLE
 	char	buf[64];
 	
@@ -1211,7 +1293,7 @@
 
 static void zs_unthrottle(struct tty_struct * tty)
 {
-	struct sun_serial *info = (struct sun_serial *)tty->driver_data;
+	struct sun_serial *info = (struct sun_serial *) tty->driver_data;
 #ifdef SERIAL_DEBUG_THROTTLE
 	char	buf[64];
 	
@@ -1268,7 +1350,7 @@
 {
 	struct serial_struct new_serial;
 	struct sun_serial old_info;
-	int 			retval = 0;
+	int retval = 0;
 
 	if (!new_info || copy_from_user(&new_serial,new_info,sizeof(new_serial)))
 		return -EFAULT;
@@ -1326,10 +1408,11 @@
 	unsigned char status;
 
 	cli();
-	status = info->zs_channel->control;
+	status = sbus_readb(&info->zs_channel->control);
 	ZSDELAY();
+	ZSLOG(REGCTRL, status, 0);
 	sti();
-	put_user_ret(status,value, -EFAULT);
+	put_user_ret(status, value, -EFAULT);
 	return 0;
 }
 
@@ -1339,8 +1422,9 @@
 	unsigned int result;
 
 	cli();
-	status = info->zs_channel->control;
+	status = sbus_readb(&info->zs_channel->control);
 	ZSDELAY();
+	ZSLOG(REGCTRL, status, 0);
 	sti();
 	result =  ((info->curregs[5] & RTS) ? TIOCM_RTS : 0)
 		| ((info->curregs[5] & DTR) ? TIOCM_DTR : 0)
@@ -1402,7 +1486,7 @@
 static int zs_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 {
-	struct sun_serial * info = (struct sun_serial *)tty->driver_data;
+	struct sun_serial * info = (struct sun_serial *) tty->driver_data;
 	int retval;
 
 	if (serial_paranoia_check(info, tty->device, "zs_ioctl"))
@@ -1469,7 +1553,7 @@
 
 static void zs_set_termios(struct tty_struct *tty, struct termios *old_termios)
 {
-	struct sun_serial *info = (struct sun_serial *)tty->driver_data;
+	struct sun_serial *info = (struct sun_serial *) tty->driver_data;
 
 	if (tty->termios->c_cflag == old_termios->c_cflag)
 		return;
@@ -1495,7 +1579,7 @@
  */
 static void zs_close(struct tty_struct *tty, struct file * filp)
 {
-	struct sun_serial * info = (struct sun_serial *)tty->driver_data;
+	struct sun_serial * info = (struct sun_serial *) tty->driver_data;
 	unsigned long flags;
 
 	if (!info || serial_paranoia_check(info, tty->device, "zs_close"))
@@ -1598,7 +1682,7 @@
  */
 void zs_hangup(struct tty_struct *tty)
 {
-	struct sun_serial * info = (struct sun_serial *)tty->driver_data;
+	struct sun_serial * info = (struct sun_serial *) tty->driver_data;
 
 	if (serial_paranoia_check(info, tty->device, "zs_hangup"))
 		return;
@@ -1629,9 +1713,8 @@
 			   struct sun_serial *info)
 {
 	DECLARE_WAITQUEUE(wait, current);
-	int		retval;
-	int		do_clocal = 0;
-	unsigned char	r0;
+	int retval, do_clocal = 0;
+	unsigned char r0;
 
 	/*
 	 * If the device is in the middle of being closed, then block
@@ -1769,10 +1852,11 @@
  */
 int zs_open(struct tty_struct *tty, struct file * filp)
 {
-	struct sun_serial	*info;
-	int 			retval, line;
+	struct sun_serial *info;
+	int retval, line;
 
 	line = MINOR(tty->device) - tty->driver.minor_start;
+
 	/* The zilog lines for the mouse/keyboard must be
 	 * opened using their respective drivers.
 	 */
@@ -1844,7 +1928,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.45 $";
+	char *revision = "$Revision: 1.52 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -1869,16 +1953,19 @@
 	int busnode, seen, zsnode, sun4u_ino;
 	static int irq = 0;
 
-	if(chip < 0 || chip >= NUM_SERIAL)
-		panic("get_zs bogon zs chip number");
+	if(chip < 0 || chip >= NUM_SERIAL) {
+		prom_printf("get_zs bogon zs chip number");
+		prom_halt();
+	}
 
 	if(central_bus)
 		busnode = central_bus->child->prom_node;
 	else
 		busnode = prom_searchsiblings(prom_getchild(prom_root_node), "sbus");
-	if(busnode == 0 || busnode == -1)
-		panic("get_zs: no zs bus to search");
-
+	if(busnode == 0 || busnode == -1) {
+		prom_printf("get_zs: no zs bus to search");
+		prom_halt();
+	}
 	zsnode = prom_getchild(busnode);
 	seen = 0;
 	while(zsnode) {
@@ -1891,8 +1978,8 @@
 						   (void *) vaddr, sizeof(vaddr));
 
 			if(len == -1 || central_bus != NULL) {
-				struct linux_sbus *sbus = NULL;
-				struct linux_sbus_device *sdev = NULL;
+				struct sbus_bus *sbus = NULL;
+				struct sbus_dev *sdev = NULL;
 
 				/* "address" property is not guarenteed,
 				 * everything in I/O is implicitly mapped
@@ -1911,11 +1998,9 @@
 				if (sdev == NULL && central_bus == NULL)
 					prom_halt();
 				if (central_bus == NULL) {
-					prom_apply_sbus_ranges(sbus, sdev->reg_addrs, 1, sdev);
-					mapped_addr = (unsigned long)
-						sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
-							       PAGE_SIZE, "Zilog Registers",
-							       sdev->reg_addrs[0].which_io, 0x0);
+					mapped_addr =
+					    sbus_ioremap(&sdev->resource[0], 0,
+							 PAGE_SIZE, "Zilog Registers");
 				} else {
 					struct linux_prom_registers zsregs[1];
 					int err;
@@ -1927,11 +2012,11 @@
 						prom_printf("ZS: Cannot map Zilog regs.\n");
 						prom_halt();
 					}
-					prom_apply_fhc_ranges(central_bus->child, &zsregs[0], 1);
-					prom_apply_central_ranges(central_bus, &zsregs[0], 1);
-					mapped_addr = (unsigned long)
-						__va((((unsigned long)zsregs[0].which_io)<<32) |
-						     (((unsigned long)zsregs[0].phys_addr)));
+					apply_fhc_ranges(central_bus->child, &zsregs[0], 1);
+					apply_central_ranges(central_bus, &zsregs[0], 1);
+					mapped_addr =
+						((((u64)zsregs[0].which_io)<<32UL)|
+						 ((u64)zsregs[0].phys_addr));
 				}
 			} else if(len % sizeof(unsigned int)) {
 				prom_printf("WHOOPS:  proplen for %s "
@@ -1946,13 +2031,14 @@
 					       (sizeof(sun4u_ino)));
 			if(!irq) {
 				if (central_bus) {
-					irq = zilog_irq = 
-						build_irq(12, 0, 
-							&central_bus->child->fhc_regs.uregs->fhc_uart_iclr,
-							&central_bus->child->fhc_regs.uregs->fhc_uart_imap);
+					unsigned long iclr, imap;
+
+					iclr = central_bus->child->fhc_regs.uregs + FHC_UREGS_ICLR;
+					imap = central_bus->child->fhc_regs.uregs + FHC_UREGS_IMAP;
+					irq = zilog_irq = build_irq(12, 0, iclr, imap);
 				} else {
 					irq = zilog_irq = 
-						sbus_build_irq(SBus_chain, sun4u_ino);
+						sbus_build_irq(sbus_root, sun4u_ino);
 				}
 			}
 			break;
@@ -1964,10 +2050,20 @@
 		panic("get_zs: whee chip not found");
 	if(!vaddr[0] && !mapped_addr)
 		panic("get_zs: whee no serial chip mappable");
-	if (mapped_addr != 0)
+	if (mapped_addr != 0) {
 		return (struct sun_zslayout *) mapped_addr;
-	else
-		return (struct sun_zslayout *) (unsigned long) vaddr[0];
+	} else {
+		pgd_t *pgd = pgd_offset_k((unsigned long)vaddr[0]);
+		pmd_t *pmd = pmd_offset(pgd, (unsigned long)vaddr[0]);
+		pte_t *pte = pte_offset(pmd, (unsigned long)vaddr[0]);
+		unsigned long base = pte_val(*pte) & _PAGE_PADDR;
+
+		/* Translate PROM's mapping we captured at boot
+		 * time into physical address.
+		 */
+		base += ((unsigned long)vaddr[0] & ~PAGE_MASK);
+		return (struct sun_zslayout *) base;
+	}
 }
 #else /* !(__sparc_v9__) */
 static struct sun_zslayout * __init get_zs(int chip)
@@ -1990,6 +2086,8 @@
 		panic("get_zs bogon zs chip number");
 
 	if(sparc_cpu_model == sun4) {
+		struct resource dummy_resource;
+
 		/* Grrr, these have to be hardcoded aieee */
 		switch(chip) {
 		case 0:
@@ -2003,9 +2101,11 @@
 		zs_nodes[chip] = 0;
 		if(!irq)
 			zilog_irq = irq = 12;
-		vaddr[0] = (unsigned long)
-				sparc_alloc_io(paddr, 0, 8,
-					       "Zilog Serial", iospace, 0);
+		dummy_resource.start = paddr;
+		dummy_resource.end = paddr + 8 - 1;
+		dummy_resource.flags = IORESOURCE_IO;
+		vaddr[0] = sbus_ioremap(&dummy_resource, 0,
+					8, "Zilog Serial");
 	} else {
 		/* Can use the prom for other machine types */
 		zsnode = prom_getchild(prom_root_node);
@@ -2056,15 +2156,18 @@
 				} else {
 					/* On sun4d don't have address property :( */
 					struct linux_prom_registers zsreg[4];
+					struct resource res;
 					
 					if (prom_getproperty(zsnode, "reg", (char *)zsreg, sizeof(zsreg)) == -1) {
 						prom_printf ("Cannot map zs regs\n");
 						prom_halt();
 					}
 					prom_apply_generic_ranges(bbnode, cpunode, zsreg, 1);
-					vaddr[0] = (unsigned long)
-							sparc_alloc_io(zsreg[0].phys_addr, 0, 8,
-								       "Zilog Serial", zsreg[0].which_io, 0);
+					res.start = zsreg[0].phys_addr;
+					res.end = res.start + 8 - 1;
+					res.flags = zsreg[0].which_io | IORESOURCE_IO;
+					vaddr[0] = sbus_ioremap(&res, 0,
+								8, "Zilog Serial");
 				}
 				zs_nodes[chip] = zsnode;
 				len = prom_getproperty(zsnode, "intr",
@@ -2074,9 +2177,9 @@
 					prom_printf(
 					      "WHOOPS:  proplen for %s "
 					      "was %d, need multiple of "
-					      "%d\n", "address", len,
+					      "%d\n", "intr", len,
 					      sizeof(struct linux_prom_irqs));
-					panic("zilog: address property");
+					panic("zilog: intr property");
 				}
 				if(!irq) {
 					irq = zilog_irq = tmp_irq[0].pri;
@@ -2110,11 +2213,62 @@
 	write_zsreg(zs_soft[channel].zs_channel, R13, ((brg >> 8) & 0xff));
 }
 
-int __init zs_probe (unsigned long *memory_start)
+void __init zs_init_alloc_failure(const char *table_name)
+{
+	prom_printf("zs_probe: Cannot alloc %s.\n", table_name);
+	prom_halt();
+}
+
+void * __init zs_alloc_bootmem(unsigned long size)
+{
+	void *ret;
+
+	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+	if (ret != NULL)
+		memset(ret, 0, size);
+
+	return ret;
+}
+
+void __init zs_alloc_tables(void)
+{
+	zs_chips = (struct sun_zslayout **)
+		zs_alloc_bootmem(NUM_SERIAL * sizeof(struct sun_zslayout *));
+	if (zs_chips == NULL)
+		zs_init_alloc_failure("zs_chips");
+	zs_channels = (struct sun_zschannel **)
+		zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct sun_zschannel *));
+	if (zs_channels == NULL)
+		zs_init_alloc_failure("zs_channels");
+	zs_nodes = (int *)
+		zs_alloc_bootmem(NUM_SERIAL * sizeof(int));
+	if (zs_nodes == NULL)
+		zs_init_alloc_failure("zs_nodes");
+	zs_soft = (struct sun_serial *)
+		zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct sun_serial));
+	if (zs_soft == NULL)
+		zs_init_alloc_failure("zs_soft");
+	zs_ttys = (struct tty_struct *)
+		zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct tty_struct));
+	if (zs_ttys == NULL)
+		zs_init_alloc_failure("zs_ttys");
+	serial_table = (struct tty_struct **)
+		zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct tty_struct *));
+	if (serial_table == NULL)
+		zs_init_alloc_failure("serial_table");
+	serial_termios = (struct termios **)
+		zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct termios *));
+	if (serial_termios == NULL)
+		zs_init_alloc_failure("serial_termios");
+	serial_termios_locked = (struct termios **)
+		zs_alloc_bootmem(NUM_CHANNELS * sizeof(struct termios *));
+	if (serial_termios_locked == NULL)
+		zs_init_alloc_failure("serial_termios_locked");
+}
+
+int __init zs_probe(void)
 {
-	char *p;
 	int node;
-	int i;
 
 	if(sparc_cpu_model == sun4)
 		goto no_probe;
@@ -2166,42 +2320,24 @@
 	NUM_SERIAL = 2;
 
 no_probe:
-	p = (char *)((*memory_start + 7) & ~7);
-	zs_chips = (struct sun_zslayout **)(p);
-	i = NUM_SERIAL * sizeof (struct sun_zslayout *);
-	zs_channels = (struct sun_zschannel **)(p + i);
-	i += NUM_CHANNELS * sizeof (struct sun_zschannel *);
-	zs_nodes = (int *)(p + i);
-	i += NUM_SERIAL * sizeof (int);
-	zs_soft = (struct sun_serial *)(p + i);
-	i += NUM_CHANNELS * sizeof (struct sun_serial);
-	zs_ttys = (struct tty_struct *)(p + i);
-	i += NUM_CHANNELS * sizeof (struct tty_struct);
-	serial_table = (struct tty_struct **)(p + i);
-	i += NUM_CHANNELS * sizeof (struct tty_struct *);
-	serial_termios = (struct termios **)(p + i);
-	i += NUM_CHANNELS * sizeof (struct termios *);
-	serial_termios_locked = (struct termios **)(p + i);
-	i += NUM_CHANNELS * sizeof (struct termios *);
-	memset (p, 0, i);
-	*memory_start = (((unsigned long)p) + i + 7) & ~7;
+	zs_alloc_tables();
 
 	/* Fill in rs_ops struct... */
 #ifdef CONFIG_SERIAL_CONSOLE
-	sunserial_setinitfunc(memory_start, zs_console_init);
+	sunserial_setinitfunc(zs_console_init);
 #endif
-	sunserial_setinitfunc(memory_start, zs_init);
+	sunserial_setinitfunc(zs_init);
 	rs_ops.rs_kgdb_hook = zs_kgdb_hook;
 	rs_ops.rs_change_mouse_baud = zs_change_mouse_baud;
 
-	sunkbd_setinitfunc(memory_start, sun_kbd_init);
+	sunkbd_setinitfunc(sun_kbd_init);
 	kbd_ops.compute_shiftstate = sun_compute_shiftstate;
 	kbd_ops.setledstate = sun_setledstate;
 	kbd_ops.getledstate = sun_getledstate;
 	kbd_ops.setkeycode = sun_setkeycode;
 	kbd_ops.getkeycode = sun_getkeycode;
 #if defined(__sparc_v9__) && defined(CONFIG_PCI)
-	sunkbd_install_keymaps(memory_start, sun_key_maps, sun_keymap_count,
+	sunkbd_install_keymaps(sun_key_maps, sun_keymap_count,
 			       sun_func_buf, sun_func_table,
 			       sun_funcbufsize, sun_funcbufleft,
 			       sun_accent_table, sun_accent_table_size);
@@ -2214,7 +2350,8 @@
 	int channel, chip;
 	unsigned long flags;
 
-	if (!NUM_SERIAL) return;
+	if (!NUM_SERIAL)
+		return;
 	
 	save_and_cli(flags);
 	
@@ -2346,12 +2483,13 @@
 	 */
 	if (request_irq(zilog_irq, zs_interrupt,
 			(SA_INTERRUPT | SA_STATIC_ALLOC),
-			"Zilog8530", zs_chain))
-		panic("Unable to attach zs intr\n");
+			"Zilog8530", zs_chain)) {
+		prom_printf("Unable to attach zs intr\n");
+		prom_halt();
+	}
 
 	/* Initialize Hardware */
 	for(channel = 0; channel < NUM_CHANNELS; channel++) {
-
 		/* Hardware reset each chip */
 		if (!(channel & 1)) {
 			write_zsreg(zs_soft[channel].zs_channel, R9, FHWRES);
@@ -2580,12 +2718,14 @@
  */
 static void zs_fair_output(struct sun_serial *info)
 {
-	int left;		/* Output no more than that */
 	unsigned long flags;
+	int left;		/* Output no more than that */
 	char c;
 
-	if (info == 0) return;
-	if (info->xmit_buf == 0) return;
+	if (info == NULL)
+		return;
+	if (info->xmit_buf == NULL)
+		return;
 
 	save_flags(flags);  cli();
 	left = info->xmit_cnt;
@@ -2602,8 +2742,9 @@
 	}
 
 	/* Last character is being transmitted now (hopefully). */
-	info->zs_channel->control = RES_Tx_P;
+	sbus_writeb(RES_Tx_P, &info->zs_channel->control);
 	ZSDELAY();
+	ZSLOG(REGCTRL, RES_Tx_P, 1);
 
 	restore_flags(flags);
 	return;
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/char/zs.h linux/drivers/sbus/char/zs.h
--- v2.3.34/linux/drivers/sbus/char/zs.h	Wed May 12 08:41:15 1999
+++ linux/drivers/sbus/char/zs.h	Mon Dec 20 22:06:42 1999
@@ -1,11 +1,11 @@
-/* $Id: zs.h,v 1.2 1999/05/12 11:15:31 davem Exp $
+/* $Id: zs.h,v 1.3 1999/09/21 14:38:18 davem Exp $
  * zs.h: Definitions for the Sparc Zilog serial driver.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1996 Eddie C. Dost   (ecd@skynet.be)
  */
-#ifndef _SPARC_SERIAL_H
-#define _SPARC_SERIAL_H
+#ifndef _ZS_H
+#define _ZS_H
 
 /* Just one channel */
 struct sun_zschannel {
@@ -411,18 +411,17 @@
 /* Read Register 15 (value of WR 15) */
 
 /* Misc macros */
-#define ZS_CLEARERR(channel)    do { channel->control = ERR_RES; \
+#define ZS_CLEARERR(channel)    do { sbus_writeb(ERR_RES, &channel->control); \
 				     udelay(5); } while(0)
 
-#define ZS_CLEARSTAT(channel)   do { channel->control = RES_EXT_INT; \
+#define ZS_CLEARSTAT(channel)   do { sbus_writeb(RES_EXT_INT, &channel->control); \
 				     udelay(5); } while(0)
 
-#define ZS_CLEARFIFO(channel)   do { volatile unsigned char garbage; \
-				     garbage = channel->data; \
+#define ZS_CLEARFIFO(channel)   do { sbus_readb(&channel->data); \
 				     udelay(2); \
-				     garbage = channel->data; \
+				     sbus_readb(&channel->data); \
 				     udelay(2); \
-				     garbage = channel->data; \
+				     sbus_readb(&channel->data); \
 				     udelay(2); } while(0)
 
-#endif /* !(_SPARC_SERIAL_H) */
+#endif /* !(_ZS_H) */
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/dvma.c linux/drivers/sbus/dvma.c
--- v2.3.34/linux/drivers/sbus/dvma.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/sbus/dvma.c	Mon Dec 20 22:06:42 1999
@@ -15,55 +15,51 @@
 #include <asm/dma.h>
 #include <asm/sbus.h>
 
-struct Linux_SBus_DMA *dma_chain;
+struct sbus_dma *dma_chain;
 
 /* Print out the current values in the DMA control registers */
-extern __inline__ void
-dump_dma_regs(struct sparc_dma_registers *dregs)
+extern __inline__ void dump_dma_regs(unsigned long dregs)
 {
-	printk("DMA CONTROL<%08lx>  ADDR<%08lx> CNT<%08lx> TEST<%08lx>\n",
-	       (unsigned long) dregs->cond_reg,
-	       (unsigned long) dregs->st_addr,
-	       (unsigned long) dregs->cnt,
-	       (unsigned long) dregs->dma_test);
-	return;
+	printk("DMA CONTROL<%08x> ADDR<%08x> CNT<%08x> TEST<%08x>\n",
+	       sbus_readl(dregs + DMA_CSR), sbus_readl(dregs + DMA_ADDR),
+	       sbus_readl(dregs + DMA_COUNT), sbus_readl(dregs + DMA_TEST));
 }
 
-void __init init_one_dvma(struct Linux_SBus_DMA *dma, int num_dma)
+void __init init_one_dvma(struct sbus_dma *dma, int num_dma)
 {
 	printk("dma%d: ", num_dma);
 	
 	dma->next = 0;
-	dma->running=0;      /* No transfers going on as of yet */
-	dma->allocated=0;    /* No one has allocated us yet */
-	switch((dma->regs->cond_reg)&DMA_DEVICE_ID) {
+	dma->running = 0;      /* No transfers going on as of yet */
+	dma->allocated = 0;    /* No one has allocated us yet */
+	switch(sbus_readl(dma->regs + DMA_CSR)&DMA_DEVICE_ID) {
 	case DMA_VERS0:
-		dma->revision=dvmarev0;
+		dma->revision = dvmarev0;
 		printk("Revision 0 ");
 		break;
 	case DMA_ESCV1:
-		dma->revision=dvmaesc1;
+		dma->revision = dvmaesc1;
 		printk("ESC Revision 1 ");
 		break;
 	case DMA_VERS1:
-		dma->revision=dvmarev1;
+		dma->revision = dvmarev1;
 		printk("Revision 1 ");
 		break;
 	case DMA_VERS2:
-		dma->revision=dvmarev2;
+		dma->revision = dvmarev2;
 		printk("Revision 2 ");
 		break;
 	case DMA_VERHME:
-		dma->revision=dvmahme;
+		dma->revision = dvmahme;
 		printk("HME DVMA gate array ");
 		break;
 	case DMA_VERSPLUS:
-		dma->revision=dvmarevplus;
+		dma->revision = dvmarevplus;
 		printk("Revision 1 PLUS ");
 		break;
 	default:
-		printk("unknown dma version %x",
-		       (dma->regs->cond_reg)&DMA_DEVICE_ID);
+		printk("unknown dma version %08x",
+		       sbus_readl(dma->regs + DMA_CSR) & DMA_DEVICE_ID);
 		dma->allocated = 1;
 		break;
 	}
@@ -74,57 +70,47 @@
 }
 
 /* Probe this SBus DMA module(s) */
-void __init dvma_init(struct linux_sbus *sbus)
+void __init dvma_init(struct sbus_bus *sbus)
 {
-	struct linux_sbus_device *this_dev;
-	struct Linux_SBus_DMA *dma;
-	struct Linux_SBus_DMA *dchain;
-	static int num_dma=0;
+	struct sbus_dev *this_dev;
+	struct sbus_dma *dma;
+	struct sbus_dma *dchain;
+	static int num_dma = 0;
 
 	for_each_sbusdev(this_dev, sbus) {
+		char *name = this_dev->prom_name;
 		int hme = 0;
 
-		if(!strcmp(this_dev->prom_name, "SUNW,fas"))
+		if(!strcmp(name, "SUNW,fas"))
 			hme = 1;
-		else if(strcmp(this_dev->prom_name, "dma") &&
-			strcmp(this_dev->prom_name, "ledma") &&
-			strcmp(this_dev->prom_name, "espdma"))
+		else if(strcmp(name, "dma") &&
+			strcmp(name, "ledma") &&
+			strcmp(name, "espdma"))
 			continue;
 
 		/* Found one... */
-		dma = kmalloc(sizeof(struct Linux_SBus_DMA), GFP_ATOMIC);
+		dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC);
 
-		dma->SBus_dev = this_dev;
+		dma->sdev = this_dev;
 
 		/* Put at end of dma chain */
 		dchain = dma_chain;
 		if(dchain) {
-			while(dchain->next) dchain=dchain->next;
-			dchain->next=dma;
+			while(dchain->next)
+				dchain = dchain->next;
+			dchain->next = dma;
 		} else {
 			/* We're the first in line */
-			dma_chain=dma;
+			dma_chain = dma;
 		}
 
-		/* The constant PAGE_SIZE that is passed to sparc_alloc_io makes the
-		 * routine only alloc 1 page, that was what the original code did
-		 */
-		if(hme) /* On HME cards, dvma lives with esp, 2 reg sets. */
-			prom_apply_sbus_ranges(sbus, dma->SBus_dev->reg_addrs,
-					       0x2, dma->SBus_dev);
-		else    /* All others have only 1 reg set. */
-			prom_apply_sbus_ranges(sbus, dma->SBus_dev->reg_addrs,
-					       0x1, dma->SBus_dev);
-		dma->regs = (struct sparc_dma_registers *)
-			sparc_alloc_io (dma->SBus_dev->reg_addrs[0].phys_addr, 0,
-					PAGE_SIZE, "dma",
-					dma->SBus_dev->reg_addrs[0].which_io, 0x0);
+		dma->regs = sbus_ioremap(&dma->sdev->resource[0], 0,
+					 PAGE_SIZE, "dma");
 
-		dma->node = dma->SBus_dev->prom_node;
+		dma->node = dma->sdev->prom_node;
 		
 		init_one_dvma(dma, num_dma++);
-		
-	};  /* while(this_dev) */
+	}
 }
 
 #ifdef CONFIG_SUN4
@@ -133,28 +119,29 @@
 
 void __init sun4_dvma_init(void)
 {
-	struct Linux_SBus_DMA *dma;
-	struct Linux_SBus_DMA *dchain;
+	struct sbus_dma *dma;
+	struct sbus_dma *dchain;
+	struct resource r;
 
 	if(sun4_dma_physaddr) {
-		dma = kmalloc(sizeof(struct Linux_SBus_DMA), GFP_ATOMIC);
+		dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC);
 
 		/* No SBUS */
-		dma->SBus_dev = 0x0;
+		dma->sdev = NULL;
 
 		/* Only one DMA device */
-		dma_chain=dma;
+		dma_chain = dma;
 
-		dma->regs = (struct sparc_dma_registers *)
-			sparc_alloc_io (sun4_dma_physaddr, 0,
-					PAGE_SIZE, "dma", 0x0, 0x0);
+		memset(&r, 0, sizeof(r));
+		r.start = sun4_dma_physaddr;
+		dma->regs = sbus_ioremap(&r, 0, PAGE_SIZE, "dma");
 
 		/* No prom node */
 		dma->node = 0x0;
 
 		init_one_dvma(dma, 0);
 	} else {
-	  	dma_chain=0x0;
+	  	dma_chain = NULL;
 	}
 }
 
diff -u --recursive --new-file v2.3.34/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c
--- v2.3.34/linux/drivers/sbus/sbus.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/sbus/sbus.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.80 1999/09/02 05:44:33 shadow Exp $
+/* $Id: sbus.c,v 1.83 1999/10/18 01:47:01 zaitcev Exp $
  * sbus.c:  SBus support routines.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -17,17 +17,10 @@
 #include <asm/bpp.h>
 #include <asm/irq.h>
 
-/* This file has been written to be more dynamic and a bit cleaner,
- * but it still needs some spring cleaning.
- */
+struct sbus_bus *sbus_root = NULL;
 
-struct linux_sbus *SBus_chain;
 static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } };
 
-static char lbuf[128];
-
-extern void prom_sbus_ranges_init (int, struct linux_sbus *);
-
 /* Perhaps when I figure out more about the iommu we'll put a
  * device registration routine here that probe_sbus() calls to
  * setup the iommu for each Sbus.
@@ -40,151 +33,127 @@
 
 /* #define DEBUG_FILL */
 
-static void __init fill_sbus_device(int nd, struct linux_sbus_device *sbus_dev)
+static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
 {
-	int grrr, len;
-	unsigned long dev_base_addr, base;
+	unsigned long address, base;
+	int len;
 
-	sbus_dev->prom_node = nd;
-	prom_getstring(nd, "name", lbuf, sizeof(lbuf));
-	strcpy(sbus_dev->prom_name, lbuf);
-
-	dev_base_addr = prom_getint(nd, "address");
-	if(dev_base_addr != -1)
-		sbus_dev->sbus_addr = dev_base_addr;
-
-	len = prom_getproperty(nd, "reg", (void *) sbus_dev->reg_addrs,
-			       sizeof(sbus_dev->reg_addrs));
-	if(len == -1)
+	sdev->prom_node = prom_node;
+	prom_getstring(prom_node, "name",
+		       sdev->prom_name, sizeof(sdev->prom_name));
+	address = prom_getint(prom_node, "address");
+	len = prom_getproperty(prom_node, "reg",
+			       (char *) sdev->reg_addrs,
+			       sizeof(sdev->reg_addrs));
+	if (len == -1) {
+		sdev->num_registers = 0;
 		goto no_regs;
-	if(len%sizeof(struct linux_prom_registers)) {
-		prom_printf("WHOOPS:  proplen for %s was %d, need multiple of %d\n",
-		       sbus_dev->prom_name, len,
-		       (int) sizeof(struct linux_prom_registers));
-		panic("fill_sbus_device");
-	}
-	sbus_dev->num_registers = (len/sizeof(struct linux_prom_registers));
-	sbus_dev->ranges_applied = 0;
-
-	base = (unsigned long) sbus_dev->reg_addrs[0].phys_addr;
-	if(base>=SUN_SBUS_BVADDR ||
-	   (sparc_cpu_model != sun4c &&
-	    sparc_cpu_model != sun4)) {
-		/* Ahh, we can determine the slot and offset */
-		if(sparc_cpu_model == sun4u) {
-			/* A bit tricky on the SYSIO. */
-			sbus_dev->slot = sbus_dev->reg_addrs[0].which_io;
-			sbus_dev->offset = sbus_dev_offset(base);
-		} else if (sparc_cpu_model == sun4d) {
-			sbus_dev->slot = sbus_dev->reg_addrs[0].which_io;
-			sbus_dev->offset = base;
-		} else {
-			sbus_dev->slot = sbus_dev_slot(base);
-			sbus_dev->offset = sbus_dev_offset(base);
+	}
+
+	if (len % sizeof(struct linux_prom_registers)) {
+		prom_printf("fill_sbus_device: proplen for regs of %s "
+			    " was %d, need multiple of %d\n",
+			    sdev->prom_name, len,
+			    (int) sizeof(struct linux_prom_registers));
+		prom_halt();
+	}
+	if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) {
+		prom_printf("fill_sbus_device: Too many register properties "
+			    "for device %s, len=%d\n",
+			    sdev->prom_name, len);
+		prom_halt();
+	}
+	sdev->num_registers = len / sizeof(struct linux_prom_registers);
+	sdev->ranges_applied = 0;
+
+	base = (unsigned long) sdev->reg_addrs[0].phys_addr;
+	if (base >= SUN_SBUS_BVADDR ||
+	    (sparc_cpu_model != sun4c && sparc_cpu_model != sun4)) {
+		/* OK, we can compute the slot number in a
+		 * straightforward manner.
+		 */
+		if (sparc_cpu_model == sun4u ||
+		    sparc_cpu_model == sun4d)
+			sdev->slot = sdev->reg_addrs[0].which_io;
+		else
+			sdev->slot = sbus_dev_slot(base);
+	} else {
+		int rnum;
+
+		/* Fixups are needed to compute the slot number. */
+		sdev->slot = sdev->reg_addrs[0].which_io;
+		sdev->reg_addrs[0].phys_addr =
+			sbus_devaddr(sdev->slot, base);
+		for (rnum = 1; rnum < sdev->num_registers; rnum++) {
+			base = (unsigned long)
+				sdev->reg_addrs[rnum].phys_addr;
+			sdev->reg_addrs[rnum].phys_addr =
+				sbus_devaddr(sdev->slot, base);
 		}
-	} else {   /* Grrr, gotta do calculations to fix things up */
-		sbus_dev->slot = sbus_dev->reg_addrs[0].which_io;
-		sbus_dev->offset = base;
-		sbus_dev->reg_addrs[0].phys_addr = 
-			sbus_devaddr(sbus_dev->slot, base);
-		for(grrr=1; grrr<sbus_dev->num_registers; grrr++) {
-			base = (unsigned long) sbus_dev->reg_addrs[grrr].phys_addr;
-			sbus_dev->reg_addrs[grrr].phys_addr =
-				sbus_devaddr(sbus_dev->slot, base);
-		}
-		/* That surely sucked */
-	}
-	sbus_dev->sbus_addr = (unsigned long) sbus_dev->reg_addrs[0].phys_addr;
-	if(len>(sizeof(struct linux_prom_registers)*PROMREG_MAX)) {
-		prom_printf("WHOOPS:  I got too many register addresses for %s  len=%d\n",
-		       sbus_dev->prom_name, len);
-		panic("sbus device register overflow");
 	}
 
 no_regs:
-	len = prom_getproperty(nd, "address", (void *) sbus_dev->sbus_vaddrs,
-			       sizeof(sbus_dev->sbus_vaddrs));
-	if(len == -1) len=0;
-	if(len&3) {
-		prom_printf("Grrr, I didn't get a multiple of 4 proplen "
-		       "for device %s got %d\n", sbus_dev->prom_name, len);
-		len=0;
-	}
-	sbus_dev->num_vaddrs = (len/4);
-
-#ifdef __sparc_v9__  
-	len = prom_getproperty(nd, "interrupts", (void *)irqs, sizeof(irqs));
-	if((len == -1) || (len == 0)) {
-		sbus_dev->irqs[0] = 0;
-		sbus_dev->num_irqs = 0;
-	} else {
-		sbus_dev->num_irqs = 1;
-		if (irqs[0].pri < 0x20)
-			sbus_dev->irqs[0] = sbus_build_irq(sbus_dev->my_bus, 
-					irqs[0].pri + (sbus_dev->slot * 8));
-		else
-			sbus_dev->irqs[0] = sbus_build_irq(sbus_dev->my_bus, 
-					irqs[0].pri);
+	len = prom_getproperty(prom_node, "ranges",
+			       (char *)sdev->device_ranges,
+			       sizeof(sdev->device_ranges));
+	if (len == -1) {
+		sdev->num_device_ranges = 0;
+		goto no_ranges;
 	}
-#else
-	len = prom_getproperty(nd, "intr", (void *)irqs, sizeof(irqs));
-	if (len == -1) len=0;
-	if (len&7) {
-		prom_printf("Grrr, I didn't get a multiple of 8 proplen for "
-			    "device %s got %d\n", sbus_dev->prom_name, len);
-		len=0;
-	}
-	if (len > 4 * 8) {
-		prom_printf("Device %s has more than 4 interrupts\n", sbus_dev->prom_name);
-		len = 4 * 8;
-	}
-	sbus_dev->num_irqs=(len/8);
-	if(sbus_dev->num_irqs == 0)
-		sbus_dev->irqs[0]=0;
-	else if (sparc_cpu_model != sun4d)
-		for (len = 0; len < sbus_dev->num_irqs; len++)
-			sbus_dev->irqs[len] = irqs[len].pri;
-	else {
-		extern unsigned int sun4d_build_irq(struct linux_sbus_device *sdev, int irq);
-		
-		for (len = 0; len < sbus_dev->num_irqs; len++)
-			sbus_dev->irqs[len] = sun4d_build_irq(sbus_dev, irqs[len].pri);
+	if (len % sizeof(struct linux_prom_ranges)) {
+		prom_printf("fill_sbus_device: proplen for ranges of %s "
+			    " was %d, need multiple of %d\n",
+			    sdev->prom_name, len,
+			    (int) sizeof(struct linux_prom_ranges));
+		prom_halt();
 	}
-#endif
+	if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) {
+		prom_printf("fill_sbus_device: Too many range properties "
+			    "for device %s, len=%d\n",
+			    sdev->prom_name, len);
+		prom_halt();
+	}
+	sdev->num_device_ranges =
+		len / sizeof(struct linux_prom_ranges);
 
-#ifdef DEBUG_FILL
-#ifdef __sparc_v9__
-	prom_printf("Found %s at SBUS slot %x offset %016lx ",
-	       sbus_dev->prom_name, sbus_dev->slot, sbus_dev->offset);
-	if (sbus_dev->irqs[0])
-		prom_printf("irq %s\n", __irq_itoa(sbus_dev->irqs[0]));
-	else
-		prom_printf("\n");
-	prom_printf("Base address %016lx\n", sbus_dev->sbus_addr);
-#else
-	prom_printf("Found %s at SBUS slot %x offset %08lx irq-level %d\n",
-	       sbus_dev->prom_name, sbus_dev->slot, sbus_dev->offset,
-	       sbus_dev->irqs[0]);
-	prom_printf("Base address %08lx\n", sbus_dev->sbus_addr);
-#endif
-	prom_printf("REGISTERS: Probed %d register(s)\n", sbus_dev->num_registers);
-	for(len=0; len<sbus_dev->num_registers; len++)
+no_ranges:
+	/* XXX Unfortunately, IRQ issues are very arch specific.
+	 * XXX Pull this crud out into an arch specific area
+	 * XXX at some point. -DaveM
+	 */
 #ifdef __sparc_v9__
-		prom_printf("Regs<%d> at address<%08lx> IO-space<%d> size<%d "
-		       "bytes, %d words>\n", (int) len,
-		       (unsigned long) sbus_dev->reg_addrs[len].phys_addr,
-		       sbus_dev->reg_addrs[len].which_io,
-		       sbus_dev->reg_addrs[len].reg_size,
-		       (sbus_dev->reg_addrs[len].reg_size/4));
+	len = prom_getproperty(prom_node, "interrupts",
+			       (char *) irqs, sizeof(irqs));
+	if (len == -1 || len == 0) {
+		sdev->irqs[0] = 0;
+		sdev->num_irqs = 0;
+	} else {
+		unsigned int pri = irqs[0].pri;
+
+		sdev->num_irqs = 1;
+		if (pri < 0x20)
+			pri += sdev->slot * 8;
+
+		sdev->irqs[0] =	sbus_build_irq(sdev->bus, pri);
+	}
 #else
-		prom_printf("Regs<%d> at address<%016lx> IO-space<%d> size<%d "
-		       "bytes, %d words>\n", (int) len,
-		       (unsigned long) sbus_dev->reg_addrs[len].phys_addr,
-		       sbus_dev->reg_addrs[len].which_io,
-		       sbus_dev->reg_addrs[len].reg_size,
-		       (sbus_dev->reg_addrs[len].reg_size/4));
-#endif
-#endif
+	len = prom_getproperty(prom_node, "intr",
+			       (char *)irqs, sizeof(irqs));
+	if (len == -1)
+		len = 0;
+	sdev->num_irqs = len / 8;
+	if (sdev->num_irqs == 0) {
+		sdev->irqs[0] = 0;
+	} else if (sparc_cpu_model == sun4d) {
+		extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
+
+		for (len = 0; len < sdev->num_irqs; len++)
+			sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri);
+	} else {
+		for (len = 0; len < sdev->num_irqs; len++)
+			sdev->irqs[len] = irqs[len].pri;
+	}
+#endif /* !__sparc_v9__ */
 }
 
 /* This routine gets called from whoever needs the sbus first, to scan
@@ -193,8 +162,8 @@
  * devices.
  */
 
-extern void iommu_init(int iommu_node, struct linux_sbus *sbus);
-extern void iounit_init(int sbi_node, int iounit_node, struct linux_sbus *sbus);
+extern void iommu_init(int iommu_node, struct sbus_bus *sbus);
+extern void iounit_init(int sbi_node, int iounit_node, struct sbus_bus *sbus);
 void sun4_init(void);
 #ifdef CONFIG_SUN_OPENPROMIO
 extern int openprom_init(void);
@@ -213,41 +182,133 @@
 #endif
 
 static void __init sbus_do_child_siblings(int start_node,
-					  struct linux_sbus_device *child,
-					  struct linux_sbus *sbus)
+					  struct sbus_dev *child,
+					  struct sbus_dev *parent,
+					  struct sbus_bus *sbus)
 {
-	struct linux_sbus_device *this_dev = child;
+	struct sbus_dev *this_dev = child;
 	int this_node = start_node;
 
 	/* Child already filled in, just need to traverse siblings. */
-	child->child = 0;
+	child->child = NULL;
+	child->parent = parent;
 	while((this_node = prom_getsibling(this_node)) != 0) {
-		this_dev->next = kmalloc(sizeof(struct linux_sbus_device), GFP_ATOMIC);
+		this_dev->next = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
 		this_dev = this_dev->next;
 		this_dev->next = 0;
+		this_dev->parent = parent;
 
-		this_dev->my_bus = sbus;
+		this_dev->bus = sbus;
 		fill_sbus_device(this_node, this_dev);
 
 		if(prom_getchild(this_node)) {
-			this_dev->child = kmalloc(sizeof(struct linux_sbus_device),
+			this_dev->child = kmalloc(sizeof(struct sbus_dev),
 						  GFP_ATOMIC);
-			this_dev->child->my_bus = sbus;
+			this_dev->child->bus = sbus;
 			fill_sbus_device(prom_getchild(this_node), this_dev->child);
 			sbus_do_child_siblings(prom_getchild(this_node),
-					       this_dev->child, sbus);
+					       this_dev->child, this_dev, sbus);
 		} else {
-			this_dev->child = 0;
+			this_dev->child = NULL;
 		}
 	}
 }
 
+/*
+ * XXX This functions appears to be a distorted version of
+ * prom_sbus_ranges_init(), with all sun4d stuff cut away.
+ * Ask DaveM what is going on here, how is sun4d supposed to work... XXX
+ */
+static void __init sbus_bus_ranges_init(int parent_node, struct sbus_bus *sbus)
+{
+	int len;
+
+	len = prom_getproperty(sbus->prom_node, "ranges",
+			       (char *) sbus->sbus_ranges,
+			       sizeof(sbus->sbus_ranges));
+	if (len == -1 || len == 0) {
+		sbus->num_sbus_ranges = 0;
+		return;
+	}
+	sbus->num_sbus_ranges = len / sizeof(struct linux_prom_ranges);
+}
+
+static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges,
+					  int num_ranges,
+					  struct linux_prom_registers *regs,
+					  int num_regs)
+{
+	if (num_ranges) {
+		int regnum;
+
+		for (regnum = 0; regnum < num_regs; regnum++) {
+			int rngnum;
+
+			for (rngnum = 0; rngnum < num_ranges; rngnum++) {
+				if (regs[regnum].which_io == ranges[rngnum].ot_child_space)
+					break;
+			}
+			if (rngnum == num_ranges) {
+				prom_printf("sbus_apply_ranges: Cannot find matching "
+					    "range nregs[%d] nranges[%d].\n",
+					    num_regs, num_ranges);
+				prom_halt();
+			}
+			regs[regnum].which_io = ranges[rngnum].ot_parent_space;
+			regs[regnum].phys_addr += ranges[rngnum].ot_parent_base;
+		}
+	}
+}
+
+static void __init __fixup_regs_sdev(struct sbus_dev *sdev)
+{
+	if (sdev->num_registers != 0) {
+		struct sbus_dev *parent = sdev->parent;
+		int i;
+
+		while (parent != NULL) {
+			__apply_ranges_to_regs(parent->device_ranges,
+					       parent->num_device_ranges,
+					       sdev->reg_addrs,
+					       sdev->num_registers);
+
+			parent = parent->parent;
+		}
+
+		__apply_ranges_to_regs(sdev->bus->sbus_ranges,
+				       sdev->bus->num_sbus_ranges,
+				       sdev->reg_addrs,
+				       sdev->num_registers);
+
+		for (i = 0; i < sdev->num_registers; i++) {
+			struct resource *res = &sdev->resource[i];
+
+			res->start = sdev->reg_addrs[i].phys_addr;
+			res->end = (res->start +
+				    (unsigned long)sdev->reg_addrs[i].reg_size - 1UL);
+			res->flags = IORESOURCE_IO |
+				(sdev->reg_addrs[i].which_io & 0xff);
+		}
+	}
+}
+
+static void __init sbus_fixup_all_regs(struct sbus_dev *first_sdev)
+{
+	struct sbus_dev *sdev;
+
+	for (sdev = first_sdev; sdev; sdev = sdev->next) {
+		if (sdev->child)
+			sbus_fixup_all_regs(sdev->child);
+		__fixup_regs_sdev(sdev);
+	}
+}
+
 void __init sbus_init(void)
 {
-	register int nd, this_sbus, sbus_devs, topnd, iommund;
+	int nd, this_sbus, sbus_devs, topnd, iommund;
 	unsigned int sbus_clock;
-	struct linux_sbus *sbus;
-	struct linux_sbus_device *this_dev;
+	struct sbus_bus *sbus;
+	struct sbus_dev *this_dev;
 	int num_sbus = 0;  /* How many did we find? */
 	
 #ifdef CONFIG_SUN4
@@ -303,33 +364,38 @@
 	/* Ok, we've found the first one, allocate first SBus struct
 	 * and place in chain.
 	 */
-	sbus = SBus_chain = kmalloc(sizeof(struct linux_sbus), GFP_ATOMIC);
-	sbus->next = 0;
+	sbus = sbus_root = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
+	sbus->next = NULL;
 	sbus->prom_node = nd;
-	this_sbus=nd;
+	this_sbus = nd;
 
 	if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d)
 		iommu_init(iommund, sbus);
 
 	/* Loop until we find no more SBUS's */
 	while(this_sbus) {
+#ifdef __sparc_v9__						  
 		/* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */
-		if(sparc_cpu_model == sun4u)
-			iommu_init(this_sbus, sbus);
+		if(sparc_cpu_model == sun4u) {
+			extern void sbus_iommu_init(int prom_node, struct sbus_bus *sbus);
+
+			sbus_iommu_init(this_sbus, sbus);
+		}
+#endif
 #ifndef __sparc_v9__						  
-		else if (sparc_cpu_model == sun4d)
+		if (sparc_cpu_model == sun4d)
 			iounit_init(this_sbus, iommund, sbus);
 #endif						   
 		printk("sbus%d: ", num_sbus);
 		sbus_clock = prom_getint(this_sbus, "clock-frequency");
-		if(sbus_clock==-1) sbus_clock = (25*1000*1000);
+		if(sbus_clock == -1)
+			sbus_clock = (25*1000*1000);
 		printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000),
 		       (int) (((sbus_clock/1000)%1000 != 0) ? 
 			      (((sbus_clock/1000)%1000) + 1000) : 0));
 
-		prom_getstring(this_sbus, "name", lbuf, sizeof(lbuf));
-		lbuf[sizeof(sbus->prom_name) - 1] = 0;
-		strcpy(sbus->prom_name, lbuf);
+		prom_getstring(this_sbus, "name",
+			       sbus->prom_name, sizeof(sbus->prom_name));
 		sbus->clock_freq = sbus_clock;
 #ifndef __sparc_v9__		
 		if (sparc_cpu_model == sun4d) {
@@ -338,60 +404,69 @@
 		}
 #endif
 		
-		prom_sbus_ranges_init (iommund, sbus);
+		sbus_bus_ranges_init(iommund, sbus);
 
 		sbus_devs = prom_getchild(this_sbus);
 
-		sbus->devices = kmalloc(sizeof(struct linux_sbus_device), GFP_ATOMIC);
+		sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
 
 		this_dev = sbus->devices;
-		this_dev->next = 0;
+		this_dev->next = NULL;
 
-		this_dev->my_bus = sbus;
+		this_dev->bus = sbus;
+		this_dev->parent = NULL;
 		fill_sbus_device(sbus_devs, this_dev);
 
 		/* Should we traverse for children? */
 		if(prom_getchild(sbus_devs)) {
 			/* Allocate device node */
-			this_dev->child = kmalloc(sizeof(struct linux_sbus_device),
+			this_dev->child = kmalloc(sizeof(struct sbus_dev),
 						  GFP_ATOMIC);
 			/* Fill it */
-			this_dev->child->my_bus = sbus;
-			fill_sbus_device(prom_getchild(sbus_devs), this_dev->child);
+			this_dev->child->bus = sbus;
+			fill_sbus_device(prom_getchild(sbus_devs),
+					 this_dev->child);
 			sbus_do_child_siblings(prom_getchild(sbus_devs),
-					       this_dev->child, sbus);
+					       this_dev->child,
+					       this_dev,
+					       sbus);
 		} else {
-			this_dev->child = 0;
+			this_dev->child = NULL;
 		}
 
 		while((sbus_devs = prom_getsibling(sbus_devs)) != 0) {
 			/* Allocate device node */
-			this_dev->next = kmalloc(sizeof(struct linux_sbus_device),
+			this_dev->next = kmalloc(sizeof(struct sbus_dev),
 						 GFP_ATOMIC);
-			this_dev=this_dev->next;
-			this_dev->next=0;
+			this_dev = this_dev->next;
+			this_dev->next = NULL;
 
 			/* Fill it */
-			this_dev->my_bus = sbus;
+			this_dev->bus = sbus;
+			this_dev->parent = NULL;
 			fill_sbus_device(sbus_devs, this_dev);
 
 			/* Is there a child node hanging off of us? */
 			if(prom_getchild(sbus_devs)) {
 				/* Get new device struct */
-				this_dev->child =
-					kmalloc(sizeof(struct linux_sbus_device),
-						GFP_ATOMIC);
+				this_dev->child = kmalloc(sizeof(struct sbus_dev),
+							  GFP_ATOMIC);
 				/* Fill it */
-				this_dev->child->my_bus = sbus;
+				this_dev->child->bus = sbus;
 				fill_sbus_device(prom_getchild(sbus_devs),
 						 this_dev->child);
 				sbus_do_child_siblings(prom_getchild(sbus_devs),
-						     this_dev->child, sbus);
+						       this_dev->child,
+						       this_dev,
+						       sbus);
 			} else {
-				this_dev->child = 0;
+				this_dev->child = NULL;
 			}
 		}
 
+		/* Walk all devices and apply parent ranges. */
+		sbus_fixup_all_regs(sbus->devices);
+
 		dvma_init(sbus);
 
 		num_sbus++;
@@ -402,24 +477,28 @@
 			this_sbus = prom_searchsiblings(this_sbus, "sbus");
 		} else if(sparc_cpu_model == sun4d) {
 			iommund = prom_getsibling(iommund);
-			if(!iommund) break;
+			if(!iommund)
+				break;
 			iommund = prom_searchsiblings(iommund, "io-unit");
-			if(!iommund) break;
+			if(!iommund)
+				break;
 			this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi");
 		} else {
 			this_sbus = prom_getsibling(this_sbus);
-			if(!this_sbus) break;
+			if(!this_sbus)
+				break;
 			this_sbus = prom_searchsiblings(this_sbus, "sbus");
 		}
 		if(this_sbus) {
-			sbus->next = kmalloc(sizeof(struct linux_sbus), GFP_ATOMIC);
+			sbus->next = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
 			sbus = sbus->next;
-			sbus->next = 0;
+			sbus->next = NULL;
 			sbus->prom_node = this_sbus;
 		} else {
 			break;
 		}
 	} /* while(this_sbus) */
+
 	if (sparc_cpu_model == sun4d) {
 		extern void sun4d_init_sbi_irq(void);
 		sun4d_init_sbi_irq();
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c
--- v2.3.34/linux/drivers/scsi/BusLogic.c	Thu Nov 11 20:11:43 1999
+++ linux/drivers/scsi/BusLogic.c	Tue Dec 21 10:17:32 1999
@@ -75,13 +75,13 @@
 
 
 /*
-  BusLogic_Options can be assigned a string by the Loadable Kernel Module
-  Installation Facility to be parsed for BusLogic Driver Options
-  specifications.
+  BusLogic can be assigned a string by insmod.
 */
 
-static char
-  *BusLogic_Options =				NULL;
+#ifdef MODULE
+static char *BusLogic =	NULL;
+MODULE_PARM(BusLogic, "s");
+#endif
 
 
 /*
@@ -2724,8 +2724,10 @@
       return 0;
     }
   memset(PrototypeHostAdapter, 0, sizeof(BusLogic_HostAdapter_T));
-  if (BusLogic_Options != NULL)
-    BusLogic_ParseDriverOptions(BusLogic_Options);
+#ifdef MODULE
+  if (BusLogic != NULL)
+    BusLogic_Setup(BusLogic);
+#endif
   BusLogic_InitializeProbeInfoList(PrototypeHostAdapter);
   for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++)
     {
@@ -4655,14 +4657,14 @@
   INSMOD Loadable Kernel Module Installation Facility:
 
     insmod BusLogic.o \
-	'BusLogic_Options="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"'
+	'BusLogic="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"'
 
   NOTE: Module Utilities 2.1.71 or later is required for correct parsing
 	of driver options containing commas.
 
 */
 
-static void BusLogic_ParseDriverOptions(char *OptionsString)
+static int __init BusLogic_ParseDriverOptions(char *OptionsString)
 {
   while (true)
     {
@@ -4705,7 +4707,7 @@
 		  BusLogic_Error("BusLogic: Invalid Driver Options "
 				 "(illegal I/O Address 0x%X)\n",
 				 NULL, IO_Address);
-		  return;
+		  return 0;
 		}
 	    }
 	  else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA"))
@@ -4735,7 +4737,7 @@
 		      BusLogic_Error("BusLogic: Invalid Driver Options "
 				     "(illegal Queue Depth %d)\n",
 				     NULL, QueueDepth);
-		      return;
+		      return 0;
 		    }
 		  DriverOptions->QueueDepth[TargetID] = QueueDepth;
 		  if (*OptionsString == ',')
@@ -4747,7 +4749,7 @@
 		      BusLogic_Error("BusLogic: Invalid Driver Options "
 				     "(',' or ']' expected at '%s')\n",
 				     NULL, OptionsString);
-		      return;
+		      return 0;
 		    }
 		}
 	      if (*OptionsString != ']')
@@ -4755,7 +4757,7 @@
 		  BusLogic_Error("BusLogic: Invalid Driver Options "
 				 "(']' expected at '%s')\n",
 				 NULL, OptionsString);
-		  return;
+		  return 0;
 		}
 	      else OptionsString++;
 	    }
@@ -4769,7 +4771,7 @@
 		  BusLogic_Error("BusLogic: Invalid Driver Options "
 				 "(illegal Queue Depth %d)\n",
 				 NULL, QueueDepth);
-		  return;
+		  return 0;
 		}
 	      DriverOptions->CommonQueueDepth = QueueDepth;
 	      for (TargetID = 0;
@@ -4887,7 +4889,7 @@
 		  BusLogic_Error("BusLogic: Invalid Driver Options "
 				 "(illegal Bus Settle Time %d)\n",
 				 NULL, BusSettleTime);
-		  return;
+		  return 0;
 		}
 	      DriverOptions->BusSettleTime = BusSettleTime;
 	    }
@@ -4925,7 +4927,7 @@
 	{
 	  BusLogic_Error("BusLogic: Invalid Driver Options "
 			 "(all or no I/O Addresses must be specified)\n", NULL);
-	  return;
+	  return 0;
 	}
       /*
 	Tagged Queuing is disabled when the Queue Depth is 1 since queuing
@@ -4939,8 +4941,9 @@
 	    DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
 	  }
       if (*OptionsString == ';') OptionsString++;
-      if (*OptionsString == '\0') return;
+      if (*OptionsString == '\0') return 0;
     }
+    return 1;
 }
 
 
@@ -4948,26 +4951,30 @@
   BusLogic_Setup handles processing of Kernel Command Line Arguments.
 */
 
-void BusLogic_Setup(char *CommandLineString, int *CommandLineIntegers)
+static int __init 
+BusLogic_Setup(char *str)
 {
-  if (CommandLineIntegers[0] != 0)
-    {
-      BusLogic_Error("BusLogic: Obsolete Command Line Entry "
-		     "Format Ignored\n", NULL);
-      return;
-    }
-  if (CommandLineString == NULL || *CommandLineString == '\0') return;
-  BusLogic_ParseDriverOptions(CommandLineString);
+	int ints[3];
+
+	(void)get_options(str, ARRAY_SIZE(ints), ints);
+
+	if (ints[0] != 0) {
+		BusLogic_Error("BusLogic: Obsolete Command Line Entry "
+				"Format Ignored\n", NULL);
+		return 0;
+	}
+	if (str == NULL || *str == '\0')
+		return 0;
+	return BusLogic_ParseDriverOptions(str);
 }
 
+__setup("BusLogic=", BusLogic_Setup);
 
 /*
   Include Module support if requested.
 */
 
 #ifdef MODULE
-
-MODULE_PARM(BusLogic_Options, "s");
 
 SCSI_Host_Template_T driver_template = BUSLOGIC;
 
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/BusLogic.h linux/drivers/scsi/BusLogic.h
--- v2.3.34/linux/drivers/scsi/BusLogic.h	Tue Nov 23 22:42:21 1999
+++ linux/drivers/scsi/BusLogic.h	Tue Dec 28 17:44:24 1999
@@ -1767,8 +1767,6 @@
 				     SCSI_Command_T *, unsigned int);
 static void BusLogic_Message(BusLogic_MessageLevel_T, char *,
 			     BusLogic_HostAdapter_T *, ...);
-static void BusLogic_ParseDriverOptions(char *);
-
 
 /*
   Declare the Initialization Functions.
@@ -1803,8 +1801,8 @@
 int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *) __init;
 int BusLogic_ReleaseHostAdapter(SCSI_Host_T *) __init;
 static boolean BusLogic_ParseKeyword(char **, char *) __init;
-static void BusLogic_ParseDriverOptions(char *) __init;
-void BusLogic_Setup(char *, int *) __init;
+static int BusLogic_ParseDriverOptions(char *) __init;
+static int BusLogic_Setup(char *) __init;
 
 
 #endif /* BusLogic_DriverVersion */
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c
--- v2.3.34/linux/drivers/scsi/esp.c	Thu Nov 11 20:11:46 1999
+++ linux/drivers/scsi/esp.c	Wed Dec 22 19:55:38 1999
@@ -1,4 +1,5 @@
-/* esp.c:  EnhancedScsiProcessor Sun SCSI driver code.
+/* $Id: esp.c,v 1.89 1999/12/23 01:46:14 davem Exp $
+ * esp.c:  EnhancedScsiProcessor Sun SCSI driver code.
  *
  * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu)
  */
@@ -39,6 +40,8 @@
 #include <asm/irq.h>
 #include <asm/idprom.h>
 
+#include <linux/module.h>
+
 #define DEBUG_ESP
 /* #define DEBUG_ESP_HME */
 /* #define DEBUG_ESP_DATA */
@@ -174,18 +177,16 @@
 };
 
 /* The master ring of all esp hosts we are managing in this driver. */
-static struct Sparc_ESP *espchain;
+static struct esp *espchain;
+static spinlock_t espchain_lock = SPIN_LOCK_UNLOCKED;
 static int esps_running = 0;
 
 /* Forward declarations. */
 static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
-#ifndef __sparc_v9__
-static void esp_intr_4d(int irq, void *dev_id, struct pt_regs *pregs);
-#endif
 
 /* Debugging routines */
 struct esp_cmdstrings {
-	unchar cmdchar;
+	u8 cmdchar;
 	char *text;
 } esp_cmd_strings[] = {
 	/* Miscellaneous */
@@ -225,16 +226,16 @@
 #define NUM_ESP_COMMANDS  ((sizeof(esp_cmd_strings)) / (sizeof(struct esp_cmdstrings)))
 
 /* Print textual representation of an ESP command */
-static inline void esp_print_cmd(unchar espcmd)
+static inline void esp_print_cmd(u8 espcmd)
 {
-	unchar dma_bit = espcmd & ESP_CMD_DMA;
+	u8 dma_bit = espcmd & ESP_CMD_DMA;
 	int i;
 
 	espcmd &= ~dma_bit;
-	for(i=0; i<NUM_ESP_COMMANDS; i++)
-		if(esp_cmd_strings[i].cmdchar == espcmd)
+	for (i = 0; i < NUM_ESP_COMMANDS; i++)
+		if (esp_cmd_strings[i].cmdchar == espcmd)
 			break;
-	if(i==NUM_ESP_COMMANDS)
+	if (i == NUM_ESP_COMMANDS)
 		printk("ESP_Unknown");
 	else
 		printk("%s%s", esp_cmd_strings[i].text,
@@ -242,9 +243,9 @@
 }
 
 /* Print the status register's value */
-static inline void esp_print_statreg(unchar statreg)
+static inline void esp_print_statreg(u8 statreg)
 {
-	unchar phase;
+	u8 phase;
 
 	printk("STATUS<");
 	phase = statreg & ESP_STAT_PMASK;
@@ -255,44 +256,44 @@
 			  (phase == ESP_MOP ? "MSG-OUT" :
 			   (phase == ESP_MIP ? "MSG_IN" :
 			    "unknown")))))));
-	if(statreg & ESP_STAT_TDONE)
+	if (statreg & ESP_STAT_TDONE)
 		printk("TRANS_DONE,");
-	if(statreg & ESP_STAT_TCNT)
+	if (statreg & ESP_STAT_TCNT)
 		printk("TCOUNT_ZERO,");
-	if(statreg & ESP_STAT_PERR)
+	if (statreg & ESP_STAT_PERR)
 		printk("P_ERROR,");
-	if(statreg & ESP_STAT_SPAM)
+	if (statreg & ESP_STAT_SPAM)
 		printk("SPAM,");
-	if(statreg & ESP_STAT_INTR)
+	if (statreg & ESP_STAT_INTR)
 		printk("IRQ,");
 	printk(">");
 }
 
 /* Print the interrupt register's value */
-static inline void esp_print_ireg(unchar intreg)
+static inline void esp_print_ireg(u8 intreg)
 {
 	printk("INTREG< ");
-	if(intreg & ESP_INTR_S)
+	if (intreg & ESP_INTR_S)
 		printk("SLCT_NATN ");
-	if(intreg & ESP_INTR_SATN)
+	if (intreg & ESP_INTR_SATN)
 		printk("SLCT_ATN ");
-	if(intreg & ESP_INTR_RSEL)
+	if (intreg & ESP_INTR_RSEL)
 		printk("RSLCT ");
-	if(intreg & ESP_INTR_FDONE)
+	if (intreg & ESP_INTR_FDONE)
 		printk("FDONE ");
-	if(intreg & ESP_INTR_BSERV)
+	if (intreg & ESP_INTR_BSERV)
 		printk("BSERV ");
-	if(intreg & ESP_INTR_DC)
+	if (intreg & ESP_INTR_DC)
 		printk("DISCNCT ");
-	if(intreg & ESP_INTR_IC)
+	if (intreg & ESP_INTR_IC)
 		printk("ILL_CMD ");
-	if(intreg & ESP_INTR_SR)
+	if (intreg & ESP_INTR_SR)
 		printk("SCSI_BUS_RESET ");
 	printk(">");
 }
 
 /* Print the sequence step registers contents */
-static inline void esp_print_seqreg(unchar stepreg)
+static inline void esp_print_seqreg(u8 stepreg)
 {
 	stepreg &= ESP_STEP_VBITS;
 	printk("STEP<%s>",
@@ -306,7 +307,7 @@
 
 static char *phase_string(int phase)
 {
-	switch(phase) {
+	switch (phase) {
 	case not_issued:
 		return "UNISSUED";
 	case in_slct_norm:
@@ -374,17 +375,24 @@
 #endif
 
 #ifdef DEBUG_ESP_CMDS
-extern inline void esp_cmd(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			   unchar cmd)
+extern inline void esp_cmd(struct esp *esp, u8 cmd)
 {
 	esp->espcmdlog[esp->espcmdent] = cmd;
 	esp->espcmdent = (esp->espcmdent + 1) & 31;
-	eregs->esp_cmd = cmd;
+	sbus_writeb(cmd, esp->eregs + ESP_CMD);
 }
 #else
-#define esp_cmd(__esp, __eregs, __cmd)	(__eregs)->esp_cmd = (__cmd)
+#define esp_cmd(__esp, __cmd)	\
+	sbus_writeb((__cmd), ((__esp)->eregs) + ESP_CMD)
 #endif
 
+#define ESP_INTSOFF(__dregs)	\
+	sbus_writel(sbus_readl((__dregs)+DMA_CSR)&~(DMA_INT_ENAB), (__dregs)+DMA_CSR)
+#define ESP_INTSON(__dregs)	\
+	sbus_writel(sbus_readl((__dregs)+DMA_CSR)|DMA_INT_ENAB, (__dregs)+DMA_CSR)
+#define ESP_IRQ_P(__dregs)	\
+	(sbus_readl((__dregs)+DMA_CSR) & (DMA_HNDL_INTR|DMA_HNDL_ERROR))
+
 /* How we use the various Linux SCSI data structures for operation.
  *
  * struct scsi_cmnd:
@@ -412,10 +420,10 @@
 	Scsi_Cmnd *end;
 
 	new_SC->host_scribble = (unsigned char *) NULL;
-	if(!*SC)
+	if (!*SC)
 		*SC = new_SC;
 	else {
-		for(end=*SC;end->host_scribble;end=(Scsi_Cmnd *)end->host_scribble)
+		for (end=*SC;end->host_scribble;end=(Scsi_Cmnd *)end->host_scribble)
 			;
 		end->host_scribble = (unsigned char *) new_SC;
 	}
@@ -431,7 +439,7 @@
 {
 	Scsi_Cmnd *ptr;
 	ptr = *SC;
-	if(ptr)
+	if (ptr)
 		*SC = (Scsi_Cmnd *) (*SC)->host_scribble;
 	return ptr;
 }
@@ -440,12 +448,12 @@
 {
 	Scsi_Cmnd *ptr, *prev;
 
-	for(ptr = *SC, prev = NULL;
-	    ptr && ((ptr->target != target) || (ptr->lun != lun));
-	    prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble)
+	for (ptr = *SC, prev = NULL;
+	     ptr && ((ptr->target != target) || (ptr->lun != lun));
+	     prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble)
 		;
-	if(ptr) {
-		if(prev)
+	if (ptr) {
+		if (prev)
 			prev->host_scribble=ptr->host_scribble;
 		else
 			*SC=(Scsi_Cmnd *)ptr->host_scribble;
@@ -454,61 +462,61 @@
 }
 
 /* Resetting various pieces of the ESP scsi driver chipset/buses. */
-static void esp_reset_dma(struct Sparc_ESP *esp)
+static void esp_reset_dma(struct esp *esp)
 {
-	struct sparc_dma_registers *dregs = esp->dregs;
 	unsigned long flags;
 	int can_do_burst16, can_do_burst32, can_do_burst64;
 	int can_do_sbus64;
+	u32 tmp;
 
-	can_do_burst16 = esp->bursts & DMA_BURST16;
-	can_do_burst32 = esp->bursts & DMA_BURST32;
+	can_do_burst16 = (esp->bursts & DMA_BURST16) != 0;
+	can_do_burst32 = (esp->bursts & DMA_BURST32) != 0;
 	can_do_burst64 = 0;
 	can_do_sbus64 = 0;
-#ifdef __sparc_v9__
-	/* XXX Can sun4d do these too? */
-	can_do_burst64 = esp->bursts & DMA_BURST64;
-	can_do_sbus64 = 1;
-	mmu_set_sbus64(esp->edev, esp->bursts);
-#endif
+	if (sbus_can_dma_64bit(esp->sdev))
+		can_do_sbus64 = 1;
+	if (sbus_can_burst64(esp->sdev))
+		can_do_burst64 = (esp->bursts & DMA_BURST64) != 0;
 
 	/* Punt the DVMA into a known state. */
-	if(esp->dma->revision != dvmahme) {
-		dregs->cond_reg |= DMA_RST_SCSI;
-		dregs->cond_reg &= ~(DMA_RST_SCSI);
+	if (esp->dma->revision != dvmahme) {
+		tmp = sbus_readl(esp->dregs + DMA_CSR);
+		sbus_writel(tmp | DMA_RST_SCSI, esp->dregs + DMA_CSR);
+		sbus_writel(tmp & ~DMA_RST_SCSI, esp->dregs + DMA_CSR);
 	}
-	switch(esp->dma->revision) {
+	switch (esp->dma->revision) {
 	case dvmahme:
 		/* This is the HME DVMA gate array. */
 
 		save_flags(flags); cli(); /* I really hate this chip. */
 
-		dregs->cond_reg = DMA_RESET_FAS366;   /* Reset interface to FAS */
-		dregs->cond_reg = DMA_RST_SCSI;       /* Reset DVMA itself */
+		sbus_writel(DMA_RESET_FAS366, esp->dregs + DMA_CSR);
+		sbus_writel(DMA_RST_SCSI, esp->dregs + DMA_CSR);
 
 		esp->prev_hme_dmacsr = (DMA_PARITY_OFF|DMA_2CLKS|DMA_SCSI_DISAB|DMA_INT_ENAB);
 		esp->prev_hme_dmacsr &= ~(DMA_ENABLE|DMA_ST_WRITE|DMA_BRST_SZ);
 
-		if(can_do_burst32)
-			esp->prev_hme_dmacsr |= DMA_BRST32;
-		else if(can_do_burst64)
+		if (can_do_burst64)
 			esp->prev_hme_dmacsr |= DMA_BRST64;
+		else if (can_do_burst32)
+			esp->prev_hme_dmacsr |= DMA_BRST32;
 
-		if(can_do_sbus64)
+		if (can_do_sbus64) {
 			esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64;
+			sbus_set_sbus64(esp->sdev, esp->bursts);
+		}
 
 		/* This chip is horrible. */
-		while(dregs->cond_reg & DMA_PEND_READ)
+		while (sbus_readl(esp->dregs + DMA_CSR) & DMA_PEND_READ)
 			udelay(1);
 
-		dregs->cond_reg = 0;
-
-		dregs->cond_reg = esp->prev_hme_dmacsr;
+		sbus_writel(0, esp->dregs + DMA_CSR);
+		sbus_writel(esp->prev_hme_dmacsr, esp->dregs + DMA_CSR);
 
 		/* This is necessary to avoid having the SCSI channel
 		 * engine lock up on us.
 		 */
-		dregs->st_addr = 0;
+		sbus_writel(0, esp->dregs + DMA_ADDR);
 
 		restore_flags(flags);
 		break;
@@ -516,60 +524,68 @@
 		/* This is the gate array found in the sun4m
 		 * NCR SBUS I/O subsystem.
 		 */
-		if(esp->erev != esp100)
-			dregs->cond_reg |= DMA_3CLKS;
+		if (esp->erev != esp100) {
+			tmp = sbus_readl(esp->dregs + DMA_CSR);
+			sbus_writel(tmp | DMA_3CLKS, esp->dregs + DMA_CSR);
+		}
 		break;
 	case dvmarev3:
-		dregs->cond_reg &= ~(DMA_3CLKS);
-		dregs->cond_reg |= DMA_2CLKS;
-		if(can_do_burst32) {
-			dregs->cond_reg &= ~(DMA_BRST_SZ);
-			dregs->cond_reg |= DMA_BRST32;
+		tmp = sbus_readl(esp->dregs + DMA_CSR);
+		tmp &= ~DMA_3CLKS;
+		tmp |= DMA_2CLKS;
+		if (can_do_burst32) {
+			tmp &= ~DMA_BRST_SZ;
+			tmp |= DMA_BRST32;
 		}
+		sbus_writel(tmp, esp->dregs + DMA_CSR);
 		break;
 	case dvmaesc1:
 		/* This is the DMA unit found on SCSI/Ether cards. */
-		dregs->cond_reg |= DMA_ADD_ENABLE;
-		dregs->cond_reg &= ~DMA_BCNT_ENAB;
-		if(!can_do_burst32 && can_do_burst16) {
-			dregs->cond_reg |= DMA_ESC_BURST;
+		tmp = sbus_readl(esp->dregs + DMA_CSR);
+		tmp |= DMA_ADD_ENABLE;
+		tmp &= ~DMA_BCNT_ENAB;
+		if (!can_do_burst32 && can_do_burst16) {
+			tmp |= DMA_ESC_BURST;
 		} else {
-			dregs->cond_reg &= ~(DMA_ESC_BURST);
+			tmp &= ~(DMA_ESC_BURST);
 		}
+		sbus_writel(tmp, esp->dregs + DMA_CSR);
 		break;
 	default:
 		break;
 	};
-	DMA_INTSON(dregs);
+	ESP_INTSON(esp->dregs);
 }
 
 /* Reset the ESP chip, _not_ the SCSI bus. */
-static void esp_reset_esp(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
+static void __init esp_reset_esp(struct esp *esp)
 {
-	int family_code, version, i;
-	volatile int trash;
+	u8 family_code, version;
+	int i;
 
 	/* Now reset the ESP chip */
-	esp_cmd(esp, eregs, ESP_CMD_RC);
-	esp_cmd(esp, eregs, ESP_CMD_NULL | ESP_CMD_DMA);
-	esp_cmd(esp, eregs, ESP_CMD_NULL | ESP_CMD_DMA);
+	esp_cmd(esp, ESP_CMD_RC);
+	esp_cmd(esp, ESP_CMD_NULL | ESP_CMD_DMA);
+	esp_cmd(esp, ESP_CMD_NULL | ESP_CMD_DMA);
 
 	/* Reload the configuration registers */
-	eregs->esp_cfact = esp->cfact;
-	eregs->esp_stp   = esp->prev_stp = 0;
-	eregs->esp_soff  = esp->prev_soff = 0;
-	eregs->esp_timeo = esp->neg_defp;
+	sbus_writeb(esp->cfact, esp->eregs + ESP_CFACT);
+	esp->prev_stp = 0;
+	sbus_writeb(esp->prev_stp, esp->eregs + ESP_STP);
+	esp->prev_soff = 0;
+	sbus_writeb(esp->prev_soff, esp->eregs + ESP_SOFF);
+	sbus_writeb(esp->neg_defp, esp->eregs + ESP_TIMEO);
 
 	/* This is the only point at which it is reliable to read
 	 * the ID-code for a fast ESP chip variants.
 	 */
 	esp->max_period = ((35 * esp->ccycle) / 1000);
-	if(esp->erev == fast) {
-		version = eregs->esp_uid;
+	if (esp->erev == fast) {
+		version = sbus_readb(esp->eregs + ESP_UID);
 		family_code = (version & 0xf8) >> 3;
-		if(family_code == 0x02)
+		if (family_code == 0x02)
 			esp->erev = fas236;
-		else if(family_code == 0x0a)
+		else if (family_code == 0x0a)
 			esp->erev = fashme; /* Version is usually '5'. */
 		else
 			esp->erev = fas100a;
@@ -586,28 +602,29 @@
 	esp->max_period = (esp->max_period + 3)>>2;
 	esp->min_period = (esp->min_period + 3)>>2;
 
-	eregs->esp_cfg1  = esp->config1;
-	switch(esp->erev) {
+	sbus_writeb(esp->config1, esp->eregs + ESP_CFG1);
+	switch (esp->erev) {
 	case esp100:
 		/* nothing to do */
 		break;
 	case esp100a:
-		eregs->esp_cfg2 = esp->config2;
+		sbus_writeb(esp->config2, esp->eregs + ESP_CFG2);
 		break;
 	case esp236:
 		/* Slow 236 */
-		eregs->esp_cfg2 = esp->config2;
-		eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[0];
+		sbus_writeb(esp->config2, esp->eregs + ESP_CFG2);
+		esp->prev_cfg3 = esp->config3[0];
+		sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3);
 		break;
 	case fashme:
 		esp->config2 |= (ESP_CONFIG2_HME32 | ESP_CONFIG2_HMEFENAB);
 		/* fallthrough... */
 	case fas236:
 		/* Fast 236 or HME */
-		eregs->esp_cfg2 = esp->config2;
-		for(i=0; i<8; i++) {
-			if(esp->erev == fashme) {
-				unsigned char cfg3;
+		sbus_writeb(esp->config2, esp->eregs + ESP_CFG2);
+		for (i = 0; i < 16; i++) {
+			if (esp->erev == fashme) {
+				u8 cfg3;
 
 				cfg3 = ESP_CONFIG3_FCLOCK | ESP_CONFIG3_OBPUSH;
 				if (esp->scsi_id >= 8)
@@ -617,11 +634,12 @@
 				esp->config3[i] |= ESP_CONFIG3_FCLK;
 			}
 		}
-		eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[0];
-		if(esp->erev == fashme) {
+		esp->prev_cfg3 = esp->config3[0];
+		sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3);
+		if (esp->erev == fashme) {
 			esp->radelay = 80;
 		} else {
-			if(esp->diff)
+			if (esp->diff)
 				esp->radelay = 0;
 			else
 				esp->radelay = 96;
@@ -629,10 +647,11 @@
 		break;
 	case fas100a:
 		/* Fast 100a */
-		eregs->esp_cfg2 = esp->config2;
-		for(i=0; i<8; i++)
+		sbus_writeb(esp->config2, esp->eregs + ESP_CFG2);
+		for (i = 0; i < 16; i++)
 			esp->config3[i] |= ESP_CONFIG3_FCLOCK;
-		eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[0];
+		esp->prev_cfg3 = esp->config3[0];
+		sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3);
 		esp->radelay = 32;
 		break;
 	default:
@@ -641,202 +660,201 @@
 	};
 
 	/* Eat any bitrot in the chip */
-	trash = eregs->esp_intrpt;
+	sbus_readb(esp->eregs + ESP_INTRPT);
 	udelay(100);
 }
 
 /* This places the ESP into a known state at boot time. */
-static void esp_bootup_reset(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
+static void __init esp_bootup_reset(struct esp *esp)
 {
-	volatile unchar trash;
+	u8 tmp;
 
 	/* Reset the DMA */
 	esp_reset_dma(esp);
 
 	/* Reset the ESP */
-	esp_reset_esp(esp, eregs);
+	esp_reset_esp(esp);
 
 	/* Reset the SCSI bus, but tell ESP not to generate an irq */
-	eregs->esp_cfg1 |= ESP_CONFIG1_SRRDISAB;
-	esp_cmd(esp, eregs, ESP_CMD_RS);
+	tmp = sbus_readb(esp->eregs + ESP_CFG1);
+	tmp |= ESP_CONFIG1_SRRDISAB;
+	sbus_writeb(tmp, esp->eregs + ESP_CFG1);
+
+	esp_cmd(esp, ESP_CMD_RS);
 	udelay(400);
-	eregs->esp_cfg1 = esp->config1;
+
+	sbus_writeb(esp->config1, esp->eregs + ESP_CFG1);
 
 	/* Eat any bitrot in the chip and we are done... */
-	trash = eregs->esp_intrpt;
+	sbus_readb(esp->eregs + ESP_INTRPT);
 }
 
-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 Sparc_ESP *esp, *elink;
-	struct Scsi_Host *esp_host;
-	struct Sparc_ESP_regs *eregs;
-	struct sparc_dma_registers *dregs;
-	struct Linux_SBus_DMA *dma, *dlink;
-	unsigned int fmhz;
-	unchar ccf, bsizes, bsizes_more;
-	int esp_node, i;
-	
-	esp_host = scsi_register(tpnt, sizeof(struct Sparc_ESP));
-	if(!esp_host)
-		panic("Cannot register ESP SCSI host");
-	if(hme)
-		esp_host->max_id = 16;
-	esp = (struct Sparc_ESP *) esp_host->hostdata;
-	if(!esp)
-		panic("No esp in hostdata");
-	esp->ehost = esp_host;
-	esp->edev = esp_dev;
-	esp->esp_id = id;
-
-#ifdef __sparc_v9__
-	esp_host->unchecked_isa_dma = 1;
-#endif
-
-	/* Put into the chain of esp chips detected */
-	if(espchain) {
-		elink = espchain;
-		while(elink->next) elink = elink->next;
+static void esp_chain_add(struct esp *esp)
+{
+	spin_lock_irq(&espchain_lock);
+	if (espchain) {
+		struct esp *elink = espchain;
+		while (elink->next)
+			elink = elink->next;
 		elink->next = esp;
 	} else {
 		espchain = esp;
 	}
-	esp->next = 0;
+	esp->next = NULL;
+	spin_unlock_irq(&espchain_lock);
+}
+
+static void esp_chain_del(struct esp *esp)
+{
+	spin_lock_irq(&espchain_lock);
+	if (espchain == esp) {
+		espchain = esp->next;
+	} else {
+		struct esp *elink = espchain;
+		while (elink->next != esp)
+			elink = elink->next;
+		elink->next = esp->next;
+	}
+	esp->next = NULL;
+	spin_unlock_irq(&espchain_lock);
+}
 
-	/* Get misc. prom information */
-#define ESP_IS_MY_DVMA(esp, dma)  \
-	(!dma->SBus_dev || \
-	 ((esp->edev->my_bus == dma->SBus_dev->my_bus) && \
-          (esp->edev->slot == dma->SBus_dev->slot) && \
-	  (!strcmp(dma->SBus_dev->prom_name, "dma") || \
-	   !strcmp(dma->SBus_dev->prom_name, "espdma"))))
+static int __init esp_find_dvma(struct esp *esp, struct sbus_dev *dma_sdev)
+{
+	struct sbus_dev *sdev = esp->sdev;
+	struct sbus_dma *dma;
 
-	esp_node = esp_dev->prom_node;
-	prom_getstring(esp_node, "name", esp->prom_name,
-		       sizeof(esp->prom_name));
-	esp->prom_node = esp_node;
-	if(espdma) {
-		for_each_dvma(dlink) {
-			if(dlink->SBus_dev == espdma)
+	if (dma_sdev != NULL) {
+		for_each_dvma(dma) {
+			if (dma->sdev == dma_sdev)
 				break;
 		}
 	} else {
-		for_each_dvma(dlink) {
-			if(ESP_IS_MY_DVMA(esp, dlink) &&
-			   !dlink->allocated)
+		for_each_dvma(dma) {
+			/* If allocated already, can't use it. */
+			if (dma->allocated)
+				continue;
+
+			if (dma->sdev == NULL)
+				break;
+
+			/* If bus + slot are the same and it has the
+			 * correct OBP name, it's ours.
+			 */
+			if (sdev->bus == dma->sdev->bus &&
+			    sdev->slot == dma->sdev->slot &&
+			    (!strcmp(dma->sdev->prom_name, "dma") ||
+			     !strcmp(dma->sdev->prom_name, "espdma")))
 				break;
 		}
 	}
-#undef ESP_IS_MY_DVMA
+
 	/* If we don't know how to handle the dvma,
 	 * do not use this device.
 	 */
-	if(!dlink){
-		printk ("Cannot find dvma for ESP%d's SCSI\n",
-			esp->esp_id);
-		scsi_unregister (esp_host);
+	if (dma == NULL) {
+		printk("Cannot find dvma for ESP%d's SCSI\n", esp->esp_id);
 		return -1;
 	}
-	if (dlink->allocated){
-		printk ("esp%d: can't use my espdma\n",
-			esp->esp_id);
-		scsi_unregister (esp_host);
+	if (dma->allocated) {
+		printk("esp%d: can't use my espdma\n", esp->esp_id);
 		return -1;
 	}
-	dlink->allocated = 1;
-	dma = dlink;
+	dma->allocated = 1;
 	esp->dma = dma;
-	esp->dregs = dregs = dma->regs;
+	esp->dregs = dma->regs;
 
-	/* Map in the ESP registers from I/O space */
-	if(!hme) {
-		prom_apply_sbus_ranges(esp->edev->my_bus, 
-				       esp->edev->reg_addrs,
-				       1, esp->edev);
-
-		esp->eregs = eregs = (struct Sparc_ESP_regs *)
-		sparc_alloc_io(esp->edev->reg_addrs[0].phys_addr, 0,
-			       PAGE_SIZE, "ESP Registers",
-			       esp->edev->reg_addrs[0].which_io, 0x0);
-	} else {
-		/* On HME, two reg sets exist, first is DVMA,
-		 * second is ESP registers.
-		 */
-		esp->eregs = eregs = (struct Sparc_ESP_regs *)
-		sparc_alloc_io(esp->edev->reg_addrs[1].phys_addr, 0,
-			       PAGE_SIZE, "ESP Registers",
-			       esp->edev->reg_addrs[1].which_io, 0x0);
-	}
-	if(!eregs)
-		panic("ESP registers unmappable");
-	esp->esp_command =
-		sparc_dvma_malloc(16, "ESP DVMA Cmd Block",
-				  &esp->esp_command_dvma);
-	if(!esp->esp_command || !esp->esp_command_dvma)
-		panic("ESP DVMA transport area unmappable");
-
-	/* Set up the irq's etc. */
-	esp->ehost->base = (unsigned char *) esp->eregs;
-	esp->ehost->io_port =
-		esp->edev->reg_addrs[0].phys_addr;
-	esp->ehost->n_io_port = (unsigned char)
-		esp->edev->reg_addrs[0].reg_size;
-	esp->ehost->irq = esp->irq = esp->edev->irqs[0];
-
-#ifndef __sparc_v9__
-	if (sparc_cpu_model != sun4d) {
-		/* Allocate the irq only if necessary */
-		for_each_esp(elink) {
-			if((elink != esp) && (esp->irq == elink->irq)) {
-				goto esp_irq_acquired; /* BASIC rulez */
-			}
-		}
-		if(request_irq(esp->ehost->irq, esp_intr, SA_SHIRQ,
-			       "Sparc ESP SCSI", NULL))
-			panic("Cannot acquire ESP irq line");
-esp_irq_acquired:
-		printk("esp%d: IRQ %d ", esp->esp_id, esp->ehost->irq);
-	} else {
-		if (request_irq(esp->ehost->irq, esp_intr_4d,
-			SA_SHIRQ, "Sparc ESP SCSI", esp))
-			panic("Cannot acquire ESP irq line");
-		printk("esp%d: IRQ %s ", esp->esp_id, __irq_itoa(esp->ehost->irq));
-	}
-#else
-	/* On Ultra we must always call request_irq for each
-	 * esp, so that imap registers get setup etc.
+	return 0;
+}
+
+static int __init esp_map_regs(struct esp *esp, int hme)
+{
+	struct sbus_dev *sdev = esp->sdev;
+	struct resource *res;
+
+	/* On HME, two reg sets exist, first is DVMA,
+	 * second is ESP registers.
 	 */
-	if(request_irq(esp->ehost->irq, esp_intr,
-		       SA_SHIRQ, "Sparc ESP SCSI", esp))
-		panic("Cannot acquire ESP irq line");
-	printk("esp%d: IRQ %s ",
-	       esp->esp_id, __irq_itoa(esp->ehost->irq));
-#endif
+	if (hme)
+		res = &sdev->resource[1];
+	else
+		res = &sdev->resource[0];
+
+	esp->eregs = sbus_ioremap(res, 0, ESP_REG_SIZE, "ESP Registers");
+
+	if (esp->eregs == 0)
+		return -1;
+	return 0;
+}
+
+static int __init esp_map_cmdarea(struct esp *esp)
+{
+	struct sbus_dev *sdev = esp->sdev;
+
+	esp->esp_command = sbus_alloc_consistant(sdev, 16,
+						 &esp->esp_command_dvma);
+	if (esp->esp_command == NULL ||
+	    esp->esp_command_dvma == 0)
+		return -1;
+	return 0;
+}
+
+static int __init esp_register_irq(struct esp *esp)
+{
+	esp->ehost->irq = esp->irq = esp->sdev->irqs[0];
+
+	/* We used to try various overly-clever things to
+	 * reduce the interrupt processing overhead on
+	 * sun4c/sun4m when multiple ESP's shared the
+	 * same IRQ.  It was too complex and messy to
+	 * sanely maintain.
+	 */
+	if (request_irq(esp->ehost->irq, esp_intr,
+			SA_SHIRQ, "ESP SCSI", esp)) {
+		printk("esp%d: Cannot acquire irq line\n",
+		       esp->esp_id);
+		return -1;
+	}
+
+	printk("esp%d: IRQ %s ", esp->esp_id,
+	       __irq_itoa(esp->ehost->irq));
+
+	return 0;
+}
+
+static void __init esp_get_scsi_id(struct esp *esp)
+{
+	struct sbus_dev *sdev = esp->sdev;
 
-	/* Figure out our scsi ID on the bus */
 	esp->scsi_id = prom_getintdefault(esp->prom_node,
 					  "initiator-id",
 					  -1);
-	if(esp->scsi_id == -1)
+	if (esp->scsi_id == -1)
 		esp->scsi_id = prom_getintdefault(esp->prom_node,
 						  "scsi-initiator-id",
 						  -1);
-	if(esp->scsi_id == -1)
-		esp->scsi_id = (!esp->edev->my_bus) ? 7 :
-			prom_getintdefault(esp->edev->my_bus->prom_node,
+	if (esp->scsi_id == -1)
+		esp->scsi_id = (sdev->bus == NULL) ? 7 :
+			prom_getintdefault(sdev->bus->prom_node,
 					   "scsi-initiator-id",
 					   7);
 	esp->ehost->this_id = esp->scsi_id;
 	esp->scsi_id_mask = (1 << esp->scsi_id);
 
-	/* Check for differential SCSI-bus */
-	esp->diff = prom_getbool(esp->prom_node, "differential");
-	if(esp->diff)
-		printk("Differential ");
+}
 
-	/* Check out the clock properties of the chip. */
+static void __init esp_get_clock_params(struct esp *esp)
+{
+	struct sbus_dev *sdev = esp->sdev;
+	int prom_node = esp->prom_node;
+	int sbus_prom_node;
+	unsigned int fmhz;
+	u8 ccf;
+
+	if (sdev != NULL && sdev->bus != NULL)
+		sbus_prom_node = sdev->bus->prom_node;
+	else
+		sbus_prom_node = 0;
 
 	/* This is getting messy but it has to be done
 	 * correctly or else you get weird behavior all
@@ -884,19 +902,17 @@
 	 *    period we could ever handle on this ESP.
 	 */
 
-	fmhz = prom_getintdefault(esp->prom_node,
-				  "clock-frequency",
-				  -1);
-	if(fmhz==-1)
-		fmhz = (!esp->edev->my_bus) ? 0 :
-			prom_getintdefault(esp->edev->my_bus->prom_node,
-					   "clock-frequency",
-					   -1);
-	if(fmhz <= (5000000))
+	fmhz = prom_getintdefault(prom_node, "clock-frequency", -1);
+	if (fmhz == -1)
+		fmhz = (!sbus_prom_node) ? 0 :
+			prom_getintdefault(sbus_prom_node, "clock-frequency", -1);
+
+	if (fmhz <= (5000000))
 		ccf = 0;
 	else
 		ccf = (((5000000 - 1) + (fmhz))/(5000000));
-	if(!ccf || ccf > 8) {
+
+	if (!ccf || ccf > 8) {
 		/* If we can't find anything reasonable,
 		 * just assume 20MHZ.  This is the clock
 		 * frequency of the older sun4c's where I've
@@ -907,91 +923,134 @@
 		ccf = ESP_CCF_F4;
 		fmhz = (20000000);
 	}
-	if(ccf==(ESP_CCF_F7+1))
+
+	if (ccf == (ESP_CCF_F7 + 1))
 		esp->cfact = ESP_CCF_F0;
-	else if(ccf == ESP_CCF_NEVER)
+	else if (ccf == ESP_CCF_NEVER)
 		esp->cfact = ESP_CCF_F2;
 	else
 		esp->cfact = ccf;
+	esp->raw_cfact = ccf;
+
 	esp->cfreq = fmhz;
 	esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz);
 	esp->ctick = ESP_TICK(ccf, esp->ccycle);
 	esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);
 	esp->sync_defp = SYNC_DEFP_SLOW;
-	printk("SCSI ID %d Clk %dMHz CCF=%d TOut %d ",
+
+	printk("SCSI ID %d Clk %dMHz CCYC=%d CCF=%d TOut %d ",
 	       esp->scsi_id, (fmhz / 1000000),
-	       ccf, (int) esp->neg_defp);
+	       (int)esp->ccycle, (int)ccf, (int) esp->neg_defp);
+}
+
+static void __init esp_get_bursts(struct esp *esp, struct sbus_dev *dma)
+{
+	struct sbus_dev *sdev = esp->sdev;
+	u8 bursts;
 
-	/* Find the burst sizes this dma/sbus/esp supports. */
-	bsizes = prom_getintdefault(esp->prom_node, "burst-sizes", 0xff);
-	bsizes &= 0xff;
-	if(espdma) {
-		bsizes_more = prom_getintdefault(
-				  espdma->prom_node,
-				  "burst-sizes", 0xff);
-		if(bsizes_more != 0xff)
-			bsizes &= bsizes_more;
-	}
-	if (esp->edev->my_bus) {
-		bsizes_more = prom_getintdefault(esp->edev->my_bus->prom_node,
-						 "burst-sizes", 0xff);
-		if(bsizes_more != 0xff)
-			bsizes &= bsizes_more;
-	}
-
-	if(bsizes == 0xff || (bsizes & DMA_BURST16)==0 ||
-	   (bsizes & DMA_BURST32)==0)
-		bsizes = (DMA_BURST32 - 1);
+	bursts = prom_getintdefault(esp->prom_node, "burst-sizes", 0xff);
+
+	if (dma) {
+		u8 tmp = prom_getintdefault(dma->prom_node,
+					    "burst-sizes", 0xff);
+		if (tmp != 0xff)
+			bursts &= tmp;
+	}
+
+	if (sdev->bus) {
+		u8 tmp = prom_getintdefault(sdev->bus->prom_node,
+					    "burst-sizes", 0xff);
+		if (tmp != 0xff)
+			bursts &= tmp;
+	}
+
+	if (bursts == 0xff ||
+	    (bursts & DMA_BURST16) == 0 ||
+	    (bursts & DMA_BURST32) == 0)
+		bursts = (DMA_BURST32 - 1);
+
+	esp->bursts = bursts;
+}
 
-	esp->bursts = bsizes;
+static void __init esp_get_revision(struct esp *esp)
+{
+	u8 tmp;
 
-	/* Probe the revision of this esp */
 	esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
 	esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
-	eregs->esp_cfg2 = esp->config2;
-	if((eregs->esp_cfg2 & ~(ESP_CONFIG2_MAGIC)) !=
-	   (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
-		printk("NCR53C90(esp100)\n");
+	sbus_writeb(esp->config2, esp->eregs + ESP_CFG2);
+
+	tmp = sbus_readb(esp->eregs + ESP_CFG2);
+	tmp &= ~ESP_CONFIG2_MAGIC;
+	if (tmp != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
+		/* If what we write to cfg2 does not come back, cfg2
+		 * is not implemented, therefore this must be a plain
+		 * esp100.
+		 */
 		esp->erev = esp100;
+		printk("NCR53C90(esp100)\n");
 	} else {
-		eregs->esp_cfg2 = esp->config2 = 0;
-		eregs->esp_cfg3 = 0;
-		eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[0] = 5;
-		if(eregs->esp_cfg3 != 5) {
-			printk("NCR53C90A(esp100a)\n");
+		esp->config2 = 0;
+		esp->prev_cfg3 = esp->config3[0] = 5;
+		sbus_writeb(esp->config2, esp->eregs + ESP_CFG2);
+		sbus_writeb(0, esp->eregs + ESP_CFG3);
+		sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3);
+
+		tmp = sbus_readb(esp->eregs + ESP_CFG3);
+		if (tmp != 5) {
+			/* The cfg2 register is implemented, however
+			 * cfg3 is not, must be esp100a.
+			 */
 			esp->erev = esp100a;
+			printk("NCR53C90A(esp100a)\n");
 		} else {
 			int target;
 
-			for(target=0; target<8; target++)
+			for (target = 0; target < 16; target++)
 				esp->config3[target] = 0;
-			eregs->esp_cfg3 = esp->prev_cfg3 = 0;
-			if(ccf > ESP_CCF_F5) {
-				printk("NCR53C9XF(espfast)\n");
+			esp->prev_cfg3 = 0;
+			sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3);
+
+			/* All of cfg{1,2,3} implemented, must be one of
+			 * the fas variants, figure out which one.
+			 */
+			if (esp->raw_cfact > ESP_CCF_F5) {
 				esp->erev = fast;
-				eregs->esp_cfg2 = esp->config2 = 0;
 				esp->sync_defp = SYNC_DEFP_FAST;
+				printk("NCR53C9XF(espfast)\n");
 			} else {
-				printk("NCR53C9x(esp236)\n");
 				esp->erev = esp236;
-				eregs->esp_cfg2 = esp->config2 = 0;
+				printk("NCR53C9x(esp236)\n");
 			}
+			esp->config2 = 0;
+			sbus_writeb(esp->config2, esp->eregs + ESP_CFG2);
 		}
-	}				
+	}
+}
 
-	/* Initialize the command queues */
-	esp->current_SC = 0;
-	esp->disconnected_SC = 0;
-	esp->issue_SC = 0;
+static void __init esp_init_swstate(struct esp *esp)
+{
+	int i;
+
+	/* Driver spinlock... */
+	spin_lock_init(&esp->lock);
 
-	/* Clear the state machines. */
+	/* Command queues... */
+	esp->current_SC = NULL;
+	esp->disconnected_SC = NULL;
+	esp->issue_SC = NULL;
+
+	/* Target and current command state... */
 	esp->targets_present = 0;
 	esp->resetting_bus = 0;
 	esp->snip = 0;
-	esp->targets_present = 0;
+
+	/* Debugging... */
 	for(i = 0; i < 32; i++)
 		esp->espcmdlog[i] = 0;
 	esp->espcmdent = 0;
+
+	/* MSG phase state... */
 	for(i = 0; i < 16; i++) {
 		esp->cur_msgout[i] = 0;
 		esp->cur_msgin[i] = 0;
@@ -1002,11 +1061,73 @@
 	/* Clear the one behind caches to hold unmatchable values. */
 	esp->prev_soff = esp->prev_stp = esp->prev_cfg3 = 0xff;
 	esp->prev_hme_dmacsr = 0xffffffff;
+}
+
+static int __init detect_one_esp(Scsi_Host_Template *tpnt, struct sbus_dev *esp_dev,
+				 struct sbus_dev *espdma, struct sbus_bus *sbus,
+				 int id, int hme)
+{
+	struct Scsi_Host *esp_host = scsi_register(tpnt, sizeof(struct esp));
+	struct esp *esp;
+	
+	if (!esp_host) {
+		printk("ESP: Cannot register SCSI host\n");
+		return -1;
+	}
+	if (hme)
+		esp_host->max_id = 16;
+	esp = (struct esp *) esp_host->hostdata;
+	esp->ehost = esp_host;
+	esp->sdev = esp_dev;
+	esp->esp_id = id;
+	esp->prom_node = esp_dev->prom_node;
+	prom_getstring(esp->prom_node, "name", esp->prom_name,
+		       sizeof(esp->prom_name));
+
+	esp_chain_add(esp);
+	if (esp_find_dvma(esp, espdma) < 0)
+		goto fail_unlink;
+	if (esp_map_regs(esp, hme) < 0) {
+		printk("ESP registers unmappable");
+		goto fail_dvma_release;
+	}
+	if (esp_map_cmdarea(esp) < 0) {
+		printk("ESP DVMA transport area unmappable");
+		goto fail_unmap_regs;
+	}
+	if (esp_register_irq(esp) < 0)
+		goto fail_unmap_cmdarea;
+
+	esp_get_scsi_id(esp);
+
+	esp->diff = prom_getbool(esp->prom_node, "differential");
+	if (esp->diff)
+		printk("Differential ");
+
+	esp_get_clock_params(esp);
+	esp_get_bursts(esp, espdma);
+	esp_get_revision(esp);
+	esp_init_swstate(esp);
 
-	/* Reset the thing before we try anything... */
-	esp_bootup_reset(esp, eregs);
+	esp_bootup_reset(esp);
 
 	return 0;
+
+fail_unmap_cmdarea:
+	sbus_free_consistant(esp->sdev, 16,
+			     (void *) esp->esp_command,
+			     esp->esp_command_dvma);
+
+fail_unmap_regs:
+	sbus_iounmap(esp->eregs, ESP_REG_SIZE);
+
+fail_dvma_release:
+	esp->dma->allocated = 0;
+
+fail_unlink:
+	esp_chain_del(esp);
+	scsi_unregister(esp_host);
+	return -1;
 }
 
 /* Detecting ESP chips on the machine.  This is the simple and easy
@@ -1019,20 +1140,23 @@
 
 int __init esp_detect(Scsi_Host_Template *tpnt)
 {
-	static struct linux_sbus_device esp_dev;
+	static struct sbus_dev esp_dev;
 	int esps_in_use = 0;
 
 	espchain = 0;
 
-	if(sun4_esp_physaddr) {
+	if (sun4_esp_physaddr) {
 		memset (&esp_dev, 0, sizeof(esp_dev));
 		esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr;
 		esp_dev.irqs[0] = 4;
+		esp_dev.resource[0].start = sun4_esp_physaddr;
+		esp_dev.resource[0].end = sun4_esp_physaddr + ESP_REG_SIZE - 1;
+		esp_dev.resource[0].flags = IORESOURCE_IO;
 
 		if (!detect_one_esp(tpnt, &esp_dev, NULL, NULL, 0, 0))
 			esps_in_use++;
 		printk("ESP: Total of 1 ESP hosts found, %d actually in use.\n", esps_in_use);
-		esps_running = esps_in_use;
+		esps_running =  esps_in_use;
 	}
 	return esps_in_use;
 }
@@ -1041,12 +1165,12 @@
 
 int __init esp_detect(Scsi_Host_Template *tpnt)
 {
-	struct linux_sbus *sbus;
-	struct linux_sbus_device *esp_dev, *sbdev_iter;
+	struct sbus_bus *sbus;
+	struct sbus_dev *esp_dev, *sbdev_iter;
 	int nesps = 0, esps_in_use = 0;
 
 	espchain = 0;
-	if(!SBus_chain) {
+	if (!sbus_root) {
 #ifdef CONFIG_PCI
 		return 0;
 #else
@@ -1055,25 +1179,25 @@
 	}
 	for_each_sbus(sbus) {
 		for_each_sbusdev(sbdev_iter, sbus) {
-			struct linux_sbus_device *espdma = 0;
+			struct sbus_dev *espdma = NULL;
 			int hme = 0;
 
 			/* Is it an esp sbus device? */
 			esp_dev = sbdev_iter;
-			if(strcmp(esp_dev->prom_name, "esp") &&
-			   strcmp(esp_dev->prom_name, "SUNW,esp")) {
-				if(!strcmp(esp_dev->prom_name, "SUNW,fas")) {
+			if (strcmp(esp_dev->prom_name, "esp") &&
+			    strcmp(esp_dev->prom_name, "SUNW,esp")) {
+				if (!strcmp(esp_dev->prom_name, "SUNW,fas")) {
 					hme = 1;
 					espdma = esp_dev;
 				} else {
-					if(!esp_dev->child ||
-					   (strcmp(esp_dev->prom_name, "espdma") &&
-					    strcmp(esp_dev->prom_name, "dma")))
+					if (!esp_dev->child ||
+					    (strcmp(esp_dev->prom_name, "espdma") &&
+					     strcmp(esp_dev->prom_name, "dma")))
 						continue; /* nope... */
 					espdma = esp_dev;
 					esp_dev = esp_dev->child;
-					if(strcmp(esp_dev->prom_name, "esp") &&
-					   strcmp(esp_dev->prom_name, "SUNW,esp"))
+					if (strcmp(esp_dev->prom_name, "esp") &&
+					    strcmp(esp_dev->prom_name, "SUNW,esp"))
 						continue; /* how can this happen? */
 				}
 			}
@@ -1098,10 +1222,10 @@
  */
 const char *esp_info(struct Scsi_Host *host)
 {
-	struct Sparc_ESP *esp;
+	struct esp *esp;
 
-	esp = (struct Sparc_ESP *) host->hostdata;
-	switch(esp->erev) {
+	esp = (struct esp *) host->hostdata;
+	switch (esp->erev) {
 	case esp100:
 		return "Sparc ESP100 (NCR53C90)";
 	case esp100a:
@@ -1115,7 +1239,7 @@
 	case fas100a:
 		return "Sparc ESP100A-FAST";
 	default:
-		panic("Bogon ESP revision");
+		return "Bogon ESP revision";
 	};
 }
 
@@ -1162,7 +1286,7 @@
 	return len;
 }
 
-static int esp_host_info(struct Sparc_ESP *esp, char *ptr, off_t offset, int len)
+static int esp_host_info(struct esp *esp, char *ptr, off_t offset, int len)
 {
 	struct info_str info;
 	int i;
@@ -1173,10 +1297,10 @@
 	info.pos	= 0;
 
 	copy_info(&info, "Sparc ESP Host Adapter:\n");
-	copy_info(&info, "\tPROM node\t\t%08lx\n", (unsigned long) esp->prom_node);
+	copy_info(&info, "\tPROM node\t\t%08x\n", (unsigned int) esp->prom_node);
 	copy_info(&info, "\tPROM name\t\t%s\n", esp->prom_name);
 	copy_info(&info, "\tESP Model\t\t");
-	switch(esp->erev) {
+	switch (esp->erev) {
 	case esp100:
 		copy_info(&info, "ESP100\n");
 		break;
@@ -1204,7 +1328,7 @@
 		break;
 	};
 	copy_info(&info, "\tDMA Revision\t\t");
-	switch(esp->dma->revision) {
+	switch (esp->dma->revision) {
 	case dvmarev0:
 		copy_info(&info, "Rev 0\n");
 		break;
@@ -1231,21 +1355,21 @@
 		break;
 	};
 	copy_info(&info, "\tLive Targets\t\t[ ");
-	for(i = 0; i < 15; i++) {
-		if(esp->targets_present & (1 << i))
+	for (i = 0; i < 15; i++) {
+		if (esp->targets_present & (1 << i))
 			copy_info(&info, "%d ", i);
 	}
 	copy_info(&info, "]\n\n");
 	
 	/* Now describe the state of each existing target. */
 	copy_info(&info, "Target #\tconfig3\t\tSync Capabilities\tDisconnect\tWide\n");
-	for(i = 0; i < 15; i++) {
-		if(esp->targets_present & (1 << i)) {
+	for (i = 0; i < 15; i++) {
+		if (esp->targets_present & (1 << i)) {
 			Scsi_Device *SDptr = esp->ehost->host_queue;
 
-			while((SDptr->host != esp->ehost) &&
-			      (SDptr->id != i) &&
-			      (SDptr->next))
+			while ((SDptr->host != esp->ehost) &&
+			       (SDptr->id != i) &&
+			       (SDptr->next))
 				SDptr = SDptr->next;
 
 			copy_info(&info, "%d\t\t", i);
@@ -1257,7 +1381,6 @@
 				  (esp->config3[i] & ESP_CONFIG3_EWIDE) ? "yes" : "no");
 		}
 	}
-
 	return info.pos > info.offset? info.pos - info.offset : 0;
 }
 
@@ -1265,58 +1388,55 @@
 int esp_proc_info(char *buffer, char **start, off_t offset, int length,
 		  int hostno, int inout)
 {
-	struct Sparc_ESP *esp;
+	struct esp *esp;
 
-	if(inout)
+	if (inout)
 		return -EINVAL; /* not yet */
 
 	for_each_esp(esp) {
-		if(esp->ehost->host_no == hostno)
+		if (esp->ehost->host_no == hostno)
 			break;
 	}
-	if(!esp)
+	if (!esp)
 		return -EINVAL;
 
-	if(start)
+	if (start)
 		*start = buffer;
 
 	return esp_host_info(esp, buffer, offset, length);
 }
 
-static void esp_get_dmabufs(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
+static void esp_get_dmabufs(struct esp *esp, Scsi_Cmnd *sp)
 {
-	if(sp->use_sg == 0) {
+	if (sp->use_sg == 0) {
 		sp->SCp.this_residual = sp->request_bufflen;
 		sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
 		sp->SCp.buffers_residual = 0;
-		sp->SCp.have_data_in = mmu_get_scsi_one((char *)sp->SCp.buffer,
-							sp->SCp.this_residual,
-							esp->edev->my_bus);
+		sp->SCp.have_data_in = sbus_map_single(esp->sdev, sp->SCp.buffer,
+						       sp->SCp.this_residual);
 		sp->SCp.ptr = (char *) ((unsigned long)sp->SCp.have_data_in);
 	} else {
 		sp->SCp.buffer = (struct scatterlist *) sp->buffer;
-		sp->SCp.buffers_residual = sp->use_sg - 1;
-		sp->SCp.this_residual = sp->SCp.buffer->length;
-		mmu_get_scsi_sgl((struct mmu_sglist *) sp->SCp.buffer,
-				 sp->SCp.buffers_residual,
-				 esp->edev->my_bus);
+		sp->SCp.buffers_residual = sbus_map_sg(esp->sdev,
+						       sp->SCp.buffer,
+						       sp->use_sg);
+		sp->SCp.this_residual = sp->SCp.buffer->dvma_length;
 		sp->SCp.ptr = (char *) ((unsigned long)sp->SCp.buffer->dvma_address);
 	}
 }
 
-static void esp_release_dmabufs(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
+static void esp_release_dmabufs(struct esp *esp, Scsi_Cmnd *sp)
 {
-	if(sp->use_sg == 0)
-		mmu_release_scsi_one(sp->SCp.have_data_in,
-				     sp->request_bufflen,
-				     esp->edev->my_bus);
-	else
-		mmu_release_scsi_sgl((struct mmu_sglist *)
-				     sp->buffer, sp->use_sg - 1,
-				     esp->edev->my_bus);
+	if (sp->use_sg == 0) {
+		sbus_unmap_single(esp->sdev,
+				  sp->SCp.have_data_in,
+				  sp->request_bufflen);
+	} else {
+		sbus_unmap_sg(esp->sdev, sp->buffer, sp->use_sg);
+	}
 }
 
-static void esp_restore_pointers(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
+static void esp_restore_pointers(struct esp *esp, Scsi_Cmnd *sp)
 {
 	struct esp_pointers *ep = &esp->data_pointers[sp->target];
 
@@ -1326,7 +1446,7 @@
 	sp->SCp.buffers_residual = ep->saved_buffers_residual;
 }
 
-static void esp_save_pointers(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
+static void esp_save_pointers(struct esp *esp, Scsi_Cmnd *sp)
 {
 	struct esp_pointers *ep = &esp->data_pointers[sp->target];
 
@@ -1356,9 +1476,9 @@
  * case where we could see an interrupt is where we have disconnected
  * commands active and they are trying to reselect us.
  */
-static inline void esp_check_cmd(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
+static inline void esp_check_cmd(struct esp *esp, Scsi_Cmnd *sp)
 {
-	switch(sp->cmd_len) {
+	switch (sp->cmd_len) {
 	case 6:
 	case 10:
 	case 12:
@@ -1373,7 +1493,7 @@
 	};
 }
 
-static inline void build_sync_nego_msg(struct Sparc_ESP *esp, int period, int offset)
+static inline void build_sync_nego_msg(struct esp *esp, int period, int offset)
 {
 	esp->cur_msgout[0] = EXTENDED_MESSAGE;
 	esp->cur_msgout[1] = 3;
@@ -1384,12 +1504,12 @@
 }
 
 /* SIZE is in bits, currently HME only supports 16 bit wide transfers. */
-static inline void build_wide_nego_msg(struct Sparc_ESP *esp, int size)
+static inline void build_wide_nego_msg(struct esp *esp, int size)
 {
 	esp->cur_msgout[0] = EXTENDED_MESSAGE;
 	esp->cur_msgout[1] = 2;
 	esp->cur_msgout[2] = EXTENDED_WDTR;
-	switch(size) {
+	switch (size) {
 	case 32:
 		esp->cur_msgout[3] = 2;
 		break;
@@ -1405,28 +1525,26 @@
 	esp->msgout_len = 4;
 }
 
-static void esp_exec_cmd(struct Sparc_ESP *esp)
+static void esp_exec_cmd(struct esp *esp)
 {
-	struct sparc_dma_registers *dregs = esp->dregs;
-	struct Sparc_ESP_regs *eregs = esp->eregs;
 	Scsi_Cmnd *SCptr;
 	Scsi_Device *SDptr;
-	volatile unchar *cmdp = esp->esp_command;
-	unsigned char the_esp_command;
+	volatile u8 *cmdp = esp->esp_command;
+	u8 the_esp_command;
 	int lun, target;
 	int i;
 
 	/* Hold off if we have disconnected commands and
 	 * an IRQ is showing...
 	 */
-	if(esp->disconnected_SC && DMA_IRQ_P(dregs))
+	if (esp->disconnected_SC && ESP_IRQ_P(esp->dregs))
 		return;
 
 	/* Grab first member of the issue queue. */
 	SCptr = esp->current_SC = remove_first_SC(&esp->issue_SC);
 
 	/* Safe to panic here because current_SC is null. */
-	if(!SCptr)
+	if (!SCptr)
 		panic("esp: esp_exec_cmd and issue queue is NULL");
 
 	SDptr = SCptr->device;
@@ -1468,22 +1586,22 @@
 	 * selections should not confuse SCSI-1 we hope.
 	 */
 
-	if(SDptr->sync) {
+	if (SDptr->sync) {
 		/* this targets sync is known */
 do_sync_known:
-		if(SDptr->disconnect)
+		if (SDptr->disconnect)
 			*cmdp++ = IDENTIFY(1, lun);
 		else
 			*cmdp++ = IDENTIFY(0, lun);
 
-		if(esp->esp_slowcmd) {
+		if (esp->esp_slowcmd) {
 			the_esp_command = (ESP_CMD_SELAS | ESP_CMD_DMA);
 			esp_advance_phase(SCptr, in_slct_stop);
 		} else {
 			the_esp_command = (ESP_CMD_SELA | ESP_CMD_DMA);
 			esp_advance_phase(SCptr, in_slct_norm);
 		}
-	} else if(!(esp->targets_present & (1<<target)) || !(SDptr->disconnect)) {
+	} else if (!(esp->targets_present & (1<<target)) || !(SDptr->disconnect)) {
 		/* After the bootup SCSI code sends both the
 		 * TEST_UNIT_READY and INQUIRY commands we want
 		 * to at least attempt allowing the device to
@@ -1491,7 +1609,7 @@
 		 */
 		ESPMISC(("esp: Selecting device for first time. target=%d "
 			 "lun=%d\n", target, SCptr->lun));
-		if(!SDptr->borken && !SDptr->disconnect)
+		if (!SDptr->borken && !SDptr->disconnect)
 			SDptr->disconnect = 1;
 
 		*cmdp++ = IDENTIFY(0, lun);
@@ -1512,10 +1630,13 @@
 		 * SparcStation1 and SparcStation1+.  Allowing those
 		 * to be enabled seems to lockup the machine completely.
 		 */
-		if((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
-		   (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
-			/* But we are nice and allow tapes to disconnect. */
-			if(SDptr->type == TYPE_TAPE)
+		if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) ||
+		    (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) {
+			/* But we are nice and allow tapes and removable
+			 * disks (but not CDROMs) to disconnect.
+			 */
+			if(SDptr->type == TYPE_TAPE ||
+			   (SDptr->type != TYPE_ROM && SDptr->removable))
 				SDptr->disconnect = 1;
 			else
 				SDptr->disconnect = 0;
@@ -1531,9 +1652,10 @@
 		 * need to attempt WIDE first, before
 		 * sync nego, as per SCSI 2 standard.
 		 */
-		if(esp->erev == fashme && !SDptr->wide) {
-			if(!SDptr->borken &&
-			   SDptr->type != TYPE_ROM) {
+		if (esp->erev == fashme && !SDptr->wide) {
+			if (!SDptr->borken &&
+			   SDptr->type != TYPE_ROM &&
+			   SDptr->removable == 0) {
 				build_wide_nego_msg(esp, 16);
 				SDptr->wide = 1;
 				esp->wnip = 1;
@@ -1544,13 +1666,18 @@
 			}
 		}
 
-		if(!SDptr->borken) {
-			if((SDptr->type == TYPE_ROM)) {
+		if (!SDptr->borken) {
+			if ((SDptr->type == TYPE_ROM)) {
 				/* Nice try sucker... */
 				ESPMISC(("esp%d: Disabling sync for buggy "
 					 "CDROM.\n", esp->esp_id));
 				cdrom_hwbug_wkaround = 1;
 				build_sync_nego_msg(esp, 0, 0);
+			} else if (SDptr->removable != 0) {
+				ESPMISC(("esp%d: Not negotiating sync/wide but "
+					 "allowing disconnect for removable media.\n",
+					 esp->esp_id));
+				build_sync_nego_msg(esp, 0, 0);
 			} else {
 				build_sync_nego_msg(esp, esp->sync_defp, 15);
 			}
@@ -1584,8 +1711,10 @@
 		 *           Therefore _no_ disconnects for SCSI1 targets
 		 *           thank you very much. ;-)
 		 */
-		if(((SDptr->scsi_level < 3) && (SDptr->type != TYPE_TAPE)) ||
-		   cdrom_hwbug_wkaround || SDptr->borken) {
+		if(((SDptr->scsi_level < 3) &&
+		    (SDptr->type != TYPE_TAPE) &&
+		    SDptr->removable == 0) ||
+		    cdrom_hwbug_wkaround || SDptr->borken) {
 			ESPMISC((KERN_INFO "esp%d: Disabling DISCONNECT for target %d "
 				 "lun %d\n", esp->esp_id, SCptr->target, SCptr->lun));
 			SDptr->disconnect = 0;
@@ -1605,79 +1734,84 @@
 		esp_advance_phase(SCptr, in_slct_msg);
 	}
 
-	if(!esp->esp_slowcmd)
-		for(i = 0; i < SCptr->cmd_len; i++)
+	if (!esp->esp_slowcmd)
+		for (i = 0; i < SCptr->cmd_len; i++)
 			*cmdp++ = SCptr->cmnd[i];
 
 	/* HME sucks... */
-	if(esp->erev == fashme)
-		eregs->esp_busid = (target & 0xf) |
-			(ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT);
+	if (esp->erev == fashme)
+		sbus_writeb((target & 0xf) | (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT),
+			    esp->eregs + ESP_BUSID);
 	else
-		eregs->esp_busid = (target & 7);
+		sbus_writeb(target & 7, esp->eregs + ESP_BUSID);
 	if (esp->prev_soff != SDptr->sync_max_offset ||
 	    esp->prev_stp  != SDptr->sync_min_period ||
 	    (esp->erev > esp100a &&
 	     esp->prev_cfg3 != esp->config3[target])) {
-		eregs->esp_soff = esp->prev_soff = SDptr->sync_max_offset;
-		eregs->esp_stp  = esp->prev_stp  = SDptr->sync_min_period;
-		if(esp->erev > esp100a)
-			eregs->esp_cfg3 =
-				esp->prev_cfg3 =
-				esp->config3[target];
+		esp->prev_soff = SDptr->sync_max_offset;
+		esp->prev_stp = SDptr->sync_min_period;
+		sbus_writeb(esp->prev_soff, esp->eregs + ESP_SOFF);
+		sbus_writeb(esp->prev_stp, esp->eregs + ESP_STP);
+		if (esp->erev > esp100a) {
+			esp->prev_cfg3 = esp->config3[target];
+			sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3);
+		}
 	}
 	i = (cmdp - esp->esp_command);
 
-	if(esp->erev == fashme) {
-		esp_cmd(esp, eregs, ESP_CMD_FLUSH); /* Grrr! */
+	if (esp->erev == fashme) {
+		esp_cmd(esp, ESP_CMD_FLUSH); /* Grrr! */
 
 		/* Set up the DMA and HME counters */
-		eregs->esp_tclow = i;
-		eregs->esp_tcmed = 0;
-		eregs->fas_rlo = 0;
-		eregs->fas_rhi = 0;
-		esp_cmd(esp, eregs, the_esp_command);
+		sbus_writeb(i, esp->eregs + ESP_TCLOW);
+		sbus_writeb(0, esp->eregs + ESP_TCMED);
+		sbus_writeb(0, esp->eregs + FAS_RLO);
+		sbus_writeb(0, esp->eregs + FAS_RHI);
+		esp_cmd(esp, the_esp_command);
 
 		/* Talk about touchy hardware... */
 		esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr |
 					 (DMA_SCSI_DISAB | DMA_ENABLE)) &
 					~(DMA_ST_WRITE));
-		dregs->cnt = 16;
-		dregs->st_addr = esp->esp_command_dvma;
-		dregs->cond_reg = esp->prev_hme_dmacsr;
+		sbus_writel(16, esp->dregs + DMA_COUNT);
+		sbus_writel(esp->esp_command_dvma, esp->dregs + DMA_ADDR);
+		sbus_writel(esp->prev_hme_dmacsr, esp->dregs + DMA_CSR);
 	} else {
+		u32 tmp;
+
 		/* Set up the DMA and ESP counters */
-		eregs->esp_tclow = i;
-		eregs->esp_tcmed = 0;
-		dregs->cond_reg = ((dregs->cond_reg & ~(DMA_ST_WRITE)) | DMA_ENABLE);
-		if(esp->dma->revision == dvmaesc1) {
-			if(i) /* Workaround ESC gate array SBUS rerun bug. */
-				dregs->cnt = (PAGE_SIZE);
+		sbus_writeb(i, esp->eregs + ESP_TCLOW);
+		sbus_writeb(0, esp->eregs + ESP_TCMED);
+		tmp = sbus_readl(esp->dregs + DMA_CSR);
+		tmp &= ~DMA_ST_WRITE;
+		tmp |= DMA_ENABLE;
+		sbus_writel(tmp, esp->dregs + DMA_CSR);
+		if (esp->dma->revision == dvmaesc1) {
+			if (i) /* Workaround ESC gate array SBUS rerun bug. */
+				sbus_writel(PAGE_SIZE, esp->dregs + DMA_COUNT);
 		}
-		dregs->st_addr = esp->esp_command_dvma;
+		sbus_writel(esp->esp_command_dvma, esp->dregs + DMA_ADDR);
 
 		/* Tell ESP to "go". */
-		esp_cmd(esp, eregs, the_esp_command);
+		esp_cmd(esp, the_esp_command);
 	}
 }
 
 /* Queue a SCSI command delivered from the mid-level Linux SCSI code. */
 int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
-	struct Sparc_ESP *esp;
-	struct sparc_dma_registers *dregs;
+	struct esp *esp;
+	unsigned long flags;
 
 	/* Set up func ptr and initial driver cmd-phase. */
 	SCpnt->scsi_done = done;
 	SCpnt->SCp.phase = not_issued;
 
-	esp = (struct Sparc_ESP *) SCpnt->host->hostdata;
-	dregs = esp->dregs;
-
 	/* We use the scratch area. */
 	ESPQUEUE(("esp_queue: target=%d lun=%d ", SCpnt->target, SCpnt->lun));
 	ESPDISC(("N<%02x,%02x>", SCpnt->target, SCpnt->lun));
 
+	esp = (struct esp *) SCpnt->host->hostdata;
 	esp_get_dmabufs(esp, SCpnt);
 	esp_save_pointers(esp, SCpnt); /* FIXME for tag queueing */
 
@@ -1685,8 +1819,10 @@
 	SCpnt->SCp.Message          = 0xff;
 	SCpnt->SCp.sent_command     = 0;
 
+	spin_lock_irqsave(&esp->lock, flags);
+
 	/* Place into our queue. */
-	if(SCpnt->cmnd[0] == REQUEST_SENSE) {
+	if (SCpnt->cmnd[0] == REQUEST_SENSE) {
 		ESPQUEUE(("RQSENSE\n"));
 		prepend_SC(&esp->issue_SC, SCpnt);
 	} else {
@@ -1695,16 +1831,18 @@
 	}
 
 	/* Run it now if we can. */
-	if(!esp->current_SC && !esp->resetting_bus)
+	if (!esp->current_SC && !esp->resetting_bus)
 		esp_exec_cmd(esp);
 
+	spin_unlock_irqrestore(&esp->lock, flags);
+
 	return 0;
 }
 
 /* Only queuing supported in this ESP driver. */
 int esp_command(Scsi_Cmnd *SCpnt)
 {
-	struct Sparc_ESP *esp = (struct Sparc_ESP *) SCpnt->host->hostdata;
+	struct esp *esp = (struct esp *) SCpnt->host->hostdata;
 
 	ESPLOG(("esp%d: esp_command() called...\n", esp->esp_id));
 	return -1;
@@ -1720,8 +1858,7 @@
 		phase_string(SCptr->SCp.phase)));
 }
 
-static void esp_dump_state(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			   struct sparc_dma_registers *dregs)
+static void esp_dump_state(struct esp *esp)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 #ifdef DEBUG_ESP_CMDS
@@ -1730,40 +1867,37 @@
 
 	ESPLOG(("esp%d: dumping state\n", esp->esp_id));
 	ESPLOG(("esp%d: dma -- cond_reg<%08x> addr<%08x>\n",
-		esp->esp_id, dregs->cond_reg, dregs->st_addr));
+		esp->esp_id,
+		sbus_readl(esp->dregs + DMA_CSR),
+		sbus_readl(esp->dregs + DMA_ADDR)));
 	ESPLOG(("esp%d: SW [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
 		esp->esp_id, esp->sreg, esp->seqreg, esp->ireg));
 	ESPLOG(("esp%d: HW reread [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
-		esp->esp_id, eregs->esp_status, eregs->esp_sstep, eregs->esp_intrpt));
+		esp->esp_id,
+		sbus_readb(esp->eregs + ESP_STATUS),
+		sbus_readb(esp->eregs + ESP_SSTEP),
+		sbus_readb(esp->eregs + ESP_INTRPT)));
 #ifdef DEBUG_ESP_CMDS
 	printk("esp%d: last ESP cmds [", esp->esp_id);
 	i = (esp->espcmdent - 1) & 31;
-	printk("<");
-	esp_print_cmd(esp->espcmdlog[i]);
-	printk(">");
+	printk("<"); esp_print_cmd(esp->espcmdlog[i]); printk(">");
 	i = (i - 1) & 31;
-	printk("<");
-	esp_print_cmd(esp->espcmdlog[i]);
-	printk(">");
+	printk("<"); esp_print_cmd(esp->espcmdlog[i]); printk(">");
 	i = (i - 1) & 31;
-	printk("<");
-	esp_print_cmd(esp->espcmdlog[i]);
-	printk(">");
+	printk("<"); esp_print_cmd(esp->espcmdlog[i]); printk(">");
 	i = (i - 1) & 31;
-	printk("<");
-	esp_print_cmd(esp->espcmdlog[i]);
-	printk(">");
+	printk("<"); esp_print_cmd(esp->espcmdlog[i]); printk(">");
 	printk("]\n");
 #endif /* (DEBUG_ESP_CMDS) */
 
-	if(SCptr) {
+	if (SCptr) {
 		ESPLOG(("esp%d: current command ", esp->esp_id));
 		esp_dump_cmd(SCptr);
 	}
 	ESPLOG(("\n"));
 	SCptr = esp->disconnected_SC;
 	ESPLOG(("esp%d: disconnected ", esp->esp_id));
-	while(SCptr) {
+	while (SCptr) {
 		esp_dump_cmd(SCptr);
 		SCptr = (Scsi_Cmnd *) SCptr->host_scribble;
 	}
@@ -1773,13 +1907,14 @@
 /* Abort a command. */
 int esp_abort(Scsi_Cmnd *SCptr)
 {
-	struct Sparc_ESP *esp = (struct Sparc_ESP *) SCptr->host->hostdata;
-	struct Sparc_ESP_regs *eregs = esp->eregs;
-	struct sparc_dma_registers *dregs = esp->dregs;
+	struct esp *esp = (struct esp *) SCptr->host->hostdata;
+	unsigned long flags;
 	int don;
 
+	spin_lock_irqsave(&esp->lock, flags);
+
 	ESPLOG(("esp%d: Aborting command\n", esp->esp_id));
-	esp_dump_state(esp, eregs, dregs);
+	esp_dump_state(esp);
 
 	/* Wheee, if this is the current command on the bus, the
 	 * best we can do is assert ATN and wait for msgout phase.
@@ -1787,36 +1922,41 @@
 	 * in the driver and timeout because the eventual phase change
 	 * will cause the ESP to (eventually) give an interrupt.
 	 */
-	if(esp->current_SC == SCptr) {
+	if (esp->current_SC == SCptr) {
 		esp->cur_msgout[0] = ABORT;
 		esp->msgout_len = 1;
 		esp->msgout_ctr = 0;
-		esp_cmd(esp, eregs, ESP_CMD_SATN);
+		esp_cmd(esp, ESP_CMD_SATN);
+		spin_unlock_irqrestore(&esp->lock, flags);
 		return SCSI_ABORT_PENDING;
 	}
 
 	/* If it is still in the issue queue then we can safely
 	 * call the completion routine and report abort success.
 	 */
-	don = (dregs->cond_reg & DMA_INT_ENAB);
-	if(don) {
-		DMA_INTSOFF(dregs);
-		synchronize_irq();
+	don = (sbus_readl(esp->dregs + DMA_CSR) & DMA_INT_ENAB);
+	if (don) {
+		ESP_INTSOFF(esp->dregs);
 	}
-	if(esp->issue_SC) {
+	if (esp->issue_SC) {
 		Scsi_Cmnd **prev, *this;
-		for(prev = (&esp->issue_SC), this = esp->issue_SC;
-		    this;
-		    prev = (Scsi_Cmnd **) &(this->host_scribble),
-		    this = (Scsi_Cmnd *) this->host_scribble) {
-			if(this == SCptr) {
+		for (prev = (&esp->issue_SC), this = esp->issue_SC;
+		     this != NULL;
+		     prev = (Scsi_Cmnd **) &(this->host_scribble),
+			     this = (Scsi_Cmnd *) this->host_scribble) {
+
+			if (this == SCptr) {
 				*prev = (Scsi_Cmnd *) this->host_scribble;
 				this->host_scribble = NULL;
+
+				spin_unlock_irqrestore(&esp->lock, flags);
+
 				esp_release_dmabufs(esp, this);
 				this->result = DID_ABORT << 16;
-				this->done(this);
-				if(don)
-					DMA_INTSON(dregs);
+				this->scsi_done(this);
+				if (don)
+					ESP_INTSON(esp->dregs);
+
 				return SCSI_ABORT_SUCCESS;
 			}
 		}
@@ -1827,9 +1967,10 @@
 	 * on the bus at this time.  So, we let the SCSI code wait
 	 * a little bit and try again later.
 	 */
-	if(esp->current_SC) {
-		if(don)
-			DMA_INTSON(dregs);
+	if (esp->current_SC) {
+		if (don)
+			ESP_INTSON(esp->dregs);
+		spin_unlock_irqrestore(&esp->lock, flags);
 		return SCSI_ABORT_BUSY;
 	}
 
@@ -1840,8 +1981,9 @@
 	 * happens, we are really hung so reset the bus.
 	 */
 
-	if(don)
-		DMA_INTSON(dregs);
+	if (don)
+		ESP_INTSON(esp->dregs);
+	spin_unlock_irqrestore(&esp->lock, flags);
 	return SCSI_ABORT_SNOOZE;
 }
 
@@ -1850,28 +1992,40 @@
  * is to clean out the command queues and begin re-execution
  * of SCSI commands once more.
  */
-static int esp_finish_reset(struct Sparc_ESP *esp,
-			    struct Sparc_ESP_regs *eregs,
-			    struct sparc_dma_registers *dregs)
+static int esp_finish_reset(struct esp *esp)
 {
 	Scsi_Cmnd *sp = esp->current_SC;
 
 	/* Clean up currently executing command, if any. */
 	if (sp != NULL) {
+		esp->current_SC = NULL;
+		spin_unlock(&esp->lock);
+
 		esp_release_dmabufs(esp, sp);
 		sp->result = (DID_RESET << 16);
+
+		spin_lock(&io_request_lock);
 		sp->scsi_done(sp);
-		esp->current_SC = NULL;
+		spin_unlock(&io_request_lock);
+
+		spin_lock(&esp->lock);
 	}
 
 	/* Clean up disconnected queue, they have been invalidated
 	 * by the bus reset.
 	 */
 	if (esp->disconnected_SC) {
-		while((sp = remove_first_SC(&esp->disconnected_SC)) != NULL) {
+		while ((sp = remove_first_SC(&esp->disconnected_SC)) != NULL) {
+			spin_unlock(&esp->lock);
+
 			esp_release_dmabufs(esp, sp);
 			sp->result = (DID_RESET << 16);
+
+			spin_lock(&io_request_lock);
 			sp->scsi_done(sp);
+			spin_unlock(&io_request_lock);
+
+			spin_lock(&esp->lock);
 		}
 	}
 
@@ -1879,19 +2033,17 @@
 	esp->resetting_bus = 0;
 
 	/* Ok, now it is safe to get commands going once more. */
-	if(esp->issue_SC)
+	if (esp->issue_SC)
 		esp_exec_cmd(esp);
 
 	return do_intr_end;
 }
 
-static int esp_do_resetbus(struct Sparc_ESP *esp,
-			   struct Sparc_ESP_regs *eregs,
-			   struct sparc_dma_registers *dregs)
+static int esp_do_resetbus(struct esp *esp)
 {
 	ESPLOG(("esp%d: Resetting scsi bus\n", esp->esp_id));
 	esp->resetting_bus = 1;
-	esp_cmd(esp, eregs, ESP_CMD_RS);
+	esp_cmd(esp, ESP_CMD_RS);
 
 	return do_intr_end;
 }
@@ -1901,55 +2053,49 @@
  */
 int esp_reset(Scsi_Cmnd *SCptr, unsigned int how)
 {
-	struct Sparc_ESP *esp = (struct Sparc_ESP *) SCptr->host->hostdata;
+	struct esp *esp = (struct esp *) SCptr->host->hostdata;
+	unsigned long flags;
+
+	spin_lock_irqsave(&esp->lock, flags);
+	(void) esp_do_resetbus(esp);
+	spin_unlock_irqrestore(&esp->lock, flags);
 
-	(void) esp_do_resetbus(esp, esp->eregs, esp->dregs);
 	return SCSI_RESET_PENDING;
 }
 
 /* Internal ESP done function. */
-static void esp_done(struct Sparc_ESP *esp, int error)
+static void esp_done(struct esp *esp, int error)
 {
-	Scsi_Cmnd *done_SC;
+	Scsi_Cmnd *done_SC = esp->current_SC;
 
-	if(esp->current_SC) {
-		done_SC = esp->current_SC;
-		esp->current_SC = NULL;
-		esp_release_dmabufs(esp, done_SC);
-		done_SC->result = error;
-		done_SC->scsi_done(done_SC);
+	esp->current_SC = NULL;
+
+	spin_unlock(&esp->lock);
+	esp_release_dmabufs(esp, done_SC);
+	done_SC->result = error;
+
+	spin_lock(&io_request_lock);
+	done_SC->scsi_done(done_SC);
+	spin_unlock(&io_request_lock);
+
+	/* Bus is free, issue any commands in the queue. */
+	spin_lock(&esp->lock);
+	if (esp->issue_SC && !esp->current_SC)
+		esp_exec_cmd(esp);
 
-		/* Bus is free, issue any commands in the queue. */
-		if(esp->issue_SC && !esp->current_SC)
-			esp_exec_cmd(esp);
-	} else {
-		/* Panic is safe as current_SC is null so we may still
-		 * be able to accept more commands to sync disk buffers.
-		 */
-		ESPLOG(("panicing\n"));
-		panic("esp: done() called with NULL esp->current_SC");
-	}
 }
 
 /* Wheee, ESP interrupt engine. */  
 
 /* Forward declarations. */
-static int esp_do_phase_determine(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-				  struct sparc_dma_registers *dregs);
-static int esp_do_data_finale(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			      struct sparc_dma_registers *dregs);
-static int esp_select_complete(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			       struct sparc_dma_registers *dregs);
-static int esp_do_status(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			 struct sparc_dma_registers *dregs);
-static int esp_do_msgin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			struct sparc_dma_registers *dregs);
-static int esp_do_msgindone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			    struct sparc_dma_registers *dregs);
-static int esp_do_msgout(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			 struct sparc_dma_registers *dregs);
-static int esp_do_cmdbegin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			   struct sparc_dma_registers *dregs);
+static int esp_do_phase_determine(struct esp *esp);
+static int esp_do_data_finale(struct esp *esp);
+static int esp_select_complete(struct esp *esp);
+static int esp_do_status(struct esp *esp);
+static int esp_do_msgin(struct esp *esp);
+static int esp_do_msgindone(struct esp *esp);
+static int esp_do_msgout(struct esp *esp);
+static int esp_do_cmdbegin(struct esp *esp);
 
 #define sreg_datainp(__sreg)  (((__sreg) & ESP_STAT_PMASK) == ESP_DIP)
 #define sreg_dataoutp(__sreg) (((__sreg) & ESP_STAT_PMASK) == ESP_DOP)
@@ -1957,40 +2103,42 @@
 /* Read any bytes found in the FAS366 fifo, storing them into
  * the ESP driver software state structure.
  */
-static void hme_fifo_read(struct Sparc_ESP *esp,
-			  struct Sparc_ESP_regs *eregs)
+static void hme_fifo_read(struct esp *esp)
 {
-	unsigned long count = 0;
-	unchar status = esp->sreg;
+	u8 count = 0;
+	u8 status = esp->sreg;
 
 	/* Cannot safely frob the fifo for these following cases, but
 	 * we must always read the fifo when the reselect interrupt
 	 * is pending.
 	 */
-	if(((esp->ireg & ESP_INTR_RSEL) == 0)	&&
-	   (sreg_datainp(status)		||
-	    sreg_dataoutp(status)		||
-	    (esp->current_SC &&
-	     esp->current_SC->SCp.phase == in_data_done))) {
+	if (((esp->ireg & ESP_INTR_RSEL) == 0)	&&
+	    (sreg_datainp(status)		||
+	     sreg_dataoutp(status)		||
+	     (esp->current_SC &&
+	      esp->current_SC->SCp.phase == in_data_done))) {
 		ESPHME(("<wkaround_skipped>"));
 	} else {
-		unsigned long fcnt = eregs->esp_fflags & ESP_FF_FBYTES;
+		unsigned long fcnt = sbus_readb(esp->eregs + ESP_FFLAGS) & ESP_FF_FBYTES;
 
 		/* The HME stores bytes in multiples of 2 in the fifo. */
 		ESPHME(("hme_fifo[fcnt=%d", (int)fcnt));
-		while(fcnt) {
-			esp->hme_fifo_workaround_buffer[count++] = eregs->esp_fdata;
-			esp->hme_fifo_workaround_buffer[count++] = eregs->esp_fdata;
+		while (fcnt) {
+			esp->hme_fifo_workaround_buffer[count++] =
+				sbus_readb(esp->eregs + ESP_FDATA);
+			esp->hme_fifo_workaround_buffer[count++] =
+				sbus_readb(esp->eregs + ESP_FDATA);
 			ESPHME(("<%02x,%02x>", esp->hme_fifo_workaround_buffer[count-2], esp->hme_fifo_workaround_buffer[count-1]));
 			fcnt--;
 		}
-		if(eregs->esp_status2 & ESP_STAT2_F1BYTE) {
+		if (sbus_readb(esp->eregs + ESP_STATUS2) & ESP_STAT2_F1BYTE) {
 			ESPHME(("<poke_byte>"));
-			eregs->esp_fdata = 0;
-			esp->hme_fifo_workaround_buffer[count++] = eregs->esp_fdata;
+			sbus_writeb(0, esp->eregs + ESP_FDATA);
+			esp->hme_fifo_workaround_buffer[count++] =
+				sbus_readb(esp->eregs + ESP_FDATA);
 			ESPHME(("<%02x,0x00>", esp->hme_fifo_workaround_buffer[count-1]));
 			ESPHME(("CMD_FLUSH"));
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+			esp_cmd(esp, ESP_CMD_FLUSH);
 		} else {
 			ESPHME(("no_xtra_byte"));
 		}
@@ -1999,13 +2147,13 @@
 	esp->hme_fifo_workaround_count = count;
 }
 
-static inline void hme_fifo_push(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-				 unchar *bytes, unchar count)
+static inline void hme_fifo_push(struct esp *esp, u8 *bytes, u8 count)
 {
-	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-	while(count) {
-		eregs->esp_fdata = *bytes++;
-		eregs->esp_fdata = 0;
+	esp_cmd(esp, ESP_CMD_FLUSH);
+	while (count) {
+		u8 tmp = *bytes++;
+		sbus_writeb(tmp, esp->eregs + ESP_FDATA);
+		sbus_writeb(0, esp->eregs + ESP_FDATA);
 		count--;
 	}
 }
@@ -2013,19 +2161,18 @@
 /* We try to avoid some interrupts by jumping ahead and see if the ESP
  * has gotten far enough yet.  Hence the following.
  */
-static inline int skipahead1(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			     struct sparc_dma_registers *dregs,
-			     Scsi_Cmnd *scp, int prev_phase, int new_phase)
+static inline int skipahead1(struct esp *esp, Scsi_Cmnd *scp,
+			     int prev_phase, int new_phase)
 {
-	if(scp->SCp.sent_command != prev_phase)
+	if (scp->SCp.sent_command != prev_phase)
 		return 0;
-	if(DMA_IRQ_P(dregs)) {
+	if (ESP_IRQ_P(esp->dregs)) {
 		/* Yes, we are able to save an interrupt. */
 		if (esp->erev == fashme)
-			esp->sreg2 = eregs->esp_status2;
-		esp->sreg = (eregs->esp_status & ~(ESP_STAT_INTR));
-		esp->ireg = eregs->esp_intrpt;
-		if(esp->erev == fashme) {
+			esp->sreg2 = sbus_readb(esp->eregs + ESP_STATUS2);
+		esp->sreg = (sbus_readb(esp->eregs + ESP_STATUS) & ~(ESP_STAT_INTR));
+		esp->ireg = sbus_readb(esp->eregs + ESP_INTRPT);
+		if (esp->erev == fashme) {
 			/* This chip is really losing. */
 			ESPHME(("HME["));
 			/* Must latch fifo before reading the interrupt
@@ -2034,11 +2181,11 @@
 			 * Happy Meal indeed....
 			 */
 			ESPHME(("fifo_workaround]"));
-			if(!(esp->sreg2 & ESP_STAT2_FEMPTY) ||
-			   (esp->sreg2 & ESP_STAT2_F1BYTE))
-				hme_fifo_read(esp, eregs);
+			if (!(esp->sreg2 & ESP_STAT2_FEMPTY) ||
+			    (esp->sreg2 & ESP_STAT2_F1BYTE))
+				hme_fifo_read(esp);
 		}
-		if(!(esp->ireg & ESP_INTR_SR))
+		if (!(esp->ireg & ESP_INTR_SR))
 			return 0;
 		else
 			return do_reset_complete;
@@ -2048,21 +2195,19 @@
 	return do_intr_end;
 }
 
-static inline int skipahead2(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			     struct sparc_dma_registers *dregs,
-			     Scsi_Cmnd *scp, int prev_phase1, int prev_phase2,
-			     int new_phase)
+static inline int skipahead2(struct esp *esp, Scsi_Cmnd *scp,
+			     int prev_phase1, int prev_phase2, int new_phase)
 {
-	if(scp->SCp.sent_command != prev_phase1 &&
-	   scp->SCp.sent_command != prev_phase2)
+	if (scp->SCp.sent_command != prev_phase1 &&
+	    scp->SCp.sent_command != prev_phase2)
 		return 0;
-	if(DMA_IRQ_P(dregs)) {
+	if (ESP_IRQ_P(esp->dregs)) {
 		/* Yes, we are able to save an interrupt. */
 		if (esp->erev == fashme)
-			esp->sreg2 = eregs->esp_status2;
-		esp->sreg = (eregs->esp_status & ~(ESP_STAT_INTR));
-		esp->ireg = eregs->esp_intrpt;
-		if(esp->erev == fashme) {
+			esp->sreg2 = sbus_readb(esp->eregs + ESP_STATUS2);
+		esp->sreg = (sbus_readb(esp->eregs + ESP_STATUS) & ~(ESP_STAT_INTR));
+		esp->ireg = sbus_readb(esp->eregs + ESP_INTRPT);
+		if (esp->erev == fashme) {
 			/* This chip is really losing. */
 			ESPHME(("HME["));
 
@@ -2072,11 +2217,11 @@
 			 * Happy Meal indeed....
 			 */
 			ESPHME(("fifo_workaround]"));
-			if(!(esp->sreg2 & ESP_STAT2_FEMPTY) ||
-			   (esp->sreg2 & ESP_STAT2_F1BYTE))
-				hme_fifo_read(esp, eregs);
+			if (!(esp->sreg2 & ESP_STAT2_FEMPTY) ||
+			    (esp->sreg2 & ESP_STAT2_F1BYTE))
+				hme_fifo_read(esp);
 		}
-		if(!(esp->ireg & ESP_INTR_SR))
+		if (!(esp->ireg & ESP_INTR_SR))
 			return 0;
 		else
 			return do_reset_complete;
@@ -2087,99 +2232,98 @@
 }
 
 /* Now some dma helpers. */
-static inline void dma_setup(struct sparc_dma_registers *dregs, enum dvma_rev drev,
-			     __u32 addr, int count, int write)
+static void dma_setup(struct esp *esp, __u32 addr, int count, int write)
 {
-	unsigned long nreg = dregs->cond_reg;
-	if(write)
+	u32 nreg = sbus_readl(esp->dregs + DMA_CSR);
+
+	if (write)
 		nreg |= DMA_ST_WRITE;
 	else
 		nreg &= ~(DMA_ST_WRITE);
 	nreg |= DMA_ENABLE;
-	dregs->cond_reg = nreg;
-	if(drev == dvmaesc1) {
+	sbus_writel(nreg, esp->dregs + DMA_CSR);
+	if (esp->dma->revision == dvmaesc1) {
 		/* This ESC gate array sucks! */
 		__u32 src = addr;
 		__u32 dest = src + count;
 
-		if(dest & (PAGE_SIZE - 1))
+		if (dest & (PAGE_SIZE - 1))
 			count = PAGE_ALIGN(count);
-		dregs->cnt = count;
+		sbus_writel(count, esp->dregs + DMA_COUNT);
 	}
-	dregs->st_addr = addr;
+	sbus_writel(addr, esp->dregs + DMA_ADDR);
 }
 
-static inline void dma_drain(struct sparc_dma_registers *dregs, enum dvma_rev drev)
+static void dma_drain(struct esp *esp)
 {
-	if(drev == dvmahme)
+	u32 tmp;
+
+	if (esp->dma->revision == dvmahme)
 		return;
-	if(dregs->cond_reg & DMA_FIFO_ISDRAIN) {
-		switch(drev) {
+	if ((tmp = sbus_readl(esp->dregs + DMA_CSR)) & DMA_FIFO_ISDRAIN) {
+		switch (esp->dma->revision) {
 		default:
-			dregs->cond_reg |= DMA_FIFO_STDRAIN;
+			tmp |= DMA_FIFO_STDRAIN;
+			sbus_writel(tmp, esp->dregs + DMA_CSR);
 
 		case dvmarev3:
 		case dvmaesc1:
-			while(dregs->cond_reg & DMA_FIFO_ISDRAIN)
+			while (sbus_readl(esp->dregs + DMA_CSR) & DMA_FIFO_ISDRAIN)
 				udelay(1);
 		};
 	}
 }
 
-static inline void dma_invalidate(struct Sparc_ESP *esp,
-				  struct sparc_dma_registers *dregs,
-				  enum dvma_rev drev)
+static void dma_invalidate(struct esp *esp)
 {
-	unsigned int tmp;
+	u32 tmp;
 
-	if(drev == dvmahme) {
-		dregs->cond_reg = DMA_RST_SCSI;
+	if (esp->dma->revision == dvmahme) {
+		sbus_writel(DMA_RST_SCSI, esp->dregs + DMA_CSR);
 
 		esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr |
 					 (DMA_PARITY_OFF | DMA_2CLKS |
 					  DMA_SCSI_DISAB | DMA_INT_ENAB)) &
 					~(DMA_ST_WRITE | DMA_ENABLE));
 
-		dregs->cond_reg = 0;
-		dregs->cond_reg = esp->prev_hme_dmacsr;
+		sbus_writel(0, esp->dregs + DMA_CSR);
+		sbus_writel(esp->prev_hme_dmacsr, esp->dregs + DMA_CSR);
 
 		/* This is necessary to avoid having the SCSI channel
 		 * engine lock up on us.
 		 */
-		dregs->st_addr = 0;
+		sbus_writel(0, esp->dregs + DMA_ADDR);
 	} else {
-		while(dregs->cond_reg & DMA_PEND_READ)
+		while ((tmp = sbus_readl(esp->dregs + DMA_CSR)) & DMA_PEND_READ)
 			udelay(1);
 
-		tmp = dregs->cond_reg;
 		tmp &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB);
 		tmp |= DMA_FIFO_INV;
-		dregs->cond_reg = tmp;
-		dregs->cond_reg = (tmp & ~(DMA_FIFO_INV));
+		sbus_writel(tmp, esp->dregs + DMA_CSR);
+		tmp &= ~DMA_FIFO_INV;
+		sbus_writel(tmp, esp->dregs + DMA_CSR);
 	}
 }
 
-static inline void dma_flashclear(struct Sparc_ESP *esp,
-				  struct sparc_dma_registers *dregs,
-				  enum dvma_rev drev)
+static inline void dma_flashclear(struct esp *esp)
 {
-	dma_drain(dregs, drev);
-	dma_invalidate(esp, dregs, drev);
+	dma_drain(esp);
+	dma_invalidate(esp);
 }
 
-static inline int dma_can_transfer(Scsi_Cmnd *sp, enum dvma_rev drev)
+static int dma_can_transfer(struct esp *esp, Scsi_Cmnd *sp)
 {
 	__u32 base, end, sz;
 
-	if(drev == dvmarev3) {
+	if (esp->dma->revision == dvmarev3) {
 		sz = sp->SCp.this_residual;
-		if(sz > 0x1000000)
+		if (sz > 0x1000000)
 			sz = 0x1000000;
 	} else {
 		base = ((__u32)((unsigned long)sp->SCp.ptr));
 		base &= (0x1000000 - 1);
 		end = (base + sp->SCp.this_residual);
-		if(end > 0x1000000)
+		if (end > 0x1000000)
 			end = 0x1000000;
 		sz = (end - base);
 	}
@@ -2188,33 +2332,34 @@
 
 /* Misc. esp helper macros. */
 #define esp_setcount(__eregs, __cnt, __hme) \
-	(__eregs)->esp_tclow = ((__cnt) & 0xff); \
-	(__eregs)->esp_tcmed = (((__cnt) >> 8) & 0xff); \
-	if(__hme) { \
-		(__eregs)->fas_rlo = 0; \
-		(__eregs)->fas_rhi = 0; \
+	sbus_writeb(((__cnt)&0xff), (__eregs) + ESP_TCLOW); \
+	sbus_writeb((((__cnt)>>8)&0xff), (__eregs) + ESP_TCMED); \
+	if (__hme) { \
+		sbus_writeb((((__cnt)>>16)&0xff), (__eregs) + FAS_RLO); \
+		sbus_writeb(0, (__eregs) + FAS_RHI); \
 	}
 
-#define esp_getcount(__eregs) \
-	((((__eregs)->esp_tclow)&0xff) | \
-	 ((((__eregs)->esp_tcmed)&0xff) << 8))
+#define esp_getcount(__eregs, __hme) \
+	((sbus_readb((__eregs) + ESP_TCLOW)&0xff) | \
+	 ((sbus_readb((__eregs) + ESP_TCMED)&0xff) << 8) | \
+         ((__hme) ? sbus_readb((__eregs) + FAS_RLO) << 16 : 0))
 
-#define fcount(__esp, __eregs) \
+#define fcount(__esp) \
 	(((__esp)->erev == fashme) ? \
 	  (__esp)->hme_fifo_workaround_count : \
-	  (__eregs)->esp_fflags & ESP_FF_FBYTES)
+	  sbus_readb(((__esp)->eregs) + ESP_FFLAGS) & ESP_FF_FBYTES)
 
-#define fnzero(__esp, __eregs) \
+#define fnzero(__esp) \
 	(((__esp)->erev == fashme) ? 0 : \
-	 (__eregs)->esp_fflags & ESP_FF_ONOTZERO)
+	 sbus_readb(((__esp)->eregs) + ESP_FFLAGS) & ESP_FF_ONOTZERO)
 
 /* XXX speculative nops unnecessary when continuing amidst a data phase
  * XXX even on esp100!!!  another case of flooding the bus with I/O reg
  * XXX writes...
  */
-#define esp_maybe_nop(__esp, __eregs) \
-	if((__esp)->erev == esp100) \
-		esp_cmd((__esp), (__eregs), ESP_CMD_NULL)
+#define esp_maybe_nop(__esp) \
+	if ((__esp)->erev == esp100) \
+		esp_cmd((__esp), ESP_CMD_NULL)
 
 #define sreg_to_dataphase(__sreg) \
 	((((__sreg) & ESP_STAT_PMASK) == ESP_DOP) ? in_dataout : in_datain)
@@ -2227,23 +2372,23 @@
  * tell the ESP to eat the extraneous byte so that we can proceed
  * to the next phase.
  */
-static inline int esp100_sync_hwbug(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-				    Scsi_Cmnd *sp, int fifocnt)
+static int esp100_sync_hwbug(struct esp *esp, Scsi_Cmnd *sp, int fifocnt)
 {
 	/* Do not touch this piece of code. */
-	if((!(esp->erev == esp100)) ||
-	   (!(sreg_datainp((esp->sreg = eregs->esp_status)) && !fifocnt) &&
-	    !(sreg_dataoutp(esp->sreg) && !fnzero(esp, eregs)))) {
-		if(sp->SCp.phase == in_dataout)
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+	if ((!(esp->erev == esp100)) ||
+	    (!(sreg_datainp((esp->sreg = sbus_readb(esp->eregs + ESP_STATUS))) &&
+	       !fifocnt) &&
+	     !(sreg_dataoutp(esp->sreg) && !fnzero(esp)))) {
+		if (sp->SCp.phase == in_dataout)
+			esp_cmd(esp, ESP_CMD_FLUSH);
 		return 0;
 	} else {
 		/* Async mode for this guy. */
 		build_sync_nego_msg(esp, 0, 0);
 
 		/* Ack the bogus byte, but set ATN first. */
-		esp_cmd(esp, eregs, ESP_CMD_SATN);
-		esp_cmd(esp, eregs, ESP_CMD_MOK);
+		esp_cmd(esp, ESP_CMD_SATN);
+		esp_cmd(esp, ESP_CMD_MOK);
 		return 1;
 	}
 }
@@ -2253,15 +2398,14 @@
  * contents if we get reselected during this process.  So we just need to
  * ack the possible illegal cmd interrupt pending on the esp100.
  */
-static inline int esp100_reconnect_hwbug(struct Sparc_ESP *esp,
-					 struct Sparc_ESP_regs *eregs)
+static inline int esp100_reconnect_hwbug(struct esp *esp)
 {
-	volatile unchar junk;
+	u8 tmp;
 
-	if(esp->erev != esp100)
+	if (esp->erev != esp100)
 		return 0;
-	junk = eregs->esp_intrpt;
-	if(junk & ESP_INTR_SR)
+	tmp = sbus_readb(esp->eregs + ESP_INTRPT);
+	if (tmp & ESP_INTR_SR)
 		return 1;
 	return 0;
 }
@@ -2269,13 +2413,13 @@
 /* This verifies the BUSID bits during a reselection so that we know which
  * target is talking to us.
  */
-static inline int reconnect_target(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
+static inline int reconnect_target(struct esp *esp)
 {
 	int it, me = esp->scsi_id_mask, targ = 0;
 
-	if(2 != fcount(esp, eregs))
+	if (2 != fcount(esp))
 		return -1;
-	if(esp->erev == fashme) {
+	if (esp->erev == fashme) {
 		/* HME does not latch it's own BUS ID bits during
 		 * a reselection.  Also the target number is given
 		 * as an unsigned char, not as a sole bit number
@@ -2284,13 +2428,13 @@
 		 */
 		targ = esp->hme_fifo_workaround_buffer[0];
 	} else {
-		it = eregs->esp_fdata;
-		if(!(it & me))
+		it = sbus_readb(esp->eregs + ESP_FDATA);
+		if (!(it & me))
 			return -1;
 		it &= ~me;
-		if(it & (it - 1))
+		if (it & (it - 1))
 			return -1;
-		while(!(it & 1))
+		while (!(it & 1))
 			targ++, it >>= 1;
 	}
 	return targ;
@@ -2299,27 +2443,27 @@
 /* This verifies the identify from the target so that we know which lun is
  * being reconnected.
  */
-static inline int reconnect_lun(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
+static inline int reconnect_lun(struct esp *esp)
 {
 	int lun;
 
-	if((esp->sreg & ESP_STAT_PMASK) != ESP_MIP)
+	if ((esp->sreg & ESP_STAT_PMASK) != ESP_MIP)
 		return -1;
-	if(esp->erev == fashme)
+	if (esp->erev == fashme)
 		lun = esp->hme_fifo_workaround_buffer[1];
 	else
-		lun = eregs->esp_fdata;
+		lun = sbus_readb(esp->eregs + ESP_FDATA);
 
 	/* Yes, you read this correctly.  We report lun of zero
 	 * if we see parity error.  ESP reports parity error for
 	 * the lun byte, and this is the only way to hope to recover
 	 * because the target is connected.
 	 */
-	if(esp->sreg & ESP_STAT_PERR)
+	if (esp->sreg & ESP_STAT_PERR)
 		return 0;
 
 	/* Check for illegal bits being set in the lun. */
-	if((lun & 0x40) || !(lun & 0x80))
+	if ((lun & 0x40) || !(lun & 0x80))
 		return -1;
 
 	return lun & 7;
@@ -2328,21 +2472,22 @@
 /* This puts the driver in a state where it can revitalize a command that
  * is being continued due to reselection.
  */
-static inline void esp_connect(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			       Scsi_Cmnd *sp)
+static inline void esp_connect(struct esp *esp, Scsi_Cmnd *sp)
 {
 	Scsi_Device *dp = sp->device;
 
-	if(esp->prev_soff  != dp->sync_max_offset ||
-	   esp->prev_stp   != dp->sync_min_period ||
-	   (esp->erev > esp100a &&
-	    esp->prev_cfg3 != esp->config3[sp->target])) {
-		eregs->esp_soff = esp->prev_soff = dp->sync_max_offset;
-		eregs->esp_stp  = esp->prev_stp = dp->sync_min_period;
-		if(esp->erev > esp100a)
-			eregs->esp_cfg3 =
-				esp->prev_cfg3 =
-				esp->config3[sp->target];
+	if (esp->prev_soff  != dp->sync_max_offset ||
+	    esp->prev_stp   != dp->sync_min_period ||
+	    (esp->erev > esp100a &&
+	     esp->prev_cfg3 != esp->config3[sp->target])) {
+		esp->prev_soff = dp->sync_max_offset;
+		esp->prev_stp = dp->sync_min_period;
+		sbus_writeb(esp->prev_soff, esp->eregs + ESP_SOFF);
+		sbus_writeb(esp->prev_stp, esp->eregs + ESP_STP);
+		if (esp->erev > esp100a) {
+			esp->prev_cfg3 = esp->config3[sp->target];
+			sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3);
+		}
 	}
 	esp->current_SC = sp;
 }
@@ -2350,9 +2495,9 @@
 /* This will place the current working command back into the issue queue
  * if we are to receive a reselection amidst a selection attempt.
  */
-static inline void esp_reconnect(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
+static inline void esp_reconnect(struct esp *esp, Scsi_Cmnd *sp)
 {
-	if(!esp->disconnected_SC)
+	if (!esp->disconnected_SC)
 		ESPLOG(("esp%d: Weird, being reselected but disconnected "
 			"command queue is empty.\n", esp->esp_id));
 	esp->snip = 0;
@@ -2362,14 +2507,14 @@
 }
 
 /* Begin message in phase. */
-static int esp_do_msgin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			struct sparc_dma_registers *dregs)
+static int esp_do_msgin(struct esp *esp)
 {
 	/* Must be very careful with the fifo on the HME */
-	if((esp->erev != fashme) || !(eregs->esp_status2 & ESP_STAT2_FEMPTY))
-		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-	esp_maybe_nop(esp, eregs);
-	esp_cmd(esp, eregs, ESP_CMD_TI);
+	if ((esp->erev != fashme) ||
+	    !(sbus_readb(esp->eregs + ESP_STATUS2) & ESP_STAT2_FEMPTY))
+		esp_cmd(esp, ESP_CMD_FLUSH);
+	esp_maybe_nop(esp);
+	esp_cmd(esp, ESP_CMD_TI);
 	esp->msgin_len = 1;
 	esp->msgin_ctr = 0;
 	esp_advance_phase(esp->current_SC, in_msgindone);
@@ -2379,14 +2524,12 @@
 /* This uses various DMA csr fields and the fifo flags count value to
  * determine how many bytes were successfully sent/received by the ESP.
  */
-static inline int esp_bytes_sent(struct Sparc_ESP *esp,
-				 struct sparc_dma_registers *dregs,
-				 int fifo_count)
+static inline int esp_bytes_sent(struct esp *esp, int fifo_count)
 {
-	int rval = dregs->st_addr - esp->esp_command_dvma;
+	int rval = sbus_readl(esp->dregs + DMA_ADDR) - esp->esp_command_dvma;
 
-	if(esp->dma->revision == dvmarev1)
-		rval -= (4 - ((dregs->cond_reg & DMA_READ_AHEAD)>>11));
+	if (esp->dma->revision == dvmarev1)
+		rval -= (4 - ((sbus_readl(esp->dregs + DMA_CSR) & DMA_READ_AHEAD)>>11));
 	return rval - fifo_count;
 }
 
@@ -2394,7 +2537,7 @@
 {
 	++sp->SCp.buffer;
 	--sp->SCp.buffers_residual;
-	sp->SCp.this_residual = sp->SCp.buffer->length;
+	sp->SCp.this_residual = sp->SCp.buffer->dvma_length;
 	sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address);
 }
 
@@ -2416,25 +2559,25 @@
  * within a buffer or sub-buffer should not upset us at all no matter
  * how bad the target and/or ESP fucks things up.
  */
-static int esp_do_data(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-		       struct sparc_dma_registers *dregs)
+static int esp_do_data(struct esp *esp)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 	int thisphase, hmuch;
 
 	ESPDATA(("esp_do_data: "));
-	esp_maybe_nop(esp, eregs);
+	esp_maybe_nop(esp);
 	thisphase = sreg_to_dataphase(esp->sreg);
 	esp_advance_phase(SCptr, thisphase);
 	ESPDATA(("newphase<%s> ", (thisphase == in_datain) ? "DATAIN" : "DATAOUT"));
-	hmuch = dma_can_transfer(SCptr, esp->dma->revision);
+	hmuch = dma_can_transfer(esp, SCptr);
 	ESPDATA(("hmuch<%d> ", hmuch));
 	esp->current_transfer_size = hmuch;
-	if(esp->erev == fashme) {
-		unsigned long tmp = esp->prev_hme_dmacsr;
+
+	if (esp->erev == fashme) {
+		u32 tmp = esp->prev_hme_dmacsr;
 
 		/* Always set the ESP count registers first. */
-		esp_setcount(eregs, hmuch, 1);
+		esp_setcount(esp->eregs, hmuch, 1);
 
 		/* Get the DMA csr computed. */
 		tmp |= (DMA_SCSI_DISAB | DMA_ENABLE);
@@ -2444,38 +2587,36 @@
 			tmp &= ~(DMA_ST_WRITE);
 		esp->prev_hme_dmacsr = tmp;
 
+		ESPDATA(("DMA|TI --> do_intr_end\n"));
 		if (thisphase == in_datain) {
-			dregs->cnt = hmuch;
-			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
+			sbus_writel(hmuch, esp->dregs + DMA_COUNT);
+			esp_cmd(esp, ESP_CMD_DMA | ESP_CMD_TI);
 		} else {
-			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
-			dregs->cnt = hmuch;
+			esp_cmd(esp, ESP_CMD_DMA | ESP_CMD_TI);
+			sbus_writel(hmuch, esp->dregs + DMA_COUNT);
 		}
-		dregs->st_addr = ((__u32)((unsigned long)SCptr->SCp.ptr));
-		dregs->cond_reg = esp->prev_hme_dmacsr;
+		sbus_writel((__u32)((unsigned long)SCptr->SCp.ptr), esp->dregs+DMA_ADDR);
+		sbus_writel(esp->prev_hme_dmacsr, esp->dregs + DMA_CSR);
 	} else {
-		esp_setcount(eregs, hmuch, 0);
-		dma_setup(dregs, esp->dma->revision,
-			  ((__u32)((unsigned long)SCptr->SCp.ptr)),
+		esp_setcount(esp->eregs, hmuch, 0);
+		dma_setup(esp, ((__u32)((unsigned long)SCptr->SCp.ptr)),
 			  hmuch, (thisphase == in_datain));
 		ESPDATA(("DMA|TI --> do_intr_end\n"));
-		esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
+		esp_cmd(esp, ESP_CMD_DMA | ESP_CMD_TI);
 	}
 	return do_intr_end;
 }
 
 /* See how successful the data transfer was. */
-static int esp_do_data_finale(struct Sparc_ESP *esp,
-			      struct Sparc_ESP_regs *eregs,
-			      struct sparc_dma_registers *dregs)
+static int esp_do_data_finale(struct esp *esp)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 	int bogus_data = 0, bytes_sent = 0, fifocnt, ecount = 0;
 
 	ESPDATA(("esp_do_data_finale: "));
 
-	if(SCptr->SCp.phase == in_datain) {
-		if(esp->sreg & ESP_STAT_PERR) {
+	if (SCptr->SCp.phase == in_datain) {
+		if (esp->sreg & ESP_STAT_PERR) {
 			/* Yuck, parity error.  The ESP asserts ATN
 			 * so that we can go to message out phase
 			 * immediately and inform the target that
@@ -2486,16 +2627,16 @@
 			esp->cur_msgout[0] = INITIATOR_ERROR;
 			esp->msgout_len = 1;
 		}
-		dma_drain(dregs, esp->dma->revision);
+		dma_drain(esp);
 	}
-	dma_invalidate(esp, dregs, esp->dma->revision);
+	dma_invalidate(esp);
 
 	/* This could happen for the above parity error case. */
-	if(!(esp->ireg == ESP_INTR_BSERV)) {
+	if (esp->ireg != ESP_INTR_BSERV) {
 		/* Please go to msgout phase, please please please... */
 		ESPLOG(("esp%d: !BSERV after data, probably to msgout\n",
 			esp->esp_id));
-		return esp_do_phase_determine(esp, eregs, dregs);
+		return esp_do_phase_determine(esp);
 	}	
 
 	/* Check for partial transfers and other horrible events.
@@ -2509,22 +2650,22 @@
 	 * will move and count 16-bit quantities during wide data.
 	 * SMCC _and_ Qlogic can both bite me.
 	 */
-	fifocnt = eregs->esp_fflags & ESP_FF_FBYTES;
-	if(esp->erev != fashme)
-		ecount = esp_getcount(eregs);
+	fifocnt = (sbus_readb(esp->eregs + ESP_FFLAGS) & ESP_FF_FBYTES);
+	if (esp->erev != fashme)
+		ecount = esp_getcount(esp->eregs, 0);
 	bytes_sent = esp->current_transfer_size;
 
-	ESPDATA(("trans_sz=%d, ", bytes_sent));
-	if(esp->erev == fashme) {
-		if(!(esp->sreg & ESP_STAT_TCNT)) {
-			ecount = esp_getcount(eregs);
+	ESPDATA(("trans_sz(%d), ", bytes_sent));
+	if (esp->erev == fashme) {
+		if (!(esp->sreg & ESP_STAT_TCNT)) {
+			ecount = esp_getcount(esp->eregs, 1);
 			bytes_sent -= ecount;
 		}
 
 		/* Always subtract any cruft remaining in the FIFO. */
-		if(esp->prev_cfg3 & ESP_CONFIG3_EWIDE)
+		if (esp->prev_cfg3 & ESP_CONFIG3_EWIDE)
 			fifocnt <<= 1;
-		if(SCptr->SCp.phase == in_dataout)
+		if (SCptr->SCp.phase == in_dataout)
 			bytes_sent -= fifocnt;
 
 		/* I have an IBM disk which exhibits the following
@@ -2546,34 +2687,34 @@
 		    SCptr->SCp.phase == in_dataout) {
 			int mask = (64 - 1);
 
-			if((esp->prev_cfg3 & ESP_CONFIG3_EWIDE) == 0)
+			if ((esp->prev_cfg3 & ESP_CONFIG3_EWIDE) == 0)
 				mask >>= 1;
 
 			if (bytes_sent & mask)
 				bytes_sent -= (bytes_sent & mask);
 		}
 	} else {
-		if(!(esp->sreg & ESP_STAT_TCNT))
+		if (!(esp->sreg & ESP_STAT_TCNT))
 			bytes_sent -= ecount;
-		if(SCptr->SCp.phase == in_dataout)
+		if (SCptr->SCp.phase == in_dataout)
 			bytes_sent -= fifocnt;
 	}
 
-	ESPDATA(("bytes_sent=%d, ", bytes_sent));
+	ESPDATA(("bytes_sent(%d), ", bytes_sent));
 
 	/* If we were in synchronous mode, check for peculiarities. */
-	if(esp->erev == fashme) {
-		if(SCptr->device->sync_max_offset) {
-			if(SCptr->SCp.phase == in_dataout)
-				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+	if (esp->erev == fashme) {
+		if (SCptr->device->sync_max_offset) {
+			if (SCptr->SCp.phase == in_dataout)
+				esp_cmd(esp, ESP_CMD_FLUSH);
 		} else {
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+			esp_cmd(esp, ESP_CMD_FLUSH);
 		}
 	} else {
-		if(SCptr->device->sync_max_offset)
-			bogus_data = esp100_sync_hwbug(esp, eregs, SCptr, fifocnt);
+		if (SCptr->device->sync_max_offset)
+			bogus_data = esp100_sync_hwbug(esp, SCptr, fifocnt);
 		else
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+			esp_cmd(esp, ESP_CMD_FLUSH);
 	}
 
 	/* Until we are sure of what has happened, we are certainly
@@ -2581,7 +2722,7 @@
 	 */
 	esp_advance_phase(SCptr, in_the_dark);
 
-	if(bytes_sent < 0) {
+	if (bytes_sent < 0) {
 		/* I've seen this happen due to lost state in this
 		 * driver.  No idea why it happened, but allowing
 		 * this value to be negative caused things to
@@ -2606,15 +2747,16 @@
 	/* Update the state of our transfer. */
 	SCptr->SCp.ptr += bytes_sent;
 	SCptr->SCp.this_residual -= bytes_sent;
-	if(SCptr->SCp.this_residual < 0) {
+	if (SCptr->SCp.this_residual < 0) {
 		/* shit */
 		ESPLOG(("esp%d: Data transfer overrun.\n", esp->esp_id));
 		SCptr->SCp.this_residual = 0;
 	}
 
 	/* Maybe continue. */
-	if(!bogus_data) {
+	if (!bogus_data) {
 		ESPDATA(("!bogus_data, "));
+
 		/* NO MATTER WHAT, we advance the scatterlist,
 		 * if the target should decide to disconnect
 		 * in between scatter chunks (which is common)
@@ -2624,14 +2766,14 @@
 		 * imagine the hell I went through trying to
 		 * figure this out.
 		 */
-		if(SCptr->use_sg && !SCptr->SCp.this_residual)
+		if (SCptr->use_sg && !SCptr->SCp.this_residual)
 			advance_sg(SCptr);
-		if(sreg_datainp(esp->sreg) || sreg_dataoutp(esp->sreg)) {
+		if (sreg_datainp(esp->sreg) || sreg_dataoutp(esp->sreg)) {
 			ESPDATA(("to more data\n"));
-			return esp_do_data(esp, eregs, dregs);
+			return esp_do_data(esp);
 		}
 		ESPDATA(("to new phase\n"));
-		return esp_do_phase_determine(esp, eregs, dregs);
+		return esp_do_phase_determine(esp);
 	}
 	/* Bogus data, just wait for next interrupt. */
 	ESPLOG(("esp%d: bogus_data during end of data phase\n",
@@ -2650,27 +2792,27 @@
  */
 static int esp_should_clear_sync(Scsi_Cmnd *sp)
 {
-	unchar cmd1 = sp->cmnd[0];
-	unchar cmd2 = sp->data_cmnd[0];
+	u8 cmd1 = sp->cmnd[0];
+	u8 cmd2 = sp->data_cmnd[0];
 
 	/* These cases are for spinning up a disk and
 	 * waiting for that spinup to complete.
 	 */
-	if(cmd1 == START_STOP ||
-	   cmd2 == START_STOP)
+	if (cmd1 == START_STOP ||
+	    cmd2 == START_STOP)
 		return 0;
 
-	if(cmd1 == TEST_UNIT_READY ||
-	   cmd2 == TEST_UNIT_READY)
+	if (cmd1 == TEST_UNIT_READY ||
+	    cmd2 == TEST_UNIT_READY)
 		return 0;
 
 	/* One more special case for SCSI tape drives,
 	 * this is what is used to probe the device for
 	 * completion of a rewind or tape load operation.
 	 */
-	if(sp->device->type == TYPE_TAPE) {
-		if(cmd1 == MODE_SENSE ||
-		   cmd2 == MODE_SENSE)
+	if (sp->device->type == TYPE_TAPE) {
+		if (cmd1 == MODE_SENSE ||
+		    cmd2 == MODE_SENSE)
 			return 0;
 	}
 
@@ -2680,31 +2822,30 @@
 /* Either a command is completing or a target is dropping off the bus
  * to continue the command in the background so we can do other work.
  */
-static int esp_do_freebus(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			  struct sparc_dma_registers *dregs)
+static int esp_do_freebus(struct esp *esp)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 	int rval;
 
-	rval = skipahead2(esp, eregs, dregs, SCptr, in_status, in_msgindone, in_freeing);
-	if(rval)
+	rval = skipahead2(esp, SCptr, in_status, in_msgindone, in_freeing);
+	if (rval)
 		return rval;
-	if(esp->ireg != ESP_INTR_DC) {
+	if (esp->ireg != ESP_INTR_DC) {
 		ESPLOG(("esp%d: Target will not disconnect\n", esp->esp_id));
 		return do_reset_bus; /* target will not drop BSY... */
 	}
 	esp->msgout_len = 0;
 	esp->prevmsgout = NOP;
-	if(esp->prevmsgin == COMMAND_COMPLETE) {
+	if (esp->prevmsgin == COMMAND_COMPLETE) {
 		/* Normal end of nexus. */
-		if(esp->disconnected_SC || (esp->erev == fashme))
-			esp_cmd(esp, eregs, ESP_CMD_ESEL);
+		if (esp->disconnected_SC || (esp->erev == fashme))
+			esp_cmd(esp, ESP_CMD_ESEL);
 
-		if(SCptr->SCp.Status != GOOD &&
-		   SCptr->SCp.Status != CONDITION_GOOD &&
-		   ((1<<SCptr->target) & esp->targets_present) &&
-		   SCptr->device->sync &&
-		   SCptr->device->sync_max_offset) {
+		if (SCptr->SCp.Status != GOOD &&
+		    SCptr->SCp.Status != CONDITION_GOOD &&
+		    ((1<<SCptr->target) & esp->targets_present) &&
+		    SCptr->device->sync &&
+		    SCptr->device->sync_max_offset) {
 			/* SCSI standard says that the synchronous capabilities
 			 * should be renegotiated at this point.  Most likely
 			 * we are about to request sense from this target
@@ -2721,20 +2862,20 @@
 			 * can report not ready many times right after
 			 * loading up a tape.
 			 */
-			if(esp_should_clear_sync(SCptr) != 0)
+			if (esp_should_clear_sync(SCptr) != 0)
 				SCptr->device->sync = 0;
 		}
 		ESPDISC(("F<%02x,%02x>", SCptr->target, SCptr->lun));
 		esp_done(esp, ((SCptr->SCp.Status & 0xff) |
 			       ((SCptr->SCp.Message & 0xff)<<8) |
 			       (DID_OK << 16)));
-	} else if(esp->prevmsgin == DISCONNECT) {
+	} else if (esp->prevmsgin == DISCONNECT) {
 		/* Normal disconnect. */
-		esp_cmd(esp, eregs, ESP_CMD_ESEL);
+		esp_cmd(esp, ESP_CMD_ESEL);
 		ESPDISC(("D<%02x,%02x>", SCptr->target, SCptr->lun));
 		append_SC(&esp->disconnected_SC, SCptr);
 		esp->current_SC = NULL;
-		if(esp->issue_SC)
+		if (esp->issue_SC)
 			esp_exec_cmd(esp);
 	} else {
 		/* Driver bug, we do not expect a disconnect here
@@ -2751,7 +2892,7 @@
 /* When a reselect occurs, and we cannot find the command to
  * reconnect to in our queues, we do this.
  */
-static int esp_bad_reconnect(struct Sparc_ESP *esp)
+static int esp_bad_reconnect(struct esp *esp)
 {
 	Scsi_Cmnd *sp;
 
@@ -2760,21 +2901,21 @@
 	ESPLOG(("QUEUE DUMP\n"));
 	sp = esp->issue_SC;
 	ESPLOG(("esp%d: issue_SC[", esp->esp_id));
-	while(sp) {
+	while (sp) {
 		ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
 		sp = (Scsi_Cmnd *) sp->host_scribble;
 	}
 	ESPLOG(("]\n"));
 	sp = esp->current_SC;
 	ESPLOG(("esp%d: current_SC[", esp->esp_id));
-	while(sp) {
+	if (sp)
 		ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
-		sp = (Scsi_Cmnd *) sp->host_scribble;
-	}
+	else
+		ESPLOG(("<NULL>"));
 	ESPLOG(("]\n"));
 	sp = esp->disconnected_SC;
 	ESPLOG(("esp%d: disconnected_SC[", esp->esp_id));
-	while(sp) {
+	while (sp) {
 		ESPLOG(("<%02x,%02x>", sp->target, sp->lun));
 		sp = (Scsi_Cmnd *) sp->host_scribble;
 	}
@@ -2783,20 +2924,19 @@
 }
 
 /* Do the needy when a target tries to reconnect to us. */
-static int esp_do_reconnect(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			    struct sparc_dma_registers *dregs)
+static int esp_do_reconnect(struct esp *esp)
 {
 	int lun, target;
 	Scsi_Cmnd *SCptr;
 
 	/* Check for all bogus conditions first. */
-	target = reconnect_target(esp, eregs);
-	if(target < 0) {
+	target = reconnect_target(esp);
+	if (target < 0) {
 		ESPDISC(("bad bus bits\n"));
 		return do_reset_bus;
 	}
-	lun = reconnect_lun(esp, eregs);
-	if(lun < 0) {
+	lun = reconnect_lun(esp);
+	if (lun < 0) {
 		ESPDISC(("target=%2x, bad identify msg\n", target));
 		return do_reset_bus;
 	}
@@ -2805,23 +2945,24 @@
 	ESPDISC(("R<%02x,%02x>", target, lun));
 
 	/* Must not flush FIFO or DVMA on HME. */
-	if(esp->erev != fashme) {
-		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-		if(esp100_reconnect_hwbug(esp, eregs))
+	if (esp->erev != fashme) {
+		esp_cmd(esp, ESP_CMD_FLUSH);
+		if (esp100_reconnect_hwbug(esp))
 			return do_reset_bus;
-		esp_cmd(esp, eregs, ESP_CMD_NULL);
+		esp_cmd(esp, ESP_CMD_NULL);
 	}
 
-	SCptr = remove_SC(&esp->disconnected_SC, (unchar) target, (unchar) lun);
-	if(!SCptr)
+	SCptr = remove_SC(&esp->disconnected_SC, (u8) target, (u8) lun);
+	if (!SCptr)
 		return esp_bad_reconnect(esp);
 
-	esp_connect(esp, eregs, SCptr);
-	esp_cmd(esp, eregs, ESP_CMD_MOK);
+	esp_connect(esp, SCptr);
+	esp_cmd(esp, ESP_CMD_MOK);
 
-	if(esp->erev == fashme)
-		eregs->esp_busid = (SCptr->target & 0xf) |
-			(ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT);
+	if (esp->erev == fashme)
+		sbus_writeb(((SCptr->target & 0xf) |
+			     (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT)),
+			    esp->eregs + ESP_BUSID);
 
 	/* Reconnect implies a restore pointers operation. */
 	esp_restore_pointers(esp, SCptr);
@@ -2834,29 +2975,28 @@
 /* End of NEXUS (hopefully), pick up status + message byte then leave if
  * all goes well.
  */
-static int esp_do_status(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			 struct sparc_dma_registers *dregs)
+static int esp_do_status(struct esp *esp)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 	int intr, rval;
 
-	rval = skipahead1(esp, eregs, dregs, SCptr, in_the_dark, in_status);
-	if(rval)
+	rval = skipahead1(esp, SCptr, in_the_dark, in_status);
+	if (rval)
 		return rval;
 	intr = esp->ireg;
 	ESPSTAT(("esp_do_status: "));
-	if(intr != ESP_INTR_DC) {
+	if (intr != ESP_INTR_DC) {
 		int message_out = 0; /* for parity problems */
 
 		/* Ack the message. */
 		ESPSTAT(("ack msg, "));
-		esp_cmd(esp, eregs, ESP_CMD_MOK);
+		esp_cmd(esp, ESP_CMD_MOK);
 
-		if(esp->erev != fashme) {
-			dma_flashclear(esp, dregs, esp->dma->revision);
+		if (esp->erev != fashme) {
+			dma_flashclear(esp);
 
 			/* Wait till the first bits settle. */
-			while(esp->esp_command[0] == 0xff)
+			while (esp->esp_command[0] == 0xff)
 				udelay(1);
 		} else {
 			esp->esp_command[0] = esp->hme_fifo_workaround_buffer[0];
@@ -2883,24 +3023,24 @@
 		 *       and we must therefore wait for the
 		 *       next phase change.
 		 */
-		if(intr & ESP_INTR_FDONE) {
+		if (intr & ESP_INTR_FDONE) {
 			/* We got it all, hallejulia. */
 			ESPSTAT(("got both, "));
 			SCptr->SCp.Status = esp->esp_command[0];
 			SCptr->SCp.Message = esp->esp_command[1];
 			esp->prevmsgin = SCptr->SCp.Message;
 			esp->cur_msgin[0] = SCptr->SCp.Message;
-			if(esp->sreg & ESP_STAT_PERR) {
+			if (esp->sreg & ESP_STAT_PERR) {
 				/* There was bad parity for the
 				 * message byte, the status byte
 				 * was ok.
 				 */
 				message_out = MSG_PARITY_ERROR;
 			}
-		} else if(intr == ESP_INTR_BSERV) {
+		} else if (intr == ESP_INTR_BSERV) {
 			/* Only got status byte. */
 			ESPLOG(("esp%d: got status only, ", esp->esp_id));
-			if(!(esp->sreg & ESP_STAT_PERR)) {
+			if (!(esp->sreg & ESP_STAT_PERR)) {
 				SCptr->SCp.Status = esp->esp_command[0];
 				SCptr->SCp.Message = 0xff;
 			} else {
@@ -2915,22 +3055,22 @@
 			/* This shouldn't happen ever. */
 			ESPSTAT(("got bolixed\n"));
 			esp_advance_phase(SCptr, in_the_dark);
-			return esp_do_phase_determine(esp, eregs, dregs);
+			return esp_do_phase_determine(esp);
 		}
 
-		if(!message_out) {
+		if (!message_out) {
 			ESPSTAT(("status=%2x msg=%2x, ", SCptr->SCp.Status,
 				SCptr->SCp.Message));
-			if(SCptr->SCp.Message == COMMAND_COMPLETE) {
+			if (SCptr->SCp.Message == COMMAND_COMPLETE) {
 				ESPSTAT(("and was COMMAND_COMPLETE\n"));
 				esp_advance_phase(SCptr, in_freeing);
-				return esp_do_freebus(esp, eregs, dregs);
+				return esp_do_freebus(esp);
 			} else {
 				ESPLOG(("esp%d: and _not_ COMMAND_COMPLETE\n",
 					esp->esp_id));
 				esp->msgin_len = esp->msgin_ctr = 1;
 				esp_advance_phase(SCptr, in_msgindone);
-				return esp_do_msgindone(esp, eregs, dregs);
+				return esp_do_msgindone(esp);
 			}
 		} else {
 			/* With luck we'll be able to let the target
@@ -2945,42 +3085,42 @@
 			esp->cur_msgout[0] = message_out;
 			esp->msgout_len = esp->msgout_ctr = 1;
 			esp_advance_phase(SCptr, in_the_dark);
-			return esp_do_phase_determine(esp, eregs, dregs);
+			return esp_do_phase_determine(esp);
 		}
 	} else {
 		/* If we disconnect now, all hell breaks loose. */
 		ESPLOG(("esp%d: whoops, disconnect\n", esp->esp_id));
 		esp_advance_phase(SCptr, in_the_dark);
-		return esp_do_phase_determine(esp, eregs, dregs);
+		return esp_do_phase_determine(esp);
 	}
 }
 
-static int esp_enter_status(struct Sparc_ESP *esp,
-			    struct Sparc_ESP_regs *eregs,
-			    struct sparc_dma_registers *dregs)
+static int esp_enter_status(struct esp *esp)
 {
-	unchar thecmd = ESP_CMD_ICCSEQ;
+	u8 thecmd = ESP_CMD_ICCSEQ;
+
+	esp_cmd(esp, ESP_CMD_FLUSH);
+	if (esp->erev != fashme) {
+		u32 tmp;
 
-	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-	if(esp->erev != fashme) {
 		esp->esp_command[0] = esp->esp_command[1] = 0xff;
-		eregs->esp_tclow = 2;
-		eregs->esp_tcmed = 0;
-		dregs->cond_reg |= (DMA_ST_WRITE | DMA_ENABLE);
-		if(esp->dma->revision == dvmaesc1)
-			dregs->cnt = 0x100;
-		dregs->st_addr = esp->esp_command_dvma;
+		sbus_writeb(2, esp->eregs + ESP_TCLOW);
+		sbus_writeb(0, esp->eregs + ESP_TCMED);
+		tmp = sbus_readl(esp->dregs + DMA_CSR);
+		tmp |= (DMA_ST_WRITE | DMA_ENABLE);
+		sbus_writel(tmp, esp->dregs + DMA_CSR);
+		if (esp->dma->revision == dvmaesc1)
+			sbus_writel(0x100, esp->dregs + DMA_COUNT);
+		sbus_writel(esp->esp_command_dvma, esp->dregs + DMA_ADDR);
 		thecmd |= ESP_CMD_DMA;
 	}
-	esp_cmd(esp, eregs, thecmd);
+	esp_cmd(esp, thecmd);
 	esp_advance_phase(esp->current_SC, in_status);
 
-	return esp_do_status(esp, eregs, dregs);
+	return esp_do_status(esp);
 }
 
-static int esp_disconnect_amidst_phases(struct Sparc_ESP *esp,
-					struct Sparc_ESP_regs *eregs,
-					struct sparc_dma_registers *dregs)
+static int esp_disconnect_amidst_phases(struct esp *esp)
 {
 	Scsi_Cmnd *sp = esp->current_SC;
 	Scsi_Device *dp = sp->device;
@@ -2994,10 +3134,10 @@
 		phase_string(sp->SCp.phase),
 		phase_string(sp->SCp.sent_command)));
 
-	if(esp->disconnected_SC || (esp->erev == fashme))
-		esp_cmd(esp, eregs, ESP_CMD_ESEL);
+	if (esp->disconnected_SC != NULL || (esp->erev == fashme))
+		esp_cmd(esp, ESP_CMD_ESEL);
 
-	switch(esp->cur_msgout[0]) {
+	switch (esp->cur_msgout[0]) {
 	default:
 		/* We didn't expect this to happen at all. */
 		ESPLOG(("device is bolixed\n"));
@@ -3024,42 +3164,32 @@
 	return do_intr_end;
 }
 
-static int esp_enter_msgout(struct Sparc_ESP *esp,
-			    struct Sparc_ESP_regs *eregs,
-			    struct sparc_dma_registers *dregs)
+static int esp_enter_msgout(struct esp *esp)
 {
 	esp_advance_phase(esp->current_SC, in_msgout);
-	return esp_do_msgout(esp, eregs, dregs);
+	return esp_do_msgout(esp);
 }
 
-static int esp_enter_msgin(struct Sparc_ESP *esp,
-			   struct Sparc_ESP_regs *eregs,
-			   struct sparc_dma_registers *dregs)
+static int esp_enter_msgin(struct esp *esp)
 {
 	esp_advance_phase(esp->current_SC, in_msgin);
-	return esp_do_msgin(esp, eregs, dregs);
+	return esp_do_msgin(esp);
 }
 
-static int esp_enter_cmd(struct Sparc_ESP *esp,
-			 struct Sparc_ESP_regs *eregs,
-			 struct sparc_dma_registers *dregs)
+static int esp_enter_cmd(struct esp *esp)
 {
 	esp_advance_phase(esp->current_SC, in_cmdbegin);
-	return esp_do_cmdbegin(esp, eregs, dregs);
+	return esp_do_cmdbegin(esp);
 }
 
-static int esp_enter_badphase(struct Sparc_ESP *esp,
-			      struct Sparc_ESP_regs *eregs,
-			      struct sparc_dma_registers *dregs)
+static int esp_enter_badphase(struct esp *esp)
 {
 	ESPLOG(("esp%d: Bizarre bus phase %2x.\n", esp->esp_id,
 		esp->sreg & ESP_STAT_PMASK));
 	return do_reset_bus;
 }
 
-typedef int (*espfunc_t)(struct Sparc_ESP *,
-			 struct Sparc_ESP_regs *,
-			 struct sparc_dma_registers *);
+typedef int (*espfunc_t)(struct esp *);
 
 static espfunc_t phase_vector[] = {
 	esp_do_data,		/* ESP_DOP */
@@ -3075,39 +3205,38 @@
 /* The target has control of the bus and we have to see where it has
  * taken us.
  */
-static int esp_do_phase_determine(struct Sparc_ESP *esp,
-				  struct Sparc_ESP_regs *eregs,
-				  struct sparc_dma_registers *dregs)
+static int esp_do_phase_determine(struct esp *esp)
 {
 	if ((esp->ireg & ESP_INTR_DC) != 0)
-		return esp_disconnect_amidst_phases(esp, eregs, dregs);
-	return phase_vector[esp->sreg & ESP_STAT_PMASK](esp, eregs, dregs);
+		return esp_disconnect_amidst_phases(esp);
+	return phase_vector[esp->sreg & ESP_STAT_PMASK](esp);
 }
 
 /* First interrupt after exec'ing a cmd comes here. */
-static int esp_select_complete(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			       struct sparc_dma_registers *dregs)
+static int esp_select_complete(struct esp *esp)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 	Scsi_Device *SDptr = SCptr->device;
 	int cmd_bytes_sent, fcnt;
 
-	if(esp->erev != fashme)
-		esp->seqreg = (eregs->esp_sstep & ESP_STEP_VBITS);
-	if(esp->erev == fashme)
+	if (esp->erev != fashme)
+		esp->seqreg = (sbus_readb(esp->eregs + ESP_SSTEP) & ESP_STEP_VBITS);
+
+	if (esp->erev == fashme)
 		fcnt = esp->hme_fifo_workaround_count;
 	else
-		fcnt = (eregs->esp_fflags & ESP_FF_FBYTES);
-	cmd_bytes_sent = esp_bytes_sent(esp, dregs, fcnt);
-	dma_invalidate(esp, dregs, esp->dma->revision);
+		fcnt = (sbus_readb(esp->eregs + ESP_FFLAGS) & ESP_FF_FBYTES);
+
+	cmd_bytes_sent = esp_bytes_sent(esp, fcnt);
+	dma_invalidate(esp);
 
 	/* Let's check to see if a reselect happened
 	 * while we we're trying to select.  This must
 	 * be checked first.
 	 */
-	if(esp->ireg == (ESP_INTR_RSEL | ESP_INTR_FDONE)) {
+	if (esp->ireg == (ESP_INTR_RSEL | ESP_INTR_FDONE)) {
 		esp_reconnect(esp, SCptr);
-		return esp_do_reconnect(esp, eregs, dregs);
+		return esp_do_reconnect(esp);
 	}
 
 	/* Looks like things worked, we should see a bus service &
@@ -3116,18 +3245,18 @@
 	 * be fooled into thinking selection was successful if
 	 * ESP_INTR_DC is set, see below.
 	 */
-	if(esp->ireg == (ESP_INTR_FDONE | ESP_INTR_BSERV)) {
+	if (esp->ireg == (ESP_INTR_FDONE | ESP_INTR_BSERV)) {
 		/* target speaks... */
 		esp->targets_present |= (1<<SCptr->target);
 
 		/* What if the target ignores the sdtr? */
-		if(esp->snip)
+		if (esp->snip)
 			SDptr->sync = 1;
 
 		/* See how far, if at all, we got in getting
 		 * the information out to the target.
 		 */
-		switch(esp->seqreg) {
+		switch (esp->seqreg) {
 		default:
 
 		case ESP_STEP_ASEL:
@@ -3201,28 +3330,29 @@
 		case ESP_STEP_FINI6:
 		case ESP_STEP_FINI7:
 			/* Account for the identify message */
-			if(SCptr->SCp.phase == in_slct_norm)
+			if (SCptr->SCp.phase == in_slct_norm)
 				cmd_bytes_sent -= 1;
 		};
-		if(esp->erev != fashme)
-			esp_cmd(esp, eregs, ESP_CMD_NULL);
+
+		if (esp->erev != fashme)
+			esp_cmd(esp, ESP_CMD_NULL);
 
 		/* Be careful, we could really get fucked during synchronous
 		 * data transfers if we try to flush the fifo now.
 		 */
-		if((esp->erev != fashme) && /* not a Happy Meal and... */
-		   !fcnt && /* Fifo is empty and... */
-		   /* either we are not doing synchronous transfers or... */
-		   (!SDptr->sync_max_offset ||
-		    /* We are not going into data in phase. */
-		    ((esp->sreg & ESP_STAT_PMASK) != ESP_DIP)))
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH); /* flush is safe */
+		if ((esp->erev != fashme) && /* not a Happy Meal and... */
+		    !fcnt && /* Fifo is empty and... */
+		    /* either we are not doing synchronous transfers or... */
+		    (!SDptr->sync_max_offset ||
+		     /* We are not going into data in phase. */
+		     ((esp->sreg & ESP_STAT_PMASK) != ESP_DIP)))
+			esp_cmd(esp, ESP_CMD_FLUSH); /* flush is safe */
 
 		/* See how far we got if this is not a slow command. */
-		if(!esp->esp_slowcmd) {
-			if(cmd_bytes_sent < 0)
+		if (!esp->esp_slowcmd) {
+			if (cmd_bytes_sent < 0)
 				cmd_bytes_sent = 0;
-			if(cmd_bytes_sent != SCptr->cmd_len) {
+			if (cmd_bytes_sent != SCptr->cmd_len) {
 				/* Crapola, mark it as a slowcmd
 				 * so that we have some chance of
 				 * keeping the command alive with
@@ -3250,11 +3380,11 @@
 
 		/* Now figure out where we went. */
 		esp_advance_phase(SCptr, in_the_dark);
-		return esp_do_phase_determine(esp, eregs, dregs);
+		return esp_do_phase_determine(esp);
 	}
 
 	/* Did the target even make it? */
-	if(esp->ireg == ESP_INTR_DC) {
+	if (esp->ireg == ESP_INTR_DC) {
 		/* wheee... nobody there or they didn't like
 		 * what we told it to do, clean up.
 		 */
@@ -3263,13 +3393,14 @@
 		 * a command in the background for us, tell
 		 * the ESP to listen for them.
 		 */
-		if(esp->disconnected_SC)
-			esp_cmd(esp, eregs, ESP_CMD_ESEL);
+		if (esp->disconnected_SC)
+			esp_cmd(esp, ESP_CMD_ESEL);
 
-		if(((1<<SCptr->target) & esp->targets_present) &&
-		   esp->seqreg && esp->cur_msgout[0] == EXTENDED_MESSAGE &&
-		   (SCptr->SCp.phase == in_slct_msg ||
-		    SCptr->SCp.phase == in_slct_stop)) {
+		if (((1<<SCptr->target) & esp->targets_present) &&
+		    esp->seqreg != 0 &&
+		    (esp->cur_msgout[0] == EXTENDED_MESSAGE) &&
+		    (SCptr->SCp.phase == in_slct_msg ||
+		     SCptr->SCp.phase == in_slct_stop)) {
 			/* shit */
 			esp->snip = 0;
 			ESPLOG(("esp%d: Failed synchronous negotiation for target %d "
@@ -3299,7 +3430,7 @@
 		 * or whenever when we are scanning the bus for targets.
 		 * But first make sure that is really what is happening.
 		 */
-		if(((1<<SCptr->target) & esp->targets_present)) {
+		if (((1<<SCptr->target) & esp->targets_present)) {
 			ESPLOG(("esp%d: Warning, live target %d not responding to "
 				"selection.\n", esp->esp_id, SCptr->target));
 
@@ -3320,38 +3451,30 @@
 		return do_intr_end;
 	}
 
-
 	ESPLOG(("esp%d: Selection failure.\n", esp->esp_id));
 	printk("esp%d: Currently -- ", esp->esp_id);
-	esp_print_ireg(esp->ireg);
-	printk(" ");
-	esp_print_statreg(esp->sreg);
-	printk(" ");
-	esp_print_seqreg(esp->seqreg);
-	printk("\n");
+	esp_print_ireg(esp->ireg); printk(" ");
+	esp_print_statreg(esp->sreg); printk(" ");
+	esp_print_seqreg(esp->seqreg); printk("\n");
 	printk("esp%d: New -- ", esp->esp_id);
-	esp->sreg = eregs->esp_status;
-	esp->seqreg = eregs->esp_sstep;
-	esp->ireg = eregs->esp_intrpt;
-	esp_print_ireg(esp->ireg);
-	printk(" ");
-	esp_print_statreg(esp->sreg);
-	printk(" ");
-	esp_print_seqreg(esp->seqreg);
-	printk("\n");
+	esp->sreg = sbus_readb(esp->eregs + ESP_STATUS);
+	esp->seqreg = sbus_readb(esp->eregs + ESP_SSTEP);
+	esp->ireg = sbus_readb(esp->eregs + ESP_INTRPT);
+	esp_print_ireg(esp->ireg); printk(" ");
+	esp_print_statreg(esp->sreg); printk(" ");
+	esp_print_seqreg(esp->seqreg); printk("\n");
 	ESPLOG(("esp%d: resetting bus\n", esp->esp_id));
 	return do_reset_bus; /* ugh... */
 }
 
 /* Continue reading bytes for msgin phase. */
-static int esp_do_msgincont(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			    struct sparc_dma_registers *dregs)
+static int esp_do_msgincont(struct esp *esp)
 {
-	if(esp->ireg & ESP_INTR_BSERV) {
+	if (esp->ireg & ESP_INTR_BSERV) {
 		/* in the right phase too? */
-		if((esp->sreg & ESP_STAT_PMASK) == ESP_MIP) {
+		if ((esp->sreg & ESP_STAT_PMASK) == ESP_MIP) {
 			/* phew... */
-			esp_cmd(esp, eregs, ESP_CMD_TI);
+			esp_cmd(esp, ESP_CMD_TI);
 			esp_advance_phase(esp->current_SC, in_msgindone);
 			return do_intr_end;
 		}
@@ -3370,25 +3493,23 @@
 	return do_phase_determine;
 }
 
-static int check_singlebyte_msg(struct Sparc_ESP *esp,
-				struct Sparc_ESP_regs *eregs,
-				struct sparc_dma_registers *dregs)
+static int check_singlebyte_msg(struct esp *esp)
 {
 	esp->prevmsgin = esp->cur_msgin[0];
-	if(esp->cur_msgin[0] & 0x80) {
+	if (esp->cur_msgin[0] & 0x80) {
 		/* wheee... */
 		ESPLOG(("esp%d: target sends identify amidst phases\n",
 			esp->esp_id));
 		esp_advance_phase(esp->current_SC, in_the_dark);
 		return 0;
-	} else if(((esp->cur_msgin[0] & 0xf0) == 0x20) ||
-		  (esp->cur_msgin[0] == EXTENDED_MESSAGE)) {
+	} else if (((esp->cur_msgin[0] & 0xf0) == 0x20) ||
+		   (esp->cur_msgin[0] == EXTENDED_MESSAGE)) {
 		esp->msgin_len = 2;
 		esp_advance_phase(esp->current_SC, in_msgincont);
 		return 0;
 	}
 	esp_advance_phase(esp->current_SC, in_the_dark);
-	switch(esp->cur_msgin[0]) {
+	switch (esp->cur_msgin[0]) {
 	default:
 		/* We don't want to hear about it. */
 		ESPLOG(("esp%d: msg %02x which we don't know about\n", esp->esp_id,
@@ -3406,7 +3527,7 @@
 		 * a save/restore pointer sequence so early in the
 		 * bus transition sequences, but cover it.
 		 */
-		if(esp->esp_slowcmd) {
+		if (esp->esp_slowcmd) {
 			esp->esp_scmdleft = esp->current_SC->cmd_len;
 			esp->esp_scmdp = &esp->current_SC->cmnd[0];
 		}
@@ -3425,7 +3546,7 @@
 
 	case MESSAGE_REJECT:
 		ESPMISC(("msg reject, "));
-		if(esp->prevmsgout == EXTENDED_MESSAGE) {
+		if (esp->prevmsgout == EXTENDED_MESSAGE) {
 			Scsi_Device *SDptr = esp->current_SC->device;
 
 			/* Doesn't look like this target can
@@ -3449,11 +3570,11 @@
  * the SCSI2 standard specifically recommends against targets doing
  * this because so many initiators cannot cope with this occuring.
  */
-static int target_with_ants_in_pants(struct Sparc_ESP *esp,
+static int target_with_ants_in_pants(struct esp *esp,
 				     Scsi_Cmnd *SCptr,
 				     Scsi_Device *SDptr)
 {
-	if(SDptr->sync || SDptr->borken) {
+	if (SDptr->sync || SDptr->borken) {
 		/* sorry, no can do */
 		ESPSDTR(("forcing to async, "));
 		build_sync_nego_msg(esp, 0, 0);
@@ -3468,23 +3589,23 @@
 	return 0;
 }
 
-static void sync_report(struct Sparc_ESP *esp)
+static void sync_report(struct esp *esp)
 {
 	int msg3, msg4;
 	char *type;
 
 	msg3 = esp->cur_msgin[3];
 	msg4 = esp->cur_msgin[4];
-	if(msg4) {
+	if (msg4) {
 		int hz = 1000000000 / (msg3 * 4);
 		int integer = hz / 1000000;
 		int fraction = (hz - (integer * 1000000)) / 10000;
-		if((esp->erev == fashme) &&
-		   (esp->config3[esp->current_SC->target] & ESP_CONFIG3_EWIDE)) {
+		if ((esp->erev == fashme) &&
+		    (esp->config3[esp->current_SC->target] & ESP_CONFIG3_EWIDE)) {
 			type = "FAST-WIDE";
 			integer <<= 1;
 			fraction <<= 1;
-		} else if((msg3 * 4) < 200) {
+		} else if ((msg3 * 4) < 200) {
 			type = "FAST";
 		} else {
 			type = "synchronous";
@@ -3507,36 +3628,34 @@
 	}
 }
 
-static int check_multibyte_msg(struct Sparc_ESP *esp,
-			       struct Sparc_ESP_regs *eregs,
-			       struct sparc_dma_registers *dregs)
+static int check_multibyte_msg(struct esp *esp)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 	Scsi_Device *SDptr = SCptr->device;
-	unchar regval = 0;
+	u8 regval = 0;
 	int message_out = 0;
 
 	ESPSDTR(("chk multibyte msg: "));
-	if(esp->cur_msgin[2] == EXTENDED_SDTR) {
+	if (esp->cur_msgin[2] == EXTENDED_SDTR) {
 		int period = esp->cur_msgin[3];
 		int offset = esp->cur_msgin[4];
 
 		ESPSDTR(("is sync nego response, "));
-		if(!esp->snip) {
+		if (!esp->snip) {
 			int rval;
 
 			/* Target negotiates first! */
 			ESPSDTR(("target jumps the gun, "));
 			message_out = EXTENDED_MESSAGE; /* we must respond */
 			rval = target_with_ants_in_pants(esp, SCptr, SDptr);
-			if(rval)
+			if (rval)
 				return rval;
 		}
 
 		ESPSDTR(("examining sdtr, "));
 
 		/* Offset cannot be larger than ESP fifo size. */
-		if(offset > 15) {
+		if (offset > 15) {
 			ESPSDTR(("offset too big %2x, ", offset));
 			offset = 15;
 			ESPSDTR(("sending back new offset\n"));
@@ -3544,7 +3663,7 @@
 			return EXTENDED_MESSAGE;
 		}
 
-		if(offset && period > esp->max_period) {
+		if (offset && period > esp->max_period) {
 			/* Yeee, async for this slow device. */
 			ESPSDTR(("period too long %2x, ", period));
 			build_sync_nego_msg(esp, 0, 0);
@@ -3554,65 +3673,77 @@
 		} else if (offset && period < esp->min_period) {
 			ESPSDTR(("period too short %2x, ", period));
 			period = esp->min_period;
-			if(esp->erev > esp236)
+			if (esp->erev > esp236)
 				regval = 4;
 			else
 				regval = 5;
-		} else if(offset) {
+		} else if (offset) {
 			int tmp;
 
 			ESPSDTR(("period is ok, "));
 			tmp = esp->ccycle / 1000;
 			regval = (((period << 2) + tmp - 1) / tmp);
-			if(regval && ((esp->erev == fas100a ||
-				       esp->erev == fas236 ||
-				       esp->erev == fashme))) {
-				if(period >= 50)
+			if (regval && ((esp->erev == fas100a ||
+					esp->erev == fas236  ||
+					esp->erev == fashme))) {
+				if (period >= 50)
 					regval--;
 			}
 		}
 
-		if(offset) {
-			unchar bit;
+		if (offset) {
+			u8 bit;
 
 			SDptr->sync_min_period = (regval & 0x1f);
 			SDptr->sync_max_offset = (offset | esp->radelay);
-			if((esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme)) {
-				if((esp->erev == fas100a) || (esp->erev == fashme))
+			if (esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme) {
+				if ((esp->erev == fas100a) || (esp->erev == fashme))
 					bit = ESP_CONFIG3_FAST;
 				else
 					bit = ESP_CONFIG3_FSCSI;
-				if(period < 50)
+				if (period < 50) {
+					/* On FAS366, if using fast-20 synchronous transfers
+					 * we need to make sure the REQ/ACK assert/deassert
+					 * control bits are clear.
+					 */
+					if (esp->erev == fashme)
+						SDptr->sync_max_offset &= ~esp->radelay;
 					esp->config3[SCptr->target] |= bit;
-				else
+				} else {
 					esp->config3[SCptr->target] &= ~bit;
-				eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[SCptr->target];
+				}
+				esp->prev_cfg3 = esp->config3[SCptr->target];
+				sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3);
 			}
-			eregs->esp_soff = esp->prev_soff = SDptr->sync_min_period;
-			eregs->esp_stp  = esp->prev_stp  = SDptr->sync_max_offset;
-
+			esp->prev_soff = SDptr->sync_max_offset;
+			esp->prev_stp = SDptr->sync_min_period;
+			sbus_writeb(esp->prev_soff, esp->eregs + ESP_SOFF);
+			sbus_writeb(esp->prev_stp, esp->eregs + ESP_STP);
 			ESPSDTR(("soff=%2x stp=%2x cfg3=%2x\n",
-				SDptr->sync_max_offset,
-				SDptr->sync_min_period,
-				esp->config3[SCptr->target]));
+				 SDptr->sync_max_offset,
+				 SDptr->sync_min_period,
+				 esp->config3[SCptr->target]));
 
 			esp->snip = 0;
-		} else if(SDptr->sync_max_offset) {
-			unchar bit;
+		} else if (SDptr->sync_max_offset) {
+			u8 bit;
 
 			/* back to async mode */
 			ESPSDTR(("unaccaptable sync nego, forcing async\n"));
 			SDptr->sync_max_offset = 0;
 			SDptr->sync_min_period = 0;
-			eregs->esp_soff = esp->prev_soff = 0;
-			eregs->esp_stp = esp->prev_stp = 0;
-			if((esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme)) {
-				if((esp->erev == fas100a) || (esp->erev == fashme))
+			esp->prev_soff = 0;
+			esp->prev_stp = 0;
+			sbus_writeb(esp->prev_soff, esp->eregs + ESP_SOFF);
+			sbus_writeb(esp->prev_stp, esp->eregs + ESP_STP);
+			if (esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme) {
+				if ((esp->erev == fas100a) || (esp->erev == fashme))
 					bit = ESP_CONFIG3_FAST;
 				else
 					bit = ESP_CONFIG3_FSCSI;
 				esp->config3[SCptr->target] &= ~bit;
-				eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[SCptr->target];
+				esp->prev_cfg3 = esp->config3[SCptr->target];
+				sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3);
 			}
 		}
 
@@ -3621,7 +3752,7 @@
 		ESPSDTR(("chk multibyte msg: sync is known, "));
 		SDptr->sync = 1;
 
-		if(message_out) {
+		if (message_out) {
 			ESPLOG(("esp%d: sending sdtr back, hoping for msgout\n",
 				esp->esp_id));
 			build_sync_nego_msg(esp, period, offset);
@@ -3632,26 +3763,26 @@
 		ESPSDTR(("returning zero\n"));
 		esp_advance_phase(SCptr, in_the_dark); /* ...or else! */
 		return 0;
-	} else if(esp->cur_msgin[2] == EXTENDED_WDTR) {
+	} else if (esp->cur_msgin[2] == EXTENDED_WDTR) {
 		int size = 8 << esp->cur_msgin[3];
 
 		esp->wnip = 0;
-		if(esp->erev != fashme) {
+		if (esp->erev != fashme) {
 			ESPLOG(("esp%d: AIEEE wide msg received and not HME.\n",
 				esp->esp_id));
 			message_out = MESSAGE_REJECT;
-		} else if(size > 16) {
+		} else if (size > 16) {
 			ESPLOG(("esp%d: AIEEE wide transfer for %d size "
 				"not supported.\n", esp->esp_id, size));
 			message_out = MESSAGE_REJECT;
 		} else {
 			/* Things look good; let's see what we got. */
-			if(size == 16) {
+			if (size == 16) {
 				/* Set config 3 register for this target. */
 				esp->config3[SCptr->target] |= ESP_CONFIG3_EWIDE;
 			} else {
 				/* Just make sure it was one byte sized. */
-				if(size != 8) {
+				if (size != 8) {
 					ESPLOG(("esp%d: Aieee, wide nego of %d size.\n",
 						esp->esp_id, size));
 					message_out = MESSAGE_REJECT;
@@ -3660,7 +3791,8 @@
 				/* Pure paranoia. */
 				esp->config3[SCptr->target] &= ~(ESP_CONFIG3_EWIDE);
 			}
-			eregs->esp_cfg3 = esp->prev_cfg3 = esp->config3[SCptr->target];
+			esp->prev_cfg3 = esp->config3[SCptr->target];
+			sbus_writeb(esp->prev_cfg3, esp->eregs + ESP_CFG3);
 
 			/* Regardless, next try for sync transfers. */
 			build_sync_nego_msg(esp, esp->sync_defp, 15);
@@ -3668,7 +3800,7 @@
 			esp->snip = 1;
 			message_out = EXTENDED_MESSAGE;
 		}
-	} else if(esp->cur_msgin[2] == EXTENDED_MODIFY_DATA_POINTER) {
+	} else if (esp->cur_msgin[2] == EXTENDED_MODIFY_DATA_POINTER) {
 		ESPLOG(("esp%d: rejecting modify data ptr msg\n", esp->esp_id));
 		message_out = MESSAGE_REJECT;
 	}
@@ -3677,39 +3809,38 @@
 	return message_out;
 }
 
-static int esp_do_msgindone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			    struct sparc_dma_registers *dregs)
+static int esp_do_msgindone(struct esp *esp)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 	int message_out = 0, it = 0, rval;
 
-	rval = skipahead1(esp, eregs, dregs, SCptr, in_msgin, in_msgindone);
-	if(rval)
+	rval = skipahead1(esp, SCptr, in_msgin, in_msgindone);
+	if (rval)
 		return rval;
-	if(SCptr->SCp.sent_command != in_status) {
-		if(!(esp->ireg & ESP_INTR_DC)) {
-			if(esp->msgin_len && (esp->sreg & ESP_STAT_PERR)) {
+	if (SCptr->SCp.sent_command != in_status) {
+		if (!(esp->ireg & ESP_INTR_DC)) {
+			if (esp->msgin_len && (esp->sreg & ESP_STAT_PERR)) {
 				message_out = MSG_PARITY_ERROR;
-				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-			} else if(esp->erev != fashme &&
-				  (it = (eregs->esp_fflags & ESP_FF_FBYTES))!=1) {
+				esp_cmd(esp, ESP_CMD_FLUSH);
+			} else if (esp->erev != fashme &&
+			  (it = (sbus_readb(esp->eregs + ESP_FFLAGS) & ESP_FF_FBYTES)) != 1) {
 				/* We certainly dropped the ball somewhere. */
 				message_out = INITIATOR_ERROR;
-				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-			} else if(!esp->msgin_len) {
-				if(esp->erev == fashme)
+				esp_cmd(esp, ESP_CMD_FLUSH);
+			} else if (!esp->msgin_len) {
+				if (esp->erev == fashme)
 					it = esp->hme_fifo_workaround_buffer[0];
 				else
-					it = eregs->esp_fdata;
+					it = sbus_readb(esp->eregs + ESP_FDATA);
 				esp_advance_phase(SCptr, in_msgincont);
 			} else {
 				/* it is ok and we want it */
-				if(esp->erev == fashme)
+				if (esp->erev == fashme)
 					it = esp->cur_msgin[esp->msgin_ctr] =
 						esp->hme_fifo_workaround_buffer[0];
 				else
 					it = esp->cur_msgin[esp->msgin_ctr] =
-						eregs->esp_fdata;
+						sbus_readb(esp->eregs + ESP_FDATA);
 				esp->msgin_ctr++;
 			}
 		} else {
@@ -3719,14 +3850,14 @@
 	} else {
 		it = esp->cur_msgin[0];
 	}
-	if(!message_out && esp->msgin_len) {
-		if(esp->msgin_ctr < esp->msgin_len) {
+	if (!message_out && esp->msgin_len) {
+		if (esp->msgin_ctr < esp->msgin_len) {
 			esp_advance_phase(SCptr, in_msgincont);
-		} else if(esp->msgin_len == 1) {
-			message_out = check_singlebyte_msg(esp, eregs, dregs);
-		} else if(esp->msgin_len == 2) {
-			if(esp->cur_msgin[0] == EXTENDED_MESSAGE) {
-				if((it+2) >= 15) {
+		} else if (esp->msgin_len == 1) {
+			message_out = check_singlebyte_msg(esp);
+		} else if (esp->msgin_len == 2) {
+			if (esp->cur_msgin[0] == EXTENDED_MESSAGE) {
+				if ((it + 2) >= 15) {
 					message_out = MESSAGE_REJECT;
 				} else {
 					esp->msgin_len = (it + 2);
@@ -3736,102 +3867,103 @@
 				message_out = MESSAGE_REJECT; /* foo on you */
 			}
 		} else {
-			message_out = check_multibyte_msg(esp, eregs, dregs);
+			message_out = check_multibyte_msg(esp);
 		}
 	}
-	if(message_out < 0) {
+	if (message_out < 0) {
 		return -message_out;
-	} else if(message_out) {
-		if(((message_out != 1) &&
-		    ((message_out < 0x20) || (message_out & 0x80))))
+	} else if (message_out) {
+		if (((message_out != 1) &&
+		     ((message_out < 0x20) || (message_out & 0x80))))
 			esp->msgout_len = 1;
 		esp->cur_msgout[0] = message_out;
-		esp_cmd(esp, eregs, ESP_CMD_SATN);
+		esp_cmd(esp, ESP_CMD_SATN);
 		esp_advance_phase(SCptr, in_the_dark);
 		esp->msgin_len = 0;
 	}
-	esp->sreg = eregs->esp_status;
+	esp->sreg = sbus_readb(esp->eregs + ESP_STATUS);
 	esp->sreg &= ~(ESP_STAT_INTR);
-	if((esp->sreg & (ESP_STAT_PMSG|ESP_STAT_PCD)) == (ESP_STAT_PMSG|ESP_STAT_PCD))
-		esp_cmd(esp, eregs, ESP_CMD_MOK);
-	if((SCptr->SCp.sent_command == in_msgindone) &&
+	if ((esp->sreg & (ESP_STAT_PMSG|ESP_STAT_PCD)) == (ESP_STAT_PMSG|ESP_STAT_PCD))
+		esp_cmd(esp, ESP_CMD_MOK);
+	if ((SCptr->SCp.sent_command == in_msgindone) &&
 	    (SCptr->SCp.phase == in_freeing))
-		return esp_do_freebus(esp, eregs, dregs);
+		return esp_do_freebus(esp);
 	return do_intr_end;
 }
 
-static int esp_do_cmdbegin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			   struct sparc_dma_registers *dregs)
+static int esp_do_cmdbegin(struct esp *esp)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 
 	esp_advance_phase(SCptr, in_cmdend);
-	if(esp->erev == fashme) {
-		unsigned long tmp = dregs->cond_reg;
+	if (esp->erev == fashme) {
+		u32 tmp = sbus_readl(esp->dregs + DMA_CSR);
 		int i;
 
-		for(i = 0; i < esp->esp_scmdleft; i++)
+		for (i = 0; i < esp->esp_scmdleft; i++)
 			esp->esp_command[i] = *esp->esp_scmdp++;
 		esp->esp_scmdleft = 0;
-		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-		esp_setcount(eregs, i, 1);
-		esp_cmd(esp, eregs, (ESP_CMD_DMA | ESP_CMD_TI));
+		esp_cmd(esp, ESP_CMD_FLUSH);
+		esp_setcount(esp->eregs, i, 1);
+		esp_cmd(esp, (ESP_CMD_DMA | ESP_CMD_TI));
 		tmp |= (DMA_SCSI_DISAB | DMA_ENABLE);
 		tmp &= ~(DMA_ST_WRITE);
-		dregs->cnt = i;
-		dregs->st_addr = esp->esp_command_dvma;
-		dregs->cond_reg = tmp;
+		sbus_writel(i, esp->dregs + DMA_COUNT);
+		sbus_writel(esp->esp_command_dvma, esp->dregs + DMA_ADDR);
+		sbus_writel(tmp, esp->dregs + DMA_CSR);
 	} else {
-		unsigned char tmp;
-		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+		u8 tmp;
+
+		esp_cmd(esp, ESP_CMD_FLUSH);
 		tmp = *esp->esp_scmdp++;
 		esp->esp_scmdleft--;
-		eregs->esp_fdata = tmp;
-		esp_cmd(esp, eregs, ESP_CMD_TI);
+		sbus_writeb(tmp, esp->eregs + ESP_FDATA);
+		esp_cmd(esp, ESP_CMD_TI);
 	}
 	return do_intr_end;
 }
 
-static int esp_do_cmddone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			  struct sparc_dma_registers *dregs)
+static int esp_do_cmddone(struct esp *esp)
 {
-	if(esp->erev == fashme)
-		dma_invalidate(esp, dregs, dvmahme);
+	if (esp->erev == fashme)
+		dma_invalidate(esp);
 	else
-		esp_cmd(esp, eregs, ESP_CMD_NULL);
-	if(esp->ireg & ESP_INTR_BSERV) {
+		esp_cmd(esp, ESP_CMD_NULL);
+
+	if (esp->ireg & ESP_INTR_BSERV) {
 		esp_advance_phase(esp->current_SC, in_the_dark);
-		return esp_do_phase_determine(esp, eregs, dregs);
+		return esp_do_phase_determine(esp);
 	}
+
 	ESPLOG(("esp%d: in do_cmddone() but didn't get BSERV interrupt.\n",
 		esp->esp_id));
 	return do_reset_bus;
 }
 
-static int esp_do_msgout(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			 struct sparc_dma_registers *dregs)
+static int esp_do_msgout(struct esp *esp)
 {
-	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-	switch(esp->msgout_len) {
+	esp_cmd(esp, ESP_CMD_FLUSH);
+	switch (esp->msgout_len) {
 	case 1:
-		if(esp->erev == fashme)
-			hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 1);
+		if (esp->erev == fashme)
+			hme_fifo_push(esp, &esp->cur_msgout[0], 1);
 		else
-			eregs->esp_fdata = esp->cur_msgout[0];
-		esp_cmd(esp, eregs, ESP_CMD_TI);
+			sbus_writeb(esp->cur_msgout[0], esp->eregs + ESP_FDATA);
+
+		esp_cmd(esp, ESP_CMD_TI);
 		break;
 
 	case 2:
 		esp->esp_command[0] = esp->cur_msgout[0];
 		esp->esp_command[1] = esp->cur_msgout[1];
-		if(esp->erev == fashme) {
-			hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 2);
-			esp_cmd(esp, eregs, ESP_CMD_TI);
+
+		if (esp->erev == fashme) {
+			hme_fifo_push(esp, &esp->cur_msgout[0], 2);
+			esp_cmd(esp, ESP_CMD_TI);
 		} else {
-			dma_setup(dregs, esp->dma->revision,
-				  esp->esp_command_dvma, 2, 0);
-			esp_setcount(eregs, 2, 0);
-			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
+			dma_setup(esp, esp->esp_command_dvma, 2, 0);
+			esp_setcount(esp->eregs, 2, 0);
+			esp_cmd(esp, ESP_CMD_DMA | ESP_CMD_TI);
 		}
 		break;
 
@@ -3841,14 +3973,14 @@
 		esp->esp_command[2] = esp->cur_msgout[2];
 		esp->esp_command[3] = esp->cur_msgout[3];
 		esp->snip = 1;
-		if(esp->erev == fashme) {
-			hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 4);
-			esp_cmd(esp, eregs, ESP_CMD_TI);
+
+		if (esp->erev == fashme) {
+			hme_fifo_push(esp, &esp->cur_msgout[0], 4);
+			esp_cmd(esp, ESP_CMD_TI);
 		} else {
-			dma_setup(dregs, esp->dma->revision,
-				  esp->esp_command_dvma, 4, 0);
-			esp_setcount(eregs, 4, 0);
-			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
+			dma_setup(esp, esp->esp_command_dvma, 4, 0);
+			esp_setcount(esp->eregs, 4, 0);
+			esp_cmd(esp, ESP_CMD_DMA | ESP_CMD_TI);
 		}
 		break;
 
@@ -3859,14 +3991,14 @@
 		esp->esp_command[3] = esp->cur_msgout[3];
 		esp->esp_command[4] = esp->cur_msgout[4];
 		esp->snip = 1;
-		if(esp->erev == fashme) {
-			hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 5);
-			esp_cmd(esp, eregs, ESP_CMD_TI);
+
+		if (esp->erev == fashme) {
+			hme_fifo_push(esp, &esp->cur_msgout[0], 5);
+			esp_cmd(esp, ESP_CMD_TI);
 		} else {
-			dma_setup(dregs, esp->dma->revision,
-				  esp->esp_command_dvma, 5, 0);
-			esp_setcount(eregs, 5, 0);
-			esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
+			dma_setup(esp, esp->esp_command_dvma, 5, 0);
+			esp_setcount(esp->eregs, 5, 0);
+			esp_cmd(esp, ESP_CMD_DMA | ESP_CMD_TI);
 		}
 		break;
 
@@ -3874,46 +4006,51 @@
 		/* whoops */
 		ESPMISC(("bogus msgout sending NOP\n"));
 		esp->cur_msgout[0] = NOP;
-		if(esp->erev == fashme) {
-			hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 1);
+
+		if (esp->erev == fashme) {
+			hme_fifo_push(esp, &esp->cur_msgout[0], 1);
 		} else {
-			eregs->esp_fdata = esp->cur_msgout[0];
+			sbus_writeb(esp->cur_msgout[0], esp->eregs + ESP_FDATA);
 		}
+
 		esp->msgout_len = 1;
-		esp_cmd(esp, eregs, ESP_CMD_TI);
+		esp_cmd(esp, ESP_CMD_TI);
 		break;
-	}
+	};
+
 	esp_advance_phase(esp->current_SC, in_msgoutdone);
 	return do_intr_end;
 }
 
-static int esp_do_msgoutdone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			     struct sparc_dma_registers *dregs)
+static int esp_do_msgoutdone(struct esp *esp)
 {
-	if(esp->msgout_len > 1) {
+	if (esp->msgout_len > 1) {
 		/* XXX HME/FAS ATN deassert workaround required,
 		 * XXX no DMA flushing, only possible ESP_CMD_FLUSH
 		 * XXX to kill the fifo.
 		 */
-		if(esp->erev != fashme) {
-			while(dregs->cond_reg & DMA_PEND_READ)
+		if (esp->erev != fashme) {
+			u32 tmp;
+
+			while ((tmp = sbus_readl(esp->dregs + DMA_CSR)) & DMA_PEND_READ)
 				udelay(1);
-			dregs->cond_reg &= ~(DMA_ENABLE);
-			dma_invalidate(esp, dregs, esp->dma->revision);
+			tmp &= ~DMA_ENABLE;
+			sbus_writel(tmp, esp->dregs + DMA_CSR);
+			dma_invalidate(esp);
 		} else {
-			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+			esp_cmd(esp, ESP_CMD_FLUSH);
 		}
 	}
-	if(!(esp->ireg & ESP_INTR_DC)) {
-		if(esp->erev != fashme)
-			esp_cmd(esp, eregs, ESP_CMD_NULL);
-		switch(esp->sreg & ESP_STAT_PMASK) {
+	if (!(esp->ireg & ESP_INTR_DC)) {
+		if (esp->erev != fashme)
+			esp_cmd(esp, ESP_CMD_NULL);
+		switch (esp->sreg & ESP_STAT_PMASK) {
 		case ESP_MOP:
 			/* whoops, parity error */
 			ESPLOG(("esp%d: still in msgout, parity error assumed\n",
 				esp->esp_id));
-			if(esp->msgout_len > 1)
-				esp_cmd(esp, eregs, ESP_CMD_SATN);
+			if (esp->msgout_len > 1)
+				esp_cmd(esp, ESP_CMD_SATN);
 			esp_advance_phase(esp->current_SC, in_msgout);
 			return do_work_bus;
 
@@ -3922,10 +4059,10 @@
 
 		default:
 			/* Happy Meal fifo is touchy... */
-			if((esp->erev != fashme) &&
-			   !fcount(esp, eregs) &&
-			   !(esp->current_SC->device->sync_max_offset))
-				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+			if ((esp->erev != fashme) &&
+			    !fcount(esp) &&
+			    !(esp->current_SC->device->sync_max_offset))
+				esp_cmd(esp, ESP_CMD_FLUSH);
 			break;
 
 		};
@@ -3937,19 +4074,18 @@
 	/* If we sent out a synchronous negotiation message, update
 	 * our state.
 	 */
-	if(esp->cur_msgout[2] == EXTENDED_MESSAGE &&
-	   esp->cur_msgout[4] == EXTENDED_SDTR) {
+	if (esp->cur_msgout[2] == EXTENDED_MESSAGE &&
+	    esp->cur_msgout[4] == EXTENDED_SDTR) {
 		esp->snip = 1; /* anal retentiveness... */
 	}
 
 	esp->prevmsgout = esp->cur_msgout[0];
 	esp->msgout_len = 0;
 	esp_advance_phase(esp->current_SC, in_the_dark);
-	return esp_do_phase_determine(esp, eregs, dregs);
+	return esp_do_phase_determine(esp);
 }
 
-static int esp_bus_unexpected(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
-			      struct sparc_dma_registers *dregs)
+static int esp_bus_unexpected(struct esp *esp)
 {
 	ESPLOG(("esp%d: command in weird state %2x\n",
 		esp->esp_id, esp->current_SC->SCp.phase));
@@ -3976,25 +4112,23 @@
 };
 
 /* This is the second tier in our dual-level SCSI state machine. */
-static int esp_work_bus(struct Sparc_ESP *esp,
-			struct Sparc_ESP_regs *eregs,
-			struct sparc_dma_registers *dregs)
+static int esp_work_bus(struct esp *esp)
 {
 	Scsi_Cmnd *SCptr = esp->current_SC;
 	unsigned int phase;
 
 	ESPBUS(("esp_work_bus: "));
-	if(!SCptr) {
+	if (!SCptr) {
 		ESPBUS(("reconnect\n"));
-		return esp_do_reconnect(esp, eregs, dregs);
+		return esp_do_reconnect(esp);
 	}
 	phase = SCptr->SCp.phase;
 	if ((phase & 0xf0) == in_phases_mask)
-		return bus_vector[(phase & 0x0f)](esp, eregs, dregs);
-	else if((phase & 0xf0) == in_slct_mask)
-		return esp_select_complete(esp, eregs, dregs);
+		return bus_vector[(phase & 0x0f)](esp);
+	else if ((phase & 0xf0) == in_slct_mask)
+		return esp_select_complete(esp);
 	else
-		return esp_bus_unexpected(esp, eregs, dregs);
+		return esp_bus_unexpected(esp);
 }
 
 static espfunc_t isvc_vector[] = {
@@ -4006,25 +4140,22 @@
 };
 
 /* Main interrupt handler for an esp adapter. */
-static void esp_handle(struct Sparc_ESP *esp)
+static void esp_handle(struct esp *esp)
 {
-	struct sparc_dma_registers *dregs;
-	struct Sparc_ESP_regs *eregs;
 	Scsi_Cmnd *SCptr;
 	int what_next = do_intr_end;
 
-	eregs = esp->eregs;
-	dregs = esp->dregs;
 	SCptr = esp->current_SC;
 
 	/* Check for errors. */
-	esp->sreg = eregs->esp_status;
+	esp->sreg = sbus_readb(esp->eregs + ESP_STATUS);
 	esp->sreg &= (~ESP_STAT_INTR);
-	if(esp->erev == fashme) {
-		esp->sreg2 = eregs->esp_status2;
-		esp->seqreg = (eregs->esp_sstep & ESP_STEP_VBITS);
+	if (esp->erev == fashme) {
+		esp->sreg2 = sbus_readb(esp->eregs + ESP_STATUS2);
+		esp->seqreg = (sbus_readb(esp->eregs + ESP_SSTEP) & ESP_STEP_VBITS);
 	}
-	if(esp->sreg & (ESP_STAT_SPAM)) {
+
+	if (esp->sreg & (ESP_STAT_SPAM)) {
 		/* Gross error, could be due to one of:
 		 *
 		 * - top of fifo overwritten, could be because
@@ -4047,7 +4178,7 @@
 		 * target will be able to cleanly go away soon
 		 * so we can safely reset things.
 		 */
-		if(!SCptr) {
+		if (!SCptr) {
 			ESPLOG(("esp%d: No current cmd during gross error, "
 				"resetting bus\n", esp->esp_id));
 			what_next = do_reset_bus;
@@ -4055,7 +4186,7 @@
 		}
 	}
 
-	if(dregs->cond_reg & DMA_HNDL_ERROR) {
+	if (sbus_readl(esp->dregs + DMA_CSR) & DMA_HNDL_ERROR) {
 		/* A DMA gate array error.  Here we must
 		 * be seeing one of two things.  Either the
 		 * virtual to physical address translation
@@ -4064,7 +4195,7 @@
 		 * page.  Ho hum...
 		 */
 		ESPLOG(("esp%d: DMA error %08x\n", esp->esp_id,
-			dregs->cond_reg));
+			sbus_readl(esp->dregs + DMA_CSR)));
 
 		/* DMA gate array itself must be reset to clear the
 		 * error condition.
@@ -4075,9 +4206,9 @@
 		goto state_machine;
 	}
 
-	esp->ireg = eregs->esp_intrpt;   /* Unlatch intr and stat regs */
+	esp->ireg = sbus_readb(esp->eregs + ESP_INTRPT);   /* Unlatch intr reg */
 
-	if(esp->erev == fashme) {
+	if (esp->erev == fashme) {
 		/* This chip is really losing. */
 		ESPHME(("HME["));
 
@@ -4086,10 +4217,10 @@
 		 * register else garbage ends up in the FIFO
 		 * which confuses the driver utterly.
 		 */
-		if(!(esp->sreg2 & ESP_STAT2_FEMPTY) ||
-		   (esp->sreg2 & ESP_STAT2_F1BYTE)) {
+		if (!(esp->sreg2 & ESP_STAT2_FEMPTY) ||
+		    (esp->sreg2 & ESP_STAT2_F1BYTE)) {
 			ESPHME(("fifo_workaround]"));
-			hme_fifo_read(esp, eregs);
+			hme_fifo_read(esp);
 		} else {
 			ESPHME(("no_fifo_workaround]"));
 		}
@@ -4098,13 +4229,13 @@
 	/* No current cmd is only valid at this point when there are
 	 * commands off the bus or we are trying a reset.
 	 */
-	if(!SCptr && !esp->disconnected_SC && !(esp->ireg & ESP_INTR_SR)) {
+	if (!SCptr && !esp->disconnected_SC && !(esp->ireg & ESP_INTR_SR)) {
 		/* Panic is safe, since current_SC is null. */
 		ESPLOG(("esp%d: no command in esp_handle()\n", esp->esp_id));
 		panic("esp_handle: current_SC == penguin within interrupt!");
 	}
 
-	if(esp->ireg & (ESP_INTR_IC)) {
+	if (esp->ireg & (ESP_INTR_IC)) {
 		/* Illegal command fed to ESP.  Outside of obvious
 		 * software bugs that could cause this, there is
 		 * a condition with esp100 where we can confuse the
@@ -4115,9 +4246,9 @@
 		 */
 		ESPLOG(("esp%d: illegal command\n", esp->esp_id));
 
-		esp_dump_state(esp, eregs, dregs);
+		esp_dump_state(esp);
 
-		if(SCptr) {
+		if (SCptr != NULL) {
 			/* Devices with very buggy firmware can drop BSY
 			 * during a scatter list interrupt when using sync
 			 * mode transfers.  We continue the transfer as
@@ -4133,15 +4264,14 @@
 		}
 
 		what_next = do_reset_bus;
-	} else if(!(esp->ireg & ~(ESP_INTR_FDONE | ESP_INTR_BSERV | ESP_INTR_DC))) {
-		int phase;
-
-		if(SCptr) {
-			phase = SCptr->SCp.phase;
-			if(phase & in_phases_mask) {
-				what_next = esp_work_bus(esp, eregs, dregs);
-			} else if(phase & in_slct_mask) {
-				what_next = esp_select_complete(esp, eregs, dregs);
+	} else if (!(esp->ireg & ~(ESP_INTR_FDONE | ESP_INTR_BSERV | ESP_INTR_DC))) {
+		if (SCptr) {
+			unsigned int phase = SCptr->SCp.phase;
+
+			if (phase & in_phases_mask) {
+				what_next = esp_work_bus(esp);
+			} else if (phase & in_slct_mask) {
+				what_next = esp_select_complete(esp);
 			} else {
 				ESPLOG(("esp%d: interrupt for no good reason...\n",
 					esp->esp_id));
@@ -4152,23 +4282,23 @@
 				esp->esp_id));
 			what_next = do_reset_bus;
 		}
-	} else if(esp->ireg & ESP_INTR_SR) {
+	} else if (esp->ireg & ESP_INTR_SR) {
 		ESPLOG(("esp%d: SCSI bus reset interrupt\n", esp->esp_id));
 		what_next = do_reset_complete;
-	} else if(esp->ireg & (ESP_INTR_S | ESP_INTR_SATN)) {
+	} else if (esp->ireg & (ESP_INTR_S | ESP_INTR_SATN)) {
 		ESPLOG(("esp%d: AIEEE we have been selected by another initiator!\n",
 			esp->esp_id));
 		what_next = do_reset_bus;
-	} else if(esp->ireg & ESP_INTR_RSEL) {
-		if(!SCptr) {
+	} else if (esp->ireg & ESP_INTR_RSEL) {
+		if (SCptr == NULL) {
 			/* This is ok. */
-			what_next = esp_do_reconnect(esp, eregs, dregs);
-		} else if(SCptr->SCp.phase & in_slct_mask) {
+			what_next = esp_do_reconnect(esp);
+		} else if (SCptr->SCp.phase & in_slct_mask) {
 			/* Only selection code knows how to clean
 			 * up properly.
 			 */
 			ESPDISC(("Reselected during selection attempt\n"));
-			what_next = esp_select_complete(esp, eregs, dregs);
+			what_next = esp_select_complete(esp);
 		} else {
 			ESPLOG(("esp%d: Reselected while bus is busy\n",
 				esp->esp_id));
@@ -4178,11 +4308,11 @@
 
 	/* This is tier-one in our dual level SCSI state machine. */
 state_machine:
-	while(what_next != do_intr_end) {
+	while (what_next != do_intr_end) {
 		if (what_next >= do_phase_determine &&
-		    what_next < do_intr_end)
-			what_next = isvc_vector[what_next](esp, eregs, dregs);
-		else {
+		    what_next < do_intr_end) {
+			what_next = isvc_vector[what_next](esp);
+		} else {
 			/* state is completely lost ;-( */
 			ESPLOG(("esp%d: interrupt engine loses state, resetting bus\n",
 				esp->esp_id));
@@ -4191,102 +4321,29 @@
 	}
 }
 
-#ifndef __sparc_v9__
-
-#ifndef __SMP__
-static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
-{
-	struct Sparc_ESP *esp;
-	unsigned long flags;
-	int again;
-
-	/* Handle all ESP interrupts showing at this IRQ level. */
-	spin_lock_irqsave(&io_request_lock, flags);
-repeat:
-	again = 0;
-	for_each_esp(esp) {
-		if((esp->irq & 0xf) == irq) {
-			if(DMA_IRQ_P(esp->dregs)) {
-				again = 1;
-
-				DMA_INTSOFF(esp->dregs);
-
-				ESPIRQ(("I%d(", esp->esp_id));
-				esp_handle(esp);
-				ESPIRQ((")"));
-
-				DMA_INTSON(esp->dregs);
-			}
-		}
-	}
-	if(again)
-		goto repeat;
-	spin_unlock_irqrestore(&io_request_lock, flags);
-}
-#else
-/* For SMP we only service one ESP on the list list at our IRQ level! */
+/* Service only the ESP described by dev_id. */
 static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
-	struct Sparc_ESP *esp;
+	struct esp *esp = dev_id;
 	unsigned long flags;
 
-	/* Handle all ESP interrupts showing at this IRQ level. */
-	spin_lock_irqsave(&io_request_lock, flags);
-	for_each_esp(esp) {
-		if(((esp)->irq & 0xf) == irq) {
-			if(DMA_IRQ_P(esp->dregs)) {
-				DMA_INTSOFF(esp->dregs);
-
-				ESPIRQ(("I[%d:%d](",
-					smp_processor_id(), esp->esp_id));
-				esp_handle(esp);
-				ESPIRQ((")"));
-
-				DMA_INTSON(esp->dregs);
-				goto out;
-			}
-		}
-	}
-out:
-	spin_unlock_irqrestore(&io_request_lock, flags);
-}
-#endif
-
-static void esp_intr_4d(int irq, void *dev_id, struct pt_regs *pregs)
-{
-	struct Sparc_ESP *esp = dev_id;
-	unsigned long flags;
-
-	spin_lock_irqsave(&io_request_lock, flags);
-	if(DMA_IRQ_P(esp->dregs)) {
-		DMA_INTSOFF(esp->dregs);
+	spin_lock_irqsave(&esp->lock, flags);
+	if (ESP_IRQ_P(esp->dregs)) {
+		ESP_INTSOFF(esp->dregs);
 
 		ESPIRQ(("I[%d:%d](", smp_processor_id(), esp->esp_id));
 		esp_handle(esp);
 		ESPIRQ((")"));
 
-		DMA_INTSON(esp->dregs);
+		ESP_INTSON(esp->dregs);
 	}
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&esp->lock, flags);
 }
 
-#else /* __sparc_v9__ */
-
-static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
-{
-	struct Sparc_ESP *esp = dev_id;
-	unsigned long flags;
+#ifdef MODULE
+Scsi_Host_Template driver_template = SCSI_SPARC_ESP;
 
-	spin_lock_irqsave(&io_request_lock, flags);
-	if(DMA_IRQ_P(esp->dregs)) {
-		DMA_INTSOFF(esp->dregs);
+#include "scsi_module.c"
 
-		ESPIRQ(("I[%d:%d](", smp_processor_id(), esp->esp_id));
-		esp_handle(esp);
-		ESPIRQ((")"));
-
-		DMA_INTSON(esp->dregs);
-	}
-	spin_unlock_irqrestore(&io_request_lock, flags);
-}
-#endif
+EXPORT_NO_SYMBOLS;
+#endif /* MODULE */
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/esp.h linux/drivers/scsi/esp.h
--- v2.3.34/linux/drivers/scsi/esp.h	Thu Nov 11 20:11:46 1999
+++ linux/drivers/scsi/esp.h	Tue Dec 28 17:44:28 1999
@@ -1,4 +1,5 @@
-/* esp.h:  Defines and structures for the Sparc ESP (Enhanced SCSI
+/* $Id: esp.h,v 1.27 1999/12/15 14:12:52 davem Exp $
+ * esp.h:  Defines and structures for the Sparc ESP (Enhanced SCSI
  *         Processor) driver under Linux.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -23,182 +24,166 @@
 /* All the ESP registers are one byte each and are accessed longwords
  * apart with a big-endian ordering to the bytes.
  */
-
-struct Sparc_ESP_regs {
-                                /* Access    Description              Offset */
-    volatile unchar esp_tclow;  /* rw  Low bits of the transfer count 0x00   */
-                                unchar tlpad1[3];
-    volatile unchar esp_tcmed;  /* rw  Mid bits of the transfer count 0x04   */
-                                unchar fdpad[3];
-    volatile unchar esp_fdata;  /* rw  FIFO data bits                 0x08   */
-                                unchar cbpad[3];
-    volatile unchar esp_cmd;    /* rw  SCSI command bits              0x0c   */
-                                unchar stpad[3];
-    volatile unchar esp_status; /* ro  ESP status register            0x10   */
-#define esp_busid   esp_status  /* wo  Bus ID for select/reselect     0x10   */
-                                unchar irqpd[3];
-    volatile unchar esp_intrpt; /* ro  Kind of interrupt              0x14   */
-#define esp_timeo   esp_intrpt  /* wo  Timeout value for select/resel 0x14   */
-                                unchar sspad[3];
-    volatile unchar esp_sstep;  /* ro  Sequence step register         0x18   */
-#define esp_stp     esp_sstep   /* wo  Transfer period per sync       0x18   */
-                                unchar ffpad[3];
-    volatile unchar esp_fflags; /* ro  Bits of current FIFO info      0x1c   */
-#define esp_soff    esp_fflags  /* wo  Sync offset                    0x1c   */
-                                unchar cf1pd[3];
-    volatile unchar esp_cfg1;   /* rw  First configuration register   0x20   */
-                                unchar cfpad[3];
-    volatile unchar esp_cfact;  /* wo  Clock conversion factor        0x24   */
-#define esp_status2 esp_cfact   /* ro  HME status2 register           0x24   */
-                                unchar ctpad[3];
-    volatile unchar esp_ctest;  /* wo  Chip test register             0x28   */
-                                unchar cf2pd[3];
-    volatile unchar esp_cfg2;   /* rw  Second configuration register  0x2c   */
-                                unchar cf3pd[3];
-
-    /* The following is only found on the 53C9X series SCSI chips */
-    volatile unchar esp_cfg3;   /* rw  Third configuration register   0x30  */
-                                unchar thpd[7];
-
-    /* The following is found on all chips except the NCR53C90 (ESP100) */
-    volatile unchar esp_tchi;   /* rw  High bits of transfer count    0x38  */
-#define esp_uid     esp_tchi    /* ro  Unique ID code                 0x38  */
-#define fas_rlo     esp_tchi    /* rw  HME extended counter           0x38  */
-                                unchar fgpad[3];
-    volatile unchar esp_fgrnd;  /* rw  Data base for fifo             0x3c  */
-#define fas_rhi     esp_fgrnd   /* rw  HME extended counter           0x3c  */
-};
+					/* Access    Description              Offset */
+#define ESP_TCLOW	0x00UL		/* rw  Low bits of the transfer count 0x00   */
+#define ESP_TCMED	0x04UL		/* rw  Mid bits of the transfer count 0x04   */
+#define ESP_FDATA	0x08UL		/* rw  FIFO data bits                 0x08   */
+#define ESP_CMD		0x0cUL		/* rw  SCSI command bits              0x0c   */
+#define ESP_STATUS	0x10UL		/* ro  ESP status register            0x10   */
+#define ESP_BUSID	ESP_STATUS	/* wo  Bus ID for select/reselect     0x10   */
+#define ESP_INTRPT	0x14UL		/* ro  Kind of interrupt              0x14   */
+#define ESP_TIMEO	ESP_INTRPT	/* wo  Timeout value for select/resel 0x14   */
+#define ESP_SSTEP	0x18UL		/* ro  Sequence step register         0x18   */
+#define ESP_STP		ESP_SSTEP	/* wo  Transfer period per sync       0x18   */
+#define ESP_FFLAGS	0x1cUL		/* ro  Bits of current FIFO info      0x1c   */
+#define ESP_SOFF	ESP_FFLAGS	/* wo  Sync offset                    0x1c   */
+#define ESP_CFG1	0x20UL		/* rw  First configuration register   0x20   */
+#define ESP_CFACT	0x24UL		/* wo  Clock conversion factor        0x24   */
+#define ESP_STATUS2	ESP_CFACT	/* ro  HME status2 register           0x24   */
+#define ESP_CTEST	0x28UL		/* wo  Chip test register             0x28   */
+#define ESP_CFG2	0x2cUL		/* rw  Second configuration register  0x2c   */
+#define ESP_CFG3	0x30UL		/* rw  Third configuration register   0x30   */
+#define ESP_TCHI	0x38UL		/* rw  High bits of transfer count    0x38   */
+#define ESP_UID		ESP_TCHI	/* ro  Unique ID code                 0x38   */
+#define FAS_RLO		ESP_TCHI	/* rw  HME extended counter           0x38   */
+#define ESP_FGRND	0x3cUL		/* rw  Data base for fifo             0x3c   */
+#define FAS_RHI		ESP_FGRND	/* rw  HME extended counter           0x3c   */
+#define ESP_REG_SIZE	0x40UL
 
 /* Various revisions of the ESP board. */
 enum esp_rev {
-  esp100     = 0x00,  /* NCR53C90 - very broken */
-  esp100a    = 0x01,  /* NCR53C90A */
-  esp236     = 0x02,
-  fas236     = 0x03,
-  fas100a    = 0x04,
-  fast       = 0x05,
-  fashme     = 0x06,
-  espunknown = 0x07
+	esp100     = 0x00,  /* NCR53C90 - very broken */
+	esp100a    = 0x01,  /* NCR53C90A */
+	esp236     = 0x02,
+	fas236     = 0x03,
+	fas100a    = 0x04,
+	fast       = 0x05,
+	fashme     = 0x06,
+	espunknown = 0x07
 };
 
 /* We get one of these for each ESP probed. */
-struct Sparc_ESP {
-  struct Sparc_ESP *next;                 /* Next ESP on probed or NULL */
-  struct Sparc_ESP_regs *eregs;           /* All esp registers */
-  struct Linux_SBus_DMA *dma;             /* Who I do transfers with. */
-  struct sparc_dma_registers *dregs;      /* And his registers. */
-  struct Scsi_Host *ehost;                /* Backpointer to SCSI Host */
-
-  struct linux_sbus_device *edev;         /* Pointer to SBus entry */
-  char prom_name[64];                     /* Name of ESP device from prom */
-  int prom_node;                          /* Prom node where ESP found */
-  int esp_id;                             /* Unique per-ESP ID number */
-
-  /* ESP Configuration Registers */
-  unsigned char config1;                  /* Copy of the 1st config register */
-  unsigned char config2;                  /* Copy of the 2nd config register */
-  unsigned char config3[16];              /* Copy of the 3rd config register */
-
-  /* The current command we are sending to the ESP chip.  This esp_command
-   * ptr needs to be mapped in DVMA area so we can send commands and read
-   * from the ESP fifo without burning precious CPU cycles.  Programmed I/O
-   * sucks when we have the DVMA to do it for us.  The ESP is stupid and will
-   * only send out 6, 10, and 12 byte SCSI commands, others we need to send
-   * one byte at a time.  esp_slowcmd being set says that we are doing one
-   * of the command types ESP doesn't understand, esp_scmdp keeps track of
-   * which byte we are sending, esp_scmdleft says how many bytes to go.
-   */
-  volatile unchar *esp_command;           /* Location of command (CPU view)  */
-  __u32            esp_command_dvma;      /* Location of command (DVMA view) */
-  unsigned char esp_clen;                 /* Length of this command */
-  unsigned char esp_slowcmd;
-  unsigned char *esp_scmdp;
-  unsigned char esp_scmdleft;
-
-  /* The following are used to determine the cause of an IRQ. Upon every
-   * IRQ entry we synchronize these with the hardware registers.
-   */
-  unchar ireg;                            /* Copy of ESP interrupt register */
-  unchar sreg;                            /* Same for ESP status register */
-  unchar seqreg;                          /* The ESP sequence register */
-  unchar sreg2;                           /* Copy of HME status2 register */
-
-  /* To save register writes to the ESP, which can be expensive, we
-   * keep track of the previous value that various registers had for
-   * the last target we connected to.  If they are the same for the
-   * current target, we skip the register writes as they are not needed.
-   */
-  unchar prev_soff, prev_stp, prev_cfg3, __cache_pad;
-
-  /* We also keep a cache of the previous FAS/HME DMA CSR register value.  */
-  unsigned int prev_hme_dmacsr;
-
-  /* The HME is the biggest piece of shit I have ever seen. */
-  unchar hme_fifo_workaround_buffer[16 * 2]; /* 16-bit/entry fifo for wide scsi */
-  unchar hme_fifo_workaround_count;
-
-  /* For each target we keep track of save/restore data
-   * pointer information.  This needs to be updated majorly
-   * when we add support for tagged queueing.  -DaveM
-   */
-  struct esp_pointers {
-	  char *saved_ptr;
-	  struct scatterlist *saved_buffer;
-	  int saved_this_residual;
-	  int saved_buffers_residual;
-  } data_pointers[16] /*XXX [MAX_TAGS_PER_TARGET]*/;
-
-  /* Clock periods, frequencies, synchronization, etc. */
-  unsigned int cfreq;                    /* Clock frequency in HZ */
-  unsigned int cfact;                    /* Clock conversion factor */
-  unsigned int ccycle;                   /* One ESP clock cycle */
-  unsigned int ctick;                    /* One ESP clock time */
-  unsigned int radelay;                  /* FAST chip req/ack delay */
-  unsigned int neg_defp;                 /* Default negotiation period */
-  unsigned int sync_defp;                /* Default sync transfer period */
-  unsigned int max_period;               /* longest our period can be */
-  unsigned int min_period;               /* shortest period we can withstand */
-  /* For slow to medium speed input clock rates we shoot for 5mb/s,
-   * but for high input clock rates we try to do 10mb/s although I
-   * don't think a transfer can even run that fast with an ESP even
-   * with DMA2 scatter gather pipelining.
-   */
+struct esp {
+	spinlock_t		lock;
+	unsigned long		eregs;		/* ESP controller registers */
+	unsigned long		dregs;		/* DMA controller registers */
+	struct sbus_dma		*dma;		/* DMA controller sw state */
+	struct Scsi_Host	*ehost;		/* Backpointer to SCSI Host */
+	struct sbus_dev		*sdev;		/* Pointer to SBus entry */
+
+	/* ESP Configuration Registers */
+	u8			config1;	/* Copy of the 1st config register */
+	u8			config2;	/* Copy of the 2nd config register */
+	u8			config3[16];	/* Copy of the 3rd config register */
+
+	/* The current command we are sending to the ESP chip.  This esp_command
+	 * ptr needs to be mapped in DVMA area so we can send commands and read
+	 * from the ESP fifo without burning precious CPU cycles.  Programmed I/O
+	 * sucks when we have the DVMA to do it for us.  The ESP is stupid and will
+	 * only send out 6, 10, and 12 byte SCSI commands, others we need to send
+	 * one byte at a time.  esp_slowcmd being set says that we are doing one
+	 * of the command types ESP doesn't understand, esp_scmdp keeps track of
+	 * which byte we are sending, esp_scmdleft says how many bytes to go.
+	 */
+	volatile u8		*esp_command;    /* Location of command (CPU view)  */
+	__u32			esp_command_dvma;/* Location of command (DVMA view) */
+	unsigned char		esp_clen;	 /* Length of this command */
+	unsigned char		esp_slowcmd;
+	unsigned char		*esp_scmdp;
+	unsigned char		esp_scmdleft;
+
+	/* The following are used to determine the cause of an IRQ. Upon every
+	 * IRQ entry we synchronize these with the hardware registers.
+	 */
+	u8			ireg;		/* Copy of ESP interrupt register */
+	u8			sreg;		/* Copy of ESP status register */
+	u8			seqreg;		/* Copy of ESP sequence step register */
+	u8			sreg2;		/* Copy of HME status2 register */
+
+	/* To save register writes to the ESP, which can be expensive, we
+	 * keep track of the previous value that various registers had for
+	 * the last target we connected to.  If they are the same for the
+	 * current target, we skip the register writes as they are not needed.
+	 */
+	u8			prev_soff, prev_stp;
+	u8			prev_cfg3, __cache_pad;
+
+	/* We also keep a cache of the previous FAS/HME DMA CSR register value.  */
+	u32			prev_hme_dmacsr;
+
+	/* The HME is the biggest piece of shit I have ever seen. */
+	u8			hme_fifo_workaround_buffer[16 * 2];
+	u8			hme_fifo_workaround_count;
+
+	/* For each target we keep track of save/restore data
+	 * pointer information.  This needs to be updated majorly
+	 * when we add support for tagged queueing.  -DaveM
+	 */
+	struct esp_pointers {
+		char			*saved_ptr;
+		struct scatterlist	*saved_buffer;
+		int			saved_this_residual;
+		int			saved_buffers_residual;
+	} data_pointers[16] /*XXX [MAX_TAGS_PER_TARGET]*/;
+
+	/* Clock periods, frequencies, synchronization, etc. */
+	unsigned int		cfreq;		/* Clock frequency in HZ */
+	unsigned int		cfact;		/* Clock conversion factor */
+	unsigned int		raw_cfact;	/* Raw copy from probing */
+	unsigned int		ccycle;		/* One ESP clock cycle */
+	unsigned int		ctick;		/* One ESP clock time */
+	unsigned int		radelay;	/* FAST chip req/ack delay */
+	unsigned int		neg_defp;	/* Default negotiation period */
+	unsigned int		sync_defp;	/* Default sync transfer period */
+	unsigned int		max_period;	/* longest our period can be */
+	unsigned int		min_period;	/* shortest period we can withstand */
+
+	struct esp		*next;		/* Next ESP we probed or NULL */
+	char			prom_name[64];	/* Name of ESP device from prom */
+	int			prom_node;	/* Prom node where ESP found */
+	int			esp_id;		/* Unique per-ESP ID number */
+
+	/* For slow to medium speed input clock rates we shoot for 5mb/s,
+	 * but for high input clock rates we try to do 10mb/s although I
+	 * don't think a transfer can even run that fast with an ESP even
+	 * with DMA2 scatter gather pipelining.
+	 */
 #define SYNC_DEFP_SLOW            0x32   /* 5mb/s  */
 #define SYNC_DEFP_FAST            0x19   /* 10mb/s */
 
-  unsigned int snip;                      /* Sync. negotiation in progress */
-  unsigned int wnip;                      /* WIDE negotiation in progress */
-  unsigned int targets_present;           /* targets spoken to before */
-
-  int current_transfer_size;              /* Set at beginning of data dma */
-
-  unchar espcmdlog[32];                   /* Log of current esp cmds sent. */
-  unchar espcmdent;                       /* Current entry in esp cmd log. */
-
-  /* Misc. info about this ESP */
-  enum esp_rev erev;                      /* ESP revision */
-  int irq;                                /* SBus IRQ for this ESP */
-  int scsi_id;                            /* Who am I as initiator? */
-  int scsi_id_mask;                       /* Bitmask of 'me'. */
-  int diff;                               /* Differential SCSI bus? */
-  int bursts;                             /* Burst sizes our DVMA supports */
-
-  /* Our command queues, only one cmd lives in the current_SC queue. */
-  Scsi_Cmnd *issue_SC;           /* Commands to be issued */
-  Scsi_Cmnd *current_SC;         /* Who is currently working the bus */
-  Scsi_Cmnd *disconnected_SC;    /* Commands disconnected from the bus */
-
-  /* Message goo */
-  unchar cur_msgout[16];
-  unchar cur_msgin[16];
-  unchar prevmsgout, prevmsgin;
-  unchar msgout_len, msgin_len;
-  unchar msgout_ctr, msgin_ctr;
-
-  /* States that we cannot keep in the per cmd structure because they
-   * cannot be assosciated with any specific command.
-   */
-  unchar resetting_bus;
+	unsigned int		snip;		/* Sync. negotiation in progress */
+	unsigned int		wnip;		/* WIDE negotiation in progress */
+	unsigned int		targets_present;/* targets spoken to before */
+
+	int		current_transfer_size;	/* Set at beginning of data dma */
+
+	u8			espcmdlog[32];	/* Log of current esp cmds sent. */
+	u8			espcmdent;	/* Current entry in esp cmd log. */
+
+	/* Misc. info about this ESP */
+	enum esp_rev		erev;		/* ESP revision */
+	int			irq;		/* SBus IRQ for this ESP */
+	int			scsi_id;	/* Who am I as initiator? */
+	int			scsi_id_mask;	/* Bitmask of 'me'. */
+	int			diff;		/* Differential SCSI bus? */
+	int			bursts;		/* Burst sizes our DVMA supports */
+
+	/* Our command queues, only one cmd lives in the current_SC queue. */
+	Scsi_Cmnd		*issue_SC;	/* Commands to be issued */
+	Scsi_Cmnd		*current_SC;	/* Who is currently working the bus */
+	Scsi_Cmnd		*disconnected_SC;/* Commands disconnected from the bus */
+
+	/* Message goo */
+	u8			cur_msgout[16];
+	u8			cur_msgin[16];
+	u8			prevmsgout, prevmsgin;
+	u8			msgout_len, msgin_len;
+	u8			msgout_ctr, msgin_ctr;
+
+	/* States that we cannot keep in the per cmd structure because they
+	 * cannot be assosciated with any specific command.
+	 */
+	u8			resetting_bus;
 };
 
 /* Bitfield meanings for the above registers. */
@@ -428,7 +413,7 @@
 		this_id:        7,				\
 		sg_tablesize:   SG_ALL,				\
 		cmd_per_lun:    1,				\
-		use_clustering: DISABLE_CLUSTERING,		\
+		use_clustering: ENABLE_CLUSTERING,		\
 		use_new_eh_code: 0				\
 }
 
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/fcal.c linux/drivers/scsi/fcal.c
--- v2.3.34/linux/drivers/scsi/fcal.c	Thu Nov 11 20:11:46 1999
+++ linux/drivers/scsi/fcal.c	Mon Dec 20 22:06:42 1999
@@ -218,7 +218,7 @@
 	fc = fcal->fc;
 
 #ifdef __sparc__
-	SPRINTF ("Sun Enterprise Network Array (A5000 or E?500) on %s\n", fc->name);
+	SPRINTF ("Sun Enterprise Network Array (A5000 or E?500) on %s PROM node %x\n", fc->name, fc->dev->prom_node);
 #else
 	SPRINTF ("Fibre Channel Arbitrated Loop on %s\n", fc->name);
 #endif
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- v2.3.34/linux/drivers/scsi/fdomain.c	Tue Nov 23 22:42:21 1999
+++ linux/drivers/scsi/fdomain.c	Tue Dec 21 10:17:32 1999
@@ -280,6 +280,7 @@
 #undef MODULE
 #endif
 
+#include <linux/init.h>
 #include <linux/sched.h>
 #include <asm/io.h>
 #include <linux/blk.h>
@@ -427,8 +428,8 @@
                                    parameters.  For example:
 				   insmod fdomain fdomain=0x140,11
 				*/
-static int               fdomain[]={ 0, 0, 0 };
-MODULE_PARM(fdomain, "2-3i");
+static char * fdomain = NULL;
+MODULE_PARM(fdomain, "s");
 #endif
 
 static unsigned long addresses[] = {
@@ -563,21 +564,30 @@
    printk( "\n" );
 }
 
-void fdomain_setup( char *str, int *ints )
+static int __init fdomain_setup( char *str )
 {
-   if (setup_called++ || ints[0] < 2 || ints[0] > 3) {
-      printk( "scsi: <fdomain>"
-	      " Usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n" );
-      printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
-   }
+	int ints[4];
+
+	(void)get_options(str, ARRAY_SIZE(ints), ints);
 
-   port_base       = ints[0] >= 1 ? ints[1] : 0;
-   interrupt_level = ints[0] >= 2 ? ints[2] : 0;
-   this_id         = ints[0] >= 3 ? ints[3] : 0;
+	if (setup_called++ || ints[0] < 2 || ints[0] > 3) {
+		printk( "scsi: <fdomain>"
+		" Usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n" );
+		printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
+		return 0;
+	}
+
+	port_base       = ints[0] >= 1 ? ints[1] : 0;
+	interrupt_level = ints[0] >= 2 ? ints[2] : 0;
+	this_id         = ints[0] >= 3 ? ints[3] : 0;
    
-   bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */
+	bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */
+	++setup_called;
+	return 1;
 }
 
+__setup("fdomain=", fdomain_setup);
+
 
 static void do_pause( unsigned amount )	/* Pause for amount*10 milliseconds */
 {
@@ -694,6 +704,7 @@
    printk( "scsi: <fdomain> fdomain_isa_detect:" );
 #endif
 
+
    for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
 #if DEBUG_DETECT
       printk( " %lx(%lx),", addresses[i], bios_base );
@@ -880,13 +891,8 @@
    tpnt->proc_name = "fdomain";
 
 #ifdef MODULE
-   if (fdomain[0] || fdomain[1] || fdomain[2]) {
-      port_base       = fdomain[0];
-      interrupt_level = fdomain[1];
-      this_id         = fdomain[2];
-      bios_major = bios_minor = -1;
-      ++setup_called;
-   }
+	if (fdomain)
+		fdomain_setup(fdomain);
 #endif
    
    if (setup_called) {
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- v2.3.34/linux/drivers/scsi/hosts.h	Tue Dec 14 01:27:24 1999
+++ linux/drivers/scsi/hosts.h	Tue Dec 28 17:44:21 1999
@@ -437,6 +437,8 @@
     struct module * module;	  /* Used for loadable modules */
     unsigned char scsi_type;
     unsigned char major;
+    unsigned char min_major;      /* Minimum major in range. */ 
+    unsigned char max_major;      /* Maximum major in range. */
     unsigned char nr_dev;	  /* Number currently attached */
     unsigned char dev_noticed;	  /* Number of devices detected. */
     unsigned char dev_max;	  /* Current size of arrays */
@@ -447,7 +449,8 @@
     void (*finish)(void);	  /* Perform initialization after attachment */
     int (*attach)(Scsi_Device *); /* Attach devices to arrays */
     void (*detach)(Scsi_Device *);
-    int (*init_command)(Scsi_Cmnd *);     /* Used by new queueing code. */
+    int (*init_command)(Scsi_Cmnd *);     /* Used by new queueing code. 
+                                           Selects command for blkdevs */
 };
 
 extern struct Scsi_Device_Template sd_template;
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/pluto.c linux/drivers/scsi/pluto.c
--- v2.3.34/linux/drivers/scsi/pluto.c	Thu Nov 11 20:11:48 1999
+++ linux/drivers/scsi/pluto.c	Mon Dec 20 22:06:42 1999
@@ -287,12 +287,16 @@
 
 const char *pluto_info(struct Scsi_Host *host)
 {
-	static char buf[80];
+	static char buf[128], *p;
 	struct pluto *pluto = (struct pluto *) host->hostdata;
 
 	sprintf(buf, "SUN SparcSTORAGE Array %s fw %s serial %s %dx%d on %s",
 		pluto->rev_str, pluto->fw_rev_str, pluto->serial_str,
 		host->max_channel, host->max_id, pluto->fc->name);
+#ifdef __sparc__
+	p = strchr(buf, 0);
+	sprintf(p, " PROM node %x", pluto->fc->dev->prom_node);
+#endif	
 	return buf;
 }
 
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c
--- v2.3.34/linux/drivers/scsi/qlogicisp.c	Wed Dec 15 10:43:16 1999
+++ linux/drivers/scsi/qlogicisp.c	Mon Dec 20 22:06:42 1999
@@ -1241,8 +1241,6 @@
 	}
 
 #ifdef __sparc__
-	if (mem_base)
-		mem_base = __pa(mem_base);
 	command |= (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY|
 		    PCI_COMMAND_INVALIDATE|PCI_COMMAND_SERR);
 	pci_write_config_word(pdev, PCI_COMMAND, command);
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c
--- v2.3.34/linux/drivers/scsi/qlogicpti.c	Thu Nov 11 20:11:48 1999
+++ linux/drivers/scsi/qlogicpti.c	Mon Dec 20 22:06:42 1999
@@ -43,13 +43,14 @@
 #include <linux/module.h>
 
 #define MAX_TARGETS	16
-#define MAX_LUNS	8
+#define MAX_LUNS	8	/* 32 for 1.31 F/W */
 
-#define DEFAULT_LOOP_COUNT	1000000
+#define DEFAULT_LOOP_COUNT	10000
 
 #include "qlogicpti_asm.c"
 
-static struct qlogicpti *qptichain;
+static struct qlogicpti *qptichain = NULL;
+static spinlock_t qptichain_lock = SPIN_LOCK_UNLOCKED;
 static int qptis_running = 0;
 
 #define PACKB(a, b)			(((a)<<4)|(b))
@@ -129,144 +130,240 @@
 /* queue length's _must_ be power of two: */
 #define QUEUE_DEPTH(in, out, ql)	((in - out) & (ql))
 #define REQ_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out, 		     \
-						    QLOGICISP_REQ_QUEUE_LEN)
+						    QLOGICPTI_REQ_QUEUE_LEN)
 #define RES_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out, RES_QUEUE_LEN)
 
-static inline void qlogicpti_enable_irqs(struct qlogicpti_regs *qregs)
+static inline void qlogicpti_enable_irqs(struct qlogicpti *qpti)
 {
-	qregs->sbus_ctrl = SBUS_CTRL_ERIRQ | SBUS_CTRL_GENAB;
+	sbus_writew(SBUS_CTRL_ERIRQ | SBUS_CTRL_GENAB,
+		    qpti->qregs + SBUS_CTRL);
 }
 
-
-static inline void qlogicpti_disable_irqs(struct qlogicpti_regs *qregs)
+static inline void qlogicpti_disable_irqs(struct qlogicpti *qpti)
 {
-	qregs->sbus_ctrl = 0;
+	sbus_writew(0, qpti->qregs + SBUS_CTRL);
 }
 
-static inline void set_sbus_cfg1(struct qlogicpti_regs *qregs, unsigned char bursts)
+static inline void set_sbus_cfg1(struct qlogicpti *qpti)
 {
-	if(bursts & DMA_BURST32) {
-		qregs->sbus_cfg1 = (SBUS_CFG1_BENAB | SBUS_CFG1_B32);
-	} else if(bursts & DMA_BURST16) {
-		qregs->sbus_cfg1 = (SBUS_CFG1_BENAB | SBUS_CFG1_B16);
-	} else if(bursts & DMA_BURST8) {
-		qregs->sbus_cfg1 = (SBUS_CFG1_BENAB | SBUS_CFG1_B8);
+	u16 val;
+	u8 bursts = qpti->bursts;
+
+#if 0	/* It appears that at least PTI cards do not support
+	 * 64-byte bursts and that setting the B64 bit actually
+	 * is a nop and the chip ends up using the smallest burst
+	 * size. -DaveM
+	 */
+	if (sbus_can_burst64(qpti->sdev) && (bursts & DMA_BURST64)) {
+		val = (SBUS_CFG1_BENAB | SBUS_CFG1_B64);
+	} else
+#endif
+	if (bursts & DMA_BURST32) {
+		val = (SBUS_CFG1_BENAB | SBUS_CFG1_B32);
+	} else if (bursts & DMA_BURST16) {
+		val = (SBUS_CFG1_BENAB | SBUS_CFG1_B16);
+	} else if (bursts & DMA_BURST8) {
+		val = (SBUS_CFG1_BENAB | SBUS_CFG1_B8);
 	} else {
-		qregs->sbus_cfg1 = 0; /* No sbus bursts for you... */
+		val = 0; /* No sbus bursts for you... */
 	}
+	sbus_writew(val, qpti->qregs + SBUS_CFG1);
 }
 
 static int qlogicpti_mbox_command(struct qlogicpti *qpti, u_short param[], int force)
 {
-	struct qlogicpti_regs *qregs = qpti->qregs;
 	int loop_count;
+	u16 tmp;
 
-	if(mbox_param[param[0]] == 0)
+	if (mbox_param[param[0]] == 0)
 		return 1;
 
+	/* Set SBUS semaphore. */
+	tmp = sbus_readw(qpti->qregs + SBUS_SEMAPHORE);
+	tmp |= SBUS_SEMAPHORE_LCK;
+	sbus_writew(tmp, qpti->qregs + SBUS_SEMAPHORE);
+
+	/* Wait for host IRQ bit to clear. */
 	loop_count = DEFAULT_LOOP_COUNT;
-	while(--loop_count && (qregs->hcctrl & HCCTRL_HIRQ))
+	while (--loop_count && (sbus_readw(qpti->qregs + HCCTRL) & HCCTRL_HIRQ))
 		barrier();
-	if(!loop_count)
+	if (!loop_count)
 		printk(KERN_EMERG "qlogicpti: mbox_command loop timeout #1\n");
 
-	switch(mbox_param[param[0]] >> 4) {
-	case 6: qregs->mbox5 = param[5];
-	case 5: qregs->mbox4 = param[4];
-	case 4: qregs->mbox3 = param[3];
-	case 3: qregs->mbox2 = param[2];
-	case 2: qregs->mbox1 = param[1];
-	case 1: qregs->mbox0 = param[0];
-	}
-
-	qregs->hcctrl |= HCCTRL_SHIRQ;
+	/* Write mailbox command registers. */
+	switch (mbox_param[param[0]] >> 4) {
+	case 6: sbus_writew(param[5], qpti->qregs + MBOX5);
+	case 5: sbus_writew(param[4], qpti->qregs + MBOX4);
+	case 4: sbus_writew(param[3], qpti->qregs + MBOX3);
+	case 3: sbus_writew(param[2], qpti->qregs + MBOX2);
+	case 2: sbus_writew(param[1], qpti->qregs + MBOX1);
+	case 1: sbus_writew(param[0], qpti->qregs + MBOX0);
+	}
+
+	/* Clear RISC interrupt. */
+	tmp = sbus_readw(qpti->qregs + HCCTRL);
+	tmp |= HCCTRL_CRIRQ;
+	sbus_writew(tmp, qpti->qregs + HCCTRL);
+
+	/* Clear SBUS semaphore. */
+	sbus_writew(0, qpti->qregs + SBUS_SEMAPHORE);
+
+	/* Set HOST interrupt. */
+	tmp = sbus_readw(qpti->qregs + HCCTRL);
+	tmp |= HCCTRL_SHIRQ;
+	sbus_writew(tmp, qpti->qregs + HCCTRL);
 
+	/* Wait for HOST interrupt clears. */
 	loop_count = DEFAULT_LOOP_COUNT;
-	while(--loop_count && !(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK))
+	while (--loop_count &&
+	       (sbus_readw(qpti->qregs + HCCTRL) & HCCTRL_CRIRQ))
 		udelay(20);
-	if(!loop_count)
-		printk(KERN_EMERG "qlogicpti: mbox_command loop timeout #2\n");
+	if (!loop_count)
+		printk(KERN_EMERG "qlogicpti: mbox_command[%04x] loop timeout #2\n",
+		       param[0]);
 
+	/* Wait for SBUS semaphore to get set. */
 	loop_count = DEFAULT_LOOP_COUNT;
-	while(--loop_count && (qregs->mbox0 == 0x04))
+	while (--loop_count &&
+	       !(sbus_readw(qpti->qregs + SBUS_SEMAPHORE) & SBUS_SEMAPHORE_LCK)) {
 		udelay(20);
-	if(!loop_count)
-		printk(KERN_EMERG "qlogicpti: mbox_command loop timeout #3\n");
 
-	if(force) {
-		qregs->hcctrl = HCCTRL_CRIRQ;
-	} else {
-		if((qregs->mbox5 - qpti->res_out_ptr) == 0)
-			qregs->hcctrl = HCCTRL_CRIRQ;
+		/* Workaround for some buggy chips. */
+		if (sbus_readw(qpti->qregs + MBOX0) & 0x4000)
+			break;
 	}
+	if (!loop_count)
+		printk(KERN_EMERG "qlogicpti: mbox_command[%04x] loop timeout #3\n",
+		       param[0]);
 
-	switch(mbox_param[param[0]] & 0xf) {
-	case 6: param[5] = qregs->mbox5;
-	case 5: param[4] = qregs->mbox4;
-	case 4: param[3] = qregs->mbox3;
-	case 3: param[2] = qregs->mbox2;
-	case 2: param[1] = qregs->mbox1;
-	case 1: param[0] = qregs->mbox0;
-	}
+	/* Wait for MBOX busy condition to go away. */
+	loop_count = DEFAULT_LOOP_COUNT;
+	while (--loop_count && (sbus_readw(qpti->qregs + MBOX0) == 0x04))
+		udelay(20);
+	if (!loop_count)
+		printk(KERN_EMERG "qlogicpti: mbox_command[%04x] loop timeout #4\n",
+		       param[0]);
+
+	/* Read back output parameters. */
+	switch (mbox_param[param[0]] & 0xf) {
+	case 6: param[5] = sbus_readw(qpti->qregs + MBOX5);
+	case 5: param[4] = sbus_readw(qpti->qregs + MBOX4);
+	case 4: param[3] = sbus_readw(qpti->qregs + MBOX3);
+	case 3: param[2] = sbus_readw(qpti->qregs + MBOX2);
+	case 2: param[1] = sbus_readw(qpti->qregs + MBOX1);
+	case 1: param[0] = sbus_readw(qpti->qregs + MBOX0);
+	}
+
+	/* Clear RISC interrupt. */
+	tmp = sbus_readw(qpti->qregs + HCCTRL);
+	tmp |= HCCTRL_CRIRQ;
+	sbus_writew(tmp, qpti->qregs + HCCTRL);
+
+	/* Release SBUS semaphore. */
+	tmp = sbus_readw(qpti->qregs + SBUS_SEMAPHORE);
+	tmp &= ~(SBUS_SEMAPHORE_LCK);
+	sbus_writew(tmp, qpti->qregs + SBUS_SEMAPHORE);
 
-	qregs->sbus_semaphore &= ~(SBUS_SEMAPHORE_LCK);
+	/* We're done. */
 	return 0;
 }
 
+static inline void qlogicpti_set_hostdev_defaults(struct qlogicpti *qpti)
+{
+	int i;
+
+	qpti->host_param.initiator_scsi_id = qpti->scsi_id;
+	qpti->host_param.bus_reset_delay = 3;
+	qpti->host_param.retry_count = 0;
+	qpti->host_param.retry_delay = 5;
+	qpti->host_param.async_data_setup_time = 3;
+	qpti->host_param.req_ack_active_negation = 1;
+	qpti->host_param.data_line_active_negation = 1;
+	qpti->host_param.data_dma_burst_enable = 1;
+	qpti->host_param.command_dma_burst_enable = 1;
+	qpti->host_param.tag_aging = 8;
+	qpti->host_param.selection_timeout = 250;
+	qpti->host_param.max_queue_depth = 256;
+
+	for(i = 0; i < MAX_TARGETS; i++) {
+		/*
+		 * disconnect, parity, arq, reneg on reset, and, oddly enough
+		 * tags...the midlayer's notion of tagged support has to match
+		 * our device settings, and since we base whether we enable a
+		 * tag on a  per-cmnd basis upon what the midlayer sez, we
+		 * actually enable the capability here.
+		 */
+		qpti->dev_param[i].device_flags = 0xcd;
+		qpti->dev_param[i].execution_throttle = 16;
+		if (qpti->ultra) {
+			qpti->dev_param[i].synchronous_period = 12;
+			qpti->dev_param[i].synchronous_offset = 8;
+		} else {
+			qpti->dev_param[i].synchronous_period = 25;
+			qpti->dev_param[i].synchronous_offset = 12;
+		}
+		qpti->dev_param[i].device_enable = 1;
+	}
+	/* this is very important to set! */
+	qpti->sbits = 1 << qpti->scsi_id;
+}
+
 static int qlogicpti_reset_hardware(struct Scsi_Host *host)
 {
 	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
-	struct qlogicpti_regs *qregs = qpti->qregs;
 	u_short param[6];
 	unsigned short risc_code_addr;
 	int loop_count, i;
 	unsigned long flags;
 
-	if(qpti->is_pti != 0)
-		risc_code_addr = pti_risc_code_addr01;
-	else
-		risc_code_addr = sbus_risc_code_addr01;
+	risc_code_addr = 0x1000;	/* all load addresses are at 0x1000 */
 
 	save_flags(flags); cli();
 
-	qregs->hcctrl = HCCTRL_PAUSE;
+	sbus_writew(HCCTRL_PAUSE, qpti->qregs + HCCTRL);
 
 	/* Only reset the scsi bus if it is not free. */
-	if(qregs->cpu_pctrl & CPU_PCTRL_BSY) {
-		qregs->cpu_oride = CPU_ORIDE_RMOD;
-		qregs->cpu_cmd = CPU_CMD_BRESET;
+	if (sbus_readw(qpti->qregs + CPU_PCTRL) & CPU_PCTRL_BSY) {
+		sbus_writew(CPU_ORIDE_RMOD, qpti->qregs + CPU_ORIDE);
+		sbus_writew(CPU_CMD_BRESET, qpti->qregs + CPU_CMD);
 		udelay(400);
 	}
 
-	qregs->sbus_ctrl = SBUS_CTRL_RESET;
-	qregs->cmd_dma_ctrl = (DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ);
-	qregs->data_dma_ctrl = (DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ);
+	sbus_writew(SBUS_CTRL_RESET, qpti->qregs + SBUS_CTRL);
+	sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + CMD_DMA_CTRL);
+	sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + DATA_DMA_CTRL);
 
 	loop_count = DEFAULT_LOOP_COUNT;
-	while(--loop_count && ((qregs->mbox0 & 0xff) == 0x04))
+	while (--loop_count && ((sbus_readw(qpti->qregs + MBOX0) & 0xff) == 0x04))
 		udelay(20);
-	if(!loop_count)
+	if (!loop_count)
 		printk(KERN_EMERG "qlogicpti: reset_hardware loop timeout\n");
 
-	qregs->hcctrl = HCCTRL_PAUSE;
-	set_sbus_cfg1(qregs, qpti->bursts);
-	qlogicpti_enable_irqs(qregs);
+	sbus_writew(HCCTRL_PAUSE, qpti->qregs + HCCTRL);
+	set_sbus_cfg1(qpti);
+	qlogicpti_enable_irqs(qpti);
 
-	if(qregs->risc_psr & RISC_PSR_ULTRA) {
+	if (sbus_readw(qpti->qregs + RISC_PSR) & RISC_PSR_ULTRA) {
 		qpti->ultra = 1;
-		qregs->risc_mtreg = (RISC_MTREG_P0ULTRA | RISC_MTREG_P1ULTRA);
+		sbus_writew((RISC_MTREG_P0ULTRA | RISC_MTREG_P1ULTRA),
+			    qpti->qregs + RISC_MTREG);
 	} else {
 		qpti->ultra = 0;
-		qregs->risc_mtreg = (RISC_MTREG_P0DFLT | RISC_MTREG_P1DFLT);
+		sbus_writew((RISC_MTREG_P0DFLT | RISC_MTREG_P1DFLT),
+			    qpti->qregs + RISC_MTREG);
 	}
 
+	/* reset adapter and per-device default values. */
+	/* do it after finding out whether we're ultra mode capable */
+	qlogicpti_set_hostdev_defaults(qpti);
+
 	/* Release the RISC processor. */
-	qregs->hcctrl = HCCTRL_REL;
+	sbus_writew(HCCTRL_REL, qpti->qregs + HCCTRL);
 
 	/* Get RISC to start executing the firmware code. */
 	param[0] = MBOX_EXEC_FIRMWARE;
 	param[1] = risc_code_addr;
-	if(qlogicpti_mbox_command(qpti, param, 1)) {
+	if (qlogicpti_mbox_command(qpti, param, 1)) {
 		printk(KERN_EMERG "qlogicpti%d: Cannot execute ISP firmware.\n",
 		       qpti->qpti_id);
 		restore_flags(flags);
@@ -276,7 +373,7 @@
 	/* Set initiator scsi ID. */
 	param[0] = MBOX_SET_INIT_SCSI_ID;
 	param[1] = qpti->host_param.initiator_scsi_id;
-	if(qlogicpti_mbox_command(qpti, param, 1) ||
+	if (qlogicpti_mbox_command(qpti, param, 1) ||
 	   (param[0] != MBOX_COMMAND_COMPLETE)) {
 		printk(KERN_EMERG "qlogicpti%d: Cannot set initiator SCSI ID.\n",
 		       qpti->qpti_id);
@@ -292,7 +389,7 @@
 	param[2] = (u_short) (qpti->res_dvma >> 16);
 	param[3] = (u_short) (qpti->res_dvma & 0xffff);
 	param[4] = param[5] = 0;
-	if(qlogicpti_mbox_command(qpti, param, 1)) {
+	if (qlogicpti_mbox_command(qpti, param, 1)) {
 		printk(KERN_EMERG "qlogicpti%d: Cannot init response queue.\n",
 		       qpti->qpti_id);
 		restore_flags(flags);
@@ -300,11 +397,11 @@
 	}
 
 	param[0] = MBOX_INIT_REQ_QUEUE;
-	param[1] = QLOGICISP_REQ_QUEUE_LEN + 1;
+	param[1] = QLOGICPTI_REQ_QUEUE_LEN + 1;
 	param[2] = (u_short) (qpti->req_dvma >> 16);
 	param[3] = (u_short) (qpti->req_dvma & 0xffff);
 	param[4] = param[5] = 0;
-	if(qlogicpti_mbox_command(qpti, param, 1)) {
+	if (qlogicpti_mbox_command(qpti, param, 1)) {
 		printk(KERN_EMERG "qlogicpti%d: Cannot init request queue.\n",
 		       qpti->qpti_id);
 		restore_flags(flags);
@@ -320,7 +417,7 @@
 	param[1] = qpti->host_param.tag_aging;
 	qlogicpti_mbox_command(qpti, param, 0);
 
-	for(i = 0; i < MAX_TARGETS; i++) {
+	for (i = 0; i < MAX_TARGETS; i++) {
 		param[0] = MBOX_GET_DEV_QUEUE_PARAMS;
 		param[1] = (i << 8);
 		qlogicpti_mbox_command(qpti, param, 0);
@@ -333,15 +430,26 @@
 	param[1] = qpti->host_param.selection_timeout;
 	qlogicpti_mbox_command(qpti, param, 0);
 
-	for(i = 0; i < MAX_TARGETS; i++) {
+	for (i = 0; i < MAX_TARGETS; i++) {
 		param[0] = MBOX_SET_TARGET_PARAMS;
 		param[1] = (i << 8);
 		param[2] = (qpti->dev_param[i].device_flags << 8);
-		param[3] = (qpti->dev_param[i].synchronous_offset << 8) |
-			qpti->dev_param[i].synchronous_period;
+		/*
+		 * Since we're now loading 1.31 f/w, force narrow/async.
+		 */
+		param[2] |= 0xc0;
+		param[3] = 0;	/* no offset, we do not have sync mode yet */
 		qlogicpti_mbox_command(qpti, param, 0);
 	}
 
+	/*
+	 * Always (sigh) do an initial bus reset (kicks f/w).
+	 */
+	param[0] = MBOX_BUS_RESET;
+	param[1] = qpti->host_param.bus_reset_delay;
+	qlogicpti_mbox_command(qpti, param, 0);
+	qpti->send_marker = 1;
+
 	restore_flags(flags);
 	return 0;
 }
@@ -350,130 +458,107 @@
 
 static int __init qlogicpti_load_firmware(struct qlogicpti *qpti)
 {
-	struct qlogicpti_regs *qregs = qpti->qregs;
 	unsigned short csum = 0;
 	unsigned short param[6];
 	unsigned short *risc_code, risc_code_addr, risc_code_length;
 	unsigned long flags;
-#if !defined(MODULE) && !defined(__sparc_v9__)
-	unsigned long dvma_addr;
-#endif
 	int i, timeout;
 
-	if(qpti->is_pti != 0) {
-		risc_code = &pti_risc_code01[0];
-		risc_code_addr = pti_risc_code_addr01;
-		risc_code_length = pti_risc_code_length01;
-	} else {
-		risc_code = &sbus_risc_code01[0];
-		risc_code_addr = sbus_risc_code_addr01;
-		risc_code_length = sbus_risc_code_length01;
-	}
+	risc_code = &sbus_risc_code01[0];
+	risc_code_addr = 0x1000;	/* all f/w modules load at 0x1000 */
+	risc_code_length = sbus_risc_code_length01;
 
 	save_flags(flags); cli();
 
 	/* Verify the checksum twice, one before loading it, and once
 	 * afterwards via the mailbox commands.
 	 */
-	for(i = 0; i < risc_code_length; i++)
+	for (i = 0; i < risc_code_length; i++)
 		csum += risc_code[i];
-	if(csum) {
+	if (csum) {
+		restore_flags(flags);
 		printk(KERN_EMERG "qlogicpti%d: Aieee, firmware checksum failed!",
 		       qpti->qpti_id);
 		return 1;
 	}		
-	qregs->sbus_ctrl = SBUS_CTRL_RESET;
-	qregs->cmd_dma_ctrl = (DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ);
-	qregs->data_dma_ctrl = (DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ);
+	sbus_writew(SBUS_CTRL_RESET, qpti->qregs + SBUS_CTRL);
+	sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + CMD_DMA_CTRL);
+	sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + DATA_DMA_CTRL);
 	timeout = PTI_RESET_LIMIT;
-	while(--timeout && (qregs->sbus_ctrl & SBUS_CTRL_RESET))
+	while (--timeout && (sbus_readw(qpti->qregs + SBUS_CTRL) & SBUS_CTRL_RESET))
 		udelay(20);
-	if(!timeout) {
+	if (!timeout) {
+		restore_flags(flags);
 		printk(KERN_EMERG "qlogicpti%d: Cannot reset the ISP.", qpti->qpti_id);
 		return 1;
 	}
 
-	qregs->hcctrl = HCCTRL_RESET;
+	sbus_writew(HCCTRL_RESET, qpti->qregs + HCCTRL);
 	mdelay(1);
 
-	qregs->sbus_ctrl = (SBUS_CTRL_GENAB | SBUS_CTRL_ERIRQ);
-	set_sbus_cfg1(qregs, qpti->bursts);
-	qregs->sbus_semaphore = 0;
+	sbus_writew((SBUS_CTRL_GENAB | SBUS_CTRL_ERIRQ), qpti->qregs + SBUS_CTRL);
+	set_sbus_cfg1(qpti);
+	sbus_writew(0, qpti->qregs + SBUS_SEMAPHORE);
 
-	if(qregs->risc_psr & RISC_PSR_ULTRA) {
+	if (sbus_readw(qpti->qregs + RISC_PSR) & RISC_PSR_ULTRA) {
 		qpti->ultra = 1;
-		qregs->risc_mtreg = (RISC_MTREG_P0ULTRA | RISC_MTREG_P1ULTRA);
+		sbus_writew((RISC_MTREG_P0ULTRA | RISC_MTREG_P1ULTRA),
+			    qpti->qregs + RISC_MTREG);
 	} else {
 		qpti->ultra = 0;
-		qregs->risc_mtreg = (RISC_MTREG_P0DFLT | RISC_MTREG_P1DFLT);
+		sbus_writew((RISC_MTREG_P0DFLT | RISC_MTREG_P1DFLT),
+			    qpti->qregs + RISC_MTREG);
 	}
 
-	qregs->hcctrl = HCCTRL_REL;
+	sbus_writew(HCCTRL_REL, qpti->qregs + HCCTRL);
 
 	/* Pin lines are only stable while RISC is paused. */
-	qregs->hcctrl = HCCTRL_PAUSE;
-	if(qregs->cpu_pdiff & CPU_PDIFF_MODE)
+	sbus_writew(HCCTRL_PAUSE, qpti->qregs + HCCTRL);
+	if (sbus_readw(qpti->qregs + CPU_PDIFF) & CPU_PDIFF_MODE)
 		qpti->differential = 1;
 	else
 		qpti->differential = 0;
-	qregs->hcctrl = HCCTRL_REL;
+	sbus_writew(HCCTRL_REL, qpti->qregs + HCCTRL);
+
+	/* This shouldn't be necessary- we've reset things so we should be
+	   running from the ROM now.. */
 
 	param[0] = MBOX_STOP_FIRMWARE;
 	param[1] = param[2] = param[3] = param[4] = param[5] = 0;
-	if(qlogicpti_mbox_command(qpti, param, 1)) {
+	if (qlogicpti_mbox_command(qpti, param, 1)) {
 		printk(KERN_EMERG "qlogicpti%d: Cannot stop firmware for reload.\n",
 		       qpti->qpti_id);
 		restore_flags(flags);
 		return 1;
 	}		
 
-	/* Load the firmware. */
-#if !defined(MODULE) && !defined(__sparc_v9__)
-	if (sparc_cpu_model != sun4d) {
-		dvma_addr = (unsigned long) mmu_lockarea((char *)&risc_code[0],
-							 (sizeof(u_short) * risc_code_length));
-		param[0] = MBOX_LOAD_RAM;
-		param[1] = risc_code_addr;
-		param[2] = (dvma_addr >> 16);
-		param[3] = (dvma_addr & 0xffff);
-		param[4] = (sizeof(u_short) * risc_code_length);
-		if(qlogicpti_mbox_command(qpti, param, 1) ||
-		   (param[0] != MBOX_COMMAND_COMPLETE)) {
-			printk(KERN_EMERG "qlogicpti%d: Firmware dload failed, I'm bolixed!\n",
+	/* Load it up.. */
+	for (i = 0; i < risc_code_length; i++) {
+		param[0] = MBOX_WRITE_RAM_WORD;
+		param[1] = risc_code_addr + i;
+		param[2] = risc_code[i];
+		if (qlogicpti_mbox_command(qpti, param, 1) ||
+		    param[0] != MBOX_COMMAND_COMPLETE) {
+			printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n",
 			       qpti->qpti_id);
 			restore_flags(flags);
 			return 1;
 		}
-		mmu_unlockarea((char *)dvma_addr, (sizeof(u_short) * risc_code_length));
-	} else
-#endif
-	/* We need to do it this slow way always on Ultra, SS[12]000. */
-		for(i = 0; i < risc_code_length; i++) {
-			param[0] = MBOX_WRITE_RAM_WORD;
-			param[1] = risc_code_addr + i;
-			param[2] = risc_code[i];
-			if(qlogicpti_mbox_command(qpti, param, 1) ||
-			   param[0] != MBOX_COMMAND_COMPLETE) {
-				printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n",
-				       qpti->qpti_id);
-				restore_flags(flags);
-				return 1;
-			}
-		}
+	}
 
 	/* Reset the ISP again. */
-	qregs->hcctrl = HCCTRL_RESET;
+	sbus_writew(HCCTRL_RESET, qpti->qregs + HCCTRL);
 	mdelay(1);
 
-	qlogicpti_enable_irqs(qregs);
-	qregs->sbus_semaphore = 0;
-	qregs->hcctrl = HCCTRL_REL;
+	qlogicpti_enable_irqs(qpti);
+	sbus_writew(0, qpti->qregs + SBUS_SEMAPHORE);
+	sbus_writew(HCCTRL_REL, qpti->qregs + HCCTRL);
 
 	/* Ask ISP to verify the checksum of the new code. */
 	param[0] = MBOX_VERIFY_CHECKSUM;
 	param[1] = risc_code_addr;
-	if(qlogicpti_mbox_command(qpti, param, 1) ||
-	   (param[0] != MBOX_COMMAND_COMPLETE)) {
+	if (qlogicpti_mbox_command(qpti, param, 1) ||
+	    (param[0] != MBOX_COMMAND_COMPLETE)) {
 		printk(KERN_EMERG "qlogicpti%d: New firmware csum failure!\n",
 		       qpti->qpti_id);
 		restore_flags(flags);
@@ -486,8 +571,8 @@
 	qlogicpti_mbox_command(qpti, param, 1);
 
 	param[0] = MBOX_ABOUT_FIRMWARE;
-	if(qlogicpti_mbox_command(qpti, param, 1) ||
-	   (param[0] != MBOX_COMMAND_COMPLETE)) {
+	if (qlogicpti_mbox_command(qpti, param, 1) ||
+	    (param[0] != MBOX_COMMAND_COMPLETE)) {
 		printk(KERN_EMERG "qlogicpti%d: AboutFirmware cmd fails.\n",
 		       qpti->qpti_id);
 		restore_flags(flags);
@@ -497,8 +582,20 @@
 	/* Snag the major and minor revisions from the result. */
 	qpti->fware_majrev = param[1];
 	qpti->fware_minrev = param[2];
+	qpti->fware_micrev = param[3];
+
+	/* Set the clock rate */
+	param[0] = MBOX_SET_CLOCK_RATE;
+	param[1] = qpti->clock;
+	if (qlogicpti_mbox_command(qpti, param, 1) ||
+	    (param[0] != MBOX_COMMAND_COMPLETE)) {
+		printk(KERN_EMERG "qlogicpti%d: could not set clock rate.\n",
+		       qpti->qpti_id);
+		restore_flags(flags);
+		return 1;
+	}
 
-	if(qpti->is_pti != 0) {
+	if (qpti->is_pti != 0) {
 		/* Load scsi initiator ID and interrupt level into sbus static ram. */
 		param[0] = MBOX_WRITE_RAM_WORD;
 		param[1] = 0xff80;
@@ -517,25 +614,25 @@
 
 static int qlogicpti_verify_tmon(struct qlogicpti *qpti)
 {
-	int curstat = *qpti->sreg;
+	int curstat = sbus_readb(qpti->sreg);
 
 	curstat &= 0xf0;
-	if(!(curstat & SREG_FUSE) && (qpti->swsreg & SREG_FUSE))
+	if (!(curstat & SREG_FUSE) && (qpti->swsreg & SREG_FUSE))
 		printk("qlogicpti%d: Fuse returned to normal state.\n", qpti->qpti_id);
-	if(!(curstat & SREG_TPOWER) && (qpti->swsreg & SREG_TPOWER))
+	if (!(curstat & SREG_TPOWER) && (qpti->swsreg & SREG_TPOWER))
 		printk("qlogicpti%d: termpwr back to normal state.\n", qpti->qpti_id);
-	if(curstat != qpti->swsreg) {
+	if (curstat != qpti->swsreg) {
 		int error = 0;
-		if(curstat & SREG_FUSE) {
+		if (curstat & SREG_FUSE) {
 			error++;
 			printk("qlogicpti%d: Fuse is open!\n", qpti->qpti_id);
 		}
-		if(curstat & SREG_TPOWER) {
+		if (curstat & SREG_TPOWER) {
 			error++;
 			printk("qlogicpti%d: termpwr failure\n", qpti->qpti_id);
 		}
-		if(qpti->differential &&
-		   (curstat & SREG_DSENSE) != SREG_DSENSE) {
+		if (qpti->differential &&
+		    (curstat & SREG_DSENSE) != SREG_DSENSE) {
 			error++;
 			printk("qlogicpti%d: You have a single ended device on a "
 			       "differential bus!  Please fix!\n", qpti->qpti_id);
@@ -546,70 +643,191 @@
 	return 0;
 }
 
-static inline void qlogicpti_set_hostdev_defaults(struct qlogicpti *qpti)
+static void qpti_intr(int irq, void *dev_id, struct pt_regs *regs);
+
+static void __init qpti_chain_add(struct qlogicpti *qpti)
 {
-	int i;
+	spin_lock_irq(&qptichain_lock);
+	if (qptichain != NULL) {
+		struct qlogicpti *qlink = qptichain;
 
-	qpti->host_param.initiator_scsi_id = qpti->scsi_id;
-	qpti->host_param.bus_reset_delay = 3;
-	qpti->host_param.retry_count = 0;
-	qpti->host_param.retry_delay = 5;
-	qpti->host_param.async_data_setup_time = 3;
-	qpti->host_param.req_ack_active_negation = 1;
-	qpti->host_param.data_line_active_negation = 1;
-	qpti->host_param.data_dma_burst_enable = 1;
-	qpti->host_param.command_dma_burst_enable = 1;
-	qpti->host_param.tag_aging = 8;
-	qpti->host_param.selection_timeout = 250;
-	qpti->host_param.max_queue_depth = 256;
+		while(qlink->next)
+			qlink = qlink->next;
+		qlink->next = qpti;
+	} else {
+		qptichain = qpti;
+	}
+	qpti->next = NULL;
+	spin_unlock_irq(&qptichain_lock);
+}
 
-	for(i = 0; i < MAX_TARGETS; i++) {
-		qpti->dev_param[i].device_flags = 0xf9;
-		qpti->dev_param[i].execution_throttle = 16;
-		qpti->dev_param[i].synchronous_period = 16;
-		qpti->dev_param[i].synchronous_offset = 12;
-		qpti->dev_param[i].device_enable = 1;
+static void __init qpti_chain_del(struct qlogicpti *qpti)
+{
+	spin_lock_irq(&qptichain_lock);
+	if (qptichain == qpti) {
+		qptichain = qpti->next;
+	} else {
+		struct qlogicpti *qlink = qptichain;
+		while(qlink->next != qpti)
+			qlink = qlink->next;
+		qlink->next = qpti->next;
+	}
+	qpti->next = NULL;
+	spin_unlock_irq(&qptichain_lock);
+}
+
+static int __init qpti_map_regs(struct qlogicpti *qpti)
+{
+	struct sbus_dev *sdev = qpti->sdev;
+
+	qpti->qregs = sbus_ioremap(&sdev->resource[0], 0,
+				   sdev->reg_addrs[0].reg_size,
+				   "PTI Qlogic/ISP");
+	if (!qpti->qregs) {
+		printk("PTI: Qlogic/ISP registers are unmappable\n");
+		return -1;
+	}
+	if (qpti->is_pti) {
+		qpti->sreg = sbus_ioremap(&sdev->resource[0], (16 * 4096),
+					  sizeof(unsigned char),
+					  "PTI Qlogic/ISP statreg");
+		if (!qpti->sreg) {
+			printk("PTI: Qlogic/ISP status register is unmappable\n");
+			return -1;
+		}
 	}
+	return 0;
 }
 
-static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs);
-#ifndef __sparc_v9__
-static void do_qlogicpti_intr_handler_sun4m(int irq, void *dev_id, struct pt_regs *regs);
-#endif
+static int __init qpti_register_irq(struct qlogicpti *qpti)
+{
+	struct sbus_dev *sdev = qpti->sdev;
+
+	qpti->qhost->irq = qpti->irq = sdev->irqs[0];
+
+	/* We used to try various overly-clever things to
+	 * reduce the interrupt processing overhead on
+	 * sun4c/sun4m when multiple PTI's shared the
+	 * same IRQ.  It was too complex and messy to
+	 * sanely maintain.
+	 */
+	if (request_irq(qpti->irq, qpti_intr,
+			SA_SHIRQ, "Qlogic/PTI", qpti))
+		goto fail;
+
+	printk("qpti%d: IRQ %s ", qpti->qpti_id, __irq_itoa(qpti->irq));
+
+	return 0;
+
+fail:
+	printk("qpti%d: Cannot acquire irq line\n", qpti->qpti_id);
+	return -1;
+}
+
+static void __init qpti_get_scsi_id(struct qlogicpti *qpti)
+{
+	qpti->scsi_id = prom_getintdefault(qpti->prom_node,
+					   "initiator-id",
+					   -1);
+	if (qpti->scsi_id == -1)
+		qpti->scsi_id = prom_getintdefault(qpti->prom_node,
+						   "scsi-initiator-id",
+						   -1);
+	if (qpti->scsi_id == -1)
+		qpti->scsi_id =
+			prom_getintdefault(qpti->sdev->bus->prom_node,
+					   "scsi-initiator-id", 7);
+	qpti->qhost->this_id = qpti->scsi_id;
+
+	printk("SCSI ID %d ", qpti->scsi_id);
+}
+
+static void qpti_get_bursts(struct qlogicpti *qpti)
+{
+	struct sbus_dev *sdev = qpti->sdev;
+	u8 bursts, bmask;
+
+	bursts = prom_getintdefault(qpti->prom_node, "burst-sizes", 0xff);
+	bmask = prom_getintdefault(sdev->bus->prom_node,
+				   "burst-sizes", 0xff);
+	if (bmask != 0xff)
+		bursts &= bmask;
+	if (bursts == 0xff ||
+	    (bursts & DMA_BURST16) == 0 ||
+	    (bursts & DMA_BURST32) == 0)
+		bursts = (DMA_BURST32 - 1);
+
+	qpti->bursts = bursts;
+}
+
+static void qpti_get_clock(struct qlogicpti *qpti)
+{
+	unsigned int cfreq;
+
+	/* Check for what the clock input to this card is.
+	 * Default to 40Mhz.
+	 */
+	cfreq = prom_getintdefault(qpti->prom_node,"clock-frequency",40000000);
+	qpti->clock = (cfreq + 500000)/1000000;
+	if (qpti->clock == 0) /* bullshit */
+		qpti->clock = 40;
+}
+
+/* The request and response queues must each be aligned
+ * on a page boundry.
+ */
+static int __init qpti_map_queues(struct qlogicpti *qpti)
+{
+	struct sbus_dev *sdev = qpti->sdev;
+
+#define QSIZE(entries)	(((entries) + 1) * QUEUE_ENTRY_LEN)
+	qpti->res_cpu = sbus_alloc_consistant(sdev,
+					      QSIZE(RES_QUEUE_LEN),
+					      &qpti->res_dvma);
+	if (qpti->res_cpu == NULL ||
+	    qpti->res_dvma == 0) {
+		printk("QPTI: Cannot map response queue.\n");
+		return -1;
+	}
+
+	qpti->req_cpu = sbus_alloc_consistant(sdev,
+					      QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
+					      &qpti->req_dvma);
+	if (qpti->req_cpu == NULL ||
+	    qpti->req_dvma == 0) {
+		sbus_free_consistant(sdev, QSIZE(RES_QUEUE_LEN),
+				     qpti->res_cpu, qpti->res_dvma);
+		printk("QPTI: Cannot map request queue.\n");
+		return -1;
+	}
+	memset(qpti->res_cpu, 0, QSIZE(RES_QUEUE_LEN));
+	memset(qpti->req_cpu, 0, QSIZE(QLOGICPTI_REQ_QUEUE_LEN));
+	return 0;
+}
 
 /* Detect all PTI Qlogic ISP's in the machine. */
 int __init qlogicpti_detect(Scsi_Host_Template *tpnt)
 {
-	struct qlogicpti *qpti, *qlink;
+	struct qlogicpti *qpti;
 	struct Scsi_Host *qpti_host;
-	struct linux_sbus *sbus;
-	struct linux_sbus_device *qpti_dev, *sbdev_iter;
-	struct qlogicpti_regs *qregs;
-	volatile unsigned char *sreg;
-	unsigned char bsizes, bsizes_more;
+	struct sbus_bus *sbus;
+	struct sbus_dev *sdev;
 	int nqptis = 0, nqptis_in_use = 0;
-	int qpti_node;
-	int is_pti;
 
 	tpnt->proc_name = "qlogicpti";
-	qptichain = 0;
-	if(!SBus_chain)
-		return 0;
 	for_each_sbus(sbus) {
-		for_each_sbusdev(sbdev_iter, sbus) {
-			qpti_dev = sbdev_iter;
-
+		for_each_sbusdev(sdev, sbus) {
 			/* Is this a red snapper? */
-			if(strcmp(qpti_dev->prom_name, "ptisp") &&
-			   strcmp(qpti_dev->prom_name, "PTI,ptisp") &&
-			   strcmp(qpti_dev->prom_name, "QLGC,isp"))
+			if (strcmp(sdev->prom_name, "ptisp") &&
+			    strcmp(sdev->prom_name, "PTI,ptisp") &&
+			    strcmp(sdev->prom_name, "QLGC,isp"))
 				continue;
 
 			/* Sometimes Antares cards come up not completely
 			 * setup, and we get a report of a zero IRQ.
 			 * Skip over them in such cases so we survive.
 			 */
-			if(qpti_dev->irqs[0] == 0) {
+			if (sdev->irqs[0] == 0) {
 				printk("qpti%d: Adapter reports no interrupt, "
 				       "skipping over this card.", nqptis);
 				continue;
@@ -617,179 +835,76 @@
 
 			/* Yep, register and allocate software state. */
 			qpti_host = scsi_register(tpnt, sizeof(struct qlogicpti));
-			if(!qpti_host)
-				panic("Cannot register PTI Qlogic ISP SCSI host");
+			if (!qpti_host) {
+				printk("QPTI: Cannot register PTI Qlogic ISP SCSI host");
+				continue;
+			}
 			qpti = (struct qlogicpti *) qpti_host->hostdata;
-			if(!qpti)
-				panic("No qpti in hostdata");
+
+			spin_lock_init(&qpti->lock);
 
 			/* We are wide capable, 16 targets. */
 			qpti_host->max_id = MAX_TARGETS;
 
-#ifdef __sparc_v9__
-			qpti_host->unchecked_isa_dma = 1;
-#endif
-
 			/* Setup back pointers and misc. state. */
 			qpti->qhost = qpti_host;
-			qpti->qdev = qpti_dev;
+			qpti->sdev = sdev;
 			qpti->qpti_id = nqptis++;
-
-			/* Insert this one into the global interrupt service chain. */
-			if(qptichain) {
-				qlink = qptichain;
-				while(qlink->next) qlink = qlink->next;
-				qlink->next = qpti;
-			} else {
-				qptichain = qpti;
-			}
-			qpti->next = 0;
-
-			/* More misc. prom information. */
-			qpti_node = qpti_dev->prom_node;
-			prom_getstring(qpti_node, "name", qpti->prom_name,
+			qpti->prom_node = sdev->prom_node;
+			prom_getstring(qpti->prom_node, "name",
+				       qpti->prom_name,
 				       sizeof(qpti->prom_name));
-			qpti->prom_node = qpti_node;
-			
-			qpti->is_pti = is_pti =
-				(strcmp (qpti->prom_name, "QLGC,isp") != 0);
 
-			/* Setup the reg property for this device. */
-			prom_apply_sbus_ranges(qpti->qdev->my_bus,
-					       qpti->qdev->reg_addrs,
-					       1, qpti->qdev);
-
-			/* Map in Qlogic,ISP regs and the PTI status reg. */
-			qpti->qregs = qregs = (struct qlogicpti_regs *)
-				sparc_alloc_io(qpti->qdev->reg_addrs[0].phys_addr, 0,
-					       qpti->qdev->reg_addrs[0].reg_size,
-					       "PTI Qlogic/ISP Registers",
-					       qpti->qdev->reg_addrs[0].which_io, 0x0);
-			if(!qregs)
-				panic("PTI Qlogic/ISP registers unmappable");
-				
-			if(is_pti) {
-				/* Map this one read only. */
-				qpti->sreg = sreg = (volatile unsigned char *)
-					sparc_alloc_io((qpti->qdev->reg_addrs[0].phys_addr +
-						       (16 * 4096)), 0,
-						       sizeof(unsigned char),
-						       "PTI Qlogic/ISP Status Reg",
-						       qpti->qdev->reg_addrs[0].which_io, 1);
-				if(!sreg)
-					panic("PTI Qlogic/ISP status reg unmappable");
-				qpti->swsreg = 0;
-			}
-
-			qpti_host->base = (unsigned char *)qregs;
-			qpti_host->io_port = (unsigned int) ((unsigned long)qregs);
-			qpti_host->n_io_port = (unsigned char)
-				qpti->qdev->reg_addrs[0].reg_size;
-
-			qpti_host->irq = qpti->irq = qpti->qdev->irqs[0];
-
-			/* On Ultra and S{S1,C2}000 we must always call request_irq for each
-			 * qpti, so that imap registers get setup etc.
-			 * But irq values are different in that case anyway...
-			 * Otherwise allocate the irq only if necessary.
+			/* This is not correct, actually. There's a switch
+			 * on the PTI cards that put them into "emulation"
+			 * mode- i.e., report themselves as QLGC,isp
+			 * instead of PTI,ptisp. The only real substantive
+			 * difference between non-pti and pti cards is
+			 * the tmon register. Which is possibly even
+			 * there for Qlogic cards, but non-functional.
 			 */
-			for_each_qlogicpti(qlink) {
-				if((qlink != qpti) && (qpti->irq == qlink->irq)) {
-					goto qpti_irq_acquired; /* BASIC rulez */
-				}
-			}
-			if(request_irq(qpti->qhost->irq, 
-#ifndef __sparc_v9__			
-				       (sparc_cpu_model == sun4m || sparc_cpu_model == sun4c) ?
-				           do_qlogicpti_intr_handler_sun4m :
-#endif
-				           do_qlogicpti_intr_handler,
-				       SA_SHIRQ, "PTI Qlogic/ISP SCSI", qpti)) {
-				printk("Cannot acquire PTI Qlogic/ISP irq line\n");
-				/* XXX Unmap regs, unregister scsi host, free things. */
-				continue;
-			}
-qpti_irq_acquired:
-			printk("qpti%d: IRQ %s ",
-			       qpti->qpti_id, __irq_itoa(qpti->qhost->irq));
-
-			/* Figure out our scsi ID on the bus */
-			qpti->scsi_id = prom_getintdefault(qpti->prom_node,
-							   "initiator-id",
-							   -1);
-			if(qpti->scsi_id == -1)
-				qpti->scsi_id = prom_getintdefault(qpti->prom_node,
-								   "scsi-initiator-id",
-								   -1);
-			if(qpti->scsi_id == -1)
-				qpti->scsi_id =
-					prom_getintdefault(qpti->qdev->my_bus->prom_node,
-							   "scsi-initiator-id", 7);
-			qpti->qhost->this_id = qpti->scsi_id;
-			printk("SCSI ID %d ", qpti->scsi_id);
+			qpti->is_pti = (strcmp (qpti->prom_name, "QLGC,isp") != 0);
 
-			/* Check for what the best SBUS burst we can use happens
-			 * to be on this machine.
-			 */
-			bsizes = prom_getintdefault(qpti->prom_node,"burst-sizes",0xff);
-			bsizes &= 0xff;
-			bsizes_more = prom_getintdefault(qpti->qdev->my_bus->prom_node,
-							 "burst-sizes", 0xff);
-			if(bsizes_more != 0xff)
-				bsizes &= bsizes_more;
-			if(bsizes == 0xff || (bsizes & DMA_BURST16)==0 ||
-			   (bsizes & DMA_BURST32) == 0)
-				bsizes = (DMA_BURST32 - 1);
-			qpti->bursts = bsizes;
+			qpti_chain_add(qpti);
+			if (qpti_map_regs(qpti) < 0)
+				goto fail_unlink;
+
+			if (qpti_register_irq(qpti) < 0)
+				goto fail_unmap_regs;
+
+			qpti_get_scsi_id(qpti);
+			qpti_get_bursts(qpti);
+			qpti_get_clock(qpti);
 
 			/* Clear out Scsi_Cmnd array. */
 			memset(qpti->cmd_slots, 0, sizeof(qpti->cmd_slots));
 
-			/* The request and response queues must each be aligned
-			 * on a page boundry.
-			 */
-
-#define QSIZE(entries)	(((entries) + 1) * QUEUE_ENTRY_LEN)
-
-			qpti->res_cpu = sparc_dvma_malloc(QSIZE(RES_QUEUE_LEN),
-							  "PTISP Response Queue",
-							  &qpti->res_dvma);
-			qpti->req_cpu = sparc_dvma_malloc(QSIZE(QLOGICISP_REQ_QUEUE_LEN),
-							  "PTISP Request Queue",
-							  &qpti->req_dvma);
+			if (qpti_map_queues(qpti) < 0)
+				goto fail_free_irq;
 
-#undef QSIZE
-
-
-			/* Set adapter and per-device default values. */
-			qlogicpti_set_hostdev_defaults(qpti);
-			
 			/* Load the firmware. */
-			/* XXX Find out where is it possible to download
-			   our sbus_risc_code on non-PTI ISP1000. */
-			if(is_pti && qlogicpti_load_firmware(qpti))
-				panic("SBUS Qlogic/ISP firmware load failed");
-
-			if (is_pti) {
+			if (qlogicpti_load_firmware(qpti))
+				goto fail_unmap_queues;
+			if (qpti->is_pti) {
 				/* Check the PTI status reg. */
-				if(qlogicpti_verify_tmon(qpti))
-					panic("PTI Qlogic/ISP tmon verification failed");
+				if (qlogicpti_verify_tmon(qpti))
+					goto fail_unmap_queues;
 			}
 
 			/* Reset the ISP and init res/req queues. */
-			if(qlogicpti_reset_hardware(qpti_host))
-				panic("PTI Qlogic/ISP cannot be reset");
+			if (qlogicpti_reset_hardware(qpti_host))
+				goto fail_unmap_queues;
 
-			if (is_pti) {
-				printk("(Firmware v%d.%d)",
-				       qpti->fware_majrev, qpti->fware_minrev);
-			} else {
+			printk("(Firmware v%d.%d.%d)", qpti->fware_majrev,
+			    qpti->fware_minrev, qpti->fware_micrev);
+			{
 				char buffer[60];
 				
-				prom_getstring (qpti_node, "isp-fcode", buffer, 60);
+				prom_getstring (qpti->prom_node,
+						"isp-fcode", buffer, 60);
 				if (buffer[0])
 					printk("(Firmware %s)", buffer);
-				if (prom_getbool(qpti_node, "differential"))
+				if (prom_getbool(qpti->prom_node, "differential"))
 					qpti->differential = 1;
 			}
 			
@@ -798,6 +913,28 @@
 			       (qpti->differential ? "differential" : "single ended"));
 
 			nqptis_in_use++;
+			continue;
+
+		fail_unmap_queues:
+#define QSIZE(entries)	(((entries) + 1) * QUEUE_ENTRY_LEN)
+			sbus_free_consistant(qpti->sdev,
+					     QSIZE(RES_QUEUE_LEN),
+					     qpti->res_cpu, qpti->res_dvma);
+			sbus_free_consistant(qpti->sdev,
+					     QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
+					     qpti->req_cpu, qpti->req_dvma);
+#undef QSIZE
+		fail_free_irq:
+			free_irq(qpti->irq, qpti);
+
+		fail_unmap_regs:
+			sbus_iounmap(qpti->qregs,
+				     qpti->sdev->reg_addrs[0].reg_size);
+			if (qpti->is_pti)
+				sbus_iounmap(qpti->sreg, sizeof(unsigned char));
+		fail_unlink:
+			qpti_chain_del(qpti);
+			scsi_unregister(qpti->qhost);
 		}
 	}
 	if (nqptis)
@@ -810,17 +947,28 @@
 int qlogicpti_release(struct Scsi_Host *host)
 {
 	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
-	struct qlogicpti_regs *qregs = qpti->qregs;
+
+	/* Remove visibility from IRQ handlers. */
+	qpti_chain_del(qpti);
 
 	/* Shut up the card. */
-	qregs->sbus_ctrl = 0;
+	sbus_writew(0, qpti->qregs + SBUS_CTRL);
 
 	/* Free IRQ handler and unmap Qlogic,ISP and PTI status regs. */
-	free_irq(host->irq, NULL);
-	unmapioaddr((unsigned long)qregs);
-	/* QLGC,isp doesn't have status reg */
-	if (strcmp (qpti->prom_name, "QLGC,isp"))
-		unmapioaddr((unsigned long)qpti->sreg);
+	free_irq(qpti->irq, qpti);
+
+#define QSIZE(entries)	(((entries) + 1) * QUEUE_ENTRY_LEN)
+	sbus_free_consistant(qpti->sdev,
+			     QSIZE(RES_QUEUE_LEN),
+			     qpti->res_cpu, qpti->res_dvma);
+	sbus_free_consistant(qpti->sdev,
+			     QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
+			     qpti->req_cpu, qpti->req_dvma);
+#undef QSIZE
+
+	sbus_iounmap(qpti->qregs, qpti->sdev->reg_addrs[0].reg_size);
+	if (qpti->is_pti)
+		sbus_iounmap(qpti->sreg, sizeof(unsigned char));
 
 	return 0;
 }
@@ -830,8 +978,8 @@
 	static char buf[80];
 	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
 
-	sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %08lx",
-		__irq_itoa(qpti->qhost->irq), (unsigned long) qpti->qregs);
+	sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %lx",
+		__irq_itoa(qpti->qhost->irq), qpti->qregs);
 	return buf;
 }
 
@@ -857,18 +1005,18 @@
 	cmd->target_lun = Cmnd->lun;
 	cmd->cdb_length = Cmnd->cmd_len;
 	cmd->control_flags = 0;
-	if(Cmnd->device->tagged_supported) {
-		if(qpti->cmd_count[Cmnd->target] == 0)
+	if (Cmnd->device->tagged_supported) {
+		if (qpti->cmd_count[Cmnd->target] == 0)
 			qpti->tag_ages[Cmnd->target] = jiffies;
-		if((jiffies - qpti->tag_ages[Cmnd->target]) > (5*HZ)) {
+		if ((jiffies - qpti->tag_ages[Cmnd->target]) > (5*HZ)) {
 			cmd->control_flags = CFLAG_ORDERED_TAG;
 			qpti->tag_ages[Cmnd->target] = jiffies;
 		} else
 			cmd->control_flags = CFLAG_SIMPLE_TAG;
 	}
-	if((Cmnd->cmnd[0] == WRITE_6) ||
-	   (Cmnd->cmnd[0] == WRITE_10) ||
-	   (Cmnd->cmnd[0] == WRITE_12))
+	if ((Cmnd->cmnd[0] == WRITE_6) ||
+	    (Cmnd->cmnd[0] == WRITE_10) ||
+	    (Cmnd->cmnd[0] == WRITE_12))
 		cmd->control_flags |= CFLAG_WRITE;
 	else
 		cmd->control_flags |= CFLAG_READ;
@@ -877,42 +1025,40 @@
 }
 
 /* Do it to it baby. */
-static inline u_int load_cmd(Scsi_Cmnd *Cmnd, struct Command_Entry *cmd,
-			     struct qlogicpti *qpti, struct qlogicpti_regs *qregs,
-			     u_int in_ptr, u_int out_ptr)
+static inline int load_cmd(Scsi_Cmnd *Cmnd, struct Command_Entry *cmd,
+			   struct qlogicpti *qpti, u_int in_ptr, u_int out_ptr)
 {
-	struct dataseg * ds;
+	struct dataseg *ds;
 	struct scatterlist *sg;
-	int sg_count = Cmnd->use_sg;
 	int i, n;
 
-	if(sg_count) {
-		mmu_get_scsi_sgl((struct mmu_sglist *)Cmnd->buffer, (Cmnd->use_sg - 1),
-				 qpti->qdev->my_bus);
+	if (Cmnd->use_sg) {
+		int sg_count;
+
+		sg = (struct scatterlist *) Cmnd->buffer;
+		sg_count = sbus_map_sg(qpti->sdev, sg, Cmnd->use_sg);
 
-		cmd->segment_cnt = sg_count;
-		sg = (struct scatterlist *) Cmnd->request_buffer;
 		ds = cmd->dataseg;
+		cmd->segment_cnt = sg_count;
 
 		/* Fill in first four sg entries: */
 		n = sg_count;
-		if(n > 4)
+		if (n > 4)
 			n = 4;
-		for(i = 0; i < n; i++, sg++) {
-			ds[i].d_base = (u_int) sg->dvma_address;
-			ds[i].d_count = (u_int) sg->length;
+		for (i = 0; i < n; i++, sg++) {
+			ds[i].d_base = sg->dvma_address;
+			ds[i].d_count = sg->dvma_length;
 		}
 		sg_count -= 4;
-		while(sg_count > 0) {
+		while (sg_count > 0) {
 			struct Continuation_Entry *cont;
 
 			++cmd->hdr.entry_cnt;
 			cont = (struct Continuation_Entry *) &qpti->req_cpu[in_ptr];
 			in_ptr = NEXT_REQ_PTR(in_ptr);
-			if(in_ptr == out_ptr) {
-				printk(KERN_EMERG "qlogicpti: Unexpected request queue overflow\n");
+			if (in_ptr == out_ptr)
 				return -1;
-			}
+
 			cont->hdr.entry_type = ENTRY_CONTINUATION;
 			cont->hdr.entry_cnt = 0;
 			cont->hdr.sys_def_1 = 0;
@@ -920,24 +1066,21 @@
 			cont->reserved = 0;
 			ds = cont->dataseg;
 			n = sg_count;
-			if(n > 7)
+			if (n > 7)
 				n = 7;
-			for(i = 0; i < n; i++, sg++) {
-				ds[i].d_base = (u_int) sg->dvma_address;
-				ds[i].d_count = (u_int) sg->length;
+			for (i = 0; i < n; i++, sg++) {
+				ds[i].d_base = sg->dvma_address;
+				ds[i].d_count = sg->dvma_length;
 			}
 			sg_count -= n;
 		}
 	} else {
-		/* XXX Casts are extremely gross, but with 64-bit cpu addresses
-		 * XXX and 32-bit SBUS DVMA addresses what am I to do? -DaveM
-		 */
-		Cmnd->SCp.ptr = (char *)((unsigned long)
-					 mmu_get_scsi_one((char *)Cmnd->request_buffer,
-							  Cmnd->request_bufflen,
-							  qpti->qdev->my_bus));
+		Cmnd->SCp.ptr = (char *)(unsigned long)
+			sbus_map_single(qpti->sdev,
+					Cmnd->request_buffer,
+					Cmnd->request_bufflen);
 
-		cmd->dataseg[0].d_base = (u_int) ((unsigned long)Cmnd->SCp.ptr);
+		cmd->dataseg[0].d_base = (u32) ((unsigned long)Cmnd->SCp.ptr);
 		cmd->dataseg[0].d_count = Cmnd->request_bufflen;
 		cmd->segment_cnt = 1;
 	}
@@ -947,7 +1090,7 @@
 	qpti->cmd_slots[in_ptr] = Cmnd;
 
 	qpti->cmd_count[Cmnd->target]++;
-	qregs->mbox4 = in_ptr;
+	sbus_writew(in_ptr, qpti->qregs + MBOX4);
 	qpti->req_in_ptr = in_ptr;
 
 	return in_ptr;
@@ -957,9 +1100,126 @@
 {
 	/* Temporary workaround until bug is found and fixed (one bug has been found
 	   already, but fixing it makes things even worse) -jj */
-	int num_free = QLOGICISP_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr) - 64;
+	int num_free = QLOGICPTI_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr) - 64;
 	host->can_queue = host->host_busy + num_free;
-	host->sg_tablesize = QLOGICISP_MAX_SG(num_free);
+	host->sg_tablesize = QLOGICPTI_MAX_SG(num_free);
+}
+
+/*
+ * Until we scan the entire bus with inquiries, go throught this fella...
+ */
+static void ourdone(Scsi_Cmnd *Cmnd)
+{
+	struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->host->hostdata;
+	int tgt = Cmnd->target;
+	void (*done) (Scsi_Cmnd *);
+
+	/* This grot added by DaveM, blame him for ugliness.
+	 * The issue is that in the 2.3.x driver we use the
+	 * host_scribble portion of the scsi command as a
+	 * completion linked list at interrupt service time,
+	 * so we have to store the done function pointer elsewhere.
+	 */
+	done = (void (*)(Scsi_Cmnd *))
+		(((unsigned long) Cmnd->SCp.Message)
+#ifdef __sparc_v9__
+		 | ((unsigned long) Cmnd->SCp.Status << 32UL)
+#endif
+		 );
+
+	if ((qpti->sbits & (1 << tgt)) == 0) {
+		int ok = host_byte(Cmnd->result) == DID_OK;
+		if (Cmnd->cmnd[0] == 0x12 && ok) {
+			unsigned char *iqd;
+			if (Cmnd->use_sg == 0) {
+				iqd = ((unsigned char *)Cmnd->buffer);
+			} else {
+				iqd = ((struct scatterlist *) Cmnd->request_buffer)->address;
+			}
+			/* tags handled in midlayer */
+			/* enable sync mode? */
+			if (iqd[7] & 0x10) {
+				qpti->dev_param[tgt].device_flags |= 0x10;
+			} else {
+				qpti->dev_param[tgt].synchronous_offset = 0;
+				qpti->dev_param[tgt].synchronous_period = 0;
+			}
+			/* are we wide capable? */
+			if (iqd[7] & 0x20) {
+				qpti->dev_param[tgt].device_flags |= 0x20;
+			}
+			qpti->sbits |= (1 << tgt);
+		} else if (!ok) {
+			qpti->sbits |= (1 << tgt);
+		}
+	}
+	done(Cmnd);
+}
+
+int qlogicpti_queuecommand_slow(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *))
+{
+	unsigned long flags;
+	struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->host->hostdata;
+
+	/*
+	 * done checking this host adapter?
+	 * If not, then rewrite the command
+	 * to finish through ourdone so we
+	 * can peek at Inquiry data results.
+	 */
+	if (qpti->sbits && qpti->sbits != 0xffff) {
+		/* See above about in ourdone this ugliness... */
+		Cmnd->SCp.Message = ((unsigned long)done) & 0xffffffff;
+#ifdef __sparc_v9__
+		Cmnd->SCp.Status = ((unsigned long)done >> 32UL) & 0xffffffff;
+#endif
+		return qlogicpti_queuecommand(Cmnd, ourdone);
+	}
+	save_flags(flags); cli();
+
+	/*
+	 * We've peeked at all targets for this bus- time
+	 * to set parameters for devices for real now.
+	 */
+	if (qpti->sbits == 0xffff) {
+		int i;
+		for(i = 0; i < MAX_TARGETS; i++) {
+			u_short param[6];
+			param[0] = MBOX_SET_TARGET_PARAMS;
+			param[1] = (i << 8);
+			param[2] = (qpti->dev_param[i].device_flags << 8);
+			if (qpti->dev_param[i].device_flags & 0x10) {
+				param[3] = (qpti->dev_param[i].synchronous_offset << 8) |
+					qpti->dev_param[i].synchronous_period;
+			} else {
+				param[3] = 0;
+			}
+			(void) qlogicpti_mbox_command(qpti, param, 0);
+		}
+		/*
+		 * set to zero so any traverse through ourdone
+		 * doesn't start the whole process again,
+		 */
+		qpti->sbits = 0;
+	}
+
+	/* check to see if we're done with all adapters... */
+	for (qpti = qptichain; qpti != NULL; qpti = qpti->next) {
+		if (qpti->sbits) {
+			break;
+		}
+	}
+
+	/*
+	 * if we hit the end of the chain w/o finding adapters still
+	 * capability-configuring, then we're done with all adapters
+	 * and can rock on..
+	 */
+	if (qpti == NULL)
+		Cmnd->host->hostt->queuecommand = qlogicpti_queuecommand;
+
+	restore_flags(flags);
+	return qlogicpti_queuecommand(Cmnd, done);
 }
 
 /*
@@ -974,63 +1234,62 @@
 {
 	struct Scsi_Host *host = Cmnd->host;
 	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
-	struct qlogicpti_regs *qregs = qpti->qregs;
-	u_int in_ptr = qpti->req_in_ptr;
-	u_int out_ptr = qregs->mbox4;
-	struct Command_Entry *cmd = (struct Command_Entry *) &qpti->req_cpu[in_ptr];
+	struct Command_Entry *cmd;
+	unsigned long flags;
+	u_int out_ptr;
+	int in_ptr;
 
 	Cmnd->scsi_done = done;
+
+	spin_lock_irqsave(&qpti->lock, flags);
+
+	in_ptr = qpti->req_in_ptr;
+	cmd = (struct Command_Entry *) &qpti->req_cpu[in_ptr];
+	out_ptr = sbus_readw(qpti->qregs + MBOX4);
 	in_ptr = NEXT_REQ_PTR(in_ptr);
-	if(in_ptr == out_ptr) {
-		printk(KERN_EMERG "qlogicpti%d: request queue overflow\n",qpti->qpti_id);
+	if (in_ptr == out_ptr)
+		goto toss_command;
 
-		/* Unfortunately, unless you use the new EH code, which
-		 * we don't, the midlayer will ignore the return value,
-		 * which is insane.  We pick up the pieces like this.
-		 */
-		Cmnd->result = DID_BUS_BUSY;
-		done(Cmnd);
-		return 1;
-	}
-	if(qpti->send_marker) {
+	if (qpti->send_marker) {
 		marker_frob(cmd);
 		qpti->send_marker = 0;
-		if(NEXT_REQ_PTR(in_ptr) == out_ptr) {
-			qregs->mbox4 = in_ptr;
+		if (NEXT_REQ_PTR(in_ptr) == out_ptr) {
+			sbus_writew(in_ptr, qpti->qregs + MBOX4);
 			qpti->req_in_ptr = in_ptr;
-			printk(KERN_EMERG "qlogicpti%d: request queue overflow\n",
-			       qpti->qpti_id);
-
-			/* Unfortunately, unless you use the new EH code, which
-			 * we don't, the midlayer will ignore the return value,
-			 * which is insane.  We pick up the pieces like this.
-			 */
-			Cmnd->result = DID_BUS_BUSY;
-			done(Cmnd);
-			return 1;
+			goto toss_command;
 		}
 		cmd = (struct Command_Entry *) &qpti->req_cpu[in_ptr];
 		in_ptr = NEXT_REQ_PTR(in_ptr);
 	}
 	cmd_frob(cmd, Cmnd, qpti);
-	if((in_ptr = load_cmd(Cmnd, cmd, qpti, qregs, in_ptr, out_ptr)) == -1) {
-		/* Unfortunately, unless you use the new EH code, which
-		 * we don't, the midlayer will ignore the return value,
-		 * which is insane.  We pick up the pieces like this.
-		 */
-		Cmnd->result = DID_BUS_BUSY;
-		done(Cmnd);
-		return 1;
-	}
+	if ((in_ptr = load_cmd(Cmnd, cmd, qpti, in_ptr, out_ptr)) == -1)
+		goto toss_command;
+
 	update_can_queue(host, in_ptr, out_ptr);
+
+	spin_unlock_irqrestore(&qpti->lock, flags);
 	return 0;
+
+toss_command:
+	printk(KERN_EMERG "qlogicpti%d: request queue overflow\n",
+	       qpti->qpti_id);
+
+	spin_unlock_irqrestore(&qpti->lock, flags);
+
+	/* Unfortunately, unless you use the new EH code, which
+	 * we don't, the midlayer will ignore the return value,
+	 * which is insane.  We pick up the pieces like this.
+	 */
+	Cmnd->result = DID_BUS_BUSY;
+	done(Cmnd);
+	return 1;
 }
 
-static int qlogicpti_return_status(struct Status_Entry *sts)
+static int qlogicpti_return_status(struct Status_Entry *sts, int id)
 {
 	int host_status = DID_ERROR;
 
-	switch(sts->completion_status) {
+	switch (sts->completion_status) {
 	      case CS_COMPLETE:
 		host_status = DID_OK;
 		break;
@@ -1081,8 +1340,8 @@
 		host_status = DID_OK;
 		break;
 	      default:
-		printk(KERN_EMERG "qlogicpti : unknown completion status 0x%04x\n",
-		       sts->completion_status);
+		printk(KERN_EMERG "qpti%d: unknown completion status 0x%04x\n",
+		       id, sts->completion_status);
 		host_status = DID_ERROR;
 		break;
 	}
@@ -1090,22 +1349,19 @@
 	return (sts->scsi_status & STATUS_MASK) | (host_status << 16);
 }
 
-static __inline__ int qlogicpti_intr_handler(struct qlogicpti *qpti)
+static Scsi_Cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti)
 {
-	Scsi_Cmnd *Cmnd;
+	Scsi_Cmnd *Cmnd, *done_queue = NULL;
 	struct Status_Entry *sts;
 	u_int in_ptr, out_ptr;
-	struct qlogicpti_regs *qregs;
 
-	if(!(qpti->qregs->sbus_stat & SBUS_STAT_RINT))
-		return 0;
+	if (!(sbus_readw(qpti->qregs + SBUS_STAT) & SBUS_STAT_RINT))
+		return NULL;
 		
-	qregs = qpti->qregs;
-
-	in_ptr = qregs->mbox5;
-	qregs->hcctrl = HCCTRL_CRIRQ;
-	if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) {
-		switch(qregs->mbox0) {
+	in_ptr = sbus_readw(qpti->qregs + MBOX5);
+	sbus_writew(HCCTRL_CRIRQ, qpti->qregs + HCCTRL);
+	if (sbus_readw(qpti->qregs + SBUS_SEMAPHORE) & SBUS_SEMAPHORE_LCK) {
+		switch (sbus_readw(qpti->qregs + MBOX0)) {
 		case ASYNC_SCSI_BUS_RESET:
 		case EXECUTION_TIMEOUT_RESET:
 			qpti->send_marker = 1;
@@ -1115,13 +1371,13 @@
 		case COMMAND_ERROR:
 		case COMMAND_PARAM_ERROR:
 			break;
-		}
-		qregs->sbus_semaphore = 0;
+		};
+		sbus_writew(0, qpti->qregs + SBUS_SEMAPHORE);
 	}
 
 	/* This looks like a network driver! */
 	out_ptr = qpti->res_out_ptr;
-	while(out_ptr != in_ptr) {
+	while (out_ptr != in_ptr) {
 		u_int cmd_slot;
 
 		sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr];
@@ -1135,64 +1391,62 @@
 		Cmnd = qpti->cmd_slots[cmd_slot];
 		qpti->cmd_slots[cmd_slot] = NULL;
 
-		if(sts->completion_status == CS_RESET_OCCURRED ||
-		   sts->completion_status == CS_ABORTED ||
-		   (sts->status_flags & STF_BUS_RESET))
+		if (sts->completion_status == CS_RESET_OCCURRED ||
+		    sts->completion_status == CS_ABORTED ||
+		    (sts->status_flags & STF_BUS_RESET))
 			qpti->send_marker = 1;
 
-		if(sts->state_flags & SF_GOT_SENSE)
+		if (sts->state_flags & SF_GOT_SENSE)
 			memcpy(Cmnd->sense_buffer, sts->req_sense_data,
 			       sizeof(Cmnd->sense_buffer));
 
-		if(sts->hdr.entry_type == ENTRY_STATUS)
-			Cmnd->result = qlogicpti_return_status(sts);
+		if (sts->hdr.entry_type == ENTRY_STATUS)
+			Cmnd->result =
+			    qlogicpti_return_status(sts, qpti->qpti_id);
 		else
 			Cmnd->result = DID_ERROR << 16;
 
-		if(Cmnd->use_sg)
-			mmu_release_scsi_sgl((struct mmu_sglist *)
-					     Cmnd->buffer,
-					     Cmnd->use_sg - 1,
-					     qpti->qdev->my_bus);
-		else
-			mmu_release_scsi_one((__u32)((unsigned long)Cmnd->SCp.ptr),
-					     Cmnd->request_bufflen,
-					     qpti->qdev->my_bus);
-
+		if (Cmnd->use_sg) {
+			sbus_unmap_sg(qpti->sdev,
+				      (struct scatterlist *)Cmnd->buffer,
+				      Cmnd->use_sg);
+		} else {
+			sbus_unmap_single(qpti->sdev,
+					  (__u32)((unsigned long)Cmnd->SCp.ptr),
+					  Cmnd->request_bufflen);
+		}
 		qpti->cmd_count[Cmnd->target]--;
-		qregs->mbox5 = out_ptr;
-		Cmnd->scsi_done(Cmnd);
+		sbus_writew(out_ptr, qpti->qregs + MBOX5);
+		Cmnd->host_scribble = (unsigned char *) done_queue;
+		done_queue = Cmnd;
 	}
 	qpti->res_out_ptr = out_ptr;
-	return 1;
-}
-
-#ifndef __sparc_v9__
-
-static void do_qlogicpti_intr_handler_sun4m(int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long flags;
-	struct qlogicpti *qpti;
-	int again;
 
-	spin_lock_irqsave(&io_request_lock, flags);
-	do {
-		again = 0;
-		for_each_qlogicpti(qpti)
-			again |= qlogicpti_intr_handler(qpti);
-	} while (again);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	return done_queue;
 }
 
-#endif
-
-static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+static void qpti_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
+	struct qlogicpti *qpti = dev_id;
 	unsigned long flags;
+	Scsi_Cmnd *dq;
 
-	spin_lock_irqsave(&io_request_lock, flags);
-	qlogicpti_intr_handler((struct qlogicpti *)dev_id);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_lock_irqsave(&qpti->lock, flags);
+	dq = qlogicpti_intr_handler(qpti);
+	spin_unlock(&qpti->lock);
+
+	if (dq != NULL) {
+		spin_lock(&io_request_lock);
+		do {
+			Scsi_Cmnd *next;
+
+			next = (Scsi_Cmnd *) dq->host_scribble;
+			dq->scsi_done(dq);
+			dq = next;
+		} while (dq != NULL);
+		spin_unlock(&io_request_lock);
+	}
+	__restore_flags(flags);
 }
 
 int qlogicpti_abort(Scsi_Cmnd *Cmnd)
@@ -1201,20 +1455,39 @@
 	struct Scsi_Host *host = Cmnd->host;
 	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
 	int return_status = SCSI_ABORT_SUCCESS;
+	unsigned long flags;
+	u32 cmd_cookie;
+	int i;
 
 	printk(KERN_WARNING "qlogicpti : Aborting cmd for tgt[%d] lun[%d]\n",
 	       (int)Cmnd->target, (int)Cmnd->lun);
-	qlogicpti_disable_irqs(qpti->qregs);
+
+	spin_lock_irqsave(&qpti->lock, flags);
+
+	qlogicpti_disable_irqs(qpti);
+
+	/* Find the 32-bit cookie we gave to the firmware for
+	 * this command.
+	 */
+	for (i = 0; i < QLOGICPTI_REQ_QUEUE_LEN + 1; i++)
+		if (qpti->cmd_slots[i] == Cmnd)
+			break;
+	cmd_cookie = i;
+
 	param[0] = MBOX_ABORT;
 	param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun;
-	param[2] = ((unsigned int)((unsigned long)Cmnd)) >> 16;
-	param[3] = ((unsigned int)((unsigned long)Cmnd)) & 0xffff;
-	if(qlogicpti_mbox_command(qpti, param, 0) ||
-	   (param[0] != MBOX_COMMAND_COMPLETE)) {
+	param[2] = cmd_cookie >> 16;
+	param[3] = cmd_cookie & 0xffff;
+	if (qlogicpti_mbox_command(qpti, param, 0) ||
+	    (param[0] != MBOX_COMMAND_COMPLETE)) {
 		printk(KERN_EMERG "qlogicpti : scsi abort failure: %x\n", param[0]);
 		return_status = SCSI_ABORT_ERROR;
 	}
-	qlogicpti_enable_irqs(qpti->qregs);
+
+	qlogicpti_enable_irqs(qpti);
+
+	spin_unlock_irqrestore(&qpti->lock, flags);
+
 	return return_status;
 }
 
@@ -1224,17 +1497,26 @@
 	struct Scsi_Host *host = Cmnd->host;
 	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
 	int return_status = SCSI_RESET_SUCCESS;
+	unsigned long flags;
 
 	printk(KERN_WARNING "qlogicpti : Resetting SCSI bus!\n");
-	qlogicpti_disable_irqs(qpti->qregs);
+
+	spin_lock_irqsave(&qpti->lock, flags);
+
+	qlogicpti_disable_irqs(qpti);
+
 	param[0] = MBOX_BUS_RESET;
 	param[1] = qpti->host_param.bus_reset_delay;
-	if(qlogicpti_mbox_command(qpti, param, 0) ||
+	if (qlogicpti_mbox_command(qpti, param, 0) ||
 	   (param[0] != MBOX_COMMAND_COMPLETE)) {
 		printk(KERN_EMERG "qlogicisp : scsi bus reset failure: %x\n", param[0]);
 		return_status = SCSI_RESET_ERROR;
 	}
-	qlogicpti_enable_irqs(qpti->qregs);
+
+	qlogicpti_enable_irqs(qpti);
+
+	spin_unlock_irqrestore(&qpti->lock, flags);
+
 	return return_status;
 }
 
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/qlogicpti.h linux/drivers/scsi/qlogicpti.h
--- v2.3.34/linux/drivers/scsi/qlogicpti.h	Thu Nov 18 20:25:37 1999
+++ linux/drivers/scsi/qlogicpti.h	Mon Dec 20 22:06:42 1999
@@ -6,135 +6,28 @@
 #ifndef _QLOGICPTI_H
 #define _QLOGICPTI_H
 
-struct qlogicpti_regs {
-	/* SBUS control registers. */
-	volatile unsigned short  sbus_idlow;      /* SBUS ID, low bytes             */
-	volatile unsigned short  sbus_idhi;       /* SBUS ID, high bytes            */
-	volatile unsigned short  sbus_cfg0;       /* SBUS Config reg zero           */
-	volatile unsigned short  sbus_cfg1;       /* SBUS Config reg one            */
-	volatile unsigned short  sbus_ctrl;       /* SBUS Control reg               */
-	volatile unsigned short  sbus_stat;       /* SBUS Status reg                */
-	volatile unsigned short  sbus_semaphore;  /* SBUS Semaphore, p/v this...    */
-	unsigned char _unused0[18];               /* Reserved...                    */
-
-	/* Command DVMA control registers. */
-	volatile unsigned short  cmd_dma_cfg;     /* CMD DVMA Config reg            */
-	volatile unsigned short  cmd_dma_ctrl;    /* CMD DVMA Control reg           */
-	volatile unsigned short  cmd_dma_stat;    /* CMD DVMA Status reg            */
-	volatile unsigned short  cmd_dma_fstat;   /* CMD DVMA FIFO Status reg       */
-	volatile unsigned short  cmd_dma_cnt;     /* CMD DVMA Counter reg           */
-	unsigned short _unused1;                  /* Reserved...                    */
-	volatile unsigned short  cmd_dma_alow;    /* CMD DVMA Address low bytes     */
-	volatile unsigned short  cmd_dma_ahi;     /* CMD DVMA Address high bytes    */
-	unsigned char _unused2[16];               /* Reserved...                    */
-
-	/* Data DVMA control registers. */
-	volatile unsigned short  data_dma_cfg;    /* DATA DVMA Config reg           */
-	volatile unsigned short  data_dma_ctrl;   /* DATA DVMA Control reg          */
-	volatile unsigned short  data_dma_stat;   /* DATA DVMA Status reg           */
-	volatile unsigned short  data_dma_fstat;  /* DATA DVMA FIFO Status reg      */
-	volatile unsigned short  data_dma_clo;    /* DATA DVMA Counter low bytes    */
-	volatile unsigned short  data_dma_chi;    /* DATA DVMA Counter high bytes   */
-	volatile unsigned short  data_dma_alow;   /* DATA DVMA Address low bytes    */
-	volatile unsigned short  data_dma_ahi;    /* DATA DVMA Address high bytes   */
-	unsigned char _unused3[16];               /* Reserved...                    */
-
-	/* Data FIFO registers. */
-	volatile unsigned short  fcmd;            /* FIFO Command port              */
-	volatile unsigned short  fdata;           /* FIFO Data port                 */
-	unsigned char _unused4[28];               /* Reserved...                    */
-
-	/* Mailboxen. */
-	volatile unsigned short  mbox0;           /* MailBOX 0                      */
-	volatile unsigned short  mbox1;           /* MailBOX 1                      */
-	volatile unsigned short  mbox2;           /* MailBOX 2                      */
-	volatile unsigned short  mbox3;           /* MailBOX 3                      */
-	volatile unsigned short  mbox4;           /* MailBOX 4                      */
-	volatile unsigned short  mbox5;           /* MailBOX 5                      */
-	unsigned char _unused5[372];              /* Reserved...                    */
-
-	/* Scsi processor registers. */
-	volatile unsigned short  cpu_id;          /* PART ID                        */
-	volatile unsigned short  cpu_cfg1;        /* Config reg 1                   */
-	volatile unsigned short  cpu_cfg2;        /* Config reg 2                   */
-	volatile unsigned short  cpu_cfg3;        /* Config reg 3                   */
-	unsigned char _unused6[4];                /* Reserved...                    */
-	volatile unsigned short  cpu_pc;          /* Program Counter                */
-	unsigned short _unused7;                  /* Reserved...                    */
-	volatile unsigned short  cpu_rpc;         /* Return Program Counter         */
-	unsigned short _unused8;                  /* Reserved...                    */
-	volatile unsigned short  cpu_cmd;         /* Command                        */
-	unsigned short _unused9;                  /* Reserved...                    */
-	volatile unsigned short  cpu_irq;         /* IRQ status                     */
-	unsigned short _unused10;                 /* Reserved...                    */
-	volatile unsigned short  cpu_seq;         /* Sequence reg                   */
-	volatile unsigned short  cpu_gerr;        /* Gross Error reg (ESP lineage?) */
-	volatile unsigned short  cpu_exc;         /* Enable Exception reg           */
-	unsigned short _unused11;                 /* Reserved...                    */
-	volatile unsigned short  cpu_oride;       /* Override reg                   */
-	unsigned short _unused12;                 /* Reserved...                    */
-	volatile unsigned short  cpu_lbase;       /* Literal Base reg               */
-	unsigned short _unused13;                 /* Reserved...                    */
-	volatile unsigned short  cpu_uflags;      /* User Flags reg                 */
-	unsigned short _unused14;                 /* Reserved...                    */
-	volatile unsigned short  cpu_uexc;        /* User Exception reg             */
-	unsigned short _unused15;                 /* Reserved...                    */
-	volatile unsigned short  cpu_bkpt;        /* Breakpoint reg                 */
-	unsigned short _unused16[5];              /* Reserved...                    */
-	volatile unsigned short  cpu_sid;         /* SCSI ID reg                    */
-	volatile unsigned short  cpu_dcfg1;       /* Device Config 1                */
-	volatile unsigned short  cpu_dcfg2;       /* Device Config 2                */
-	unsigned short _unused17;                 /* Reserved...                    */
-	volatile unsigned short  cpu_pptr;        /* Phase Pointer                  */
-	unsigned short _unused18;                 /* Reserved...                    */
-	volatile unsigned short  cpu_bptr;        /* Buffer Pointer                 */
-	unsigned short _unused19;                 /* Reserved...                    */
-	volatile unsigned short  cpu_bcnt;        /* Buffer Counter                 */
-	volatile unsigned short  cpu_buf;         /* Buffer itself                  */
-	volatile unsigned short  cpu_bbyte;       /* Buffer Byte                    */
-	volatile unsigned short  cpu_bword;       /* Buffer Word                    */
-	unsigned short _unused20;                 /* Reserved...                    */
-	volatile unsigned short  cpu_fifo;        /* FIFO                           */
-	volatile unsigned short  cpu_fstat;       /* FIFO Status                    */
-	volatile unsigned short  cpu_ftop;        /* Top of FIFO                    */
-	volatile unsigned short  cpu_fbottom;     /* Bottom of FIFO                 */
-	unsigned short _unused21;                 /* Reserved...                    */
-	volatile unsigned short  cpu_treg;        /* Transfer reg                   */
-	unsigned short _unused22;                 /* Reserved...                    */
-	volatile unsigned short  cpu_clo;         /* Transfer Count low bytes       */
-	volatile unsigned short  cpu_chi;         /* Transfer Count high bytes      */
-	volatile unsigned short  cpu_cntlo;       /* Transfer Counter low bytes     */
-	volatile unsigned short  cpu_cnthi;       /* Transfer Counter low bytes     */
-	volatile unsigned short  cpu_adata;       /* Arbitration Data               */
-	volatile unsigned short  cpu_pctrl;       /* Pin Control                    */
-	volatile unsigned short  cpu_pdata;       /* Pin Data                       */
-	volatile unsigned short  cpu_pdiff;       /* Differential Pins              */
-	unsigned char _unused23[392];             /* Reserved...                    */
-
-	/* RISC processor registers. */
-	volatile unsigned short  risc_a;          /* Accumulator                    */
-	volatile unsigned short  risc_r[15];      /* General Purpose Registers      */
-	volatile unsigned short  risc_psr;        /* Processor Status Register      */
-	volatile unsigned short  risc_ivec;       /* Interrupt Vector               */
-	volatile unsigned short  risc_pcr;        /* Processor Control Register     */
-	volatile unsigned short  risc_raddr0;     /* RAM Addr reg 0                 */
-	volatile unsigned short  risc_raddr1;     /* RAM Addr reg 1                 */
-	volatile unsigned short  risc_lcr;        /* Loop Counter reg               */
-	volatile unsigned short  risc_pc;         /* Program Counter                */
-	volatile unsigned short  risc_mtreg;      /* Memory Timing reg              */
-	volatile unsigned short  risc_embreg;     /* External Memory Boundry reg    */
-	volatile unsigned short  risc_sp;         /* Stack Pointer                  */
-	volatile unsigned short  risc_hrev;       /* Hardware Revision              */
-	unsigned char _unused24[10];              /* Reserved...                    */
-
-	/* Generic control/command registers. */
-	volatile unsigned short  hcctrl;          /* Host cmd/control reg           */
-	volatile unsigned short  pbkpt0;          /* Processor Breakpoint 0         */
-	volatile unsigned short  pbkpt1;          /* Processor Breakpoint 1         */
-	volatile unsigned short  tcntrl;          /* Test Control reg               */
-	volatile unsigned short  tmreg;           /* Test Mode reg                  */
-};
+/* Qlogic/SBUS controller registers. */
+#define SBUS_CFG1	0x006UL
+#define SBUS_CTRL	0x008UL
+#define SBUS_STAT	0x00aUL
+#define SBUS_SEMAPHORE	0x00cUL
+#define CMD_DMA_CTRL	0x022UL
+#define DATA_DMA_CTRL	0x042UL
+#define MBOX0		0x080UL
+#define MBOX1		0x082UL
+#define MBOX2		0x084UL
+#define MBOX3		0x086UL
+#define MBOX4		0x088UL
+#define MBOX5		0x08aUL
+#define CPU_CMD		0x214UL
+#define CPU_ORIDE	0x224UL
+#define CPU_PCTRL	0x272UL
+#define CPU_PDIFF	0x276UL
+#define RISC_PSR	0x420UL
+#define RISC_MTREG	0x42EUL
+#define HCCTRL		0x440UL
 
+/* SCSI parameters for this driver. */
 #define MAX_TARGETS	16
 #define MAX_LUNS	8
 
@@ -149,8 +42,8 @@
  * requests are queued serially and the scatter/gather limit is
  * determined for each queue request anew.
  */
-#define QLOGICISP_REQ_QUEUE_LEN	255	/* must be power of two - 1 */
-#define QLOGICISP_MAX_SG(ql)	(4 + ((ql) > 0) ? 7*((ql) - 1) : 0)
+#define QLOGICPTI_REQ_QUEUE_LEN	255	/* must be power of two - 1 */
+#define QLOGICPTI_MAX_SG(ql)	(4 + ((ql) > 0) ? 7*((ql) - 1) : 0)
 
 #ifndef NULL
 #define NULL (0)
@@ -160,6 +53,7 @@
 int qlogicpti_release(struct Scsi_Host *);
 const char * qlogicpti_info(struct Scsi_Host *);
 int qlogicpti_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
+int qlogicpti_queuecommand_slow(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
 int qlogicpti_abort(Scsi_Cmnd *);
 int qlogicpti_reset(Scsi_Cmnd *, unsigned int);
 
@@ -182,15 +76,15 @@
 /* Am I fucking pedantic or what? */
 struct Entry_header {
 #ifdef __BIG_ENDIAN
-	u_char	entry_cnt;
-	u_char	entry_type;
-	u_char	flags;
-	u_char	sys_def_1;
+	u8	entry_cnt;
+	u8	entry_type;
+	u8	flags;
+	u8	sys_def_1;
 #else /* __LITTLE_ENDIAN */
-	u_char	entry_type;
-	u_char	entry_cnt;
-	u_char	sys_def_1;
-	u_char	flags;
+	u8	entry_type;
+	u8	entry_cnt;
+	u8	sys_def_1;
+	u8	flags;
 #endif
 };
 
@@ -208,26 +102,26 @@
 #define EFLAG_BAD_PAYLOAD	8
 
 struct dataseg {
-	u_int			d_base;
-	u_int			d_count;
+	u32	d_base;
+	u32	d_count;
 };
 
 struct Command_Entry {
 	struct Entry_header	hdr;
-	u_int			handle;
+	u32			handle;
 #ifdef __BIG_ENDIAN
-	u_char			target_id;
-	u_char			target_lun;
+	u8			target_id;
+	u8			target_lun;
 #else /* __LITTLE_ENDIAN */
-	u_char			target_lun;
-	u_char			target_id;
+	u8			target_lun;
+	u8			target_id;
 #endif
-	u_short			cdb_length;
-	u_short			control_flags;
-	u_short			rsvd;
-	u_short			time_out;
-	u_short			segment_cnt;
-	u_char			cdb[12];
+	u16			cdb_length;
+	u16			control_flags;
+	u16			rsvd;
+	u16			time_out;
+	u16			segment_cnt;
+	u8			cdb[12];
 	struct dataseg		dataseg[4];
 };
 
@@ -242,46 +136,46 @@
 
 struct Ext_Command_Entry {
 	struct Entry_header	hdr;
-	u_int			handle;
+	u32			handle;
 #ifdef __BIG_ENDIAN
-	u_char			target_id;
-	u_char			target_lun;
+	u8			target_id;
+	u8			target_lun;
 #else /* __LITTLE_ENDIAN */
-	u_char			target_lun;
-	u_char			target_id;
+	u8			target_lun;
+	u8			target_id;
 #endif
-	u_short			cdb_length;
-	u_short			control_flags;
-	u_short			rsvd;
-	u_short			time_out;
-	u_short			segment_cnt;
-	u_char			cdb[44];
+	u16			cdb_length;
+	u16			control_flags;
+	u16			rsvd;
+	u16			time_out;
+	u16			segment_cnt;
+	u8			cdb[44];
 };
 
 struct Continuation_Entry {
 	struct Entry_header	hdr;
-	u_int			reserved;
+	u32			reserved;
 	struct dataseg		dataseg[7];
 };
 
 struct Marker_Entry {
 	struct Entry_header	hdr;
-	u_int			reserved;
+	u32			reserved;
 #ifdef __BIG_ENDIAN
-	u_char			target_id;
-	u_char			target_lun;
+	u8			target_id;
+	u8			target_lun;
 #else /* __LITTLE_ENDIAN */
-	u_char			target_lun;
-	u_char			target_id;
+	u8			target_lun;
+	u8			target_id;
 #endif
 #ifdef __BIG_ENDIAN
-	u_char			rsvd;
-	u_char			modifier;
+	u8			rsvd;
+	u8			modifier;
 #else /* __LITTLE_ENDIAN */
-	u_char			modifier;
-	u_char			rsvd;
+	u8			modifier;
+	u8			rsvd;
 #endif
-	u_char			rsvds[52];
+	u8			rsvds[52];
 };
 
 /* marker entry modifier definitions */
@@ -291,16 +185,16 @@
 
 struct Status_Entry {
 	struct Entry_header	hdr;
-	u_int			handle;
-	u_short			scsi_status;
-	u_short			completion_status;
-	u_short			state_flags;
-	u_short			status_flags;
-	u_short			time;
-	u_short			req_sense_len;
-	u_int			residual;
-	u_char			rsvd[8];
-	u_char			req_sense_data[32];
+	u32			handle;
+	u16			scsi_status;
+	u16			completion_status;
+	u16			state_flags;
+	u16			status_flags;
+	u16			time;
+	u16			req_sense_len;
+	u32			residual;
+	u8			rsvd[8];
+	u8			req_sense_data[32];
 };
 
 /* status entry completion status definitions */
@@ -439,9 +333,9 @@
 #define RES_QUEUE_LEN		255	/* Must be power of two - 1 */
 #define QUEUE_ENTRY_LEN		64
 
-#define NEXT_REQ_PTR(wheee)   (((wheee) + 1) & QLOGICISP_REQ_QUEUE_LEN)
+#define NEXT_REQ_PTR(wheee)   (((wheee) + 1) & QLOGICPTI_REQ_QUEUE_LEN)
 #define NEXT_RES_PTR(wheee)   (((wheee) + 1) & RES_QUEUE_LEN)
-#define PREV_REQ_PTR(wheee)   (((wheee) - 1) & QLOGICISP_REQ_QUEUE_LEN)
+#define PREV_REQ_PTR(wheee)   (((wheee) - 1) & QLOGICPTI_REQ_QUEUE_LEN)
 #define PREV_RES_PTR(wheee)   (((wheee) - 1) & RES_QUEUE_LEN)
 
 struct pti_queue_entry {
@@ -451,41 +345,43 @@
 /* Software state for the driver. */
 struct qlogicpti {
 	/* These are the hot elements in the cache, so they come first. */
-	struct qlogicpti         *next;                 /* Next active adapter        */
-	struct qlogicpti_regs    *qregs;                /* Adapter registers          */
+	spinlock_t		  lock;			/* Driver mutex		      */
+	unsigned long             qregs;                /* Adapter registers          */
 	struct pti_queue_entry   *res_cpu;              /* Ptr to RESPONSE bufs (CPU) */
 	struct pti_queue_entry   *req_cpu;              /* Ptr to REQUEST bufs (CPU)  */
 
-	__u32                     res_dvma;             /* Ptr to RESPONSE bufs (DVMA)*/
-	__u32                     req_dvma;             /* Ptr to REQUEST bufs (DVMA) */
 	u_int	                  req_in_ptr;		/* index of next request slot */
 	u_int	                  res_out_ptr;		/* index of next result slot  */
+	long	                  send_marker;		/* must we send a marker?     */
+	struct sbus_dev		 *sdev;
+	unsigned long		  __pad;
 
 	int                       cmd_count[MAX_TARGETS];
 	unsigned long             tag_ages[MAX_TARGETS];
-	long	                  send_marker;		/* must we send a marker?     */
 
 	/* The cmd->handler is only 32-bits, so that things work even on monster
 	 * Ex000 sparc64 machines with >4GB of ram we just keep track of the
 	 * scsi command pointers here.  This is essentially what Matt Jacob does. -DaveM
 	 */
-	Scsi_Cmnd                *cmd_slots[QLOGICISP_REQ_QUEUE_LEN + 1];
+	Scsi_Cmnd                *cmd_slots[QLOGICPTI_REQ_QUEUE_LEN + 1];
 
 	/* The rest of the elements are unimportant for performance. */
-	u_char	                  fware_majrev, fware_minrev;
+	struct qlogicpti         *next;
+	__u32                     res_dvma;             /* Ptr to RESPONSE bufs (DVMA)*/
+	__u32                     req_dvma;             /* Ptr to REQUEST bufs (DVMA) */
+	u_char	                  fware_majrev, fware_minrev, fware_micrev;
 	struct Scsi_Host         *qhost;
-	struct linux_sbus_device *qdev;
 	int                       qpti_id;
 	int                       scsi_id;
 	int                       prom_node;
 	char                      prom_name[64];
 	int                       irq;
-	char                      differential, ultra;
+	char                      differential, ultra, clock;
 	unsigned char             bursts;
 	struct	host_param        host_param;
 	struct	dev_param         dev_param[MAX_TARGETS];
 
-	volatile unsigned char   *sreg;
+	unsigned long             sreg;
 #define SREG_TPOWER               0x80   /* State of termpwr           */
 #define SREG_FUSE                 0x40   /* State of on board fuse     */
 #define SREG_PDISAB               0x20   /* Disable state for power on */
@@ -493,14 +389,14 @@
 #define SREG_IMASK                0x0c   /* Interrupt level            */
 #define SREG_SPMASK               0x03   /* Mask for switch pack       */
 	unsigned char             swsreg;
-	unsigned char             is_pti; /* Non-zero if this is a PTI board. */
+	unsigned int	
+		gotirq	:	1,	/* this instance got an irq */
+		is_pti	: 	1,	/* Non-zero if this is a PTI board. */
+		sbits	:	16;	/* syncmode known bits */
 };
 
 /* How to twiddle them bits... */
 
-/* SBUS config register zero. */
-#define SBUS_CFG0_HREVMASK      0x000f      /* To get the revision              */
-
 /* SBUS config register one. */
 #define SBUS_CFG1_EPAR          0x0100      /* Enable parity checking           */
 #define SBUS_CFG1_FMASK         0x00f0      /* Forth code cycle mask            */
@@ -529,12 +425,6 @@
 #define SBUS_SEMAPHORE_STAT     0x0002      /* Semaphore status bit             */
 #define SBUS_SEMAPHORE_LCK      0x0001      /* Semaphore lock bit               */
 
-/* DVMA config register */
-#define DMA_CFG_DVMAENAB        0x0008      /* Enable scsi cpu --> dma data     */
-#define DMA_CFG_EIRQ            0x0004      /* Enable interrupts to risc cpu    */
-#define DMA_CFG_EBURST          0x0002      /* Enable sbus dvma bursts          */
-#define DMA_CFG_DIRECTION       0x0001      /* DMA direction (0=fifo->ram)      */
-
 /* DVMA control register */
 #define DMA_CTRL_CSUSPEND       0x0010      /* DMA channel suspend              */
 #define DMA_CTRL_CCLEAR         0x0008      /* DMA channel clear and reset      */
@@ -542,72 +432,6 @@
 #define DMA_CTRL_CIRQ           0x0002      /* DMA irq clear                    */
 #define DMA_CTRL_DMASTART       0x0001      /* DMA transfer start               */
 
-/* DVMA status register */
-#define DMA_STAT_PFULL          0x00c0      /* Pipe full                        */
-#define DMA_STAT_PORUN          0x0080      /* Pipe overrun                     */
-#define DMA_STAT_PSTG1          0x0040      /* Pipe has stage 1 loaded          */
-#define DMA_STAT_PEMPTY         0x0000      /* Pipe is empty                    */
-#define DMA_STAT_CSUSP          0x0030      /* Channel suspended                */
-#define DMA_STAT_CTRAN          0x0020      /* Channel transfer in progress     */
-#define DMA_STAT_CACTIVE        0x0010      /* Channel active                   */
-#define DMA_STAT_CIDLE          0x0000      /* Channel idle                     */
-#define DMA_STAT_SPAR           0x0008      /* SBUS parity error                */
-#define DMA_STAT_SERR           0x0004      /* SBUS dma error                   */
-#define DMA_STAT_TCNT           0x0002      /* Terminal count expired           */
-#define DMA_STAT_IRQ            0x0001      /* DMA interrupt                    */
-
-/* DVMA FIFO status register */
-#define DMA_FSTAT_ORUN          0x0200      /* FIFO overrun                     */
-#define DMA_FSTAT_URUN          0x0100      /* FIFO underrun                    */
-#define DMA_FSTAT_CMASK         0x007f      /* FIFO count mask                  */
-
-/* SCSI processor config 1 register */
-#define CPU_CFG1_ASTIME         0xf000      /* Asynchronous setup time mask     */
-#define CPU_CFG1_STUNIT         0x0000      /* Selection time unit              */
-#define CPU_CFG1_STIMEO         0x0600      /* Selection timeout value          */
-#define CPU_CFG1_CFACT          0x00e0      /* Clock factor                     */
-#define CPU_CFG1_SID            0x000f      /* SCSI ID                          */
-
-/* SCSI processor config 2 register */
-#define CPU_CFG2_FDISAB         0x0040      /* SCSI filter disable              */
-#define CPU_CFG2_ERAPUPS        0x0020      /* Req/Ack pullup enable            */
-#define CPU_CFG2_EDPUPS         0x0010      /* Data active pullup enable        */
-#define CPU_CFG2_ECAUTO         0x0008      /* Autoload device config enable    */
-#define CPU_CFG2_ERESEL         0x0002      /* Enable reselections              */
-#define CPU_CFG2_ESEL           0x0001      /* Enable selections                */
-
-/* SCSI processor interrupt register */
-#define CPU_IRQ_PERR            0x8000      /* Parity error                     */
-#define CPU_IRQ_GERR            0x4000      /* Gross error                      */
-#define CPU_IRQ_FABORT          0x2000      /* Function abort                   */
-#define CPU_IRQ_CFAIL           0x1000      /* Condition failed                 */
-#define CPU_IRQ_FEMPTY          0x0800      /* FIFO empty                       */
-#define CPU_IRQ_BCZ             0x0400      /* Byte counter is zero             */
-#define CPU_IRQ_XZ              0x0200      /* Transfer counter is zero         */
-#define CPU_IRQ_IRQ             0x0080      /* SCSI processor interrupt pending */
-#define CPU_IRQ_CRUN            0x0040      /* Command is running               */
-#define CPU_IRQ_RCODE           0x000f      /* Return code for interrupt        */
-
-/* SCSI processor gross error register */
-#define CPU_GERR_ONZ            0x0040      /* Offset not zero                  */
-#define CPU_GERR_OUF            0x0020      /* Offset underflowed               */
-#define CPU_GERR_OOF            0x0010      /* Offset overflowed                */
-#define CPU_GERR_FUF            0x0008      /* FIFO underflowed                 */
-#define CPU_GERR_FOF            0x0004      /* FIFO overflowed                  */
-#define CPU_GERR_WERR           0x0002      /* Error on write                   */
-#define CPU_GERR_ILL            0x0001      /* Instruction was illegal          */
-
-/* SCSI processor exception register */
-#define CPU_EXC_UZERO           0x8000      /* User exception zero              */
-#define CPU_EXC_UONE            0x4000      /* User exception one               */
-#define CPU_EXC_BFREE           0x0200      /* Bus free                         */
-#define CPU_EXC_TATN            0x0100      /* ATN in target mode               */
-#define CPU_EXC_RESEL           0x0080      /* Reselect exception               */
-#define CPU_EXC_SEL             0x0040      /* Selection exception              */
-#define CPU_EXC_ARB             0x0020      /* Arbitration exception            */
-#define CPU_EXC_GERR            0x0010      /* Gross error exception            */
-#define CPU_EXC_RESET           0x0008      /* Bus reset exception              */
-
 /* SCSI processor override register */
 #define CPU_ORIDE_ETRIG         0x8000      /* External trigger enable          */
 #define CPU_ORIDE_STEP          0x4000      /* Single step mode enable          */
@@ -626,38 +450,6 @@
 /* SCSI processor commands */
 #define CPU_CMD_BRESET          0x300b      /* Reset SCSI bus                   */
 
-/* SCSI processor user exception register */
-#define CPU_UEXC_ONE            0x0002      /* User exception one               */
-#define CPU_UEXC_ZERO           0x0001      /* User exception zero              */
-
-/* SCSI processor SCSI id register */
-#define CPU_SID_RSEID           0x0f00      /* Who is sel/resel'ing us          */
-#define CPU_SID_SID             0x000f      /* Selection ID                     */
-
-/* SCSI processor device config 1 */
-#define CPU_DCFG1_SHOLD         0x7000      /* Sync data hold                   */
-#define CPU_DCFG1_SSETUP        0x0f00      /* Sync data setup                  */
-#define CPU_DCFG1_SOFF          0x000f      /* Sync data offset                 */
-
-/* SCSI processor device config 2 */
-#define CPU_DCFG2_FMASK         0xf000      /* Device flags                     */
-#define CPU_DCFG2_EWIDE         0x0400      /* WIDE enable                      */
-#define CPU_DCFG2_EPAR          0x0200      /* Parity enable                    */
-#define CPU_DCFG2_EBLK          0x0100      /* Block mode transfer enable       */
-#define CPU_DCFG2_AMASK         0x0007      /* Assertion period mask            */
-
-/* SCSI processor phase pointer register */
-#define CPU_PPTR_STAT           0x1000      /* Status buf offset                */
-#define CPU_PPTR_MSGIN          0x0700      /* Msg-in buf offset                */
-#define CPU_PPTR_COM            0x00f0      /* Cmd buf offset                   */
-#define CPU_PPTR_MSGOUT         0x0007      /* Msg-out buf offset               */
-
-/* SCSI processor fifo status register */
-#define CPU_FSTAT_TFULL         0x8000      /* Top residue full                 */
-#define CPU_FSTAT_ARES          0x4000      /* Odd residue for wide transfer    */
-#define CPU_FSTAT_CMSK          0x001c      /* FIFO count mask                  */
-#define CPU_FSTAT_BRES          0x0001      /* Bottom residue full              */
-
 /* SCSI processor pin control register */
 #define CPU_PCTRL_PVALID        0x8000      /* Phase bits are valid             */
 #define CPU_PCTRL_PHI           0x0400      /* Parity bit high                  */
@@ -724,14 +516,14 @@
 	detect:		qlogicpti_detect,			   \
 	release:	qlogicpti_release,			   \
 	info:		qlogicpti_info,				   \
-	queuecommand:	qlogicpti_queuecommand,			   \
+	queuecommand:	qlogicpti_queuecommand_slow,		   \
 	abort:		qlogicpti_abort,			   \
 	reset:		qlogicpti_reset,			   \
-	can_queue:	QLOGICISP_REQ_QUEUE_LEN,		   \
+	can_queue:	QLOGICPTI_REQ_QUEUE_LEN,		   \
 	this_id:	7,					   \
-	sg_tablesize:	QLOGICISP_MAX_SG(QLOGICISP_REQ_QUEUE_LEN), \
+	sg_tablesize:	QLOGICPTI_MAX_SG(QLOGICPTI_REQ_QUEUE_LEN), \
 	cmd_per_lun:	1,					   \
-	use_clustering:	DISABLE_CLUSTERING,			   \
+	use_clustering:	ENABLE_CLUSTERING,			   \
 	use_new_eh_code: 0					   \
 }
 
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/qlogicpti_asm.c linux/drivers/scsi/qlogicpti_asm.c
--- v2.3.34/linux/drivers/scsi/qlogicpti_asm.c	Mon Mar 15 16:11:31 1999
+++ linux/drivers/scsi/qlogicpti_asm.c	Mon Dec 20 22:06:42 1999
@@ -1,2298 +1,1160 @@
-/* Version 1.24 Initiator Firmware (Aug 8, 1996) */
-
-unsigned short pti_risc_code_addr01 = 0x1000;
-
-unsigned short pti_risc_code01[] __initdata = {
-	0x0078, 0x1030, 0x0000, 0x231f, 0x0000, 0x12ff, 0x2043, 0x4f50,
+/* Version 1.31.00 ISP1000 Initiator RISC firmware */
+unsigned short sbus_risc_code01[] __initdata = {
+	0x0078, 0x1030, 0x0000, 0x2419, 0x0000, 0x12ff, 0x2043, 0x4f50,
 	0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932,
 	0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749,
 	0x4320, 0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049,
 	0x5350, 0x3130, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520,
-	0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3234, 0x2020,
+	0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3331, 0x2020,
 	0x20b9, 0x1212, 0x20c1, 0x0008, 0x2071, 0x0010, 0x70c3, 0x0004,
-	0x20c9, 0x3eff, 0x2089, 0x10c5, 0x70c7, 0x4953, 0x70cb, 0x5020,
+	0x20c9, 0x3fff, 0x2089, 0x10c8, 0x70c7, 0x4953, 0x70cb, 0x5020,
 	0x70cf, 0x2020, 0x70d3, 0x0001, 0x3f00, 0x70d6, 0x2031, 0x0030,
-	0x2079, 0x3400, 0x7863, 0x0000, 0x2fa0, 0x2009, 0x032b, 0x2011,
+	0x2079, 0x3500, 0x7863, 0x0000, 0x2fa0, 0x2009, 0x0327, 0x2011,
 	0x0000, 0x20a9, 0x0040, 0x42a4, 0x8109, 0x00c0, 0x1051, 0x789b,
 	0x0101, 0x780b, 0x0002, 0x780f, 0x0002, 0x784f, 0x0bb8, 0x2069,
-	0x3440, 0x00a8, 0x1067, 0x681b, 0x003c, 0x0078, 0x1069, 0x681b,
-	0x0028, 0x6807, 0x0007, 0x680b, 0x00fa, 0x680f, 0x0008, 0x6813,
-	0x0005, 0x681f, 0x0000, 0x6823, 0x0006, 0x6817, 0x0008, 0x6827,
-	0x0000, 0x2069, 0x3500, 0x2011, 0x0020, 0x2009, 0x0010, 0x680b,
-	0x0c19, 0x680f, 0x0019, 0x6803, 0xdd00, 0x6807, 0x001a, 0x6a1a,
-	0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, 0x8109, 0x00c0, 0x107f,
-	0x2069, 0x3580, 0x20a9, 0x0080, 0x6837, 0x0000, 0x680b, 0x0040,
-	0x6817, 0x0100, 0x681f, 0x0064, 0xade8, 0x0010, 0x0070, 0x10a2,
-	0x0078, 0x1094, 0x1078, 0x1a17, 0x1078, 0x2e4c, 0x1078, 0x1670,
-	0x1078, 0x32c0, 0x3200, 0xa085, 0x000d, 0x2090, 0x70c3, 0x0000,
-	0x0090, 0x10b9, 0x70c0, 0xa086, 0x0002, 0x00c0, 0x10b9, 0x1078,
-	0x11b8, 0x1078, 0x10e9, 0x1078, 0x17f8, 0x1078, 0x1989, 0x1078,
-	0x3187, 0x1078, 0x1766, 0x0078, 0x10b9, 0x10cd, 0x10cf, 0x1b6c,
-	0x1b6c, 0x2ea6, 0x2ea6, 0x1b6c, 0x1b6c, 0x0078, 0x10cd, 0x0078,
-	0x10cf, 0x0078, 0x10d1, 0x0078, 0x10d3, 0x7008, 0x800c, 0x00c8,
-	0x10e4, 0x7007, 0x0002, 0xa08c, 0x000c, 0x00c0, 0x10e5, 0x8004,
-	0x8004, 0x00c8, 0x10e4, 0x087a, 0x097a, 0x70c3, 0x4002, 0x0078,
-	0x11bb, 0x0068, 0x1135, 0x2061, 0x0000, 0x6018, 0xa084, 0x0001,
-	0x00c0, 0x1135, 0x7814, 0xa005, 0x00c0, 0x10fa, 0x0010, 0x1136,
-	0x0078, 0x1135, 0x2009, 0x3468, 0x2104, 0xa005, 0x00c0, 0x1135,
-	0x7814, 0xa086, 0x0001, 0x00c0, 0x1107, 0x1078, 0x1529, 0x7817,
-	0x0000, 0x2009, 0x346f, 0x2104, 0xa065, 0x0040, 0x1123, 0x2009,
-	0x346a, 0x211c, 0x8108, 0x2114, 0x8108, 0x2104, 0xa210, 0xa399,
-	0x0000, 0x2009, 0x001c, 0x6083, 0x0103, 0x1078, 0x1600, 0x00c0,
-	0x112f, 0x1078, 0x1667, 0x2009, 0x346f, 0x200b, 0x0000, 0x2009,
-	0x3469, 0x2104, 0x200b, 0x0000, 0xa005, 0x0040, 0x1133, 0x2001,
-	0x4005, 0x0078, 0x11ba, 0x0078, 0x11b8, 0x007c, 0x70c3, 0x0000,
-	0x70c7, 0x0000, 0x70cb, 0x0000, 0x70cf, 0x0000, 0x70c0, 0xa0bc,
-	0xffc0, 0x00c0, 0x1186, 0x2038, 0x0079, 0x1146, 0x11b8, 0x1203,
-	0x11d1, 0x1203, 0x1254, 0x1254, 0x11c8, 0x157f, 0x125f, 0x11c4,
-	0x11d5, 0x11d7, 0x11d9, 0x11db, 0x1584, 0x11c4, 0x1265, 0x1281,
-	0x1537, 0x1579, 0x11dd, 0x1468, 0x148a, 0x14a2, 0x14c5, 0x1421,
-	0x142f, 0x1443, 0x1457, 0x12ed, 0x11c4, 0x129d, 0x12a4, 0x12a9,
-	0x12ae, 0x12b4, 0x12b9, 0x12be, 0x12c3, 0x12c8, 0x12cc, 0x12e1,
-	0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x12f9, 0x1302, 0x1311,
-	0x1337, 0x1341, 0x1348, 0x136e, 0x137d, 0x138c, 0x139e, 0x1406,
-	0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x1416, 0xa0bc, 0xffa0,
-	0x00c0, 0x11c4, 0x2038, 0xa084, 0x001f, 0x0079, 0x118f, 0x11c4,
-	0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4,
-	0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4,
-	0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4, 0x11c4,
-	0x11c4, 0x15dc, 0x15e6, 0x15ea, 0x15f8, 0x11c4, 0x11c4, 0x72ca,
-	0x71c6, 0x2001, 0x4006, 0x0078, 0x11ba, 0x73ce, 0x72ca, 0x71c6,
-	0x2001, 0x4000, 0x70c2, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091,
-	0x5000, 0x2091, 0x4080, 0x007c, 0x70c3, 0x4001, 0x0078, 0x11bb,
-	0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078,
-	0x11b8, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, 0x11b8, 0x0078,
-	0x11b8, 0x0078, 0x11b8, 0x0078, 0x11b8, 0x2091, 0x8000, 0x70c3,
-	0x0000, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3,
-	0x0001, 0x3f00, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031,
-	0x0030, 0x2059, 0x1000, 0x2029, 0x0457, 0x2051, 0x0470, 0x2061,
-	0x0472, 0x20b9, 0xffff, 0x20c1, 0x0000, 0x2091, 0x5000, 0x2091,
-	0x4080, 0x0078, 0x0455, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0,
-	0x2098, 0x2031, 0x0030, 0x81ff, 0x0040, 0x11b8, 0x7007, 0x0004,
-	0x731a, 0x721e, 0x2051, 0x0012, 0x2049, 0x1232, 0x2041, 0x11b8,
-	0x7003, 0x0002, 0xa786, 0x0001, 0x00c0, 0x1224, 0x2049, 0x1240,
-	0x2041, 0x124c, 0x7003, 0x0003, 0x7017, 0x0000, 0x810b, 0x7112,
-	0x00c8, 0x122c, 0x7017, 0x0001, 0x7007, 0x0001, 0xa786, 0x0001,
-	0x0040, 0x1240, 0x700c, 0xa084, 0x007f, 0x8004, 0x2009, 0x0020,
-	0xa102, 0x0942, 0x094a, 0x20a8, 0x26a0, 0x53a6, 0x0078, 0x10d5,
-	0x700c, 0xa084, 0x007f, 0x0040, 0x1240, 0x80ac, 0x0048, 0x1240,
-	0x2698, 0x53a5, 0x0078, 0x10d5, 0x700c, 0xa084, 0x007f, 0x80ac,
-	0x2698, 0x53a5, 0x0078, 0x11b8, 0x71c4, 0x70c8, 0x2114, 0xa79e,
-	0x0004, 0x00c0, 0x125c, 0x200a, 0x72ca, 0x0078, 0x11b7, 0x70c7,
-	0x0001, 0x70cb, 0x0018, 0x0078, 0x11b8, 0x70c4, 0x72c8, 0x73cc,
-	0x74d0, 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x127b,
-	0x8001, 0x7872, 0x7a7a, 0x7b7e, 0x7c76, 0x7898, 0xa084, 0xfffc,
-	0x789a, 0x0078, 0x127f, 0x7898, 0xa085, 0x0001, 0x789a, 0x0078,
-	0x11b8, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce,
-	0x74d6, 0xa005, 0x0040, 0x1297, 0x8001, 0x7886, 0x7a8e, 0x7b92,
-	0x7c8a, 0x7898, 0xa084, 0xfcff, 0x789a, 0x0078, 0x129b, 0x7898,
-	0xa085, 0x0100, 0x789a, 0x0078, 0x11b8, 0x2009, 0x3459, 0x210c,
-	0x2011, 0x042c, 0x0078, 0x11b6, 0x2009, 0x3441, 0x210c, 0x0078,
-	0x11b7, 0x2009, 0x3442, 0x210c, 0x0078, 0x11b7, 0x2061, 0x3440,
-	0x610c, 0x6210, 0x0078, 0x11b6, 0x2009, 0x3445, 0x210c, 0x0078,
-	0x11b7, 0x2009, 0x3446, 0x210c, 0x0078, 0x11b7, 0x2009, 0x3447,
-	0x210c, 0x0078, 0x11b7, 0x2009, 0x3448, 0x210c, 0x0078, 0x11b7,
-	0x7908, 0x7a0c, 0x0078, 0x11b6, 0x71c4, 0x8107, 0xa084, 0x000f,
-	0x8003, 0x8003, 0x8003, 0xa0e8, 0x3500, 0x6a00, 0x6804, 0xa084,
-	0x0008, 0x0040, 0x12de, 0x6b08, 0x0078, 0x12df, 0x6b0c, 0x0078,
-	0x11b5, 0x77c4, 0x1078, 0x1681, 0x2091, 0x8000, 0x6b1c, 0x6a14,
-	0x2091, 0x8001, 0x2708, 0x0078, 0x11b5, 0x77c4, 0x1078, 0x1681,
-	0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10, 0x2091, 0x8001, 0x0078,
-	0x11b5, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b0, 0x1078, 0x1a9b,
-	0x0078, 0x11b5, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b0, 0x2011,
-	0x3441, 0x2204, 0x007e, 0x2112, 0x1078, 0x1a54, 0x017f, 0x0078,
-	0x11b7, 0x71c4, 0x2011, 0x132f, 0x20a9, 0x0008, 0x2204, 0xa106,
-	0x0040, 0x1321, 0x8210, 0x0070, 0x131f, 0x0078, 0x1316, 0x0078,
-	0x11b0, 0xa292, 0x132f, 0x027e, 0x2011, 0x3442, 0x2204, 0x2112,
-	0x017f, 0x007e, 0x1078, 0x1a60, 0x017f, 0x0078, 0x11b7, 0x03e8,
-	0x00fa, 0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061,
-	0x3440, 0x610c, 0x6210, 0x70c4, 0x600e, 0x70c8, 0x6012, 0x0078,
-	0x11b6, 0x2061, 0x3440, 0x6114, 0x70c4, 0x6016, 0x0078, 0x11b7,
-	0x71c4, 0x2011, 0x0004, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040,
-	0x1361, 0x2011, 0x0005, 0x2019, 0x1212, 0xa186, 0x0032, 0x0040,
-	0x1361, 0x2011, 0x0006, 0x2019, 0x2323, 0xa186, 0x003c, 0x00c0,
-	0x11b0, 0x2061, 0x3440, 0x6018, 0x007e, 0x611a, 0x23b8, 0x1078,
-	0x1a71, 0x1078, 0x32c0, 0x017f, 0x0078, 0x11b7, 0x71c4, 0xa184,
-	0xffcf, 0x00c0, 0x11b0, 0x2011, 0x3447, 0x2204, 0x2112, 0x007e,
-	0x1078, 0x1a93, 0x017f, 0x0078, 0x11b7, 0x71c4, 0xa182, 0x0010,
-	0x00c8, 0x11b0, 0x2011, 0x3448, 0x2204, 0x007e, 0x2112, 0x1078,
-	0x1a82, 0x017f, 0x0078, 0x11b7, 0x71c4, 0x72c8, 0xa184, 0xfffd,
-	0x00c0, 0x11af, 0xa284, 0xfffd, 0x00c0, 0x11af, 0x2100, 0x7908,
-	0x780a, 0x2200, 0x7a0c, 0x780e, 0x0078, 0x11b6, 0x71c4, 0x8107,
-	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, 0x3500, 0x2019,
-	0x0000, 0x72c8, 0x6800, 0x007e, 0xa226, 0x0040, 0x13cd, 0x6a02,
-	0xa484, 0x2000, 0x0040, 0x13b6, 0xa39d, 0x0010, 0xa484, 0x1000,
-	0x0040, 0x13bc, 0xa39d, 0x0008, 0xa484, 0x4000, 0x0040, 0x13cd,
-	0x810f, 0xa284, 0x4000, 0x0040, 0x13c9, 0x1078, 0x1ab5, 0x0078,
-	0x13cd, 0x1078, 0x1aa7, 0x0078, 0x13cd, 0x72cc, 0x82ff, 0x0040,
-	0x13ff, 0x6808, 0xa206, 0x0040, 0x13ff, 0xa2a4, 0x00ff, 0x2061,
-	0x3440, 0x6118, 0xa186, 0x0028, 0x0040, 0x13e6, 0xa186, 0x0032,
-	0x0040, 0x13ec, 0xa186, 0x003c, 0x0040, 0x13f2, 0xa482, 0x0064,
-	0x0048, 0x13fc, 0x0078, 0x13f6, 0xa482, 0x0050, 0x0048, 0x13fc,
-	0x0078, 0x13f6, 0xa482, 0x0043, 0x0048, 0x13fc, 0x71c4, 0x71c6,
-	0x027f, 0x72ca, 0x0078, 0x11b1, 0x6a0a, 0xa39d, 0x000a, 0x6804,
-	0xa305, 0x6806, 0x027f, 0x6b0c, 0x0078, 0x11b5, 0x77c4, 0x1078,
-	0x1681, 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8,
-	0x6816, 0x70cc, 0x681e, 0x2708, 0x0078, 0x11b5, 0x71c4, 0x72c8,
-	0x73cc, 0xa182, 0x0010, 0x00c8, 0x11b0, 0x1078, 0x1ac3, 0x0078,
-	0x11b5, 0x77c4, 0x1078, 0x1681, 0x2091, 0x8000, 0x6a08, 0xa295,
-	0x0002, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x11b6, 0x77c4,
-	0x1078, 0x1681, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a,
-	0x6804, 0xa005, 0x0040, 0x143e, 0x1078, 0x19f8, 0x2091, 0x8001,
-	0x2708, 0x0078, 0x11b6, 0x77c4, 0x1078, 0x1681, 0x2091, 0x8000,
-	0x6a08, 0xa295, 0x0004, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1452,
-	0x1078, 0x19f8, 0x2091, 0x8001, 0x2708, 0x0078, 0x11b6, 0x77c4,
-	0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000,
-	0x1078, 0x168e, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078, 0x11b6,
-	0x77c4, 0x72c8, 0x73cc, 0x77c6, 0x72ca, 0x73ce, 0x1078, 0x1707,
-	0x00c0, 0x1486, 0x6818, 0xa005, 0x0040, 0x1480, 0x2708, 0x1078,
-	0x1ad3, 0x00c0, 0x1480, 0x7817, 0xffff, 0x2091, 0x8001, 0x007c,
-	0x2091, 0x8001, 0x2001, 0x4005, 0x0078, 0x11ba, 0x2091, 0x8001,
-	0x0078, 0x11b8, 0x77c4, 0x77c6, 0x2061, 0x3440, 0x60a3, 0x0003,
-	0x67b6, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091,
-	0x8000, 0x1078, 0x168e, 0x2091, 0x8001, 0x7817, 0xffff, 0x1078,
-	0x19f8, 0x007c, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00,
-	0x2061, 0x3440, 0x60a3, 0x0002, 0x67b6, 0x7817, 0xffff, 0x1078,
-	0x19f8, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x2091,
-	0x8000, 0x1078, 0x168e, 0x70c8, 0x6836, 0x8738, 0xa784, 0x0007,
-	0x00c0, 0x14b9, 0x2091, 0x8001, 0x007c, 0x7898, 0xa084, 0x0003,
-	0x00c0, 0x14e9, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004,
-	0x2051, 0x0008, 0x1078, 0x1681, 0x2091, 0x8000, 0x6808, 0xa80d,
-	0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x0007, 0x00c0, 0x14d2,
-	0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0,
-	0x14d2, 0x2091, 0x8000, 0x2069, 0x0100, 0x6830, 0xa084, 0x0040,
-	0x0040, 0x1512, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084,
-	0x0004, 0x0040, 0x14ff, 0x0070, 0x14ff, 0x0078, 0x14f6, 0x684b,
-	0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040, 0x150c,
-	0x0070, 0x150c, 0x0078, 0x1503, 0x20a9, 0x00fa, 0x0070, 0x1512,
-	0x0078, 0x150e, 0x2079, 0x3400, 0x7817, 0x0001, 0x2061, 0x3440,
-	0x60a3, 0x0001, 0x60c3, 0x000f, 0x7898, 0xa085, 0x0002, 0x789a,
-	0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0046, 0x2091, 0x8001,
-	0x007c, 0x7898, 0xa084, 0xfffd, 0x789a, 0xa084, 0x0001, 0x00c0,
-	0x1533, 0x1078, 0x1749, 0x71c4, 0x71c6, 0x794a, 0x007c, 0x74c4,
-	0x73c8, 0x72cc, 0x74c6, 0x73ca, 0x72ce, 0x2079, 0x3400, 0x2009,
-	0x0040, 0x1078, 0x165e, 0x0040, 0x1575, 0x1078, 0x162e, 0x0040,
-	0x154d, 0x1078, 0x1667, 0x0078, 0x1575, 0x6010, 0x7817, 0xffff,
-	0x2009, 0x3468, 0x200b, 0x0005, 0x8108, 0x200b, 0x0000, 0x8108,
-	0x230a, 0x8108, 0x220a, 0x8108, 0x240a, 0x8108, 0x200a, 0x8108,
-	0x200b, 0x0000, 0x8108, 0x2c0a, 0xa02e, 0x2530, 0x0e7e, 0x1078,
-	0x2e25, 0x0e7f, 0x6592, 0x65a2, 0x6696, 0x66a6, 0x60ab, 0x0000,
-	0x60af, 0x0000, 0x1078, 0x19f8, 0x007c, 0x70c3, 0x4005, 0x0078,
-	0x11bb, 0x71c4, 0x70c7, 0x0000, 0x7906, 0x0078, 0x11b8, 0x71c4,
-	0x71c6, 0x2168, 0x0078, 0x1586, 0x2069, 0x1000, 0x690c, 0xa016,
-	0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, 0x1588, 0xa285, 0x0000,
-	0x00c0, 0x1596, 0x70c3, 0x4000, 0x0078, 0x1598, 0x70c3, 0x4003,
-	0x70ca, 0x0078, 0x11bb, 0x71c4, 0x72c8, 0x73cc, 0x2100, 0xa184,
-	0xfffc, 0x00c0, 0x11c4, 0x2100, 0x0079, 0x15a6, 0x15bd, 0x15d2,
-	0x15d4, 0x15d6, 0x70c3, 0x4003, 0x71ce, 0x72d2, 0x73d6, 0x0078,
-	0x15b9, 0x70c3, 0x4000, 0x70cf, 0x0000, 0x70d3, 0x0000, 0x70d7,
-	0x0000, 0x77c6, 0x71ca, 0x0078, 0x11b8, 0x2031, 0x15d8, 0x2624,
-	0x8630, 0x2412, 0x2204, 0xa446, 0x00c0, 0x15aa, 0xa484, 0xffff,
-	0x00c0, 0x15bf, 0x2031, 0x15d8, 0x8210, 0x8319, 0xa384, 0xffff,
-	0x00c0, 0x15bf, 0x0078, 0x15b1, 0x0078, 0x15b1, 0x0078, 0x15b1,
-	0x5555, 0xaaaa, 0xffff, 0x0000, 0x7960, 0x71c6, 0x71c4, 0xa182,
-	0x0003, 0x00c8, 0x11b0, 0x7962, 0x0078, 0x11b8, 0x7960, 0x71c6,
-	0x0078, 0x11b8, 0x7954, 0x71c6, 0x71c4, 0x7956, 0x7958, 0x71ca,
-	0x71c8, 0x795a, 0x795c, 0x71ce, 0x71cc, 0x795e, 0x0078, 0x11b8,
-	0x7954, 0x71c6, 0x7958, 0x71ca, 0x795c, 0x71ce, 0x0078, 0x11b8,
-	0x700c, 0xa084, 0x007f, 0x0040, 0x160c, 0x7007, 0x0004, 0x7004,
-	0xa084, 0x0004, 0x00c0, 0x1607, 0x7017, 0x0000, 0x7112, 0x721a,
-	0x731e, 0x8108, 0x810c, 0x81a9, 0x8c98, 0x20a1, 0x0030, 0x6080,
-	0x20a2, 0x53a6, 0x780c, 0xa085, 0x0000, 0x7002, 0x7007, 0x0001,
-	0x7108, 0x8104, 0x00c8, 0x1620, 0x7007, 0x0002, 0xa184, 0x000c,
-	0x710c, 0xa184, 0x0300, 0x7003, 0x0000, 0x007c, 0x700c, 0xa084,
-	0x007f, 0x0040, 0x163a, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
-	0x00c0, 0x1635, 0x7017, 0x0000, 0x7112, 0x721a, 0x731e, 0x2099,
-	0x0030, 0x8108, 0x81ac, 0x780c, 0xa085, 0x0001, 0x7002, 0x7007,
-	0x0001, 0x7008, 0x800c, 0x00c8, 0x1649, 0x7007, 0x0002, 0xa08c,
-	0x000c, 0x00c0, 0x165b, 0x710c, 0xa184, 0x0300, 0x00c0, 0x165b,
-	0x2ca0, 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, 0x7850, 0xa065,
-	0x0040, 0x1666, 0x2c04, 0x7852, 0x2063, 0x0000, 0x007c, 0x0f7e,
-	0x2079, 0x3400, 0x7850, 0x2062, 0x2c00, 0x7852, 0x0f7f, 0x007c,
-	0x2011, 0x3f00, 0x7a52, 0x2019, 0x042c, 0x8319, 0x0040, 0x167e,
-	0xa280, 0x002e, 0x2012, 0x2010, 0x0078, 0x1675, 0x2013, 0x0000,
-	0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, 0x0007, 0x8003, 0x8003,
-	0x8003, 0x8003, 0xa105, 0xa0e8, 0x3580, 0x007c, 0x1078, 0x1681,
-	0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xffef, 0xa80d,
-	0x690a, 0x2009, 0x344f, 0x210c, 0x6804, 0xa005, 0x0040, 0x16ab,
-	0xa116, 0x00c0, 0x16ab, 0x2060, 0x6000, 0x6806, 0x017e, 0x200b,
-	0x0000, 0x0078, 0x16ae, 0x2009, 0x0000, 0x017e, 0x6804, 0xa065,
-	0x0040, 0x16bd, 0x6000, 0x6806, 0x1078, 0x16ce, 0x1078, 0x17ac,
-	0x6810, 0x8001, 0x6812, 0x00c0, 0x16ae, 0x017f, 0x6902, 0x6906,
-	0x007c, 0xa065, 0x0040, 0x16cd, 0x6098, 0x609b, 0x0000, 0x2008,
-	0x1078, 0x1667, 0x2100, 0x0078, 0x16c1, 0x007c, 0x6003, 0x0103,
-	0x20a9, 0x001c, 0xac80, 0x0004, 0x20a0, 0x2001, 0x0000, 0x40a4,
-	0x6828, 0x6016, 0x682c, 0x601e, 0x007c, 0x0e7e, 0x2071, 0x3440,
-	0x7040, 0xa08c, 0x0080, 0x00c0, 0x16eb, 0xa088, 0x3480, 0x2d0a,
-	0x8000, 0x7042, 0xa006, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x3440,
-	0x2009, 0x3480, 0x7240, 0x8221, 0x8211, 0x0048, 0x1705, 0x2104,
-	0x8108, 0xad06, 0x00c0, 0x16f4, 0x8119, 0x211e, 0x8108, 0x8318,
-	0x8211, 0x00c8, 0x16fd, 0x7442, 0xa006, 0x0e7f, 0x007c, 0x1078,
-	0x1681, 0x2091, 0x8000, 0x6804, 0x781e, 0xa065, 0x0040, 0x1748,
-	0x0078, 0x1718, 0x2c00, 0x781e, 0x6000, 0xa065, 0x0040, 0x1748,
-	0x600c, 0xa306, 0x00c0, 0x1712, 0x6008, 0xa206, 0x00c0, 0x1712,
-	0x2c28, 0x6804, 0xac06, 0x00c0, 0x172f, 0x6000, 0x2060, 0x6806,
-	0xa005, 0x00c0, 0x172f, 0x6803, 0x0000, 0x0078, 0x1739, 0x6400,
-	0x781c, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1739, 0x2c00,
-	0x6802, 0x2560, 0x1078, 0x16ce, 0x6017, 0x0005, 0x601f, 0x0020,
-	0x1078, 0x17ac, 0x6810, 0x8001, 0x6812, 0x2001, 0xffff, 0xa005,
-	0x007c, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051,
-	0x0008, 0x2091, 0x8000, 0x1078, 0x168e, 0x8738, 0xa784, 0x0007,
-	0x00c0, 0x1753, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784,
-	0x0f00, 0x00c0, 0x1753, 0x2091, 0x8001, 0x007c, 0x2061, 0x0000,
-	0x6018, 0xa084, 0x0001, 0x00c0, 0x1773, 0x78ac, 0x78af, 0x0000,
-	0xa005, 0x00c0, 0x1774, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x177a,
-	0x1078, 0x1b4e, 0x0079, 0x177c, 0x178c, 0x178e, 0x1794, 0x1798,
-	0x178c, 0x179c, 0x178c, 0x178c, 0x178c, 0x178c, 0x17a2, 0x17a6,
-	0x178c, 0x178c, 0x178c, 0x178c, 0x1078, 0x1b4e, 0x1078, 0x1749,
-	0x2001, 0x8001, 0x0078, 0x11ba, 0x2001, 0x8003, 0x0078, 0x11ba,
-	0x2001, 0x8004, 0x0078, 0x11ba, 0x1078, 0x1749, 0x2001, 0x8006,
-	0x0078, 0x11ba, 0x2001, 0x800c, 0x0078, 0x11ba, 0x1078, 0x1749,
-	0x2001, 0x800d, 0x0078, 0x11ba, 0x2c04, 0x6082, 0x2c08, 0x2063,
-	0x0000, 0x7864, 0x8000, 0x7866, 0x7868, 0xa005, 0x796a, 0x0040,
-	0x17bc, 0x2c02, 0x0078, 0x17bd, 0x796e, 0x007c, 0x0c7e, 0x2061,
-	0x3400, 0x6883, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6064, 0x8000,
-	0x6066, 0x6068, 0xa005, 0x616a, 0x0040, 0x17d1, 0x2d02, 0x0078,
-	0x17d2, 0x616e, 0x0c7f, 0x007c, 0x1078, 0x17e5, 0x0040, 0x17e4,
-	0x0c7e, 0x6098, 0xa065, 0x0040, 0x17df, 0x1078, 0x16c1, 0x0c7f,
-	0x609b, 0x0000, 0x1078, 0x1667, 0x007c, 0x786c, 0xa065, 0x0040,
-	0x17f7, 0x2091, 0x8000, 0x7864, 0x8001, 0x7866, 0x2c04, 0x786e,
-	0xa005, 0x00c0, 0x17f5, 0x786a, 0x8000, 0x2091, 0x8001, 0x007c,
-	0x7898, 0xa005, 0x00c0, 0x1846, 0x7974, 0x70d0, 0x0005, 0x0005,
-	0x72d0, 0xa206, 0x00c0, 0x17fd, 0x2200, 0xa106, 0x00c0, 0x1814,
-	0x7804, 0xa005, 0x0040, 0x1846, 0x7807, 0x0000, 0x0068, 0x1846,
-	0x2091, 0x4080, 0x0078, 0x1846, 0x1078, 0x165e, 0x0040, 0x1846,
-	0x7a7c, 0x7b78, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399, 0x0000,
-	0x2009, 0x0040, 0x1078, 0x162e, 0x0040, 0x183d, 0x1078, 0x1667,
-	0x7880, 0x8000, 0x7882, 0xa086, 0x0002, 0x00c0, 0x1846, 0x2091,
-	0x8000, 0x78af, 0x0002, 0x7883, 0x0000, 0x7898, 0xa085, 0x0003,
-	0x789a, 0x2091, 0x8001, 0x0078, 0x1846, 0x7883, 0x0000, 0x1078,
-	0x1973, 0x6000, 0xa084, 0x0007, 0x0079, 0x1847, 0x007c, 0x184f,
-	0x185e, 0x187e, 0x184f, 0x1890, 0x184f, 0x184f, 0x184f, 0x2039,
-	0x0400, 0x78a8, 0xa705, 0x78aa, 0x6004, 0xa705, 0x6006, 0x1078,
-	0x18ce, 0x6018, 0x78a6, 0x1078, 0x195b, 0x007c, 0x78a8, 0xa084,
-	0x0100, 0x0040, 0x1865, 0x0078, 0x184f, 0x78ab, 0x0000, 0x6000,
-	0x8007, 0xa084, 0x00ff, 0x789e, 0x8001, 0x609b, 0x0000, 0x0040,
-	0x187b, 0x1078, 0x18ce, 0x0040, 0x187b, 0x78a8, 0xa085, 0x0100,
-	0x78aa, 0x0078, 0x187d, 0x1078, 0x18f2, 0x007c, 0x78a8, 0xa08c,
-	0x0e00, 0x00c0, 0x1887, 0xa084, 0x0100, 0x00c0, 0x1889, 0x0078,
-	0x184f, 0x1078, 0x18ce, 0x00c0, 0x188f, 0x1078, 0x18f2, 0x007c,
-	0x78a8, 0xa084, 0x0100, 0x0040, 0x1897, 0x0078, 0x184f, 0x78ab,
-	0x0000, 0x6710, 0x20a9, 0x0001, 0x6014, 0xa084, 0x00ff, 0xa005,
-	0x0040, 0x18b4, 0xa7bc, 0xff00, 0x20a9, 0x0008, 0xa08e, 0x0001,
-	0x0040, 0x18b4, 0x2039, 0x0000, 0x20a9, 0x0080, 0xa08e, 0x0002,
-	0x0040, 0x18b4, 0x0078, 0x18cb, 0x1078, 0x1681, 0x2d00, 0x2091,
-	0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde,
-	0x680a, 0x2d00, 0xa080, 0x0010, 0x2068, 0x2091, 0x8001, 0x0070,
-	0x18cb, 0x0078, 0x18b7, 0x1078, 0x1667, 0x007c, 0x78a0, 0xa06d,
-	0x00c0, 0x18d9, 0x2c00, 0x78a2, 0x78a6, 0x609b, 0x0000, 0x0078,
-	0x18e5, 0x2c00, 0x689a, 0x609b, 0x0000, 0x78a2, 0x2d00, 0x6002,
-	0x78a4, 0xad06, 0x00c0, 0x18e5, 0x6002, 0x789c, 0x8001, 0x789e,
-	0x00c0, 0x18f1, 0x78a8, 0xa084, 0x0000, 0x78aa, 0x78a4, 0x2060,
-	0xa006, 0x007c, 0xa02e, 0x2530, 0x6118, 0xa184, 0x0060, 0x619e,
-	0x0040, 0x18fe, 0x0e7e, 0x1078, 0x2e25, 0x0e7f, 0x6592, 0x65a2,
-	0x6696, 0x66a6, 0x60ab, 0x0000, 0x60af, 0x0000, 0x6710, 0x1078,
-	0x1681, 0x2091, 0x8000, 0x6808, 0xa084, 0x0001, 0x0040, 0x1920,
-	0x2091, 0x8001, 0x1078, 0x16ce, 0x2091, 0x8000, 0x1078, 0x17ac,
-	0x2091, 0x8001, 0x78a3, 0x0000, 0x78a7, 0x0000, 0x0078, 0x195a,
-	0x6020, 0xa096, 0x0001, 0x00c0, 0x1927, 0x8000, 0x6022, 0x6a10,
-	0x6814, 0x2091, 0x8001, 0xa202, 0x0048, 0x1936, 0x0040, 0x1936,
-	0x2039, 0x0200, 0x1078, 0x195b, 0x0078, 0x195a, 0x2c08, 0x2091,
-	0x8000, 0x6800, 0xa065, 0x0040, 0x193e, 0x6102, 0x6902, 0x00c0,
-	0x1942, 0x6906, 0x2160, 0x6003, 0x0000, 0x6810, 0x8000, 0x6812,
-	0x2091, 0x8001, 0x6808, 0xa08c, 0x0040, 0x0040, 0x1954, 0xa086,
-	0x0040, 0x680a, 0x1078, 0x16dd, 0x1078, 0x19f8, 0x78a7, 0x0000,
-	0x78a3, 0x0000, 0x007c, 0x6004, 0xa705, 0x6006, 0x2091, 0x8000,
-	0x1078, 0x17ac, 0x2091, 0x8001, 0x78a4, 0xa065, 0x0040, 0x196e,
-	0x6098, 0x78a6, 0x609b, 0x0000, 0x0078, 0x195e, 0x78a3, 0x0000,
-	0x78a7, 0x0000, 0x007c, 0x7970, 0x7874, 0x8000, 0xa10a, 0x00c8,
-	0x197a, 0xa006, 0x7876, 0x70d2, 0x7804, 0xa005, 0x0040, 0x1988,
-	0x8001, 0x7806, 0x00c0, 0x1988, 0x0068, 0x1988, 0x2091, 0x4080,
-	0x007c, 0x0068, 0x19a1, 0x2029, 0x0000, 0x786c, 0xa065, 0x0040,
-	0x199c, 0x1078, 0x19a2, 0x0040, 0x199c, 0x1078, 0x19b8, 0x00c0,
-	0x199c, 0x8528, 0x0078, 0x198d, 0x85ff, 0x0040, 0x19a1, 0x2091,
-	0x4080, 0x007c, 0x7b84, 0x7988, 0x72d4, 0x0005, 0x0005, 0x70d4,
-	0xa206, 0x00c0, 0x19a4, 0x2200, 0xa102, 0x00c0, 0x19b2, 0x2300,
-	0xa005, 0x007c, 0x0048, 0x19b6, 0xa302, 0x007c, 0x8002, 0x007c,
-	0x1078, 0x19ea, 0x2009, 0x001c, 0x6024, 0xa005, 0x0040, 0x19c2,
-	0x2009, 0x0040, 0x1078, 0x1600, 0x0040, 0x19db, 0x7894, 0x8000,
-	0x7896, 0xa086, 0x0002, 0x00c0, 0x19e9, 0x2091, 0x8000, 0x78af,
-	0x0003, 0x7897, 0x0000, 0x7898, 0xa085, 0x0300, 0x789a, 0x2091,
-	0x8001, 0x0078, 0x19e9, 0x7897, 0x0000, 0x1078, 0x17d4, 0x7984,
-	0x7888, 0x8000, 0xa10a, 0x00c8, 0x19e6, 0xa006, 0x788a, 0x70d6,
-	0xa006, 0x007c, 0x8107, 0x8004, 0x8004, 0x7a90, 0x7b8c, 0xa210,
-	0xa399, 0x0000, 0x007c, 0x2009, 0x3468, 0x2091, 0x8000, 0x200a,
-	0x0f7e, 0x2079, 0x0100, 0x2009, 0x3440, 0x2091, 0x8000, 0x2104,
-	0xa086, 0x0000, 0x00c0, 0x1a13, 0x2009, 0x3412, 0x2104, 0xa005,
-	0x00c0, 0x1a13, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x1a13, 0x0018,
-	0x1a13, 0x781b, 0x0044, 0x2091, 0x8001, 0x0f7f, 0x007c, 0x127e,
-	0x2091, 0x2300, 0x2071, 0x3440, 0x2079, 0x0100, 0x2019, 0x2d1f,
-	0x20a1, 0x012b, 0x2304, 0xa005, 0x0040, 0x1a2f, 0x789a, 0x8318,
-	0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318, 0x0078, 0x1a22, 0x789b,
-	0x0020, 0x20a9, 0x0010, 0x78af, 0x0000, 0x78af, 0x0220, 0x0070,
-	0x1a3b, 0x0078, 0x1a33, 0x7003, 0x0000, 0x1078, 0x1b3a, 0x7004,
-	0xa084, 0x000f, 0xa085, 0x6280, 0x7806, 0x780f, 0x9200, 0x7843,
-	0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, 0x7047, 0x347f, 0x7043,
-	0x0000, 0x127f, 0x2000, 0x007c, 0xa18c, 0x000f, 0x2011, 0x0101,
-	0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x1078, 0x1b3a, 0x007c,
-	0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x0070, 0x1a69, 0x0078,
-	0x1a64, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012,
-	0x007c, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x0070, 0x1a7a,
-	0x0078, 0x1a75, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205,
-	0x200a, 0x007c, 0x2011, 0x0101, 0x20a9, 0x000c, 0x810b, 0x0070,
-	0x1a8b, 0x0078, 0x1a86, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff,
-	0xa105, 0x2012, 0x007c, 0x2011, 0x0102, 0x2204, 0xa084, 0xffcf,
-	0xa105, 0x2012, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e,
-	0x2061, 0x0100, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x8103,
-	0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4,
-	0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080,
-	0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa085, 0x0020,
-	0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e,
-	0x2061, 0x0100, 0x609a, 0x60a4, 0x62ae, 0x2010, 0x60a4, 0x63ae,
-	0x2018, 0x0c7f, 0x007c, 0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040,
-	0x1b16, 0x2061, 0x3e80, 0x1078, 0x1b1c, 0x0040, 0x1b04, 0x20a9,
-	0x0000, 0x2061, 0x3d80, 0x0c7e, 0x1078, 0x1b1c, 0x0040, 0x1af0,
-	0x0c7f, 0x8c60, 0x0070, 0x1aee, 0x0078, 0x1ae3, 0x0078, 0x1b16,
-	0x007f, 0xa082, 0x3d80, 0x2071, 0x3440, 0x70ba, 0x601c, 0xa085,
-	0x0800, 0x601e, 0x2091, 0x8001, 0x71b6, 0x2001, 0x0004, 0x70a2,
-	0x1078, 0x19f3, 0x0078, 0x1b12, 0x2071, 0x3440, 0x601c, 0xa085,
-	0x0800, 0x601e, 0x2091, 0x8001, 0x71b6, 0x2001, 0x0006, 0x70a2,
-	0x1078, 0x19f3, 0x2001, 0x0000, 0x0078, 0x1b18, 0x2001, 0x0001,
-	0xa005, 0x0e7f, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x2c04, 0xa005,
-	0x0040, 0x1b35, 0x2060, 0x600c, 0xa306, 0x00c0, 0x1b32, 0x6008,
-	0xa206, 0x00c0, 0x1b32, 0x6010, 0xa106, 0x00c0, 0x1b32, 0xa006,
-	0x0078, 0x1b39, 0x6000, 0x0078, 0x1b1f, 0xa085, 0x0001, 0x2091,
-	0x8001, 0x007c, 0x2011, 0x3441, 0x220c, 0xa18c, 0x000f, 0x2011,
-	0x013b, 0x2204, 0xa084, 0x0100, 0x0040, 0x1b4d, 0x2019, 0x0112,
-	0x201b, 0x1000, 0x2021, 0xff80, 0x2122, 0x007c, 0x0068, 0x1b4e,
-	0x007e, 0x2071, 0x0000, 0x7018, 0xa084, 0x0001, 0x00c0, 0x1b53,
-	0x007f, 0x2e08, 0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3,
-	0x8002, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x007f,
-	0x2070, 0x007f, 0x0078, 0x1b6a, 0x107e, 0x007e, 0x127e, 0x2091,
-	0x2300, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0xa594, 0x003f, 0xa484,
-	0x4000, 0x0040, 0x1b81, 0xa784, 0x007c, 0x00c0, 0x2ceb, 0x1078,
-	0x1b4e, 0xa49c, 0x000f, 0xa382, 0x0004, 0x0050, 0x1b89, 0x1078,
-	0x1b4e, 0x8507, 0xa084, 0x000f, 0x0079, 0x1b8e, 0x1f8e, 0x202f,
-	0x2055, 0x226e, 0x24d4, 0x251c, 0x2555, 0x25d0, 0x262a, 0x26ae,
-	0x1bb4, 0x1b9e, 0x1df7, 0x1ec1, 0x24b3, 0x1b9e, 0x1078, 0x1b4e,
-	0x0018, 0x1b71, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c,
-	0x7003, 0x0000, 0x703f, 0x0000, 0x7030, 0xa005, 0x0040, 0x1bb2,
-	0x7033, 0x0000, 0x0018, 0x1b71, 0x705c, 0xa005, 0x00c0, 0x1c5b,
-	0x70a0, 0xa084, 0x0007, 0x0079, 0x1bbd, 0x1c7a, 0x1bc5, 0x1bd3,
-	0x1bf4, 0x1c1a, 0x1c46, 0x1c44, 0x1bc5, 0x7808, 0xa084, 0xfffd,
-	0x780a, 0x2009, 0x0046, 0x1078, 0x2393, 0x00c0, 0x1bd1, 0x7003,
-	0x0004, 0x0078, 0x1ba0, 0x1078, 0x2cad, 0x00c0, 0x1bf2, 0x70b4,
-	0x8007, 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, 0x78ab, 0x000c,
-	0x789b, 0x0060, 0x78ab, 0x0001, 0x785b, 0x0004, 0x2009, 0x00f7,
-	0x1078, 0x2391, 0x00c0, 0x1bf2, 0x7003, 0x0004, 0x70c3, 0x000f,
-	0x7033, 0x3470, 0x0078, 0x1ba0, 0x1078, 0x2cad, 0x00c0, 0x1c18,
-	0x71b4, 0x8107, 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, 0xa18c,
-	0x0007, 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060,
-	0x78ab, 0x0002, 0x785b, 0x0004, 0x2009, 0x00f7, 0x1078, 0x2391,
-	0x00c0, 0x1c18, 0x7003, 0x0004, 0x70c3, 0x000f, 0x7033, 0x3470,
-	0x0078, 0x1ba0, 0x1078, 0x2cad, 0x00c0, 0x1c42, 0x71b4, 0x8107,
-	0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d,
-	0x00c0, 0x79aa, 0x78ab, 0x0020, 0x71b8, 0x79aa, 0x78ab, 0x000d,
-	0x789b, 0x0060, 0x78ab, 0x0004, 0x785b, 0x0004, 0x2009, 0x00f7,
-	0x1078, 0x2391, 0x00c0, 0x1c42, 0x7003, 0x0004, 0x70c3, 0x000f,
-	0x7033, 0x3470, 0x0078, 0x1ba0, 0x0078, 0x1bf4, 0x1078, 0x2cad,
-	0x00c0, 0x1ba0, 0x70bc, 0x2068, 0x789b, 0x0010, 0x6810, 0xa084,
-	0x0007, 0xa085, 0x0080, 0x78aa, 0x6e18, 0x2041, 0x0001, 0x2001,
-	0x0004, 0x0078, 0x1d82, 0x1078, 0x2cad, 0x00c0, 0x1ba0, 0x789b,
-	0x0010, 0x705c, 0x2068, 0x6f10, 0x1078, 0x2bfc, 0x6008, 0xa085,
-	0x0010, 0x600a, 0x6810, 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa,
-	0x2031, 0x0020, 0x2041, 0x0001, 0x1078, 0x2d0c, 0x2001, 0x0003,
-	0x0078, 0x1d6d, 0x0018, 0x1b71, 0x7440, 0xa485, 0x0000, 0x0040,
-	0x1c94, 0xa080, 0x3480, 0x2030, 0x7144, 0x8108, 0xa12a, 0x0048,
-	0x1c8b, 0x2009, 0x3480, 0x2164, 0x6504, 0x85ff, 0x00c0, 0x1ca1,
-	0x8421, 0x00c0, 0x1c85, 0x7146, 0x7003, 0x0000, 0x703f, 0x0000,
-	0x0078, 0x1ba0, 0x7640, 0xa6b0, 0x3480, 0x7144, 0x2600, 0x0078,
-	0x1c90, 0x7146, 0x2568, 0x2558, 0x753e, 0x2c50, 0x6034, 0xa085,
-	0x0000, 0x00c0, 0x1c9e, 0x6708, 0x7736, 0xa784, 0x013f, 0x0040,
-	0x1cd3, 0xa784, 0x0021, 0x00c0, 0x1c9e, 0xa784, 0x0002, 0x0040,
-	0x1cc0, 0xa784, 0x0004, 0x0040, 0x1c9e, 0xa7bc, 0xfffb, 0x670a,
-	0xa784, 0x0008, 0x00c0, 0x1c9e, 0xa784, 0x0010, 0x00c0, 0x1c9e,
-	0xa784, 0x0100, 0x0040, 0x1cd3, 0x6018, 0xa005, 0x00c0, 0x1c9e,
-	0xa7bc, 0xfeff, 0x670a, 0x681f, 0x0000, 0x6e18, 0xa684, 0x000e,
-	0x6118, 0x0040, 0x1ce3, 0x601c, 0xa102, 0x0048, 0x1ce6, 0x0040,
-	0x1ce6, 0x0078, 0x1c9a, 0x81ff, 0x00c0, 0x1c9a, 0xa784, 0x0080,
-	0x00c0, 0x1cec, 0x700c, 0x6022, 0xa7bc, 0xff7f, 0x670a, 0x6b10,
-	0x8307, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3500,
-	0x2060, 0x2048, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x2a60,
-	0x0018, 0x1b71, 0x789b, 0x0010, 0xa046, 0x1078, 0x2cad, 0x00c0,
-	0x1ba0, 0x6b10, 0xa39c, 0x0007, 0xa39d, 0x00c0, 0x704c, 0xa084,
-	0x8000, 0x0040, 0x1d17, 0xa684, 0x0001, 0x0040, 0x1d19, 0xa39c,
-	0xffbf, 0xa684, 0x0010, 0x0040, 0x1d1f, 0xa39d, 0x0020, 0x7baa,
-	0x8840, 0xa684, 0x000e, 0x00c0, 0x1d2a, 0xa7bd, 0x0010, 0x670a,
-	0x0078, 0x1d6b, 0x714c, 0xa18c, 0x0800, 0x0040, 0x2870, 0x2011,
-	0x0021, 0x8004, 0x8004, 0x0048, 0x1d41, 0x2011, 0x0022, 0x8004,
-	0x0048, 0x1d41, 0x2011, 0x0020, 0x8004, 0x0048, 0x1d41, 0x0040,
-	0x1d6b, 0x7aaa, 0x8840, 0x1078, 0x2cc6, 0x6a10, 0x610c, 0x8108,
-	0xa18c, 0x00ff, 0xa1e0, 0x3d80, 0x2c64, 0x8cff, 0x0040, 0x1d62,
-	0x6010, 0xa206, 0x00c0, 0x1d4c, 0x60b4, 0x8001, 0x60b6, 0x00c0,
-	0x1d47, 0x0c7e, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x0c7f,
-	0x0078, 0x1c7a, 0x1078, 0x2cad, 0x00c0, 0x1ba0, 0x2a60, 0x610e,
-	0x79aa, 0x8840, 0x712e, 0x2001, 0x0001, 0x007e, 0x7150, 0xa184,
-	0x0018, 0x0040, 0x1d81, 0xa184, 0x0010, 0x0040, 0x1d7b, 0x1078,
-	0x2a33, 0x00c0, 0x1d81, 0xa184, 0x0008, 0x0040, 0x1d81, 0x1078,
-	0x294d, 0x007f, 0x7002, 0xa68c, 0x0060, 0x88ff, 0x0040, 0x1d8a,
-	0xa18d, 0x0004, 0x795a, 0x69b2, 0x789b, 0x0060, 0x2800, 0x78aa,
-	0x789b, 0x0061, 0x6814, 0xa085, 0x8000, 0x6816, 0x78aa, 0x157e,
-	0x137e, 0x147e, 0x20a1, 0x012c, 0x789b, 0x0000, 0x8000, 0x80ac,
-	0xad80, 0x000a, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6810,
-	0x8007, 0x789b, 0x007e, 0x78aa, 0x6d90, 0x7dd6, 0x7dde, 0x6e94,
-	0x7ed2, 0x7eda, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x1db9, 0x0098,
-	0x1dc1, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x2cc6, 0x0078,
-	0x1ba8, 0x7200, 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x1dce,
-	0x781b, 0x0049, 0x1078, 0x2cc6, 0x0078, 0x1ddf, 0x6ab0, 0xa295,
-	0x2000, 0x7a5a, 0x781b, 0x0049, 0x1078, 0x2cc6, 0x7200, 0x2500,
-	0xa605, 0x0040, 0x1ddf, 0xa284, 0x0007, 0x1079, 0x1ded, 0xad80,
-	0x0008, 0x7032, 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x1deb,
-	0x6018, 0x8000, 0x601a, 0x0078, 0x1ba0, 0x1df5, 0x2ffc, 0x2ffc,
-	0x2feb, 0x2ffc, 0x1df5, 0x1df5, 0x1df5, 0x1078, 0x1b4e, 0x7808,
-	0xa084, 0xfffd, 0x780a, 0x0f7e, 0x2079, 0x3400, 0x7898, 0x0f7f,
-	0xa084, 0x0001, 0x0040, 0x1e1d, 0x70a0, 0xa086, 0x0001, 0x00c0,
-	0x1e0c, 0x70a2, 0x0078, 0x1ea5, 0x70a0, 0xa086, 0x0005, 0x00c0,
-	0x1e1b, 0x70bc, 0x2068, 0x6817, 0x0004, 0x6813, 0x0000, 0x681c,
-	0xa085, 0x0008, 0x681e, 0x70a3, 0x0000, 0x157e, 0x2011, 0x0004,
-	0x71a0, 0xa186, 0x0001, 0x0040, 0x1e3f, 0xa186, 0x0007, 0x00c0,
-	0x1e2f, 0x2009, 0x342b, 0x200b, 0x0005, 0x0078, 0x1e3f, 0x2009,
-	0x3413, 0x2104, 0x2009, 0x3412, 0x200a, 0x2009, 0x342b, 0x200b,
-	0x0001, 0x70a3, 0x0000, 0x70a7, 0x0001, 0x0078, 0x1e41, 0x70a3,
-	0x0000, 0x1078, 0x2e0e, 0x20a9, 0x0010, 0x2039, 0x0000, 0x1078,
-	0x2b01, 0xa7b8, 0x0100, 0x0070, 0x1e4f, 0x0078, 0x1e47, 0x7000,
-	0x2020, 0x0079, 0x1e53, 0x1e81, 0x1e6a, 0x1e6a, 0x1e5d, 0x1e81,
-	0x1e81, 0x1e5b, 0x1e5b, 0x1078, 0x1b4e, 0x2021, 0x3457, 0x2404,
-	0xa005, 0x0040, 0x1e6a, 0xad06, 0x00c0, 0x1e6a, 0x6800, 0x2022,
-	0x0078, 0x1e7a, 0x681c, 0xa084, 0x0001, 0x00c0, 0x1e76, 0x6f10,
-	0x1078, 0x2bfc, 0x1078, 0x283d, 0x0078, 0x1e7a, 0x7054, 0x2060,
-	0x6800, 0x6002, 0x6a16, 0x681c, 0xa085, 0x0008, 0x681e, 0x1078,
-	0x17be, 0x2021, 0x3e80, 0x1078, 0x1eab, 0x2021, 0x3457, 0x1078,
-	0x1eab, 0x20a9, 0x0000, 0x2021, 0x3d80, 0x1078, 0x1eab, 0x8420,
-	0x0070, 0x1e94, 0x0078, 0x1e8d, 0x20a9, 0x0080, 0x2061, 0x3580,
-	0x6018, 0x6110, 0xa102, 0x6012, 0x601b, 0x0000, 0xace0, 0x0010,
-	0x0070, 0x1ea4, 0x0078, 0x1e98, 0x157f, 0x7003, 0x0000, 0x703f,
-	0x0000, 0x0078, 0x1ba0, 0x047e, 0x2404, 0xa005, 0x0040, 0x1ebd,
-	0x2068, 0x6800, 0x007e, 0x6a16, 0x681c, 0xa085, 0x0008, 0x681e,
-	0x1078, 0x17be, 0x007f, 0x0078, 0x1ead, 0x047f, 0x2023, 0x0000,
-	0x007c, 0xa282, 0x0003, 0x0050, 0x1ec7, 0x1078, 0x1b4e, 0x2300,
-	0x0079, 0x1eca, 0x1ecd, 0x1f40, 0x1f4e, 0xa282, 0x0002, 0x0040,
-	0x1ed3, 0x1078, 0x1b4e, 0x70a0, 0x70a3, 0x0000, 0x70c3, 0x0000,
-	0x0079, 0x1eda, 0x1ee2, 0x1ee2, 0x1ee4, 0x1f18, 0x287b, 0x1ee2,
-	0x1f18, 0x1ee2, 0x1078, 0x1b4e, 0x77b4, 0x1078, 0x2b01, 0x77b4,
-	0xa7bc, 0x0f00, 0x1078, 0x2bfc, 0x6018, 0xa005, 0x0040, 0x1f0f,
-	0x2021, 0x3e80, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x1f69,
-	0x0040, 0x1f0f, 0x157e, 0x20a9, 0x0000, 0x2021, 0x3d80, 0x047e,
-	0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x1f69, 0x047f, 0x0040,
-	0x1f0e, 0x8420, 0x0070, 0x1f0e, 0x0078, 0x1eff, 0x157f, 0x8738,
-	0xa784, 0x0007, 0x00c0, 0x1eea, 0x0078, 0x1ba8, 0x0078, 0x1ba8,
-	0x77b4, 0x1078, 0x2bfc, 0x6018, 0xa005, 0x0040, 0x1f3e, 0x2021,
-	0x3e80, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x1f69, 0x0040,
-	0x1f3e, 0x157e, 0x20a9, 0x0000, 0x2021, 0x3d80, 0x047e, 0x2009,
-	0x0005, 0x2011, 0x0020, 0x1078, 0x1f69, 0x047f, 0x0040, 0x1f3d,
-	0x8420, 0x0070, 0x1f3d, 0x0078, 0x1f2e, 0x157f, 0x0078, 0x1ba8,
-	0x2200, 0x0079, 0x1f43, 0x1f46, 0x1f48, 0x1f48, 0x1078, 0x1b4e,
-	0x70a3, 0x0000, 0x70a7, 0x0001, 0x0078, 0x1ba0, 0x2200, 0x0079,
-	0x1f51, 0x1f56, 0x1f48, 0x1f54, 0x1078, 0x1b4e, 0x1078, 0x23a0,
-	0x7000, 0xa086, 0x0001, 0x00c0, 0x2813, 0x1078, 0x2853, 0x6008,
-	0xa084, 0xffef, 0x600a, 0x1078, 0x2806, 0x0040, 0x2813, 0x0078,
-	0x1c7a, 0x2404, 0xa005, 0x0040, 0x1f8a, 0x2068, 0x2d04, 0x007e,
-	0x6810, 0xa706, 0x0040, 0x1f78, 0x2d20, 0x007f, 0x0078, 0x1f6a,
-	0x007f, 0x2022, 0x6916, 0x681c, 0xa205, 0x681e, 0x1078, 0x17be,
-	0x6010, 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078,
-	0x2853, 0x007c, 0xa085, 0x0001, 0x0078, 0x1f89, 0x2300, 0x0079,
-	0x1f91, 0x1f96, 0x1f94, 0x1fd5, 0x1078, 0x1b4e, 0x78e4, 0xa005,
-	0x00d0, 0x1fb9, 0x0018, 0x1fb9, 0x2008, 0xa084, 0x0030, 0x00c0,
-	0x1fa5, 0x781b, 0x0049, 0x0078, 0x1ba0, 0x78ec, 0xa084, 0x0003,
-	0x0040, 0x1fa1, 0x2100, 0xa084, 0x0007, 0x0079, 0x1faf, 0x1fc3,
-	0x1fc9, 0x1fbd, 0x1fb7, 0x2ca7, 0x2ca7, 0x1fb7, 0x1fcf, 0x1078,
-	0x1b4e, 0x2001, 0x0003, 0x0078, 0x2282, 0x1078, 0x2ae4, 0x781b,
-	0x0055, 0x0078, 0x1ba0, 0x1078, 0x2ae4, 0x781b, 0x00dc, 0x0078,
-	0x1ba0, 0x1078, 0x2ae4, 0x781b, 0x00e3, 0x0078, 0x1ba0, 0x1078,
-	0x2ae4, 0x781b, 0x009d, 0x0078, 0x1ba0, 0xa584, 0x000f, 0x00c0,
-	0x1ff4, 0x1078, 0x23a0, 0x7000, 0x0079, 0x1fde, 0x1fe6, 0x1fe8,
-	0x1fe6, 0x2813, 0x2813, 0x2813, 0x1fe6, 0x1fe6, 0x1078, 0x1b4e,
-	0x1078, 0x2853, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x2806,
-	0x0040, 0x2813, 0x0078, 0x1c7a, 0x78e4, 0xa005, 0x00d0, 0x1fb9,
-	0x0018, 0x1fb9, 0x2008, 0xa084, 0x0030, 0x00c0, 0x2003, 0x781b,
-	0x0049, 0x0078, 0x1ba0, 0x78ec, 0xa084, 0x0003, 0x0040, 0x1fff,
-	0x2100, 0xa184, 0x0007, 0x0079, 0x200d, 0x201d, 0x2023, 0x2017,
-	0x2015, 0x2ca7, 0x2ca7, 0x2015, 0x2c9f, 0x1078, 0x1b4e, 0x1078,
-	0x2aec, 0x781b, 0x0055, 0x0078, 0x1ba0, 0x1078, 0x2aec, 0x781b,
-	0x00dc, 0x0078, 0x1ba0, 0x1078, 0x2aec, 0x781b, 0x00e3, 0x0078,
-	0x1ba0, 0x1078, 0x2aec, 0x781b, 0x009d, 0x0078, 0x1ba0, 0x2300,
-	0x0079, 0x2032, 0x2037, 0x2035, 0x2039, 0x1078, 0x1b4e, 0x0078,
-	0x25d0, 0x6817, 0x0008, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030,
-	0x0040, 0x25d0, 0x78ec, 0xa084, 0x0003, 0x0040, 0x25d0, 0xa184,
-	0x0007, 0x0079, 0x204b, 0x1fc3, 0x1fc9, 0x1fbd, 0x2c7f, 0x2ca7,
-	0x2ca7, 0x2053, 0x2c9f, 0x1078, 0x1b4e, 0xa282, 0x0005, 0x0050,
-	0x205b, 0x1078, 0x1b4e, 0x2300, 0x0079, 0x205e, 0x2061, 0x2256,
-	0x2262, 0x2200, 0x0079, 0x2064, 0x2069, 0x206b, 0x207e, 0x2069,
-	0x223b, 0x1078, 0x1b4e, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff,
-	0xa082, 0x0020, 0x0048, 0x2ac5, 0xa08a, 0x0004, 0x00c8, 0x2ac5,
-	0x0079, 0x207a, 0x2ac5, 0x2ac5, 0x2ac5, 0x2a73, 0x789b, 0x0018,
-	0x79a8, 0xa184, 0x0080, 0x0040, 0x2093, 0xa184, 0x0018, 0x0040,
-	0x208f, 0x0078, 0x2ac5, 0x7000, 0xa005, 0x00c0, 0x2089, 0x2011,
-	0x0003, 0x0078, 0x26bc, 0xa184, 0x00ff, 0xa08a, 0x0010, 0x00c8,
-	0x2ac5, 0x0079, 0x209b, 0x20ad, 0x20ab, 0x20c3, 0x20c5, 0x214a,
-	0x2ac5, 0x2ac5, 0x214c, 0x2ac5, 0x2ac5, 0x2237, 0x2237, 0x2ac5,
-	0x2ac5, 0x2ac5, 0x2239, 0x1078, 0x1b4e, 0xa684, 0x1000, 0x0040,
-	0x20ba, 0x2001, 0x0300, 0x8000, 0x8000, 0x783a, 0x781b, 0x009a,
-	0x0078, 0x1ba0, 0x6814, 0xa084, 0x8000, 0x0040, 0x20c1, 0x6817,
-	0x0003, 0x0078, 0x2c7f, 0x1078, 0x1b4e, 0x691c, 0x691e, 0xa684,
-	0x1800, 0x00c0, 0x20df, 0x681c, 0xa084, 0x0001, 0x00c0, 0x20e7,
-	0x6814, 0xa086, 0x0008, 0x00c0, 0x20d7, 0x6817, 0x0000, 0xa684,
-	0x0400, 0x0040, 0x2146, 0x781b, 0x0058, 0x0078, 0x1ba0, 0xa684,
-	0x1000, 0x0040, 0x20e7, 0x781b, 0x0058, 0x0078, 0x1ba0, 0xa684,
-	0x0060, 0x0040, 0x2142, 0xa684, 0x0800, 0x0040, 0x2142, 0xa684,
-	0x8000, 0x00c0, 0x20f5, 0x0078, 0x210f, 0xa6b4, 0x7fff, 0x7e5a,
-	0x6eb2, 0x789b, 0x0074, 0x7aac, 0x79ac, 0x78ac, 0x801b, 0x00c8,
-	0x2102, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b94,
-	0x2100, 0xa302, 0x68ae, 0x6b90, 0x2200, 0xa303, 0x68aa, 0xa684,
-	0x4000, 0x0040, 0x2117, 0xa6b4, 0xbfff, 0x7e5a, 0x6eb2, 0xa006,
-	0x1078, 0x30a0, 0x6aac, 0x69a8, 0x6c94, 0x6b90, 0x2200, 0xa105,
-	0x0040, 0x2126, 0x2200, 0xa422, 0x2100, 0xa31b, 0x7cd2, 0x7bd6,
-	0x2300, 0xa405, 0x00c0, 0x2134, 0xa6b5, 0x4000, 0x7e5a, 0x6eb2,
-	0x781b, 0x0067, 0x0078, 0x1ba0, 0x781b, 0x0067, 0x2200, 0xa115,
-	0x00c0, 0x213e, 0x1078, 0x2ffc, 0x0078, 0x1ba0, 0x1078, 0x3029,
-	0x0078, 0x1ba0, 0x781b, 0x006a, 0x0078, 0x1ba0, 0x781b, 0x0058,
-	0x0078, 0x1ba0, 0x1078, 0x1b4e, 0x0078, 0x21a9, 0x691c, 0xa184,
-	0x0100, 0x0040, 0x2164, 0xa18c, 0xfeff, 0x691e, 0x0c7e, 0x7048,
+	0x3540, 0x00a8, 0x106a, 0x681b, 0x003c, 0x2009, 0x1313, 0x21b8,
+	0x0078, 0x106c, 0x681b, 0x0028, 0x6807, 0x0007, 0x680b, 0x00fa,
+	0x680f, 0x0008, 0x6813, 0x0005, 0x681f, 0x0000, 0x6823, 0x0006,
+	0x6817, 0x0008, 0x6827, 0x0000, 0x2069, 0x3600, 0x2011, 0x0020,
+	0x2009, 0x0010, 0x680b, 0x0c19, 0x680f, 0x0019, 0x6803, 0xdd00,
+	0x6807, 0x001a, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004,
+	0x8109, 0x00c0, 0x1082, 0x2069, 0x3680, 0x20a9, 0x0080, 0x6837,
+	0x0000, 0x680b, 0x0040, 0x6817, 0x0100, 0x681f, 0x0064, 0xade8,
+	0x0010, 0x0070, 0x10a5, 0x0078, 0x1097, 0x1078, 0x1a38, 0x1078,
+	0x2f3a, 0x1078, 0x1681, 0x1078, 0x33ba, 0x3200, 0xa085, 0x000d,
+	0x2090, 0x70c3, 0x0000, 0x0090, 0x10bc, 0x70c0, 0xa086, 0x0002,
+	0x00c0, 0x10bc, 0x1078, 0x11ba, 0x1078, 0x10ec, 0x1078, 0x1817,
+	0x1078, 0x19a8, 0x1078, 0x327d, 0x1078, 0x177d, 0x0078, 0x10bc,
+	0x10d0, 0x10d2, 0x1bc3, 0x1bc3, 0x2f98, 0x2f98, 0x1bc3, 0x1bc3,
+	0x0078, 0x10d0, 0x0078, 0x10d2, 0x0078, 0x10d4, 0x0078, 0x10d6,
+	0x7008, 0x800c, 0x00c8, 0x10e7, 0x7007, 0x0002, 0xa08c, 0x000c,
+	0x00c0, 0x10e8, 0x8004, 0x8004, 0x00c8, 0x10e7, 0x087a, 0x097a,
+	0x70c3, 0x4002, 0x0078, 0x11bd, 0x7814, 0xa005, 0x00c0, 0x10f4,
+	0x0010, 0x1130, 0x0078, 0x112f, 0x2009, 0x3568, 0x2104, 0xa005,
+	0x00c0, 0x112f, 0x7814, 0xa086, 0x0001, 0x00c0, 0x1101, 0x1078,
+	0x1536, 0x7817, 0x0000, 0x2009, 0x356f, 0x2104, 0xa065, 0x0040,
+	0x111d, 0x2009, 0x356a, 0x211c, 0x8108, 0x2114, 0x8108, 0x2104,
+	0xa210, 0xa399, 0x0000, 0x2009, 0x001c, 0x6083, 0x0103, 0x1078,
+	0x1611, 0x00c0, 0x1129, 0x1078, 0x1678, 0x2009, 0x356f, 0x200b,
+	0x0000, 0x2009, 0x3569, 0x2104, 0x200b, 0x0000, 0xa005, 0x0040,
+	0x112d, 0x2001, 0x4005, 0x0078, 0x11bc, 0x0078, 0x11ba, 0x007c,
+	0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x0040, 0x1138, 0x007c,
+	0x70c3, 0x0000, 0x70c7, 0x0000, 0x70cb, 0x0000, 0x70cf, 0x0000,
+	0x70c0, 0xa0bc, 0xffc0, 0x00c0, 0x1188, 0x2038, 0x0079, 0x1148,
+	0x11ba, 0x1205, 0x11d3, 0x1205, 0x1256, 0x1256, 0x11ca, 0x1590,
+	0x1261, 0x11c6, 0x11d7, 0x11d9, 0x11db, 0x11dd, 0x1595, 0x11c6,
+	0x1267, 0x1283, 0x1544, 0x158a, 0x11df, 0x146b, 0x148d, 0x14a7,
+	0x14d0, 0x1424, 0x1432, 0x1446, 0x145a, 0x12ef, 0x11c6, 0x129f,
+	0x12a6, 0x12ab, 0x12b0, 0x12b6, 0x12bb, 0x12c0, 0x12c5, 0x12ca,
+	0x12ce, 0x12e3, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x12fb,
+	0x1304, 0x1313, 0x1339, 0x1343, 0x134a, 0x1370, 0x137f, 0x138e,
+	0x13a0, 0x1409, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x1419,
+	0xa0bc, 0xffa0, 0x00c0, 0x11c6, 0x2038, 0xa084, 0x001f, 0x0079,
+	0x1191, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6,
+	0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6,
+	0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6,
+	0x11c6, 0x11c6, 0x11c6, 0x15ed, 0x15f7, 0x15fb, 0x1609, 0x11c6,
+	0x11c6, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078, 0x11bc, 0x73ce,
+	0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x2061, 0x0000, 0x601b,
+	0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x007c, 0x70c3, 0x4001,
+	0x0078, 0x11bd, 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005,
+	0x53a3, 0x0078, 0x11ba, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078,
+	0x11ba, 0x0078, 0x11ba, 0x0078, 0x11ba, 0x0078, 0x11ba, 0x2091,
+	0x8000, 0x70c3, 0x0000, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf,
+	0x2020, 0x70d3, 0x0001, 0x3f00, 0x70d6, 0x2079, 0x0000, 0x781b,
+	0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x0457, 0x2051,
+	0x0470, 0x2061, 0x0472, 0x20b9, 0xffff, 0x20c1, 0x0000, 0x2091,
+	0x5000, 0x2091, 0x4080, 0x0078, 0x0455, 0x71d0, 0x72c8, 0x73cc,
+	0x70c4, 0x20a0, 0x2098, 0x2031, 0x0030, 0x81ff, 0x0040, 0x11ba,
+	0x7007, 0x0004, 0x731a, 0x721e, 0x2051, 0x0012, 0x2049, 0x1234,
+	0x2041, 0x11ba, 0x7003, 0x0002, 0xa786, 0x0001, 0x00c0, 0x1226,
+	0x2049, 0x1242, 0x2041, 0x124e, 0x7003, 0x0003, 0x7017, 0x0000,
+	0x810b, 0x7112, 0x00c8, 0x122e, 0x7017, 0x0001, 0x7007, 0x0001,
+	0xa786, 0x0001, 0x0040, 0x1242, 0x700c, 0xa084, 0x007f, 0x8004,
+	0x2009, 0x0020, 0xa102, 0x0942, 0x094a, 0x20a8, 0x26a0, 0x53a6,
+	0x0078, 0x10d8, 0x700c, 0xa084, 0x007f, 0x0040, 0x1242, 0x80ac,
+	0x0048, 0x1242, 0x2698, 0x53a5, 0x0078, 0x10d8, 0x700c, 0xa084,
+	0x007f, 0x80ac, 0x2698, 0x53a5, 0x0078, 0x11ba, 0x71c4, 0x70c8,
+	0x2114, 0xa79e, 0x0004, 0x00c0, 0x125e, 0x200a, 0x72ca, 0x0078,
+	0x11b9, 0x70c7, 0x0001, 0x70cb, 0x001f, 0x0078, 0x11ba, 0x70c4,
+	0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005,
+	0x0040, 0x127d, 0x8001, 0x7872, 0x7a7a, 0x7b7e, 0x7c76, 0x7898,
+	0xa084, 0xfffc, 0x789a, 0x0078, 0x1281, 0x7898, 0xa085, 0x0001,
+	0x789a, 0x0078, 0x11ba, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6,
+	0x72ca, 0x73ce, 0x74d6, 0xa005, 0x0040, 0x1299, 0x8001, 0x7886,
+	0x7a8e, 0x7b92, 0x7c8a, 0x7898, 0xa084, 0xfcff, 0x789a, 0x0078,
+	0x129d, 0x7898, 0xa085, 0x0100, 0x789a, 0x0078, 0x11ba, 0x2009,
+	0x3559, 0x210c, 0x2011, 0x0410, 0x0078, 0x11b8, 0x2009, 0x3541,
+	0x210c, 0x0078, 0x11b9, 0x2009, 0x3542, 0x210c, 0x0078, 0x11b9,
+	0x2061, 0x3540, 0x610c, 0x6210, 0x0078, 0x11b8, 0x2009, 0x3545,
+	0x210c, 0x0078, 0x11b9, 0x2009, 0x3546, 0x210c, 0x0078, 0x11b9,
+	0x2009, 0x3547, 0x210c, 0x0078, 0x11b9, 0x2009, 0x3548, 0x210c,
+	0x0078, 0x11b9, 0x7908, 0x7a0c, 0x0078, 0x11b8, 0x71c4, 0x8107,
+	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, 0x3600, 0x6a00,
+	0x6804, 0xa084, 0x0008, 0x0040, 0x12e0, 0x6b08, 0x0078, 0x12e1,
+	0x6b0c, 0x0078, 0x11b7, 0x77c4, 0x1078, 0x1692, 0x2091, 0x8000,
+	0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x11b7, 0x77c4,
+	0x1078, 0x1692, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10, 0x2091,
+	0x8001, 0x0078, 0x11b7, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b2,
+	0x1078, 0x1abc, 0x0078, 0x11b7, 0x71c4, 0xa182, 0x0010, 0x00c8,
+	0x11b2, 0x2011, 0x3541, 0x2204, 0x007e, 0x2112, 0x1078, 0x1a75,
+	0x017f, 0x0078, 0x11b9, 0x71c4, 0x2011, 0x1331, 0x20a9, 0x0008,
+	0x2204, 0xa106, 0x0040, 0x1323, 0x8210, 0x0070, 0x1321, 0x0078,
+	0x1318, 0x0078, 0x11b2, 0xa292, 0x1331, 0x027e, 0x2011, 0x3542,
+	0x2204, 0x2112, 0x017f, 0x007e, 0x1078, 0x1a81, 0x017f, 0x0078,
+	0x11b9, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032,
+	0x004b, 0x2061, 0x3540, 0x610c, 0x6210, 0x70c4, 0x600e, 0x70c8,
+	0x6012, 0x0078, 0x11b8, 0x2061, 0x3540, 0x6114, 0x70c4, 0x6016,
+	0x0078, 0x11b9, 0x71c4, 0x2011, 0x0004, 0x2019, 0x1212, 0xa186,
+	0x0028, 0x0040, 0x1363, 0x2011, 0x0005, 0x2019, 0x1212, 0xa186,
+	0x0032, 0x0040, 0x1363, 0x2011, 0x0006, 0x2019, 0x1313, 0xa186,
+	0x003c, 0x00c0, 0x11b2, 0x2061, 0x3540, 0x6018, 0x007e, 0x611a,
+	0x23b8, 0x1078, 0x1a92, 0x1078, 0x33ba, 0x017f, 0x0078, 0x11b9,
+	0x71c4, 0xa184, 0xffcf, 0x00c0, 0x11b2, 0x2011, 0x3547, 0x2204,
+	0x2112, 0x007e, 0x1078, 0x1ab4, 0x017f, 0x0078, 0x11b9, 0x71c4,
+	0xa182, 0x0010, 0x00c8, 0x11b2, 0x2011, 0x3548, 0x2204, 0x007e,
+	0x2112, 0x1078, 0x1aa3, 0x017f, 0x0078, 0x11b9, 0x71c4, 0x72c8,
+	0xa184, 0xfffd, 0x00c0, 0x11b1, 0xa284, 0xfffd, 0x00c0, 0x11b1,
+	0x2100, 0x7908, 0x780a, 0x2200, 0x7a0c, 0x780e, 0x0078, 0x11b8,
+	0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8,
+	0x3600, 0x2019, 0x0000, 0x72c8, 0x6800, 0x007e, 0xa226, 0x0040,
+	0x13cf, 0x6a02, 0xa484, 0x2000, 0x0040, 0x13b8, 0xa39d, 0x0010,
+	0xa484, 0x1000, 0x0040, 0x13be, 0xa39d, 0x0008, 0xa484, 0x4000,
+	0x0040, 0x13cf, 0x810f, 0xa284, 0x4000, 0x0040, 0x13cb, 0x1078,
+	0x1ad6, 0x0078, 0x13cf, 0x1078, 0x1ac8, 0x0078, 0x13cf, 0x72cc,
+	0x82ff, 0x0040, 0x1401, 0x6808, 0xa206, 0x0040, 0x1401, 0xa2a4,
+	0x00ff, 0x2061, 0x3540, 0x6118, 0xa186, 0x0028, 0x0040, 0x13e8,
+	0xa186, 0x0032, 0x0040, 0x13ee, 0xa186, 0x003c, 0x0040, 0x13f4,
+	0xa482, 0x0064, 0x0048, 0x13fe, 0x0078, 0x13f8, 0xa482, 0x0050,
+	0x0048, 0x13fe, 0x0078, 0x13f8, 0xa482, 0x0043, 0x0048, 0x13fe,
+	0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x11b3, 0x6a0a, 0xa39d,
+	0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, 0x0078,
+	0x11b7, 0x77c4, 0x1078, 0x1692, 0x2091, 0x8000, 0x6a14, 0x6b1c,
+	0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078,
+	0x11b7, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8, 0x11b2,
+	0x1078, 0x1ae4, 0x0078, 0x11b7, 0x77c4, 0x1078, 0x1692, 0x2091,
+	0x8000, 0x6a08, 0xa295, 0x0002, 0x6a0a, 0x2091, 0x8001, 0x2708,
+	0x0078, 0x11b8, 0x77c4, 0x1078, 0x1692, 0x2091, 0x8000, 0x6a08,
+	0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1441, 0x1078,
+	0x1a19, 0x2091, 0x8001, 0x2708, 0x0078, 0x11b8, 0x77c4, 0x1078,
+	0x1692, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0004, 0x6a0a, 0x6804,
+	0xa005, 0x0040, 0x1455, 0x1078, 0x1a19, 0x2091, 0x8001, 0x2708,
+	0x0078, 0x11b8, 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051,
+	0x0020, 0x2091, 0x8000, 0x1078, 0x169f, 0x2091, 0x8001, 0x2708,
+	0x6a08, 0x0078, 0x11b8, 0x77c4, 0x72c8, 0x73cc, 0x77c6, 0x72ca,
+	0x73ce, 0x1078, 0x1718, 0x00c0, 0x1489, 0x6818, 0xa005, 0x0040,
+	0x1483, 0x2708, 0x1078, 0x1af4, 0x00c0, 0x1483, 0x7817, 0xffff,
+	0x2091, 0x8001, 0x007c, 0x2091, 0x8001, 0x2001, 0x4005, 0x0078,
+	0x11bc, 0x2091, 0x8001, 0x0078, 0x11ba, 0x77c4, 0x77c6, 0x2041,
+	0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
+	0x169f, 0x2061, 0x3540, 0x60a3, 0x0003, 0x67b6, 0x60a7, 0x0000,
+	0x7817, 0xffff, 0x2091, 0x8001, 0x1078, 0x1a19, 0x007c, 0x77c8,
+	0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2061,
+	0x3540, 0x60a3, 0x0002, 0x60a7, 0x0000, 0x67b6, 0x7817, 0xffff,
+	0x1078, 0x1a19, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049, 0x0004,
+	0x2051, 0x0010, 0x2091, 0x8000, 0x1078, 0x169f, 0x70c8, 0x6836,
+	0x8738, 0xa784, 0x0007, 0x00c0, 0x14c4, 0x2091, 0x8001, 0x007c,
+	0x7898, 0xa084, 0x0003, 0x00c0, 0x14f4, 0x2039, 0x0000, 0x2041,
+	0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078, 0x1692, 0x2091,
+	0x8000, 0x6808, 0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784,
+	0x0007, 0x00c0, 0x14dd, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f,
+	0xa784, 0x0f00, 0x00c0, 0x14dd, 0x2091, 0x8000, 0x2069, 0x0100,
+	0x6830, 0xa084, 0x0040, 0x0040, 0x151d, 0x684b, 0x0004, 0x20a9,
+	0x0014, 0x6848, 0xa084, 0x0004, 0x0040, 0x150a, 0x0070, 0x150a,
+	0x0078, 0x1501, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084,
+	0x0001, 0x0040, 0x1517, 0x0070, 0x1517, 0x0078, 0x150e, 0x20a9,
+	0x00fa, 0x0070, 0x151d, 0x0078, 0x1519, 0x2079, 0x3500, 0x7817,
+	0x0001, 0x2061, 0x3540, 0x60a3, 0x0001, 0x60a7, 0x0000, 0x60c3,
+	0x000f, 0x7898, 0xa085, 0x0002, 0x789a, 0x6808, 0xa084, 0xfffd,
+	0x680a, 0x681b, 0x0046, 0x2091, 0x8001, 0x007c, 0x7898, 0xa084,
+	0xfffd, 0x789a, 0xa084, 0x0001, 0x00c0, 0x1540, 0x1078, 0x1760,
+	0x71c4, 0x71c6, 0x794a, 0x007c, 0x74c4, 0x73c8, 0x72cc, 0x74c6,
+	0x73ca, 0x72ce, 0x2079, 0x3500, 0x2009, 0x0040, 0x1078, 0x166f,
+	0x0040, 0x1586, 0x1078, 0x163f, 0x0040, 0x155a, 0x1078, 0x1678,
+	0x0078, 0x1586, 0x6010, 0x2091, 0x8001, 0x7817, 0xffff, 0x2009,
+	0x3568, 0x200b, 0x0005, 0x8108, 0x200b, 0x0000, 0x8108, 0x230a,
+	0x8108, 0x220a, 0x8108, 0x240a, 0x8108, 0x200a, 0x8108, 0x200b,
+	0x0000, 0x8108, 0x2c0a, 0xa02e, 0x2530, 0x0e7e, 0x1078, 0x2f13,
+	0x0e7f, 0x6592, 0x65a2, 0x6696, 0x66a6, 0x60ab, 0x0000, 0x60af,
+	0x0000, 0x2091, 0x8001, 0x1078, 0x1a19, 0x007c, 0x70c3, 0x4005,
+	0x0078, 0x11bd, 0x71c4, 0x70c7, 0x0000, 0x7906, 0x0078, 0x11ba,
+	0x71c4, 0x71c6, 0x2168, 0x0078, 0x1597, 0x2069, 0x1000, 0x690c,
+	0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, 0x1599, 0xa285,
+	0x0000, 0x00c0, 0x15a7, 0x70c3, 0x4000, 0x0078, 0x15a9, 0x70c3,
+	0x4003, 0x70ca, 0x0078, 0x11bd, 0x71c4, 0x72c8, 0x73cc, 0x2100,
+	0xa184, 0xfffc, 0x00c0, 0x11c6, 0x2100, 0x0079, 0x15b7, 0x15ce,
+	0x15e3, 0x15e5, 0x15e7, 0x70c3, 0x4003, 0x71ce, 0x72d2, 0x73d6,
+	0x0078, 0x15ca, 0x70c3, 0x4000, 0x70cf, 0x0000, 0x70d3, 0x0000,
+	0x70d7, 0x0000, 0x77c6, 0x71ca, 0x0078, 0x11ba, 0x2031, 0x15e9,
+	0x2624, 0x8630, 0x2412, 0x2204, 0xa446, 0x00c0, 0x15bb, 0xa484,
+	0xffff, 0x00c0, 0x15d0, 0x2031, 0x15e9, 0x8210, 0x8319, 0xa384,
+	0xffff, 0x00c0, 0x15d0, 0x0078, 0x15c2, 0x0078, 0x15c2, 0x0078,
+	0x15c2, 0x5555, 0xaaaa, 0xffff, 0x0000, 0x7960, 0x71c6, 0x71c4,
+	0xa182, 0x0003, 0x00c8, 0x11b2, 0x7962, 0x0078, 0x11ba, 0x7960,
+	0x71c6, 0x0078, 0x11ba, 0x7954, 0x71c6, 0x71c4, 0x7956, 0x7958,
+	0x71ca, 0x71c8, 0x795a, 0x795c, 0x71ce, 0x71cc, 0x795e, 0x0078,
+	0x11ba, 0x7954, 0x71c6, 0x7958, 0x71ca, 0x795c, 0x71ce, 0x0078,
+	0x11ba, 0x700c, 0xa084, 0x007f, 0x0040, 0x161d, 0x7007, 0x0004,
+	0x7004, 0xa084, 0x0004, 0x00c0, 0x1618, 0x7017, 0x0000, 0x7112,
+	0x721a, 0x731e, 0x8108, 0x810c, 0x81a9, 0x8c98, 0x20a1, 0x0030,
+	0x6080, 0x20a2, 0x53a6, 0x780c, 0xa085, 0x0000, 0x7002, 0x7007,
+	0x0001, 0x7108, 0x8104, 0x00c8, 0x1631, 0x7007, 0x0002, 0xa184,
+	0x000c, 0x710c, 0xa184, 0x0300, 0x7003, 0x0000, 0x007c, 0x700c,
+	0xa084, 0x007f, 0x0040, 0x164b, 0x7007, 0x0004, 0x7004, 0xa084,
+	0x0004, 0x00c0, 0x1646, 0x7017, 0x0000, 0x7112, 0x721a, 0x731e,
+	0x2099, 0x0030, 0x8108, 0x81ac, 0x780c, 0xa085, 0x0001, 0x7002,
+	0x7007, 0x0001, 0x7008, 0x800c, 0x00c8, 0x165a, 0x7007, 0x0002,
+	0xa08c, 0x000c, 0x00c0, 0x166c, 0x710c, 0xa184, 0x0300, 0x00c0,
+	0x166c, 0x2ca0, 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, 0x7850,
+	0xa065, 0x0040, 0x1677, 0x2c04, 0x7852, 0x2063, 0x0000, 0x007c,
+	0x0f7e, 0x2079, 0x3500, 0x7850, 0x2062, 0x2c00, 0x7852, 0x0f7f,
+	0x007c, 0x2011, 0x4000, 0x7a52, 0x2019, 0x0410, 0x8319, 0x0040,
+	0x168f, 0xa280, 0x002f, 0x2012, 0x2010, 0x0078, 0x1686, 0x2013,
+	0x0000, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, 0x0007, 0x8003,
+	0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8, 0x3680, 0x007c, 0x1078,
+	0x1692, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xffef,
+	0xa80d, 0x690a, 0x2009, 0x354f, 0x210c, 0x6804, 0xa005, 0x0040,
+	0x16bc, 0xa116, 0x00c0, 0x16bc, 0x2060, 0x6000, 0x6806, 0x017e,
+	0x200b, 0x0000, 0x0078, 0x16bf, 0x2009, 0x0000, 0x017e, 0x6804,
+	0xa065, 0x0040, 0x16ce, 0x6000, 0x6806, 0x1078, 0x16df, 0x1078,
+	0x17cb, 0x6810, 0x8001, 0x6812, 0x00c0, 0x16bf, 0x017f, 0x6902,
+	0x6906, 0x007c, 0xa065, 0x0040, 0x16de, 0x6098, 0x609b, 0x0000,
+	0x2008, 0x1078, 0x1678, 0x2100, 0x0078, 0x16d2, 0x007c, 0x6003,
+	0x0103, 0x20a9, 0x001c, 0xac80, 0x0004, 0x20a0, 0x2001, 0x0000,
+	0x40a4, 0x6828, 0x6016, 0x682c, 0x601e, 0x007c, 0x0e7e, 0x2071,
+	0x3540, 0x7040, 0xa08c, 0x0080, 0x00c0, 0x16fc, 0xa088, 0x3580,
+	0x2d0a, 0x8000, 0x7042, 0xa006, 0x0e7f, 0x007c, 0x0e7e, 0x2071,
+	0x3540, 0x2009, 0x3580, 0x7240, 0x8221, 0x8211, 0x0048, 0x1716,
+	0x2104, 0x8108, 0xad06, 0x00c0, 0x1705, 0x8119, 0x211e, 0x8108,
+	0x8318, 0x8211, 0x00c8, 0x170e, 0x7442, 0xa006, 0x0e7f, 0x007c,
+	0x1078, 0x1692, 0x2091, 0x8000, 0x6804, 0x781e, 0xa065, 0x0040,
+	0x175f, 0x0078, 0x1729, 0x2c00, 0x781e, 0x6000, 0xa065, 0x0040,
+	0x175f, 0x600c, 0xa306, 0x00c0, 0x1723, 0x6008, 0xa206, 0x00c0,
+	0x1723, 0x2c28, 0x2001, 0x354f, 0x2004, 0xac06, 0x0040, 0x175f,
+	0x6804, 0xac06, 0x00c0, 0x1746, 0x6000, 0x2060, 0x6806, 0xa005,
+	0x00c0, 0x1746, 0x6803, 0x0000, 0x0078, 0x1750, 0x6400, 0x781c,
+	0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1750, 0x2c00, 0x6802,
+	0x2560, 0x1078, 0x16df, 0x6017, 0x0005, 0x601f, 0x0020, 0x1078,
+	0x17cb, 0x6810, 0x8001, 0x6812, 0x2001, 0xffff, 0xa005, 0x007c,
+	0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008,
+	0x2091, 0x8000, 0x1078, 0x169f, 0x8738, 0xa784, 0x0007, 0x00c0,
+	0x176a, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00,
+	0x00c0, 0x176a, 0x2091, 0x8001, 0x007c, 0x2061, 0x0000, 0x6018,
+	0xa084, 0x0001, 0x00c0, 0x178a, 0x78ac, 0x78af, 0x0000, 0xa005,
+	0x00c0, 0x178b, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x1791, 0x1078,
+	0x1ba5, 0x0079, 0x1793, 0x17a3, 0x17a5, 0x17ab, 0x17af, 0x17a3,
+	0x17b3, 0x17a3, 0x17a3, 0x17a3, 0x17a3, 0x17b9, 0x17bd, 0x17a3,
+	0x17a3, 0x17a3, 0x17a3, 0x1078, 0x1ba5, 0x1078, 0x1760, 0x2001,
+	0x8001, 0x0078, 0x17c3, 0x2001, 0x8003, 0x0078, 0x17c3, 0x2001,
+	0x8004, 0x0078, 0x17c3, 0x1078, 0x1760, 0x2001, 0x8006, 0x0078,
+	0x17c3, 0x2001, 0x800c, 0x0078, 0x17c3, 0x1078, 0x1760, 0x2001,
+	0x800d, 0x0078, 0x17c3, 0x70c2, 0x2061, 0x0000, 0x601b, 0x0001,
+	0x2091, 0x4080, 0x007c, 0x2c04, 0x6082, 0x2c08, 0x2063, 0x0000,
+	0x7864, 0x8000, 0x7866, 0x7868, 0xa005, 0x796a, 0x0040, 0x17db,
+	0x2c02, 0x0078, 0x17dc, 0x796e, 0x007c, 0x0c7e, 0x2061, 0x3500,
+	0x6883, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6064, 0x8000, 0x6066,
+	0x6068, 0xa005, 0x616a, 0x0040, 0x17f0, 0x2d02, 0x0078, 0x17f1,
+	0x616e, 0x0c7f, 0x007c, 0x1078, 0x1804, 0x0040, 0x1803, 0x0c7e,
+	0x6098, 0xa065, 0x0040, 0x17fe, 0x1078, 0x16d2, 0x0c7f, 0x609b,
+	0x0000, 0x1078, 0x1678, 0x007c, 0x786c, 0xa065, 0x0040, 0x1816,
+	0x2091, 0x8000, 0x7864, 0x8001, 0x7866, 0x2c04, 0x786e, 0xa005,
+	0x00c0, 0x1814, 0x786a, 0x8000, 0x2091, 0x8001, 0x007c, 0x7898,
+	0xa005, 0x00c0, 0x1865, 0x7974, 0x70d0, 0x0005, 0x0005, 0x72d0,
+	0xa206, 0x00c0, 0x181c, 0x2200, 0xa106, 0x00c0, 0x1833, 0x7804,
+	0xa005, 0x0040, 0x1865, 0x7807, 0x0000, 0x0068, 0x1865, 0x2091,
+	0x4080, 0x0078, 0x1865, 0x1078, 0x166f, 0x0040, 0x1865, 0x7a7c,
+	0x7b78, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399, 0x0000, 0x2009,
+	0x0040, 0x1078, 0x163f, 0x0040, 0x185c, 0x1078, 0x1678, 0x7880,
+	0x8000, 0x7882, 0xa086, 0x0002, 0x00c0, 0x1865, 0x2091, 0x8000,
+	0x78af, 0x0002, 0x7883, 0x0000, 0x7898, 0xa085, 0x0003, 0x789a,
+	0x2091, 0x8001, 0x0078, 0x1865, 0x7883, 0x0000, 0x1078, 0x1992,
+	0x6000, 0xa084, 0x0007, 0x0079, 0x1866, 0x007c, 0x186e, 0x187d,
+	0x189d, 0x186e, 0x18af, 0x186e, 0x186e, 0x186e, 0x2039, 0x0400,
+	0x78a8, 0xa705, 0x78aa, 0x6004, 0xa705, 0x6006, 0x1078, 0x18ed,
+	0x6018, 0x78a6, 0x1078, 0x197a, 0x007c, 0x78a8, 0xa084, 0x0100,
+	0x0040, 0x1884, 0x0078, 0x186e, 0x78ab, 0x0000, 0x6000, 0x8007,
+	0xa084, 0x00ff, 0x789e, 0x8001, 0x609b, 0x0000, 0x0040, 0x189a,
+	0x1078, 0x18ed, 0x0040, 0x189a, 0x78a8, 0xa085, 0x0100, 0x78aa,
+	0x0078, 0x189c, 0x1078, 0x1911, 0x007c, 0x78a8, 0xa08c, 0x0e00,
+	0x00c0, 0x18a6, 0xa084, 0x0100, 0x00c0, 0x18a8, 0x0078, 0x186e,
+	0x1078, 0x18ed, 0x00c0, 0x18ae, 0x1078, 0x1911, 0x007c, 0x78a8,
+	0xa084, 0x0100, 0x0040, 0x18b6, 0x0078, 0x186e, 0x78ab, 0x0000,
+	0x6710, 0x20a9, 0x0001, 0x6014, 0xa084, 0x00ff, 0xa005, 0x0040,
+	0x18d3, 0xa7bc, 0xff00, 0x20a9, 0x0008, 0xa08e, 0x0001, 0x0040,
+	0x18d3, 0x2039, 0x0000, 0x20a9, 0x0080, 0xa08e, 0x0002, 0x0040,
+	0x18d3, 0x0078, 0x18ea, 0x1078, 0x1692, 0x2d00, 0x2091, 0x8000,
+	0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde, 0x680a,
+	0x2d00, 0xa080, 0x0010, 0x2068, 0x2091, 0x8001, 0x0070, 0x18ea,
+	0x0078, 0x18d6, 0x1078, 0x1678, 0x007c, 0x78a0, 0xa06d, 0x00c0,
+	0x18f8, 0x2c00, 0x78a2, 0x78a6, 0x609b, 0x0000, 0x0078, 0x1904,
+	0x2c00, 0x689a, 0x609b, 0x0000, 0x78a2, 0x2d00, 0x6002, 0x78a4,
+	0xad06, 0x00c0, 0x1904, 0x6002, 0x789c, 0x8001, 0x789e, 0x00c0,
+	0x1910, 0x78a8, 0xa084, 0x0000, 0x78aa, 0x78a4, 0x2060, 0xa006,
+	0x007c, 0xa02e, 0x2530, 0x6118, 0xa184, 0x0060, 0x619e, 0x0040,
+	0x191d, 0x0e7e, 0x1078, 0x2f13, 0x0e7f, 0x6592, 0x65a2, 0x6696,
+	0x66a6, 0x60ab, 0x0000, 0x60af, 0x0000, 0x6710, 0x1078, 0x1692,
+	0x2091, 0x8000, 0x6808, 0xa084, 0x0001, 0x0040, 0x193f, 0x2091,
+	0x8001, 0x1078, 0x16df, 0x2091, 0x8000, 0x1078, 0x17cb, 0x2091,
+	0x8001, 0x78a3, 0x0000, 0x78a7, 0x0000, 0x0078, 0x1979, 0x6020,
+	0xa096, 0x0001, 0x00c0, 0x1946, 0x8000, 0x6022, 0x6a10, 0x6814,
+	0x2091, 0x8001, 0xa202, 0x0048, 0x1955, 0x0040, 0x1955, 0x2039,
+	0x0200, 0x1078, 0x197a, 0x0078, 0x1979, 0x2c08, 0x2091, 0x8000,
+	0x6800, 0xa065, 0x0040, 0x195d, 0x6102, 0x6902, 0x00c0, 0x1961,
+	0x6906, 0x2160, 0x6003, 0x0000, 0x6810, 0x8000, 0x6812, 0x2091,
+	0x8001, 0x6808, 0xa08c, 0x0040, 0x0040, 0x1973, 0xa086, 0x0040,
+	0x680a, 0x1078, 0x16ee, 0x1078, 0x1a19, 0x78a7, 0x0000, 0x78a3,
+	0x0000, 0x007c, 0x6004, 0xa705, 0x6006, 0x2091, 0x8000, 0x1078,
+	0x17cb, 0x2091, 0x8001, 0x78a4, 0xa065, 0x0040, 0x198d, 0x6098,
+	0x78a6, 0x609b, 0x0000, 0x0078, 0x197d, 0x78a3, 0x0000, 0x78a7,
+	0x0000, 0x007c, 0x7970, 0x7874, 0x8000, 0xa10a, 0x00c8, 0x1999,
+	0xa006, 0x7876, 0x70d2, 0x7804, 0xa005, 0x0040, 0x19a7, 0x8001,
+	0x7806, 0x00c0, 0x19a7, 0x0068, 0x19a7, 0x2091, 0x4080, 0x007c,
+	0x0068, 0x19c2, 0x2029, 0x0000, 0x786c, 0xa065, 0x0040, 0x19bd,
+	0x1078, 0x19c3, 0x0040, 0x19bd, 0x057e, 0x1078, 0x19d9, 0x057f,
+	0x00c0, 0x19bd, 0x8528, 0x0078, 0x19ac, 0x85ff, 0x0040, 0x19c2,
+	0x2091, 0x4080, 0x007c, 0x7b84, 0x7988, 0x72d4, 0x0005, 0x0005,
+	0x70d4, 0xa206, 0x00c0, 0x19c5, 0x2200, 0xa102, 0x00c0, 0x19d3,
+	0x2300, 0xa005, 0x007c, 0x0048, 0x19d7, 0xa302, 0x007c, 0x8002,
+	0x007c, 0x1078, 0x1a0b, 0x2009, 0x001c, 0x6024, 0xa005, 0x0040,
+	0x19e3, 0x2009, 0x0040, 0x1078, 0x1611, 0x0040, 0x19fc, 0x7894,
+	0x8000, 0x7896, 0xa086, 0x0002, 0x00c0, 0x1a0a, 0x2091, 0x8000,
+	0x78af, 0x0003, 0x7897, 0x0000, 0x7898, 0xa085, 0x0300, 0x789a,
+	0x2091, 0x8001, 0x0078, 0x1a0a, 0x7897, 0x0000, 0x1078, 0x17f3,
+	0x7984, 0x7888, 0x8000, 0xa10a, 0x00c8, 0x1a07, 0xa006, 0x788a,
+	0x70d6, 0xa006, 0x007c, 0x8107, 0x8004, 0x8004, 0x7a90, 0x7b8c,
+	0xa210, 0xa399, 0x0000, 0x007c, 0x2009, 0x3568, 0x2091, 0x8000,
+	0x200a, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x3540, 0x2091, 0x8000,
+	0x2104, 0xa086, 0x0000, 0x00c0, 0x1a34, 0x2009, 0x3512, 0x2104,
+	0xa005, 0x00c0, 0x1a34, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x1a34,
+	0x0018, 0x1a34, 0x781b, 0x0044, 0x2091, 0x8001, 0x0f7f, 0x007c,
+	0x127e, 0x2091, 0x2300, 0x2071, 0x3540, 0x2079, 0x0100, 0x2019,
+	0x2dd8, 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040, 0x1a50, 0x789a,
+	0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318, 0x0078, 0x1a43,
+	0x789b, 0x0020, 0x20a9, 0x0010, 0x78af, 0x0000, 0x78af, 0x0220,
+	0x0070, 0x1a5c, 0x0078, 0x1a54, 0x7003, 0x0000, 0x1078, 0x1b5b,
+	0x7004, 0xa084, 0x000f, 0xa085, 0x6280, 0x7806, 0x780f, 0x9200,
+	0x7843, 0x00d8, 0x7853, 0x0080, 0x780b, 0x0038, 0x7047, 0x357f,
+	0x7043, 0x0000, 0x127f, 0x2000, 0x007c, 0xa18c, 0x000f, 0x2011,
+	0x0101, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x1078, 0x1b5b,
+	0x007c, 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x0070, 0x1a8a,
+	0x0078, 0x1a85, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105,
+	0x2012, 0x007c, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x0070,
+	0x1a9b, 0x0078, 0x1a96, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f,
+	0xa205, 0x200a, 0x007c, 0x2011, 0x0101, 0x20a9, 0x000c, 0x810b,
+	0x0070, 0x1aac, 0x0078, 0x1aa7, 0xa18c, 0xf000, 0x2204, 0xa084,
+	0x0fff, 0xa105, 0x2012, 0x007c, 0x2011, 0x0102, 0x2204, 0xa084,
+	0xffcf, 0xa105, 0x2012, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020,
+	0x0c7e, 0x2061, 0x0100, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c,
+	0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a,
+	0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003,
+	0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa085,
+	0x0020, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020,
+	0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0x62ae, 0x2010, 0x60a4,
+	0x63ae, 0x2018, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e,
+	0x6818, 0xa005, 0x0040, 0x1b39, 0x2061, 0x3f80, 0x1078, 0x1b41,
+	0x0040, 0x1b27, 0x20a9, 0x0000, 0x2061, 0x3e80, 0x0c7e, 0x1078,
+	0x1b41, 0x0040, 0x1b13, 0x0c7f, 0x8c60, 0x0070, 0x1b11, 0x0078,
+	0x1b06, 0x0078, 0x1b39, 0x007f, 0xa082, 0x3e80, 0x2071, 0x3540,
+	0x70ba, 0x601c, 0xa085, 0x0800, 0x601e, 0x71b6, 0x60a7, 0x0000,
+	0x2001, 0x0004, 0x70a2, 0x1078, 0x1a14, 0x0078, 0x1b35, 0x2071,
+	0x3540, 0x601c, 0xa085, 0x0800, 0x601e, 0x71b6, 0x60a7, 0x0000,
+	0x2001, 0x0006, 0x70a2, 0x1078, 0x1a14, 0x2001, 0x0000, 0x0078,
+	0x1b3b, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f,
+	0x007c, 0x2c04, 0xa005, 0x0040, 0x1b58, 0x2060, 0x600c, 0xa306,
+	0x00c0, 0x1b55, 0x6008, 0xa206, 0x00c0, 0x1b55, 0x6010, 0xa106,
+	0x00c0, 0x1b55, 0xa006, 0x0078, 0x1b5a, 0x6000, 0x0078, 0x1b42,
+	0xa085, 0x0001, 0x007c, 0x2011, 0x3541, 0x220c, 0xa18c, 0x000f,
+	0x2011, 0x013b, 0x2204, 0xa084, 0x0100, 0x0040, 0x1b6a, 0x2021,
+	0xff80, 0x2122, 0x007c, 0x0e7e, 0x68e4, 0xa08c, 0x0020, 0x0040,
+	0x1ba3, 0xa084, 0x0006, 0x00c0, 0x1ba3, 0x6010, 0x8007, 0xa084,
+	0x000f, 0x8003, 0x8003, 0x8003, 0xa0f0, 0x3600, 0x7004, 0xa084,
+	0x000a, 0x00c0, 0x1ba3, 0x7108, 0xa194, 0xff00, 0x0040, 0x1ba3,
+	0xa18c, 0x00ff, 0x2001, 0x0019, 0xa106, 0x0040, 0x1b96, 0x2001,
+	0x0032, 0xa106, 0x0040, 0x1b9a, 0x0078, 0x1b9e, 0x2009, 0x0020,
+	0x0078, 0x1ba0, 0x2009, 0x003f, 0x0078, 0x1ba0, 0x2011, 0x0000,
+	0x2100, 0xa205, 0x700a, 0x0e7f, 0x007c, 0x0068, 0x1ba5, 0x007e,
+	0x2071, 0x0000, 0x7018, 0xa084, 0x0001, 0x00c0, 0x1baa, 0x007f,
+	0x2e08, 0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002,
+	0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x007f, 0x2070,
+	0x007f, 0x0078, 0x1bc1, 0x107e, 0x007e, 0x127e, 0x2091, 0x2300,
+	0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0xa594, 0x003f, 0xa484, 0x4000,
+	0x0040, 0x1bd8, 0xa784, 0x007c, 0x00c0, 0x2d9c, 0x1078, 0x1ba5,
+	0xa49c, 0x000f, 0xa382, 0x0004, 0x0050, 0x1be0, 0x1078, 0x1ba5,
+	0x8507, 0xa084, 0x000f, 0x0079, 0x1be5, 0x1fea, 0x209a, 0x20c0,
+	0x22e6, 0x256b, 0x25b3, 0x25ea, 0x2665, 0x26bf, 0x2744, 0x1c0b,
+	0x1bf5, 0x1e53, 0x1f1d, 0x254a, 0x1bf5, 0x1078, 0x1ba5, 0x0018,
+	0x1bc8, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, 0x7003,
+	0x0000, 0x703f, 0x0000, 0x7030, 0xa005, 0x0040, 0x1c09, 0x7033,
+	0x0000, 0x0018, 0x1bc8, 0x705c, 0xa005, 0x00c0, 0x1cb6, 0x70a0,
+	0xa084, 0x0007, 0x0079, 0x1c14, 0x1cd6, 0x1c1c, 0x1c2a, 0x1c4b,
+	0x1c71, 0x1c9d, 0x1c9b, 0x1c1c, 0x7808, 0xa084, 0xfffd, 0x780a,
+	0x2009, 0x0046, 0x1078, 0x2412, 0x00c0, 0x1c28, 0x7003, 0x0004,
+	0x0078, 0x1bf7, 0x1078, 0x2d5e, 0x00c0, 0x1c49, 0x70b4, 0x8007,
+	0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, 0x78ab, 0x000c, 0x789b,
+	0x0060, 0x78ab, 0x0001, 0x785b, 0x0004, 0x2009, 0x00f7, 0x1078,
+	0x2410, 0x00c0, 0x1c49, 0x7003, 0x0004, 0x70c3, 0x000f, 0x7033,
+	0x3570, 0x0078, 0x1bf7, 0x1078, 0x2d5e, 0x00c0, 0x1c6f, 0x71b4,
+	0x8107, 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, 0xa18c, 0x0007,
+	0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab,
+	0x0002, 0x785b, 0x0004, 0x2009, 0x00f7, 0x1078, 0x2410, 0x00c0,
+	0x1c6f, 0x7003, 0x0004, 0x70c3, 0x000f, 0x7033, 0x3570, 0x0078,
+	0x1bf7, 0x1078, 0x2d5e, 0x00c0, 0x1c99, 0x71b4, 0x8107, 0x789b,
+	0x007e, 0x78aa, 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, 0x00c0,
+	0x79aa, 0x78ab, 0x0020, 0x71b8, 0x79aa, 0x78ab, 0x000d, 0x789b,
+	0x0060, 0x78ab, 0x0004, 0x785b, 0x0004, 0x2009, 0x00f7, 0x1078,
+	0x2410, 0x00c0, 0x1c99, 0x7003, 0x0004, 0x70c3, 0x000f, 0x7033,
+	0x3570, 0x0078, 0x1bf7, 0x0078, 0x1c4b, 0x1078, 0x2d5e, 0x00c0,
+	0x1bf7, 0x70bc, 0x2068, 0x789b, 0x0010, 0x6f10, 0x1078, 0x2ca1,
+	0x2c50, 0x6810, 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa, 0x6e18,
+	0x2041, 0x0001, 0x2001, 0x0004, 0x0078, 0x1dde, 0x1078, 0x2d5e,
+	0x00c0, 0x1bf7, 0x789b, 0x0010, 0x705c, 0x2068, 0x6f10, 0x1078,
+	0x2ca1, 0x2c50, 0x6008, 0xa085, 0x0010, 0x600a, 0x6810, 0xa084,
+	0x0007, 0xa085, 0x0080, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001,
+	0x1078, 0x2dc5, 0x2001, 0x0003, 0x0078, 0x1dc9, 0x0018, 0x1bc8,
+	0x7440, 0xa485, 0x0000, 0x0040, 0x1cf0, 0xa080, 0x3580, 0x2030,
+	0x7144, 0x8108, 0xa12a, 0x0048, 0x1ce7, 0x2009, 0x3580, 0x2164,
+	0x6504, 0x85ff, 0x00c0, 0x1cfd, 0x8421, 0x00c0, 0x1ce1, 0x7146,
+	0x7003, 0x0000, 0x703f, 0x0000, 0x0078, 0x1bf7, 0x7640, 0xa6b0,
+	0x3580, 0x7144, 0x2600, 0x0078, 0x1cec, 0x7146, 0x2568, 0x2558,
+	0x753e, 0x2c50, 0x6034, 0xa085, 0x0000, 0x00c0, 0x1cfa, 0x6708,
+	0x7736, 0xa784, 0x013f, 0x0040, 0x1d2f, 0xa784, 0x0021, 0x00c0,
+	0x1cfa, 0xa784, 0x0002, 0x0040, 0x1d1c, 0xa784, 0x0004, 0x0040,
+	0x1cfa, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0008, 0x00c0, 0x1cfa,
+	0xa784, 0x0010, 0x00c0, 0x1cfa, 0xa784, 0x0100, 0x0040, 0x1d2f,
+	0x6018, 0xa005, 0x00c0, 0x1cfa, 0xa7bc, 0xfeff, 0x670a, 0x681f,
+	0x0000, 0x6e18, 0xa684, 0x000e, 0x6118, 0x0040, 0x1d3f, 0x601c,
+	0xa102, 0x0048, 0x1d42, 0x0040, 0x1d42, 0x0078, 0x1cf6, 0x81ff,
+	0x00c0, 0x1cf6, 0xa784, 0x0080, 0x00c0, 0x1d48, 0x700c, 0x6022,
+	0xa7bc, 0xff7f, 0x670a, 0x6b10, 0x8307, 0xa084, 0x000f, 0x8003,
+	0x8003, 0x8003, 0xa080, 0x3600, 0x2060, 0x2048, 0x704a, 0x6000,
+	0x704e, 0x6004, 0x7052, 0x2a60, 0x0018, 0x1bc8, 0x789b, 0x0010,
+	0xa046, 0x1078, 0x2d5e, 0x00c0, 0x1bf7, 0x6b10, 0xa39c, 0x0007,
+	0xa39d, 0x00c0, 0x704c, 0xa084, 0x8000, 0x0040, 0x1d73, 0xa684,
+	0x0001, 0x0040, 0x1d75, 0xa39c, 0xffbf, 0xa684, 0x0010, 0x0040,
+	0x1d7b, 0xa39d, 0x0020, 0x7baa, 0x8840, 0xa684, 0x000e, 0x00c0,
+	0x1d86, 0xa7bd, 0x0010, 0x670a, 0x0078, 0x1dc7, 0x714c, 0xa18c,
+	0x0800, 0x0040, 0x2902, 0x2011, 0x0021, 0x8004, 0x8004, 0x0048,
+	0x1d9d, 0x2011, 0x0022, 0x8004, 0x0048, 0x1d9d, 0x2011, 0x0020,
+	0x8004, 0x0048, 0x1d9d, 0x0040, 0x1dc7, 0x7aaa, 0x8840, 0x1078,
+	0x2d77, 0x6a10, 0x610c, 0x8108, 0xa18c, 0x00ff, 0xa1e0, 0x3e80,
+	0x2c64, 0x8cff, 0x0040, 0x1dbe, 0x6010, 0xa206, 0x00c0, 0x1da8,
+	0x60b4, 0x8001, 0x60b6, 0x00c0, 0x1da3, 0x0c7e, 0x2a60, 0x6008,
+	0xa085, 0x0100, 0x600a, 0x0c7f, 0x0078, 0x1cd6, 0x1078, 0x2d5e,
+	0x00c0, 0x1bf7, 0x2a60, 0x610e, 0x79aa, 0x8840, 0x712e, 0x2001,
+	0x0001, 0x007e, 0x7150, 0xa184, 0x0018, 0x0040, 0x1ddd, 0xa184,
+	0x0010, 0x0040, 0x1dd7, 0x1078, 0x2acc, 0x00c0, 0x1ddd, 0xa184,
+	0x0008, 0x0040, 0x1ddd, 0x1078, 0x29e6, 0x007f, 0x7002, 0xa68c,
+	0x0060, 0x88ff, 0x0040, 0x1de6, 0xa18d, 0x0004, 0x795a, 0x69b2,
+	0x789b, 0x0060, 0x2800, 0x78aa, 0x789b, 0x0061, 0x6814, 0xa085,
+	0x8000, 0x6816, 0x78aa, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012c,
+	0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000a, 0x2098, 0x53a6,
+	0x147f, 0x137f, 0x157f, 0x6810, 0x8007, 0x789b, 0x007e, 0x78aa,
+	0x6d90, 0x7dd6, 0x7dde, 0x6e94, 0x7ed2, 0x7eda, 0x7830, 0xa084,
+	0x00c0, 0x00c0, 0x1e15, 0x0098, 0x1e1d, 0x6008, 0xa084, 0xffef,
+	0x600a, 0x1078, 0x2d77, 0x0078, 0x1bff, 0x7200, 0xa284, 0x0007,
+	0xa086, 0x0001, 0x00c0, 0x1e2a, 0x781b, 0x0049, 0x1078, 0x2d77,
+	0x0078, 0x1e3b, 0x6ab0, 0xa295, 0x2000, 0x7a5a, 0x781b, 0x0049,
+	0x1078, 0x2d77, 0x7200, 0x2500, 0xa605, 0x0040, 0x1e3b, 0xa284,
+	0x0007, 0x1079, 0x1e49, 0xad80, 0x0008, 0x7032, 0xa284, 0x0007,
+	0xa086, 0x0001, 0x00c0, 0x1e47, 0x6018, 0x8000, 0x601a, 0x0078,
+	0x1bf7, 0x1e51, 0x30f0, 0x30f0, 0x30df, 0x30f0, 0x1e51, 0x1e51,
+	0x1e51, 0x1078, 0x1ba5, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0f7e,
+	0x2079, 0x3500, 0x7898, 0x0f7f, 0xa084, 0x0001, 0x0040, 0x1e79,
+	0x70a0, 0xa086, 0x0001, 0x00c0, 0x1e68, 0x70a2, 0x0078, 0x1f01,
+	0x70a0, 0xa086, 0x0005, 0x00c0, 0x1e77, 0x70bc, 0x2068, 0x6817,
+	0x0004, 0x6813, 0x0000, 0x681c, 0xa085, 0x0008, 0x681e, 0x70a3,
+	0x0000, 0x157e, 0x2011, 0x0004, 0x71a0, 0xa186, 0x0001, 0x0040,
+	0x1e9b, 0xa186, 0x0007, 0x00c0, 0x1e8b, 0x2009, 0x352b, 0x200b,
+	0x0005, 0x0078, 0x1e9b, 0x2009, 0x3513, 0x2104, 0x2009, 0x3512,
+	0x200a, 0x2009, 0x352b, 0x200b, 0x0001, 0x70a3, 0x0000, 0x70a7,
+	0x0001, 0x0078, 0x1e9d, 0x70a3, 0x0000, 0x1078, 0x2ec7, 0x20a9,
+	0x0010, 0x2039, 0x0000, 0x1078, 0x2ba6, 0xa7b8, 0x0100, 0x0070,
+	0x1eab, 0x0078, 0x1ea3, 0x7000, 0x2020, 0x0079, 0x1eaf, 0x1edd,
+	0x1ec6, 0x1ec6, 0x1eb9, 0x1edd, 0x1edd, 0x1eb7, 0x1eb7, 0x1078,
+	0x1ba5, 0x2021, 0x3557, 0x2404, 0xa005, 0x0040, 0x1ec6, 0xad06,
+	0x00c0, 0x1ec6, 0x6800, 0x2022, 0x0078, 0x1ed6, 0x681c, 0xa084,
+	0x0001, 0x00c0, 0x1ed2, 0x6f10, 0x1078, 0x2ca1, 0x1078, 0x28d9,
+	0x0078, 0x1ed6, 0x7054, 0x2060, 0x6800, 0x6002, 0x6a16, 0x681c,
+	0xa085, 0x0008, 0x681e, 0x1078, 0x17dd, 0x2021, 0x3f80, 0x1078,
+	0x1f07, 0x2021, 0x3557, 0x1078, 0x1f07, 0x20a9, 0x0000, 0x2021,
+	0x3e80, 0x1078, 0x1f07, 0x8420, 0x0070, 0x1ef0, 0x0078, 0x1ee9,
+	0x20a9, 0x0080, 0x2061, 0x3680, 0x6018, 0x6110, 0xa102, 0x6012,
+	0x601b, 0x0000, 0xace0, 0x0010, 0x0070, 0x1f00, 0x0078, 0x1ef4,
+	0x157f, 0x7003, 0x0000, 0x703f, 0x0000, 0x0078, 0x1bf7, 0x047e,
+	0x2404, 0xa005, 0x0040, 0x1f19, 0x2068, 0x6800, 0x007e, 0x6a16,
+	0x681c, 0xa085, 0x0008, 0x681e, 0x1078, 0x17dd, 0x007f, 0x0078,
+	0x1f09, 0x047f, 0x2023, 0x0000, 0x007c, 0xa282, 0x0003, 0x0050,
+	0x1f23, 0x1078, 0x1ba5, 0x2300, 0x0079, 0x1f26, 0x1f29, 0x1f9c,
+	0x1faa, 0xa282, 0x0002, 0x0040, 0x1f2f, 0x1078, 0x1ba5, 0x70a0,
+	0x70a3, 0x0000, 0x70c3, 0x0000, 0x0079, 0x1f36, 0x1f3e, 0x1f3e,
+	0x1f40, 0x1f74, 0x2908, 0x1f3e, 0x1f74, 0x1f3e, 0x1078, 0x1ba5,
+	0x77b4, 0x1078, 0x2ba6, 0x77b4, 0xa7bc, 0x0f00, 0x1078, 0x2ca1,
+	0x6018, 0xa005, 0x0040, 0x1f6b, 0x2021, 0x3f80, 0x2009, 0x0004,
+	0x2011, 0x0010, 0x1078, 0x1fc5, 0x0040, 0x1f6b, 0x157e, 0x20a9,
+	0x0000, 0x2021, 0x3e80, 0x047e, 0x2009, 0x0004, 0x2011, 0x0010,
+	0x1078, 0x1fc5, 0x047f, 0x0040, 0x1f6a, 0x8420, 0x0070, 0x1f6a,
+	0x0078, 0x1f5b, 0x157f, 0x8738, 0xa784, 0x0007, 0x00c0, 0x1f46,
+	0x0078, 0x1bff, 0x0078, 0x1bff, 0x77b4, 0x1078, 0x2ca1, 0x6018,
+	0xa005, 0x0040, 0x1f9a, 0x2021, 0x3f80, 0x2009, 0x0005, 0x2011,
+	0x0020, 0x1078, 0x1fc5, 0x0040, 0x1f9a, 0x157e, 0x20a9, 0x0000,
+	0x2021, 0x3e80, 0x047e, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078,
+	0x1fc5, 0x047f, 0x0040, 0x1f99, 0x8420, 0x0070, 0x1f99, 0x0078,
+	0x1f8a, 0x157f, 0x0078, 0x1bff, 0x2200, 0x0079, 0x1f9f, 0x1fa2,
+	0x1fa4, 0x1fa4, 0x1078, 0x1ba5, 0x70a3, 0x0000, 0x70a7, 0x0001,
+	0x0078, 0x1bf7, 0x2200, 0x0079, 0x1fad, 0x1fb2, 0x1fa4, 0x1fb0,
+	0x1078, 0x1ba5, 0x1078, 0x241f, 0x7000, 0xa086, 0x0001, 0x00c0,
+	0x28af, 0x1078, 0x28ef, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078,
+	0x28a2, 0x0040, 0x28af, 0x0078, 0x1cd6, 0x2404, 0xa005, 0x0040,
+	0x1fe6, 0x2068, 0x2d04, 0x007e, 0x6810, 0xa706, 0x0040, 0x1fd4,
+	0x2d20, 0x007f, 0x0078, 0x1fc6, 0x007f, 0x2022, 0x6916, 0x681c,
+	0xa205, 0x681e, 0x1078, 0x17dd, 0x6010, 0x8001, 0x6012, 0x6008,
+	0xa084, 0xffef, 0x600a, 0x1078, 0x28ef, 0x007c, 0xa085, 0x0001,
+	0x0078, 0x1fe5, 0x2300, 0x0079, 0x1fed, 0x1ff2, 0x1ff0, 0x2035,
+	0x1078, 0x1ba5, 0x78e4, 0xa005, 0x00d0, 0x2015, 0x0018, 0x2015,
+	0x2008, 0xa084, 0x0030, 0x00c0, 0x2001, 0x781b, 0x0049, 0x0078,
+	0x1bf7, 0x78ec, 0xa084, 0x0003, 0x0040, 0x1ffd, 0x2100, 0xa084,
+	0x0007, 0x0079, 0x200b, 0x2023, 0x2029, 0x201d, 0x2013, 0x2d58,
+	0x2d58, 0x2013, 0x202f, 0x1078, 0x1ba5, 0x7000, 0xa005, 0x0040,
+	0x1bff, 0x2001, 0x0003, 0x0078, 0x22fa, 0x1078, 0x2b89, 0x781b,
+	0x0055, 0x0078, 0x1bf7, 0x1078, 0x2b89, 0x781b, 0x00dc, 0x0078,
+	0x1bf7, 0x1078, 0x2b89, 0x781b, 0x00e3, 0x0078, 0x1bf7, 0x1078,
+	0x2b89, 0x781b, 0x009d, 0x0078, 0x1bf7, 0xa584, 0x000f, 0x00c0,
+	0x205f, 0x1078, 0x241f, 0x7000, 0x0079, 0x203e, 0x2046, 0x2053,
+	0x2046, 0x28af, 0x2048, 0x28af, 0x2046, 0x2046, 0x1078, 0x1ba5,
+	0x71a0, 0x70a3, 0x0000, 0xa186, 0x0004, 0x00c0, 0x2051, 0x0078,
+	0x2908, 0x0078, 0x28af, 0x1078, 0x28ef, 0x6008, 0xa084, 0xffef,
+	0x600a, 0x1078, 0x28a2, 0x0040, 0x28af, 0x0078, 0x1cd6, 0x78e4,
+	0xa005, 0x00d0, 0x2015, 0x0018, 0x2015, 0x2008, 0xa084, 0x0030,
+	0x00c0, 0x206e, 0x781b, 0x0049, 0x0078, 0x1bf7, 0x78ec, 0xa084,
+	0x0003, 0x0040, 0x206a, 0x2100, 0xa184, 0x0007, 0x0079, 0x2078,
+	0x2088, 0x208e, 0x2082, 0x2080, 0x2d58, 0x2d58, 0x2080, 0x2d50,
+	0x1078, 0x1ba5, 0x1078, 0x2b91, 0x781b, 0x0055, 0x0078, 0x1bf7,
+	0x1078, 0x2b91, 0x781b, 0x00dc, 0x0078, 0x1bf7, 0x1078, 0x2b91,
+	0x781b, 0x00e3, 0x0078, 0x1bf7, 0x1078, 0x2b91, 0x781b, 0x009d,
+	0x0078, 0x1bf7, 0x2300, 0x0079, 0x209d, 0x20a2, 0x20a0, 0x20a4,
+	0x1078, 0x1ba5, 0x0078, 0x2665, 0x6817, 0x0008, 0x78a3, 0x0000,
+	0x79e4, 0xa184, 0x0030, 0x0040, 0x2665, 0x78ec, 0xa084, 0x0003,
+	0x0040, 0x2665, 0xa184, 0x0007, 0x0079, 0x20b6, 0x2023, 0x2029,
+	0x201d, 0x2d30, 0x2d58, 0x2d58, 0x20be, 0x2d50, 0x1078, 0x1ba5,
+	0xa282, 0x0005, 0x0050, 0x20c6, 0x1078, 0x1ba5, 0x2300, 0x0079,
+	0x20c9, 0x20cc, 0x22ce, 0x22da, 0x2200, 0x0079, 0x20cf, 0x20d4,
+	0x20d6, 0x20e9, 0x20d4, 0x22b3, 0x1078, 0x1ba5, 0x789b, 0x0018,
+	0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0048, 0x2b6a, 0xa08a,
+	0x0004, 0x00c8, 0x2b6a, 0x0079, 0x20e5, 0x2b6a, 0x2b6a, 0x2b6a,
+	0x2b0c, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0040, 0x20fe,
+	0xa184, 0x0018, 0x0040, 0x20fa, 0x0078, 0x2b6a, 0x7000, 0xa005,
+	0x00c0, 0x20f4, 0x2011, 0x0003, 0x0078, 0x2752, 0xa184, 0x00ff,
+	0xa08a, 0x0010, 0x00c8, 0x2b6a, 0x0079, 0x2106, 0x2118, 0x2116,
+	0x212e, 0x2130, 0x21c2, 0x2b6a, 0x2b6a, 0x21c4, 0x2b6a, 0x2b6a,
+	0x22af, 0x22af, 0x2b6a, 0x2b6a, 0x2b6a, 0x22b1, 0x1078, 0x1ba5,
+	0xa684, 0x1000, 0x0040, 0x2125, 0x2001, 0x0300, 0x8000, 0x8000,
+	0x783a, 0x781b, 0x009a, 0x0078, 0x1bf7, 0x6814, 0xa084, 0x8000,
+	0x0040, 0x212c, 0x6817, 0x0003, 0x0078, 0x2d30, 0x1078, 0x1ba5,
+	0x691c, 0x691e, 0xa684, 0x1800, 0x00c0, 0x214a, 0x681c, 0xa084,
+	0x0001, 0x00c0, 0x2152, 0x6814, 0xa086, 0x0008, 0x00c0, 0x2142,
+	0x6817, 0x0000, 0xa684, 0x0400, 0x0040, 0x21be, 0x781b, 0x0058,
+	0x0078, 0x1bf7, 0xa684, 0x1000, 0x0040, 0x2152, 0x781b, 0x0058,
+	0x0078, 0x1bf7, 0xa684, 0x0060, 0x0040, 0x21ba, 0xa684, 0x0800,
+	0x0040, 0x21ba, 0xa684, 0x8000, 0x00c0, 0x2160, 0x0078, 0x217a,
+	0xa6b4, 0x7fff, 0x7e5a, 0x6eb2, 0x789b, 0x0074, 0x7aac, 0x79ac,
+	0x78ac, 0x801b, 0x00c8, 0x216d, 0x8000, 0xa084, 0x003f, 0xa108,
+	0xa291, 0x0000, 0x6b94, 0x2100, 0xa302, 0x68ae, 0x6b90, 0x2200,
+	0xa303, 0x68aa, 0xa684, 0x4000, 0x0040, 0x2182, 0xa6b4, 0xbfff,
+	0x7e5a, 0x6eb2, 0x7000, 0xa086, 0x0003, 0x00c0, 0x218f, 0x1078,
+	0x2f3a, 0x1078, 0x30df, 0x781b, 0x0067, 0x0078, 0x1bf7, 0xa006,
+	0x1078, 0x3194, 0x6aac, 0x69a8, 0x6c94, 0x6b90, 0x2200, 0xa105,
+	0x0040, 0x219e, 0x2200, 0xa422, 0x2100, 0xa31b, 0x7cd2, 0x7bd6,
+	0x2300, 0xa405, 0x00c0, 0x21ac, 0xa6b5, 0x4000, 0x7e5a, 0x6eb2,
+	0x781b, 0x0067, 0x0078, 0x1bf7, 0x781b, 0x0067, 0x2200, 0xa115,
+	0x00c0, 0x21b6, 0x1078, 0x30f0, 0x0078, 0x1bf7, 0x1078, 0x311d,
+	0x0078, 0x1bf7, 0x781b, 0x006a, 0x0078, 0x1bf7, 0x781b, 0x0058,
+	0x0078, 0x1bf7, 0x1078, 0x1ba5, 0x0078, 0x2221, 0x691c, 0xa184,
+	0x0100, 0x0040, 0x21dc, 0xa18c, 0xfeff, 0x691e, 0x0c7e, 0x7048,
 	0x2060, 0x6000, 0xa084, 0xefff, 0x6002, 0x6004, 0xa084, 0xfff5,
-	0x6006, 0x0c7f, 0x0078, 0x2198, 0xa184, 0x0200, 0x0040, 0x2198,
+	0x6006, 0x0c7f, 0x0078, 0x2210, 0xa184, 0x0200, 0x0040, 0x2210,
 	0xa18c, 0xfdff, 0x691e, 0x0c7e, 0x7048, 0x2060, 0x6000, 0xa084,
 	0xdfff, 0x6002, 0x6004, 0xa084, 0xffef, 0x6006, 0x2008, 0x2c48,
-	0x0c7f, 0xa184, 0x0008, 0x0040, 0x2198, 0x1078, 0x2bf8, 0x1078,
-	0x294d, 0x88ff, 0x0040, 0x2198, 0x789b, 0x0060, 0x2800, 0x78aa,
-	0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2194,
-	0x781b, 0x0055, 0x0078, 0x1ba0, 0x781b, 0x0069, 0x0078, 0x1ba0,
-	0x7e58, 0xa684, 0x0400, 0x00c0, 0x21a1, 0x781b, 0x0058, 0x0078,
-	0x1ba0, 0x781b, 0x006a, 0x0078, 0x1ba0, 0x0078, 0x2acb, 0x0078,
-	0x2acb, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x0040, 0x21a7,
+	0x0c7f, 0xa184, 0x0008, 0x0040, 0x2210, 0x1078, 0x2c9d, 0x1078,
+	0x29e6, 0x88ff, 0x0040, 0x2210, 0x789b, 0x0060, 0x2800, 0x78aa,
+	0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x220c,
+	0x781b, 0x0055, 0x0078, 0x1bf7, 0x781b, 0x0069, 0x0078, 0x1bf7,
+	0x7e58, 0xa684, 0x0400, 0x00c0, 0x2219, 0x781b, 0x0058, 0x0078,
+	0x1bf7, 0x781b, 0x006a, 0x0078, 0x1bf7, 0x0078, 0x2b70, 0x0078,
+	0x2b70, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x0040, 0x221f,
 	0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0,
-	0x21cc, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x21c4,
-	0x0048, 0x21c4, 0x0078, 0x21c6, 0x0078, 0x214e, 0x24a8, 0x7aa8,
-	0x00f0, 0x21c6, 0x0078, 0x21b2, 0xa284, 0x00f0, 0xa086, 0x0020,
-	0x00c0, 0x2228, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040, 0x21dc,
-	0x0048, 0x21dc, 0x0078, 0x2225, 0xa286, 0x0023, 0x0040, 0x21a7,
+	0x2244, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x223c,
+	0x0048, 0x223c, 0x0078, 0x223e, 0x0078, 0x21c6, 0x24a8, 0x7aa8,
+	0x00f0, 0x223e, 0x0078, 0x222a, 0xa284, 0x00f0, 0xa086, 0x0020,
+	0x00c0, 0x22a0, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040, 0x2254,
+	0x0048, 0x2254, 0x0078, 0x229d, 0xa286, 0x0023, 0x0040, 0x221f,
 	0x6818, 0xa084, 0xfff1, 0x681a, 0x7e58, 0xa684, 0xfff1, 0xa085,
 	0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085, 0x0010, 0x600a, 0x0c7e,
 	0x7048, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0010,
-	0x0040, 0x2200, 0x1078, 0x2bf8, 0x1078, 0x2a33, 0x0078, 0x220f,
+	0x0040, 0x2278, 0x1078, 0x2c9d, 0x1078, 0x2acc, 0x0078, 0x2287,
 	0x0c7e, 0x7048, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xa184,
-	0x0008, 0x0040, 0x2198, 0x1078, 0x2bf8, 0x1078, 0x294d, 0x88ff,
-	0x0040, 0x2198, 0x789b, 0x0060, 0x2800, 0x78aa, 0xa6b5, 0x0004,
-	0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2221, 0x781b, 0x0055, 0x0078,
-	0x1ba0, 0x781b, 0x0069, 0x0078, 0x1ba0, 0x7aa8, 0x0078, 0x21b2,
-	0x8318, 0x2300, 0xa102, 0x0040, 0x2231, 0x0048, 0x2231, 0x0078,
-	0x21b2, 0xa284, 0x0080, 0x00c0, 0x2ad1, 0x0078, 0x2acb, 0x0078,
-	0x2ad1, 0x0078, 0x2ac5, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff,
-	0xa08e, 0x0001, 0x0040, 0x2246, 0x1078, 0x1b4e, 0x7aa8, 0xa294,
-	0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x2ac5,
-	0x0079, 0x2252, 0x2ac5, 0x28a0, 0x2ac5, 0x29ce, 0xa282, 0x0000,
-	0x00c0, 0x225c, 0x1078, 0x1b4e, 0x1078, 0x2ae4, 0x781b, 0x0069,
-	0x0078, 0x1ba0, 0xa282, 0x0003, 0x00c0, 0x2268, 0x1078, 0x1b4e,
-	0x1078, 0x2af4, 0x781b, 0x0069, 0x0078, 0x1ba0, 0xa282, 0x0004,
-	0x0050, 0x2274, 0x1078, 0x1b4e, 0x2300, 0x0079, 0x2277, 0x227a,
-	0x2351, 0x237b, 0xa286, 0x0003, 0x0040, 0x2280, 0x1078, 0x1b4e,
-	0x2001, 0x0000, 0x703a, 0x7000, 0xa084, 0x0007, 0x0079, 0x2288,
-	0x2290, 0x2292, 0x2292, 0x2471, 0x2499, 0x243b, 0x2290, 0x2290,
-	0x1078, 0x1b4e, 0xa684, 0x1000, 0x00c0, 0x229a, 0x1078, 0x2e0e,
-	0x0040, 0x232b, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x22e2, 0xa186,
-	0x0008, 0x00c0, 0x22b1, 0x1078, 0x2853, 0x6008, 0xa084, 0xffef,
-	0x600a, 0x1078, 0x2806, 0x0040, 0x22e2, 0x1078, 0x2e0e, 0x0078,
-	0x22c9, 0xa186, 0x0028, 0x00c0, 0x22e2, 0x1078, 0x2e0e, 0x6008,
-	0xa084, 0xffef, 0x600a, 0x6018, 0xa005, 0x0040, 0x22c9, 0x8001,
-	0x601a, 0xa005, 0x0040, 0x22c9, 0x8001, 0xa005, 0x0040, 0x22c9,
-	0x601e, 0x681c, 0xa084, 0x0001, 0x0040, 0x1ba8, 0x681c, 0xa084,
+	0x0008, 0x0040, 0x2210, 0x1078, 0x2c9d, 0x1078, 0x29e6, 0x88ff,
+	0x0040, 0x2210, 0x789b, 0x0060, 0x2800, 0x78aa, 0xa6b5, 0x0004,
+	0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2299, 0x781b, 0x0055, 0x0078,
+	0x1bf7, 0x781b, 0x0069, 0x0078, 0x1bf7, 0x7aa8, 0x0078, 0x222a,
+	0x8318, 0x2300, 0xa102, 0x0040, 0x22a9, 0x0048, 0x22a9, 0x0078,
+	0x222a, 0xa284, 0x0080, 0x00c0, 0x2b76, 0x0078, 0x2b70, 0x0078,
+	0x2b76, 0x0078, 0x2b6a, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff,
+	0xa08e, 0x0001, 0x0040, 0x22be, 0x1078, 0x1ba5, 0x7aa8, 0xa294,
+	0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x2b6a,
+	0x0079, 0x22ca, 0x2b6a, 0x2939, 0x2b6a, 0x2a67, 0xa282, 0x0000,
+	0x00c0, 0x22d4, 0x1078, 0x1ba5, 0x1078, 0x2b89, 0x781b, 0x0069,
+	0x0078, 0x1bf7, 0xa282, 0x0003, 0x00c0, 0x22e0, 0x1078, 0x1ba5,
+	0x1078, 0x2b99, 0x781b, 0x0069, 0x0078, 0x1bf7, 0xa282, 0x0004,
+	0x0050, 0x22ec, 0x1078, 0x1ba5, 0x2300, 0x0079, 0x22ef, 0x22f2,
+	0x23c9, 0x23fa, 0xa286, 0x0003, 0x0040, 0x22f8, 0x1078, 0x1ba5,
+	0x2001, 0x0000, 0x703a, 0x7000, 0xa084, 0x0007, 0x0079, 0x2300,
+	0x2308, 0x230a, 0x230a, 0x2508, 0x2530, 0x24d2, 0x2308, 0x2308,
+	0x1078, 0x1ba5, 0xa684, 0x1000, 0x00c0, 0x2312, 0x1078, 0x2ec7,
+	0x0040, 0x23a3, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x235a, 0xa186,
+	0x0008, 0x00c0, 0x2329, 0x1078, 0x28ef, 0x6008, 0xa084, 0xffef,
+	0x600a, 0x1078, 0x28a2, 0x0040, 0x235a, 0x1078, 0x2ec7, 0x0078,
+	0x2341, 0xa186, 0x0028, 0x00c0, 0x235a, 0x1078, 0x2ec7, 0x6008,
+	0xa084, 0xffef, 0x600a, 0x6018, 0xa005, 0x0040, 0x2341, 0x8001,
+	0x601a, 0xa005, 0x0040, 0x2341, 0x8001, 0xa005, 0x0040, 0x2341,
+	0x601e, 0x681c, 0xa084, 0x0001, 0x0040, 0x1bff, 0x681c, 0xa084,
 	0xfffe, 0x681e, 0x7054, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f,
-	0x6004, 0x6802, 0xa005, 0x2d00, 0x00c0, 0x22df, 0x6002, 0x6006,
-	0x0078, 0x1ba8, 0x017e, 0x1078, 0x23a0, 0x017f, 0xa684, 0xdf00,
-	0x681a, 0x6827, 0x0000, 0x6f10, 0x81ff, 0x0040, 0x232b, 0xa186,
-	0x0002, 0x00c0, 0x2323, 0xa684, 0x0800, 0x00c0, 0x22ff, 0xa684,
-	0x0060, 0x0040, 0x22ff, 0x78d8, 0x7adc, 0x682e, 0x6a2a, 0x8717,
-	0xa294, 0x000f, 0x8213, 0x8213, 0x8213, 0xa290, 0x3500, 0xa290,
-	0x0000, 0x221c, 0xa384, 0x0100, 0x00c0, 0x2310, 0x0078, 0x2316,
+	0x6004, 0x6802, 0xa005, 0x2d00, 0x00c0, 0x2357, 0x6002, 0x6006,
+	0x0078, 0x1bff, 0x017e, 0x1078, 0x241f, 0x017f, 0xa684, 0xdf00,
+	0x681a, 0x6827, 0x0000, 0x6f10, 0x81ff, 0x0040, 0x23a3, 0xa186,
+	0x0002, 0x00c0, 0x239b, 0xa684, 0x0800, 0x00c0, 0x2377, 0xa684,
+	0x0060, 0x0040, 0x2377, 0x78d8, 0x7adc, 0x682e, 0x6a2a, 0x8717,
+	0xa294, 0x000f, 0x8213, 0x8213, 0x8213, 0xa290, 0x3600, 0xa290,
+	0x0000, 0x221c, 0xa384, 0x0100, 0x00c0, 0x2388, 0x0078, 0x238e,
 	0x8210, 0x2204, 0xa085, 0x0018, 0x2012, 0x8211, 0xa384, 0x0400,
-	0x0040, 0x2323, 0x689c, 0xa084, 0x0100, 0x00c0, 0x2323, 0x1078,
-	0x23fa, 0x0078, 0x1ba8, 0xa186, 0x0018, 0x0040, 0x232b, 0xa186,
-	0x0014, 0x0040, 0x1ba8, 0x6912, 0x6814, 0xa084, 0x8000, 0x0040,
-	0x2333, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x1078, 0x2844,
-	0x1078, 0x2853, 0x00c0, 0x2340, 0x6008, 0xa084, 0xffef, 0x600a,
-	0x681c, 0xa084, 0x0001, 0x00c0, 0x2349, 0x1078, 0x283d, 0x0078,
-	0x234d, 0x7054, 0x2060, 0x6800, 0x6002, 0x1078, 0x17be, 0x0078,
-	0x1ba8, 0xa282, 0x0004, 0x0048, 0x2357, 0x1078, 0x1b4e, 0x2200,
-	0x0079, 0x235a, 0x235e, 0x2360, 0x2366, 0x2360, 0x1078, 0x1b4e,
-	0x1078, 0x2ae4, 0x781b, 0x0069, 0x0078, 0x1ba0, 0x7890, 0x8007,
-	0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c,
-	0x00ff, 0xa186, 0x0003, 0x0040, 0x2377, 0x0078, 0x2ac5, 0x781b,
-	0x006a, 0x0078, 0x1ba0, 0x681c, 0xa085, 0x0004, 0x681e, 0x82ff,
-	0x00c0, 0x2386, 0x1078, 0x2ae4, 0x0078, 0x238d, 0x8211, 0x0040,
-	0x238b, 0x1078, 0x1b4e, 0x1078, 0x2af4, 0x781b, 0x0069, 0x0078,
-	0x1ba0, 0x1078, 0x2cc6, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x239d,
-	0x0018, 0x239d, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c,
-	0xa684, 0x0060, 0x00c0, 0x23aa, 0x682f, 0x0000, 0x682b, 0x0000,
-	0x0078, 0x23f9, 0xa684, 0x0800, 0x00c0, 0x23b1, 0x1078, 0x2e0e,
-	0x007c, 0xa684, 0x0020, 0x0040, 0x23d3, 0x78d0, 0x8003, 0x00c8,
-	0x23bf, 0xa006, 0x1078, 0x30a0, 0x78d4, 0x1078, 0x3103, 0xa684,
-	0x4000, 0x0040, 0x23c9, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078,
-	0x23ae, 0x7038, 0xa005, 0x00c0, 0x23cd, 0x79d8, 0x7adc, 0x692e,
-	0x6a2a, 0x0078, 0x23ae, 0xa684, 0x4000, 0x0040, 0x23dd, 0x682f,
-	0x0000, 0x682b, 0x0000, 0x0078, 0x23ae, 0x7038, 0xa005, 0x00c0,
-	0x23e3, 0x703b, 0x0007, 0x79d8, 0x7adc, 0x78d0, 0x80f3, 0x00c8,
-	0x23ea, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x692e,
-	0x6a2a, 0x2100, 0xa205, 0x00c0, 0x23f7, 0x0078, 0x23ae, 0x1078,
-	0x30a0, 0x007c, 0xa384, 0x0200, 0x0040, 0x2402, 0x6008, 0xa085,
-	0x0002, 0x600a, 0x6817, 0x0006, 0x6a28, 0x692c, 0x6a3a, 0x693e,
-	0x682b, 0x0300, 0x682f, 0x0000, 0x6833, 0x2000, 0x6893, 0x0000,
-	0x6897, 0x0020, 0x7000, 0x0079, 0x2415, 0x241d, 0x241f, 0x2428,
-	0x241d, 0x241d, 0x241d, 0x241d, 0x241d, 0x1078, 0x1b4e, 0x681c,
-	0xa084, 0x0001, 0x00c0, 0x2428, 0x1078, 0x283d, 0x0078, 0x242e,
-	0x7054, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60, 0x2021, 0x3457,
-	0x2404, 0xa005, 0x0040, 0x2437, 0x2020, 0x0078, 0x2430, 0x2d22,
-	0x206b, 0x0000, 0x007c, 0x77b4, 0x1078, 0x2b01, 0xa7bc, 0x0f00,
-	0x1078, 0x2bfc, 0x6018, 0xa005, 0x0040, 0x246a, 0x0d7e, 0x2001,
-	0x3e90, 0x2068, 0x0d7f, 0x2021, 0x3e80, 0x2009, 0x0004, 0x2011,
-	0x0010, 0x1078, 0x1f69, 0x0040, 0x246a, 0x157e, 0x20a9, 0x0000,
-	0x2021, 0x3d80, 0x047e, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078,
-	0x1f69, 0x047f, 0x0040, 0x2469, 0x8420, 0x0070, 0x2469, 0x0078,
-	0x245a, 0x157f, 0x8738, 0xa784, 0x0007, 0x00c0, 0x2440, 0x0078,
-	0x1ba8, 0x1078, 0x2844, 0x1078, 0x2853, 0x6827, 0x0000, 0x789b,
-	0x000e, 0x6f10, 0x6813, 0x0002, 0x1078, 0x30d4, 0xa684, 0x0800,
-	0x0040, 0x2486, 0x6918, 0xa18d, 0x2000, 0x691a, 0x6814, 0xa084,
-	0x8000, 0x0040, 0x248d, 0x6817, 0x0000, 0x2021, 0x3457, 0x6800,
-	0x2022, 0x6a38, 0x693c, 0x6a2a, 0x692e, 0x1078, 0x17be, 0x0078,
-	0x1ba8, 0x1078, 0x23a0, 0x6827, 0x0000, 0x789b, 0x000e, 0x6f10,
-	0x1078, 0x2ccb, 0xa08c, 0x00ff, 0x6912, 0x6814, 0xa084, 0x8000,
-	0x0040, 0x24ac, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x70a3,
-	0x0000, 0x0078, 0x1ba8, 0xa006, 0x1078, 0x2e0e, 0x6813, 0x0000,
-	0x6817, 0x0001, 0xa68c, 0xdf00, 0x691a, 0x6827, 0x0000, 0x7000,
-	0x0079, 0x24c2, 0x24ca, 0x24cc, 0x24cc, 0x24ce, 0x24ce, 0x24ce,
-	0x24ca, 0x24ca, 0x1078, 0x1b4e, 0x1078, 0x2853, 0x6008, 0xa084,
-	0xffef, 0x600a, 0x0078, 0x281e, 0x2300, 0x0079, 0x24d7, 0x24da,
-	0x24dc, 0x251a, 0x1078, 0x1b4e, 0x7000, 0x0079, 0x24df, 0x24e7,
-	0x24e9, 0x24e9, 0x24f4, 0x24e9, 0x24fb, 0x24e7, 0x24e7, 0x1078,
-	0x1b4e, 0xa684, 0x2000, 0x00c0, 0x24f4, 0xa6b5, 0x2000, 0x7e5a,
-	0x1078, 0x2ffc, 0x0078, 0x2c7f, 0x6814, 0xa084, 0x8000, 0x0040,
-	0x24fb, 0x6817, 0x0007, 0x2009, 0x3418, 0x210c, 0xa186, 0x0000,
-	0x0040, 0x2510, 0xa186, 0x0001, 0x0040, 0x2514, 0x2009, 0x342b,
-	0x200b, 0x000b, 0x70a3, 0x0001, 0x781b, 0x0046, 0x0078, 0x1ba0,
-	0x781b, 0x00dd, 0x0078, 0x1ba0, 0x2009, 0x342b, 0x200b, 0x000a,
-	0x0078, 0x1ba0, 0x1078, 0x1b4e, 0x2300, 0x0079, 0x251f, 0x2522,
-	0x2524, 0x2547, 0x1078, 0x1b4e, 0x7000, 0x0079, 0x2527, 0x252f,
-	0x2531, 0x2531, 0x253c, 0x2531, 0x2543, 0x252f, 0x252f, 0x1078,
-	0x1b4e, 0xa684, 0x2000, 0x00c0, 0x253c, 0xa6b5, 0x2000, 0x7e5a,
-	0x1078, 0x2ffc, 0x0078, 0x2c7f, 0x6814, 0xa084, 0x8000, 0x0040,
-	0x2543, 0x6817, 0x0007, 0x781b, 0x00e4, 0x0078, 0x1ba0, 0x681c,
-	0xa085, 0x0004, 0x681e, 0x1078, 0x2c4a, 0xa6b5, 0x0800, 0x1078,
-	0x2ae4, 0x781b, 0x0069, 0x0078, 0x1ba0, 0x2300, 0x0079, 0x2558,
-	0x255b, 0x255d, 0x255f, 0x1078, 0x1b4e, 0x1078, 0x1b4e, 0xa684,
-	0x0400, 0x00c0, 0x257e, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab,
-	0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xa184, 0x0020, 0x0040,
-	0x2576, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x257a, 0x2001, 0x0014,
-	0x0078, 0x2282, 0xa184, 0x0007, 0x0079, 0x25b6, 0x7a90, 0xa294,
-	0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0040, 0x25b4, 0x789b,
-	0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, 0x25a5, 0x7ba8, 0x7ba8,
-	0xa386, 0x0001, 0x00c0, 0x2598, 0x2009, 0xfff7, 0x0078, 0x259e,
-	0xa386, 0x0003, 0x00c0, 0x25a5, 0x2009, 0xffef, 0x0c7e, 0x7048,
-	0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab,
-	0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x691c, 0xa18c,
-	0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2c7f, 0x1fc3, 0x1fc9,
-	0x25c0, 0x25c8, 0x25be, 0x25be, 0x25be, 0x2c7f, 0x1078, 0x1b4e,
-	0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2c87,
-	0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2c7f,
-	0x79e4, 0xa184, 0x0030, 0x0040, 0x25da, 0x78ec, 0xa084, 0x0003,
-	0x00c0, 0x25e2, 0x6814, 0xa085, 0x8000, 0x6816, 0x2001, 0x0014,
-	0x0078, 0x2282, 0xa184, 0x0007, 0x0079, 0x25e6, 0x2c7f, 0x2c7f,
-	0x25ee, 0x2c7f, 0x2ca7, 0x2ca7, 0x2c7f, 0x2c7f, 0xa684, 0x0400,
-	0x00c0, 0x261f, 0x681c, 0xa084, 0x0001, 0x0040, 0x2c87, 0xa68c,
-	0x2060, 0xa18c, 0xfffb, 0x795a, 0x69b2, 0x789b, 0x0060, 0x78ab,
-	0x0000, 0x789b, 0x0061, 0x6814, 0xa085, 0x8000, 0x6816, 0x78aa,
-	0x157e, 0x137e, 0x147e, 0x20a1, 0x012c, 0x789b, 0x0000, 0x8000,
-	0x80ac, 0xad80, 0x000a, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f,
-	0x6810, 0x8007, 0x789b, 0x007e, 0x78aa, 0x0078, 0x2c87, 0x6814,
-	0xa084, 0x8000, 0x0040, 0x2626, 0x6817, 0x0008, 0x781b, 0x00d8,
-	0x0078, 0x1ba0, 0x2300, 0x0079, 0x262d, 0x2632, 0x26ac, 0x2630,
-	0x1078, 0x1b4e, 0x7000, 0xa084, 0x0007, 0x0079, 0x2637, 0x263f,
-	0x2641, 0x265d, 0x263f, 0x263f, 0x243b, 0x263f, 0x263f, 0x1078,
-	0x1b4e, 0x691c, 0xa18d, 0x0001, 0x691e, 0x6800, 0x6006, 0xa005,
-	0x00c0, 0x264b, 0x6002, 0x6818, 0xa084, 0x000e, 0x0040, 0x2657,
-	0x7014, 0x68b6, 0x712c, 0xa188, 0x3d80, 0x0078, 0x2659, 0x2009,
-	0x3e80, 0x2104, 0x6802, 0x2d0a, 0x7156, 0x691c, 0x691e, 0x6eb2,
-	0xa684, 0x0060, 0x0040, 0x26aa, 0xa684, 0x0800, 0x00c0, 0x266e,
-	0x6890, 0x6894, 0x1078, 0x2e0e, 0x0078, 0x26aa, 0xa684, 0x0020,
-	0x0040, 0x2680, 0xa006, 0x1078, 0x30a0, 0x78d0, 0x8003, 0x00c8,
-	0x267c, 0x78d4, 0x1078, 0x3103, 0x79d8, 0x7adc, 0x0078, 0x2684,
-	0x1078, 0x2c09, 0x1078, 0x30a0, 0xa684, 0x8000, 0x0040, 0x26aa,
-	0xa684, 0x7fff, 0x68b2, 0x789b, 0x0074, 0x1078, 0x2ccb, 0x2010,
-	0x1078, 0x2ccb, 0x2008, 0xa684, 0x0020, 0x00c0, 0x26a2, 0x1078,
-	0x2ccb, 0x801b, 0x00c8, 0x269d, 0x8000, 0xa084, 0x003f, 0xa108,
-	0xa291, 0x0000, 0x6b94, 0x2100, 0xa302, 0x68ae, 0x6b90, 0x2200,
-	0xa303, 0x68aa, 0x0078, 0x1ba8, 0x0078, 0x2ad1, 0x7033, 0x0000,
-	0xa282, 0x0005, 0x0050, 0x26b6, 0x1078, 0x1b4e, 0x2300, 0x0079,
-	0x26b9, 0x26bc, 0x26c6, 0x26e9, 0x2200, 0x0079, 0x26bf, 0x26c4,
-	0x2ad1, 0x26c4, 0x2712, 0x2763, 0x1078, 0x1b4e, 0x7000, 0xa086,
-	0x0001, 0x00c0, 0x26d3, 0x1078, 0x2853, 0x1078, 0x2e0e, 0x7034,
-	0x600a, 0x0078, 0x26d8, 0x7000, 0xa086, 0x0003, 0x0040, 0x26cd,
-	0x7003, 0x0005, 0x2001, 0x3e90, 0x2068, 0x703e, 0x7032, 0x2200,
-	0x0079, 0x26e2, 0x2ad1, 0x26e7, 0x2712, 0x26e7, 0x2ad1, 0x1078,
-	0x1b4e, 0x7000, 0xa086, 0x0001, 0x00c0, 0x26f6, 0x1078, 0x2853,
-	0x1078, 0x2e0e, 0x7034, 0x600a, 0x0078, 0x26fb, 0x7000, 0xa086,
-	0x0003, 0x0040, 0x26f0, 0x7003, 0x0005, 0x2001, 0x3e90, 0x2068,
-	0x703e, 0x7032, 0x2200, 0x0079, 0x2705, 0x270c, 0x270a, 0x270c,
-	0x270a, 0x270c, 0x1078, 0x1b4e, 0x1078, 0x2af4, 0x781b, 0x0069,
-	0x0078, 0x1ba0, 0x7000, 0xa086, 0x0001, 0x00c0, 0x271f, 0x1078,
-	0x2853, 0x1078, 0x2e0e, 0x7034, 0x600a, 0x0078, 0x2724, 0x7000,
-	0xa086, 0x0003, 0x0040, 0x2719, 0x7003, 0x0002, 0x7a80, 0xa294,
-	0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215, 0x2069,
-	0x3e80, 0x2d04, 0x2d08, 0x7156, 0x2068, 0xa005, 0x0040, 0x273f,
-	0x6810, 0xa206, 0x0040, 0x2758, 0x6800, 0x0078, 0x2732, 0x7003,
-	0x0005, 0x2001, 0x3e90, 0x2068, 0x703e, 0x7032, 0x157e, 0x20a9,
-	0x002e, 0x2003, 0x0000, 0x8000, 0x0070, 0x2750, 0x0078, 0x2749,
-	0x157f, 0x6a12, 0x68b3, 0x0700, 0x681f, 0x0800, 0x6823, 0x0003,
-	0x6eb0, 0x7e5a, 0x681c, 0xa084, 0x0c00, 0x0040, 0x27b9, 0x1078,
-	0x2aec, 0x0078, 0x27b9, 0x7000, 0xa086, 0x0001, 0x00c0, 0x2770,
-	0x1078, 0x2853, 0x1078, 0x2e0e, 0x7034, 0x600a, 0x0078, 0x2775,
-	0x7000, 0xa086, 0x0003, 0x0040, 0x276a, 0x7003, 0x0002, 0x7a80,
-	0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215,
-	0x79a8, 0x79a8, 0xa18c, 0x00ff, 0xa1e8, 0x3d80, 0x2d04, 0x2d08,
-	0x7156, 0x2068, 0xa005, 0x0040, 0x2794, 0x6810, 0xa206, 0x0040,
-	0x27ad, 0x6800, 0x0078, 0x2787, 0x7003, 0x0005, 0x2001, 0x3e90,
-	0x2068, 0x703e, 0x7032, 0x157e, 0x20a9, 0x002e, 0x2003, 0x0000,
-	0x8000, 0x0070, 0x27a5, 0x0078, 0x279e, 0x157f, 0x6a12, 0x68b3,
-	0x0700, 0x681f, 0x0800, 0x6823, 0x0003, 0x6eb0, 0x7e5a, 0x681c,
-	0xa084, 0x0c00, 0x0040, 0x27b9, 0x1078, 0x2ae8, 0x7e58, 0x0078,
-	0x27b9, 0x027e, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
-	0xa080, 0x3500, 0x2060, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052,
-	0xa684, 0x0060, 0x0040, 0x27ea, 0x6b94, 0x6c90, 0x69a8, 0x68ac,
-	0xa105, 0x00c0, 0x27db, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x1078,
-	0x2ffc, 0x0078, 0x27ea, 0x68ac, 0xa31a, 0x2100, 0xa423, 0x2400,
-	0xa305, 0x0040, 0x27ea, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68ac,
-	0x1078, 0x3029, 0x077f, 0x1078, 0x2bfc, 0x2009, 0x006a, 0xa684,
-	0x0008, 0x0040, 0x27f5, 0x2009, 0x0069, 0xa6b5, 0x2000, 0x7e5a,
-	0x791a, 0x2d00, 0x703e, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003,
-	0x8003, 0xa080, 0x3500, 0x2048, 0x0078, 0x1ba0, 0x6020, 0xa005,
-	0x0040, 0x2812, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a,
-	0x7010, 0x6026, 0x007c, 0xa006, 0x1078, 0x2e0e, 0x6813, 0x0000,
-	0x6817, 0x0001, 0x681f, 0x0040, 0x681b, 0x0100, 0x7000, 0xa084,
-	0x0007, 0x0079, 0x2823, 0x282b, 0x282d, 0x282d, 0x2839, 0x2835,
-	0x282b, 0x282b, 0x282b, 0x1078, 0x1b4e, 0x1078, 0x2844, 0x1078,
-	0x283d, 0x1078, 0x17be, 0x0078, 0x1ba8, 0x70a3, 0x0000, 0x0078,
-	0x1ba8, 0x6817, 0x0000, 0x0078, 0x2471, 0x6800, 0xa005, 0x00c0,
-	0x2842, 0x6002, 0x6006, 0x007c, 0x6010, 0xa005, 0x0040, 0x284d,
-	0x8001, 0x00d0, 0x284d, 0x1078, 0x1b4e, 0x6012, 0x6008, 0xa084,
-	0xffef, 0x600a, 0x007c, 0x6018, 0xa005, 0x0040, 0x2859, 0x8001,
-	0x601a, 0x007c, 0x1078, 0x2cc6, 0x6814, 0xa084, 0x8000, 0x0040,
-	0x2863, 0x6817, 0x0018, 0x0078, 0x2894, 0x1078, 0x2cc6, 0x6814,
-	0xa084, 0x8000, 0x0040, 0x286e, 0x6817, 0x0019, 0x0078, 0x2894,
-	0x1078, 0x2cc6, 0x6814, 0xa084, 0x8000, 0x0040, 0x2879, 0x6817,
-	0x001a, 0x0078, 0x2894, 0x71b8, 0xa18c, 0x00ff, 0xa1e8, 0x3d80,
-	0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, 0x2888, 0x0078, 0x1ba8,
-	0x6810, 0x72b4, 0xa206, 0x0040, 0x2890, 0x6800, 0x0078, 0x2881,
-	0x6800, 0x200a, 0x6817, 0x0005, 0x681b, 0x0000, 0x681f, 0x0020,
-	0x1078, 0x2844, 0x1078, 0x283d, 0x1078, 0x17be, 0x0078, 0x1ba8,
-	0xa282, 0x0003, 0x00c0, 0x2ac5, 0x7da8, 0xa5ac, 0x00ff, 0x7ea8,
-	0xa6b4, 0x00ff, 0x691c, 0xa18d, 0x0080, 0x691e, 0xa184, 0x0100,
-	0x0040, 0x2900, 0xa18c, 0xfeff, 0x691e, 0xa6b4, 0x00ff, 0x0040,
-	0x28ea, 0xa682, 0x000f, 0x0048, 0x28c1, 0x0040, 0x28c1, 0x2031,
-	0x000f, 0x852b, 0x852b, 0x1078, 0x2b7f, 0x0040, 0x28cb, 0x1078,
-	0x299a, 0x0078, 0x28f3, 0x1078, 0x2b3a, 0x0c7e, 0x2960, 0x6004,
-	0xa084, 0xfff5, 0x6006, 0x1078, 0x29be, 0x0c7f, 0x691c, 0xa18d,
-	0x0100, 0x691e, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400,
-	0x00c0, 0x28e6, 0x781b, 0x0055, 0x0078, 0x1ba0, 0x781b, 0x0069,
-	0x0078, 0x1ba0, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006,
-	0x1078, 0x29be, 0x0c7f, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x28fc,
-	0x781b, 0x0058, 0x0078, 0x1ba0, 0x781b, 0x006a, 0x0078, 0x1ba0,
-	0x0c7e, 0x7048, 0x2060, 0x6100, 0xa18c, 0x1000, 0x0040, 0x2940,
-	0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000f, 0x0048, 0x2914,
-	0x0040, 0x2914, 0x2011, 0x000f, 0x2600, 0xa202, 0x00c8, 0x2919,
-	0x2230, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0,
-	0x2929, 0xa282, 0x0019, 0x00c8, 0x292f, 0x2011, 0x0019, 0x0078,
-	0x292f, 0xa282, 0x000c, 0x00c8, 0x292f, 0x2011, 0x000c, 0x2200,
-	0xa502, 0x00c8, 0x2934, 0x2228, 0x1078, 0x2b3e, 0x852b, 0x852b,
-	0x1078, 0x2b7f, 0x0040, 0x2940, 0x1078, 0x299a, 0x0078, 0x2944,
-	0x1078, 0x2b3a, 0x1078, 0x29be, 0x7858, 0xa085, 0x0004, 0x785a,
-	0x0c7f, 0x781b, 0x0069, 0x0078, 0x1ba0, 0x0c7e, 0x2960, 0x6000,
-	0xa084, 0x1000, 0x00c0, 0x2968, 0x6010, 0xa084, 0x000f, 0x00c0,
-	0x2962, 0xa18c, 0x0002, 0x00c0, 0x2962, 0xa18c, 0xfff5, 0x6106,
-	0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x298a,
-	0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0, 0x2978,
-	0xa282, 0x0019, 0x00c8, 0x297e, 0x2011, 0x0019, 0x0078, 0x297e,
-	0xa282, 0x000c, 0x00c8, 0x297e, 0x2011, 0x000c, 0x6308, 0x831f,
-	0xa39c, 0x00ff, 0xa382, 0x000f, 0x0048, 0x298a, 0x0040, 0x298a,
-	0x2019, 0x000f, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001,
-	0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x681c, 0xa085, 0x0100, 0x681e,
-	0x0c7f, 0x007c, 0x0c7e, 0x7148, 0x2160, 0x2008, 0xa084, 0xfff0,
-	0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084,
-	0xfff8, 0xa18c, 0x0007, 0xa105, 0x78a6, 0x6016, 0x788a, 0xa6b4,
-	0x000f, 0x8637, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa605, 0x600e,
-	0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x007c, 0x0c7e, 0x7048,
-	0x2060, 0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012,
-	0x7884, 0xa084, 0xfff0, 0x7886, 0x0c7f, 0x007c, 0xa282, 0x0002,
-	0x00c0, 0x2ac5, 0x7aa8, 0x691c, 0xa18d, 0x0080, 0x691e, 0xa184,
-	0x0200, 0x0040, 0x2a13, 0xa18c, 0xfdff, 0x691e, 0xa294, 0x00ff,
-	0xa282, 0x0002, 0x00c8, 0x2ac5, 0x1078, 0x2a5a, 0x1078, 0x29be,
-	0xa980, 0x0001, 0x200c, 0x1078, 0x2bf8, 0x1078, 0x294d, 0x88ff,
-	0x0040, 0x2a06, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5,
-	0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2a02, 0x781b, 0x0055,
-	0x0078, 0x1ba0, 0x781b, 0x0069, 0x0078, 0x1ba0, 0x7e58, 0xa684,
-	0x0400, 0x00c0, 0x2a0f, 0x781b, 0x0058, 0x0078, 0x1ba0, 0x781b,
-	0x006a, 0x0078, 0x1ba0, 0xa282, 0x0002, 0x00c8, 0x2a1b, 0xa284,
-	0x0001, 0x0040, 0x2a25, 0x7148, 0xa188, 0x0000, 0x210c, 0xa18c,
-	0x2000, 0x00c0, 0x2a25, 0x2011, 0x0000, 0x1078, 0x2b2c, 0x1078,
-	0x2a5a, 0x1078, 0x29be, 0x7858, 0xa085, 0x0004, 0x785a, 0x781b,
-	0x0069, 0x0078, 0x1ba0, 0x0c7e, 0x027e, 0x2960, 0x6000, 0x2011,
-	0x0001, 0xa084, 0x2000, 0x00c0, 0x2a4a, 0x6014, 0xa084, 0x0040,
-	0x00c0, 0x2a48, 0xa18c, 0xffef, 0x6106, 0xa006, 0x0078, 0x2a57,
-	0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003,
-	0x7aaa, 0xa8c0, 0x0004, 0x681c, 0xa085, 0x0200, 0x681e, 0x027f,
-	0x0c7f, 0x007c, 0x0c7e, 0x7048, 0x2060, 0x82ff, 0x0040, 0x2a62,
-	0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084,
-	0xffbf, 0xa205, 0x78a6, 0x6016, 0x788a, 0x6004, 0xa084, 0xffef,
-	0x6006, 0x0c7f, 0x007c, 0xa684, 0x0020, 0x0040, 0x2ac1, 0x7888,
-	0xa084, 0x0040, 0x0040, 0x2ac1, 0x78a8, 0x8001, 0x0040, 0x2a80,
-	0x7bb8, 0xa384, 0x003f, 0x831b, 0x00c8, 0x2a87, 0x8000, 0xa005,
-	0x0040, 0x2aa8, 0x831b, 0x00c8, 0x2a90, 0x8001, 0x0040, 0x2abd,
-	0xa006, 0x1078, 0x30a0, 0x78b4, 0x1078, 0x3103, 0x0078, 0x2ac1,
-	0xa684, 0x4000, 0x0040, 0x2aa8, 0x78b8, 0x801b, 0x00c8, 0x2aa1,
-	0x8000, 0xa084, 0x003f, 0x00c0, 0x2abd, 0xa6b4, 0xbfff, 0x7e5a,
-	0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108, 0x00c8, 0x2ab1, 0xa291,
-	0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x30a0, 0x781b,
-	0x0067, 0x1078, 0x2f6a, 0x0078, 0x1ba0, 0x781b, 0x0067, 0x0078,
-	0x1ba0, 0x781b, 0x006a, 0x0078, 0x1ba0, 0x1078, 0x2af8, 0x781b,
-	0x0069, 0x0078, 0x1ba0, 0x1078, 0x2ae4, 0x781b, 0x0069, 0x0078,
-	0x1ba0, 0x6823, 0x0002, 0x1078, 0x2aec, 0x691c, 0xa18d, 0x0020,
-	0x691e, 0x6814, 0xa084, 0x8000, 0x0040, 0x2ae0, 0x6817, 0x0005,
-	0x781b, 0x0069, 0x0078, 0x1ba0, 0x2001, 0x0005, 0x0078, 0x2afa,
-	0x2001, 0x000c, 0x0078, 0x2afa, 0x2001, 0x0006, 0x0078, 0x2afa,
-	0x2001, 0x000d, 0x0078, 0x2afa, 0x2001, 0x0009, 0x0078, 0x2afa,
-	0x2001, 0x0007, 0x789b, 0x007f, 0x78aa, 0xa6b5, 0x0008, 0x7e5a,
-	0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703,
-	0xa0e0, 0x3500, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f,
-	0x0040, 0x2b1a, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085,
-	0x0008, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040,
-	0x0040, 0x2b2a, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085,
-	0x0010, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001,
-	0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab,
-	0x0004, 0x007c, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, 0x0010,
-	0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa,
-	0x789b, 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007, 0xa084,
-	0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c,
-	0xfff0, 0x2001, 0x3446, 0x2004, 0xa082, 0x0028, 0x0040, 0x2b68,
-	0x2021, 0x2bdf, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x2b6e,
-	0x2021, 0x2beb, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064,
-	0x2404, 0xa084, 0xfff0, 0xa106, 0x0040, 0x2b7d, 0x8420, 0x2300,
-	0xa210, 0x0070, 0x2b7d, 0x0078, 0x2b70, 0x157f, 0x007c, 0x157e,
-	0x2011, 0x3446, 0x2214, 0xa282, 0x0032, 0x0048, 0x2b93, 0x0040,
-	0x2b97, 0x2021, 0x2bd1, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
-	0x0032, 0x0078, 0x2ba7, 0xa282, 0x0028, 0x0040, 0x2b9f, 0x2021,
-	0x2bdf, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x2ba5, 0x2021,
-	0x2beb, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2200,
-	0xa502, 0x0040, 0x2bb7, 0x0048, 0x2bb7, 0x8420, 0x2300, 0xa210,
-	0x0070, 0x2bb4, 0x0078, 0x2ba7, 0x157f, 0xa006, 0x007c, 0x157f,
-	0xa582, 0x0064, 0x00c8, 0x2bc0, 0x7808, 0xa085, 0x0040, 0x780a,
-	0x78ec, 0xa084, 0x0300, 0x0040, 0x2bce, 0x2404, 0xa09e, 0x2002,
-	0x00c0, 0x2bce, 0x2001, 0x2101, 0x0078, 0x2bcf, 0x2404, 0xa005,
-	0x007c, 0x2002, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404, 0x5604,
-	0x6605, 0x6805, 0x7806, 0x7a06, 0x0a07, 0x0c07, 0x0e07, 0x3202,
-	0x4202, 0x5202, 0x6202, 0x7202, 0x6605, 0x7605, 0x7805, 0x7a05,
-	0x7c05, 0x7e05, 0x7f05, 0x2202, 0x3202, 0x4202, 0x5202, 0x5404,
-	0x6404, 0x7404, 0x7604, 0x7804, 0x7a04, 0x7c04, 0x7e04, 0x7f04,
-	0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784,
-	0x0007, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e0, 0x3580,
-	0x007c, 0x79d8, 0x7adc, 0x78d0, 0x801b, 0x00c8, 0x2c10, 0x8000,
-	0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x007c, 0x0f7e, 0x2079,
-	0x0100, 0x2009, 0x3440, 0x2091, 0x8000, 0x2104, 0x0079, 0x2c20,
-	0x2c46, 0x2c2a, 0x2c2a, 0x2c2a, 0x2c2a, 0x2c2a, 0x2c28, 0x2c28,
-	0x1078, 0x1b4e, 0x784b, 0x0004, 0x68b0, 0xa085, 0x4000, 0x68b2,
-	0x7858, 0xa085, 0x4000, 0x785a, 0x7830, 0xa084, 0x0080, 0x00c0,
-	0x2c46, 0x0018, 0x2c46, 0x6818, 0xa084, 0x0020, 0x00c0, 0x2c44,
-	0x781b, 0x00dd, 0x0078, 0x2c46, 0x781b, 0x00e4, 0x2091, 0x8001,
-	0x0f7f, 0x007c, 0x0c7e, 0x6810, 0x8007, 0xa084, 0x000f, 0x8003,
-	0x8003, 0x8003, 0xa0e0, 0x3500, 0x6004, 0xa084, 0x000a, 0x00c0,
-	0x2c7d, 0x6108, 0xa194, 0xff00, 0x0040, 0x2c7d, 0xa18c, 0x00ff,
-	0x2001, 0x0019, 0xa106, 0x0040, 0x2c6c, 0x2001, 0x0032, 0xa106,
-	0x0040, 0x2c70, 0x0078, 0x2c74, 0x2009, 0x0020, 0x0078, 0x2c76,
-	0x2009, 0x003f, 0x0078, 0x2c76, 0x2011, 0x0000, 0x2100, 0xa205,
-	0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f, 0x007c, 0x781b,
-	0x006a, 0x0078, 0x1ba0, 0x781b, 0x0069, 0x0078, 0x1ba0, 0x781b,
-	0x0058, 0x0078, 0x1ba0, 0x781b, 0x0055, 0x0078, 0x1ba0, 0x781b,
-	0x00dd, 0x0078, 0x1ba0, 0x781b, 0x00dc, 0x0078, 0x1ba0, 0x781b,
-	0x00e4, 0x0078, 0x1ba0, 0x781b, 0x00e3, 0x0078, 0x1ba0, 0x781b,
-	0x009e, 0x0078, 0x1ba0, 0x781b, 0x009d, 0x0078, 0x1ba0, 0x70a3,
-	0x0001, 0x781b, 0x0046, 0x0078, 0x1ba0, 0x007e, 0x7830, 0xa084,
-	0x00c0, 0x00c0, 0x2cc4, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005,
-	0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, 0x2cc4,
-	0x7808, 0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0x7808, 0xa085,
-	0x0002, 0x780a, 0x007c, 0x7830, 0xa084, 0x0040, 0x00c0, 0x2ccb,
-	0x0098, 0x2cd4, 0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, 0x780a,
+	0x0040, 0x239b, 0x689c, 0xa084, 0x0100, 0x00c0, 0x239b, 0x1078,
+	0x2491, 0x0078, 0x1bff, 0xa186, 0x0018, 0x0040, 0x23a3, 0xa186,
+	0x0014, 0x0040, 0x1bff, 0x6912, 0x6814, 0xa084, 0x8000, 0x0040,
+	0x23ab, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x1078, 0x28e0,
+	0x1078, 0x28ef, 0x00c0, 0x23b8, 0x6008, 0xa084, 0xffef, 0x600a,
+	0x681c, 0xa084, 0x0001, 0x00c0, 0x23c1, 0x1078, 0x28d9, 0x0078,
+	0x23c5, 0x7054, 0x2060, 0x6800, 0x6002, 0x1078, 0x17dd, 0x0078,
+	0x1bff, 0xa282, 0x0004, 0x0048, 0x23cf, 0x1078, 0x1ba5, 0x2200,
+	0x0079, 0x23d2, 0x23d6, 0x23d8, 0x23e5, 0x23d8, 0x1078, 0x1ba5,
+	0x7000, 0xa086, 0x0005, 0x0040, 0x23e1, 0x1078, 0x2b89, 0x781b,
+	0x0069, 0x781b, 0x006a, 0x0078, 0x1bf7, 0x7890, 0x8007, 0x8001,
+	0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff,
+	0xa186, 0x0003, 0x0040, 0x23f6, 0x0078, 0x2b6a, 0x781b, 0x006a,
+	0x0078, 0x1bf7, 0x681c, 0xa085, 0x0004, 0x681e, 0x82ff, 0x00c0,
+	0x2405, 0x1078, 0x2b89, 0x0078, 0x240c, 0x8211, 0x0040, 0x240a,
+	0x1078, 0x1ba5, 0x1078, 0x2b99, 0x781b, 0x0069, 0x0078, 0x1bf7,
+	0x1078, 0x2d77, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x241c, 0x0018,
+	0x241c, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684,
+	0x0060, 0x00c0, 0x2429, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078,
+	0x2490, 0xa684, 0x0800, 0x00c0, 0x2438, 0x68b0, 0xa084, 0x4800,
+	0xa635, 0xa684, 0x0800, 0x00c0, 0x2438, 0x1078, 0x2ec7, 0x007c,
+	0xa684, 0x0020, 0x0040, 0x2462, 0x78d0, 0x8003, 0x00c8, 0x2446,
+	0xa006, 0x1078, 0x3194, 0x78d4, 0x1078, 0x31f9, 0xa684, 0x4000,
+	0x0040, 0x2450, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078, 0x2435,
+	0x68b0, 0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x244a,
+	0x7038, 0xa005, 0x00c0, 0x245c, 0x79d8, 0x7adc, 0x692e, 0x6a2a,
+	0x0078, 0x2435, 0xa684, 0x4000, 0x0040, 0x246c, 0x682f, 0x0000,
+	0x682b, 0x0000, 0x0078, 0x2435, 0x68b0, 0xa084, 0x4800, 0xa635,
+	0xa684, 0x4000, 0x00c0, 0x2466, 0x7038, 0xa005, 0x00c0, 0x247a,
+	0x703b, 0x0007, 0x79d8, 0x7adc, 0x78d0, 0x80f3, 0x00c8, 0x2481,
+	0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x692e, 0x6a2a,
+	0x2100, 0xa205, 0x00c0, 0x248e, 0x0078, 0x2435, 0x1078, 0x3194,
+	0x007c, 0xa384, 0x0200, 0x0040, 0x2499, 0x6008, 0xa085, 0x0002,
+	0x600a, 0x6817, 0x0006, 0x6a28, 0x692c, 0x6a3a, 0x693e, 0x682b,
+	0x0300, 0x682f, 0x0000, 0x6833, 0x2000, 0x6893, 0x0000, 0x6897,
+	0x0020, 0x7000, 0x0079, 0x24ac, 0x24b4, 0x24b6, 0x24bf, 0x24b4,
+	0x24b4, 0x24b4, 0x24b4, 0x24b4, 0x1078, 0x1ba5, 0x681c, 0xa084,
+	0x0001, 0x00c0, 0x24bf, 0x1078, 0x28d9, 0x0078, 0x24c5, 0x7054,
+	0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60, 0x2021, 0x3557, 0x2404,
+	0xa005, 0x0040, 0x24ce, 0x2020, 0x0078, 0x24c7, 0x2d22, 0x206b,
+	0x0000, 0x007c, 0x77b4, 0x1078, 0x2ba6, 0xa7bc, 0x0f00, 0x1078,
+	0x2ca1, 0x6018, 0xa005, 0x0040, 0x2501, 0x0d7e, 0x2001, 0x3f90,
+	0x2068, 0x0d7f, 0x2021, 0x3f80, 0x2009, 0x0004, 0x2011, 0x0010,
+	0x1078, 0x1fc5, 0x0040, 0x2501, 0x157e, 0x20a9, 0x0000, 0x2021,
+	0x3e80, 0x047e, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x1fc5,
+	0x047f, 0x0040, 0x2500, 0x8420, 0x0070, 0x2500, 0x0078, 0x24f1,
+	0x157f, 0x8738, 0xa784, 0x0007, 0x00c0, 0x24d7, 0x0078, 0x1bff,
+	0x1078, 0x28e0, 0x1078, 0x28ef, 0x6827, 0x0000, 0x789b, 0x000e,
+	0x6f10, 0x6813, 0x0002, 0x1078, 0x31ca, 0xa684, 0x0800, 0x0040,
+	0x251d, 0x6918, 0xa18d, 0x2000, 0x691a, 0x6814, 0xa084, 0x8000,
+	0x0040, 0x2524, 0x6817, 0x0000, 0x2021, 0x3557, 0x6800, 0x2022,
+	0x6a38, 0x693c, 0x6a2a, 0x692e, 0x1078, 0x17dd, 0x0078, 0x1bff,
+	0x1078, 0x241f, 0x6827, 0x0000, 0x789b, 0x000e, 0x6f10, 0x1078,
+	0x2d7c, 0xa08c, 0x00ff, 0x6912, 0x6814, 0xa084, 0x8000, 0x0040,
+	0x2543, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x70a3, 0x0000,
+	0x0078, 0x1bff, 0xa006, 0x1078, 0x2ec7, 0x6813, 0x0000, 0x6817,
+	0x0001, 0xa68c, 0xdf00, 0x691a, 0x6827, 0x0000, 0x7000, 0x0079,
+	0x2559, 0x2561, 0x2563, 0x2563, 0x2565, 0x2565, 0x2565, 0x2561,
+	0x2561, 0x1078, 0x1ba5, 0x1078, 0x28ef, 0x6008, 0xa084, 0xffef,
+	0x600a, 0x0078, 0x28ba, 0x2300, 0x0079, 0x256e, 0x2571, 0x2573,
+	0x25b1, 0x1078, 0x1ba5, 0x7000, 0x0079, 0x2576, 0x257e, 0x2580,
+	0x2580, 0x258b, 0x2580, 0x2592, 0x257e, 0x257e, 0x1078, 0x1ba5,
+	0xa684, 0x2000, 0x00c0, 0x258b, 0xa6b5, 0x2000, 0x7e5a, 0x1078,
+	0x30f0, 0x0078, 0x2d30, 0x6814, 0xa084, 0x8000, 0x0040, 0x2592,
+	0x6817, 0x0007, 0x2009, 0x3518, 0x210c, 0xa186, 0x0000, 0x0040,
+	0x25a7, 0xa186, 0x0001, 0x0040, 0x25ab, 0x2009, 0x352b, 0x200b,
+	0x000b, 0x70a3, 0x0001, 0x781b, 0x0046, 0x0078, 0x1bf7, 0x781b,
+	0x00dd, 0x0078, 0x1bf7, 0x2009, 0x352b, 0x200b, 0x000a, 0x0078,
+	0x1bf7, 0x1078, 0x1ba5, 0x2300, 0x0079, 0x25b6, 0x25b9, 0x25bb,
+	0x25de, 0x1078, 0x1ba5, 0x7000, 0x0079, 0x25be, 0x25c6, 0x25c8,
+	0x25c8, 0x25d3, 0x25c8, 0x25da, 0x25c6, 0x25c6, 0x1078, 0x1ba5,
+	0xa684, 0x2000, 0x00c0, 0x25d3, 0xa6b5, 0x2000, 0x7e5a, 0x1078,
+	0x30f0, 0x0078, 0x2d30, 0x6814, 0xa084, 0x8000, 0x0040, 0x25da,
+	0x6817, 0x0007, 0x781b, 0x00e4, 0x0078, 0x1bf7, 0x681c, 0xa085,
+	0x0004, 0x681e, 0xa6b5, 0x0800, 0x1078, 0x2b89, 0x781b, 0x0069,
+	0x0078, 0x1bf7, 0x2300, 0x0079, 0x25ed, 0x25f0, 0x25f2, 0x25f4,
+	0x1078, 0x1ba5, 0x1078, 0x1ba5, 0xa684, 0x0400, 0x00c0, 0x2613,
+	0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb,
+	0x785a, 0x79e4, 0xa184, 0x0020, 0x0040, 0x260b, 0x78ec, 0xa084,
+	0x0003, 0x00c0, 0x260f, 0x2001, 0x0014, 0x0078, 0x22fa, 0xa184,
+	0x0007, 0x0079, 0x264b, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060,
+	0x79a8, 0x81ff, 0x0040, 0x2649, 0x789b, 0x0010, 0x7ba8, 0xa384,
+	0x0001, 0x00c0, 0x263a, 0x7ba8, 0x7ba8, 0xa386, 0x0001, 0x00c0,
+	0x262d, 0x2009, 0xfff7, 0x0078, 0x2633, 0xa386, 0x0003, 0x00c0,
+	0x263a, 0x2009, 0xffef, 0x0c7e, 0x7048, 0x2060, 0x6004, 0xa104,
+	0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb,
+	0x785a, 0x782b, 0x3009, 0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff,
+	0x691e, 0x0078, 0x2d30, 0x2023, 0x2029, 0x2655, 0x265d, 0x2653,
+	0x2653, 0x2653, 0x2d30, 0x1078, 0x1ba5, 0x691c, 0xa18c, 0xfdff,
+	0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d38, 0x691c, 0xa18c, 0xfdff,
+	0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d30, 0x79e4, 0xa184, 0x0030,
+	0x0040, 0x266f, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x2677, 0x6814,
+	0xa085, 0x8000, 0x6816, 0x2001, 0x0014, 0x0078, 0x22fa, 0xa184,
+	0x0007, 0x0079, 0x267b, 0x2d30, 0x2d30, 0x2683, 0x2d30, 0x2d58,
+	0x2d58, 0x2d30, 0x2d30, 0xa684, 0x0400, 0x00c0, 0x26b4, 0x681c,
+	0xa084, 0x0001, 0x0040, 0x2d38, 0xa68c, 0x2060, 0xa18c, 0xfffb,
+	0x795a, 0x69b2, 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061,
+	0x6814, 0xa085, 0x8000, 0x6816, 0x78aa, 0x157e, 0x137e, 0x147e,
+	0x20a1, 0x012c, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000a,
+	0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6810, 0x8007, 0x789b,
+	0x007e, 0x78aa, 0x0078, 0x2d38, 0x6814, 0xa084, 0x8000, 0x0040,
+	0x26bb, 0x6817, 0x0008, 0x781b, 0x00d8, 0x0078, 0x1bf7, 0x2300,
+	0x0079, 0x26c2, 0x26c7, 0x2742, 0x26c5, 0x1078, 0x1ba5, 0x7000,
+	0xa084, 0x0007, 0x0079, 0x26cc, 0x26d4, 0x26d6, 0x26f2, 0x26d4,
+	0x26d4, 0x24d2, 0x26d4, 0x26d4, 0x1078, 0x1ba5, 0x691c, 0xa18d,
+	0x0001, 0x691e, 0x6800, 0x6006, 0xa005, 0x00c0, 0x26e0, 0x6002,
+	0x6818, 0xa084, 0x000e, 0x0040, 0x26ec, 0x7014, 0x68b6, 0x712c,
+	0xa188, 0x3e80, 0x0078, 0x26ee, 0x2009, 0x3f80, 0x2104, 0x6802,
+	0x2d0a, 0x7156, 0x6eb2, 0xa684, 0x0060, 0x0040, 0x2740, 0xa684,
+	0x0800, 0x00c0, 0x2704, 0xa684, 0x7fff, 0x68b2, 0x6890, 0x6894,
+	0x1078, 0x2ec7, 0x0078, 0x2740, 0xa684, 0x0020, 0x0040, 0x2716,
+	0xa006, 0x1078, 0x3194, 0x78d0, 0x8003, 0x00c8, 0x2712, 0x78d4,
+	0x1078, 0x31f9, 0x79d8, 0x7adc, 0x0078, 0x271a, 0x1078, 0x2cae,
+	0x1078, 0x3194, 0xa684, 0x8000, 0x0040, 0x2740, 0xa684, 0x7fff,
+	0x68b2, 0x789b, 0x0074, 0x1078, 0x2d7c, 0x2010, 0x1078, 0x2d7c,
+	0x2008, 0xa684, 0x0020, 0x00c0, 0x2738, 0x1078, 0x2d7c, 0x801b,
+	0x00c8, 0x2733, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
+	0x6b94, 0x2100, 0xa302, 0x68ae, 0x6b90, 0x2200, 0xa303, 0x68aa,
+	0x0078, 0x1bff, 0x0078, 0x2b76, 0x7033, 0x0000, 0xa282, 0x0005,
+	0x0050, 0x274c, 0x1078, 0x1ba5, 0x2300, 0x0079, 0x274f, 0x2752,
+	0x275c, 0x277f, 0x2200, 0x0079, 0x2755, 0x275a, 0x2b76, 0x275a,
+	0x27a8, 0x27f9, 0x1078, 0x1ba5, 0x7000, 0xa086, 0x0001, 0x00c0,
+	0x2769, 0x1078, 0x28ef, 0x1078, 0x2ec7, 0x7034, 0x600a, 0x0078,
+	0x276e, 0x7000, 0xa086, 0x0003, 0x0040, 0x2763, 0x7003, 0x0005,
+	0x2001, 0x3f90, 0x2068, 0x703e, 0x7032, 0x2200, 0x0079, 0x2778,
+	0x2b76, 0x277d, 0x27a8, 0x277d, 0x2b76, 0x1078, 0x1ba5, 0x7000,
+	0xa086, 0x0001, 0x00c0, 0x278c, 0x1078, 0x28ef, 0x1078, 0x2ec7,
+	0x7034, 0x600a, 0x0078, 0x2791, 0x7000, 0xa086, 0x0003, 0x0040,
+	0x2786, 0x7003, 0x0005, 0x2001, 0x3f90, 0x2068, 0x703e, 0x7032,
+	0x2200, 0x0079, 0x279b, 0x27a2, 0x27a0, 0x27a2, 0x27a0, 0x27a2,
+	0x1078, 0x1ba5, 0x1078, 0x2b99, 0x781b, 0x0069, 0x0078, 0x1bf7,
+	0x7000, 0xa086, 0x0001, 0x00c0, 0x27b5, 0x1078, 0x28ef, 0x1078,
+	0x2ec7, 0x7034, 0x600a, 0x0078, 0x27ba, 0x7000, 0xa086, 0x0003,
+	0x0040, 0x27af, 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b,
+	0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215, 0x2069, 0x3f80, 0x2d04,
+	0x2d08, 0x7156, 0x2068, 0xa005, 0x0040, 0x27d5, 0x6810, 0xa206,
+	0x0040, 0x27ee, 0x6800, 0x0078, 0x27c8, 0x7003, 0x0005, 0x2001,
+	0x3f90, 0x2068, 0x703e, 0x7032, 0x157e, 0x20a9, 0x002f, 0x2003,
+	0x0000, 0x8000, 0x0070, 0x27e6, 0x0078, 0x27df, 0x157f, 0x6a12,
+	0x68b3, 0x0700, 0x681f, 0x0800, 0x6823, 0x0003, 0x6eb0, 0x7e5a,
+	0x681c, 0xa084, 0x0c00, 0x0040, 0x284f, 0x1078, 0x2b91, 0x0078,
+	0x284f, 0x7000, 0xa086, 0x0001, 0x00c0, 0x2806, 0x1078, 0x28ef,
+	0x1078, 0x2ec7, 0x7034, 0x600a, 0x0078, 0x280b, 0x7000, 0xa086,
+	0x0003, 0x0040, 0x2800, 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00,
+	0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215, 0x79a8, 0x79a8,
+	0xa18c, 0x00ff, 0xa1e8, 0x3e80, 0x2d04, 0x2d08, 0x7156, 0x2068,
+	0xa005, 0x0040, 0x282a, 0x6810, 0xa206, 0x0040, 0x2843, 0x6800,
+	0x0078, 0x281d, 0x7003, 0x0005, 0x2001, 0x3f90, 0x2068, 0x703e,
+	0x7032, 0x157e, 0x20a9, 0x002f, 0x2003, 0x0000, 0x8000, 0x0070,
+	0x283b, 0x0078, 0x2834, 0x157f, 0x6a12, 0x68b3, 0x0700, 0x681f,
+	0x0800, 0x6823, 0x0003, 0x6eb0, 0x7e5a, 0x681c, 0xa084, 0x0c00,
+	0x0040, 0x284f, 0x1078, 0x2b8d, 0x7e58, 0x0078, 0x284f, 0x027e,
+	0x8207, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600,
+	0x2060, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0xa684, 0x0060,
+	0x0040, 0x2886, 0x6b94, 0x6c90, 0x69a8, 0x68ac, 0xa105, 0x00c0,
+	0x2874, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4, 0xb7ff, 0x7e5a,
+	0x1078, 0x30f0, 0x0078, 0x2886, 0x68ac, 0xa31a, 0x2100, 0xa423,
+	0x2400, 0xa305, 0x0040, 0x2886, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde,
+	0x68ac, 0xa6b4, 0xbfff, 0x7e5a, 0x1078, 0x311d, 0x077f, 0x1078,
+	0x2ca1, 0x2009, 0x006a, 0xa684, 0x0008, 0x0040, 0x2891, 0x2009,
+	0x0069, 0xa6b5, 0x2000, 0x7e5a, 0x791a, 0x2d00, 0x703e, 0x8207,
+	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, 0x2048,
+	0x0078, 0x1bf7, 0x6020, 0xa005, 0x0040, 0x28ae, 0x8001, 0x6022,
+	0x6008, 0xa085, 0x0008, 0x600a, 0x7010, 0x6026, 0x007c, 0xa006,
+	0x1078, 0x2ec7, 0x6813, 0x0000, 0x6817, 0x0001, 0x681f, 0x0040,
+	0x681b, 0x0100, 0x7000, 0xa084, 0x0007, 0x0079, 0x28bf, 0x28c7,
+	0x28c9, 0x28c9, 0x28d5, 0x28d1, 0x28c7, 0x28c7, 0x28c7, 0x1078,
+	0x1ba5, 0x1078, 0x28e0, 0x1078, 0x28d9, 0x1078, 0x17dd, 0x0078,
+	0x1bff, 0x70a3, 0x0000, 0x0078, 0x1bff, 0x6817, 0x0000, 0x0078,
+	0x2508, 0x6800, 0xa005, 0x00c0, 0x28de, 0x6002, 0x6006, 0x007c,
+	0x6010, 0xa005, 0x0040, 0x28e9, 0x8001, 0x00d0, 0x28e9, 0x1078,
+	0x1ba5, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x007c, 0x6018,
+	0xa005, 0x0040, 0x28f5, 0x8001, 0x601a, 0x007c, 0x1078, 0x2d77,
+	0x6817, 0x0018, 0x0078, 0x2926, 0x1078, 0x2d77, 0x6817, 0x0019,
+	0x0078, 0x2926, 0x1078, 0x2d77, 0x6817, 0x001a, 0x0078, 0x2926,
+	0x77b4, 0x1078, 0x2ca1, 0x71b8, 0xa18c, 0x00ff, 0xa1e8, 0x3e80,
+	0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, 0x2918, 0x0078, 0x1bff,
+	0x6810, 0x72b4, 0xa206, 0x0040, 0x2920, 0x6800, 0x0078, 0x2911,
+	0x6800, 0x200a, 0x6817, 0x0005, 0x70bf, 0x0000, 0x1078, 0x28e0,
+	0x681c, 0xa084, 0x0001, 0x00c0, 0x292f, 0x1078, 0x28d9, 0x1078,
+	0x28ef, 0x681b, 0x0000, 0x681f, 0x0020, 0x1078, 0x17dd, 0x0078,
+	0x1bff, 0xa282, 0x0003, 0x00c0, 0x2b6a, 0x7da8, 0xa5ac, 0x00ff,
+	0x7ea8, 0xa6b4, 0x00ff, 0x691c, 0xa18d, 0x0080, 0x691e, 0xa184,
+	0x0100, 0x0040, 0x2999, 0xa18c, 0xfeff, 0x691e, 0xa6b4, 0x00ff,
+	0x0040, 0x2983, 0xa682, 0x000f, 0x0048, 0x295a, 0x0040, 0x295a,
+	0x2031, 0x000f, 0x852b, 0x852b, 0x1078, 0x2c24, 0x0040, 0x2964,
+	0x1078, 0x2a33, 0x0078, 0x298c, 0x1078, 0x2bdf, 0x0c7e, 0x2960,
+	0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x2a57, 0x0c7f, 0x691c,
+	0xa18d, 0x0100, 0x691e, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684,
+	0x0400, 0x00c0, 0x297f, 0x781b, 0x0055, 0x0078, 0x1bf7, 0x781b,
+	0x0069, 0x0078, 0x1bf7, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5,
+	0x6006, 0x1078, 0x2a57, 0x0c7f, 0x7e58, 0xa684, 0x0400, 0x00c0,
+	0x2995, 0x781b, 0x0058, 0x0078, 0x1bf7, 0x781b, 0x006a, 0x0078,
+	0x1bf7, 0x0c7e, 0x7048, 0x2060, 0x6100, 0xa18c, 0x1000, 0x0040,
+	0x29d9, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000f, 0x0048,
+	0x29ad, 0x0040, 0x29ad, 0x2011, 0x000f, 0x2600, 0xa202, 0x00c8,
+	0x29b2, 0x2230, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028,
+	0x00c0, 0x29c2, 0xa282, 0x0019, 0x00c8, 0x29c8, 0x2011, 0x0019,
+	0x0078, 0x29c8, 0xa282, 0x000c, 0x00c8, 0x29c8, 0x2011, 0x000c,
+	0x2200, 0xa502, 0x00c8, 0x29cd, 0x2228, 0x1078, 0x2be3, 0x852b,
+	0x852b, 0x1078, 0x2c24, 0x0040, 0x29d9, 0x1078, 0x2a33, 0x0078,
+	0x29dd, 0x1078, 0x2bdf, 0x1078, 0x2a57, 0x7858, 0xa085, 0x0004,
+	0x785a, 0x0c7f, 0x781b, 0x0069, 0x0078, 0x1bf7, 0x0c7e, 0x2960,
+	0x6000, 0xa084, 0x1000, 0x00c0, 0x2a01, 0x6010, 0xa084, 0x000f,
+	0x00c0, 0x29fb, 0xa18c, 0x0002, 0x00c0, 0x29fb, 0xa18c, 0xfff5,
+	0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078,
+	0x2a23, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0,
+	0x2a11, 0xa282, 0x0019, 0x00c8, 0x2a17, 0x2011, 0x0019, 0x0078,
+	0x2a17, 0xa282, 0x000c, 0x00c8, 0x2a17, 0x2011, 0x000c, 0x6308,
+	0x831f, 0xa39c, 0x00ff, 0xa382, 0x000f, 0x0048, 0x2a23, 0x0040,
+	0x2a23, 0x2019, 0x000f, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab,
+	0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x681c, 0xa085, 0x0100,
+	0x681e, 0x0c7f, 0x007c, 0x0c7e, 0x7148, 0x2160, 0x2008, 0xa084,
+	0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4,
+	0xa084, 0xfff8, 0xa18c, 0x0007, 0xa105, 0x78a6, 0x6016, 0x788a,
+	0xa6b4, 0x000f, 0x8637, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa605,
+	0x600e, 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x007c, 0x0c7e,
+	0x7048, 0x2060, 0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6,
+	0x6012, 0x7884, 0xa084, 0xfff0, 0x7886, 0x0c7f, 0x007c, 0xa282,
+	0x0002, 0x00c0, 0x2b6a, 0x7aa8, 0x691c, 0xa18d, 0x0080, 0x691e,
+	0xa184, 0x0200, 0x0040, 0x2aac, 0xa18c, 0xfdff, 0x691e, 0xa294,
+	0x00ff, 0xa282, 0x0002, 0x00c8, 0x2b6a, 0x1078, 0x2af3, 0x1078,
+	0x2a57, 0xa980, 0x0001, 0x200c, 0x1078, 0x2c9d, 0x1078, 0x29e6,
+	0x88ff, 0x0040, 0x2a9f, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58,
+	0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2a9b, 0x781b,
+	0x0055, 0x0078, 0x1bf7, 0x781b, 0x0069, 0x0078, 0x1bf7, 0x7e58,
+	0xa684, 0x0400, 0x00c0, 0x2aa8, 0x781b, 0x0058, 0x0078, 0x1bf7,
+	0x781b, 0x006a, 0x0078, 0x1bf7, 0xa282, 0x0002, 0x00c8, 0x2ab4,
+	0xa284, 0x0001, 0x0040, 0x2abe, 0x7148, 0xa188, 0x0000, 0x210c,
+	0xa18c, 0x2000, 0x00c0, 0x2abe, 0x2011, 0x0000, 0x1078, 0x2bd1,
+	0x1078, 0x2af3, 0x1078, 0x2a57, 0x7858, 0xa085, 0x0004, 0x785a,
+	0x781b, 0x0069, 0x0078, 0x1bf7, 0x0c7e, 0x027e, 0x2960, 0x6000,
+	0x2011, 0x0001, 0xa084, 0x2000, 0x00c0, 0x2ae3, 0x6014, 0xa084,
+	0x0040, 0x00c0, 0x2ae1, 0xa18c, 0xffef, 0x6106, 0xa006, 0x0078,
+	0x2af0, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab,
+	0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x681c, 0xa085, 0x0200, 0x681e,
+	0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7048, 0x2060, 0x82ff, 0x0040,
+	0x2afb, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4,
+	0xa084, 0xffbf, 0xa205, 0x78a6, 0x6016, 0x788a, 0x6004, 0xa084,
+	0xffef, 0x6006, 0x0c7f, 0x007c, 0x007e, 0x7000, 0xa086, 0x0003,
+	0x0040, 0x2b15, 0x007f, 0x0078, 0x2b18, 0x007f, 0x0078, 0x2b66,
+	0xa684, 0x0020, 0x0040, 0x2b66, 0x7888, 0xa084, 0x0040, 0x0040,
+	0x2b66, 0x78a8, 0x8001, 0x0040, 0x2b25, 0x7bb8, 0xa384, 0x003f,
+	0x831b, 0x00c8, 0x2b2c, 0x8000, 0xa005, 0x0040, 0x2b4d, 0x831b,
+	0x00c8, 0x2b35, 0x8001, 0x0040, 0x2b62, 0xa006, 0x1078, 0x3194,
+	0x78b4, 0x1078, 0x31f9, 0x0078, 0x2b66, 0xa684, 0x4000, 0x0040,
+	0x2b4d, 0x78b8, 0x801b, 0x00c8, 0x2b46, 0x8000, 0xa084, 0x003f,
+	0x00c0, 0x2b62, 0xa6b4, 0xbfff, 0x7e5a, 0x79d8, 0x7adc, 0x2001,
+	0x0001, 0xa108, 0x00c8, 0x2b56, 0xa291, 0x0000, 0x79d2, 0x79da,
+	0x7ad6, 0x7ade, 0x1078, 0x3194, 0x781b, 0x0067, 0x1078, 0x305e,
+	0x0078, 0x1bf7, 0x781b, 0x0067, 0x0078, 0x1bf7, 0x781b, 0x006a,
+	0x0078, 0x1bf7, 0x1078, 0x2b9d, 0x781b, 0x0069, 0x0078, 0x1bf7,
+	0x1078, 0x2b89, 0x781b, 0x0069, 0x0078, 0x1bf7, 0x6823, 0x0002,
+	0x1078, 0x2b91, 0x691c, 0xa18d, 0x0020, 0x691e, 0x6814, 0xa084,
+	0x8000, 0x0040, 0x2b85, 0x6817, 0x0005, 0x781b, 0x0069, 0x0078,
+	0x1bf7, 0x2001, 0x0005, 0x0078, 0x2b9f, 0x2001, 0x000c, 0x0078,
+	0x2b9f, 0x2001, 0x0006, 0x0078, 0x2b9f, 0x2001, 0x000d, 0x0078,
+	0x2b9f, 0x2001, 0x0009, 0x0078, 0x2b9f, 0x2001, 0x0007, 0x789b,
+	0x007f, 0x78aa, 0xa6b5, 0x0008, 0x7e5a, 0x007c, 0x077e, 0x873f,
+	0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0xa0e0, 0x3600, 0xa7b8,
+	0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f, 0x0040, 0x2bbf, 0xa184,
+	0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085, 0x0008, 0x6006, 0x8738,
+	0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040, 0x0040, 0x2bcf, 0xa184,
+	0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085, 0x0010, 0x6006, 0x077f,
+	0x007c, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab,
+	0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, 0x0004, 0x007c, 0x2031,
+	0x0000, 0x2029, 0x0032, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab,
+	0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa, 0x789b, 0x0060, 0x78ab,
+	0x0005, 0x007c, 0x157e, 0x8007, 0xa084, 0x00ff, 0x8003, 0x8003,
+	0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, 0xfff0, 0x2001, 0x3546,
+	0x2004, 0xa082, 0x0028, 0x0040, 0x2c0d, 0x2021, 0x2c84, 0x2019,
+	0x0014, 0x20a9, 0x000c, 0x0078, 0x2c13, 0x2021, 0x2c90, 0x2019,
+	0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2404, 0xa084, 0xfff0,
+	0xa106, 0x0040, 0x2c22, 0x8420, 0x2300, 0xa210, 0x0070, 0x2c22,
+	0x0078, 0x2c15, 0x157f, 0x007c, 0x157e, 0x2011, 0x3546, 0x2214,
+	0xa282, 0x0032, 0x0048, 0x2c38, 0x0040, 0x2c3c, 0x2021, 0x2c76,
+	0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032, 0x0078, 0x2c4c,
+	0xa282, 0x0028, 0x0040, 0x2c44, 0x2021, 0x2c84, 0x2019, 0x0014,
+	0x20a9, 0x000c, 0x0078, 0x2c4a, 0x2021, 0x2c90, 0x2019, 0x0019,
+	0x20a9, 0x000d, 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x2c5c,
+	0x0048, 0x2c5c, 0x8420, 0x2300, 0xa210, 0x0070, 0x2c59, 0x0078,
+	0x2c4c, 0x157f, 0xa006, 0x007c, 0x157f, 0xa582, 0x0064, 0x00c8,
+	0x2c65, 0x7808, 0xa085, 0x0070, 0x780a, 0x78ec, 0xa084, 0x0300,
+	0x0040, 0x2c73, 0x2404, 0xa09e, 0x1201, 0x00c0, 0x2c73, 0x2001,
+	0x2101, 0x0078, 0x2c74, 0x2404, 0xa005, 0x007c, 0x1201, 0x3002,
+	0x3202, 0x4203, 0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806,
+	0x7a06, 0x0a07, 0x0c07, 0x0e07, 0x3202, 0x4202, 0x5202, 0x6202,
+	0x7202, 0x6605, 0x7605, 0x7805, 0x7a05, 0x7c05, 0x7e05, 0x7f05,
+	0x2202, 0x3202, 0x4202, 0x5202, 0x5404, 0x6404, 0x7404, 0x7604,
+	0x7804, 0x7a04, 0x7c04, 0x7e04, 0x7f04, 0x789b, 0x0010, 0xa046,
+	0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, 0x0007, 0x8003, 0x8003,
+	0x8003, 0x8003, 0xa105, 0xa0e0, 0x3680, 0x007c, 0x79d8, 0x7adc,
+	0x78d0, 0x801b, 0x00c8, 0x2cb5, 0x8000, 0xa084, 0x003f, 0xa108,
+	0xa291, 0x0000, 0x007c, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x3540,
+	0x2091, 0x8000, 0x2104, 0x0079, 0x2cc5, 0x2cf7, 0x2ccf, 0x2ccf,
+	0x2ccf, 0x2ccf, 0x2ccf, 0x2ccd, 0x2ccd, 0x1078, 0x1ba5, 0x784b,
+	0x0004, 0x7848, 0xa084, 0x0004, 0x00c0, 0x2cd1, 0x784b, 0x0008,
+	0x7848, 0xa084, 0x0008, 0x00c0, 0x2cd8, 0x68b0, 0xa085, 0x4000,
+	0x68b2, 0x7858, 0xa085, 0x4000, 0x785a, 0x7830, 0xa084, 0x0080,
+	0x00c0, 0x2cf7, 0x0018, 0x2cf7, 0x6818, 0xa084, 0x0020, 0x00c0,
+	0x2cf5, 0x781b, 0x00dd, 0x0078, 0x2cf7, 0x781b, 0x00e4, 0x2091,
+	0x8001, 0x0f7f, 0x007c, 0x0c7e, 0x6810, 0x8007, 0xa084, 0x000f,
+	0x8003, 0x8003, 0x8003, 0xa0e0, 0x3600, 0x6004, 0xa084, 0x000a,
+	0x00c0, 0x2d2e, 0x6108, 0xa194, 0xff00, 0x0040, 0x2d2e, 0xa18c,
+	0x00ff, 0x2001, 0x0019, 0xa106, 0x0040, 0x2d1d, 0x2001, 0x0032,
+	0xa106, 0x0040, 0x2d21, 0x0078, 0x2d25, 0x2009, 0x0020, 0x0078,
+	0x2d27, 0x2009, 0x003f, 0x0078, 0x2d27, 0x2011, 0x0000, 0x2100,
+	0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f, 0x007c,
+	0x781b, 0x006a, 0x0078, 0x1bf7, 0x781b, 0x0069, 0x0078, 0x1bf7,
+	0x781b, 0x0058, 0x0078, 0x1bf7, 0x781b, 0x0055, 0x0078, 0x1bf7,
+	0x781b, 0x00dd, 0x0078, 0x1bf7, 0x781b, 0x00dc, 0x0078, 0x1bf7,
+	0x781b, 0x00e4, 0x0078, 0x1bf7, 0x781b, 0x00e3, 0x0078, 0x1bf7,
+	0x781b, 0x009e, 0x0078, 0x1bf7, 0x781b, 0x009d, 0x0078, 0x1bf7,
+	0x70a3, 0x0001, 0x781b, 0x0046, 0x0078, 0x1bf7, 0x007e, 0x7830,
+	0xa084, 0x00c0, 0x00c0, 0x2d75, 0x7808, 0xa084, 0xfffd, 0x780a,
 	0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040,
-	0x2ce3, 0x0098, 0x2ce1, 0x78ac, 0x007e, 0x7808, 0xa085, 0x0002,
-	0x780a, 0x007f, 0x007c, 0xa784, 0x0070, 0x0040, 0x2cef, 0x6817,
-	0x0003, 0x7858, 0xa084, 0x3f00, 0x681a, 0x682f, 0x0000, 0x682b,
-	0x0000, 0x784b, 0x0008, 0x78e4, 0xa005, 0x00d0, 0x1fb9, 0xa084,
-	0x0020, 0x0040, 0x1fb9, 0x78ec, 0xa084, 0x0003, 0x0040, 0x1fb9,
-	0x0018, 0x1fb9, 0x0078, 0x2acb, 0x0c7e, 0x6810, 0x8007, 0xa084,
-	0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3500, 0x2060, 0x2048,
-	0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x0c7f, 0x007c, 0x0020,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0062, 0x0009, 0x0014, 0x0014, 0x9847, 0x0014, 0x0014,
-	0x98f5, 0x98e7, 0x0014, 0x0014, 0x0080, 0x00bf, 0x0100, 0x0402,
-	0x2008, 0xf880, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014, 0xa200,
-	0x8838, 0x817e, 0x842a, 0x84a0, 0x3806, 0x8839, 0x28c2, 0x9cc3,
-	0xa805, 0x0864, 0xa83b, 0x3008, 0x28c1, 0x9cc3, 0xa201, 0x300c,
-	0x2847, 0x8161, 0x846a, 0x8000, 0x84a4, 0x1856, 0x883a, 0xa808,
-	0x28e2, 0x9ca0, 0xa8f3, 0x0864, 0xa829, 0x300c, 0xa801, 0x3008,
-	0x28e1, 0x9ca0, 0x280d, 0xa204, 0x64c0, 0x67a0, 0x6fc0, 0x1814,
-	0x883b, 0x7023, 0x8576, 0x8677, 0xa80f, 0x786e, 0x883e, 0xa80c,
-	0x282b, 0xa205, 0x64a0, 0x67a0, 0x6fc0, 0x1814, 0x883b, 0x7023,
-	0x8576, 0x8677, 0xa801, 0x883e, 0x2069, 0x28c1, 0x9cc3, 0x2044,
-	0x2103, 0x20a2, 0x2081, 0xa8dc, 0xa207, 0x0014, 0xa203, 0x8000,
-	0x84a8, 0x85a4, 0x1872, 0x849a, 0x883c, 0x1fe2, 0xf601, 0xa208,
-	0x856e, 0x866f, 0x0704, 0x3008, 0x9ca0, 0x0014, 0xa202, 0x8000,
-	0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf848, 0x8174, 0x86eb, 0x85eb,
-	0x872e, 0x87a9, 0x883f, 0x08e6, 0xa8f1, 0xf861, 0xa8e8, 0xf801,
-	0x0014, 0xf881, 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfaa2, 0x1de2,
-	0x0014, 0x8532, 0xf221, 0x0014, 0x1de2, 0x84a8, 0xd6e0, 0x1fe6,
-	0x0014, 0xa206, 0x6865, 0x817f, 0x842a, 0x1dc1, 0x8823, 0x0016,
-	0x6042, 0x8008, 0xa8fa, 0x8000, 0x84a4, 0x8160, 0x842a, 0xf021,
-	0x3008, 0x84a8, 0x1dc6, 0x20d7, 0x8822, 0x0016, 0x8000, 0x2848,
-	0x1011, 0xa8fc, 0x3008, 0x8000, 0xa000, 0x2802, 0x1011, 0xa8fd,
-	0xa887, 0x3008, 0x283d, 0x1011, 0xa8fd, 0xa209, 0x0017, 0x300c,
-	0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014, 0x26e0, 0x873a, 0xfaa2,
-	0x19f2, 0x1fe2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x817e, 0x842a,
-	0x84a0, 0x3806, 0x0210, 0x9ccd, 0x0704, 0x0000, 0x127e, 0x2091,
-	0x2200, 0x2049, 0x2e0e, 0x7000, 0x7204, 0xa205, 0x720c, 0xa215,
-	0x7008, 0xa084, 0xfffd, 0xa205, 0x0040, 0x2e20, 0x1078, 0x2e68,
-	0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x6424, 0x84ff, 0x0040,
-	0x2e42, 0x2c70, 0x2039, 0x2e47, 0x2704, 0xae68, 0x680c, 0xa630,
-	0x6808, 0xa529, 0x8421, 0x0040, 0x2e42, 0x8738, 0x2704, 0xa005,
-	0x00c0, 0x2e2d, 0x7098, 0xa075, 0x0040, 0x2e42, 0x2039, 0x2e44,
-	0x0078, 0x2e2c, 0x007c, 0x0000, 0x0004, 0x0008, 0x000c, 0x0010,
-	0x0014, 0x0018, 0x001c, 0x0000, 0x127e, 0x2091, 0x2200, 0x2079,
-	0x3400, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003,
-	0x0000, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003,
-	0x0000, 0x2049, 0x0000, 0x78b3, 0x0000, 0x127f, 0x2000, 0x007c,
-	0x2049, 0x2e68, 0x7004, 0x8004, 0x00c8, 0x2e90, 0x7007, 0x0012,
-	0x7108, 0x7008, 0xa106, 0x00c0, 0x2e70, 0xa184, 0x0030, 0x0040,
-	0x2e7d, 0xa086, 0x0030, 0x00c0, 0x2e70, 0x7000, 0xa084, 0x0001,
-	0x00c0, 0x2e90, 0x7008, 0xa084, 0x000c, 0x00c0, 0x2e90, 0x710c,
-	0xa184, 0x0300, 0x00c0, 0x2e90, 0xa184, 0x007f, 0x00c0, 0x2e68,
-	0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xa084, 0x0008, 0x00c0,
-	0x2e94, 0x7007, 0x0012, 0x7108, 0x8104, 0x0048, 0x2e99, 0x78b3,
-	0x0000, 0x7003, 0x0000, 0x2049, 0x0000, 0x007c, 0x107e, 0x007e,
-	0x127e, 0x157e, 0x2091, 0x2200, 0x7108, 0x1078, 0x2eb6, 0x157f,
-	0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, 0x7204, 0x2118,
-	0x7108, 0x700c, 0xa084, 0x0300, 0x00c0, 0x2ef8, 0xa184, 0x000c,
-	0x00c0, 0x2ef8, 0x8213, 0x8213, 0x8213, 0x8213, 0xa284, 0x0100,
-	0xa10d, 0x810b, 0x810b, 0x810f, 0xa184, 0x0007, 0x0079, 0x2ed0,
-	0x2eda, 0x2eea, 0x2ef8, 0x2eea, 0x2f0c, 0x2f0c, 0x2ef8, 0x2f0a,
-	0x1078, 0x1b4e, 0x7007, 0x0002, 0x8aff, 0x00c0, 0x2ee3, 0x2049,
-	0x0000, 0x0078, 0x2ee7, 0x1078, 0x3077, 0x00c0, 0x2ee3, 0x78b3,
-	0x0000, 0x007c, 0x7007, 0x0002, 0x8aff, 0x00c0, 0x2ef1, 0x0078,
-	0x2ef5, 0x1078, 0x3077, 0x00c0, 0x2ef1, 0x78b3, 0x0000, 0x007c,
-	0x7007, 0x0002, 0x1078, 0x2e68, 0x1078, 0x2c16, 0x6814, 0xa084,
-	0x8000, 0x0040, 0x2f05, 0x6817, 0x0002, 0x007c, 0x1078, 0x1b4e,
-	0x1078, 0x1b4e, 0x1078, 0x2f5c, 0x7210, 0x7114, 0x700c, 0xa09c,
-	0x007f, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000, 0x78b0, 0xa005,
-	0x0040, 0x2f1e, 0x78b3, 0x0000, 0x0078, 0x2f41, 0x1078, 0x2f5c,
-	0x2704, 0x2c58, 0xac60, 0x630c, 0x2200, 0xa322, 0x6308, 0x2100,
-	0xa31b, 0x2400, 0xa305, 0x0040, 0x2f37, 0x00c8, 0x2f37, 0x8412,
-	0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078, 0x2f1e, 0x2b60,
-	0x8a07, 0xa7ba, 0x2e44, 0xa73d, 0x2c00, 0x6882, 0x6f86, 0x6c8e,
-	0x6b8a, 0x1078, 0x2e68, 0x007c, 0x8738, 0x2704, 0xa005, 0x00c0,
-	0x2f50, 0x6098, 0xa005, 0x0040, 0x2f59, 0x2060, 0x2039, 0x2e44,
-	0x8a51, 0x0040, 0x2f58, 0x7008, 0xa084, 0x00c0, 0xa086, 0x00c0,
-	0x007c, 0x2051, 0x0000, 0x007c, 0x8a50, 0x8739, 0x2704, 0xa004,
-	0x00c0, 0x2f69, 0x2039, 0x2e4a, 0x6000, 0xa064, 0x00c0, 0x2f69,
-	0x2d60, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x6880,
-	0x2060, 0x6884, 0x6b88, 0x6c8c, 0x8057, 0xaad4, 0x00ff, 0xa084,
-	0x00ff, 0xa0b8, 0x2e44, 0x7e08, 0xa6b5, 0x000c, 0x6818, 0xa084,
-	0x0040, 0x0040, 0x2f85, 0xa6b5, 0x0001, 0x0f7e, 0x2079, 0x0100,
-	0x7858, 0x0f7f, 0xa084, 0x0040, 0x0040, 0x2f94, 0xa684, 0x0001,
-	0x00c0, 0x2f94, 0xa6b5, 0x0001, 0x7007, 0x0004, 0x7004, 0xa084,
-	0x0004, 0x00c0, 0x2f96, 0x7000, 0xa005, 0x0040, 0x2fa1, 0x1078,
-	0x1b4e, 0x2400, 0xa305, 0x00c0, 0x2fa7, 0x0078, 0x2fe4, 0x2c58,
-	0x2704, 0xac60, 0x6004, 0xa400, 0x007e, 0x701a, 0x6000, 0xa301,
-	0x701e, 0x2009, 0x04fd, 0x2104, 0xa086, 0x04fd, 0x007f, 0x00c0,
-	0x2fd4, 0xa084, 0x0001, 0x0040, 0x2fd4, 0xa684, 0x0001, 0x00c0,
-	0x2fd4, 0x7013, 0x0001, 0x7017, 0x0000, 0x7602, 0x7007, 0x0001,
-	0x78b3, 0x0001, 0xa4a0, 0x0001, 0xa399, 0x0000, 0x6004, 0xa400,
-	0x701a, 0x6000, 0xa301, 0x701e, 0x620c, 0x2400, 0xa202, 0x7012,
-	0x6208, 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60,
-	0x1078, 0x2f44, 0x0078, 0x2fe6, 0x1078, 0x3077, 0x00c0, 0x2fe4,
-	0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f,
-	0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x2ff2, 0x7003,
-	0x0008, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200,
-	0x0d7f, 0x2049, 0x2ffc, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
-	0x00c0, 0x3005, 0x7000, 0xa005, 0x0040, 0x3010, 0x1078, 0x1b4e,
-	0x7e08, 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, 0x0040, 0x301a,
-	0xa6b5, 0x0001, 0x6824, 0xa005, 0x0040, 0x3026, 0x2050, 0x2039,
-	0x2e47, 0x2d60, 0x1078, 0x3077, 0x00c0, 0x3022, 0x127f, 0x2000,
-	0x007c, 0x127e, 0x007e, 0x017e, 0x0d7e, 0x2091, 0x2200, 0x0d7f,
-	0x037f, 0x047f, 0x7e08, 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040,
-	0x0040, 0x303c, 0xa6b5, 0x0001, 0x2049, 0x3029, 0x6824, 0xa055,
-	0x0040, 0x3074, 0x2d70, 0x2e60, 0x2039, 0x2e47, 0x2704, 0xae68,
-	0x680c, 0xa422, 0x6808, 0xa31b, 0x0048, 0x3061, 0x8a51, 0x00c0,
-	0x3053, 0x1078, 0x1b4e, 0x8738, 0x2704, 0xa005, 0x00c0, 0x3047,
-	0x7098, 0xa075, 0x2060, 0x0040, 0x3074, 0x2039, 0x2e44, 0x0078,
-	0x3046, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x690c, 0x2400,
-	0xa122, 0x6908, 0x2300, 0xa11b, 0x00c8, 0x3070, 0x1078, 0x1b4e,
-	0x2071, 0x0020, 0x0078, 0x2f94, 0x127f, 0x2000, 0x007c, 0x7008,
-	0xa084, 0x00c0, 0xa086, 0x00c0, 0x0040, 0x309f, 0x2704, 0xac08,
-	0x2104, 0x701e, 0x8108, 0x2104, 0x701a, 0x8108, 0x2104, 0x7016,
-	0x8108, 0x2104, 0x7012, 0x0f7e, 0x2079, 0x0100, 0x7858, 0x0f7f,
-	0xa084, 0x0040, 0x0040, 0x309a, 0xa684, 0x0001, 0x00c0, 0x309a,
-	0xa6b5, 0x0001, 0x7602, 0x7007, 0x0001, 0x1078, 0x2f44, 0x007c,
-	0x127e, 0x007e, 0x0d7e, 0x2091, 0x2200, 0x2049, 0x30a0, 0x0d7f,
-	0x087f, 0x7108, 0xa184, 0x00c0, 0x00c0, 0x30b6, 0x6824, 0xa005,
-	0x0040, 0x30c6, 0x1078, 0x2f0c, 0x0078, 0x30c6, 0x7108, 0x8104,
-	0x00c8, 0x30be, 0x1078, 0x2eb6, 0x0078, 0x30a9, 0x7007, 0x0010,
-	0x7108, 0x8104, 0x00c8, 0x30c0, 0x1078, 0x2eb6, 0x7008, 0xa086,
-	0x0002, 0x00c0, 0x30a9, 0x7000, 0xa005, 0x00c0, 0x30a9, 0x2049,
-	0x0000, 0x127f, 0x2000, 0x007c, 0x127e, 0x147e, 0x137e, 0x157e,
-	0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x30d4, 0xad80, 0x0010,
-	0x20a0, 0x2099, 0x0031, 0x700c, 0xa084, 0x007f, 0x6826, 0x7007,
-	0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0040, 0x30f2, 0x8000,
-	0x80ac, 0x53a5, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
-	0x30f4, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f,
-	0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x2200,
-	0x0d7f, 0x2049, 0x3103, 0x6880, 0x2060, 0x6884, 0x6b88, 0x6c8c,
-	0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0xa0b8, 0x2e44, 0x7e08,
-	0xa6b5, 0x0004, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
-	0x311c, 0x2c58, 0x2704, 0xac60, 0x6004, 0xa400, 0x701a, 0x6000,
-	0xa301, 0x701e, 0x7013, 0x0001, 0x7017, 0x0000, 0x7602, 0x7007,
-	0x0001, 0x007f, 0x8007, 0x2009, 0x0031, 0x200a, 0x00a0, 0x3136,
-	0x7108, 0x7007, 0x0002, 0x810c, 0x00c8, 0x3136, 0x810c, 0x0048,
-	0x3143, 0x0078, 0x2ef8, 0xa4a0, 0x0001, 0xa399, 0x0000, 0x6b8a,
-	0x6c8e, 0x7007, 0x0004, 0x2049, 0x0000, 0x7003, 0x0000, 0x127f,
-	0x2000, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e,
-	0x00c8, 0x315b, 0xa200, 0x00f0, 0x3156, 0x8086, 0x818e, 0x007c,
-	0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x3181, 0xa11a, 0x00c8,
-	0x3181, 0x8213, 0x818d, 0x0048, 0x3174, 0xa11a, 0x00c8, 0x3175,
-	0x00f0, 0x3169, 0x0078, 0x3179, 0xa11a, 0x2308, 0x8210, 0x00f0,
-	0x3169, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f,
-	0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x317d, 0x00e0,
-	0x31c1, 0x2091, 0x6000, 0x7820, 0x8001, 0x7822, 0x00c0, 0x31bb,
-	0x7824, 0x7822, 0x2091, 0x8000, 0x2069, 0x3440, 0x6800, 0xa084,
-	0x0007, 0x0040, 0x31ab, 0xa086, 0x0002, 0x0040, 0x31ab, 0x6830,
-	0xa00d, 0x0040, 0x31ab, 0x2104, 0xa005, 0x0040, 0x31ab, 0x8001,
-	0x200a, 0x0040, 0x3277, 0x2061, 0x3580, 0x20a9, 0x0080, 0x6034,
-	0xa005, 0x0040, 0x31b5, 0x8001, 0x6036, 0xace0, 0x0010, 0x0070,
-	0x31bb, 0x0078, 0x31af, 0x1078, 0x31dc, 0x1078, 0x31c4, 0x1078,
-	0x3201, 0x2091, 0x8001, 0x007c, 0x783c, 0x8001, 0x783e, 0x00c0,
-	0x31db, 0x7840, 0x783e, 0x7848, 0xa005, 0x0040, 0x31db, 0x8001,
-	0x784a, 0x00c0, 0x31db, 0x0f7e, 0x2079, 0x0100, 0x1078, 0x2cc6,
-	0x0f7f, 0x1078, 0x19f8, 0x007c, 0x7834, 0x8001, 0x7836, 0x00c0,
-	0x3200, 0x7838, 0x7836, 0x2091, 0x8000, 0x7844, 0xa005, 0x00c0,
-	0x31eb, 0x2001, 0x0101, 0x8001, 0x7846, 0xa080, 0x3d80, 0x2040,
-	0x2004, 0xa065, 0x0040, 0x3200, 0x6020, 0xa005, 0x0040, 0x31fc,
-	0x8001, 0x6022, 0x0040, 0x3230, 0x6000, 0x2c40, 0x0078, 0x31f1,
-	0x007c, 0x7828, 0x8001, 0x782a, 0x00c0, 0x322f, 0x782c, 0x782a,
-	0x7830, 0xa005, 0x00c0, 0x320e, 0x2001, 0x0080, 0x8001, 0x7832,
-	0x8003, 0x8003, 0x8003, 0x8003, 0xa090, 0x3580, 0xa298, 0x0002,
-	0x2304, 0xa084, 0x0008, 0x0040, 0x322f, 0xa290, 0x0009, 0x2204,
-	0xa005, 0x0040, 0x3227, 0x8001, 0x2012, 0x00c0, 0x322f, 0x2304,
-	0xa084, 0xfff7, 0xa085, 0x0080, 0x201a, 0x1078, 0x19f8, 0x007c,
-	0x2069, 0x3440, 0x6800, 0xa005, 0x0040, 0x323a, 0x683c, 0xac06,
-	0x0040, 0x3277, 0x6017, 0x0006, 0x60b0, 0xa084, 0x3f00, 0x601a,
+	0x2d75, 0x7808, 0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0x7808,
+	0xa085, 0x0002, 0x780a, 0x007c, 0x7830, 0xa084, 0x0040, 0x00c0,
+	0x2d7c, 0x0098, 0x2d85, 0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd,
+	0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021,
+	0x0040, 0x2d94, 0x0098, 0x2d92, 0x78ac, 0x007e, 0x7808, 0xa085,
+	0x0002, 0x780a, 0x007f, 0x007c, 0xa784, 0x0070, 0x0040, 0x2da8,
+	0x0c7e, 0x2d60, 0x2f68, 0x1078, 0x1b6b, 0x2d78, 0x2c68, 0x0c7f,
+	0x6817, 0x0003, 0x7858, 0xa084, 0x3f00, 0x681a, 0x682f, 0x0000,
+	0x682b, 0x0000, 0x784b, 0x0008, 0x78e4, 0xa005, 0x00d0, 0x2015,
+	0xa084, 0x0020, 0x0040, 0x2015, 0x78ec, 0xa084, 0x0003, 0x0040,
+	0x2015, 0x0018, 0x2015, 0x0078, 0x2b70, 0x0c7e, 0x6810, 0x8007,
+	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, 0x2060,
+	0x2048, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x0c7f, 0x007c,
+	0x0020, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+	0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+	0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+	0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+	0x0000, 0x0020, 0x0062, 0x0009, 0x0014, 0x0014, 0x9847, 0x0014,
+	0x0014, 0x98f5, 0x98e7, 0x0014, 0x0014, 0x0080, 0x00bf, 0x0100,
+	0x0402, 0x2008, 0xf880, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014,
+	0xa200, 0x8838, 0x817e, 0x842a, 0x84a0, 0x3806, 0x8839, 0x28c2,
+	0x9cc3, 0xa805, 0x0864, 0xa83b, 0x3008, 0x28c1, 0x9cc3, 0xa201,
+	0x300c, 0x2847, 0x8161, 0x846a, 0x8000, 0x84a4, 0x1856, 0x883a,
+	0xa808, 0x28e2, 0x9ca0, 0xa8f3, 0x0864, 0xa829, 0x300c, 0xa801,
+	0x3008, 0x28e1, 0x9ca0, 0x280d, 0xa204, 0x64c0, 0x67a0, 0x6fc0,
+	0x1814, 0x883b, 0x7023, 0x8576, 0x8677, 0xa80f, 0x786e, 0x883e,
+	0xa80c, 0x282b, 0xa205, 0x64a0, 0x67a0, 0x6fc0, 0x1814, 0x883b,
+	0x7023, 0x8576, 0x8677, 0xa801, 0x883e, 0x2069, 0x28c1, 0x9cc3,
+	0x2044, 0x2103, 0x20a2, 0x2081, 0xa8dc, 0xa207, 0x0014, 0xa203,
+	0x8000, 0x84a8, 0x85a4, 0x1872, 0x849a, 0x883c, 0x1fe2, 0xf601,
+	0xa208, 0x856e, 0x866f, 0x0704, 0x3008, 0x9ca0, 0x0014, 0xa202,
+	0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf848, 0x8174, 0x86eb,
+	0x85eb, 0x872e, 0x87a9, 0x883f, 0x08e6, 0xa8f1, 0xf861, 0xa8e8,
+	0xf801, 0x0014, 0xf881, 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfaa2,
+	0x1de2, 0x0014, 0x8532, 0xf221, 0x0014, 0x1de2, 0x84a8, 0xd6e0,
+	0x1fe6, 0x0014, 0xa206, 0x6865, 0x817f, 0x842a, 0x1dc1, 0x8823,
+	0x0016, 0x6042, 0x8008, 0xa8fa, 0x8000, 0x84a4, 0x8160, 0x842a,
+	0xf021, 0x3008, 0x84a8, 0x1dc6, 0x20d7, 0x8822, 0x0016, 0x8000,
+	0x2848, 0x1011, 0xa8fc, 0x3008, 0x8000, 0xa000, 0x2802, 0x1011,
+	0xa8fd, 0xa887, 0x3008, 0x283d, 0x1011, 0xa8fd, 0xa209, 0x0017,
+	0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014, 0x26e0, 0x873a,
+	0xfaa2, 0x19f2, 0x1fe2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x817e,
+	0x842a, 0x84a0, 0x3806, 0x0210, 0x9ccd, 0x0704, 0x0000, 0x127e,
+	0x2091, 0x2200, 0x2049, 0x2ec7, 0x7000, 0x7204, 0xa205, 0x720c,
+	0xa215, 0x7008, 0xa084, 0xfffd, 0xa205, 0x0040, 0x2ed9, 0x0078,
+	0x2ede, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x7000, 0xa084,
+	0x0001, 0x00c0, 0x2f0c, 0x7108, 0x8104, 0x00c8, 0x2eeb, 0x1078,
+	0x2fa8, 0x0078, 0x2ee3, 0x700c, 0xa08c, 0x007f, 0x0040, 0x2f0c,
+	0x7004, 0x8004, 0x00c8, 0x2f03, 0x7014, 0xa005, 0x00c0, 0x2eff,
+	0x7010, 0xa005, 0x0040, 0x2f03, 0xa102, 0x00c8, 0x2ee3, 0x7007,
+	0x0010, 0x0078, 0x2f0c, 0x8aff, 0x0040, 0x2f0c, 0x1078, 0x316b,
+	0x00c0, 0x2f06, 0x0040, 0x2ee3, 0x1078, 0x2f56, 0x7003, 0x0000,
+	0x127f, 0x2000, 0x007c, 0x6424, 0x84ff, 0x0040, 0x2f30, 0x2c70,
+	0x2039, 0x2f35, 0x2704, 0xae68, 0x680c, 0xa630, 0x6808, 0xa529,
+	0x8421, 0x0040, 0x2f30, 0x8738, 0x2704, 0xa005, 0x00c0, 0x2f1b,
+	0x7098, 0xa075, 0x0040, 0x2f30, 0x2039, 0x2f32, 0x0078, 0x2f1a,
+	0x007c, 0x0000, 0x0004, 0x0008, 0x000c, 0x0010, 0x0014, 0x0018,
+	0x001c, 0x0000, 0x127e, 0x2091, 0x2200, 0x2079, 0x3500, 0x2071,
+	0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2071,
+	0x0020, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2049,
+	0x0000, 0x78b3, 0x0000, 0x127f, 0x2000, 0x007c, 0x2049, 0x2f56,
+	0x7004, 0x8004, 0x00c8, 0x2f82, 0x7007, 0x0012, 0x7108, 0x7008,
+	0xa106, 0x00c0, 0x2f5e, 0xa184, 0x0030, 0x0040, 0x2f6b, 0xa086,
+	0x0030, 0x00c0, 0x2f5e, 0x7000, 0xa084, 0x0001, 0x00c0, 0x2f82,
+	0x7008, 0xa084, 0x000c, 0x00c0, 0x2f80, 0x710c, 0xa184, 0x0300,
+	0x00c0, 0x2f80, 0xa184, 0x007f, 0x00c0, 0x2f56, 0x0078, 0x2f82,
+	0x6817, 0x0003, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xa084,
+	0x0008, 0x00c0, 0x2f86, 0x7007, 0x0012, 0x7108, 0x8104, 0x0048,
+	0x2f8b, 0x78b3, 0x0000, 0x7003, 0x0000, 0x2049, 0x0000, 0x007c,
+	0x107e, 0x007e, 0x127e, 0x157e, 0x2091, 0x2200, 0x7108, 0x1078,
+	0x2fa8, 0x157f, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c,
+	0x7204, 0x2118, 0x7108, 0x700c, 0xa084, 0x0300, 0x00c0, 0x2fea,
+	0xa184, 0x000c, 0x00c0, 0x2fea, 0x8213, 0x8213, 0x8213, 0x8213,
+	0xa284, 0x0100, 0xa10d, 0x810b, 0x810b, 0x810f, 0xa184, 0x0007,
+	0x0079, 0x2fc2, 0x2fcc, 0x2fdc, 0x2fea, 0x2fdc, 0x2ffe, 0x2ffe,
+	0x2fea, 0x2ffc, 0x1078, 0x1ba5, 0x7007, 0x0002, 0x8aff, 0x00c0,
+	0x2fd5, 0x2049, 0x0000, 0x0078, 0x2fd9, 0x1078, 0x316b, 0x00c0,
+	0x2fd5, 0x78b3, 0x0000, 0x007c, 0x7007, 0x0002, 0x8aff, 0x00c0,
+	0x2fe3, 0x0078, 0x2fe7, 0x1078, 0x316b, 0x00c0, 0x2fe3, 0x78b3,
+	0x0000, 0x007c, 0x7007, 0x0002, 0x1078, 0x2f56, 0x1078, 0x2cbb,
+	0x6814, 0xa084, 0x8000, 0x0040, 0x2ff7, 0x6817, 0x0002, 0x007c,
+	0x1078, 0x1ba5, 0x1078, 0x1ba5, 0x1078, 0x3050, 0x7210, 0x7114,
+	0x700c, 0xa09c, 0x007f, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000,
+	0x78b0, 0xa005, 0x0040, 0x3010, 0x78b3, 0x0000, 0x0078, 0x3033,
+	0x1078, 0x3050, 0x2704, 0x2c58, 0xac60, 0x630c, 0x2200, 0xa322,
+	0x6308, 0x2100, 0xa31b, 0x2400, 0xa305, 0x0040, 0x3029, 0x00c8,
+	0x3029, 0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078,
+	0x3010, 0x2b60, 0x8a07, 0xa7ba, 0x2f32, 0xa73d, 0x2c00, 0x6882,
+	0x6f86, 0x6c8e, 0x6b8a, 0x7007, 0x0012, 0x1078, 0x2f56, 0x007c,
+	0x8738, 0x2704, 0xa005, 0x00c0, 0x3044, 0x6098, 0xa005, 0x0040,
+	0x304d, 0x2060, 0x2039, 0x2f32, 0x8a51, 0x0040, 0x304c, 0x7008,
+	0xa084, 0x00c0, 0xa086, 0x00c0, 0x007c, 0x2051, 0x0000, 0x007c,
+	0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x305d, 0x2039, 0x2f38,
+	0x6000, 0xa064, 0x00c0, 0x305d, 0x2d60, 0x007c, 0x127e, 0x0d7e,
+	0x2091, 0x2200, 0x0d7f, 0x6880, 0x2060, 0x6884, 0x6b88, 0x6c8c,
+	0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0xa0b8, 0x2f32, 0x7e08,
+	0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, 0x0040, 0x3079, 0xa6b5,
+	0x0001, 0x0f7e, 0x2079, 0x0100, 0x7858, 0x0f7f, 0xa084, 0x0040,
+	0x0040, 0x3088, 0xa684, 0x0001, 0x00c0, 0x3088, 0xa6b5, 0x0001,
+	0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x308a, 0x7000,
+	0xa005, 0x0040, 0x3095, 0x1078, 0x1ba5, 0x2400, 0xa305, 0x00c0,
+	0x309b, 0x0078, 0x30d8, 0x2c58, 0x2704, 0xac60, 0x6004, 0xa400,
+	0x007e, 0x701a, 0x6000, 0xa301, 0x701e, 0x2009, 0x04fd, 0x2104,
+	0xa086, 0x04fd, 0x007f, 0x00c0, 0x30c8, 0xa084, 0x0001, 0x0040,
+	0x30c8, 0xa684, 0x0001, 0x00c0, 0x30c8, 0x7013, 0x0001, 0x7017,
+	0x0000, 0x7602, 0x7007, 0x0001, 0x78b3, 0x0001, 0xa4a0, 0x0001,
+	0xa399, 0x0000, 0x6004, 0xa400, 0x701a, 0x6000, 0xa301, 0x701e,
+	0x620c, 0x2400, 0xa202, 0x7012, 0x6208, 0x2300, 0xa203, 0x7016,
+	0x7602, 0x7007, 0x0001, 0x2b60, 0x1078, 0x3038, 0x0078, 0x30da,
+	0x1078, 0x316b, 0x00c0, 0x30d8, 0x127f, 0x2000, 0x007c, 0x127e,
+	0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xa084,
+	0x0004, 0x00c0, 0x30e6, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c,
+	0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x30f0, 0x7007,
+	0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x30f9, 0x7000, 0xa005,
+	0x0040, 0x3104, 0x1078, 0x1ba5, 0x7e08, 0xa6b5, 0x000c, 0x6818,
+	0xa084, 0x0040, 0x0040, 0x310e, 0xa6b5, 0x0001, 0x6824, 0xa005,
+	0x0040, 0x311a, 0x2050, 0x2039, 0x2f35, 0x2d60, 0x1078, 0x316b,
+	0x00c0, 0x3116, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x017e,
+	0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f, 0x047f, 0x7e08, 0xa6b5,
+	0x000c, 0x6818, 0xa084, 0x0040, 0x0040, 0x3130, 0xa6b5, 0x0001,
+	0x2049, 0x311d, 0x6824, 0xa055, 0x0040, 0x3168, 0x2d70, 0x2e60,
+	0x2039, 0x2f35, 0x2704, 0xae68, 0x680c, 0xa422, 0x6808, 0xa31b,
+	0x0048, 0x3155, 0x8a51, 0x00c0, 0x3147, 0x1078, 0x1ba5, 0x8738,
+	0x2704, 0xa005, 0x00c0, 0x313b, 0x7098, 0xa075, 0x2060, 0x0040,
+	0x3168, 0x2039, 0x2f32, 0x0078, 0x313a, 0x8422, 0x8420, 0x831a,
+	0xa399, 0x0000, 0x690c, 0x2400, 0xa122, 0x6908, 0x2300, 0xa11b,
+	0x00c8, 0x3164, 0x1078, 0x1ba5, 0x2071, 0x0020, 0x0078, 0x3088,
+	0x127f, 0x2000, 0x007c, 0x7008, 0xa084, 0x00c0, 0xa086, 0x00c0,
+	0x0040, 0x3193, 0x2704, 0xac08, 0x2104, 0x701e, 0x8108, 0x2104,
+	0x701a, 0x8108, 0x2104, 0x7016, 0x8108, 0x2104, 0x7012, 0x0f7e,
+	0x2079, 0x0100, 0x7858, 0x0f7f, 0xa084, 0x0040, 0x0040, 0x318e,
+	0xa684, 0x0001, 0x00c0, 0x318e, 0xa6b5, 0x0001, 0x7602, 0x7007,
+	0x0001, 0x1078, 0x3038, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091,
+	0x2200, 0x2049, 0x3194, 0x0d7f, 0x087f, 0x7108, 0xa184, 0x00c0,
+	0x00c0, 0x31aa, 0x6824, 0xa005, 0x0040, 0x31ba, 0x0078, 0x2ede,
+	0x0078, 0x31ba, 0x7108, 0x8104, 0x00c8, 0x31b2, 0x1078, 0x2fa8,
+	0x0078, 0x319d, 0x7007, 0x0010, 0x7108, 0x8104, 0x00c8, 0x31b4,
+	0x1078, 0x2fa8, 0x7008, 0xa086, 0x0002, 0x00c0, 0x319d, 0x7000,
+	0xa005, 0x00c0, 0x319d, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f,
+	0x2000, 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0d7e, 0x2091,
+	0x2200, 0x0d7f, 0x2049, 0x31ca, 0xad80, 0x0010, 0x20a0, 0x2099,
+	0x0031, 0x700c, 0xa084, 0x007f, 0x6826, 0x7007, 0x0008, 0x7007,
+	0x0002, 0x7003, 0x0001, 0x0040, 0x31e8, 0x8000, 0x80ac, 0x53a5,
+	0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x31ea, 0x2049,
+	0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f, 0x127f, 0x2000,
+	0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049,
+	0x31f9, 0x6880, 0x2060, 0x6884, 0x6b88, 0x6c8c, 0x8057, 0xaad4,
+	0x00ff, 0xa084, 0x00ff, 0xa0b8, 0x2f32, 0x7e08, 0xa6b5, 0x0004,
+	0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x3212, 0x2c58,
+	0x2704, 0xac60, 0x6004, 0xa400, 0x701a, 0x6000, 0xa301, 0x701e,
+	0x7013, 0x0001, 0x7017, 0x0000, 0x7602, 0x7007, 0x0001, 0x007f,
+	0x8007, 0x2009, 0x0031, 0x200a, 0x00a0, 0x322c, 0x7108, 0x7007,
+	0x0002, 0x810c, 0x00c8, 0x322c, 0x810c, 0x0048, 0x3239, 0x0078,
+	0x2fea, 0xa4a0, 0x0001, 0xa399, 0x0000, 0x6b8a, 0x6c8e, 0x7007,
+	0x0004, 0x2049, 0x0000, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c,
+	0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x3251,
+	0xa200, 0x00f0, 0x324c, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9,
+	0x0010, 0xa005, 0x0040, 0x3277, 0xa11a, 0x00c8, 0x3277, 0x8213,
+	0x818d, 0x0048, 0x326a, 0xa11a, 0x00c8, 0x326b, 0x00f0, 0x325f,
+	0x0078, 0x326f, 0xa11a, 0x2308, 0x8210, 0x00f0, 0x325f, 0x007e,
+	0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f, 0x007c, 0x007e,
+	0x3200, 0xa085, 0x0800, 0x0078, 0x3273, 0x00e0, 0x32bf, 0x2091,
+	0x6000, 0x7820, 0x8001, 0x7822, 0x00c0, 0x32b9, 0x7824, 0x7822,
+	0x2091, 0x8000, 0x2069, 0x3540, 0x6800, 0xa084, 0x0007, 0x0040,
+	0x32a1, 0xa086, 0x0002, 0x0040, 0x32a1, 0x6830, 0xa00d, 0x0040,
+	0x32a1, 0x2104, 0xa005, 0x0040, 0x32a1, 0x8001, 0x200a, 0x0040,
+	0x336f, 0x2061, 0x3680, 0x20a9, 0x0080, 0x6034, 0xa005, 0x0040,
+	0x32b3, 0x8001, 0x6036, 0x00c0, 0x32b3, 0x6010, 0xa005, 0x0040,
+	0x32b3, 0x1078, 0x1a19, 0xace0, 0x0010, 0x0070, 0x32b9, 0x0078,
+	0x32a5, 0x1078, 0x32d4, 0x1078, 0x32c2, 0x1078, 0x32f9, 0x2091,
+	0x8001, 0x007c, 0x783c, 0x8001, 0x783e, 0x00c0, 0x32d3, 0x7840,
+	0x783e, 0x7848, 0xa005, 0x0040, 0x32d3, 0x8001, 0x784a, 0x00c0,
+	0x32d3, 0x1078, 0x1a19, 0x007c, 0x7834, 0x8001, 0x7836, 0x00c0,
+	0x32f8, 0x7838, 0x7836, 0x2091, 0x8000, 0x7844, 0xa005, 0x00c0,
+	0x32e3, 0x2001, 0x0101, 0x8001, 0x7846, 0xa080, 0x3e80, 0x2040,
+	0x2004, 0xa065, 0x0040, 0x32f8, 0x6020, 0xa005, 0x0040, 0x32f4,
+	0x8001, 0x6022, 0x0040, 0x3328, 0x6000, 0x2c40, 0x0078, 0x32e9,
+	0x007c, 0x7828, 0x8001, 0x782a, 0x00c0, 0x3327, 0x782c, 0x782a,
+	0x7830, 0xa005, 0x00c0, 0x3306, 0x2001, 0x0080, 0x8001, 0x7832,
+	0x8003, 0x8003, 0x8003, 0x8003, 0xa090, 0x3680, 0xa298, 0x0002,
+	0x2304, 0xa084, 0x0008, 0x0040, 0x3327, 0xa290, 0x0009, 0x2204,
+	0xa005, 0x0040, 0x331f, 0x8001, 0x2012, 0x00c0, 0x3327, 0x2304,
+	0xa084, 0xfff7, 0xa085, 0x0080, 0x201a, 0x1078, 0x1a19, 0x007c,
+	0x2069, 0x3540, 0x6800, 0xa005, 0x0040, 0x3332, 0x683c, 0xac06,
+	0x0040, 0x336f, 0x6017, 0x0006, 0x60b0, 0xa084, 0x3f00, 0x601a,
 	0x601c, 0xa084, 0x00ff, 0xa085, 0x0060, 0x601e, 0x6000, 0x2042,
-	0x6710, 0x6fb6, 0x1078, 0x1681, 0x6818, 0xa005, 0x0040, 0x3252,
+	0x6710, 0x6fb6, 0x1078, 0x1692, 0x6818, 0xa005, 0x0040, 0x334a,
 	0x8001, 0x681a, 0x6808, 0xa084, 0xffef, 0x680a, 0x6810, 0x8001,
-	0x00d0, 0x325c, 0x1078, 0x1b4e, 0x6812, 0x602f, 0x0000, 0x602b,
-	0x0000, 0x2c68, 0x1078, 0x17be, 0x2069, 0x3440, 0x2001, 0x0006,
-	0x68a2, 0x7944, 0xa184, 0x0100, 0x00c0, 0x3272, 0x69ba, 0x2001,
-	0x0004, 0x68a2, 0x1078, 0x19f3, 0x2091, 0x8001, 0x007c, 0x2009,
-	0x344f, 0x2164, 0x2069, 0x0100, 0x6017, 0x0006, 0x6858, 0xa084,
-	0x3f00, 0x601a, 0x601c, 0xa084, 0x00ff, 0xa085, 0x0048, 0x601e,
-	0x602f, 0x0000, 0x602b, 0x0000, 0x6830, 0xa084, 0x0040, 0x0040,
-	0x32b1, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004,
-	0x0040, 0x329e, 0x0070, 0x329e, 0x0078, 0x3295, 0x684b, 0x0009,
-	0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040, 0x32ab, 0x0070,
-	0x32ab, 0x0078, 0x32a2, 0x20a9, 0x00fa, 0x0070, 0x32b1, 0x0078,
-	0x32ad, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0046, 0x2009,
-	0x3468, 0x200b, 0x0007, 0x784c, 0x784a, 0x2091, 0x8001, 0x007c,
-	0x2079, 0x3400, 0x1078, 0x3309, 0x1078, 0x32d1, 0x1078, 0x32e6,
-	0x1078, 0x32fb, 0x7833, 0x0000, 0x7847, 0x0000, 0x784b, 0x0000,
-	0x007c, 0x2019, 0x000a, 0x2011, 0x3446, 0x2204, 0xa086, 0x0032,
-	0x0040, 0x32e3, 0x2019, 0x000c, 0x2204, 0xa086, 0x003c, 0x0040,
-	0x32e3, 0x2019, 0x0008, 0x7b2a, 0x7b2e, 0x007c, 0x2019, 0x0030,
-	0x2011, 0x3446, 0x2204, 0xa086, 0x0032, 0x0040, 0x32f8, 0x2019,
-	0x0039, 0x2204, 0xa086, 0x003c, 0x0040, 0x32f8, 0x2019, 0x0027,
-	0x7b36, 0x7b3a, 0x007c, 0x2019, 0x000d, 0x2011, 0x3446, 0x2204,
-	0xa086, 0x003c, 0x0040, 0x3306, 0x2019, 0x000a, 0x7b3e, 0x7b42,
-	0x007c, 0x2019, 0x2faf, 0x2011, 0x3446, 0x2204, 0xa086, 0x0032,
-	0x0040, 0x331b, 0x2019, 0x3971, 0x2204, 0xa086, 0x003c, 0x0040,
-	0x331b, 0x2019, 0x2626, 0x7b22, 0x7b26, 0x007c, 0xae5b
-};
-
-unsigned short pti_risc_code_length01 = 0x231f;
-
-/* Version 1.31.00 ISP1000 Initiator RISC firmware
- * We use this for all non-PTI SBUS boards.
- */
-unsigned short sbus_risc_code_addr01 = 0x1000;
-
-unsigned short sbus_risc_code01[] __initdata = {
-	0x0078, 0x1030, 0xa5e3, 0x241a, 0x0001, 0x12ff, 0x2043, 0x4f50,
-	0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932,
-	0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749,
-	0x4320, 0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049,
-	0x5350, 0x3130, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520,
-	0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3331, 0x2020,
-	0x2071, 0x0010, 0x70c3, 0x0004, 0x20c9, 0x3fff, 0x2089, 0x10ca,
-	0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0001,
-	0x3f00, 0x70d6, 0x2031, 0x0030, 0x2079, 0x3500, 0x7863, 0x0000,
-	0x2fa0, 0x2009, 0x012b, 0x2011, 0x0000, 0x20a9, 0x0040, 0x42a4,
-	0x8109, 0x00c0, 0x104d, 0x789b, 0x0101, 0x780b, 0x0002, 0x780f,
-	0x0002, 0x784f, 0x0bb8, 0x2069, 0x3540, 0x00a8, 0x106c, 0x681b,
-	0x003c, 0x2009, 0x1313, 0xa18c, 0xff00, 0x3700, 0xa084, 0x00ff,
-	0xa105, 0x20b8, 0x0078, 0x106e, 0x681b, 0x0028, 0x6807, 0x0007,
-	0x680b, 0x00fa, 0x680f, 0x0008, 0x6813, 0x0005, 0x681f, 0x0000,
-	0x6823, 0x0006, 0x6817, 0x0008, 0x6827, 0x0000, 0x2069, 0x3600,
-	0x2011, 0x0020, 0x2009, 0x0010, 0x680b, 0x0c19, 0x680f, 0x0019,
-	0x6803, 0xdd00, 0x6807, 0x001a, 0x6a1a, 0x2d00, 0xa0e8, 0x0008,
-	0xa290, 0x0004, 0x8109, 0x00c0, 0x1084, 0x2069, 0x3680, 0x20a9,
-	0x0080, 0x6837, 0x0000, 0x680b, 0x0040, 0x6817, 0x0064, 0x681f,
-	0x0002, 0xade8, 0x0010, 0x0070, 0x10a7, 0x0078, 0x1099, 0x1078,
-	0x1a42, 0x1078, 0x2f3d, 0x1078, 0x168b, 0x1078, 0x33bb, 0x3200,
-	0xa085, 0x000d, 0x2090, 0x70c3, 0x0000, 0x0090, 0x10be, 0x70c0,
-	0xa086, 0x0002, 0x00c0, 0x10be, 0x1078, 0x11be, 0x1078, 0x10ee,
-	0x1078, 0x1821, 0x1078, 0x19b2, 0x1078, 0x3280, 0x1078, 0x1787,
-	0x0078, 0x10be, 0x10d2, 0x10d4, 0x1b9f, 0x1b9f, 0x2f9b, 0x2f9b,
-	0x1b9f, 0x1b9f, 0x0078, 0x10d2, 0x0078, 0x10d4, 0x0078, 0x10d6,
-	0x0078, 0x10d8, 0x7008, 0x800c, 0x00c8, 0x10e9, 0x7007, 0x0002,
-	0xa08c, 0x000c, 0x00c0, 0x10ea, 0x8004, 0x8004, 0x00c8, 0x10e9,
-	0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, 0x11c1, 0x0068, 0x1133,
-	0x7814, 0xa005, 0x00c0, 0x10f8, 0x0010, 0x1134, 0x0078, 0x1133,
-	0x2009, 0x3568, 0x2104, 0xa005, 0x00c0, 0x1133, 0x7814, 0xa086,
-	0x0001, 0x00c0, 0x1105, 0x1078, 0x1540, 0x7817, 0x0000, 0x2009,
-	0x356f, 0x2104, 0xa065, 0x0040, 0x1121, 0x2009, 0x356a, 0x211c,
-	0x8108, 0x2114, 0x8108, 0x2104, 0xa210, 0xa399, 0x0000, 0x2009,
-	0x001c, 0x6083, 0x0103, 0x1078, 0x161b, 0x00c0, 0x112d, 0x1078,
-	0x1682, 0x2009, 0x356f, 0x200b, 0x0000, 0x2009, 0x3569, 0x2104,
-	0x200b, 0x0000, 0xa005, 0x0040, 0x1131, 0x2001, 0x4005, 0x0078,
-	0x11c0, 0x0078, 0x11be, 0x007c, 0x2061, 0x0000, 0x6018, 0xa084,
-	0x0001, 0x0040, 0x113c, 0x007c, 0x70c3, 0x0000, 0x70c7, 0x0000,
-	0x70cb, 0x0000, 0x70cf, 0x0000, 0x70c0, 0xa0bc, 0xffc0, 0x00c0,
-	0x118c, 0x2038, 0x0079, 0x114c, 0x11be, 0x1209, 0x11d7, 0x1209,
-	0x125a, 0x125a, 0x11ce, 0x159a, 0x1265, 0x11ca, 0x11db, 0x11dd,
-	0x11df, 0x11e1, 0x159f, 0x11ca, 0x126b, 0x1287, 0x154e, 0x1594,
-	0x11e3, 0x1475, 0x1497, 0x14b1, 0x14da, 0x142e, 0x143c, 0x1450,
-	0x1464, 0x12f3, 0x11ca, 0x12a3, 0x12aa, 0x12af, 0x12b4, 0x12ba,
-	0x12bf, 0x12c4, 0x12c9, 0x12ce, 0x12d2, 0x12e7, 0x11ca, 0x11ca,
-	0x11ca, 0x11ca, 0x11ca, 0x12ff, 0x1308, 0x1317, 0x133d, 0x1347,
-	0x134e, 0x137a, 0x1389, 0x1398, 0x13aa, 0x1413, 0x11ca, 0x11ca,
-	0x11ca, 0x11ca, 0x11ca, 0x1423, 0xa0bc, 0xffa0, 0x00c0, 0x11ca,
-	0x2038, 0xa084, 0x001f, 0x0079, 0x1195, 0x11ca, 0x11ca, 0x11ca,
-	0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca,
-	0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca,
-	0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x11ca, 0x15f7,
-	0x1601, 0x1605, 0x1613, 0x11ca, 0x11ca, 0x72ca, 0x71c6, 0x2001,
-	0x4006, 0x0078, 0x11c0, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000,
-	0x70c2, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091,
-	0x4080, 0x007c, 0x70c3, 0x4001, 0x0078, 0x11c1, 0x2099, 0x0041,
-	0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078, 0x11be, 0x70c4,
-	0x70c3, 0x0004, 0x007a, 0x0078, 0x11be, 0x0078, 0x11be, 0x0078,
-	0x11be, 0x0078, 0x11be, 0x2091, 0x8000, 0x70c3, 0x0000, 0x70c7,
-	0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0001, 0x3f00,
-	0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031, 0x0030, 0x2059,
-	0x1000, 0x2029, 0x0457, 0x2051, 0x0470, 0x2061, 0x0472, 0x20b9,
-	0xffff, 0x20c1, 0x0000, 0x2091, 0x5000, 0x2091, 0x4080, 0x0078,
-	0x0455, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0, 0x2098, 0x2031,
-	0x0030, 0x81ff, 0x0040, 0x11be, 0x7007, 0x0004, 0x731a, 0x721e,
-	0x2051, 0x0012, 0x2049, 0x1238, 0x2041, 0x11be, 0x7003, 0x0002,
-	0xa786, 0x0001, 0x00c0, 0x122a, 0x2049, 0x1246, 0x2041, 0x1252,
-	0x7003, 0x0003, 0x7017, 0x0000, 0x810b, 0x7112, 0x00c8, 0x1232,
-	0x7017, 0x0001, 0x7007, 0x0001, 0xa786, 0x0001, 0x0040, 0x1246,
-	0x700c, 0xa084, 0x007f, 0x8004, 0x2009, 0x0020, 0xa102, 0x0942,
-	0x094a, 0x20a8, 0x26a0, 0x53a6, 0x0078, 0x10da, 0x700c, 0xa084,
-	0x007f, 0x0040, 0x1246, 0x80ac, 0x0048, 0x1246, 0x2698, 0x53a5,
-	0x0078, 0x10da, 0x700c, 0xa084, 0x007f, 0x80ac, 0x2698, 0x53a5,
-	0x0078, 0x11be, 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x00c0,
-	0x1262, 0x200a, 0x72ca, 0x0078, 0x11bd, 0x70c7, 0x0001, 0x70cb,
-	0x001f, 0x0078, 0x11be, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6,
-	0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x1281, 0x8001, 0x7872,
-	0x7a7a, 0x7b7e, 0x7c76, 0x7898, 0xa084, 0xfffc, 0x789a, 0x0078,
-	0x1285, 0x7898, 0xa085, 0x0001, 0x789a, 0x0078, 0x11be, 0x70c4,
-	0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6, 0xa005,
-	0x0040, 0x129d, 0x8001, 0x7886, 0x7a8e, 0x7b92, 0x7c8a, 0x7898,
-	0xa084, 0xfcff, 0x789a, 0x0078, 0x12a1, 0x7898, 0xa085, 0x0100,
-	0x789a, 0x0078, 0x11be, 0x2009, 0x3559, 0x210c, 0x2011, 0x015c,
-	0x0078, 0x11bc, 0x2009, 0x3541, 0x210c, 0x0078, 0x11bd, 0x2009,
-	0x3542, 0x210c, 0x0078, 0x11bd, 0x2061, 0x3540, 0x610c, 0x6210,
-	0x0078, 0x11bc, 0x2009, 0x3545, 0x210c, 0x0078, 0x11bd, 0x2009,
-	0x3546, 0x210c, 0x0078, 0x11bd, 0x2009, 0x3547, 0x210c, 0x0078,
-	0x11bd, 0x2009, 0x3548, 0x210c, 0x0078, 0x11bd, 0x7908, 0x7a0c,
-	0x0078, 0x11bc, 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
-	0x8003, 0xa0e8, 0x3600, 0x6a00, 0x6804, 0xa084, 0x0008, 0x0040,
-	0x12e4, 0x6b08, 0x0078, 0x12e5, 0x6b0c, 0x0078, 0x11bb, 0x77c4,
-	0x1078, 0x169c, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001,
-	0x2708, 0x0078, 0x11bb, 0x77c4, 0x1078, 0x169c, 0x2091, 0x8000,
-	0x6908, 0x6a18, 0x6b10, 0x2091, 0x8001, 0x0078, 0x11bb, 0x71c4,
-	0xa182, 0x0010, 0x00c8, 0x11b6, 0x1078, 0x1ac6, 0x0078, 0x11bb,
-	0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b6, 0x2011, 0x3541, 0x2204,
-	0x007e, 0x2112, 0x1078, 0x1a7f, 0x017f, 0x0078, 0x11bd, 0x71c4,
-	0x2011, 0x1335, 0x20a9, 0x0008, 0x2204, 0xa106, 0x0040, 0x1327,
-	0x8210, 0x0070, 0x1325, 0x0078, 0x131c, 0x0078, 0x11b6, 0xa292,
-	0x1335, 0x027e, 0x2011, 0x3542, 0x2204, 0x2112, 0x017f, 0x007e,
-	0x1078, 0x1a8b, 0x017f, 0x0078, 0x11bd, 0x03e8, 0x00fa, 0x01f4,
-	0x02ee, 0x0064, 0x0019, 0x0032, 0x004b, 0x2061, 0x3540, 0x610c,
-	0x6210, 0x70c4, 0x600e, 0x70c8, 0x6012, 0x0078, 0x11bc, 0x2061,
-	0x3540, 0x6114, 0x70c4, 0x6016, 0x0078, 0x11bd, 0x71c4, 0x2011,
-	0x0004, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, 0x1367, 0x2011,
-	0x0005, 0x2019, 0x1212, 0xa186, 0x0032, 0x0040, 0x1367, 0x2011,
-	0x0006, 0x2019, 0x1313, 0xa186, 0x003c, 0x00c0, 0x11b6, 0x2061,
-	0x3540, 0x6018, 0x007e, 0x611a, 0xa39c, 0xff00, 0x3700, 0xa084,
-	0x00ff, 0xa305, 0x20b8, 0x1078, 0x1a9c, 0x1078, 0x33bb, 0x017f,
-	0x0078, 0x11bd, 0x71c4, 0xa184, 0xffcf, 0x00c0, 0x11b6, 0x2011,
-	0x3547, 0x2204, 0x2112, 0x007e, 0x1078, 0x1abe, 0x017f, 0x0078,
-	0x11bd, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b6, 0x2011, 0x3548,
-	0x2204, 0x007e, 0x2112, 0x1078, 0x1aad, 0x017f, 0x0078, 0x11bd,
-	0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x11b5, 0xa284, 0xfffd,
-	0x00c0, 0x11b5, 0x2100, 0x7908, 0x780a, 0x2200, 0x7a0c, 0x780e,
-	0x0078, 0x11bc, 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
-	0x8003, 0xa0e8, 0x3600, 0x2019, 0x0000, 0x72c8, 0x6800, 0x007e,
-	0xa226, 0x0040, 0x13d9, 0x6a02, 0xa484, 0x2000, 0x0040, 0x13c2,
-	0xa39d, 0x0010, 0xa484, 0x1000, 0x0040, 0x13c8, 0xa39d, 0x0008,
-	0xa484, 0x4000, 0x0040, 0x13d9, 0x810f, 0xa284, 0x4000, 0x0040,
-	0x13d5, 0x1078, 0x1ae0, 0x0078, 0x13d9, 0x1078, 0x1ad2, 0x0078,
-	0x13d9, 0x72cc, 0x82ff, 0x0040, 0x140b, 0x6808, 0xa206, 0x0040,
-	0x140b, 0xa2a4, 0x00ff, 0x2061, 0x3540, 0x6118, 0xa186, 0x0028,
-	0x0040, 0x13f2, 0xa186, 0x0032, 0x0040, 0x13f8, 0xa186, 0x003c,
-	0x0040, 0x13fe, 0xa482, 0x0064, 0x0048, 0x1408, 0x0078, 0x1402,
-	0xa482, 0x0050, 0x0048, 0x1408, 0x0078, 0x1402, 0xa482, 0x0043,
-	0x0048, 0x1408, 0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x11b7,
-	0x6a0a, 0xa39d, 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c,
-	0x71c4, 0x0078, 0x11bb, 0x77c4, 0x1078, 0x169c, 0x2091, 0x8000,
-	0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e,
-	0x2708, 0x0078, 0x11bb, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010,
-	0x00c8, 0x11b6, 0x1078, 0x1aee, 0x0078, 0x11bb, 0x77c4, 0x1078,
-	0x169c, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0002, 0x6a0a, 0x2091,
-	0x8001, 0x2708, 0x0078, 0x11bc, 0x77c4, 0x1078, 0x169c, 0x2091,
-	0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0040,
-	0x144b, 0x1078, 0x1a23, 0x2091, 0x8001, 0x2708, 0x0078, 0x11bc,
-	0x77c4, 0x1078, 0x169c, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0004,
-	0x6a0a, 0x6804, 0xa005, 0x0040, 0x145f, 0x1078, 0x1a23, 0x2091,
-	0x8001, 0x2708, 0x0078, 0x11bc, 0x77c4, 0x2041, 0x0001, 0x2049,
-	0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, 0x16a9, 0x2091,
-	0x8001, 0x2708, 0x6a08, 0x0078, 0x11bc, 0x77c4, 0x72c8, 0x73cc,
-	0x77c6, 0x72ca, 0x73ce, 0x1078, 0x1722, 0x00c0, 0x1493, 0x6818,
-	0xa005, 0x0040, 0x148d, 0x2708, 0x1078, 0x1afe, 0x00c0, 0x148d,
-	0x7817, 0xffff, 0x2091, 0x8001, 0x007c, 0x2091, 0x8001, 0x2001,
-	0x4005, 0x0078, 0x11c0, 0x2091, 0x8001, 0x0078, 0x11be, 0x77c4,
-	0x77c6, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091,
-	0x8000, 0x1078, 0x16a9, 0x2061, 0x3540, 0x60a3, 0x0003, 0x67b6,
-	0x60a7, 0x0000, 0x7817, 0xffff, 0x2091, 0x8001, 0x1078, 0x1a23,
-	0x007c, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091,
-	0x8000, 0x2061, 0x3540, 0x60a3, 0x0002, 0x60a7, 0x0000, 0x67b6,
-	0x7817, 0xffff, 0x1078, 0x1a23, 0x2091, 0x8001, 0x2041, 0x0021,
-	0x2049, 0x0004, 0x2051, 0x0010, 0x2091, 0x8000, 0x1078, 0x16a9,
-	0x70c8, 0x6836, 0x8738, 0xa784, 0x0007, 0x00c0, 0x14ce, 0x2091,
-	0x8001, 0x007c, 0x7898, 0xa084, 0x0003, 0x00c0, 0x14fe, 0x2039,
-	0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078,
-	0x169c, 0x2091, 0x8000, 0x6808, 0xa80d, 0x690a, 0x2091, 0x8001,
-	0x8738, 0xa784, 0x0007, 0x00c0, 0x14e7, 0xa7bc, 0xff00, 0x873f,
-	0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x14e7, 0x2091, 0x8000,
-	0x2069, 0x0100, 0x6830, 0xa084, 0x0040, 0x0040, 0x1527, 0x684b,
-	0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004, 0x0040, 0x1514,
-	0x0070, 0x1514, 0x0078, 0x150b, 0x684b, 0x0009, 0x20a9, 0x0014,
-	0x6848, 0xa084, 0x0001, 0x0040, 0x1521, 0x0070, 0x1521, 0x0078,
-	0x1518, 0x20a9, 0x00fa, 0x0070, 0x1527, 0x0078, 0x1523, 0x2079,
-	0x3500, 0x7817, 0x0001, 0x2061, 0x3540, 0x60a3, 0x0001, 0x60a7,
-	0x0000, 0x60c3, 0x000f, 0x7898, 0xa085, 0x0002, 0x789a, 0x6808,
-	0xa084, 0xfffd, 0x680a, 0x681b, 0x0046, 0x2091, 0x8001, 0x007c,
-	0x7898, 0xa084, 0xfffd, 0x789a, 0xa084, 0x0001, 0x00c0, 0x154a,
-	0x1078, 0x176a, 0x71c4, 0x71c6, 0x794a, 0x007c, 0x74c4, 0x73c8,
-	0x72cc, 0x74c6, 0x73ca, 0x72ce, 0x2079, 0x3500, 0x2009, 0x0040,
-	0x1078, 0x1679, 0x0040, 0x1590, 0x1078, 0x1649, 0x0040, 0x1564,
-	0x1078, 0x1682, 0x0078, 0x1590, 0x6010, 0x2091, 0x8001, 0x7817,
-	0xffff, 0x2009, 0x3568, 0x200b, 0x0005, 0x8108, 0x200b, 0x0000,
-	0x8108, 0x230a, 0x8108, 0x220a, 0x8108, 0x240a, 0x8108, 0x200a,
-	0x8108, 0x200b, 0x0000, 0x8108, 0x2c0a, 0xa02e, 0x2530, 0x0e7e,
-	0x1078, 0x2f16, 0x0e7f, 0x6592, 0x65a2, 0x6696, 0x66a6, 0x60ab,
-	0x0000, 0x60af, 0x0000, 0x2091, 0x8001, 0x1078, 0x1a23, 0x007c,
-	0x70c3, 0x4005, 0x0078, 0x11c1, 0x71c4, 0x70c7, 0x0000, 0x7906,
-	0x0078, 0x11be, 0x71c4, 0x71c6, 0x2168, 0x0078, 0x15a1, 0x2069,
-	0x1000, 0x690c, 0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0,
-	0x15a3, 0xa285, 0x0000, 0x00c0, 0x15b1, 0x70c3, 0x4000, 0x0078,
-	0x15b3, 0x70c3, 0x4003, 0x70ca, 0x0078, 0x11c1, 0x71c4, 0x72c8,
-	0x73cc, 0x2100, 0xa184, 0xfffc, 0x00c0, 0x11ca, 0x2100, 0x0079,
-	0x15c1, 0x15d8, 0x15ed, 0x15ef, 0x15f1, 0x70c3, 0x4003, 0x71ce,
-	0x72d2, 0x73d6, 0x0078, 0x15d4, 0x70c3, 0x4000, 0x70cf, 0x0000,
-	0x70d3, 0x0000, 0x70d7, 0x0000, 0x77c6, 0x71ca, 0x0078, 0x11be,
-	0x2031, 0x15f3, 0x2624, 0x8630, 0x2412, 0x2204, 0xa446, 0x00c0,
-	0x15c5, 0xa484, 0xffff, 0x00c0, 0x15da, 0x2031, 0x15f3, 0x8210,
-	0x8319, 0xa384, 0xffff, 0x00c0, 0x15da, 0x0078, 0x15cc, 0x0078,
-	0x15cc, 0x0078, 0x15cc, 0x5555, 0xaaaa, 0xffff, 0x0000, 0x7960,
-	0x71c6, 0x71c4, 0xa182, 0x0003, 0x00c8, 0x11b6, 0x7962, 0x0078,
-	0x11be, 0x7960, 0x71c6, 0x0078, 0x11be, 0x7954, 0x71c6, 0x71c4,
-	0x7956, 0x7958, 0x71ca, 0x71c8, 0x795a, 0x795c, 0x71ce, 0x71cc,
-	0x795e, 0x0078, 0x11be, 0x7954, 0x71c6, 0x7958, 0x71ca, 0x795c,
-	0x71ce, 0x0078, 0x11be, 0x700c, 0xa084, 0x007f, 0x0040, 0x1627,
-	0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x1622, 0x7017,
-	0x0000, 0x7112, 0x721a, 0x731e, 0x8108, 0x810c, 0x81a9, 0x8c98,
-	0x20a1, 0x0030, 0x6080, 0x20a2, 0x53a6, 0x780c, 0xa085, 0x0000,
-	0x7002, 0x7007, 0x0001, 0x7108, 0x8104, 0x00c8, 0x163b, 0x7007,
-	0x0002, 0xa184, 0x000c, 0x710c, 0xa184, 0x0300, 0x7003, 0x0000,
-	0x007c, 0x700c, 0xa084, 0x007f, 0x0040, 0x1655, 0x7007, 0x0004,
-	0x7004, 0xa084, 0x0004, 0x00c0, 0x1650, 0x7017, 0x0000, 0x7112,
-	0x721a, 0x731e, 0x2099, 0x0030, 0x8108, 0x81ac, 0x780c, 0xa085,
-	0x0001, 0x7002, 0x7007, 0x0001, 0x7008, 0x800c, 0x00c8, 0x1664,
-	0x7007, 0x0002, 0xa08c, 0x000c, 0x00c0, 0x1676, 0x710c, 0xa184,
-	0x0300, 0x00c0, 0x1676, 0x2ca0, 0x53a5, 0xa006, 0x7003, 0x0000,
-	0x007c, 0x7850, 0xa065, 0x0040, 0x1681, 0x2c04, 0x7852, 0x2063,
-	0x0000, 0x007c, 0x0f7e, 0x2079, 0x3500, 0x7850, 0x2062, 0x2c00,
-	0x7852, 0x0f7f, 0x007c, 0x2011, 0x4000, 0x7a52, 0x2019, 0x015c,
-	0x8319, 0x0040, 0x1699, 0xa280, 0x002f, 0x2012, 0x2010, 0x0078,
-	0x1690, 0x2013, 0x0000, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784,
-	0x0007, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8, 0x3680,
-	0x007c, 0x1078, 0x169c, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808,
-	0xa084, 0xffef, 0xa80d, 0x690a, 0x2009, 0x354f, 0x210c, 0x6804,
-	0xa005, 0x0040, 0x16c6, 0xa116, 0x00c0, 0x16c6, 0x2060, 0x6000,
-	0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x16c9, 0x2009, 0x0000,
-	0x017e, 0x6804, 0xa065, 0x0040, 0x16d8, 0x6000, 0x6806, 0x1078,
-	0x16e9, 0x1078, 0x17d5, 0x6810, 0x8001, 0x6812, 0x00c0, 0x16c9,
-	0x017f, 0x6902, 0x6906, 0x007c, 0xa065, 0x0040, 0x16e8, 0x6098,
-	0x609b, 0x0000, 0x2008, 0x1078, 0x1682, 0x2100, 0x0078, 0x16dc,
-	0x007c, 0x6003, 0x0103, 0x20a9, 0x001c, 0xac80, 0x0004, 0x20a0,
-	0x2001, 0x0000, 0x40a4, 0x6828, 0x6016, 0x682c, 0x601e, 0x007c,
-	0x0e7e, 0x2071, 0x3540, 0x7040, 0xa08c, 0x0080, 0x00c0, 0x1706,
-	0xa088, 0x3580, 0x2d0a, 0x8000, 0x7042, 0xa006, 0x0e7f, 0x007c,
-	0x0e7e, 0x2071, 0x3540, 0x2009, 0x3580, 0x7240, 0x8221, 0x8211,
-	0x0048, 0x1720, 0x2104, 0x8108, 0xad06, 0x00c0, 0x170f, 0x8119,
-	0x211e, 0x8108, 0x8318, 0x8211, 0x00c8, 0x1718, 0x7442, 0xa006,
-	0x0e7f, 0x007c, 0x1078, 0x169c, 0x2091, 0x8000, 0x6804, 0x781e,
-	0xa065, 0x0040, 0x1769, 0x0078, 0x1733, 0x2c00, 0x781e, 0x6000,
-	0xa065, 0x0040, 0x1769, 0x600c, 0xa306, 0x00c0, 0x172d, 0x6008,
-	0xa206, 0x00c0, 0x172d, 0x2c28, 0x2001, 0x354f, 0x2004, 0xac06,
-	0x0040, 0x1769, 0x6804, 0xac06, 0x00c0, 0x1750, 0x6000, 0x2060,
-	0x6806, 0xa005, 0x00c0, 0x1750, 0x6803, 0x0000, 0x0078, 0x175a,
-	0x6400, 0x781c, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x175a,
-	0x2c00, 0x6802, 0x2560, 0x1078, 0x16e9, 0x6017, 0x0005, 0x601f,
-	0x0020, 0x1078, 0x17d5, 0x6810, 0x8001, 0x6812, 0x2001, 0xffff,
-	0xa005, 0x007c, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004,
-	0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x16a9, 0x8738, 0xa784,
-	0x0007, 0x00c0, 0x1774, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f,
-	0xa784, 0x0f00, 0x00c0, 0x1774, 0x2091, 0x8001, 0x007c, 0x2061,
-	0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1794, 0x78ac, 0x78af,
-	0x0000, 0xa005, 0x00c0, 0x1795, 0x007c, 0xa08c, 0xfff0, 0x0040,
-	0x179b, 0x1078, 0x1b81, 0x0079, 0x179d, 0x17ad, 0x17af, 0x17b5,
-	0x17b9, 0x17ad, 0x17bd, 0x17ad, 0x17ad, 0x17ad, 0x17ad, 0x17c3,
-	0x17c7, 0x17ad, 0x17ad, 0x17ad, 0x17ad, 0x1078, 0x1b81, 0x1078,
-	0x176a, 0x2001, 0x8001, 0x0078, 0x17cd, 0x2001, 0x8003, 0x0078,
-	0x17cd, 0x2001, 0x8004, 0x0078, 0x17cd, 0x1078, 0x176a, 0x2001,
-	0x8006, 0x0078, 0x17cd, 0x2001, 0x800c, 0x0078, 0x17cd, 0x1078,
-	0x176a, 0x2001, 0x800d, 0x0078, 0x17cd, 0x70c2, 0x2061, 0x0000,
-	0x601b, 0x0001, 0x2091, 0x4080, 0x007c, 0x2c04, 0x6082, 0x2c08,
-	0x2063, 0x0000, 0x7864, 0x8000, 0x7866, 0x7868, 0xa005, 0x796a,
-	0x0040, 0x17e5, 0x2c02, 0x0078, 0x17e6, 0x796e, 0x007c, 0x0c7e,
-	0x2061, 0x3500, 0x6883, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6064,
-	0x8000, 0x6066, 0x6068, 0xa005, 0x616a, 0x0040, 0x17fa, 0x2d02,
-	0x0078, 0x17fb, 0x616e, 0x0c7f, 0x007c, 0x1078, 0x180e, 0x0040,
-	0x180d, 0x0c7e, 0x6098, 0xa065, 0x0040, 0x1808, 0x1078, 0x16dc,
-	0x0c7f, 0x609b, 0x0000, 0x1078, 0x1682, 0x007c, 0x786c, 0xa065,
-	0x0040, 0x1820, 0x2091, 0x8000, 0x7864, 0x8001, 0x7866, 0x2c04,
-	0x786e, 0xa005, 0x00c0, 0x181e, 0x786a, 0x8000, 0x2091, 0x8001,
-	0x007c, 0x7898, 0xa005, 0x00c0, 0x186f, 0x7974, 0x70d0, 0x0005,
-	0x0005, 0x72d0, 0xa206, 0x00c0, 0x1826, 0x2200, 0xa106, 0x00c0,
-	0x183d, 0x7804, 0xa005, 0x0040, 0x186f, 0x7807, 0x0000, 0x0068,
-	0x186f, 0x2091, 0x4080, 0x0078, 0x186f, 0x1078, 0x1679, 0x0040,
-	0x186f, 0x7a7c, 0x7b78, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399,
-	0x0000, 0x2009, 0x0040, 0x1078, 0x1649, 0x0040, 0x1866, 0x1078,
-	0x1682, 0x7880, 0x8000, 0x7882, 0xa086, 0x0002, 0x00c0, 0x186f,
-	0x2091, 0x8000, 0x78af, 0x0002, 0x7883, 0x0000, 0x7898, 0xa085,
-	0x0003, 0x789a, 0x2091, 0x8001, 0x0078, 0x186f, 0x7883, 0x0000,
-	0x1078, 0x199c, 0x6000, 0xa084, 0x0007, 0x0079, 0x1870, 0x007c,
-	0x1878, 0x1887, 0x18a7, 0x1878, 0x18b9, 0x1878, 0x1878, 0x1878,
-	0x2039, 0x0400, 0x78a8, 0xa705, 0x78aa, 0x6004, 0xa705, 0x6006,
-	0x1078, 0x18f7, 0x6018, 0x78a6, 0x1078, 0x1984, 0x007c, 0x78a8,
-	0xa084, 0x0100, 0x0040, 0x188e, 0x0078, 0x1878, 0x78ab, 0x0000,
-	0x6000, 0x8007, 0xa084, 0x00ff, 0x789e, 0x8001, 0x609b, 0x0000,
-	0x0040, 0x18a4, 0x1078, 0x18f7, 0x0040, 0x18a4, 0x78a8, 0xa085,
-	0x0100, 0x78aa, 0x0078, 0x18a6, 0x1078, 0x191b, 0x007c, 0x78a8,
-	0xa08c, 0x0e00, 0x00c0, 0x18b0, 0xa084, 0x0100, 0x00c0, 0x18b2,
-	0x0078, 0x1878, 0x1078, 0x18f7, 0x00c0, 0x18b8, 0x1078, 0x191b,
-	0x007c, 0x78a8, 0xa084, 0x0100, 0x0040, 0x18c0, 0x0078, 0x1878,
-	0x78ab, 0x0000, 0x6710, 0x20a9, 0x0001, 0x6014, 0xa084, 0x00ff,
-	0xa005, 0x0040, 0x18dd, 0xa7bc, 0xff00, 0x20a9, 0x0008, 0xa08e,
-	0x0001, 0x0040, 0x18dd, 0x2039, 0x0000, 0x20a9, 0x0080, 0xa08e,
-	0x0002, 0x0040, 0x18dd, 0x0078, 0x18f4, 0x1078, 0x169c, 0x2d00,
-	0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084,
-	0xffde, 0x680a, 0x2d00, 0xa080, 0x0010, 0x2068, 0x2091, 0x8001,
-	0x0070, 0x18f4, 0x0078, 0x18e0, 0x1078, 0x1682, 0x007c, 0x78a0,
-	0xa06d, 0x00c0, 0x1902, 0x2c00, 0x78a2, 0x78a6, 0x609b, 0x0000,
-	0x0078, 0x190e, 0x2c00, 0x689a, 0x609b, 0x0000, 0x78a2, 0x2d00,
-	0x6002, 0x78a4, 0xad06, 0x00c0, 0x190e, 0x6002, 0x789c, 0x8001,
-	0x789e, 0x00c0, 0x191a, 0x78a8, 0xa084, 0x0000, 0x78aa, 0x78a4,
-	0x2060, 0xa006, 0x007c, 0xa02e, 0x2530, 0x6118, 0xa184, 0x0060,
-	0x619e, 0x0040, 0x1927, 0x0e7e, 0x1078, 0x2f16, 0x0e7f, 0x6592,
-	0x65a2, 0x6696, 0x66a6, 0x60ab, 0x0000, 0x60af, 0x0000, 0x6710,
-	0x1078, 0x169c, 0x2091, 0x8000, 0x6808, 0xa084, 0x0001, 0x0040,
-	0x1949, 0x2091, 0x8001, 0x1078, 0x16e9, 0x2091, 0x8000, 0x1078,
-	0x17d5, 0x2091, 0x8001, 0x78a3, 0x0000, 0x78a7, 0x0000, 0x0078,
-	0x1983, 0x6020, 0xa096, 0x0001, 0x00c0, 0x1950, 0x8000, 0x6022,
-	0x6a10, 0x6814, 0x2091, 0x8001, 0xa202, 0x0048, 0x195f, 0x0040,
-	0x195f, 0x2039, 0x0200, 0x1078, 0x1984, 0x0078, 0x1983, 0x2c08,
-	0x2091, 0x8000, 0x6800, 0xa065, 0x0040, 0x1967, 0x6102, 0x6902,
-	0x00c0, 0x196b, 0x6906, 0x2160, 0x6003, 0x0000, 0x6810, 0x8000,
-	0x6812, 0x2091, 0x8001, 0x6808, 0xa08c, 0x0040, 0x0040, 0x197d,
-	0xa086, 0x0040, 0x680a, 0x1078, 0x16f8, 0x1078, 0x1a23, 0x78a7,
-	0x0000, 0x78a3, 0x0000, 0x007c, 0x6004, 0xa705, 0x6006, 0x2091,
-	0x8000, 0x1078, 0x17d5, 0x2091, 0x8001, 0x78a4, 0xa065, 0x0040,
-	0x1997, 0x6098, 0x78a6, 0x609b, 0x0000, 0x0078, 0x1987, 0x78a3,
-	0x0000, 0x78a7, 0x0000, 0x007c, 0x7970, 0x7874, 0x8000, 0xa10a,
-	0x00c8, 0x19a3, 0xa006, 0x7876, 0x70d2, 0x7804, 0xa005, 0x0040,
-	0x19b1, 0x8001, 0x7806, 0x00c0, 0x19b1, 0x0068, 0x19b1, 0x2091,
-	0x4080, 0x007c, 0x0068, 0x19cc, 0x2029, 0x0000, 0x786c, 0xa065,
-	0x0040, 0x19c7, 0x1078, 0x19cd, 0x0040, 0x19c7, 0x057e, 0x1078,
-	0x19e3, 0x057f, 0x00c0, 0x19c7, 0x8528, 0x0078, 0x19b6, 0x85ff,
-	0x0040, 0x19cc, 0x2091, 0x4080, 0x007c, 0x7b84, 0x7988, 0x72d4,
-	0x0005, 0x0005, 0x70d4, 0xa206, 0x00c0, 0x19cf, 0x2200, 0xa102,
-	0x00c0, 0x19dd, 0x2300, 0xa005, 0x007c, 0x0048, 0x19e1, 0xa302,
-	0x007c, 0x8002, 0x007c, 0x1078, 0x1a15, 0x2009, 0x001c, 0x6024,
-	0xa005, 0x0040, 0x19ed, 0x2009, 0x0040, 0x1078, 0x161b, 0x0040,
-	0x1a06, 0x7894, 0x8000, 0x7896, 0xa086, 0x0002, 0x00c0, 0x1a14,
-	0x2091, 0x8000, 0x78af, 0x0003, 0x7897, 0x0000, 0x7898, 0xa085,
-	0x0300, 0x789a, 0x2091, 0x8001, 0x0078, 0x1a14, 0x7897, 0x0000,
-	0x1078, 0x17fd, 0x7984, 0x7888, 0x8000, 0xa10a, 0x00c8, 0x1a11,
-	0xa006, 0x788a, 0x70d6, 0xa006, 0x007c, 0x8107, 0x8004, 0x8004,
-	0x7a90, 0x7b8c, 0xa210, 0xa399, 0x0000, 0x007c, 0x2009, 0x3568,
-	0x2091, 0x8000, 0x200a, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x3540,
-	0x2091, 0x8000, 0x2104, 0xa086, 0x0000, 0x00c0, 0x1a3e, 0x2009,
-	0x3512, 0x2104, 0xa005, 0x00c0, 0x1a3e, 0x7830, 0xa084, 0x00c0,
-	0x00c0, 0x1a3e, 0x0018, 0x1a3e, 0x781b, 0x0044, 0x2091, 0x8001,
-	0x0f7f, 0x007c, 0x127e, 0x2091, 0x2300, 0x2071, 0x3540, 0x2079,
-	0x0100, 0x2019, 0x2ddb, 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040,
-	0x1a5a, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318,
-	0x0078, 0x1a4d, 0x789b, 0x0020, 0x20a9, 0x0010, 0x78af, 0x0000,
-	0x78af, 0x0220, 0x0070, 0x1a66, 0x0078, 0x1a5e, 0x7003, 0x0000,
-	0x1078, 0x1b65, 0x7004, 0xa084, 0x000f, 0xa085, 0x6280, 0x7806,
-	0x780f, 0x9200, 0x7843, 0x00d8, 0x7853, 0x0080, 0x780b, 0x0008,
-	0x7047, 0x357f, 0x7043, 0x0000, 0x127f, 0x2000, 0x007c, 0xa18c,
-	0x000f, 0x2011, 0x0101, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012,
-	0x1078, 0x1b65, 0x007c, 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b,
-	0x0070, 0x1a94, 0x0078, 0x1a8f, 0xa18c, 0x0e00, 0x2204, 0xa084,
-	0xf1ff, 0xa105, 0x2012, 0x007c, 0x2009, 0x0101, 0x20a9, 0x0005,
-	0x8213, 0x0070, 0x1aa5, 0x0078, 0x1aa0, 0xa294, 0x00e0, 0x2104,
-	0xa084, 0xff1f, 0xa205, 0x200a, 0x007c, 0x2011, 0x0101, 0x20a9,
-	0x000c, 0x810b, 0x0070, 0x1ab6, 0x0078, 0x1ab1, 0xa18c, 0xf000,
-	0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x007c, 0x2011, 0x0102,
-	0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x8103, 0x8003,
-	0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x62ac, 0x63ac,
-	0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061,
-	0x0100, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c,
-	0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a,
-	0x60a4, 0xa085, 0x0020, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003,
-	0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0x62ae,
-	0x2010, 0x60a4, 0x63ae, 0x2018, 0x0c7f, 0x007c, 0x2091, 0x8000,
-	0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040, 0x1b43, 0x2061, 0x3f80,
-	0x1078, 0x1b4b, 0x0040, 0x1b31, 0x20a9, 0x0000, 0x2061, 0x3e80,
-	0x0c7e, 0x1078, 0x1b4b, 0x0040, 0x1b1d, 0x0c7f, 0x8c60, 0x0070,
-	0x1b1b, 0x0078, 0x1b10, 0x0078, 0x1b43, 0x007f, 0xa082, 0x3e80,
-	0x2071, 0x3540, 0x70ba, 0x601c, 0xa085, 0x0800, 0x601e, 0x71b6,
-	0x60a7, 0x0000, 0x2001, 0x0004, 0x70a2, 0x1078, 0x1a1e, 0x0078,
-	0x1b3f, 0x2071, 0x3540, 0x601c, 0xa085, 0x0800, 0x601e, 0x71b6,
-	0x60a7, 0x0000, 0x2001, 0x0006, 0x70a2, 0x1078, 0x1a1e, 0x2001,
-	0x0000, 0x0078, 0x1b45, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005,
-	0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005, 0x0040, 0x1b62, 0x2060,
-	0x600c, 0xa306, 0x00c0, 0x1b5f, 0x6008, 0xa206, 0x00c0, 0x1b5f,
-	0x6010, 0xa106, 0x00c0, 0x1b5f, 0xa006, 0x0078, 0x1b64, 0x6000,
-	0x0078, 0x1b4c, 0xa085, 0x0001, 0x007c, 0x2011, 0x3541, 0x220c,
-	0xa18c, 0x000f, 0x2011, 0x013b, 0x2204, 0xa084, 0x0100, 0x0040,
-	0x1b80, 0x2019, 0x0112, 0x201b, 0x1000, 0x2021, 0x013a, 0x2122,
-	0x2013, 0x0080, 0x2013, 0x008c, 0x2013, 0x0000, 0x201b, 0x0000,
-	0x007c, 0x0068, 0x1b81, 0x007e, 0x2071, 0x0000, 0x7018, 0xa084,
-	0x0001, 0x00c0, 0x1b86, 0x007f, 0x2e08, 0x2071, 0x0010, 0x70ca,
-	0x007f, 0x70c6, 0x70c3, 0x8002, 0x2071, 0x0000, 0x701b, 0x0001,
-	0x2091, 0x4080, 0x007f, 0x2070, 0x007f, 0x0078, 0x1b9d, 0x107e,
-	0x007e, 0x127e, 0x2091, 0x2300, 0x7f3c, 0x7e58, 0x7c30, 0x7d38,
-	0xa594, 0x003f, 0xa484, 0x4000, 0x0040, 0x1bb4, 0xa784, 0x007c,
-	0x00c0, 0x2da7, 0x1078, 0x1b81, 0xa49c, 0x000f, 0xa382, 0x0004,
-	0x0050, 0x1bbc, 0x1078, 0x1b81, 0x8507, 0xa084, 0x000f, 0x0079,
-	0x1bc1, 0x1fed, 0x209d, 0x20c3, 0x22e9, 0x2576, 0x25be, 0x25f5,
-	0x2670, 0x26ca, 0x274f, 0x1be7, 0x1bd1, 0x1e56, 0x1f20, 0x2555,
-	0x1bd1, 0x1078, 0x1b81, 0x0018, 0x1ba4, 0x127f, 0x2091, 0x8001,
-	0x007f, 0x107f, 0x007c, 0x7003, 0x0000, 0x703f, 0x0000, 0x7030,
-	0xa005, 0x0040, 0x1be5, 0x7033, 0x0000, 0x0018, 0x1ba4, 0x705c,
-	0xa005, 0x00c0, 0x1ca5, 0x70a0, 0xa084, 0x0007, 0x0079, 0x1bf0,
-	0x1cd1, 0x1bf8, 0x1c06, 0x1c27, 0x1c4d, 0x1c79, 0x1c77, 0x1bf8,
-	0x7808, 0xa084, 0xfffd, 0x780a, 0x2009, 0x0046, 0x1078, 0x241b,
-	0x00c0, 0x1c04, 0x7003, 0x0004, 0x0078, 0x1bd3, 0x1078, 0x2d69,
-	0x00c0, 0x1c25, 0x70b4, 0x8007, 0x789b, 0x007e, 0x78aa, 0x789b,
-	0x0010, 0x78ab, 0x000c, 0x789b, 0x0060, 0x78ab, 0x0001, 0x785b,
-	0x0004, 0x2009, 0x00f7, 0x1078, 0x2419, 0x00c0, 0x1c25, 0x7003,
-	0x0004, 0x70c3, 0x000f, 0x7033, 0x3570, 0x0078, 0x1bd3, 0x1078,
-	0x2d69, 0x00c0, 0x1c4b, 0x71b4, 0x8107, 0x789b, 0x007e, 0x78aa,
-	0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, 0x00c0, 0x79aa, 0x78ab,
-	0x0006, 0x789b, 0x0060, 0x78ab, 0x0002, 0x785b, 0x0004, 0x2009,
-	0x00f7, 0x1078, 0x2419, 0x00c0, 0x1c4b, 0x7003, 0x0004, 0x70c3,
-	0x000f, 0x7033, 0x3570, 0x0078, 0x1bd3, 0x1078, 0x2d69, 0x00c0,
-	0x1c75, 0x71b4, 0x8107, 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010,
-	0xa18c, 0x0007, 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0020, 0x71b8,
-	0x79aa, 0x78ab, 0x000d, 0x789b, 0x0060, 0x78ab, 0x0004, 0x785b,
-	0x0004, 0x2009, 0x00f7, 0x1078, 0x2419, 0x00c0, 0x1c75, 0x7003,
-	0x0004, 0x70c3, 0x000f, 0x7033, 0x3570, 0x0078, 0x1bd3, 0x0078,
-	0x1c27, 0x1078, 0x2d69, 0x00c0, 0x1bd3, 0x70bc, 0x2068, 0x789b,
-	0x0010, 0x6f10, 0x1078, 0x2cac, 0x2c50, 0x6810, 0x007e, 0x8007,
-	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, 0x2048,
-	0x0c7e, 0x2060, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x0c7f,
-	0x007f, 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa, 0x6e18, 0x2041,
-	0x0001, 0x2001, 0x0004, 0x0078, 0x1dcc, 0x1078, 0x2d69, 0x00c0,
-	0x1bd3, 0x789b, 0x0010, 0x705c, 0x2068, 0x6f10, 0x1078, 0x2cac,
-	0x2c50, 0x6008, 0xa085, 0x0010, 0x600a, 0x6820, 0xa005, 0x0040,
-	0x1cc1, 0xa082, 0x0006, 0x0048, 0x1cbf, 0x0078, 0x1cc1, 0x6823,
-	0x0005, 0x6810, 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa, 0x2031,
-	0x0020, 0x2041, 0x0001, 0x1078, 0x2dc8, 0x2001, 0x0003, 0x0078,
-	0x1dcc, 0x0018, 0x1ba4, 0x7440, 0xa485, 0x0000, 0x0040, 0x1ceb,
-	0xa080, 0x3580, 0x2030, 0x7144, 0x8108, 0xa12a, 0x0048, 0x1ce2,
-	0x2009, 0x3580, 0x2164, 0x6504, 0x85ff, 0x00c0, 0x1cf8, 0x8421,
-	0x00c0, 0x1cdc, 0x7146, 0x7003, 0x0000, 0x703f, 0x0000, 0x0078,
-	0x1bd3, 0x7640, 0xa6b0, 0x3580, 0x7144, 0x2600, 0x0078, 0x1ce7,
-	0x7146, 0x2568, 0x2558, 0x753e, 0x2c50, 0x6034, 0xa085, 0x0000,
-	0x00c0, 0x1cf5, 0x6708, 0x7736, 0xa784, 0x013f, 0x0040, 0x1d2a,
-	0xa784, 0x0021, 0x00c0, 0x1cf5, 0xa784, 0x0002, 0x0040, 0x1d17,
-	0xa784, 0x0004, 0x0040, 0x1cf5, 0xa7bc, 0xfffb, 0x670a, 0xa784,
-	0x0008, 0x00c0, 0x1cf5, 0xa784, 0x0010, 0x00c0, 0x1cf5, 0xa784,
-	0x0100, 0x0040, 0x1d2a, 0x6018, 0xa005, 0x00c0, 0x1cf5, 0xa7bc,
-	0xfeff, 0x670a, 0x681f, 0x0000, 0x6e18, 0xa684, 0x000e, 0x6118,
-	0x0040, 0x1d3a, 0x601c, 0xa102, 0x0048, 0x1d3d, 0x0040, 0x1d3d,
-	0x0078, 0x1cf1, 0x81ff, 0x00c0, 0x1cf1, 0xa784, 0x0080, 0x00c0,
-	0x1d43, 0x700c, 0x6022, 0xa7bc, 0xff7f, 0x670a, 0x6b10, 0x8307,
-	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, 0x2060,
-	0x2048, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x2a60, 0x0018,
-	0x1ba4, 0x789b, 0x0010, 0xa046, 0x1078, 0x2d69, 0x00c0, 0x1bd3,
-	0x6b10, 0xa39c, 0x0007, 0xa39d, 0x00c0, 0x704c, 0xa084, 0x8000,
-	0x0040, 0x1d6e, 0xa684, 0x0001, 0x0040, 0x1d74, 0xa39c, 0xffbf,
-	0xa684, 0x000e, 0x00c0, 0x2901, 0xa684, 0x0010, 0x0040, 0x1d7e,
-	0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2907, 0x7baa, 0x8840,
-	0xa684, 0x000e, 0x00c0, 0x1d89, 0xa7bd, 0x0010, 0x670a, 0x0078,
-	0x1dca, 0x714c, 0xa18c, 0x0800, 0x0040, 0x290d, 0x2011, 0x0021,
-	0x8004, 0x8004, 0x0048, 0x1da0, 0x2011, 0x0022, 0x8004, 0x0048,
-	0x1da0, 0x2011, 0x0020, 0x8004, 0x0048, 0x1da0, 0x0040, 0x1dca,
-	0x7aaa, 0x8840, 0x1078, 0x2d82, 0x6a10, 0x610c, 0x8108, 0xa18c,
-	0x00ff, 0xa1e0, 0x3e80, 0x2c64, 0x8cff, 0x0040, 0x1dc1, 0x6010,
-	0xa206, 0x00c0, 0x1dab, 0x60b4, 0x8001, 0x60b6, 0x00c0, 0x1da6,
-	0x0c7e, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x0c7f, 0x0078,
-	0x1cd1, 0x1078, 0x2d69, 0x00c0, 0x1bd3, 0x2a60, 0x610e, 0x79aa,
-	0x8840, 0x712e, 0x2001, 0x0001, 0x007e, 0x7150, 0xa184, 0x0018,
-	0x0040, 0x1de0, 0xa184, 0x0010, 0x0040, 0x1dda, 0x1078, 0x2ad7,
-	0x00c0, 0x1de0, 0xa184, 0x0008, 0x0040, 0x1de0, 0x1078, 0x29f1,
-	0x007f, 0x7002, 0xa68c, 0x0060, 0x88ff, 0x0040, 0x1de9, 0xa18d,
-	0x0004, 0x795a, 0x69b2, 0x789b, 0x0060, 0x2800, 0x78aa, 0x789b,
-	0x0061, 0x6814, 0xa085, 0x8000, 0x6816, 0x78aa, 0x157e, 0x137e,
-	0x147e, 0x20a1, 0x012c, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80,
-	0x000a, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6810, 0x8007,
-	0x789b, 0x007e, 0x78aa, 0x6d90, 0x7dd6, 0x7dde, 0x6e94, 0x7ed2,
-	0x7eda, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x1e18, 0x0098, 0x1e20,
-	0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x2d82, 0x0078, 0x1bdb,
-	0x7200, 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x1e2d, 0x781b,
-	0x0049, 0x1078, 0x2d82, 0x0078, 0x1e3e, 0x6ab0, 0xa295, 0x2000,
-	0x7a5a, 0x781b, 0x0049, 0x1078, 0x2d82, 0x7200, 0x2500, 0xa605,
-	0x0040, 0x1e3e, 0xa284, 0x0007, 0x1079, 0x1e4c, 0xad80, 0x0008,
-	0x7032, 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x1e4a, 0x6018,
-	0x8000, 0x601a, 0x0078, 0x1bd3, 0x1e54, 0x30f3, 0x30f3, 0x30e2,
-	0x30f3, 0x1e54, 0x1e54, 0x1e54, 0x1078, 0x1b81, 0x7808, 0xa084,
-	0xfffd, 0x780a, 0x0f7e, 0x2079, 0x3500, 0x7898, 0x0f7f, 0xa084,
-	0x0001, 0x0040, 0x1e7c, 0x70a0, 0xa086, 0x0001, 0x00c0, 0x1e6b,
-	0x70a2, 0x0078, 0x1f04, 0x70a0, 0xa086, 0x0005, 0x00c0, 0x1e7a,
-	0x70bc, 0x2068, 0x6817, 0x0004, 0x6813, 0x0000, 0x681c, 0xa085,
-	0x0008, 0x681e, 0x70a3, 0x0000, 0x157e, 0x2011, 0x0004, 0x71a0,
-	0xa186, 0x0001, 0x0040, 0x1e9e, 0xa186, 0x0007, 0x00c0, 0x1e8e,
-	0x2009, 0x352b, 0x200b, 0x0005, 0x0078, 0x1e9e, 0x2009, 0x3513,
-	0x2104, 0x2009, 0x3512, 0x200a, 0x2009, 0x352b, 0x200b, 0x0001,
-	0x70a3, 0x0000, 0x70a7, 0x0001, 0x0078, 0x1ea0, 0x70a3, 0x0000,
-	0x1078, 0x2eca, 0x20a9, 0x0010, 0x2039, 0x0000, 0x1078, 0x2bb1,
-	0xa7b8, 0x0100, 0x0070, 0x1eae, 0x0078, 0x1ea6, 0x7000, 0x2020,
-	0x0079, 0x1eb2, 0x1ee0, 0x1ec9, 0x1ec9, 0x1ebc, 0x1ee0, 0x1ee0,
-	0x1eba, 0x1eba, 0x1078, 0x1b81, 0x2021, 0x3557, 0x2404, 0xa005,
-	0x0040, 0x1ec9, 0xad06, 0x00c0, 0x1ec9, 0x6800, 0x2022, 0x0078,
-	0x1ed9, 0x681c, 0xa084, 0x0001, 0x00c0, 0x1ed5, 0x6f10, 0x1078,
-	0x2cac, 0x1078, 0x28e4, 0x0078, 0x1ed9, 0x7054, 0x2060, 0x6800,
-	0x6002, 0x6a16, 0x681c, 0xa085, 0x0008, 0x681e, 0x1078, 0x17e7,
-	0x2021, 0x3f80, 0x1078, 0x1f0a, 0x2021, 0x3557, 0x1078, 0x1f0a,
-	0x20a9, 0x0000, 0x2021, 0x3e80, 0x1078, 0x1f0a, 0x8420, 0x0070,
-	0x1ef3, 0x0078, 0x1eec, 0x20a9, 0x0080, 0x2061, 0x3680, 0x6018,
-	0x6110, 0xa102, 0x6012, 0x601b, 0x0000, 0xace0, 0x0010, 0x0070,
-	0x1f03, 0x0078, 0x1ef7, 0x157f, 0x7003, 0x0000, 0x703f, 0x0000,
-	0x0078, 0x1bd3, 0x047e, 0x2404, 0xa005, 0x0040, 0x1f1c, 0x2068,
-	0x6800, 0x007e, 0x6a16, 0x681c, 0xa085, 0x0008, 0x681e, 0x1078,
-	0x17e7, 0x007f, 0x0078, 0x1f0c, 0x047f, 0x2023, 0x0000, 0x007c,
-	0xa282, 0x0003, 0x0050, 0x1f26, 0x1078, 0x1b81, 0x2300, 0x0079,
-	0x1f29, 0x1f2c, 0x1f9f, 0x1fad, 0xa282, 0x0002, 0x0040, 0x1f32,
-	0x1078, 0x1b81, 0x70a0, 0x70a3, 0x0000, 0x70c3, 0x0000, 0x0079,
-	0x1f39, 0x1f41, 0x1f41, 0x1f43, 0x1f77, 0x2913, 0x1f41, 0x1f77,
-	0x1f41, 0x1078, 0x1b81, 0x77b4, 0x1078, 0x2bb1, 0x77b4, 0xa7bc,
-	0x0f00, 0x1078, 0x2cac, 0x6018, 0xa005, 0x0040, 0x1f6e, 0x2021,
-	0x3f80, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x1fc8, 0x0040,
-	0x1f6e, 0x157e, 0x20a9, 0x0000, 0x2021, 0x3e80, 0x047e, 0x2009,
-	0x0004, 0x2011, 0x0010, 0x1078, 0x1fc8, 0x047f, 0x0040, 0x1f6d,
-	0x8420, 0x0070, 0x1f6d, 0x0078, 0x1f5e, 0x157f, 0x8738, 0xa784,
-	0x0007, 0x00c0, 0x1f49, 0x0078, 0x1bdb, 0x0078, 0x1bdb, 0x77b4,
-	0x1078, 0x2cac, 0x6018, 0xa005, 0x0040, 0x1f9d, 0x2021, 0x3f80,
-	0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x1fc8, 0x0040, 0x1f9d,
-	0x157e, 0x20a9, 0x0000, 0x2021, 0x3e80, 0x047e, 0x2009, 0x0005,
-	0x2011, 0x0020, 0x1078, 0x1fc8, 0x047f, 0x0040, 0x1f9c, 0x8420,
-	0x0070, 0x1f9c, 0x0078, 0x1f8d, 0x157f, 0x0078, 0x1bdb, 0x2200,
-	0x0079, 0x1fa2, 0x1fa5, 0x1fa7, 0x1fa7, 0x1078, 0x1b81, 0x70a3,
-	0x0000, 0x70a7, 0x0001, 0x0078, 0x1bd3, 0x2200, 0x0079, 0x1fb0,
-	0x1fb5, 0x1fa7, 0x1fb3, 0x1078, 0x1b81, 0x1078, 0x2428, 0x7000,
-	0xa086, 0x0001, 0x00c0, 0x28ba, 0x1078, 0x28fa, 0x6008, 0xa084,
-	0xffef, 0x600a, 0x1078, 0x28ad, 0x0040, 0x28ba, 0x0078, 0x1cd1,
-	0x2404, 0xa005, 0x0040, 0x1fe9, 0x2068, 0x2d04, 0x007e, 0x6810,
-	0xa706, 0x0040, 0x1fd7, 0x2d20, 0x007f, 0x0078, 0x1fc9, 0x007f,
-	0x2022, 0x6916, 0x681c, 0xa205, 0x681e, 0x1078, 0x17e7, 0x6010,
-	0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x28fa,
-	0x007c, 0xa085, 0x0001, 0x0078, 0x1fe8, 0x2300, 0x0079, 0x1ff0,
-	0x1ff5, 0x1ff3, 0x2038, 0x1078, 0x1b81, 0x78e4, 0xa005, 0x00d0,
-	0x2018, 0x0018, 0x2018, 0x2008, 0xa084, 0x0030, 0x00c0, 0x2004,
-	0x781b, 0x0049, 0x0078, 0x1bd3, 0x78ec, 0xa084, 0x0003, 0x0040,
-	0x2000, 0x2100, 0xa084, 0x0007, 0x0079, 0x200e, 0x2026, 0x202c,
-	0x2020, 0x2016, 0x2d63, 0x2d63, 0x2016, 0x2032, 0x1078, 0x1b81,
-	0x7000, 0xa005, 0x0040, 0x1bdb, 0x2001, 0x0003, 0x0078, 0x22fd,
-	0x1078, 0x2b94, 0x781b, 0x0055, 0x0078, 0x1bd3, 0x1078, 0x2b94,
-	0x781b, 0x00dc, 0x0078, 0x1bd3, 0x1078, 0x2b94, 0x781b, 0x00e3,
-	0x0078, 0x1bd3, 0x1078, 0x2b94, 0x781b, 0x009d, 0x0078, 0x1bd3,
-	0xa584, 0x000f, 0x00c0, 0x2062, 0x1078, 0x2428, 0x7000, 0x0079,
-	0x2041, 0x2049, 0x2056, 0x2049, 0x28ba, 0x204b, 0x28ba, 0x2049,
-	0x2049, 0x1078, 0x1b81, 0x71a0, 0x70a3, 0x0000, 0xa186, 0x0004,
-	0x00c0, 0x2054, 0x0078, 0x2913, 0x0078, 0x28ba, 0x1078, 0x28fa,
-	0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x28ad, 0x0040, 0x28ba,
-	0x0078, 0x1cd1, 0x78e4, 0xa005, 0x00d0, 0x2018, 0x0018, 0x2018,
-	0x2008, 0xa084, 0x0030, 0x00c0, 0x2071, 0x781b, 0x0049, 0x0078,
-	0x1bd3, 0x78ec, 0xa084, 0x0003, 0x0040, 0x206d, 0x2100, 0xa184,
-	0x0007, 0x0079, 0x207b, 0x208b, 0x2091, 0x2085, 0x2083, 0x2d63,
-	0x2d63, 0x2083, 0x2d5b, 0x1078, 0x1b81, 0x1078, 0x2b9c, 0x781b,
-	0x0055, 0x0078, 0x1bd3, 0x1078, 0x2b9c, 0x781b, 0x00dc, 0x0078,
-	0x1bd3, 0x1078, 0x2b9c, 0x781b, 0x00e3, 0x0078, 0x1bd3, 0x1078,
-	0x2b9c, 0x781b, 0x009d, 0x0078, 0x1bd3, 0x2300, 0x0079, 0x20a0,
-	0x20a5, 0x20a3, 0x20a7, 0x1078, 0x1b81, 0x0078, 0x2670, 0x6817,
-	0x0008, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x2670,
-	0x78ec, 0xa084, 0x0003, 0x0040, 0x2670, 0xa184, 0x0007, 0x0079,
-	0x20b9, 0x2026, 0x202c, 0x2020, 0x2d3b, 0x2d63, 0x2d63, 0x20c1,
-	0x2d5b, 0x1078, 0x1b81, 0xa282, 0x0005, 0x0050, 0x20c9, 0x1078,
-	0x1b81, 0x2300, 0x0079, 0x20cc, 0x20cf, 0x22d1, 0x22dd, 0x2200,
-	0x0079, 0x20d2, 0x20d7, 0x20d9, 0x20ec, 0x20d7, 0x22b6, 0x1078,
-	0x1b81, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020,
-	0x0048, 0x2b75, 0xa08a, 0x0004, 0x00c8, 0x2b75, 0x0079, 0x20e8,
-	0x2b75, 0x2b75, 0x2b75, 0x2b17, 0x789b, 0x0018, 0x79a8, 0xa184,
-	0x0080, 0x0040, 0x2101, 0xa184, 0x0018, 0x0040, 0x20fd, 0x0078,
-	0x2b75, 0x7000, 0xa005, 0x00c0, 0x20f7, 0x2011, 0x0003, 0x0078,
-	0x275d, 0xa184, 0x00ff, 0xa08a, 0x0010, 0x00c8, 0x2b75, 0x0079,
-	0x2109, 0x211b, 0x2119, 0x2131, 0x2133, 0x21c5, 0x2b75, 0x2b75,
-	0x21c7, 0x2b75, 0x2b75, 0x22b2, 0x22b2, 0x2b75, 0x2b75, 0x2b75,
-	0x22b4, 0x1078, 0x1b81, 0xa684, 0x1000, 0x0040, 0x2128, 0x2001,
-	0x0300, 0x8000, 0x8000, 0x783a, 0x781b, 0x009a, 0x0078, 0x1bd3,
-	0x6814, 0xa084, 0x8000, 0x0040, 0x212f, 0x6817, 0x0003, 0x0078,
-	0x2d3b, 0x1078, 0x1b81, 0x691c, 0x691e, 0xa684, 0x1800, 0x00c0,
-	0x214d, 0x681c, 0xa084, 0x0001, 0x00c0, 0x2155, 0x6814, 0xa086,
-	0x0008, 0x00c0, 0x2145, 0x6817, 0x0000, 0xa684, 0x0400, 0x0040,
-	0x21c1, 0x781b, 0x0058, 0x0078, 0x1bd3, 0xa684, 0x1000, 0x0040,
-	0x2155, 0x781b, 0x0058, 0x0078, 0x1bd3, 0xa684, 0x0060, 0x0040,
-	0x21bd, 0xa684, 0x0800, 0x0040, 0x21bd, 0xa684, 0x8000, 0x00c0,
-	0x2163, 0x0078, 0x217d, 0xa6b4, 0x7fff, 0x7e5a, 0x6eb2, 0x789b,
-	0x0074, 0x7aac, 0x79ac, 0x78ac, 0x801b, 0x00c8, 0x2170, 0x8000,
-	0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b94, 0x2100, 0xa302,
-	0x68ae, 0x6b90, 0x2200, 0xa303, 0x68aa, 0xa684, 0x4000, 0x0040,
-	0x2185, 0xa6b4, 0xbfff, 0x7e5a, 0x6eb2, 0x7000, 0xa086, 0x0003,
-	0x00c0, 0x2192, 0x1078, 0x2f3d, 0x1078, 0x30e2, 0x781b, 0x0067,
-	0x0078, 0x1bd3, 0xa006, 0x1078, 0x3197, 0x6aac, 0x69a8, 0x6c94,
-	0x6b90, 0x2200, 0xa105, 0x0040, 0x21a1, 0x2200, 0xa422, 0x2100,
-	0xa31b, 0x7cd2, 0x7bd6, 0x2300, 0xa405, 0x00c0, 0x21af, 0xa6b5,
-	0x4000, 0x7e5a, 0x6eb2, 0x781b, 0x0067, 0x0078, 0x1bd3, 0x781b,
-	0x0067, 0x2200, 0xa115, 0x00c0, 0x21b9, 0x1078, 0x30f3, 0x0078,
-	0x1bd3, 0x1078, 0x3120, 0x0078, 0x1bd3, 0x781b, 0x006a, 0x0078,
-	0x1bd3, 0x781b, 0x0058, 0x0078, 0x1bd3, 0x1078, 0x1b81, 0x0078,
-	0x2224, 0x691c, 0xa184, 0x0100, 0x0040, 0x21df, 0xa18c, 0xfeff,
-	0x691e, 0x0c7e, 0x7048, 0x2060, 0x6000, 0xa084, 0xefff, 0x6002,
-	0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078, 0x2213, 0xa184,
-	0x0200, 0x0040, 0x2213, 0xa18c, 0xfdff, 0x691e, 0x0c7e, 0x7048,
-	0x2060, 0x6000, 0xa084, 0xdfff, 0x6002, 0x6004, 0xa084, 0xffef,
-	0x6006, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2213,
-	0x1078, 0x2ca8, 0x1078, 0x29f1, 0x88ff, 0x0040, 0x2213, 0x789b,
-	0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684,
-	0x0400, 0x00c0, 0x220f, 0x781b, 0x0055, 0x0078, 0x1bd3, 0x781b,
-	0x0069, 0x0078, 0x1bd3, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x221c,
-	0x781b, 0x0058, 0x0078, 0x1bd3, 0x781b, 0x006a, 0x0078, 0x1bd3,
-	0x0078, 0x2b7b, 0x0078, 0x2b7b, 0x2019, 0x0000, 0x7990, 0xa18c,
-	0x0007, 0x0040, 0x2222, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff,
-	0xa286, 0x0001, 0x00c0, 0x2247, 0x2300, 0x7ca8, 0xa400, 0x2018,
-	0xa102, 0x0040, 0x223f, 0x0048, 0x223f, 0x0078, 0x2241, 0x0078,
-	0x21c9, 0x24a8, 0x7aa8, 0x00f0, 0x2241, 0x0078, 0x222d, 0xa284,
-	0x00f0, 0xa086, 0x0020, 0x00c0, 0x22a3, 0x8318, 0x8318, 0x2300,
-	0xa102, 0x0040, 0x2257, 0x0048, 0x2257, 0x0078, 0x22a0, 0xa286,
-	0x0023, 0x0040, 0x2222, 0x6818, 0xa084, 0xfff1, 0x681a, 0x7e58,
-	0xa684, 0xfff1, 0xa085, 0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085,
-	0x0010, 0x600a, 0x0c7e, 0x7048, 0x2060, 0x6004, 0x2008, 0x2c48,
-	0x0c7f, 0xa184, 0x0010, 0x0040, 0x227b, 0x1078, 0x2ca8, 0x1078,
-	0x2ad7, 0x0078, 0x228a, 0x0c7e, 0x7048, 0x2060, 0x6004, 0x2008,
-	0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2213, 0x1078, 0x2ca8,
-	0x1078, 0x29f1, 0x88ff, 0x0040, 0x2213, 0x789b, 0x0060, 0x2800,
-	0x78aa, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x229c,
-	0x781b, 0x0055, 0x0078, 0x1bd3, 0x781b, 0x0069, 0x0078, 0x1bd3,
-	0x7aa8, 0x0078, 0x222d, 0x8318, 0x2300, 0xa102, 0x0040, 0x22ac,
-	0x0048, 0x22ac, 0x0078, 0x222d, 0xa284, 0x0080, 0x00c0, 0x2b81,
-	0x0078, 0x2b7b, 0x0078, 0x2b81, 0x0078, 0x2b75, 0x789b, 0x0018,
-	0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0040, 0x22c1, 0x1078,
-	0x1b81, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a,
-	0x0004, 0x00c8, 0x2b75, 0x0079, 0x22cd, 0x2b75, 0x2944, 0x2b75,
-	0x2a72, 0xa282, 0x0000, 0x00c0, 0x22d7, 0x1078, 0x1b81, 0x1078,
-	0x2b94, 0x781b, 0x0069, 0x0078, 0x1bd3, 0xa282, 0x0003, 0x00c0,
-	0x22e3, 0x1078, 0x1b81, 0x1078, 0x2ba4, 0x781b, 0x0069, 0x0078,
-	0x1bd3, 0xa282, 0x0004, 0x0050, 0x22ef, 0x1078, 0x1b81, 0x2300,
-	0x0079, 0x22f2, 0x22f5, 0x23d2, 0x2403, 0xa286, 0x0003, 0x0040,
-	0x22fb, 0x1078, 0x1b81, 0x2001, 0x0000, 0x703a, 0x7000, 0xa084,
-	0x0007, 0x0079, 0x2303, 0x230b, 0x230d, 0x230d, 0x2513, 0x253b,
-	0x24dd, 0x230b, 0x230b, 0x1078, 0x1b81, 0xa684, 0x1000, 0x00c0,
-	0x2315, 0x1078, 0x2eca, 0x0040, 0x23ac, 0x7868, 0xa08c, 0x00ff,
-	0x0040, 0x235d, 0xa186, 0x0008, 0x00c0, 0x232c, 0x1078, 0x28fa,
-	0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x28ad, 0x0040, 0x235d,
-	0x1078, 0x2eca, 0x0078, 0x2344, 0xa186, 0x0028, 0x00c0, 0x235d,
-	0x1078, 0x2eca, 0x6008, 0xa084, 0xffef, 0x600a, 0x6018, 0xa005,
-	0x0040, 0x2344, 0x8001, 0x601a, 0xa005, 0x0040, 0x2344, 0x8001,
-	0xa005, 0x0040, 0x2344, 0x601e, 0x681c, 0xa084, 0x0001, 0x0040,
-	0x1bdb, 0x681c, 0xa084, 0xfffe, 0x681e, 0x7054, 0x0c7e, 0x2060,
-	0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802, 0xa005, 0x2d00, 0x00c0,
-	0x235a, 0x6002, 0x6006, 0x0078, 0x1bdb, 0x017e, 0x1078, 0x2428,
-	0x017f, 0xa684, 0xdf00, 0x681a, 0x6827, 0x0000, 0x6f10, 0x81ff,
-	0x0040, 0x23ac, 0xa186, 0x0002, 0x00c0, 0x23a4, 0xa684, 0x0800,
-	0x00c0, 0x237a, 0xa684, 0x0060, 0x0040, 0x237a, 0x78d8, 0x7adc,
-	0x682e, 0x6a2a, 0x8717, 0xa294, 0x000f, 0x8213, 0x8213, 0x8213,
-	0xa290, 0x3600, 0xa290, 0x0000, 0x221c, 0xa384, 0x0100, 0x00c0,
-	0x238b, 0x0078, 0x2391, 0x8210, 0x2204, 0xa085, 0x0018, 0x2012,
-	0x8211, 0xa384, 0x0400, 0x0040, 0x239e, 0x689c, 0xa084, 0x0100,
-	0x00c0, 0x239e, 0x1078, 0x249c, 0x0078, 0x1bdb, 0x6008, 0xa085,
-	0x0002, 0x600a, 0x0078, 0x23ac, 0xa186, 0x0018, 0x0040, 0x23ac,
-	0xa186, 0x0014, 0x0040, 0x1bdb, 0x6912, 0x6814, 0xa084, 0x8000,
-	0x0040, 0x23b4, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x1078,
-	0x28eb, 0x1078, 0x28fa, 0x00c0, 0x23c1, 0x6008, 0xa084, 0xffef,
-	0x600a, 0x681c, 0xa084, 0x0001, 0x00c0, 0x23ca, 0x1078, 0x28e4,
-	0x0078, 0x23ce, 0x7054, 0x2060, 0x6800, 0x6002, 0x1078, 0x17e7,
-	0x0078, 0x1bdb, 0xa282, 0x0004, 0x0048, 0x23d8, 0x1078, 0x1b81,
-	0x2200, 0x0079, 0x23db, 0x23df, 0x23e1, 0x23ee, 0x23e1, 0x1078,
-	0x1b81, 0x7000, 0xa086, 0x0005, 0x0040, 0x23ea, 0x1078, 0x2b94,
-	0x781b, 0x0069, 0x781b, 0x006a, 0x0078, 0x1bd3, 0x7890, 0x8007,
-	0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c,
-	0x00ff, 0xa186, 0x0003, 0x0040, 0x23ff, 0x0078, 0x2b75, 0x781b,
-	0x006a, 0x0078, 0x1bd3, 0x681c, 0xa085, 0x0004, 0x681e, 0x82ff,
-	0x00c0, 0x240e, 0x1078, 0x2b94, 0x0078, 0x2415, 0x8211, 0x0040,
-	0x2413, 0x1078, 0x1b81, 0x1078, 0x2ba4, 0x781b, 0x0069, 0x0078,
-	0x1bd3, 0x1078, 0x2d82, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2425,
-	0x0018, 0x2425, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c,
-	0xa684, 0x0060, 0x00c0, 0x2432, 0x682f, 0x0000, 0x682b, 0x0000,
-	0x0078, 0x249b, 0xa684, 0x0800, 0x00c0, 0x2441, 0x68b0, 0xa084,
-	0x4800, 0xa635, 0xa684, 0x0800, 0x00c0, 0x2441, 0x1078, 0x2eca,
-	0x007c, 0xa684, 0x0020, 0x0040, 0x246d, 0x78d0, 0x8003, 0x00c8,
-	0x244f, 0xa006, 0x1078, 0x3197, 0x78d4, 0x1078, 0x31fc, 0xa684,
-	0x4000, 0x0040, 0x2459, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078,
-	0x243e, 0x68b0, 0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0,
-	0x2453, 0x7038, 0xa005, 0x00c0, 0x2467, 0x703b, 0x0007, 0x79d8,
-	0x7adc, 0x692e, 0x6a2a, 0x0078, 0x243e, 0xa684, 0x4000, 0x0040,
-	0x2477, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078, 0x243e, 0x68b0,
-	0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x2471, 0x7038,
-	0xa005, 0x00c0, 0x2485, 0x703b, 0x0007, 0x79d8, 0x7adc, 0x78d0,
-	0x80f3, 0x00c8, 0x248c, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291,
-	0x0000, 0x692e, 0x6a2a, 0x2100, 0xa205, 0x00c0, 0x2499, 0x0078,
-	0x243e, 0x1078, 0x3197, 0x007c, 0xa384, 0x0200, 0x0040, 0x24a4,
-	0x6008, 0xa085, 0x0002, 0x600a, 0x6817, 0x0006, 0x6a28, 0x692c,
-	0x6a3a, 0x693e, 0x682b, 0x0300, 0x682f, 0x0000, 0x6833, 0x2000,
-	0x6893, 0x0000, 0x6897, 0x0020, 0x7000, 0x0079, 0x24b7, 0x24bf,
-	0x24c1, 0x24ca, 0x24bf, 0x24bf, 0x24bf, 0x24bf, 0x24bf, 0x1078,
-	0x1b81, 0x681c, 0xa084, 0x0001, 0x00c0, 0x24ca, 0x1078, 0x28e4,
-	0x0078, 0x24d0, 0x7054, 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60,
-	0x2021, 0x3557, 0x2404, 0xa005, 0x0040, 0x24d9, 0x2020, 0x0078,
-	0x24d2, 0x2d22, 0x206b, 0x0000, 0x007c, 0x77b4, 0x1078, 0x2bb1,
-	0xa7bc, 0x0f00, 0x1078, 0x2cac, 0x6018, 0xa005, 0x0040, 0x250c,
-	0x0d7e, 0x2001, 0x3f90, 0x2068, 0x0d7f, 0x2021, 0x3f80, 0x2009,
-	0x0004, 0x2011, 0x0010, 0x1078, 0x1fc8, 0x0040, 0x250c, 0x157e,
-	0x20a9, 0x0000, 0x2021, 0x3e80, 0x047e, 0x2009, 0x0004, 0x2011,
-	0x0010, 0x1078, 0x1fc8, 0x047f, 0x0040, 0x250b, 0x8420, 0x0070,
-	0x250b, 0x0078, 0x24fc, 0x157f, 0x8738, 0xa784, 0x0007, 0x00c0,
-	0x24e2, 0x0078, 0x1bdb, 0x1078, 0x28eb, 0x1078, 0x28fa, 0x6827,
-	0x0000, 0x789b, 0x000e, 0x6f10, 0x6813, 0x0002, 0x1078, 0x31cd,
-	0xa684, 0x0800, 0x0040, 0x2528, 0x6918, 0xa18d, 0x2000, 0x691a,
-	0x6814, 0xa084, 0x8000, 0x0040, 0x252f, 0x6817, 0x0000, 0x2021,
-	0x3557, 0x6800, 0x2022, 0x6a38, 0x693c, 0x6a2a, 0x692e, 0x1078,
-	0x17e7, 0x0078, 0x1bdb, 0x1078, 0x2428, 0x6827, 0x0000, 0x789b,
-	0x000e, 0x6f10, 0x1078, 0x2d87, 0xa08c, 0x00ff, 0x6912, 0x6814,
-	0xa084, 0x8000, 0x0040, 0x254e, 0x7038, 0x6816, 0xa68c, 0xdf00,
-	0x691a, 0x70a3, 0x0000, 0x0078, 0x1bdb, 0xa006, 0x1078, 0x2eca,
-	0x6813, 0x0000, 0x6817, 0x0001, 0xa68c, 0xdf00, 0x691a, 0x6827,
-	0x0000, 0x7000, 0x0079, 0x2564, 0x256c, 0x256e, 0x256e, 0x2570,
-	0x2570, 0x2570, 0x256c, 0x256c, 0x1078, 0x1b81, 0x1078, 0x28fa,
-	0x6008, 0xa084, 0xffef, 0x600a, 0x0078, 0x28c5, 0x2300, 0x0079,
-	0x2579, 0x257c, 0x257e, 0x25bc, 0x1078, 0x1b81, 0x7000, 0x0079,
-	0x2581, 0x2589, 0x258b, 0x258b, 0x2596, 0x258b, 0x259d, 0x2589,
-	0x2589, 0x1078, 0x1b81, 0xa684, 0x2000, 0x00c0, 0x2596, 0xa6b5,
-	0x2000, 0x7e5a, 0x1078, 0x30f3, 0x0078, 0x2d3b, 0x6814, 0xa084,
-	0x8000, 0x0040, 0x259d, 0x6817, 0x0007, 0x2009, 0x3518, 0x210c,
-	0xa186, 0x0000, 0x0040, 0x25b2, 0xa186, 0x0001, 0x0040, 0x25b6,
-	0x2009, 0x352b, 0x200b, 0x000b, 0x70a3, 0x0001, 0x781b, 0x0046,
-	0x0078, 0x1bd3, 0x781b, 0x00dd, 0x0078, 0x1bd3, 0x2009, 0x352b,
-	0x200b, 0x000a, 0x0078, 0x1bd3, 0x1078, 0x1b81, 0x2300, 0x0079,
-	0x25c1, 0x25c4, 0x25c6, 0x25e9, 0x1078, 0x1b81, 0x7000, 0x0079,
-	0x25c9, 0x25d1, 0x25d3, 0x25d3, 0x25de, 0x25d3, 0x25e5, 0x25d1,
-	0x25d1, 0x1078, 0x1b81, 0xa684, 0x2000, 0x00c0, 0x25de, 0xa6b5,
-	0x2000, 0x7e5a, 0x1078, 0x30f3, 0x0078, 0x2d3b, 0x6814, 0xa084,
-	0x8000, 0x0040, 0x25e5, 0x6817, 0x0007, 0x781b, 0x00e4, 0x0078,
-	0x1bd3, 0x681c, 0xa085, 0x0004, 0x681e, 0xa6b5, 0x0800, 0x1078,
-	0x2b94, 0x781b, 0x0069, 0x0078, 0x1bd3, 0x2300, 0x0079, 0x25f8,
-	0x25fb, 0x25fd, 0x25ff, 0x1078, 0x1b81, 0x1078, 0x1b81, 0xa684,
-	0x0400, 0x00c0, 0x261e, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab,
-	0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xa184, 0x0020, 0x0040,
-	0x2616, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x261a, 0x2001, 0x0014,
-	0x0078, 0x22fd, 0xa184, 0x0007, 0x0079, 0x2656, 0x7a90, 0xa294,
-	0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0040, 0x2654, 0x789b,
-	0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, 0x2645, 0x7ba8, 0x7ba8,
-	0xa386, 0x0001, 0x00c0, 0x2638, 0x2009, 0xfff7, 0x0078, 0x263e,
-	0xa386, 0x0003, 0x00c0, 0x2645, 0x2009, 0xffef, 0x0c7e, 0x7048,
-	0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab,
-	0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x691c, 0xa18c,
-	0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d3b, 0x2026, 0x202c,
-	0x2660, 0x2668, 0x265e, 0x265e, 0x265e, 0x2d3b, 0x1078, 0x1b81,
-	0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d43,
-	0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d3b,
-	0x79e4, 0xa184, 0x0030, 0x0040, 0x267a, 0x78ec, 0xa084, 0x0003,
-	0x00c0, 0x2682, 0x6814, 0xa085, 0x8000, 0x6816, 0x2001, 0x0014,
-	0x0078, 0x22fd, 0xa184, 0x0007, 0x0079, 0x2686, 0x2d3b, 0x2d3b,
-	0x268e, 0x2d3b, 0x2d63, 0x2d63, 0x2d3b, 0x2d3b, 0xa684, 0x0400,
-	0x00c0, 0x26bf, 0x681c, 0xa084, 0x0001, 0x0040, 0x2d43, 0xa68c,
-	0x2060, 0xa18c, 0xfffb, 0x795a, 0x69b2, 0x789b, 0x0060, 0x78ab,
-	0x0000, 0x789b, 0x0061, 0x6814, 0xa085, 0x8000, 0x6816, 0x78aa,
-	0x157e, 0x137e, 0x147e, 0x20a1, 0x012c, 0x789b, 0x0000, 0x8000,
-	0x80ac, 0xad80, 0x000a, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f,
-	0x6810, 0x8007, 0x789b, 0x007e, 0x78aa, 0x0078, 0x2d43, 0x6814,
-	0xa084, 0x8000, 0x0040, 0x26c6, 0x6817, 0x0008, 0x781b, 0x00d8,
-	0x0078, 0x1bd3, 0x2300, 0x0079, 0x26cd, 0x26d2, 0x274d, 0x26d0,
-	0x1078, 0x1b81, 0x7000, 0xa084, 0x0007, 0x0079, 0x26d7, 0x26df,
-	0x26e1, 0x26fd, 0x26df, 0x26df, 0x24dd, 0x26df, 0x26df, 0x1078,
-	0x1b81, 0x691c, 0xa18d, 0x0001, 0x691e, 0x6800, 0x6006, 0xa005,
-	0x00c0, 0x26eb, 0x6002, 0x6818, 0xa084, 0x000e, 0x0040, 0x26f7,
-	0x7014, 0x68b6, 0x712c, 0xa188, 0x3e80, 0x0078, 0x26f9, 0x2009,
-	0x3f80, 0x2104, 0x6802, 0x2d0a, 0x7156, 0x6eb2, 0xa684, 0x0060,
-	0x0040, 0x274b, 0xa684, 0x0800, 0x00c0, 0x270f, 0xa684, 0x7fff,
-	0x68b2, 0x6890, 0x6894, 0x1078, 0x2eca, 0x0078, 0x274b, 0xa684,
-	0x0020, 0x0040, 0x2721, 0xa006, 0x1078, 0x3197, 0x78d0, 0x8003,
-	0x00c8, 0x271d, 0x78d4, 0x1078, 0x31fc, 0x79d8, 0x7adc, 0x0078,
-	0x2725, 0x1078, 0x2cb9, 0x1078, 0x3197, 0xa684, 0x8000, 0x0040,
-	0x274b, 0xa684, 0x7fff, 0x68b2, 0x789b, 0x0074, 0x1078, 0x2d87,
-	0x2010, 0x1078, 0x2d87, 0x2008, 0xa684, 0x0020, 0x00c0, 0x2743,
-	0x1078, 0x2d87, 0x801b, 0x00c8, 0x273e, 0x8000, 0xa084, 0x003f,
-	0xa108, 0xa291, 0x0000, 0x6b94, 0x2100, 0xa302, 0x68ae, 0x6b90,
-	0x2200, 0xa303, 0x68aa, 0x0078, 0x1bdb, 0x0078, 0x2b81, 0x7033,
-	0x0000, 0xa282, 0x0005, 0x0050, 0x2757, 0x1078, 0x1b81, 0x2300,
-	0x0079, 0x275a, 0x275d, 0x2767, 0x278a, 0x2200, 0x0079, 0x2760,
-	0x2765, 0x2b81, 0x2765, 0x27b3, 0x2804, 0x1078, 0x1b81, 0x7000,
-	0xa086, 0x0001, 0x00c0, 0x2774, 0x1078, 0x28fa, 0x1078, 0x2eca,
-	0x7034, 0x600a, 0x0078, 0x2779, 0x7000, 0xa086, 0x0003, 0x0040,
-	0x276e, 0x7003, 0x0005, 0x2001, 0x3f90, 0x2068, 0x703e, 0x7032,
-	0x2200, 0x0079, 0x2783, 0x2b81, 0x2788, 0x27b3, 0x2788, 0x2b81,
-	0x1078, 0x1b81, 0x7000, 0xa086, 0x0001, 0x00c0, 0x2797, 0x1078,
-	0x28fa, 0x1078, 0x2eca, 0x7034, 0x600a, 0x0078, 0x279c, 0x7000,
-	0xa086, 0x0003, 0x0040, 0x2791, 0x7003, 0x0005, 0x2001, 0x3f90,
-	0x2068, 0x703e, 0x7032, 0x2200, 0x0079, 0x27a6, 0x27ad, 0x27ab,
-	0x27ad, 0x27ab, 0x27ad, 0x1078, 0x1b81, 0x1078, 0x2ba4, 0x781b,
-	0x0069, 0x0078, 0x1bd3, 0x7000, 0xa086, 0x0001, 0x00c0, 0x27c0,
-	0x1078, 0x28fa, 0x1078, 0x2eca, 0x7034, 0x600a, 0x0078, 0x27c5,
-	0x7000, 0xa086, 0x0003, 0x0040, 0x27ba, 0x7003, 0x0002, 0x7a80,
-	0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215,
-	0x2069, 0x3f80, 0x2d04, 0x2d08, 0x7156, 0x2068, 0xa005, 0x0040,
-	0x27e0, 0x6810, 0xa206, 0x0040, 0x27f9, 0x6800, 0x0078, 0x27d3,
-	0x7003, 0x0005, 0x2001, 0x3f90, 0x2068, 0x703e, 0x7032, 0x157e,
-	0x20a9, 0x002f, 0x2003, 0x0000, 0x8000, 0x0070, 0x27f1, 0x0078,
-	0x27ea, 0x157f, 0x6a12, 0x68b3, 0x0700, 0x681f, 0x0800, 0x6823,
-	0x0003, 0x6eb0, 0x7e5a, 0x681c, 0xa084, 0x0c00, 0x0040, 0x285a,
-	0x1078, 0x2b9c, 0x0078, 0x285a, 0x7000, 0xa086, 0x0001, 0x00c0,
-	0x2811, 0x1078, 0x28fa, 0x1078, 0x2eca, 0x7034, 0x600a, 0x0078,
-	0x2816, 0x7000, 0xa086, 0x0003, 0x0040, 0x280b, 0x7003, 0x0002,
-	0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007,
-	0xa215, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0xa1e8, 0x3e80, 0x2d04,
-	0x2d08, 0x7156, 0x2068, 0xa005, 0x0040, 0x2835, 0x6810, 0xa206,
-	0x0040, 0x284e, 0x6800, 0x0078, 0x2828, 0x7003, 0x0005, 0x2001,
-	0x3f90, 0x2068, 0x703e, 0x7032, 0x157e, 0x20a9, 0x002f, 0x2003,
-	0x0000, 0x8000, 0x0070, 0x2846, 0x0078, 0x283f, 0x157f, 0x6a12,
-	0x68b3, 0x0700, 0x681f, 0x0800, 0x6823, 0x0003, 0x6eb0, 0x7e5a,
-	0x681c, 0xa084, 0x0c00, 0x0040, 0x285a, 0x1078, 0x2b98, 0x7e58,
-	0x0078, 0x285a, 0x027e, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003,
-	0x8003, 0xa080, 0x3600, 0x2060, 0x704a, 0x6000, 0x704e, 0x6004,
-	0x7052, 0xa684, 0x0060, 0x0040, 0x2891, 0x6b94, 0x6c90, 0x69a8,
-	0x68ac, 0xa105, 0x00c0, 0x287f, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde,
-	0xa6b4, 0xb7ff, 0x7e5a, 0x1078, 0x30f3, 0x0078, 0x2891, 0x68ac,
-	0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x0040, 0x2891, 0x7bd2,
-	0x7bda, 0x7cd6, 0x7cde, 0x68ac, 0xa6b4, 0xbfff, 0x7e5a, 0x1078,
-	0x3120, 0x077f, 0x1078, 0x2cac, 0x2009, 0x006a, 0xa684, 0x0008,
-	0x0040, 0x289c, 0x2009, 0x0069, 0xa6b5, 0x2000, 0x7e5a, 0x791a,
-	0x2d00, 0x703e, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
-	0xa080, 0x3600, 0x2048, 0x0078, 0x1bd3, 0x6020, 0xa005, 0x0040,
-	0x28b9, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a, 0x7010,
-	0x6026, 0x007c, 0xa006, 0x1078, 0x2eca, 0x6813, 0x0000, 0x6817,
-	0x0001, 0x681f, 0x0040, 0x681b, 0x0100, 0x7000, 0xa084, 0x0007,
-	0x0079, 0x28ca, 0x28d2, 0x28d4, 0x28d4, 0x28e0, 0x28dc, 0x28d2,
-	0x28d2, 0x28d2, 0x1078, 0x1b81, 0x1078, 0x28eb, 0x1078, 0x28e4,
-	0x1078, 0x17e7, 0x0078, 0x1bdb, 0x70a3, 0x0000, 0x0078, 0x1bdb,
-	0x6817, 0x0000, 0x0078, 0x2513, 0x6800, 0xa005, 0x00c0, 0x28e9,
-	0x6002, 0x6006, 0x007c, 0x6010, 0xa005, 0x0040, 0x28f4, 0x8001,
-	0x00d0, 0x28f4, 0x1078, 0x1b81, 0x6012, 0x6008, 0xa084, 0xffef,
-	0x600a, 0x007c, 0x6018, 0xa005, 0x0040, 0x2900, 0x8001, 0x601a,
-	0x007c, 0x1078, 0x2d82, 0x6817, 0x0018, 0x0078, 0x2931, 0x1078,
-	0x2d82, 0x6817, 0x0019, 0x0078, 0x2931, 0x1078, 0x2d82, 0x6817,
-	0x001a, 0x0078, 0x2931, 0x77b4, 0x1078, 0x2cac, 0x71b8, 0xa18c,
-	0x00ff, 0xa1e8, 0x3e80, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0,
-	0x2923, 0x0078, 0x1bdb, 0x6810, 0x72b4, 0xa206, 0x0040, 0x292b,
-	0x6800, 0x0078, 0x291c, 0x6800, 0x200a, 0x6817, 0x0005, 0x70bf,
-	0x0000, 0x1078, 0x28eb, 0x681c, 0xa084, 0x0001, 0x00c0, 0x293a,
-	0x1078, 0x28e4, 0x1078, 0x28fa, 0x681b, 0x0000, 0x681f, 0x0020,
-	0x1078, 0x17e7, 0x0078, 0x1bdb, 0xa282, 0x0003, 0x00c0, 0x2b75,
-	0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x691c, 0xa18d,
-	0x0080, 0x691e, 0xa184, 0x0100, 0x0040, 0x29a4, 0xa18c, 0xfeff,
-	0x691e, 0xa6b4, 0x00ff, 0x0040, 0x298e, 0xa682, 0x000f, 0x0048,
-	0x2965, 0x0040, 0x2965, 0x2031, 0x000f, 0x852b, 0x852b, 0x1078,
-	0x2c2f, 0x0040, 0x296f, 0x1078, 0x2a3e, 0x0078, 0x2997, 0x1078,
-	0x2bea, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078,
-	0x2a62, 0x0c7f, 0x691c, 0xa18d, 0x0100, 0x691e, 0x7e58, 0xa6b5,
-	0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x298a, 0x781b, 0x0055,
-	0x0078, 0x1bd3, 0x781b, 0x0069, 0x0078, 0x1bd3, 0x0c7e, 0x2960,
-	0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x2a62, 0x0c7f, 0x7e58,
-	0xa684, 0x0400, 0x00c0, 0x29a0, 0x781b, 0x0058, 0x0078, 0x1bd3,
-	0x781b, 0x006a, 0x0078, 0x1bd3, 0x0c7e, 0x7048, 0x2060, 0x6100,
-	0xa18c, 0x1000, 0x0040, 0x29e4, 0x6208, 0x8217, 0xa294, 0x00ff,
-	0xa282, 0x000f, 0x0048, 0x29b8, 0x0040, 0x29b8, 0x2011, 0x000f,
-	0x2600, 0xa202, 0x00c8, 0x29bd, 0x2230, 0x6208, 0xa294, 0x00ff,
-	0x7018, 0xa086, 0x0028, 0x00c0, 0x29cd, 0xa282, 0x0019, 0x00c8,
-	0x29d3, 0x2011, 0x0019, 0x0078, 0x29d3, 0xa282, 0x000c, 0x00c8,
-	0x29d3, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8, 0x29d8, 0x2228,
-	0x1078, 0x2bee, 0x852b, 0x852b, 0x1078, 0x2c2f, 0x0040, 0x29e4,
-	0x1078, 0x2a3e, 0x0078, 0x29e8, 0x1078, 0x2bea, 0x1078, 0x2a62,
-	0x7858, 0xa085, 0x0004, 0x785a, 0x0c7f, 0x781b, 0x0069, 0x0078,
-	0x1bd3, 0x0c7e, 0x2960, 0x6000, 0xa084, 0x1000, 0x00c0, 0x2a0c,
-	0x6010, 0xa084, 0x000f, 0x00c0, 0x2a06, 0xa18c, 0x0002, 0x00c0,
-	0x2a06, 0xa18c, 0xfff5, 0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032,
-	0x2019, 0x0000, 0x0078, 0x2a2e, 0x6208, 0xa294, 0x00ff, 0x7018,
-	0xa086, 0x0028, 0x00c0, 0x2a1c, 0xa282, 0x0019, 0x00c8, 0x2a22,
-	0x2011, 0x0019, 0x0078, 0x2a22, 0xa282, 0x000c, 0x00c8, 0x2a22,
-	0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000f,
-	0x0048, 0x2a2e, 0x0040, 0x2a2e, 0x2019, 0x000f, 0x78ab, 0x0001,
-	0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005,
-	0x681c, 0xa085, 0x0100, 0x681e, 0x0c7f, 0x007c, 0x0c7e, 0x7148,
-	0x2160, 0x2008, 0xa084, 0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a,
-	0x7eae, 0x6612, 0x78a4, 0xa084, 0xfff8, 0xa18c, 0x0007, 0xa105,
-	0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f, 0x8637, 0x8204, 0x8004,
-	0xa084, 0x00ff, 0xa605, 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006,
-	0x0c7f, 0x007c, 0x0c7e, 0x7048, 0x2060, 0x6018, 0x789a, 0x78a4,
-	0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886,
-	0x0c7f, 0x007c, 0xa282, 0x0002, 0x00c0, 0x2b75, 0x7aa8, 0x691c,
-	0xa18d, 0x0080, 0x691e, 0xa184, 0x0200, 0x0040, 0x2ab7, 0xa18c,
-	0xfdff, 0x691e, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8, 0x2b75,
-	0x1078, 0x2afe, 0x1078, 0x2a62, 0xa980, 0x0001, 0x200c, 0x1078,
-	0x2ca8, 0x1078, 0x29f1, 0x88ff, 0x0040, 0x2aaa, 0x789b, 0x0060,
-	0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400,
-	0x00c0, 0x2aa6, 0x781b, 0x0055, 0x0078, 0x1bd3, 0x781b, 0x0069,
-	0x0078, 0x1bd3, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x2ab3, 0x781b,
-	0x0058, 0x0078, 0x1bd3, 0x781b, 0x006a, 0x0078, 0x1bd3, 0xa282,
-	0x0002, 0x00c8, 0x2abf, 0xa284, 0x0001, 0x0040, 0x2ac9, 0x7148,
-	0xa188, 0x0000, 0x210c, 0xa18c, 0x2000, 0x00c0, 0x2ac9, 0x2011,
-	0x0000, 0x1078, 0x2bdc, 0x1078, 0x2afe, 0x1078, 0x2a62, 0x7858,
-	0xa085, 0x0004, 0x785a, 0x781b, 0x0069, 0x0078, 0x1bd3, 0x0c7e,
-	0x027e, 0x2960, 0x6000, 0x2011, 0x0001, 0xa084, 0x2000, 0x00c0,
-	0x2aee, 0x6014, 0xa084, 0x0040, 0x00c0, 0x2aec, 0xa18c, 0xffef,
-	0x6106, 0xa006, 0x0078, 0x2afb, 0x2011, 0x0000, 0x78ab, 0x0001,
-	0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x681c,
-	0xa085, 0x0200, 0x681e, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7048,
-	0x2060, 0x82ff, 0x0040, 0x2b06, 0x2011, 0x0040, 0x6018, 0xa080,
-	0x0002, 0x789a, 0x78a4, 0xa084, 0xffbf, 0xa205, 0x78a6, 0x6016,
-	0x788a, 0x6004, 0xa084, 0xffef, 0x6006, 0x0c7f, 0x007c, 0x007e,
-	0x7000, 0xa086, 0x0003, 0x0040, 0x2b20, 0x007f, 0x0078, 0x2b23,
-	0x007f, 0x0078, 0x2b71, 0xa684, 0x0020, 0x0040, 0x2b71, 0x7888,
-	0xa084, 0x0040, 0x0040, 0x2b71, 0x78a8, 0x8001, 0x0040, 0x2b30,
-	0x7bb8, 0xa384, 0x003f, 0x831b, 0x00c8, 0x2b37, 0x8000, 0xa005,
-	0x0040, 0x2b58, 0x831b, 0x00c8, 0x2b40, 0x8001, 0x0040, 0x2b6d,
-	0xa006, 0x1078, 0x3197, 0x78b4, 0x1078, 0x31fc, 0x0078, 0x2b71,
-	0xa684, 0x4000, 0x0040, 0x2b58, 0x78b8, 0x801b, 0x00c8, 0x2b51,
-	0x8000, 0xa084, 0x003f, 0x00c0, 0x2b6d, 0xa6b4, 0xbfff, 0x7e5a,
-	0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108, 0x00c8, 0x2b61, 0xa291,
-	0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x3197, 0x781b,
-	0x0067, 0x1078, 0x3061, 0x0078, 0x1bd3, 0x781b, 0x0067, 0x0078,
-	0x1bd3, 0x781b, 0x006a, 0x0078, 0x1bd3, 0x1078, 0x2ba8, 0x781b,
-	0x0069, 0x0078, 0x1bd3, 0x1078, 0x2b94, 0x781b, 0x0069, 0x0078,
-	0x1bd3, 0x6823, 0x0002, 0x1078, 0x2b9c, 0x691c, 0xa18d, 0x0020,
-	0x691e, 0x6814, 0xa084, 0x8000, 0x0040, 0x2b90, 0x6817, 0x0005,
-	0x781b, 0x0069, 0x0078, 0x1bd3, 0x2001, 0x0005, 0x0078, 0x2baa,
-	0x2001, 0x000c, 0x0078, 0x2baa, 0x2001, 0x0006, 0x0078, 0x2baa,
-	0x2001, 0x000d, 0x0078, 0x2baa, 0x2001, 0x0009, 0x0078, 0x2baa,
-	0x2001, 0x0007, 0x789b, 0x007f, 0x78aa, 0xa6b5, 0x0008, 0x7e5a,
-	0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703,
-	0xa0e0, 0x3600, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f,
-	0x0040, 0x2bca, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085,
-	0x0008, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040,
-	0x0040, 0x2bda, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085,
-	0x0010, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001,
-	0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab,
-	0x0004, 0x007c, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, 0x0010,
-	0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa,
-	0x789b, 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007, 0xa084,
-	0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c,
-	0xfff0, 0x2001, 0x3546, 0x2004, 0xa082, 0x0028, 0x0040, 0x2c18,
-	0x2021, 0x2c8f, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x2c1e,
-	0x2021, 0x2c9b, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064,
-	0x2404, 0xa084, 0xfff0, 0xa106, 0x0040, 0x2c2d, 0x8420, 0x2300,
-	0xa210, 0x0070, 0x2c2d, 0x0078, 0x2c20, 0x157f, 0x007c, 0x157e,
-	0x2011, 0x3546, 0x2214, 0xa282, 0x0032, 0x0048, 0x2c43, 0x0040,
-	0x2c47, 0x2021, 0x2c81, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
-	0x0032, 0x0078, 0x2c57, 0xa282, 0x0028, 0x0040, 0x2c4f, 0x2021,
-	0x2c8f, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x2c55, 0x2021,
-	0x2c9b, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2200,
-	0xa502, 0x0040, 0x2c67, 0x0048, 0x2c67, 0x8420, 0x2300, 0xa210,
-	0x0070, 0x2c64, 0x0078, 0x2c57, 0x157f, 0xa006, 0x007c, 0x157f,
-	0xa582, 0x0064, 0x00c8, 0x2c70, 0x7808, 0xa085, 0x0070, 0x780a,
-	0x78ec, 0xa084, 0x0300, 0x0040, 0x2c7e, 0x2404, 0xa09e, 0x1201,
-	0x00c0, 0x2c7e, 0x2001, 0x2101, 0x0078, 0x2c7f, 0x2404, 0xa005,
-	0x007c, 0x1201, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404, 0x5604,
-	0x6605, 0x6805, 0x7806, 0x7a06, 0x0a07, 0x0c07, 0x0e07, 0x3202,
-	0x4202, 0x5202, 0x6202, 0x7202, 0x6605, 0x7605, 0x7805, 0x7a05,
-	0x7c05, 0x7e05, 0x7f05, 0x2202, 0x3202, 0x4202, 0x5202, 0x5404,
-	0x6404, 0x7404, 0x7604, 0x7804, 0x7a04, 0x7c04, 0x7e04, 0x7f04,
-	0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784,
-	0x0007, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e0, 0x3680,
-	0x007c, 0x79d8, 0x7adc, 0x78d0, 0x801b, 0x00c8, 0x2cc0, 0x8000,
-	0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x007c, 0x0f7e, 0x2079,
-	0x0100, 0x2009, 0x3540, 0x2091, 0x8000, 0x2104, 0x0079, 0x2cd0,
-	0x2d02, 0x2cda, 0x2cda, 0x2cda, 0x2cda, 0x2cda, 0x2cd8, 0x2cd8,
-	0x1078, 0x1b81, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004, 0x00c0,
-	0x2cdc, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0, 0x2ce3,
-	0x68b0, 0xa085, 0x4000, 0x68b2, 0x7858, 0xa085, 0x4000, 0x785a,
-	0x7830, 0xa084, 0x0080, 0x00c0, 0x2d02, 0x0018, 0x2d02, 0x6818,
-	0xa084, 0x0020, 0x00c0, 0x2d00, 0x781b, 0x00dd, 0x0078, 0x2d02,
-	0x781b, 0x00e4, 0x2091, 0x8001, 0x0f7f, 0x007c, 0x0c7e, 0x6810,
-	0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e0, 0x3600,
-	0x6004, 0xa084, 0x000a, 0x00c0, 0x2d39, 0x6108, 0xa194, 0xff00,
-	0x0040, 0x2d39, 0xa18c, 0x00ff, 0x2001, 0x0019, 0xa106, 0x0040,
-	0x2d28, 0x2001, 0x0032, 0xa106, 0x0040, 0x2d2c, 0x0078, 0x2d30,
-	0x2009, 0x0020, 0x0078, 0x2d32, 0x2009, 0x003f, 0x0078, 0x2d32,
-	0x2011, 0x0000, 0x2100, 0xa205, 0x600a, 0x6004, 0xa085, 0x0002,
-	0x6006, 0x0c7f, 0x007c, 0x781b, 0x006a, 0x0078, 0x1bd3, 0x781b,
-	0x0069, 0x0078, 0x1bd3, 0x781b, 0x0058, 0x0078, 0x1bd3, 0x781b,
-	0x0055, 0x0078, 0x1bd3, 0x781b, 0x00dd, 0x0078, 0x1bd3, 0x781b,
-	0x00dc, 0x0078, 0x1bd3, 0x781b, 0x00e4, 0x0078, 0x1bd3, 0x781b,
-	0x00e3, 0x0078, 0x1bd3, 0x781b, 0x009e, 0x0078, 0x1bd3, 0x781b,
-	0x009d, 0x0078, 0x1bd3, 0x70a3, 0x0001, 0x781b, 0x0046, 0x0078,
-	0x1bd3, 0x007e, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2d80, 0x7808,
-	0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec,
-	0xa084, 0x0021, 0x0040, 0x2d80, 0x7808, 0xa085, 0x0002, 0x780a,
-	0x007f, 0x007c, 0x7808, 0xa085, 0x0002, 0x780a, 0x007c, 0x7830,
-	0xa084, 0x0040, 0x00c0, 0x2d87, 0x0098, 0x2d90, 0x78ac, 0x007c,
-	0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005,
-	0x78ec, 0xa084, 0x0021, 0x0040, 0x2d9f, 0x0098, 0x2d9d, 0x78ac,
-	0x007e, 0x7808, 0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0xa784,
-	0x0070, 0x0040, 0x2dab, 0x6817, 0x0003, 0x7858, 0xa084, 0x3f00,
-	0x681a, 0x682f, 0x0000, 0x682b, 0x0000, 0x784b, 0x0008, 0x78e4,
-	0xa005, 0x00d0, 0x2018, 0xa084, 0x0020, 0x0040, 0x2018, 0x78ec,
-	0xa084, 0x0003, 0x0040, 0x2018, 0x0018, 0x2018, 0x0078, 0x2b7b,
-	0x0c7e, 0x6810, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
-	0xa080, 0x3600, 0x2060, 0x2048, 0x704a, 0x6000, 0x704e, 0x6004,
-	0x7052, 0x0c7f, 0x007c, 0x0020, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0062, 0x0009, 0x0014,
-	0x0014, 0x9847, 0x0014, 0x0014, 0x98f5, 0x98e7, 0x0014, 0x0014,
-	0x0080, 0x00bf, 0x0100, 0x0402, 0x2008, 0xf880, 0xa20a, 0x0014,
-	0x300b, 0xa20c, 0x0014, 0xa200, 0x8838, 0x817e, 0x842a, 0x84a0,
-	0x3806, 0x8839, 0x28c2, 0x9cc3, 0xa805, 0x0864, 0xa83b, 0x3008,
-	0x28c1, 0x9cc3, 0xa201, 0x300c, 0x2847, 0x8161, 0x846a, 0x8000,
-	0x84a4, 0x1856, 0x883a, 0xa808, 0x28e2, 0x9ca0, 0xa8f3, 0x0864,
-	0xa829, 0x300c, 0xa801, 0x3008, 0x28e1, 0x9ca0, 0x280d, 0xa204,
-	0x64c0, 0x67a0, 0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677,
-	0xa80f, 0x786e, 0x883e, 0xa80c, 0x282b, 0xa205, 0x64a0, 0x67a0,
-	0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677, 0xa801, 0x883e,
-	0x2069, 0x28c1, 0x9cc3, 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8dc,
-	0xa207, 0x0014, 0xa203, 0x8000, 0x84a8, 0x85a4, 0x1872, 0x849a,
-	0x883c, 0x1fe2, 0xf601, 0xa208, 0x856e, 0x866f, 0x0704, 0x3008,
-	0x9ca0, 0x0014, 0xa202, 0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2,
-	0xf848, 0x8174, 0x86eb, 0x85eb, 0x872e, 0x87a9, 0x883f, 0x08e6,
-	0xa8f1, 0xf861, 0xa8e8, 0xf801, 0x0014, 0xf881, 0x0016, 0x85b2,
-	0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014, 0x8532, 0xf221, 0x0014,
-	0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014, 0xa206, 0x6865, 0x817f,
-	0x842a, 0x1dc1, 0x8823, 0x0016, 0x6042, 0x8008, 0xa8fa, 0x8000,
-	0x84a4, 0x8160, 0x842a, 0xf021, 0x3008, 0x84a8, 0x1dc6, 0x20d7,
-	0x8822, 0x0016, 0x8000, 0x2848, 0x1011, 0xa8fc, 0x3008, 0x8000,
-	0xa000, 0x2802, 0x1011, 0xa8fd, 0xa887, 0x3008, 0x283d, 0x1011,
-	0xa8fd, 0xa209, 0x0017, 0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1,
-	0x0014, 0x26e0, 0x873a, 0xfaa2, 0x19f2, 0x1fe2, 0x0014, 0xa20b,
-	0x0014, 0xa20d, 0x817e, 0x842a, 0x84a0, 0x3806, 0x0210, 0x9ccd,
-	0x0704, 0x0000, 0x127e, 0x2091, 0x2200, 0x2049, 0x2eca, 0x7000,
-	0x7204, 0xa205, 0x720c, 0xa215, 0x7008, 0xa084, 0xfffd, 0xa205,
-	0x0040, 0x2edc, 0x0078, 0x2ee1, 0x7003, 0x0000, 0x127f, 0x2000,
-	0x007c, 0x7000, 0xa084, 0x0001, 0x00c0, 0x2f0f, 0x7108, 0x8104,
-	0x00c8, 0x2eee, 0x1078, 0x2fab, 0x0078, 0x2ee6, 0x700c, 0xa08c,
-	0x007f, 0x0040, 0x2f0f, 0x7004, 0x8004, 0x00c8, 0x2f06, 0x7014,
-	0xa005, 0x00c0, 0x2f02, 0x7010, 0xa005, 0x0040, 0x2f06, 0xa102,
-	0x00c8, 0x2ee6, 0x7007, 0x0010, 0x0078, 0x2f0f, 0x8aff, 0x0040,
-	0x2f0f, 0x1078, 0x316e, 0x00c0, 0x2f09, 0x0040, 0x2ee6, 0x1078,
-	0x2f59, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x6424, 0x84ff,
-	0x0040, 0x2f33, 0x2c70, 0x2039, 0x2f38, 0x2704, 0xae68, 0x680c,
-	0xa630, 0x6808, 0xa529, 0x8421, 0x0040, 0x2f33, 0x8738, 0x2704,
-	0xa005, 0x00c0, 0x2f1e, 0x7098, 0xa075, 0x0040, 0x2f33, 0x2039,
-	0x2f35, 0x0078, 0x2f1d, 0x007c, 0x0000, 0x0004, 0x0008, 0x000c,
-	0x0010, 0x0014, 0x0018, 0x001c, 0x0000, 0x127e, 0x2091, 0x2200,
-	0x2079, 0x3500, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002,
-	0x7003, 0x0000, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007, 0x0002,
-	0x7003, 0x0000, 0x2049, 0x0000, 0x78b3, 0x0000, 0x127f, 0x2000,
-	0x007c, 0x2049, 0x2f59, 0x7004, 0x8004, 0x00c8, 0x2f85, 0x7007,
-	0x0012, 0x7108, 0x7008, 0xa106, 0x00c0, 0x2f61, 0xa184, 0x0030,
-	0x0040, 0x2f6e, 0xa086, 0x0030, 0x00c0, 0x2f61, 0x7000, 0xa084,
-	0x0001, 0x00c0, 0x2f85, 0x7008, 0xa084, 0x000c, 0x00c0, 0x2f83,
-	0x710c, 0xa184, 0x0300, 0x00c0, 0x2f83, 0xa184, 0x007f, 0x00c0,
-	0x2f59, 0x0078, 0x2f85, 0x6817, 0x0003, 0x7007, 0x0012, 0x7007,
-	0x0008, 0x7004, 0xa084, 0x0008, 0x00c0, 0x2f89, 0x7007, 0x0012,
-	0x7108, 0x8104, 0x0048, 0x2f8e, 0x78b3, 0x0000, 0x7003, 0x0000,
-	0x2049, 0x0000, 0x007c, 0x107e, 0x007e, 0x127e, 0x157e, 0x2091,
-	0x2200, 0x7108, 0x1078, 0x2fab, 0x157f, 0x127f, 0x2091, 0x8001,
-	0x007f, 0x107f, 0x007c, 0x7204, 0x2118, 0x7108, 0x700c, 0xa084,
-	0x0300, 0x00c0, 0x2fed, 0xa184, 0x000c, 0x00c0, 0x2fed, 0x8213,
-	0x8213, 0x8213, 0x8213, 0xa284, 0x0100, 0xa10d, 0x810b, 0x810b,
-	0x810f, 0xa184, 0x0007, 0x0079, 0x2fc5, 0x2fcf, 0x2fdf, 0x2fed,
-	0x2fdf, 0x3001, 0x3001, 0x2fed, 0x2fff, 0x1078, 0x1b81, 0x7007,
-	0x0002, 0x8aff, 0x00c0, 0x2fd8, 0x2049, 0x0000, 0x0078, 0x2fdc,
-	0x1078, 0x316e, 0x00c0, 0x2fd8, 0x78b3, 0x0000, 0x007c, 0x7007,
-	0x0002, 0x8aff, 0x00c0, 0x2fe6, 0x0078, 0x2fea, 0x1078, 0x316e,
-	0x00c0, 0x2fe6, 0x78b3, 0x0000, 0x007c, 0x7007, 0x0002, 0x1078,
-	0x2f59, 0x1078, 0x2cc6, 0x6814, 0xa084, 0x8000, 0x0040, 0x2ffa,
-	0x6817, 0x0002, 0x007c, 0x1078, 0x1b81, 0x1078, 0x1b81, 0x1078,
-	0x3053, 0x7210, 0x7114, 0x700c, 0xa09c, 0x007f, 0x2800, 0xa300,
-	0xa211, 0xa189, 0x0000, 0x78b0, 0xa005, 0x0040, 0x3013, 0x78b3,
-	0x0000, 0x0078, 0x3036, 0x1078, 0x3053, 0x2704, 0x2c58, 0xac60,
-	0x630c, 0x2200, 0xa322, 0x6308, 0x2100, 0xa31b, 0x2400, 0xa305,
-	0x0040, 0x302c, 0x00c8, 0x302c, 0x8412, 0x8210, 0x830a, 0xa189,
-	0x0000, 0x2b60, 0x0078, 0x3013, 0x2b60, 0x8a07, 0xa7ba, 0x2f35,
-	0xa73d, 0x2c00, 0x6882, 0x6f86, 0x6c8e, 0x6b8a, 0x7007, 0x0012,
-	0x1078, 0x2f59, 0x007c, 0x8738, 0x2704, 0xa005, 0x00c0, 0x3047,
-	0x6098, 0xa005, 0x0040, 0x3050, 0x2060, 0x2039, 0x2f35, 0x8a51,
-	0x0040, 0x304f, 0x7008, 0xa084, 0x00c0, 0xa086, 0x00c0, 0x007c,
-	0x2051, 0x0000, 0x007c, 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0,
-	0x3060, 0x2039, 0x2f3b, 0x6000, 0xa064, 0x00c0, 0x3060, 0x2d60,
-	0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x6880, 0x2060,
-	0x6884, 0x6b88, 0x6c8c, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff,
-	0xa0b8, 0x2f35, 0x7e08, 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040,
-	0x0040, 0x307c, 0xa6b5, 0x0001, 0x0f7e, 0x2079, 0x0100, 0x7858,
-	0x0f7f, 0xa084, 0x0040, 0x0040, 0x308b, 0xa684, 0x0001, 0x00c0,
-	0x308b, 0xa6b5, 0x0001, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
-	0x00c0, 0x308d, 0x7000, 0xa005, 0x0040, 0x3098, 0x1078, 0x1b81,
-	0x2400, 0xa305, 0x00c0, 0x309e, 0x0078, 0x30db, 0x2c58, 0x2704,
-	0xac60, 0x6004, 0xa400, 0x007e, 0x701a, 0x6000, 0xa301, 0x701e,
-	0x2009, 0x04fd, 0x2104, 0xa086, 0x04fd, 0x007f, 0x00c0, 0x30cb,
-	0xa084, 0x0001, 0x0040, 0x30cb, 0xa684, 0x0001, 0x00c0, 0x30cb,
-	0x7013, 0x0001, 0x7017, 0x0000, 0x7602, 0x7007, 0x0001, 0x78b3,
-	0x0001, 0xa4a0, 0x0001, 0xa399, 0x0000, 0x6004, 0xa400, 0x701a,
-	0x6000, 0xa301, 0x701e, 0x620c, 0x2400, 0xa202, 0x7012, 0x6208,
-	0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078,
-	0x303b, 0x0078, 0x30dd, 0x1078, 0x316e, 0x00c0, 0x30db, 0x127f,
-	0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007,
-	0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x30e9, 0x7003, 0x0008,
-	0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f,
-	0x2049, 0x30f3, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
-	0x30fc, 0x7000, 0xa005, 0x0040, 0x3107, 0x1078, 0x1b81, 0x7e08,
-	0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, 0x0040, 0x3111, 0xa6b5,
-	0x0001, 0x6824, 0xa005, 0x0040, 0x311d, 0x2050, 0x2039, 0x2f38,
-	0x2d60, 0x1078, 0x316e, 0x00c0, 0x3119, 0x127f, 0x2000, 0x007c,
-	0x127e, 0x007e, 0x017e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f,
-	0x047f, 0x7e08, 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, 0x0040,
-	0x3133, 0xa6b5, 0x0001, 0x2049, 0x3120, 0x6824, 0xa055, 0x0040,
-	0x316b, 0x2d70, 0x2e60, 0x2039, 0x2f38, 0x2704, 0xae68, 0x680c,
-	0xa422, 0x6808, 0xa31b, 0x0048, 0x3158, 0x8a51, 0x00c0, 0x314a,
-	0x1078, 0x1b81, 0x8738, 0x2704, 0xa005, 0x00c0, 0x313e, 0x7098,
-	0xa075, 0x2060, 0x0040, 0x316b, 0x2039, 0x2f35, 0x0078, 0x313d,
-	0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x690c, 0x2400, 0xa122,
-	0x6908, 0x2300, 0xa11b, 0x00c8, 0x3167, 0x1078, 0x1b81, 0x2071,
-	0x0020, 0x0078, 0x308b, 0x127f, 0x2000, 0x007c, 0x7008, 0xa084,
-	0x00c0, 0xa086, 0x00c0, 0x0040, 0x3196, 0x2704, 0xac08, 0x2104,
-	0x701e, 0x8108, 0x2104, 0x701a, 0x8108, 0x2104, 0x7016, 0x8108,
-	0x2104, 0x7012, 0x0f7e, 0x2079, 0x0100, 0x7858, 0x0f7f, 0xa084,
-	0x0040, 0x0040, 0x3191, 0xa684, 0x0001, 0x00c0, 0x3191, 0xa6b5,
-	0x0001, 0x7602, 0x7007, 0x0001, 0x1078, 0x303b, 0x007c, 0x127e,
-	0x007e, 0x0d7e, 0x2091, 0x2200, 0x2049, 0x3197, 0x0d7f, 0x087f,
-	0x7108, 0xa184, 0x00c0, 0x00c0, 0x31ad, 0x6824, 0xa005, 0x0040,
-	0x31bd, 0x0078, 0x2ee1, 0x0078, 0x31bd, 0x7108, 0x8104, 0x00c8,
-	0x31b5, 0x1078, 0x2fab, 0x0078, 0x31a0, 0x7007, 0x0010, 0x7108,
-	0x8104, 0x00c8, 0x31b7, 0x1078, 0x2fab, 0x7008, 0xa086, 0x0002,
-	0x00c0, 0x31a0, 0x7000, 0xa005, 0x00c0, 0x31a0, 0x7003, 0x0000,
-	0x2049, 0x0000, 0x127f, 0x2000, 0x007c, 0x127e, 0x147e, 0x137e,
-	0x157e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x31cd, 0xad80,
-	0x0010, 0x20a0, 0x2099, 0x0031, 0x700c, 0xa084, 0x007f, 0x6826,
-	0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0040, 0x31eb,
-	0x8000, 0x80ac, 0x53a5, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
-	0x00c0, 0x31ed, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f,
-	0x147f, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091,
-	0x2200, 0x0d7f, 0x2049, 0x31fc, 0x6880, 0x2060, 0x6884, 0x6b88,
-	0x6c8c, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0xa0b8, 0x2f35,
-	0x7e08, 0xa6b5, 0x0004, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
-	0x00c0, 0x3215, 0x2c58, 0x2704, 0xac60, 0x6004, 0xa400, 0x701a,
-	0x6000, 0xa301, 0x701e, 0x7013, 0x0001, 0x7017, 0x0000, 0x7602,
-	0x7007, 0x0001, 0x007f, 0x8007, 0x2009, 0x0031, 0x200a, 0x00a0,
-	0x322f, 0x7108, 0x7007, 0x0002, 0x810c, 0x00c8, 0x322f, 0x810c,
-	0x0048, 0x323c, 0x0078, 0x2fed, 0xa4a0, 0x0001, 0xa399, 0x0000,
-	0x6b8a, 0x6c8e, 0x7007, 0x0004, 0x2049, 0x0000, 0x7003, 0x0000,
-	0x127f, 0x2000, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086,
-	0x818e, 0x00c8, 0x3254, 0xa200, 0x00f0, 0x324f, 0x8086, 0x818e,
-	0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x327a, 0xa11a,
-	0x00c8, 0x327a, 0x8213, 0x818d, 0x0048, 0x326d, 0xa11a, 0x00c8,
-	0x326e, 0x00f0, 0x3262, 0x0078, 0x3272, 0xa11a, 0x2308, 0x8210,
-	0x00f0, 0x3262, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f,
-	0x157f, 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x3276,
-	0x00e0, 0x32c2, 0x2091, 0x6000, 0x7820, 0x8001, 0x7822, 0x00c0,
-	0x32bc, 0x7824, 0x7822, 0x2091, 0x8000, 0x2069, 0x3540, 0x6800,
-	0xa084, 0x0007, 0x0040, 0x32a4, 0xa086, 0x0002, 0x0040, 0x32a4,
-	0x6830, 0xa00d, 0x0040, 0x32a4, 0x2104, 0xa005, 0x0040, 0x32a4,
-	0x8001, 0x200a, 0x0040, 0x3372, 0x2061, 0x3680, 0x20a9, 0x0080,
-	0x6034, 0xa005, 0x0040, 0x32b6, 0x8001, 0x6036, 0x00c0, 0x32b6,
-	0x6010, 0xa005, 0x0040, 0x32b6, 0x1078, 0x1a23, 0xace0, 0x0010,
-	0x0070, 0x32bc, 0x0078, 0x32a8, 0x1078, 0x32d7, 0x1078, 0x32c5,
-	0x1078, 0x32fc, 0x2091, 0x8001, 0x007c, 0x783c, 0x8001, 0x783e,
-	0x00c0, 0x32d6, 0x7840, 0x783e, 0x7848, 0xa005, 0x0040, 0x32d6,
-	0x8001, 0x784a, 0x00c0, 0x32d6, 0x1078, 0x1a23, 0x007c, 0x7834,
-	0x8001, 0x7836, 0x00c0, 0x32fb, 0x7838, 0x7836, 0x2091, 0x8000,
-	0x7844, 0xa005, 0x00c0, 0x32e6, 0x2001, 0x0101, 0x8001, 0x7846,
-	0xa080, 0x3e80, 0x2040, 0x2004, 0xa065, 0x0040, 0x32fb, 0x6020,
-	0xa005, 0x0040, 0x32f7, 0x8001, 0x6022, 0x0040, 0x332b, 0x6000,
-	0x2c40, 0x0078, 0x32ec, 0x007c, 0x7828, 0x8001, 0x782a, 0x00c0,
-	0x332a, 0x782c, 0x782a, 0x7830, 0xa005, 0x00c0, 0x3309, 0x2001,
-	0x0080, 0x8001, 0x7832, 0x8003, 0x8003, 0x8003, 0x8003, 0xa090,
-	0x3680, 0xa298, 0x0002, 0x2304, 0xa084, 0x0008, 0x0040, 0x332a,
-	0xa290, 0x0009, 0x2204, 0xa005, 0x0040, 0x3322, 0x8001, 0x2012,
-	0x00c0, 0x332a, 0x2304, 0xa084, 0xfff7, 0xa085, 0x0080, 0x201a,
-	0x1078, 0x1a23, 0x007c, 0x2069, 0x3540, 0x6800, 0xa005, 0x0040,
-	0x3335, 0x683c, 0xac06, 0x0040, 0x3372, 0x6017, 0x0006, 0x60b0,
-	0xa084, 0x3f00, 0x601a, 0x601c, 0xa084, 0x00ff, 0xa085, 0x0060,
-	0x601e, 0x6000, 0x2042, 0x6710, 0x6fb6, 0x1078, 0x169c, 0x6818,
-	0xa005, 0x0040, 0x334d, 0x8001, 0x681a, 0x6808, 0xa084, 0xffef,
-	0x680a, 0x6810, 0x8001, 0x00d0, 0x3357, 0x1078, 0x1b81, 0x6812,
-	0x602f, 0x0000, 0x602b, 0x0000, 0x2c68, 0x1078, 0x17e7, 0x2069,
-	0x3540, 0x2001, 0x0006, 0x68a2, 0x7944, 0xa184, 0x0100, 0x00c0,
-	0x336d, 0x69ba, 0x2001, 0x0004, 0x68a2, 0x1078, 0x1a1e, 0x2091,
-	0x8001, 0x007c, 0x2009, 0x354f, 0x2164, 0x2069, 0x0100, 0x6017,
-	0x0006, 0x6858, 0xa084, 0x3f00, 0x601a, 0x601c, 0xa084, 0x00ff,
-	0xa085, 0x0048, 0x601e, 0x602f, 0x0000, 0x602b, 0x0000, 0x6830,
-	0xa084, 0x0040, 0x0040, 0x33ac, 0x684b, 0x0004, 0x20a9, 0x0014,
-	0x6848, 0xa084, 0x0004, 0x0040, 0x3399, 0x0070, 0x3399, 0x0078,
-	0x3390, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001,
-	0x0040, 0x33a6, 0x0070, 0x33a6, 0x0078, 0x339d, 0x20a9, 0x00fa,
-	0x0070, 0x33ac, 0x0078, 0x33a8, 0x6808, 0xa084, 0xfffd, 0x680a,
-	0x681b, 0x0046, 0x2009, 0x3568, 0x200b, 0x0007, 0x784c, 0x784a,
-	0x2091, 0x8001, 0x007c, 0x2079, 0x3500, 0x1078, 0x3404, 0x1078,
-	0x33cc, 0x1078, 0x33e1, 0x1078, 0x33f6, 0x7833, 0x0000, 0x7847,
-	0x0000, 0x784b, 0x0000, 0x007c, 0x2019, 0x000a, 0x2011, 0x3546,
-	0x2204, 0xa086, 0x0032, 0x0040, 0x33de, 0x2019, 0x000c, 0x2204,
-	0xa086, 0x003c, 0x0040, 0x33de, 0x2019, 0x0008, 0x7b2a, 0x7b2e,
-	0x007c, 0x2019, 0x0030, 0x2011, 0x3546, 0x2204, 0xa086, 0x0032,
-	0x0040, 0x33f3, 0x2019, 0x0039, 0x2204, 0xa086, 0x003c, 0x0040,
-	0x33f3, 0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019, 0x000d,
-	0x2011, 0x3546, 0x2204, 0xa086, 0x003c, 0x0040, 0x3401, 0x2019,
-	0x000a, 0x7b3e, 0x7b42, 0x007c, 0x2019, 0x2faf, 0x2011, 0x3546,
-	0x2204, 0xa086, 0x0032, 0x0040, 0x3416, 0x2019, 0x3971, 0x2204,
-	0xa086, 0x003c, 0x0040, 0x3416, 0x2019, 0x2626, 0x7b22, 0x7b26,
-	0x007c, 0xda3e
+	0x00d0, 0x3354, 0x1078, 0x1ba5, 0x6812, 0x602f, 0x0000, 0x602b,
+	0x0000, 0x2c68, 0x1078, 0x17dd, 0x2069, 0x3540, 0x2001, 0x0006,
+	0x68a2, 0x7944, 0xa184, 0x0100, 0x00c0, 0x336a, 0x69ba, 0x2001,
+	0x0004, 0x68a2, 0x1078, 0x1a14, 0x2091, 0x8001, 0x007c, 0x2009,
+	0x354f, 0x2164, 0x2069, 0x0100, 0x1078, 0x1b6b, 0x6017, 0x0006,
+	0x6858, 0xa084, 0x3f00, 0x601a, 0x601c, 0xa084, 0x00ff, 0xa085,
+	0x0048, 0x601e, 0x602f, 0x0000, 0x602b, 0x0000, 0x6830, 0xa084,
+	0x0040, 0x0040, 0x33ab, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848,
+	0xa084, 0x0004, 0x0040, 0x3398, 0x0070, 0x3398, 0x0078, 0x338f,
+	0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040,
+	0x33a5, 0x0070, 0x33a5, 0x0078, 0x339c, 0x20a9, 0x00fa, 0x0070,
+	0x33ab, 0x0078, 0x33a7, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b,
+	0x0046, 0x2009, 0x3568, 0x200b, 0x0007, 0x784c, 0x784a, 0x2091,
+	0x8001, 0x007c, 0x2079, 0x3500, 0x1078, 0x3403, 0x1078, 0x33cb,
+	0x1078, 0x33e0, 0x1078, 0x33f5, 0x7833, 0x0000, 0x7847, 0x0000,
+	0x784b, 0x0000, 0x007c, 0x2019, 0x000a, 0x2011, 0x3546, 0x2204,
+	0xa086, 0x0032, 0x0040, 0x33dd, 0x2019, 0x000c, 0x2204, 0xa086,
+	0x003c, 0x0040, 0x33dd, 0x2019, 0x0008, 0x7b2a, 0x7b2e, 0x007c,
+	0x2019, 0x0030, 0x2011, 0x3546, 0x2204, 0xa086, 0x0032, 0x0040,
+	0x33f2, 0x2019, 0x0039, 0x2204, 0xa086, 0x003c, 0x0040, 0x33f2,
+	0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019, 0x000d, 0x2011,
+	0x3546, 0x2204, 0xa086, 0x003c, 0x0040, 0x3400, 0x2019, 0x000a,
+	0x7b3e, 0x7b42, 0x007c, 0x2019, 0x2faf, 0x2011, 0x3546, 0x2204,
+	0xa086, 0x0032, 0x0040, 0x3415, 0x2019, 0x3971, 0x2204, 0xa086,
+	0x003c, 0x0040, 0x3415, 0x2019, 0x2626, 0x7b22, 0x7b26, 0x007c,
+	0x92a7
 };
-
-unsigned short sbus_risc_code_length01 = 0x241a;
+unsigned short sbus_risc_code_length01 = 0x2419;
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.3.34/linux/drivers/scsi/scsi.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/scsi.c	Sun Dec 26 10:52:04 1999
@@ -1470,9 +1470,6 @@
 	 */
 
 
-	host->host_busy++;
-	device->device_busy++;
-
 	/*
 	 * Our own function scsi_done (which marks the host as not busy, disables
 	 * the timeout counter, etc) will be called by us or by the
@@ -1575,6 +1572,9 @@
 	 * Since serial_number is now 0, the error handler cound detect this
 	 * situation and avoid to call the the low level driver abort routine.
 	 * (DB)
+         *
+         * FIXME(eric) - I believe that this test is now redundant, due to
+         * the test of the return status of del_timer().
 	 */
 	if (SCpnt->state == SCSI_STATE_TIMEOUT) {
 		SCSI_LOG_MLCOMPLETE(1, printk("Ignoring completion of %p due to timeout status", SCpnt));
@@ -2020,7 +2020,7 @@
 	spin_unlock_irqrestore(&device_request_lock, flags);
 }
 
-static ssize_t proc_scsi_gen_write(struct file * file, const char * buf,
+static int proc_scsi_gen_write(struct file * file, const char * buf,
                               unsigned long length, void *data);
 
 #ifndef MODULE			/* { */
@@ -2215,7 +2215,7 @@
 	return (len);
 }
 
-static ssize_t proc_scsi_gen_write(struct file * file, const char * buf,
+static int proc_scsi_gen_write(struct file * file, const char * buf,
                               unsigned long length, void *data)
 {
 	Scsi_Cmnd *SCpnt;
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c
--- v2.3.34/linux/drivers/scsi/scsi_error.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/scsi_error.c	Sun Dec 26 10:52:04 1999
@@ -1778,6 +1778,17 @@
 	for (SCpnt = SCdone; SCpnt != NULL; SCpnt = SCdone) {
 		SCdone = SCpnt->bh_next;
 		SCpnt->bh_next = NULL;
+                /*
+                 * Oh, this is a vile hack.  scsi_done() expects a timer
+                 * to be running on the command.  If there isn't, it assumes
+                 * that the command has actually timed out, and a timer
+                 * handler is running.  That may well be how we got into
+                 * this fix, but right now things are stable.  We add
+                 * a timer back again so that we can report completion.
+                 * scsi_done() will immediately remove said timer from
+                 * the command, and then process it.
+                 */
+		scsi_add_timer(SCpnt, 100, scsi_eh_times_out);
 		scsi_done(SCpnt);
 	}
 
@@ -1809,7 +1820,14 @@
 	int rtn;
 	DECLARE_MUTEX_LOCKED(sem);
 
+        /*
+         * We only listen to signals if the HA was loaded as a module.
+         * If the HA was compiled into the kernel, then we don't listen
+         * to any signals.
+         */
+        if( host->loaded_as_module ) {
 	siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
+        }
 
 	lock_kernel();
 
@@ -1844,10 +1862,14 @@
 		 * trying to unload a module.
 		 */
 		SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler sleeping\n"));
+                if( host->loaded_as_module ) {
 		down_interruptible(&sem);
 
 		if (signal_pending(current))
 			break;
+                } else {
+                        down(&sem);
+                }
 
 		SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler waking up\n"));
 
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c
--- v2.3.34/linux/drivers/scsi/scsi_lib.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/scsi_lib.c	Sun Dec 26 10:52:05 1999
@@ -607,6 +607,22 @@
 		if (spnt->blk && spnt->major == major) {
 			return spnt;
 		}
+		/*
+		 * I am still not entirely satisfied with this solution,
+		 * but it is good enough for now.  Disks have a number of
+		 * major numbers associated with them, the primary
+		 * 8, which we test above, and a secondary range of 7
+		 * different consecutive major numbers.   If this ever
+		 * becomes insufficient, then we could add another function
+		 * to the structure, and generalize this completely.
+		 */
+		if( spnt->min_major != 0 
+		    && spnt->max_major != 0
+		    && major >= spnt->min_major
+		    && major <= spnt->max_major )
+		{
+			return spnt;
+		}
 	}
 	return NULL;
 }
@@ -742,11 +758,16 @@
 			if (!SCpnt) {
 				break;
 			}
-			SHpnt->host_busy++;
-			SDpnt->device_busy++;
 		}
 
 		/*
+		 * Now bump the usage count for both the host and the
+		 * device.
+		 */
+		SHpnt->host_busy++;
+		SDpnt->device_busy++;
+
+		/*
 		 * FIXME(eric)
 		 * I am not sure where the best place to do this is.  We need
 		 * to hook in a place where we are likely to come if in user
@@ -821,12 +842,14 @@
 			 * get those allocated here.  
 			 */
 			if (!SDpnt->scsi_init_io_fn(SCpnt)) {
+				spin_lock_irq(&io_request_lock);
 				continue;
 			}
 			/*
 			 * Initialize the actual SCSI command for this request.
 			 */
 			if (!STpnt->init_command(SCpnt)) {
+				spin_lock_irq(&io_request_lock);
 				continue;
 			}
 		}
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/scsi_merge.c linux/drivers/scsi/scsi_merge.c
--- v2.3.34/linux/drivers/scsi/scsi_merge.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/scsi_merge.c	Sun Dec 26 10:52:05 1999
@@ -290,6 +290,30 @@
 
 	count = bh->b_size >> 9;
 	sector = bh->b_rsector;
+#if CONFIG_HIGHMEM
+	/*
+	 * This is a temporary hack for the time being.
+	 * In some cases, the ll_rw_blk layer is creating
+	 * bounce buffers for us - this implies that we don't
+	 * need to down here, but queue management becomes quite
+	 * difficult otherwise.  When the ll_rw_blk layer gets
+	 * cleaned up to handle bounce buffers better, then
+	 * this hack can be cleaned up.
+	 */
+	if( sector == -1 )
+	{
+		struct buffer_head * bh_new;
+		bh_new = (struct buffer_head *) bh->b_dev_id;
+		if( bh_new != NULL )
+		{
+			sector = bh_new->b_rsector;
+		}
+		if( sector == -1 )
+		{
+			panic("Unable to merge ambiguous block request");
+		}
+	}
+#endif
 
 	/*
 	 * We come in here in one of two cases.   The first is that we
@@ -765,7 +789,8 @@
 	if( scsi_dma_free_sectors > 30 ) {
 		for (this_count = 0, bh = SCpnt->request.bh;
 		     bh; bh = bh->b_reqnext) {
-			if( scsi_dma_free_sectors < 30 || this_count == sectors )
+			if( scsi_dma_free_sectors - this_count < 30 
+			    || this_count == sectors )
 			{
 				break;
 			}
@@ -831,24 +856,11 @@
  * We always force "_VALID" to 1.  Eventually clean this up
  * and get rid of the extra argument.
  */
-#if 0
-/* Old definitions */
-INITIO(scsi_init_io_, 0, 0, 0)
-INITIO(scsi_init_io_d, 0, 0, 1)
-INITIO(scsi_init_io_c, 0, 1, 0)
-INITIO(scsi_init_io_dc, 0, 1, 1)
-
-/* Newer redundant definitions. */
-INITIO(scsi_init_io_, 1, 0, 0)
-INITIO(scsi_init_io_d, 1, 0, 1)
-INITIO(scsi_init_io_c, 1, 1, 0)
-INITIO(scsi_init_io_dc, 1, 1, 1)
-#endif
-
 INITIO(scsi_init_io_v, 1, 0, 0)
 INITIO(scsi_init_io_vd, 1, 0, 1)
 INITIO(scsi_init_io_vc, 1, 1, 0)
 INITIO(scsi_init_io_vdc, 1, 1, 1)
+
 /*
  * Function:    initialize_merge_fn()
  *
@@ -881,21 +893,12 @@
 	 * If this host has an unlimited tablesize, then don't bother with a
 	 * merge manager.  The whole point of the operation is to make sure
 	 * that requests don't grow too large, and this host isn't picky.
-	 */
-	if (SHpnt->sg_tablesize == SG_ALL) {
-		if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) {
-			SDpnt->scsi_init_io_fn = scsi_init_io_v;
-		} else if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma != 0) {
-			SDpnt->scsi_init_io_fn = scsi_init_io_vd;
-		} else if (CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) {
-			SDpnt->scsi_init_io_fn = scsi_init_io_vc;
-		} else if (CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma != 0) {
-			SDpnt->scsi_init_io_fn = scsi_init_io_vdc;
-		}
-		return;
-	}
-	/*
-	 * Now pick out the correct function.
+	 *
+	 * Note that ll_rw_blk.c is effectively maintaining a segment
+	 * count which is only valid if clustering is used, and it obviously
+	 * doesn't handle the DMA case.   In the end, it
+	 * is simply easier to do it ourselves with our own functions
+	 * rather than rely upon the default behavior of ll_rw_blk.
 	 */
 	if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) {
 		q->merge_fn = scsi_merge_fn_;
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c
--- v2.3.34/linux/drivers/scsi/scsi_proc.c	Tue Dec  7 09:32:46 1999
+++ linux/drivers/scsi/scsi_proc.c	Mon Dec 20 22:05:10 1999
@@ -91,8 +91,8 @@
 				      * use some slack for overruns 
 				      */
 
-static ssize_t proc_scsi_write(struct file * file, const char * buf,
-                              unsigned long count, void *data)
+static int proc_scsi_write(struct file * file, const char * buf,
+                           unsigned long count, void *data)
 {
 	struct Scsi_Host *hpnt = data;
 	ssize_t ret = 0;
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.3.34/linux/drivers/scsi/sd.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/sd.c	Sun Dec 26 10:52:05 1999
@@ -202,6 +202,11 @@
 	tag:"sd",
 	scsi_type:TYPE_DISK,
 	major:SCSI_DISK0_MAJOR,
+        /*
+         * Secondary range of majors that this driver handles.
+         */
+	min_major:SCSI_DISK1_MAJOR,
+	max_major:SCSI_DISK7_MAJOR,
 	blk:1,
 	detect:sd_detect,
 	init:sd_init,
@@ -229,7 +234,7 @@
 	Scsi_Disk *dpnt;
 	char nbuff[6];
 
-	devm = MINOR(SCpnt->request.rq_dev);
+	devm = SD_PARTITION(SCpnt->request.rq_dev);
 	dev = DEVICE_NR(SCpnt->request.rq_dev);
 
 	block = SCpnt->request.sector;
@@ -561,7 +566,7 @@
 			default:
 				break;
 			}
-			error_sector -= sd[MINOR(SCpnt->request.rq_dev)].start_sect;
+			error_sector -= sd[SD_PARTITION(SCpnt->request.rq_dev)].start_sect;
 			error_sector &= ~(block_sectors - 1);
 			good_sectors = error_sector - SCpnt->request.sector;
 			if (good_sectors < 0 || good_sectors >= this_count)
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v2.3.34/linux/drivers/scsi/sg.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/sg.c	Sun Dec 26 10:52:05 1999
@@ -101,10 +101,17 @@
 static void sg_detach(Scsi_Device *);
 
 
-struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", NULL, 0xff,
-                                           SCSI_GENERIC_MAJOR, 0, 0, 0, 0,
-                                           sg_detect, sg_init,
-                                           sg_finish, sg_attach, sg_detach};
+struct Scsi_Device_Template sg_template = 
+{
+	tag:"sg", 
+	scsi_type:0xff,
+	major:SCSI_GENERIC_MAJOR, 
+	detect:sg_detect, 
+	init:sg_init,
+	finish:sg_finish, 
+	attach:sg_attach, 
+	detach:sg_detach
+};
 
 
 typedef struct sg_scatter_hold  /* holding area for scsi scatter gather info */
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v2.3.34/linux/drivers/scsi/st.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/st.c	Sun Dec 26 10:52:05 1999
@@ -11,7 +11,7 @@
    Copyright 1992 - 1999 Kai Makisara
    email Kai.Makisara@metla.fi
 
-   Last modified: Tue Oct 19 21:39:15 1999 by makisara@kai.makisara.local
+   Last modified: Thu Dec 16 23:08:29 1999 by makisara@kai.makisara.local
    Some small formal changes - aeb, 950809
  */
 
@@ -147,10 +147,16 @@
 static void st_detach(Scsi_Device *);
 
 struct Scsi_Device_Template st_template =
-{NULL, "tape", "st", NULL, TYPE_TAPE,
- SCSI_TAPE_MAJOR, 0, 0, 0, 0,
- st_detect, st_init,
- NULL, st_attach, st_detach};
+{
+	name:"tape", 
+	tag:"st", 
+	scsi_type:TYPE_TAPE,
+	major:SCSI_TAPE_MAJOR, 
+	detect:st_detect, 
+	init:st_init,
+	attach:st_attach, 
+	detach:st_detach
+};
 
 static int st_compression(Scsi_Tape *, int);
 
@@ -289,10 +295,14 @@
 	unsigned char *bp;
 
 	if (SCpnt == NULL)
-		SCpnt = scsi_allocate_device(STp->device, 1, FALSE);
+		SCpnt = scsi_allocate_device(STp->device, 1, TRUE);
 		if (SCpnt == NULL) {
-			printk(KERN_ERR "st%d: Can't get SCSI request.\n",
-                               TAPE_NR(STp->devt));
+			DEBC( printk(KERN_ERR "st%d: Can't get SCSI request.\n",
+				     TAPE_NR(STp->devt)); );
+			if (signal_pending(current))
+				(STp->buffer)->last_result_fatal = (-EINTR);
+			else
+				(STp->buffer)->last_result_fatal = (-EBUSY);
 			return NULL;
 		}
 
@@ -386,7 +396,7 @@
 
 	SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->timeout, MAX_RETRIES, TRUE);
 	if (!SCpnt)
-		return (-EBUSY);
+		return (STp->buffer)->last_result_fatal;
 
 	scsi_release_command(SCpnt);
 	SCpnt = NULL;
@@ -444,7 +454,7 @@
 		SCpnt = st_do_scsi(NULL, STp, cmd, transfer, STp->timeout,
                                    MAX_WRITE_RETRIES, TRUE);
 		if (!SCpnt)
-			return (-EBUSY);
+			return (STp->buffer)->last_result_fatal;
 
 		STps = &(STp->ps[STp->partition]);
 		if ((STp->buffer)->last_result_fatal != 0) {
@@ -656,7 +666,7 @@
 			__MOD_DEC_USE_COUNT(scsi_tapes[dev].device->host->hostt->module);
 		if (st_template.module)
 			__MOD_DEC_USE_COUNT(st_template.module);
-		return (-EBUSY);
+		return (STp->buffer)->last_result_fatal;
 	}
 
 	if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
@@ -905,8 +915,10 @@
 
 			SCpnt = st_do_scsi(NULL, STp, cmd, 0, STp->timeout,
                                            MAX_WRITE_RETRIES, TRUE);
-			if (!SCpnt)
+			if (!SCpnt) {
+				result = (STp->buffer)->last_result_fatal;
 				goto out;
+			}
 
 			if ((STp->buffer)->last_result_fatal != 0 &&
 			    ((SCpnt->sense_buffer[0] & 0x70) != 0x70 ||
@@ -1184,7 +1196,7 @@
 		SCpnt = st_do_scsi(SCpnt, STp, cmd, transfer, STp->timeout,
 				   MAX_WRITE_RETRIES, TRUE);
 		if (!SCpnt)
-			return (-EBUSY);
+			return (STp->buffer)->last_result_fatal;
 
 		if ((STp->buffer)->last_result_fatal != 0) {
                         DEBC(printk(ST_DEB_MSG "st%d: Error on write:\n", dev));
@@ -1300,7 +1312,8 @@
 		SCpnt = st_do_scsi(SCpnt, STp, cmd, (STp->buffer)->writing, STp->timeout,
 				   MAX_WRITE_RETRIES, FALSE);
 		if (SCpnt == NULL)
-			return (-EIO);
+			return (STp->buffer)->last_result_fatal;
+
 	} else if (SCpnt != NULL) {
 		scsi_release_command(SCpnt);
 		SCpnt = NULL;
@@ -1360,7 +1373,7 @@
 	SCpnt = st_do_scsi(SCpnt, STp, cmd, bytes, STp->timeout, MAX_RETRIES, TRUE);
 	*aSCpnt = SCpnt;
 	if (!SCpnt)
-		return (-EBUSY);
+		return (STp->buffer)->last_result_fatal;
 
 	(STp->buffer)->read_pointer = 0;
 	STps->at_sm = 0;
@@ -1838,7 +1851,8 @@
 
 	SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->timeout, 0, TRUE);
 	if (SCpnt == NULL)
-		return (-EBUSY);
+		return (STp->buffer)->last_result_fatal;
+
 	dev = TAPE_NR(SCpnt->request.rq_dev);
 
 	if ((STp->buffer)->last_result_fatal != 0) {
@@ -2210,7 +2224,7 @@
 
 	SCpnt = st_do_scsi(NULL, STp, cmd, datalen, timeout, MAX_RETRIES, TRUE);
 	if (!SCpnt)
-		return (-EBUSY);
+		return (STp->buffer)->last_result_fatal;
 
 	ioctl_result = (STp->buffer)->last_result_fatal;
 
@@ -2372,7 +2386,7 @@
 	}
 	SCpnt = st_do_scsi(NULL, STp, scmd, 20, STp->timeout, MAX_READY_RETRIES, TRUE);
 	if (!SCpnt)
-		return (-EBUSY);
+		return (STp->buffer)->last_result_fatal;
 
 	if ((STp->buffer)->last_result_fatal != 0 ||
 	    (STp->device->scsi_level >= SCSI_2 &&
@@ -2478,7 +2492,7 @@
 
 	SCpnt = st_do_scsi(NULL, STp, scmd, 20, timeout, MAX_READY_RETRIES, TRUE);
 	if (!SCpnt)
-		return (-EBUSY);
+		return (STp->buffer)->last_result_fatal;
 
 	STps->drv_block = STps->drv_file = (-1);
 	STps->eof = ST_NOEOF;
@@ -2569,7 +2583,8 @@
 
 	SCpnt = st_do_scsi(SCpnt, STp, cmd, 200, STp->timeout, MAX_READY_RETRIES, TRUE);
 	if (SCpnt == NULL)
-		return (-EBUSY);
+		return (STp->buffer)->last_result_fatal;
+
 	scsi_release_command(SCpnt);
 	SCpnt = NULL;
 
@@ -2633,7 +2648,8 @@
 	SCpnt = st_do_scsi(SCpnt, STp, cmd, cmd[4], STp->long_timeout,
 			   MAX_READY_RETRIES, TRUE);
 	if (SCpnt == NULL)
-		return (-EBUSY);
+		return (STp->buffer)->last_result_fatal;
+
 	scsi_release_command(SCpnt);
 	SCpnt = NULL;
 
diff -u --recursive --new-file v2.3.34/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c
--- v2.3.34/linux/drivers/scsi/sym53c8xx.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/scsi/sym53c8xx.c	Mon Dec 20 22:06:42 1999
@@ -679,10 +679,8 @@
 #endif
 
 #ifdef __sparc__
-#include <asm/irq.h>
-#  define ioremap(base, size)	((u_long) __va(base))
-#  define iounmap(vaddr)
-#  define pcivtobus(p)			((p) & pci_dvma_mask)
+#  include <asm/irq.h>
+#  define pcivtobus(p)			bus_dvma_to_mem(p)
 #  define memcpy_to_pci(a, b, c)	memcpy_toio((a), (b), (c))
 #elif defined(__alpha__)
 #  define pcivtobus(p)			((p) & 0xfffffffful)
@@ -11882,11 +11880,10 @@
 	/*
 	**    Fix-ups for sparc.
 	*/
-	base = __pa(base);
-	base_2 = __pa(base_2);
-
 	if (!cache_line_size)
 		suggested_cache_line_size = 16;
+
+	driver_setup.pci_fix_up |= 0x7;
 #endif	/* __sparc__ */
 
 #if defined(__i386__) && !defined(MODULE)
diff -u --recursive --new-file v2.3.34/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v2.3.34/linux/drivers/sound/Config.in	Tue Dec  7 09:32:46 1999
+++ linux/drivers/sound/Config.in	Sun Dec 26 19:34:04 1999
@@ -20,9 +20,7 @@
 dep_tristate '  Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
 dep_tristate '  Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND
 dep_tristate '  ESS Technology Solo1' CONFIG_SOUND_ESSSOLO1 $CONFIG_SOUND
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-    dep_tristate '  ESS Maestro, Maestro2, Maestro2E driver (EXPERIMENTAL)' CONFIG_SOUND_MAESTRO $CONFIG_SOUND
-fi
+dep_tristate '  ESS Maestro, Maestro2, Maestro2E driver' CONFIG_SOUND_MAESTRO $CONFIG_SOUND
 dep_tristate '  S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
 if [ "$CONFIG_VISWS" = "y" ]; then
     dep_tristate '  SGI Visual Workstation Sound' CONFIG_SOUND_VWSND $CONFIG_SOUND
diff -u --recursive --new-file v2.3.34/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c
--- v2.3.34/linux/drivers/sound/maestro.c	Thu Nov 18 20:25:37 1999
+++ linux/drivers/sound/maestro.c	Sun Dec 26 19:34:04 1999
@@ -1,6 +1,6 @@
 /*****************************************************************************
  *
- *      ESS Maestro/Maestro-2/Maestro-2E driver for Linux 2.2.x
+ *      ESS Maestro/Maestro-2/Maestro-2E driver for Linux 2.[23].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
@@ -28,25 +28,25 @@
  *	proprietors of Hack Central for fine lodging.
  *
  *  Supported devices:
- *  /dev/dsp0-7    standard /dev/dsp device, (mostly) OSS compatible
+ *  /dev/dsp0-3    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
+ *	codec or 2.  In the Maestro we have the APUs, the ASSP, 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 loth
+ *	APUs.  The ASSP is a wacky DSP like device that ESS is loth
  *	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 initialization differences.
+ *	the ASSP, and initialization differences.
  *
  *  Driver Operation
  *
@@ -55,25 +55,19 @@
  *	/dev/dsp? device.  2 channels for output, and 4 channels for
  *	input.
  *
- *	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.
+ *	Each APU can do a number of things, but we only really use
+ *	3 basic functions.  For playback we use them to convert PCM
+ *	data fetched over PCI by the wavecahche into analog data that
+ *	is handed to the codec.  One APU for mono, and a pair for stereo.
+ *	When in stereo, the combination of smarts in the APU and Wavecache
+ *	decide which wavecache gets the left or right channel.
  *
- *	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.
- *
- *	This also pollutes the recording paths as well.  We have to use
- *	2 L/R incoming APUs that are fixed at 16bit/48khz.  We then pipe
- * 	these through 2 rate converion apus that mix them down to the
- * 	requested frequency and write them to memory through the wavecache.
- *	We also apparently need a 512byte region thats used as temp space 
- *	between the incoming APUs and the rate converters.
+ *	For record we still use the old overly mono system.  For each in
+ *	coming channel the data comes in from the codec, through a 'input'
+ *	APU, through another rate converter APU, and then into memory via
+ *	the wavecache and PCI.  If its stereo, we mash it back into LRLR in
+ *	software.  The pass between the 2 APUs is supposedly what requires us
+ *	to have a 512 byte buffer sitting around in wavecache/memory.
  *
  *	The wavecache makes our life even more fun.  First off, it can
  *	only address the first 28 bits of PCI address space, making it
@@ -113,9 +107,19 @@
  *	similar.
  *	
  * History
+ *  v0.13 - Nov 18 1999 - Zach Brown <zab@redhat.com>
+ *	fix nec Versas?  man would that be cool.
+ *  v0.12 - Nov 12 1999 - Zach Brown <zab@redhat.com>
+ *	brown bag volume max fix..
+ *  v0.11 - Nov 11 1999 - Zach Brown <zab@redhat.com>
+ *	use proper stereo apu decoding, mmap/write should work.
+ *	make volume sliders more useful, tweak rate calculation.
+ *	fix lame 8bit format reporting bug.  duh. apm apu saving buglet also
+ *	fix maestro 1 clock freq "bug", remove pt101 support
  *  v0.10 - Oct 28 1999 - Zach Brown <zab@redhat.com>
  *	aha, so, sometimes the WP writes a status word to offset 0
  *	  from one of the PCMBARs.  rearrange allocation accordingly..
+ *	  cheers again to Eric for being a good hacker in investigating this.
  *	Jeroen Hoogervorst submits 7500 fix out of nowhere.  yay.  :)
  *  v0.09 - Oct 23 1999 - Zach Brown <zab@redhat.com>
  *	added APM support.
@@ -159,16 +163,12 @@
  *
  * TODO
  *	some people get indir reg timeouts?
- *	anyone have a pt101 codec?
- *	mmap(), but beware stereo encoding nastiness.
- *	actually post pci writes
  *	fix bob frequency
+ *	endianness
  *	do smart things with ac97 2.0 bits.
- *	ugh.. non aligned writes in the middle of a data stream.. ugh
- *	sort out 0x34->0x36 crap in init
  *	docking and dual codecs and 978?
- *	pcm_sync?
- *	actually use LRLR
+ *	leave 54->61 open
+ *	resolve 2.3/2.2 stuff
  *
  *	it also would be fun to have a mode that would not use pci dma at all
  *	but would copy into the wavecache on board memory and use that 
@@ -189,12 +189,14 @@
  #define SILLY_INIT_SEM(SEM) SEM=MUTEX;
  #define init_waitqueue_head init_waitqueue
  #define SILLY_MAKE_INIT(FUNC) __initfunc(FUNC)
+ #define SILLY_OFFSET(VMA) ((VMA)->vm_offset)
 
 #else
 
  #define SILLY_PCI_BASE_ADDRESS(PCIDEV) (PCIDEV->resource[0].start)
  #define SILLY_INIT_SEM(SEM) init_MUTEX(&SEM)
  #define SILLY_MAKE_INIT(FUNC) __init FUNC
+ #define SILLY_OFFSET(VMA) ((VMA)->vm_pgoff)
 
 #endif
 
@@ -241,7 +243,7 @@
 #endif
 
 /* --------------------------------------------------------------------- */
-#define DRIVER_VERSION "0.10"
+#define DRIVER_VERSION "0.13"
 
 #ifndef PCI_VENDOR_ESS
 #define PCI_VENDOR_ESS			0x125D
@@ -256,6 +258,10 @@
 
 #define ESS_CHAN_HARD		0x100
 
+/* NEC Versas ? */
+#define NEC_VERSA_SUBID1	0x80581033
+#define NEC_VERSA_SUBID2	0x803c1033
+
 
 /* changed so that I could actually find all the
 	references and fix them up.  its a little more readable now. */
@@ -271,8 +277,8 @@
 #define DAC_RUNNING		1
 #define ADC_RUNNING		2
 
-#define MAX_DSP_ORDER	3
-#define MAX_DSPS	(1<<3)
+#define MAX_DSP_ORDER	2
+#define MAX_DSPS	(1<<MAX_DSP_ORDER)
 #define NR_DSPS		(1<<dsps_order)
 #define NR_IDRS		32
 
@@ -296,6 +302,11 @@
 	[TYPE_MAESTRO2E] = "ESS Maestro 2E"
 };
 
+static int clock_freq[]={
+	[TYPE_MAESTRO] = (49152000L / 1024L),
+	[TYPE_MAESTRO2] = (50000000L / 1024L),
+	[TYPE_MAESTRO2E] = (50000000L / 1024L)
+};
 
 /* --------------------------------------------------------------------- */
 
@@ -521,7 +532,7 @@
 	[SOUND_MIXER_BASS] =            0x3232,
 	[SOUND_MIXER_TREBLE] =          0x3232,
 	[SOUND_MIXER_SPEAKER] =         0x3232,
-	[SOUND_MIXER_MIC] =     0x3232,
+	[SOUND_MIXER_MIC] =     0x8000, /* annoying */
 	[SOUND_MIXER_LINE] =    0x3232,
 	[SOUND_MIXER_CD] =      0x3232,
 	[SOUND_MIXER_VIDEO] =   0x3232,
@@ -599,6 +610,23 @@
 /* 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 */
+	
+/* linear scale -> log */
+unsigned char lin2log[101] = 
+{
+0, 0 , 15 , 23 , 30 , 34 , 38 , 42 , 45 , 47 ,
+50 , 52 , 53 , 55 , 57 , 58 , 60 , 61 , 62 ,
+63 , 65 , 66 , 67 , 68 , 69 , 69 , 70 , 71 ,
+72 , 73 , 73 , 74 , 75 , 75 , 76 , 77 , 77 ,
+78 , 78 , 79 , 80 , 80 , 81 , 81 , 82 , 82 ,
+83 , 83 , 84 , 84 , 84 , 85 , 85 , 86 , 86 ,
+87 , 87 , 87 , 88 , 88 , 88 , 89 , 89 , 89 ,
+90 , 90 , 90 , 91 , 91 , 91 , 92 , 92 , 92 ,
+93 , 93 , 93 , 94 , 94 , 94 , 94 , 95 , 95 ,
+95 , 95 , 96 , 96 , 96 , 96 , 97 , 97 , 97 ,
+97 , 98 , 98 , 98 , 98 , 99 , 99 , 99 , 99 , 99 
+};
+
 static void ac97_write_mixer(struct ess_card *card,int mixer, unsigned int left, unsigned int right)
 {
 	u16 val=0;
@@ -614,12 +642,13 @@
 			right = (right * mh->scale) / 100;
 			left = (left * mh->scale) / 100;
 			if ((left == 0) && (right == 0))
-				val |= 0x8000; 
-		} else {
-			right = ((100 - right) * mh->scale) / 100;
-			left = ((100 - left) * mh->scale) / 100;
-			if((left == mh->scale) && (right == mh->scale))
 				val |= 0x8000;
+		} else {
+			/* log conversion for the stereo controls */
+			if((left == 0) && (right == 0))
+				val = 0x8000;
+			right = ((100 - lin2log[right]) * mh->scale) / 100;
+			left = ((100 - lin2log[left]) * mh->scale) / 100;
 		}
 
 		val |= (left << 8) | right;
@@ -772,6 +801,8 @@
 	return 0;
 }
 
+#if 0  /* there has been 1 person on the planet with a pt101 that we
+	know of.  If they care, they can put this back in :) */
 static u16 maestro_pt101_init(struct ess_card *card,int iobase)
 {
 	printk(KERN_INFO "maestro: PT101 Codec detected, initializing but _not_ installing mixer device.\n");
@@ -792,6 +823,7 @@
 	maestro_ac97_set(iobase, 0x0E, 0x801F);
 	return 0;
 }
+#endif
 
 /* this is very magic, and very slow.. */
 static void 
@@ -799,6 +831,7 @@
 {
 	u16 save_68;
 	u16 w;
+	u32 vend;
 
 	outw( inw(ioaddr + 0x38) & 0xfffc, ioaddr + 0x38);
 	outw( inw(ioaddr + 0x3a) & 0xfffc, ioaddr + 0x3a);
@@ -808,6 +841,7 @@
 	outw(0x0000,  ioaddr+0x36);
 	save_68 = inw(ioaddr+0x68);
 	pci_read_config_word(pcidev, 0x58, &w);	/* something magical with gpio and bus arb. */
+	pci_read_config_dword(pcidev, PCI_SUBSYSTEM_VENDOR_ID, &vend);
 	if( w & 0x1)
 		save_68 |= 0x10;
 	outw(0xfffe, ioaddr + 0x64);	/* tickly gpio 0.. */
@@ -861,6 +895,12 @@
 		}
 	}
 #endif
+	if ( vend == NEC_VERSA_SUBID1 || vend == NEC_VERSA_SUBID2) {
+		/* turn on external amp? */
+		outw(0xf9ff, ioaddr + 0x64);
+		outw(inw(ioaddr+0x68) | 0x600, ioaddr + 0x68);
+		outw(0x0209, ioaddr + 0x60);
+	}
 }
 /*
  *	Indirect register access. Not all registers are readable so we
@@ -1065,13 +1105,12 @@
 /* sets the play formats of these apus, should be passed the already shifted format */
 static void set_apu_fmt(struct ess_state *s, int apu, int mode)
 {
-	if(mode&ESS_FMT_16BIT) { 
-		s->apu_mode[apu] = 0x10;
-		s->apu_mode[apu+1] = 0x10;
-	} else {
-		s->apu_mode[apu] = 0x30;
-		s->apu_mode[apu+1] = 0x30;
-	}
+	int apu_fmt = 0x10;
+
+	if(!(mode&ESS_FMT_16BIT)) apu_fmt+=0x20; 
+	if((mode&ESS_FMT_STEREO)) apu_fmt+=0x10; 
+	s->apu_mode[apu]   = apu_fmt;
+	s->apu_mode[apu+1] = apu_fmt;
 }
 
 /* this only fixes the output apu mode to be later set by start_dac and
@@ -1082,18 +1121,21 @@
 	set_apu_fmt(s, 0, (s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_MASK);
 }
 
-static u16 compute_rate(u32 freq)
+/* this is off by a little bit.. */
+static u32 compute_rate(struct ess_state *s, u32 freq)
 {
-	if(freq==48000)
-		return 0xFFFF;
-	freq<<=16;
-	freq/=48000;
-	return freq;
+	u32 clock = clock_freq[s->card->card_type];     
+
+	if (freq == 48000) return 0x10000;
+
+	return ((freq / clock) <<16 )+  
+		(((freq % clock) << 16) / clock);
 }
 
-static void set_dac_rate(struct ess_state *s, unsigned rate)
+static void set_dac_rate(struct ess_state *s, unsigned int rate)
 {
 	u32 freq;
+	int fmt = (s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_MASK;
 
 	if (rate > 48000)
 		rate = 48000;
@@ -1102,12 +1144,12 @@
 
 	s->ratedac = rate;
 
-	if(!((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_16BIT))
-		rate >>= 1; /* who knows */
+	if(! (fmt & ESS_FMT_16BIT) && !(fmt & ESS_FMT_STEREO))
+		rate >>= 1;
 
 /*	M_printk("computing dac rate %d with mode %d\n",rate,s->fmt);*/
 
-	freq = compute_rate(rate);
+	freq = compute_rate(s, rate);
 	
 	/* Load the frequency, turn on 6dB */
 	apu_set_register(s, 0, 2,(apu_get_register(s, 0, 2)&0x00FF)|
@@ -1122,14 +1164,15 @@
 {
 	u32 freq;
 
-	if (rate > 48000)
-		rate = 48000;
+	/* Sample Rate conversion APUs don't like 0x10000 for their rate */
+	if (rate > 47999)
+		rate = 47999;
 	if (rate < 4000)
 		rate = 4000;
 
 	s->rateadc = rate;
 
-	freq = compute_rate(rate);
+	freq = compute_rate(s, rate);
 	
 	/* Load the frequency, turn on 6dB */
 	apu_set_register(s, 2, 2,(apu_get_register(s, 2, 2)&0x00FF)|
@@ -1234,27 +1277,21 @@
 	/* 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_FMT_STEREO) {
-		size >>=1; 
 		high_apu++;
+		/* only 16/stereo gets size divided */
+		if(mode&ESS_FMT_16BIT)
+			size>>=1;
 	}
 	
 	for(channel=0; channel <= high_apu; channel++)
 	{
-		int i;
-		
-		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);
+		pa = virt_to_bus(buffer);
 
 		/* set the wavecache control reg */
 		tmpval = (pa - 0x10) & 0xFFF8;
-		if(!(mode & 2)) tmpval |= 4; /* 8bit */ 
+		if(!(mode & ESS_FMT_16BIT)) tmpval |= 4;
+		if(mode & ESS_FMT_STEREO) tmpval |= 2;
 		ess->apu_base[channel]=tmpval;
 		wave_set_register(ess, ess->apu[channel]<<3, tmpval);
 		
@@ -1262,14 +1299,17 @@
 		pa>>=1; /* words */
 		
 		/* base offset of dma calcs when reading the pointer
-			on this left one */
+			on the left one */
 		if(!channel) ess->dma_dac.base = pa&0xFFFF;
 		
 		pa|=0x00400000;			/* System RAM */
-		
-		/* Begin loading the APU */		
-		for(i=0;i<15;i++)		/* clear all PBRs */
-			apu_set_register(ess, channel, i, 0x0000);
+
+		/* XXX the 16bit here might not be needed.. */
+		if((mode & ESS_FMT_STEREO) && (mode & ESS_FMT_16BIT)) {
+			if(channel) 
+				pa|=0x00800000;			/* Stereo */
+			pa>>=1;
+		}
 			
 /* XXX think about endianess when writing these registers */
 		M_printk("maestro: ess_play_setup: APU[%d] pa = 0x%x\n", ess->apu[channel], pa);
@@ -1290,16 +1330,17 @@
 		/* dma on, no envelopes, filter to all 1s) */
 		apu_set_register(ess, channel, 0, 0x400F);
 		
-		if(mode&ESS_FMT_STEREO)
-			/* set panning: left or right */
-			apu_set_register(ess, channel, 10, 0x8F00 | (channel ? 0x10 : 0));
-		else
-			apu_set_register(ess, channel, 10, 0x8F08);
-
 		if(mode&ESS_FMT_16BIT)
 			ess->apu_mode[channel]=0x10;
 		else
 			ess->apu_mode[channel]=0x30;
+
+		if(mode&ESS_FMT_STEREO) {
+			/* set panning: left or right */
+			apu_set_register(ess, channel, 10, 0x8F00 | (channel ? 0x10 : 0));
+			ess->apu_mode[channel] += 0x10;
+		} else
+			apu_set_register(ess, channel, 10, 0x8F08);
 	}
 	
 	/* clear WP interupts */
@@ -1660,29 +1701,20 @@
 clear_advance(struct ess_state *s)
 {
 	unsigned char c = ((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_16BIT) ? 0 : 0x80;
+	
 	unsigned char *buf = s->dma_dac.rawbuf;
 	unsigned bsize = s->dma_dac.dmasize;
-	/* swptr is always in bytes as read from an apu.. */
 	unsigned bptr = s->dma_dac.swptr;
 	unsigned len = s->dma_dac.fragsize;
-	int i=1;
-
-	if((s->fmt >> ESS_DAC_SHIFT)  & ESS_FMT_STEREO) {
-		i++;
-		bsize >>=1;
-	}
-		
-	for ( ;i; i-- , buf += bsize) {
-
-		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);
+	
+	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! */
@@ -1725,8 +1757,13 @@
 	}
 	/* update DAC pointer */
 	if (s->dma_dac.ready) {
-		/* this is so gross.  */
-		hwptr = (/*s->dma_dac.dmasize -*/ get_dmaa(s)) % s->dma_dac.dmasize; 
+		hwptr = get_dmaa(s) % s->dma_dac.dmasize; 
+		/* the apu only reports the length it has seen, not the
+			length of the memory that has been used (the WP
+			knows that */
+		if ( ((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_MASK) == (ESS_FMT_STEREO|ESS_FMT_16BIT))
+			hwptr<<=1;
+
 		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;
@@ -2190,42 +2227,6 @@
 	return ret;
 }
 
-/* god this is gross..*/
-/* again, the mode passed is shifted/masked */
-static 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.  */
-
-	unsigned char *so,*left,*right;
-	int i;
-
-	so = tmp_buffer;
-	left = real_buffer + offset;
-	right = real_buffer + bufsize/2 + offset;
-
-	if(mode & ESS_FMT_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)
 {
@@ -2233,9 +2234,7 @@
 	ssize_t ret;
 	unsigned long flags;
 	unsigned swptr;
-	unsigned char *splitbuf = NULL;
 	int cnt;
-	int mode = (s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_MASK;
 	
 	VALIDATE_STATE(s);
 	if (ppos != &file->f_pos)
@@ -2246,9 +2245,6 @@
 		return ret;
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
-	/* XXX be more clever than this.. */
-	if (!(splitbuf = kmalloc(count,GFP_KERNEL)))
-		return -ENOMEM; 
 	ret = 0;
 
 	calc_bob_rate(s);
@@ -2262,12 +2258,8 @@
 		}
 		swptr = s->dma_dac.swptr;
 
-		if(mode & ESS_FMT_STEREO) {
-			/* in stereo we have the 'dual' buffers.. */
-			cnt = ((s->dma_dac.dmasize/2)-swptr)*2;
-		} else {
-			cnt = s->dma_dac.dmasize-swptr;
-		}
+		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;
 
@@ -2276,10 +2268,6 @@
 		if (cnt > count)
 			cnt = count;
 
-		/* our goofball stereo splitter can only deal in mults of 4 */
-		if (cnt > 0) 
-			cnt &= ~3;
-
 		if (cnt <= 0) {
 			start_dac(s);
 			if (file->f_flags & O_NONBLOCK) {
@@ -2309,26 +2297,13 @@
 			}
 			continue;
 		}
-		if(mode & ESS_FMT_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,
-				mode);
-		} else {
-			if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
-				if (!ret) ret = -EFAULT;
-				goto return_free;
-			}
+		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
+			if (!ret) ret = -EFAULT;
+			goto return_free;
 		}
 
-		if(mode & ESS_FMT_STEREO) {
-			/* again with the weird pointer magic */
-			swptr = (swptr + (cnt/2)) % (s->dma_dac.dmasize/2);
-		} else {
-			swptr = (swptr + cnt) % s->dma_dac.dmasize;
-		}
+		swptr = (swptr + cnt) % s->dma_dac.dmasize;
+
 		spin_lock_irqsave(&s->lock, flags);
 		s->dma_dac.swptr = swptr;
 		s->dma_dac.count += cnt;
@@ -2340,7 +2315,6 @@
 		start_dac(s);
 	}
 return_free:
-	if (splitbuf) kfree(splitbuf);
 	return ret;
 }
 
@@ -2374,8 +2348,6 @@
 	return mask;
 }
 
-/* this needs to be fixed to deal with the dual 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;
@@ -2388,13 +2360,18 @@
 		if ((ret = prog_dmabuf(s, 1)) != 0)
 			return ret;
 		db = &s->dma_dac;
-	} else if (vma->vm_flags & VM_READ) {
+	} else 
+#if 0
+	/* if we can have the wp/wc do the combining
+		we can turn this back on.  */
+	      if (vma->vm_flags & VM_READ) {
 		if ((ret = prog_dmabuf(s, 0)) != 0)
 			return ret;
 		db = &s->dma_adc;
-	} else 
+	} else  
+#endif
 		return -EINVAL;
-	if (vma->vm_pgofft != 0)
+	if (SILLY_OFFSET(vma) != 0)
 		return -EINVAL;
 	size = vma->vm_end - vma->vm_start;
 	if (size > (PAGE_SIZE << db->buforder))
@@ -2404,7 +2381,6 @@
 	db->mapped = 1;
 	return 0;
 }
-#endif
 
 static int ess_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
@@ -2434,7 +2410,7 @@
 		return 0;
 
 	case SNDCTL_DSP_GETCAPS:
-		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER /*| DSP_CAP_MMAP*/, (int *)arg);
+		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg);
 		
         case SNDCTL_DSP_RESET:
 		if (file->f_mode & FMODE_WRITE) {
@@ -2515,7 +2491,7 @@
 					   : (ESS_FMT_STEREO << ESS_DAC_SHIFT))) ? 2 : 1, (int *)arg);
 		
 	case SNDCTL_DSP_GETFMTS: /* Returns a mask */
-                return put_user(AFMT_S8|AFMT_S16_LE, (int *)arg);
+                return put_user(AFMT_U8|AFMT_S16_LE, (int *)arg);
 		
 	case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
 		get_user_ret(val, (int *)arg, -EFAULT);
@@ -2548,7 +2524,7 @@
 			(ESS_FMT_16BIT << ESS_ADC_SHIFT) 
 			: (ESS_FMT_16BIT << ESS_DAC_SHIFT))) ? 
 				AFMT_S16_LE : 
-				AFMT_S8, 
+				AFMT_U8, 
 			(int *)arg);
 		
 	case SNDCTL_DSP_POST:
@@ -2938,7 +2914,7 @@
 	NULL,  /* readdir */
 	&ess_poll,
 	&ess_ioctl,
-	NULL,	/* XXX &ess_mmap, */
+	&ess_mmap,
 	&ess_open,
 	NULL,	/* flush */
 	&ess_release,
@@ -3000,7 +2976,7 @@
 	w&=~(1<<7);		/* HWV off */
 	w&=~(1<<6);		/* Debounce off */
 	w&=~(1<<5);		/* GPIO 4:5 */
-	w|= (1<<4);             /* Disconnect from the CHI.  Enabling this in made a dell 7500 work. */
+	w|= (1<<4);             /* Disconnect from the CHI.  Enabling this made a dell 7500 work. */
 	w&=~(1<<3);		/* IDMA off (undocumented) */
 	w&=~(1<<2);		/* MIDI fix off (undoc) */
 	w&=~(1<<1);		/* reserved, always write 0 */
@@ -3303,7 +3279,8 @@
 	maestro_config(card);
 
 	if(maestro_ac97_get(iobase, 0x00)==0x0080) {
-		maestro_pt101_init(card,iobase);
+		printk(KERN_ERR "maestro: my goodness!  you seem to have a pt101 codec, which is quite rare.\n"
+				"\tyou should tell someone about this.\n");
 	} else {
 		maestro_ac97_init(card,iobase);
 	}
@@ -3451,7 +3428,7 @@
 }
 
 static int 
-maestro_apm_suspend(void)
+maestro_suspend(void)
 {
 	struct ess_card *card;
 	unsigned long flags;
@@ -3474,7 +3451,7 @@
 			stop_dac(s);
 			stop_adc(s);
 			for(j=0;j<6;j++) 
-				card->apu_map[s->apu[i]][5]=apu_get_register(s,i,5);
+				card->apu_map[s->apu[j]][5]=apu_get_register(s,j,5);
 
 		}
 
@@ -3491,7 +3468,7 @@
 	return 0;
 }
 static int 
-maestro_apm_resume(void)
+maestro_resume(void)
 {
 	struct ess_card *card;
 	unsigned long flags;
@@ -3565,11 +3542,11 @@
 	case APM_SYS_SUSPEND: 
 	case APM_CRITICAL_SUSPEND: 
 	case APM_USER_SUSPEND: 
-		maestro_apm_suspend();break;
+		maestro_suspend();break;
 	case APM_NORMAL_RESUME: 
 	case APM_CRITICAL_RESUME: 
 	case APM_STANDBY_RESUME: 
-		maestro_apm_resume();break;
+		maestro_resume();break;
 	default: break;
 	}
 
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/.indent.pro linux/drivers/usb/.indent.pro
--- v2.3.34/linux/drivers/usb/.indent.pro	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/.indent.pro	Wed Dec 31 16:00:00 1969
@@ -1 +0,0 @@
--i8 -br -nce -npsl 
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/Config.in linux/drivers/usb/Config.in
--- v2.3.34/linux/drivers/usb/Config.in	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/Config.in	Mon Dec 27 14:01:53 1999
@@ -7,32 +7,32 @@
 tristate 'Support for USB' CONFIG_USB
 if [ ! "$CONFIG_USB" = "n" ]; then
 comment 'USB Controllers'
-   dep_tristate '  UHCI (Intel PIIX4 and others) support' CONFIG_USB_UHCI \
+   dep_tristate '  UHCI (Intel PIIX4, VIA, and others) support' CONFIG_USB_UHCI \
 	$CONFIG_USB
 
-   dep_tristate '  OHCI-HCD (compaq and some others) support' \
+   dep_tristate '  OHCI-HCD (Compaq, iMacs, OPTi, SiS, and others) support' \
 		CONFIG_USB_OHCI_HCD $CONFIG_USB
 
 comment 'Miscellaneous USB options'
    if [ "$CONFIG_PROC_FS" != "n" ]; then
       bool '  /proc/bus/usb support' CONFIG_USB_PROC
    fi
-   dep_tristate '  EZUSB Firmware downloader' CONFIG_USB_EZUSB $CONFIG_USB
 
 comment 'USB Devices'
-   dep_tristate '  USB mouse support' CONFIG_USB_MOUSE $CONFIG_USB
-   dep_tristate '  USB HP scanner support' CONFIG_USB_HP_SCANNER $CONFIG_USB
    dep_tristate '  USB keyboard support' CONFIG_USB_KBD $CONFIG_USB
+   dep_tristate '  USB mouse support' CONFIG_USB_MOUSE $CONFIG_USB
+   dep_tristate '  USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
+   dep_tristate '  USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
    dep_tristate '  USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB
    dep_tristate '  USB Communications Device Class (ACM) support' CONFIG_USB_ACM $CONFIG_USB
-   dep_tristate '  USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
-   dep_tristate '  USB Belkin and Peracom serial support' CONFIG_USB_SERIAL $CONFIG_USB
+   dep_tristate '  USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
    dep_tristate '  USB CPiA Camera support' CONFIG_USB_CPIA $CONFIG_USB
    dep_tristate '  USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
-   dep_tristate '  USB SCSI Support' CONFIG_USB_SCSI $CONFIG_USB
+   dep_tristate '  USB SCSI (mass storage) support' CONFIG_USB_SCSI $CONFIG_USB
    if [ "$CONFIG_USB_SCSI" != "n" ]; then
       bool '    USB SCSI verbose debug' CONFIG_USB_SCSI_DEBUG
    fi
+   dep_tristate '  EZUSB Firmware downloader' CONFIG_USB_EZUSB $CONFIG_USB
    dep_tristate '  USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
    dep_tristate '  DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB 
 fi
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/Makefile linux/drivers/usb/Makefile
--- v2.3.34/linux/drivers/usb/Makefile	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/Makefile	Mon Dec 27 14:02:31 1999
@@ -53,15 +53,13 @@
 endif
 ifeq ($(CONFIG_USB_MOUSE),m)
   M_OBJS += mouse.o	
-  MI_OBJS += mouse.o
 endif
 
-ifeq ($(CONFIG_USB_HP_SCANNER),y)
-  L_OBJS += hp_scanner.o
+ifeq ($(CONFIG_USB_SCANNER),y)
+  L_OBJS += scanner.o
 endif
-ifeq ($(CONFIG_USB_HP_SCANNER),m)
-  M_OBJS  +=hp_scanner.o
-  MI_OBJS +=hp_scanner.o
+ifeq ($(CONFIG_USB_SCANNER),m)
+  M_OBJS  +=scanner.o
 endif
 
 ifeq ($(CONFIG_USB_ACM),y)
@@ -69,7 +67,6 @@
 endif
 ifeq ($(CONFIG_USB_ACM),m)
   M_OBJS += acm.o
-  MI_OBJS += acm.o
 endif
 
 ifeq ($(CONFIG_USB_PRINTER),y)
@@ -78,7 +75,6 @@
 
 ifeq ($(CONFIG_USB_PRINTER),m)
   M_OBJS += printer.o
-  MI_OBJS += printer.o  
 endif
 
 ifeq ($(CONFIG_USB_SERIAL),y)
@@ -87,7 +83,6 @@
 
 ifeq ($(CONFIG_USB_SERIAL),m)
   M_OBJS += usb-serial.o
-  MI_OBJS += usb-serial.o  
 endif
 
 ifneq ($(CONFIG_ADB_KEYBOARD),y)
@@ -111,7 +106,6 @@
 
 ifeq ($(CONFIG_USB_AUDIO),m)
   M_OBJS += audio.o
-  MI_OBJS += audio.o
 endif
 
 ifeq ($(CONFIG_USB_CPIA),y)
@@ -120,7 +114,6 @@
 
 ifeq ($(CONFIG_USB_CPIA),m)
   M_OBJS += cpia.o
-  MI_OBJS += cpia.o
 endif
 
 ifeq ($(CONFIG_USB_DC2XX),y)
@@ -128,7 +121,6 @@
 endif
 ifeq ($(CONFIG_USB_DC2XX),m)
   M_OBJS += dc2xx.o
-  MI_OBJS += dc2xx.o
 endif
 
 ifeq ($(CONFIG_USB_SCSI),y)
@@ -152,7 +144,6 @@
 
 ifeq ($(CONFIG_USB_EZUSB),m)
   M_OBJS += ezusb.o
-  MI_OBJS += ezusb.o
 endif
 
 ifeq ($(CONFIG_USB_USS720),y)
@@ -161,7 +152,6 @@
 
 ifeq ($(CONFIG_USB_USS720),m)
   M_OBJS += uss720.o
-  MI_OBJS += uss720.o
 endif
 
 ifeq ($(CONFIG_USB_DABUSB),y)
@@ -170,7 +160,6 @@
 
 ifeq ($(CONFIG_USB_DABUSB),m)
   M_OBJS += dabusb.o
-  MI_OBJS += dabusb.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/README.hp_scanner linux/drivers/usb/README.hp_scanner
--- v2.3.34/linux/drivers/usb/README.hp_scanner	Tue Sep  7 12:14:07 1999
+++ linux/drivers/usb/README.hp_scanner	Wed Dec 31 16:00:00 1969
@@ -1,59 +0,0 @@
-August 30, 1999
-
-
-Overview
-
-This README will address issues regarding how to configure the kernel
-to access a USB HP Scanner.  The scanner should support the Scanner
-Control Language (SCL) so that applications such as SANE can access it
-properly.  Refer to the document README.hp_scanner_sane for guidance
-on how to configure SANE to use the USB HP Scanner.
-
-
-Requirements
-
-A host with a USB port.  Ideally, either a UHCI (Intel) or OHCI
-(Compaq and others) hardware port should work.  However, I've only
-been able to really use an OHCI controller.  I did have access to a
-system with a UHCI controller but some very limited testing did not
-produce satisfactory results.
-
-A Linux kernel with USB support (preferably 2.3.15+).
-
-A Linux kernel with USB HP Scanner support.
-
-
-Configuration
-
-Add both USB controller support and USB HP Scanner support using `make
-menuconfig`.  If you decide to use the ohci-hcd driver, don't forget
-to add HUB support.  Compile and install the modules.  Testing was
-performed only as modules, YMMV.
-
-Add a device for the USB scanner: `mknod /dev/usbscanner c 16 1`
-
-Set appropriate permissions for /dev/usbscanner.  Both read and write
-permissions are needed for proper operation.
-
-Load the appropriate modules:
-
-  OHCI:
-
-    modprobe usb-ohci
-    modprobe hp_scanner
-
-  OHCI-HCD:
-    modprobe usb-ohci-hcd
-    modprobe hub
-    modprobe hp_scanner
-
-That's it.  SANE should now be able to access the device.  
-
-There is a small test program (hp_scan.c) that can be used to test the
-scanner device.  It's purpose is to test the driver(s) without having
-to retrieve/configure SANE.  Hp_scan.c will scan the entire bed and
-put the output into a file called out.dat in the current directory.
-The data in the file is raw data.
-
-David /\/elson
-dnelson@jump.net
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/README.hp_scanner_sane linux/drivers/usb/README.hp_scanner_sane
--- v2.3.34/linux/drivers/usb/README.hp_scanner_sane	Tue Sep  7 12:14:07 1999
+++ linux/drivers/usb/README.hp_scanner_sane	Wed Dec 31 16:00:00 1969
@@ -1,67 +0,0 @@
-August 30, 1999
-
-NOTE: This is all VERY alpha.  Use at your own risk.  There is no
-warranty expressed nor implied.
-
-
-Introduction
-
-This document will hopefully provide enough info on how to get SANE
-working with a Hewlett Packard USB capable scanner using the USB
-interface.  The majority of HP Scanners support the Scanner Control
-Language (SCL) which is both published by HP and supported by SANE.
-The only HP Scanner that I'm aware of that does not support SCL is the
-4200C.  All other HP scanners with USB interfaces should work (4100C,
-5200C, 6200C).  Of course as HP releases new scanners this information
-may change.
-
-
-Requirements
-
-In order to get this running you'll need USB support in your kernel in
-addition to USB HP Scanner support.  Please refer to README.hp_scanner
-for issues pertaining to Linux USB and USB HP Scanner support.
-
-An installed version of SANE which is available from
-http://www.mostang.com/sane/.  Testing has been performed using
-version SANE-1.0.1.  For instructions on building and installing SANE,
-refer to the various README files within the distribution.
-
-
-Ok, so what do I do?
-
-NOTE: $INSTALL_DIR is the location where SANE was installed.  It may
-be /usr/local, /usr, /opt or somewhere else.  If you don't know, ask
-your system administrator.
-
-1) Make sure that you have the libsane-hp.* libraries under the
-$INSTALL_DIR/lib/sane/ directory.
-
-2) Under the directory $INSTALL_DIR/etc/sane.d/ edit the following
-files: dll.conf, hp.conf.
-
-  dll.conf:  Make sure that the 'hp' entry is present and uncommented.
-
-  hp.conf: This should contain two lines:
-
-    option connect-device
-    /dev/usbscanner
-
-3) You should now be able to use SANE (xscanimage or scanimage).
-
-Don't forget to read any relevant man pages regarding the usage of
-SANE.  If you have other entries uncommented in dll.conf, you my have
-to specify the device to (x)scanimage.  The xscanimage (1) man page
-has info on how to get 'The Gimp' to work with xscanimage.  Note that
-Gimp support must be compiled into SANE for it work.  If you are
-dealing with a RedHat system, you'll also need to install the
-gimp-devel rpm package.
-
-NOTE: Most of the time xscanimage will run without incident, then on
-the next invocation it'll core dump at different locations.  I don't
-know why yet and I don't have a work around either other than to try
-again.  But once you get it started, it'll scan without any problems
-(or at least it does for me).
-
-David /\/elson
-dnelson@jump.net
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/README.scanner linux/drivers/usb/README.scanner
--- v2.3.34/linux/drivers/usb/README.scanner	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/README.scanner	Mon Dec 27 14:01:53 1999
@@ -0,0 +1,231 @@
+Oct 19, 1999
+
+CHANGES
+
+- Ammended for linux-2.3.22+
+- Appended hp_scan.c to end of this README
+- Removed most references to HP
+
+
+OVERVIEW
+
+This README will address issues regarding how to configure the kernel
+to access a USB scanner.  Although the driver was originally conceived
+for USB HP scanners, it's general enough so that it can be used with
+other scanners.  Also, one can now pass the USB Vendor and
+Product ID's using module parameters for unknown scanners.  Refer to
+the document README.scanner_hp_sane for guidance on how to configure
+SANE to use a USB HP Scanner.
+
+
+ADDITIONAL INFORMATION
+
+http://www.linux-usb.org/
+http://www.dynamine.net/linux-usb/HOWTO/
+
+
+REQUIREMENTS
+
+A host with a USB port.  Ideally, either a UHCI (Intel) or OHCI
+(Compaq and others) hardware port should work.  However, I've only
+been able to really use an OHCI controller.  I did have access to a
+system with a UHCI controller but some very limited testing did not
+produce satisfactory results.  Luke Ordelmans
+<postbus@ordelmans.demon.nl> has reported success using the UHCI host
+controller with kernel 2.3.18 and a ChainTech motherboard.  Here
+lately I've been having better success with the ohci-hcd driver.  But
+since Linux USB support is still in a state of constant development
+that may change at a later date.  I am confident that eventually all
+the host contollers will perform without incident.
+
+A Linux kernel with USB support (preferably linux-2.3.18+)
+
+A Linux kernel with USB Scanner support.
+
+
+CONFIGURATION
+
+Using `make menuconfig` or your prefered method for configuring the
+kernel, select 'Support for USB', 'OHCI/OHCI-HCD/UHCI' depending on
+your hardware, 'USB hub support', and 'USB Scanner support'.  Compile
+and install the modules (you may need to execute `depmod -a` to update
+the module dependencies).  Testing was performed only as modules,
+YMMV.
+
+Add a device for the USB scanner:
+  linux-2.3.22 and above: `mknod /dev/usbscanner c 180 48`
+  linux-2.3.21 and below: `mknod /dev/usbscanner c 16 1`
+
+Set appropriate permissions for /dev/usbscanner (don't forget about
+group and world permissions).  Both read and write permissions are
+required for proper operation.
+
+Load the appropriate modules (if compiled as modules):
+
+  OHCI:
+    modprobe usb-ohci
+    modprobe scanner
+
+  OHCI-HCD:
+    modprobe usb-ohci-hcd
+    modprobe hub
+    modprobe scanner
+
+  UHCI:
+    modprobe usb-uhci
+    modprobe hub (don't know if this is required or not)
+    modprobe scanner
+
+That's it.  SANE should now be able to access the device.  
+
+There is a small test program (hp_scan.c -- appended below) that can
+be used to test the scanner device if it's an HP scanner that supports
+SCL.  Its purpose is to test the driver without having to
+retrieve/configure SANE.  Hp_scan.c will scan the entire bed and put
+the output into a file called 'out.dat' in the current directory.  The
+data in the file is raw data so it's not very useful for imaging.
+
+
+MODULE PARAMETERS
+
+If you have a device that wish to experiment with or try using this
+driver with, but the Vendor and Product ID's are not coded in, don't
+despair.  If the driver was compiled as a module, you can pass options
+to the driver.  Simply add 'options scanner vendor=0x####
+product=0x****' to the conf.modules/modules.conf file replacing the
+#'s and the *'s with the correct ID's.  The ID's can be retrieved from
+the messages file or using `cat /proc/bus/usb/devices` if USB /proc
+support was selected during kernel configuration.
+
+
+BUGS
+
+If you encounter any problems feel free to drop me an email.
+
+David /\/elson
+dnelson@jump.net
+http://www.jump.net/~dnelson
+
+--------------- snip -- hp_scan.c -- snip ---------------
+/*
+
+This is a really crude attempt at writing a short test program.  It's
+mostly only to be used to test connectivity with USB HP scanners that
+understand SCL.  Currently, the supported models are 4100C, 5200C,
+6200C, and the 6300C.  Note that the 4200C is *NOT* acceptable.
+
+Copyright (C) David E. Nelson <dnelson@jump.net>, 1999
+
+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 <stdio.h>
+#include <stdlib.h>
+#include <error.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/*
+   Gray Output produces about a 8945400 byte file.
+   Color Output produces a 26836200 byte file. 
+   
+   To compile: gcc -o hp_scan hp_scan.c
+*/
+
+// #define COLOR /* Undef to scan GrayScale */
+
+int send_cmd(int, const char *, int);
+int read_cmd(int, char *, int);
+
+int
+main(void) {
+
+	ssize_t cnt = 0, total_cnt = 0;
+
+	FILE *fpout;
+
+	int fp;
+	int data_size = 32768;
+
+	char *data;
+
+	static char reset_cmd[] = {'\x1b','E'};
+
+#ifdef COLOR
+	static char data_type_cmd[] = {'\x1b','*','a','5','T'}; /* Color */
+	static char data_width_cmd[] = {'\x1b','*','a','2','4','G'}; /* 24 Bit Color */
+#else
+	static char data_type_cmd[] = {'\x1b','*','a','4','T'}; /* Gray */
+	static char data_width_cmd[] = {'\x1b','*','a','8','G'}; /* 8 Bit Gray */
+#endif
+
+	static char query_cmd[] = {'\x1b', '*', 's', '2', '5', '7', 'E'};
+	static char start_scan_cmd[] = {'\x1b','*','f','0','S'};
+	
+	if(!(data=malloc(data_size))) {
+		perror("malloc failed");
+		exit (1);
+	}
+	
+	if((fp=open("/dev/usbscanner", O_RDWR)) < 0) {
+		perror("Unable to open scanner device");
+		exit (1);
+	}
+
+	if((fpout=fopen("out.dat", "w+")) == NULL) {
+		perror("Unable to open ouput file");
+		exit(1);
+	}
+
+	send_cmd(fp, reset_cmd, sizeof(reset_cmd));
+	send_cmd(fp, data_type_cmd, sizeof(data_type_cmd));
+	send_cmd(fp, data_width_cmd, sizeof(data_width_cmd));
+	send_cmd(fp, start_scan_cmd, sizeof(start_scan_cmd));
+
+	while ((cnt = read(fp, data, data_size)) > 0) {
+		printf("Read: %u\n", cnt); 
+		if(fwrite(data, sizeof(char), cnt, fpout) < 0) {
+			perror("Write to output file failed");
+			exit (1);
+		}
+		total_cnt += cnt;
+	}
+	if (cnt < 0) {
+		perror("Read from scanner failed");
+		exit (1);
+	}
+
+	printf("\nRead %lu bytes.\n", total_cnt);
+
+	send_cmd(fp, reset_cmd, sizeof(reset_cmd));
+
+	close(fp);
+	fclose(fpout);
+	return (0);
+}
+
+int
+send_cmd(int fp, const char * cmd, int length) {
+
+	int result;
+	int x;
+
+	if((result = write(fp, cmd, length)) != length) {
+		printf ("Write warning: %d bytes requested, %d written\n");
+	} else if (result < 0) {
+		perror ("send_cmd failure");
+		exit (1);
+	}
+	return (result);
+}
+	
+int
+read_cmd(int fp, char * response, int length) {
+
+	return read(fp, response, length);
+
+}
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/README.scanner_hp_sane linux/drivers/usb/README.scanner_hp_sane
--- v2.3.34/linux/drivers/usb/README.scanner_hp_sane	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/README.scanner_hp_sane	Mon Dec 27 14:01:53 1999
@@ -0,0 +1,69 @@
+Oct. 19, 1999
+
+CHANGES
+
+- Ammended for Linux-2.3.22+
+
+
+INTRODUCTION
+
+This document will hopefully provide enough info on how to get SANE
+working with a Hewlett Packard USB capable scanner using the USB
+interface.  The majority of HP Scanners support the Scanner Control
+Language (SCL) which is both published by HP and supported by SANE.
+The only HP Scanner that I'm aware of that does not support SCL is the
+4200C.  All other HP scanners with USB interfaces should work (4100C,
+5200C, 6200C, and 6300C).  Of course as HP releases new scanners this
+information may change.
+
+
+REQUIREMENTS
+
+In order to get this running you'll need USB support in your kernel in
+addition to USB Scanner support.  Please refer to README.scanner
+for issues pertaining to Linux USB and USB Scanner support.
+
+An installed version of SANE which is available from
+http://www.mostang.com/sane/.  Testing has been performed using
+version SANE-1.0.1.  For instructions on building and installing SANE,
+refer to the various README files within the SANE distribution.
+
+
+OK, I'VE INSTALLED SANE. SO WHAT DO I DO NOW?
+
+NOTE: $INSTALL_DIR is the location where SANE was installed.  It may
+be /usr/local, /usr, /opt or somewhere else.  If you don't know, ask
+your system administrator.
+
+1) Make sure that you have the libsane-hp.* libraries under the
+$INSTALL_DIR/lib/sane/ directory.  If you don't, then the HP backend
+was either not compiled or installed properly.
+
+2) Under the directory $INSTALL_DIR/etc/sane.d/ edit the following
+files: dll.conf, hp.conf.
+
+  dll.conf:  Make sure that the 'hp' entry is present and uncommented.
+
+  hp.conf: This should contain two lines:
+
+    /dev/usbscanner
+    option connect-device
+
+3) You should now be able to use SANE (xscanimage or scanimage).
+
+Don't forget to read any relevant man pages regarding the usage of
+SANE.  If you have other entries uncommented in dll.conf, you may have
+to specify the device to (x)scanimage.  Again, `man` is your friend.
+The xscanimage (1) man page has info on how to get 'The Gimp' to work
+with xscanimage.  Note that Gimp support must be compiled into SANE
+for it work.  If you are dealing with a RedHat system, this means that
+you'll also need to install the gimp-devel rpm package.
+
+NOTE: The issues regarding core dumping by (x)scanimage have (or seem
+to be thus far) been resolved with version 0.2+ of the USB scanner
+driver which should be available in linux-2.3.23.  If you notice
+otherwise, please contact me.
+
+David /\/elson
+dnelson@jump.net
+http://www.jump.net/~dnelson
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
--- v2.3.34/linux/drivers/usb/acm.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/acm.c	Mon Dec 27 14:03:38 1999
@@ -1,53 +1,34 @@
 /*
- * USB Abstract Control Model based on Brad Keryan's USB busmouse driver
+ * acm.c  Version 0.10
  *
- * (C) Copyright 1999 Armin Fuerst <armin.please@put.your.email.here.!!!!>
- * (C) Copyright 1999 Pavel Machek <pavel@suse.cz>
- * (C) Copyright 1999 Johannes Erdfelt <jerdfelt@valinux.com>
+ * Copyright (c) 1999 Armin Fuerst	<fuerst@in.tum.de>
+ * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
+ * Copyright (c) 1999 Johannes Erdfelt	<jerdfelt@valinux.com>
+ * Copyright (c) 1999 Vojtech Pavlik	<vojtech@suse.cz>
  *
- * version 0.8: Fixed endianity bug, some cleanups. I really hate to have
- * half of driver in form if (...) { info("x"); return y; }
- * 						Pavel Machek <pavel@suse.cz>
+ * USB Abstract Control Model driver for USB modems and ISDN adapters
  *
- * version 0.7: Added usb flow control. Fixed bug in uhci.c (what idiot
- * wrote this code? ...Oops that was me). Fixed module cleanup. Did some
- * testing at 3Com => zmodem uload+download works, pppd had trouble but
- * seems to work now. Changed Menuconfig texts "Communications Device
- * Class (ACM)" might be a bit more intuitive. Ported to 2.3.13-1 prepatch.
- * (2/8/99)
+ * Sponsored by SuSE
  *
- * version 0.6: Modularized driver, added disconnect code, improved
- * assignment of device to tty minor number.
- * (21/7/99)
- *
- * version 0.5: Driver now generates a tty instead of a simple character
- * device. Moved async bulk transfer to 2.3.10 kernel version. fixed a bug
- * in uhci_td_allocate. Commenetd out getstringtable which causes crash.
- * (13/7/99)
- *
- * version 0.4: Small fixes in the FIFO, cleanup. Updated Bulk transfer in
- * uhci.c. Should have the correct interface now.
- * (6/6/99)
- *
- * 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!
- * (27/5/99)
- *
- * version 0.2: Improved Bulk transfer. TX led now flashes every time data is
- * sent. Send Encapsulated Data is not needed, nor does it do anything.
- * Why's that ?!? Thanks to Thomas Sailer for his close look at the bulk code.
- * He told me about some importand bugs. (5/21/99)
+ * ChangeLog:
+ *	v0.9  Vojtech Pavlik - thorough cleaning, URBification, almost a rewrite
+ *      v0.10 Vojtech Pavlik - some more cleanups
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
  *
- * version 0.1: Bulk transfer for uhci seems to work now, no dangling tds any
- * more. TX led of the ISDN TA flashed the first time. Does this mean it works?
- * The interrupt of the ctrl endpoint crashes the kernel => no read possible
- * (5/19/99)
+ * 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.
  *
- * version 0.0: Driver sets up configuration, sets up data pipes, opens misc
- * device. No actual data transfer is done, since we don't have bulk transfer,
- * yet. Purely skeleton for now. (5/8/99)
+ * 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/kernel.h>
@@ -62,581 +43,491 @@
 #include <linux/tty_flip.h>
 #include <linux/tty.h>
 #include <linux/module.h>
+#include <linux/config.h>
 
 #include "usb.h"
 
-#define NR_PORTS 3
-#define ACM_MAJOR 166	/* Wow, major is now officially allocated */
+#ifdef CONFIG_USB_ACM_DEBUG
+#define acm_debug(fmt,arg...)	printk(KERN_DEBUG "acm: " fmt "\n" , ##arg)
+#else
+#define acm_debug(fmt,arg...)	do {} while(0)
+#endif
+
+/*
+ * Major and minor numbers.
+ */
+
+#define ACM_TTY_MAJOR		166
+#define ACM_TTY_MINORS		8
 
-//#define info(message...) printk(KERN_DEBUG message)
-#define info(message...)
+/*
+ * Output control lines.
+ */
 
-#define CTRL_STAT_DTR	1
-#define CTRL_STAT_RTS	2
+#define ACM_CTRL_DTR		0x01
+#define ACM_CTRL_RTS		0x02
 
-static struct usb_driver acm_driver;
+/*
+ * Input control lines and line errors.
+ */
+
+#define ACM_CTRL_DCD		0x01
+#define ACM_CTRL_DSR		0x02
+#define ACM_CTRL_BRK		0x04
+#define ACM_CTRL_RI		0x08
+
+#define ACM_CTRL_FRAMING	0x10
+#define ACM_CTRL_PARITY		0x20
+#define ACM_CTRL_OVERRUN	0x40
 
-static int acm_refcount;
+/*
+ * Line speed and caracter encoding.
+ */
 
-static struct tty_driver acm_tty_driver;
-static struct tty_struct *acm_tty[NR_PORTS];
-static struct termios *acm_termios[NR_PORTS];
-static struct termios *acm_termios_locked[NR_PORTS];
-static struct acm_state acm_state_table[NR_PORTS];
-
-struct acm_state {
-	struct usb_device *dev;				//the coresponding usb device
-	int cfgnum;					//configuration number on this device
-	struct tty_struct *tty;				//the coresponding tty
-	char present;					//a device for this struct was detected => this tty is used
-	char active;					//someone has this acm's device open
-	unsigned int ctrlstate;				//Status of the serial control lines  (handshake,...)
-	unsigned int linecoding;			//Status of the line coding (Bits, Stop, Parity)
-	int writesize, readsize;			//size of the usb buffers
-	char *writebuffer, *readbuffer;			//the usb buffers
-	void *readtransfer, *writetransfer;
-	void *ctrltransfer;				//ptr to HC internal transfer struct
-	char writing, reading;				//flag if transfer is running
-	unsigned int readendp,writeendp,ctrlendp;	//endpoints and
-	unsigned int readpipe,writepipe,ctrlpipe;	//pipes (are one of these obsolete?)
-	unsigned ctrlinterval;				//interval to poll from device
+struct acm_coding {
+	__u32 speed;
+	__u8 stopbits;
+	__u8 parity;
+	__u8 databits;
+} __attribute__ ((packed));
+
+/*
+ * Internal driver structures.
+ */
+
+struct acm {
+	struct usb_device *dev;				/* the coresponding usb device */
+	struct usb_config_descriptor *cfg;		/* configuration number on this device */
+	struct tty_struct *tty;				/* the coresponding tty */
+	unsigned int ctrlin;				/* input control lines (DCD, DSR, RI, break, overruns) */
+	unsigned int ctrlout;				/* output control lines (DTR, RTS) */
+	struct acm_coding linecoding;			/* line coding (bits, stop, parity) */
+	unsigned int writesize;				/* max packet size for the output bulk endpoint */
+	struct urb ctrlurb, readurb, writeurb;		/* urbs */
+	unsigned char present;				/* this device is connected to the usb bus */
+	unsigned char used;				/* someone has this acm's device open */
 };
 
-#define ACM_READY (acm->present && acm->active)
+static struct usb_driver acm_driver;
+static struct acm acm_table[ACM_TTY_MINORS];
+
+#define ACM_READY(acm)	(acm->present && acm->used)
 
-//functions for various ACM requests
+/*
+ * Functions for ACM control messages.
+ */
 
-void Set_Control_Line_Status(unsigned int status, struct acm_state *acm)
+static void acm_set_control(unsigned int status, struct acm *acm)
 {
-	struct usb_device *dev = acm->dev;
-	int ret;
+	if (usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), 0x22, 0x22, status, 0, NULL, 0, HZ) < 0)
+		acm_debug("acm_set_control() failed");
 
-	info("Set_control_Line_Status\n");
+	acm_debug("output control lines: dtr%c rts%c",
+		acm->ctrlout & ACM_CTRL_DTR ? '+' : '-', acm->ctrlout & ACM_CTRL_RTS ? '+' : '-');
+}
 
-	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x22, 0x22,
-		status, 0, NULL, 0, HZ);
-	if (ret < 0)
-		printk(KERN_ERR "acm: Set_Control_Line_Status failed\n");
+#if 0
+static void acm_set_coding(struct acm_coding *coding, struct acm *acm)
+{
+	if (usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), 0x30, 0x22, 0, 0, coding, sizeof(struct acm_coding), HZ) < 0)
+		acm_debug("acm_set_coding() failed");
+}
 
-	acm->ctrlstate = status;
+static void acm_send_break(int ms, struct acm *acm)
+{
+	if (usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), 0x30, 0x33, ms, 0, NULL, 0, HZ) < 0)
+		acm_debug("acm_send_break() failed");
 }
+#endif
 
-void Set_Line_Coding(unsigned int coding, struct acm_state *acm)
+/*
+ * Interrupt handler for various ACM control events
+ */
+
+static void acm_ctrl_irq(struct urb *urb)
 {
-	struct usb_device *dev = acm->dev;
-	int ret;
+	struct acm *acm = urb->context;
+	devrequest *dr = urb->transfer_buffer;
+	unsigned char *data = (unsigned char *)(dr + 1);
 
-	info("Set_Line_Coding\n");
+	if (urb->status < 0) {
+		acm_debug("nonzero ctrl irq status received: %d", urb->status);
+		return;
+	}
 
-	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x30, 0x22,
-		coding, 0, NULL, 0, HZ);
+	if (!ACM_READY(acm)) return;
 
-	acm->linecoding = coding;
-}
+	switch (dr->request) {
 
-//Interrupt handler for various usb events
-static int acm_irq(int state, void *__buffer, int count, void *dev_id)
-{
-	unsigned char *data;
-	struct acm_state *acm = (struct acm_state *)dev_id;
-	devrequest *dr;
+		case 0x20: /* Set serial line state */
 
-	info("ACM_USB_IRQ\n");
+			if ((dr->index != 1) || (dr->length != 2)) {
+				acm_debug("unknown set serial line request: index %d len %d", dr->index, dr->length);
+				return;
+			}
 
-	if (state) {
-		printk(KERN_DEBUG "acm_irq: strange state received: %x\n", state);
-		return 0;
-	}
+			acm->ctrlin = data[0] | (((unsigned int) data[1]) << 8);
 
-	if (!acm->present)
-		return 0;
-	if (!acm->active)
-		return 1;
+			acm_debug("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
+				acm->ctrlin & ACM_CTRL_DCD ? '+' : '-',	acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
+				acm->ctrlin & ACM_CTRL_BRK ? '+' : '-',	acm->ctrlin & ACM_CTRL_RI  ? '+' : '-',
+				acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-',	acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
+				acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-');
 
-	dr = __buffer;
-	data = __buffer;
-	data += sizeof(dr);
- 
-#if 0
-	printk("reqtype: %02X\n",dr->requesttype);
-	printk("request: %02X\n",dr->request);
-	printk("wValue: %02X\n",dr->value);
-	printk("wIndex: %02X\n",dr->index);
-	printk("wLength: %02X\n",dr->length);
-#endif
+			return;
 
-	switch(dr->request) {
-	case 0x00: /* Network connection */
-		printk(KERN_DEBUG "Network connection: ");
-		if (dr->request==0) printk(KERN_DEBUG "disconnected\n");
-		if (dr->request==1) printk(KERN_DEBUG "connected\n");
-		break;
-
-	case 0x01: /* Response available */
-		printk(KERN_DEBUG "Response available\n");
-		break;
-
-	case 0x20: /* Set serial line state */
-		printk(KERN_DEBUG "acm.c: Set serial control line state\n");
-		if ((dr->index==1) && (dr->length==2)) {
-			acm->ctrlstate= data[0] || (data[1] << 16);
-			printk(KERN_DEBUG "Serstate: %02X\n",acm->ctrlstate);
-		}
-		break;
+		default:
+			acm_debug("unknown control event received: request %d index %d len %d data0 %d data1 %d",
+				dr->request, dr->index, dr->length, data[0], data[1]);
+			return;
 	}
 
-	return 1; /* Continue transfer */
+	return;
 }
 
-static int acm_read_irq(int state, void *__buffer, int count, void *dev_id)
+static void acm_read_bulk(struct urb *urb)
 {
-	struct acm_state *acm = (struct acm_state *) dev_id; 
-       	struct tty_struct *tty = acm->tty; 
-       	unsigned char* data=__buffer;
+	struct acm *acm = urb->context;
+	struct tty_struct *tty = acm->tty;
+	unsigned char *data = urb->transfer_buffer;
 	int i;
 
-	info("ACM_READ_IRQ: state %d, %d bytes\n", state, count);
-	if (state) {
-		printk( "acm_read_irq: strange state received: %x\n", state );
-		return 1;
+	if (urb->status) {
+		acm_debug("nonzero read bulk status received: %d", urb->status);
+		return;
 	}
-	
-	if (!ACM_READY)
-		return 0;	/* stop transfer */
 
-	for (i=0;i<count;i++)
-		tty_insert_flip_char(tty,data[i],0);
-  	tty_flip_buffer_push(tty);
+	if (!ACM_READY(acm)) return;
+
+	for (i = 0; i < urb->actual_length; i++)
+		tty_insert_flip_char(tty, data[i], 0);
 
-	return 1;
+	tty_flip_buffer_push(tty);
+
+	if (usb_submit_urb(urb))
+		acm_debug("failed resubmitting read urb");
+
+	return;
 }
 
-static int acm_write_irq(int state, void *__buffer, int count, void *dev_id)
+static void acm_write_bulk(struct urb *urb)
 {
-	struct acm_state *acm = (struct acm_state *) dev_id;
-       	struct tty_struct *tty = acm->tty;
+	struct acm *acm = (struct acm *)urb->context;
+	struct tty_struct *tty = acm->tty;
 
-	info("ACM_WRITE_IRQ\n");
+	if (urb->status) {
+		acm_debug("nonzero write bulk status received: %d", urb->status);
+		return;
+	}
 
-	if (!ACM_READY)
-		return 0; /* stop transfer */
+	if (!ACM_READY(acm)) return;
 
-	usb_terminate_bulk(acm->dev, acm->writetransfer);
-	acm->writing = 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 0; /* stop tranfer */
+	return;
 }
 
-/*TTY STUFF*/
-static int rs_open(struct tty_struct *tty, struct file *filp)
-{
-	struct acm_state *acm;
-	int ret;
+/*
+ * TTY handlers
+ */
 
-	info("USB_FILE_OPEN\n");
+static int acm_tty_open(struct tty_struct *tty, struct file *filp)
+{
+	struct acm *acm = &acm_table[MINOR(tty->device)];
 
-	tty->driver_data = acm =
-		&acm_state_table[MINOR(tty->device) - tty->driver.minor_start];
+	tty->driver_data = acm;
 	acm->tty = tty;
-	 
-	if (!acm->present)
-		return -EINVAL;
 
-	if (acm->active++)
+	if (!acm->present) return -EINVAL;
+
+	if (acm->used++) {
+		MOD_INC_USE_COUNT;
 		return 0;
- 
+	}
+
 	MOD_INC_USE_COUNT;
 
-	/* Start reading from the device */
-	ret = usb_request_irq(acm->dev, acm->ctrlpipe, acm_irq,
-		acm->ctrlinterval, acm, &acm->ctrltransfer);
-	if (ret)
-		printk(KERN_ERR "usb-acm: usb_request_irq failed (0x%x)\n", ret);
-	acm->reading = 1;
-	acm->readtransfer = usb_request_bulk(acm->dev, acm->readpipe,
-		acm_read_irq, acm->readbuffer, acm->readsize, acm);
+	if (usb_submit_urb(&acm->ctrlurb))
+		acm_debug("usb_submit_urb(ctrl irq) failed");
+
+	if (usb_submit_urb(&acm->readurb))
+		acm_debug("usb_submit_urb(read bulk) failed");
 
-	Set_Control_Line_Status(CTRL_STAT_DTR | CTRL_STAT_RTS, acm);
+	acm_set_control(acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS, acm);
 
 	return 0;
 }
 
-static void rs_close(struct tty_struct *tty, struct file *filp)
+static void acm_tty_close(struct tty_struct *tty, struct file *filp)
 {
-	struct acm_state *acm = (struct acm_state *) tty->driver_data;
+	struct acm *acm = tty->driver_data;
 
-	info("rs_close\n");
+	if (!ACM_READY(acm)) return;
 
-	if (!acm->present)
+	if (--acm->used) {
+		MOD_DEC_USE_COUNT;
 		return;
-
-	if (--acm->active)
-		return;
-
-	Set_Control_Line_Status(0, acm);
-
-	if (acm->writing) {
-		usb_terminate_bulk(acm->dev, acm->writetransfer);
-		acm->writing = 0;
-	}
-	if (acm->reading) {
-		usb_terminate_bulk(acm->dev, acm->readtransfer);
-		acm->reading = 0;
 	}
-//	usb_release_irq(acm->dev, acm->ctrltransfer, acm->ctrlpipe);
+
+	acm_set_control(acm->ctrlout = 0, acm);
+	usb_unlink_urb(&acm->writeurb);
+	usb_unlink_urb(&acm->readurb);
 
 	MOD_DEC_USE_COUNT;
 }
 
-static int rs_write(struct tty_struct *tty, int from_user,
-		    const unsigned char *buf, int count)
+static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
 {
-	struct acm_state *acm = (struct acm_state *)tty->driver_data;
-	int written;
-
-	info("rs_write\n");
-
-	if (!ACM_READY)
-		return -EINVAL;
+	struct acm *acm = tty->driver_data;
 
-	if (acm->writing) {
-		info("already writing\n");
-		return 0;
-	}
+	if (!ACM_READY(acm)) return -EINVAL;
+	if (acm->writeurb.status == -EINPROGRESS) return 0;
 
-	written = (count>acm->writesize) ? acm->writesize : count;
+	count = (count > acm->writesize) ? acm->writesize : count;
 
 	if (from_user)
-		copy_from_user(acm->writebuffer, buf, written);
+		copy_from_user(acm->writeurb.transfer_buffer, buf, count);
 	else
-		memcpy(acm->writebuffer, buf, written);
+		memcpy(acm->writeurb.transfer_buffer, buf, count);
 
-	//start the transfer
-	acm->writing = 1;
-	acm->writetransfer = usb_request_bulk(acm->dev, acm->writepipe,
-		acm_write_irq, acm->writebuffer, written, acm);
+	acm->writeurb.transfer_buffer_length = count;
 
-	return written;
-} 
+	if (usb_submit_urb(&acm->writeurb))
+		acm_debug("usb_submit_urb(write bulk) failed");
 
-static void rs_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	printk(KERN_DEBUG "acm: rs_put_char: Who called this unsupported routine?\n");
-	BUG();
+	return count;
 }
 
-static int rs_write_room(struct tty_struct *tty)
+static int acm_tty_write_room(struct tty_struct *tty)
 {
-	struct acm_state *acm = (struct acm_state *) tty->driver_data;
-
-	info("rs_write_room\n");
-
-	if (!ACM_READY)
-		return -EINVAL;
-
-	return acm->writing ? 0 : acm->writesize;
+	struct acm *acm = tty->driver_data;
+	if (!ACM_READY(acm)) return -EINVAL;
+	return acm->writeurb.status == -EINPROGRESS ? 0 : acm->writesize;
 }
 
-static int rs_chars_in_buffer(struct tty_struct *tty)
+static int acm_tty_chars_in_buffer(struct tty_struct *tty)
 {
-	struct acm_state *acm = (struct acm_state *) tty->driver_data;
-
-//	info("rs_chars_in_buffer\n");
-
-	if (!ACM_READY)
-		return -EINVAL;
-
-	return acm->writing ? acm->writesize : 0;
+	struct acm *acm = tty->driver_data;
+	if (!ACM_READY(acm)) return -EINVAL;
+	return acm->writeurb.status == -EINPROGRESS ? acm->writesize : 0;
 }
 
-static void rs_throttle(struct tty_struct *tty)
+static void acm_tty_throttle(struct tty_struct *tty)
 {
-	struct acm_state *acm = (struct acm_state *) tty->driver_data;
-
-	info("rs_throttle\n");
-
-	if (!ACM_READY)
-		return;
-/*
-	if (I_IXOFF(tty))
-		rs_send_xchar(tty, STOP_CHAR(tty));
-*/
+	struct acm *acm = tty->driver_data;
+	if (!ACM_READY(acm)) return;
 	if (tty->termios->c_cflag & CRTSCTS)
-		Set_Control_Line_Status(acm->ctrlstate & ~CTRL_STAT_RTS, acm);
+		acm_set_control(acm->ctrlout &= ~ACM_CTRL_RTS, acm);
 }
 
-static void rs_unthrottle(struct tty_struct *tty)
+static void acm_tty_unthrottle(struct tty_struct *tty)
 {
-	struct acm_state *acm = (struct acm_state *) tty->driver_data;
+	struct acm *acm = tty->driver_data;
+	if (!ACM_READY(acm)) return;
+	if (tty->termios->c_cflag & CRTSCTS)
+		acm_set_control(acm->ctrlout |= ACM_CTRL_RTS, acm);
+}
 
-	info("rs_unthrottle\n");
+static void acm_tty_set_termios(struct tty_struct *tty, struct termios *old)
+{
+	acm_debug("set_termios called, but not there yet");
+	return;
+}
 
-	if (!ACM_READY)
-		return;
 /*
-	if (I_IXOFF(tty))
-		rs_send_xchar(tty, STOP_CHAR(tty));
-*/
-	if (tty->termios->c_cflag & CRTSCTS)
-		Set_Control_Line_Status(acm->ctrlstate | CTRL_STAT_RTS, acm);
-}
+ * USB probe and disconnect routines.
+ */
 
-static int get_free_acm(void)
+static void *acm_probe(struct usb_device *dev, unsigned int ifnum)
 {
-	int i;
- 
-	for (i = 0; i < NR_PORTS; i++) {
-		if (!acm_state_table[i].present)
-			return i;
-	}
-	return -1;
-}
-
-static void * acm_probe(struct usb_device *dev, unsigned int ifnum)
-{
-	struct acm_state *acm;
-	struct usb_interface_descriptor *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	int cfgnum,acmno;
-	int swapped=0;
-	
-	info("acm_probe\n");
-	
-	if (0>(acmno=get_free_acm())) {
-		info("Too many acm devices connected\n");
+	struct acm *acm;
+	struct usb_interface_descriptor *ifcom, *ifdata;
+	struct usb_endpoint_descriptor *epctrl, *epread, *epwrite;
+	int readsize, ctrlsize, minor, i;
+	unsigned char *buf;
+	char *s = NULL;
+
+	for (minor = 0; minor < ACM_TTY_MINORS &&
+		(acm_table[minor].present || acm_table[minor].used); minor++);
+	if (acm_table[minor].present || acm_table[minor].used) {
+		acm_debug("no more free acm devices");
 		return NULL;
 	}
-	acm = &acm_state_table[acmno];
+	acm = acm_table + minor;
+	memset(acm, 0, sizeof(struct acm));
+
+	acm->dev = dev;
 
-	/* Only use CDC */
-	if (dev->descriptor.bDeviceClass != 2 ||
-	    dev->descriptor.bDeviceSubClass != 0 ||
-	    dev->descriptor.bDeviceProtocol != 0)
+	if (dev->descriptor.bDeviceClass != 2 || dev->descriptor.bDeviceSubClass != 0
+		|| dev->descriptor.bDeviceProtocol != 0) {
 		return NULL;
+	}
 
-#define IFCLASS(if) ((if->bInterfaceClass << 24) | (if->bInterfaceSubClass << 16) | (if->bInterfaceProtocol << 8) | (if->bNumEndpoints))
+	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
 
-	/* FIXME: should the driver really be doing the configuration
-	 * selecting or should the usbcore?  [different configurations
-	 * can have different bandwidth requirements] -greg */
-
-	/* 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 (IFCLASS(interface) != 0x02020101)
-			continue;
+		acm_debug("probing config %d", i);
+		acm->cfg = dev->config + i;
 
-		/* Which uses an interrupt input */
-		endpoint = &interface->endpoint[0];
-		if ((endpoint->bEndpointAddress & 0x80) != 0x80 ||
-		    (endpoint->bmAttributes & 3) != 3)
-			continue;
-			
-		/* The second one should be a Data interface? */
-		interface = &dev->config[cfgnum].interface[1].altsetting[0];
-		if (interface->bInterfaceClass != 10 ||
-		    interface->bNumEndpoints != 2)
+		ifcom = acm->cfg->interface[0].altsetting + 0;
+		if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 ||
+		    ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints != 1)
 			continue;
 
-		/* make sure both interfaces are available for our use */
-		if (usb_interface_claimed(&dev->config[cfgnum].interface[0]) ||
-		    usb_interface_claimed(&dev->config[cfgnum].interface[1])) {
-			printk("usb-acm: required interface already has a driver\n");
+		epctrl = ifcom->endpoint + 0;
+		if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3)
 			continue;
-		}
 
-		endpoint = &interface->endpoint[0];
-		if ((endpoint->bEndpointAddress & 0x80) != 0x80)
-			swapped = 1;
-
-		/*With a bulk input */
-		endpoint = &interface->endpoint[0^swapped];
-		if ((endpoint->bEndpointAddress & 0x80) != 0x80 ||
-		    (endpoint->bmAttributes & 3) != 2)
+		ifdata = acm->cfg->interface[1].altsetting + 0;
+		if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints != 2)
 			continue;
-			
-		/*And a bulk output */
-		endpoint = &interface->endpoint[1^swapped];
-		if ((endpoint->bEndpointAddress & 0x80) == 0x80 ||
-		    (endpoint->bmAttributes & 3) != 2)
+
+		if (usb_interface_claimed(acm->cfg->interface + 0) ||
+		    usb_interface_claimed(acm->cfg->interface + 1))
 			continue;
 
-		printk("USB ACM %d found\n",acmno);
-		usb_set_configuration(dev, dev->config[cfgnum].bConfigurationValue);
+		epread = ifdata->endpoint + 0;
+		epwrite = ifdata->endpoint + 1;
 
-		acm->dev=dev;
+		if ((epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
+		   ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
+			continue;
 
-		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^swapped].wMaxPacketSize,GFP_KERNEL);
-		acm->reading=0;
-		if (!acm->readbuffer) {
-			printk("ACM: Couldn't allocate readbuffer\n");
-			return NULL;
+		if ((epread->bEndpointAddress & 0x80) != 0x80) {
+			epread = ifdata->endpoint + 1;
+			epwrite = ifdata->endpoint + 0;
 		}
 
-		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^swapped].wMaxPacketSize, GFP_KERNEL);
-		acm->writing=0;
-		if (!acm->writebuffer) {
-			printk("ACM: Couldn't allocate writebuffer\n");
-			kfree(acm->readbuffer);
+		usb_set_configuration(dev, acm->cfg->bConfigurationValue);
+
+		ctrlsize = epctrl->wMaxPacketSize;
+		readsize = epread->wMaxPacketSize;
+		acm->writesize = epwrite->wMaxPacketSize;
+
+		if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL)))
 			return NULL;
-		}
 
-		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;
+		FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
+			buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
 
-		acm->cfgnum = cfgnum;
-		acm->present=1;				
-		MOD_INC_USE_COUNT;
+		FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
+			buf += ctrlsize, readsize, acm_read_bulk, acm);
+
+		FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
+			buf += readsize , acm->writesize, acm_write_bulk, acm);
+
+		printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
+
+		usb_driver_claim_interface(&acm_driver, acm->cfg->interface + 0, acm);
+		usb_driver_claim_interface(&acm_driver, acm->cfg->interface + 1, acm);
+
+		acm->present = 1;
 
-		usb_driver_claim_interface(&acm_driver,
-				&dev->config[cfgnum].interface[0], acm);
-		usb_driver_claim_interface(&acm_driver,
-				&dev->config[cfgnum].interface[1], acm);
 		return acm;
 	}
+
 	return NULL;
 }
 
 static void acm_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct acm_state *acm = ptr;
+	struct acm *acm = ptr;
 
-	info("acm_disconnect\n");
-	
-	if (!acm->present)
+	if (!acm->present) {
+		acm_debug("disconnect on nonexisting interface");
 		return;
+	}
 
-	acm->active=0;
-	acm->present=0;
-	if (acm->writing){
-		usb_terminate_bulk(acm->dev, acm->writetransfer);
-		acm->writing=0;
-	}
-	if (acm->reading){
-		usb_terminate_bulk(acm->dev, acm->readtransfer);
-		acm->reading=0;
-	}
-	usb_release_irq(acm->dev,acm->ctrltransfer, acm->ctrlpipe);
-	//BUG: What to do if a device is open?? Notify process or not allow cleanup?
-	kfree(acm->writebuffer);
-	kfree(acm->readbuffer);
-
-	/* release the interfaces so that other drivers can have at them */
-	usb_driver_release_interface(&acm_driver,
-				&dev->config[acm->cfgnum].interface[0]);
-	usb_driver_release_interface(&acm_driver,
-				&dev->config[acm->cfgnum].interface[1]);
+	acm->present = 0;
 
-	MOD_DEC_USE_COUNT;
+	usb_unlink_urb(&acm->ctrlurb);
+	usb_unlink_urb(&acm->readurb);
+	usb_unlink_urb(&acm->writeurb);
+
+	kfree(acm->ctrlurb.transfer_buffer);
+
+	usb_driver_release_interface(&acm_driver, acm->cfg->interface + 0);
+	usb_driver_release_interface(&acm_driver, acm->cfg->interface + 1);
 }
 
-/*USB DRIVER STUFF*/
+/*
+ * USB driver structure.
+ */
+
 static struct usb_driver acm_driver = {
-	"acm",
-	acm_probe,
-	acm_disconnect,
-	{ NULL, NULL }
+	name:		"acm",
+	probe:		acm_probe,
+	disconnect:	acm_disconnect
+};
+
+/*
+ * TTY driver structures.
+ */
+
+static int acm_tty_refcount;
+
+static struct tty_struct *acm_tty_table[ACM_TTY_MINORS];
+static struct termios *acm_tty_termios[ACM_TTY_MINORS];
+static struct termios *acm_tty_termios_locked[ACM_TTY_MINORS];
+
+static struct tty_driver acm_tty_driver = {
+	magic:			TTY_DRIVER_MAGIC,
+	driver_name:		"usb",
+	name:			"ttyACM",
+	major:			ACM_TTY_MAJOR,
+	minor_start:		0,
+	num:			ACM_TTY_MINORS,
+	type:			TTY_DRIVER_TYPE_SERIAL,
+	subtype:		SERIAL_TYPE_NORMAL,
+	flags:			TTY_DRIVER_REAL_RAW,
+
+	refcount:		&acm_tty_refcount,
+
+	table:			acm_tty_table,
+	termios:		acm_tty_termios,
+	termios_locked:		acm_tty_termios_locked,
+
+	open:			acm_tty_open,
+	close:			acm_tty_close,
+	write:			acm_tty_write,
+	write_room:		acm_tty_write_room,
+	set_termios:		acm_tty_set_termios,
+	throttle:		acm_tty_throttle,
+	unthrottle:		acm_tty_unthrottle,
+	chars_in_buffer:	acm_tty_chars_in_buffer
 };
 
+/*
+ * Init / cleanup.
+ */
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	usb_deregister(&acm_driver);
+	tty_unregister_driver(&acm_tty_driver);
+}
+
+int init_module(void)
+#else
 int usb_acm_init(void)
+#endif
 {
-	int cnt;
+	memset(acm_table, 0, sizeof(struct acm) * ACM_TTY_MINORS);
 
-	info("usb_acm_init\n");
+	acm_tty_driver.init_termios =		tty_std_termios;
+	acm_tty_driver.init_termios.c_cflag =	B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 
-	//INITIALIZE GLOBAL DATA STRUCTURES
-	for (cnt = 0; cnt < NR_PORTS; cnt++)
-		memset(&acm_state_table[cnt], 0, sizeof(struct acm_state));
-
-	//REGISTER TTY DRIVER
-	memset(&acm_tty_driver, 0, sizeof(struct tty_driver));
-	acm_tty_driver.magic = TTY_DRIVER_MAGIC;
-	acm_tty_driver.driver_name = "usb";
-	acm_tty_driver.name = "ttyACM";
-	acm_tty_driver.major = ACM_MAJOR;
-	acm_tty_driver.minor_start = 0;
-	acm_tty_driver.num = NR_PORTS;
-	acm_tty_driver.type = TTY_DRIVER_TYPE_SERIAL;
-	acm_tty_driver.subtype = SERIAL_TYPE_NORMAL;
-	acm_tty_driver.init_termios = tty_std_termios;
-	acm_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	acm_tty_driver.flags = TTY_DRIVER_REAL_RAW;
-	acm_tty_driver.refcount = &acm_refcount;
-	acm_tty_driver.table = acm_tty;
-	acm_tty_driver.termios = acm_termios;
-	acm_tty_driver.termios_locked = acm_termios_locked;
-
-	acm_tty_driver.open = rs_open;
-	acm_tty_driver.close = rs_close;
-	acm_tty_driver.write = rs_write;
-	acm_tty_driver.put_char = rs_put_char;
-	acm_tty_driver.flush_chars = NULL; //rs_flush_chars;
-	acm_tty_driver.write_room = rs_write_room;
-	acm_tty_driver.ioctl = NULL; //rs_ioctl
-	acm_tty_driver.set_termios = NULL; //rs_set_termios;
-	acm_tty_driver.set_ldisc = NULL;
-	acm_tty_driver.throttle = rs_throttle;
-	acm_tty_driver.unthrottle = rs_unthrottle;
-	acm_tty_driver.stop = NULL; //rs_stop;
-	acm_tty_driver.start = NULL; //rs_start;
-	acm_tty_driver.hangup = NULL; //rs_hangup;
-	acm_tty_driver.break_ctl = NULL; //rs_break;
-	acm_tty_driver.wait_until_sent = NULL; //rs_wait_until_sent;
-	acm_tty_driver.send_xchar = NULL; //rs_send_xchar;
-	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;
-	if (tty_register_driver(&acm_tty_driver)) {
-		printk(KERN_ERR "acm: failed to register tty driver\n");
-		return -EPERM;
-	}
+	if (tty_register_driver(&acm_tty_driver))
+		return -1;
 
 	if (usb_register(&acm_driver) < 0) {
 		tty_unregister_driver(&acm_tty_driver);
 		return -1;
 	}
 
-	printk(KERN_INFO "USB ACM registered.\n");
 	return 0;
 }
 
-void usb_acm_cleanup(void)
-{
-	int i;
-	struct acm_state *acm;
-
-	info("usb_acm_cleanup\n");
-		
-	for (i=0;i<NR_PORTS;i++) {
-		acm=&acm_state_table[i];
-		if (acm->present) {
-			printk("disconnecting %d\n",i);
-			acm_disconnect(acm->dev, acm);
-		}  
-	}
-	tty_unregister_driver(&acm_tty_driver);
-	
-	usb_deregister(&acm_driver);
-	
-}
-
-#ifdef MODULE
-int init_module(void)
-{
-	return usb_acm_init();
-}
-
-void cleanup_module(void)
-{
-	usb_acm_cleanup();
-}
-#endif
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/audio.c linux/drivers/usb/audio.c
--- v2.3.34/linux/drivers/usb/audio.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/audio.c	Tue Dec 28 10:24:11 1999
@@ -56,6 +56,9 @@
  *		that means they won't play short sounds. Should probably maintain
  *		the ISO datastream even if there's nothing to play.
  *		Fix counting the total_bytes counter, RealPlayer G2 depends on it.
+ * 1999-12-20:  Fix bad bug in conversion to per interface probing.
+ *		disconnect was called multiple times for the audio device,
+ *		leading to a premature freeing of the audio structures
  *
  */
 
@@ -131,6 +134,7 @@
  */
 
 /*****************************************************************************/
+
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/malloc.h>
@@ -148,7 +152,6 @@
 #include <linux/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-//#include <linux/spinlock.h>
 
 #include "usb.h"
 #include "audio.h"
@@ -621,137 +624,145 @@
 	usbin_stop(as);
 }
 
-static void usbin_convert(struct usbin *u, unsigned char *buffer, unsigned int samples)
+static void conversion(const void *ibuf, unsigned int ifmt, void *obuf, unsigned int ofmt, void *tmp, unsigned int scnt)
 {
-	union {
-		__s16 s[64];
-		unsigned char b[0];
-	} tmp;
-	unsigned int scnt, maxs, ufmtsh, dfmtsh, cnt, i;
+	unsigned int cnt, i;
 	__s16 *sp, *sp2, s;
 	unsigned char *bp;
 
-	ufmtsh = AFMT_BYTESSHIFT(u->format);
-	dfmtsh = AFMT_BYTESSHIFT(u->dma.format);
-	maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64;
-	while (samples > 0) {
-		scnt = samples;
-		if (scnt > maxs)
-			scnt = maxs;
-		cnt = scnt;
-		if (AFMT_ISSTEREO(u->format))
-			cnt <<= 1;
-		sp = tmp.s + cnt;
-		switch (u->format & ~AFMT_STEREO) {
-		case AFMT_U8:
-			for (bp = buffer+cnt, i = 0; i < cnt; i++) {
-				bp--;
-				sp--;
-				*sp = (*bp ^ 0x80) << 8;
-			}
-			break;
+	cnt = scnt;
+	if (AFMT_ISSTEREO(ifmt))
+		cnt <<= 1;
+	sp = ((__s16 *)tmp) + cnt;
+	switch (ifmt & ~AFMT_STEREO) {
+	case AFMT_U8:
+		for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) {
+			bp--;
+			sp--;
+			*sp = (*bp ^ 0x80) << 8;
+		}
+		break;
+			
+	case AFMT_S8:
+		for (bp = ((unsigned char *)ibuf)+cnt, i = 0; i < cnt; i++) {
+			bp--;
+			sp--;
+			*sp = *bp << 8;
+		}
+		break;
+		
+	case AFMT_U16_LE:
+		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {
+			bp -= 2;
+			sp--;
+			*sp = (bp[0] | (bp[1] << 8)) ^ 0x8000;
+		}
+		break;
 
-		case AFMT_S8:
-			for (bp = buffer+cnt, i = 0; i < cnt; i++) {
-				bp--;
-				sp--;
-				*sp = *bp << 8;
-			}
-			break;
+	case AFMT_U16_BE:
+		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {
+			bp -= 2;
+			sp--;
+			*sp = (bp[1] | (bp[0] << 8)) ^ 0x8000;
+		}
+		break;
 
-		case AFMT_U16_LE:
-			for (bp = buffer+2*cnt, i = 0; i < cnt; i++) {
-				bp -= 2;
-				sp--;
-				*sp = (bp[0] | (bp[1] << 8)) ^ 0x8000;
-			}
-			break;
+	case AFMT_S16_LE:
+		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {
+			bp -= 2;
+			sp--;
+			*sp = bp[0] | (bp[1] << 8);
+		}
+		break;
 
-		case AFMT_U16_BE:
-			for (bp = buffer+2*cnt, i = 0; i < cnt; i++) {
-				bp -= 2;
-				sp--;
-				*sp = (bp[1] | (bp[0] << 8)) ^ 0x8000;
-			}
-			break;
+	case AFMT_S16_BE:
+		for (bp = ((unsigned char *)ibuf)+2*cnt, i = 0; i < cnt; i++) {
+			bp -= 2;
+			sp--;
+			*sp = bp[1] | (bp[0] << 8);
+		}
+		break;
+	}
+	if (!AFMT_ISSTEREO(ifmt) && AFMT_ISSTEREO(ofmt)) {
+		/* expand from mono to stereo */
+		for (sp = ((__s16 *)tmp)+scnt, sp2 = ((__s16 *)tmp)+2*scnt, i = 0; i < scnt; i++) {
+			sp--;
+			sp2 -= 2;
+			sp2[0] = sp2[1] = sp[0];
+		}
+	}
+	if (AFMT_ISSTEREO(ifmt) && !AFMT_ISSTEREO(ofmt)) {
+		/* contract from stereo to mono */
+		for (sp = sp2 = ((__s16 *)tmp), i = 0; i < scnt; i++, sp++, sp2 += 2)
+			sp[0] = (sp2[0] + sp2[1]) >> 1;
+	}
+	cnt = scnt;
+	if (AFMT_ISSTEREO(ofmt))
+		cnt <<= 1;
+	sp = ((__s16 *)tmp);
+	bp = ((unsigned char *)obuf);
+	switch (ofmt & ~AFMT_STEREO) {
+	case AFMT_U8:
+		for (i = 0; i < cnt; i++, sp++, bp++)
+			*bp = (*sp >> 8) ^ 0x80;
+		break;
 
-		case AFMT_S16_LE:
-			for (bp = buffer+2*cnt, i = 0; i < cnt; i++) {
-				bp -= 2;
-				sp--;
-				*sp = bp[0] | (bp[1] << 8);
-			}
-			break;
+	case AFMT_S8:
+		for (i = 0; i < cnt; i++, sp++, bp++)
+			*bp = *sp >> 8;
+		break;
 
-		case AFMT_S16_BE:
-			for (bp = buffer+2*cnt, i = 0; i < cnt; i++) {
-				bp -= 2;
-				sp--;
-				*sp = bp[1] | (bp[0] << 8);
-			}
-			break;
+	case AFMT_U16_LE:
+		for (i = 0; i < cnt; i++, sp++, bp += 2) {
+			s = *sp;
+			bp[0] = s;
+			bp[1] = (s >> 8) ^ 0x80;
 		}
-		if (!AFMT_ISSTEREO(u->format) && AFMT_ISSTEREO(u->dma.format)) {
-			/* expand from mono to stereo */
-			for (sp = tmp.s+scnt, sp2 = tmp.s+2*scnt, i = 0; i < scnt; i++) {
-				sp--;
-				sp2 -= 2;
-				sp2[0] = sp2[1] = sp[0];
-			}
-		}
-		if (AFMT_ISSTEREO(u->format) && !AFMT_ISSTEREO(u->dma.format)) {
-			/* contract from stereo to mono */
-			for (sp = sp2 = tmp.s, i = 0; i < scnt; i++, sp++, sp2 += 2)
-				sp[0] = (sp2[0] + sp2[1]) >> 1;
-		}
-		cnt = scnt;
-		if (AFMT_ISSTEREO(u->dma.format))
-			cnt <<= 1;
-		sp = tmp.s;
-		bp = tmp.b;
-		switch (u->dma.format & ~AFMT_STEREO) {
-		case AFMT_U8:
-			for (i = 0; i < cnt; i++, sp++, bp++)
-				*bp = (*sp >> 8) ^ 0x80;
-			break;
+		break;
 
-		case AFMT_S8:
-			for (i = 0; i < cnt; i++, sp++, bp++)
-				*bp = *sp >> 8;
-			break;
+	case AFMT_U16_BE:
+		for (i = 0; i < cnt; i++, sp++, bp += 2) {
+			s = *sp;
+			bp[1] = s;
+			bp[0] = (s >> 8) ^ 0x80;
+		}
+		break;
 
-		case AFMT_U16_LE:
-			for (i = 0; i < cnt; i++, sp++, bp += 2) {
-				s = *sp;
-				bp[0] = s;
-				bp[1] = (s >> 8) ^ 0x80;
-			}
-			break;
+	case AFMT_S16_LE:
+		for (i = 0; i < cnt; i++, sp++, bp += 2) {
+			s = *sp;
+			bp[0] = s;
+			bp[1] = s >> 8;
+		}
+		break;
 
-		case AFMT_U16_BE:
-			for (i = 0; i < cnt; i++, sp++, bp += 2) {
-				s = *sp;
-				bp[1] = s;
-				bp[0] = (s >> 8) ^ 0x80;
-			}
-			break;
+	case AFMT_S16_BE:
+		for (i = 0; i < cnt; i++, sp++, bp += 2) {
+			s = *sp;
+			bp[1] = s;
+			bp[0] = s >> 8;
+		}
+		break;
+	}
+	
+}
 
-		case AFMT_S16_LE:
-			for (i = 0; i < cnt; i++, sp++, bp += 2) {
-				s = *sp;
-				bp[0] = s;
-				bp[1] = s >> 8;
-			}
-			break;
+static void usbin_convert(struct usbin *u, unsigned char *buffer, unsigned int samples)
+{
+	union {
+		__s16 s[64];
+		unsigned char b[0];
+	} tmp;
+	unsigned int scnt, maxs, ufmtsh, dfmtsh;
 
-		case AFMT_S16_BE:
-			for (i = 0; i < cnt; i++, sp++, bp += 2) {
-				s = *sp;
-				bp[1] = s;
-				bp[0] = s >> 8;
-			}
-			break;
-		}
+	ufmtsh = AFMT_BYTESSHIFT(u->format);
+	dfmtsh = AFMT_BYTESSHIFT(u->dma.format);
+	maxs = (AFMT_ISSTEREO(u->dma.format | u->format)) ? 32 : 64;
+	while (samples > 0) {
+		scnt = samples;
+		if (scnt > maxs)
+			scnt = maxs;
+		conversion(buffer, u->format, tmp.b, u->dma.format, tmp.b, scnt);
 		dmabuf_copyin(&u->dma, tmp.b, scnt << dfmtsh);
 		buffer += scnt << ufmtsh;
 		samples -= scnt;
@@ -1040,7 +1051,7 @@
 	i = u->flags;
 	spin_unlock_irqrestore(&as->lock, flags);
 	while (i & (FLG_URB0RUNNING|FLG_URB1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
- 		set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		set_current_state(notkilled ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
 		schedule_timeout(1);
 		spin_lock_irqsave(&as->lock, flags);
 		i = u->flags;
@@ -1078,7 +1089,6 @@
 static void usbout_disc(struct usb_audiodev *as)
 {
 	struct usbout *u = &as->usbout;
-
 	unsigned long flags;
 
 	spin_lock_irqsave(&as->lock, flags);
@@ -1093,9 +1103,7 @@
 		__s16 s[64];
 		unsigned char b[0];
 	} tmp;
-	unsigned int scnt, maxs, ufmtsh, dfmtsh, cnt, i;
-	__s16 *sp, *sp2, s;
-	unsigned char *bp;
+	unsigned int scnt, maxs, ufmtsh, dfmtsh;
 
 	ufmtsh = AFMT_BYTESSHIFT(u->format);
 	dfmtsh = AFMT_BYTESSHIFT(u->dma.format);
@@ -1104,121 +1112,8 @@
 		scnt = samples;
 		if (scnt > maxs)
 			scnt = maxs;
-		cnt = scnt;
-		if (AFMT_ISSTEREO(u->dma.format))
-			cnt <<= 1;
 		dmabuf_copyout(&u->dma, tmp.b, scnt << dfmtsh);
-		sp = tmp.s + cnt;
-		switch (u->dma.format & ~AFMT_STEREO) {
-		case AFMT_U8:
-			for (bp = tmp.b+cnt, i = 0; i < cnt; i++) {
-				bp--;
-				sp--;
-				*sp = (*bp ^ 0x80) << 8;
-			}
-			break;
-
-		case AFMT_S8:
-			for (bp = tmp.b+cnt, i = 0; i < cnt; i++) {
-				bp--;
-				sp--;
-				*sp = *bp << 8;
-			}
-			break;
-
-		case AFMT_U16_LE:
-			for (bp = tmp.b+2*cnt, i = 0; i < cnt; i++) {
-				bp -= 2;
-				sp--;
-				*sp = (bp[0] | (bp[1] << 8)) ^ 0x8000;
-			}
-			break;
-
-		case AFMT_U16_BE:
-			for (bp = tmp.b+2*cnt, i = 0; i < cnt; i++) {
-				bp -= 2;
-				sp--;
-				*sp = (bp[1] | (bp[0] << 8)) ^ 0x8000;
-			}
-			break;
-
-		case AFMT_S16_LE:
-			for (bp = tmp.b+2*cnt, i = 0; i < cnt; i++) {
-				bp -= 2;
-				sp--;
-				*sp = bp[0] | (bp[1] << 8);
-			}
-			break;
-
-		case AFMT_S16_BE:
-			for (bp = tmp.b+2*cnt, i = 0; i < cnt; i++) {
-				bp -= 2;
-				sp--;
-				*sp = bp[1] | (bp[0] << 8);
-			}
-			break;
-		}
-		if (!AFMT_ISSTEREO(u->dma.format) && AFMT_ISSTEREO(u->format)) {
-			/* expand from mono to stereo */
-			for (sp = tmp.s+scnt, sp2 = tmp.s+2*scnt, i = 0; i < scnt; i++) {
-				sp--;
-				sp2 -= 2;
-				sp2[0] = sp2[1] = sp[0];
-			}
-		}
-		if (AFMT_ISSTEREO(u->dma.format) && !AFMT_ISSTEREO(u->format)) {
-			/* contract from stereo to mono */
-			for (sp = sp2 = tmp.s, i = 0; i < scnt; i++, sp++, sp2 += 2)
-				sp[0] = (sp2[0] + sp2[1]) >> 1;
-		}
-		cnt = scnt;
-		if (AFMT_ISSTEREO(u->format))
-			cnt <<= 1;
-		sp = tmp.s;
-		bp = buffer;
-		switch (u->format & ~AFMT_STEREO) {
-		case AFMT_U8:
-			for (i = 0; i < cnt; i++, sp++, bp++)
-				*bp = (*sp >> 8) ^ 0x80;
-			break;
-
-		case AFMT_S8:
-			for (i = 0; i < cnt; i++, sp++, bp++)
-				*bp = *sp >> 8;
-			break;
-
-		case AFMT_U16_LE:
-			for (i = 0; i < cnt; i++, sp++, bp += 2) {
-				s = *sp;
-				bp[0] = s;
-				bp[1] = (s >> 8) ^ 0x80;
-			}
-			break;
-
-		case AFMT_U16_BE:
-			for (i = 0; i < cnt; i++, sp++, bp += 2) {
-				s = *sp;
-				bp[1] = s;
-				bp[0] = (s >> 8) ^ 0x80;
-			}
-			break;
-
-		case AFMT_S16_LE:
-			for (i = 0; i < cnt; i++, sp++, bp += 2) {
-				s = *sp;
-				bp[0] = s;
-				bp[1] = s >> 8;
-			}
-			break;
-
-		case AFMT_S16_BE:
-			for (i = 0; i < cnt; i++, sp++, bp += 2) {
-				s = *sp;
-				bp[1] = s;
-				bp[0] = s >> 8;
-			}
-			break;
-		}
+		conversion(tmp.b, u->dma.format, buffer, u->format, tmp.b, scnt);
 		buffer += scnt << ufmtsh;
 		samples -= scnt;
 	}
@@ -1534,7 +1429,7 @@
 	struct usb_device *dev = as->state->usbdev;
 	struct usb_config_descriptor *config = dev->actconfig;
 	struct usb_interface_descriptor *alts;
-	struct usb_interface *iface;	
+	struct usb_interface *iface;
 	struct usbin *u = &as->usbin;
 	struct dmabuf *d = &u->dma;
 	struct audioformat *fmt;
@@ -1793,7 +1688,7 @@
 				    (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
 			goto err;
 		return 0;
-		
+                
 	case BASS_CONTROL:
 	case MID_CONTROL:
 	case TREBLE_CONTROL:
@@ -1808,7 +1703,7 @@
 				    (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 1, HZ) < 0)
 			goto err;
 		return 0;
-	       
+
 	default:
 		return -1;
 	}
@@ -1816,7 +1711,7 @@
 
  err:
 	printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", 
-	       dev->devnum, ms->iface, ch->unitid, ch->chnum, ch->selector);
+		dev->devnum, ms->iface, ch->unitid, ch->chnum, ch->selector);
 	return -1;
 }
 
@@ -1842,7 +1737,6 @@
 	while (!list_empty(&s->audiolist)) {
 		as = list_entry(s->audiolist.next, struct usb_audiodev, list);
 		list_del(&as->list);
-		
 		usbin_release(as);
 		usbout_release(as);
 		dmabuf_release(&as->usbin.dma);
@@ -1851,7 +1745,6 @@
 	}
 	while (!list_empty(&s->mixerlist)) {
 		ms = list_entry(s->mixerlist.next, struct usb_mixerdev, list);
-		
 		list_del(&ms->list);
 		kfree(ms);
 	}
@@ -1956,7 +1849,7 @@
 		case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
 			/* don't know how to handle this yet */
 			return put_user(0, (int *)arg);
-			
+
 		case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
 			for (val = i = 0; i < ms->numch; i++)
 				val |= 1 << ms->ch[i].osschannel;
@@ -1965,7 +1858,7 @@
 		case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
 			/* don't know how to handle this yet */
 			return put_user(0, (int *)arg);
-			
+                        
 		case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
 			for (val = i = 0; i < ms->numch; i++)
 				if (ms->ch[i].flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))
@@ -3240,10 +3133,10 @@
 
 static void usb_audio_featureunit(struct consmixstate *state, unsigned char *ftr)
 {
-//	struct usb_device *dev = state->s->usbdev;
+	struct usb_device *dev = state->s->usbdev;
 	struct mixerchannel *ch;
 	unsigned short chftr, mchftr;
-//	unsigned char data[1];
+	unsigned char data[1];
 
 	usb_audio_recurseunit(state, ftr[4]);
 	if (state->nrchannels == 0) {
@@ -3521,12 +3414,12 @@
 		if (iface->altsetting[1].endpoint[0].bEndpointAddress & USB_DIR_IN) {
 			if (numifin < USB_MAXINTERFACES) {
 				ifin[numifin++] = j;
-				usb_driver_claim_interface(&usb_audio_driver, iface, s);
+				usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1);
 			}
 		} else {
 			if (numifout < USB_MAXINTERFACES) {
 				ifout[numifout++] = j;
-				usb_driver_claim_interface(&usb_audio_driver, iface, s);
+				usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1);
 			}
 		}
 	}
@@ -3555,6 +3448,7 @@
 	down(&open_sem);
 	list_add_tail(&s->audiodev, &audiodevs);
 	up(&open_sem);
+	printk(KERN_DEBUG "usb_audio_parsecontrol: usb_audio_state at %p\n", s);
 	return s;
 }
 
@@ -3607,7 +3501,7 @@
 	if (!(buffer = kmalloc(buflen, GFP_KERNEL)))
 		return NULL;
 	ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buffer, buflen);
-	if (ret<0) {
+	if (ret < 0) {
 		kfree(buffer);
 		printk(KERN_ERR "usbaudio: cannot get config descriptor %d of device %d\n", i, dev->devnum);
 		return NULL;
@@ -3624,7 +3518,16 @@
 	struct list_head *list;
 	struct usb_audiodev *as;
 	struct usb_mixerdev *ms;
-	
+
+	/* we get called with -1 for every audiostreaming interface registered */
+	if (s == (struct usb_audio_state *)-1) {
+		printk(KERN_DEBUG "usb_audio_disconnect: called with -1\n");
+		return;
+	}
+	if (!s->usbdev) {
+		printk(KERN_DEBUG "usb_audio_disconnect: already called for %p!\n", s);
+		return;
+	}
 	down(&open_sem);
 	list_del(&s->audiodev);
 	INIT_LIST_HEAD(&s->audiodev);
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/hp_scanner.c linux/drivers/usb/hp_scanner.c
--- v2.3.34/linux/drivers/usb/hp_scanner.c	Tue Nov 23 22:42:21 1999
+++ linux/drivers/usb/hp_scanner.c	Wed Dec 31 16:00:00 1969
@@ -1,333 +0,0 @@
-/* -*- linux-c -*- */
-
-/* 
- * Driver for USB HP Scanners
- *
- * David E. Nelson (dnelson@jump.net)
- * 
- * 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.
- *
- * Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
- *
- * History
- *  0.1  8/31/1999
- *
- *    Developed/tested using linux-2.3.15 with minor ohci.c changes to
- *    support short packes during bulk xfer mode.  Some testing was
- *    done with ohci-hcd but the performace was low.  Very limited
- *    testing was performed with uhci but I was unable to get it to
- *    work.  Initial relase to the linux-usb development effort.
- *
- * */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/malloc.h>
-#include <linux/spinlock.h>
-
-#include "usb.h"
-
-/* stall/wait timeout for scanner */
-#define NAK_TIMEOUT (HZ)
-
-/* For some reason, an IBUF_SIZE of 8192 causes REALLY big problems
- * with linux-2.3.15.  Anything more than 4k seems to not have an
- * effect on increasing performance. Anything smaller than 4k hurts
- * it.  */
-#define IBUF_SIZE 4096
-
-/* This is a scanner, so not much data is sent to it.  The largest
- * stuff may be some kind of maps and stuff but that's kinda rare.  */
-#define OBUF_SIZE 128
-
-struct hpscan_usb_data {
-	struct usb_device 	*hpscan_dev;            /* init: probe_scanner */
-	__u8			isopen;			/* nz if open */
-
-	__u8                    present;                /* Device is present on the bus */
-	char			*obuf;			/* transfer buffers */
-	char			*ibuf;		
-	wait_queue_head_t	wait_q;			/* for timeouts */
-};
-
-static struct hpscan_usb_data hpscan;
-
-static int
-open_scanner(struct inode * inode, struct file * file)
-{
-	struct hpscan_usb_data *hps = &hpscan;
-
-	if (hps->isopen) {
-		return -EBUSY;
-	}
-	hps->isopen = 1;
-
-	init_waitqueue_head(&hps->wait_q);
-
-	MOD_INC_USE_COUNT;
-
-	return 0;
-}
-
-static int
-close_scanner(struct inode * inode, struct file * file)
-{
-	struct hpscan_usb_data *hps = &hpscan;
-
-	hps->isopen = 0;
-
-	MOD_DEC_USE_COUNT;
-
-	return 0;
-}
-
-static ssize_t
-write_scanner(struct file * file, const char * buffer,
-              size_t count, loff_t *ppos)
-{
-	struct hpscan_usb_data *hps = &hpscan;
-
-	unsigned long copy_size;
-	unsigned long bytes_written = 0;
-	unsigned long partial;
-
-	int result = 0;
-	int maxretry;
-	
-	do {
-		unsigned long thistime;
-		char *obuf = hps->obuf;
-
-		thistime = copy_size = (count > OBUF_SIZE) ?  OBUF_SIZE : count;
-		if (copy_from_user(hps->obuf, buffer, copy_size))
-			return -EFAULT;
-		maxretry = 5;
-		while (thistime) {
-			if (!hps->hpscan_dev)
-				return -ENODEV;
-			if (signal_pending(current)) {
-				return bytes_written ? bytes_written : -EINTR;
-			}
-
-			result = usb_bulk_msg(hps->hpscan_dev,usb_sndbulkpipe(hps->hpscan_dev, 2), obuf, thistime, &partial, HZ*10);
-			
-			//printk(KERN_DEBUG "write stats: result:%d thistime:%lu partial:%lu\n", result, thistime, partial);
-
-			if (result == USB_ST_TIMEOUT) {	/* NAK - so hold for a while */
-				if(!maxretry--) {
-					return -ETIME;
-				}
-				interruptible_sleep_on_timeout(&hps->wait_q, NAK_TIMEOUT);
-				continue;
-			} else if (!result & partial) {
-				obuf += partial;
-				thistime -= partial;
-			} else
-				break;
-		};
-		if (result) {
-			printk("Write Whoops - %x\n", result);
-			return -EIO;
-		}
-		bytes_written += copy_size;
-		count -= copy_size;
-		buffer += copy_size;
-	} while ( count > 0 );
-	
-	return bytes_written ? bytes_written : -EIO;
-}
-
-static ssize_t
-read_scanner(struct file * file, char * buffer,
-             size_t count, loff_t *ppos)
-{
-	struct hpscan_usb_data *hps = &hpscan;
-
-	ssize_t read_count;
-
-	unsigned long partial;
-
-	int this_read;
-	int result;
-
-/* Wait for the scanner to get it's act together.  This may involve
- * resetting the head, warming up the lamp, etc.  maxretry is number
- * of seconds.  */
-	int maxretry = 30; 
-
-	char *ibuf = hps->ibuf;
-
-	read_count = 0;
-
-	while (count) {
-		if (signal_pending(current)) {
-			return read_count ? read_count : -EINTR;
-		}
-		if (!hps->hpscan_dev)
-			return -ENODEV;
-		this_read = (count > IBUF_SIZE) ? IBUF_SIZE : count;
-		
-		result = usb_bulk_msg(hps->hpscan_dev, usb_rcvbulkpipe(hps->hpscan_dev, 1), ibuf, this_read, &partial, HZ*10);
-
-		printk(KERN_DEBUG "read stats: result:%d this_read:%u partial:%lu\n", result, this_read, partial);
-		
-		if (partial) {
-			count = this_read = partial;
-		} else if (result == USB_ST_TIMEOUT || result == 15) { 	/* FIXME: 15 ??? */
-			if(!maxretry--) {
-				printk(KERN_DEBUG "read_scanner: maxretry timeout\n");
-				return -ETIME;
-			}
-			interruptible_sleep_on_timeout(&hps->wait_q, NAK_TIMEOUT);
-			continue;
-		} else if (result != USB_ST_DATAUNDERRUN) {
-			printk("Read Whoops - result:%u partial:%lu this_read:%u\n", result, partial, this_read);
-			return -EIO;
-		} else {
-			return (0);
-		}
-		
-		if (this_read) {
-			if (copy_to_user(buffer, ibuf, this_read))
-				return -EFAULT;
-			count -= this_read;
-			read_count += this_read;
-			buffer += this_read;
-		}
-	}
-	return read_count;
-}
-
-static void *
-probe_scanner(struct usb_device *dev, unsigned int ifnum)
-{
-	struct hpscan_usb_data *hps = &hpscan;
-
-	/*
-	 * Don't bother using an HP 4200C since it does NOT understand
-	 * SCL and HP isn't going to be releasing the specs any time
-	 * soon.  */
-	if (dev->descriptor.idVendor != 0x3f0 ) {
-		printk(KERN_INFO "Scanner is not an HP Scanner.\n");
-		return NULL;
-	}
-
-	if (dev->descriptor.idProduct != 0x101 && /* HP 4100C */
-	    dev->descriptor.idProduct != 0x202 && /* HP 5100C */
-            dev->descriptor.idProduct != 0x601) { /* HP 6300C */
-		printk(KERN_INFO "Scanner model not supported/tested.\n");
-		return NULL;
-	}
-	
-	printk(KERN_DEBUG "USB Scanner found at address %d\n", dev->devnum);
-	
-	hps->present = 1;
-	hps->hpscan_dev = dev;
-
-	if (!(hps->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
-		return NULL;
-	}
-
-	if (!(hps->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
-		return NULL;
-	}
-  
-	return hps;
-}
-
-static void
-disconnect_scanner(struct usb_device *dev, void *ptr)
-{
-	struct hpscan_usb_data *hps = (struct hpscan_usb_data *) ptr;
-
-	if (hps->isopen) {
-		/* better let it finish - the release will do whats needed */
-		hps->hpscan_dev = NULL;
-		return;
-	}
-	kfree(hps->ibuf);
-	kfree(hps->obuf);
-
-	hps->present = 0;
-}
-
-static struct
-file_operations usb_scanner_fops = {
-	NULL,		/* seek */
-	read_scanner,
-	write_scanner,
-	NULL,		/* readdir */
-	NULL,		/* poll */
-	NULL,    	/* ioctl */
-	NULL,		/* mmap */
-	open_scanner,
-	NULL,		/* flush */
-	close_scanner,
-	NULL,         
-	NULL,         /* fasync */
-};
-
-static struct
-usb_driver scanner_driver = {
-	"usbscanner",
-	probe_scanner,
-	disconnect_scanner,
-	{ NULL, NULL },
-	&usb_scanner_fops,
-	48
-};
-
-int
-usb_hp_scanner_init(void)
-{
-	if (usb_register(&scanner_driver) < 0)
-		return -1;
-
-	printk(KERN_DEBUG "USB Scanner support registered.\n");
-	return 0;
-}
-
-
-void
-usb_hp_scanner_cleanup(void)
-{
-	struct hpscan_usb_data *hps = &hpscan;
-
-	hps->present = 0;
-	usb_deregister(&scanner_driver);
-}
-
-#ifdef MODULE
-
-int
-init_module(void)
-{
-	return usb_hp_scanner_init();
-}
-
-void
-cleanup_module(void)
-{
-	usb_hp_scanner_cleanup();
-}
-#endif
-
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.3.34/linux/drivers/usb/hub.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/hub.c	Tue Dec 28 10:24:11 1999
@@ -4,6 +4,8 @@
  * (C) Copyright 1999 Linus Torvalds
  * (C) Copyright 1999 Johannes Erdfelt
  * (C) Copyright 1999 Gregory P. Smith
+ *
+ * $Id: hub.c,v 1.15 1999/12/27 15:17:45 acher Exp $
  */
 
 #include <linux/kernel.h>
@@ -45,6 +47,12 @@
 		USB_DT_HUB << 8, 0, data, size, HZ);
 }
 
+static int usb_clear_hub_feature(struct usb_device *dev,  int feature)
+{
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0 , NULL, 0, HZ);
+}
+
 static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
 {
 	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -190,7 +198,6 @@
 	printk(KERN_INFO "hub: enabling power on all ports\n");
 	for (i = 0; i < hub->nports; i++)
 		usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
-
 	return 0;
 }
 
@@ -305,7 +312,9 @@
 	struct usb_device *usb;
 	struct usb_port_status portsts;
 	unsigned short portstatus, portchange;
+	int tries;
 
+	wait_ms(100);
 	/* Check status */
 	if (usb_get_port_status(hub, port + 1, &portsts)<0) {
 		printk(KERN_ERR "get_port_status failed\n");
@@ -314,7 +323,8 @@
 
 	portstatus = le16_to_cpu(portsts.wPortStatus);
 	portchange = le16_to_cpu(portsts.wPortChange);
-	printk("hub.c: portstatus %x, change %x\n",portstatus,portchange);
+	printk("hub.c: portstatus %x, change %x, %s\n",portstatus,portchange,
+	(portstatus&(1<<USB_PORT_FEAT_LOWSPEED)?"Low Speed":"High Speed"));
 	/* If it's not in CONNECT and ENABLE state, we're done */
 	if ((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
 	    (!(portstatus & USB_PORT_STAT_ENABLE))) {
@@ -324,10 +334,37 @@
 		return;
 	}
 	wait_ms(400);	
+
 	/* Reset the port */
-	usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
-	wait_ms(100);	
+
+#define MAX_TRIES 5
+	
+	for(tries=0;tries<MAX_TRIES;tries++) {
+		
+		usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
+		wait_ms(200);	
+		
+		if (usb_get_port_status(hub, port + 1, &portsts)<0) {
+			printk(KERN_ERR "get_port_status failed\n");
+			return;
+		}
+		portstatus = le16_to_cpu(portsts.wPortStatus);
+		portchange = le16_to_cpu(portsts.wPortChange);
+		printk("hub.c: portstatus %x, change %x, %s\n",portstatus,portchange,
+		(portstatus&(1<<USB_PORT_FEAT_LOWSPEED)?"Low Speed":"High Speed"));
+
+		if ((portstatus&(1<<USB_PORT_FEAT_ENABLE))) 
+			break;
+
+		wait_ms(200);
+	}
+
+	if (tries==MAX_TRIES) {
+		printk("hub.c: Can not enable port %i after %i retries, disabling port\n",port+1,MAX_TRIES);
+		return;
+	}
 	/* Allocate a new device struct for it */
+
 	usb = usb_alloc_dev(hub, hub->bus);
 	if (!usb) {
 		printk(KERN_ERR "couldn't allocate usb_device\n");
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/inits.h linux/drivers/usb/inits.h
--- v2.3.34/linux/drivers/usb/inits.h	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/inits.h	Mon Dec 27 14:01:53 1999
@@ -1,17 +1,24 @@
 int usb_acm_init(void);
+void usb_acm_cleanup(void);
 int usb_audio_init(void);
+int usb_cpia_init(void);
+void usb_cpia_cleanup(void);
+int usb_dc2xx_init(void);
+void usb_dc2xx_cleanup(void);
 int usb_hub_init(void);
 void usb_hub_cleanup(void);
 int usb_kbd_init(void);
+void usb_kbd_cleanup(void);
 void usb_major_init(void);
 void usb_major_cleanup(void);
+int usb_mouse_init(void);
 void usb_mouse_cleanup(void);
-int usb_hp_scanner_init(void);
-void usb_hp_scanner_cleanup(void);
+int usb_scanner_init(void);
+void usb_scanner_cleanup(void);
 int usb_printer_init(void);
-int proc_usb_init (void);
-void proc_usb_cleanup (void);
 int usb_scsi_init(void);
-int usb_serial_init (void);
+int usb_serial_init(void);
 int dabusb_init(void);
 void dabusb_cleanup(void);
+int proc_usb_init(void);
+void proc_usb_cleanup(void);
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/keymap.c linux/drivers/usb/keymap.c
--- v2.3.34/linux/drivers/usb/keymap.c	Sat Oct  9 11:47:50 1999
+++ linux/drivers/usb/keymap.c	Tue Dec 28 10:25:14 1999
@@ -9,7 +9,7 @@
     0x04,  0x05,  0x06,  0x07,  0x08,  0x09,  0x0a,  0x0b,
     0x1c,  0x01,  0x0e,  0x0f,  0x39,  0x0c,  0x0d,  0x1a,
 
-    0x1b,  0x2b,  0x00,  0x27,  0x28,  0x29,  0x33,  0x34,
+    0x1b,  0x2b,  0x2b,  0x27,  0x28,  0x29,  0x33,  0x34,
     0x35,  0x3a,  0x3b,  0x3c,  0x3d,  0x3e,  0x3f,  0x40,
 
     0x41,  0x42,  0x43,  0x44,  0x57,  0x58,  0xb7,  0x46,
@@ -18,7 +18,7 @@
     0xcb,  0xd0,  0xc8,  0x45,  0xb5,  0x37,  0x4a,  0x4e,
     0x9c,  0x4f,  0x50,  0x51,  0x4b,  0x4c,  0x4d,  0x47,
 
-    0x48,  0x49,  0x52,  0x53,  0x00,  0x6d,  0x00,  0x00,
+    0x48,  0x49,  0x52,  0x53,  0x56,  0x6d,  0x00,  0x00,
     0xbd,  0xbe,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
 
     0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/mouse.c linux/drivers/usb/mouse.c
--- v2.3.34/linux/drivers/usb/mouse.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/mouse.c	Tue Dec 28 10:24:11 1999
@@ -236,22 +236,38 @@
 
 /*
  * Look like a PS/2 mouse, please..
- *
+ * In XFree86 (3.3.5 tested) you must select Protocol "NetMousePS/2",
+ * then use your wheel as Button 4 and 5 via ZAxisMapping 4 5.
  * The PS/2 protocol is fairly strange, but
  * oh, well, it's at least common..
  */
 static ssize_t read_mouse(struct file * file, char * buffer, size_t count, loff_t *ppos)
 {
+	DECLARE_WAITQUEUE(wait, current);
 	int retval = 0;
 	static int state = 0;
 	struct mouse_state *mouse = &static_mouse_state;
 
 	if (!mouse->present)
 		return 0;
-	/*
-	 * FIXME - Other mouse drivers handle blocking and nonblocking reads
-	 * differently here...
-	 */
+
+	if (!mouse->ready) {
+		if (file->f_flags & O_NONBLOCK) return -EAGAIN;
+
+		add_wait_queue(&mouse->wait, &wait);
+repeat:
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (!mouse->ready && !signal_pending(current)) {
+			schedule();
+		goto repeat;
+		}
+		current->state = TASK_RUNNING;
+		remove_wait_queue(&mouse->wait, &wait);
+	}
+	if (signal_pending(current)) return -ERESTARTSYS;
+
+	if (!mouse->present)
+		return 0;
 	if (count) {
 		mouse->ready = 0;
 		switch (state) {
@@ -389,7 +405,7 @@
 	{
 		printk(KERN_DEBUG "%s(%d): mouse resume\n", __FILE__, __LINE__);
 		/* restart the usb controller's polling of the mouse */
-		
+
 		pipe = usb_rcvintpipe(mouse->dev, mouse->bEndpointAddress);
 		FILL_INT_URB(mouse->urb,mouse->dev,pipe,
 			     mouse->buffer,
@@ -411,10 +427,11 @@
 static void mouse_disconnect(struct usb_device *dev, void *priv)
 {
 	struct mouse_state *mouse = priv;
-
+	
 	/* stop the usb interrupt transfer */
 	if (mouse->present) {
-	  usb_unlink_urb(mouse->urb);
+		usb_unlink_urb(mouse->urb);
+		wake_up(&mouse->wait);
 	}
 
 	/* this might need work */
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/printer.c linux/drivers/usb/printer.c
--- v2.3.34/linux/drivers/usb/printer.c	Thu Nov 18 20:25:37 1999
+++ linux/drivers/usb/printer.c	Mon Dec 27 14:01:05 1999
@@ -1,4 +1,3 @@
-
 /* Driver for USB Printers
  * 
  * Copyright 1999 Michael Gee (michael@linuxspecific.com)
@@ -22,10 +21,21 @@
 
 #include "usb.h"
 
+/* Define IEEE_DEVICE_ID if you want to see the IEEE-1284 Device ID string.
+ * This may include the printer's serial number.
+ * An example from an HP 970C DeskJet printer is (this is one long string,
+ * with the serial number changed):
+MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:Hewlett-Packard DeskJet 970C;SERN:US970CSEPROF;VSTATUS:$HB0$NC0,ff,DN,IDLE,CUT,K1,C0,DP,NR,KP000,CP027;VP:0800,FL,B0;VJ:                    ;
+ */
+#define IEEE_DEVICE_ID
+
 #define NAK_TIMEOUT (HZ)				/* stall wait for printer */
 #define MAX_RETRY_COUNT ((60*60*HZ)/NAK_TIMEOUT)	/* should not take 1 minute a page! */
 
 #define BIG_BUF_SIZE			8192
+#define SUBCLASS_PRINTERS		1
+#define PROTOCOL_UNIDIRECTIONAL		1
+#define PROTOCOL_BIDIRECTIONAL		2
 
 /*
  * USB Printer Requests
@@ -59,12 +69,16 @@
 static unsigned char printer_read_status(struct pp_usb_data *p)
 {
 	__u8 status;
+	int err;
 	struct usb_device *dev = p->pusb_dev;
 
-	if (usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
+	err = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
 		USB_PRINTER_REQ_GET_PORT_STATUS,
 		USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN,
-		0, 0, &status, 1, HZ)) {
+		0, 0, &status, sizeof(status), HZ);
+	if (err < 0) {
+		printk(KERN_ERR "usblp%d: read_status control_msg error = %d\n",
+			p->minor, err);
  		return 0;
 	}
 	return status;
@@ -81,36 +95,39 @@
 	else if ((status & LP_POUTPA)) {
 		if (last != LP_POUTPA) {
 			last = LP_POUTPA;
-			printk(KERN_INFO "usblp%d out of paper\n", p->minor);
+			printk(KERN_INFO "usblp%d out of paper (%x)\n", p->minor, status);
 		}
 	} else if (!(status & LP_PSELECD)) {
 		if (last != LP_PSELECD) {
 			last = LP_PSELECD;
-			printk(KERN_INFO "usblp%d off-line\n", p->minor);
+			printk(KERN_INFO "usblp%d off-line (%x)\n", p->minor, status);
 		}
 	} else {
 		if (last != LP_PERRORP) {
 			last = LP_PERRORP;
-			printk(KERN_INFO "usblp%d on fire\n", p->minor);
+			printk(KERN_INFO "usblp%d on fire (%x)\n", p->minor, status);
 		}
 	}
 
 	p->last_error = last;
-
 	return status;
 }
 
 static void printer_reset(struct pp_usb_data *p)
 {
 	struct usb_device *dev = p->pusb_dev;
+	int err;
 
-	usb_control_msg(dev, usb_sndctrlpipe(dev,0),
+	err = usb_control_msg(dev, usb_sndctrlpipe(dev,0),
 		USB_PRINTER_REQ_SOFT_RESET,
 		USB_TYPE_CLASS | USB_RECIP_OTHER,
 		0, 0, NULL, 0, HZ);
+	if (err < 0)
+		printk(KERN_ERR "usblp%d: reset control_msg error = %d\n",
+			p->minor, err);
 }
 
-static int open_printer(struct inode * inode, struct file * file)
+static int open_printer(struct inode *inode, struct file *file)
 {
 	struct pp_usb_data *p;
 
@@ -123,10 +140,14 @@
 	p->minor = MINOR(inode->i_rdev);
 
 	if (p->isopen++) {
+		printk(KERN_ERR "usblp%d: printer is already open\n",
+			p->minor);
 		return -EBUSY;
 	}
 	if (!(p->obuf = (char *)__get_free_page(GFP_KERNEL))) {
 		p->isopen = 0;
+		printk(KERN_ERR "usblp%d: cannot allocate memory\n",
+			p->minor);
 		return -ENOMEM;
 	}
 
@@ -140,7 +161,7 @@
 	return 0;
 }
 
-static int close_printer(struct inode * inode, struct file * file)
+static int close_printer(struct inode *inode, struct file *file)
 {
 	struct pp_usb_data *p = file->private_data;
 
@@ -156,8 +177,8 @@
 	return 0;
 }
 
-static ssize_t write_printer(struct file * file,
-       const char * buffer, size_t count, loff_t *ppos)
+static ssize_t write_printer(struct file *file,
+       const char *buffer, size_t count, loff_t *ppos)
 {
 	struct pp_usb_data *p = file->private_data;
 	unsigned long copy_size;
@@ -174,6 +195,7 @@
 		if (copy_from_user(p->obuf, buffer, copy_size))
 			return -EFAULT;
 		maxretry = MAX_RETRY_COUNT;
+
 		while (thistime) {
 			if (!p->pusb_dev)
 				return -ENODEV;
@@ -212,8 +234,8 @@
 	return bytes_written ? bytes_written : -EIO;
 }
 
-static ssize_t read_printer(struct file * file,
-       char * buffer, size_t count, loff_t *ppos)
+static ssize_t read_printer(struct file *file,
+       char *buffer, size_t count, loff_t *ppos)
 {
 	struct pp_usb_data *p = file->private_data;
 	int read_count = 0;
@@ -231,11 +253,14 @@
 		}
 		if (!p->pusb_dev)
 			return -ENODEV;
-		this_read = (count > sizeof(buf)) ? sizeof(buf) : count;
 
+		this_read = (count > sizeof(buf)) ? sizeof(buf) : count;
 		result = usb_bulk_msg(p->pusb_dev,
 			  usb_rcvbulkpipe(p->pusb_dev, p->bulk_in_ep),
 			  buf, this_read, &partial, HZ*20);
+		if (result < 0)
+			printk(KERN_ERR "usblp%d read_printer bulk_msg error = %d\n",
+				p->minor, result);
 
 		/* unlike writes, we don't retry a NAK, just stop now */
 		if (!result & partial)
@@ -251,14 +276,16 @@
 			buffer += this_read;
 		}
 	}
+
 	return read_count;
 }
 
-static void * printer_probe(struct usb_device *dev, unsigned int ifnum)
+static void *printer_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct usb_interface_descriptor *interface;
 	struct pp_usb_data *pp;
 	int i;
+	__u8 status;
 
 	/*
 	 * FIXME - this will not cope with combined printer/scanners
@@ -274,8 +301,9 @@
 
 	/* Let's be paranoid (for the moment). */
 	if (interface->bInterfaceClass != USB_CLASS_PRINTER ||
-	    interface->bInterfaceSubClass != 1 ||
-	    (interface->bInterfaceProtocol != 2 && interface->bInterfaceProtocol != 1) ||
+	    interface->bInterfaceSubClass != SUBCLASS_PRINTERS ||
+	    (interface->bInterfaceProtocol != PROTOCOL_BIDIRECTIONAL &&
+	    interface->bInterfaceProtocol != PROTOCOL_UNIDIRECTIONAL) ||
 	    interface->bNumEndpoints > 2) {
 		return NULL;
 	}
@@ -308,75 +336,89 @@
 			break;
 	}
 	if (i >= MAX_PRINTERS) {
-		printk("No minor table space available for USB Printer\n");
+		printk(KERN_ERR "No minor table space available for new USB printer\n");
 		return NULL;
 	}
 
-	printk(KERN_INFO "USB Printer found at address %d\n", dev->devnum);
+	printk(KERN_INFO "USB printer found at address %d\n", dev->devnum);
 
 	if (!(pp = kmalloc(sizeof(struct pp_usb_data), GFP_KERNEL))) {
-		printk(KERN_DEBUG "usb_printer: no memory!\n");
+		printk(KERN_DEBUG "USB printer: no memory!\n");
 		return NULL;
 	}
 
 	memset(pp, 0, sizeof(struct pp_usb_data));
 	minor_data[i] = PPDATA(pp);
-	minor_data[i]->minor = i;
-	minor_data[i]->pusb_dev = dev;
-	minor_data[i]->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE;
-	if (interface->bInterfaceProtocol != 2)		/* if not bidirectional */
-		minor_data[i]->noinput = 1;
 
-	minor_data[i]->bulk_out_index =
+	pp->minor = i;
+	pp->pusb_dev = dev;
+	pp->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE;
+	if (interface->bInterfaceProtocol != PROTOCOL_BIDIRECTIONAL)
+		pp->noinput = 1;
+
+	pp->bulk_out_index =
 		((interface->endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK)
 		  == USB_DIR_OUT) ? 0 : 1;
-	minor_data[i]->bulk_in_index = minor_data[i]->noinput ? -1 :
-		(minor_data[i]->bulk_out_index == 0) ? 1 : 0;
-	minor_data[i]->bulk_in_ep = minor_data[i]->noinput ? -1 :
-		interface->endpoint[minor_data[i]->bulk_in_index].bEndpointAddress &
+	pp->bulk_in_index = pp->noinput ? -1 :
+		(pp->bulk_out_index == 0) ? 1 : 0;
+	pp->bulk_in_ep = pp->noinput ? -1 :
+		interface->endpoint[pp->bulk_in_index].bEndpointAddress &
 		USB_ENDPOINT_NUMBER_MASK;
-	minor_data[i]->bulk_out_ep =
-		interface->endpoint[minor_data[i]->bulk_out_index].bEndpointAddress &
+	pp->bulk_out_ep =
+		interface->endpoint[pp->bulk_out_index].bEndpointAddress &
 		USB_ENDPOINT_NUMBER_MASK;
-	if (interface->bInterfaceProtocol == 2) {	/* if bidirectional */
-		minor_data[i]->maxin =
-			interface->endpoint[minor_data[i]->bulk_in_index].wMaxPacketSize;
+	if (interface->bInterfaceProtocol == PROTOCOL_BIDIRECTIONAL) {
+		pp->maxin =
+			interface->endpoint[pp->bulk_in_index].wMaxPacketSize;
 	}
 
-	printk(KERN_INFO "USB Printer Summary:\n");
-	printk(KERN_INFO "index=%d, maxout=%d, noinput=%d\n",
-		i, minor_data[i]->maxout, minor_data[i]->noinput);
+	printk(KERN_INFO "usblp%d Summary:\n", pp->minor);
+	printk(KERN_INFO "index=%d, maxout=%d, noinput=%d, maxin=%d\n",
+		i, pp->maxout, pp->noinput, pp->maxin);
 	printk(KERN_INFO "bulk_in_ix=%d, bulk_in_ep=%d, bulk_out_ix=%d, bulk_out_ep=%d\n",
-		minor_data[i]->bulk_in_index,
-		minor_data[i]->bulk_in_ep,
-		minor_data[i]->bulk_out_index,
-		minor_data[i]->bulk_out_ep);
+		pp->bulk_in_index,
+		pp->bulk_in_ep,
+		pp->bulk_out_index,
+		pp->bulk_out_ep);
 
-#if 0
+#ifdef IEEE_DEVICE_ID
 	{
-		__u8 status;
-		__u8 ieee_id[64];
+		__u8 ieee_id[64]; /* first 2 bytes are (big-endian) length */
+				/* This string space may be too short. */
+		int length = (ieee_id[0] << 8) + ieee_id[1]; /* high-low */
+				/* This calc. or be16_to_cpu() both get
+				 * some weird results for <length>. */
+		int err;
 
 		/* Let's get the device id if possible. */
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
+		err = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
 		    USB_PRINTER_REQ_GET_DEVICE_ID,
 		    USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN,
 		    0, 0, ieee_id,
-		    sizeof(ieee_id)-1, HZ) == 0) {
+		    sizeof(ieee_id)-1, HZ);
+		if (err >= 0) {
 			if (ieee_id[1] < sizeof(ieee_id) - 1)
 				ieee_id[ieee_id[1]+2] = '\0';
 			else
 				ieee_id[sizeof(ieee_id)-1] = '\0';
-			printk(KERN_INFO "  USB Printer ID is %s\n",
-				&ieee_id[2]);
+			printk(KERN_INFO "usblp%d Device ID length=%d [%x:%x]\n",
+				pp->minor, length, ieee_id[0], ieee_id[1]);
+			printk(KERN_INFO "usblp%d Device ID=%s\n",
+				pp->minor, &ieee_id[2]);
 		}
-		status = printer_read_status(PPDATA(pp));
-		printk(KERN_INFO "  Status is %s,%s,%s\n",
-		       (status & LP_PSELECD) ? "Selected" : "Not Selected",
-		       (status & LP_POUTPA)  ? "No Paper" : "Paper",
-		       (status & LP_PERRORP) ? "No Error" : "Error");
+		else
+			printk(KERN_INFO "usblp%d: error = %d reading IEEE-1284 Device ID\n",
+				pp->minor, err);
 	}
 #endif
+
+	status = printer_read_status(PPDATA(pp));
+	printk(KERN_INFO "usblp%d probe status is %x: %s,%s,%s\n",
+		pp->minor, status,
+		(status & LP_PSELECD) ? "Selected" : "Not Selected",
+		(status & LP_POUTPA)  ? "No Paper" : "Paper",
+		(status & LP_PERRORP) ? "No Error" : "Error");
+
 	return pp;
 }
 
@@ -422,7 +464,7 @@
 	if (usb_register(&printer_driver))
 		return -1;
 
-	printk(KERN_INFO "USB Printer support registered.\n");
+	printk(KERN_INFO "USB Printer driver registered.\n");
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/proc_usb.c linux/drivers/usb/proc_usb.c
--- v2.3.34/linux/drivers/usb/proc_usb.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/proc_usb.c	Wed Dec 22 11:04:50 1999
@@ -381,22 +381,12 @@
 	return start;
 }
 
-static char *usb_dump_string(char *start, char *end, const struct usb_device *dev, char *id, int index)
-{
-	if (start > end)
-		return start;
-	start += sprintf(start, "Interface:");
-	if (index <= dev->maxstring && dev->stringindex && dev->stringindex[index])
-		start += sprintf(start, "%s: %s ", id, dev->stringindex[index]);
-	return start;
-}
-
 #endif /* PROC_EXTRA */
 
 /*****************************************************************/
 
 static char *usb_device_dump(char *start, char *end, const struct usb_device *usbdev,
-			     int bus, int level, int index, int count)
+			     const struct usb_bus *bus, int level, int index, int count)
 {
 	int chix;
 	int cnt = 0;
@@ -410,7 +400,7 @@
 	 * So the root hub's parent is 0 and any device that is
 	 * plugged into the root hub has a parent of 0.
 	 */
-	start += sprintf(start, format_topo, bus, level, parent_devnum, index, count,
+	start += sprintf(start, format_topo, bus->busnum-1, level, parent_devnum, index, count,
 			 usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild);
 	/*
 	 * level = topology-tier level;
@@ -418,11 +408,18 @@
 	 * index = parent's connector number;
 	 * count = device count at this level
 	 */
-	/* do not dump descriptors for root hub */
-	if (usbdev->devnum >= 0)
-		start = usb_dump_desc(start, end, usbdev);
+	/* If this is the root hub, display the bandwidth information */
+	if (level == 0)
+		start += sprintf(start, format_bandwidth, bus->bandwidth_allocated, 
+				FRAME_TIME_MAX_USECS_ALLOC,
+				(100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
+			         bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
+
+	/* show the descriptor information for this device */
+	start = usb_dump_desc(start, end, usbdev);
 	if (start > end)
 		return start + sprintf(start, "(truncated)\n");
+
 	/* Now look at all of this device's children. */
 	for (chix = 0; chix < usbdev->maxchild; chix++) {
 		if (start > end)
@@ -440,7 +437,6 @@
 	char *page, *end;
 	ssize_t ret = 0;
 	unsigned int pos, len;
-	int busnum = 0;
 
 	if (*ppos < 0)
 		return -EINVAL;
@@ -453,13 +449,9 @@
 	pos = *ppos;
 	usb_bus_list = usb_bus_get_list();
 	/* enumerate busses */
-	for (buslist = usb_bus_list->next; buslist != usb_bus_list; buslist = buslist->next, ++busnum) {
-		/* print bandwidth allocation */
+	for (buslist = usb_bus_list->next; buslist != usb_bus_list; buslist = buslist->next) {
 		bus = list_entry(buslist, struct usb_bus, bus_list);
-		len = sprintf(page, format_bandwidth, bus->bandwidth_allocated, FRAME_TIME_MAX_USECS_ALLOC,
-			      (100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
-			      bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
-		end = usb_device_dump(page + len, page + (PAGE_SIZE - 100), bus->root_hub, busnum, 0, 0, 0);
+		end = usb_device_dump(page, page + (PAGE_SIZE - 100), bus->root_hub, bus, 0, 0, 0);
 		len = end - page;
 		if (len > pos) {
 			len -= pos;
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/scanner.c linux/drivers/usb/scanner.c
--- v2.3.34/linux/drivers/usb/scanner.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/scanner.c	Mon Dec 27 14:01:53 1999
@@ -0,0 +1,516 @@
+/* -*- linux-c -*- */
+
+/* 
+ * Driver for USB Scanners (linux-2.3.33)
+ *
+ * David E. Nelson (dnelson@jump.net)
+ * 
+ * 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.
+ *
+ * Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
+ *
+ * History
+ *  0.1  8/31/1999
+ *
+ *    Developed/tested using linux-2.3.15 with minor ohci.c changes to
+ *    support short packes during bulk xfer mode.  Some testing was
+ *    done with ohci-hcd but the performace was low.  Very limited
+ *    testing was performed with uhci but I was unable to get it to
+ *    work.  Initial relase to the linux-usb development effort.
+ *
+ *  0.2  10/16/1999
+ *
+ *    FIXED:
+ *    - Device can't be opened unless a scanner is plugged into the USB.
+ *    - Finally settled on a reasonable value for the I/O buffer's.
+ *    - Cleaned up write_scanner()
+ *    - Disabled read/write stats
+ *    - A little more code cleanup
+ *
+ *  0.3  10/18/1999
+ *
+ *    FIXED:
+ *    - Device registration changed to reflect new device
+ *      allocation/registration for linux-2.3.22+.
+ *    - Adopted David Brownell's <david-b@pacbell.net> technique for 
+ *      assigning bulk endpoints.
+ *    - Removed unnessesary #include's
+ *    - Scanner model now reported via syslog INFO after being detected 
+ *      *and* configured.
+ *    - Added user specified verdor:product USB ID's which can be passed 
+ *      as module parameters.
+ *
+ *  0.3.1
+ *    FIXED:
+ *    - Applied patches for linux-2.3.25.
+ *    - Error number reporting changed to reflect negative return codes.
+ *
+ *  0.3.2
+ *    FIXED:
+ *    - Applied patches for linux-2.3.26 to scanner_init().
+ *    - Debug read/write stats now report values as signed decimal.
+ *
+ *
+ *  0.3.3
+ *    FIXED:
+ *    - Updated the bulk_msg() calls to usb usb_bulk_msg().
+ *    - Added a small delay in the write_scanner() method to aid in
+ *      avoiding NULL data reads on HP scanners.  We'll see how this works.
+ *    - Return values from usb_bulk_msg() now ignore positive values for
+ *      use with the ohci driver.
+ *    - Added conditional debugging instead of commenting/uncommenting
+ *      all over the place.
+ *    - kfree()'d the pointer after using usb_string() as documented in
+ *      linux-usb-api.txt.
+ *    - Added usb_set_configuration().  It got lost in version 0.3 -- ack!
+ *    - Added the HP 5200C USB Vendor/Product ID's
+ *
+ *  TODO
+ *    - Simultaneous multiple device attachment
+ *    - ioctl()'s ?
+ *
+ *  Thanks to:
+ *    - All the folks on the linux-usb list who put up with me. :)  This 
+ *      has been a great learning experience for me.
+ *    - To Linus Torvalds for this great OS.
+ *    - The GNU folks.
+ *    - The folks that forwarded Vendor:Product ID's to me.
+ *    - And anybody else who chimed in with reports and suggestions.
+ *
+ *  Performance:
+ *    System: Pentium 120, 80 MB RAM, OHCI, Linux 2.3.23, HP 4100C USB Scanner
+ *            300 dpi scan of the entire bed
+ *      24 Bit Color ~ 70 secs - 3.6 Mbit/sec
+ *       8 Bit Gray  ~ 17 secs - 4.2 Mbit/sec
+ * */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+
+#include "usb.h"
+
+// #define SCN_DBG /* Enable to print results of read/write_scanner() calls */
+// #define RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */
+// #define WR_DATA_DUMP
+
+#ifdef SCN_DBG
+#define SCN_DEBUG(X) X
+#else
+#define SCN_DEBUG(X)
+#endif
+
+#define IBUF_SIZE 32768
+#define OBUF_SIZE 4096
+
+struct hpscan_usb_data {
+	struct usb_device *hpscan_dev;
+        int isopen;		/* Not zero if the device is open */
+	int present;		/* Device is present on the bus */
+	char *obuf, *ibuf;	/* transfer buffers */
+	char iep, oep;          /* I/O Endpoints */
+};
+
+static struct hpscan_usb_data hpscan;
+
+MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson");
+MODULE_DESCRIPTION("USB Scanner Driver");
+
+static __u16 vendor=0, product=0;
+MODULE_PARM(vendor, "i");
+MODULE_PARM_DESC(vendor, "User specified USB idVendor");
+
+MODULE_PARM(product, "i");
+MODULE_PARM_DESC(product, "User specified USB idProduct");
+
+static int
+open_scanner(struct inode * inode, struct file * file)
+{
+	struct hpscan_usb_data *hps = &hpscan;
+
+	if (!hps->present) {
+		return -ENODEV;
+	}
+
+	if (!hps->hpscan_dev) {
+		return -ENODEV;
+	}
+
+	if (hps->isopen) {
+		return -EBUSY;
+	}
+
+	hps->isopen = 1;
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+static int
+close_scanner(struct inode * inode, struct file * file)
+{
+	struct hpscan_usb_data *hps = &hpscan;
+
+	hps->isopen = 0;
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+static ssize_t
+write_scanner(struct file * file, const char * buffer,
+              size_t count, loff_t *ppos)
+{
+	struct hpscan_usb_data *hps = &hpscan;
+
+	unsigned long copy_size;
+	unsigned long bytes_written = 0;
+	unsigned long partial;
+
+	ssize_t ret = 0;
+
+	int result = 0;
+	
+	char *obuf = hps->obuf;
+
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	while (count > 0) {
+
+		if (signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+
+		copy_size = (count > OBUF_SIZE) ? OBUF_SIZE : count;
+		
+		if (copy_from_user(hps->obuf, buffer, copy_size)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		result = usb_bulk_msg(hps->hpscan_dev,usb_sndbulkpipe(hps->hpscan_dev, hps->oep), obuf, copy_size, &partial, 30*HZ);
+		SCN_DEBUG(printk(KERN_DEBUG "write stats: result:%d copy_size:%lu partial:%lu\n", (int)result, copy_size, partial);)
+
+		if (result == USB_ST_TIMEOUT) {	/* NAK -- shouldn't happen */
+			printk(KERN_WARNING "write_scanner: NAK recieved.\n");
+			ret = -ETIME;
+			break;
+		} else if (result < 0) { /* We should not get any I/O errors */
+			printk(KERN_WARNING "write_scanner: funky result: %d. Please notify the maintainer.\n", result);
+			ret = -EIO;
+			break;
+		} 
+
+#ifdef WR_DATA_DUMP
+		if (partial) {
+			unsigned char cnt, cnt_max;
+			cnt_max = (partial > 24) ? 24 : partial;
+			printk(KERN_DEBUG "dump: ");
+			for (cnt=0; cnt < cnt_max; cnt++) {
+				printk("%X ", obuf[cnt]);
+			}
+			printk("\n");
+		}
+#endif
+		if (partial != copy_size) { /* Unable to write complete amount */
+			ret = -EIO;
+			break;
+		}
+
+		if (partial) { /* Data written */
+			obuf += partial;
+			count -= partial;
+			bytes_written += partial;
+		} else { /* No data written */
+			ret = 0;
+			bytes_written = 0;
+			break;
+		}
+	}
+//	mdelay(5);
+	set_current_state(TASK_RUNNING);
+	return ret ? ret : bytes_written;
+}
+
+static ssize_t
+read_scanner(struct file * file, char * buffer,
+             size_t count, loff_t *ppos)
+{
+	struct hpscan_usb_data *hps = &hpscan;
+
+	ssize_t read_count, ret = 0;
+
+	unsigned long partial;
+
+	int this_read;
+	int result;
+
+	char *ibuf = hps->ibuf;
+
+	read_count = 0;
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	while (count) {
+		if (signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+
+		this_read = (count > IBUF_SIZE) ? IBUF_SIZE : count;
+		
+		result = usb_bulk_msg(hps->hpscan_dev, usb_rcvbulkpipe(hps->hpscan_dev, hps->iep), ibuf, this_read, &partial, 60*HZ);
+		SCN_DEBUG(printk(KERN_DEBUG "read stats: result:%d this_read:%u partial:%lu\n", (int)result, this_read, partial);)
+
+		if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */
+			printk(KERN_WARNING "read_scanner: NAK received\n");
+			ret = -ETIME;
+			break;
+		} else if ((result < 0) && (result != USB_ST_DATAUNDERRUN)) {
+			printk(KERN_WARNING "read_scanner: funky result: %d. Please notify the maintainer.\n", (int)result);
+			ret = -EIO;
+			break;
+		}
+
+#ifdef RD_DATA_DUMP
+		if (partial) {
+			unsigned char cnt, cnt_max;
+			cnt_max = (partial > 24) ? 24 : partial;
+			printk(KERN_DEBUG "dump: ");
+			for (cnt=0; cnt < cnt_max; cnt++) {
+				printk("%X ", ibuf[cnt]);
+			}
+			printk("\n");
+		}
+#endif
+
+		if (partial) { /* Data returned */
+			count = this_read = partial;
+		} else {
+			ret = 0;
+			read_count = 0;
+			break;
+		}
+
+		if (this_read) {
+			if (copy_to_user(buffer, ibuf, this_read)) {
+				ret = -EFAULT;
+				break;
+			}
+			count -= this_read;
+			read_count += this_read;
+			buffer += this_read;
+		}
+	}
+	set_current_state(TASK_RUNNING);
+	return ret ? ret : read_count;
+}
+
+static void *
+probe_scanner(struct usb_device *dev, unsigned int ifnum)
+{
+	struct hpscan_usb_data *hps = &hpscan;
+	struct usb_endpoint_descriptor *endpoint;
+
+	char *ident;
+
+	hps->present = 0;
+
+	if (vendor != 0 || product != 0) {
+		printk(KERN_INFO "USB Scanner Vendor:Product - %x:%x\n", vendor, product);
+	}
+
+/* There doesn't seem to be an imaging class defined in the USB
+ * Spec. (yet).  If there is, HP isn't following it and it doesn't
+ * look like anybody else is either.  Therefore, we have to test the
+ * Vendor and Product ID's to see what we have.  This makes this
+ * driver a high maintenance driver since it has to be updated with
+ * each release of a product.  Also, other scanners may be able to use
+ * this driver but again, their Vendor and Product ID's must be added.
+ *
+ * NOTE: Just because a product is supported here does not mean that
+ * applications exist that support the product.  It's in the hopes
+ * that this will allow developers a means to produce applications
+ * that will support USB products.
+ *
+ * Until we detect a device which is pleasing, we silently punt.
+ * */
+
+	if (dev->descriptor.idVendor != 0x03f0 && /* Hewlett Packard */
+	    dev->descriptor.idVendor != 0x06bd && /* AGFA */
+	    dev->descriptor.idVendor != 0x1606 && /* UMAX */
+	    dev->descriptor.idVendor != vendor ) { /* User specified */
+		return NULL;
+	}
+
+	if (dev->descriptor.idProduct != 0x0101 && /* HP 4100C */
+	    dev->descriptor.idProduct != 0x0102 && /* HP 4200C & PhotoSmart S20? */
+	    dev->descriptor.idProduct != 0x0202 && /* HP 5100C */
+	    dev->descriptor.idProduct != 0x0401 && /* HP 5200C */
+	    dev->descriptor.idProduct != 0x0201 && /* HP 6200C */
+	    dev->descriptor.idProduct != 0x0601 && /* HP 6300C */
+	    dev->descriptor.idProduct != 0x0001 && /* AGFA SnapScan 1212U */
+	    dev->descriptor.idProduct != 0x0030 && /* Umax 2000U */
+	    dev->descriptor.idProduct != product) { /* User specified */
+		return NULL;
+	}
+
+/* After this point we can be a little noisy about what we are trying to
+ *  configure. */
+
+	if (dev->descriptor.bNumConfigurations != 1 || 
+	    dev->config[0].bNumInterfaces != 1) {
+		printk(KERN_INFO "probe_scanner: only simple configurations supported\n");
+		return NULL;
+	}
+
+	endpoint = dev->config[0].interface[0].altsetting[0].endpoint;
+
+	if (endpoint[0].bmAttributes != USB_ENDPOINT_XFER_BULK
+	    || endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK) {
+		printk(KERN_INFO "probe_scanner: invalid bulk endpoints\n");
+		return NULL;
+	}
+
+	if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
+                printk (KERN_INFO "probe_scanner: failed usb_set_configuration\n");
+		hps->hpscan_dev = NULL;
+                return NULL;
+        }
+
+/* By the time we get here, we should be dealing with a fairly simple
+ * device that supports at least two bulk endpoints on endpoints 1 and
+ * 2.
+ *
+ * We determine the bulk endpoints so that the read_*() and write_*()
+ * procedures can recv/send data to the correct endpoint.
+ * */
+
+	hps->iep = hps->oep = 0;
+
+	if ((endpoint[0].bEndpointAddress & 0x80) == 0x80) {
+		hps->iep = endpoint[0].bEndpointAddress & 0x7f;
+	} else {
+		hps->oep = endpoint[0].bEndpointAddress;
+	}
+
+	if ((endpoint[1].bEndpointAddress & 0x80) == 0x80) {
+		hps->iep = endpoint[1].bEndpointAddress & 0x7f;
+	} else {
+		hps->oep = endpoint[1].bEndpointAddress;
+	}
+
+	ident = usb_string(dev, dev->descriptor.iProduct); /* usb_string allocates memory using kmalloc() so kfree() needs to be called afterwards when the pointer is no longer needed. */
+	printk(KERN_INFO "USB Scanner (%s) found at address %d\n", ident, dev->devnum);
+	kfree(ident);
+
+	SCN_DEBUG(printk(KERN_DEBUG "probe_scanner: using bulk endpoints - In: %x  Out: %x\n", hps->iep, hps->oep);)
+
+	hps->present = 1;
+	hps->hpscan_dev = dev;
+
+	if (!(hps->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
+		return NULL;
+	}
+
+	if (!(hps->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
+		return NULL;
+	}
+
+	return hps;
+}
+
+static void
+disconnect_scanner(struct usb_device *dev, void *ptr)
+{
+	struct hpscan_usb_data *hps = (struct hpscan_usb_data *) ptr;
+
+	if (hps->isopen) {
+		/* better let it finish - the release will do whats needed */
+		hps->hpscan_dev = NULL;
+		return;
+	}
+	kfree(hps->ibuf);
+	kfree(hps->obuf);
+
+	hps->present = 0;
+}
+
+static struct
+file_operations usb_scanner_fops = {
+	NULL,		/* seek */
+	read_scanner,
+	write_scanner,
+	NULL,		/* readdir */
+	NULL,		/* poll */
+	NULL,    	/* ioctl */
+	NULL,		/* mmap */
+	open_scanner,
+	NULL,		/* flush */
+	close_scanner,
+	NULL,         
+	NULL,         /* fasync */
+};
+
+static struct
+usb_driver scanner_driver = {
+       "usbscanner",
+       probe_scanner,
+       disconnect_scanner,
+       { NULL, NULL },
+       &usb_scanner_fops,
+       48
+};
+
+int
+usb_scanner_init(void)
+{
+        if (usb_register(&scanner_driver) < 0)
+                return -1;
+
+	printk(KERN_INFO "USB Scanner support registered.\n");
+	return 0;
+}
+
+
+void
+usb_scanner_cleanup(void)
+{
+	struct hpscan_usb_data *hps = &hpscan;
+
+	hps->present = 0;
+	usb_deregister(&scanner_driver);
+}
+
+#ifdef MODULE
+
+int
+init_module(void)
+{
+	return usb_scanner_init();
+}
+
+void
+cleanup_module(void)
+{
+	usb_scanner_cleanup();
+}
+#endif
+
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.3.34/linux/drivers/usb/uhci.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/uhci.c	Tue Dec 28 10:24:11 1999
@@ -12,7 +12,7 @@
  * (C) Copyright 1999 Johannes Erdfelt
  * (C) Copyright 1999 Randy Dunlap
  *
- * $Id: uhci.c,v 1.139 1999/12/17 17:50:59 fliegl Exp $
+ * $Id: uhci.c,v 1.149 1999/12/26 20:57:14 acher Exp $
  */
 
 
@@ -646,7 +646,7 @@
 	/* Build the TDs for the bulk request */
 	len = purb->transfer_buffer_length;
 	data = purb->transfer_buffer;
-	dbg (KERN_DEBUG MODSTR "uhci_submit_bulk_urb: len %d\n", len);
+	dbg (KERN_DEBUG MODSTR "uhci_submit_bulk_urb: pipe %x, len %d\n", pipe, len);
 	
 	while (len > 0) {
 		int pktsze = len;
@@ -675,7 +675,7 @@
 		//dbg("insert td %p, len %i\n",td,pktsze);
 
 		insert_td (s, qh, td, UHCI_PTR_DEPTH);
-
+		
 		/* Alternate Data0/1 (start with Data0) */
 		usb_dotoggle (purb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
 	}
@@ -701,8 +701,7 @@
 	unsigned long flags=0;
 	struct list_head *p;
 
-	if (!purb)		// you never know... 
-
+	if (!purb)		// you never know...
 		return -1;
 
 	s = (puhci_t) purb->dev->bus->hcpriv;	// get pointer to uhci struct
@@ -720,6 +719,8 @@
 		// URB probably still in work
 		purb_priv = purb->hcpriv;
 		dequeue_urb (s, &purb->urb_list,1);
+		purb->status = USB_ST_URB_KILLED;	// mark urb as killed
+		
 		if(!in_interrupt()) {
 			spin_unlock_irqrestore (&s->unlink_urb_lock, flags);	// allow interrupts from here
 		}
@@ -757,8 +758,7 @@
 			delete_qh (s, qh);		// remove it physically
 
 		}
-		purb->status = USB_ST_URB_KILLED;	// mark urb as killed
-
+		
 #ifdef _UHCI_SLAB
 		kmem_cache_free(urb_priv_kmem, purb->hcpriv);
 #else
@@ -872,11 +872,13 @@
 					now, purb->start_frame, purb->number_of_packets, purb->pipe);
 				{
 					puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
-					struct list_head *p = s->urb_list.next;
+					struct list_head *p;
 					purb_t u;
 					int a = -1, b = -1;
 					unsigned long flags;
+
 					spin_lock_irqsave (&s->urb_list_lock, flags);
+					p=s->urb_list.next;
 
 					for (; p != &s->urb_list; p = p->next) {
 						u = list_entry (p, urb_t, urb_list);
@@ -1093,9 +1095,10 @@
 		// we can accept this urb if it is not queued at this time 
 		// or if non-iso transfer requests should be scheduled for the same device and pipe
 		if ((usb_pipetype (purb->pipe) != PIPE_ISOCHRONOUS &&
-		     tmp->dev == purb->dev && tmp->pipe == purb->pipe) || (purb == tmp))
+		     tmp->dev == purb->dev && tmp->pipe == purb->pipe) || (purb == tmp)) {
+			spin_unlock_irqrestore (&s->urb_list_lock, flags);
 			return 1;	// found another urb already queued for processing
-
+		}
 	}
 
 	spin_unlock_irqrestore (&s->urb_list_lock, flags);
@@ -1122,7 +1125,7 @@
 
 	if (search_dev_ep (s, purb)) {
 		usb_dec_dev_use (purb->dev);
-		return -ENXIO;	// no such address
+		return -ENXIO;	// urb already queued
 
 	}
 
@@ -1379,7 +1382,7 @@
 	for (i = 0; i < 8; i++)
 		uhci->rh.c_p_r[i] = 0;
 
-	dbg (KERN_DEBUG MODSTR "Root-Hub: adr: %2x cmd(%1x): %04 %04 %04 %04\n",
+	dbg(KERN_DEBUG MODSTR "Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x\n",
 	     uhci->rh.devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
 
 	switch (bmRType_bReq) {
@@ -1519,7 +1522,7 @@
 	}
 
 
-	dbg (KERN_DEBUG MODSTR "Root-Hub stat port1: %x port2: %x \n",
+	printk (KERN_DEBUG MODSTR "Root-Hub stat port1: %x port2: %x \n",
 	     inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2));
 
 	purb->actual_length = len;
@@ -1681,27 +1684,32 @@
 		       	uhci_show_td (desc);	// show first TD of each transfer
 #endif
 
-		// go into error condition to keep data_toggle unchanged if short packet occurs
-		if ((purb->transfer_flags & USB_DISABLE_SPD) && (actual_length < maxlength)) {
-			ret = USB_ST_SHORT_PACKET;
-			printk (KERN_DEBUG MODSTR "process_transfer: SPD!!\n");
-			break;	// exit after this TD because SP was detected
+		// got less data than requested
+		if ( (actual_length < maxlength)) {
+			if (purb->transfer_flags & USB_DISABLE_SPD) {
+				ret = USB_ST_SHORT_PACKET;	// treat as real error
+				printk (KERN_DEBUG MODSTR "process_transfer: SPD!!\n");
+				break;	// exit after this TD because SP was detected
+			}
 
+			// short read during control-IN: re-start status stage
+			if ((usb_pipetype (purb->pipe) == PIPE_CONTROL)) {
+				if (uhci_packetid(last_desc->hw.td.info) == USB_PID_OUT) {
+					uhci_show_td (last_desc);
+					qh->hw.qh.element = virt_to_bus (last_desc);  // re-trigger status stage
+					printk("uhci: short packet during control transfer, retrigger status stage @ %p\n",last_desc);
+					purb_priv->short_control_packet=1;
+					return 0;
+				}
+			}
+			// all other cases: short read is OK
+			data_toggle = uhci_toggle (desc->hw.td.info);
+			break;
 		}
 
 		data_toggle = uhci_toggle (desc->hw.td.info);
 		//printk(KERN_DEBUG MODSTR"process_transfer: len:%d status:%x mapped:%x toggle:%d\n", actual_length, desc->hw.td.status,status, data_toggle);      
-#if 1
-		if ((usb_pipetype (purb->pipe) == PIPE_CONTROL) && (actual_length < maxlength)) {
-			if (uhci_packetid(last_desc->hw.td.info) == USB_PID_OUT) {
-				uhci_show_td (last_desc);
-				qh->hw.qh.element = virt_to_bus (last_desc);  // re-trigger status stage
-				printk("uhci: short packet during control transfer, retrigger status stage\n");
-				purb_priv->short_control_packet=1;
-				return 0;
-			}
-		}
-#endif
+
 	}
 	usb_settoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe), !data_toggle);
 	transfer_finished:
@@ -1714,15 +1722,14 @@
 		status & TD_CTRL_NAK )
 	{
 		ret=0;
-		purb->status=0;
+		status=0;
 	}
 
 	unlink_qh (s, qh);
 	delete_qh (s, qh);
 
 	purb->status = status;
-	
-                                                                        	
+	                                                  	
 	dbg(KERN_DEBUG MODSTR"process_transfer: urb %p, wanted len %d, len %d status %x err %d\n",
 		purb,purb->transfer_buffer_length,purb->actual_length, purb->status, purb->error_count);
 	//dbg(KERN_DEBUG MODSTR"process_transfer: exit\n");
@@ -1748,21 +1755,15 @@
 	{
 		desc = list_entry (p, uhci_desc_t, desc_list);
 
-		if (desc->hw.td.status & TD_CTRL_NAK) {
-			// NAKed transfer
-			//printk("TD NAK Status @%p %08x\n",desc,desc->hw.td.status);
-			goto err;
-		}
-
 		if (desc->hw.td.status & TD_CTRL_ACTIVE) {
 			// do not process active TDs
 			//printk("TD ACT Status @%p %08x\n",desc,desc->hw.td.status);
-			goto err;
+			break;
 		}
 
 		if (!desc->hw.td.status & TD_CTRL_IOC) {
-			// do not process one-shot TDs
-			goto err;
+			// do not process one-shot TDs, no recycling
+			break;
 		}
 		// extract transfer parameters from TD
 
@@ -1778,7 +1779,7 @@
 		// if any error occured: ignore this td, and continue
 		if (status != USB_ST_NOERROR) {
 			purb->error_count++;
-			goto err;
+			goto recycle;
 		}
 		else
 			purb->actual_length = actual_length;
@@ -1794,7 +1795,7 @@
 			purb->complete ((struct urb *) purb);
 			purb->status = USB_ST_URB_PENDING;
 		}
-
+	recycle:
 		// Recycle INT-TD if interval!=0, else mark TD as one-shot
 		if (purb->interval) {
 			desc->hw.td.status |= TD_CTRL_ACTIVE;
@@ -1804,10 +1805,9 @@
 			usb_dotoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe));
 		}
 		else {
-			desc->hw.td.status &= ~TD_CTRL_IOC;
+			desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD
 		}
-
-	      err:
+	err:
 	}
 
 	return ret;
@@ -1882,10 +1882,12 @@
 _static int process_urb (puhci_t s, struct list_head *p)
 {
 	int ret = USB_ST_NOERROR;
-	purb_t purb = list_entry (p, urb_t, urb_list);
-	spin_lock(&s->urb_list_lock);
+	purb_t purb;
 
+	spin_lock(&s->urb_list_lock);
+	purb=list_entry (p, urb_t, urb_list);
 	dbg ( /*KERN_DEBUG */ MODSTR "found queued urb: %p\n", purb);
+
 	switch (usb_pipetype (purb->pipe)) {
 	case PIPE_CONTROL:
 	case PIPE_BULK:
@@ -1933,7 +1935,7 @@
 			if (purb->complete && (!proceed || (purb->transfer_flags & USB_URB_EARLY_COMPLETE))) {
 				dbg (KERN_DEBUG MODSTR "process_transfer: calling early completion\n");
 				purb->complete ((struct urb *) purb);
-				if (!proceed && is_ring)
+				if (!proceed && is_ring && (purb->status != USB_ST_URB_KILLED))
 					uhci_submit_urb (purb);
 			}
 
@@ -1942,7 +1944,7 @@
 				tmp = purb->next;	// pointer to first urb
 
 				do {
-					if ((tmp->status != USB_ST_URB_PENDING) && uhci_submit_urb (tmp) != USB_ST_NOERROR)
+					if ((tmp->status != USB_ST_URB_PENDING) && (tmp->status != USB_ST_URB_KILLED) && uhci_submit_urb (tmp) != USB_ST_NOERROR)
 						break;
 					tmp = tmp->next;
 				}
@@ -2160,6 +2162,7 @@
 	start_hc (s);
 
 	if (request_irq (irq, uhci_interrupt, SA_SHIRQ, MODNAME, s)) {
+		printk(MODSTR KERN_ERR"request_irq %d failed!\n",irq);
 		usb_free_bus (bus);
 		reset_hc (s);
 		release_region (s->io_addr, s->io_size);
@@ -2204,9 +2207,6 @@
 		/* Is it already in use? */
 		if (check_region (io_addr, io_size))
 			break;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,8)
-		pci_enable_device (dev);
-#endif
 		/* disable legacy emulation */
 		pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT);
 
@@ -2297,10 +2297,21 @@
 		if (type != 0)
 			continue;
 
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,8)
+		pci_enable_device (dev);
+#endif
+		if(!dev->irq)
+		{
+			printk(KERN_ERR MODSTR"Found UHCI device with no IRQ assigned. Check BIOS settings!\n");
+			continue;
+		}
+
 		/* Ok set it up */
 		retval = start_uhci (dev);
+	
 		if (!retval)
 			i++;
+
 	}
 
 #ifdef CONFIG_APM
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/usb-core.c linux/drivers/usb/usb-core.c
--- v2.3.34/linux/drivers/usb/usb-core.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/usb-core.c	Mon Dec 27 14:01:53 1999
@@ -43,8 +43,8 @@
 #	ifdef CONFIG_USB_MOUSE
 		usb_mouse_init();
 #	endif
-#       ifdef CONFIG_USB_HP_SCANNER
-                usb_hp_scanner_init();
+#       ifdef CONFIG_USB_SCANNER
+                usb_scanner_init();
 #       endif
 #	ifdef CONFIG_USB_KBD
 		usb_kbd_init();
@@ -87,16 +87,28 @@
 	proc_usb_cleanup ();
 #endif
 	usb_hub_cleanup();	
-#ifndef MODULE
 
+#ifndef MODULE
 #	ifdef CONFIG_USB_MOUSE
         	usb_mouse_cleanup();
 #	endif
-#       ifdef CONFIG_USB_HP_SCANNER
-                usb_hp_scanner_cleanup();
+#       ifdef CONFIG_USB_SCANNER
+                usb_scanner_cleanup();
 #       endif
 #	ifdef CONFIG_USB_DABUSB
 		dabusb_cleanup();
+#	endif
+#	ifdef CONFIG_USB_KBD
+		usb_kbd_cleanup();
+#	endif
+#	ifdef CONFIG_USB_ACM
+		usb_acm_cleanup();
+#	endif
+#	ifdef CONFIG_USB_CPIA
+		usb_cpia_cleanup();
+#	endif
+#	ifdef CONFIG_USB_DC2XX
+		usb_dc2xx_cleanup();
 #	endif
 #endif
 }
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/usb-serial.c linux/drivers/usb/usb-serial.c
--- v2.3.34/linux/drivers/usb/usb-serial.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/usb-serial.c	Wed Dec 22 10:53:51 1999
@@ -14,6 +14,13 @@
  *
  * See README.serial for more information on using this driver.
  * 
+ * version 0.2.3 (12/21/99) gkh
+ *	Added initial support for the Connect Tech WhiteHEAT converter.
+ *	Incremented the number of ports in expectation of getting the
+ *	WhiteHEAT to work properly (4 ports per connection).
+ *	Added notification on insertion and removal of what port the
+ *	device is/was connected to (and what kind of device it was).
+ *
  * version 0.2.2 (12/16/99) gkh
  *	Changed major number to the new allocated number. We're legal now!
  *
@@ -88,12 +95,12 @@
 #define BELKIN_SERIAL_CONVERTER		0x8007
 #define PERACOM_VENDOR_ID		0x0565
 #define PERACOM_SERIAL_CONVERTER	0x0001
+#define CONNECT_TECH_VENDOR_ID		0x0710
+#define CONNECT_TECH_WHITE_HEAT_ID	0x0001
 
 
 #define SERIAL_MAJOR	188	/* Nice legal number now */
-
-#define NUM_PORTS	4	/* Have to pick a number for now. Need to look */
-				/* into dynamically creating them at insertion time. */
+#define NUM_PORTS	16	/* Actually we are allowed 255, but this is good for now */
 
 
 static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
@@ -119,26 +126,6 @@
 static void serial_unthrottle (struct tty_struct * tty);
 
 
-/* function prototypes for the eTek type converters (this included Belkin and Peracom) */
-static int etek_serial_open (struct tty_struct *tty, struct file * filp);
-static void etek_serial_close (struct tty_struct *tty, struct file * filp);
-static int etek_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
-static void etek_serial_put_char (struct tty_struct *tty, unsigned char ch);
-static int etek_write_room (struct tty_struct *tty);
-static int etek_chars_in_buffer (struct tty_struct *tty);
-static void etek_throttle (struct tty_struct * tty);
-static void etek_unthrottle (struct tty_struct * tty);
-
-
-/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
-static int generic_serial_open (struct tty_struct *tty, struct file * filp);
-static void generic_serial_close (struct tty_struct *tty, struct file * filp);
-static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
-static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch);
-static int generic_write_room (struct tty_struct *tty);
-static int generic_chars_in_buffer (struct tty_struct *tty);
-
-
 /* This structure defines the individual serial converter. */
 struct usb_serial_device_type {
 	char	*name;
@@ -157,10 +144,17 @@
 	int  (*chars_in_buffer)(struct tty_struct *tty);
 	void (*throttle)(struct tty_struct * tty);
 	void (*unthrottle)(struct tty_struct * tty);
-
 };
 
 
+/* function prototypes for the eTek type converters (this included Belkin and Peracom) */
+static int  etek_serial_open		(struct tty_struct *tty, struct file *filp);
+static void etek_serial_close		(struct tty_struct *tty, struct file *filp);
+static int  etek_serial_write		(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static void etek_serial_put_char	(struct tty_struct *tty, unsigned char ch);
+static int  etek_write_room		(struct tty_struct *tty);
+static int  etek_chars_in_buffer	(struct tty_struct *tty);
+
 /* All of the device info needed for the Belkin Serial Converter */
 static __u16	belkin_vendor_id	= BELKIN_VENDOR_ID;
 static __u16	belkin_product_id	= BELKIN_SERIAL_CONVERTER;
@@ -177,8 +171,8 @@
 	etek_serial_put_char,
 	etek_write_room,
 	etek_chars_in_buffer,
-	etek_throttle,
-	etek_unthrottle
+	NULL,
+	NULL
 };
 
 /* All of the device info needed for the Peracom Serial Converter */
@@ -197,10 +191,50 @@
 	etek_serial_put_char,
 	etek_write_room,
 	etek_chars_in_buffer,
-	etek_throttle,
-	etek_unthrottle
+	NULL,
+	NULL
+};
+
+
+/* function prototypes for the Connect Tech WhiteHEAT serial converter */
+static int  whiteheat_serial_open	(struct tty_struct *tty, struct file *filp);
+static void whiteheat_serial_close	(struct tty_struct *tty, struct file *filp);
+static int  whiteheat_serial_write	(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static void whiteheat_serial_put_char	(struct tty_struct *tty, unsigned char ch);
+static int  whiteheat_write_room	(struct tty_struct *tty);
+static int  whiteheat_chars_in_buffer	(struct tty_struct *tty);
+static void whiteheat_throttle		(struct tty_struct *tty);
+static void whiteheat_unthrottle	(struct tty_struct *tty);
+
+/* All of the device info needed for the Connect Tech WhiteHEAT */
+static __u16	connecttech_vendor_id			= CONNECT_TECH_VENDOR_ID;
+static __u16	connecttech_whiteheat_product_id	= CONNECT_TECH_WHITE_HEAT_ID;
+static struct usb_serial_device_type whiteheat_device = {
+	"Connect Tech - WhiteHEAT",
+	&connecttech_vendor_id,			/* the Connect Tech vendor id */
+	&connecttech_whiteheat_product_id,	/* the White Heat product id */
+	DONT_CARE,		/* don't have to have an interrupt in endpoint */
+	DONT_CARE,		/* don't have to have a bulk in endpoint */
+	DONT_CARE,		/* don't have to have a bulk out endpoint */
+	whiteheat_serial_open,
+	whiteheat_serial_close,
+	whiteheat_serial_write,
+	whiteheat_serial_put_char,
+	whiteheat_write_room,
+	whiteheat_chars_in_buffer,
+	whiteheat_throttle,
+	whiteheat_unthrottle
 };
 
+
+/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
+static int  generic_serial_open		(struct tty_struct *tty, struct file *filp);
+static void generic_serial_close	(struct tty_struct *tty, struct file *filp);
+static int  generic_serial_write	(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static void generic_serial_put_char	(struct tty_struct *tty, unsigned char ch);
+static int  generic_write_room		(struct tty_struct *tty);
+static int  generic_chars_in_buffer	(struct tty_struct *tty);
+
 /* All of the device info needed for the Generic Serial Converter */
 static struct usb_serial_device_type generic_device = {
 	"Generic",
@@ -225,6 +259,7 @@
    entry is NULL. */
 static struct usb_serial_device_type *usb_serial_devices[] = {
 	&generic_device,
+	&whiteheat_device,
 	&belkin_device,
 	&peracom_device,
 	NULL
@@ -238,6 +273,7 @@
 	void *				irq_handle;
 	unsigned int			irqpipe;
 	struct tty_struct *		tty;		/* the coresponding tty for this device */
+	unsigned char			number;
 	char				present;
 	char				active;
 
@@ -292,7 +328,7 @@
        	unsigned char* data = buffer;
 	int i;
 
-	debug_info("USB serial: serial_read_irq\n");
+	debug_info("USB Serial: serial_read_irq\n");
 
 #ifdef SERIAL_DEBUG
 	if (count) {
@@ -340,9 +376,11 @@
 }
 
 
+#if 0
+/* we will need this soon... removed for now to keep the compile warnings down */
 static int usb_serial_irq (int state, void *buffer, int len, void *dev_id)
 {
-//	struct usb_serial_state *serial = (struct usb_serial_state *) dev_id;
+	struct usb_serial_state *serial = (struct usb_serial_state *) dev_id;
 
 	debug_info("USB Serial: usb_serial_irq\n");
 
@@ -352,7 +390,7 @@
 
 	return (1);
 }
-
+#endif
 
 
 
@@ -753,11 +791,141 @@
 }
 
 
-static void etek_throttle (struct tty_struct * tty)
+/*****************************************************************************
+ * Connect Tech's White Heat specific driver functions
+ *****************************************************************************/
+static int whiteheat_serial_open (struct tty_struct *tty, struct file *filp)
 {
 	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
 
-	debug_info("USB Serial: etek_throttle\n");
+	debug_info("USB Serial: whiteheat_serial_open\n");
+
+	if (!serial->present) {
+		debug_info("USB Serial: no device registered\n");
+		return -EINVAL;
+	}
+
+	if (serial->active) {
+		debug_info ("USB Serial: device already open\n");
+		return -EINVAL;
+	}
+	serial->active = 1;
+ 
+	/*Start reading from the device*/
+	serial->bulk_in_inuse = 1;
+	serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial);
+
+	/* Need to do device specific setup here (control lines, baud rate, etc.) */
+	/* FIXME!!! */
+
+	return (0);
+}
+
+
+static void whiteheat_serial_close(struct tty_struct *tty, struct file * filp)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	debug_info("USB Serial: whiteheat_serial_close\n");
+	
+	/* Need to change the control lines here */
+	/* FIXME */
+	
+	/* shutdown our bulk reads and writes */
+	if (serial->bulk_out_inuse){
+		usb_terminate_bulk (serial->dev, serial->bulk_out_transfer);
+		serial->bulk_out_inuse = 0;
+	}
+	if (serial->bulk_in_inuse){
+		usb_terminate_bulk (serial->dev, serial->bulk_in_transfer);
+		serial->bulk_in_inuse = 0;
+	}
+
+	/* release the irq? */
+	
+	serial->active = 0;
+}
+
+
+static int whiteheat_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	int written;
+	
+	debug_info("USB Serial: whiteheat_serial_write\n");
+
+	if (serial->bulk_out_inuse) {
+		debug_info ("USB Serial: already writing\n");
+		return (0);
+	}
+
+	written = (count > serial->bulk_out_size) ? serial->bulk_out_size : count;
+	  
+	if (from_user) {
+		copy_from_user(serial->bulk_out_buffer, buf, written);
+	}
+	else {
+		memcpy (serial->bulk_out_buffer, buf, written);
+	}  
+
+	/* send the data out the bulk port */
+	serial->bulk_out_inuse = 1;
+	serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, written, serial);
+
+	return (written);
+} 
+
+
+static void whiteheat_serial_put_char (struct tty_struct *tty, unsigned char ch)
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+	
+	debug_info("USB Serial: whiteheat_serial_put_char\n");
+	
+	if (serial->bulk_out_inuse) {
+		debug_info ("USB Serial: already writing\n");
+		return;
+	}
+
+	/* send the single character out the bulk port */
+	serial->bulk_out_buffer[0] = ch;
+	serial->bulk_out_inuse = 1;
+	serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, 1, serial);
+
+	return;
+}
+
+
+static int whiteheat_write_room (struct tty_struct *tty) 
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+
+	debug_info("USB Serial: whiteheat_write_room\n");
+	
+	if (serial->bulk_out_inuse) {
+		return (0);
+	}
+
+	return (serial->bulk_out_size);
+}
+
+
+static int whiteheat_chars_in_buffer (struct tty_struct *tty) 
+{
+	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+
+	debug_info("USB Serial: whiteheat_chars_in_buffer\n");
+	
+	if (serial->bulk_out_inuse) {
+		return (serial->bulk_out_size);
+	}
+
+	return (0);
+}
+
+
+static void whiteheat_throttle (struct tty_struct * tty)
+{
+	debug_info("USB Serial: whiteheat_throttle\n");
 	
 	/* Change the control signals */
 	/* FIXME!!! */
@@ -766,11 +934,9 @@
 }
 
 
-static void etek_unthrottle (struct tty_struct * tty)
+static void whiteheat_unthrottle (struct tty_struct * tty)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-
-	debug_info("USB Serial: etek_unthrottle\n");
+	debug_info("USB Serial: whiteheat_unthrottle\n");
 	
 	/* Change the control signals */
 	/* FIXME!!! */
@@ -953,7 +1119,7 @@
 	while (usb_serial_devices[device_num] != NULL) {
 		type = usb_serial_devices[device_num];
 		#ifdef SERIAL_DEBUG
-			printk ("USB Serial: Looking at %s\nVendor id=%.4x\nProduct id=%.4x\n", type->name, *(type->idVendor), *(type->idProduct));
+			printk ("USB Serial: Looking at %s Vendor id=%.4x Product id=%.4x\n", type->name, *(type->idVendor), *(type->idProduct));
 		#endif		
 
 		/* look at the device descriptor */
@@ -1013,7 +1179,7 @@
 			    (bulk_in_pipe & type->needs_bulk_in) &&
 			    (bulk_out_pipe & type->needs_bulk_out)) {
 				/* found all that we need */
-				printk (KERN_INFO "USB serial converter detected.\n");
+				printk (KERN_INFO "USB Serial: %s converter detected.\n", type->name);
 
 				if (0>(serial_num = Get_Free_Serial())) {
 					debug_info("USB Serial: Too many devices connected\n");
@@ -1025,6 +1191,7 @@
 			       	memset(serial, 0, sizeof(struct usb_serial_state));
 			       	serial->dev = dev;
 				serial->type = type;
+				serial->number = serial_num;
 
 				/* set up the endpoint information */
 				if (bulk_in_endpoint) {
@@ -1086,6 +1253,7 @@
 				serial->present = 1;
 				MOD_INC_USE_COUNT;
 
+				printk(KERN_INFO "USB Serial: %s converter now attached to ttyUSB%d\n", type->name, serial_num);
 				return serial;
 			} else {
 				printk(KERN_INFO "USB Serial: descriptors matched, but endpoints did not\n");
@@ -1139,11 +1307,15 @@
 
 		serial->present = 0;
 		serial->active = 0;
+
+		printk (KERN_INFO "USB Serial: %s converter now disconnected from ttyUSB%d\n", serial->type->name, serial->number);
+
+	} else {
+		printk (KERN_INFO "USB Serial: device disconnected.\n");
 	}
 	
 	MOD_DEC_USE_COUNT;
 
-	printk (KERN_INFO "USB Serial: device disconnected.\n");
 }
 
 
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.3.34/linux/drivers/usb/usb.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/usb.c	Tue Dec 28 10:24:11 1999
@@ -15,7 +15,7 @@
  * It should be considered a slave, with no callbacks. Callbacks
  * are evil.
  *
- * $Id: usb.c,v 1.37 1999/12/17 10:48:08 fliegl Exp $
+ * $Id: usb.c,v 1.39 1999/12/27 15:17:47 acher Exp $
  */
 
 #ifndef EXPORT_SYMTAB
@@ -36,12 +36,9 @@
 #define MODSTR "usbcore: "
 
 #ifdef USB_DEBUG
-	#define dbg printk
+	#define dbg(format, arg...) printk(format, ## arg)
 #else
-	#define dbg nix
-static void nix(const char *format, ...)
-{
-}
+	#define dbg(format, arg...)
 #endif
 
 /*
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/usb.h linux/drivers/usb/usb.h
--- v2.3.34/linux/drivers/usb/usb.h	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/usb.h	Tue Dec 28 10:24:11 1999
@@ -227,8 +227,8 @@
 
 static __inline__ void wait_ms(unsigned int ms)
 {
-        current->state = TASK_UNINTERRUPTIBLE;
-        schedule_timeout(1 + ms * HZ / 1000);
+	current->state = TASK_UNINTERRUPTIBLE;
+	schedule_timeout(1 + ms * HZ / 1000);
 }
 
 typedef struct {
@@ -371,7 +371,7 @@
 	int num_altsetting;		/* number of alternate settings */
 	int max_altsetting;             /* total memory allocated */
  
-        struct usb_driver *driver;	/* driver */
+	struct usb_driver *driver;	/* driver */
 	void *private_data;
 };
 
@@ -475,35 +475,35 @@
 
 #define FILL_CONTROL_URB(a,aa,b,c,d,e,f,g) \
     do {\
-	a->dev=aa;\
-	a->pipe=b;\
-	a->setup_packet=c;\
-	a->transfer_buffer=d;\
-	a->transfer_buffer_length=e;\
-	a->complete=f;\
-	a->context=g;\
+	(a)->dev=aa;\
+	(a)->pipe=b;\
+	(a)->setup_packet=c;\
+	(a)->transfer_buffer=d;\
+	(a)->transfer_buffer_length=e;\
+	(a)->complete=f;\
+	(a)->context=g;\
     } while (0)
 
 #define FILL_BULK_URB(a,aa,b,c,d,e,f) \
     do {\
-	a->dev=aa;\
-	a->pipe=b;\
-	a->transfer_buffer=c;\
-	a->transfer_buffer_length=d;\
-	a->complete=e;\
-	a->context=f;\
+	(a)->dev=aa;\
+	(a)->pipe=b;\
+	(a)->transfer_buffer=c;\
+	(a)->transfer_buffer_length=d;\
+	(a)->complete=e;\
+	(a)->context=f;\
     } while (0)
     
 #define FILL_INT_URB(a,aa,b,c,d,e,f,g) \
     do {\
-	a->dev=aa;\
-	a->pipe=b;\
-	a->transfer_buffer=c;\
-	a->transfer_buffer_length=d;\
-	a->complete=e;\
-	a->context=f;\
-	a->interval=g;\
-	a->start_frame=-1;\
+	(a)->dev=aa;\
+	(a)->pipe=b;\
+	(a)->transfer_buffer=c;\
+	(a)->transfer_buffer_length=d;\
+	(a)->complete=e;\
+	(a)->context=f;\
+	(a)->interval=g;\
+	(a)->start_frame=-1;\
     } while (0)
 
 purb_t usb_alloc_urb(int iso_packets);
@@ -561,7 +561,6 @@
 	int bandwidth_isoc_reqs;	/* number of Isoc. requesters */
 
 	/* procfs entry */
-	int proc_busnum;
 	struct proc_dir_entry *proc_entry;
 };
 
diff -u --recursive --new-file v2.3.34/linux/drivers/usb/uss720.c linux/drivers/usb/uss720.c
--- v2.3.34/linux/drivers/usb/uss720.c	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/uss720.c	Wed Dec 22 17:36:47 1999
@@ -363,7 +363,7 @@
 		return 0;
 	if (change_mode(pp, ECR_EPP))
 		return 0;
-	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buf, length, &rlen, HZ*20);
+	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buf, length, &rlen, HZ*20);
 	if (i)
 		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buf, length, rlen);
 	change_mode(pp, ECR_PS2);
@@ -424,7 +424,7 @@
 		return 0;
 	if (change_mode(pp, ECR_ECP))
 		return 0;
-	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buffer, len, &rlen, HZ*20);
+	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20);
 	if (i)
 		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buffer, len, rlen);
 	change_mode(pp, ECR_PS2);
@@ -475,7 +475,7 @@
 		return 0;
 	if (change_mode(pp, ECR_PPF))
 		return 0;
-	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buffer, len, &rlen, HZ*20);
+	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20);
 	if (i)
 		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buffer, len, rlen);
 	change_mode(pp, ECR_PS2);
diff -u --recursive --new-file v2.3.34/linux/drivers/video/Makefile linux/drivers/video/Makefile
--- v2.3.34/linux/drivers/video/Makefile	Tue Dec 14 01:27:24 1999
+++ linux/drivers/video/Makefile	Mon Dec 20 22:06:42 1999
@@ -131,6 +131,9 @@
 clean:
 	rm -f core *.o *.a *.s
 
+../conmakehash: ../conmakehash.c
+	$(HOSTCC) $(HOSTCFLAGS) -o ../conmakehash ../conmakehash.c
+
 promcon_tbl.c: prom.uni ../char/conmakehash
 	../char/conmakehash prom.uni | \
 	sed -e '/#include <[^>]*>/p' -e 's/types/init/' \
diff -u --recursive --new-file v2.3.34/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.3.34/linux/drivers/video/atyfb.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/video/atyfb.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.126 1999/09/16 18:46:23 geert Exp $
+/*  $Id: atyfb.c,v 1.133 1999/12/09 10:23:13 davem Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *	Copyright (C) 1997-1998  Geert Uytterhoeven
@@ -269,8 +269,8 @@
     } fbcon_cmap;
     u8 blitter_may_be_busy;
 #ifdef __sparc__
-    u8 open;
     u8 mmaped;
+    int open;
     int vtconsole;
     int consolecnt;
 #endif
@@ -2622,10 +2622,8 @@
     struct fb_info_aty *fb = (struct fb_info_aty *)info;
 
     if (user) {
-	if (fb->open)
-	    return -EBUSY;
+	fb->open++;
 	fb->mmaped = 0;
-	fb->open = 1;
 	fb->vtconsole = -1;
     } else {
 	fb->consolecnt++;
@@ -2635,17 +2633,54 @@
     return(0);
 }
 
+struct fb_var_screeninfo default_var = {
+    /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+    640, 480, 640, 480, 0, 0, 8, 0,
+    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+    0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
+    0, FB_VMODE_NONINTERLACED
+};
+
 static int atyfb_release(struct fb_info *info, int user)
 {
 #ifdef __sparc__
     struct fb_info_aty *fb = (struct fb_info_aty *)info;
 
     if (user) {
-	if (fb->vtconsole != -1)
-	    vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
-	fb->open = 0;
-	fb->mmaped = 0;
-	fb->vtconsole = -1;
+	fb->open--;
+	udelay(1000);
+	wait_for_idle(fb);
+	if (!fb->open) {
+		int was_mmaped = fb->mmaped;
+
+		fb->mmaped = 0;
+		if (fb->vtconsole != -1)
+			vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
+		fb->vtconsole = -1;
+
+		if (was_mmaped) {
+			struct fb_var_screeninfo var;
+
+			/* Now reset the default display config, we have no
+			 * idea what the program(s) which mmap'd the chip did
+			 * to the configuration, nor whether it restored it
+			 * correctly.
+			 */
+			var = default_var;
+			if (noaccel)
+				var.accel_flags &= ~FB_ACCELF_TEXT;
+			else
+				var.accel_flags |= FB_ACCELF_TEXT;
+			if (var.yres == var.yres_virtual) {
+				u32 vram = (fb->total_vram - (PAGE_SIZE << 2));
+				var.yres_virtual = ((vram * 8) / var.bits_per_pixel) /
+					var.xres_virtual;
+				if (var.yres_virtual < var.yres)
+					var.yres_virtual = var.yres;
+			}
+			atyfb_set_var(&var, -1, &fb->fb_info);
+		}
+	}
     } else {
 	fb->consolecnt--;
     }
@@ -2708,15 +2743,6 @@
 }
 
 
-struct fb_var_screeninfo default_var = {
-    /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
-    640, 480, 640, 480, 0, 0, 8, 0,
-    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-    0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
-    0, FB_VMODE_NONINTERLACED
-};
-
-
     /*
      *  Get the Fixed Part of the Display
      */
@@ -4069,6 +4095,14 @@
 #endif
 	
 
+#ifdef CONFIG_PMAC_PBOOK
+    if (first_display == NULL)
+	pmu_register_sleep_notifier(&aty_sleep_notifier);
+    info->next = first_display;
+    first_display = info;
+#endif
+	
+
 #ifdef CONFIG_FB_COMPAT_XPMAC
     if (!console_fb_info)
 	console_fb_info = &info->fb_info;
@@ -4772,6 +4806,98 @@
     FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * Save the contents of the frame buffer when we go to sleep,
+ * and restore it when we wake up again.
+ */
+int
+aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
+{
+	struct fb_info_aty *info;
+ 	unsigned int pm;
+ 	
+	for (info = first_display; info != NULL; info = info->next) {
+		struct fb_fix_screeninfo fix;
+		int nb;
+		
+		atyfb_get_fix(&fix, fg_console, (struct fb_info *)info);
+		nb = fb_display[fg_console].var.yres * fix.line_length;
+
+		switch (when) {
+		case PBOOK_SLEEP_NOW:
+			/* Stop accel engine (stop bus mastering) */
+			if (info->current_par.accel_flags & FB_ACCELF_TEXT)
+				reset_engine(info);
+#if 1
+			/* Backup fb content */	
+			info->save_framebuffer = vmalloc(nb);
+			if (info->save_framebuffer)
+				memcpy(info->save_framebuffer,
+				       (void *)info->frame_buffer, nb);
+#endif
+			/* Blank display and LCD */				       
+			atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);			
+			
+			/* Set chip to "suspend" mode. Note: There's an HW bug in the
+			   chip which prevents proper resync on wakeup with automatic
+			   power management, we handle suspend manually using the
+			   following (weird) sequence described by ATI. Note2:
+			   We could enable this for all Rage LT Pro chip ids */
+			if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) {
+				pm = aty_ld_le32(POWER_MANAGEMENT, info);
+				pm &= ~PWR_MGT_ON;
+				aty_st_le32(POWER_MANAGEMENT, pm, info);
+				pm = aty_ld_le32(POWER_MANAGEMENT, info);
+				pm &= ~(PWR_BLON | AUTO_PWR_UP);
+				pm |= SUSPEND_NOW;
+				aty_st_le32(POWER_MANAGEMENT, pm, info);
+				pm = aty_ld_le32(POWER_MANAGEMENT, info);
+				pm |= PWR_MGT_ON;
+				aty_st_le32(POWER_MANAGEMENT, pm, info);
+				do {
+					pm = aty_ld_le32(POWER_MANAGEMENT, info);
+				} while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
+				mdelay(500);
+			}
+			break;
+		case PBOOK_WAKE:
+			/* Wakeup chip */
+			if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) {
+				pm = aty_ld_le32(POWER_MANAGEMENT, info);
+				pm &= ~PWR_MGT_ON;
+				aty_st_le32(POWER_MANAGEMENT, pm, info);
+				pm = aty_ld_le32(POWER_MANAGEMENT, info);
+				pm |=  (PWR_BLON | AUTO_PWR_UP);
+				pm &= ~SUSPEND_NOW;
+				aty_st_le32(POWER_MANAGEMENT, pm, info);
+				pm = aty_ld_le32(POWER_MANAGEMENT, info);
+				pm |= PWR_MGT_ON;
+				aty_st_le32(POWER_MANAGEMENT, pm, info);
+				do {
+					pm = aty_ld_le32(POWER_MANAGEMENT, info);
+				} while ((pm & PWR_MGT_STATUS_MASK) != 0);
+				mdelay(500);
+			}
+#if 1
+			/* Restore fb content */			
+			if (info->save_framebuffer) {
+				memcpy((void *)info->frame_buffer,
+				       info->save_framebuffer, nb);
+				vfree(info->save_framebuffer);
+				info->save_framebuffer = 0;
+			}
+#endif
+			/* Restore display */			
+			atyfb_set_par(&info->current_par, info);
+			atyfbcon_blank(0, (struct fb_info *)info);
+			break;
+		}
+	}
+	return PBOOK_SLEEP_OK;
+}
+#endif /* CONFIG_PMAC_PBOOK */
 
 #ifdef CONFIG_PMAC_PBOOK
 /*
diff -u --recursive --new-file v2.3.34/linux/drivers/video/bwtwofb.c linux/drivers/video/bwtwofb.c
--- v2.3.34/linux/drivers/video/bwtwofb.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/video/bwtwofb.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: bwtwofb.c,v 1.8 1999/08/26 05:13:09 shadow Exp $
+/* $Id: bwtwofb.c,v 1.11 1999/11/19 09:56:54 davem Exp $
  * bwtwofb.c: BWtwo frame buffer driver
  *
  * Copyright (C) 1998 Jakub Jelinek   (jj@ultra.linux.cz)
@@ -85,17 +85,33 @@
 
 static void bw2_blank (struct fb_info_sbusfb *fb)
 {
-	fb->s.bw2.regs->control &= ~BWTWO_CTL_ENABLE_VIDEO;
+	unsigned long flags;
+	u8 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	tmp = sbus_readb(&fb->s.bw2.regs->control);
+	tmp &= ~BWTWO_CTL_ENABLE_VIDEO;
+	sbus_writeb(tmp, &fb->s.bw2.regs->control);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void bw2_unblank (struct fb_info_sbusfb *fb)
 {
-	fb->s.bw2.regs->control |= BWTWO_CTL_ENABLE_VIDEO;
+	unsigned long flags;
+	u8 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	tmp = sbus_readb(&fb->s.bw2.regs->control);
+	tmp |= BWTWO_CTL_ENABLE_VIDEO;
+	sbus_writeb(tmp, &fb->s.bw2.regs->control);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
-static void bw2_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
+static void bw2_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) >> 3);
+	p->screen_base += (y_margin - fb->y_margin) *
+		p->line_length + ((x_margin - fb->x_margin) >> 3);
 }
 
 static u8 bw2regs_1600[] __initdata = {
@@ -142,17 +158,29 @@
 	struct fbtype *type = &fb->type;
 #ifdef CONFIG_SUN4
 	unsigned long phys = sun4_bwtwo_physaddr;
+	struct resource res;
 #else
 	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
 #endif
+	struct resource *resp;
+	unsigned int vaddr;
 
 #ifndef FBCON_HAS_MFB
 	return NULL;
 #endif
 
+#ifdef CONFIG_SUN4
+	res.start = phys;
+	res.end = res.start + BWTWO_REGISTER_OFFSET + sizeof(struct bw2_regs) - 1;
+	res.flags = IORESOURE_IO | (fb->iospace & 0xff);
+	resp = &res;
+#else
+	resp = &fb->sbdp->resource[0];
+#endif
 	if (!fb->s.bw2.regs) {
-		fb->s.bw2.regs = (struct bw2_regs *)sparc_alloc_io(phys+BWTWO_REGISTER_OFFSET, 0, 
-				sizeof(struct bw2_regs), "bw2_regs", fb->iospace, 0);
+		fb->s.bw2.regs = (struct bw2_regs *)
+			sbus_ioremap(resp, BWTWO_REGISTER_OFFSET,
+				     sizeof(struct bw2_regs), "bw2 regs");
 		if ((!ARCH_SUN4) && (!prom_getbool(fb->prom_node, "width"))) {
 			/* Ugh, broken PROM didn't initialize us.
 			 * Let's deal with this ourselves.
@@ -161,7 +189,7 @@
 			u8 *p;
 			int sizechange = 0;
 
-			status = fb->s.bw2.regs->status;
+			status = sbus_readb(&fb->s.bw2.regs->status);
 			mon = status & BWTWO_SR_RES_MASK;
 			switch (status & BWTWO_SR_ID_MASK) {
 				case BWTWO_SR_ID_MONO_ECL:
@@ -191,21 +219,24 @@
 					prom_halt();
 					return NULL; /* fool gcc. */
 			}
-			for ( ; *p; p += 2)
-				((u8 *)fb->s.bw2.regs)[p[0]] = p[1];
+			for ( ; *p; p += 2) {
+				u8 *regp = &((u8 *)fb->s.bw2.regs)[p[0]];
+				sbus_writeb(p[1], regp);
+			}
 		}
 	}
 
 	strcpy(fb->info.modename, "BWtwo");
 	strcpy(fix->id, "BWtwo");
-	fix->line_length = fb->var.xres_virtual>>3;
+	fix->line_length = fb->var.xres_virtual >> 3;
 	fix->accel = FB_ACCEL_SUN_BWTWO;
 	
 	disp->scrollmode = SCROLL_YREDRAW;
 	disp->inverse = 1;
-	if (!disp->screen_base)
-		disp->screen_base = (char *)sparc_alloc_io(phys, 0, 
-			type->fb_size, "bw2_ram", fb->iospace, 0);
+	if (!disp->screen_base) {
+		disp->screen_base = (char *)
+			sbus_ioremap(resp, 0, type->fb_size, "bw2 ram");
+	}
 	disp->screen_base += fix->line_length * fb->y_margin + (fb->x_margin >> 3);
 	fb->dispsw = fbcon_mfb;
 	fix->visual = FB_VISUAL_MONO01;
@@ -213,10 +244,13 @@
 #ifndef CONFIG_SUN4
 	fb->blank = bw2_blank;
 	fb->unblank = bw2_unblank;
+
+	prom_getproperty(fb->sbdp->prom_node, "address",
+			 (char *)&vaddr, sizeof(vaddr));
+	fb->physbase = __get_phys((unsigned long)vaddr);
+
 #endif
 	fb->margins = bw2_margins;
-	
-	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.34/linux/drivers/video/cgfourteenfb.c linux/drivers/video/cgfourteenfb.c
--- v2.3.34/linux/drivers/video/cgfourteenfb.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/video/cgfourteenfb.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: cgfourteenfb.c,v 1.5 1999/08/10 15:56:02 davem Exp $
+/* $Id: cgfourteenfb.c,v 1.7 1999/11/19 09:57:01 davem Exp $
  * cgfourteenfb.c: CGfourteen frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -153,10 +153,10 @@
  * I currently use the clut instead of the Xlut
  */
 struct cg14_clut {
-	unsigned int c_clut [256];
-	unsigned int c_clutd [256];    /* i wonder what the 'd' is for */
-	unsigned int c_clut_inc [256];
-	unsigned int c_clutd_inc [256];
+	u32 c_clut [256];
+	u32 c_clutd [256];    /* i wonder what the 'd' is for */
+	u32 c_clut_inc [256];
+	u32 c_clutd_inc [256];
 };
 
 static struct sbus_mmap_map cg14_mmap_map[] __initdata = {
@@ -179,40 +179,55 @@
 	{ 0,			0,			0		    }
 };
 
-static void cg14_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
+static void cg14_loadcmap (struct fb_info_sbusfb *fb, struct display *p,
+			   int index, int count)
 {
 	struct cg14_clut *clut = fb->s.cg14.clut;
+	unsigned long flags;
 	        
-	for (; count--; index++)
-		clut->c_clut[index] = 
-			(fb->color_map CM(index,2) << 16) |
-			(fb->color_map CM(index,1) << 8) |
-			(fb->color_map CM(index,0));
+	spin_lock_irqsave(&fb->lock, flags);
+	for (; count--; index++) {
+		u32 val;
+
+		val = ((fb->color_map CM(index,2) << 16) |
+		       (fb->color_map CM(index,1) << 8) |
+		       (fb->color_map CM(index,0)));
+		sbus_writel(val, &clut->c_clut[index]);
+	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
-static void cg14_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
+static void cg14_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);
+	p->screen_base += (y_margin - fb->y_margin) *
+		p->line_length + (x_margin - fb->x_margin);
 }
 
 static void cg14_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
 {
 	struct cg14_cursor *cur = fb->s.cg14.cursor;
+	unsigned long flags;
 	
-	cur->color0 = ((red[0]) | (green[0] << 8) | (blue[0] << 16));
-	cur->color1 = ((red[1]) | (green[1] << 8) | (blue[1] << 16));
+	spin_lock_irqsave(&fb->lock, flags);
+	sbus_writel(((red[0]) | (green[0] << 8) | (blue[0] << 16)), &cur->color0);
+	sbus_writel(((red[1]) | (green[1] << 8) | (blue[1] << 16)), &cur->color1);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 /* Set cursor shape */
 static void cg14_setcurshape (struct fb_info_sbusfb *fb)
 {
 	struct cg14_cursor *cur = fb->s.cg14.cursor;
+	unsigned long flags;
 	int i;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	for (i = 0; i < 32; i++){
-		cur->cpl0 [i] = fb->cursor.bits[0][i];
-		cur->cpl1 [i] = fb->cursor.bits[1][i];
+		sbus_writel(fb->cursor.bits[0][i], &cur->cpl0[i]);
+		sbus_writel(fb->cursor.bits[1][i], &cur->cpl1[i]);
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 /* Load cursor information */
@@ -220,40 +235,67 @@
 {
 	struct cg_cursor *c = &fb->cursor;
 	struct cg14_cursor *cur = fb->s.cg14.cursor;
+	unsigned long flags;
                 
-	if (c->enable)
-		cur->ccr |= CG14_CCR_ENABLE;
-	cur->cursx = ((c->cpos.fbx - c->chot.fbx) & 0xfff);
-	cur->cursy = ((c->cpos.fby - c->chot.fby) & 0xfff);
+	spin_lock_irqsave(&fb->lock, flags);
+	if (c->enable) {
+		u8 tmp = sbus_readb(&cur->ccr);
+
+		tmp |= CG14_CCR_ENABLE;
+		sbus_writeb(tmp, &cur->ccr);
+	}
+	sbus_writew(((c->cpos.fbx - c->chot.fbx) & 0xfff), &cur->cursx);
+	sbus_writew(((c->cpos.fby - c->chot.fby) & 0xfff), &cur->cursy);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg14_switch_from_graph (struct fb_info_sbusfb *fb)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&fb->lock, flags);
+
 	/* Set the 8-bpp mode */
 	if (fb->open && fb->mmaped){
 		volatile char *mcr = &fb->s.cg14.regs->mcr;
+		char tmp;
 	                                
 		fb->s.cg14.mode = 8;
-		*mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK));
+		tmp = sbus_readb(mcr);
+		tmp &= ~(CG14_MCR_PIXMODE_MASK);
+		sbus_writeb(tmp, mcr);
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg14_reset (struct fb_info_sbusfb *fb)
 {
 	volatile char *mcr = &fb->s.cg14.regs->mcr;
+	unsigned long flags;
+	char tmp;
 	        
-	*mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK));
+	spin_lock_irqsave(&fb->lock, flags);
+	tmp = sbus_readb(mcr);
+	tmp &= ~(CG14_MCR_PIXMODE_MASK);
+	sbus_writeb(tmp, mcr);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned long arg)
 {
 	volatile char *mcr = &fb->s.cg14.regs->mcr;
 	struct mdi_cfginfo *mdii;
-	int mode;
+	unsigned long flags;
+	int mode, ret = 0;
+	char tmp;
 	        
 	switch (cmd) {
 	case MDI_RESET:
-		*mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK);
+		spin_lock_irqsave(&fb->lock, flags);
+		tmp = sbus_readb(mcr);
+		tmp &= ~CG14_MCR_PIXMODE_MASK;
+		sbus_writeb(tmp, mcr);
+		spin_unlock_irqrestore(&fb->lock, flags);
 		break;
 	case MDI_GET_CFGINFO:
 		mdii = (struct mdi_cfginfo *)arg;
@@ -266,26 +308,35 @@
 		break;
 	case MDI_SET_PIXELMODE:
 		get_user_ret(mode, (int *)arg, -EFAULT);
+
+		spin_lock_irqsave(&fb->lock, flags);
+		tmp = sbus_readb(mcr);
 		switch (mode){
 		case MDI_32_PIX:
-			*mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK) |
+			tmp = (tmp & ~CG14_MCR_PIXMODE_MASK) |
 				(CG14_MCR_PIXMODE_32 << CG14_MCR_PIXMODE_SHIFT);
 			break;
 		case MDI_16_PIX:
-			*mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK) | 0x20;
+			tmp = (tmp & ~CG14_MCR_PIXMODE_MASK) | 0x20;
 			break;
 		case MDI_8_PIX:
-			*mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK);
+			tmp = (tmp & ~CG14_MCR_PIXMODE_MASK);
 			break;
 		default:
-			return -ENOSYS;
+			ret = -ENOSYS;
+			break;
+		};
+		if (ret == 0) {
+			sbus_writeb(tmp, mcr);
+			fb->s.cg14.mode = mode;
 		}
-		fb->s.cg14.mode = mode;
+		spin_unlock_irqrestore(&fb->lock, flags);
 		break;
 	default:
-		return -EINVAL;
-	}
-	return 0;
+		ret = -EINVAL;
+	};
+
+	return ret;
 }
 
 static unsigned long __init get_phys(unsigned long addr)
@@ -372,7 +423,7 @@
 	fb->reset = cg14_reset;
 	fb->switch_from_graph = cg14_switch_from_graph;
 	fb->ioctl = cg14_ioctl;
-	
+
 	fb->s.cg14.mode = 8;
 	fb->s.cg14.ramsize = (is_8mb) ? 0x800000 : 0x400000;
 	
diff -u --recursive --new-file v2.3.34/linux/drivers/video/cgsixfb.c linux/drivers/video/cgsixfb.c
--- v2.3.34/linux/drivers/video/cgsixfb.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/video/cgsixfb.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.19 1999/08/10 15:56:03 davem Exp $
+/* $Id: cgsixfb.c,v 1.21 1999/11/19 09:56:57 davem Exp $
  * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -31,15 +31,15 @@
  * The FBC could be the frame buffer control
  * The FHC could is the frame buffer hardware control.
  */
-#define CG6_ROM_OFFSET       0x0
-#define CG6_BROOKTREE_OFFSET 0x200000
-#define CG6_DHC_OFFSET       0x240000
-#define CG6_ALT_OFFSET       0x280000
-#define CG6_FHC_OFFSET       0x300000
-#define CG6_THC_OFFSET       0x301000
-#define CG6_FBC_OFFSET       0x700000
-#define CG6_TEC_OFFSET       0x701000
-#define CG6_RAM_OFFSET       0x800000
+#define CG6_ROM_OFFSET       0x0UL
+#define CG6_BROOKTREE_OFFSET 0x200000UL
+#define CG6_DHC_OFFSET       0x240000UL
+#define CG6_ALT_OFFSET       0x280000UL
+#define CG6_FHC_OFFSET       0x300000UL
+#define CG6_THC_OFFSET       0x301000UL
+#define CG6_FBC_OFFSET       0x700000UL
+#define CG6_TEC_OFFSET       0x701000UL
+#define CG6_RAM_OFFSET       0x800000UL
 
 /* FHC definitions */
 #define CG6_FHC_FBID_SHIFT           24
@@ -231,19 +231,21 @@
 {
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct cg6_fbc *fbc = fb->s.cg6.fbc;
+	unsigned long flags;
 	int x, y, w, h;
 	int i;
 	
+	spin_lock_irqsave(&fb->lock, flags);
 	do {
-		i = fbc->s;
+		i = sbus_readl(&fbc->s);
 	} while (i & 0x10000000);
-	fbc->fg = attr_bgcol_ec(p,conp);
-	fbc->bg = attr_bgcol_ec(p,conp);
-	fbc->pixelm = ~(0);
-	fbc->alu = 0xea80ff00;
-	fbc->s = 0;
-	fbc->clip = 0;
-	fbc->pm = ~(0);
+	sbus_writel(attr_bgcol_ec(p,conp), &fbc->fg);
+	sbus_writel(attr_bgcol_ec(p,conp), &fbc->bg);
+	sbus_writel(~0, &fbc->pixelm);
+	sbus_writel(0xea80ff00, &fbc->alu);
+	sbus_writel(0, &fbc->s);
+	sbus_writel(0, &fbc->clip);
+	sbus_writel(~0, &fbc->pm);
 
         if (fontheightlog(p)) {
 		y = sy << fontheightlog(p); h = height << fontheightlog(p);
@@ -255,13 +257,14 @@
 	} else {
 		x = sx * fontwidth(p); w = width * fontwidth(p);
 	}
-	fbc->arecty = y + fb->y_margin;
-	fbc->arectx = x + fb->x_margin;
-	fbc->arecty = y + fb->y_margin + h;
-	fbc->arectx = x + fb->x_margin + w;
+	sbus_writel(y + fb->y_margin, &fbc->arecty);
+	sbus_writel(x + fb->x_margin, &fbc->arectx);
+	sbus_writel(y + fb->y_margin + h, &fbc->arecty);
+	sbus_writel(x + fb->x_margin + w, &fbc->arectx);
 	do {
-		i = fbc->draw;
+		i = sbus_readl(&fbc->draw);
 	} while (i < 0 && (i & 0x20000000));
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg6_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
@@ -269,36 +272,41 @@
 {
 	int i;
 	register struct cg6_fbc *fbc = fb->s.cg6.fbc;
+	unsigned long flags;
 	
+	spin_lock_irqsave(&fb->lock, flags);
 	do {
-		i = fbc->s;
+		i = sbus_readl(&fbc->s);
 	} while (i & 0x10000000);
-	fbc->fg = attr_bgcol(p,s);
-	fbc->bg = attr_bgcol(p,s);
-	fbc->pixelm = ~(0);
-	fbc->alu = 0xea80ff00;
-	fbc->s = 0;
-	fbc->clip = 0;
-	fbc->pm = ~(0);
+	sbus_writel(attr_bgcol(p,s), &fbc->fg);
+	sbus_writel(attr_bgcol(p,s), &fbc->bg);
+	sbus_writel(~0, &fbc->pixelm);
+	sbus_writel(0xea80ff00, &fbc->alu);
+	sbus_writel(0, &fbc->s);
+	sbus_writel(0, &fbc->clip);
+	sbus_writel(~0, &fbc->pm);
 	while (count-- > 0) {
-		fbc->arecty = boxes[1];
-		fbc->arectx = boxes[0];
-		fbc->arecty = boxes[3];
-		fbc->arectx = boxes[2];
+		sbus_writel(boxes[1], &fbc->arecty);
+		sbus_writel(boxes[0], &fbc->arectx);
+		sbus_writel(boxes[3], &fbc->arecty);
+		sbus_writel(boxes[2], &fbc->arectx);
 		boxes += 4;
 		do {
-			i = fbc->draw;
+			i = sbus_readl(&fbc->draw);
 		} while (i < 0 && (i & 0x20000000));
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
 {
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct cg6_fbc *fbc = fb->s.cg6.fbc;
+	unsigned long flags;
 	int i, x, y;
 	u8 *fd;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	if (fontheightlog(p)) {
 		y = fb->y_margin + (yy << fontheightlog(p));
 		i = ((c & p->charmask) << fontheightlog(p));
@@ -315,30 +323,35 @@
 	else
 		x = fb->x_margin + (xx * fontwidth(p));
 	do {
-		i = fbc->s;
+		i = sbus_readl(&fbc->s);
 	} while (i & 0x10000000);
-	fbc->fg = attr_fgcol(p,c);
-	fbc->bg = attr_bgcol(p,c);
-	fbc->mode = 0x140000;
-	fbc->alu = 0xe880fc30;
-	fbc->pixelm = ~(0);
-	fbc->s = 0;
-	fbc->clip = 0;
-	fbc->pm = 0xff;
-	fbc->incx = 0;
-	fbc->incy = 1;
-	fbc->x0 = x;
-	fbc->x1 = x + fontwidth(p) - 1;
-	fbc->y0 = y;
+	sbus_writel(attr_fgcol(p,c), &fbc->fg);
+	sbus_writel(attr_bgcol(p,c), &fbc->bg);
+	sbus_writel(0x140000, &fbc->mode);
+	sbus_writel(0xe880fc30, &fbc->alu);
+	sbus_writel(~0, &fbc->pixelm);
+	sbus_writel(0, &fbc->s);
+	sbus_writel(0, &fbc->clip);
+	sbus_writel(0xff, &fbc->pm);
+	sbus_writel(0, &fbc->incx);
+	sbus_writel(1, &fbc->incy);
+	sbus_writel(x, &fbc->x0);
+	sbus_writel(x + fontwidth(p) - 1, &fbc->x1);
+	sbus_writel(y, &fbc->y0);
 	if (fontwidth(p) <= 8) {
-		for (i = 0; i < fontheight(p); i++)
-			fbc->font = *fd++ << 24;
+		for (i = 0; i < fontheight(p); i++) {
+			u32 val = *fd++ << 24;
+			sbus_writel(val, &fbc->font);
+		}
 	} else {
 		for (i = 0; i < fontheight(p); i++) {
-			fbc->font = *(u16 *)fd << 16;
+			u32 val = *(u16 *)fd << 16;
+
+			sbus_writel(val, &fbc->font);
 			fd += 2;
 		}
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
@@ -346,20 +359,22 @@
 {
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct cg6_fbc *fbc = fb->s.cg6.fbc;
+	unsigned long flags;
 	int i, x, y;
 	u8 *fd1, *fd2, *fd3, *fd4;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	do {
-		i = fbc->s;
+		i = sbus_readl(&fbc->s);
 	} while (i & 0x10000000);
-	fbc->fg = attr_fgcol(p, scr_readw(s));
-	fbc->bg = attr_bgcol(p, scr_readw(s));
-	fbc->mode = 0x140000;
-	fbc->alu = 0xe880fc30;
-	fbc->pixelm = ~(0);
-	fbc->s = 0;
-	fbc->clip = 0;
-	fbc->pm = 0xff;
+	sbus_writel(attr_fgcol(p, scr_readw(s)), &fbc->fg);
+	sbus_writel(attr_bgcol(p, scr_readw(s)), &fbc->bg);
+	sbus_writel(0x140000, &fbc->mode);
+	sbus_writel(0xe880fc30, &fbc->alu);
+	sbus_writel(~0, &fbc->pixelm);
+	sbus_writel(0, &fbc->s);
+	sbus_writel(0, &fbc->clip);
+	sbus_writel(0xff, &fbc->pm);
 	x = fb->x_margin;
 	y = fb->y_margin;
 	if (fontwidthlog(p))
@@ -373,11 +388,11 @@
 	if (fontwidth(p) <= 8) {
 		while (count >= 4) {
 			count -= 4;
-			fbc->incx = 0;
-			fbc->incy = 1;
-			fbc->x0 = x;
-			fbc->x1 = (x += 4 * fontwidth(p)) - 1;
-			fbc->y0 = y;
+			sbus_writel(0, &fbc->incx);
+			sbus_writel(1, &fbc->incy);
+			sbus_writel(x, &fbc->x0);
+			sbus_writel((x += 4 * fontwidth(p)) - 1, &fbc->x1);
+			sbus_writel(y, &fbc->y0);
 			if (fontheightlog(p)) {
 				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
 				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
@@ -390,23 +405,36 @@
 				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
 			}
 			if (fontwidth(p) == 8) {
-				for (i = 0; i < fontheight(p); i++)
-					fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
-						<< 8)) << 8)) << 8);
+				for (i = 0; i < fontheight(p); i++) {
+					u32 val = ((u32)*fd4++) |
+						((((u32)*fd3++) |
+						  ((((u32)*fd2++) |
+						    (((u32)*fd1++)
+						     << 8)) << 8)) << 8);
+					sbus_writel(val, &fbc->font);
+				}
 			} else {
-				for (i = 0; i < fontheight(p); i++)
-					fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
-						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
+				for (i = 0; i < fontheight(p); i++) {
+					u32 val = (((u32)*fd4++) |
+						   ((((u32)*fd3++) |
+						     ((((u32)*fd2++) |
+						       (((u32)*fd1++) 
+							<< fontwidth(p))) <<
+						      fontwidth(p))) <<
+						    fontwidth(p))) <<
+						(24 - 3 * fontwidth(p));
+					sbus_writel(val, &fbc->font);
+				}
 			}
 		}
 	} else {
 		while (count >= 2) {
 			count -= 2;
-			fbc->incx = 0;
-			fbc->incy = 1;
-			fbc->x0 = x;
-			fbc->x1 = (x += 2 * fontwidth(p)) - 1;
-			fbc->y0 = y;
+			sbus_writel(0, &fbc->incx);
+			sbus_writel(1, &fbc->incy);
+			sbus_writel(x, &fbc->x0);
+			sbus_writel((x += 2 * fontwidth(p)) - 1, &fbc->x1);
+			sbus_writel(y, &fbc->y0);
 			if (fontheightlog(p)) {
 				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
 				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
@@ -415,34 +443,40 @@
 				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
 			}
 			for (i = 0; i < fontheight(p); i++) {
-				fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
+				u32 val = ((((u32)*(u16 *)fd1) << fontwidth(p)) |
+					   ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
+				sbus_writel(val, &fbc->font);
 				fd1 += 2; fd2 += 2;
 			}
 		}
 	}
 	while (count) {
 		count--;
-		fbc->incx = 0;
-		fbc->incy = 1;
-		fbc->x0 = x;
-		fbc->x1 = (x += fontwidth(p)) - 1;
-		fbc->y0 = y;
+		sbus_writel(0, &fbc->incx);
+		sbus_writel(1, &fbc->incy);
+		sbus_writel(x, &fbc->x0);
+		sbus_writel((x += fontwidth(p)) - 1, &fbc->x1);
+		sbus_writel(y, &fbc->y0);
 		if (fontheightlog(p))
 			i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
 		else
 			i = ((scr_readw(s++) & p->charmask) * fontheight(p));
 		if (fontwidth(p) <= 8) {
 			fd1 = p->fontdata + i;
-			for (i = 0; i < fontheight(p); i++)
-				fbc->font = *fd1++ << 24;
+			for (i = 0; i < fontheight(p); i++) {
+				u32 val = *fd1++ << 24;
+				sbus_writel(val, &fbc->font);
+			}
 		} else {
 			fd1 = p->fontdata + (i << 1);
 			for (i = 0; i < fontheight(p); i++) {
-				fbc->font = *(u16 *)fd1 << 16;
+				u32 val = *(u16 *)fd1 << 16;
+				sbus_writel(val, &fbc->font);
 				fd1 += 2;
 			}
 		}
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg6_revc(struct display *p, int xx, int yy)
@@ -453,24 +487,33 @@
 static void cg6_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
 {
 	struct bt_regs *bt = fb->s.cg6.bt;
+	unsigned long flags;
 	int i;
                 
+	spin_lock_irqsave(&fb->lock, flags);
 	bt->addr = index << 24;
 	for (i = index; count--; i++){
-		bt->color_map = fb->color_map CM(i,0) << 24;
-		bt->color_map = fb->color_map CM(i,1) << 24;
-		bt->color_map = fb->color_map CM(i,2) << 24;
+		sbus_writel(fb->color_map CM(i,0) << 24,
+			    &bt->color_map);
+		sbus_writel(fb->color_map CM(i,1) << 24,
+			    &bt->color_map);
+		sbus_writel(fb->color_map CM(i,2) << 24,
+			    &bt->color_map);
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg6_restore_palette (struct fb_info_sbusfb *fb)
 {
 	struct bt_regs *bt = fb->s.cg6.bt;
+	unsigned long flags;
                 
-	bt->addr = 0;
-	bt->color_map = 0xffffffff;
-	bt->color_map = 0xffffffff;
-	bt->color_map = 0xffffffff;
+	spin_lock_irqsave(&fb->lock, flags);
+	sbus_writel(0, &bt->addr);
+	sbus_writel(0xffffffff, &bt->color_map);
+	sbus_writel(0xffffffff, &bt->color_map);
+	sbus_writel(0xffffffff, &bt->color_map);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static struct display_switch cg6_dispsw __initdata = {
@@ -481,52 +524,77 @@
 static void cg6_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
 {
         struct bt_regs *bt = fb->s.cg6.bt;
+	unsigned long flags;
         
-	bt->addr = 1 << 24;
-	bt->cursor = red[0] << 24;
-	bt->cursor = green[0] << 24;
-	bt->cursor = blue[0] << 24;
-	bt->addr = 3 << 24;
-	bt->cursor = red[1] << 24;
-	bt->cursor = green[1] << 24;
-	bt->cursor = blue[1] << 24;
+	spin_lock_irqsave(&fb->lock, flags);
+	sbus_writel(1 << 24, &bt->addr);
+	sbus_writel(red[0] << 24, &bt->cursor);
+	sbus_writel(green[0] << 24, &bt->cursor);
+	sbus_writel(blue[0] << 24, &bt->cursor);
+	sbus_writel(3 << 24, &bt->addr);
+	sbus_writel(red[1] << 24, &bt->cursor);
+	sbus_writel(green[1] << 24, &bt->cursor);
+	sbus_writel(blue[1] << 24, &bt->cursor);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 /* Set cursor shape */
 static void cg6_setcurshape (struct fb_info_sbusfb *fb)
 {
 	struct cg6_thc *thc = fb->s.cg6.thc;
+	unsigned long flags;
 	int i;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	for (i = 0; i < 32; i++) {
-		thc->thc_cursmask [i] = fb->cursor.bits[0][i];
-		thc->thc_cursbits [i] = fb->cursor.bits[1][i];
+		sbus_writel(fb->cursor.bits[0][i],
+			    &thc->thc_cursmask [i]);
+		sbus_writel(fb->cursor.bits[1][i],
+			    &thc->thc_cursbits [i]);
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 /* Load cursor information */
 static void cg6_setcursor (struct fb_info_sbusfb *fb)
 {
 	unsigned int v;
+	unsigned long flags;
 	struct cg_cursor *c = &fb->cursor;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	if (c->enable)
 		v = ((c->cpos.fbx - c->chot.fbx) << 16)
 		    |((c->cpos.fby - c->chot.fby) & 0xffff);
 	else
 		/* Magic constant to turn off the cursor */
 		v = ((65536-32) << 16) | (65536-32);
-	fb->s.cg6.thc->thc_cursxy = v;
+	sbus_writel(v, &fb->s.cg6.thc->thc_cursxy);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg6_blank (struct fb_info_sbusfb *fb)
 {
-	fb->s.cg6.thc->thc_misc &= ~CG6_THC_MISC_VIDEO;
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	tmp = sbus_readl(&fb->s.cg6.thc->thc_misc);
+	tmp &= ~CG6_THC_MISC_VIDEO;
+	sbus_writel(tmp, &fb->s.cg6.thc->thc_misc);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg6_unblank (struct fb_info_sbusfb *fb)
 {
-	fb->s.cg6.thc->thc_misc |= CG6_THC_MISC_VIDEO;
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	tmp = sbus_readl(&fb->s.cg6.thc->thc_misc);
+	tmp |= CG6_THC_MISC_VIDEO;
+	sbus_writel(tmp, &fb->s.cg6.thc->thc_misc);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg6_reset (struct fb_info_sbusfb *fb)
@@ -534,32 +602,35 @@
 	unsigned int rev, conf;
 	struct cg6_tec *tec = fb->s.cg6.tec;
 	struct cg6_fbc *fbc = fb->s.cg6.fbc;
-	u32 mode;
+	unsigned long flags;
+	u32 mode, tmp;
 	int i;
 	
+	spin_lock_irqsave(&fb->lock, flags);
+
 	/* Turn off stuff in the Transform Engine. */
-	tec->tec_matrix = 0;
-	tec->tec_clip = 0;
-	tec->tec_vdc = 0;
+	sbus_writel(0, &tec->tec_matrix);
+	sbus_writel(0, &tec->tec_clip);
+	sbus_writel(0, &tec->tec_vdc);
 
 	/* Take care of bugs in old revisions. */
-	rev = (*(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;
+	rev = (sbus_readl(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;
 	if (rev < 5) {
-		conf = (*(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) |
+		conf = (sbus_readl(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) |
 			CG6_FHC_CPU_68020 | CG6_FHC_TEST |
 			(11 << CG6_FHC_TEST_X_SHIFT) |
 			(11 << CG6_FHC_TEST_Y_SHIFT);
 		if (rev < 2)
 			conf |= CG6_FHC_DST_DISABLE;
-		*(fb->s.cg6.fhc) = conf;
+		sbus_writel(conf, fb->s.cg6.fhc);
 	}
 
 	/* Set things in the FBC. Bad things appear to happen if we do
 	 * back to back store/loads on the mode register, so copy it
 	 * out instead. */
-	mode = fbc->mode;
+	mode = sbus_readl(&fbc->mode);
 	do {
-		i = fbc->s;
+		i = sbus_readl(&fbc->s);
 	} while (i & 0x10000000);
 	mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
 		       CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
@@ -569,23 +640,29 @@
 		      CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
 		      CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
 		      CG6_FBC_BDISP_0);
-	fbc->mode = mode;
+	sbus_writel(mode, &fbc->mode);
+
+	sbus_writel(0, &fbc->clip);
+	sbus_writel(0, &fbc->offx);
+	sbus_writel(0, &fbc->offy);
+	sbus_writel(0, &fbc->clipminx);
+	sbus_writel(0, &fbc->clipminy);
+	sbus_writel(fb->type.fb_width - 1, &fbc->clipmaxx);
+	sbus_writel(fb->type.fb_height - 1, &fbc->clipmaxy);
 
-	fbc->clip = 0;
-	fbc->offx = 0;
-	fbc->offy = 0;
-	fbc->clipminx = 0;
-	fbc->clipminy = 0;
-	fbc->clipmaxx = fb->type.fb_width - 1;
-	fbc->clipmaxy = fb->type.fb_height - 1;
 	/* Enable cursor in Brooktree DAC. */
-	fb->s.cg6.bt->addr = 0x06 << 24;
-	fb->s.cg6.bt->control |= 0x03 << 24;
+	sbus_writel(0x06 << 24, &fb->s.cg6.bt->addr);
+	tmp = sbus_readl(&fb->s.cg6.bt->control);
+	tmp |= 0x03 << 24;
+	sbus_writel(tmp, &fb->s.cg6.bt->control);
+
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg6_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);
+	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)
@@ -595,7 +672,7 @@
 	int i;
 	
 	do {
-		i = fbc->s;
+		i = sbus_readl(&fbc->s);
 	} while (i & 0x10000000);
 	return 0;
 }
@@ -608,7 +685,8 @@
 	struct fb_var_screeninfo *var = &fb->var;
 	struct display *disp = &fb->disp;
 	struct fbtype *type = &fb->type;
-	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
+	struct sbus_dev *sdev = fb->sbdp;
+	unsigned long phys = sdev->reg_addrs[0].phys_addr;
 	u32 conf;
 	char *p;
 	char *cardtype;
@@ -616,7 +694,8 @@
 	struct fb_ops *fbops;
 
 	fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
-	if (!fbops) return NULL;
+	if (fbops == NULL)
+		return NULL;
 	
 	*fbops = *fb->info.fbops;
 	fbops->fb_rasterimg = cg6_rasterimg;
@@ -633,20 +712,40 @@
 	var->accel_flags = FB_ACCELF_TEXT;
 	
 	disp->scrollmode = SCROLL_YREDRAW;
-	if (!disp->screen_base)
-		disp->screen_base = (char *)sparc_alloc_io(phys + CG6_RAM_OFFSET, 0, 
-			type->fb_size, "cgsix_ram", fb->iospace, 0);
+	if (!disp->screen_base) {
+		disp->screen_base = (char *)
+			sbus_ioremap(&sdev->resource[0], CG6_RAM_OFFSET,
+				     type->fb_size, "cgsix ram");
+	}
 	disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
-	fb->s.cg6.fbc = (struct cg6_fbc *)sparc_alloc_io(phys + CG6_FBC_OFFSET, 0, 
-			4096, "cgsix_fbc", fb->iospace, 0);
-	fb->s.cg6.tec = (struct cg6_tec *)sparc_alloc_io(phys + CG6_TEC_OFFSET, 0, 
-			sizeof(struct cg6_tec), "cgsix_tec", fb->iospace, 0);
-	fb->s.cg6.thc = (struct cg6_thc *)sparc_alloc_io(phys + CG6_THC_OFFSET, 0, 
-				sizeof(struct cg6_thc), "cgsix_thc", fb->iospace, 0);
-	fb->s.cg6.bt = bt = (struct bt_regs *)sparc_alloc_io(phys + CG6_BROOKTREE_OFFSET, 0, 
-				sizeof(struct bt_regs), "cgsix_dac", fb->iospace, 0);
-	fb->s.cg6.fhc = (u32 *)sparc_alloc_io(phys + CG6_FHC_OFFSET, 0, 
-				sizeof(u32), "cgsix_fhc", fb->iospace, 0);
+	fb->s.cg6.fbc = (struct cg6_fbc *)
+		sbus_ioremap(&sdev->resource[0], CG6_FBC_OFFSET,
+			     4096, "cgsix fbc");
+	fb->s.cg6.tec = (struct cg6_tec *)
+		sbus_ioremap(&sdev->resource[0], CG6_TEC_OFFSET,
+			     sizeof(struct cg6_tec), "cgsix tec");
+	fb->s.cg6.thc = (struct cg6_thc *)
+		sbus_ioremap(&sdev->resource[0], CG6_THC_OFFSET,
+			     sizeof(struct cg6_thc), "cgsix thc");
+	fb->s.cg6.bt = bt = (struct bt_regs *)
+		sbus_ioremap(&sdev->resource[0], CG6_BROOKTREE_OFFSET,
+			     sizeof(struct bt_regs), "cgsix dac");
+	fb->s.cg6.fhc = (u32 *)
+		sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET,
+			     sizeof(u32), "cgsix fhc");
+#if 0
+	prom_printf("CG6: RES[%016lx:%016lx:%016lx]\n",
+		    sdev->resource[0].start,
+		    sdev->resource[0].end,
+		    sdev->resource[0].flags);
+	prom_printf("CG6: fbc(%p) tec(%p) thc(%p) bt(%p) fhc(%p)\n",
+		    fb->s.cg6.fbc,
+		    fb->s.cg6.tec,
+		    fb->s.cg6.thc,
+		    fb->s.cg6.bt,
+		    fb->s.cg6.fhc);
+	prom_halt();
+#endif
 	fb->dispsw = cg6_dispsw;
 
 	fb->margins = cg6_margins;
@@ -664,16 +763,16 @@
 	fb->mmap_map = cg6_mmap_map;
 	
 	/* Initialize Brooktree DAC */
-	bt->addr = 0x04 << 24;         /* color planes */
-	bt->control = 0xff << 24;
-	bt->addr = 0x05 << 24;
-	bt->control = 0x00 << 24;
-	bt->addr = 0x06 << 24;         /* overlay plane */
-	bt->control = 0x73 << 24;
-	bt->addr = 0x07 << 24;
-	bt->control = 0x00 << 24;
+	sbus_writel(0x04 << 24, &bt->addr);         /* color planes */
+	sbus_writel(0xff << 24, &bt->control);
+	sbus_writel(0x05 << 24, &bt->addr);
+	sbus_writel(0x00 << 24, &bt->control);
+	sbus_writel(0x06 << 24, &bt->addr);         /* overlay plane */
+	sbus_writel(0x73 << 24, &bt->control);
+	sbus_writel(0x07 << 24, &bt->addr);
+	sbus_writel(0x00 << 24, &bt->control);
 	
-	conf = *fb->s.cg6.fhc;
+	conf = sbus_readl(fb->s.cg6.fhc);
 	switch(conf & CG6_FHC_CPU_MASK) {
 	case CG6_FHC_CPU_SPARC: p = "sparc"; break;
 	case CG6_FHC_CPU_68020: p = "68020"; break;
@@ -696,12 +795,14 @@
 	                                                                        
 	sprintf(idstring, 
 #ifdef __sparc_v9__
-		    "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys, 
+		    "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys,
 #else	
-		    "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]", fb->iospace, phys, 
+		    "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]",
+		    fb->iospace, phys, 
 #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);
+		    ((sbus_readl(&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);
diff -u --recursive --new-file v2.3.34/linux/drivers/video/cgthreefb.c linux/drivers/video/cgthreefb.c
--- v2.3.34/linux/drivers/video/cgthreefb.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/video/cgthreefb.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: cgthreefb.c,v 1.5 1999/08/10 15:56:04 davem Exp $
+/* $Id: cgthreefb.c,v 1.8 1999/11/19 09:57:08 davem Exp $
  * cgthreefb.c: CGthree frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -71,8 +71,8 @@
 };
 
 /* Offset of interesting structures in the OBIO space */
-#define CG3_REGS_OFFSET	     0x400000
-#define CG3_RAM_OFFSET	     0x800000
+#define CG3_REGS_OFFSET	     0x400000UL
+#define CG3_RAM_OFFSET	     0x800000UL
 
 static struct sbus_mmap_map cg3_mmap_map[] = {
 	{ CG3_MMAP_OFFSET,	CG3_RAM_OFFSET,		SBUS_MMAP_FBSIZE(1) },
@@ -88,30 +88,55 @@
 static void cg3_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
 {
 	struct bt_regs *bt = &fb->s.cg3.regs->cmap;
+	unsigned long flags;
 	u32 *i;
+	volatile u8 *regp;
 	int steps;
 	        
+	spin_lock_irqsave(&fb->lock, flags);
+
 	i = (((u32 *)fb->color_map) + D4M3(index));
 	steps = D4M3(index+count-1) - D4M3(index)+3;
 	                        
-	*(volatile u8 *)&bt->addr = (u8)D4M4(index);
-	while (steps--)
-		bt->color_map = *i++;
+	regp = (volatile u8 *)&bt->addr;
+	sbus_writeb(D4M4(index), regp);
+	while (steps--) {
+		u32 val = *i++;
+		sbus_writel(val, &bt->color_map);
+	}
+
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg3_blank (struct fb_info_sbusfb *fb)
 {
-	fb->s.cg3.regs->control &= ~CG3_CR_ENABLE_VIDEO;
+	unsigned long flags;
+	u8 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	tmp = sbus_readl(&fb->s.cg3.regs->control);
+	tmp &= ~CG3_CR_ENABLE_VIDEO;
+	sbus_writel(tmp, &fb->s.cg3.regs->control);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void cg3_unblank (struct fb_info_sbusfb *fb)
 {
-	fb->s.cg3.regs->control |= CG3_CR_ENABLE_VIDEO;
+	unsigned long flags;
+	u8 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	tmp = sbus_readl(&fb->s.cg3.regs->control);
+	tmp |= CG3_CR_ENABLE_VIDEO;
+	sbus_writel(tmp, &fb->s.cg3.regs->control);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
-static void cg3_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
+static void cg3_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);
+	p->screen_base += (y_margin - fb->y_margin) *
+		p->line_length + (x_margin - fb->x_margin);
 }
 
 static u8 cg3regvals_66hz[] __initdata = {	/* 1152 x 900, 66 Hz */
@@ -150,7 +175,8 @@
 	struct fb_fix_screeninfo *fix = &fb->fix;
 	struct display *disp = &fb->disp;
 	struct fbtype *type = &fb->type;
-	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
+	struct sbus_dev *sdev = fb->sbdp;
+	unsigned long phys = sdev->reg_addrs[0].phys_addr;
 	int cgRDI = strstr(fb->sbdp->prom_name, "cgRDI") != NULL;
 
 #ifndef FBCON_HAS_CFB8
@@ -158,8 +184,9 @@
 #endif
 
 	if (!fb->s.cg3.regs) {
-		fb->s.cg3.regs = (struct cg3_regs *)sparc_alloc_io(phys+CG3_REGS_OFFSET, 0, 
-				sizeof(struct cg3_regs), "cg3_regs", fb->iospace, 0);
+		fb->s.cg3.regs = (struct cg3_regs *)
+			sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET,
+				     sizeof(struct cg3_regs), "cg3 regs");
 		if (cgRDI) {
 			char buffer[40];
 			char *p;
@@ -189,9 +216,11 @@
 	fix->accel = FB_ACCEL_SUN_CGTHREE;
 	
 	disp->scrollmode = SCROLL_YREDRAW;
-	if (!disp->screen_base)
-		disp->screen_base = (char *)sparc_alloc_io(phys+CG3_RAM_OFFSET, 0, 
-			type->fb_size, "cg3_ram", fb->iospace, 0);
+	if (!disp->screen_base) {
+		disp->screen_base = (char *)
+			sbus_ioremap(&sdev->resource[0], CG3_RAM_OFFSET,
+				     type->fb_size, "cg3 ram");
+	}
 	disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
 	fb->dispsw = fbcon_cfb8;
 
@@ -219,7 +248,7 @@
 		if (cgRDI)
 			type = CG3_RDI;
 		else {
-			u8 status = fb->s.cg3.regs->status, mon;
+			u8 status = sbus_readb(&fb->s.cg3.regs->status), mon;
 			if ((status & CG3_SR_ID_MASK) == CG3_SR_ID_COLOR) {
 				mon = status & CG3_SR_RES_MASK;
 				if (mon == CG3_SR_1152_900_76_A ||
@@ -235,12 +264,17 @@
 			}
 		}
 
-		for (p = cg3_regvals[type]; *p; p += 2)
-			((u8 *)fb->s.cg3.regs)[p[0]] = p[1];
-
+		for (p = cg3_regvals[type]; *p; p += 2) {
+			u8 *regp = &((u8 *)fb->s.cg3.regs)[p[0]];
+			sbus_writeb(p[1], regp);
+		}
 		for (p = cg3_dacvals; *p; p += 2) {
-			*(volatile u8 *)&fb->s.cg3.regs->cmap.addr = p[0];
-			*(volatile u8 *)&fb->s.cg3.regs->cmap.control = p[1];
+			volatile u8 *regp;
+
+			regp = (volatile u8 *)&fb->s.cg3.regs->cmap.addr;
+			sbus_writeb(p[0], regp);
+			regp = (volatile u8 *)&fb->s.cg3.regs->cmap.control;
+			sbus_writeb(p[1], regp);
 		}
 	}
 
diff -u --recursive --new-file v2.3.34/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c
--- v2.3.34/linux/drivers/video/creatorfb.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/video/creatorfb.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: creatorfb.c,v 1.29 1999/08/10 15:56:07 davem Exp $
+/* $Id: creatorfb.c,v 1.31 1999/11/19 09:57:12 davem Exp $
  * creatorfb.c: Creator/Creator3D frame buffer driver
  *
  * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
@@ -21,6 +21,8 @@
 
 #include <video/sbusfb.h>
 
+#include <asm/upa.h>
+
 #define	FFB_SFB8R_VOFF		0x00000000
 #define	FFB_SFB8G_VOFF		0x00400000
 #define	FFB_SFB8B_VOFF		0x00800000
@@ -49,24 +51,24 @@
 #define	FFB_PROM_VOFF		0x0bc08000
 #define	FFB_EXP_VOFF		0x0bc18000
 
-#define	FFB_SFB8R_POFF		0x04000000
-#define	FFB_SFB8G_POFF		0x04400000
-#define	FFB_SFB8B_POFF		0x04800000
-#define	FFB_SFB8X_POFF		0x04c00000
-#define	FFB_SFB32_POFF		0x05000000
-#define	FFB_SFB64_POFF		0x06000000
-#define	FFB_FBC_REGS_POFF	0x00600000
-#define	FFB_BM_FBC_REGS_POFF	0x00600000
-#define	FFB_DFB8R_POFF		0x01000000
-#define	FFB_DFB8G_POFF		0x01400000
-#define	FFB_DFB8B_POFF		0x01800000
-#define	FFB_DFB8X_POFF		0x01c00000
-#define	FFB_DFB24_POFF		0x02000000
-#define	FFB_DFB32_POFF		0x03000000
-#define	FFB_FBC_KREGS_POFF	0x00610000
-#define	FFB_DAC_POFF		0x00400000
-#define	FFB_PROM_POFF		0x00000000
-#define	FFB_EXP_POFF		0x00200000
+#define	FFB_SFB8R_POFF		0x04000000UL
+#define	FFB_SFB8G_POFF		0x04400000UL
+#define	FFB_SFB8B_POFF		0x04800000UL
+#define	FFB_SFB8X_POFF		0x04c00000UL
+#define	FFB_SFB32_POFF		0x05000000UL
+#define	FFB_SFB64_POFF		0x06000000UL
+#define	FFB_FBC_REGS_POFF	0x00600000UL
+#define	FFB_BM_FBC_REGS_POFF	0x00600000UL
+#define	FFB_DFB8R_POFF		0x01000000UL
+#define	FFB_DFB8G_POFF		0x01400000UL
+#define	FFB_DFB8B_POFF		0x01800000UL
+#define	FFB_DFB8X_POFF		0x01c00000UL
+#define	FFB_DFB24_POFF		0x02000000UL
+#define	FFB_DFB32_POFF		0x03000000UL
+#define	FFB_FBC_KREGS_POFF	0x00610000UL
+#define	FFB_DAC_POFF		0x00400000UL
+#define	FFB_PROM_POFF		0x00000000UL
+#define	FFB_EXP_POFF		0x00200000UL
 
 /* Draw operations */
 #define FFB_DRAWOP_DOT		0x00
@@ -132,10 +134,18 @@
 
 struct ffb_fbc {
 	/* Next vertex registers */
-	u32		xxx1[3]; volatile u32 alpha; volatile u32 red;
-	volatile u32 green; volatile u32 blue; volatile u32 depth; volatile
-	u32 y; volatile u32 x; u32 xxx2[2]; volatile u32 ryf; volatile u32
-	rxf; u32 xxx3[2];
+	u32		xxx1[3];
+	volatile u32	alpha;
+	volatile u32	red;
+	volatile u32	green;
+	volatile u32	blue;
+	volatile u32	depth;
+	volatile u32	y;
+	volatile u32	x;
+	u32		xxx2[2];
+	volatile u32	ryf;
+	volatile u32	rxf;
+	u32		xxx3[2];
 	
 	volatile u32	dmyf;
 	volatile u32	dmxf;
@@ -275,7 +285,7 @@
 
 	if (cache - n < 0) {
 		fbc = fb->s.ffb.fbc;
-		do {	cache = (fbc->ucsr & FFB_UCSR_FIFO_MASK) - 8;
+		do {	cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK) - 8;
 		} while (cache - n < 0);
 	}
 	fb->s.ffb.fifo_cache = cache - n;
@@ -286,10 +296,11 @@
 	int limit = 10000;
 
 	do {
-		if((ffb->ucsr & FFB_UCSR_ALL_BUSY) == 0)
+		if ((upa_readl(&ffb->ucsr) & FFB_UCSR_ALL_BUSY) == 0)
 			break;
-		if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
-			ffb->ucsr = FFB_UCSR_ALL_ERRORS;
+		if ((upa_readl(&ffb->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) {
+			upa_writel(FFB_UCSR_ALL_ERRORS, &ffb->ucsr);
+		}
 	} while(--limit > 0);
 }
 
@@ -333,13 +344,15 @@
 {
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+	unsigned long flags;
 	u64 yx, hw;
 	int fg;
 	
+	spin_lock_irqsave(&fb->lock, flags);
 	fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
 	if (fg != fb->s.ffb.fg_cache) {
 		FFBFifo(fb, 5);
-		fbc->fg = fg;
+		upa_writel(fg, &fbc->fg);
 		fb->s.ffb.fg_cache = fg;
 	} else
 		FFBFifo(fb, 4);
@@ -354,40 +367,46 @@
 	} else {
 		yx += sx * fontwidth(p); hw += width * fontwidth(p);
 	}
-	*(volatile u64 *)&fbc->by = yx + fb->s.ffb.yx_margin;
-	*(volatile u64 *)&fbc->bh = hw;
+	upa_writeq(yx + fb->s.ffb.yx_margin, &fbc->by);
+	upa_writeq(hw, &fbc->bh);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
 		     int count, unsigned short *boxes)
 {
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+	unsigned long flags;
 	int fg;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
 	if (fg != fb->s.ffb.fg_cache) {
 		FFBFifo(fb, 1);
-		fbc->fg = fg;
+		upa_writel(fg, &fbc->fg);
 		fb->s.ffb.fg_cache = fg;
 	}
 	while (count-- > 0) {
 		FFBFifo(fb, 4);
-		fbc->by = boxes[1];
-		fbc->bx = boxes[0];
-		fbc->bh = boxes[3] - boxes[1];
-		fbc->bw = boxes[2] - boxes[0];
+		upa_writel(boxes[1], &fbc->by);
+		upa_writel(boxes[0], &fbc->bx);
+		upa_writel(boxes[3] - boxes[1], &fbc->bh);
+		upa_writel(boxes[2] - boxes[0], &fbc->bw);
 		boxes += 4;
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
 {
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+	unsigned long flags;
 	int i, xy;
 	u8 *fd;
 	u64 fgbg;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	if (fontheightlog(p)) {
 		xy = (yy << (16 + fontheightlog(p)));
 		i = ((c & p->charmask) << fontheightlog(p));
@@ -407,21 +426,27 @@
 	       ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
 	if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
 		FFBFifo(fb, 2);
-		*(volatile u64 *)&fbc->fg = fgbg;
+		upa_writeq(fgbg, &fbc->fg);
 		*(u64 *)&fb->s.ffb.fg_cache = fgbg;
 	}
 	FFBFifo(fb, 2 + fontheight(p));
-	fbc->fontxy = xy;
-	fbc->fontw = fontwidth(p);
+	upa_writel(xy, &fbc->fontxy);
+	upa_writel(fontwidth(p), &fbc->fontw);
 	if (fontwidth(p) <= 8) {
-		for (i = 0; i < fontheight(p); i++)
-			fbc->font = *fd++ << 24;
+		for (i = 0; i < fontheight(p); i++) {
+			u32 val = *fd++ << 24;
+
+			upa_writel(val, &fbc->font);
+		}
 	} else {
 		for (i = 0; i < fontheight(p); i++) {
-			fbc->font = *(u16 *)fd << 16;
+			u32 val = *(u16 *)fd << 16;
+
+			upa_writel(val, &fbc->font);
 			fd += 2;
 		}
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
@@ -429,15 +454,17 @@
 {
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+	unsigned long flags;
 	int i, xy;
 	u8 *fd1, *fd2, *fd3, *fd4;
 	u64 fgbg;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,scr_readw(s))])) << 32) |
 	       ((u32 *)p->dispsw_data)[attr_bgcol(p,scr_readw(s))];
 	if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
 		FFBFifo(fb, 2);
-		*(volatile u64 *)&fbc->fg = fgbg;
+		upa_writeq(fgbg, &fbc->fg);
 		*(u64 *)&fb->s.ffb.fg_cache = fgbg;
 	}
 	xy = fb->s.ffb.xy_margin;
@@ -453,8 +480,8 @@
 		while (count >= 4) {
 			count -= 4;
 			FFBFifo(fb, 2 + fontheight(p));
-			fbc->fontw = 4 * fontwidth(p);
-			fbc->fontxy = xy;
+			upa_writel(4 * fontwidth(p), &fbc->fontw);
+			upa_writel(xy, &fbc->fontxy);
 			if (fontheightlog(p)) {
 				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
 				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
@@ -467,14 +494,20 @@
 				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
 			}
 			if (fontwidth(p) == 8) {
-				for (i = 0; i < fontheight(p); i++)
-					fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
+				for (i = 0; i < fontheight(p); i++) {
+					u32 val;
+
+					val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
 						<< 8)) << 8)) << 8);
+					upa_writel(val, &fbc->font);
+				}
 				xy += 32;
 			} else {
-				for (i = 0; i < fontheight(p); i++)
-					fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
+				for (i = 0; i < fontheight(p); i++) {
+					u32 val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
 						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
+					upa_writel(val, &fbc->font);
+				}
 				xy += 4 * fontwidth(p);
 			}
 		}
@@ -482,8 +515,8 @@
 		while (count >= 2) {
 			count -= 2;
 			FFBFifo(fb, 2 + fontheight(p));
-			fbc->fontw = 2 * fontwidth(p);
-			fbc->fontxy = xy;
+			upa_writel(2 * fontwidth(p), &fbc->fontw);
+			upa_writel(xy, &fbc->fontxy);
 			if (fontheightlog(p)) {
 				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
 				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
@@ -492,7 +525,9 @@
 				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
 			}
 			for (i = 0; i < fontheight(p); i++) {
-				fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
+				u32 val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
+
+				upa_writel(val, &fbc->font);
 				fd1 += 2; fd2 += 2;
 			}
 			xy += 2 * fontwidth(p);
@@ -501,25 +536,31 @@
 	while (count) {
 		count--;
 		FFBFifo(fb, 2 + fontheight(p));
-		fbc->fontw = fontwidth(p);
-		fbc->fontxy = xy;
+		upa_writel(fontwidth(p), &fbc->fontw);
+		upa_writel(xy, &fbc->fontxy);
 		if (fontheightlog(p))
 			i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
 		else
 			i = ((scr_readw(s++) & p->charmask) * fontheight(p));
 		if (fontwidth(p) <= 8) {
 			fd1 = p->fontdata + i;
-			for (i = 0; i < fontheight(p); i++)
-				fbc->font = *fd1++ << 24;
+			for (i = 0; i < fontheight(p); i++) {
+				u32 val = *fd1++ << 24;
+
+				upa_writel(val, &fbc->font);
+			}
 		} else {
 			fd1 = p->fontdata + (i << 1);
 			for (i = 0; i < fontheight(p); i++) {
-				fbc->font = *(u16 *)fd1 << 16;
+				u32 val = *(u16 *)fd1 << 16;
+
+				upa_writel(val, &fbc->font);
 				fd1 += 2;
 			}
 		}
 		xy += fontwidth(p);
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void ffb_revc(struct display *p, int xx, int yy)
@@ -527,23 +568,61 @@
 	/* Not used if hw cursor */
 }
 
+#if 0
+static void ffb_blank(struct fb_info_sbusfb *fb)
+{
+	struct ffb_dac *dac = fb->s.ffb.dac;
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	upa_writel(0x6000, &dac->type);
+	tmp = (upa_readl(&dac->value) & ~0x1);
+	upa_writel(0x6000, &dac->type);
+	upa_writel(tmp, &dac->value);
+	spin_unlock_irqrestore(&fb->lock, flags);
+}
+#endif
+
+static void ffb_unblank(struct fb_info_sbusfb *fb)
+{
+	struct ffb_dac *dac = fb->s.ffb.dac;
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	upa_writel(0x6000, &dac->type);
+	tmp = (upa_readl(&dac->value) | 0x1);
+	upa_writel(0x6000, &dac->type);
+	upa_writel(tmp, &dac->value);
+	spin_unlock_irqrestore(&fb->lock, flags);
+}
+
 static void ffb_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
 {
 	struct ffb_dac *dac = fb->s.ffb.dac;
+	unsigned long flags;
 	int i, j = count;
 	
-	dac->type = 0x2000 | index;
-	for (i = index; j--; i++)
+	spin_lock_irqsave(&fb->lock, flags);
+	upa_writel(0x2000 | index, &dac->type);
+	for (i = index; j--; i++) {
+		u32 val;
+
 		/* Feed the colors in :)) */
-		dac->value = ((fb->color_map CM(i,0))) |
-			     ((fb->color_map CM(i,1)) << 8) |
-			     ((fb->color_map CM(i,2)) << 16);
+		val = ((fb->color_map CM(i,0))) |
+			((fb->color_map CM(i,1)) << 8) |
+			((fb->color_map CM(i,2)) << 16);
+		upa_writel(val, &dac->value);
+	}
 	if (!p)
-		return;
+		goto out;
 	for (i = index, j = count; i < 16 && j--; i++)
 		((u32 *)p->dispsw_data)[i] = ((fb->color_map CM(i,0))) |
 			      		     ((fb->color_map CM(i,1)) << 8) |
 					     ((fb->color_map CM(i,2)) << 16);
+out:
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static struct display_switch ffb_dispsw __initdata = {
@@ -554,53 +633,67 @@
 static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
 {
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+	unsigned long flags;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	fb->s.ffb.xy_margin = (y_margin << 16) + x_margin;
 	fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin;
 	p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
 	FFBWait(fbc);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
-static inline void ffb_curs_enable (struct fb_info_sbusfb *fb, int enable)
+static __inline__ void __ffb_curs_enable (struct fb_info_sbusfb *fb, int enable)
 {
 	struct ffb_dac *dac = fb->s.ffb.dac;
-	
-	dac->type2 = 0x100;
-	if (fb->s.ffb.dac_rev <= 2)
-		dac->value2 = enable ? 3 : 0;
-	else
-		dac->value2 = enable ? 0 : 3;
+	u32 val;
+
+	upa_writel(0x100, &dac->type2);
+	if (fb->s.ffb.dac_rev <= 2) {
+		val = enable ? 3 : 0;
+	} else {
+		val = enable ? 0 : 3;
+	}
+	upa_writel(val, &dac->value2);
 }
 
 static void ffb_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
 {
 	struct ffb_dac *dac = fb->s.ffb.dac;
+	unsigned long flags;
 	
-	ffb_curs_enable (fb, 0);
-	dac->type2 = 0x102;
-	dac->value2 = (red[0] | (green[0]<<8) | (blue[0]<<16));
-	dac->value2 = (red[1] | (green[1]<<8) | (blue[1]<<16));
+	spin_lock_irqsave(&fb->lock, flags);
+	__ffb_curs_enable (fb, 0);
+	upa_writel(0x102, &dac->type2);
+	upa_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &dac->value2);
+	upa_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &dac->value2);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 /* Set cursor shape */
 static void ffb_setcurshape (struct fb_info_sbusfb *fb)
 {
 	struct ffb_dac *dac = fb->s.ffb.dac;
+	unsigned long flags;
 	int i, j;
 
-	ffb_curs_enable (fb, 0);
+	spin_lock_irqsave(&fb->lock, flags);
+	__ffb_curs_enable (fb, 0);
 	for (j = 0; j < 2; j++) {
-		dac->type2 = j ? 0 : 0x80;
+		u32 val = j ? 0 : 0x80;
+
+		upa_writel(val, &dac->type2);
 		for (i = 0; i < 0x40; i++) {
 			if (fb->cursor.size.fbx <= 32) {
-				dac->value2 = fb->cursor.bits [j][i];
-				dac->value2 = 0;
+				upa_writel(fb->cursor.bits [j][i], &dac->value2);
+				upa_writel(0, &dac->value2);
 			} else {
-				dac->value2 = fb->cursor.bits [j][2*i];
-				dac->value2 = fb->cursor.bits [j][2*i+1];
+				upa_writel(fb->cursor.bits [j][2*i], &dac->value2);
+				upa_writel(fb->cursor.bits [j][2*i+1], &dac->value2);
 			}
 		}
 	}	
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 /* Load cursor information */
@@ -608,31 +701,41 @@
 {
 	struct ffb_dac *dac = fb->s.ffb.dac;
 	struct cg_cursor *c = &fb->cursor;
+	unsigned long flags;
+	u32 val;
 
-	dac->type2 = 0x104;
+	spin_lock_irqsave(&fb->lock, flags);
+	upa_writel(0x104, &dac->type2);
 	/* Should this be just 0x7ff?? 
 	   Should I do some margin handling and setcurshape in that case? */
-	dac->value2 = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16)
-	              |((c->cpos.fbx - c->chot.fbx) & 0xffff);
-	ffb_curs_enable (fb, fb->cursor.enable);
+	val = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16)
+		|((c->cpos.fbx - c->chot.fbx) & 0xffff);
+	upa_writel(val, &dac->value2);
+	__ffb_curs_enable (fb, fb->cursor.enable);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void ffb_switch_from_graph (struct fb_info_sbusfb *fb)
 {
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+	unsigned long flags;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	FFBWait(fbc);
 	fb->s.ffb.fifo_cache = 0;
 	FFBFifo(fb, 8);
-	fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
-	fbc->fbc = 0x2000707f;
-	fbc->rop = FFB_ROP_NEW;
-	fbc->drawop = FFB_DRAWOP_RECTANGLE;
-	fbc->pmask = 0xffffffff;
-	fbc->fontinc = 0x10000;
-	fbc->fg = fb->s.ffb.fg_cache;
-	fbc->bg = fb->s.ffb.bg_cache;
+	upa_writel(FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|
+		   FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST,
+		   &fbc->ppc);
+	upa_writel(0x2000707f, &fbc->fbc);
+	upa_writel(FFB_ROP_NEW, &fbc->rop);
+	upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);
+	upa_writel(0xffffffff, &fbc->pmask);
+	upa_writel(0x10000, &fbc->fontinc);
+	upa_writel(fb->s.ffb.fg_cache, &fbc->fg);
+	upa_writel(fb->s.ffb.bg_cache, &fbc->bg);
 	FFBWait(fbc);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static int __init ffb_rasterimg (struct fb_info *info, int start)
@@ -659,12 +762,15 @@
 		return NULL;
 		
 	disp->dispsw_data = (void *)kmalloc(16 * sizeof(u32), GFP_KERNEL);
-	if (!disp->dispsw_data)
+	if (disp->dispsw_data == NULL)
 		return NULL;
 	memset(disp->dispsw_data, 0, 16 * sizeof(u32));
 
 	fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
-	if (!fbops) return NULL;
+	if (fbops == NULL) {
+		kfree(disp->dispsw_data);
+		return NULL;
+	}
 	
 	*fbops = *fb->info.fbops;
 	fbops->fb_rasterimg = ffb_rasterimg;
@@ -698,8 +804,8 @@
 	disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin;
 	fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin;
 	fb->s.ffb.yx_margin = (((u64)fb->y_margin) << 32) + fb->x_margin;
-	fb->s.ffb.fbc = (struct ffb_fbc *)((char *)__va(regs[0].phys_addr) + FFB_FBC_REGS_POFF);
-	fb->s.ffb.dac = (struct ffb_dac *)((char *)__va(regs[0].phys_addr) + FFB_DAC_POFF);
+	fb->s.ffb.fbc = (struct ffb_fbc *)(regs[0].phys_addr + FFB_FBC_REGS_POFF);
+	fb->s.ffb.dac = (struct ffb_dac *)(regs[0].phys_addr + FFB_DAC_POFF);
 	fb->dispsw = ffb_dispsw;
 
 	fb->margins = ffb_margins;
@@ -709,12 +815,22 @@
 	fb->setcurshape = ffb_setcurshape;
 	fb->switch_from_graph = ffb_switch_from_graph;
 	fb->fill = ffb_fill;
+#if 0
+	/* XXX Can't enable this for now, I've seen cases
+	 * XXX where the VC was blanked, and Xsun24 was started
+	 * XXX via a remote login, the sunfb code did not
+	 * XXX unblank creator when it was mmap'd for some
+	 * XXX reason, investigate later... -DaveM
+	 */
+	fb->blank = ffb_blank;
+	fb->unblank = ffb_unblank;
+#endif
 	
 	/* If there are any read errors or fifo overflow conditions,
 	 * clear them now.
 	 */
-	if((fb->s.ffb.fbc->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
-		fb->s.ffb.fbc->ucsr = FFB_UCSR_ALL_ERRORS;
+	if((upa_readl(&fb->s.ffb.fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
+		upa_writel(FFB_UCSR_ALL_ERRORS, &fb->s.ffb.fbc->ucsr);
 
 	ffb_switch_from_graph(fb);
 	
@@ -726,17 +842,25 @@
 	
 	type->fb_depth = 24;
 	
-	fb->s.ffb.dac->type = 0x8000;
-	fb->s.ffb.dac_rev = (fb->s.ffb.dac->value >> 0x1c);
+	upa_writel(0x8000, &fb->s.ffb.dac->type);
+	fb->s.ffb.dac_rev = (upa_readl(&fb->s.ffb.dac->value) >> 0x1c);
 	                
 	i = prom_getintdefault (fb->prom_node, "board_type", 8);
-	                                                        
-	sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
+
+	sprintf(idstring, "%s at %016lx type %d DAC %d",
+		fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
 	
 	/* Elite3D has different DAC revision numbering, and no DAC revisions
 	   have the reversed meaning of cursor enable */
 	if (afb)
 		fb->s.ffb.dac_rev = 10;
 	
+	/* Unblank it just to be sure.  When there are multiple
+	 * FFB/AFB cards in the system, or it is not the OBP
+	 * chosen console, it will have video outputs off in
+	 * the DAC.
+	 */
+	ffb_unblank(fb);
+
 	return idstring;
 }
diff -u --recursive --new-file v2.3.34/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.3.34/linux/drivers/video/fbmem.c	Tue Dec  7 09:32:46 1999
+++ linux/drivers/video/fbmem.c	Mon Dec 20 22:06:42 1999
@@ -416,19 +416,18 @@
 	if (fb->fb_mmap)
 		return fb->fb_mmap(info, file, vma);
 
-#if defined(__sparc__)
+#if defined(__sparc__) && !defined(__sparc_v9__)
 	/* Should never get here, all fb drivers should have their own
 	   mmap routines */
 	return -EINVAL;
 #else
-	/* non-SPARC... */
+	/* !sparc32... */
 
 	fb->fb_get_fix(&fix, PROC_CONSOLE(info), info);
 
 	/* frame buffer memory */
 	start = fix.smem_start;
 	len = (start & ~PAGE_MASK)+fix.smem_len;
-	start &= PAGE_MASK;
 	len = (len+~PAGE_MASK) & PAGE_MASK;		/* someone's on crack. */
 	if (off >= len) {
 		/* memory mapped io */
@@ -438,13 +437,36 @@
 			return -EINVAL;
 		start = fix.mmio_start;
 		len = (start & ~PAGE_MASK)+fix.mmio_len;
-		start &= PAGE_MASK;
 		len = (len+~PAGE_MASK) & PAGE_MASK;
 	}
+	start &= PAGE_MASK;
 	if ((vma->vm_end - vma->vm_start + off) > len)
 		return -EINVAL;
 	off += start;
 	vma->vm_pgoff = off >> PAGE_SHIFT;
+#if defined(__sparc_v9__)
+	vma->vm_flags |= (VM_SHM | VM_LOCKED);
+	{
+		unsigned long align, j;
+		for (align = 0x400000; align > PAGE_SIZE; align >>= 3)
+			if (len >= align && !((start & ~PAGE_MASK) & (align - 1)))
+				break;
+		if (align > PAGE_SIZE && vma->vm_start & (align - 1)) {
+			/* align as much as possible */
+			struct vm_area_struct *vmm;
+			j = (-vma->vm_start) & (align - 1);
+			vmm = find_vma(current->mm, vma->vm_start);
+			if (!vmm || vmm->vm_start >= vma->vm_end + j) {
+				vma->vm_start += j;
+				vma->vm_end += j;
+			}
+		}
+	}
+	if (io_remap_page_range(vma->vm_start, off,
+				vma->vm_end - vma->vm_start, vma->vm_page_prot, 0))
+		return -EAGAIN;
+	vma->vm_flags |= VM_IO;
+#else
 #if defined(__mc68000__)
 	if (CPU_IS_020_OR_030)
 		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
@@ -476,9 +498,9 @@
 	if (io_remap_page_range(vma->vm_start, off,
 			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
 		return -EAGAIN;
+#endif /* !__sparc_v9__ */
 	return 0;
-
-#endif /* defined(__sparc__) */
+#endif /* !sparc32 */
 }
 
 static int
diff -u --recursive --new-file v2.3.34/linux/drivers/video/iga.h linux/drivers/video/iga.h
--- v2.3.34/linux/drivers/video/iga.h	Thu Oct 15 15:24:18 1998
+++ linux/drivers/video/iga.h	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: iga.h,v 1.1 1998/10/07 11:36:07 jj Exp $
+/* $Id: iga.h,v 1.2 1999/09/11 22:56:31 zaitcev Exp $
  * iga1682.h: Sparc/PCI iga1682 driver constants etc.
  *
  * Copyleft 1998 V. Roganov and G. Raiko
@@ -12,6 +12,8 @@
     unsigned int total_vram;
 };
 
+#define IGA_ATTR_CTL			0x3C0
+#define   IGA_IDX_VGA_OVERSCAN		0x11
 #define DAC_W_INDEX                     0x03C8
 #define DAC_DATA                        0x03C9
 #define IGA_EXT_CNTRL                   0x3CE
diff -u --recursive --new-file v2.3.34/linux/drivers/video/igafb.c linux/drivers/video/igafb.c
--- v2.3.34/linux/drivers/video/igafb.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/video/igafb.c	Mon Dec 20 22:06:42 1999
@@ -23,11 +23,9 @@
        Support for video modes and acceleration must be added
        together with accelerated X-Windows driver implementation.
 
-                                                (Anyone to help with this?)
-
        Most important thing at this moment is that we have working
        JavaEngine1  console & X  with new console interface.
-       
+
 ******************************************************************************/
 
 #include <linux/module.h>
@@ -78,7 +76,7 @@
 struct fb_info_iga {
     struct fb_info fb_info;
     unsigned long frame_buffer_phys;
-    unsigned long frame_buffer;
+    char *frame_buffer;
     unsigned long io_base_phys;
     unsigned long io_base;
     u32 total_vram;
@@ -142,23 +140,19 @@
 
 /*
  *   Memory-mapped I/O functions for Sparc PCI
+ *
+ * On sparc we happen to access I/O with memory mapped functions too.
  */ 
-static inline unsigned char pci_inb (struct fb_info_iga *info, 
-				     unsigned int reg) 
-{
-	return *(volatile unsigned char*)(info->io_base + reg);
-}
-static inline void pci_outb (struct fb_info_iga *info, unsigned char c,
-			     unsigned int reg) 
-{
-	*(volatile unsigned char*)(info->io_base + reg) = c;
-}
+#define pci_inb(info, reg)        readb(info->io_base+(reg))
+#define pci_outb(info, val, reg)  writeb(val, info->io_base+(reg))
+
 static inline unsigned int iga_inb(struct fb_info_iga *info,
 				   unsigned int reg, unsigned int idx )
 {
         pci_outb(info, idx, reg);
         return pci_inb(info, reg + 1);
 }
+
 static inline void iga_outb(struct fb_info_iga *info, unsigned char val,
 			    unsigned int reg, unsigned int idx )
 {
@@ -176,8 +170,24 @@
 {
         int i;
 
-        for (i=0; i < 3; i++) 
-                iga_outb(info, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
+#if 0
+	/*
+	 * PROM does this for us, so keep this code as a reminder
+	 * about required read from 0x3DA and writing of 0x20 in the end.
+	 */
+	(void) pci_inb(info, 0x3DA);		/* required for every access */
+	pci_outb(info, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL);
+	(void) pci_inb(info, IGA_ATTR_CTL+1);
+	pci_outb(info, 0x38, IGA_ATTR_CTL);
+	pci_outb(info, 0x20, IGA_ATTR_CTL);	/* re-enable visual */
+#endif
+	/*
+	 * This does not work as it was designed because the overscan
+	 * color is looked up in the palette. Therefore, under X11
+	 * overscan changes color.
+	 */
+	for (i=0; i < 3; i++)
+		iga_outb(info, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
 }
 
 
@@ -217,7 +227,7 @@
         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
         strcpy(fix->id, igafb_name);
 
-        fix->smem_start = fb->frame_buffer;
+        fix->smem_start = (unsigned long) fb->frame_buffer;
         fix->smem_len = fb->total_vram;
         fix->xpanstep = 0;
         fix->ypanstep = 0;
@@ -269,17 +279,17 @@
 	for (page = 0; page < size; ) {
 		map_size = 0;
 		for (i = 0; fb->mmap_map[i].size; i++) {
-			unsigned long start = (fb->mmap_map[i].voff) >> PAGE_SHIFT;
-			unsigned long end = start + (fb->mmap_map[i].size) >> PAGE_SHIFT;
-			unsigned long offset = vma->vm_pgoff + (page >> PAGE_SHIFT);
+			unsigned long start = fb->mmap_map[i].voff;
+			unsigned long end = start + fb->mmap_map[i].size;
+			unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page;
 
 			if (start > offset)
 				continue;
 			if (offset >= end)
 				continue;
 
-			map_size = fb->mmap_map[i].size - ((offset - start) << PAGE_SHIFT);
-			map_offset = fb->mmap_map[i].poff + ((offset - start) << PAGE_SHIFT);
+			map_size = fb->mmap_map[i].size - (offset - start);
+			map_offset = fb->mmap_map[i].poff + (offset - start);
 			break;
 		}
 		if (!map_size) {
@@ -359,13 +369,13 @@
         info->palette[regno].red   = red;
         info->palette[regno].green = green;
         info->palette[regno].blue  = blue;
-        
+
 	pci_outb(info, regno, DAC_W_INDEX);
 	pci_outb(info, red,   DAC_DATA);
 	pci_outb(info, green, DAC_DATA);
 	pci_outb(info, blue,  DAC_DATA);
 
-	if (regno << 16)
+	if (regno < 16)
 		switch (default_var.bits_per_pixel) {
 #ifdef FBCON_HAS_CFB16
 		case 16:
@@ -475,7 +485,7 @@
         struct fb_fix_screeninfo fix;
         struct display *display;
         struct display_switch *sw;
-        
+
         if (con >= 0)
                 display = &fb_display[con];
         else 
@@ -484,7 +494,7 @@
         igafb_get_fix(&fix, con, &info->fb_info);
 
         memset(display, 0, sizeof(struct display));
-        display->screen_base = (char*)info->frame_buffer;
+        display->screen_base = info->frame_buffer;
         display->visual = fix.visual;
         display->type = fix.type;
         display->type_aux = fix.type_aux;
@@ -506,19 +516,19 @@
         case 15:
         case 16:
                 sw = &fbcon_cfb16;
-		display->dispsw_data = fbcon_cmap.cfb16;
+		display->dispsw_data = info->fbcon_cmap.cfb16;
                 break;
 #endif
 #ifdef FBCON_HAS_CFB24
 	case 24:
 		sw = &fbcon_cfb24;
-		display->dispsw_data = fbcon_cmap.cfb24;
+		display->dispsw_data = info->fbcon_cmap.cfb24;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB32
         case 32:
                 sw = &fbcon_cfb32;
-		display->dispsw_data = fbcon_cmap.cfb32;
+		display->dispsw_data = info->fbcon_cmap.cfb32;
                 break;
 #endif
         default:
@@ -534,15 +544,15 @@
 static int igafb_switch(int con, struct fb_info *fb_info)
 {
 	struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
-	
+
         /* Do we have to save the colormap? */
         if (fb_display[info->currcon].cmap.len)
                 fb_get_cmap(&fb_display[info->currcon].cmap, 1,
                             iga_getcolreg, fb_info);
-        
-        info->currcon = con;
-        /* Install new colormap */
-        do_install_cmap(con, fb_info);
+
+	info->currcon = con;
+	/* Install new colormap */
+	do_install_cmap(con, fb_info);
 	igafb_update_var(con, fb_info);
         return 1;
 }
@@ -577,15 +587,17 @@
         if (default_var.bits_per_pixel > 8) {
                 info->video_cmap_len = 16;
         } else {
-		int i, j;
-                for(i = 0; i < 16; i++) {
-                        j = color_table[i];
-                        info->palette[i].red   = default_red[j];
-                        info->palette[i].green = default_grn[j];
-                        info->palette[i].blue  = default_blu[j];
-                }
                 info->video_cmap_len = 256;
         }
+	{
+		int j, k;
+		for (j = 0; j < 16; j++) {
+			k = color_table[j];
+			info->palette[j].red = default_red[k];
+			info->palette[j].green = default_grn[k];
+			info->palette[j].blue = default_blu[k];
+		}
+	}
 
 	strcpy(info->fb_info.modename, igafb_name);
 	info->fb_info.node = -1;
@@ -598,16 +610,6 @@
 	info->fb_info.blank = &igafb_blank;
 	info->fb_info.flags=FBINFO_FLAG_DEFAULT;
 
-	{
-		int j, k;
-		for (j = 0; j < 16; j++) {
-			k = color_table[j];
-			info->palette[j].red = default_red[k];
-			info->palette[j].green = default_grn[k];
-			info->palette[j].blue = default_blu[k];
-		}
-	}
-
 	igafb_set_disp(-1, info);
 
 	if (register_framebuffer(&info->fb_info) < 0)
@@ -619,7 +621,7 @@
 
 	iga_blank_border(info); 
 	return 1;
-}	
+}
 
 
 int __init igafb_init(void)
@@ -637,6 +639,10 @@
         pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 
                                PCI_DEVICE_ID_INTERG_1682, 0);
 	if (pdev == NULL) {
+		/*
+		 * XXX We tried to use cyber2000fb.c for IGS 2000.
+		 * But it does not initialize the chip in JavaStation-E, alas.
+		 */
         	pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 
                                0x2000, 0);
         	if(pdev == NULL)
@@ -651,35 +657,43 @@
         }
         memset(info, 0, sizeof(struct fb_info_iga));
 
-	info->frame_buffer = pdev->resource[0].start;
+	info->frame_buffer = ioremap(pdev->resource[0].start, 1024*1024*2);
 	if (!info->frame_buffer) {
 		kfree(info);
 		return -ENXIO;
 	}
 
-        pcibios_read_config_dword(0, pdev->devfn,
-                                  PCI_BASE_ADDRESS_0, 
-                                  (unsigned int*)&addr);
+	addr = pdev->resource[0].start;
 	if (!addr)
 		return -ENXIO;
 	info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
 
 #ifdef __sparc__
-
-	info->io_base_phys = info->frame_buffer_phys;
-
 	/*
-	 * The right test would be to look if there is a base I/O address.
-	 * But it appears that IGA 1682 reuses _memory_ address as a base
-	 * for I/O accesses.
+	 * The following is sparc specific and this is why:
+	 *
+	 * IGS2000 has its I/O memory mapped and we want
+	 * to generate memory cycles on PCI, e.g. do ioremap(),
+	 * then readb/writeb() as in Documentation/IO-mapping.txt.
+	 *
+	 * IGS1682 is more traditional, it responds to PCI I/O
+	 * cycles, so we want to access it with inb()/outb().
+	 *
+	 * On sparc, PCIC converts CPU memory access within
+	 * phys window 0x3000xxxx into PCI I/O cycles. Therefore
+	 * we may use readb/writeb to access them with IGS1682.
+	 *
+	 * We do not take io_base_phys from resource[n].start
+	 * on IGS1682 because that chip is BROKEN. It does not
+	 * have a base register for I/O. We just "know" what its
+	 * I/O addresses are.
 	 */
 	if (iga2000) {
-		info->io_base = (int) sparc_alloc_io(info->frame_buffer_phys |
-		    0x00800000, NULL, 0x1000, "iga", 0, 0);
+		info->io_base_phys = info->frame_buffer_phys | 0x00800000;
 	} else {
-		/* Obtain virtual address and correct physical by PCIC shift */
-		info->io_base = pcic_alloc_io(&info->io_base_phys);
+		info->io_base_phys = 0x30000000;	/* XXX */
 	}
+	info->io_base = (int) ioremap(info->io_base_phys, 0x1000);
 	if (!info->io_base) {
                 kfree(info);
 		return -ENXIO;
@@ -748,6 +762,7 @@
             }
 
 #endif
+
         if (!iga_init(info)) {
 		if (info->mmap_map)
 			kfree(info->mmap_map);
diff -u --recursive --new-file v2.3.34/linux/drivers/video/leofb.c linux/drivers/video/leofb.c
--- v2.3.34/linux/drivers/video/leofb.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/video/leofb.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: leofb.c,v 1.7 1999/08/09 11:06:52 jj Exp $
+/* $Id: leofb.c,v 1.10 1999/11/19 09:57:05 davem Exp $
  * leofb.c: Leo (ZX) 24/8bit frame buffer driver
  *
  * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
@@ -23,19 +23,19 @@
 #include <video/sbusfb.h>
 #include <asm/io.h>
 
-#define LEO_OFF_LC_SS0_KRN	0x00200000
-#define LEO_OFF_LC_SS0_USR	0x00201000
-#define LEO_OFF_LC_SS1_KRN	0x01200000
-#define LEO_OFF_LC_SS1_USR	0x01201000
-#define LEO_OFF_LD_SS0		0x00400000
-#define LEO_OFF_LD_SS1		0x01400000
-#define LEO_OFF_LD_GBL		0x00401000
-#define LEO_OFF_LX_KRN		0x00600000
-#define LEO_OFF_LX_CURSOR	0x00601000
-#define LEO_OFF_SS0		0x00800000
-#define LEO_OFF_SS1		0x01800000
-#define LEO_OFF_UNK		0x00602000
-#define LEO_OFF_UNK2		0x00000000
+#define LEO_OFF_LC_SS0_KRN	0x00200000UL
+#define LEO_OFF_LC_SS0_USR	0x00201000UL
+#define LEO_OFF_LC_SS1_KRN	0x01200000UL
+#define LEO_OFF_LC_SS1_USR	0x01201000UL
+#define LEO_OFF_LD_SS0		0x00400000UL
+#define LEO_OFF_LD_SS1		0x01400000UL
+#define LEO_OFF_LD_GBL		0x00401000UL
+#define LEO_OFF_LX_KRN		0x00600000UL
+#define LEO_OFF_LX_CURSOR	0x00601000UL
+#define LEO_OFF_SS0		0x00800000UL
+#define LEO_OFF_SS1		0x01800000UL
+#define LEO_OFF_UNK		0x00602000UL
+#define LEO_OFF_UNK2		0x00000000UL
 
 #define LEO_CUR_ENABLE		0x00000080
 #define LEO_CUR_UPDATE		0x00000030
@@ -175,14 +175,16 @@
 {
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = fb->s.leo.ld_ss0;
+	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
+	unsigned long flags;
 	int x, y, w, h;
 	int i;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	do {
-		i = us->csr;
+		i = sbus_readl(&us->csr);
 	} while (i & 0x20000000);
-	ss->fg = (attr_bgcol_ec(p,conp)<<24);
+	sbus_writel((attr_bgcol_ec(p,conp)<<24), &ss->fg);
 	if (fontheightlog(p)) {
 		y = sy << fontheightlog(p); h = height << fontheightlog(p);
 	} else {
@@ -193,9 +195,10 @@
 	} else {
 		x = sx * fontwidth(p); w = width * fontwidth(p);
 	}
-	us->extent = (w - 1) | ((h - 1) << 11);
-	us->fill = (x + fb->x_margin) | ((y + fb->y_margin) << 11) |
-		   0x80000000;
+	sbus_writel((w - 1) | ((h - 1) << 11), &us->extent);
+	sbus_writel((x + fb->x_margin) | ((y + fb->y_margin) << 11) | 0x80000000,
+		    &us->fill);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
@@ -203,29 +206,36 @@
 {
 	int i;
 	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = fb->s.leo.ld_ss0;
+	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
+	unsigned long flags;
 	
-	ss->fg = (attr_bgcol(p,s)<<24);
+	spin_lock_irqsave(&fb->lock, flags);
+	sbus_writel((attr_bgcol(p,s)<<24), &ss->fg);
 	while (count-- > 0) {
 		do {
-			i = us->csr;
+			i = sbus_readl(&us->csr);
 		} while (i & 0x20000000);
-		us->extent = (boxes[2] - boxes[0] - 1) | 
-			     ((boxes[3] - boxes[1] - 1) << 11);
-		us->fill = boxes[0] | (boxes[1] << 11) | 0x80000000;
+		sbus_writel((boxes[2] - boxes[0] - 1) | 
+			    ((boxes[3] - boxes[1] - 1) << 11),
+			    &us->extent);
+		sbus_writel(boxes[0] | (boxes[1] << 11) | 0x80000000,
+			    &us->fill);
 		boxes += 4;
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
 {
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = fb->s.leo.ld_ss0;
+	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
+	unsigned long flags;
 	int i, x, y;
 	u8 *fd;
 	u32 *u;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	if (fontheightlog(p)) {
 		y = yy << (fontheightlog(p) + 11);
 		i = (c & p->charmask) << fontheightlog(p);
@@ -242,21 +252,28 @@
 	else
 		x = xx * fontwidth(p);
 	do {
-		i = us->csr;
+		i = sbus_readl(&us->csr);
 	} while (i & 0x20000000);
-	ss->fg = attr_fgcol(p,c) << 24;
-	ss->bg = attr_bgcol(p,c) << 24;
-	us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p));
+	sbus_writel(attr_fgcol(p,c) << 24, &ss->fg);
+	sbus_writel(attr_bgcol(p,c) << 24, &ss->bg);
+	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)),
+		    &us->fontmsk);
 	u = ((u32 *)p->screen_base) + y + x;
 	if (fontwidth(p) <= 8) {
-		for (i = 0; i < fontheight(p); i++, u += 2048)
-			*u = *fd++ << 24;
+		for (i = 0; i < fontheight(p); i++, u += 2048) {
+			u32 val = *fd++ << 24;
+
+			sbus_writel(val, u);
+		}
 	} else {
 		for (i = 0; i < fontheight(p); i++, u += 2048) {
-			*u = *(u16 *)fd << 16;
+			u32 val = *(u16 *)fd << 16;
+
+			sbus_writel(val, u);
 			fd += 2;
 		}
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
@@ -264,17 +281,19 @@
 {
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = fb->s.leo.ld_ss0;
+	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
+	unsigned long flags;
 	int i, x, y;
 	u8 *fd1, *fd2, *fd3, *fd4;
 	u32 *u;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	do {
-		i = us->csr;
+		i = sbus_readl(&us->csr);
 	} while (i & 0x20000000);
-	ss->fg = attr_fgcol(p,scr_readw(s)) << 24;
-	ss->bg = attr_bgcol(p,scr_readw(s)) << 24;
-	us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p));
+	sbus_writel(attr_fgcol(p,scr_readw(s)) << 24, &ss->fg);
+	sbus_writel(attr_bgcol(p,scr_readw(s)) << 24, &ss->bg);
+	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
 	if (fontwidthlog(p))
 		x = (xx << fontwidthlog(p));
 	else
@@ -285,7 +304,7 @@
 		y = (yy * fontheight(p)) << 11;
 	u = ((u32 *)p->screen_base) + y + x;
 	if (fontwidth(p) <= 8) {
-		us->fontmsk = 0xFFFFFFFF<<(32-4*fontwidth(p));
+		sbus_writel(0xFFFFFFFF<<(32-4*fontwidth(p)), &us->fontmsk);
 		x = 4*fontwidth(p) - fontheight(p)*2048;
 		while (count >= 4) {
 			count -= 4;
@@ -301,19 +320,27 @@
 				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
 			}
 			if (fontwidth(p) == 8) {
-				for (i = 0; i < fontheight(p); i++, u += 2048)
-					*u = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
+				for (i = 0; i < fontheight(p); i++, u += 2048) {
+					u32 val;
+
+					val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
 						<< 8)) << 8)) << 8);
+					sbus_writel(val, u);
+				}
 				u += x;
 			} else {
-				for (i = 0; i < fontheight(p); i++, u += 2048)
-					*u = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
+				for (i = 0; i < fontheight(p); i++, u += 2048) {
+					u32 val;
+
+					val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
 						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
+					sbus_writel(val, u);
+				}
 				u += x;
 			}
 		}
 	} else {
-		us->fontmsk = 0xFFFFFFFF<<(32-2*fontwidth(p));
+		sbus_writel(0xFFFFFFFF<<(32-2*fontwidth(p)), &us->fontmsk);
 		x = 2*fontwidth(p) - fontheight(p)*2048;
 		while (count >= 2) {
 			count -= 2;
@@ -325,13 +352,16 @@
 				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
 			}
 			for (i = 0; i < fontheight(p); i++, u += 2048) {
-				*u = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
+				u32 val;
+
+				val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
+				sbus_writel(val, u);
 				fd1 += 2; fd2 += 2;
 			}
 			u += x;
 		}
 	}
-	us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p));
+	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
 	x = fontwidth(p) - fontheight(p)*2048;
 	while (count) {
 		count--;
@@ -341,17 +371,23 @@
 			i = ((scr_readw(s++) & p->charmask) * fontheight(p));
 		if (fontwidth(p) <= 8) {
 			fd1 = p->fontdata + i;
-			for (i = 0; i < fontheight(p); i++, u += 2048)
-				*u = *fd1++ << 24;
+			for (i = 0; i < fontheight(p); i++, u += 2048) {
+				u32 val = *fd1++ << 24;
+
+				sbus_writel(val, u);
+			}
 		} else {
 			fd1 = p->fontdata + (i << 1);
 			for (i = 0; i < fontheight(p); i++, u += 2048) {
-				*u = *(u16 *)fd1 << 16;
+				u32 val = *(u16 *)fd1 << 16;
+
+				sbus_writel(val, u);
 				fd1 += 2;
 			}
 		}
 		u += x;
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void leo_revc(struct display *p, int xx, int yy)
@@ -363,32 +399,53 @@
 {
 	int i;
 	
-	for (i = 0; (lx_krn->krn_csr & LEO_KRN_CSR_PROGRESS) && i < 300000; i++)
+	for (i = 0; (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000; i++)
 		udelay (1); /* Busy wait at most 0.3 sec */
-	if (i == 300000) return -EFAULT; /* Timed out - should we print some message? */
+	if (i == 300000)
+		return -EFAULT; /* Timed out - should we print some message? */
 	return 0;
 }
 
 static void leo_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
 {
         struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
+	unsigned long flags;
+	u32 tmp;
 	int i;
 	
-	lx_krn->krn_type = LEO_KRN_TYPE_CLUT0;
+	spin_lock_irqsave(&fb->lock, flags);
+	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
 	i = leo_wait (lx_krn);
-	if (i) return;
-	lx_krn->krn_type = LEO_KRN_TYPE_CLUTDATA;
-	for (i = 0; i < 256; i++)
-		lx_krn->krn_value = fb->color_map CM(i,0) |
-				    (fb->color_map CM(i,1) << 8) |
-				    (fb->color_map CM(i,2) << 16); /* Throw colors there :)) */
-	lx_krn->krn_type = LEO_KRN_TYPE_CLUT0;
-	lx_krn->krn_csr |= (LEO_KRN_CSR_UNK|LEO_KRN_CSR_UNK2);
+	if (i)
+		goto out;
+	sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type);
+	for (i = 0; i < 256; i++) {
+		u32 val;
+
+		val = fb->color_map CM(i,0) |
+			(fb->color_map CM(i,1) << 8) |
+			(fb->color_map CM(i,2) << 16);
+
+		sbus_writel(val, &lx_krn->krn_value); /* Throw colors there :)) */
+	}
+	sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type);
+	tmp = sbus_readl(&lx_krn->krn_csr);
+	tmp |= (LEO_KRN_CSR_UNK|LEO_KRN_CSR_UNK2);
+	sbus_writel(tmp, &lx_krn->krn_csr);
+out:
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void leo_restore_palette (struct fb_info_sbusfb *fb)
 {
-	fb->s.leo.ld_ss1->ss1_misc &= ~(LEO_SS1_MISC_ENABLE);
+	u32 tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc);
+	tmp &= ~(LEO_SS1_MISC_ENABLE);
+	sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static struct display_switch leo_dispsw __initdata = {
@@ -399,15 +456,20 @@
 static void leo_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
 {
         struct leo_cursor *l = fb->s.leo.cursor;
+	unsigned long flags;
 	int i;
-                
-	for (i = 0; (l->cur_misc & LEO_CUR_PROGRESS) && i < 300000; i++)
+
+	spin_lock_irqsave(&fb->lock, flags);
+	for (i = 0; (sbus_readl(&l->cur_misc) & LEO_CUR_PROGRESS) && i < 300000; i++)
 		udelay (1); /* Busy wait at most 0.3 sec */
-	if (i == 300000) return; /* Timed out - should we print some message? */
-	l->cur_type = LEO_CUR_TYPE_CMAP;
-	l->cur_data = (red[0] | (green[0]<<8) | (blue[0]<<16));
-	l->cur_data = (red[1] | (green[1]<<8) | (blue[1]<<16));
-	l->cur_misc = LEO_CUR_UPDATECMAP;
+	if (i == 300000)
+		goto out; /* Timed out - should we print some message? */
+	sbus_writel(LEO_CUR_TYPE_CMAP, &l->cur_type);
+	sbus_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &l->cur_data);
+	sbus_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &l->cur_data);
+	sbus_writel(LEO_CUR_UPDATECMAP, &l->cur_misc);
+out:
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 /* Set cursor shape */
@@ -416,10 +478,15 @@
 	int i, j, k;
 	u32 m, n, mask;
 	struct leo_cursor *l = fb->s.leo.cursor;
-                        
-	l->cur_misc &= ~LEO_CUR_ENABLE;
+	u32 tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	tmp = sbus_readl(&l->cur_misc);
+	tmp &= ~LEO_CUR_ENABLE;
+	sbus_writel(tmp, &l->cur_misc);
 	for (k = 0; k < 2; k ++) {
-		l->cur_type = (k * LEO_CUR_TYPE_IMAGE); /* LEO_CUR_TYPE_MASK is 0 */
+		sbus_writel((k * LEO_CUR_TYPE_IMAGE), &l->cur_type);
 		for (i = 0; i < 32; i++) {
 			mask = 0;
 			m = fb->cursor.bits[k][i];
@@ -427,10 +494,13 @@
 			for (j = 0, n = 1; j < 32; j++, n <<= 1)
 				if (m & n)
 					mask |= (0x80000000 >> j);
-			l->cur_data = mask;
+			sbus_writel(mask, &l->cur_data);
 		}
 	}
-	l->cur_misc |= LEO_CUR_ENABLE;
+	tmp = sbus_readl(&l->cur_misc);
+	tmp |= LEO_CUR_ENABLE;
+	sbus_writel(tmp, &l->cur_misc);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 /* Load cursor information */
@@ -438,26 +508,54 @@
 {
 	struct cg_cursor *c = &fb->cursor;
 	struct leo_cursor *l = fb->s.leo.cursor;
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	tmp = sbus_readl(&l->cur_misc);
+	tmp &= ~LEO_CUR_ENABLE;
+	sbus_writel(tmp, &l->cur_misc);
+
+	sbus_writel(((c->cpos.fbx - c->chot.fbx) & 0x7ff) |
+		    (((c->cpos.fby - c->chot.fby) & 0x7ff) << 11),
+		    &l->cur_cursxy);
 
-	l->cur_misc &= ~LEO_CUR_ENABLE;
-	l->cur_cursxy = ((c->cpos.fbx - c->chot.fbx) & 0x7ff)
-	|(((c->cpos.fby - c->chot.fby) & 0x7ff) << 11);
-	l->cur_misc |= LEO_CUR_UPDATE;
+	tmp = sbus_readl(&l->cur_misc);
+	tmp |= LEO_CUR_UPDATE;
 	if (c->enable)
-		l->cur_misc |= LEO_CUR_ENABLE;
+		tmp |= LEO_CUR_ENABLE;
+	sbus_writel(tmp, &l->cur_misc);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void leo_blank (struct fb_info_sbusfb *fb)
 {
-	fb->s.leo.lx_krn->krn_type = LEO_KRN_TYPE_VIDEO;
-	fb->s.leo.lx_krn->krn_csr &= ~LEO_KRN_CSR_ENABLE;
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
+
+	tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr);
+	tmp &= ~LEO_KRN_CSR_ENABLE;
+	sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void leo_unblank (struct fb_info_sbusfb *fb)
 {
-	fb->s.leo.lx_krn->krn_type = LEO_KRN_TYPE_VIDEO;
-	if (!(fb->s.leo.lx_krn->krn_csr & LEO_KRN_CSR_ENABLE))
-		fb->s.leo.lx_krn->krn_csr |= LEO_KRN_CSR_ENABLE;
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	sbus_writel(LEO_KRN_TYPE_VIDEO, &fb->s.leo.lx_krn->krn_type);
+
+	tmp = sbus_readl(&fb->s.leo.lx_krn->krn_csr);
+	if (!(tmp & LEO_KRN_CSR_ENABLE)) {
+		tmp |= LEO_KRN_CSR_ENABLE;
+		sbus_writel(tmp, &fb->s.leo.lx_krn->krn_csr);
+	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static int __init
@@ -467,20 +565,21 @@
 	struct fb_wid_item *wi;
 	int i, j;
 
-	lx_krn->krn_type = LEO_KRN_TYPE_WID;
+	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
 	i = leo_wait (lx_krn);
-	if (i) return i;
+	if (i)
+		return i;
 	for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
 		switch (wi->wi_type) {
 		case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break;
 		case FB_WID_DBL_24: j = wi->wi_index & 0x3f; break;
 		default: return -EINVAL;
 		}
-		lx_krn->krn_type = 0x5800 + j;
-		lx_krn->krn_value = wi->wi_values[0];
+		sbus_writel(0x5800 + j, &lx_krn->krn_type);
+		sbus_writel(wi->wi_values[0], &lx_krn->krn_value);
 	}
-	lx_krn->krn_type = LEO_KRN_TYPE_WID;
-	lx_krn->krn_csr = 3;
+	sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type);
+	sbus_writel(3, &lx_krn->krn_csr);
 	return 0;
 }
 
@@ -492,35 +591,38 @@
 static void leo_switch_from_graph (struct fb_info_sbusfb *fb)
 {
 	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
-	register struct leo_ld *ss = fb->s.leo.ld_ss0;
+	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
+	unsigned long flags;
 
-	ss->wid = 0xffffffff;	
-	ss->wmask = 0xffff;
-	ss->vclipmin = 0;
-	ss->vclipmax = fb->s.leo.extent;
-	ss->planemask = 0xff000000;
-	ss->rop = 0x310850;
-	ss->widclip = 0;
-	us->addrspace = 4;
-	us->fontt = 0;
+	spin_lock_irqsave(&fb->lock, flags);
+	sbus_writel(0xffffffff, &ss->wid);
+	sbus_writel(0xffff, &ss->wmask);
+	sbus_writel(0, &ss->vclipmin);
+	sbus_writel(fb->s.leo.extent, &ss->vclipmax);
+	sbus_writel(0xff000000, &ss->planemask);
+	sbus_writel(0x310850, &ss->rop);
+	sbus_writel(0, &ss->widclip);
+	sbus_writel(4, &us->addrspace);
+	sbus_writel(0, &us->fontt);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 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;
+	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
 
 	if (start) {
-		ss->wid = 1;
-		ss->planemask = 0xffffff;
-		ss->rop = 0x310b90;
-		us->addrspace = 0;
+		sbus_writel(1, &ss->wid);
+		sbus_writel(0xffffff, &ss->planemask); 
+		sbus_writel(0x310b90, &ss->rop);
+		sbus_writel(0, &us->addrspace);
 	} else {
-		ss->wid = 0xffffffff;
-		ss->planemask = 0xff000000;
-		ss->rop = 0x310850;
-		us->addrspace = 4;
+		sbus_writel(0xffffffff, &ss->wid);
+		sbus_writel(0xff000000, &ss->planemask);
+		sbus_writel(0x310850, &ss->rop);
+		sbus_writel(4, &us->addrspace);
 	}
 	return 0;
 }
@@ -533,13 +635,15 @@
 	struct fb_var_screeninfo *var = &fb->var;
 	struct display *disp = &fb->disp;
 	struct fbtype *type = &fb->type;
-	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
+	struct sbus_dev *sdev = fb->sbdp;
+	unsigned long phys = sdev->reg_addrs[0].phys_addr;
 	struct fb_wid_item wi;
 	struct fb_wid_list wl;
 	int i;
 	register struct leo_lc_ss0_usr *us;
 	register struct leo_ld *ss;
 	struct fb_ops *fbops;
+	u32 tmp;
 
 	strcpy(fb->info.modename, "Leo");
 		
@@ -554,32 +658,36 @@
 	var->accel_flags = FB_ACCELF_TEXT;
 	
 	fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
-	if (!fbops) return NULL;
+	if (fbops == NULL)
+		return NULL;
 	
 	*fbops = *fb->info.fbops;
 	fbops->fb_rasterimg = leo_rasterimg;
 	fb->info.fbops = fbops;
 	
 	disp->scrollmode = SCROLL_YREDRAW;
-	if (!disp->screen_base)
-		disp->screen_base = (char *)sparc_alloc_io(phys + LEO_OFF_SS0, 0, 
-			0x800000, "leo_ram", fb->iospace, 0);
+	if (!disp->screen_base) {
+		disp->screen_base = (char *)
+			sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0,
+				     0x800000, "leo ram");
+	}
 	disp->screen_base += 8192 * fb->y_margin + 4 * fb->x_margin;
 	us = fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *)
-			sparc_alloc_io(phys + LEO_OFF_LC_SS0_USR, 0, 
-			0x1000, "leo_lc_ss0_usr", fb->iospace, 0);
-	ss = fb->s.leo.ld_ss0 = (struct leo_ld *)
-			sparc_alloc_io(phys + LEO_OFF_LD_SS0, 0, 
-			0x1000, "leo_ld_ss0", fb->iospace, 0);
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR,
+			     0x1000, "leolc ss0usr");
+	fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *)
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0,
+			     0x1000, "leold ss0");
+	ss = (struct leo_ld *) fb->s.leo.ld_ss0;
 	fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *)
-			sparc_alloc_io(phys + LEO_OFF_LD_SS1, 0, 
-			0x1000, "leo_ld_ss1", fb->iospace, 0);
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1,
+			     0x1000, "leold ss1");
 	fb->s.leo.lx_krn = (struct leo_lx_krn *)
-			sparc_alloc_io(phys + LEO_OFF_LX_KRN, 0, 
-			0x1000, "leo_lx_krn", fb->iospace, 0);
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN,
+			     0x1000, "leolx krn");
 	fb->s.leo.cursor = (struct leo_cursor *)
-			sparc_alloc_io(phys + LEO_OFF_LX_CURSOR, 0, 
-			sizeof(struct leo_cursor), "leo_lx_cursor", fb->iospace, 0);
+		sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR,
+			     sizeof(struct leo_cursor), "leolx cursor");
 	fb->dispsw = leo_dispsw;
 	
 	fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16);
@@ -601,22 +709,24 @@
 	wi.wi_values [0] = 0x30;
 	leo_wid_put (fb, &wl);
 
-	fb->s.leo.ld_ss1->ss1_misc |= LEO_SS1_MISC_ENABLE;
-
-	ss->wid = 0xffffffff;
-	ss->wmask = 0xffff;
-	ss->vclipmin = 0;
-	ss->vclipmax = fb->s.leo.extent;
-	ss->fg = 0;
-	ss->planemask = 0xff000000;
-	ss->rop = 0x310850;
-	ss->widclip = 0;
-	us->extent = (type->fb_width-1) | ((type->fb_height-1) << 11);
-	us->addrspace = 4;
-	us->fill = 0x80000000;
-	us->fontt = 0;
+	tmp = sbus_readl(&fb->s.leo.ld_ss1->ss1_misc);
+	tmp |= LEO_SS1_MISC_ENABLE;
+	sbus_writel(tmp, &fb->s.leo.ld_ss1->ss1_misc);
+
+	sbus_writel(0xffffffff, &ss->wid);
+	sbus_writel(0xffff, &ss->wmask);
+	sbus_writel(0, &ss->vclipmin);
+	sbus_writel(fb->s.leo.extent, &ss->vclipmax);
+	sbus_writel(0, &ss->fg);
+	sbus_writel(0xff000000, &ss->planemask);
+	sbus_writel(0x310850, &ss->rop);
+	sbus_writel(0, &ss->widclip);
+	sbus_writel((type->fb_width-1) | ((type->fb_height-1) << 11), &us->extent);
+	sbus_writel(4, &us->addrspace);
+	sbus_writel(0x80000000, &us->fill);
+	sbus_writel(0, &us->fontt);
 	do {
-		i = us->csr;
+		i = sbus_readl(&us->csr);
 	} while (i & 0x20000000);
 
 	fb->margins = leo_margins;
diff -u --recursive --new-file v2.3.34/linux/drivers/video/p9100.h linux/drivers/video/p9100.h
--- v2.3.34/linux/drivers/video/p9100.h	Tue Aug 31 17:29:14 1999
+++ linux/drivers/video/p9100.h	Mon Dec 20 22:06:42 1999
@@ -11,17 +11,17 @@
 #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
+#define P9100_SYSCTL_OFF	0x0UL
+#define P9100_VIDEOCTL_OFF	0x100UL
+#define P9100_VRAMCTL_OFF 	0x180UL
+#define P9100_RAMDAC_OFF 	0x200UL
+#define P9100_VIDEOCOPROC_OFF 	0x400UL
 
 /* P9100 command registers */
-#define P9100_CMD_OFF 0x0
+#define P9100_CMD_OFF 0x0UL
 
 /* P9100 framebuffer memory */
-#define P9100_FB_OFF 0x0
+#define P9100_FB_OFF 0x0UL
 
 
 /* 3 bits: 2=8bpp 3=16bpp 5=32bpp 7=24bpp */
diff -u --recursive --new-file v2.3.34/linux/drivers/video/p9100fb.c linux/drivers/video/p9100fb.c
--- v2.3.34/linux/drivers/video/p9100fb.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/video/p9100fb.c	Mon Dec 20 22:06:42 1999
@@ -42,7 +42,7 @@
 { \
   struct p9100_ctrl *actual; \
   actual = (struct p9100_ctrl *)fb->s.p9100.ctrl; \
-  out = actual-> ## member ; \
+  out = sbus_readl(&actual-> ## member ); \
 }
 
 #define READCTL(member, out) \
@@ -50,8 +50,8 @@
   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 ; \
+  out = sbus_readl(&enab-> ## member ); \
+  out = sbus_readl(&actual-> ## member ); \
 }
 
 #define WRITECTL(member, val) \
@@ -60,14 +60,17 @@
   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; \
+  __writetmp = sbus_readl(&enab-> ## member ); \
+  sbus_writel(val, &actual-> ## member ); \
 }
 
 static void p9100_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
 {
-	int i;
+	unsigned long flags;
 	u32 tmp;
+	int i;
+
+	spin_lock_irqsave(&fb->lock, flags);
 
 	_READCTL(pwrup_cfg, tmp);
 	WRITECTL(ramdac_cmap_wridx, (index << 16));
@@ -80,22 +83,32 @@
 		_READCTL(pwrup_cfg, tmp);
 		WRITECTL(ramdac_palette_data, (fb->color_map CM(i,2) << 16));
 	}
+
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 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);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	READCTL(vid_screenpaint_timectl1, val);
+	val &= ~ SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
+	WRITECTL(vid_screenpaint_timectl1, val);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 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);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	READCTL(vid_screenpaint_timectl1, val);
+	val |= SCREENPAINT_TIMECTL1_ENABLE_VIDEO;
+	WRITECTL(vid_screenpaint_timectl1, val);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void p9100_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
@@ -111,7 +124,8 @@
 	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;
+	struct sbus_dev *sdev = fb->sbdp;
+	unsigned long phys = sdev->reg_addrs[2].phys_addr;
 	int tmp;
 
 #ifndef FBCON_HAS_CFB8
@@ -124,9 +138,9 @@
          */
 
 	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);
+		fb->s.p9100.ctrl = (struct p9100_ctrl *)
+			sbus_ioremap(&sdev->resource[0], 0,
+				     sdev->reg_addrs[0].reg_size, "p9100 ctrl");
 	}
 
 	strcpy(fb->info.modename, "p9100");
@@ -136,10 +150,10 @@
 
 	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 = (char *)
+			sbus_ioremap(&sdev->resource[2], 0,
+				     type->fb_size, "p9100 ram");
+	fb->s.p9100.fbmem = (volatile u32 *)disp->screen_base;
 	disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
 
 	READCTL(sys_config, tmp);
@@ -171,7 +185,8 @@
 	fb->physbase = phys;
 	fb->mmap_map = p9100_mmap_map;
 	
-	sprintf(idstring, "%s at 0x%x", "p9100", disp->screen_base);
+	sprintf(idstring, "%s at 0x%x", "p9100", 
+		(unsigned int)disp->screen_base);
 
 	return idstring;
 }
diff -u --recursive --new-file v2.3.34/linux/drivers/video/pm2fb.c linux/drivers/video/pm2fb.c
--- v2.3.34/linux/drivers/video/pm2fb.c	Thu Aug 26 13:05:40 1999
+++ linux/drivers/video/pm2fb.c	Mon Dec 20 22:06:42 1999
@@ -1,6 +1,7 @@
 /*
  * Permedia2 framebuffer driver.
  * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ * Copyright (c) 1999 Jakub Jelinek (jakub@redhat.com)
  * Based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven.
  * --------------------------------------------------------------------------
  * $Id: pm2fb.c,v 1.163 1999/02/21 14:06:49 illo Exp $
@@ -38,17 +39,28 @@
 #include <video/fbcon-cfb32.h>
 #include "pm2fb.h"
 #include "cvisionppc.h"
+#ifdef __sparc__
+#include <asm/pbm.h>
+#include <asm/fbio.h>
+#endif
 
 #if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
 #error	"The endianness of the target host has not been defined."
 #endif
 
+#if defined(__BIG_ENDIAN) && !defined(__sparc__)
+#define PM2FB_BE_APERTURE
+#endif
+
+/* Need to debug this some more */
+#undef PM2FB_HW_CURSOR
+
 #if defined(CONFIG_FB_PM2_PCI) && !defined(CONFIG_PCI)
 #undef CONFIG_FB_PM2_PCI
 #warning "support for Permedia2 PCI boards with no generic PCI support!"
 #endif
 
-#define PM2FB_MASTER_DEBUG
+#undef PM2FB_MASTER_DEBUG
 #ifdef PM2FB_MASTER_DEBUG
 #define DPRINTK(a,b...)	printk(KERN_DEBUG "pm2fb: %s: " a, __FUNCTION__ , ## b)
 #else
@@ -102,12 +114,20 @@
 #define OPTF_OLD_MEM		(1L<<0)
 #define OPTF_YPAN		(1L<<1)
 #define OPTF_VIRTUAL		(1L<<2)
+#define OPTF_USER		(1L<<3)
 static struct {
 	char font[40];
 	u32 flags;
 	struct pm2fb_par user_mode;
 } pm2fb_options =
+#ifdef __sparc__
+	/* For some reason Raptor is not happy with the low-end mode */
+	{"\0", 0L, {31499,640,480,4,20,50,209,0,3,20,499,80,0,8,121}};
+#else
 	{"\0", 0L, {25174,640,480,4,28,40,199,9,11,45,524,80,0,8,121}};
+#endif
+
+static char curblink __initdata = 1;
 
 static const struct {
 	char name[16];
@@ -185,12 +205,30 @@
 };
 #endif
 
+#define DEFAULT_CURSOR_BLINK_RATE       (20)
+#define CURSOR_DRAW_DELAY               (2)
+
+struct pm2_cursor {
+    int	enable;
+    int on;
+    int vbl_cnt;
+    int blink_rate;
+    struct {
+        u16 x, y;
+    } pos, hot, size;
+    u8 color[6];
+    u8 bits[8][64];
+    u8 mask[8][64];
+    struct timer_list *timer;
+};
+
 static const char permedia2_name[16]="Permedia2";
 
 static struct pm2fb_info {
 	struct fb_info_gen gen;
 	int board;			/* Permedia2 board index (see
 					   board_table[] below) */
+	pm2type_t type;
 	struct {
 		unsigned long  fb_base;	/* physical framebuffer memory base */
 		u32 fb_size;		/* framebuffer memory size */
@@ -233,6 +271,7 @@
 		u32 cmap32[16];
 #endif
 	} cmap;
+	struct pm2_cursor *cursor;
 } fb_info;
 
 #ifdef CONFIG_FB_PM2_CVPPC
@@ -245,6 +284,18 @@
 static void pm2pci_init(struct pm2fb_info*);
 #endif
 
+#ifdef PM2FB_HW_CURSOR
+static void pm2fb_cursor(struct display *p, int mode, int x, int y);
+static int pm2fb_set_font(struct display *d, int width, int height);
+static struct pm2_cursor *pm2_init_cursor(struct pm2fb_info *fb);
+static void pm2v_set_cursor_color(struct pm2fb_info *fb, u8 *red, u8 *green, u8 *blue);
+static void pm2v_set_cursor_shape(struct pm2fb_info *fb);
+static u8 cursor_color_map[2] = { 0, 0xff };
+#else
+#define pm2fb_cursor NULL
+#define pm2fb_set_font NULL
+#endif
+
 /*
  * Table of the supported Permedia2 based boards.
  * Three hooks are defined for each board:
@@ -363,17 +414,50 @@
 
 inline static u32 pm2_RDAC_RD(struct pm2fb_info* p, s32 idx) {
 
-	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
+	int index = PM2R_RD_INDEXED_DATA;
+	switch (p->type) {
+	case PM2_TYPE_PERMEDIA2:
+		pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
+		break;
+	case PM2_TYPE_PERMEDIA2V:
+		pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
+		index = PM2VR_RD_INDEXED_DATA;
+		break;
+	}	
 	DEFRW();
-	return pm2_RD(p, PM2R_RD_INDEXED_DATA);
+	return pm2_RD(p, index);
 }
 
 inline static void pm2_RDAC_WR(struct pm2fb_info* p, s32 idx,
 						u32 v) {
 
-	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
-	DEFW();
-	pm2_WR(p, PM2R_RD_INDEXED_DATA, v);
+	int index = PM2R_RD_INDEXED_DATA;
+	switch (p->type) {
+	case PM2_TYPE_PERMEDIA2:
+		pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
+		break;
+	case PM2_TYPE_PERMEDIA2V:
+		pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
+		index = PM2VR_RD_INDEXED_DATA;
+		break;
+	}	
+	DEFRW();
+	pm2_WR(p, index, v);
+}
+
+inline static u32 pm2v_RDAC_RD(struct pm2fb_info* p, s32 idx) {
+
+	pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
+	DEFRW();
+	return pm2_RD(p, PM2VR_RD_INDEXED_DATA);
+}
+
+inline static void pm2v_RDAC_WR(struct pm2fb_info* p, s32 idx,
+						u32 v) {
+
+	pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);
+	DEFRW();
+	pm2_WR(p, PM2VR_RD_INDEXED_DATA, v);
 }
 
 #ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
@@ -435,8 +519,8 @@
 	return timing;
 }
 
-static void mnp(u32 clk, unsigned char* mm, unsigned char* nn,
-							unsigned char* pp) {
+static void pm2_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
+		unsigned char* pp) {
 	unsigned char m;
 	unsigned char n;
 	unsigned char p;
@@ -463,6 +547,30 @@
 	}
 }
 
+static void pm2v_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
+		unsigned char* pp) {
+	unsigned char m;
+	unsigned char n;
+	unsigned char p;
+	u32 f;
+	s32 delta=1000;
+
+	*mm=*nn=*pp=0;
+	for (n=1; n; n++) {
+		for (m=1; m; m++) {
+			for (p=0; p<2; p++) {
+				f=PM2_REFERENCE_CLOCK*n/(m * (1<<(p+1)));
+				if (clk>f-delta && clk<f+delta) {
+					delta=clk>f?clk-f:f-clk;
+					*mm=m;
+					*nn=n;
+					*pp=p;
+				}
+			}
+		}
+	}
+}
+
 static void wait_pm2(struct pm2fb_info* i) {
 
 	WAIT_FIFO(i, 1);
@@ -474,12 +582,12 @@
 	} while (pm2_RD(i, PM2R_OUT_FIFO)!=PM2TAG(PM2R_SYNC));
 }
 
-static void set_memclock(struct pm2fb_info* info, u32 clk) {
+static void pm2_set_memclock(struct pm2fb_info* info, u32 clk) {
 	int i;
 	unsigned char m, n, p;
 
-	mnp(clk, &m, &n, &p);
-	WAIT_FIFO(info, 5);
+	pm2_mnp(clk, &m, &n, &p);
+	WAIT_FIFO(info, 10);
 	pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 6);
 	DEFW();
 	pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_1, m);
@@ -493,23 +601,36 @@
 		!(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);
 }
 
-static void set_pixclock(struct pm2fb_info* info, u32 clk) {
+static void pm2_set_pixclock(struct pm2fb_info* info, u32 clk) {
 	int i;
 	unsigned char m, n, p;
 
-	mnp(clk, &m, &n, &p);
-	WAIT_FIFO(info, 5);
-	pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 0);
-	DEFW();
-	pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A1, m);
-	pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A2, n);
-	DEFW();
-	pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
-	DEFW();
-	pm2_RDAC_RD(info, PM2I_RD_PIXEL_CLOCK_STATUS);
-	DEFR();
-	for (i=256; i &&
-		!(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);
+	switch (info->type) {
+	case PM2_TYPE_PERMEDIA2:
+		pm2_mnp(clk, &m, &n, &p);
+		WAIT_FIFO(info, 10);
+		pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 0);
+		DEFW();
+		pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A1, m);
+		pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A2, n);
+		DEFW();
+		pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
+		DEFW();
+		pm2_RDAC_RD(info, PM2I_RD_PIXEL_CLOCK_STATUS);
+		DEFR();
+		for (i=256; i &&
+		     !(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);
+		break;
+	case PM2_TYPE_PERMEDIA2V:
+		pm2v_mnp(clk/2, &m, &n, &p);
+		WAIT_FIFO(info, 8);
+		pm2_WR(info, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CLK0_PRESCALE >> 8);
+		pm2v_RDAC_WR(info, PM2VI_RD_CLK0_PRESCALE, m);
+		pm2v_RDAC_WR(info, PM2VI_RD_CLK0_FEEDBACK, n);
+		pm2v_RDAC_WR(info, PM2VI_RD_CLK0_POSTSCALE, p);
+		pm2_WR(info, PM2VR_RD_INDEX_HIGH, 0);
+		break;
+	}
 }
 
 static void clear_palette(struct pm2fb_info* p) {
@@ -543,7 +664,7 @@
 
 	WAIT_FIFO(i, 2);
 #ifdef __LITTLE_ENDIAN
-	pm2_WR(i, PM2R_APERTURE_ONE, 0);	/* FIXME */
+	pm2_WR(i, PM2R_APERTURE_ONE, 0);
 	pm2_WR(i, PM2R_APERTURE_TWO, 0);
 #else
 	switch (p->depth) {
@@ -567,32 +688,46 @@
 static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
 	u32 clrmode=0;
 	u32 txtmap=0;
+	u32 pixsize=0;
+	u32 clrformat=0;
 	u32 xres;
+	u32 video, tmp;
 
+	if (i->type == PM2_TYPE_PERMEDIA2V) {
+		WAIT_FIFO(i, 1);
+		pm2_WR(i, PM2VR_RD_INDEX_HIGH, 0);
+	}
 	xres=(p->width+31)&~31;
 	set_aperture(i, p);
 	DEFRW();
-	WAIT_FIFO(i, 22);
+	WAIT_FIFO(i, 27);
 	pm2_RDAC_WR(i, PM2I_RD_COLOR_KEY_CONTROL, p->depth==8?0:
 						PM2F_COLOR_KEY_TEST_OFF);
 	switch (p->depth) {
 		case 8:
 			pm2_WR(i, PM2R_FB_READ_PIXEL, 0);
+			clrformat=0x0e;
 			break;
 		case 16:
 			pm2_WR(i, PM2R_FB_READ_PIXEL, 1);
 			clrmode=PM2F_RD_TRUECOLOR|0x06;
 			txtmap=PM2F_TEXTEL_SIZE_16;
+			pixsize=1;
+			clrformat=0x70;
 			break;
 		case 32:
 			pm2_WR(i, PM2R_FB_READ_PIXEL, 2);
 			clrmode=PM2F_RD_TRUECOLOR|0x08;
 			txtmap=PM2F_TEXTEL_SIZE_32;
+			pixsize=2;
+			clrformat=0x20;
 			break;
 		case 24:
 			pm2_WR(i, PM2R_FB_READ_PIXEL, 4);
 			clrmode=PM2F_RD_TRUECOLOR|0x09;
 			txtmap=PM2F_TEXTEL_SIZE_24;
+			pixsize=4;
+			clrformat=0x20;
 			break;
 	}
 	pm2_WR(i, PM2R_SCREEN_SIZE, (p->height<<16)|p->width);
@@ -613,10 +748,34 @@
 	pm2_WR(i, PM2R_SCREEN_STRIDE, p->stride);
 	DEFW();
 	pm2_WR(i, PM2R_SCREEN_BASE, p->base);
-	pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB|
-						PM2F_RD_GUI_ACTIVE|clrmode);
-	pm2_WR(i, PM2R_VIDEO_CONTROL, p->video);
-	set_pixclock(i, p->pixclock);
+	/* HW cursor needs /VSYNC for recognizing vert retrace */
+	video=p->video & ~(PM2F_HSYNC_ACT_LOW|PM2F_VSYNC_ACT_LOW);
+	video|=PM2F_HSYNC_ACT_HIGH|PM2F_VSYNC_ACT_HIGH;
+	switch (i->type) {
+	case PM2_TYPE_PERMEDIA2:
+		tmp = PM2F_RD_PALETTE_WIDTH_8;
+		pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB|
+						   PM2F_RD_GUI_ACTIVE|clrmode);
+		if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW)
+			tmp |= 4; /* invert hsync */
+		if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW)
+			tmp |= 8; /* invert vsync */
+		pm2_RDAC_WR(i, PM2I_RD_MISC_CONTROL, tmp);
+		break;
+	case PM2_TYPE_PERMEDIA2V:
+		tmp = 0;
+		pm2v_RDAC_WR(i, PM2VI_RD_PIXEL_SIZE, pixsize);
+		pm2v_RDAC_WR(i, PM2VI_RD_COLOR_FORMAT, clrformat);
+		if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW)
+			tmp |= 1; /* invert hsync */
+		if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW)
+			tmp |= 4; /* invert vsync */
+		pm2v_RDAC_WR(i, PM2VI_RD_SYNC_CONTROL, tmp);
+		pm2v_RDAC_WR(i, PM2VI_RD_MISC_CONTROL, 1);
+		break;
+	}
+	pm2_WR(i, PM2R_VIDEO_CONTROL, video);
+	pm2_set_pixclock(i, p->pixclock);
 };
 
 /*
@@ -682,6 +841,8 @@
 
 static void pm2fb_reset(struct pm2fb_info* p) {
 
+	if (p->type == PM2_TYPE_PERMEDIA2V)
+		pm2_WR(p, PM2VR_RD_INDEX_HIGH, 0);
 	pm2_WR(p, PM2R_RESET_STATUS, 0);
 	DEFRW();
 	while (pm2_RD(p, PM2R_RESET_STATUS)&PM2F_BEING_RESET);
@@ -729,8 +890,16 @@
 	pm2_WR(p, PM2R_LOGICAL_OP_MODE, 0);
 	pm2_WR(p, PM2R_STATISTICS_MODE, 0);
 	pm2_WR(p, PM2R_SCISSOR_MODE, 0);
-	pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0);
-	pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8);
+	switch (p->type) {
+	case PM2_TYPE_PERMEDIA2:
+		pm2_RDAC_WR(p, PM2I_RD_MODE_CONTROL, 0); /* no overlay */
+		pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0);
+		pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8);
+		break;
+	case PM2_TYPE_PERMEDIA2V:
+		pm2v_RDAC_WR(p, PM2VI_RD_MISC_CONTROL, 1); /* 8bit */
+		break;
+	}
 	pm2_RDAC_WR(p, PM2I_RD_COLOR_KEY_CONTROL, 0);
 	pm2_RDAC_WR(p, PM2I_RD_OVERLAY_KEY, 0);
 	pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
@@ -738,7 +907,7 @@
 	pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
 	clear_palette(p);
 	if (p->memclock)
-		set_memclock(p, p->memclock);
+		pm2_set_memclock(p, p->memclock);
 }
 
 static int __init pm2fb_conf(struct pm2fb_info* p){
@@ -759,7 +928,7 @@
 	}
 	p->regions.v_fb=MMAP(p->regions.p_fb, p->regions.fb_size);
 
-#ifdef __LITTLE_ENDIAN
+#ifndef PM2FB_BE_APERTURE
 	p->regions.p_regs=p->regions.rg_base;
 #else
 	p->regions.p_regs=p->regions.rg_base+PM2_REGS_SIZE;
@@ -771,6 +940,10 @@
 		return 0;
 	}
 	p->regions.v_regs=MMAP(p->regions.p_regs, PM2_REGS_SIZE);
+
+#ifdef PM2FB_HW_CURSOR
+	p->cursor = pm2_init_cursor(p);
+#endif
 	return 1;
 }
 
@@ -818,10 +991,11 @@
 	return 1;
 }
 
-static int cvppc_detect(struct pm2fb_info* p) {
+static int __init cvppc_detect(struct pm2fb_info* p) {
 
 	if (!cvppc_PCI_init(&p->board_par.cvppc))
 		return 0;
+	p->type = PM2_TYPE_PERMEDIA2;
 	p->regions.fb_base=CVPPC_FB_APERTURE_ONE;
 	p->regions.fb_size=CVPPC_FB_SIZE;
 	p->regions.rg_base=CVPPC_REGS_REGION;
@@ -846,9 +1020,25 @@
  * Generic PCI detection routines
  */
 #ifdef CONFIG_FB_PM2_PCI
-static int pm2pci_detect(struct pm2fb_info* p) {
+struct {
+	unsigned short vendor, device;
+	char *name;
+	pm2type_t type;
+} pm2pci_cards[] __initdata = {
+{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020, "Texas Instruments TVP4020", PM2_TYPE_PERMEDIA2 },
+{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2, "3dLabs Permedia 2", PM2_TYPE_PERMEDIA2 },
+{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V, "3dLabs Permedia 2v", PM2_TYPE_PERMEDIA2V },
+{ 0, 0 }
+};
+
+static int __init pm2pci_detect(struct pm2fb_info* p) {
 	struct pm2pci_par* pci=&p->board_par.pci;
+	struct pci_dev* dev;
+	int i;
 	unsigned char* m;
+#ifdef __sparc__
+	struct pcidev_cookie *pcp;
+#endif
 
 	memset(pci, 0, sizeof(struct pm2pci_par));
 	if (!pci_present()) {
@@ -856,9 +1046,16 @@
 		return 0;
 	}
 	DPRINTK("scanning PCI bus for known chipsets...\n");
-	if ((pci->dev=pci_find_device(PCI_VENDOR_ID_TI,
-					PCI_DEVICE_ID_TI_TVP4020, NULL))) {
-		DPRINTK("... found Texas Instruments TVP4020\n");
+
+	for (dev = pci_devices; !pci->dev && dev; dev = dev->next) {
+		for (i = 0; pm2pci_cards[i].vendor; i++)
+			if (pm2pci_cards[i].vendor == dev->vendor &&
+			    pm2pci_cards[i].device == dev->device) {
+				pci->dev = dev;
+				p->type = pm2pci_cards[i].type;
+				DPRINTK("... found %s\n", pm2pci_cards[i].name);
+				break;
+			}
 	}
 	if (!pci->dev) {
 		DPRINTK("no PCI board found.\n");
@@ -870,8 +1067,43 @@
 			pci->dev->resource[2].start,
 			pci->dev->resource[PCI_ROM_RESOURCE].start);
 #ifdef __sparc__
-	p->regions.rg_base= __pa(pci->dev->resource[0].start);
-	p->regions.fb_base= __pa(pci->dev->resource[1].start);
+	p->regions.rg_base= pci->dev->resource[0].start;
+	p->regions.fb_base= pci->dev->resource[1].start;
+	pcp = pci->dev->sysdata;
+	/* If the user has not asked for a particular mode, lets guess */
+	if (pcp->prom_node && !(pm2fb_options.flags & OPTF_USER)) {
+		char timing[256], *q, *r;
+		unsigned long w, h;
+		int i;
+		prom_getstring(pcp->prom_node, "timing-numbers", timing, 256);
+		/* FIXME: Find out what the actual pixclock is and other values as well */
+		if (timing[0]) {
+			w = simple_strtoul(timing, &q, 0);
+			h = 0;
+			if (q == timing) w = 0;
+			if (w) {
+				for (i = 0; i < 3; i++) {
+					for (r = q; *r && (*r < '0' || *r > '9'); r++);
+					simple_strtoul(r, &q, 0);
+					if (r == q) break;
+				}
+				if (i < 3) w = 0;
+			}
+			if (w) {
+				for (r = q; *r && (*r < '0' || *r > '9'); r++);
+				h = simple_strtoul(r, &q, 0);
+				if (r == q) w = 0;
+			}
+			if (w == 640 && h == 480) w = 0;
+			if (w) {
+				for (i=0; user_mode[i].name[0] &&
+					  (w != user_mode[i].par.width ||
+					   h != user_mode[i].par.height); i++);
+				if (user_mode[i].name[0])
+					memcpy(&p->current_par, &user_mode[i].par, sizeof(user_mode[i].par));
+			}
+		}
+	}
 #else
 	if (pm2fb_options.flags & OPTF_VIRTUAL) {
 		p->regions.rg_base= __pa(pci->dev->resource[0].start);
@@ -882,7 +1114,7 @@
 		p->regions.fb_base= (pci->dev->resource[0].start);
 	}
 #endif
-#ifdef __BIG_ENDIAN
+#ifdef PM2FB_BE_APERTURE
 	p->regions.rg_base += PM2_REGS_SIZE;
 #endif
 	if ((m=MMAP(p->regions.rg_base, PM2_REGS_SIZE))) {
@@ -1049,7 +1281,7 @@
 static struct display_switch pm2_cfb8 = {
 	fbcon_cfb8_setup, pm2fb_pp_bmove, pm2fb_clear8,
 	fbcon_cfb8_putc, fbcon_cfb8_putcs, fbcon_cfb8_revc,
-	NULL /* cursor() */, NULL /* set_font() */,
+	pm2fb_cursor, pm2fb_set_font,
 	pm2fb_clear_margins8,
 	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
 #endif /* FBCON_HAS_CFB8 */
@@ -1089,7 +1321,7 @@
 static struct display_switch pm2_cfb16 = {
 	fbcon_cfb16_setup, pm2fb_pp_bmove, pm2fb_clear16,
 	fbcon_cfb16_putc, fbcon_cfb16_putcs, fbcon_cfb16_revc,
-	NULL /* cursor() */, NULL /* set_font() */,
+	pm2fb_cursor, pm2fb_set_font,
 	pm2fb_clear_margins16,
 	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
 #endif /* FBCON_HAS_CFB16 */
@@ -1147,7 +1379,7 @@
 static struct display_switch pm2_cfb24 = {
 	fbcon_cfb24_setup, pm2fb_bmove, pm2fb_clear24,
 	fbcon_cfb24_putc, fbcon_cfb24_putcs, fbcon_cfb24_revc,
-	NULL /* cursor() */, NULL /* set_font() */,
+	pm2fb_cursor, pm2fb_set_font,
 	pm2fb_clear_margins24,
 	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
 #endif /* FBCON_HAS_CFB24 */
@@ -1185,7 +1417,7 @@
 static struct display_switch pm2_cfb32 = {
 	fbcon_cfb32_setup, pm2fb_bmove, pm2fb_clear32,
 	fbcon_cfb32_putc, fbcon_cfb32_putcs, fbcon_cfb32_revc,
-	NULL /* cursor() */, NULL /* set_font() */,
+	pm2fb_cursor, pm2fb_set_font,
 	pm2fb_clear_margins32,
 	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
 #endif /* FBCON_HAS_CFB32 */
@@ -1265,7 +1497,7 @@
 	p.height=var->yres_virtual;
 	p.depth=(var->bits_per_pixel+7)&~7;
 	p.depth=p.depth>32?32:p.depth;
-	data64=p.depth>8;
+	data64=p.depth>8 || i->type == PM2_TYPE_PERMEDIA2V;
 	xres=(var->xres+31)&~31;
 	if (p.width<xres+var->xoffset)
 		p.width=xres+var->xoffset;
@@ -1424,14 +1656,12 @@
 
 static void set_user_mode(struct pm2fb_info* i) {
 
-	memcpy(&i->current_par, &pm2fb_options.user_mode,
-						sizeof(i->current_par));
 	if (pm2fb_options.flags & OPTF_YPAN) {
+		int h = i->current_par.height;
 		i->current_par.height=i->regions.fb_size/
 			(i->current_par.width*i->current_par.depth/8);
 		i->current_par.height=MIN(i->current_par.height,2047);
-		i->current_par.height=MAX(i->current_par.height,
-						pm2fb_options.user_mode.height);
+		i->current_par.height=MAX(i->current_par.height,h);
 	}
 }
 
@@ -1463,6 +1693,12 @@
 	set_screen(i, p);
 	i->current_par=*p;
 	i->current_par_valid=1;
+#ifdef PM2FB_HW_CURSOR	
+	if (i->cursor) {
+		pm2v_set_cursor_color(i, cursor_color_map, cursor_color_map, cursor_color_map);
+		pm2v_set_cursor_shape(i);
+	}
+#endif
 }
 
 static int pm2fb_getcolreg(unsigned regno,
@@ -1584,6 +1820,210 @@
 	return 0;
 }
 
+#ifdef PM2FB_HW_CURSOR
+/***************************************************************************
+ * Hardware cursor support
+ ***************************************************************************/
+ 
+static u8 cursor_bits_lookup[16] = {
+	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
+	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
+};
+
+static u8 cursor_mask_lookup[16] = {
+	0x00, 0x80, 0x20, 0xa0, 0x08, 0x88, 0x28, 0xa8,
+	0x02, 0x82, 0x22, 0xa2, 0x0a, 0x8a, 0x2a, 0xaa
+};
+
+static void pm2v_set_cursor_color(struct pm2fb_info *fb, u8 *red, u8 *green, u8 *blue)
+{
+	struct pm2_cursor *c = fb->cursor;
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		c->color[3*i] = red[i];
+		c->color[3*i+1] = green[i];
+		c->color[3*i+2] = blue[i];
+	}
+
+	WAIT_FIFO(fb, 14);
+	pm2_WR(fb, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PALETTE >> 8);
+	for (i = 0; i < 6; i++)
+		pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PALETTE+i, c->color[i]);
+	pm2_WR(fb, PM2VR_RD_INDEX_HIGH, 0);
+}
+
+static void pm2v_set_cursor_shape(struct pm2fb_info *fb)
+{
+	struct pm2_cursor *c = fb->cursor;
+	u8 m, b;
+	int i, x, y;
+
+	WAIT_FIFO(fb, 1);
+	pm2_WR(fb, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PATTERN >> 8);
+	for (y = 0, i = 0; y < c->size.y; y++) {
+		WAIT_FIFO(fb, 32);
+		for (x = 0; x < c->size.x >> 3; x++) {
+			m = c->mask[x][y];
+			b = c->bits[x][y];
+			pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i,
+				     cursor_mask_lookup[m >> 4] |
+				     cursor_bits_lookup[(b & m) >> 4]);
+			pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i + 1,
+				     cursor_mask_lookup[m & 0x0f] |
+				     cursor_bits_lookup[(b & m) & 0x0f]);
+			i+=2;
+		}
+		for ( ; x < 8; x++) {
+			pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i, 0);
+			pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i + 1, 0);
+			i+=2;
+		}
+	}
+	for (; y < 64; y++) {
+		WAIT_FIFO(fb, 32);
+		for (x = 0; x < 8; x++) {
+			pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i, 0);
+			pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i + 1, 0);
+			i+=2;
+		}
+	}
+	WAIT_FIFO(fb, 1);
+	pm2_WR(fb, PM2VR_RD_INDEX_HIGH, 0);
+}
+
+static void pm2v_set_cursor(struct pm2fb_info *fb, int on)
+{
+	struct pm2_cursor *c = fb->cursor;
+	int x = c->pos.x;
+
+	if (!on) x = 4000;
+	WAIT_FIFO(fb, 14);
+	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_X_LOW, x & 0xff);
+	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_X_HIGH, (x >> 8) & 0x0f);
+	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_Y_LOW, c->pos.y & 0xff);
+	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_Y_HIGH, (c->pos.y >> 8) & 0x0f);
+	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_X_HOT, c->hot.x & 0x3f);
+	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_Y_HOT, c->hot.y & 0x3f);
+	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_MODE, 0x11);
+}
+
+static void pm2_cursor_timer_handler(unsigned long dev_addr)
+{
+	struct pm2fb_info *fb = (struct pm2fb_info *)dev_addr;
+
+	if (!fb->cursor->enable)
+		goto out;
+
+	if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) {
+		fb->cursor->on ^= 1;
+		pm2v_set_cursor(fb, fb->cursor->on);
+		fb->cursor->vbl_cnt = fb->cursor->blink_rate;
+	}
+
+out:
+	fb->cursor->timer->expires = jiffies + (HZ / 50);
+	add_timer(fb->cursor->timer);
+}
+
+static void pm2fb_cursor(struct display *p, int mode, int x, int y)
+{
+	struct pm2fb_info *fb = (struct pm2fb_info *)p->fb_info;
+	struct pm2_cursor *c = fb->cursor;
+
+	if (!c) return;
+
+	x *= fontwidth(p);
+	y *= fontheight(p);
+	if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable)
+		return;
+
+	c->enable = 0;
+	if (c->on)
+		pm2v_set_cursor(fb, 0);
+	c->pos.x = x;
+	c->pos.y = y;
+
+	switch (mode) {
+	case CM_ERASE:
+		c->on = 0;
+		break;
+
+	case CM_DRAW:
+	case CM_MOVE:
+		if (c->on)
+			pm2v_set_cursor(fb, 1);
+		else
+			c->vbl_cnt = CURSOR_DRAW_DELAY;
+		c->enable = 1;
+		break;
+	}
+}
+
+static struct pm2_cursor * __init pm2_init_cursor(struct pm2fb_info *fb)
+{
+	struct pm2_cursor *cursor;
+
+	if (fb->type != PM2_TYPE_PERMEDIA2V)
+		return 0; /* FIXME: Support hw cursor everywhere */
+
+	cursor = kmalloc(sizeof(struct pm2_cursor), GFP_ATOMIC);
+	if (!cursor)
+		return 0;
+	memset(cursor, 0, sizeof(*cursor));
+
+	cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
+	if (!cursor->timer) {
+		kfree(cursor);
+		return 0;
+	}
+	memset(cursor->timer, 0, sizeof(*cursor->timer));
+
+	cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
+
+	if (curblink) {
+		init_timer(cursor->timer);
+		cursor->timer->expires = jiffies + (HZ / 50);
+		cursor->timer->data = (unsigned long)fb;
+		cursor->timer->function = pm2_cursor_timer_handler;
+		add_timer(cursor->timer);
+	}
+
+	return cursor;
+}
+
+static int pm2fb_set_font(struct display *d, int width, int height)
+{
+	struct pm2fb_info *fb = (struct pm2fb_info *)d->fb_info;
+	struct pm2_cursor *c = fb->cursor;
+	int i, j;
+
+	if (c) {
+		if (!width || !height) {
+			width = 8;
+			height = 16;
+		}
+
+		c->hot.x = 0;
+		c->hot.y = 0;
+		c->size.x = width;
+		c->size.y = height;
+
+		memset(c->bits, 0xff, sizeof(c->bits));
+		memset(c->mask, 0, sizeof(c->mask));
+
+		for (i = 0, j = width; j >= 0; j -= 8, i++) {
+			c->mask[i][height-2] = (j >= 8) ? 0xff : (0xff << (8 - j));
+			c->mask[i][height-1] = (j >= 8) ? 0xff : (0xff << (8 - j));
+		}
+
+		pm2v_set_cursor_color(fb, cursor_color_map, cursor_color_map, cursor_color_map);
+		pm2v_set_cursor_shape(fb);
+	}
+	return 1;
+}
+#endif /* PM2FB_HW_CURSOR */
+
 /***************************************************************************
  * Begin of public functions
  ***************************************************************************/
@@ -1609,6 +2049,7 @@
 int __init pm2fb_init(void){
 
 	memset(&fb_info, 0, sizeof(fb_info));
+	memcpy(&fb_info.current_par, &pm2fb_options.user_mode, sizeof(fb_info.current_par));
 	if (!pm2fb_conf(&fb_info))
 		return -ENXIO;
 	pm2fb_reset(&fb_info);
@@ -1640,17 +2081,19 @@
 	return 0;
 }
 
-void __init pm2fb_mode_setup(char* options){
+static void __init pm2fb_mode_setup(char* options){
 	int i;
 
 	for (i=0; user_mode[i].name[0] &&
 		strcmp(options, user_mode[i].name); i++);
-	if (user_mode[i].name[0])
+	if (user_mode[i].name[0]) {
 		memcpy(&pm2fb_options.user_mode, &user_mode[i].par,
 					sizeof(pm2fb_options.user_mode));
+		pm2fb_options.flags |= OPTF_USER;
+	}
 }
 
-void __init pm2fb_font_setup(char* options){
+static void __init pm2fb_font_setup(char* options){
 
 	strncpy(pm2fb_options.font, options, sizeof(pm2fb_options.font));
 	pm2fb_options.font[sizeof(pm2fb_options.font)-1]='\0';
@@ -1672,6 +2115,8 @@
 			pm2fb_options.flags |= OPTF_OLD_MEM;
 		else if (!strcmp(options, "virtual"))
 			pm2fb_options.flags |= OPTF_VIRTUAL;
+		else if (!strcmp(options, "noblink"))
+			curblink = 0;
 		options=next;
 	}
 	return 0;
@@ -1682,8 +2127,14 @@
  ***************************************************************************/
 
 #ifdef MODULE
+
+static char *mode = NULL;
+
+MODULE_PARM(mode, "s");
+
 int __init init_module(void) {
 
+	if (mode) pm2fb_mode_setup(mode);
 	return pm2fb_init();
 }
 
diff -u --recursive --new-file v2.3.34/linux/drivers/video/pm2fb.h linux/drivers/video/pm2fb.h
--- v2.3.34/linux/drivers/video/pm2fb.h	Thu Feb 25 10:02:12 1999
+++ linux/drivers/video/pm2fb.h	Mon Dec 20 22:06:42 1999
@@ -108,6 +108,11 @@
 #define PM2R_FB_SOURCE_DELTA				0x8d88
 #define PM2R_CONFIG					0x8d90
 
+/* Permedia2v */
+#define PM2VR_RD_INDEX_LOW				0x4020
+#define PM2VR_RD_INDEX_HIGH				0x4028
+#define PM2VR_RD_INDEXED_DATA				0x4030
+
 /* Permedia2 RAMDAC indexed registers */
 #define PM2I_RD_CURSOR_CONTROL				0x06
 #define PM2I_RD_COLOR_MODE				0x18
@@ -127,6 +132,28 @@
 #define PM2I_RD_GREEN_KEY				0x43
 #define PM2I_RD_BLUE_KEY				0x44
 
+/* Permedia2v extensions */
+#define PM2VI_RD_MISC_CONTROL				0x000
+#define PM2VI_RD_SYNC_CONTROL				0x001
+#define PM2VI_RD_DAC_CONTROL				0x002
+#define PM2VI_RD_PIXEL_SIZE				0x003
+#define PM2VI_RD_COLOR_FORMAT				0x004
+#define PM2VI_RD_CURSOR_MODE				0x005
+#define PM2VI_RD_CURSOR_X_LOW				0x007
+#define PM2VI_RD_CURSOR_X_HIGH				0x008
+#define PM2VI_RD_CURSOR_Y_LOW				0x009
+#define PM2VI_RD_CURSOR_Y_HIGH				0x00A
+#define PM2VI_RD_CURSOR_X_HOT				0x00B
+#define PM2VI_RD_CURSOR_Y_HOT				0x00C
+#define PM2VI_RD_CLK0_PRESCALE				0x201
+#define PM2VI_RD_CLK0_FEEDBACK				0x202
+#define PM2VI_RD_CLK0_POSTSCALE				0x203
+#define PM2VI_RD_CLK1_PRESCALE				0x204
+#define PM2VI_RD_CLK1_FEEDBACK				0x205
+#define PM2VI_RD_CLK1_POSTSCALE				0x206
+#define PM2VI_RD_CURSOR_PALETTE				0x303
+#define PM2VI_RD_CURSOR_PATTERN				0x400
+
 /* Fields and flags */
 #define PM2F_RENDER_AREASTIPPLE				(1L<<0)
 #define PM2F_RENDER_FASTFILL				(1L<<3)
@@ -178,6 +205,11 @@
 #define PM2F_MEM_BANKS_2				(1L<<29)
 #define PM2F_MEM_BANKS_3				(2L<<29)
 #define PM2F_MEM_BANKS_4				(3L<<29)
+
+typedef enum {
+	PM2_TYPE_PERMEDIA2,
+	PM2_TYPE_PERMEDIA2V
+} pm2type_t;
 
 #endif /* PM2FB_H */
 
diff -u --recursive --new-file v2.3.34/linux/drivers/video/sbusfb.c linux/drivers/video/sbusfb.c
--- v2.3.34/linux/drivers/video/sbusfb.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/video/sbusfb.c	Mon Dec 20 22:06:42 1999
@@ -965,7 +965,7 @@
 extern void (*prom_palette)(int);
 
 static void __init sbusfb_init_fb(int node, int parent, int fbtype,
-				      struct linux_sbus_device *sbdp)
+				  struct sbus_dev *sbdp)
 {
 	struct fb_fix_screeninfo *fix;
 	struct fb_var_screeninfo *var;
@@ -991,6 +991,7 @@
 	disp = &fb->disp;
 	type = &fb->type;
 	
+	spin_lock_init(&fb->lock);
 	fb->prom_node = node;
 	fb->prom_parent = parent;
 	fb->sbdp = sbdp;
@@ -1165,8 +1166,8 @@
 int __init sbusfb_init(void)
 {
 	int type;
-	struct linux_sbus_device *sbdp;
-	struct linux_sbus *sbus;
+	struct sbus_dev *sbdp;
+	struct sbus_bus *sbus;
 	char prom_name[40];
 	extern int con_is_present(void);
 	
@@ -1198,17 +1199,19 @@
 		}
 	}
 #endif
-	if (!SBus_chain) return 0;
+	if (sbus_root == NULL)
+		return 0;
 	for_all_sbusdev(sbdp, sbus) {
 		type = known_card(sbdp->prom_name);
-		if (type == FBTYPE_NOTYPE) continue;
-		if (prom_getproperty(sbdp->prom_node, "emulation", prom_name, sizeof(prom_name)) > 0) {
+		if (type == FBTYPE_NOTYPE)
+			continue;
+		if (prom_getproperty(sbdp->prom_node, "emulation",
+				     prom_name, sizeof(prom_name)) > 0) {
 			type = known_card(prom_name);
-			if (type == FBTYPE_NOTYPE) type = known_card(sbdp->prom_name);
+			if (type == FBTYPE_NOTYPE)
+				type = known_card(sbdp->prom_name);
 		}
-		prom_apply_sbus_ranges(sbdp->my_bus, &sbdp->reg_addrs[0],
-				       sbdp->num_registers, sbdp);
-		sbusfb_init_fb(sbdp->prom_node, sbdp->my_bus->prom_node, type, sbdp);
+		sbusfb_init_fb(sbdp->prom_node, sbdp->bus->prom_node, type, sbdp);
 	}
 	return 0;
 }	
diff -u --recursive --new-file v2.3.34/linux/drivers/video/tcxfb.c linux/drivers/video/tcxfb.c
--- v2.3.34/linux/drivers/video/tcxfb.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/video/tcxfb.c	Mon Dec 20 22:06:42 1999
@@ -1,4 +1,4 @@
-/* $Id: tcxfb.c,v 1.8 1999/08/10 15:56:26 davem Exp $
+/* $Id: tcxfb.c,v 1.11 1999/11/19 09:57:21 davem Exp $
  * tcxfb.c: TCX 24/8bit frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -23,6 +23,7 @@
 
 #include <video/sbusfb.h>
 #include <asm/io.h>
+#include <asm/sbus.h>
 
 #include <video/fbcon-cfb8.h>
 
@@ -85,118 +86,167 @@
 	{ 0,			0,		0		    }
 };
 
-static void tcx_set_control_plane (struct fb_info_sbusfb *fb)
+static void __tcx_set_control_plane (struct fb_info_sbusfb *fb)
 {
 	u32 *p, *pend;
         
 	p = fb->s.tcx.cplane;
-	if (!p) return;
-	for (pend = p + fb->type.fb_size; p < pend; p++)
-		*p &= 0xffffff;
+	if (p == NULL)
+		return;
+	for (pend = p + fb->type.fb_size; p < pend; p++) {
+		u32 tmp = sbus_readl(p);
+
+		tmp &= 0xffffff;
+		sbus_writel(tmp, p);
+	}
 }
                                                 
 static void tcx_switch_from_graph (struct fb_info_sbusfb *fb)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&fb->lock, flags);
+
 	/* Reset control plane to 8bit mode if necessary */
 	if (fb->open && fb->mmaped)
-		tcx_set_control_plane (fb);
+		__tcx_set_control_plane (fb);
+
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void tcx_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
 {
 	struct bt_regs *bt = fb->s.tcx.bt;
+	unsigned long flags;
 	int i;
                 
-	bt->addr = index << 24;
+	spin_lock_irqsave(&fb->lock, flags);
+	sbus_writel(index << 24, &bt->addr);
 	for (i = index; count--; i++){
-		bt->color_map = fb->color_map CM(i,0) << 24;
-		bt->color_map = fb->color_map CM(i,1) << 24;
-		bt->color_map = fb->color_map CM(i,2) << 24;
+		sbus_writel(fb->color_map CM(i,0) << 24, &bt->color_map);
+		sbus_writel(fb->color_map CM(i,1) << 24, &bt->color_map);
+		sbus_writel(fb->color_map CM(i,2) << 24, &bt->color_map);
 	}
-	bt->addr = 0;
+	sbus_writel(0, &bt->addr);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void tcx_restore_palette (struct fb_info_sbusfb *fb)
 {
 	struct bt_regs *bt = fb->s.tcx.bt;
+	unsigned long flags;
                 
-	bt->addr = 0;
-	bt->color_map = 0xffffffff;
-	bt->color_map = 0xffffffff;
-	bt->color_map = 0xffffffff;
+	spin_lock_irqsave(&fb->lock, flags);
+	sbus_writel(0, &bt->addr);
+	sbus_writel(0xffffffff, &bt->color_map);
+	sbus_writel(0xffffffff, &bt->color_map);
+	sbus_writel(0xffffffff, &bt->color_map);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void tcx_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
 {
         struct bt_regs *bt = fb->s.tcx.bt;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fb->lock, flags);
 
 	/* Note the 2 << 24 is different from cg6's 1 << 24 */
-	bt->addr = 2 << 24;
-	bt->cursor = red[0] << 24;
-	bt->cursor = green[0] << 24;
-	bt->cursor = blue[0] << 24;
-	bt->addr = 3 << 24;
-	bt->cursor = red[1] << 24;
-	bt->cursor = green[1] << 24;
-	bt->cursor = blue[1] << 24;
-	bt->addr = 0;
+	sbus_writel(2 << 24, &bt->addr);
+	sbus_writel(red[0] << 24, &bt->cursor);
+	sbus_writel(green[0] << 24, &bt->cursor);
+	sbus_writel(blue[0] << 24, &bt->cursor);
+	sbus_writel(3 << 24, &bt->addr);
+	sbus_writel(red[1] << 24, &bt->cursor);
+	sbus_writel(green[1] << 24, &bt->cursor);
+	sbus_writel(blue[1] << 24, &bt->cursor);
+	sbus_writel(0, &bt->addr);
+
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 /* Set cursor shape */
 static void tcx_setcurshape (struct fb_info_sbusfb *fb)
 {
 	struct tcx_thc *thc = fb->s.tcx.thc;
+	unsigned long flags;
 	int i;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	for (i = 0; i < 32; i++){
-		thc->thc_cursmask [i] = fb->cursor.bits[0][i];
-		thc->thc_cursbits [i] = fb->cursor.bits[1][i];
+		sbus_writel(fb->cursor.bits[0][i], &thc->thc_cursmask[i]);
+		sbus_writel(fb->cursor.bits[1][i], &thc->thc_cursbits[i]);
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 /* Load cursor information */
 static void tcx_setcursor (struct fb_info_sbusfb *fb)
 {
-	unsigned int v;
 	struct cg_cursor *c = &fb->cursor;
+	unsigned long flags;
+	unsigned int v;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	if (c->enable)
 		v = ((c->cpos.fbx - c->chot.fbx) << 16)
 		    |((c->cpos.fby - c->chot.fby) & 0xffff);
 	else
 		/* Magic constant to turn off the cursor */
 		v = ((65536-32) << 16) | (65536-32);
-	fb->s.tcx.thc->thc_cursxy = v;
+	sbus_writel(v, &fb->s.tcx.thc->thc_cursxy);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void tcx_blank (struct fb_info_sbusfb *fb)
 {
-	fb->s.tcx.thc->thc_misc &= ~TCX_THC_MISC_VIDEO;
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	tmp = sbus_readl(&fb->s.tcx.thc->thc_misc);
+	tmp &= ~TCX_THC_MISC_VIDEO;
 	/* This should put us in power-save */
-	fb->s.tcx.thc->thc_misc |= TCX_THC_MISC_VSYNC_DIS;
-        fb->s.tcx.thc->thc_misc |= TCX_THC_MISC_HSYNC_DIS;
+	tmp |= TCX_THC_MISC_VSYNC_DIS;
+        tmp |= TCX_THC_MISC_HSYNC_DIS;
+	sbus_writel(tmp, &fb->s.tcx.thc->thc_misc);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void tcx_unblank (struct fb_info_sbusfb *fb)
 {
-	fb->s.tcx.thc->thc_misc &= ~TCX_THC_MISC_VSYNC_DIS;
-	fb->s.tcx.thc->thc_misc &= ~TCX_THC_MISC_HSYNC_DIS;
-	fb->s.tcx.thc->thc_misc |= TCX_THC_MISC_VIDEO;
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	tmp = sbus_readl(&fb->s.tcx.thc->thc_misc);
+	tmp &= ~TCX_THC_MISC_VSYNC_DIS;
+	tmp &= ~TCX_THC_MISC_HSYNC_DIS;
+	tmp |= TCX_THC_MISC_VIDEO;
+	sbus_writel(tmp, &fb->s.tcx.thc->thc_misc);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void tcx_reset (struct fb_info_sbusfb *fb)
 {
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
 	if (fb->open && fb->mmaped)
-		tcx_set_control_plane(fb);
+		__tcx_set_control_plane(fb);
 	
 	/* Turn off stuff in the Transform Engine. */
-	fb->s.tcx.tec->tec_matrix = 0;
-	fb->s.tcx.tec->tec_clip = 0;
-	fb->s.tcx.tec->tec_vdc = 0;
+	sbus_writel(0, &fb->s.tcx.tec->tec_matrix);
+	sbus_writel(0, &fb->s.tcx.tec->tec_clip);
+	sbus_writel(0, &fb->s.tcx.tec->tec_vdc);
 
 	/* Enable cursor in Brooktree DAC. */
-	fb->s.tcx.bt->addr = 0x06 << 24;
-	fb->s.tcx.bt->control |= 0x03 << 24;
+	sbus_writel(0x06 << 24, &fb->s.tcx.bt->addr);
+	tmp = sbus_readl(&fb->s.tcx.bt->control);
+	tmp |= 0x03 << 24;
+	sbus_writel(tmp, &fb->s.tcx.bt->control);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void tcx_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
@@ -211,7 +261,8 @@
 	struct fb_fix_screeninfo *fix = &fb->fix;
 	struct display *disp = &fb->disp;
 	struct fbtype *type = &fb->type;
-	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
+	struct sbus_dev *sdev = fb->sbdp;
+	unsigned long phys = sdev->reg_addrs[0].phys_addr;
 	int lowdepth, i, j;
 
 #ifndef FBCON_HAS_CFB8
@@ -219,7 +270,7 @@
 #endif
 
 	lowdepth = prom_getbool (fb->prom_node, "tcx-8-bit");
-	
+
 	if (lowdepth) {
 		strcpy(fb->info.modename, "TCX8");
 		strcpy(fix->id, "TCX8");
@@ -229,21 +280,27 @@
 	}
 	fix->line_length = fb->var.xres_virtual;
 	fix->accel = FB_ACCEL_SUN_TCX;
-	
+
 	disp->scrollmode = SCROLL_YREDRAW;
-	if (!disp->screen_base)
-		disp->screen_base = (char *)sparc_alloc_io(phys, 0, 
-			type->fb_size, "tcx_ram", fb->iospace, 0);
+	if (!disp->screen_base) {
+		disp->screen_base = (char *)
+			sbus_ioremap(&sdev->resource[0], 0,
+				     type->fb_size, "tcx ram");
+	}
 	disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
-	fb->s.tcx.tec = (struct tcx_tec *)sparc_alloc_io(fb->sbdp->reg_addrs[7].phys_addr, 0, 
-			sizeof(struct tcx_tec), "tcx_tec", fb->iospace, 0);
-	fb->s.tcx.thc = (struct tcx_thc *)sparc_alloc_io(fb->sbdp->reg_addrs[9].phys_addr, 0, 
-			sizeof(struct tcx_thc), "tcx_thc", fb->iospace, 0);
-	fb->s.tcx.bt = (struct bt_regs *)sparc_alloc_io(fb->sbdp->reg_addrs[8].phys_addr, 0, 
-			sizeof(struct bt_regs), "tcx_dac", fb->iospace, 0);
+	fb->s.tcx.tec = (struct tcx_tec *)
+		sbus_ioremap(&sdev->resource[7], 0,
+			     sizeof(struct tcx_tec), "tcx tec");
+	fb->s.tcx.thc = (struct tcx_thc *)
+		sbus_ioremap(&sdev->resource[9], 0,
+			     sizeof(struct tcx_thc), "tcx thc");
+	fb->s.tcx.bt = (struct bt_regs *)
+		sbus_ioremap(&sdev->resource[8], 0, 
+			     sizeof(struct bt_regs), "tcx dac");
 	if (!lowdepth) {
-		fb->s.tcx.cplane = (u32 *)sparc_alloc_io(fb->sbdp->reg_addrs[4].phys_addr, 0, 
-				type->fb_size*4, "tcx_cplane", fb->iospace, 0);
+		fb->s.tcx.cplane = (u32 *)
+			sbus_ioremap(&sdev->resource[4], 0, 
+				     type->fb_size * sizeof(u32), "tcx cplane");
 		type->fb_depth = 24;
 		fb->switch_from_graph = tcx_switch_from_graph;
 	} else {
@@ -284,19 +341,22 @@
 	fb->mmap_map = tcx_mmap_map;
 
 	/* Initialize Brooktree DAC */
-	fb->s.tcx.bt->addr = 0x04 << 24;         /* color planes */
-	fb->s.tcx.bt->control = 0xff << 24;
-	fb->s.tcx.bt->addr = 0x05 << 24;
-	fb->s.tcx.bt->control = 0x00 << 24;
-	fb->s.tcx.bt->addr = 0x06 << 24;         /* overlay plane */
-	fb->s.tcx.bt->control = 0x73 << 24;
-	fb->s.tcx.bt->addr = 0x07 << 24;
-	fb->s.tcx.bt->control = 0x00 << 24;
-
-	sprintf(idstring, "tcx at %x.%08lx Rev %d.%d %s", fb->iospace, phys,
-		    (fb->s.tcx.thc->thc_rev >> TCX_THC_REV_REV_SHIFT) & TCX_THC_REV_REV_MASK,
-                    (fb->s.tcx.thc->thc_rev >> TCX_THC_REV_MINREV_SHIFT) & TCX_THC_REV_MINREV_MASK,
-		    lowdepth ? "8-bit only" : "24-bit depth");
+	sbus_writel(0x04 << 24, &fb->s.tcx.bt->addr);         /* color planes */
+	sbus_writel(0xff << 24, &fb->s.tcx.bt->control);
+	sbus_writel(0x05 << 24, &fb->s.tcx.bt->addr);
+	sbus_writel(0x00 << 24, &fb->s.tcx.bt->control);
+	sbus_writel(0x06 << 24, &fb->s.tcx.bt->addr);         /* overlay plane */
+	sbus_writel(0x73 << 24, &fb->s.tcx.bt->control);
+	sbus_writel(0x07 << 24, &fb->s.tcx.bt->addr);
+	sbus_writel(0x00 << 24, &fb->s.tcx.bt->control);
+
+	sprintf(idstring, "tcx at %x.%08lx Rev %d.%d %s",
+		fb->iospace, phys,
+		((sbus_readl(&fb->s.tcx.thc->thc_rev) >> TCX_THC_REV_REV_SHIFT) &
+		 TCX_THC_REV_REV_MASK),
+		((sbus_readl(&fb->s.tcx.thc->thc_rev) >> TCX_THC_REV_MINREV_SHIFT) &
+		 TCX_THC_REV_MINREV_MASK),
+		lowdepth ? "8-bit only" : "24-bit depth");
 		    
 	tcx_reset(fb);
 
diff -u --recursive --new-file v2.3.34/linux/fs/Config.in linux/fs/Config.in
--- v2.3.34/linux/fs/Config.in	Tue Dec 14 01:27:24 1999
+++ linux/fs/Config.in	Mon Dec 27 13:10:56 1999
@@ -29,6 +29,7 @@
    tristate 'EFS filesystem support (read only) (EXPERIMENTAL)' CONFIG_EFS_FS
 fi
 
+tristate 'Compressed ROM filessytem support' CONFIG_CRAMFS
 tristate 'ISO 9660 CDROM filesystem support' CONFIG_ISO9660_FS
 if [ "$CONFIG_ISO9660_FS" != "n" ]; then
    bool '  Microsoft Joliet CDROM extensions' CONFIG_JOLIET
diff -u --recursive --new-file v2.3.34/linux/fs/Makefile linux/fs/Makefile
--- v2.3.34/linux/fs/Makefile	Tue Nov 23 22:42:21 1999
+++ linux/fs/Makefile	Mon Dec 27 17:30:02 1999
@@ -7,18 +7,18 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile.
 
-L_TARGET := filesystems.a
-L_OBJS    = $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
+FILESYSTEMS = $(join $(SUB_DIRS),$(SUB_DIRS:%=/%.o))
 O_TARGET := fs.o
 O_OBJS    = open.o read_write.o devices.o file_table.o buffer.o \
 		super.o  block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
 		ioctl.o readdir.o select.o fifo.o locks.o filesystems.o \
-		dcache.o inode.o attr.o bad_inode.o file.o iobuf.o $(BINFMTS) 
+		dcache.o inode.o attr.o bad_inode.o file.o iobuf.o \
+		$(BINFMTS) $(FILESYSTEMS)
 
 MOD_LIST_NAME := FS_MODULES
 ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
 		hpfs sysv smbfs ncpfs ufs efs affs romfs autofs hfs lockd \
-		nfsd nls devpts adfs partitions qnx4 udf bfs
+		nfsd nls devpts adfs partitions qnx4 udf bfs cramfs openpromfs
 
 SUB_DIRS := partitions
 
@@ -28,6 +28,22 @@
 O_OBJS += noquot.o
 endif
 
+ifeq ($(CONFIG_EXT2_FS),y)
+SUB_DIRS += ext2
+else
+  ifeq ($(CONFIG_EXT2_FS),m)
+  MOD_SUB_DIRS += ext2
+  endif
+endif
+
+ifeq ($(CONFIG_CRAMFS),y)
+SUB_DIRS += cramfs
+else
+  ifeq ($(CONFIG_CRAMFS),m)
+  MOD_SUB_DIRS += cramfs
+  endif
+endif
+
 ifeq ($(CONFIG_CODA_FS),y)
 SUB_DIRS += coda
 else
@@ -44,14 +60,6 @@
   endif
 endif
 
-ifeq ($(CONFIG_EXT2_FS),y)
-SUB_DIRS += ext2
-else
-  ifeq ($(CONFIG_EXT2_FS),m)
-  MOD_SUB_DIRS += ext2
-  endif
-endif
-
 ifeq ($(CONFIG_FAT_FS),y)
 SUB_DIRS += fat
 else
@@ -78,10 +86,6 @@
 
 ifdef CONFIG_PROC_FS
 SUB_DIRS += proc
-ifeq ($(CONFIG_SUN_OPENPROMFS),m)
-MOD_IN_SUB_DIRS += proc
-MOD_TO_LIST += openpromfs.o
-endif
 endif
 
 ifeq ($(CONFIG_BFS_FS),y)
@@ -262,6 +266,14 @@
 else
   ifeq ($(CONFIG_DEVPTS_FS),m)
   MOD_SUB_DIRS += devpts
+  endif
+endif
+
+ifeq ($(CONFIG_SUN_OPENPROMFS),y)
+SUB_DIRS += openpromfs
+else
+  ifeq ($(CONFIG_SUN_OPENPROMFS),m)
+  MOD_SUB_DIRS += openpromfs
   endif
 endif
 
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/Makefile linux/fs/cramfs/Makefile
--- v2.3.34/linux/fs/cramfs/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/Makefile	Mon Dec 27 15:57:32 1999
@@ -0,0 +1,12 @@
+#
+# Makefile for the linux cramfs routines.
+#
+
+O_TARGET := cramfs.o
+
+O_OBJS := inode.o uncompress.o inflate/zlib.o
+
+include $(TOPDIR)/Rules.make
+
+inflate/zlib.o:
+	make -C inflate
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/cramfs.h linux/fs/cramfs/cramfs.h
--- v2.3.34/linux/fs/cramfs/cramfs.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/cramfs.h	Tue Nov 23 16:18:54 1999
@@ -0,0 +1,41 @@
+#ifndef __CRAMFS_H
+#define __CRAMFS_H
+
+#define CRAMFS_MAGIC		0x28cd3d45	/* some random number */
+#define CRAMFS_SIGNATURE	"Compressed ROMFS"
+
+/*
+ * Reasonably terse representation of the inode
+ * data.. When the mode of the inode indicates
+ * a special device node, the "offset" bits will
+ * encode i_rdev. In other cases, "offset" points
+ * to the ROM image for the actual file data
+ * (whether that data be directory or compressed
+ * file data depends on the inode type again)
+ */
+struct cramfs_inode {
+	u32 mode:16, uid:16;
+	u32 size:24, gid:8;
+	u32 namelen:6, offset:26;
+};
+
+/*
+ * Superblock information at the beginning of the FS.
+ */
+struct cramfs_super {
+	u32 magic;		/* 0x28cd3d45 - random number */
+	u32 size;		/* > offset, < 2**26 */
+	u32 flags;		/* 0 */
+	u32 future;		/* 0 */
+	u8 signature[16];	/* "Compressed ROMFS" */
+	u8 fsid[16];		/* random number */
+	u8 name[16];		/* user-defined name */
+	struct cramfs_inode root;	/* Root inode data */
+};
+
+/* Uncompression interfaces to the underlying zlib */
+int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen);
+int cramfs_uncompress_init(void);
+int cramfs_uncompress_exit(void);
+
+#endif
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/Makefile linux/fs/cramfs/inflate/Makefile
--- v2.3.34/linux/fs/cramfs/inflate/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/Makefile	Mon Dec 27 13:22:13 1999
@@ -0,0 +1,34 @@
+#
+# inflate/Makefile
+#
+#
+# NOTE NOTE NOTE!
+#
+# This code is basically a bastardized version of the zlib
+# library uncompression. It avoids dynamic allocations at
+# all cost, and is cut down in other ways too, to make it
+# simpler and more specialized. If you want to get the real
+# thing, don't look here.
+#
+# The simplifications mean that this version of the library
+# (unlike the real lib) is completely single-threaded, and
+# you cannot do multiple uncompressions at a time. You can
+# ONLY use it to uncompress a single block, with both the
+# source and the destination completely in memory. In SMP
+# environments, the uncompression has to be protected by
+# some lock to guarantee single-threaded access to the static
+# data structures used for inflation.
+#
+# You have been warned.
+#
+# (The upsides of the simplification is that you can't get in
+# any nasty situations wrt memory management, and that the
+# uncompression can be done without blocking on allocation).
+#
+
+OBJECTFILES=adler32.o infblock.o infcodes.o inffast.o inflate.o inftrees.o infutil.o uncompr.o
+
+zlib.o: $(OBJECTFILES)
+	ld -r -o zlib.o $(OBJECTFILES)
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/adler32.c linux/fs/cramfs/inflate/adler32.c
--- v2.3.34/linux/fs/cramfs/inflate/adler32.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/adler32.c	Tue Nov  2 15:10:58 1999
@@ -0,0 +1,48 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+    uLong adler;
+    const Bytef *buf;
+    uInt len;
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == Z_NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+	    buf += 16;
+            k -= 16;
+        }
+        if (k != 0) do {
+            s1 += *buf++;
+	    s2 += s1;
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+    return (s2 << 16) | s1;
+}
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/infblock.c linux/fs/cramfs/inflate/infblock.c
--- v2.3.34/linux/fs/cramfs/inflate/infblock.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/infblock.c	Wed Nov  3 10:45:46 1999
@@ -0,0 +1,379 @@
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local const uInt 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};
+
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarily, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+
+void inflate_blocks_reset(s, z, c)
+inflate_blocks_statef *s;
+z_streamp z;
+uLongf *c;
+{
+  if (c != Z_NULL)
+    *c = s->check;
+  if (s->mode == CODES)
+    inflate_codes_free(s->sub.decode.codes, z);
+  s->mode = TYPE;
+  s->bitk = 0;
+  s->bitb = 0;
+  s->read = s->write = s->window;
+  if (s->checkfn != Z_NULL)
+    z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
+  Tracev((stderr, "inflate:   blocks reset\n"));
+}
+
+
+inflate_blocks_statef *inflate_blocks_new(z, c, w)
+z_streamp z;
+check_func c;
+uInt w;
+{
+  inflate_blocks_statef *s;
+  static struct inflate_blocks_state working_blocks_state;
+  static inflate_huft working_hufts[MANY];
+  static unsigned char working_window[1 << MAX_WBITS];
+
+  s = &working_blocks_state;
+  s->hufts = working_hufts;
+  s->window = working_window;
+  s->end = s->window + w;
+  s->checkfn = c;
+  s->mode = TYPE;
+  Tracev((stderr, "inflate:   blocks allocated\n"));
+  inflate_blocks_reset(s, z, Z_NULL);
+  return s;
+}
+
+
+int inflate_blocks(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+  uInt t;               /* temporary storage */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input based on current state */
+  while (1) switch (s->mode)
+  {
+    case TYPE:
+      NEEDBITS(3)
+      t = (uInt)b & 7;
+      s->last = t & 1;
+      switch (t >> 1)
+      {
+        case 0:                         /* stored */
+          Tracev((stderr, "inflate:     stored block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          t = k & 7;                    /* go to byte boundary */
+          DUMPBITS(t)
+          s->mode = LENS;               /* get length of stored block */
+          break;
+        case 1:                         /* fixed */
+          Tracev((stderr, "inflate:     fixed codes block%s\n",
+                 s->last ? " (last)" : ""));
+          {
+            uInt bl, bd;
+            inflate_huft *tl, *td;
+
+            inflate_trees_fixed(&bl, &bd, &tl, &td, z);
+            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+            if (s->sub.decode.codes == Z_NULL)
+            {
+              r = Z_MEM_ERROR;
+              LEAVE
+            }
+          }
+          DUMPBITS(3)
+          s->mode = CODES;
+          break;
+        case 2:                         /* dynamic */
+          Tracev((stderr, "inflate:     dynamic codes block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          s->mode = TABLE;
+          break;
+        case 3:                         /* illegal */
+          DUMPBITS(3)
+          s->mode = BAD;
+          z->msg = (char*)"invalid block type";
+          r = Z_DATA_ERROR;
+          LEAVE
+      }
+      break;
+    case LENS:
+      NEEDBITS(32)
+      if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+      {
+        s->mode = BAD;
+        z->msg = (char*)"invalid stored block lengths";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+      s->sub.left = (uInt)b & 0xffff;
+      b = k = 0;                      /* dump bits */
+      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
+      s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
+      break;
+    case STORED:
+      if (n == 0)
+        LEAVE
+      NEEDOUT
+      t = s->sub.left;
+      if (t > n) t = n;
+      if (t > m) t = m;
+      memcpy(q, p, t);
+      p += t;  n -= t;
+      q += t;  m -= t;
+      if ((s->sub.left -= t) != 0)
+        break;
+      Tracev((stderr, "inflate:       stored end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      s->mode = s->last ? DRY : TYPE;
+      break;
+    case TABLE:
+      NEEDBITS(14)
+      s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+      {
+        s->mode = BAD;
+        z->msg = (char*)"too many length or distance symbols";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+#endif
+      {
+      	static unsigned int working_blens [258 + 0x1f + 0x1f];
+      	s->sub.trees.blens = working_blens;
+      }
+      DUMPBITS(14)
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       table sizes ok\n"));
+      s->mode = BTREE;
+    case BTREE:
+      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+      {
+        NEEDBITS(3)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+        DUMPBITS(3)
+      }
+      while (s->sub.trees.index < 19)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+      s->sub.trees.bb = 7;
+      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+                             &s->sub.trees.tb, s->hufts, z);
+      if (t != Z_OK)
+      {
+        r = t;
+        if (r == Z_DATA_ERROR)
+          s->mode = BAD;
+        LEAVE
+      }
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       bits tree ok\n"));
+      s->mode = DTREE;
+    case DTREE:
+      while (t = s->sub.trees.table,
+             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+      {
+        inflate_huft *h;
+        uInt i, j, c;
+
+        t = s->sub.trees.bb;
+        NEEDBITS(t)
+        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+        t = h->bits;
+        c = h->base;
+        if (c < 16)
+        {
+          DUMPBITS(t)
+          s->sub.trees.blens[s->sub.trees.index++] = c;
+        }
+        else /* c == 16..18 */
+        {
+          i = c == 18 ? 7 : c - 14;
+          j = c == 18 ? 11 : 3;
+          NEEDBITS(t + i)
+          DUMPBITS(t)
+          j += (uInt)b & inflate_mask[i];
+          DUMPBITS(i)
+          i = s->sub.trees.index;
+          t = s->sub.trees.table;
+          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+              (c == 16 && i < 1))
+          {
+            s->mode = BAD;
+            z->msg = (char*)"invalid bit length repeat";
+            r = Z_DATA_ERROR;
+            LEAVE
+          }
+          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+          do {
+            s->sub.trees.blens[i++] = c;
+          } while (--j);
+          s->sub.trees.index = i;
+        }
+      }
+      s->sub.trees.tb = Z_NULL;
+      {
+        uInt bl, bd;
+        inflate_huft *tl, *td;
+        inflate_codes_statef *c;
+
+        bl = 9;         /* must be <= 9 for lookahead assumptions */
+        bd = 6;         /* must be <= 9 for lookahead assumptions */
+        t = s->sub.trees.table;
+        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+                                  s->sub.trees.blens, &bl, &bd, &tl, &td,
+                                  s->hufts, z);
+        if (t != Z_OK)
+        {
+          if (t == (uInt)Z_DATA_ERROR)
+            s->mode = BAD;
+          r = t;
+          LEAVE
+        }
+        Tracev((stderr, "inflate:       trees ok\n"));
+        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+        {
+          r = Z_MEM_ERROR;
+          LEAVE
+        }
+        s->sub.decode.codes = c;
+      }
+      s->mode = CODES;
+    case CODES:
+      UPDATE
+      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+        return inflate_flush(s, z, r);
+      r = Z_OK;
+      inflate_codes_free(s->sub.decode.codes, z);
+      LOAD
+      Tracev((stderr, "inflate:       codes end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      if (!s->last)
+      {
+        s->mode = TYPE;
+        break;
+      }
+      s->mode = DRY;
+    case DRY:
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      s->mode = DONE;
+    case DONE:
+      r = Z_STREAM_END;
+      LEAVE
+    case BAD:
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+}
+
+
+int inflate_blocks_free(s, z)
+inflate_blocks_statef *s;
+z_streamp z;
+{
+  inflate_blocks_reset(s, z, Z_NULL);
+  Tracev((stderr, "inflate:   blocks freed\n"));
+  return Z_OK;
+}
+
+
+void inflate_set_dictionary(s, d, n)
+inflate_blocks_statef *s;
+const Bytef *d;
+uInt  n;
+{
+  memcpy(s->window, d, n);
+  s->read = s->write = s->window + n;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
+ * IN assertion: s != Z_NULL
+ */
+int inflate_blocks_sync_point(s)
+inflate_blocks_statef *s;
+{
+  return s->mode == LENS;
+}
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/infblock.h linux/fs/cramfs/inflate/infblock.h
--- v2.3.34/linux/fs/cramfs/inflate/infblock.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/infblock.h	Tue Nov  2 11:29:32 1999
@@ -0,0 +1,39 @@
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+extern inflate_blocks_statef * inflate_blocks_new OF((
+    z_streamp z,
+    check_func c,               /* check function */
+    uInt w));                   /* window size */
+
+extern int inflate_blocks OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));                      /* initial return code */
+
+extern void inflate_blocks_reset OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    uLongf *));                  /* check value on output */
+
+extern int inflate_blocks_free OF((
+    inflate_blocks_statef *,
+    z_streamp));
+
+extern void inflate_set_dictionary OF((
+    inflate_blocks_statef *s,
+    const Bytef *d,  /* dictionary */
+    uInt  n));       /* dictionary length */
+
+extern int inflate_blocks_sync_point OF((
+    inflate_blocks_statef *s));
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/infcodes.c linux/fs/cramfs/inflate/infcodes.c
--- v2.3.34/linux/fs/cramfs/inflate/infcodes.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/infcodes.c	Wed Nov  3 10:28:13 1999
@@ -0,0 +1,256 @@
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+      START,    /* x: set up for LEN */
+      LEN,      /* i: get length/literal/eob next */
+      LENEXT,   /* i: getting length extra (have base) */
+      DIST,     /* i: get distance next */
+      DISTEXT,  /* i: getting distance extra */
+      COPY,     /* o: copying bytes in window, waiting for space */
+      LIT,      /* o: got literal, waiting for output space */
+      WASH,     /* o: got eob, possibly still output waiting */
+      END,      /* x: got eob and all data flushed */
+      BADCODE}  /* x: got error */
+inflate_codes_mode;
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+  /* mode */
+  inflate_codes_mode mode;      /* current inflate_codes mode */
+
+  /* mode dependent information */
+  uInt len;
+  union {
+    struct {
+      inflate_huft *tree;       /* pointer into tree */
+      uInt need;                /* bits needed */
+    } code;             /* if LEN or DIST, where in tree */
+    uInt lit;           /* if LIT, literal */
+    struct {
+      uInt get;                 /* bits to get for extra */
+      uInt dist;                /* distance back to copy from */
+    } copy;             /* if EXT or COPY, where and how much */
+  } sub;                /* submode */
+
+  /* mode independent information */
+  Byte lbits;           /* ltree bits decoded per branch */
+  Byte dbits;           /* dtree bits decoder per branch */
+  inflate_huft *ltree;          /* literal/length/eob tree */
+  inflate_huft *dtree;          /* distance tree */
+
+};
+
+
+inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+z_streamp z;
+{
+  inflate_codes_statef *c;
+  static inflate_codes_statef memory_allocation;
+
+  c = &memory_allocation;
+  {
+    c->mode = START;
+    c->lbits = (Byte)bl;
+    c->dbits = (Byte)bd;
+    c->ltree = tl;
+    c->dtree = td;
+    Tracev((stderr, "inflate:       codes new\n"));
+  }
+  return c;
+}
+
+
+int inflate_codes(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+  uInt j;               /* temporary storage */
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  Bytef *f;             /* pointer to copy strings from */
+  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input and output based on current state */
+  while (1) switch (c->mode)
+  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+    case START:         /* x: set up for LEN */
+#ifndef SLOW
+      if (m >= 258 && n >= 10)
+      {
+        UPDATE
+        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+        LOAD
+        if (r != Z_OK)
+        {
+          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+          break;
+        }
+      }
+#endif /* !SLOW */
+      c->sub.code.need = c->lbits;
+      c->sub.code.tree = c->ltree;
+      c->mode = LEN;
+    case LEN:           /* i: get length/literal/eob next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e == 0)               /* literal */
+      {
+        c->sub.lit = t->base;
+        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                 "inflate:         literal '%c'\n" :
+                 "inflate:         literal 0x%02x\n", t->base));
+        c->mode = LIT;
+        break;
+      }
+      if (e & 16)               /* length */
+      {
+        c->sub.copy.get = e & 15;
+        c->len = t->base;
+        c->mode = LENEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t + t->base;
+        break;
+      }
+      if (e & 32)               /* end of block */
+      {
+        Tracevv((stderr, "inflate:         end of block\n"));
+        c->mode = WASH;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = (char*)"invalid literal/length code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case LENEXT:        /* i: getting length extra (have base) */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->len += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      c->sub.code.need = c->dbits;
+      c->sub.code.tree = c->dtree;
+      Tracevv((stderr, "inflate:         length %u\n", c->len));
+      c->mode = DIST;
+    case DIST:          /* i: get distance next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e & 16)               /* distance */
+      {
+        c->sub.copy.get = e & 15;
+        c->sub.copy.dist = t->base;
+        c->mode = DISTEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t + t->base;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = (char*)"invalid distance code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case DISTEXT:       /* i: getting distance extra */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->sub.copy.dist += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
+      c->mode = COPY;
+    case COPY:          /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+      f = (uInt)(q - s->window) < c->sub.copy.dist ?
+          s->end - (c->sub.copy.dist - (q - s->window)) :
+          q - c->sub.copy.dist;
+#else
+      f = q - c->sub.copy.dist;
+      if ((uInt)(q - s->window) < c->sub.copy.dist)
+        f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
+#endif
+      while (c->len)
+      {
+        NEEDOUT
+        OUTBYTE(*f++)
+        if (f == s->end)
+          f = s->window;
+        c->len--;
+      }
+      c->mode = START;
+      break;
+    case LIT:           /* o: got literal, waiting for output space */
+      NEEDOUT
+      OUTBYTE(c->sub.lit)
+      c->mode = START;
+      break;
+    case WASH:          /* o: got eob, possibly more output */
+      if (k > 7)        /* return unused byte, if any */
+      {
+        Assert(k < 16, "inflate_codes grabbed too many bytes")
+        k -= 8;
+        n++;
+        p--;            /* can always return one */
+      }
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      c->mode = END;
+    case END:
+      r = Z_STREAM_END;
+      LEAVE
+    case BADCODE:       /* x: got error */
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+#ifdef NEED_DUMMY_RETURN
+  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
+#endif
+}
+
+
+void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_streamp z;
+{
+  Tracev((stderr, "inflate:       codes free\n"));
+}
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/infcodes.h linux/fs/cramfs/inflate/infcodes.h
--- v2.3.34/linux/fs/cramfs/inflate/infcodes.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/infcodes.h	Tue Nov  2 11:29:32 1999
@@ -0,0 +1,27 @@
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+extern inflate_codes_statef *inflate_codes_new OF((
+    uInt, uInt,
+    inflate_huft *, inflate_huft *,
+    z_streamp ));
+
+extern int inflate_codes OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));
+
+extern void inflate_codes_free OF((
+    inflate_codes_statef *,
+    z_streamp ));
+
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/inffast.c linux/fs/cramfs/inflate/inffast.c
--- v2.3.34/linux/fs/cramfs/inflate/inffast.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/inffast.c	Tue Nov  2 11:29:32 1999
@@ -0,0 +1,170 @@
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "infblock.h"
+#include "infcodes.h"
+#include "infutil.h"
+#include "inffast.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
+
+/* Called with number of bytes left to write in window at least 258
+   (the maximum string length) and number of input bytes available
+   at least ten.  The ten bytes are six bytes for the longest length/
+   distance pair plus four bytes for overloading the bit buffer. */
+
+int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+inflate_blocks_statef *s;
+z_streamp z;
+{
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  uInt ml;              /* mask for literal/length tree */
+  uInt md;              /* mask for distance tree */
+  uInt c;               /* bytes to copy */
+  uInt d;               /* distance back to copy from */
+  Bytef *r;             /* copy source pointer */
+
+  /* load input, output, bit values */
+  LOAD
+
+  /* initialize masks */
+  ml = inflate_mask[bl];
+  md = inflate_mask[bd];
+
+  /* do until not enough input or output space for fast loop */
+  do {                          /* assume called with m >= 258 && n >= 10 */
+    /* get literal/length code */
+    GRABBITS(20)                /* max bits for literal/length code */
+    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+    {
+      DUMPBITS(t->bits)
+      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                "inflate:         * literal '%c'\n" :
+                "inflate:         * literal 0x%02x\n", t->base));
+      *q++ = (Byte)t->base;
+      m--;
+      continue;
+    }
+    do {
+      DUMPBITS(t->bits)
+      if (e & 16)
+      {
+        /* get extra bits for length */
+        e &= 15;
+        c = t->base + ((uInt)b & inflate_mask[e]);
+        DUMPBITS(e)
+        Tracevv((stderr, "inflate:         * length %u\n", c));
+
+        /* decode distance base of block to copy */
+        GRABBITS(15);           /* max bits for distance code */
+        e = (t = td + ((uInt)b & md))->exop;
+        do {
+          DUMPBITS(t->bits)
+          if (e & 16)
+          {
+            /* get extra bits to add to distance base */
+            e &= 15;
+            GRABBITS(e)         /* get extra bits (up to 13) */
+            d = t->base + ((uInt)b & inflate_mask[e]);
+            DUMPBITS(e)
+            Tracevv((stderr, "inflate:         * distance %u\n", d));
+
+            /* do the copy */
+            m -= c;
+            if ((uInt)(q - s->window) >= d)     /* offset before dest */
+            {                                   /*  just copy */
+              r = q - d;
+              *q++ = *r++;  c--;        /* minimum count is three, */
+              *q++ = *r++;  c--;        /*  so unroll loop a little */
+            }
+            else                        /* else offset after destination */
+            {
+              e = d - (uInt)(q - s->window); /* bytes from offset to end */
+              r = s->end - e;           /* pointer to offset */
+              if (c > e)                /* if source crosses, */
+              {
+                c -= e;                 /* copy to end of window */
+                do {
+                  *q++ = *r++;
+                } while (--e);
+                r = s->window;          /* copy rest from start of window */
+              }
+            }
+            do {                        /* copy all or what's left */
+              *q++ = *r++;
+            } while (--c);
+            break;
+          }
+          else if ((e & 64) == 0)
+          {
+            t += t->base;
+            e = (t += ((uInt)b & inflate_mask[e]))->exop;
+          }
+          else
+          {
+            z->msg = (char*)"invalid distance code";
+            UNGRAB
+            UPDATE
+            return Z_DATA_ERROR;
+          }
+        } while (1);
+        break;
+      }
+      if ((e & 64) == 0)
+      {
+        t += t->base;
+        if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
+        {
+          DUMPBITS(t->bits)
+          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                    "inflate:         * literal '%c'\n" :
+                    "inflate:         * literal 0x%02x\n", t->base));
+          *q++ = (Byte)t->base;
+          m--;
+          break;
+        }
+      }
+      else if (e & 32)
+      {
+        Tracevv((stderr, "inflate:         * end of block\n"));
+        UNGRAB
+        UPDATE
+        return Z_STREAM_END;
+      }
+      else
+      {
+        z->msg = (char*)"invalid literal/length code";
+        UNGRAB
+        UPDATE
+        return Z_DATA_ERROR;
+      }
+    } while (1);
+  } while (m >= 258 && n >= 10);
+
+  /* not enough input or output--restore pointers and return */
+  UNGRAB
+  UPDATE
+  return Z_OK;
+}
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/inffast.h linux/fs/cramfs/inflate/inffast.h
--- v2.3.34/linux/fs/cramfs/inflate/inffast.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/inffast.h	Tue Nov  2 11:29:32 1999
@@ -0,0 +1,17 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+extern int inflate_fast OF((
+    uInt,
+    uInt,
+    inflate_huft *,
+    inflate_huft *,
+    inflate_blocks_statef *,
+    z_streamp ));
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/inffixed.h linux/fs/cramfs/inflate/inffixed.h
--- v2.3.34/linux/fs/cramfs/inflate/inffixed.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/inffixed.h	Tue Nov  2 11:29:32 1999
@@ -0,0 +1,151 @@
+/* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by the maketree.c program
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+local uInt fixed_bl = 9;
+local uInt fixed_bd = 5;
+local inflate_huft fixed_tl[] = {
+    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
+    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
+    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
+    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
+    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
+    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
+    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
+    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
+    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
+    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
+    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
+    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
+    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
+    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
+    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
+    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
+    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
+    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
+    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
+    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
+    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
+    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
+    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
+    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
+    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
+    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
+    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
+    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
+    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
+    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
+    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
+    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
+    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
+    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
+    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
+    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
+    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
+    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
+    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
+    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
+    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
+    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
+    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
+    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
+    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
+    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
+    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
+    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
+    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
+    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
+    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
+    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
+    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
+    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
+    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
+    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
+    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
+    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
+    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
+    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
+    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
+    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
+    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
+    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
+    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
+    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
+    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
+    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
+    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
+    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
+    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
+    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
+    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
+    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
+    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
+    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
+    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
+    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
+    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
+    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
+    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
+    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
+    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
+    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
+    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
+    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
+    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
+    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
+    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
+    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
+    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
+    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
+    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
+    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
+    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
+    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
+    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
+    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
+    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
+    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
+    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
+    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
+    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
+    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
+    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
+    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
+    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
+    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
+    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
+    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
+    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
+    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
+  };
+local inflate_huft fixed_td[] = {
+    {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
+    {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
+    {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
+    {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
+    {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
+    {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
+    {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
+    {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
+  };
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/inflate.c linux/fs/cramfs/inflate/inflate.c
--- v2.3.34/linux/fs/cramfs/inflate/inflate.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/inflate.c	Wed Nov  3 10:32:21 1999
@@ -0,0 +1,335 @@
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+
+struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
+
+typedef enum {
+      METHOD,   /* waiting for method byte */
+      FLAG,     /* waiting for flag byte */
+      DICT4,    /* four dictionary check bytes to go */
+      DICT3,    /* three dictionary check bytes to go */
+      DICT2,    /* two dictionary check bytes to go */
+      DICT1,    /* one dictionary check byte to go */
+      DICT0,    /* waiting for inflateSetDictionary */
+      BLOCKS,   /* decompressing blocks */
+      CHECK4,   /* four check bytes to go */
+      CHECK3,   /* three check bytes to go */
+      CHECK2,   /* two check bytes to go */
+      CHECK1,   /* one check byte to go */
+      DONE,     /* finished check, done */
+      BAD}      /* got an error--stay here */
+inflate_mode;
+
+/* inflate private state */
+struct internal_state {
+
+  /* mode */
+  inflate_mode  mode;   /* current inflate mode */
+
+  /* mode dependent information */
+  union {
+    uInt method;        /* if FLAGS, method byte */
+    struct {
+      uLong was;                /* computed check value */
+      uLong need;               /* stream check value */
+    } check;            /* if CHECK, check values to compare */
+    uInt marker;        /* if BAD, inflateSync's marker bytes count */
+  } sub;        /* submode */
+
+  /* mode independent information */
+  int  nowrap;          /* flag for no wrapper */
+  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
+  inflate_blocks_statef 
+    *blocks;            /* current inflate_blocks state */
+
+};
+
+
+int ZEXPORT inflateReset(z)
+z_streamp z;
+{
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->total_in = z->total_out = 0;
+  z->msg = Z_NULL;
+  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+  inflate_blocks_reset(z->state->blocks, z, Z_NULL);
+  Tracev((stderr, "inflate: reset\n"));
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateEnd(z)
+z_streamp z;
+{
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->blocks != Z_NULL)
+    inflate_blocks_free(z->state->blocks, z);
+  z->state = Z_NULL;
+  Tracev((stderr, "inflate: end\n"));
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateInit2_(z, w, version, stream_size)
+z_streamp z;
+int w;
+const char *version;
+int stream_size;
+{
+  static struct internal_state internal_state;
+
+  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+      stream_size != sizeof(z_stream))
+      return Z_VERSION_ERROR;
+
+  /* initialize state */
+  if (z == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->msg = Z_NULL;
+  z->state = &internal_state;
+  z->state->blocks = Z_NULL;
+
+  /* handle undocumented nowrap option (no zlib header or check) */
+  z->state->nowrap = 0;
+  if (w < 0)
+  {
+    w = - w;
+    z->state->nowrap = 1;
+  }
+
+  /* set window size */
+  if (w < 8 || w > 15)
+  {
+    inflateEnd(z);
+    return Z_STREAM_ERROR;
+  }
+  z->state->wbits = (uInt)w;
+
+  /* create inflate_blocks state */
+  if ((z->state->blocks =
+      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+      == Z_NULL)
+  {
+    inflateEnd(z);
+    return Z_MEM_ERROR;
+  }
+  Tracev((stderr, "inflate: allocated\n"));
+
+  /* reset state */
+  inflateReset(z);
+  return Z_OK;
+}
+
+
+int ZEXPORT inflateInit_(z, version, stream_size)
+z_streamp z;
+const char *version;
+int stream_size;
+{
+  return inflateInit2_(z, DEF_WBITS, version, stream_size);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int ZEXPORT inflate(z, f)
+z_streamp z;
+int f;
+{
+  int r;
+  uInt b;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
+    return Z_STREAM_ERROR;
+  f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
+  r = Z_BUF_ERROR;
+  while (1) switch (z->state->mode)
+  {
+    case METHOD:
+      NEEDBYTE
+      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"unknown compression method";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"invalid window size";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      z->state->mode = FLAG;
+    case FLAG:
+      NEEDBYTE
+      b = NEXTBYTE;
+      if (((z->state->sub.method << 8) + b) % 31)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"incorrect header check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Tracev((stderr, "inflate: zlib header ok\n"));
+      if (!(b & PRESET_DICT))
+      {
+        z->state->mode = BLOCKS;
+        break;
+      }
+      z->state->mode = DICT4;
+    case DICT4:
+      NEEDBYTE
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = DICT3;
+    case DICT3:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = DICT2;
+    case DICT2:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = DICT1;
+    case DICT1:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+      z->adler = z->state->sub.check.need;
+      z->state->mode = DICT0;
+      return Z_NEED_DICT;
+    case DICT0:
+      z->state->mode = BAD;
+      z->msg = (char*)"need dictionary";
+      z->state->sub.marker = 0;       /* can try inflateSync */
+      return Z_STREAM_ERROR;
+    case BLOCKS:
+      r = inflate_blocks(z->state->blocks, z, r);
+      if (r == Z_DATA_ERROR)
+      {
+        z->state->mode = BAD;
+        z->state->sub.marker = 0;       /* can try inflateSync */
+        break;
+      }
+      if (r == Z_OK)
+        r = f;
+      if (r != Z_STREAM_END)
+        return r;
+      r = f;
+      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+      if (z->state->nowrap)
+      {
+        z->state->mode = DONE;
+        break;
+      }
+      z->state->mode = CHECK4;
+    case CHECK4:
+      NEEDBYTE
+      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+      z->state->mode = CHECK3;
+    case CHECK3:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+      z->state->mode = CHECK2;
+    case CHECK2:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+      z->state->mode = CHECK1;
+    case CHECK1:
+      NEEDBYTE
+      z->state->sub.check.need += (uLong)NEXTBYTE;
+
+      if (z->state->sub.check.was != z->state->sub.check.need)
+      {
+        z->state->mode = BAD;
+        z->msg = (char*)"incorrect data check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Tracev((stderr, "inflate: zlib check ok\n"));
+      z->state->mode = DONE;
+    case DONE:
+      return Z_STREAM_END;
+    case BAD:
+      return Z_DATA_ERROR;
+    default:
+      return Z_STREAM_ERROR;
+  }
+#ifdef NEED_DUMMY_RETURN
+  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
+#endif
+}
+
+
+int ZEXPORT inflateSync(z)
+z_streamp z;
+{
+  uInt n;       /* number of bytes to look at */
+  Bytef *p;     /* pointer to bytes */
+  uInt m;       /* number of marker bytes found in a row */
+  uLong r, w;   /* temporaries to save total_in and total_out */
+
+  /* set up */
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->mode != BAD)
+  {
+    z->state->mode = BAD;
+    z->state->sub.marker = 0;
+  }
+  if ((n = z->avail_in) == 0)
+    return Z_BUF_ERROR;
+  p = z->next_in;
+  m = z->state->sub.marker;
+
+  /* search */
+  while (n && m < 4)
+  {
+    static const Byte mark[4] = {0, 0, 0xff, 0xff};
+    if (*p == mark[m])
+      m++;
+    else if (*p)
+      m = 0;
+    else
+      m = 4 - m;
+    p++, n--;
+  }
+
+  /* restore */
+  z->total_in += p - z->next_in;
+  z->next_in = p;
+  z->avail_in = n;
+  z->state->sub.marker = m;
+
+  /* return no joy or set up to restart on a new block */
+  if (m != 4)
+    return Z_DATA_ERROR;
+  r = z->total_in;  w = z->total_out;
+  inflateReset(z);
+  z->total_in = r;  z->total_out = w;
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
+ * but removes the length bytes of the resulting empty stored block. When
+ * decompressing, PPP checks that at the end of input packet, inflate is
+ * waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(z)
+z_streamp z;
+{
+  if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
+    return Z_STREAM_ERROR;
+  return inflate_blocks_sync_point(z->state->blocks);
+}
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/inftrees.c linux/fs/cramfs/inflate/inftrees.c
--- v2.3.34/linux/fs/cramfs/inflate/inftrees.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/inftrees.c	Wed Nov  3 10:30:07 1999
@@ -0,0 +1,392 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+const char inflate_copyright[] =
+   " inflate 1.1.3 Copyright 1995-1998 Mark Adler ";
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+struct internal_state  {int dummy;}; /* for buggy compilers */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+    uIntf *,            /* code lengths in bits */
+    uInt,               /* number of codes */
+    uInt,               /* number of "simple" codes */
+    const uIntf *,      /* list of base values for non-simple codes */
+    const uIntf *,      /* list of extra bits for non-simple codes */
+    inflate_huft * FAR*,/* result: starting table */
+    uIntf *,            /* maximum lookup bits (returns actual) */
+    inflate_huft *,     /* space for trees */
+    uInt *,             /* hufts used in space */
+    uIntf * ));         /* space for values */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local const uInt cplens[31] = { /* 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};
+        /* see note #13 above about 258 */
+local const uInt cplext[31] = { /* 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, 112, 112}; /* 112==invalid */
+local const uInt cpdist[30] = { /* 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};
+local const uInt cpdext[30] = { /* 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};
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15         /* maximum bit length of any code */
+
+local int huft_build(b, n, s, d, e, t, m, hp, hn, v)
+uIntf *b;               /* code lengths in bits (all assumed <= BMAX) */
+uInt n;                 /* number of codes (assumed <= 288) */
+uInt s;                 /* number of simple-valued codes (0..s-1) */
+const uIntf *d;         /* list of base values for non-simple codes */
+const uIntf *e;         /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t;  /* result: starting table */
+uIntf *m;               /* maximum lookup bits, returns actual */
+inflate_huft *hp;       /* space for trees */
+uInt *hn;               /* hufts used in space */
+uIntf *v;               /* working area: values in order of bit length */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
+   if the given code set is incomplete (the tables are still built in this
+   case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+   lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+  uInt a;                       /* counter for codes of length k */
+  uInt c[BMAX+1];               /* bit length count table */
+  uInt f;                       /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register uInt i;              /* counter, current code */
+  register uInt j;              /* counter */
+  register int k;               /* number of bits in current code */
+  int l;                        /* bits per table (returned in m) */
+  uInt mask;                    /* (1 << w) - 1, to avoid cc -O bug on HP */
+  register uIntf *p;            /* pointer into c[], b[], or v[] */
+  inflate_huft *q;              /* points to current table */
+  struct inflate_huft_s r;      /* table entry for structure assignment */
+  inflate_huft *u[BMAX];        /* table stack */
+  register int w;               /* bits before this table == (l * h) */
+  uInt x[BMAX+1];               /* bit offsets, then code stack */
+  uIntf *xp;                    /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  uInt z;                       /* number of entries in current table */
+
+
+  /* Generate counts for each bit length */
+  p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+  C4                            /* clear c[]--assume BMAX+1 is 16 */
+  p = b;  i = n;
+  do {
+    c[*p++]++;                  /* assume all entries <= BMAX */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (inflate_huft *)Z_NULL;
+    *m = 0;
+    return Z_OK;
+  }
+
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((uInt)l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((uInt)l > i)
+    l = i;
+  *m = l;
+
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return Z_DATA_ERROR;
+  if ((y -= c[i]) < 0)
+    return Z_DATA_ERROR;
+  c[i] += y;
+
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+
+  /* Make a table of values in order of bit lengths */
+  p = b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+  n = x[g];                     /* set n to length of v */
+
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = -l;                       /* bits decoded == (l * h) */
+  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
+  q = (inflate_huft *)Z_NULL;   /* ditto */
+  z = 0;                        /* ditto */
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+    a = c[k];
+    while (a--)
+    {
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l)
+      {
+        h++;
+        w += l;                 /* previous table always l bits */
+
+        /* compute minimum size table less than or equal to l bits */
+        z = g - w;
+        z = z > (uInt)l ? l : z;        /* table size upper limit */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          if (j < z)
+            while (++j < z)     /* try smaller tables up to z bits */
+            {
+              if ((f <<= 1) <= *++xp)
+                break;          /* enough codes to use up j bits */
+              f -= *xp;         /* else deduct codes from patterns */
+            }
+        }
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate new table */
+        if (*hn + z > MANY)     /* (note: doesn't matter for fixed) */
+          return Z_MEM_ERROR;   /* not enough memory */
+        u[h] = q = hp + *hn;
+        *hn += z;
+
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.bits = (Byte)l;     /* bits to dump before this table */
+          r.exop = (Byte)j;     /* bits in this table */
+          j = i >> (w - l);
+          r.base = (uInt)(q - u[h-1] - j);   /* offset to this table */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+        else
+          *t = q;               /* first table is returned result */
+      }
+
+      /* set up table entry in r */
+      r.bits = (Byte)(k - w);
+      if (p >= v + n)
+        r.exop = 128 + 64;      /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
+        r.base = *p++;          /* simple code is just the value */
+      }
+      else
+      {
+        r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
+        r.base = d[*p++ - s];
+      }
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      mask = (1 << w) - 1;      /* needed on HP, cc -O bug */
+      while ((i & mask) != x[h])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+        mask = (1 << w) - 1;
+      }
+    }
+  }
+
+
+  /* Return Z_BUF_ERROR if we were given an incomplete table */
+  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+int inflate_trees_bits(c, bb, tb, hp, z)
+uIntf *c;               /* 19 code lengths */
+uIntf *bb;              /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+inflate_huft *hp;       /* space for trees */
+z_streamp z;            /* for messages */
+{
+  int r;
+  uInt hn = 0;          /* hufts used in space */
+  uIntf *v;             /* work area for huft_build */
+  static unsigned int work_area[19];
+
+  v = work_area;
+  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
+                 tb, bb, hp, &hn, v);
+  if (r == Z_DATA_ERROR)
+    z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+  else if (r == Z_BUF_ERROR || *bb == 0)
+  {
+    z->msg = (char*)"incomplete dynamic bit lengths tree";
+    r = Z_DATA_ERROR;
+  }
+  return r;
+}
+
+int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z)
+uInt nl;                /* number of literal/length codes */
+uInt nd;                /* number of distance codes */
+uIntf *c;               /* that many (total) code lengths */
+uIntf *bl;              /* literal desired/actual bit depth */
+uIntf *bd;              /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+inflate_huft *hp;       /* space for trees */
+z_streamp z;            /* for messages */
+{
+  int r;
+  uInt hn = 0;          /* hufts used in space */
+  uIntf *v;             /* work area for huft_build */
+  static unsigned int work_area[288];
+
+  /* allocate work area */
+  v = work_area;
+
+  /* build literal/length tree */
+  r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
+  if (r != Z_OK || *bl == 0)
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = (char*)"oversubscribed literal/length tree";
+    else if (r != Z_MEM_ERROR)
+    {
+      z->msg = (char*)"incomplete literal/length tree";
+      r = Z_DATA_ERROR;
+    }
+    return r;
+  }
+
+  /* build distance tree */
+  r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
+  if (r != Z_OK || (*bd == 0 && nl > 257))
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = (char*)"oversubscribed distance tree";
+    else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+      r = Z_OK;
+    }
+#else
+      z->msg = (char*)"incomplete distance tree";
+      r = Z_DATA_ERROR;
+    }
+    else if (r != Z_MEM_ERROR)
+    {
+      z->msg = (char*)"empty distance tree with lengths";
+      r = Z_DATA_ERROR;
+    }
+    return r;
+#endif
+  }
+
+  /* done */
+  return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+#include "inffixed.h"
+
+
+int inflate_trees_fixed(bl, bd, tl, td, z)
+uIntf *bl;               /* literal desired/actual bit depth */
+uIntf *bd;               /* distance desired/actual bit depth */
+inflate_huft * FAR *tl;  /* literal/length tree result */
+inflate_huft * FAR *td;  /* distance tree result */
+z_streamp z;             /* for memory allocation */
+{
+  *bl = fixed_bl;
+  *bd = fixed_bd;
+  *tl = fixed_tl;
+  *td = fixed_td;
+  return Z_OK;
+}
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/inftrees.h linux/fs/cramfs/inflate/inftrees.h
--- v2.3.34/linux/fs/cramfs/inflate/inftrees.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/inftrees.h	Tue Nov  2 11:29:32 1999
@@ -0,0 +1,58 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+  union {
+    struct {
+      Byte Exop;        /* number of extra bits or operation */
+      Byte Bits;        /* number of bits in this code or subcode */
+    } what;
+    uInt pad;           /* pad structure to a power of 2 (4 bytes for */
+  } word;               /*  16-bit, 8 bytes for 32-bit int's) */
+  uInt base;            /* literal, length base, distance base,
+                           or table offset */
+};
+
+/* Maximum size of dynamic tree.  The maximum found in a long but non-
+   exhaustive search was 1004 huft structures (850 for length/literals
+   and 154 for distances, the latter actually the result of an
+   exhaustive search).  The actual maximum is not known, but the
+   value below is more than safe. */
+#define MANY 1440
+
+extern int inflate_trees_bits OF((
+    uIntf *,                    /* 19 code lengths */
+    uIntf *,                    /* bits tree desired/actual depth */
+    inflate_huft * FAR *,       /* bits tree result */
+    inflate_huft *,             /* space for trees */
+    z_streamp));                /* for messages */
+
+extern int inflate_trees_dynamic OF((
+    uInt,                       /* number of literal/length codes */
+    uInt,                       /* number of distance codes */
+    uIntf *,                    /* that many (total) code lengths */
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *,       /* distance tree result */
+    inflate_huft *,             /* space for trees */
+    z_streamp));                /* for messages */
+
+extern int inflate_trees_fixed OF((
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *,       /* distance tree result */
+    z_streamp));                /* for memory allocation */
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/infutil.c linux/fs/cramfs/inflate/infutil.c
--- v2.3.34/linux/fs/cramfs/inflate/infutil.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/infutil.c	Tue Nov  2 11:36:15 1999
@@ -0,0 +1,87 @@
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#include "zutil.h"
+#include "infblock.h"
+#include "inftrees.h"
+#include "infcodes.h"
+#include "infutil.h"
+
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
+/* And'ing with mask[n] masks the lower n bits */
+uInt inflate_mask[17] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+
+/* copy as much as possible from the sliding window to the output area */
+int inflate_flush(s, z, r)
+inflate_blocks_statef *s;
+z_streamp z;
+int r;
+{
+  uInt n;
+  Bytef *p;
+  Bytef *q;
+
+  /* local copies of source and destination pointers */
+  p = z->next_out;
+  q = s->read;
+
+  /* compute number of bytes to copy as far as end of window */
+  n = (uInt)((q <= s->write ? s->write : s->end) - q);
+  if (n > z->avail_out) n = z->avail_out;
+  if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+  /* update counters */
+  z->avail_out -= n;
+  z->total_out += n;
+
+  /* update check information */
+  if (s->checkfn != Z_NULL)
+    z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+  /* copy as far as end of window */
+  memcpy(p, q, n);
+  p += n;
+  q += n;
+
+  /* see if more to copy at beginning of window */
+  if (q == s->end)
+  {
+    /* wrap pointers */
+    q = s->window;
+    if (s->write == s->end)
+      s->write = s->window;
+
+    /* compute bytes to copy */
+    n = (uInt)(s->write - q);
+    if (n > z->avail_out) n = z->avail_out;
+    if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+    /* update counters */
+    z->avail_out -= n;
+    z->total_out += n;
+
+    /* update check information */
+    if (s->checkfn != Z_NULL)
+      z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+    /* copy */
+    memcpy(p, q, n);
+    p += n;
+    q += n;
+  }
+
+  /* update pointers */
+  z->next_out = p;
+  s->read = q;
+
+  /* done */
+  return r;
+}
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/infutil.h linux/fs/cramfs/inflate/infutil.h
--- v2.3.34/linux/fs/cramfs/inflate/infutil.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/infutil.h	Tue Nov  2 11:29:32 1999
@@ -0,0 +1,98 @@
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFUTIL_H
+#define _INFUTIL_H
+
+typedef enum {
+      TYPE,     /* get type bits (3, including end bit) */
+      LENS,     /* get lengths for stored */
+      STORED,   /* processing stored block */
+      TABLE,    /* get table lengths */
+      BTREE,    /* get bit lengths tree for a dynamic block */
+      DTREE,    /* get length, distance trees for a dynamic block */
+      CODES,    /* processing fixed or dynamic block */
+      DRY,      /* output remaining window bytes */
+      DONE,     /* finished last block, done */
+      BAD}      /* got a data error--stuck here */
+inflate_block_mode;
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+  /* mode */
+  inflate_block_mode  mode;     /* current inflate_block mode */
+
+  /* mode dependent information */
+  union {
+    uInt left;          /* if STORED, bytes left to copy */
+    struct {
+      uInt table;               /* table lengths (14 bits) */
+      uInt index;               /* index into blens (or border) */
+      uIntf *blens;             /* bit lengths of codes */
+      uInt bb;                  /* bit length tree depth */
+      inflate_huft *tb;         /* bit length decoding tree */
+    } trees;            /* if DTREE, decoding info for trees */
+    struct {
+      inflate_codes_statef 
+         *codes;
+    } decode;           /* if CODES, current state */
+  } sub;                /* submode */
+  uInt last;            /* true if this block is the last block */
+
+  /* mode independent information */
+  uInt bitk;            /* bits in bit buffer */
+  uLong bitb;           /* bit buffer */
+  inflate_huft *hufts;  /* single malloc for tree space */
+  Bytef *window;        /* sliding window */
+  Bytef *end;           /* one byte after sliding window */
+  Bytef *read;          /* window read pointer */
+  Bytef *write;         /* window write pointer */
+  check_func checkfn;   /* check function */
+  uLong check;          /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/*   update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/*   get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/*   output bytes */
+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/*   load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
+extern uInt inflate_mask[17];
+
+/* copy as much as possible from the sliding window to the output area */
+extern int inflate_flush OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));
+
+struct internal_state      {int dummy;}; /* for buggy compilers */
+
+#endif
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/uncompr.c linux/fs/cramfs/inflate/uncompr.c
--- v2.3.34/linux/fs/cramfs/inflate/uncompr.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/uncompr.c	Tue Nov  2 13:31:37 1999
@@ -0,0 +1,55 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#include "zlib.h"
+
+/* ===========================================================================
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+int ZEXPORT uncompress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
+    uLong sourceLen;
+{
+    z_stream stream;
+    int err;
+
+    stream.next_in = (Bytef*)source;
+    stream.avail_in = (uInt)sourceLen;
+    /* Check for source > 64K on 16-bit machine: */
+    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+    stream.next_out = dest;
+    stream.avail_out = (uInt)*destLen;
+    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+    err = inflateInit(&stream);
+    if (err != Z_OK) return err;
+
+    err = inflate(&stream, Z_FINISH);
+    if (err != Z_STREAM_END) {
+        inflateEnd(&stream);
+        return err == Z_OK ? Z_BUF_ERROR : err;
+    }
+    *destLen = stream.total_out;
+
+    err = inflateEnd(&stream);
+    return err;
+}
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/zconf.h linux/fs/cramfs/inflate/zconf.h
--- v2.3.34/linux/fs/cramfs/inflate/zconf.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/zconf.h	Wed Nov  3 10:44:27 1999
@@ -0,0 +1,90 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+#if defined(__GNUC__) || defined(__386__) || defined(i386)
+#  ifndef __32BIT__
+#    define __32BIT__
+#  endif
+#endif
+
+#if defined(__STDC__) || defined(__cplusplus)
+#  ifndef STDC
+#    define STDC
+#  endif
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  define MAX_MEM_LEVEL 9
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef FAR
+#   define FAR
+#endif
+
+typedef unsigned char  Byte;  /* 8 bits */
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+typedef Byte  FAR Bytef;
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+typedef void FAR *voidpf;
+typedef void     *voidp;
+
+#include <sys/types.h> /* for off_t */
+#include <unistd.h>    /* for SEEK_* and off_t */
+#define z_off_t  off_t
+
+#endif /* _ZCONF_H */
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/zlib.h linux/fs/cramfs/inflate/zlib.h
--- v2.3.34/linux/fs/cramfs/inflate/zlib.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/zlib.h	Tue Nov  2 13:30:57 1999
@@ -0,0 +1,893 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.1.3, July 9th, 1998
+
+  Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.1.3"
+
+/* 
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms will be added later and will have the same
+  stream interface.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+     The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio.
+
+     The library does not install any signal handler. The decoder checks
+  the consistency of the compressed data, so the library should never
+  crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func nozalloc;  /* used to allocate the internal state */
+    free_func  nozfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: ascii or binary */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_ASCII    1
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+   This check is automatically made by deflateInit and inflateInit.
+ */
+
+/* 
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression. The fields
+   zalloc, zfree and opaque must be initialized before by the caller.
+   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+   use default allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at
+   all (the input data is simply copied a block at a time).
+   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+   compression (currently equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).
+   msg is set to null if there is no error message.  deflateInit does not
+   perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce some
+  output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows. deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly. This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).
+    Some output may be provided even if flush is not set.
+
+  Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating avail_in or avail_out accordingly; avail_out
+  should never be zero before the call. The application can consume the
+  compressed output when it wants, for example when the output buffer is full
+  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+  and with zero avail_out, it must be called again after making room in the
+  output buffer because there might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far. (In particular
+  avail_in is zero after the call if enough output space has been provided
+  before the call.)  Flushing may degrade compression for some compression
+  algorithms and so it should be used only when necessary.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+  the compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there
+  was enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error. After
+  deflate has returned Z_STREAM_END, the only possible operations on the
+  stream are deflateReset or deflateEnd.
+  
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step. In this case, avail_out must be at least
+  0.1% larger than avail_in plus 12 bytes.  If deflate does not return
+  Z_STREAM_END, then it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update data_type if it can make a good guess about
+  the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+  binary. This field is only for information purposes and does not affect
+  the compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero).
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded). In the error case,
+   msg may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/* 
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression. The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+   value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller.  msg is set to null if there is no error
+   message. inflateInit does not perform any decompression apart from reading
+   the zlib header if present: this will be done by inflate().  (So next_in and
+   avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may some
+  introduce some output latency (reading input without producing any output)
+  except when forced to flush.
+
+  The detailed semantics are as follows. inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there
+    is no more input data or no more space in the output buffer (see below
+    about the flush parameter).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+  must be called again after making room in the output buffer because there
+  might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
+  output as possible to the output buffer. The flushing behavior of inflate is
+  not specified for values of the flush parameter other than Z_SYNC_FLUSH
+  and Z_FINISH, but the current implementation actually flushes as much output
+  as possible anyway.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+  is never required, but can be used to inform inflate that a faster routine
+  may be used for the single inflate() call.
+
+     If a preset dictionary is needed at this point (see inflateSetDictionary
+  below), inflate sets strm-adler to the adler32 checksum of the
+  dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise 
+  it sets strm->adler to the adler32 checksum of all output produced
+  so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
+  an error code as described below. At the end of the stream, inflate()
+  checks that its computed adler32 checksum is equal to that saved by the
+  compressor and returns Z_STREAM_END only if the checksum is correct.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect
+  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
+  (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
+  enough memory, Z_BUF_ERROR if no progress is possible or if there was not
+  enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
+  case, the application may then call inflateSync to look for a good
+  compression block.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*   
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options. The
+   fields next_in, zalloc, zfree and opaque must be initialized before by
+   the caller.
+
+     The method parameter is the compression method. It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library. Larger values of this parameter result in better
+   compression at the expense of memory usage. The default value is 15 if
+   deflateInit is used instead.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state. memLevel=1 uses minimum memory but
+   is slow and reduces compression ratio; memLevel=9 uses maximum memory
+   for optimal speed. The default value is 8. See zconf.h for total memory
+   usage as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm. Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match).  Filtered data consists mostly of small values with a
+   somewhat random distribution. In this case, the compression algorithm is
+   tuned to compress them better. The effect of Z_FILTERED is to force more
+   Huffman coding and less string matching; it is somewhat intermediate
+   between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+   the compression ratio but not the correctness of the compressed output even
+   if it is not set appropriately.
+
+      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+   method). msg is set to null if there is no error message.  deflateInit2 does
+   not perform any compression: this will be done by deflate().
+*/
+                            
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output. This function must be called
+   immediately after deflateInit, deflateInit2 or deflateReset, before any
+   call of deflate. The compressor and decompressor must use exactly the same
+   dictionary (see inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary. Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size in
+   deflate or deflate2. Thus the strings most likely to be useful should be
+   put at the end of the dictionary, not at the front.
+
+     Upon return of this function, strm->adler is set to the Adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor. (The Adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.)
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if the compression method is bsort). deflateSetDictionary does not
+   perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter. The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and
+   can consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.
+   The stream will keep the same compression level and any other attributes
+   that may have been set by deflateInit2.
+
+      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+				      int level,
+				      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different
+   strategy. If the compression level is changed, the input available so far
+   is compressed with the old level (and may be flushed); the new level will
+   take effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to
+   be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+   if strm->avail_out was zero.
+*/
+
+/*   
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter. The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library. The default value is 15 if inflateInit is used
+   instead. If a compressed stream with a larger window size is given as
+   input, inflate() will return with the error code Z_DATA_ERROR instead of
+   trying to allocate a larger window.
+
+      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+   memLevel). msg is set to null if there is no error message.  inflateInit2
+   does not perform any decompression apart from reading the zlib header if
+   present: this will be done by inflate(). (So next_in and avail_in may be
+   modified, but next_out and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence. This function must be called immediately after a call of inflate
+   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+   can be determined from the Adler32 value returned by this call of
+   inflate. The compressor and decompressor must use exactly the same
+   dictionary (see deflateSetDictionary).
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect Adler32 value). inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/* 
+    Skips invalid compressed data until a full flush point (see above the
+  description of deflate with Z_FULL_FLUSH) can be found, or until all
+  available input is skipped. No output is provided.
+
+    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the
+   basic stream-oriented functions. To simplify the interface, some
+   default options are assumed (compression level and memory usage,
+   standard memory allocation functions). The source code of these
+   utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be at least 0.1% larger than
+   sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+   compressed buffer.
+     This function can be used to compress a whole file at once if the
+   input file is mmap'ed.
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen  OF((const char *path, const char *mode));
+/*
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb") but can also include a compression level
+   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+   Huffman only compression as in "wb1h". (See the description
+   of deflateInit2 for more information about the strategy parameter.)
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     gzopen returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).  */
+
+ZEXTERN gzFile ZEXPORT gzdopen  OF((int fd, const char *mode));
+/*
+     gzdopen() associates a gzFile with the file descriptor fd.  File
+   descriptors are obtained from calls like open, dup, creat, pipe or
+   fileno (in the file has been previously opened with fopen).
+   The mode parameter is as in gzopen.
+     The next call of gzclose on the returned gzFile will also close the
+   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+     gzdopen returns NULL if there was insufficient memory to allocate
+   the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy. See the description
+   of deflateInit2 for the meaning of these parameters.
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+ZEXTERN int ZEXPORT    gzread  OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.
+   If the input file was not in gzip format, gzread copies the given number
+   of bytes into the buffer.
+     gzread returns the number of uncompressed bytes actually read (0 for
+   end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT    gzwrite OF((gzFile file, 
+				   const voidp buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes actually written
+   (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA   gzprintf OF((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+      Reads bytes from the compressed file until len-1 characters are read, or
+   a newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  The string is then terminated with a null
+   character.
+      gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzputc OF((gzFile file, int c));
+/*
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT    gzgetc OF((gzFile file));
+/*
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT    gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function. The return value is the zlib
+   error number (see function gzerror below). gzflush returns Z_OK if
+   the flush parameter is Z_FINISH and all output could be flushed.
+     gzflush should be called only when strictly necessary because it can
+   degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT    gzseek OF((gzFile file,
+				      z_off_t offset, int whence));
+/* 
+      Sets the starting position for the next gzread or gzwrite on the
+   given compressed file. The offset represents a number of bytes in the
+   uncompressed data stream. The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow. If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+/*
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+
+   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state. The return value is the zlib
+   error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occurred in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the
+   compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running crc with the bytes buf[0..len-1] and return the updated
+   crc. If buf is NULL, this function returns the required initial value
+   for the crc. Pre- and post-conditioning (one's complement) is performed
+   within this function so it shouldn't be done by the application.
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
+    struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char   * ZEXPORT zError           OF((int err));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table    OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inflate/zutil.h linux/fs/cramfs/inflate/zutil.h
--- v2.3.34/linux/fs/cramfs/inflate/zutil.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inflate/zutil.h	Fri Dec  3 21:05:30 1999
@@ -0,0 +1,120 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id$ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#  include <stddef.h>
+#  include <stdlib.h>
+
+#ifdef __KERNEL__
+#  include <linux/string.h>
+#  include <linux/errno.h>
+#else
+#  include <string.h>
+#  include <errno.h>
+#endif
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+  return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+        /* Common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03  /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+#  define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+         /* functions */
+
+/* Diagnostic functions */
+#ifdef DEBUG
+#  include <stdio.h>
+   extern int z_verbose;
+   extern void z_error    OF((char *m));
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) {if (z_verbose>=0) fprintf x ;}
+#  define Tracev(x) {if (z_verbose>0) fprintf x ;}
+#  define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+
+typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf,
+				       uInt len));
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void   zcfree  OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) ({ \
+	printf("alloc %d %d at %s:%d\n", items, size, __FILE__, __LINE__); \
+	calloc((items), (size)); })
+#define ZFREE(strm, addr)  free(addr)
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* _Z_UTIL_H */
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/inode.c linux/fs/cramfs/inode.c
--- v2.3.34/linux/fs/cramfs/inode.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/inode.c	Mon Dec 27 12:34:02 1999
@@ -0,0 +1,488 @@
+/*
+ * Compressed rom filesystem for Linux.
+ *
+ * Copyright (C) 1999 Linus Torvalds.
+ *
+ * This file is released under the GPL.
+ */
+
+/*
+ * These are the VFS interfaces to the compressed rom filesystem.
+ * The actual compression is based on zlib, see the other files.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+
+#include <asm/uaccess.h>
+
+#include "cramfs.h"
+
+static struct super_operations cramfs_ops;
+static struct inode_operations cramfs_file_inode_operations;
+static struct inode_operations cramfs_dir_inode_operations;
+static struct inode_operations cramfs_symlink_inode_operations;
+
+#define CRAMINO(x)	((x)->offset?(x)->offset<<2:1)
+
+static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode)
+{
+	struct inode * inode = get_empty_inode();
+
+	if (inode) {
+		inode->i_mode = cramfs_inode->mode;
+		inode->i_uid = cramfs_inode->uid;
+		inode->i_size = cramfs_inode->size;
+		inode->i_gid = cramfs_inode->gid;
+		inode->i_ino = CRAMINO(cramfs_inode);
+		inode->i_sb = sb;
+		inode->i_dev = sb->s_dev;
+		insert_inode_hash(inode);
+		if (S_ISREG(inode->i_mode))
+			inode->i_op = &cramfs_file_inode_operations;
+		else if (S_ISDIR(inode->i_mode))
+			inode->i_op = &cramfs_dir_inode_operations;
+		else if (S_ISLNK(inode->i_mode))
+			inode->i_op = &cramfs_symlink_inode_operations;
+		else {
+			inode->i_size = 0;
+			init_special_inode(inode, inode->i_mode, cramfs_inode->size);
+		}
+	}
+	return inode;
+}
+
+/*
+ * We have our own block cache: don't fill up the buffer cache
+ * with the rom-image, because the way the filesystem is set
+ * up the accesses should be fairly regular and cached in the
+ * page cache and dentry tree anyway..
+ *
+ * This also acts as a way to guarantee contiguous areas of
+ * up to 2*PAGE_CACHE_SIZE, so that the caller doesn't need
+ * to worry about end-of-buffer issues even when decompressing
+ * a full page cache.
+ */
+#define READ_BUFFERS (2)
+static unsigned char read_buffers[READ_BUFFERS][PAGE_CACHE_SIZE*4];
+static int buffer_blocknr[READ_BUFFERS];
+static int last_buffer = 0;
+
+static void *cramfs_read(struct super_block *sb, unsigned int offset)
+{
+	struct buffer_head * bh_array[4];
+	int i, blocknr, buffer;
+
+	blocknr = offset >> PAGE_CACHE_SHIFT;
+	offset &= PAGE_CACHE_SIZE-1;
+	for (i = 0; i < READ_BUFFERS; i++) {
+		if (blocknr == buffer_blocknr[i])
+			return read_buffers[i] + offset;
+	}
+
+	/* Ok, read in four buffers completely first */
+	for (i = 0; i < 4; i++)
+		bh_array[i] = bread(sb->s_dev, blocknr + i, PAGE_CACHE_SIZE);
+
+	/* Ok, copy them to the staging area without sleeping.. */
+	buffer = last_buffer;
+	last_buffer = buffer ^ 1;
+	buffer_blocknr[buffer] = blocknr;
+	for (i = 0; i < 4; i++) {
+		struct buffer_head * bh = bh_array[i];
+		if (bh) {
+			memcpy(read_buffers[buffer] + i*PAGE_CACHE_SIZE, bh->b_data, PAGE_CACHE_SIZE);
+			bforget(bh);
+		}
+		blocknr++;
+	}
+	return read_buffers[buffer] + offset;
+}
+			
+
+static struct super_block * cramfs_read_super(struct super_block *sb, void *data, int silent)
+{
+	int i;
+	struct cramfs_super super;
+	unsigned long root_offset;
+	struct super_block * retval = NULL;
+
+	lock_super(sb);
+	set_blocksize(sb->s_dev, PAGE_CACHE_SIZE);
+	sb->s_blocksize = PAGE_CACHE_SIZE;
+	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+
+	/* Invalidate the read buffers on mount: think disk change.. */
+	for (i = 0; i < READ_BUFFERS; i++)
+		buffer_blocknr[i] = -1;
+
+	/* Read the first block and get the superblock from it */
+	memcpy(&super, cramfs_read(sb, 0), sizeof(super));
+
+	/* Do sanity checks on the superblock */
+	if (super.magic != CRAMFS_MAGIC) {
+		printk("wrong magic\n");
+		goto out;
+	}
+	if (memcmp(super.signature, CRAMFS_SIGNATURE, sizeof(super.signature))) {
+		printk("wrong signature\n");
+		goto out;
+	}
+
+	/* Check that the root inode is in a sane state */
+	root_offset = super.root.offset << 2;
+	if (root_offset < sizeof(struct cramfs_super)) {
+		printk("root offset too small\n");
+		goto out;
+	}
+	if (root_offset >= super.size) {
+		printk("root offset too large (%lu %u)\n", root_offset, super.size);
+		goto out;
+	}
+	if (!S_ISDIR(super.root.mode)) {
+		printk("root is not a directory\n");
+		goto out;
+	}
+
+	/* Set it all up.. */
+	sb->s_op	= &cramfs_ops;
+	sb->s_root = d_alloc_root(get_cramfs_inode(sb, &super.root));
+	retval = sb;
+
+out:
+	unlock_super(sb);
+	return retval;
+}
+
+/* Nothing to do.. */
+static void cramfs_put_super(struct super_block *sb)
+{
+	return;
+}
+
+static int cramfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
+{
+	struct statfs tmp;
+
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.f_type = CRAMFS_MAGIC;
+	tmp.f_bsize = PAGE_CACHE_SIZE;
+	tmp.f_blocks = 0;
+	tmp.f_namelen = 255;
+	return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0;
+}
+
+/*
+ * Read a cramfs directory entry..
+ *
+ * Remember: the inode number is the byte offset of the start
+ * of the directory..
+ */
+static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
+	unsigned int offset;
+	int copied;
+
+	/* Offset within the thing.. */
+	offset = filp->f_pos;
+	if (offset >= inode->i_size)
+		return 0;
+	/* Directory entries are always 4-byte aligned */
+	if (offset & 3)
+		return -EINVAL;
+
+	copied = 0;
+	while (offset < inode->i_size) {
+		struct cramfs_inode *de;
+		unsigned long nextoffset;
+		char *name;
+		int namelen, error;
+
+		de = cramfs_read(sb, offset + inode->i_ino);
+		name = (char *)(de+1);
+
+		/*
+		 * Namelengths on disk are shifted by two
+		 * and the name padded out to 4-byte boundaries
+		 * with zeroes.
+		 */
+		namelen = de->namelen << 2;
+		nextoffset = offset + sizeof(*de) + namelen;
+		for (;;) {
+			if (!namelen)
+				return -EIO;
+			if (name[namelen-1])
+				break;
+			namelen--;
+		}
+		error = filldir(dirent, name, namelen, offset, CRAMINO(de));
+		if (error)
+			break;
+
+		offset = nextoffset;
+		filp->f_pos = offset;
+		copied++;
+	}
+	return 0;
+}
+
+/*
+ * Lookup and fill in the inode data..
+ */
+static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry)
+{
+	unsigned int offset = 0;
+
+	while (offset < dir->i_size) {
+		struct cramfs_inode *de;
+		char *name;
+		int namelen;
+
+		de = cramfs_read(dir->i_sb, offset + dir->i_ino);
+		name = (char *)(de+1);
+		namelen = de->namelen << 2;
+		offset += sizeof(*de) + namelen;
+
+		/* Quick check that the name is roughly the right length */
+		if (((dentry->d_name.len + 3) & ~3) != namelen)
+			continue;
+
+		for (;;) {
+			if (!namelen)
+				return ERR_PTR(-EIO);
+			if (name[namelen-1])
+				break;
+			namelen--;
+		}
+		if (namelen != dentry->d_name.len)
+			continue;
+		if (memcmp(dentry->d_name.name, name, namelen))
+			continue;
+		d_add(dentry, get_cramfs_inode(dir->i_sb, de));
+		return NULL;
+	}
+	d_add(dentry, NULL);
+	return NULL;
+}
+
+static int cramfs_readpage(struct dentry *dentry, struct page * page)
+{
+	struct inode *inode = dentry->d_inode;
+	unsigned long maxblock, bytes;
+
+	maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+	bytes = 0;
+	if (page->index < maxblock) {
+		struct super_block *sb = inode->i_sb;
+		unsigned long block_offset = inode->i_ino + page->index*4;
+		unsigned long start_offset = inode->i_ino + maxblock*4;
+		unsigned long end_offset;
+
+		end_offset = *(u32 *) cramfs_read(sb, block_offset);
+		if (page->index)
+			start_offset = *(u32 *) cramfs_read(sb, block_offset-4);
+
+		bytes = inode->i_size & (PAGE_CACHE_SIZE - 1);
+		if (page->index < maxblock)
+			bytes = PAGE_CACHE_SIZE;
+
+		cramfs_uncompress_block((void *) page_address(page), PAGE_CACHE_SIZE, cramfs_read(sb, start_offset), end_offset - start_offset);
+	}
+	memset((void *) (page_address(page) + bytes), 0, PAGE_CACHE_SIZE - bytes);
+	SetPageUptodate(page);
+	UnlockPage(page);
+	return 0;
+}
+
+static struct page *get_symlink_page(struct dentry *dentry)
+{
+	return read_cache_page(&dentry->d_inode->i_data, 0, (filler_t *)cramfs_readpage, dentry);
+}
+
+static int cramfs_readlink(struct dentry *dentry, char *buffer, int len)
+{
+	struct inode *inode = dentry->d_inode;
+	int retval;
+
+	if (!inode || !S_ISLNK(inode->i_mode))
+		return -EBADF;
+
+	retval = inode->i_size;
+	if (retval) {
+		int len;
+		struct page *page = get_symlink_page(dentry);
+
+		if (IS_ERR(page))
+			return PTR_ERR(page);
+		wait_on_page(page);
+		len = retval;
+		retval = -EIO;
+		if (Page_Uptodate(page)) {
+			retval = -EFAULT;
+			if (!copy_to_user(buffer, (void *) page_address(page), len))
+				retval = len;
+		}
+		page_cache_release(page);
+	}
+	return retval;
+}
+
+static struct dentry *cramfs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
+{
+	struct page *page = get_symlink_page(dentry);
+	struct dentry *result;
+
+	if (IS_ERR(page)) {
+		dput(base);
+		return ERR_PTR(PTR_ERR(page));
+	}
+
+	result = lookup_dentry((void *) page_address(page), base, follow);
+	page_cache_release(page);
+	return result;
+}
+
+/*
+ * Our operations:
+ *
+ * A regular file can be read and mmap'ed.
+ */
+static struct file_operations cramfs_file_operations = {
+	NULL,			/* lseek - default */
+	generic_file_read,	/* read */
+	NULL,			/* write - bad */
+	NULL,			/* readdir */
+	NULL,			/* poll - default */
+	NULL,			/* ioctl */
+	generic_file_mmap,	/* mmap */
+	NULL,			/* open */
+	NULL,			/* flush */
+	NULL,			/* release */
+	NULL,			/* fsync */
+	NULL,			/* fasync */
+	NULL,			/* check_media_change */
+	NULL			/* revalidate */
+};
+
+/*
+ * A directory can only readdir
+ */
+static struct file_operations cramfs_directory_operations = {
+	NULL,			/* lseek - default */
+	NULL,			/* read */
+	NULL,			/* write - bad */
+	cramfs_readdir,		/* readdir */
+	NULL,			/* poll - default */
+	NULL,			/* ioctl */
+	NULL,			/* mmap */
+	NULL,			/* open */
+	NULL,			/* flush */
+	NULL,			/* release */
+	NULL,			/* fsync */
+	NULL,			/* fasync */
+	NULL,			/* check_media_change */
+	NULL			/* revalidate */
+};
+
+static struct inode_operations cramfs_file_inode_operations = {
+	&cramfs_file_operations,
+	NULL,			/* create */
+	NULL,			/* lookup */
+	NULL,			/* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	NULL,			/* readlink */
+	NULL,			/* follow_link */
+	NULL,			/* get_block */
+	cramfs_readpage,	/* readpage */
+	NULL,			/* writepage */
+	NULL,			/* truncate */
+	NULL,			/* permission */
+	NULL			/* revalidate */
+};
+
+static struct inode_operations cramfs_dir_inode_operations = {
+	&cramfs_directory_operations,
+	NULL,			/* create */
+	cramfs_lookup,		/* lookup */
+	NULL,			/* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	NULL,			/* readlink */
+	NULL,			/* follow_link */
+	NULL,			/* get_block */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
+	NULL,			/* truncate */
+	NULL,			/* permission */
+	NULL			/* revalidate */
+};
+
+static struct inode_operations cramfs_symlink_inode_operations = {
+	NULL,			/* symlinks do not have files */
+	NULL,			/* create */
+	NULL,			/* lookup */
+	NULL,			/* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	cramfs_readlink,		/* readlink */
+	cramfs_follow_link,	/* follow_link */
+	NULL,			/* get_block */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
+	NULL,			/* truncate */
+	NULL,			/* permission */
+	NULL			/* revalidate */
+};
+
+static struct super_operations cramfs_ops = {
+	NULL,			/* read inode */
+	NULL,			/* write inode */
+	NULL,			/* put inode */
+	NULL,			/* delete inode */
+	NULL,			/* notify change */
+	cramfs_put_super,		/* put super */
+	NULL,			/* write super */
+	cramfs_statfs,		/* statfs */
+	NULL			/* remount */
+};
+
+static struct file_system_type cramfs_fs_type = {
+	"cramfs",
+	FS_REQUIRES_DEV,
+	cramfs_read_super,
+	NULL
+};
+
+static int __init init_cramfs_fs(void)
+{
+	cramfs_uncompress_init();
+	return register_filesystem(&cramfs_fs_type);
+}
+
+static void __exit exit_cramfs_fs(void)
+{
+	cramfs_uncompress_exit();
+	unregister_filesystem(&cramfs_fs_type);
+}
+
+module_init(init_cramfs_fs)
+module_exit(exit_cramfs_fs)
diff -u --recursive --new-file v2.3.34/linux/fs/cramfs/uncompress.c linux/fs/cramfs/uncompress.c
--- v2.3.34/linux/fs/cramfs/uncompress.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/uncompress.c	Tue Nov 23 14:43:51 1999
@@ -0,0 +1,60 @@
+/*
+ * uncompress.c
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * cramfs interfaces to the uncompression library. There's really just
+ * three entrypoints:
+ *
+ *  - cramfs_uncompress_init() - called to initialize the thing.
+ *  - cramfs_uncompress_exit() - tell me when you're done
+ *  - cramfs_uncompress_block() - uncompress a block.
+ *
+ * NOTE NOTE NOTE! The uncompression is entirely single-threaded. We
+ * only have one stream, and we'll initialize it only once even if it
+ * then is used by multiple filesystems.
+ */
+
+#include <linux/kernel.h>
+
+#include "inflate/zlib.h"
+
+static z_stream stream;
+static int initialized = 0;
+
+int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
+{
+	int err;
+
+	stream.next_in = src;
+	stream.avail_in = srclen;
+
+	stream.next_out = dst;
+	stream.avail_out = dstlen;
+
+	inflateReset(&stream);
+
+	err = inflate(&stream, Z_FINISH);
+	if (err != Z_STREAM_END) {
+		printk("Error %d while decompressing!\n", err);
+		printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
+	}
+	return stream.total_out;
+}
+
+int cramfs_uncompress_init(void)
+{
+	if (!initialized++) {
+		stream.next_in = NULL;
+		stream.avail_in = 0;
+		inflateInit(&stream);
+	}
+	return 0;
+}
+
+int cramfs_uncompress_exit(void)
+{
+	if (!--initialized)
+		inflateEnd(&stream);
+	return 0;
+}
diff -u --recursive --new-file v2.3.34/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.3.34/linux/fs/ext2/super.c	Mon Nov  1 13:56:27 1999
+++ linux/fs/ext2/super.c	Mon Dec 27 16:01:34 1999
@@ -723,33 +723,6 @@
 	return 0;
 }
 
-static struct file_system_type ext2_fs_type = {
-	"ext2", 
-	FS_REQUIRES_DEV /* | FS_IBASKET */,	/* ibaskets have unresolved bugs */
-        ext2_read_super, 
-	NULL
-};
-
-int __init init_ext2_fs(void)
-{
-        return register_filesystem(&ext2_fs_type);
-}
-
-#ifdef MODULE
-EXPORT_NO_SYMBOLS;
-
-int init_module(void)
-{
-	return init_ext2_fs();
-}
-
-void cleanup_module(void)
-{
-        unregister_filesystem(&ext2_fs_type);
-}
-
-#endif
-
 int ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
 {
 	unsigned long overhead;
@@ -805,3 +778,25 @@
 	tmp.f_namelen = EXT2_NAME_LEN;
 	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
 }
+
+static struct file_system_type ext2_fs_type = {
+	"ext2", 
+	FS_REQUIRES_DEV /* | FS_IBASKET */,	/* ibaskets have unresolved bugs */
+        ext2_read_super, 
+	NULL
+};
+
+static int __init init_ext2_fs(void)
+{
+        return register_filesystem(&ext2_fs_type);
+}
+
+static int __exit exit_ext2_fs(void)
+{
+	unregister_filesystem(&ext2_fs_type);
+}
+
+EXPORT_NO_SYMBOLS;
+
+module_init(init_ext2_fs)
+module_exit(exit_ext2_fs)
diff -u --recursive --new-file v2.3.34/linux/fs/filesystems.c linux/fs/filesystems.c
--- v2.3.34/linux/fs/filesystems.c	Tue Dec  7 09:32:47 1999
+++ linux/fs/filesystems.c	Mon Dec 27 16:04:11 1999
@@ -32,6 +32,7 @@
 #include <linux/devpts_fs.h>
 #include <linux/bfs_fs.h>
 #include <linux/adfs_fs.h>
+#include <linux/openprom_fs.h>
 #include <linux/major.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -53,10 +54,6 @@
 
 void __init filesystem_setup(void)
 {
-#ifdef CONFIG_EXT2_FS
-	init_ext2_fs();
-#endif
-
 #ifdef CONFIG_MINIX_FS
 	init_minix_fs();
 #endif
@@ -159,6 +156,10 @@
 
 #ifdef CONFIG_BFS_FS
 	init_bfs_fs();
+#endif
+
+#ifdef CONFIG_SUN_OPENPROMFS
+	init_openprom_fs();
 #endif
    
 #ifdef CONFIG_NLS
diff -u --recursive --new-file v2.3.34/linux/fs/openpromfs/Makefile linux/fs/openpromfs/Makefile
--- v2.3.34/linux/fs/openpromfs/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/fs/openpromfs/Makefile	Mon Dec 20 22:05:10 1999
@@ -0,0 +1,14 @@
+#
+# Makefile for the Linux minix filesystem routines.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile.
+
+O_TARGET := openpromfs.o
+O_OBJS   := inode.o
+M_OBJS   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.34/linux/fs/openpromfs/inode.c linux/fs/openpromfs/inode.c
--- v2.3.34/linux/fs/openpromfs/inode.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/openpromfs/inode.c	Mon Dec 20 22:05:10 1999
@@ -0,0 +1,1153 @@
+/* $Id: inode.c,v 1.1 1999/12/20 12:23:44 jj Exp $
+ * openpromfs.c: /proc/openprom handling routines
+ *
+ * Copyright (C) 1996-1999 Jakub Jelinek  (jakub@redhat.com)
+ * Copyright (C) 1998      Eddie C. Dost  (ecd@skynet.be)
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/openprom_fs.h>
+#include <linux/locks.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+#include <asm/uaccess.h>
+
+#define ALIASES_NNODES 64
+
+typedef struct {
+	u16	parent;
+	u16	next;
+	u16	child;
+	u16	first_prop;
+	u32	node;
+} openpromfs_node;
+
+typedef struct {
+#define OPP_STRING	0x10
+#define OPP_STRINGLIST	0x20
+#define OPP_BINARY	0x40
+#define OPP_HEXSTRING	0x80
+#define OPP_DIRTY	0x01
+#define OPP_QUOTED	0x02
+#define OPP_NOTQUOTED	0x04
+#define OPP_ASCIIZ	0x08
+	u32	flag;
+	u32	alloclen;
+	u32	len;
+	char	*value;
+	char	name[8];
+} openprom_property;
+
+static openpromfs_node *nodes = NULL;
+static int alloced = 0;
+static u16 last_node = 0;
+static u16 first_prop = 0;
+static u16 options = 0xffff;
+static u16 aliases = 0xffff;
+static int aliases_nodes = 0;
+static char *alias_names [ALIASES_NNODES];
+
+#define OPENPROM_ROOT_INO	16
+#define OPENPROM_FIRST_INO	OPENPROM_ROOT_INO
+#define NODE(ino) nodes[ino - OPENPROM_FIRST_INO]
+#define NODE2INO(node) (node + OPENPROM_FIRST_INO)
+#define NODEP2INO(no) (no + OPENPROM_FIRST_INO + last_node)
+
+static int openpromfs_create (struct inode *, struct dentry *, int);
+static int openpromfs_readdir(struct file *, void *, filldir_t);
+static struct dentry *openpromfs_lookup(struct inode *, struct dentry *dentry);
+static int openpromfs_unlink (struct inode *, struct dentry *dentry);
+
+static ssize_t nodenum_read(struct file *file, char *buf,
+			    size_t count, loff_t *ppos)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	char buffer[10];
+	
+	if (count < 0 || !inode->u.generic_ip)
+		return -EINVAL;
+	sprintf (buffer, "%8.8x\n", (u32)(long)(inode->u.generic_ip));
+	if (file->f_pos >= 9)
+		return 0;
+	if (count > 9 - file->f_pos)
+		count = 9 - file->f_pos;
+	copy_to_user(buf, buffer + file->f_pos, count);
+	file->f_pos += count;
+	return count;
+}
+
+static ssize_t property_read(struct file *filp, char *buf,
+			     size_t count, loff_t *ppos)
+{
+	struct inode *inode = filp->f_dentry->d_inode;
+	int i, j, k;
+	u32 node;
+	char *p, *s;
+	u32 *q;
+	openprom_property *op;
+	char buffer[64];
+	
+	if (filp->f_pos >= 0xffffff)
+		return -EINVAL;
+	if (!filp->private_data) {
+		node = nodes[(u16)((long)inode->u.generic_ip)].node;
+		i = ((u32)(long)inode->u.generic_ip) >> 16;
+		if ((u16)((long)inode->u.generic_ip) == aliases) {
+			if (i >= aliases_nodes)
+				p = 0;
+			else
+				p = alias_names [i];
+		} else
+			for (p = prom_firstprop (node, buffer);
+			     i && p && *p;
+			     p = prom_nextprop (node, p, buffer), i--)
+				/* nothing */ ;
+		if (!p || !*p)
+			return -EIO;
+		i = prom_getproplen (node, p);
+		if (i < 0) {
+			if ((u16)((long)inode->u.generic_ip) == aliases)
+				i = 0;
+			else
+				return -EIO;
+		}
+		k = i;
+		if (i < 64) i = 64;
+		filp->private_data = kmalloc (sizeof (openprom_property)
+					      + (j = strlen (p)) + 2 * i,
+					      GFP_KERNEL);
+		if (!filp->private_data)
+			return -ENOMEM;
+		op = (openprom_property *)filp->private_data;
+		op->flag = 0;
+		op->alloclen = 2 * i;
+		strcpy (op->name, p);
+		op->value = (char *)(((unsigned long)(op->name + j + 4)) & ~3);
+		op->len = k;
+		if (k && prom_getproperty (node, p, op->value, i) < 0)
+			return -EIO;
+		op->value [k] = 0;
+		if (k) {
+			for (s = 0, p = op->value; p < op->value + k; p++) {
+				if ((*p >= ' ' && *p <= '~') || *p == '\n') {
+					op->flag |= OPP_STRING;
+					s = p;
+					continue;
+				}
+				if (p > op->value && !*p && s == p - 1) {
+					if (p < op->value + k - 1)
+						op->flag |= OPP_STRINGLIST;
+					else
+						op->flag |= OPP_ASCIIZ;
+					continue;
+				}
+				if (k == 1 && !*p) {
+					op->flag |= (OPP_STRING|OPP_ASCIIZ);
+					break;
+				}
+				op->flag &= ~(OPP_STRING|OPP_STRINGLIST);
+				if (k & 3)
+					op->flag |= OPP_HEXSTRING;
+				else
+					op->flag |= OPP_BINARY;
+				break;
+			}
+			if (op->flag & OPP_STRINGLIST)
+				op->flag &= ~(OPP_STRING);
+			if (op->flag & OPP_ASCIIZ)
+				op->len--;
+		}
+	} else
+		op = (openprom_property *)filp->private_data;
+	if (!count || !(op->len || (op->flag & OPP_ASCIIZ)))
+		return 0;
+	if (op->flag & OPP_STRINGLIST) {
+		for (k = 0, p = op->value; p < op->value + op->len; p++)
+			if (!*p)
+				k++;
+		i = op->len + 4 * k + 3;
+	} else if (op->flag & OPP_STRING) {
+		i = op->len + 3;
+	} else if (op->flag & OPP_BINARY) {
+		i = (op->len * 9) >> 2;
+	} else {
+		i = (op->len << 1) + 1;
+	}
+	k = filp->f_pos;
+	if (k >= i) return 0;
+	if (count > i - k) count = i - k;
+	if (op->flag & OPP_STRING) {
+		if (!k) {
+			__put_user('\'', buf);
+			k++;
+			count--;
+		}
+
+		if (k + count >= i - 2)
+			j = i - 2 - k;
+		else
+			j = count;
+
+		if (j >= 0) {
+			copy_to_user(buf + k - filp->f_pos,
+				     op->value + k - 1, j);
+			count -= j;
+			k += j;
+		}
+
+		if (count)
+			__put_user('\'', &buf [k++ - filp->f_pos]);
+		if (count > 1)
+			__put_user('\n', &buf [k++ - filp->f_pos]);
+
+	} else if (op->flag & OPP_STRINGLIST) {
+		char *tmp;
+
+		tmp = kmalloc (i, GFP_KERNEL);
+		if (!tmp)
+			return -ENOMEM;
+
+		s = tmp;
+		*s++ = '\'';
+		for (p = op->value; p < op->value + op->len; p++) {
+			if (!*p) {
+				strcpy(s, "' + '");
+				s += 5;
+				continue;
+			}
+			*s++ = *p;
+		}
+		strcpy(s, "'\n");
+
+		copy_to_user(buf, tmp + k, count);
+
+		kfree(tmp);
+		k += count;
+
+	} else if (op->flag & OPP_BINARY) {
+		char buffer[10];
+		u32 *first, *last;
+		int first_off, last_cnt;
+
+		first = ((u32 *)op->value) + k / 9;
+		first_off = k % 9;
+		last = ((u32 *)op->value) + (k + count - 1) / 9;
+		last_cnt = (k + count) % 9;
+		if (!last_cnt) last_cnt = 9;
+
+		if (first == last) {
+			sprintf (buffer, "%08x.", *first);
+			copy_to_user (buf, buffer + first_off, last_cnt - first_off);
+			buf += last_cnt - first_off;
+		} else {		
+			for (q = first; q <= last; q++) {
+				sprintf (buffer, "%08x.", *q);
+				if (q == first) {
+					copy_to_user (buf, buffer + first_off,
+						      9 - first_off);
+					buf += 9 - first_off;
+				} else if (q == last) {
+					copy_to_user (buf, buffer, last_cnt);
+					buf += last_cnt;
+				} else {
+					copy_to_user (buf, buffer, 9);
+					buf += 9;
+				}
+			}
+		}
+
+		if (last == (u32 *)(op->value + op->len - 4) && last_cnt == 9)
+			__put_user('\n', (buf - 1));
+
+		k += count;
+
+	} else if (op->flag & OPP_HEXSTRING) {
+		char buffer[2];
+
+		if ((k < i - 1) && (k & 1)) {
+			sprintf (buffer, "%02x", *(op->value + (k >> 1)));
+			__put_user(buffer[1], &buf[k++ - filp->f_pos]);
+			count--;
+		}
+
+		for (; (count > 1) && (k < i - 1); k += 2) {
+			sprintf (buffer, "%02x", *(op->value + (k >> 1)));
+			copy_to_user (buf + k - filp->f_pos, buffer, 2);
+			count -= 2;
+		}
+
+		if (count && (k < i - 1)) {
+			sprintf (buffer, "%02x", *(op->value + (k >> 1)));
+			__put_user(buffer[0], &buf[k++ - filp->f_pos]);
+			count--;
+		}
+
+		if (count)
+			__put_user('\n', &buf [k++ - filp->f_pos]);
+	}
+	count = k - filp->f_pos;
+	filp->f_pos = k;
+	return count;
+}
+
+static ssize_t property_write(struct file *filp, const char *buf,
+			      size_t count, loff_t *ppos)
+{
+	int i, j, k;
+	char *p;
+	u32 *q;
+	void *b;
+	openprom_property *op;
+	
+	if (filp->f_pos >= 0xffffff)
+		return -EINVAL;
+	if (!filp->private_data) {
+		i = property_read (filp, NULL, 0, 0);
+		if (i)
+			return i;
+	}
+	k = filp->f_pos;
+	op = (openprom_property *)filp->private_data;
+	if (!(op->flag & OPP_STRING)) {
+		u32 *first, *last;
+		int first_off, last_cnt;
+		u32 mask, mask2;
+		char tmp [9];
+		int forcelen = 0;
+		
+		j = k % 9;
+		for (i = 0; i < count; i++, j++) {
+			if (j == 9) j = 0;
+			if (!j) {
+				char ctmp;
+				__get_user(ctmp, &buf[i]);
+				if (ctmp != '.') {
+					if (ctmp != '\n') {
+						if (op->flag & OPP_BINARY)
+							return -EINVAL;
+						else
+							goto write_try_string;
+					} else {
+						count = i + 1;
+						forcelen = 1;
+						break;
+					}
+				}
+			} else {
+				char ctmp;
+				__get_user(ctmp, &buf[i]);
+				if (ctmp < '0' || 
+				    (ctmp > '9' && ctmp < 'A') ||
+				    (ctmp > 'F' && ctmp < 'a') ||
+				    ctmp > 'f') {
+					if (op->flag & OPP_BINARY)
+						return -EINVAL;
+					else
+						goto write_try_string;
+				}
+			}
+		}
+		op->flag |= OPP_BINARY;
+		tmp [8] = 0;
+		i = ((count + k + 8) / 9) << 2;
+		if (op->alloclen <= i) {
+			b = kmalloc (sizeof (openprom_property) + 2 * i,
+				     GFP_KERNEL);
+			if (!b)
+				return -ENOMEM;
+			memcpy (b, filp->private_data,
+				sizeof (openprom_property)
+				+ strlen (op->name) + op->alloclen);
+			memset (((char *)b) + sizeof (openprom_property)
+				+ strlen (op->name) + op->alloclen, 
+				0, 2 * i - op->alloclen);
+			op = (openprom_property *)b;
+			op->alloclen = 2*i;
+			b = filp->private_data;
+			filp->private_data = (void *)op;
+			kfree (b);
+		}
+		first = ((u32 *)op->value) + (k / 9);
+		first_off = k % 9;
+		last = (u32 *)(op->value + i);
+		last_cnt = (k + count) % 9;
+		if (first + 1 == last) {
+			memset (tmp, '0', 8);
+			copy_from_user (tmp + first_off, buf,
+					(count + first_off > 8) ? 8 - first_off : count);
+			mask = 0xffffffff;
+			mask2 = 0xffffffff;
+			for (j = 0; j < first_off; j++)
+				mask >>= 1;
+			for (j = 8 - count - first_off; j > 0; j--)
+				mask2 <<= 1;
+			mask &= mask2;
+			if (mask) {
+				*first &= ~mask;
+				*first |= simple_strtoul (tmp, 0, 16);
+				op->flag |= OPP_DIRTY;
+			}
+		} else {
+			op->flag |= OPP_DIRTY;
+			for (q = first; q < last; q++) {
+				if (q == first) {
+					if (first_off < 8) {
+						memset (tmp, '0', 8);
+						copy_from_user (tmp + first_off, buf,
+								8 - first_off);
+						mask = 0xffffffff;
+						for (j = 0; j < first_off; j++)
+							mask >>= 1;
+						*q &= ~mask;
+						*q |= simple_strtoul (tmp,0,16);
+					}
+					buf += 9;
+				} else if ((q == last - 1) && last_cnt
+					   && (last_cnt < 8)) {
+					memset (tmp, '0', 8);
+					copy_from_user (tmp, buf, last_cnt);
+					mask = 0xffffffff;
+					for (j = 0; j < 8 - last_cnt; j++)
+						mask <<= 1;
+					*q &= ~mask;
+					*q |= simple_strtoul (tmp, 0, 16);
+					buf += last_cnt;
+				} else {
+					char tchars[17]; /* XXX yuck... */
+
+					copy_from_user(tchars, buf, 16);
+					*q = simple_strtoul (tchars, 0, 16);
+					buf += 9;
+				}
+			}
+		}
+		if (!forcelen) {
+			if (op->len < i)
+				op->len = i;
+		} else
+			op->len = i;
+		filp->f_pos += count;
+	}
+write_try_string:
+	if (!(op->flag & OPP_BINARY)) {
+		if (!(op->flag & (OPP_QUOTED | OPP_NOTQUOTED))) {
+			char ctmp;
+
+			/* No way, if somebody starts writing from the middle, 
+			 * we don't know whether he uses quotes around or not 
+			 */
+			if (k > 0)
+				return -EINVAL;
+			__get_user(ctmp, buf);
+			if (ctmp == '\'') {
+				op->flag |= OPP_QUOTED;
+				buf++;
+				count--;
+				filp->f_pos++;
+				if (!count) {
+					op->flag |= OPP_STRING;
+					return 1;
+				}
+			} else
+				op->flag |= OPP_NOTQUOTED;
+		}
+		op->flag |= OPP_STRING;
+		if (op->alloclen <= count + filp->f_pos) {
+			b = kmalloc (sizeof (openprom_property)
+				     + 2 * (count + filp->f_pos), GFP_KERNEL);
+			if (!b)
+				return -ENOMEM;
+			memcpy (b, filp->private_data,
+				sizeof (openprom_property)
+				+ strlen (op->name) + op->alloclen);
+			memset (((char *)b) + sizeof (openprom_property)
+				+ strlen (op->name) + op->alloclen, 
+				0, 2*(count - filp->f_pos) - op->alloclen);
+			op = (openprom_property *)b;
+			op->alloclen = 2*(count + filp->f_pos);
+			b = filp->private_data;
+			filp->private_data = (void *)op;
+			kfree (b);
+		}
+		p = op->value + filp->f_pos - ((op->flag & OPP_QUOTED) ? 1 : 0);
+		copy_from_user (p, buf, count);
+		op->flag |= OPP_DIRTY;
+		for (i = 0; i < count; i++, p++)
+			if (*p == '\n') {
+				*p = 0;
+				break;
+			}
+		if (i < count) {
+			op->len = p - op->value;
+			filp->f_pos += i + 1;
+			if ((p > op->value) && (op->flag & OPP_QUOTED)
+			    && (*(p - 1) == '\''))
+				op->len--;
+		} else {
+			if (p - op->value > op->len)
+				op->len = p - op->value;
+			filp->f_pos += count;
+		}
+	}
+	return filp->f_pos - k;
+}
+
+int property_release (struct inode *inode, struct file *filp)
+{
+	openprom_property *op = (openprom_property *)filp->private_data;
+	unsigned long flags;
+	int error;
+	u32 node;
+	
+	if (!op)
+		return 0;
+	node = nodes[(u16)((long)inode->u.generic_ip)].node;
+	if ((u16)((long)inode->u.generic_ip) == aliases) {
+		if ((op->flag & OPP_DIRTY) && (op->flag & OPP_STRING)) {
+			char *p = op->name;
+			int i = (op->value - op->name) - strlen (op->name) - 1;
+			op->value [op->len] = 0;
+			*(op->value - 1) = ' ';
+			if (i) {
+				for (p = op->value - i - 2; p >= op->name; p--)
+					p[i] = *p;
+				p = op->name + i;
+			}
+			memcpy (p - 8, "nvalias ", 8);
+			prom_feval (p - 8);
+		}
+	} else if (op->flag & OPP_DIRTY) {
+		if (op->flag & OPP_STRING) {
+			op->value [op->len] = 0;
+			save_and_cli (flags);
+			error = prom_setprop (node, op->name,
+					      op->value, op->len + 1);
+			restore_flags (flags);
+			if (error <= 0)
+				printk (KERN_WARNING "openpromfs: "
+					"Couldn't write property %s\n",
+					op->name);
+		} else if ((op->flag & OPP_BINARY) || !op->len) {
+			save_and_cli (flags);
+			error = prom_setprop (node, op->name,
+					      op->value, op->len);
+			restore_flags (flags);
+			if (error <= 0)
+				printk (KERN_WARNING "openpromfs: "
+					"Couldn't write property %s\n",
+					op->name);
+		} else {
+			printk (KERN_WARNING "openpromfs: "
+				"Unknown property type of %s\n",
+				op->name);
+		}
+	}
+	kfree (filp->private_data);
+	return 0;
+}
+
+static struct file_operations openpromfs_prop_ops = {
+	NULL,			/* lseek - default */
+	property_read,		/* read */
+	property_write,		/* write - bad */
+	NULL,			/* readdir */
+	NULL,			/* poll - default */
+	NULL,			/* ioctl - default */
+	NULL,			/* mmap */
+	NULL,			/* no special open code */
+	NULL,			/* flush */
+	property_release,	/* no special release code */
+	NULL			/* can't fsync */
+};
+
+static struct inode_operations openpromfs_prop_inode_ops = {
+	&openpromfs_prop_ops,	/* default property file-ops */
+};
+
+static struct file_operations openpromfs_nodenum_ops = {
+	NULL,			/* lseek - default */
+	nodenum_read,		/* read */
+	NULL,			/* write - bad */
+	NULL,			/* readdir */
+	NULL,			/* poll - default */
+	NULL,			/* ioctl - default */
+	NULL,			/* mmap */
+	NULL,			/* no special open code */
+	NULL,			/* flush */
+	NULL,			/* no special release code */
+	NULL			/* can't fsync */
+};
+
+static struct inode_operations openpromfs_nodenum_inode_ops = {
+	&openpromfs_nodenum_ops,/* default .node file-ops */
+};
+
+static struct file_operations openprom_alias_operations = {
+	NULL,			/* lseek - default */
+	NULL,			/* read - bad */
+	NULL,			/* write - bad */
+	openpromfs_readdir,	/* readdir */
+	NULL,			/* poll - default */
+	NULL,			/* ioctl - default */
+	NULL,			/* mmap */
+	NULL,			/* no special open code */
+	NULL,			/* flush */
+	NULL,			/* no special release code */
+	NULL			/* can't fsync */
+};
+
+static struct inode_operations openprom_alias_inode_operations = {
+	&openprom_alias_operations,/* default aliases directory file-ops */
+	openpromfs_create,	/* create */
+	openpromfs_lookup,	/* lookup */
+	NULL,			/* link */
+	openpromfs_unlink,	/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	NULL,			/* readlink */
+	NULL,			/* follow_link */
+	NULL,			/* get_block */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
+	NULL,			/* truncate */
+	NULL,			/* permission */
+	NULL			/* revalidate */
+};
+
+extern struct inode_operations openprom_inode_operations;
+
+static int lookup_children(u16 n, const char * name, int len)
+{
+	int ret;
+	u16 node;
+	for (; n != 0xffff; n = nodes[n].next) {
+		node = nodes[n].child;
+		if (node != 0xffff) {
+			char buffer[128];
+			int i;
+			char *p;
+			
+			while (node != 0xffff) {
+				if (prom_getname (nodes[node].node,
+						  buffer, 128) >= 0) {
+					i = strlen (buffer);
+					if ((len == i)
+					    && !strncmp (buffer, name, len))
+						return NODE2INO(node);
+					p = strchr (buffer, '@');
+					if (p && (len == p - buffer)
+					    && !strncmp (buffer, name, len))
+						return NODE2INO(node);
+				}
+				node = nodes[node].next;
+			}
+		} else
+			continue;
+		ret = lookup_children (nodes[n].child, name, len);
+		if (ret) return ret;
+	}
+	return 0;
+}
+
+static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentry)
+{
+	int ino = 0;
+#define OPFSL_DIR	0
+#define OPFSL_PROPERTY	1
+#define OPFSL_NODENUM	2
+	int type = 0;
+	char buffer[128];
+	char *p;
+	const char *name;
+	u32 n;
+	u16 dirnode;
+	unsigned int len;
+	int i;
+	struct inode *inode;
+	char buffer2[64];
+	
+	inode = NULL;
+	name = dentry->d_name.name;
+	len = dentry->d_name.len;
+	if (name [0] == '.' && len == 5 && !strncmp (name + 1, "node", 4)) {
+		ino = NODEP2INO(NODE(dir->i_ino).first_prop);
+		type = OPFSL_NODENUM;
+	}
+	if (!ino) {
+		u16 node = NODE(dir->i_ino).child;
+		while (node != 0xffff) {
+			if (prom_getname (nodes[node].node, buffer, 128) >= 0) {
+				i = strlen (buffer);
+				if (len == i && !strncmp (buffer, name, len)) {
+					ino = NODE2INO(node);
+					type = OPFSL_DIR;
+					break;
+				}
+				p = strchr (buffer, '@');
+				if (p && (len == p - buffer)
+				    && !strncmp (buffer, name, len)) {
+					ino = NODE2INO(node);
+					type = OPFSL_DIR;
+					break;
+				}
+			}
+			node = nodes[node].next;
+		}
+	}
+	n = NODE(dir->i_ino).node;
+	dirnode = dir->i_ino - OPENPROM_FIRST_INO;
+	if (!ino) {
+		int j = NODEP2INO(NODE(dir->i_ino).first_prop);
+		if (dirnode != aliases) {
+			for (p = prom_firstprop (n, buffer2);
+			     p && *p;
+			     p = prom_nextprop (n, p, buffer2)) {
+				j++;
+				if ((len == strlen (p))
+				    && !strncmp (p, name, len)) {
+					ino = j;
+					type = OPFSL_PROPERTY;
+					break;
+				}
+			}
+		} else {
+			int k;
+			for (k = 0; k < aliases_nodes; k++) {
+				j++;
+				if (alias_names [k]
+				    && (len == strlen (alias_names [k]))
+				    && !strncmp (alias_names [k], name, len)) {
+					ino = j;
+					type = OPFSL_PROPERTY;
+					break;
+				}
+			}
+		}
+	}
+	if (!ino) {
+		ino = lookup_children (NODE(dir->i_ino).child, name, len);
+		if (ino)
+			type = OPFSL_DIR;
+		else
+			return ERR_PTR(-ENOENT);
+	}
+	inode = iget (dir->i_sb, ino);
+	if (!inode)
+		return ERR_PTR(-EINVAL);
+	switch (type) {
+	case OPFSL_DIR:
+		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
+		if (ino == OPENPROM_FIRST_INO + aliases) {
+			inode->i_mode |= S_IWUSR;
+			inode->i_op = &openprom_alias_inode_operations;
+		} else
+			inode->i_op = &openprom_inode_operations;
+		inode->i_nlink = 2;
+		break;
+	case OPFSL_NODENUM:
+		inode->i_mode = S_IFREG | S_IRUGO;
+		inode->i_op = &openpromfs_nodenum_inode_ops;
+		inode->i_nlink = 1;
+		inode->u.generic_ip = (void *)(long)(n);
+		break;
+	case OPFSL_PROPERTY:
+		if ((dirnode == options) && (len == 17)
+		    && !strncmp (name, "security-password", 17))
+			inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
+		else {
+			inode->i_mode = S_IFREG | S_IRUGO;
+			if (dirnode == options || dirnode == aliases) {
+				if (len != 4 || strncmp (name, "name", 4))
+					inode->i_mode |= S_IWUSR;
+			}
+		}
+		inode->i_op = &openpromfs_prop_inode_ops;
+		inode->i_nlink = 1;
+		if (inode->i_size < 0)
+			inode->i_size = 0;
+		inode->u.generic_ip = (void *)(long)(((u16)dirnode) | 
+			(((u16)(ino - NODEP2INO(NODE(dir->i_ino).first_prop) - 1)) << 16));
+		break;
+	}
+
+	inode->i_gid = 0;
+	inode->i_uid = 0;
+
+	d_add(dentry, inode);
+	return NULL;
+}
+
+static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
+{
+	struct inode *inode = filp->f_dentry->d_inode;
+	unsigned int ino;
+	u32 n;
+	int i, j;
+	char buffer[128];
+	u16 node;
+	char *p;
+	char buffer2[64];
+	
+	ino = inode->i_ino;
+	i = filp->f_pos;
+	switch (i) {
+	case 0:
+		if (filldir(dirent, ".", 1, i, ino) < 0) return 0;
+		i++;
+		filp->f_pos++;
+		/* fall thru */
+	case 1:
+		if (filldir(dirent, "..", 2, i, 
+			(NODE(ino).parent == 0xffff) ? 
+			OPENPROM_ROOT_INO : NODE2INO(NODE(ino).parent)) < 0) 
+			return 0;
+		i++;
+		filp->f_pos++;
+		/* fall thru */
+	default:
+		i -= 2;
+		node = NODE(ino).child;
+		while (i && node != 0xffff) {
+			node = nodes[node].next;
+			i--;
+		}
+		while (node != 0xffff) {
+			if (prom_getname (nodes[node].node, buffer, 128) < 0)
+				return 0;
+			if (filldir(dirent, buffer, strlen(buffer),
+				    filp->f_pos, NODE2INO(node)) < 0)
+				return 0;
+			filp->f_pos++;
+			node = nodes[node].next;
+		}
+		j = NODEP2INO(NODE(ino).first_prop);
+		if (!i) {
+			if (filldir(dirent, ".node", 5, filp->f_pos, j) < 0)
+				return 0;
+			filp->f_pos++;
+		} else
+			i--;
+		n = NODE(ino).node;
+		if (ino == OPENPROM_FIRST_INO + aliases) {
+			for (j++; i < aliases_nodes; i++, j++) {
+				if (alias_names [i]) {
+					if (filldir (dirent, alias_names [i], 
+						strlen (alias_names [i]), 
+						filp->f_pos, j) < 0) return 0;
+					filp->f_pos++;
+				}
+			}
+		} else {
+			for (p = prom_firstprop (n, buffer2);
+			     p && *p;
+			     p = prom_nextprop (n, p, buffer2)) {
+				j++;
+				if (i) i--;
+				else {
+					if (filldir(dirent, p, strlen(p),
+						    filp->f_pos, j) < 0)
+						return 0;
+					filp->f_pos++;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+static int openpromfs_create (struct inode *dir, struct dentry *dentry, int mode)
+{
+	char *p;
+	struct inode *inode;
+	
+	if (!dir)
+		return -ENOENT;
+	if (dentry->d_name.len > 256)
+		return -EINVAL;
+	if (aliases_nodes == ALIASES_NNODES)
+		return -EIO;
+	p = kmalloc (dentry->d_name.len + 1, GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+	strncpy (p, dentry->d_name.name, dentry->d_name.len);
+	p [dentry->d_name.len] = 0;
+	alias_names [aliases_nodes++] = p;
+	inode = iget (dir->i_sb,
+			NODEP2INO(NODE(dir->i_ino).first_prop) + aliases_nodes);
+	if (!inode)
+		return -EINVAL;
+	inode->i_mode = S_IFREG | S_IRUGO | S_IWUSR;
+	inode->i_op = &openpromfs_prop_inode_ops;
+	inode->i_nlink = 1;
+	if (inode->i_size < 0) inode->i_size = 0;
+	inode->u.generic_ip = (void *)(long)(((u16)aliases) | 
+			(((u16)(aliases_nodes - 1)) << 16));
+	d_instantiate(dentry, inode);
+	return 0;
+}
+
+static int openpromfs_unlink (struct inode *dir, struct dentry *dentry)
+{
+	unsigned int len;
+	char *p;
+	const char *name;
+	int i;
+	
+	name = dentry->d_name.name;
+	len = dentry->d_name.len;
+	for (i = 0; i < aliases_nodes; i++)
+		if ((strlen (alias_names [i]) == len)
+		    && !strncmp (name, alias_names[i], len)) {
+			char buffer[512];
+			
+			p = alias_names [i];
+			alias_names [i] = NULL;
+			kfree (p);
+			strcpy (buffer, "nvunalias ");
+			memcpy (buffer + 10, name, len);
+			buffer [10 + len] = 0;
+			prom_feval (buffer);
+		}
+	d_delete(dentry);
+	return 0;
+}
+
+/* {{{ init section */
+#ifndef MODULE
+static int __init check_space (u16 n)
+#else
+static int check_space (u16 n)
+#endif
+{
+	unsigned long pages;
+
+	if ((1 << alloced) * PAGE_SIZE < (n + 2) * sizeof(openpromfs_node)) {
+		pages = __get_free_pages (GFP_KERNEL, alloced + 1);
+		if (!pages)
+			return -1;
+
+		if (nodes) {
+			memcpy ((char *)pages, (char *)nodes,
+				(1 << alloced) * PAGE_SIZE);
+			free_pages ((unsigned long)nodes, alloced);
+		}
+		alloced++;
+		nodes = (openpromfs_node *)pages;
+	}
+	return 0;
+}
+
+#ifndef MODULE
+static u16 __init get_nodes (u16 parent, u32 node)
+#else
+static u16 get_nodes (u16 parent, u32 node)
+#endif
+{
+	char *p;
+	u16 n = last_node++, i;
+	char buffer[64];
+
+	if (check_space (n) < 0)
+		return 0xffff;
+	nodes[n].parent = parent;
+	nodes[n].node = node;
+	nodes[n].next = 0xffff;
+	nodes[n].child = 0xffff;
+	nodes[n].first_prop = first_prop++;
+	if (!parent) {
+		char buffer[8];
+		int j;
+		
+		if ((j = prom_getproperty (node, "name", buffer, 8)) >= 0) {
+		    buffer[j] = 0;
+		    if (!strcmp (buffer, "options"))
+			options = n;
+		    else if (!strcmp (buffer, "aliases"))
+		        aliases = n;
+		}
+	}
+	if (n != aliases)
+		for (p = prom_firstprop (node, buffer);
+		     p && p != (char *)-1 && *p;
+		     p = prom_nextprop (node, p, buffer))
+			first_prop++;
+	else {
+		char *q;
+		for (p = prom_firstprop (node, buffer);
+		     p && p != (char *)-1 && *p;
+		     p = prom_nextprop (node, p, buffer)) {
+			if (aliases_nodes == ALIASES_NNODES)
+				break;
+			for (i = 0; i < aliases_nodes; i++)
+				if (!strcmp (p, alias_names [i]))
+					break;
+			if (i < aliases_nodes)
+				continue;
+			q = kmalloc (strlen (p) + 1, GFP_KERNEL);
+			if (!q)
+				return 0xffff;
+			strcpy (q, p);
+			alias_names [aliases_nodes++] = q;
+		}
+		first_prop += ALIASES_NNODES;
+	}
+	node = prom_getchild (node);
+	if (node) {
+		parent = get_nodes (n, node);
+		if (parent == 0xffff)
+			return 0xffff;
+		nodes[n].child = parent;
+		while ((node = prom_getsibling (node)) != 0) {
+			i = get_nodes (n, node);
+			if (i == 0xffff)
+				return 0xffff;
+			nodes[parent].next = i;
+			parent = i;
+		}
+	}
+	return n;
+}
+
+
+static struct file_operations openprom_operations = {
+	NULL,			/* lseek - default */
+	NULL,			/* read - bad */
+	NULL,			/* write - bad */
+	openpromfs_readdir,	/* readdir */
+};
+
+static struct inode_operations openprom_inode_operations = {
+	&openprom_operations,/* default net directory file-ops */
+	NULL,			/* create */
+	openpromfs_lookup,	/* lookup */
+};
+
+static void openprom_read_inode(struct inode * inode)
+{
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	if (inode->i_ino == OPENPROM_ROOT_INO) {
+		inode->i_op = &openprom_inode_operations;
+		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
+	}
+}
+
+static void openprom_put_super(struct super_block *sb)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+static int openprom_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+{
+	struct statfs tmp;
+
+	tmp.f_type = OPENPROM_SUPER_MAGIC;
+	tmp.f_bsize = PAGE_SIZE/sizeof(long);	/* ??? */
+	tmp.f_blocks = 0;
+	tmp.f_bfree = 0;
+	tmp.f_bavail = 0;
+	tmp.f_files = 0;
+	tmp.f_ffree = 0;
+	tmp.f_namelen = NAME_MAX;
+	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
+static struct super_operations openprom_sops = { 
+	openprom_read_inode,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	openprom_put_super,
+	NULL,
+	openprom_statfs,
+	NULL
+};
+
+struct super_block *openprom_read_super(struct super_block *s,void *data, 
+				    int silent)
+{
+	struct inode * root_inode;
+
+	MOD_INC_USE_COUNT;
+	lock_super(s);
+	s->s_blocksize = 1024;
+	s->s_blocksize_bits = 10;
+	s->s_magic = OPENPROM_SUPER_MAGIC;
+	s->s_op = &openprom_sops;
+	root_inode = iget(s, OPENPROM_ROOT_INO);
+	if (!root_inode)
+		goto out_no_root;
+	s->s_root = d_alloc_root(root_inode);
+	if (!s->s_root)
+		goto out_no_root;
+	unlock_super(s);
+	return s;
+
+out_no_root:
+	printk("openprom_read_super: get root inode failed\n");
+	iput(root_inode);
+	s->s_dev = 0;
+	unlock_super(s);
+	return NULL;
+}
+
+static struct file_system_type openprom_fs_type = {
+	"openpromfs",
+	0,
+	openprom_read_super,
+	NULL
+};
+
+static int init_openprom_fs(void)
+{
+	nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0);
+	if (!nodes) {
+		printk (KERN_WARNING "openpromfs: can't get free page\n");
+		return -EIO;
+	}
+	if (get_nodes (0xffff, prom_root_node) == 0xffff) {
+		printk (KERN_WARNING "openpromfs: couldn't setup tree\n");
+		return -EIO;
+	}
+	nodes[last_node].first_prop = first_prop;
+	return register_filesystem(&openprom_fs_type);
+}
+
+#ifdef MODULE
+
+EXPORT_NO_SYMBOLS;
+
+int init_module (void)
+{
+	return init_openprom_fs();
+}
+
+#else
+
+void __init openpromfs_init (void)
+{
+	init_openprom_fs();
+}
+#endif
+
+#ifdef MODULE
+void cleanup_module (void)
+{
+	int i;
+	unregister_filesystem(&openprom_fs_type);
+	free_pages ((unsigned long)nodes, alloced);
+	for (i = 0; i < aliases_nodes; i++)
+		if (alias_names [i])
+			kfree (alias_names [i]);
+	nodes = NULL;
+}
+#endif
diff -u --recursive --new-file v2.3.34/linux/fs/proc/Makefile linux/fs/proc/Makefile
--- v2.3.34/linux/fs/proc/Makefile	Tue Nov 23 22:42:21 1999
+++ linux/fs/proc/Makefile	Mon Dec 20 22:05:10 1999
@@ -16,16 +16,6 @@
 OX_OBJS  := procfs_syms.o
 M_OBJS   := 
 
-ifeq ($(CONFIG_SUN_OPENPROMFS),y)
-O_OBJS += openpromfs.o
-OX_OBJS  := openprom-dev.o
-else
-  ifeq ($(CONFIG_SUN_OPENPROMFS),m)
-  M_OBJS += openpromfs.o
-  OX_OBJS  := openprom-dev.o
-  endif
-endif
-
 ifeq ($(CONFIG_PROC_DEVICETREE),y)
 O_OBJS += proc_devtree.o
 endif
diff -u --recursive --new-file v2.3.34/linux/fs/proc/base.c linux/fs/proc/base.c
--- v2.3.34/linux/fs/proc/base.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/proc/base.c	Fri Dec 24 10:37:09 1999
@@ -513,7 +513,7 @@
   E(PROC_PID_CMDLINE,	"cmdline",	S_IFREG|S_IRUGO),
   E(PROC_PID_STAT,	"stat",		S_IFREG|S_IRUGO),
   E(PROC_PID_STATM,	"statm",	S_IFREG|S_IRUGO),
-#ifdef SMP
+#ifdef __SMP__
   E(PROC_PID_CPU,	"cpu",		S_IFREG|S_IRUGO),
 #endif
 #if CONFIG_AP1000
@@ -865,7 +865,7 @@
 		case PROC_PID_MAPS:
 			inode->i_op = &proc_maps_inode_operations;
 			break;
-#ifdef SMP
+#ifdef __SMP__
 		case PROC_PID_CPU:
 			inode->i_op = &proc_info_inode_operations;
 			inode->u.proc_i.op.proc_read = proc_pid_cpu;
diff -u --recursive --new-file v2.3.34/linux/fs/proc/kcore.c linux/fs/proc/kcore.c
--- v2.3.34/linux/fs/proc/kcore.c	Tue Nov 23 22:42:21 1999
+++ linux/fs/proc/kcore.c	Mon Dec 20 22:05:10 1999
@@ -119,7 +119,7 @@
 
 extern char saved_command_line[];
 
-static size_t get_kcore_size(int *num_vma, int *elf_buflen)
+static size_t get_kcore_size(int *num_vma, size_t *elf_buflen)
 {
 	size_t try, size = 0;
 	struct vm_struct *m;
diff -u --recursive --new-file v2.3.34/linux/fs/proc/openprom-dev.c linux/fs/proc/openprom-dev.c
--- v2.3.34/linux/fs/proc/openprom-dev.c	Tue Nov 23 22:42:21 1999
+++ linux/fs/proc/openprom-dev.c	Wed Dec 31 16:00:00 1969
@@ -1,46 +0,0 @@
-/*
- *  linux/fs/proc/openprom-dev.c
- *
- *  handling of devices attached to openpromfs.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/module.h>
-
-struct openpromfs_dev *openprom_devices = NULL;
-static ino_t openpromdev_ino = PROC_OPENPROMD_FIRST;
-
-int proc_openprom_regdev(struct openpromfs_dev *d)
-{
-	if (openpromdev_ino == PROC_OPENPROMD_FIRST + PROC_NOPENPROMD)
-		return -1;
-	d->next = openprom_devices;
-	d->inode = openpromdev_ino++;
-	openprom_devices = d;
-	return 0;
-}
-
-int proc_openprom_unregdev(struct openpromfs_dev *d)
-{
-	if (d == openprom_devices) {
-		openprom_devices = d->next;
-	} else if (!openprom_devices)
-		return -1;
-	else {
-		struct openpromfs_dev *p;
-		
-		for (p = openprom_devices; p->next != d && p->next; p = p->next);
-		if (!p->next) return -1;
-		p->next = d->next;
-	}
-	return 0;
-}
-
-#if defined(CONFIG_SUN_OPENPROMFS_MODULE)
-EXPORT_SYMBOL(openprom_devices);
-#endif
diff -u --recursive --new-file v2.3.34/linux/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c
--- v2.3.34/linux/fs/proc/openpromfs.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/proc/openpromfs.c	Wed Dec 31 16:00:00 1969
@@ -1,1200 +0,0 @@
-/* $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)
- * Copyright (C) 1998      Eddie C. Dost  (ecd@skynet.be)
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/fs.h>
-#include <linux/proc_fs.h>
-#include <linux/init.h>
-
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/uaccess.h>
-
-#define ALIASES_NNODES 64
-
-typedef struct {
-	u16	parent;
-	u16	next;
-	u16	child;
-	u16	first_prop;
-	u32	node;
-} openpromfs_node;
-
-typedef struct {
-#define OPP_STRING	0x10
-#define OPP_STRINGLIST	0x20
-#define OPP_BINARY	0x40
-#define OPP_HEXSTRING	0x80
-#define OPP_DIRTY	0x01
-#define OPP_QUOTED	0x02
-#define OPP_NOTQUOTED	0x04
-#define OPP_ASCIIZ	0x08
-	u32	flag;
-	u32	alloclen;
-	u32	len;
-	char	*value;
-	char	name[8];
-} openprom_property;
-
-static openpromfs_node *nodes = NULL;
-static int alloced = 0;
-static u16 last_node = 0;
-static u16 first_prop = 0;
-static u16 options = 0xffff;
-static u16 aliases = 0xffff;
-static int aliases_nodes = 0;
-static char *alias_names [ALIASES_NNODES];
-extern struct openpromfs_dev *openprom_devices;
-
-#define NODE(ino) nodes[ino - PROC_OPENPROM_FIRST]
-#define NODE2INO(node) (node + PROC_OPENPROM_FIRST)
-#define NODEP2INO(no) (no + PROC_OPENPROM_FIRST + last_node)
-
-static int openpromfs_create (struct inode *, struct dentry *, int);
-static int openpromfs_readdir(struct file *, void *, filldir_t);
-static struct dentry *openpromfs_lookup(struct inode *, struct dentry *dentry);
-static int openpromfs_unlink (struct inode *, struct dentry *dentry);
-
-static ssize_t nodenum_read(struct file *file, char *buf,
-			    size_t count, loff_t *ppos)
-{
-	struct inode *inode = file->f_dentry->d_inode;
-	char buffer[10];
-	
-	if (count < 0 || !inode->u.generic_ip)
-		return -EINVAL;
-	sprintf (buffer, "%8.8x\n", (u32)(long)(inode->u.generic_ip));
-	if (file->f_pos >= 9)
-		return 0;
-	if (count > 9 - file->f_pos)
-		count = 9 - file->f_pos;
-	copy_to_user(buf, buffer + file->f_pos, count);
-	file->f_pos += count;
-	return count;
-}
-
-static ssize_t property_read(struct file *filp, char *buf,
-			     size_t count, loff_t *ppos)
-{
-	struct inode *inode = filp->f_dentry->d_inode;
-	int i, j, k;
-	u32 node;
-	char *p, *s;
-	u32 *q;
-	openprom_property *op;
-	char buffer[64];
-	
-	if (filp->f_pos >= 0xffffff)
-		return -EINVAL;
-	if (!filp->private_data) {
-		node = nodes[(u16)((long)inode->u.generic_ip)].node;
-		i = ((u32)(long)inode->u.generic_ip) >> 16;
-		if ((u16)((long)inode->u.generic_ip) == aliases) {
-			if (i >= aliases_nodes)
-				p = 0;
-			else
-				p = alias_names [i];
-		} else
-			for (p = prom_firstprop (node, buffer);
-			     i && p && *p;
-			     p = prom_nextprop (node, p, buffer), i--)
-				/* nothing */ ;
-		if (!p || !*p)
-			return -EIO;
-		i = prom_getproplen (node, p);
-		if (i < 0) {
-			if ((u16)((long)inode->u.generic_ip) == aliases)
-				i = 0;
-			else
-				return -EIO;
-		}
-		k = i;
-		if (i < 64) i = 64;
-		filp->private_data = kmalloc (sizeof (openprom_property)
-					      + (j = strlen (p)) + 2 * i,
-					      GFP_KERNEL);
-		if (!filp->private_data)
-			return -ENOMEM;
-		op = (openprom_property *)filp->private_data;
-		op->flag = 0;
-		op->alloclen = 2 * i;
-		strcpy (op->name, p);
-		op->value = (char *)(((unsigned long)(op->name + j + 4)) & ~3);
-		op->len = k;
-		if (k && prom_getproperty (node, p, op->value, i) < 0)
-			return -EIO;
-		op->value [k] = 0;
-		if (k) {
-			for (s = 0, p = op->value; p < op->value + k; p++) {
-				if ((*p >= ' ' && *p <= '~') || *p == '\n') {
-					op->flag |= OPP_STRING;
-					s = p;
-					continue;
-				}
-				if (p > op->value && !*p && s == p - 1) {
-					if (p < op->value + k - 1)
-						op->flag |= OPP_STRINGLIST;
-					else
-						op->flag |= OPP_ASCIIZ;
-					continue;
-				}
-				if (k == 1 && !*p) {
-					op->flag |= (OPP_STRING|OPP_ASCIIZ);
-					break;
-				}
-				op->flag &= ~(OPP_STRING|OPP_STRINGLIST);
-				if (k & 3)
-					op->flag |= OPP_HEXSTRING;
-				else
-					op->flag |= OPP_BINARY;
-				break;
-			}
-			if (op->flag & OPP_STRINGLIST)
-				op->flag &= ~(OPP_STRING);
-			if (op->flag & OPP_ASCIIZ)
-				op->len--;
-		}
-	} else
-		op = (openprom_property *)filp->private_data;
-	if (!count || !(op->len || (op->flag & OPP_ASCIIZ)))
-		return 0;
-	if (op->flag & OPP_STRINGLIST) {
-		for (k = 0, p = op->value; p < op->value + op->len; p++)
-			if (!*p)
-				k++;
-		i = op->len + 4 * k + 3;
-	} else if (op->flag & OPP_STRING) {
-		i = op->len + 3;
-	} else if (op->flag & OPP_BINARY) {
-		i = (op->len * 9) >> 2;
-	} else {
-		i = (op->len << 1) + 1;
-	}
-	k = filp->f_pos;
-	if (k >= i) return 0;
-	if (count > i - k) count = i - k;
-	if (op->flag & OPP_STRING) {
-		if (!k) {
-			__put_user('\'', buf);
-			k++;
-			count--;
-		}
-
-		if (k + count >= i - 2)
-			j = i - 2 - k;
-		else
-			j = count;
-
-		if (j >= 0) {
-			copy_to_user(buf + k - filp->f_pos,
-				     op->value + k - 1, j);
-			count -= j;
-			k += j;
-		}
-
-		if (count)
-			__put_user('\'', &buf [k++ - filp->f_pos]);
-		if (count > 1)
-			__put_user('\n', &buf [k++ - filp->f_pos]);
-
-	} else if (op->flag & OPP_STRINGLIST) {
-		char *tmp;
-
-		tmp = kmalloc (i, GFP_KERNEL);
-		if (!tmp)
-			return -ENOMEM;
-
-		s = tmp;
-		*s++ = '\'';
-		for (p = op->value; p < op->value + op->len; p++) {
-			if (!*p) {
-				strcpy(s, "' + '");
-				s += 5;
-				continue;
-			}
-			*s++ = *p;
-		}
-		strcpy(s, "'\n");
-
-		copy_to_user(buf, tmp + k, count);
-
-		kfree(tmp);
-		k += count;
-
-	} else if (op->flag & OPP_BINARY) {
-		char buffer[10];
-		u32 *first, *last;
-		int first_off, last_cnt;
-
-		first = ((u32 *)op->value) + k / 9;
-		first_off = k % 9;
-		last = ((u32 *)op->value) + (k + count - 1) / 9;
-		last_cnt = (k + count) % 9;
-		if (!last_cnt) last_cnt = 9;
-
-		if (first == last) {
-			sprintf (buffer, "%08x.", *first);
-			copy_to_user (buf, buffer + first_off, last_cnt - first_off);
-			buf += last_cnt - first_off;
-		} else {		
-			for (q = first; q <= last; q++) {
-				sprintf (buffer, "%08x.", *q);
-				if (q == first) {
-					copy_to_user (buf, buffer + first_off,
-						      9 - first_off);
-					buf += 9 - first_off;
-				} else if (q == last) {
-					copy_to_user (buf, buffer, last_cnt);
-					buf += last_cnt;
-				} else {
-					copy_to_user (buf, buffer, 9);
-					buf += 9;
-				}
-			}
-		}
-
-		if (last == (u32 *)(op->value + op->len - 4) && last_cnt == 9)
-			__put_user('\n', (buf - 1));
-
-		k += count;
-
-	} else if (op->flag & OPP_HEXSTRING) {
-		char buffer[2];
-
-		if ((k < i - 1) && (k & 1)) {
-			sprintf (buffer, "%02x", *(op->value + (k >> 1)));
-			__put_user(buffer[1], &buf[k++ - filp->f_pos]);
-			count--;
-		}
-
-		for (; (count > 1) && (k < i - 1); k += 2) {
-			sprintf (buffer, "%02x", *(op->value + (k >> 1)));
-			copy_to_user (buf + k - filp->f_pos, buffer, 2);
-			count -= 2;
-		}
-
-		if (count && (k < i - 1)) {
-			sprintf (buffer, "%02x", *(op->value + (k >> 1)));
-			__put_user(buffer[0], &buf[k++ - filp->f_pos]);
-			count--;
-		}
-
-		if (count)
-			__put_user('\n', &buf [k++ - filp->f_pos]);
-	}
-	count = k - filp->f_pos;
-	filp->f_pos = k;
-	return count;
-}
-
-static ssize_t property_write(struct file *filp, const char *buf,
-			      size_t count, loff_t *ppos)
-{
-	int i, j, k;
-	char *p;
-	u32 *q;
-	void *b;
-	openprom_property *op;
-	
-	if (filp->f_pos >= 0xffffff)
-		return -EINVAL;
-	if (!filp->private_data) {
-		i = property_read (filp, NULL, 0, 0);
-		if (i)
-			return i;
-	}
-	k = filp->f_pos;
-	op = (openprom_property *)filp->private_data;
-	if (!(op->flag & OPP_STRING)) {
-		u32 *first, *last;
-		int first_off, last_cnt;
-		u32 mask, mask2;
-		char tmp [9];
-		int forcelen = 0;
-		
-		j = k % 9;
-		for (i = 0; i < count; i++, j++) {
-			if (j == 9) j = 0;
-			if (!j) {
-				char ctmp;
-				__get_user(ctmp, &buf[i]);
-				if (ctmp != '.') {
-					if (ctmp != '\n') {
-						if (op->flag & OPP_BINARY)
-							return -EINVAL;
-						else
-							goto write_try_string;
-					} else {
-						count = i + 1;
-						forcelen = 1;
-						break;
-					}
-				}
-			} else {
-				char ctmp;
-				__get_user(ctmp, &buf[i]);
-				if (ctmp < '0' || 
-				    (ctmp > '9' && ctmp < 'A') ||
-				    (ctmp > 'F' && ctmp < 'a') ||
-				    ctmp > 'f') {
-					if (op->flag & OPP_BINARY)
-						return -EINVAL;
-					else
-						goto write_try_string;
-				}
-			}
-		}
-		op->flag |= OPP_BINARY;
-		tmp [8] = 0;
-		i = ((count + k + 8) / 9) << 2;
-		if (op->alloclen <= i) {
-			b = kmalloc (sizeof (openprom_property) + 2 * i,
-				     GFP_KERNEL);
-			if (!b)
-				return -ENOMEM;
-			memcpy (b, filp->private_data,
-				sizeof (openprom_property)
-				+ strlen (op->name) + op->alloclen);
-			memset (((char *)b) + sizeof (openprom_property)
-				+ strlen (op->name) + op->alloclen, 
-				0, 2 * i - op->alloclen);
-			op = (openprom_property *)b;
-			op->alloclen = 2*i;
-			b = filp->private_data;
-			filp->private_data = (void *)op;
-			kfree (b);
-		}
-		first = ((u32 *)op->value) + (k / 9);
-		first_off = k % 9;
-		last = (u32 *)(op->value + i);
-		last_cnt = (k + count) % 9;
-		if (first + 1 == last) {
-			memset (tmp, '0', 8);
-			copy_from_user (tmp + first_off, buf,
-					(count + first_off > 8) ? 8 - first_off : count);
-			mask = 0xffffffff;
-			mask2 = 0xffffffff;
-			for (j = 0; j < first_off; j++)
-				mask >>= 1;
-			for (j = 8 - count - first_off; j > 0; j--)
-				mask2 <<= 1;
-			mask &= mask2;
-			if (mask) {
-				*first &= ~mask;
-				*first |= simple_strtoul (tmp, 0, 16);
-				op->flag |= OPP_DIRTY;
-			}
-		} else {
-			op->flag |= OPP_DIRTY;
-			for (q = first; q < last; q++) {
-				if (q == first) {
-					if (first_off < 8) {
-						memset (tmp, '0', 8);
-						copy_from_user (tmp + first_off, buf,
-								8 - first_off);
-						mask = 0xffffffff;
-						for (j = 0; j < first_off; j++)
-							mask >>= 1;
-						*q &= ~mask;
-						*q |= simple_strtoul (tmp,0,16);
-					}
-					buf += 9;
-				} else if ((q == last - 1) && last_cnt
-					   && (last_cnt < 8)) {
-					memset (tmp, '0', 8);
-					copy_from_user (tmp, buf, last_cnt);
-					mask = 0xffffffff;
-					for (j = 0; j < 8 - last_cnt; j++)
-						mask <<= 1;
-					*q &= ~mask;
-					*q |= simple_strtoul (tmp, 0, 16);
-					buf += last_cnt;
-				} else {
-					char tchars[17]; /* XXX yuck... */
-
-					copy_from_user(tchars, buf, 16);
-					*q = simple_strtoul (tchars, 0, 16);
-					buf += 9;
-				}
-			}
-		}
-		if (!forcelen) {
-			if (op->len < i)
-				op->len = i;
-		} else
-			op->len = i;
-		filp->f_pos += count;
-	}
-write_try_string:
-	if (!(op->flag & OPP_BINARY)) {
-		if (!(op->flag & (OPP_QUOTED | OPP_NOTQUOTED))) {
-			char ctmp;
-
-			/* No way, if somebody starts writing from the middle, 
-			 * we don't know whether he uses quotes around or not 
-			 */
-			if (k > 0)
-				return -EINVAL;
-			__get_user(ctmp, buf);
-			if (ctmp == '\'') {
-				op->flag |= OPP_QUOTED;
-				buf++;
-				count--;
-				filp->f_pos++;
-				if (!count) {
-					op->flag |= OPP_STRING;
-					return 1;
-				}
-			} else
-				op->flag |= OPP_NOTQUOTED;
-		}
-		op->flag |= OPP_STRING;
-		if (op->alloclen <= count + filp->f_pos) {
-			b = kmalloc (sizeof (openprom_property)
-				     + 2 * (count + filp->f_pos), GFP_KERNEL);
-			if (!b)
-				return -ENOMEM;
-			memcpy (b, filp->private_data,
-				sizeof (openprom_property)
-				+ strlen (op->name) + op->alloclen);
-			memset (((char *)b) + sizeof (openprom_property)
-				+ strlen (op->name) + op->alloclen, 
-				0, 2*(count - filp->f_pos) - op->alloclen);
-			op = (openprom_property *)b;
-			op->alloclen = 2*(count + filp->f_pos);
-			b = filp->private_data;
-			filp->private_data = (void *)op;
-			kfree (b);
-		}
-		p = op->value + filp->f_pos - ((op->flag & OPP_QUOTED) ? 1 : 0);
-		copy_from_user (p, buf, count);
-		op->flag |= OPP_DIRTY;
-		for (i = 0; i < count; i++, p++)
-			if (*p == '\n') {
-				*p = 0;
-				break;
-			}
-		if (i < count) {
-			op->len = p - op->value;
-			filp->f_pos += i + 1;
-			if ((p > op->value) && (op->flag & OPP_QUOTED)
-			    && (*(p - 1) == '\''))
-				op->len--;
-		} else {
-			if (p - op->value > op->len)
-				op->len = p - op->value;
-			filp->f_pos += count;
-		}
-	}
-	return filp->f_pos - k;
-}
-
-int property_release (struct inode *inode, struct file *filp)
-{
-	openprom_property *op = (openprom_property *)filp->private_data;
-	unsigned long flags;
-	int error;
-	u32 node;
-	
-	if (!op)
-		return 0;
-	node = nodes[(u16)((long)inode->u.generic_ip)].node;
-	if ((u16)((long)inode->u.generic_ip) == aliases) {
-		if ((op->flag & OPP_DIRTY) && (op->flag & OPP_STRING)) {
-			char *p = op->name;
-			int i = (op->value - op->name) - strlen (op->name) - 1;
-			op->value [op->len] = 0;
-			*(op->value - 1) = ' ';
-			if (i) {
-				for (p = op->value - i - 2; p >= op->name; p--)
-					p[i] = *p;
-				p = op->name + i;
-			}
-			memcpy (p - 8, "nvalias ", 8);
-			prom_feval (p - 8);
-		}
-	} else if (op->flag & OPP_DIRTY) {
-		if (op->flag & OPP_STRING) {
-			op->value [op->len] = 0;
-			save_and_cli (flags);
-			error = prom_setprop (node, op->name,
-					      op->value, op->len + 1);
-			restore_flags (flags);
-			if (error <= 0)
-				printk (KERN_WARNING "/proc/openprom: "
-					"Couldn't write property %s\n",
-					op->name);
-		} else if ((op->flag & OPP_BINARY) || !op->len) {
-			save_and_cli (flags);
-			error = prom_setprop (node, op->name,
-					      op->value, op->len);
-			restore_flags (flags);
-			if (error <= 0)
-				printk (KERN_WARNING "/proc/openprom: "
-					"Couldn't write property %s\n",
-					op->name);
-		} else {
-			printk (KERN_WARNING "/proc/openprom: "
-				"Unknown property type of %s\n",
-				op->name);
-		}
-	}
-	kfree (filp->private_data);
-	return 0;
-}
-
-static struct file_operations openpromfs_prop_ops = {
-	NULL,			/* lseek - default */
-	property_read,		/* read */
-	property_write,		/* write - bad */
-	NULL,			/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	property_release,	/* no special release code */
-	NULL			/* can't fsync */
-};
-
-static struct inode_operations openpromfs_prop_inode_ops = {
-	&openpromfs_prop_ops,	/* default property file-ops */
-};
-
-static struct file_operations openpromfs_nodenum_ops = {
-	NULL,			/* lseek - default */
-	nodenum_read,		/* read */
-	NULL,			/* write - bad */
-	NULL,			/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* can't fsync */
-};
-
-static struct inode_operations openpromfs_nodenum_inode_ops = {
-	&openpromfs_nodenum_ops,/* default .node file-ops */
-};
-
-static struct file_operations openprom_alias_operations = {
-	NULL,			/* lseek - default */
-	NULL,			/* read - bad */
-	NULL,			/* write - bad */
-	openpromfs_readdir,	/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-	NULL,			/* flush */
-	NULL,			/* no special release code */
-	NULL			/* can't fsync */
-};
-
-static struct inode_operations openprom_alias_inode_operations = {
-	&openprom_alias_operations,/* default aliases directory file-ops */
-	openpromfs_create,	/* create */
-	openpromfs_lookup,	/* lookup */
-	NULL,			/* link */
-	openpromfs_unlink,	/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
-};
-
-extern struct inode_operations openprom_inode_operations;
-
-static int lookup_children(u16 n, const char * name, int len)
-{
-	int ret;
-	u16 node;
-	for (; n != 0xffff; n = nodes[n].next) {
-		node = nodes[n].child;
-		if (node != 0xffff) {
-			char buffer[128];
-			int i;
-			char *p;
-			
-			while (node != 0xffff) {
-				if (prom_getname (nodes[node].node,
-						  buffer, 128) >= 0) {
-					i = strlen (buffer);
-					if ((len == i)
-					    && !strncmp (buffer, name, len))
-						return NODE2INO(node);
-					p = strchr (buffer, '@');
-					if (p && (len == p - buffer)
-					    && !strncmp (buffer, name, len))
-						return NODE2INO(node);
-				}
-				node = nodes[node].next;
-			}
-		} else
-			continue;
-		ret = lookup_children (nodes[n].child, name, len);
-		if (ret) return ret;
-	}
-	return 0;
-}
-
-static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentry)
-{
-	int ino = 0;
-#define OPFSL_DIR	0
-#define OPFSL_PROPERTY	1
-#define OPFSL_NODENUM	2
-#define OPFSL_DEVICE	3
-	int type = 0;
-	char buffer[128];
-	char *p;
-	const char *name;
-	u32 n;
-	u16 dirnode;
-	unsigned int len;
-	int i;
-	struct inode *inode;
-	struct openpromfs_dev *d = NULL;
-	char buffer2[64];
-	
-	inode = NULL;
-	name = dentry->d_name.name;
-	len = dentry->d_name.len;
-	if (name [0] == '.' && len == 5 && !strncmp (name + 1, "node", 4)) {
-		ino = NODEP2INO(NODE(dir->i_ino).first_prop);
-		type = OPFSL_NODENUM;
-	}
-	if (!ino) {
-		u16 node = NODE(dir->i_ino).child;
-		while (node != 0xffff) {
-			if (prom_getname (nodes[node].node, buffer, 128) >= 0) {
-				i = strlen (buffer);
-				if (len == i && !strncmp (buffer, name, len)) {
-					ino = NODE2INO(node);
-					type = OPFSL_DIR;
-					break;
-				}
-				p = strchr (buffer, '@');
-				if (p && (len == p - buffer)
-				    && !strncmp (buffer, name, len)) {
-					ino = NODE2INO(node);
-					type = OPFSL_DIR;
-					break;
-				}
-			}
-			node = nodes[node].next;
-		}
-	}
-	n = NODE(dir->i_ino).node;
-	dirnode = dir->i_ino - PROC_OPENPROM_FIRST;
-	if (!ino) {
-		int j = NODEP2INO(NODE(dir->i_ino).first_prop);
-		if (dirnode != aliases) {
-			for (p = prom_firstprop (n, buffer2);
-			     p && *p;
-			     p = prom_nextprop (n, p, buffer2)) {
-				j++;
-				if ((len == strlen (p))
-				    && !strncmp (p, name, len)) {
-					ino = j;
-					type = OPFSL_PROPERTY;
-					break;
-				}
-			}
-		} else {
-			int k;
-			for (k = 0; k < aliases_nodes; k++) {
-				j++;
-				if (alias_names [k]
-				    && (len == strlen (alias_names [k]))
-				    && !strncmp (alias_names [k], name, len)) {
-					ino = j;
-					type = OPFSL_PROPERTY;
-					break;
-				}
-			}
-		}
-	}
-	if (!ino) {
-		for (d = openprom_devices; d; d = d->next)
-			if ((d->node == n) && (strlen (d->name) == len)
-			    && !strncmp (d->name, name, len)) {
-				ino = d->inode;
-				type = OPFSL_DEVICE;
-				break;
-			}
-	}
-	if (!ino) {
-		ino = lookup_children (NODE(dir->i_ino).child, name, len);
-		if (ino)
-			type = OPFSL_DIR;
-		else
-			return ERR_PTR(-ENOENT);
-	}
-	inode = iget (dir->i_sb, ino, 0);
-	if (!inode)
-		return ERR_PTR(-EINVAL);
-	switch (type) {
-	case OPFSL_DIR:
-		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
-		if (ino == PROC_OPENPROM_FIRST + aliases) {
-			inode->i_mode |= S_IWUSR;
-			inode->i_op = &openprom_alias_inode_operations;
-		} else
-			inode->i_op = &openprom_inode_operations;
-		inode->i_nlink = 2;
-		break;
-	case OPFSL_NODENUM:
-		inode->i_mode = S_IFREG | S_IRUGO;
-		inode->i_op = &openpromfs_nodenum_inode_ops;
-		inode->i_nlink = 1;
-		inode->u.generic_ip = (void *)(long)(n);
-		break;
-	case OPFSL_PROPERTY:
-		if ((dirnode == options) && (len == 17)
-		    && !strncmp (name, "security-password", 17))
-			inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
-		else {
-			inode->i_mode = S_IFREG | S_IRUGO;
-			if (dirnode == options || dirnode == aliases) {
-				if (len != 4 || strncmp (name, "name", 4))
-					inode->i_mode |= S_IWUSR;
-			}
-		}
-		inode->i_op = &openpromfs_prop_inode_ops;
-		inode->i_nlink = 1;
-		if (inode->i_size < 0)
-			inode->i_size = 0;
-		inode->u.generic_ip = (void *)(long)(((u16)dirnode) | 
-			(((u16)(ino - NODEP2INO(NODE(dir->i_ino).first_prop) - 1)) << 16));
-		break;
-	case OPFSL_DEVICE:
-		init_special_inode(d->mode, kdev_to_nr(d->rdev));
-	}		
-
-	inode->i_gid = 0;
-	inode->i_uid = 0;
-
-	d_add(dentry, inode);
-	return NULL;
-}
-
-static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
-{
-	struct inode *inode = filp->f_dentry->d_inode;
-	unsigned int ino;
-	u32 n;
-	int i, j;
-	char buffer[128];
-	u16 node;
-	char *p;
-	struct openpromfs_dev *d;
-	char buffer2[64];
-	
-	ino = inode->i_ino;
-	i = filp->f_pos;
-	switch (i) {
-	case 0:
-		if (filldir(dirent, ".", 1, i, ino) < 0) return 0;
-		i++;
-		filp->f_pos++;
-		/* fall thru */
-	case 1:
-		if (filldir(dirent, "..", 2, i, 
-			(NODE(ino).parent == 0xffff) ? 
-			PROC_ROOT_INO : NODE2INO(NODE(ino).parent)) < 0) 
-			return 0;
-		i++;
-		filp->f_pos++;
-		/* fall thru */
-	default:
-		i -= 2;
-		node = NODE(ino).child;
-		while (i && node != 0xffff) {
-			node = nodes[node].next;
-			i--;
-		}
-		while (node != 0xffff) {
-			if (prom_getname (nodes[node].node, buffer, 128) < 0)
-				return 0;
-			if (filldir(dirent, buffer, strlen(buffer),
-				    filp->f_pos, NODE2INO(node)) < 0)
-				return 0;
-			filp->f_pos++;
-			node = nodes[node].next;
-		}
-		j = NODEP2INO(NODE(ino).first_prop);
-		if (!i) {
-			if (filldir(dirent, ".node", 5, filp->f_pos, j) < 0)
-				return 0;
-			filp->f_pos++;
-		} else
-			i--;
-		n = NODE(ino).node;
-		if (ino == PROC_OPENPROM_FIRST + aliases) {
-			for (j++; i < aliases_nodes; i++, j++) {
-				if (alias_names [i]) {
-					if (filldir (dirent, alias_names [i], 
-						strlen (alias_names [i]), 
-						filp->f_pos, j) < 0) return 0;
-					filp->f_pos++;
-				}
-			}
-		} else {
-			for (p = prom_firstprop (n, buffer2);
-			     p && *p;
-			     p = prom_nextprop (n, p, buffer2)) {
-				j++;
-				if (i) i--;
-				else {
-					if (filldir(dirent, p, strlen(p),
-						    filp->f_pos, j) < 0)
-						return 0;
-					filp->f_pos++;
-				}
-			}
-		}
-		for (d = openprom_devices; d; d = d->next) {
-			if (d->node == n) {
-				if (i) i--;
-				else {
-					if (filldir(dirent, d->name,
-						    strlen(d->name),
-						    filp->f_pos, d->inode) < 0)
-						return 0;
-					filp->f_pos++;
-				}
-			}
-		}
-	}
-	return 0;
-}
-
-static int openpromfs_create (struct inode *dir, struct dentry *dentry, int mode)
-{
-	char *p;
-	struct inode *inode;
-	
-	if (!dir)
-		return -ENOENT;
-	if (dentry->d_name.len > 256)
-		return -EINVAL;
-	if (aliases_nodes == ALIASES_NNODES)
-		return -EIO;
-	p = kmalloc (dentry->d_name.len + 1, GFP_KERNEL);
-	if (!p)
-		return -ENOMEM;
-	strncpy (p, dentry->d_name.name, dentry->d_name.len);
-	p [dentry->d_name.len] = 0;
-	alias_names [aliases_nodes++] = p;
-	inode = iget (dir->i_sb,
-			NODEP2INO(NODE(dir->i_ino).first_prop) + aliases_nodes);
-	if (!inode)
-		return -EINVAL;
-	inode->i_mode = S_IFREG | S_IRUGO | S_IWUSR;
-	inode->i_op = &openpromfs_prop_inode_ops;
-	inode->i_nlink = 1;
-	if (inode->i_size < 0) inode->i_size = 0;
-	inode->u.generic_ip = (void *)(long)(((u16)aliases) | 
-			(((u16)(aliases_nodes - 1)) << 16));
-	d_instantiate(dentry, inode);
-	return 0;
-}
-
-static int openpromfs_unlink (struct inode *dir, struct dentry *dentry)
-{
-	unsigned int len;
-	char *p;
-	const char *name;
-	int i;
-	
-	name = dentry->d_name.name;
-	len = dentry->d_name.len;
-	for (i = 0; i < aliases_nodes; i++)
-		if ((strlen (alias_names [i]) == len)
-		    && !strncmp (name, alias_names[i], len)) {
-			char buffer[512];
-			
-			p = alias_names [i];
-			alias_names [i] = NULL;
-			kfree (p);
-			strcpy (buffer, "nvunalias ");
-			memcpy (buffer + 10, name, len);
-			buffer [10 + len] = 0;
-			prom_feval (buffer);
-		}
-	d_delete(dentry);
-	return 0;
-}
-
-/* {{{ init section */
-#ifndef MODULE
-static int __init check_space (u16 n)
-#else
-static int check_space (u16 n)
-#endif
-{
-	unsigned long pages;
-
-	if ((1 << alloced) * PAGE_SIZE < (n + 2) * sizeof(openpromfs_node)) {
-		pages = __get_free_pages (GFP_KERNEL, alloced + 1);
-		if (!pages)
-			return -1;
-
-		if (nodes) {
-			memcpy ((char *)pages, (char *)nodes,
-				(1 << alloced) * PAGE_SIZE);
-			free_pages ((unsigned long)nodes, alloced);
-		}
-		alloced++;
-		nodes = (openpromfs_node *)pages;
-	}
-	return 0;
-}
-
-#ifndef MODULE
-static u16 __init get_nodes (u16 parent, u32 node)
-#else
-static u16 get_nodes (u16 parent, u32 node)
-#endif
-{
-	char *p;
-	u16 n = last_node++, i;
-	char buffer[64];
-
-	if (check_space (n) < 0)
-		return 0xffff;
-	nodes[n].parent = parent;
-	nodes[n].node = node;
-	nodes[n].next = 0xffff;
-	nodes[n].child = 0xffff;
-	nodes[n].first_prop = first_prop++;
-	if (!parent) {
-		char buffer[8];
-		int j;
-		
-		if ((j = prom_getproperty (node, "name", buffer, 8)) >= 0) {
-		    buffer[j] = 0;
-		    if (!strcmp (buffer, "options"))
-			options = n;
-		    else if (!strcmp (buffer, "aliases"))
-		        aliases = n;
-		}
-	}
-	if (n != aliases)
-		for (p = prom_firstprop (node, buffer);
-		     p && p != (char *)-1 && *p;
-		     p = prom_nextprop (node, p, buffer))
-			first_prop++;
-	else {
-		char *q;
-		for (p = prom_firstprop (node, buffer);
-		     p && p != (char *)-1 && *p;
-		     p = prom_nextprop (node, p, buffer)) {
-			if (aliases_nodes == ALIASES_NNODES)
-				break;
-			for (i = 0; i < aliases_nodes; i++)
-				if (!strcmp (p, alias_names [i]))
-					break;
-			if (i < aliases_nodes)
-				continue;
-			q = kmalloc (strlen (p) + 1, GFP_KERNEL);
-			if (!q)
-				return 0xffff;
-			strcpy (q, p);
-			alias_names [aliases_nodes++] = q;
-		}
-		first_prop += ALIASES_NNODES;
-	}
-	node = prom_getchild (node);
-	if (node) {
-		parent = get_nodes (n, node);
-		if (parent == 0xffff)
-			return 0xffff;
-		nodes[n].child = parent;
-		while ((node = prom_getsibling (node)) != 0) {
-			i = get_nodes (n, node);
-			if (i == 0xffff)
-				return 0xffff;
-			nodes[parent].next = i;
-			parent = i;
-		}
-	}
-	return n;
-}
-
-
-#ifdef MODULE
-void openpromfs_use (struct inode *inode, int inc)
-{
-	static int root_fresh = 1;
-	static int dec_first = 1;
-	if (inc) {
-		if (inode->i_count == 1)
-			MOD_INC_USE_COUNT;
-		else if (root_fresh && inode->i_ino == PROC_OPENPROM_FIRST) {
-			root_fresh = 0;
-			MOD_INC_USE_COUNT;
-		}
-	} else {
-		if (inode->i_ino == PROC_OPENPROM_FIRST)
-			root_fresh = 0;
-		if (!dec_first)
-			MOD_DEC_USE_COUNT;
-	}
-	dec_first = 0;
-}
-
-#else
-#define openpromfs_use 0
-#endif
-
-static struct file_operations openprom_operations = {
-	NULL,			/* lseek - default */
-	NULL,			/* read - bad */
-	NULL,			/* write - bad */
-	openpromfs_readdir,	/* readdir */
-};
-
-static struct inode_operations openprom_inode_operations = {
-	&openprom_operations,/* default net directory file-ops */
-	NULL,			/* create */
-	openpromfs_lookup,	/* lookup */
-};
-
-static void openprom_read_inode(struct inode * inode)
-{
-	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-	if (inode->i_ino == PROC_OPENPROM) {
-		inode->i_op = &openprom_inode_operations;
-	}
-}
-
-static void openprom_put_super(struct super_block *sb)
-{
-	MOD_DEC_USE_COUNT;
-}
-
-static int openprom_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
-{
-	struct statfs tmp;
-
-	tmp.f_type = PROC_SUPER_MAGIC;		/* FIXME */
-	tmp.f_bsize = PAGE_SIZE/sizeof(long);	/* ??? */
-	tmp.f_blocks = 0;
-	tmp.f_bfree = 0;
-	tmp.f_bavail = 0;
-	tmp.f_files = 0;
-	tmp.f_ffree = 0;
-	tmp.f_namelen = NAME_MAX;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
-}
-
-static struct super_operations openprom_sops = { 
-	openprom_read_inode,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	openprom_put_super,
-	NULL,
-	openprom_statfs,
-	NULL
-};
-
-struct super_block *openprom_read_super(struct super_block *s,void *data, 
-				    int silent)
-{
-	struct inode * root_inode;
-
-	MOD_INC_USE_COUNT;
-	lock_super(s);
-	s->s_blocksize = 1024;
-	s->s_blocksize_bits = 10;
-	s->s_magic = PROC_SUPER_MAGIC;	/* FIXME */
-	s->s_op = &openprom_sops;
-	root_inode = iget(s, PROC_OPENPROM);
-	if (!root_inode)
-		goto out_no_root;
-	s->s_root = d_alloc_root(root_inode);
-	if (!s->s_root)
-		goto out_no_root;
-	unlock_super(s);
-	return s;
-
-out_no_root:
-	printk("proc_read_super: get root inode failed\n");
-	iput(root_inode);
-	s->s_dev = 0;
-	unlock_super(s);
-	return NULL;
-}
-
-static struct file_system_type openprom_fs_type = {
-	"openprom", 
-	0,
-	openprom_read_super, 
-	NULL
-};
-
-static int init_openprom_fs(void)
-{
-	nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0);
-	if (!nodes) {
-		printk (KERN_WARNING "/proc/openprom: can't get free page\n");
-		return -EIO;
-	}
-	if (get_nodes (0xffff, prom_root_node) == 0xffff) {
-		printk (KERN_WARNING "/proc/openprom: couldn't setup tree\n");
-		return -EIO;
-	}
-	nodes[last_node].first_prop = first_prop;
-	return register_filesystem(&openprom_fs_type);
-}
-
-#ifdef MODULE
-
-EXPORT_NO_SYMBOLS;
-
-int init_module (void)
-{
-	return init_openprom_fs();
-}
-
-#else
-
-void __init openpromfs_init (void)
-{
-	init_openprom_fs();
-}
-#endif
-
-#ifdef MODULE
-void cleanup_module (void)
-{
-	int i;
-	unregister_filesystem(&openprom_fs_type);
-	free_pages ((unsigned long)nodes, alloced);
-	for (i = 0; i < aliases_nodes; i++)
-		if (alias_names [i])
-			kfree (alias_names [i]);
-	nodes = NULL;
-}
-#endif
diff -u --recursive --new-file v2.3.34/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.3.34/linux/fs/proc/root.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/proc/root.c	Mon Dec 20 22:05:10 1999
@@ -73,9 +73,6 @@
 	proc_root_fs = proc_mkdir("fs", 0);
 	proc_root_driver = proc_mkdir("driver", 0);
 #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
-#ifdef CONFIG_SUN_OPENPROMFS
-	openpromfs_init ();
-#endif
 	/* just give it a mountpoint */
 	proc_mkdir("openprom", 0);
 #endif
diff -u --recursive --new-file v2.3.34/linux/fs/qnx4/BUGS linux/fs/qnx4/BUGS
--- v2.3.34/linux/fs/qnx4/BUGS	Mon Aug 31 13:01:35 1998
+++ linux/fs/qnx4/BUGS	Wed Dec 22 17:38:27 1999
@@ -1,4 +1,13 @@
-Last update: 03-07-1998
+Last update: 1999-12-23
+
+- Fragmented files and directories were incorrectly handled.
+  Fixed 1999-12-23, Anders.
+
+- readdir sometimes returned the same dir entry more than once.
+  Fixed 1999-12-13, Anders.
+
+- File names with a length of exactly 16 chars were handled incorrectly.
+  Fixed 1999-12-11, Anders.
 
 - Files in a subdir can't be accessed, I think that the inode information
   is not correctly copied at some point. Solved 06-06-1998, Richard.
diff -u --recursive --new-file v2.3.34/linux/fs/qnx4/README linux/fs/qnx4/README
--- v2.3.34/linux/fs/qnx4/README	Mon Aug 31 13:01:35 1998
+++ linux/fs/qnx4/README	Wed Dec 22 17:38:27 1999
@@ -1,9 +1,9 @@
 
   This is a snapshot of the QNX4 filesystem for Linux.
-  Please send diffs and remarks to <qnxfs@rtc-one.net> .
+  Please send diffs and remarks to <al@alarsen.net> .
   
 Credits :
 
 Richard "Scuba" A. Frowijn     <scuba@wxs.nl>
 Frank "Jedi/Sector One" Denis  <j@4u.net>
-
+Anders Larsen                  <al@alarsen.net>
diff -u --recursive --new-file v2.3.34/linux/fs/qnx4/TODO linux/fs/qnx4/TODO
--- v2.3.34/linux/fs/qnx4/TODO	Mon Aug 31 13:01:35 1998
+++ linux/fs/qnx4/TODO	Wed Dec 22 17:38:27 1999
@@ -1,5 +1,8 @@
 Name       : QNX4 TODO list
-Last update: 29-06-1998
+Last update: 1999-12-23
+
+    - Writing is still unsupported (it may compile, but it certainly won't
+      bring you any joy).
 
     - qnx4_checkroot (inode.c), currently there's a look for the '/' in
       the root direntry, if so then the current mounted device is a qnx4
@@ -11,10 +14,6 @@
       
     - Bitmap functions. To find out the free space, largest free block, etc.
       Partly done (RO), Richard, 05/06/1998. Optimized 20-06-1998, Frank.
-    
-    - Symbolic links. symlinks.c have to be rewritten.
-    
-    - Extended files.
     
     - Complete write, unlink and truncate functions : the bitmap should be
 updated.
diff -u --recursive --new-file v2.3.34/linux/fs/qnx4/bitmap.c linux/fs/qnx4/bitmap.c
--- v2.3.34/linux/fs/qnx4/bitmap.c	Tue Sep  1 10:43:13 1998
+++ linux/fs/qnx4/bitmap.c	Wed Dec 22 17:38:27 1999
@@ -1,12 +1,12 @@
-/* 
+/*
  * QNX4 file system, Linux implementation.
- * 
- * Version : 0.1
- * 
+ *
+ * Version : 0.2.1
+ *
  * Using parts of the xiafs filesystem.
- * 
+ *
  * History :
- * 
+ *
  * 28-05-1998 by Richard Frowijn : first release.
  * 20-06-1998 by Frank Denis : basic optimisations.
  * 25-06-1998 by Frank Denis : qnx4_is_free, qnx4_set_bitmap, qnx4_bmap .
@@ -86,7 +86,7 @@
 	return qnx4_count_free_blocks(sb) * QNX4_INODES_PER_BLOCK;	/* FIXME */
 }
 
-int qnx4_is_free(struct super_block *sb, int block)
+int qnx4_is_free(struct super_block *sb, long block)
 {
 	int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
 	int size = sb->u.qnx4_sb.BitMap->di_size;
@@ -115,18 +115,9 @@
 	return ret;
 }
 
-int qnx4_bmap(struct inode *inode, int block)
-{
-   QNX4DEBUG(("qnx4: bmap on block [%d]\n", block));
-   if (block < 0) {
-      return 0;
-   }
-   return !qnx4_is_free(inode->i_sb, block);
-}
-
 #ifdef CONFIG_QNX4FS_RW
 
-int qnx4_set_bitmap(struct super_block *sb, int block, int busy)
+int qnx4_set_bitmap(struct super_block *sb, long block, int busy)
 {
 	int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
 	int size = sb->u.qnx4_sb.BitMap->di_size;
diff -u --recursive --new-file v2.3.34/linux/fs/qnx4/dir.c linux/fs/qnx4/dir.c
--- v2.3.34/linux/fs/qnx4/dir.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/qnx4/dir.c	Wed Dec 22 17:38:27 1999
@@ -1,12 +1,12 @@
-/* 
+/*
  * QNX4 file system, Linux implementation.
- * 
- * Version : 0.1
- * 
+ *
+ * Version : 0.2.1
+ *
  * Using parts of the xiafs filesystem.
- * 
+ *
  * History :
- * 
+ *
  * 28-05-1998 by Richard Frowijn : first release.
  * 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support.
  */
@@ -20,55 +20,60 @@
 
 #include <asm/segment.h>
 
-static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir);
-
 static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
 	unsigned int offset;
 	struct buffer_head *bh;
 	struct qnx4_inode_entry *de;
-	long blknum;
-	int i;
+	struct qnx4_link_info *le;
+	unsigned long blknum;
+	int ix, ino;
 	int size;
 
-	blknum = inode->u.qnx4_i.i_first_xtnt.xtnt_blk - 1 +
-	    ((filp->f_pos >> 6) >> 3);
-
 	QNX4DEBUG(("qnx4_readdir:i_size = %ld\n", (long) inode->i_size));
 	QNX4DEBUG(("filp->f_pos         = %ld\n", (long) filp->f_pos));
-	QNX4DEBUG(("BlkNum              = %ld\n", (long) blknum));
 
 	while (filp->f_pos < inode->i_size) {
+		blknum = qnx4_block_map( inode, filp->f_pos / QNX4_BLOCK_SIZE );
 		bh = bread(inode->i_dev, blknum, QNX4_BLOCK_SIZE);
 		if(bh==NULL)
 		{
 			printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum);
 			break;
 		}
-		i = (filp->f_pos - (((filp->f_pos >> 6) >> 3) << 9)) & 0x3f;
-		while (i < QNX4_INODES_PER_BLOCK) {
-			offset = i * QNX4_DIR_ENTRY_SIZE;
+		ix = (filp->f_pos / QNX4_DIR_ENTRY_SIZE - (filp->f_pos / QNX4_BLOCK_SIZE) * QNX4_INODES_PER_BLOCK) % QNX4_INODES_PER_BLOCK;
+		while (ix < QNX4_INODES_PER_BLOCK) {
+			offset = ix * QNX4_DIR_ENTRY_SIZE;
 			de = (struct qnx4_inode_entry *) (bh->b_data + offset);
 			size = strlen(de->di_fname);
 			if (size) {
-
-				QNX4DEBUG(("qnx4_readdir:%s\n", de->di_fname));
-
-				if ((de->di_mode) || (de->di_status == QNX4_FILE_LINK)) {
-					if (de->di_status) {
-						if (filldir(dirent, de->di_fname, size, filp->f_pos, de->di_first_xtnt.xtnt_blk) < 0) {
-							brelse(bh);
-							return 0;
-						}
+				if ( !( de->di_status & QNX4_FILE_LINK ) && size > QNX4_SHORT_NAME_MAX )
+					size = QNX4_SHORT_NAME_MAX;
+				else if ( size > QNX4_NAME_MAX )
+					size = QNX4_NAME_MAX;
+
+				if ( ( de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK) ) != 0 ) {
+					QNX4DEBUG(("qnx4_readdir:%.*s\n", size, de->di_fname));
+					if ( ( de->di_status & QNX4_FILE_LINK ) == 0 )
+						ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1;
+					else
+					{
+						le  = (struct qnx4_link_info*)de;
+						ino = ( le->dl_inode_blk - 1 ) *
+							QNX4_INODES_PER_BLOCK +
+							le->dl_inode_ndx;
+					}
+					if (filldir(dirent, de->di_fname, size, filp->f_pos, ino) < 0) {
+						brelse(bh);
+						return 0;
 					}
 				}
 			}
-			i++;
+			ix++;
 			filp->f_pos += QNX4_DIR_ENTRY_SIZE;
 		}
 		brelse(bh);
-		blknum++;
 	}
 	UPDATE_ATIME(inode);
 
@@ -77,52 +82,19 @@
 
 static struct file_operations qnx4_dir_operations =
 {
-	NULL,			/* lseek - default */
-	NULL,			/* read */
-	NULL,			/* write - bad */
-	qnx4_readdir,		/* readdir */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	NULL,			/* mmap */
-	NULL,			/* no special open code */
-        NULL,                   /* no special flush code */
-	NULL,			/* no special release code */
-	file_fsync,		/* default fsync */
-	NULL,			/* default fasync */
-	NULL,			/* default check_media_change */
-	NULL,			/* default revalidate */
+	readdir:		qnx4_readdir,
+	fsync:			file_fsync,
 };
 
 struct inode_operations qnx4_dir_inode_operations =
 {
-	&qnx4_dir_operations,
-#ifdef CONFIG_QNX4FS_RW
-	qnx4_create,
-#else
-	NULL,			/* create */
-#endif
-	qnx4_lookup,
-	NULL,			/* link */
+	default_file_ops:	&qnx4_dir_operations,
 #ifdef CONFIG_QNX4FS_RW
-	qnx4_unlink,		/* unlink */
-#else
-	NULL,
+	create:			qnx4_create,
 #endif
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
+	lookup:			qnx4_lookup,
 #ifdef CONFIG_QNX4FS_RW
-	qnx4_rmdir,		/* rmdir */
-#else
-	NULL,
+	unlink:			qnx4_unlink,
+	rmdir:			qnx4_rmdir,
 #endif
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
diff -u --recursive --new-file v2.3.34/linux/fs/qnx4/file.c linux/fs/qnx4/file.c
--- v2.3.34/linux/fs/qnx4/file.c	Mon Dec 20 18:48:22 1999
+++ linux/fs/qnx4/file.c	Wed Dec 22 17:38:27 1999
@@ -1,12 +1,12 @@
-/* 
+/*
  * QNX4 file system, Linux implementation.
- * 
- * Version : 0.1
- * 
+ *
+ * Version : 0.2.1
+ *
  * Using parts of the xiafs filesystem.
- * 
+ *
  * History :
- * 
+ *
  * 25-05-1998 by Richard Frowijn : first release.
  * 21-06-1998 by Frank Denis : wrote qnx4_readpage to use generic_file_read.
  * 27-06-1998 by Frank Denis : file overwriting.
@@ -34,8 +34,6 @@
 #define MAX(a,b) (((a)>(b))?(a):(b))
 
 
-static int qnx4_readpage(struct dentry *dentry, struct page *page);
-
 #ifdef CONFIG_QNX4FS_RW
 static ssize_t qnx4_file_write(struct file *filp, const char *buf,
 			       size_t count, loff_t * ppos)
@@ -124,7 +122,7 @@
 			}
 			break;
 		}
-		update_vm_cache(inode, pos, p, c);
+//		update_vm_cache(inode, pos, p, c);
 		mark_buffer_uptodate(bh, 1);
 		mark_buffer_dirty(bh, 0);
 		brelse(bh);
@@ -145,112 +143,28 @@
 #endif
 
 /*
- * We have moostly NULL's here: the current defaults are ok for
+ * We have mostly NULL's here: the current defaults are ok for
  * the qnx4 filesystem.
  */
 static struct file_operations qnx4_file_operations =
 {
-	NULL,			/* lseek - default */
-	generic_file_read,	/* read */
+	read:			generic_file_read,
 #ifdef CONFIG_QNX4FS_RW
-	qnx4_file_write,	/* write */
-#else
-	NULL,
+	write:			qnx4_file_write,
 #endif
-	NULL,			/* readdir - bad */
-	NULL,			/* poll - default */
-	NULL,			/* ioctl - default */
-	generic_file_mmap,	/* mmap */
-	NULL,			/* no special open is needed */
-        NULL,                   /* no special flush code */
-	NULL,			/* release */
-#ifdef CONFIG_QNX4FS_RW   
-	qnx4_sync_file,	        /* fsync */
-#else
-        NULL,
+	mmap:			generic_file_mmap,
+#ifdef CONFIG_QNX4FS_RW
+	fsync:			qnx4_sync_file,
 #endif
-	NULL,			/* fasync */
-	NULL,			/* check_media_change */
-	NULL,			/* revalidate */
-	NULL			/* lock */
 };
 
 struct inode_operations qnx4_file_inode_operations =
 {
-	&qnx4_file_operations,	/* default file operations */
-	NULL,			/* create? It's not a directory */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	qnx4_bmap,	        /* get_block */
-	qnx4_readpage,		/* readpage */
-	NULL,			/* writepage */
+	default_file_ops:	&qnx4_file_operations,
+	get_block:		qnx4_get_block,
+	readpage:		block_read_full_page,
 #ifdef CONFIG_QNX4FS_RW
-	qnx4_truncate,		/* truncate */
-#else
-	NULL,
+	writepage:		block_write_full_page,
+	truncate:		qnx4_truncate,
 #endif
-	NULL,			/* permission */
-	NULL			/* revalidate */
 };
-
-static int qnx4_readpage(struct dentry *dentry, struct page *page)
-{
-	struct inode *inode = dentry->d_inode;
-	struct qnx4_inode_info *qnx4_ino = &inode->u.qnx4_i;
-	unsigned long buf;
-	unsigned long offset, avail, readlen;
-	unsigned long start;
-	unsigned long count;
-	struct buffer_head *bh;
-	int res = -EIO;
-
-	QNX4DEBUG(("qnx4: readpage index=[%ld]\n", (long) page->index));
-
-	if (qnx4_ino->i_xblk != 0) {
-		printk("qnx4: sorry, this file is extended, don't know how to handle it (yet) !\n");
-		return -EIO;
-	}
-	atomic_inc(&page->count);
-	buf = page_address(page);
-	clear_bit(PG_uptodate, &page->flags);
-	clear_bit(PG_error, &page->flags);
-	offset = page->index<<PAGE_SHIFT;
-
-	if (offset < inode->i_size) {
-		res = 0;
-		avail = inode->i_size - offset;
-		readlen = MIN(avail, PAGE_SIZE);
-		start = qnx4_ino->i_first_xtnt.xtnt_blk + (offset >> 9) - 1;
-		count = PAGE_SIZE / QNX4_BLOCK_SIZE;
-		do {
-			QNX4DEBUG(("qnx4: reading page starting at [%ld]\n", (long) start));
-			if ((bh = bread(inode->i_dev, start, QNX4_BLOCK_SIZE)) == NULL) {
-				printk("qnx4: data corrupted or I/O error.\n");
-				res = -EIO;
-			} else {
-				memcpy((void *) buf, bh->b_data, QNX4_BLOCK_SIZE);
-			}
-			buf += QNX4_BLOCK_SIZE;
-			start++;
-			count--;
-		} while (count != 0);
-	}
-	if (res != 0) {
-		set_bit(PG_error, &page->flags);
-		memset((void *) buf, 0, PAGE_SIZE);
-	} else {
-		set_bit(PG_uptodate, &page->flags);
-	}
-	UnlockPage(page);
-/*  free_page(buf); */
-
-	return res;
-}
diff -u --recursive --new-file v2.3.34/linux/fs/qnx4/inode.c linux/fs/qnx4/inode.c
--- v2.3.34/linux/fs/qnx4/inode.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/qnx4/inode.c	Wed Dec 22 17:38:27 1999
@@ -1,12 +1,12 @@
-/* 
+/*
  * QNX4 file system, Linux implementation.
- * 
- * Version : 0.1
- * 
+ *
+ * Version : 0.2.1
+ *
  * Using parts of the xiafs filesystem.
- * 
+ *
  * History :
- * 
+ *
  * 01-06-1998 by Richard Frowijn : first release.
  * 20-06-1998 by Frank Denis : Linux 2.1.99+ support, boot signature, misc.
  * 30-06-1998 by Frank Denis : first step to write inodes.
@@ -49,7 +49,7 @@
 				kdevname(inode->i_dev), inode->i_ino);
 			err = -1;
 		}
-	        brelse (bh);	   
+	        brelse (bh);
 	} else if (!bh) {
 		err = -1;
 	}
@@ -120,28 +120,17 @@
 
 static struct super_operations qnx4_sops =
 {
-	qnx4_read_inode,
-#ifdef CONFIG_QNX4FS_RW
-	qnx4_write_inode,
-#else
-	NULL,
-#endif
-	NULL,			/* put_inode */
+	read_inode:	qnx4_read_inode,
 #ifdef CONFIG_QNX4FS_RW
-	qnx4_delete_inode,
-#else
-	NULL,			/* delete_inode */
+	write_inode:	qnx4_write_inode,
+	delete_inode:	qnx4_delete_inode,
 #endif
-	NULL,			/* notify_change */
-	qnx4_put_super,
+	put_super:	qnx4_put_super,
 #ifdef CONFIG_QNX4FS_RW
-	qnx4_write_super,
-#else
-	NULL,
+	write_super:	qnx4_write_super,
 #endif
-	qnx4_statfs,
-	qnx4_remount,
-	NULL			/* clear_inode */
+	statfs:		qnx4_statfs,
+	remount_fs:	qnx4_remount,
 };
 
 static int qnx4_remount(struct super_block *sb, int *flags, char *data)
@@ -215,6 +204,89 @@
 	return NULL;
 }
 
+int qnx4_get_block( struct inode *inode, long iblock, struct buffer_head *bh, int create )
+{
+	unsigned long phys;
+
+	QNX4DEBUG(("qnx4: qnx4_get_block inode=[%ld] iblock=[%ld]\n",inode->i_ino,iblock));
+
+	phys = qnx4_block_map( inode, iblock );
+	if ( phys )
+	{
+		// logical block is before EOF
+		bh->b_dev     = inode->i_dev;
+		bh->b_blocknr = phys;
+		bh->b_state  |= (1UL << BH_Mapped);
+	}
+	else if ( create )
+	{
+		// to be done.
+	}
+	return 0;
+}
+
+unsigned long qnx4_block_map( struct inode *inode, long iblock )
+{
+	int ix;
+	long offset, i_xblk;
+	unsigned long block = 0;
+	struct buffer_head *bh = 0;
+	struct qnx4_xblk *xblk = 0;
+	struct qnx4_inode_info *qnx4_inode = &inode->u.qnx4_i;
+	qnx4_nxtnt_t nxtnt = qnx4_inode->i_num_xtnts;
+
+	if ( iblock < qnx4_inode->i_first_xtnt.xtnt_size )
+	{
+		// iblock is in the first extent. This is easy.
+		block = qnx4_inode->i_first_xtnt.xtnt_blk + iblock - 1;
+	}
+	else
+	{
+		// iblock is beyond first extent. We have to follow the extent chain.
+		i_xblk = qnx4_inode->i_xblk;
+		offset = iblock - qnx4_inode->i_first_xtnt.xtnt_size;
+		ix = 0;
+		while ( --nxtnt > 0 )
+		{
+			if ( ix == 0 )
+			{
+				// read next xtnt block.
+				bh = bread( inode->i_dev, i_xblk - 1, QNX4_BLOCK_SIZE );
+				if ( !bh )
+				{
+					QNX4DEBUG(("qnx4: I/O error reading xtnt block [%ld])\n", i_xblk - 1));
+					return -EIO;
+				}
+				xblk = (struct qnx4_xblk*)bh->b_data;
+				if ( memcmp( xblk->xblk_signature, "IamXblk", 7 ) )
+				{
+					QNX4DEBUG(("qnx4: block at %ld is not a valid xtnt\n", qnx4_inode->i_xblk));
+					break;
+				}
+			}
+			if ( offset < xblk->xblk_xtnts[ix].xtnt_size )
+			{
+				// got it!
+				block = xblk->xblk_xtnts[ix].xtnt_blk + offset - 1;
+				break;
+			}
+			offset -= xblk->xblk_xtnts[ix].xtnt_size;
+			if ( ++ix > QNX4_MAX_XTNTS_PER_XBLK )
+			{
+				i_xblk = xblk->xblk_next_xblk;
+				ix = 0;
+				brelse( bh );
+				bh = 0;
+			}
+		}
+		if ( bh )
+			brelse( bh );
+	}
+
+	QNX4DEBUG(("qnx4: mapping block %ld of inode %ld = %ld\n",iblock,inode->i_ino,block));
+	return block;
+}
+
 static int qnx4_statfs(struct super_block *sb,
 		       struct statfs *buf, int bufsize)
 {
@@ -238,7 +310,7 @@
  * it really _is_ a qnx4 filesystem, and to check the size
  * of the directory entry.
  */
-static const char *qnx4_checkroot(struct super_block *s)
+static const char *qnx4_checkroot(struct super_block *sb)
 {
 	struct buffer_head *bh;
 	struct qnx4_inode_entry *rootdir;
@@ -246,14 +318,14 @@
 	int i, j;
 	int found = 0;
 
-	if (*(s->u.qnx4_sb.sb->RootDir.di_fname) != '/') {
+	if (*(sb->u.qnx4_sb.sb->RootDir.di_fname) != '/') {
 		return "no qnx4 filesystem (no root dir).";
 	} else {
-		QNX4DEBUG(("QNX4 filesystem found on dev %s.\n", kdevname(s->s_dev)));
-		rd = s->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_blk - 1;
-		rl = s->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_size;
+		QNX4DEBUG(("QNX4 filesystem found on dev %s.\n", kdevname(sb->s_dev)));
+		rd = sb->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_blk - 1;
+		rl = sb->u.qnx4_sb.sb->RootDir.di_first_xtnt.xtnt_size;
 		for (j = 0; j < rl; j++) {
-			bh = bread(s->s_dev, rd + j, QNX4_BLOCK_SIZE);	/* root dir, first block */
+			bh = bread(sb->s_dev, rd + j, QNX4_BLOCK_SIZE);	/* root dir, first block */
 			if (bh == NULL) {
 				return "unable to read root entry.";
 			}
@@ -263,13 +335,12 @@
 					QNX4DEBUG(("Rootdir entry found : [%s]\n", rootdir->di_fname));
 					if (!strncmp(rootdir->di_fname, QNX4_BMNAME, sizeof QNX4_BMNAME)) {
 						found = 1;
-						s->u.qnx4_sb.BitMap = rootdir;	/* keep bitmap inode known */
+						sb->u.qnx4_sb.BitMap = kmalloc( sizeof( struct qnx4_inode_entry ), GFP_KERNEL );
+						memcpy( sb->u.qnx4_sb.BitMap, rootdir, sizeof( struct qnx4_inode_entry ) );	/* keep bitmap inode known */
 						break;
 					}
 				}
 			}
-			/* WAIT! s->u.qnx4_sb.BitMap points into bh->b_data
-			   and now we release bh?? */
 			brelse(bh);
 			if (found != 0) {
 				break;
@@ -282,13 +353,12 @@
 	return NULL;
 }
 
-static struct super_block *qnx4_read_super(struct super_block *s, 
+static struct super_block *qnx4_read_super(struct super_block *s,
 					   void *data, int silent)
 {
 	struct buffer_head *bh;
 	kdev_t dev = s->s_dev;
 	struct inode *root;
-	char *tmpc;
 	const char *errmsg;
 
 	MOD_INC_USE_COUNT;
@@ -306,9 +376,7 @@
 		printk("qnx4: unable to read the boot sector\n");
 		goto outnobh;
 	}
-	tmpc = (char *) bh->b_data;
-	if (tmpc[4] != 'Q' || tmpc[5] != 'N' || tmpc[6] != 'X' ||
-	    tmpc[7] != '4' || tmpc[8] != 'F' || tmpc[9] != 'S') {
+	if ( memcmp( (char*)bh->b_data + 4, "QNX4FS", 6 ) ) {
 		if (!silent)
 			printk("qnx4: wrong fsid in boot sector.\n");
 		goto out;
@@ -328,7 +396,7 @@
 	s->u.qnx4_sb.sb_buf = bh;
 	s->u.qnx4_sb.sb = (struct qnx4_super_block *) bh->b_data;
 
- 
+
  	/* check before allocating dentries, inodes, .. */
 	errmsg = qnx4_checkroot(s);
 	if (errmsg != NULL) {
@@ -336,18 +404,18 @@
  			printk("qnx4: %s\n", errmsg);
 		goto out;
 	}
- 
+
  	/* does root not have inode number QNX4_ROOT_INO ?? */
  	root = iget(s, QNX4_ROOT_INO * QNX4_INODES_PER_BLOCK);
  	if (!root) {
  		printk("qnx4: get inode failed\n");
  		goto out;
  	}
- 
+
  	s->s_root = d_alloc_root(root);
  	if (s->s_root == NULL)
  		goto outi;
- 
+
 	brelse(bh);
 	unlock_super(s);
 	s->s_dirt = 1;
@@ -368,6 +436,7 @@
 
 static void qnx4_put_super(struct super_block *sb)
 {
+	kfree_s( sb->u.qnx4_sb.BitMap, sizeof( struct qnx4_inode_entry ) );
 	MOD_DEC_USE_COUNT;
 	return;
 }
@@ -434,7 +503,7 @@
 
 int __init init_qnx4_fs(void)
 {
-	printk("QNX4 filesystem v0.2 registered.\n");
+	printk("QNX4 filesystem 0.2.1 registered.\n");
 	return register_filesystem(&qnx4_fs_type);
 }
 
diff -u --recursive --new-file v2.3.34/linux/fs/qnx4/namei.c linux/fs/qnx4/namei.c
--- v2.3.34/linux/fs/qnx4/namei.c	Mon May 10 14:14:28 1999
+++ linux/fs/qnx4/namei.c	Wed Dec 22 17:38:27 1999
@@ -1,7 +1,7 @@
 /* 
  * QNX4 file system, Linux implementation.
  * 
- * Version : 0.1
+ * Version : 0.2.1
  * 
  * Using parts of the xiafs filesystem.
  * 
@@ -33,7 +33,8 @@
 		      struct buffer_head *bh, unsigned long *offset)
 {
 	struct qnx4_inode_entry *de;
-	int namelen;
+	struct qnx4_link_info *le;
+	int namelen, thislen;
 
 	if (bh == NULL) {
 		printk("qnx4: matching unassigned buffer !\n");
@@ -41,23 +42,24 @@
 	}
 	de = (struct qnx4_inode_entry *) (bh->b_data + *offset);
 	*offset += QNX4_DIR_ENTRY_SIZE;
-	if ((de->di_status & 0x08) == 0x08) {
+	if ((de->di_status & QNX4_FILE_LINK) != 0) {
 		namelen = QNX4_NAME_MAX;
 	} else {
-		namelen = _SHORT_NAME_MAX;
+		namelen = QNX4_SHORT_NAME_MAX;
 	}
 	/* "" means "." ---> so paths like "/usr/lib//libc.a" work */
 	if (!len && (de->di_fname[0] == '.') && (de->di_fname[1] == '\0')) {
 		return 1;
 	}
-	if (len != strlen(de->di_fname)) {
+	thislen = strlen( de->di_fname );
+	if ( thislen > namelen )
+		thislen = namelen;
+	if (len != thislen) {
 		return 0;
 	}
 	if (strncmp(name, de->di_fname, len) == 0) {
-		if ((de->di_mode) || (de->di_status == QNX4_FILE_LINK)) {
-			if (de->di_status) {
-				return 1;
-			}
+		if ((de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK)) != 0) {
+			return 1;
 		}
 	}
 	return 0;
@@ -75,19 +77,19 @@
 		return NULL;
 	}
 	bh = NULL;
-	blkofs = dir->u.qnx4_i.i_first_xtnt.xtnt_blk - 1;
-	offset = block = 0;
-	while (block * QNX4_BLOCK_SIZE + offset < dir->i_size) {
+	block = offset = blkofs = 0;
+	while (blkofs * QNX4_BLOCK_SIZE + offset < dir->i_size) {
 		if (!bh) {
-			bh = qnx4_bread(dir, block + blkofs, 0);
+			block = qnx4_block_map( dir, blkofs );
+			bh = qnx4_bread(dir, block, 0);
 			if (!bh) {
-				block++;
+				blkofs++;
 				continue;
 			}
 		}
 		*res_dir = (struct qnx4_inode_entry *) (bh->b_data + offset);
 		if (qnx4_match(len, name, bh, &offset)) {
-			*ino = (block + blkofs) * QNX4_INODES_PER_BLOCK +
+			*ino = block * QNX4_INODES_PER_BLOCK +
 			    (offset / QNX4_DIR_ENTRY_SIZE) - 1;
 			return bh;
 		}
@@ -97,7 +99,7 @@
 		brelse(bh);
 		bh = NULL;
 		offset = 0;
-		block++;
+		blkofs++;
 	}
 	brelse(bh);
 	*res_dir = NULL;
diff -u --recursive --new-file v2.3.34/linux/fs/qnx4/symlinks.c linux/fs/qnx4/symlinks.c
--- v2.3.34/linux/fs/qnx4/symlinks.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/qnx4/symlinks.c	Wed Dec 22 17:38:27 1999
@@ -1,7 +1,7 @@
 /* 
  * QNX4 file system, Linux implementation.
  * 
- * Version : 0.1
+ * Version : 0.2.1
  * 
  * Using parts of the xiafs filesystem.
  * 
@@ -31,88 +31,8 @@
  */
 struct inode_operations qnx4_symlink_inode_operations =
 {
-	NULL,			/* no file-operations */
-	NULL,			/* create */
-	NULL,			/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	qnx4_readlink,		/* readlink */
-	qnx4_follow_link,	/* follow_link */
-	NULL,			/* get_block */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* truncate */
-	NULL,			/* permission */
-	NULL			/* revalidate */
+	readlink:		page_readlink,
+	follow_link:		page_follow_link,
+	get_block:		qnx4_get_block,
+	readpage:		block_read_full_page,
 };
-
-static struct dentry *qnx4_follow_link(struct dentry *dentry,
-				       struct dentry *base, unsigned int follow)
-{
-#if 0
-	struct inode *inode = dentry->d_inode;
-	struct buffer_head *bh;
-
-	if (!inode) {
-		return ERR_PTR(-ENOENT);
-	}
-	if (current->link_count > 5) {
-		return ERR_PTR(-ELOOP);
-	}
-	if (!(bh = qnx4_bread(inode, 0, 0))) {
-		return ERR_PTR(-EIO);
-	}
-	current->link_count++;
-	current->link_count--;
-	brelse(bh);
-	return 0;
-#else
-	printk("qnx4: qnx4_follow_link needs to be fixed.\n");
-	return ERR_PTR(-EIO);
-#endif
-}
-
-static int qnx4_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
-	struct inode *inode = dentry->d_inode;
-	struct buffer_head *bh;
-	int i;
-	char c;
-	struct qnx4_inode_info *qnx4_ino;
-
-	QNX4DEBUG(("qnx4: qnx4_readlink() called\n"));
-
-	if (buffer == NULL || inode == NULL || !S_ISLNK(inode->i_mode)) {
-		return -EINVAL;
-	}
-	qnx4_ino = &inode->u.qnx4_i;
-	if (buflen > 1023) {
-		buflen = 1023;
-	}
-	bh = bread(inode->i_dev, qnx4_ino->i_first_xtnt.xtnt_blk,
-		   QNX4_BLOCK_SIZE);
-	if (bh == NULL) {
-		QNX4DEBUG(("qnx4: NULL symlink bh\n"));
-		return 0;
-	}
-	QNX4DEBUG(("qnx4: qnx4_bread sym called -> [%s]\n",
-		   bh->b_data));
-	if (bh->b_data[0] != 0) {
-		i = 0;
-		while (i < buflen && (c = bh->b_data[i])) {
-			i++;
-			put_user(c, buffer++);
-		}
-		brelse(bh);
-		return i;
-	} else {
-		brelse(bh);
-		memcpy(buffer, "fixme", 5);
-		return 5;
-	}
-}
diff -u --recursive --new-file v2.3.34/linux/fs/stat.c linux/fs/stat.c
--- v2.3.34/linux/fs/stat.c	Mon Dec 20 18:48:22 1999
+++ linux/fs/stat.c	Tue Dec 21 21:56:42 1999
@@ -283,7 +283,7 @@
 
 
 /* ---------- LFS-64 ----------- */
-#if BITS_PER_LONG == 32
+#if !defined(__alpha__)
 
 static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf)
 {
@@ -400,4 +400,4 @@
 	return err;
 }
 
-#endif /* BITS_PER_LONG == 32 */
+#endif /* LFS-64 */
diff -u --recursive --new-file v2.3.34/linux/include/asm-ppc/hw_irq.h linux/include/asm-ppc/hw_irq.h
--- v2.3.34/linux/include/asm-ppc/hw_irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/hw_irq.h	Mon Dec 27 14:10:20 1999
@@ -0,0 +1,57 @@
+/*
+ * $Id: irq_control.h,v 1.8 1999/09/15 23:58:48 cort Exp $
+ *
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ */
+#ifndef _PPC_HW_IRQ_H
+#define _PPC_HW_IRQ_H
+
+#if 0
+/* Structure describing interrupts */
+struct hw_interrupt_type {
+	const char * typename;
+	void (*startup)(unsigned int irq);
+	void (*shutdown)(unsigned int irq);
+	void (*enable)(unsigned int irq);
+	void (*disable)(unsigned int irq);
+	void (*mask_and_ack)(unsigned int irq);
+	int irq_offset;
+};
+
+struct irqdesc {
+	struct irqaction *action;
+	struct hw_interrupt_type *ctl;
+};
+#endif
+
+struct int_control_struct
+{
+	void (*int_cli)(void);
+	void (*int_sti)(void);
+	void (*int_restore_flags)(unsigned long);
+	void (*int_save_flags)(unsigned long *);
+};
+extern struct int_control_struct int_control;
+extern unsigned long timer_interrupt_intercept;
+extern unsigned long do_IRQ_intercept;
+void timer_interrupt(struct pt_regs *);
+
+extern void __no_use_sti(void);
+extern void __no_use_cli(void);
+extern void __no_use_restore_flags(unsigned long);
+extern void __no_use_save_flags(unsigned long *);
+
+#define __cli() int_control.int_cli()
+#define __sti() int_control.int_sti()
+#define __save_flags(flags) int_control.int_save_flags(&flags)
+#define __restore_flags(flags) int_control.int_restore_flags(flags)
+#define __save_and_cli(flags) ({__save_flags(flags);__cli();})
+
+extern void do_lost_interrupts(unsigned long);
+extern atomic_t ppc_n_lost_interrupts;
+
+#define mask_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->disable) irq_desc[irq].handler->disable(irq);})
+#define unmask_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->enable) irq_desc[irq].handler->enable(irq);})
+#define mask_and_ack_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->ack) irq_desc[irq].handler->ack(irq);})
+
+#endif /* _PPC_HW_IRQ_H */
diff -u --recursive --new-file v2.3.34/linux/include/asm-ppc/irq_control.h linux/include/asm-ppc/irq_control.h
--- v2.3.34/linux/include/asm-ppc/irq_control.h	Thu Nov 18 20:25:38 1999
+++ linux/include/asm-ppc/irq_control.h	Wed Dec 31 16:00:00 1969
@@ -1,60 +0,0 @@
-/*
- * $Id: irq_control.h,v 1.8 1999/09/15 23:58:48 cort Exp $
- *
- * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
- */
-#ifndef _PPC_IRQ_CONTROL_H
-#define _PPC_IRQ_CONTROL_H
-
-#include <asm/irq.h>
-#include <asm/atomic.h>
-
-/* Structure describing interrupts */
-struct hw_interrupt_type {
-	const char * typename;
-	void (*startup)(unsigned int irq);
-	void (*shutdown)(unsigned int irq);
-	void (*enable)(unsigned int irq);
-	void (*disable)(unsigned int irq);
-	void (*mask_and_ack)(unsigned int irq);
-	int irq_offset;
-};
-
-struct irqdesc {
-	struct irqaction *action;
-	struct hw_interrupt_type *ctl;
-};
-
-extern struct irqdesc irq_desc[NR_IRQS];
-
-struct int_control_struct
-{
-	void (*int_cli)(void);
-	void (*int_sti)(void);
-	void (*int_restore_flags)(unsigned long);
-	void (*int_save_flags)(unsigned long *);
-};
-extern struct int_control_struct int_control;
-extern unsigned long timer_interrupt_intercept;
-extern unsigned long do_IRQ_intercept;
-void timer_interrupt(struct pt_regs *);
-
-extern void __no_use_sti(void);
-extern void __no_use_cli(void);
-extern void __no_use_restore_flags(unsigned long);
-extern void __no_use_save_flags(unsigned long *);
-
-#define __cli() int_control.int_cli()
-#define __sti() int_control.int_sti()
-#define __save_flags(flags) int_control.int_save_flags(&flags)
-#define __restore_flags(flags) int_control.int_restore_flags(flags)
-#define __save_and_cli(flags) ({__save_flags(flags);__cli();})
-
-extern void do_lost_interrupts(unsigned long);
-extern atomic_t ppc_n_lost_interrupts;
-
-#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);})
-
-#endif /* _PPC_IRQ_CONTROL_H */
diff -u --recursive --new-file v2.3.34/linux/include/asm-ppc/system.h linux/include/asm-ppc/system.h
--- v2.3.34/linux/include/asm-ppc/system.h	Sun Nov  7 16:37:34 1999
+++ linux/include/asm-ppc/system.h	Mon Dec 27 14:10:20 1999
@@ -10,7 +10,7 @@
 
 #include <asm/processor.h>
 #include <asm/atomic.h>
-#include <asm/irq_control.h>
+#include <asm/hw_irq.h>
 
 /*
  * Memory barrier.
diff -u --recursive --new-file v2.3.34/linux/include/asm-ppc/unistd.h linux/include/asm-ppc/unistd.h
--- v2.3.34/linux/include/asm-ppc/unistd.h	Tue Dec  7 09:32:51 1999
+++ linux/include/asm-ppc/unistd.h	Mon Dec 27 14:10:20 1999
@@ -195,6 +195,12 @@
 #define __NR_putpmsg		188	/* some people actually want streams */
 #define __NR_vfork		189
 #define __NR_ugetrlimit		191	/* SuS compliant getrlimit */
+#define __NR_mmap2		192
+#define __NR_truncate64		193
+#define __NR_ftruncate64	194
+#define __NR_stat64		195
+#define __NR_lstat64		196
+#define __NR_fstat64		197
 
 #define __NR(n)	#n
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/asm_offsets.h linux/include/asm-sparc/asm_offsets.h
--- v2.3.34/linux/include/asm-sparc/asm_offsets.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-sparc/asm_offsets.h	Mon Dec 20 22:05:52 1999
@@ -73,86 +73,86 @@
 #define AOFF_task_pidhash_pprev	0x00000088
 #define ASIZ_task_pidhash_pprev	0x00000004
 #define AOFF_task_wait_chldexit	0x0000008c
-#define ASIZ_task_wait_chldexit	0x00000014
-#define AOFF_task_vfork_sem	0x000000a0
+#define ASIZ_task_wait_chldexit	0x00000010
+#define AOFF_task_vfork_sem	0x0000009c
 #define ASIZ_task_vfork_sem	0x00000004
-#define AOFF_task_policy	0x000000a4
+#define AOFF_task_policy	0x000000a0
 #define ASIZ_task_policy	0x00000004
-#define AOFF_task_rt_priority	0x000000a8
+#define AOFF_task_rt_priority	0x000000a4
 #define ASIZ_task_rt_priority	0x00000004
-#define AOFF_task_it_real_value	0x000000ac
+#define AOFF_task_it_real_value	0x000000a8
 #define ASIZ_task_it_real_value	0x00000004
-#define AOFF_task_it_prof_value	0x000000b0
+#define AOFF_task_it_prof_value	0x000000ac
 #define ASIZ_task_it_prof_value	0x00000004
-#define AOFF_task_it_virt_value	0x000000b4
+#define AOFF_task_it_virt_value	0x000000b0
 #define ASIZ_task_it_virt_value	0x00000004
-#define AOFF_task_it_real_incr	0x000000b8
+#define AOFF_task_it_real_incr	0x000000b4
 #define ASIZ_task_it_real_incr	0x00000004
-#define AOFF_task_it_prof_incr	0x000000bc
+#define AOFF_task_it_prof_incr	0x000000b8
 #define ASIZ_task_it_prof_incr	0x00000004
-#define AOFF_task_it_virt_incr	0x000000c0
+#define AOFF_task_it_virt_incr	0x000000bc
 #define ASIZ_task_it_virt_incr	0x00000004
-#define AOFF_task_real_timer	0x000000c4
+#define AOFF_task_real_timer	0x000000c0
 #define ASIZ_task_real_timer	0x00000014
-#define AOFF_task_times	0x000000d8
+#define AOFF_task_times	0x000000d4
 #define ASIZ_task_times	0x00000010
-#define AOFF_task_start_time	0x000000e8
+#define AOFF_task_start_time	0x000000e4
 #define ASIZ_task_start_time	0x00000004
-#define AOFF_task_per_cpu_utime	0x000000ec
+#define AOFF_task_per_cpu_utime	0x000000e8
 #define ASIZ_task_per_cpu_utime	0x00000004
-#define AOFF_task_min_flt	0x000000f4
+#define AOFF_task_min_flt	0x000000f0
 #define ASIZ_task_min_flt	0x00000004
-#define AOFF_task_maj_flt	0x000000f8
+#define AOFF_task_maj_flt	0x000000f4
 #define ASIZ_task_maj_flt	0x00000004
-#define AOFF_task_nswap	0x000000fc
+#define AOFF_task_nswap	0x000000f8
 #define ASIZ_task_nswap	0x00000004
-#define AOFF_task_cmin_flt	0x00000100
+#define AOFF_task_cmin_flt	0x000000fc
 #define ASIZ_task_cmin_flt	0x00000004
-#define AOFF_task_cmaj_flt	0x00000104
+#define AOFF_task_cmaj_flt	0x00000100
 #define ASIZ_task_cmaj_flt	0x00000004
-#define AOFF_task_cnswap	0x00000108
+#define AOFF_task_cnswap	0x00000104
 #define ASIZ_task_cnswap	0x00000004
-#define AOFF_task_uid	0x0000010e
+#define AOFF_task_uid	0x0000010a
 #define ASIZ_task_uid	0x00000002
-#define AOFF_task_euid	0x00000110
+#define AOFF_task_euid	0x0000010c
 #define ASIZ_task_euid	0x00000002
-#define AOFF_task_suid	0x00000112
+#define AOFF_task_suid	0x0000010e
 #define ASIZ_task_suid	0x00000002
-#define AOFF_task_fsuid	0x00000114
+#define AOFF_task_fsuid	0x00000110
 #define ASIZ_task_fsuid	0x00000002
-#define AOFF_task_gid	0x00000116
+#define AOFF_task_gid	0x00000112
 #define ASIZ_task_gid	0x00000002
-#define AOFF_task_egid	0x00000118
+#define AOFF_task_egid	0x00000114
 #define ASIZ_task_egid	0x00000002
-#define AOFF_task_sgid	0x0000011a
+#define AOFF_task_sgid	0x00000116
 #define ASIZ_task_sgid	0x00000002
-#define AOFF_task_fsgid	0x0000011c
+#define AOFF_task_fsgid	0x00000118
 #define ASIZ_task_fsgid	0x00000002
-#define AOFF_task_ngroups	0x00000120
+#define AOFF_task_ngroups	0x0000011c
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x00000124
+#define AOFF_task_groups	0x00000120
 #define ASIZ_task_groups	0x00000040
-#define AOFF_task_cap_effective	0x00000164
+#define AOFF_task_cap_effective	0x00000160
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x00000168
+#define AOFF_task_cap_inheritable	0x00000164
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x0000016c
+#define AOFF_task_cap_permitted	0x00000168
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x00000170
+#define AOFF_task_user	0x0000016c
 #define ASIZ_task_user	0x00000004
-#define AOFF_task_rlim	0x00000174
+#define AOFF_task_rlim	0x00000170
 #define ASIZ_task_rlim	0x00000050
-#define AOFF_task_used_math	0x000001c4
+#define AOFF_task_used_math	0x000001c0
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x000001c6
+#define AOFF_task_comm	0x000001c2
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x000001d8
+#define AOFF_task_link_count	0x000001d4
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x000001dc
+#define AOFF_task_tty	0x000001d8
 #define ASIZ_task_tty	0x00000004
-#define AOFF_task_semundo	0x000001e0
+#define AOFF_task_semundo	0x000001dc
 #define ASIZ_task_semundo	0x00000004
-#define AOFF_task_semsleeping	0x000001e4
+#define AOFF_task_semsleeping	0x000001e0
 #define ASIZ_task_semsleeping	0x00000004
 #define AOFF_task_thread	0x000001e8
 #define ASIZ_task_thread	0x00000388
@@ -165,20 +165,20 @@
 #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	0x00000584
+#define ASIZ_task_sigmask_lock	0x00000000
+#define AOFF_task_sig	0x00000580
 #define ASIZ_task_sig	0x00000004
-#define AOFF_task_signal	0x00000588
+#define AOFF_task_signal	0x00000584
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000590
+#define AOFF_task_blocked	0x0000058c
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000598
+#define AOFF_task_sigqueue	0x00000594
 #define ASIZ_task_sigqueue	0x00000004
-#define AOFF_task_sigqueue_tail	0x0000059c
+#define AOFF_task_sigqueue_tail	0x00000598
 #define ASIZ_task_sigqueue_tail	0x00000004
-#define AOFF_task_sas_ss_sp	0x000005a0
+#define AOFF_task_sas_ss_sp	0x0000059c
 #define ASIZ_task_sas_ss_sp	0x00000004
-#define AOFF_task_sas_ss_size	0x000005a4
+#define AOFF_task_sas_ss_size	0x000005a0
 #define ASIZ_task_sas_ss_size	0x00000004
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000004
@@ -195,48 +195,48 @@
 #define AOFF_mm_map_count	0x00000018
 #define ASIZ_mm_map_count	0x00000004
 #define AOFF_mm_mmap_sem	0x0000001c
-#define ASIZ_mm_mmap_sem	0x00000020
-#define AOFF_mm_page_table_lock	0x0000003c
-#define ASIZ_mm_page_table_lock	0x00000001
-#define AOFF_mm_context	0x00000040
+#define ASIZ_mm_mmap_sem	0x0000001c
+#define AOFF_mm_page_table_lock	0x00000038
+#define ASIZ_mm_page_table_lock	0x00000000
+#define AOFF_mm_context	0x00000038
 #define ASIZ_mm_context	0x00000004
-#define AOFF_mm_start_code	0x00000044
+#define AOFF_mm_start_code	0x0000003c
 #define ASIZ_mm_start_code	0x00000004
-#define AOFF_mm_end_code	0x00000048
+#define AOFF_mm_end_code	0x00000040
 #define ASIZ_mm_end_code	0x00000004
-#define AOFF_mm_start_data	0x0000004c
+#define AOFF_mm_start_data	0x00000044
 #define ASIZ_mm_start_data	0x00000004
-#define AOFF_mm_end_data	0x00000050
+#define AOFF_mm_end_data	0x00000048
 #define ASIZ_mm_end_data	0x00000004
-#define AOFF_mm_start_brk	0x00000054
+#define AOFF_mm_start_brk	0x0000004c
 #define ASIZ_mm_start_brk	0x00000004
-#define AOFF_mm_brk	0x00000058
+#define AOFF_mm_brk	0x00000050
 #define ASIZ_mm_brk	0x00000004
-#define AOFF_mm_start_stack	0x0000005c
+#define AOFF_mm_start_stack	0x00000054
 #define ASIZ_mm_start_stack	0x00000004
-#define AOFF_mm_arg_start	0x00000060
+#define AOFF_mm_arg_start	0x00000058
 #define ASIZ_mm_arg_start	0x00000004
-#define AOFF_mm_arg_end	0x00000064
+#define AOFF_mm_arg_end	0x0000005c
 #define ASIZ_mm_arg_end	0x00000004
-#define AOFF_mm_env_start	0x00000068
+#define AOFF_mm_env_start	0x00000060
 #define ASIZ_mm_env_start	0x00000004
-#define AOFF_mm_env_end	0x0000006c
+#define AOFF_mm_env_end	0x00000064
 #define ASIZ_mm_env_end	0x00000004
-#define AOFF_mm_rss	0x00000070
+#define AOFF_mm_rss	0x00000068
 #define ASIZ_mm_rss	0x00000004
-#define AOFF_mm_total_vm	0x00000074
+#define AOFF_mm_total_vm	0x0000006c
 #define ASIZ_mm_total_vm	0x00000004
-#define AOFF_mm_locked_vm	0x00000078
+#define AOFF_mm_locked_vm	0x00000070
 #define ASIZ_mm_locked_vm	0x00000004
-#define AOFF_mm_def_flags	0x0000007c
+#define AOFF_mm_def_flags	0x00000074
 #define ASIZ_mm_def_flags	0x00000004
-#define AOFF_mm_cpu_vm_mask	0x00000080
+#define AOFF_mm_cpu_vm_mask	0x00000078
 #define ASIZ_mm_cpu_vm_mask	0x00000004
-#define AOFF_mm_swap_cnt	0x00000084
+#define AOFF_mm_swap_cnt	0x0000007c
 #define ASIZ_mm_swap_cnt	0x00000004
-#define AOFF_mm_swap_address	0x00000088
+#define AOFF_mm_swap_address	0x00000080
 #define ASIZ_mm_swap_address	0x00000004
-#define AOFF_mm_segments	0x0000008c
+#define AOFF_mm_segments	0x00000084
 #define ASIZ_mm_segments	0x00000004
 #define AOFF_thread_uwinmask	0x00000000
 #define ASIZ_thread_uwinmask	0x00000004
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/audioio.h linux/include/asm-sparc/audioio.h
--- v2.3.34/linux/include/asm-sparc/audioio.h	Tue Sep  7 12:14:07 1999
+++ linux/include/asm-sparc/audioio.h	Mon Dec 20 22:05:52 1999
@@ -271,7 +271,7 @@
         int index; 
 
         /* This device */
-        struct linux_sbus_device *dev;
+        struct sbus_dev *dev;
 
 	/* Processes blocked on open() sit here. */
 	wait_queue_head_t open_wait;
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/div64.h linux/include/asm-sparc/div64.h
--- v2.3.34/linux/include/asm-sparc/div64.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/div64.h	Mon Dec 20 22:05:52 1999
@@ -0,0 +1,11 @@
+#ifndef __SPARC_DIV64
+#define __SPARC_DIV64
+
+/* We're not 64-bit, but... */
+#define do_div(n,base) ({ \
+	int __res; \
+	__res = ((unsigned long) n) % (unsigned) base; \
+	n = ((unsigned long) n) / (unsigned) base; \
+	__res; })
+
+#endif /* __SPARC_DIV64 */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/dma.h linux/include/asm-sparc/dma.h
--- v2.3.34/linux/include/asm-sparc/dma.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc/dma.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: dma.h,v 1.31 1999/09/10 10:44:15 davem Exp $
+/* $Id: dma.h,v 1.34 1999/10/24 16:01:21 zaitcev Exp $
  * include/asm-sparc/dma.h
  *
  * Copyright 1995 (C) David S. Miller (davem@caip.rutgers.edu)
@@ -44,13 +44,11 @@
 #define SIZE_16MB      (16*1024*1024)
 #define SIZE_64K       (64*1024)
 
-/* Structure to describe the current status of DMA registers on the Sparc */
-struct sparc_dma_registers {
-  __volatile__ __u32 cond_reg;	/* DMA condition register */
-  __volatile__ __u32 st_addr;	/* Start address of this transfer */
-  __volatile__ __u32 cnt;	/* How many bytes to transfer */
-  __volatile__ __u32 dma_test;	/* DMA test register */
-};
+/* SBUS DMA controller reg offsets */
+#define DMA_CSR		0x00UL		/* rw  DMA control/status register    0x00   */
+#define DMA_ADDR	0x04UL		/* rw  DMA transfer address register  0x04   */
+#define DMA_COUNT	0x08UL		/* rw  DMA transfer count register    0x08   */
+#define DMA_TEST	0x0cUL		/* rw  DMA test/debug register        0x0c   */
 
 /* DVMA chip revisions */
 enum dvma_rev {
@@ -66,10 +64,10 @@
 #define DMA_HASCOUNT(rev)  ((rev)==dvmaesc1)
 
 /* Linux DMA information structure, filled during probe. */
-struct Linux_SBus_DMA {
-	struct Linux_SBus_DMA *next;
-	struct linux_sbus_device *SBus_dev;
-	struct sparc_dma_registers *regs;
+struct sbus_dma {
+	struct sbus_dma *next;
+	struct sbus_dev *sdev;
+	unsigned long regs;
 
 	/* Status, misc info */
 	int node;                /* Prom node for this DMA device */
@@ -85,7 +83,7 @@
 	enum dvma_rev revision;
 };
 
-extern struct Linux_SBus_DMA *dma_chain;
+extern struct sbus_dma *dma_chain;
 
 /* Broken hardware... */
 #ifdef CONFIG_SUN4
@@ -98,7 +96,7 @@
 #define DMA_ISESC1(dma)      ((dma)->revision == dvmaesc1)
 
 /* Main routines in dma.c */
-extern void dvma_init(struct linux_sbus *);
+extern void dvma_init(struct sbus_bus *);
 
 /* Fields in the cond_reg register */
 /* First, the version identification bits */
@@ -133,7 +131,9 @@
 #define DMA_SCSI_DISAB   0x00020000        /* No FIFO drains during reg */
 #define DMA_DSBL_WR_INV  0x00020000        /* No EC inval. on slave writes */
 #define DMA_ADD_ENABLE   0x00040000        /* Special ESC DVMA optimization */
-#define DMA_E_BURST8	 0x00040000	   /* ENET: SBUS r/w burst size */
+#define DMA_E_BURSTS	 0x000c0000	   /* ENET: SBUS r/w burst mask */
+#define DMA_E_BURST32	 0x00040000	   /* ENET: SBUS 32 byte r/w burst */
+#define DMA_E_BURST16	 0x00000000	   /* ENET: SBUS 16 byte r/w burst */
 #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/BPP: 32byte bursts */
@@ -192,6 +192,7 @@
 	if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \
    } while(0)
 
+#if 0	/* P3 this stuff is inline in ledma.c:init_restart_ledma() */
 /* Pause until counter runs out or BIT isn't set in the DMA condition
  * register.
  */
@@ -225,6 +226,7 @@
 	if(dma->revision>dvmarev1) regs->cond_reg |= DMA_3CLKS;            \
 	dma->running = 0;                                                  \
 } while(0)
+#endif
 
 #define for_each_dvma(dma) \
         for((dma) = dma_chain; (dma); (dma) = (dma)->next)
@@ -232,5 +234,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_SPARC_DMA_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/ebus.h linux/include/asm-sparc/ebus.h
--- v2.3.34/linux/include/asm-sparc/ebus.h	Sun Oct  4 10:22:44 1998
+++ linux/include/asm-sparc/ebus.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ebus.h,v 1.1 1998/09/22 05:54:41 jj Exp $
+/* $Id: ebus.h,v 1.2 1999/09/11 23:05:55 zaitcev Exp $
  * ebus.h: PCI to Ebus pseudo driver software state.
  *
  * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) 
@@ -9,6 +9,9 @@
 #ifndef __SPARC_EBUS_H
 #define __SPARC_EBUS_H
 
+#ifndef _LINUX_IOPORT_H
+#include <linux/ioport.h>
+#endif
 #include <asm/oplib.h>
 
 struct linux_ebus_child {
@@ -17,7 +20,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;
@@ -29,7 +32,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;
@@ -91,11 +94,5 @@
 
 #define for_each_edevchild(dev, child)					\
         for((child) = (dev)->children; (child); (child) = (child)->next)
-
-/* P3: Actually unused in sparc */
-#define for_all_ebusdev(dev, bus)					\
-	for ((bus) = ebus_chain, ((dev) = (bus) ? (bus)->devices : 0);	\
-	     (bus); ((dev) = (dev)->next ? (dev)->next :		\
-	     ((bus) = (bus)->next, (bus) ? (bus)->devices : 0)))
 
 #endif /* !(__SPARC_EBUS_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/floppy.h linux/include/asm-sparc/floppy.h
--- v2.3.34/linux/include/asm-sparc/floppy.h	Thu Apr 22 19:24:51 1999
+++ linux/include/asm-sparc/floppy.h	Mon Dec 20 22:05:52 1999
@@ -286,6 +286,7 @@
 {
 	char state[128];
 	int tnode, fd_node, num_regs;
+	struct resource r;
 
 	use_virtual_dma = 1;
 	
@@ -322,12 +323,11 @@
 	num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs, sizeof(fd_regs));
 	num_regs = (num_regs / sizeof(fd_regs[0]));
 	prom_apply_obio_ranges(fd_regs, num_regs);
-	sun_fdc = (struct sun_flpy_controller *) sparc_alloc_io(fd_regs[0].phys_addr,
-								0x0,
-								fd_regs[0].reg_size,
-								"floppy",
-								fd_regs[0].which_io,
-								0x0);
+	memset(&r, 0, sizeof(r));
+	r.flags = fd_regs[0].which_io;
+	r.start = fd_regs[0].phys_addr;
+	sun_fdc = (struct sun_flpy_controller *)
+	    sbus_ioremap(&r, 0, fd_regs[0].reg_size, "floppy");
 
 	/* Last minute sanity check... */
 	if(sun_fdc->status_82072 == 0xff) {
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/head.h linux/include/asm-sparc/head.h
--- v2.3.34/linux/include/asm-sparc/head.h	Thu Apr 22 19:24:52 1999
+++ linux/include/asm-sparc/head.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: head.h,v 1.36 1999/04/20 13:22:42 anton Exp $ */
+/* $Id: head.h,v 1.38 1999/12/01 23:52:04 davem Exp $ */
 #ifndef __SPARC_HEAD_H
 #define __SPARC_HEAD_H
 
@@ -53,6 +53,12 @@
         b linux_sparc_syscall; \
         or %l7, %lo(C_LABEL(sunos_sys_table)), %l7;
 
+#define SUNOS_NO_SYSCALL_TRAP \
+        b sunos_syscall; \
+        rd %psr, %l0; \
+        nop; \
+        nop;
+
 /* Software trap for Slowaris system calls. */
 #define SOLARIS_SYSCALL_TRAP \
         b solaris_syscall; \
@@ -86,6 +92,10 @@
 /* The Set Condition Codes software trap for userland. */
 #define SETCC_TRAP \
         b setcc_trap_handler; mov %psr, %l0; nop; nop;
+
+/* The Get PSR software trap for userland. */
+#define GETPSR_TRAP \
+	mov %psr, %o0; jmpl %l2, %g0; rett %l2 + 4; nop;
 
 /* This is for hard interrupts from level 1-14, 15 is non-maskable (nmi) and
  * gets handled with another macro.
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/io-unit.h linux/include/asm-sparc/io-unit.h
--- v2.3.34/linux/include/asm-sparc/io-unit.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc/io-unit.h	Mon Dec 20 22:05:52 1999
@@ -55,8 +55,8 @@
 #define IOUNIT_BMAPM_START	IOUNIT_BMAP2_END
 #define IOUNIT_BMAPM_END	((IOUNIT_DMA_SIZE - IOUNIT_DVMA_SIZE) >> PAGE_SHIFT)
 
-extern __u32 iounit_map_dma_init(struct linux_sbus *, int);
+extern __u32 iounit_map_dma_init(struct sbus_bus *, int);
 #define iounit_map_dma_finish(sbus, addr, len) mmu_release_scsi_one(addr, len, sbus)
-extern __u32 iounit_map_dma_page(__u32, void *, struct linux_sbus *);
+extern __u32 iounit_map_dma_page(__u32, void *, struct sbus_bus *);
 
 #endif /* !(_SPARC_IO_UNIT_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/io.h linux/include/asm-sparc/io.h
--- v2.3.34/linux/include/asm-sparc/io.h	Tue Dec  7 09:32:51 1999
+++ linux/include/asm-sparc/io.h	Mon Dec 20 22:05:52 1999
@@ -1,165 +1,153 @@
-/* $Id: io.h,v 1.20 1999/06/03 15:02:50 davem Exp $ */
+/*
+ * $Id: io.h,v 1.24 1999/12/20 04:58:40 davem Exp $
+ */
 #ifndef __SPARC_IO_H
 #define __SPARC_IO_H
 
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/ioport.h>  /* struct resource */
 
 #include <asm/page.h>      /* IO address mapping routines need this */
 #include <asm/system.h>
 
-/*
- * Defines for io operations on the Sparc. Whether a memory access is going
- * to i/o sparc is encoded in the pte. The type bits determine whether this
- * is i/o sparc, on board memory, or VME space for VME cards. I think VME
- * space only works on sun4's
- */
-
 #define virt_to_bus virt_to_phys
 
+
 extern __inline__ unsigned  flip_dword (unsigned d) {
-        return ((d&0xff)<<24) | (((d>>8)&0xff)<<16) | (((d>>16)&0xff)<<8)| ((d>>24)&0xff);
+	return ((d&0xff)<<24) | (((d>>8)&0xff)<<16) | (((d>>16)&0xff)<<8)| ((d>>24)&0xff);
 }
 
 extern __inline__ unsigned short flip_word (unsigned short d) {
-        return ((d&0xff) << 8) | ((d>>8)&0xff);
+	return ((d&0xff) << 8) | ((d>>8)&0xff);
 }
 
-extern __inline__ unsigned long readb(unsigned long addr)
-{
-       return *(volatile unsigned char*)addr;
+/*
+ * Memory mapped I/O to PCI
+ */
+extern __inline__ unsigned long readb(unsigned long addr) {
+	return *(volatile unsigned char*)addr;
 }
 
-extern __inline__ unsigned long readw(unsigned long addr)
-{
-       return flip_word(*(volatile unsigned short*)addr);
+extern __inline__ unsigned long readw(unsigned long addr) {
+	return flip_word(*(volatile unsigned short*)addr);
 }
 
-extern __inline__ unsigned long readl(unsigned long addr)
-{
-       return flip_dword(*(volatile unsigned long*)addr);
+extern __inline__ unsigned long readl(unsigned long addr) {
+	return flip_dword(*(volatile unsigned long*)addr);
 }
 
-extern __inline__ void writeb(unsigned short b, unsigned long addr)
-{
-       *(volatile unsigned char*)addr = b;
+extern __inline__ void writeb(unsigned char b, unsigned long addr) {
+	*(volatile unsigned char*)addr = b;
 }
 
-extern __inline__ void writew(unsigned short b, unsigned long addr)
-{
-       *(volatile unsigned short*)addr = flip_word(b);
+extern __inline__ void writew(unsigned short b, unsigned long addr) {
+	*(volatile unsigned short*)addr = flip_word(b);
 }
 
-extern __inline__ void writel(unsigned int b, unsigned long addr)
-{
-        *(volatile unsigned long*)addr = flip_dword(b);
+extern __inline__ void writel(unsigned int b, unsigned long addr) {
+	*(volatile unsigned long*)addr = flip_dword(b);
 }
 
-extern __inline__ unsigned long inb_local(unsigned long addr)
-{
-       return readb(addr);
-}
+/*
+ * I/O space operations
+ *
+ * Arrangement on a Sun is somewhat complicated.
+ *
+ * First of all, we want to use standard Linux drivers
+ * for keyboard, PC serial, etc. These drivers think
+ * they access I/O space and use inb/outb.
+ * On the other hand, EBus bridge accepts PCI *memory*
+ * cycles and converts them into ISA *I/O* cycles.
+ * Ergo, we want inb & outb to generate PCI memory cycles.
+ *
+ * If we want to issue PCI *I/O* cycles, we do this
+ * with a low 64K fixed window in PCIC. This window gets
+ * mapped somewhere into virtual kernel space and we
+ * can use inb/outb again.
+ */
+#define inb_local(addr)		readb(addr)
+#define inb(addr)		readb(addr)
+#define inw(addr)		readw(addr)
+#define inl(addr)		readl(addr)
+#define inb_p(addr)		readb(addr)
+
+#define outb_local(b, addr)	writeb(b, addr)
+#define outb(b, addr)		writeb(b, addr)
+#define outw(b, addr)		writew(b, addr)
+#define outl(b, addr)		writel(b, addr)
+#define outb_p(b, addr)		writeb(b, addr)
 
-extern __inline__ void outb_local(unsigned char b, unsigned long addr)
-{
-       return writeb(b,addr);
-}
+#define IO_SPACE_LIMIT 0xffffffff
 
-extern __inline__ unsigned long inb(unsigned long addr)
-{
-       return readb(addr);
+/*
+ * SBus accessors.
+ *
+ * SBus has only one, memory mapped, I/O space.
+ * We do not need to flip bytes for SBus of course.
+ */
+extern __inline__ unsigned int _sbus_readb(unsigned long addr) {
+	return *(volatile unsigned char*)addr;
 }
 
-extern __inline__ unsigned long inw(unsigned long addr)
-{
-       return readw(addr);
+extern __inline__ unsigned int _sbus_readw(unsigned long addr) {
+	return *(volatile unsigned short*)addr;
 }
 
-extern __inline__ unsigned long inl(unsigned long addr)
-{
-       return readl(addr);
+extern __inline__ unsigned int _sbus_readl(unsigned long addr) {
+	return *(volatile unsigned long*)addr;
 }
 
-extern __inline__ void outb(unsigned char b, unsigned long addr)
-{
-       return writeb(b,addr);
+extern __inline__ void _sbus_writeb(unsigned char b, unsigned long addr) {
+	*(volatile unsigned char*)addr = b;
 }
 
-extern __inline__ void outw(unsigned short b, unsigned long addr)
-{
-       return writew(b,addr);
+extern __inline__ void _sbus_writew(unsigned short b, unsigned long addr) {
+	*(volatile unsigned short*)addr = b;
 }
 
-extern __inline__ void outl(unsigned int b, unsigned long addr)
-{
-       return writel(b,addr);
+extern __inline__ void _sbus_writel(unsigned int b, unsigned long addr) {
+	*(volatile unsigned long*)addr = b;
 }
 
-#define inb_p inb
-#define outb_p outb
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-extern void sun4c_mapioaddr(unsigned long, unsigned long, int bus_type, int rdonly);
-extern void srmmu_mapioaddr(unsigned long, unsigned long, int bus_type, int rdonly);
-
-extern __inline__ void mapioaddr(unsigned long physaddr, unsigned long virt_addr,
-				 int bus, int rdonly)
-{
-	switch(sparc_cpu_model) {
-	case sun4c:
-	case sun4:
-		sun4c_mapioaddr(physaddr, virt_addr, bus, rdonly);
-		break;
-	case sun4m:
-	case sun4d:
-	case sun4e:
-		srmmu_mapioaddr(physaddr, virt_addr, bus, rdonly);
-		break;
-	default:
-		printk("mapioaddr: Trying to map IO space for unsupported machine.\n");
-		printk("mapioaddr: sparc_cpu_model = %d\n", sparc_cpu_model);
-		printk("mapioaddr: Halting...\n");
-		halt();
-	};
-	return;
+/*
+ * The only reason for #define's is to hide casts to unsigned long.
+ * XXX Rewrite drivers without structures for registers.
+ */
+#define sbus_readb(a)	_sbus_readb((unsigned long)(a))
+#define sbus_readw(a)	_sbus_readw((unsigned long)(a))
+#define sbus_readl(a)	_sbus_readl((unsigned long)(a))
+#define sbus_writeb(v, a)	_sbus_writeb(v, (unsigned long)(a))
+#define sbus_writew(v, a)	_sbus_writew(v, (unsigned long)(a))
+#define sbus_writel(v, a)	_sbus_writel(v, (unsigned long)(a))
+
+static inline void *sbus_memset_io(void *__dst, int c, __kernel_size_t n)
+{
+	unsigned long dst = (unsigned long)__dst;
+
+	while(n--) {
+		sbus_writeb(c, dst);
+		dst++;
+	}
+	return (void *) dst;
 }
 
-extern void srmmu_unmapioaddr(unsigned long virt);
-extern void sun4c_unmapioaddr(unsigned long virt);
-
-extern __inline__ void unmapioaddr(unsigned long virt_addr)
-{
-	switch(sparc_cpu_model) {
-	case sun4c:
-	case sun4:
-		sun4c_unmapioaddr(virt_addr);
-		break;
-	case sun4m:
-	case sun4d:
-	case sun4e:
-		srmmu_unmapioaddr(virt_addr);
-		break;
-	default:
-		printk("unmapioaddr: sparc_cpu_model = %d, halt...\n", sparc_cpu_model);
-		halt();
-	};
-	return;
-}
-
-extern void *sparc_alloc_io (u32 pa, void *va, int sz, char *name, u32 io, int rdonly);
-extern void sparc_free_io (void *vaddr, int sz);
-extern void *_sparc_dvma_malloc (int sz, char *name);
+/*
+ * Bus number may be embedded in the higher bits of the physical address.
+ * This is why we have no bus number argument to ioremap().
+ */
+extern void *ioremap(unsigned long offset, unsigned long size);
+extern void iounmap(void *addr);
 
-/* Returns CPU visible address, dvmaaddr_p is a pointer to where
- * the DVMA visible (ie. SBUS/PSYCO+PCI) address should be stored.
+/* P3: talk davem into dropping "name" argument in favor of res->name */
+/*
+ * Bus number may be in res->flags... somewhere.
  */
-static __inline__ void *sparc_dvma_malloc(int size, char *name, __u32 *dvmaaddr_p)
-{
-	void *cpuaddr = _sparc_dvma_malloc(size, name);
-	*dvmaaddr_p = (__u32) cpuaddr;
-	return cpuaddr;
-}
+extern unsigned long sbus_ioremap(struct resource *res, unsigned long offset,
+    unsigned long size, char *name);
+/* XXX Partial deallocations? I think not! */
+extern void sbus_iounmap(unsigned long vaddr, unsigned long size);
+
 
 #define virt_to_phys(x) __pa((unsigned long)(x))
 #define phys_to_virt(x) __va((unsigned long)(x))
@@ -169,11 +157,11 @@
  * so rtc_port is static in it. This should not change unless a new
  * hardware pops up.
  */
-
 #define RTC_PORT(x)   (rtc_port + (x))
 #define RTC_ALWAYS_BCD  0
 
 /* Nothing to do */
+/* P3: Only IDE DMA may need these. */
 
 #define dma_cache_inv(_start,_size)		do { } while (0)
 #define dma_cache_wback(_start,_size)		do { } while (0)
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/ioctl.h linux/include/asm-sparc/ioctl.h
--- v2.3.34/linux/include/asm-sparc/ioctl.h	Sat Nov  9 00:29:28 1996
+++ linux/include/asm-sparc/ioctl.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ioctl.h,v 1.5 1996/05/17 03:31:09 davem Exp $ */
+/* $Id: ioctl.h,v 1.6 1999/12/01 23:58:36 davem Exp $ */
 #ifndef _SPARC_IOCTL_H
 #define _SPARC_IOCTL_H
 
@@ -39,5 +39,13 @@
 #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 PCMCIA... */
+
+#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 /* !(_SPARC_IOCTL_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/ipc.h linux/include/asm-sparc/ipc.h
--- v2.3.34/linux/include/asm-sparc/ipc.h	Thu Dec 19 01:03:37 1996
+++ linux/include/asm-sparc/ipc.h	Mon Dec 20 22:05:52 1999
@@ -23,6 +23,9 @@
 #define SHMGET		23
 #define SHMCTL		24
 
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC            25
+
 #define IPCCALL(version,op)	((version)<<16 | (op))
 
 #endif
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/jsflash.h linux/include/asm-sparc/jsflash.h
--- v2.3.34/linux/include/asm-sparc/jsflash.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/jsflash.h	Mon Dec 20 22:05:52 1999
@@ -0,0 +1,39 @@
+/*
+ * jsflash.h: OS Flash SIMM support for JavaStations.
+ *
+ * Copyright (C) 1999  Pete Zaitcev
+ */
+
+#ifndef _SPARC_JSFLASH_H
+#define _SPARC_JSFLASH_H
+
+#ifndef _SPARC_TYPES_H
+#include <asm/types.h>
+#endif
+
+/*
+ * Semantics of the offset is a full address.
+ * Hardcode it or get it from probe ioctl.
+ *
+ * We use full bus address, so that we would be
+ * automatically compatible with possible future systems.
+ */
+
+#define JSFLASH_IDENT   (('F'<<8)|54)
+struct jsflash_ident_arg {
+	__u64 off;                /* 0x20000000 is included */
+	__u32 size;
+	char name[32];		/* With trailing zero */
+};
+
+#define JSFLASH_ERASE   (('F'<<8)|55)
+/* Put 0 as argument, may be flags or sector number... */
+
+#define JSFLASH_PROGRAM (('F'<<8)|56)
+struct jsflash_program_arg {
+	__u64 data;		/* char* for sparc and sparc64 */
+	__u64 off;
+	__u32 size;
+};
+
+#endif /* _SPARC_IDE_H */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/keyboard.h linux/include/asm-sparc/keyboard.h
--- v2.3.34/linux/include/asm-sparc/keyboard.h	Mon Oct 11 15:38:15 1999
+++ linux/include/asm-sparc/keyboard.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: keyboard.h,v 1.2 1999/04/28 11:59:07 davem Exp $
+/* $Id: keyboard.h,v 1.3 1999/11/23 08:56:44 davem Exp $
  * linux/include/asm-sparc/keyboard.h
  *
  * sparc64 Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be)
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/mmu_context.h linux/include/asm-sparc/mmu_context.h
--- v2.3.34/linux/include/asm-sparc/mmu_context.h	Sun Jul 25 13:45:25 1999
+++ linux/include/asm-sparc/mmu_context.h	Mon Dec 20 22:05:52 1999
@@ -3,28 +3,32 @@
 
 #include <asm/btfixup.h>
 
-/* For now I still leave the context handling in the
- * switch_to() macro, I'll do it right soon enough.
- */
-#define get_mmu_context(x) do { } while (0)
+#ifndef __ASSEMBLY__
 
-/* Initialize the context related info for a new mm_struct
- * instance.
+/*
+ * Initialize a new mmu context.  This is invoked when a new
+ * address space instance (unique or shared) is instantiated.
  */
-BTFIXUPDEF_CALL(void, init_new_context, struct mm_struct *)
-
-#define init_new_context(mm) BTFIXUP_CALL(init_new_context)(mm)
+#define init_new_context(tsk, mm) ((mm)->context = NO_CONTEXT)
 
-/* Destroy context related info for an mm_struct that is about
- * to be put to rest.
+/*
+ * Destroy a dead context.  This occurs when mmput drops the
+ * mm_users count to zero, the mmaps have been released, and
+ * all the page tables have been flushed.  Our job is to destroy
+ * any remaining processor-specific state.
  */
 BTFIXUPDEF_CALL(void, destroy_context, struct mm_struct *)
 
 #define destroy_context(mm) BTFIXUP_CALL(destroy_context)(mm)
 
-/* This need not do anything on Sparc32.  The switch happens
- * properly later as a side effect of calling flush_thread.
- */
-#define activate_context(tsk)	do { } while(0)
+/* Switch the current MM context. */
+BTFIXUPDEF_CALL(void, switch_mm, struct mm_struct *, struct mm_struct *, struct task_struct *, int)
+
+#define switch_mm(old_mm, mm, tsk, cpu) BTFIXUP_CALL(switch_mm)(old_mm, mm, tsk, cpu)
+
+/* Activate a new MM instance for the current task. */
+#define activate_mm(active_mm, mm) switch_mm((active_mm), (mm), NULL, smp_processor_id())
+
+#endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC_MMU_CONTEXT_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/openpromio.h linux/include/asm-sparc/openpromio.h
--- v2.3.34/linux/include/asm-sparc/openpromio.h	Sat Nov  9 11:55:01 1996
+++ linux/include/asm-sparc/openpromio.h	Mon Dec 20 22:05:52 1999
@@ -29,6 +29,10 @@
 #define	OPROMGETCONS		0x20004F0A
 #define	OPROMGETFBNAME		0x20004F0B
 #define	OPROMGETBOOTARGS	0x20004F0C
+/* Linux extensions */				/* Arguments in oprom_array: */
+#define OPROMSETCUR		0x20004FF0	/* int node - Sets current node */
+#define OPROMPCI2NODE		0x20004FF1	/* int pci_bus, pci_devfn - Sets current node to PCI device's node */
+#define OPROMPATH2NODE		0x20004FF2	/* char path[] - Set current node from fully qualified PROM path */
 
 /*
  * Return values from OPROMGETCONS:
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/pbm.h linux/include/asm-sparc/pbm.h
--- v2.3.34/linux/include/asm-sparc/pbm.h	Sun Oct  4 10:22:44 1998
+++ linux/include/asm-sparc/pbm.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,5 @@
-/* $Id: pbm.h,v 1.1 1998/09/22 05:54:44 jj Exp $
+/* $Id: pbm.h,v 1.3 1999/12/20 17:06:35 zaitcev Exp $
+ *
  * pbm.h: PCI bus module pseudo driver software state
  *        Adopted from sparc64 by V. Roganov and G. Raiko
  *
@@ -6,6 +7,14 @@
  * pbm.h: U2P PCI bus module pseudo driver software state.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * To put things into perspective, consider sparc64 with a few PCI controllers.
+ * Each type would have an own structure, with instances related one to one.
+ * We have only pcic on sparc, but we want to be compatible with sparc64 pbm.h.
+ * All three represent different abstractions.
+ *   pci_bus  - Linux PCI subsystem view of a PCI bus (including bridged buses)
+ *   pbm      - Arch-specific view of a PCI bus (sparc or sparc64)
+ *   pcic     - Chip-specific information for PCIC.
  */
 
 #ifndef __SPARC_PBM_H
@@ -14,34 +23,15 @@
 #include <linux/pci.h>
 #include <asm/oplib.h>
 
-struct linux_pbm_info;
-
-/* 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;
-};
-
 struct linux_pbm_info {
-	struct pci_vma			*IO_assignments;
-	struct pci_vma			*MEM_assignments;
-	int				prom_node;
-	char				prom_name[64];
-	struct linux_prom_pci_ranges	pbm_ranges[PROMREG_MAX];
-	int				num_pbm_ranges;
+	int		prom_node;
+	char		prom_name[64];
+	/* struct linux_prom_pci_ranges	pbm_ranges[PROMREG_MAX]; */
+	/* int		num_pbm_ranges; */
 
 	/* Now things for the actual PCI bus probes. */
-	unsigned int			pci_first_busno;
-	unsigned int			pci_last_busno;
-	struct pci_bus			pci_bus;
+	unsigned int	pci_first_busno;	/* Can it be nonzero? */
+	struct pci_bus	*pci_bus;		/* Was inline, MJ allocs now */
 };
 
 /* PCI devices which are not bridges have this placed in their pci_dev
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/pcic.h linux/include/asm-sparc/pcic.h
--- v2.3.34/linux/include/asm-sparc/pcic.h	Wed Jun  9 14:44:26 1999
+++ linux/include/asm-sparc/pcic.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: pcic.h,v 1.2 1999/06/03 15:02:51 davem Exp $
+/* $Id: pcic.h,v 1.4 1999/11/17 07:34:20 zaitcev Exp $
  * pcic.h: JavaEngine 1 specific PCI definitions.
  *
  * Copyright (C) 1998 V. Roganov and G. Raiko
@@ -13,22 +13,26 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/pci.h>
+#include <linux/ioport.h>
 #include <asm/pbm.h>
 
 struct linux_pcic {
         unsigned long           pcic_regs;
         unsigned long           pcic_io;
-        unsigned long           pcic_io_phys;
-        unsigned long           pcic_mapped_io;
         unsigned long           pcic_config_space_addr;
         unsigned long           pcic_config_space_data;
+	struct resource		pcic_res_regs;
+	struct resource		pcic_res_io;
+	struct resource		pcic_res_cfg_addr;
+	struct resource		pcic_res_cfg_data;
         struct linux_pbm_info   pbm;
 	struct pcic_ca2irq	*pcic_imap;
 	int			pcic_imdim;
 };
 
-extern unsigned long pcic_alloc_io(unsigned long* addr);
-extern void pcic_probe(void);
+extern int pcic_probe(void);
+/* Erm... MJ redefined pcibios_present() so that it does not work early. */
+extern int pcic_present(void);
 extern void sun4m_pci_init_IRQ(void);
 
 #endif
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/pgtable.h linux/include/asm-sparc/pgtable.h
--- v2.3.34/linux/include/asm-sparc/pgtable.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc/pgtable.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.82 1999/09/10 10:44:21 davem Exp $ */
+/* $Id: pgtable.h,v 1.86 1999/12/16 14:41:19 anton Exp $ */
 #ifndef _SPARC_PGTABLE_H
 #define _SPARC_PGTABLE_H
 
@@ -32,10 +32,6 @@
 
 #define quick_kernel_fault(addr) BTFIXUP_CALL(quick_kernel_fault)(addr)
 
-/* Allocate a block of RAM which is aligned to its size.
-   This procedure can be used until the call to mem_init(). */
-extern void *sparc_init_alloc(unsigned long *kbrk, unsigned long size);
-
 /* Routines for data transfer buffers. */
 BTFIXUPDEF_CALL(char *, mmu_lockarea, char *, unsigned long)
 BTFIXUPDEF_CALL(void,   mmu_unlockarea, char *, unsigned long)
@@ -43,25 +39,27 @@
 #define mmu_lockarea(vaddr,len) BTFIXUP_CALL(mmu_lockarea)(vaddr,len)
 #define mmu_unlockarea(vaddr,len) BTFIXUP_CALL(mmu_unlockarea)(vaddr,len)
 
-/* Routines for getting a dvma scsi buffer. */
-struct mmu_sglist {
-	char *addr;
-	char *__dont_touch;
-	unsigned int len;
-	__u32 dvma_addr;
-};
-BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, char *, unsigned long, struct linux_sbus *sbus)
-BTFIXUPDEF_CALL(void,  mmu_get_scsi_sgl, struct mmu_sglist *, int, struct linux_sbus *sbus)
-BTFIXUPDEF_CALL(void,  mmu_release_scsi_one, __u32, unsigned long, struct linux_sbus *sbus)
-BTFIXUPDEF_CALL(void,  mmu_release_scsi_sgl, struct mmu_sglist *, int, struct linux_sbus *sbus)
-BTFIXUPDEF_CALL(void,  mmu_map_dma_area, unsigned long addr, int len)
+/* These are implementations for sbus_map_sg/sbus_unmap_sg... collapse later */
+BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, char *, unsigned long, struct sbus_bus *sbus)
+BTFIXUPDEF_CALL(void,  mmu_get_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus)
+BTFIXUPDEF_CALL(void,  mmu_release_scsi_one, __u32, unsigned long, struct sbus_bus *sbus)
+BTFIXUPDEF_CALL(void,  mmu_release_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus)
 
 #define mmu_get_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_get_scsi_one)(vaddr,len,sbus)
 #define mmu_get_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_get_scsi_sgl)(sg,sz,sbus)
 #define mmu_release_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_release_scsi_one)(vaddr,len,sbus)
 #define mmu_release_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_release_scsi_sgl)(sg,sz,sbus)
 
-#define mmu_map_dma_area(addr,len) BTFIXUP_CALL(mmu_map_dma_area)(addr,len)
+/* mmu_map/unmap is provided by iommu/iounit; mmu_flush/inval probably belongs to CPU... */
+BTFIXUPDEF_CALL(void,  mmu_map_dma_area, unsigned long va, __u32 addr, int len)
+BTFIXUPDEF_CALL(void,  mmu_unmap_dma_area, unsigned long addr, int len)
+BTFIXUPDEF_CALL(void,  mmu_inval_dma_area, unsigned long addr, int len)
+BTFIXUPDEF_CALL(void,  mmu_flush_dma_area, unsigned long addr, int len)
+
+#define mmu_map_dma_area(va, ba,len) BTFIXUP_CALL(mmu_map_dma_area)(va,ba,len)
+#define mmu_unmap_dma_area(ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(ba,len)
+#define mmu_inval_dma_area(va,len) BTFIXUP_CALL(mmu_unmap_dma_area)(va,len)
+#define mmu_flush_dma_area(va,len) BTFIXUP_CALL(mmu_unmap_dma_area)(va,len)
 
 BTFIXUPDEF_SIMM13(pmd_shift)
 BTFIXUPDEF_SETHI(pmd_size)
@@ -93,6 +91,10 @@
 #define VMALLOC_START (0xfe300000)
 #define VMALLOC_END   ~0x0UL
 
+#define pte_ERROR(e)	__builtin_trap()
+#define pmd_ERROR(e)	__builtin_trap()
+#define pgd_ERROR(e)	__builtin_trap()
+
 BTFIXUPDEF_INT(page_none)
 BTFIXUPDEF_INT(page_shared)
 BTFIXUPDEF_INT(page_copy)
@@ -163,6 +165,12 @@
 
 extern int num_contexts;
 
+/* First physical page can be anywhere, the following is needed so that
+ * va-->pa and vice versa conversions work properly without performance
+ * hit for all __pa()/__va() operations.
+ */
+extern unsigned long phys_base;
+
 /*
  * BAD_PAGETABLE is used when we need a bogus page-table, while
  * BAD_PAGE is used for a bogus page.
@@ -170,14 +178,13 @@
  * 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 pte_t __bad_page(void);
 extern unsigned long empty_zero_page;
 
 #define BAD_PAGETABLE __bad_pagetable()
 #define BAD_PAGE __bad_page()
-#define ZERO_PAGE(vaddr) ((unsigned long)(&(empty_zero_page)))
+#define ZERO_PAGE(vaddr) (mem_map + (((unsigned long)&empty_zero_page - PAGE_OFFSET + phys_base) >> PAGE_SHIFT))
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR      (8*sizeof(unsigned long))
@@ -187,22 +194,14 @@
 
 #define SIZEOF_PTR_LOG2   2
 
-BTFIXUPDEF_CALL_CONST(unsigned long, pte_page, pte_t)
+BTFIXUPDEF_CALL_CONST(unsigned long, pte_pagenr, pte_t)
 BTFIXUPDEF_CALL_CONST(unsigned long, pmd_page, pmd_t)
 BTFIXUPDEF_CALL_CONST(unsigned long, pgd_page, pgd_t)
 
-#define pte_page(pte) BTFIXUP_CALL(pte_page)(pte)
+#define pte_pagenr(pte) BTFIXUP_CALL(pte_pagenr)(pte)
 #define pmd_page(pmd) BTFIXUP_CALL(pmd_page)(pmd)
 #define pgd_page(pgd) BTFIXUP_CALL(pgd_page)(pgd)
 
-BTFIXUPDEF_CALL(void, sparc_update_rootmmu_dir, struct task_struct *, pgd_t *pgdir)
-
-#define SET_PAGE_DIR(tsk,pgdir) BTFIXUP_CALL(sparc_update_rootmmu_dir)(tsk, pgdir)
-       
-/* to find an entry in a page-table */
-#define PAGE_PTR(address) \
-((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-
 BTFIXUPDEF_SETHI(none_mask)
 BTFIXUPDEF_CALL_CONST(int, pte_present, pte_t)
 BTFIXUPDEF_CALL(void, pte_clear, pte_t *)
@@ -294,11 +293,19 @@
 #define pte_mkdirty(pte) BTFIXUP_CALL(pte_mkdirty)(pte)
 #define pte_mkyoung(pte) BTFIXUP_CALL(pte_mkyoung)(pte)
 
+#define page_pte_prot(page, prot)	mk_pte(page, prot)
+#define page_pte(page)			page_pte_prot(page, __pgprot(0))
+
+/* Permanent address of a page. */
+#define page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
+#define pte_page(x) (mem_map+pte_pagenr(x))
+
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
-BTFIXUPDEF_CALL_CONST(pte_t, mk_pte, unsigned long, pgprot_t)
+BTFIXUPDEF_CALL_CONST(pte_t, mk_pte, struct page *, pgprot_t)
+
 BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_phys, unsigned long, pgprot_t)
 BTFIXUPDEF_CALL_CONST(pte_t, mk_pte_io, unsigned long, pgprot_t, int)
 
@@ -428,10 +435,10 @@
 #define local_flush_tlb_range(mm,start,end) BTFIXUP_CALL(local_flush_tlb_range)(mm,start,end)
 #define local_flush_tlb_page(vma,addr) BTFIXUP_CALL(local_flush_tlb_page)(vma,addr)
 
-BTFIXUPDEF_CALL(void, local_flush_page_to_ram, unsigned long)
+BTFIXUPDEF_CALL(void, local_flush_page_to_ram, struct page *)
 BTFIXUPDEF_CALL(void, local_flush_sig_insns, struct mm_struct *, unsigned long)
 
-#define local_flush_page_to_ram(addr) BTFIXUP_CALL(local_flush_page_to_ram)(addr)
+#define local_flush_page_to_ram(page) BTFIXUP_CALL(local_flush_page_to_ram)(page)
 #define local_flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(local_flush_sig_insns)(mm,insn_addr)
 
 extern void smp_flush_cache_all(void);
@@ -447,7 +454,7 @@
 				  unsigned long start,
 				  unsigned long end);
 extern void smp_flush_tlb_page(struct vm_area_struct *mm, unsigned long page);
-extern void smp_flush_page_to_ram(unsigned long page);
+extern void smp_flush_page_to_ram(struct page *page);
 extern void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);
 #endif
 
@@ -472,20 +479,15 @@
 #define flush_tlb_range(mm,start,end) BTFIXUP_CALL(flush_tlb_range)(mm,start,end)
 #define flush_tlb_page(vma,addr) BTFIXUP_CALL(flush_tlb_page)(vma,addr)
 
-BTFIXUPDEF_CALL(void, flush_page_to_ram, unsigned long)
+BTFIXUPDEF_CALL(void, flush_page_to_ram, struct page *)
 BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long)
 
-#define flush_page_to_ram(addr) BTFIXUP_CALL(flush_page_to_ram)(addr)
+#define flush_page_to_ram(page) BTFIXUP_CALL(flush_page_to_ram)(page)
 #define flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(flush_sig_insns)(mm,insn_addr)
 
 /* The permissions for pgprot_val to make a page mapped on the obio space */
 extern unsigned int pg_iobits;
 
-/* MMU context switching. */
-BTFIXUPDEF_CALL(void, switch_to_context, struct task_struct *)
-
-#define switch_to_context(tsk) BTFIXUP_CALL(switch_to_context)(tsk)
-
 /* Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
  * hook is made available.
@@ -577,7 +579,6 @@
 extern unsigned long *sparc_valid_addr_bitmap;
 
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define PageSkip(page)		(test_bit(PG_skip, &(page)->flags))
 #define kern_addr_valid(addr)	(test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
 
 #endif /* !(_SPARC_PGTABLE_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/poll.h linux/include/asm-sparc/poll.h
--- v2.3.34/linux/include/asm-sparc/poll.h	Thu Jan 23 22:40:28 1997
+++ linux/include/asm-sparc/poll.h	Mon Dec 20 22:05:52 1999
@@ -11,6 +11,7 @@
 #define POLLWRNORM	POLLOUT
 #define POLLRDBAND	128
 #define POLLWRBAND	256
+#define POLLMSG		512
 
 struct pollfd {
 	int fd;
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h
--- v2.3.34/linux/include/asm-sparc/processor.h	Thu Nov 11 20:11:52 1999
+++ linux/include/asm-sparc/processor.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.72 1999/08/14 03:52:04 anton Exp $
+/* $Id: processor.h,v 1.73 1999/12/15 14:18:52 davem Exp $
  * include/asm-sparc/processor.h
  *
  * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
@@ -161,7 +161,34 @@
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
-unsigned long get_wchan(struct task_struct *p);
+#define get_wchan(__TSK) \
+({	extern void scheduling_functions_start_here(void); \
+	extern void scheduling_functions_end_here(void); \
+	unsigned long pc, fp, bias = 0; \
+	unsigned long task_base = (unsigned long) (__TSK); \
+        unsigned long __ret = 0; \
+	struct reg_window *rw; \
+	int count = 0; \
+	if (!(__TSK) || (__TSK) == current || \
+            (__TSK)->state == TASK_RUNNING) \
+		goto __out; \
+	fp = (__TSK)->thread.ksp + bias; \
+	do { \
+		/* Bogus frame pointer? */ \
+		if (fp < (task_base + sizeof(struct task_struct)) || \
+		    fp >= (task_base + (2 * PAGE_SIZE))) \
+			break; \
+		rw = (struct reg_window *) fp; \
+		pc = rw->ins[7]; \
+		if (pc < ((unsigned long) scheduling_functions_start_here) || \
+                    pc >= ((unsigned long) scheduling_functions_end_here)) { \
+			__ret = pc; \
+			goto __out; \
+		} \
+		fp = rw->ins[6] + bias; \
+	} while (++count < 16); \
+__out:	__ret; \
+})
 
 #define KSTK_EIP(tsk)  ((tsk)->thread.kregs->pc)
 #define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/resource.h linux/include/asm-sparc/resource.h
--- v2.3.34/linux/include/asm-sparc/resource.h	Tue Dec 14 01:27:24 1999
+++ linux/include/asm-sparc/resource.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: resource.h,v 1.9 1999/08/14 03:52:05 anton Exp $
+/* $Id: resource.h,v 1.11 1999/12/15 17:51:59 jj Exp $
  * resource.h: Resource definitions.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -26,18 +26,23 @@
 
 /*
  * SuS says limits have to be unsigned.
- * Which makes a ton more sense anyway.
+ * We make this unsigned, but keep the
+ * old value.
  */
-#define RLIM_INFINITY	(~0UL)
+#define RLIM_INFINITY	0x7fffffff
 
 #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}, {0, 0},		\
-    {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX}  \
+#define INIT_RLIMITS			\
+{					\
+    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {_STK_LIM, RLIM_INFINITY},		\
+    {       0, RLIM_INFINITY},		\
+    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {INR_OPEN, INR_OPEN}, {0, 0},	\
+    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {RLIM_INFINITY, RLIM_INFINITY}	\
 }
 
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/sbus.h linux/include/asm-sparc/sbus.h
--- v2.3.34/linux/include/asm-sparc/sbus.h	Wed Mar 10 16:53:37 1999
+++ linux/include/asm-sparc/sbus.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: sbus.h,v 1.16 1998/12/16 04:33:52 davem Exp $
+/* $Id: sbus.h,v 1.19 1999/10/25 06:17:56 zaitcev Exp $
  * sbus.h:  Defines for the Sun SBus.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -7,8 +7,11 @@
 #ifndef _SPARC_SBUS_H
 #define _SPARC_SBUS_H
 
+#include <linux/ioport.h>
+
 #include <asm/oplib.h>
 #include <asm/iommu.h>
+#include <asm/scatterlist.h>
 
 /* We scan which devices are on the SBus using the PROM node device
  * tree.  SBus devices are described in two different ways.  You can
@@ -34,77 +37,82 @@
   return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>25);
 }
 
-extern __inline__ unsigned long sbus_dev_offset(unsigned long dev_addr)
-{
-  return (unsigned long) (((dev_addr)-SUN_SBUS_BVADDR)&SBUS_OFF_MASK);
-}
-
-struct linux_sbus;
+struct sbus_bus;
 
 /* Linux SBUS device tables */
-struct linux_sbus_device {
-  struct linux_sbus_device *next;      /* next device on this SBus or null */
-  struct linux_sbus_device *child;     /* For ledma and espdma on sun4m */
-  struct linux_sbus *my_bus;           /* Back ptr to sbus */
-  int prom_node;                       /* PROM device tree node for this device */
-  char prom_name[32];                  /* PROM device name */
-
-  struct linux_prom_registers reg_addrs[PROMREG_MAX];
-  int num_registers, ranges_applied;
-
-  unsigned int irqs[4];
-  int num_irqs;
-
-  unsigned long sbus_addr;             /* Absolute base address for device. */
-  unsigned long sbus_vaddrs[PROMVADDR_MAX];
-  unsigned long num_vaddrs;
-  unsigned long offset;                /* Offset given by PROM */
-  int slot;
+struct sbus_dev {
+	struct sbus_bus	*bus;       /* Back ptr to sbus */
+	struct sbus_dev	*next;      /* next device on this SBus or null */
+	struct sbus_dev	*child;     /* For ledma and espdma on sun4m */
+	struct sbus_dev	*parent;    /* Parent device if not toplevel */
+	int prom_node;              /* PROM device tree node for this device */
+	char prom_name[64];         /* PROM device name */
+	int slot;
+
+	struct resource resource[PROMREG_MAX];
+
+	struct linux_prom_registers reg_addrs[PROMREG_MAX];
+	int num_registers, ranges_applied;
+
+	struct linux_prom_ranges device_ranges[PROMREG_MAX];
+	int num_device_ranges;
+
+	unsigned int irqs[4];
+	int num_irqs;
 };
 
 /* This struct describes the SBus(s) found on this machine. */
-struct linux_sbus {
-	struct linux_sbus *next;             /* next SBus, if more than one SBus */
-	struct linux_sbus_device *devices;   /* Link to devices on this SBus */
-	struct iommu_struct *iommu;          /* IOMMU for this sbus if applicable */
-	int prom_node;                       /* PROM device tree node for this SBus */
-	char prom_name[16];                  /* Usually "sbus" or "sbi" */
-	int clock_freq;
+struct sbus_bus {
+	void			*iommu;		/* Opaque IOMMU cookie */
+	struct sbus_dev		*devices;	/* Link to devices on this SBus */
+	struct sbus_bus		*next;		/* next SBus, if more than one SBus */
+	int			prom_node;	/* PROM device tree node for this SBus */
+	char			prom_name[64];  /* Usually "sbus" or "sbi" */
+	int			clock_freq;
+
 	struct linux_prom_ranges sbus_ranges[PROMREG_MAX];
 	int num_sbus_ranges;
+
 	int devid;
 	int board;
 };
 
-extern struct linux_sbus *SBus_chain;
+extern struct sbus_bus *sbus_root;
 
 extern __inline__ int
-sbus_is_slave(struct linux_sbus_device *dev)
+sbus_is_slave(struct sbus_dev *dev)
 {
-	/* Have to write this for sun4c's */
+	/* XXX Have to write this for sun4c's */
 	return 0;
 }
 
 /* Device probing routines could find these handy */
 #define for_each_sbus(bus) \
-        for((bus) = SBus_chain; (bus); (bus)=(bus)->next)
+        for((bus) = sbus_root; (bus); (bus)=(bus)->next)
 
 #define for_each_sbusdev(device, bus) \
         for((device) = (bus)->devices; (device); (device)=(device)->next)
         
 #define for_all_sbusdev(device, bus) \
-	for((bus) = SBus_chain, (device) = (bus)->devices; (bus); (device)=((device)->next ? (device)->next : ((bus) = (bus)->next, (bus) ? (bus)->devices : 0)))
-
-/* If you did not get the buffer from mmu_get_*() or sparc_alloc_dvma()
- * then you must use this to get the 32-bit SBUS dvma address.
- * And in this case it is your responsibility to make sure the buffer
- * is GFP_DMA, ie. that it is not greater than MAX_DMA_ADDRESS.
- */
-#define sbus_dvma_addr(__addr)	((__u32)(__addr))
+	for((bus) = sbus_root, ((device) = (bus) ? (bus)->devices : 0); (bus); (device)=((device)->next ? (device)->next : ((bus) = (bus)->next, (bus) ? (bus)->devices : 0)))
 
-/* Apply promlib probed SBUS ranges to registers. */
-extern void prom_apply_sbus_ranges(struct linux_sbus *sbus, 
-				   struct linux_prom_registers *sbusregs,
-				   int nregs, struct linux_sbus_device *sdev);
+/* Driver DVMA interfaces. */
+#define sbus_can_dma_64bit(sdev)	(1)
+#define sbus_can_burst64(sdev)		(1)
+extern void sbus_set_sbus64(struct sbus_dev *, int);
+
+/* These yield IOMMU mappings in consistant mode. */
+extern void *sbus_alloc_consistant(struct sbus_dev *, long, u32 *dma_addrp);
+extern void sbus_free_consistant(struct sbus_dev *, long, void *, u32);
+
+/* All the rest use streaming mode mappings. */
+extern u32 sbus_map_single(struct sbus_dev *, void *, long);
+extern void sbus_unmap_single(struct sbus_dev *, u32, long);
+extern void sbus_map_sg(struct sbus_dev *, struct scatterlist *, int);
+extern void sbus_unmap_sg(struct sbus_dev *, struct scatterlist *, int);
+
+/* Finally, allow explicit synchronization of streamable mappings. */
+extern void sbus_dma_sync_single(struct sbus_dev *, u32, long);
+extern void sbus_dma_sync_sg(struct sbus_dev *, struct scatterlist *, int);
 
 #endif /* !(_SPARC_SBUS_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/scatterlist.h linux/include/asm-sparc/scatterlist.h
--- v2.3.34/linux/include/asm-sparc/scatterlist.h	Mon Apr 14 16:28:21 1997
+++ linux/include/asm-sparc/scatterlist.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: scatterlist.h,v 1.2 1997/04/10 05:13:24 davem Exp $ */
+/* $Id: scatterlist.h,v 1.3 1999/10/18 01:47:13 zaitcev Exp $ */
 #ifndef _SPARC_SCATTERLIST_H
 #define _SPARC_SCATTERLIST_H
 
@@ -9,6 +9,7 @@
     unsigned int length;
 
     __u32 dvma_address; /* A place to hang host-specific addresses at. */
+    __u32 dvma_length;
 };
 
 #define ISA_DMA_THRESHOLD (~0UL)
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/shmparam.h linux/include/asm-sparc/shmparam.h
--- v2.3.34/linux/include/asm-sparc/shmparam.h	Sun Nov  7 16:37:34 1999
+++ linux/include/asm-sparc/shmparam.h	Mon Dec 20 22:05:52 1999
@@ -1,7 +1,10 @@
-/* $Id: shmparam.h,v 1.4 1998/09/28 07:15:01 jj Exp $ */
+/* $Id: shmparam.h,v 1.6 1999/12/09 10:32:41 davem Exp $ */
 #ifndef _ASMSPARC_SHMPARAM_H
 #define _ASMSPARC_SHMPARAM_H
 
-#define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
+extern int vac_cache_size;
+#define SHMLBA (vac_cache_size ? vac_cache_size : \
+		(sparc_cpu_model == sun4c ? (64 * 1024) : \
+		 (sparc_cpu_model == sun4 ? (128 * 1024) : PAGE_SIZE)))
 
 #endif /* _ASMSPARC_SHMPARAM_H */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/spinlock.h linux/include/asm-sparc/spinlock.h
--- v2.3.34/linux/include/asm-sparc/spinlock.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc/spinlock.h	Mon Dec 20 22:05:52 1999
@@ -32,16 +32,8 @@
 extern void _do_spin_unlock(spinlock_t *lock);
 
 #define spin_trylock(lp)	_spin_trylock(lp)
-
 #define spin_lock(lock)		_do_spin_lock(lock, "spin_lock")
-#define spin_lock_irq(lock)	do { __cli(); _do_spin_lock(lock, "spin_lock_irq"); } while(0)
-#define spin_lock_bh(lock)	do { local_bh_disable(); _do_spin_lock(lock, "spin_lock_irq"); } while(0)
-#define spin_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_spin_lock(lock, "spin_lock_irqsave"); } while(0)
-
 #define spin_unlock(lock)	_do_spin_unlock(lock)
-#define spin_unlock_irq(lock)	do { _do_spin_unlock(lock); __sti(); } while(0)
-#define spin_unlock_bh(lock)	do { _do_spin_unlock(lock); local_bh_enable(); } while(0)
-#define spin_unlock_irqrestore(lock, flags) do { _do_spin_unlock(lock); __restore_flags(flags); } while(0)
 
 struct _rwlock_debug {
 	volatile unsigned int lock;
@@ -63,9 +55,6 @@
 	_do_read_lock(lock, "read_lock"); \
 	__restore_flags(flags); \
 } while(0)
-#define read_lock_irq(lock)	do { __cli(); _do_read_lock(lock, "read_lock_irq"); } while(0)
-#define read_lock_bh(lock)	do { local_bh_disable(); _do_read_lock(lock, "read_lock_irq"); } while(0)
-#define read_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_read_lock(lock, "read_lock_irqsave"); } while(0)
 
 #define read_unlock(lock) \
 do {	unsigned long flags; \
@@ -73,9 +62,6 @@
 	_do_read_unlock(lock, "read_unlock"); \
 	__restore_flags(flags); \
 } while(0)
-#define read_unlock_irq(lock)	do { _do_read_unlock(lock, "read_unlock_irq"); __sti(); } while(0)
-#define read_unlock_bh(lock)	do { _do_read_unlock(lock, "read_unlock_irq"); local_bh_enable(); } while(0)
-#define read_unlock_irqrestore(lock, flags) do { _do_read_unlock(lock, "read_unlock_irqrestore"); __restore_flags(flags); } while(0)
 
 #define write_lock(lock) \
 do {	unsigned long flags; \
@@ -83,9 +69,6 @@
 	_do_write_lock(lock, "write_lock"); \
 	__restore_flags(flags); \
 } while(0)
-#define write_lock_irq(lock)	do { __cli(); _do_write_lock(lock, "write_lock_irq"); } while(0)
-#define write_lock_bh(lock)	do { local_bh_disable(); _do_write_lock(lock, "write_lock_irq"); } while(0)
-#define write_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_write_lock(lock, "write_lock_irqsave"); } while(0)
 
 #define write_unlock(lock) \
 do {	unsigned long flags; \
@@ -93,9 +76,6 @@
 	_do_write_unlock(lock); \
 	__restore_flags(flags); \
 } while(0)
-#define write_unlock_irq(lock)	do { _do_write_unlock(lock); __sti(); } while(0)
-#define write_unlock_bh(lock)	do { _do_write_unlock(lock); local_bh_enable(); } while(0)
-#define write_unlock_irqrestore(lock, flags) do { _do_write_unlock(lock); __restore_flags(flags); } while(0)
 
 #else /* !SPIN_LOCK_DEBUG */
 
@@ -139,82 +119,6 @@
 	__asm__ __volatile__("stb %%g0, [%0]" : : "r" (lock) : "memory");
 }
 
-extern __inline__ void spin_lock_irq(spinlock_t *lock)
-{
-	__asm__ __volatile__("
-	rd	%%psr, %%g2
-	or	%%g2, %0, %%g2
-	wr	%%g2, 0x0, %%psr
-	nop; nop; nop;
-1:	ldstub	[%1], %%g2
-	orcc	%%g2, 0x0, %%g0
-	bne,a	2f
-	 ldub	[%1], %%g2
-	.text	2
-2:	orcc	%%g2, 0x0, %%g0
-	bne,a	2b
-	 ldub	[%1], %%g2
-	b,a	1b
-	.previous
-"	: /* No outputs */
-	: "i" (PSR_PIL), "r" (lock)
-	: "g2", "memory", "cc");
-}
-
-#define spin_lock_bh(___lk) do { local_bh_disable(); spin_lock(___lk); } while(0)
-
-extern __inline__ void spin_unlock_irq(spinlock_t *lock)
-{
-	__asm__ __volatile__("
-	rd	%%psr, %%g2
-	andn	%%g2, %1, %%g2
-	stb	%%g0, [%0]
-	wr	%%g2, 0x0, %%psr
-	nop; nop; nop;
-"	: /* No outputs. */
-	: "r" (lock), "i" (PSR_PIL)
-	: "g2", "memory");
-}
-
-#define spin_unlock_bh(___lk) do { spin_unlock(___lk); local_bh_enable(); } while(0)
-
-#define spin_lock_irqsave(__lock, flags)	\
-do {						\
-	register spinlock_t *__lp asm("g1");	\
-	__lp = (__lock);			\
-	__asm__ __volatile__(			\
-	"rd	%%psr, %0\n\t"			\
-	"or	%0, %1, %%g2\n\t"		\
-	"wr	%%g2, 0x0, %%psr\n\t"		\
-	"nop; nop; nop;\n"			\
-	"1:\n\t"				\
-	"ldstub	[%2], %%g2\n\t"			\
-	"orcc	%%g2, 0x0, %%g0\n\t"		\
-	"bne,a	2f\n\t"				\
-	" ldub	[%2], %%g2\n\t"			\
-	".text	2\n"				\
-	"2:\n\t"				\
-	"orcc	%%g2, 0x0, %%g0\n\t"		\
-	"bne,a	2b\n\t"				\
-	" ldub	[%2], %%g2\n\t"			\
-	"b,a	1b\n\t"				\
-	".previous\n"				\
-	: "=r" (flags)				\
-	: "i" (PSR_PIL), "r" (__lp)		\
-	: "g2", "memory", "cc");		\
-} while(0)
-
-extern __inline__ void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
-{
-	__asm__ __volatile__("
-	stb	%%g0, [%0]
-	wr	%1, 0x0, %%psr
-	nop; nop; nop;
-"	: /* No outputs. */
-	: "r" (lock), "r" (flags)
-	: "memory", "cc");
-}
-
 /* Read-write spinlocks, allowing multiple readers
  * but only one writer.
  *
@@ -299,24 +203,6 @@
 }
 
 #define write_unlock(rw)	do { (rw)->lock = 0; } while(0)
-#define read_lock_irq(lock)	do { __cli(); _read_lock(lock); } while (0)
-#define read_unlock_irq(lock)	do { _read_unlock(lock); __sti(); } while (0)
-#define write_lock_irq(lock)	do { __cli(); write_lock(lock); } while (0)
-#define write_unlock_irq(lock)	do { write_unlock(lock); __sti(); } while (0)
-
-#define read_lock_bh(lock)	do { local_bh_disable(); _read_lock(lock); } while (0)
-#define read_unlock_bh(lock)	do { _read_unlock(lock); local_bh_enable(); } while (0)
-#define write_lock_bh(lock)	do { local_bh_disable(); write_lock(lock); } while (0)
-#define write_unlock_bh(lock)	do { write_unlock(lock); local_bh_enable(); } while (0)
-
-#define read_lock_irqsave(lock, flags)	\
-	do { __save_and_cli(flags); _read_lock(lock); } while (0)
-#define read_unlock_irqrestore(lock, flags) \
-	do { _read_unlock(lock); __restore_flags(flags); } while (0)
-#define write_lock_irqsave(lock, flags)	\
-	do { __save_and_cli(flags); write_lock(lock); } while (0)
-#define write_unlock_irqrestore(lock, flags) \
-	do { write_unlock(lock); __restore_flags(flags); } while (0)
 
 #endif /* SPIN_LOCK_DEBUG */
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/stat.h linux/include/asm-sparc/stat.h
--- v2.3.34/linux/include/asm-sparc/stat.h	Tue Aug  4 16:03:35 1998
+++ linux/include/asm-sparc/stat.h	Tue Dec 21 21:56:42 1999
@@ -1,4 +1,4 @@
-/* $Id: stat.h,v 1.9 1998/07/26 05:24:39 davem Exp $ */
+/* $Id: stat.h,v 1.10 1999/12/21 14:09:41 jj Exp $ */
 #ifndef _SPARC_STAT_H
 #define _SPARC_STAT_H
 
@@ -36,6 +36,42 @@
 	off_t   st_blksize;
 	off_t   st_blocks;
 	unsigned long  __unused4[2];
+};
+
+struct stat64 {
+	unsigned char	__pad0[6];
+	unsigned short	st_dev;
+	unsigned char	__pad1[4];
+
+	unsigned int	st_ino;
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+
+	unsigned char	__pad2[6];
+	unsigned short	st_rdev;
+
+	unsigned char	__pad3[8];
+
+	long long	st_size;
+	unsigned int	st_blksize;
+
+	unsigned char	__pad4[8];
+	unsigned int	st_blocks;
+
+	unsigned int	st_atime;
+	unsigned int	__unused1;
+
+	unsigned int	st_mtime;
+	unsigned int	__unused2;
+
+	unsigned int	st_ctime;
+	unsigned int	__unused3;
+
+	unsigned int	__unused4;
+	unsigned int	__unused5;
 };
 
 #endif
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h
--- v2.3.34/linux/include/asm-sparc/system.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc/system.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.75 1999/09/01 08:06:08 davem Exp $ */
+/* $Id: system.h,v 1.80 1999/12/16 12:58:31 anton Exp $ */
 #include <linux/config.h>
 
 #ifndef __SPARC_SYSTEM_H
@@ -15,8 +15,6 @@
 #include <asm/ptrace.h>
 #include <asm/btfixup.h>
 
-#define EMPTY_PGT       (&empty_bad_page)
-#define EMPTY_PGE	(&empty_bad_page_table)
 #endif /* __KERNEL__ */
 
 #ifndef __ASSEMBLY__
@@ -72,18 +70,33 @@
 #define SWITCH_ENTER \
 	if(prev->flags & PF_USEDFPU) { \
 		put_psr(get_psr() | PSR_EF); \
-		fpsave(&prev->tss.float_regs[0], &prev->tss.fsr, \
-		       &prev->tss.fpqueue[0], &prev->tss.fpqdepth); \
+		fpsave(&prev->thread.float_regs[0], &prev->thread.fsr, \
+		       &prev->thread.fpqueue[0], &prev->thread.fpqdepth); \
 		prev->flags &= ~PF_USEDFPU; \
-		prev->tss.kregs->psr &= ~PSR_EF; \
+		prev->thread.kregs->psr &= ~PSR_EF; \
 	}
 
 #define SWITCH_DO_LAZY_FPU
 #else
 #define SWITCH_ENTER
-#define SWITCH_DO_LAZY_FPU if(last_task_used_math != next) next->tss.kregs->psr&=~PSR_EF;
+#define SWITCH_DO_LAZY_FPU if(last_task_used_math != next) next->thread.kregs->psr&=~PSR_EF;
 #endif
 
+/*
+ * Flush windows so that the VM switch which follows
+ * would not pull the stack from under us.
+ *
+ * SWITCH_ENTER and SWITH_DO_LAZY_FPU do not work yet (e.g. SMP does not work)
+ */
+#define prepare_to_switch() do { \
+	__asm__ __volatile__( \
+	".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \
+	"save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
+	"save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
+	"save %sp, -0x40, %sp\n\t" \
+	"restore; restore; restore; restore; restore; restore; restore"); \
+} while(0)
+
 	/* Much care has gone into this code, do not touch it.
 	 *
 	 * We need to loadup regs l0/l1 for the newly forked child
@@ -91,6 +104,9 @@
 	 * holding certain values, gcc is told that they are clobbered.
 	 * Gcc needs registers for 3 values in and 1 value out, so we
 	 * clobber every non-fixed-usage register besides l2/l3/o4/o5.  -DaveM
+	 *
+	 * Hey Dave, that do not touch sign is too much of an incentive
+	 * - Anton
 	 */
 #define switch_to(prev, next, last) do {						\
 	__label__ here;									\
@@ -98,16 +114,7 @@
 	extern struct task_struct *current_set[NR_CPUS];				\
 	SWITCH_ENTER									\
 	SWITCH_DO_LAZY_FPU								\
-	__asm__ __volatile__(								\
-	".globl\tflush_patch_switch\nflush_patch_switch:\n\t"				\
-	"save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t"		\
-	"save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t"		\
-	"save %sp, -0x40, %sp\n\t"							\
-	"restore; restore; restore; restore; restore; restore; restore");		\
-	if(!(next->tss.flags & SPARC_FLAG_KTHREAD) &&					\
-	   !(next->flags & PF_EXITING))							\
-		switch_to_context(next);						\
-	next->mm->cpu_vm_mask |= (1 << smp_processor_id());				\
+	next->active_mm->cpu_vm_mask |= (1 << smp_processor_id());			\
 	task_pc = ((unsigned long) &&here) - 0x8;					\
 	__asm__ __volatile__(								\
 	"mov	%%g6, %%g3\n\t"								\
@@ -136,16 +143,16 @@
 	" mov	%%g3, %0\n\t"								\
         : "=&r" (last)									\
         : "r" (&(current_set[hard_smp_processor_id()])), "r" (next),			\
-	  "i" ((const unsigned long)(&((struct task_struct *)0)->tss.kpsr)),		\
-	  "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ksp)),		\
+	  "i" ((const unsigned long)(&((struct task_struct *)0)->thread.kpsr)),		\
+	  "i" ((const unsigned long)(&((struct task_struct *)0)->thread.ksp)),		\
 	  "r" (task_pc)									\
 	: "g1", "g2", "g3", "g4", "g5", "g7", "l0", "l1",				\
 	"l4", "l5", "l6", "l7", "i0", "i1", "i2", "i3", "i4", "i5", "o0", "o1", "o2",	\
 	"o3");										\
 here:  } while(0)
 
-/* Changing the IRQ level on the Sparc.   We now avoid writing the psr
- * whenever possible.
+/*
+ * Changing the IRQ level on the Sparc.
  */
 extern __inline__ void setipl(unsigned long __orig_psr)
 {
@@ -237,6 +244,10 @@
 #define __save_flags(flags)	((flags) = getipl())
 #define __save_and_cli(flags)	((flags) = read_psr_and_cli())
 #define __restore_flags(flags)	setipl((flags))
+#define local_irq_disable()		__cli()
+#define local_irq_enable()		__sti()
+#define local_irq_save(flags)		__save_and_cli(flags)
+#define local_irq_restore(flags)	__restore_flags(flags)
 
 #ifdef __SMP__
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/termios.h linux/include/asm-sparc/termios.h
--- v2.3.34/linux/include/asm-sparc/termios.h	Mon Nov  1 13:56:27 1999
+++ linux/include/asm-sparc/termios.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: termios.h,v 1.29 1999/03/25 09:11:18 davem Exp $ */
+/* $Id: termios.h,v 1.30 1999/12/02 09:57:46 davem Exp $ */
 #ifndef _SPARC_TERMIOS_H
 #define _SPARC_TERMIOS_H
 
@@ -69,7 +69,7 @@
 #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 */
-#define N_SYNC_PPP	14
+#define N_SYNC_PPP	14	/* synchronous PPP */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/uaccess.h linux/include/asm-sparc/uaccess.h
--- v2.3.34/linux/include/asm-sparc/uaccess.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-sparc/uaccess.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.19 1999/08/14 03:52:11 anton Exp $
+/* $Id: uaccess.h,v 1.20 1999/11/23 08:56:45 davem Exp $
  * uaccess.h: User space memore access functions.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -384,6 +384,7 @@
 } __sfu_res; })
 
 extern int __strlen_user(const char *);
+extern int __strnlen_user(const char *, long len);
 
 extern __inline__ int strlen_user(const char *str)
 {
@@ -391,6 +392,14 @@
 		return 0;
 	else
 		return __strlen_user(str);
+}
+
+extern __inline__ int strnlen_user(const char *str, long len)
+{
+	if(!access_ok(VERIFY_READ, str, 0))
+		return 0;
+	else
+		return __strnlen_user(str, len);
 }
 
 #endif  /* __ASSEMBLY__ */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h
--- v2.3.34/linux/include/asm-sparc/unistd.h	Wed Jul 28 10:30:10 1999
+++ linux/include/asm-sparc/unistd.h	Tue Dec 21 21:56:42 1999
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.55 1999/04/07 17:14:15 davem Exp $ */
+/* $Id: unistd.h,v 1.59 1999/12/21 14:09:43 jj Exp $ */
 #ifndef _SPARC_UNISTD_H
 #define _SPARC_UNISTD_H
 
@@ -71,14 +71,14 @@
 /* #define __NR_mctl             53    SunOS specific                              */
 #define __NR_ioctl               54 /* Common                                      */
 #define __NR_reboot              55 /* Common                                      */
-/* #define __NR_ni_syscall       56    ENOSYS under SunOS                          */
+#define __NR_mmap2		 56 /* Linux sparc32 Specific			   */
 #define __NR_symlink             57 /* Common                                      */
 #define __NR_readlink            58 /* Common                                      */
 #define __NR_execve              59 /* Common                                      */
 #define __NR_umask               60 /* Common                                      */
 #define __NR_chroot              61 /* Common                                      */
 #define __NR_fstat               62 /* Common                                      */
-/* #define __NR_ni_syscall       63    ENOSYS under SunOS                          */
+#define __NR_fstat64		 63 /* Linux sparc32 Specific			   */
 #define __NR_getpagesize         64 /* Common                                      */
 #define __NR_msync               65 /* Common in newer 1.3.x revs...               */
 #define __NR_vfork               66 /* Common                                      */
@@ -92,14 +92,14 @@
 #define __NR_mprotect            74 /* Common                                      */
 /* #define __NR_madvise          75    SunOS Specific                              */
 #define __NR_vhangup             76 /* Common                                      */
-/* #define __NR_ni_syscall       77    ENOSYS under SunOS                          */
+#define __NR_truncate64		 77 /* Linux sparc32 Specific			   */
 /* #define __NR_mincore          78    SunOS Specific                              */
 #define __NR_getgroups           79 /* Common                                      */
 #define __NR_setgroups           80 /* Common                                      */
 #define __NR_getpgrp             81 /* Common                                      */
 /* #define __NR_setpgrp          82    setpgid, same difference...                 */
 #define __NR_setitimer           83 /* Common                                      */
-/* #define __NR_ni_syscall       84    ENOSYS under SunOS                          */
+#define __NR_ftruncate64	 84 /* Linux sparc32 Specific			   */
 #define __NR_swapon              85 /* Common                                      */
 #define __NR_getitimer           86 /* Common                                      */
 /* #define __NR_gethostname      87    SunOS Specific                              */
@@ -147,14 +147,14 @@
 #define __NR_truncate           129 /* Common                                      */
 #define __NR_ftruncate          130 /* Common                                      */
 #define __NR_flock              131 /* Common                                      */
-/* #define __NR_ni_syscall      132    ENOSYS under SunOS                          */
+#define __NR_lstat64		132 /* Linux sparc32 Specific			   */
 #define __NR_sendto             133 /* Common                                      */
 #define __NR_shutdown           134 /* Common                                      */
 #define __NR_socketpair         135 /* Common                                      */
 #define __NR_mkdir              136 /* Common                                      */
 #define __NR_rmdir              137 /* Common                                      */
 #define __NR_utimes             138 /* SunOS Specific                              */
-/* #define __NR_ni_syscall      139    ENOSYS under SunOS                          */
+#define __NR_stat64		139 /* Linux sparc32 Specific			   */
 /* #define __NR_adjtime         140    SunOS Specific                              */
 #define __NR_getpeername        141 /* Common                                      */
 /* #define __NR_gethostid       142    SunOS Specific                              */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/asm_offsets.h linux/include/asm-sparc64/asm_offsets.h
--- v2.3.34/linux/include/asm-sparc64/asm_offsets.h	Mon Aug  2 22:07:16 1999
+++ linux/include/asm-sparc64/asm_offsets.h	Mon Dec 20 22:05:52 1999
@@ -186,7 +186,13 @@
 #define ASIZ_task_sas_ss_sp	0x00000008
 #define AOFF_task_sas_ss_size	0x00000820
 #define ASIZ_task_sas_ss_size	0x00000008
-#define ASIZ_task	0x00000830
+#define AOFF_task_parent_exec_id	0x00000828
+#define ASIZ_task_parent_exec_id	0x00000004
+#define AOFF_task_self_exec_id	0x0000082c
+#define ASIZ_task_self_exec_id	0x00000004
+#define AOFF_task_exit_sem	0x00000830
+#define ASIZ_task_exit_sem	0x00000030
+#define ASIZ_task	0x00000860
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
 #define AOFF_mm_mmap_avl	0x00000008
@@ -474,7 +480,13 @@
 #define ASIZ_task_sas_ss_sp	0x00000008
 #define AOFF_task_sas_ss_size	0x00000a18
 #define ASIZ_task_sas_ss_size	0x00000008
-#define ASIZ_task	0x00000a20
+#define AOFF_task_parent_exec_id	0x00000a20
+#define ASIZ_task_parent_exec_id	0x00000004
+#define AOFF_task_self_exec_id	0x00000a24
+#define ASIZ_task_self_exec_id	0x00000004
+#define AOFF_task_exit_sem	0x00000a28
+#define ASIZ_task_exit_sem	0x00000038
+#define ASIZ_task	0x00000a60
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
 #define AOFF_mm_mmap_avl	0x00000008
@@ -760,7 +772,13 @@
 #define ASIZ_task_sas_ss_sp	0x00000008
 #define AOFF_task_sas_ss_size	0x00000a30
 #define ASIZ_task_sas_ss_size	0x00000008
-#define ASIZ_task	0x00000a40
+#define AOFF_task_parent_exec_id	0x00000a38
+#define ASIZ_task_parent_exec_id	0x00000004
+#define AOFF_task_self_exec_id	0x00000a3c
+#define ASIZ_task_self_exec_id	0x00000004
+#define AOFF_task_exit_sem	0x00000a40
+#define ASIZ_task_exit_sem	0x00000040
+#define ASIZ_task	0x00000a80
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
 #define AOFF_mm_mmap_avl	0x00000008
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/audioio.h linux/include/asm-sparc64/audioio.h
--- v2.3.34/linux/include/asm-sparc64/audioio.h	Tue Sep  7 12:14:07 1999
+++ linux/include/asm-sparc64/audioio.h	Mon Dec 20 22:05:52 1999
@@ -271,7 +271,7 @@
         int index; 
 
         /* This device */
-        struct linux_sbus_device *dev;
+        struct sbus_dev *dev;
 
 	/* Processes blocked on open() sit here. */
 	wait_queue_head_t open_wait;
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/auxio.h linux/include/asm-sparc64/auxio.h
--- v2.3.34/linux/include/asm-sparc64/auxio.h	Thu Mar 27 14:40:09 1997
+++ linux/include/asm-sparc64/auxio.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: auxio.h,v 1.1 1997/03/14 21:05:27 jj Exp $
+/* $Id: auxio.h,v 1.2 1999/09/21 14:39:25 davem Exp $
  * auxio.h:  Definitions and code for the Auxiliary I/O register.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -11,7 +11,7 @@
 /* FIXME: All of this should be checked for sun4u. It has /sbus/auxio, but
    I don't know whether it is the same and don't have a floppy */
 
-extern unsigned char *auxio_register;
+extern unsigned long auxio_register;
 
 /* This register is an unsigned char in IO space.  It does two things.
  * First, it is used to control the front panel LED light on machines
@@ -33,16 +33,50 @@
 #define AUXIO_FLPY_EJCT   0x02    /* Eject floppy disk.  Write only. */
 #define AUXIO_LED         0x01    /* On if set, off if unset. Read/Write */
 
-#define AUXREG   ((volatile unsigned char *)(auxio_register))
+#define AUXREG   (auxio_register)
 
 /* These are available on sun4c */
-#define TURN_ON_LED   if (AUXREG) *AUXREG = (*AUXREG | AUXIO_ORMEIN | AUXIO_LED)
-#define TURN_OFF_LED  if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_LED))
-#define FLIP_LED      if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) ^ AUXIO_LED)
-#define FLPY_MOTORON  if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) | AUXIO_FLPY_DSEL)
-#define FLPY_MOTOROFF if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_FLPY_DSEL))
-#define FLPY_TCNTON   if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) | AUXIO_FLPY_TCNT)
-#define FLPY_TCNTOFF  if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_FLPY_TCNT))
+#define TURN_ON_LED   \
+do {	if (AUXREG) \
+		sbus_writeb(sbus_readb(AUXREG) | \
+			    (AUXIO_ORMEIN | AUXIO_LED), AUXREG); \
+} while(0)
+#define TURN_OFF_LED  \
+do {	if (AUXREG) \
+		sbus_writeb((sbus_readb(AUXREG) | \
+			     AUXIO_ORMEIN) & (~AUXIO_LED), \
+			    AUXREG); \
+} while(0)
+#define FLIP_LED	\
+do {	if (AUXREG)  \
+		sbus_writeb((sbus_readb(AUXREG) | \
+			     AUXIO_ORMEIN) ^ AUXIO_LEN, \
+			    AUXREG); \
+} while(0)
+#define FLPY_MOTORON	\
+do {	if (AUXREG) \
+		sbus_writeb(sbus_readb(AUXREG) | \
+			    (AUXIO_ORMEIN | AUXIO_FLPY_DSEL), \
+			    AUXREG); \
+} while(0)
+#define FLPY_MOTOROFF	\
+do {	if (AUXREG) \
+		sbus_writeb((sbus_readb(AUXREG) | \
+			     AUXIO_ORMEIN) & (~AUXIO_FLPY_DSEL), \
+			    AUXREG); \
+} while(0)
+#define FLPY_TCNTON	\
+do {	if (AUXREG) \
+		sbus_writeb((sbus_readb(AUXREG) | \
+			     AUXIO_ORMEIN) | AUXIO_FLPY_TCNT, \
+			    AUXREG); \
+} while(0)
+#define FLPY_TCNTOFF	\
+do {	if (AUXREG) \
+		sbus_writeb((sbus_readb(AUXREG) | \
+			     AUXIO_ORMEIN) & (~AUXIO_FLPY_TCNT), \
+			    AUXREG); \
+} while(0)
 
 #ifndef __ASSEMBLY__
 extern __inline__ void set_auxio(unsigned char bits_on, unsigned char bits_off)
@@ -53,8 +87,13 @@
 	save_flags(flags); cli();
 
 	if(AUXREG) {
-		regval = *AUXREG;
-		*AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN4M;
+		unsigned char newval;
+
+		regval = sbus_readb(AUXREG);
+		newval  = regval | bits_on;
+		newval &= ~bits_off;
+		newval |= AUXIO_ORMEIN4M;
+		sbus_writeb(newval, AUXREG);
 	}
 	restore_flags(flags);
 }
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/div64.h linux/include/asm-sparc64/div64.h
--- v2.3.34/linux/include/asm-sparc64/div64.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/div64.h	Mon Dec 20 22:05:52 1999
@@ -0,0 +1,14 @@
+#ifndef __SPARC64_DIV64
+#define __SPARC64_DIV64
+
+/*
+ * Hey, we're already 64-bit, no
+ * need to play games..
+ */
+#define do_div(n,base) ({ \
+	int __res; \
+	__res = ((unsigned long) n) % (unsigned) base; \
+	n = ((unsigned long) n) / (unsigned) base; \
+	__res; })
+
+#endif /* __SPARC64_DIV64 */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/dma.h linux/include/asm-sparc64/dma.h
--- v2.3.34/linux/include/asm-sparc64/dma.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc64/dma.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: dma.h,v 1.16 1999/09/10 10:44:32 davem Exp $
+/* $Id: dma.h,v 1.18 1999/12/01 10:47:22 davem Exp $
  * include/asm-sparc64/dma.h
  *
  * Copyright 1996 (C) David S. Miller (davem@caip.rutgers.edu)
@@ -33,22 +33,17 @@
 #define MAX_DMA_CHANNELS 8
 #define DMA_MODE_READ    1
 #define DMA_MODE_WRITE   2
-
-/* This is actually used. */
-extern unsigned long phys_base;
-#define MAX_DMA_ADDRESS  (phys_base + (0xfe000000UL) + PAGE_OFFSET)
+#define MAX_DMA_ADDRESS  (~0UL)
 
 /* Useful constants */
 #define SIZE_16MB      (16*1024*1024)
 #define SIZE_64K       (64*1024)
 
-/* Structure to describe the current status of DMA registers on the Sparc */
-struct sparc_dma_registers {
-  __volatile__ __u32 cond_reg;	/* DMA condition register */
-  __volatile__ __u32 st_addr;	/* Start address of this transfer */
-  __volatile__ __u32 cnt;	/* How many bytes to transfer */
-  __volatile__ __u32 dma_test;	/* DMA test register */
-};
+/* SBUS DMA controller reg offsets */
+#define DMA_CSR		0x00UL		/* rw  DMA control/status register    0x00   */
+#define DMA_ADDR	0x04UL		/* rw  DMA transfer address register  0x04   */
+#define DMA_COUNT	0x08UL		/* rw  DMA transfer count register    0x08   */
+#define DMA_TEST	0x0cUL		/* rw  DMA test/debug register        0x0c   */
 
 /* DVMA chip revisions */
 enum dvma_rev {
@@ -64,10 +59,10 @@
 #define DMA_HASCOUNT(rev)  ((rev)==dvmaesc1)
 
 /* Linux DMA information structure, filled during probe. */
-struct Linux_SBus_DMA {
-	struct Linux_SBus_DMA *next;
-	struct linux_sbus_device *SBus_dev;
-	struct sparc_dma_registers *regs;
+struct sbus_dma {
+	struct sbus_dma *next;
+	struct sbus_dev *sdev;
+	unsigned long regs;
 
 	/* Status, misc info */
 	int node;                /* Prom node for this DMA device */
@@ -75,7 +70,7 @@
 	int allocated;           /* Are we "owned" by anyone yet? */
 
 	/* Transfer information. */
-	unsigned int addr;       /* Start address of current transfer */
+	u32 addr;                /* Start address of current transfer */
 	int nbytes;              /* Size of current transfer */
 	int realbytes;           /* For splitting up large transfers, etc. */
 
@@ -83,14 +78,14 @@
 	enum dvma_rev revision;
 };
 
-extern struct Linux_SBus_DMA *dma_chain;
+extern struct sbus_dma *dma_chain;
 
 /* Broken hardware... */
 #define DMA_ISBROKEN(dma)    ((dma)->revision == dvmarev1)
 #define DMA_ISESC1(dma)      ((dma)->revision == dvmaesc1)
 
 /* Main routines in dma.c */
-extern void dvma_init(struct linux_sbus *);
+extern void dvma_init(struct sbus_bus *);
 
 /* Fields in the cond_reg register */
 /* First, the version identification bits */
@@ -124,7 +119,9 @@
 #define DMA_SCSI_DISAB   0x00020000        /* No FIFO drains during reg */
 #define DMA_DSBL_WR_INV  0x00020000        /* No EC inval. on slave writes */
 #define DMA_ADD_ENABLE   0x00040000        /* Special ESC DVMA optimization */
-#define DMA_E_BURST8	 0x00040000	   /* ENET: SBUS r/w burst size */
+#define DMA_E_BURSTS	 0x000c0000	   /* ENET: SBUS r/w burst mask */
+#define DMA_E_BURST32	 0x00040000	   /* ENET: SBUS 32 byte r/w burst */
+#define DMA_E_BURST16	 0x00000000	   /* ENET: SBUS 16 byte r/w burst */
 #define DMA_BRST_SZ      0x000c0000        /* SCSI: SBUS r/w burst size */
 #define DMA_BRST64       0x000c0000        /* SCSI: 64byte bursts (HME on UltraSparc only) */
 #define DMA_BRST32       0x00040000        /* SCSI: 32byte bursts */
@@ -156,18 +153,42 @@
 #define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL))
 
 /* Yes, I hack a lot of elisp in my spare time... */
-#define DMA_ERROR_P(regs)  ((((regs)->cond_reg) & DMA_HNDL_ERROR))
-#define DMA_IRQ_P(regs)    ((((regs)->cond_reg) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)))
-#define DMA_WRITE_P(regs)  ((((regs)->cond_reg) & DMA_ST_WRITE))
-#define DMA_OFF(regs)      ((((regs)->cond_reg) &= (~DMA_ENABLE)))
-#define DMA_INTSOFF(regs)  ((((regs)->cond_reg) &= (~DMA_INT_ENAB)))
-#define DMA_INTSON(regs)   ((((regs)->cond_reg) |= (DMA_INT_ENAB)))
-#define DMA_PUNTFIFO(regs) ((((regs)->cond_reg) |= DMA_FIFO_INV))
-#define DMA_SETSTART(regs, addr)  ((((regs)->st_addr) = (char *) addr))
-#define DMA_BEGINDMA_W(regs) \
-        ((((regs)->cond_reg |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB))))
-#define DMA_BEGINDMA_R(regs) \
-        ((((regs)->cond_reg |= ((DMA_ENABLE|DMA_INT_ENAB)&(~DMA_ST_WRITE)))))
+#define DMA_ERROR_P(regs)  (((sbus_readl((regs) + DMA_CSR) & DMA_HNDL_ERROR))
+#define DMA_IRQ_P(regs)    (((sbus_readl((regs) + DMA_CSR)) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)))
+#define DMA_WRITE_P(regs)  (((sbus_readl((regs) + DMA_CSR) & DMA_ST_WRITE))
+#define DMA_OFF(__regs)		\
+do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
+	tmp &= ~DMA_ENABLE; \
+	sbus_writel(tmp, (__regs) + DMA_CSR); \
+} while(0)
+#define DMA_INTSOFF(__regs)	\
+do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
+	tmp &= ~DMA_INT_ENAB; \
+	sbus_writel(tmp, (__regs) + DMA_CSR); \
+} while(0)
+#define DMA_INTSON(__regs)	\
+do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
+	tmp |= DMA_INT_ENAB; \
+	sbus_writel(tmp, (__regs) + DMA_CSR); \
+} while(0)
+#define DMA_PUNTFIFO(__regs)	\
+do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
+	tmp |= DMA_FIFO_INV; \
+	sbus_writel(tmp, (__regs) + DMA_CSR); \
+} while(0)
+#define DMA_SETSTART(__regs, __addr)	\
+	sbus_writel((u32)(__addr), (__regs) + DMA_ADDR);
+#define DMA_BEGINDMA_W(__regs)	\
+do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
+	tmp |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB); \
+	sbus_writel(tmp, (__regs) + DMA_CSR); \
+} while(0)
+#define DMA_BEGINDMA_R(__regs)	\
+do {	u32 tmp = sbus_readl((__regs) + DMA_CSR); \
+	tmp |= (DMA_ENABLE|DMA_INT_ENAB); \
+	tmp &= ~DMA_ST_WRITE; \
+	sbus_writel(tmp, (__regs) + DMA_CSR); \
+} while(0)
 
 /* For certain DMA chips, we need to disable ints upon irq entry
  * and turn them back on when we are done.  So in any ESP interrupt
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/elf.h linux/include/asm-sparc64/elf.h
--- v2.3.34/linux/include/asm-sparc64/elf.h	Fri Aug  6 11:58:00 1999
+++ linux/include/asm-sparc64/elf.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: elf.h,v 1.21 1999/08/04 07:04:23 jj Exp $ */
+/* $Id: elf.h,v 1.23 1999/12/15 14:19:06 davem Exp $ */
 #ifndef __ASM_SPARC64_ELF_H
 #define __ASM_SPARC64_ELF_H
 
@@ -48,7 +48,7 @@
    that it will "exec", and that there is sufficient room for the brk.  */
 
 #ifndef ELF_ET_DYN_BASE
-#define ELF_ET_DYN_BASE         0xfffff80000000000UL
+#define ELF_ET_DYN_BASE         0x0000010000000000UL
 #endif
 
 
@@ -75,9 +75,17 @@
 		flags &= ~SPARC_FLAG_32BIT;		\
 	if (flags != current->thread.flags) {		\
 		unsigned long pgd_cache = 0UL;		\
-		if (flags & SPARC_FLAG_32BIT)		\
-		  pgd_cache =				\
-		    pgd_val(current->mm->pgd[0])<<11UL;	\
+		if (flags & SPARC_FLAG_32BIT) {		\
+		  pgd_t *pgd0 = &current->mm->pgd[0];	\
+		  if (pgd_none (*pgd0)) {		\
+		    pmd_t *page = get_pmd_fast();	\
+		    if (!page)				\
+		      (void) get_pmd_slow(pgd0, 0);	\
+                    else				\
+                      pgd_set(pgd0, page);		\
+		  }					\
+		  pgd_cache = pgd_val(*pgd0) << 11UL;	\
+		}					\
 		__asm__ __volatile__(			\
 			"stxa\t%0, [%1] %2"		\
 			: /* no outputs */		\
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/fhc.h linux/include/asm-sparc64/fhc.h
--- v2.3.34/linux/include/asm-sparc64/fhc.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/fhc.h	Mon Dec 20 22:05:52 1999
@@ -1,7 +1,7 @@
-/* $Id: fhc.h,v 1.4 1998/12/14 12:18:20 davem Exp $
+/* $Id: fhc.h,v 1.5 1999/09/21 14:39:29 davem Exp $
  * fhc.h: Structures for central/fhc pseudo driver on Sunfire/Starfire/Wildfire.
  *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com)
  */
 
 #ifndef _SPARC64_FHC_H
@@ -9,29 +9,20 @@
 
 #include <linux/timer.h>
 
-#include <asm/firehose.h>
 #include <asm/oplib.h>
+#include <asm/upa.h>
 
 struct linux_fhc;
 
-struct clock_board_regs {
-	u8	control;
-	u8	_unused1[0x10 - 0x01];
-	u8	stat1;
-	u8	_unused2[0x10 - 0x01];
-	u8	stat2;
-	u8	_unused3[0x10 - 0x01];
-	u8	pwr_stat;
-	u8	_unused4[0x10 - 0x01];
-	u8	pwr_presence;
-	u8	_unused5[0x10 - 0x01];
-	u8	temperature;
-	u8	_unused6[0x10 - 0x01];
-	u8	irq_diag;
-	u8	_unused7[0x10 - 0x01];
-	u8	pwr_stat2;
-	u8	_unused8[0x10 - 0x01];
-};
+/* Clock board register offsets. */
+#define CLOCK_CTRL	0x00UL	/* Main control */
+#define CLOCK_STAT1	0x10UL	/* Status one */
+#define CLOCK_STAT2	0x20UL	/* Status two */
+#define CLOCK_PWRSTAT	0x30UL	/* Power status */
+#define CLOCK_PWRPRES	0x40UL	/* Power presence */
+#define CLOCK_TEMP	0x50UL	/* Temperature */
+#define CLOCK_IRQDIAG	0x60UL	/* IRQ diagnostics */
+#define CLOCK_PWRSTAT2	0x70UL	/* Power status two */
 
 #define CLOCK_CTRL_LLED		0x04	/* Left LED, 0 == on */
 #define CLOCK_CTRL_MLED		0x02	/* Mid LED, 1 == on */
@@ -39,9 +30,9 @@
 
 struct linux_central {
 	struct linux_fhc		*child;
-	volatile u8			*cfreg;
-	struct clock_board_regs		*clkregs;
-	volatile u8			*clkver;
+	unsigned long			cfreg;
+	unsigned long			clkregs;
+	unsigned long			clkver;
 	int				slots;
 	int				prom_node;
 	char				prom_name[64];
@@ -50,6 +41,71 @@
 	int				num_central_ranges;
 };
 
+/* Firehose controller register offsets */
+struct fhc_regs {
+	unsigned long			pregs;	/* FHC internal regs */
+#define FHC_PREGS_ID	0x00UL	/* FHC ID */
+#define  FHC_ID_VERS		0xf0000000 /* Version of this FHC		*/
+#define  FHC_ID_PARTID		0x0ffff000 /* Part ID code (0x0f9f == FHC)	*/
+#define  FHC_ID_MANUF		0x0000007e /* Manufacturer (0x3e == SUN's JEDEC)*/
+#define  FHC_ID_RESV		0x00000001 /* Read as one			*/
+#define FHC_PREGS_RCS	0x10UL	/* FHC Reset Control/Status Register */
+#define  FHC_RCS_POR		0x80000000 /* Last reset was a power cycle	*/
+#define  FHC_RCS_SPOR		0x40000000 /* Last reset was sw power on reset	*/
+#define  FHC_RCS_SXIR		0x20000000 /* Last reset was sw XIR reset	*/
+#define  FHC_RCS_BPOR		0x10000000 /* Last reset was due to POR button	*/
+#define  FHC_RCS_BXIR		0x08000000 /* Last reset was due to XIR button	*/
+#define  FHC_RCS_WEVENT		0x04000000 /* CPU reset was due to wakeup event	*/
+#define  FHC_RCS_CFATAL		0x02000000 /* Centerplane Fatal Error signalled	*/
+#define  FHC_RCS_FENAB		0x01000000 /* Fatal errors elicit system reset	*/
+#define FHC_PREGS_CTRL	0x20UL	/* FHC Control Register */
+#define  FHC_CONTROL_ICS	0x00100000 /* Ignore Centerplane Signals	*/
+#define  FHC_CONTROL_FRST	0x00080000 /* Fatal Error Reset Enable		*/
+#define  FHC_CONTROL_LFAT	0x00040000 /* AC/DC signalled a local error	*/
+#define  FHC_CONTROL_SLINE	0x00010000 /* Firmware Synchronization Line	*/
+#define  FHC_CONTROL_DCD	0x00008000 /* DC-->DC Converter Disable		*/
+#define  FHC_CONTROL_POFF	0x00004000 /* AC/DC Controller PLL Disable	*/
+#define  FHC_CONTROL_FOFF	0x00002000 /* FHC Controller PLL Disable	*/
+#define  FHC_CONTROL_AOFF	0x00001000 /* CPU A SRAM/SBD Low Power Mode	*/
+#define  FHC_CONTROL_BOFF	0x00000800 /* CPU B SRAM/SBD Low Power Mode	*/
+#define  FHC_CONTROL_PSOFF	0x00000400 /* Turns off this FHC's power supply	*/
+#define  FHC_CONTROL_IXIST	0x00000200 /* 0=FHC tells clock board it exists	*/
+#define  FHC_CONTROL_XMSTR	0x00000100 /* 1=Causes this FHC to be XIR master*/
+#define  FHC_CONTROL_LLED	0x00000040 /* 0=Left LED ON			*/
+#define  FHC_CONTROL_MLED	0x00000020 /* 1=Middle LED ON			*/
+#define  FHC_CONTROL_RLED	0x00000010 /* 1=Right LED			*/
+#define  FHC_CONTROL_BPINS	0x00000003 /* Spare Bidirectional Pins		*/
+#define FHC_PREGS_BSR	0x30UL	/* FHC Board Status Register */
+#define  FHC_BSR_DA64		0x00040000 /* Port A: 0=128bit 1=64bit data path */
+#define  FHC_BSR_DB64		0x00020000 /* Port B: 0=128bit 1=64bit data path */
+#define  FHC_BSR_BID		0x0001e000 /* Board ID                           */
+#define  FHC_BSR_SA		0x00001c00 /* Port A UPA Speed (from the pins)   */
+#define  FHC_BSR_SB		0x00000380 /* Port B UPA Speed (from the pins)   */
+#define  FHC_BSR_NDIAG		0x00000040 /* Not in Diag Mode                   */
+#define  FHC_BSR_NTBED		0x00000020 /* Not in TestBED Mode                */
+#define  FHC_BSR_NIA		0x0000001c /* Jumper, bit 18 in PROM space       */
+#define  FHC_BSR_SI		0x00000001 /* Spare input pin value              */
+#define FHC_PREGS_ECC	0x40UL	/* FHC ECC Control Register (16 bits) */
+#define FHC_PREGS_JCTRL	0x50UL	/* FHC JTAG Control Register */
+#define  FHC_JTAG_CTRL_MENAB	0x80000000 /* Indicates this is JTAG Master	 */
+#define  FHC_JTAG_CTRL_MNONE	0x40000000 /* Indicates no JTAG Master present	 */
+#define FHC_PREGS_JCMD	0x60UL	/* FHC JTAG Command Register */
+	unsigned long			ireg;	/* FHC IGN reg */
+#define FHC_IREG_IGN	0x00UL	/* This FHC's IGN */
+	unsigned long			ffregs;	/* FHC fanfail regs */
+#define FHC_FFREGS_IMAP	0x00UL	/* FHC Fanfail IMAP */
+#define FHC_FFREGS_ICLR	0x10UL	/* FHC Fanfail ICLR */
+	unsigned long			sregs;	/* FHC system regs */
+#define FHC_SREGS_IMAP	0x00UL	/* FHC System IMAP */
+#define FHC_SREGS_ICLR	0x10UL	/* FHC System ICLR */
+	unsigned long			uregs;	/* FHC uart regs */
+#define FHC_UREGS_IMAP	0x00UL	/* FHC Uart IMAP */
+#define FHC_UREGS_ICLR	0x10UL	/* FHC Uart ICLR */
+	unsigned long			tregs;	/* FHC TOD regs */
+#define FHC_TREGS_IMAP	0x00UL	/* FHC TOD IMAP */
+#define FHC_TREGS_ICLR	0x10UL	/* FHC TOD ICLR */
+};
+
 struct linux_fhc {
 	struct linux_fhc		*next;
 	struct linux_central		*parent;	/* NULL if not central FHC */
@@ -65,12 +121,12 @@
 
 extern struct linux_central *central_bus;
 
-extern void prom_apply_central_ranges(struct linux_central *central, 
-				      struct linux_prom_registers *regs,
-				      int nregs);
-
-extern void prom_apply_fhc_ranges(struct linux_fhc *fhc, 
-				   struct linux_prom_registers *regs,
-				  int nregs);
+extern void apply_central_ranges(struct linux_central *central, 
+				 struct linux_prom_registers *regs,
+				 int nregs);
+
+extern void apply_fhc_ranges(struct linux_fhc *fhc, 
+			     struct linux_prom_registers *regs,
+			     int nregs);
 
 #endif /* !(_SPARC64_FHC_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/firehose.h linux/include/asm-sparc64/firehose.h
--- v2.3.34/linux/include/asm-sparc64/firehose.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/firehose.h	Wed Dec 31 16:00:00 1969
@@ -1,141 +0,0 @@
-/* $Id: firehose.h,v 1.4 1998/12/02 10:16:47 davem Exp $
- * firehose.h: Defines for the Fire Hose Controller (FHC) found
- *             on Sunfire/Starfire/Wildfire systems.
- *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC64_FIREHOSE_H
-#define _SPARC64_FIREHOSE_H
-
-#include <linux/types.h>
-
-/* Fire Hose Controller Internal Registers */
-struct fhc_internal_regs {
-/*0x0000*/	u32	fhc_id;		/* FHC ID Register			*/
-		u32	_unused1[3];
-/*0x0010*/	u32	fhc_rcs;	/* FHC Reset Control/Status Register	*/
-		u32	_unused2[3];
-/*0x0020*/	u32	fhc_control;	/* FHC Control Register			*/
-		u32	_unused3[3];
-/*0x0030*/	u32	fhc_bsr;	/* FHC Board Status Register		*/
-		u32	_unused4[3];
-/*0x0040*/	u32	fhc_ecc;	/* FHC ECC Control Register (16 bits)	*/
-		u32	_unused5[43];
-/*0x00f0*/	u32	fhc_jtag_ctrl;	/* FHC JTAG Control Register		*/
-		u32	_unused6[3];
-/*0x0100*/	u32	fhc_jtag_cmd;	/* FHC JTAG Command Register		*/
-};
-
-/* Part of same space of regs, but mapped separately in PROM reg property
- * for the FHC, thus we have the following few structs...
- */
-struct fhc_ign_reg {
-/*0x2000*/	u32	fhc_ign;		/* FHC Interrupt Group Number	*/
-};
-
-struct fhc_fanfail_regs {
-/*0x4000*/	u32	fhc_ff_imap;		/* FHC FanFail Interrupt Map	*/
-		u32	_pad[3];
-/*0x4010*/	u32	fhc_ff_iclr;		/* FHC FanFail Interrupt Clear	*/
-};
-
-struct fhc_system_regs {
-/*0x6000*/	u32	fhc_sys_imap;		/* FHC System Interrupt Map	*/
-		u32	_pad[3];
-/*0x6010*/	u32	fhc_sys_iclr;		/* FHC System Interrupt Clear	*/
-};
-
-struct fhc_uart_regs {
-/*0x8000*/	u32	fhc_uart_imap;		/* FHC UART Interrupt Map	*/
-		u32	_pad[3];
-/*0x8010*/	u32	fhc_uart_iclr;		/* FHC UART Interrupt Clear	*/
-};
-
-struct fhc_tod_regs {
-/*0xa000*/	u32	fhc_tod_imap;		/* FHC TOD Interrupt Map	*/
-		u32	_pad1[3];
-/*0xa010*/	u32	fhc_tod_iclr;		/* FHC TOD Interrupt Clear	*/
-};
-
-/* All of the above. */
-struct fhc_regs {
-	struct fhc_internal_regs	*pregs;
-	struct fhc_ign_reg		*ireg;
-	struct fhc_fanfail_regs		*ffregs;
-	struct fhc_system_regs		*sregs;
-	struct fhc_uart_regs		*uregs;
-	struct fhc_tod_regs		*tregs;
-};
-
-/* FHC ID Register */
-#define FHC_ID_VERS		0xf0000000 /* Version of this FHC		*/
-#define FHC_ID_PARTID		0x0ffff000 /* Part ID code (0x0f9f == FHC)	*/
-#define FHC_ID_MANUF		0x0000007e /* Manufacturer (0x3e == SUN's JEDEC)*/
-#define FHC_ID_RESV		0x00000001 /* Read as one			*/
-
-/* FHC Control Register */
-#define FHC_CONTROL_ICS		0x00100000 /* Ignore Centerplane Signals	*/
-#define FHC_CONTROL_FRST	0x00080000 /* Fatal Error Reset Enable		*/
-#define FHC_CONTROL_LFAT	0x00040000 /* AC/DC signalled a local error	*/
-#define FHC_CONTROL_SLINE	0x00010000 /* Firmware Synchronization Line	*/
-#define FHC_CONTROL_DCD		0x00008000 /* DC-->DC Converter Disable		*/
-#define FHC_CONTROL_POFF	0x00004000 /* AC/DC Controller PLL Disable	*/
-#define FHC_CONTROL_FOFF	0x00002000 /* FHC Controller PLL Disable	*/
-#define FHC_CONTROL_AOFF	0x00001000 /* CPU A SRAM/SBD Low Power Mode	*/
-#define FHC_CONTROL_BOFF	0x00000800 /* CPU B SRAM/SBD Low Power Mode	*/
-#define FHC_CONTROL_PSOFF	0x00000400 /* Turns off this FHC's power supply	*/
-#define FHC_CONTROL_IXIST	0x00000200 /* 0=FHC tells clock board it exists	*/
-#define FHC_CONTROL_XMSTR	0x00000100 /* 1=Causes this FHC to be XIR master*/
-#define FHC_CONTROL_LLED	0x00000040 /* 0=Left LED ON			*/
-#define FHC_CONTROL_MLED	0x00000020 /* 1=Middle LED ON			*/
-#define FHC_CONTROL_RLED	0x00000010 /* 1=Right LED			*/
-#define FHC_CONTROL_BPINS	0x00000003 /* Spare Bidirectional Pins		*/
-
-/* FHC Reset Control/Status Register */
-#define FHC_RCS_POR		0x80000000 /* Last reset was a power cycle	*/
-#define FHC_RCS_SPOR		0x40000000 /* Last reset was sw power on reset	*/
-#define FHC_RCS_SXIR		0x20000000 /* Last reset was sw XIR reset	*/
-#define FHC_RCS_BPOR		0x10000000 /* Last reset was due to POR button	*/
-#define FHC_RCS_BXIR		0x08000000 /* Last reset was due to XIR button	*/
-#define FHC_RCS_WEVENT		0x04000000 /* CPU reset was due to wakeup event	*/
-#define FHC_RCS_CFATAL		0x02000000 /* Centerplane Fatal Error signalled	*/
-#define FHC_RCS_FENAB		0x01000000 /* Fatal errors elicit system reset	*/
-
-/* FHC Board Status Register */
-#define FHC_BSR_DA64		0x00040000 /* Port A: 0=128bit 1=64bit data path */
-#define FHC_BSR_DB64		0x00020000 /* Port B: 0=128bit 1=64bit data path */
-#define FHC_BSR_BID		0x0001e000 /* Board ID                           */
-#define FHC_BSR_SA		0x00001c00 /* Port A UPA Speed (from the pins)   */
-#define FHC_BSR_SB		0x00000380 /* Port B UPA Speed (from the pins)   */
-#define FHC_BSR_NDIAG		0x00000040 /* Not in Diag Mode                   */
-#define FHC_BSR_NTBED		0x00000020 /* Not in TestBED Mode                */
-#define FHC_BSR_NIA		0x0000001c /* Jumper, bit 18 in PROM space       */
-#define FHC_BSR_SI		0x00000001 /* Spare input pin value              */
-
-/* FHC JTAG Control Register */
-#define FHC_JTAG_CTRL_MENAB	0x80000000 /* Indicates this is JTAG Master	 */
-#define FHC_JTAG_CTRL_MNONE	0x40000000 /* Indicates no JTAG Master present	 */
-
-/* FHC then has an Interrupt Group Number register, essentially this is a 32-bit
- * register with the low 5 bits specifying the IGN of this FHC for interrupt
- * generation purposes, it is a product of the BoardID/Pins seen by the FHC
- * at power on time.  I suspect the firmware really sets this value though
- * during POST.  On board FHC devices generate fixed INO interrupt packet
- * values, of course these are concatenated with the IGN before it reaches the
- * CPU:
- *
- *	IRQ Source		INO Value
- *	----------------------------------------
- *	"System" Interrupt	0x38
- *	Zilogs			0x39
- *	Mostek			0x3a
- *	Fan Failure		0x3b
- *	Spare 1			0x3c
- *	Spare 2			0x3d
- *
- * Consult the sysio.h header for the layout of the Interrupt Mapping and
- * Interrupt Clear register bits as they are the same. -DaveM
- */
-
-#endif /* !(_SPARC64_FIREHOSE_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/floppy.h linux/include/asm-sparc64/floppy.h
--- v2.3.34/linux/include/asm-sparc64/floppy.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-sparc64/floppy.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.22 1999/08/31 07:02:12 davem Exp $
+/* $Id: floppy.h,v 1.23 1999/09/21 14:39:34 davem Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -50,8 +50,8 @@
 
 /* You'll only ever find one controller on an Ultra anyways. */
 static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1;
-volatile unsigned char *fdc_status;
-static struct linux_sbus_device *floppy_sdev = NULL;
+unsigned long fdc_status;
+static struct sbus_dev *floppy_sdev = NULL;
 
 struct sun_floppy_ops {
 	unsigned char	(*fd_inb) (unsigned long port);
@@ -120,12 +120,12 @@
 		printk("floppy: Asked to read unknown port %lx\n", port);
 		panic("floppy: Port bolixed.");
 	case 4: /* FD_STATUS */
-		return sun_fdc->status_82077 & ~STATUS_DMA;
+		return sbus_readb(&sun_fdc->status_82077) & ~STATUS_DMA;
 	case 5: /* FD_DATA */
-		return sun_fdc->data_82077;
+		return sbus_readb(&sun_fdc->data_82077);
 	case 7: /* FD_DIR */
 		/* XXX: Is DCL on 0x80 in sun4m? */
-		return sun_fdc->dir_82077;
+		return sbus_readb(&sun_fdc->dir_82077);
 	};
 	panic("sun_82072_fd_inb: How did I get here?");
 }
@@ -139,16 +139,16 @@
 		panic("floppy: Port bolixed.");
 	case 2: /* FD_DOR */
 		/* Happily, the 82077 has a real DOR register. */
-		sun_fdc->dor_82077 = value;
+		sbus_writeb(value, &sun_fdc->dor_82077);
 		break;
 	case 5: /* FD_DATA */
-		sun_fdc->data_82077 = value;
+		sbus_writeb(value, &sun_fdc->data_82077);
 		break;
 	case 7: /* FD_DCR */
-		sun_fdc->dcr_82077 = value;
+		sbus_writeb(value, &sun_fdc->dcr_82077);
 		break;
 	case 4: /* FD_STATUS */
-		sun_fdc->status_82077 = value;
+		sbus_writeb(value, &sun_fdc->status_82077);
 		break;
 	};
 	return;
@@ -553,8 +553,8 @@
 {
 	char state[128];
 	int fd_node, num_regs;
-	struct linux_sbus *bus;
-	struct linux_sbus_device *sdev = NULL;
+	struct sbus_bus *bus;
+	struct sbus_dev *sdev = NULL;
 	static int initialized = 0;
 
 	if (initialized)
@@ -622,7 +622,7 @@
 
 		sun_fdops.fd_eject = sun_pci_fd_eject;
 
-        	fdc_status = &sun_fdc->status_82077;
+        	fdc_status = (unsigned long) &sun_fdc->status_82077;
 		FLOPPY_MOTOR_MASK = 0xf0;
 
 		/*
@@ -715,17 +715,17 @@
 	num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs,
 				    sizeof(fd_regs));
 	num_regs = (num_regs / sizeof(fd_regs[0]));
-	prom_apply_sbus_ranges(sdev->my_bus, fd_regs, num_regs, sdev);
+
 	/*
 	 * We cannot do sparc_alloc_io here: it does request_region,
 	 * which the generic floppy driver tries to do once again.
 	 */
 	sun_fdc = (struct sun_flpy_controller *)
-				(PAGE_OFFSET + fd_regs[0].phys_addr + 
-				 (((unsigned long)fd_regs[0].which_io) << 32));
+		(PAGE_OFFSET + fd_regs[0].phys_addr + 
+		 (((unsigned long)fd_regs[0].which_io) << 32));
 
 	/* Last minute sanity check... */
-	if(sun_fdc->status1_82077 == 0xff) {
+	if(sbus_readb(&sun_fdc->status1_82077) == 0xff) {
 		sun_fdc = (struct sun_flpy_controller *)-1;
 		return 0;
 	}
@@ -748,7 +748,7 @@
 
 	sun_fdops.fd_eject = sun_fd_eject;
 
-        fdc_status = &sun_fdc->status_82077;
+        fdc_status = (unsigned long) &sun_fdc->status_82077;
 
 	/* Success... */
 	allowed_drive_mask = 0x01;
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/ide.h linux/include/asm-sparc64/ide.h
--- v2.3.34/linux/include/asm-sparc64/ide.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-sparc64/ide.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ide.h,v 1.16 1999/08/30 10:14:42 davem Exp $
+/* $Id: ide.h,v 1.17 1999/12/15 22:18:49 davem Exp $
  * ide.h: Ultra/PCI specific IDE glue.
  *
  * Copyright (C) 1997  David S. Miller (davem@caip.rutgers.edu)
@@ -11,7 +11,7 @@
 #ifdef __KERNEL__
 
 #include <linux/config.h>
-#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
 #include <asm/io.h>
 #include <asm/hdreg.h>
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/io.h linux/include/asm-sparc64/io.h
--- v2.3.34/linux/include/asm-sparc64/io.h	Tue Dec  7 09:32:51 1999
+++ linux/include/asm-sparc64/io.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.24 1999/09/06 01:17:54 davem Exp $ */
+/* $Id: io.h,v 1.29 1999/12/20 04:58:42 davem Exp $ */
 #ifndef __SPARC64_IO_H
 #define __SPARC64_IO_H
 
@@ -13,7 +13,9 @@
 #define __SLOW_DOWN_IO	do { } while (0)
 #define SLOW_DOWN_IO	do { } while (0)
 
+#undef NEW_PCI_DMA_MAP
 
+#ifndef NEW_PCI_DMA_MAP
 #define PCI_DVMA_HASHSZ	256
 
 extern unsigned long pci_dvma_v2p_hash[PCI_DVMA_HASHSZ];
@@ -21,7 +23,7 @@
 
 #define pci_dvma_ahashfn(addr)	(((addr) >> 24) & 0xff)
 
-extern __inline__ unsigned long virt_to_phys(volatile void *addr)
+extern __inline__ unsigned long virt_to_bus(volatile void *addr)
 {
 	unsigned long vaddr = (unsigned long)addr;
 	unsigned long off;
@@ -34,7 +36,7 @@
 	return vaddr + off;
 }
 
-extern __inline__ void *phys_to_virt(unsigned long addr)
+extern __inline__ void *bus_to_virt(unsigned long addr)
 {
 	unsigned long paddr = addr & 0xffffffffUL;
 	unsigned long off;
@@ -42,9 +44,12 @@
 	off = pci_dvma_p2v_hash[pci_dvma_ahashfn(paddr)];
 	return (void *)(paddr + off);
 }
-
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
+#else
+extern unsigned long virt_to_bus_not_defined_use_pci_map(volatile void *addr);
+#define virt_to_bus virt_to_bus_not_defined_use_pci_map
+extern unsigned long bus_to_virt_not_defined_use_pci_map(volatile void *addr);
+#define bus_to_virt bus_to_virt_not_defined_use_pci_map
+#endif
 
 /* Different PCI controllers we support have their PCI MEM space
  * mapped to an either 2GB (Psycho) or 4GB (Sabre) aligned area,
@@ -58,7 +63,7 @@
 {
 	unsigned int ret;
 
-	__asm__ __volatile__("lduba [%1] %2, %0"
+	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_inb */"
 			     : "=r" (ret)
 			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 
@@ -69,7 +74,7 @@
 {
 	unsigned int ret;
 
-	__asm__ __volatile__("lduha [%1] %2, %0"
+	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_inw */"
 			     : "=r" (ret)
 			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 
@@ -80,7 +85,7 @@
 {
 	unsigned int ret;
 
-	__asm__ __volatile__("lduwa [%1] %2, %0"
+	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_inl */"
 			     : "=r" (ret)
 			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 
@@ -89,23 +94,23 @@
 
 extern __inline__ void outb(unsigned char b, unsigned long addr)
 {
-	__asm__ __volatile__("stba %0, [%1] %2"
+	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_outb */"
 			     : /* no outputs */
-			     : "r" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
+			     : "Jr" (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"
+	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_outw */"
 			     : /* no outputs */
-			     : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
+			     : "Jr" (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"
+	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_outl */"
 			     : /* no outputs */
-			     : "r" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
+			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
 #define inb_p inb
@@ -123,7 +128,7 @@
 {
 	unsigned int ret;
 
-	__asm__ __volatile__("lduba [%1] %2, %0"
+	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* pci_readb */"
 			     : "=r" (ret)
 			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 
@@ -134,7 +139,7 @@
 {
 	unsigned int ret;
 
-	__asm__ __volatile__("lduha [%1] %2, %0"
+	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* pci_readw */"
 			     : "=r" (ret)
 			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 
@@ -145,7 +150,7 @@
 {
 	unsigned int ret;
 
-	__asm__ __volatile__("lduwa [%1] %2, %0"
+	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* pci_readl */"
 			     : "=r" (ret)
 			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 
@@ -154,23 +159,23 @@
 
 extern __inline__ void _writeb(unsigned char b, unsigned long addr)
 {
-	__asm__ __volatile__("stba %0, [%1] %2"
+	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* pci_writeb */"
 			     : /* no outputs */
-			     : "r" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
+			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
 extern __inline__ void _writew(unsigned short w, unsigned long addr)
 {
-	__asm__ __volatile__("stha %0, [%1] %2"
+	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* pci_writew */"
 			     : /* no outputs */
-			     : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
+			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
 extern __inline__ void _writel(unsigned int l, unsigned long addr)
 {
-	__asm__ __volatile__("stwa %0, [%1] %2"
+	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* pci_writel */"
 			     : /* no outputs */
-			     : "r" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
+			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E_L));
 }
 
 #define readb(__addr)		(_readb((unsigned long)(__addr)))
@@ -180,57 +185,127 @@
 #define writew(__w, __addr)	(_writew((__w), (unsigned long)(__addr)))
 #define writel(__l, __addr)	(_writel((__l), (unsigned long)(__addr)))
 
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * Memcpy to/from I/O space is just a regular memory operation on
- * Ultra as well.
+/* Valid I/O Space regions are anywhere, because each PCI bus supported
+ * can live in an arbitrary area of the physical address range.
  */
+#define IO_SPACE_LIMIT 0xffffffffffffffffUL
 
-/*
- * FIXME: Write faster routines using ASL_*L for this.
+/* Now, SBUS variants, only difference from PCI is that we do
+ * not use little-endian ASIs.
  */
+extern __inline__ unsigned int _sbus_readb(unsigned long addr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* sbus_readb */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+extern __inline__ unsigned int _sbus_readw(unsigned long addr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* sbus_readw */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+extern __inline__ unsigned int _sbus_readl(unsigned long addr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* sbus_readl */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+extern __inline__ void _sbus_writeb(unsigned char b, unsigned long addr)
+{
+	__asm__ __volatile__("stba\t%r0, [%1] %2\t/* sbus_writeb */"
+			     : /* no outputs */
+			     : "Jr" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+extern __inline__ void _sbus_writew(unsigned short w, unsigned long addr)
+{
+	__asm__ __volatile__("stha\t%r0, [%1] %2\t/* sbus_writew */"
+			     : /* no outputs */
+			     : "Jr" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+extern __inline__ void _sbus_writel(unsigned int l, unsigned long addr)
+{
+	__asm__ __volatile__("stwa\t%r0, [%1] %2\t/* sbus_writel */"
+			     : /* no outputs */
+			     : "Jr" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+#define sbus_readb(__addr)		(_sbus_readb((unsigned long)(__addr)))
+#define sbus_readw(__addr)		(_sbus_readw((unsigned long)(__addr)))
+#define sbus_readl(__addr)		(_sbus_readl((unsigned long)(__addr)))
+#define sbus_writeb(__b, __addr)	(_sbus_writeb((__b), (unsigned long)(__addr)))
+#define sbus_writew(__w, __addr)	(_sbus_writew((__w), (unsigned long)(__addr)))
+#define sbus_writel(__l, __addr)	(_sbus_writel((__l), (unsigned long)(__addr)))
+
+static inline void *sbus_memset_io(void *__dst, int c, __kernel_size_t n)
+{
+	unsigned long dst = (unsigned long)__dst;
+
+	while(n--) {
+		sbus_writeb(c, dst);
+		dst++;
+	}
+	return (void *) dst;
+}
+
 static inline void *
 memset_io(void *dst, int c, __kernel_size_t n)
 {
 	char *d = dst;
 
-	while (n--)
-		*d++ = c;
+	while (n--) {
+		writeb(c, d);
+		d++;
+	}
 
 	return dst;
 }
 
 static inline void *
-memcpy_fromio(void *dst, const void *src, __kernel_size_t n)
+memcpy_fromio(void *dst, unsigned long src, __kernel_size_t n)
 {
-	const char *s = src;
 	char *d = dst;
 
-	while (n--)
-		*d++ = *s++;
+	while (n--) {
+		char tmp = readb(src);
+		*d++ = tmp;
+		src++;
+	}
 
 	return dst;
 }
 
 static inline void *
-memcpy_toio(void *dst, const void *src, __kernel_size_t n)
+memcpy_toio(unsigned long dst, const void *src, __kernel_size_t n)
 {
 	const char *s = src;
-	char *d = dst;
+	unsigned long d = dst;
 
-	while (n--)
-		*d++ = *s++;
-
-	return dst;
+	while (n--) {
+		char tmp = *s++;
+		writeb(tmp, d);
+		d++;
+	}
+	return (void *)dst;
 }
 
-#if 0 /* XXX Not exactly, we need to use ASI_*L from/to the I/O end,
-       * XXX so these are disabled until we code that stuff.
-       */
-#define eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),((char *)(b)),(c),(d))
-#endif
-
 static inline int check_signature(unsigned long io_addr,
 				  const unsigned char *signature,
 				  int length)
@@ -251,27 +326,18 @@
 #define ioremap(__offset, __size)	((void *)(__offset))
 #define iounmap(__addr)			do { } while(0)
 
-extern void sparc_ultra_mapioaddr(unsigned long physaddr,
-				  unsigned long virt_addr,
-				  int bus, int rdonly);
-extern void sparc_ultra_unmapioaddr(unsigned long virt_addr);
-
-extern __inline__ void mapioaddr(unsigned long physaddr,
-				 unsigned long virt_addr,
-				 int bus, int rdonly)
-{
-	sparc_ultra_mapioaddr(physaddr, virt_addr, bus, rdonly);
-}
-
-extern __inline__ void unmapioaddr(unsigned long virt_addr)
-{
-	sparc_ultra_unmapioaddr(virt_addr);
-}
+/* Similarly for SBUS. */
+#define sbus_ioremap(__res, __offset, __size, __name) \
+({	unsigned long __ret; \
+	__ret  = (__res)->start + (((__res)->flags & 0x1ffUL) << 32UL); \
+	__ret += (unsigned long) (__offset); \
+	if (! request_region((__ret), (__size), (__name))) \
+		__ret = 0UL; \
+	__ret; \
+})
 
-extern void *sparc_alloc_io(u32 pa, void *va, int sz, char *name,
-			    u32 io, int rdonly);
-extern void sparc_free_io (void *va, int sz);
-extern void *sparc_dvma_malloc (int sz, char *name, __u32 *dvma_addr);
+#define sbus_iounmap(__addr, __size)	\
+	release_region((__addr), (__size))
 
 /* Nothing to do */
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/iommu.h linux/include/asm-sparc64/iommu.h
--- v2.3.34/linux/include/asm-sparc64/iommu.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc64/iommu.h	Mon Dec 20 22:05:52 1999
@@ -1,40 +1,12 @@
-/* iommu.h: Definitions for the sun5 IOMMU.
+/* $Id: iommu.h,v 1.9 1999/09/21 14:39:39 davem Exp $
+ * iommu.h: Definitions for the sun5 IOMMU.
  *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 1999 David S. Miller (davem@caip.rutgers.edu)
  */
 #ifndef _SPARC64_IOMMU_H
 #define _SPARC64_IOMMU_H
 
-#include <linux/spinlock.h>
-#include <asm/page.h>
-#include <asm/sysio.h>
-
-/* The iommu handles all virtual to physical address translations
- * that occur between the SYSIO and physical memory.  Access by
- * the cpu to IO registers and similar go over the UPA so are
- * translated by the on chip TLB's.  The iommu and the TLB do
- * not need to have the same translations at all, in fact most
- * of the time the translations they handle are a disjoint set.
- * Basically the iommu handles all SYSIO dvma translations.
- */
-
-/* The IOMMU register set. */
-#define IOMMU_CTRL_IMPL     0xf000000000000000 /* Implementation                */
-#define IOMMU_CTRL_VERS     0x0f00000000000000 /* Version                       */
-#define IOMMU_CTRL_TSBSZ    0x0000000000070000 /* TSB Size                      */
-#define IOMMU_TSBSZ_1K      0x0000000000000000 /* TSB Table 1024 8-byte entries */
-#define IOMMU_TSBSZ_2K      0x0000000000010000 /* TSB Table 2048 8-byte entries */
-#define IOMMU_TSBSZ_4K      0x0000000000020000 /* TSB Table 4096 8-byte entries */
-#define IOMMU_TSBSZ_8K      0x0000000000030000 /* TSB Table 8192 8-byte entries */
-#define IOMMU_TSBSZ_16K     0x0000000000040000 /* TSB Table 16k 8-byte entries  */
-#define IOMMU_TSBSZ_32K     0x0000000000050000 /* TSB Table 32k 8-byte entries  */
-#define IOMMU_TSBSZ_64K     0x0000000000060000 /* TSB Table 64k 8-byte entries  */
-#define IOMMU_TSBSZ_128K    0x0000000000070000 /* TSB Table 128k 8-byte entries */
-#define IOMMU_CTRL_TBWSZ    0x0000000000000004 /* Assumed page size, 0=8k 1=64k */
-#define IOMMU_CTRL_DENAB    0x0000000000000002 /* Diagnostic mode enable        */
-#define IOMMU_CTRL_ENAB     0x0000000000000001 /* IOMMU Enable                  */
-
-/* The format of an iopte in the page tables, we only use 64k pages. */
+/* The format of an iopte in the page tables. */
 #define IOPTE_VALID         0x8000000000000000 /* IOPTE is valid                   */
 #define IOPTE_64K           0x2000000000000000 /* IOPTE is for 64k page            */
 #define IOPTE_STBUF         0x1000000000000000 /* DVMA can use streaming buffer    */
@@ -43,13 +15,5 @@
 #define IOPTE_PAGE          0x00007fffffffe000 /* Physical page number (PA[40:13]) */
 #define IOPTE_CACHE         0x0000000000000010 /* Cached (in UPA E-cache)          */
 #define IOPTE_WRITE         0x0000000000000002 /* Writeable                        */
-
-struct iommu_struct {
-	struct sysio_regs	*sysio_regs;
-	iopte_t			*page_table;
-	volatile unsigned int	flushflag;
-	unsigned int		strbuf_enabled;
-	spinlock_t		iommu_lock;
-};
 
 #endif /* !(_SPARC_IOMMU_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/ipc.h linux/include/asm-sparc64/ipc.h
--- v2.3.34/linux/include/asm-sparc64/ipc.h	Wed Apr 23 19:01:28 1997
+++ linux/include/asm-sparc64/ipc.h	Mon Dec 20 22:05:52 1999
@@ -23,6 +23,9 @@
 #define SHMGET		23
 #define SHMCTL		24
 
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC            25
+
 /* We don't need to maintain backward compatibility on 64bit, we've started fresh */
 #define IPCCALL(version,op)	(op)
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/irq.h linux/include/asm-sparc64/irq.h
--- v2.3.34/linux/include/asm-sparc64/irq.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc64/irq.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: irq.h,v 1.16 1999/09/06 01:17:52 davem Exp $
+/* $Id: irq.h,v 1.17 1999/09/21 14:39:41 davem Exp $
  * irq.h: IRQ registers on the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -61,13 +61,24 @@
 /*0x08*/void *irq_info;
 
 	/* Sun5 Interrupt Clear Register. */
-/*0x10*/volatile unsigned int *iclr;
+/*0x10*/unsigned long iclr;
 
 	/* Sun5 Interrupt Mapping Register. */
-/*0x18*/volatile unsigned int *imap;
+/*0x18*/unsigned long imap;
 
 };
 
+/* IMAP/ICLR register defines */
+#define IMAP_VALID		0x80000000	/* IRQ Enabled		*/
+#define IMAP_TID		0x7c000000	/* UPA TargetID		*/
+#define IMAP_IGN		0x000007c0	/* IRQ Group Number	*/
+#define IMAP_INO		0x0000003f	/* IRQ Number		*/
+#define IMAP_INR		0x000007ff	/* Full interrupt number*/
+
+#define ICLR_IDLE		0x00000000	/* Idle state		*/
+#define ICLR_TRANSMIT		0x00000001	/* Transmit state	*/
+#define ICLR_PENDING		0x00000003	/* Pending state	*/
+
 /* 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.	 */
@@ -98,7 +109,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, volatile unsigned int *iclr, volatile unsigned int *imap);
+extern unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long 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.34/linux/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h
--- v2.3.34/linux/include/asm-sparc64/mmu_context.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc64/mmu_context.h	Mon Dec 20 22:05:52 1999
@@ -1,14 +1,14 @@
-/* $Id: mmu_context.h,v 1.40 1999/09/10 10:44:37 davem Exp $ */
+/* $Id: mmu_context.h,v 1.41 1999/09/10 15:39:03 jj Exp $ */
 #ifndef __SPARC64_MMU_CONTEXT_H
 #define __SPARC64_MMU_CONTEXT_H
 
 /* Derived heavily from Linus's Alpha/AXP ASN code... */
 
+#ifndef __ASSEMBLY__
+
 #include <linux/spinlock.h>
 #include <asm/system.h>
 #include <asm/spitfire.h>
-
-#ifndef __ASSEMBLY__
 
 extern spinlock_t ctx_alloc_lock;
 extern unsigned long tlb_context_cache;
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/openpromio.h linux/include/asm-sparc64/openpromio.h
--- v2.3.34/linux/include/asm-sparc64/openpromio.h	Mon Dec 30 02:00:03 1996
+++ linux/include/asm-sparc64/openpromio.h	Mon Dec 20 22:05:52 1999
@@ -29,6 +29,10 @@
 #define	OPROMGETCONS		0x20004F0A
 #define	OPROMGETFBNAME		0x20004F0B
 #define	OPROMGETBOOTARGS	0x20004F0C
+/* Linux extensions */				/* Arguments in oprom_array: */
+#define OPROMSETCUR		0x20004FF0	/* int node - Sets current node */
+#define OPROMPCI2NODE		0x20004FF1	/* int pci_bus, pci_devfn - Sets current node to PCI device's node */
+#define OPROMPATH2NODE		0x20004FF2	/* char path[] - Set current node from fully qualified PROM path */
 
 /*
  * Return values from OPROMGETCONS:
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/oplib.h linux/include/asm-sparc64/oplib.h
--- v2.3.34/linux/include/asm-sparc64/oplib.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc64/oplib.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: oplib.h,v 1.11 1999/08/31 19:25:49 davem Exp $
+/* $Id: oplib.h,v 1.12 1999/11/19 05:53:12 davem Exp $
  * oplib.h:  Describes the interface and available routines in the
  *           Linux Prom library.
  *
@@ -222,6 +222,24 @@
 extern long prom_dtlb_load(unsigned long index,
 			   unsigned long tte_data,
 			   unsigned long vaddr);
+
+/* Map/Unmap client program address ranges.  First the format of
+ * the mapping mode argument.
+ */
+#define PROM_MAP_WRITE	0x0001 /* Writable */
+#define PROM_MAP_READ	0x0002 /* Readable - sw */
+#define PROM_MAP_EXEC	0x0004 /* Executable - sw */
+#define PROM_MAP_LOCKED	0x0010 /* Locked, use i/dtlb load calls for this instead */
+#define PROM_MAP_CACHED	0x0020 /* Cacheable in both L1 and L2 caches */
+#define PROM_MAP_SE	0x0040 /* Side-Effects */
+#define PROM_MAP_GLOB	0x0080 /* Global */
+#define PROM_MAP_IE	0x0100 /* Invert-Endianness */
+#define PROM_MAP_DEFAULT (PROM_MAP_WRITE | PROM_MAP_READ | PROM_MAP_EXEC | PROM_MAP_CACHED)
+
+extern int prom_map(int mode, unsigned long size,
+		    unsigned long vaddr, unsigned long paddr);
+extern void prom_unmap(unsigned long size, unsigned long vaddr);
+
 
 /* PROM device tree traversal functions... */
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/page.h linux/include/asm-sparc64/page.h
--- v2.3.34/linux/include/asm-sparc64/page.h	Mon Aug  2 22:07:16 1999
+++ linux/include/asm-sparc64/page.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: page.h,v 1.27 1999/07/31 00:07:25 davem Exp $ */
+/* $Id: page.h,v 1.29 1999/12/09 10:32:43 davem Exp $ */
 
 #ifndef _SPARC64_PAGE_H
 #define _SPARC64_PAGE_H
@@ -21,8 +21,8 @@
 #define BUG()		__builtin_trap()
 #define PAGE_BUG(page)	BUG()
 
-extern void clear_page(unsigned long page);
-extern void copy_page(unsigned long to, unsigned long from);
+extern void clear_page(void *page);
+extern void copy_page(void *to, void *from);
 
 /* GROSS, defining this makes gcc pass these types as aggregates,
  * and thus on the stack, turn this crap off... -DaveM
@@ -103,6 +103,9 @@
 #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 virt_to_phys __pa
+#define phys_to_virt __va
 
 #ifndef __ASSEMBLY__
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/pbm.h linux/include/asm-sparc64/pbm.h
--- v2.3.34/linux/include/asm-sparc64/pbm.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc64/pbm.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: pbm.h,v 1.18 1999/09/10 10:44:40 davem Exp $
+/* $Id: pbm.h,v 1.19 1999/12/17 12:32:13 jj Exp $
  * pbm.h: UltraSparc PCI controller software state.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -25,6 +25,9 @@
  * PCI bus module controls it's own autonomous PCI bus.
  */
 
+#define PBM_LOGCLUSTERS 3
+#define PBM_NCLUSTERS (1 << PBM_LOGCLUSTERS)
+
 struct pci_controller_info;
 
 /* This contains the software state necessary to drive a PCI
@@ -40,8 +43,8 @@
 	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? */
+	iopte_t		*page_table;		/* The page table itself. */
+	int		page_table_sz_bits;	/* log2 of ow many pages does it map? */
 
 	/* Base PCI memory space address where IOMMU mappings
 	 * begin.
@@ -49,7 +52,6 @@
 	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 */
@@ -60,12 +62,18 @@
 	 * completion of all previous writes into IOMMU/STC.
 	 */
 	unsigned long	write_complete_reg;
+
+	/* If PBM_NCLUSTERS is ever decreased to 4 or lower,
+	 * or if largest supported page_table_sz * 8K goes above
+	 * 2GB, you must increase the size of the type of
+	 * these counters.  You have been duly warned. -DaveM
+	 */
+	u16		lowest_free[PBM_NCLUSTERS];
 };
 
 /* 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 */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/pci.h linux/include/asm-sparc64/pci.h
--- v2.3.34/linux/include/asm-sparc64/pci.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc64/pci.h	Mon Dec 20 22:05:52 1999
@@ -9,35 +9,81 @@
  */
 #define pcibios_assign_all_busses()	0
 
-/* Map kernel buffer using consistant mode DMA for PCI device.
- * Returns a 32-bit PCI DMA address.
+struct pci_dev;
+
+/* Allocate and map kernel buffer using consistant mode DMA for PCI device.
+ * Returns non-NULL cpu-view pointer to the buffer if successful and
+ * sets *dma_addrp to the pci side dma address as well, else *dma_addrp
+ * is undefined.
  */
-extern u32 pci_map_consistant(struct pci_dev *, void *, int);
+extern void *pci_alloc_consistant(struct pci_dev *pdev, long size, u32 *dma_addrp);
 
-/* Unmap a consistant DMA translation. */
-extern void pci_unmap_consistant(struct pci_dev *, u32, int);
+/* Free and unmap a consistant DMA buffer.
+ * cpu_addr is what was returned from pci_alloc_consistant,
+ * size must be the same as what as passed into pci_alloc_consistant,
+ * and likewise dma_addr must be the same as what *dma_addrp was set to.
+ *
+ * References to the memory and mappings assosciated with cpu_addr/dma_addr
+ * past this call are illegal.
+ */
+extern void pci_free_consistant(struct pci_dev *pdev, long size, void *cpu_addr, u32 dma_addr);
 
-/* Map a single buffer for PCI DMA in streaming mode. */
-extern u32 pci_map_single(struct pci_dev *, void *, int);
+/* Map a single buffer of the indicate size for PCI DMA in streaming mode.
+ * The 32-bit PCI bus mastering address to use is returned.
+ *
+ * Once the device is given the dma address, the device owns this memory
+ * until either pci_unmap_single or pci_sync_single is performed.
+ */
+extern u32 pci_map_single(struct pci_dev *pdev, void *buffer, long size);
 
-/* Unmap a single streaming mode DMA translation. */
-extern void pci_unmap_single(struct pci_dev *, u32, int);
+/* Unmap a single streaming mode DMA translation.  The dma_addr and size
+ * must match what was provided for in a previous pci_map_single call.  All
+ * other usages are undefined.
+ *
+ * After this call, reads by the cpu to the buffer are guarenteed to see
+ * whatever the device wrote there.
+ */
+extern void pci_unmap_single(struct pci_dev *pdev, u32 dma_addr, long size);
 
 /* Map a set of buffers described by scatterlist in streaming
- * mode for PCI DMA.
+ * mode for PCI DMA.  This is the scather-gather version of the
+ * above pci_map_single interface.  Here the scatter gather list
+ * elements are each tagged with the appropriate PCI dma address
+ * and length.  They are obtained via sg_dma_{address,length}(SG).
+ *
+ * NOTE: An implementation may be able to use a smaller number of
+ *       DMA address/length pairs than there are SG table elements.
+ *       (for example via virtual mapping capabilities)
+ *	 The routine returns the number of addr/length pairs actually
+ *	 used, at most nents.
+ *
+ * Device ownership issues as mentioned above for pci_map_single are
+ * the same here.
  */
-extern void pci_map_sg(struct pci_dev *, struct scatterlist *, int);
+extern int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents);
 
-/* Unmap a set of streaming mode DMA translations. */
-extern void pci_unmap_sg(struct pci_dev *, struct scatterlist *, int);
+/* Unmap a set of streaming mode DMA translations.
+ * Again, cpu read rules concerning calls here are the same as for
+ * pci_unmap_single() above.
+ */
+extern void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents);
 
 /* Make physical memory consistant for a single
  * streaming mode DMA translation after a transfer.
+ *
+ * If you perform a pci_map_single() but wish to interrogate the
+ * buffer using the cpu, yet do not wish to teardown the PCI dma
+ * mapping, you must call this function before doing so.  At the
+ * next point you give the PCI dma address back to the card, the
+ * device again owns the buffer.
  */
-extern void pci_dma_sync_single(struct pci_dev *, u32, int);
+extern void pci_dma_sync_single(struct pci_dev *, u32, long);
 
 /* Make physical memory consistant for a set of streaming
  * mode DMA translations after a transfer.
+ *
+ * The same as pci_dma_sync_single but for a scatter-gather list,
+ * same rules and usage.
  */
 extern void pci_dma_sync_sg(struct pci_dev *, struct scatterlist *, int);
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/pgalloc.h linux/include/asm-sparc64/pgalloc.h
--- v2.3.34/linux/include/asm-sparc64/pgalloc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/pgalloc.h	Tue Dec 21 21:56:42 1999
@@ -0,0 +1,301 @@
+/* $Id */
+#ifndef _SPARC64_PGALLOC_H
+#define _SPARC64_PGALLOC_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/page.h>
+
+/* Cache and TLB flush operations. */
+
+/* These are the same regardless of whether this is an SMP kernel or not. */
+#define flush_cache_mm(__mm) \
+	do { if ((__mm) == current->mm) flushw_user(); } while(0)
+#define flush_cache_range(mm, start, end) \
+	flush_cache_mm(mm)
+#define flush_cache_page(vma, page) \
+	flush_cache_mm((vma)->vm_mm)
+
+/* These operations are unnecessary on the SpitFire since D-CACHE is write-through. */
+#define flush_icache_range(start, end)		do { } while (0)
+#define flush_page_to_ram(page)			do { } while (0)
+
+extern void __flush_dcache_range(unsigned long start, unsigned long end);
+
+extern void __flush_cache_all(void);
+
+extern void __flush_tlb_all(void);
+extern void __flush_tlb_mm(unsigned long context, unsigned long r);
+extern void __flush_tlb_range(unsigned long context, unsigned long start,
+			      unsigned long r, unsigned long end,
+			      unsigned long pgsz, unsigned long size);
+extern void __flush_tlb_page(unsigned long context, unsigned long page, unsigned long r);
+
+#ifndef __SMP__
+
+#define flush_cache_all()	__flush_cache_all()
+#define flush_tlb_all()		__flush_tlb_all()
+
+#define flush_tlb_mm(__mm) \
+do { if(CTX_VALID((__mm)->context)) \
+	__flush_tlb_mm(CTX_HWBITS((__mm)->context), SECONDARY_CONTEXT); \
+} while(0)
+
+#define flush_tlb_range(__mm, start, end) \
+do { if(CTX_VALID((__mm)->context)) { \
+	unsigned long __start = (start)&PAGE_MASK; \
+	unsigned long __end = (end)&PAGE_MASK; \
+	__flush_tlb_range(CTX_HWBITS((__mm)->context), __start, \
+			  SECONDARY_CONTEXT, __end, PAGE_SIZE, \
+			  (__end - __start)); \
+     } \
+} while(0)
+
+#define flush_tlb_page(vma, page) \
+do { struct mm_struct *__mm = (vma)->vm_mm; \
+     if(CTX_VALID(__mm->context)) \
+	__flush_tlb_page(CTX_HWBITS(__mm->context), (page)&PAGE_MASK, \
+			 SECONDARY_CONTEXT); \
+} while(0)
+
+#else /* __SMP__ */
+
+extern void smp_flush_cache_all(void);
+extern void smp_flush_tlb_all(void);
+extern void smp_flush_tlb_mm(struct mm_struct *mm);
+extern void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+				unsigned long end);
+extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page);
+
+#define flush_cache_all()	smp_flush_cache_all()
+#define flush_tlb_all()		smp_flush_tlb_all()
+
+extern __inline__ void flush_tlb_mm(struct mm_struct *mm)
+{
+	if (CTX_VALID(mm->context))
+		smp_flush_tlb_mm(mm);
+}
+
+extern __inline__ void flush_tlb_range(struct mm_struct *mm, unsigned long start,
+				       unsigned long end)
+{
+	if (CTX_VALID(mm->context))
+		smp_flush_tlb_range(mm, start, end);
+}
+
+extern __inline__ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	struct mm_struct *mm = vma->vm_mm;
+
+	if (CTX_VALID(mm->context))
+		smp_flush_tlb_page(mm, page);
+}
+
+#endif /* ! __SMP__ */
+
+/* Page table allocation/freeing. */
+#ifdef __SMP__
+/* Sliiiicck */
+#define pgt_quicklists	cpu_data[smp_processor_id()]
+#else
+extern struct pgtable_cache_struct {
+	unsigned long *pgd_cache;
+	unsigned long *pte_cache[2];
+	unsigned int pgcache_size;
+	unsigned int pgdcache_size;
+} pgt_quicklists;
+#endif
+#define pgd_quicklist		(pgt_quicklists.pgd_cache)
+#define pmd_quicklist		((unsigned long *)0)
+#define pte_quicklist		(pgt_quicklists.pte_cache)
+#define pgtable_cache_size	(pgt_quicklists.pgcache_size)
+#define pgd_cache_size		(pgt_quicklists.pgdcache_size)
+
+#ifndef __SMP__
+
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
+{
+	struct page *page = mem_map + MAP_NR(pgd);
+
+	if (!page->pprev_hash) {
+		(unsigned long *)page->next_hash = pgd_quicklist;
+		pgd_quicklist = (unsigned long *)page;
+	}
+	(unsigned long)page->pprev_hash |=
+		(((unsigned long)pgd & (PAGE_SIZE / 2)) ? 2 : 1);
+	pgd_cache_size++;
+}
+
+extern __inline__ pgd_t *get_pgd_fast(void)
+{
+        struct page *ret;
+
+        if ((ret = (struct page *)pgd_quicklist) != NULL) {
+                unsigned long mask = (unsigned long)ret->pprev_hash;
+		unsigned long off = 0;
+
+		if (mask & 1)
+			mask &= ~1;
+		else {
+			off = PAGE_SIZE / 2;
+			mask &= ~2;
+		}
+		(unsigned long)ret->pprev_hash = mask;
+		if (!mask)
+			pgd_quicklist = (unsigned long *)ret->next_hash;
+                ret = (struct page *)(__page_address(ret) + off);
+                pgd_cache_size--;
+        } else {
+		ret = (struct page *) __get_free_page(GFP_KERNEL);
+		if(ret) {
+			struct page *page = mem_map + MAP_NR(ret);
+			
+			memset(ret, 0, PAGE_SIZE);
+			(unsigned long)page->pprev_hash = 2;
+			(unsigned long *)page->next_hash = pgd_quicklist;
+			pgd_quicklist = (unsigned long *)page;
+			pgd_cache_size++;
+		}
+        }
+        return (pgd_t *)ret;
+}
+
+#else /* __SMP__ */
+
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
+{
+	*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
+	pgd_quicklist = (unsigned long *) pgd;
+	pgtable_cache_size++;
+}
+
+extern __inline__ pgd_t *get_pgd_fast(void)
+{
+	unsigned long *ret;
+
+	if((ret = pgd_quicklist) != NULL) {
+		pgd_quicklist = (unsigned long *)(*ret);
+		ret[0] = 0;
+		pgtable_cache_size--;
+	} else {
+		ret = (unsigned long *) __get_free_page(GFP_KERNEL);
+		if(ret)
+			memset(ret, 0, PAGE_SIZE);
+	}
+	return (pgd_t *)ret;
+}
+
+extern __inline__ void free_pgd_slow(pgd_t *pgd)
+{
+	free_page((unsigned long)pgd);
+}
+
+#endif /* __SMP__ */
+
+extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long address_premasked);
+
+extern __inline__ pmd_t *get_pmd_fast(void)
+{
+	unsigned long *ret;
+	int color = 0;
+
+	if (pte_quicklist[color] == NULL)
+		color = 1;
+	if((ret = (unsigned long *)pte_quicklist[color]) != NULL) {
+		pte_quicklist[color] = (unsigned long *)(*ret);
+		ret[0] = 0;
+		pgtable_cache_size--;
+	}
+	return (pmd_t *)ret;
+}
+
+extern __inline__ void free_pmd_fast(pmd_t *pmd)
+{
+	unsigned long color;
+
+	color = (((unsigned long)pmd >> PAGE_SHIFT) & 0x1UL);
+	*(unsigned long *)pmd = (unsigned long) pte_quicklist[color];
+	pte_quicklist[color] = (unsigned long *) pmd;
+	pgtable_cache_size++;
+}
+
+extern __inline__ void free_pmd_slow(pmd_t *pmd)
+{
+	free_page((unsigned long)pmd);
+}
+
+extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted,
+			   unsigned long color);
+
+extern __inline__ pte_t *get_pte_fast(unsigned long color)
+{
+	unsigned long *ret;
+
+	if((ret = (unsigned long *)pte_quicklist[color]) != NULL) {
+		pte_quicklist[color] = (unsigned long *)(*ret);
+		ret[0] = 0;
+		pgtable_cache_size--;
+	}
+	return (pte_t *)ret;
+}
+
+extern __inline__ void free_pte_fast(pte_t *pte)
+{
+	unsigned long color = (((unsigned long)pte >> PAGE_SHIFT) & 0x1);
+	*(unsigned long *)pte = (unsigned long) pte_quicklist[color];
+	pte_quicklist[color] = (unsigned long *) pte;
+	pgtable_cache_size++;
+}
+
+extern __inline__ void free_pte_slow(pte_t *pte)
+{
+	free_page((unsigned long)pte);
+}
+
+#define pte_free_kernel(pte)	free_pte_fast(pte)
+#define pte_free(pte)		free_pte_fast(pte)
+#define pmd_free_kernel(pmd)	free_pmd_fast(pmd)
+#define pmd_free(pmd)		free_pmd_fast(pmd)
+#define pgd_free(pgd)		free_pgd_fast(pgd)
+#define pgd_alloc()		get_pgd_fast()
+
+extern inline pte_t * pte_alloc(pmd_t *pmd, unsigned long address)
+{
+	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+	if (pmd_none(*pmd)) {
+		/* Be careful, address can be just about anything... */
+		unsigned long color = (((unsigned long)pmd)>>2UL) & 0x1UL;
+		pte_t *page = get_pte_fast(color);
+
+		if (!page)
+			return get_pte_slow(pmd, address, color);
+		pmd_set(pmd, page);
+		return page + address;
+	}
+	return (pte_t *) pmd_page(*pmd) + address;
+}
+
+extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
+{
+	address = (address >> PMD_SHIFT) & (REAL_PTRS_PER_PMD - 1);
+	if (pgd_none(*pgd)) {
+		pmd_t *page = get_pmd_fast();
+
+		if (!page)
+			return get_pmd_slow(pgd, address);
+		pgd_set(pgd, page);
+		return page + address;
+	}
+	return (pmd_t *) pgd_page(*pgd) + address;
+}
+
+#define pte_alloc_kernel(pmd, addr)	pte_alloc(pmd, addr)
+#define pmd_alloc_kernel(pgd, addr)	pmd_alloc(pgd, addr)
+
+extern int do_check_pgt_cache(int, int);
+
+/* Nothing to do on sparc64 :) */
+#define set_pgdir(address, entry)	do { } while(0)
+
+#endif /* _SPARC64_PGALLOC_H */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h
--- v2.3.34/linux/include/asm-sparc64/pgtable.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-sparc64/pgtable.h	Tue Dec 21 21:56:42 1999
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.110 1999/08/30 10:14:57 davem Exp $
+/* $Id: pgtable.h,v 1.118 1999/12/21 21:24:35 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -12,17 +12,12 @@
  * the SpitFire page tables.
  */
 
-#ifndef __ASSEMBLY__
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#endif
 #include <asm/spitfire.h>
 #include <asm/asi.h>
 #include <asm/mmu_context.h>
 #include <asm/system.h>
 
 #ifndef __ASSEMBLY__
-#include <asm/sbus.h>
 
 /* Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
@@ -69,6 +64,10 @@
 #define VMALLOC_VMADDR(x)	((unsigned long)(x))
 #define VMALLOC_END		0x0000000200000000UL
 
+#define pte_ERROR(e)	__builtin_trap()
+#define pmd_ERROR(e)	__builtin_trap()
+#define pgd_ERROR(e)	__builtin_trap()
+
 #endif /* !(__ASSEMBLY__) */
 
 /* SpitFire TTE bits. */
@@ -157,109 +156,30 @@
  * hit for all __pa()/__va() operations.
  */
 extern unsigned long phys_base;
-#define ZERO_PAGE(vaddr)	((unsigned long)__va(phys_base))
-
-/* Allocate a block of RAM which is aligned to its size.
- * This procedure can be used until the call to mem_init().
- */
-extern void *sparc_init_alloc(unsigned long *kbrk, unsigned long size);
-
-/* Cache and TLB flush operations. */
-
-/* These are the same regardless of whether this is an SMP kernel or not. */
-#define flush_cache_mm(__mm) \
-	do { if ((__mm) == current->mm) flushw_user(); } while(0)
-#define flush_cache_range(mm, start, end) \
-	flush_cache_mm(mm)
-#define flush_cache_page(vma, page) \
-	flush_cache_mm((vma)->vm_mm)
-
-/* These operations are unnecessary on the SpitFire since D-CACHE is write-through. */
-#define flush_icache_range(start, end)		do { } while (0)
-#define flush_page_to_ram(page)			do { } while (0)
-
-extern void __flush_dcache_range(unsigned long start, unsigned long end);
-
-extern void __flush_cache_all(void);
-
-extern void __flush_tlb_all(void);
-extern void __flush_tlb_mm(unsigned long context, unsigned long r);
-extern void __flush_tlb_range(unsigned long context, unsigned long start,
-			      unsigned long r, unsigned long end,
-			      unsigned long pgsz, unsigned long size);
-extern void __flush_tlb_page(unsigned long context, unsigned long page, unsigned long r);
-
-#ifndef __SMP__
+#define ZERO_PAGE(vaddr)	(mem_map + (phys_base>>PAGE_SHIFT))
 
-#define flush_cache_all()	__flush_cache_all()
-#define flush_tlb_all()		__flush_tlb_all()
+/* Warning: These take pointers to page structs now... */
+#define mk_pte(page, pgprot)		\
+	__pte(((page - mem_map) << PAGE_SHIFT) | pgprot_val(pgprot))
+#define page_pte_prot(page, prot)	mk_pte(page, prot)
+#define page_pte(page)			page_pte_prot(page, __pgprot(0))
 
-#define flush_tlb_mm(__mm) \
-do { if(CTX_VALID((__mm)->context)) \
-	__flush_tlb_mm(CTX_HWBITS((__mm)->context), SECONDARY_CONTEXT); \
-} while(0)
-
-#define flush_tlb_range(__mm, start, end) \
-do { if(CTX_VALID((__mm)->context)) { \
-	unsigned long __start = (start)&PAGE_MASK; \
-	unsigned long __end = (end)&PAGE_MASK; \
-	__flush_tlb_range(CTX_HWBITS((__mm)->context), __start, \
-			  SECONDARY_CONTEXT, __end, PAGE_SIZE, \
-			  (__end - __start)); \
-     } \
-} while(0)
-
-#define flush_tlb_page(vma, page) \
-do { struct mm_struct *__mm = (vma)->vm_mm; \
-     if(CTX_VALID(__mm->context)) \
-	__flush_tlb_page(CTX_HWBITS(__mm->context), (page)&PAGE_MASK, \
-			 SECONDARY_CONTEXT); \
-} while(0)
-
-#else /* __SMP__ */
-
-extern void smp_flush_cache_all(void);
-extern void smp_flush_tlb_all(void);
-extern void smp_flush_tlb_mm(struct mm_struct *mm);
-extern void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start,
-				unsigned long end);
-extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page);
-
-#define flush_cache_all()	smp_flush_cache_all()
-#define flush_tlb_all()		smp_flush_tlb_all()
-
-extern __inline__ void flush_tlb_mm(struct mm_struct *mm)
-{
-	if (CTX_VALID(mm->context))
-		smp_flush_tlb_mm(mm);
-}
+#define mk_pte_phys(physpage, pgprot)	(__pte((physpage) | pgprot_val(pgprot)))
 
-extern __inline__ void flush_tlb_range(struct mm_struct *mm, unsigned long start,
-				       unsigned long end)
+extern inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
 {
-	if (CTX_VALID(mm->context))
-		smp_flush_tlb_range(mm, start, end);
-}
+	pte_t __pte;
 
-extern __inline__ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
-	struct mm_struct *mm = vma->vm_mm;
+	pte_val(__pte) = (pte_val(orig_pte) & _PAGE_CHG_MASK) |
+		pgprot_val(new_prot);
 
-	if (CTX_VALID(mm->context))
-		smp_flush_tlb_page(mm, page);
+	return __pte;
 }
-
-#endif
-
-#define mk_pte(page, pgprot)		(__pte(__pa(page) | pgprot_val(pgprot)))
-#define mk_pte_phys(physpage, pgprot)	(__pte((physpage) | pgprot_val(pgprot)))
-#define pte_modify(_pte, newprot) \
-	(pte_val(_pte) = ((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)))
 #define pmd_set(pmdp, ptep)	\
 	(pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL))
 #define pgd_set(pgdp, pmdp)	\
 	(pgd_val(*(pgdp)) = (__pa((unsigned long) (pmdp)) >> 11UL))
-#define pte_page(pte)   ((unsigned long) __va(((pte_val(pte)&~PAGE_OFFSET)&~(0xfffUL))))
+#define pte_pagenr(pte)   ((unsigned long) ((pte_val(pte)&~PAGE_OFFSET)>>PAGE_SHIFT))
 #define pmd_page(pmd)			((unsigned long) __va((pmd_val(pmd)<<11UL)))
 #define pgd_page(pgd)			((unsigned long) __va((pgd_val(pgd)<<11UL)))
 #define pte_none(pte) 			(!pte_val(pte))
@@ -286,6 +206,12 @@
 #define pte_mkclean(pte)	(__pte(pte_val(pte) & ~(_PAGE_MODIFIED|_PAGE_W)))
 #define pte_mkold(pte)		(__pte(((pte_val(pte)<<1UL)>>1UL) & ~_PAGE_ACCESSED))
 
+/* Permanent address of a page. */
+#define __page_address(page)	((page)->virtual)
+#define page_address(page)	({ __page_address(page); })
+
+#define pte_page(x) (mem_map+pte_pagenr(x))
+
 /* Be very careful when you change these three, they are delicate. */
 static __inline__ pte_t pte_mkyoung(pte_t _pte)
 {	if(pte_val(_pte) & _PAGE_READ)
@@ -322,226 +248,7 @@
 #define pte_offset(dir, address)	((pte_t *) pmd_page(*(dir)) + \
 					((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
 
-/* Very stupidly, we used to get new pgd's and pmd's, init their contents
- * to point to the NULL versions of the next level page table, later on
- * completely re-init them the same way, then free them up.  This wasted
- * a lot of work and caused unnecessary memory traffic.  How broken...
- * We fix this by caching them.
- */
-
-#ifdef __SMP__
-/* Sliiiicck */
-#define pgt_quicklists	cpu_data[smp_processor_id()]
-#else
-extern struct pgtable_cache_struct {
-	unsigned long *pgd_cache;
-	unsigned long *pte_cache;
-	unsigned int pgcache_size;
-	unsigned int pgdcache_size;
-} pgt_quicklists;
-#endif
-#define pgd_quicklist		(pgt_quicklists.pgd_cache)
-#define pmd_quicklist		((unsigned long *)0)
-#define pte_quicklist		(pgt_quicklists.pte_cache)
-#define pgtable_cache_size	(pgt_quicklists.pgcache_size)
-#define pgd_cache_size		(pgt_quicklists.pgdcache_size)
-
-#ifndef __SMP__
-
-extern __inline__ void free_pgd_fast(pgd_t *pgd)
-{
-	struct page *page = mem_map + MAP_NR(pgd);
-
-	if (!page->pprev_hash) {
-		(unsigned long *)page->next_hash = pgd_quicklist;
-		pgd_quicklist = (unsigned long *)page;
-	}
-	(unsigned long)page->pprev_hash |=
-		(((unsigned long)pgd & (PAGE_SIZE / 2)) ? 2 : 1);
-	pgd_cache_size++;
-}
-
-extern __inline__ pgd_t *get_pgd_fast(void)
-{
-        struct page *ret;
-
-        if ((ret = (struct page *)pgd_quicklist) != NULL) {
-                unsigned long mask = (unsigned long)ret->pprev_hash;
-		unsigned long off = 0;
-
-		if (mask & 1)
-			mask &= ~1;
-		else {
-			off = PAGE_SIZE / 2;
-			mask &= ~2;
-		}
-		(unsigned long)ret->pprev_hash = mask;
-		if (!mask)
-			pgd_quicklist = (unsigned long *)ret->next_hash;
-                ret = (struct page *)(page_address(ret) + off);
-                pgd_cache_size--;
-        } else {
-		ret = (struct page *) __get_free_page(GFP_KERNEL);
-		if(ret) {
-			struct page *page = mem_map + MAP_NR(ret);
-			
-			memset(ret, 0, PAGE_SIZE);
-			(unsigned long)page->pprev_hash = 2;
-			(unsigned long *)page->next_hash = pgd_quicklist;
-			pgd_quicklist = (unsigned long *)page;
-			pgd_cache_size++;
-		}
-        }
-        return (pgd_t *)ret;
-}
-
-#else /* __SMP__ */
-
-extern __inline__ void free_pgd_fast(pgd_t *pgd)
-{
-	*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
-	pgd_quicklist = (unsigned long *) pgd;
-	pgtable_cache_size++;
-}
-
-extern __inline__ pgd_t *get_pgd_fast(void)
-{
-	unsigned long *ret;
-
-	if((ret = pgd_quicklist) != NULL) {
-		pgd_quicklist = (unsigned long *)(*ret);
-		ret[0] = 0;
-		pgtable_cache_size--;
-	} else {
-		ret = (unsigned long *) __get_free_page(GFP_KERNEL);
-		if(ret)
-			memset(ret, 0, PAGE_SIZE);
-	}
-	return (pgd_t *)ret;
-}
-
-extern __inline__ void free_pgd_slow(pgd_t *pgd)
-{
-	free_page((unsigned long)pgd);
-}
-
-#endif /* __SMP__ */
-
-extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long address_premasked);
-
-extern __inline__ pmd_t *get_pmd_fast(void)
-{
-	unsigned long *ret;
-
-	if((ret = (unsigned long *)pte_quicklist) != NULL) {
-		pte_quicklist = (unsigned long *)(*ret);
-		ret[0] = 0;
-		pgtable_cache_size--;
-	}
-	return (pmd_t *)ret;
-}
-
-extern __inline__ void free_pmd_fast(pgd_t *pmd)
-{
-	*(unsigned long *)pmd = (unsigned long) pte_quicklist;
-	pte_quicklist = (unsigned long *) pmd;
-	pgtable_cache_size++;
-}
-
-extern __inline__ void free_pmd_slow(pmd_t *pmd)
-{
-	free_page((unsigned long)pmd);
-}
-
-extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
-
-extern __inline__ pte_t *get_pte_fast(void)
-{
-	unsigned long *ret;
-
-	if((ret = (unsigned long *)pte_quicklist) != NULL) {
-		pte_quicklist = (unsigned long *)(*ret);
-		ret[0] = 0;
-		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);
-}
-
-#define pte_free_kernel(pte)	free_pte_fast(pte)
-#define pte_free(pte)		free_pte_fast(pte)
-#define pmd_free_kernel(pmd)	free_pmd_fast(pmd)
-#define pmd_free(pmd)		free_pmd_fast(pmd)
-#define pgd_free(pgd)		free_pgd_fast(pgd)
-#define pgd_alloc()		get_pgd_fast()
-
-extern inline pte_t * pte_alloc(pmd_t *pmd, unsigned long address)
-{
-	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-	if (pmd_none(*pmd)) {
-		pte_t *page = get_pte_fast();
-
-		if (!page)
-			return get_pte_slow(pmd, address);
-		pmd_set(pmd, page);
-		return page + address;
-	}
-	return (pte_t *) pmd_page(*pmd) + address;
-}
-
-extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
-{
-	address = (address >> PMD_SHIFT) & (REAL_PTRS_PER_PMD - 1);
-	if (pgd_none(*pgd)) {
-		pmd_t *page = get_pmd_fast();
-
-		if (!page)
-			return get_pmd_slow(pgd, address);
-		pgd_set(pgd, page);
-		return page + address;
-	}
-	return (pmd_t *) pgd_page(*pgd) + address;
-}
-
-#define pte_alloc_kernel(pmd, addr)	pte_alloc(pmd, addr)
-#define pmd_alloc_kernel(pgd, addr)	pmd_alloc(pgd, addr)
-
-extern int do_check_pgt_cache(int, int);
-
-/* Nothing to do on sparc64 :) */
-#define set_pgdir(address, entry)	do { } while(0)
-
 extern pgd_t swapper_pg_dir[1];
-/* Routines for getting a dvma scsi buffer. */
-struct mmu_sglist {
-	char *addr;
-	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);
-extern void  mmu_get_scsi_sgl(struct mmu_sglist *, int, struct linux_sbus *sbus);
-
-extern void mmu_release_scsi_one(u32 vaddr, unsigned long len,
-				 struct linux_sbus *sbus);
-extern void mmu_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus);
-
-#define NEED_DMA_SYNCHRONIZATION
-#define mmu_sync_dma(dma_addr, len, sbus_instance)	\
-	mmu_release_scsi_one((dma_addr), (len), (sbus_instance))
 
 /* These do nothing with the way I have things setup. */
 #define mmu_lockarea(vaddr, len)		(vaddr)
@@ -579,14 +286,11 @@
 	if ((__flags & VM_EXEC) != 0 && \
 	    ((pte_val(_pte) & (_PAGE_PRESENT | _PAGE_WRITE | _PAGE_MODIFIED)) == \
 	     (_PAGE_PRESENT | _PAGE_WRITE | _PAGE_MODIFIED))) { \
-		flush_icache_page(pte_page(_pte) - page_offset); \
+		flush_icache_page(pte_pagenr(_pte) << PAGE_SHIFT); \
 	} \
 } while(0)
 
 /* Make a non-present pseudo-TTE. */
-extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
-{ pte_t pte; pte_val(pte) = (type<<PAGE_SHIFT)|(offset<<(PAGE_SHIFT+8)); return pte; }
-
 extern inline pte_t mk_pte_io(unsigned long page, pgprot_t prot, int space)
 {
 	pte_t pte;
@@ -595,9 +299,16 @@
 	return pte;
 }
 
-#define SWP_TYPE(entry)		(((entry>>PAGE_SHIFT) & 0xff))
-#define SWP_OFFSET(entry)	((entry) >> (PAGE_SHIFT+8))
-#define SWP_ENTRY(type,offset)	pte_val(mk_swap_pte((type),(offset)))
+/* Encode and de-code a swap entry */
+#define SWP_TYPE(entry)		(((entry).val >> PAGE_SHIFT) & 0xff)
+#define SWP_OFFSET(entry)	((entry).val >> (PAGE_SHIFT + 8))
+#define SWP_ENTRY(type, offset)	\
+	( (swp_entry_t) \
+	  { \
+		((type << PAGE_SHIFT) | (offset << (PAGE_SHIFT + 8))) \
+	  } )
+#define pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
+#define swp_entry_to_pte(x)		((pte_t) { (x).val })
 
 extern __inline__ unsigned long
 sun4u_get_pte (unsigned long addr)
@@ -631,8 +342,8 @@
 extern unsigned long *sparc64_valid_addr_bitmap;
 
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
-#define PageSkip(page)		(test_bit(PG_skip, &(page)->flags))
-#define kern_addr_valid(addr)	(test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap))
+#define kern_addr_valid(addr)	\
+	(test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap))
 
 extern int io_remap_page_range(unsigned long from, unsigned long offset,
 			       unsigned long size, pgprot_t prot, int space);
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/poll.h linux/include/asm-sparc64/poll.h
--- v2.3.34/linux/include/asm-sparc64/poll.h	Mon Mar 17 14:54:33 1997
+++ linux/include/asm-sparc64/poll.h	Mon Dec 20 22:05:52 1999
@@ -11,6 +11,7 @@
 #define POLLWRNORM	POLLOUT
 #define POLLRDBAND	128
 #define POLLWRBAND	256
+#define POLLMSG		512
 
 struct pollfd {
 	int fd;
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h
--- v2.3.34/linux/include/asm-sparc64/processor.h	Thu Nov 11 20:11:52 1999
+++ linux/include/asm-sparc64/processor.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.57 1999/08/04 03:20:05 davem Exp $
+/* $Id: processor.h,v 1.58 1999/12/15 14:19:14 davem Exp $
  * include/asm-sparc64/processor.h
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -109,10 +109,20 @@
 /* Return saved PC of a blocked thread. */
 extern __inline__ unsigned long thread_saved_pc(struct thread_struct *t)
 {
-	unsigned long *sp = (unsigned long *)(t->ksp + STACK_BIAS);
-	unsigned long *fp = (unsigned long *)(sp[14] + STACK_BIAS);
-
-	return fp[15];
+	unsigned long ret = 0xdeadbeefUL;
+	
+	if (t->ksp) {
+		unsigned long *sp;
+		sp = (unsigned long *)(t->ksp + STACK_BIAS);
+		if (((unsigned long)sp & (sizeof(long) - 1)) == 0UL &&
+		    sp[14]) {
+			unsigned long *fp;
+			fp = (unsigned long *)(sp[14] + STACK_BIAS);
+			if (((unsigned long)fp & (sizeof(long) - 1)) == 0UL)
+				ret = fp[15];
+		}
+	}
+	return ret;
 }
 
 /* On Uniprocessor, even in RMO processes see TSO semantics */
@@ -209,7 +219,35 @@
 #define release_segments(mm)		do { } while (0)
 #define forget_segments()		do { } while (0)
 
-unsigned long get_wchan(struct task_struct *p);
+#define get_wchan(__TSK) \
+({	extern void scheduling_functions_start_here(void); \
+	extern void scheduling_functions_end_here(void); \
+	unsigned long pc, fp, bias = 0; \
+	unsigned long task_base = (unsigned long) (__TSK); \
+	struct reg_window *rw; \
+        unsigned long __ret = 0; \
+	int count = 0; \
+	if (!(__TSK) || (__TSK) == current || \
+            (__TSK)->state == TASK_RUNNING) \
+		goto __out; \
+	bias = STACK_BIAS; \
+	fp = (__TSK)->thread.ksp + bias; \
+	do { \
+		/* Bogus frame pointer? */ \
+		if (fp < (task_base + sizeof(struct task_struct)) || \
+		    fp >= (task_base + (2 * PAGE_SIZE))) \
+			break; \
+		rw = (struct reg_window *) fp; \
+		pc = rw->ins[7]; \
+		if (pc < ((unsigned long) scheduling_functions_start_here) || \
+		    pc >= ((unsigned long) scheduling_functions_end_here)) { \
+			__ret = pc; \
+			goto __out; \
+		} \
+		fp = rw->ins[6] + bias; \
+	} while (++count < 16); \
+__out:	__ret; \
+})
 
 #define KSTK_EIP(tsk)  ((tsk)->thread.kregs->tpc)
 #define KSTK_ESP(tsk)  ((tsk)->thread.kregs->u_regs[UREG_FP])
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/resource.h linux/include/asm-sparc64/resource.h
--- v2.3.34/linux/include/asm-sparc64/resource.h	Tue Dec 14 01:27:24 1999
+++ linux/include/asm-sparc64/resource.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: resource.h,v 1.5 1999/07/30 09:31:21 davem Exp $
+/* $Id: resource.h,v 1.7 1999/12/15 17:52:08 jj Exp $
  * resource.h: Resource definitions.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -31,13 +31,17 @@
 #define RLIM_INFINITY	(~0UL)
 
 #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}, {0, 0},			\
-    {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX}	\
+#define INIT_RLIMITS			\
+{					\
+    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {_STK_LIM, RLIM_INFINITY},		\
+    {       0, RLIM_INFINITY},		\
+    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {INR_OPEN, INR_OPEN}, {0, 0},	\
+    {RLIM_INFINITY, RLIM_INFINITY},	\
+    {RLIM_INFINITY, RLIM_INFINITY}	\
 }
 
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/sbus.h linux/include/asm-sparc64/sbus.h
--- v2.3.34/linux/include/asm-sparc64/sbus.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/sbus.h	Mon Dec 20 22:05:52 1999
@@ -1,16 +1,17 @@
-/* $Id: sbus.h,v 1.10 1998/12/16 04:33:58 davem Exp $
- * sbus.h:  Defines for the Sun SBus.
+/* $Id: sbus.h,v 1.12 1999/12/20 14:08:25 jj Exp $
+ * sbus.h: Defines for the Sun SBus.
  *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com)
  */
 
-/* XXX This needs to be mostly redone for sun5 SYSIO. */
-
 #ifndef _SPARC64_SBUS_H
 #define _SPARC64_SBUS_H
 
+#include <linux/ioport.h>
+
 #include <asm/oplib.h>
 #include <asm/iommu.h>
+#include <asm/scatterlist.h>
 
 /* We scan which devices are on the SBus using the PROM node device
  * tree.  SBus devices are described in two different ways.  You can
@@ -36,73 +37,75 @@
   return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>28);
 }
 
-extern __inline__ unsigned long sbus_dev_offset(unsigned long dev_addr)
-{
-  return (unsigned long) (((dev_addr)-SUN_SBUS_BVADDR)&SBUS_OFF_MASK);
-}
-
-struct linux_sbus;
+struct sbus_bus;
 
 /* Linux SBUS device tables */
-struct linux_sbus_device {
-  struct linux_sbus_device *next;      /* next device on this SBus or null */
-  struct linux_sbus_device *child;     /* For ledma and espdma on sun4m */
-  struct linux_sbus *my_bus;           /* Back ptr to sbus */
-  int prom_node;                       /* PROM device tree node for this device */
-  char prom_name[32];                  /* PROM device name */
-
-  struct linux_prom_registers reg_addrs[PROMREG_MAX];
-  int num_registers, ranges_applied;
-
-  unsigned int irqs[4];
-  int num_irqs;
-
-  unsigned long sbus_addr;             /* Absolute base address for device. */
-  unsigned long sbus_vaddrs[PROMVADDR_MAX];
-  unsigned long num_vaddrs;
-  unsigned long offset;                /* Offset given by PROM */
-  int slot;
+struct sbus_dev {
+	struct sbus_bus *bus;	/* Our toplevel parent SBUS	*/
+	struct sbus_dev *next;	/* Chain of siblings		*/
+	struct sbus_dev *child;	/* Chain of children		*/
+	struct sbus_dev *parent;/* Parent device if not toplevel*/
+	int prom_node;		/* OBP node of this device	*/
+	char prom_name[64];	/* OBP device name property	*/
+	int slot;		/* SBUS slot number		*/
+
+	struct resource resource[PROMREG_MAX];
+
+	struct linux_prom_registers reg_addrs[PROMREG_MAX];
+	int num_registers, ranges_applied;
+
+	struct linux_prom_ranges device_ranges[PROMREG_MAX];
+	int num_device_ranges;
+
+	unsigned int irqs[4];
+	int num_irqs;
 };
 
 /* This struct describes the SBus(s) found on this machine. */
-struct linux_sbus {
-	struct linux_sbus *next;             /* next SBus, if more than one SBus */
-	struct linux_sbus_device *devices;   /* Link to devices on this SBus */
-	struct iommu_struct *iommu;          /* IOMMU for this sbus if applicable */
-	int prom_node;                       /* PROM device tree node for this SBus */
-	char prom_name[64];                  /* Usually "sbus" or "sbi" */
-	int clock_freq;
+struct sbus_bus {
+	void			*iommu;		/* Opaque IOMMU cookie	*/
+	struct sbus_dev		*devices;	/* Tree of SBUS devices	*/
+	struct sbus_bus		*next;		/* Next SBUS in system	*/
+	int			prom_node;      /* OBP node of SBUS	*/
+	char			prom_name[64];	/* Usually "sbus" or "sbi" */
+	int			clock_freq;
+
 	struct linux_prom_ranges sbus_ranges[PROMREG_MAX];
 	int num_sbus_ranges;
-	int upaid;
+
+	int portid;
 	void *starfire_cookie;
 };
 
-extern struct linux_sbus *SBus_chain;
+extern struct sbus_bus *sbus_root;
 
 /* Device probing routines could find these handy */
 #define for_each_sbus(bus) \
-        for((bus) = SBus_chain; (bus); (bus)=(bus)->next)
+        for((bus) = sbus_root; (bus); (bus)=(bus)->next)
 
 #define for_each_sbusdev(device, bus) \
         for((device) = (bus)->devices; (device); (device)=(device)->next)
         
 #define for_all_sbusdev(device, bus) \
-	for((bus) = SBus_chain, ((device) = (bus) ? (bus)->devices : 0); (bus); (device)=((device)->next ? (device)->next : ((bus) = (bus)->next, (bus) ? (bus)->devices : 0)))
-
-extern void mmu_set_sbus64(struct linux_sbus_device *, int);
-
-/* If you did not get the buffer from mmu_get_*() or sparc_alloc_dvma()
- * then you must use this to get the 32-bit SBUS dvma address.
- * And in this case it is your responsibility to make sure the buffer
- * is GFP_DMA, ie. that it is not greater than MAX_DMA_ADDRESS.
- */
-extern unsigned long phys_base;
-#define sbus_dvma_addr(__addr)	((__u32)(__pa(__addr) - phys_base))
+	for((bus) = sbus_root, ((device) = (bus) ? (bus)->devices : 0); (bus); (device)=((device)->next ? (device)->next : ((bus) = (bus)->next, (bus) ? (bus)->devices : 0)))
 
-/* Apply promlib probed SBUS ranges to registers. */
-extern void prom_apply_sbus_ranges(struct linux_sbus *sbus, 
-				   struct linux_prom_registers *sbusregs, int nregs, 
-				   struct linux_sbus_device *sdev);
+/* Driver DVMA interfaces. */
+#define sbus_can_dma_64bit(sdev)	(1)
+#define sbus_can_burst64(sdev)		(1)
+extern void sbus_set_sbus64(struct sbus_dev *, int);
+
+/* These yield IOMMU mappings in consistant mode. */
+extern void *sbus_alloc_consistant(struct sbus_dev *, long, u32 *dma_addrp);
+extern void sbus_free_consistant(struct sbus_dev *, long, void *, u32);
+
+/* All the rest use streaming mode mappings. */
+extern u32 sbus_map_single(struct sbus_dev *, void *, long);
+extern void sbus_unmap_single(struct sbus_dev *, u32, long);
+extern int sbus_map_sg(struct sbus_dev *, struct scatterlist *, int);
+extern void sbus_unmap_sg(struct sbus_dev *, struct scatterlist *, int);
+
+/* Finally, allow explicit synchronization of streamable mappings. */
+extern void sbus_dma_sync_single(struct sbus_dev *, u32, long);
+extern void sbus_dma_sync_sg(struct sbus_dev *, struct scatterlist *, int);
 
 #endif /* !(_SPARC64_SBUS_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/scatterlist.h linux/include/asm-sparc64/scatterlist.h
--- v2.3.34/linux/include/asm-sparc64/scatterlist.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-sparc64/scatterlist.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: scatterlist.h,v 1.7 1999/08/30 10:15:01 davem Exp $ */
+/* $Id: scatterlist.h,v 1.9 1999/12/17 12:32:15 jj Exp $ */
 #ifndef _SPARC64_SCATTERLIST_H
 #define _SPARC64_SCATTERLIST_H
 
@@ -14,7 +14,9 @@
     __u32 dvma_length;
 };
 
-extern unsigned long phys_base;
-#define ISA_DMA_THRESHOLD (phys_base + (0xfe000000UL) + PAGE_OFFSET)
+#define sg_dma_address(sg) ((sg)->dvma_address)
+#define sg_dma_len(sg)     ((sg)->dvma_length)
+
+#define ISA_DMA_THRESHOLD	(~0UL)
 
 #endif /* !(_SPARC64_SCATTERLIST_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/sfp-machine.h linux/include/asm-sparc64/sfp-machine.h
--- v2.3.34/linux/include/asm-sparc64/sfp-machine.h	Tue Dec  7 09:32:51 1999
+++ linux/include/asm-sparc64/sfp-machine.h	Mon Dec 20 22:05:52 1999
@@ -37,7 +37,7 @@
   _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_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_D(R,X,Y)	_FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
 #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv(Q,R,X,Y)
 
 #define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/shmparam.h linux/include/asm-sparc64/shmparam.h
--- v2.3.34/linux/include/asm-sparc64/shmparam.h	Sun Nov  7 16:37:34 1999
+++ linux/include/asm-sparc64/shmparam.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: shmparam.h,v 1.3 1998/09/28 07:15:03 jj Exp $ */
+/* $Id: shmparam.h,v 1.4 1999/12/09 10:32:44 davem Exp $ */
 #ifndef _ASMSPARC64_SHMPARAM_H
 #define _ASMSPARC64_SHMPARAM_H
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/smp.h linux/include/asm-sparc64/smp.h
--- v2.3.34/linux/include/asm-sparc64/smp.h	Mon Aug  2 22:07:16 1999
+++ linux/include/asm-sparc64/smp.h	Mon Dec 20 22:05:52 1999
@@ -33,19 +33,19 @@
 /* Keep this a multiple of 64-bytes for cache reasons. */
 struct cpuinfo_sparc {
 	/* Dcache line 1 */
-	unsigned long	irq_count;
-	unsigned long	bh_count;
+	unsigned int	irq_count;
+	unsigned int	bh_count;
 	unsigned int	multiplier;
 	unsigned int	counter;
+	unsigned int	idle_volume;
+	unsigned int	__pad;
 	unsigned long	udelay_val;
 
 	/* Dcache line 2 */
 	unsigned int	pgcache_size;
 	unsigned int	pgdcache_size;
-	unsigned long	*pte_cache;
+	unsigned long	*pte_cache[2];
 	unsigned long	*pgd_cache;
-	unsigned int	idle_volume;
-	unsigned int	__pad;
 
 	/* Dcache lines 3 and 4 */
 	unsigned int	irq_worklists[16];
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/stat.h linux/include/asm-sparc64/stat.h
--- v2.3.34/linux/include/asm-sparc64/stat.h	Tue Aug  4 16:03:35 1998
+++ linux/include/asm-sparc64/stat.h	Tue Dec 21 21:56:42 1999
@@ -1,4 +1,4 @@
-/* $Id: stat.h,v 1.5 1998/07/26 05:24:41 davem Exp $ */
+/* $Id: stat.h,v 1.6 1999/12/21 14:09:48 jj Exp $ */
 #ifndef _SPARC64_STAT_H
 #define _SPARC64_STAT_H
 
@@ -41,5 +41,46 @@
 	off_t   st_blocks;
 	unsigned long  __unused4[2];
 };
+
+#ifdef __KERNEL__
+/* This is sparc32 stat64 structure. */
+
+struct stat64 {
+	unsigned char	__pad0[6];
+	unsigned short	st_dev;
+	unsigned char	__pad1[4];
+
+	unsigned int	st_ino;
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+
+	unsigned char	__pad2[6];
+	unsigned short	st_rdev;
+
+	unsigned char	__pad3[8];
+
+	long long	st_size;
+	unsigned int	st_blksize;
+
+	unsigned char	__pad4[8];
+	unsigned int	st_blocks;
+
+	unsigned int	st_atime;
+	unsigned int	__unused1;
+
+	unsigned int	st_mtime;
+	unsigned int	__unused2;
+
+	unsigned int	st_ctime;
+	unsigned int	__unused3;
+
+	unsigned int	__unused4;
+	unsigned int	__unused5;
+};
+
+#endif
 
 #endif
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/sysio.h linux/include/asm-sparc64/sysio.h
--- v2.3.34/linux/include/asm-sparc64/sysio.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-sparc64/sysio.h	Wed Dec 31 16:00:00 1969
@@ -1,441 +0,0 @@
-/* $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)
- */
-
-#ifndef __SPARC64_SYSIO_H
-#define __SPARC64_SYSIO_H
-
-#include <linux/types.h>
-
-/* SUN5 SYSIO Register Set, one per controller probed. */
-struct sysio_regs {
-/*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*/	volatile u64	ue_afsr;	/* UE Async Fault Status	*/
-/*0x0038*/	volatile u64	ue_afar;	/* UE Async Fault Address	*/
-
-		/* Correctable Error Fault Registers */
-/*0x0040*/	volatile u64	ce_afsr;	/* CE Async Fault Status	*/
-/*0x0048*/	volatile u64	ce_afar;	/* CE Async Fault Address	*/
-
-		volatile u64	__pad0[0x16];
-
-		/* Performance Monitoring Registers */
-/*0x0100*/	volatile u64	pmon_control;
-/*0x0108*/	volatile u64	pmon_counter;
-
-		volatile u64	__pad1[0x3de];
-
-		/* SBUS Module Registers */
-/*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
-		 * are for on-board devices, in particular for Electron/Pulsar
-		 * they are:
-		 *
-		 *	slot 4) Audio
-		 *	slot 5) MACIO
-		 *	slot 6) SLAVIO
-		 *
-		 * On Sunfire/Starfire/Wildfire enterprise boxen these upper slots
-		 * are unused.
-		 */
-/*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		*/
-
-		volatile u64	__pad2[0x75];
-
-		/* SBUS IOMMU lives here */
-/*0x2400*/	volatile u64	iommu_control;	/* IOMMU Control		*/
-/*0x2408*/	volatile u64	iommu_tsbbase;	/* IOMMU TSB Base		*/
-/*0x2410*/	volatile u64	iommu_flush;	/* IOMMU Flush Register		*/
-
-		volatile u64	__pad3[0x7d];
-
-		/* SBUS/IOMMU Streaming Buffer Registers */
-/*0x2800*/	volatile u64	sbuf_control;	/* StrBuffer Control		*/
-/*0x2808*/	volatile u64	sbuf_pflush;	/* StrBuffer Page Flush		*/
-/*0x2810*/	volatile u64	sbuf_fsync;	/* StrBuffer Flush Synchronization Reg */
-
-		volatile u64	__pad4[0x7d];
-
-		/* Interrupt mapping/control registers */
-/*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*/	volatile u32	_irpad, irq_retry;
-
-		volatile u64	__pad5[0x7b];
-
-		/* The following are only used on Fusion/Electron/Pulsar
-		 * desktop systems, they mean nothing on Sunfire/Starfire/Wildfire
-		 */
-/*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 */
-
-		volatile u64	__pad6[0x6c];
-
-		/* Interrupt Clear Registers */
-/*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;
-
-		volatile u64	__pad11[0x6e];
-
-		/* Counters/Timers */
-/*0x3c00*/	volatile u64	tim0_cnt;
-/*0x3c08*/	volatile u64	tim0_lim;
-/*0x3c10*/	volatile u64	tim1_cnt;
-/*0x3c18*/	volatile u64	tim1_lim;
-
-		volatile u64	__pad12[0x7c];
-
-		/* DMA Scoreboard Diagnostic Registers */
-/*0x4000*/	volatile u64	dscore_reg0;	/* DMA Scoreboard Diag Reg 0	*/
-/*0x4008*/	volatile u64	dscore_reg1;	/* DMA Scoreboard Diag Reg 1	*/
-
-		volatile u64	__pad13[0x7e];
-
-		/* SBUS IOMMU Diagnostic Registers */
-/*0x4400*/	volatile u64	sbus_vdiag;	/* SBUS VADDR Diagnostic Register */
-/*0x4408*/	volatile u64	sbus_tcompare;	/* SBUS IOMMU TLB Tag Compare	  */
-
-		volatile u64	__pad14[0x1e];
-
-		/* More IOMMU diagnostic things */
-/*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    */
-
-		volatile u64	__pad15[0x20];
-
-		/* Interrupt State Diagnostics */
-/*0x4800*/	volatile u64	sbus_istate;
-/*0x4808*/	volatile u64	obio_istate;
-
-		volatile u64	__pad16[0xfe];
-
-		/* Streaming Buffer Diagnostic Area */
-/*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 */
-#define SYSIO_UPPID_FESC	0xff00000000000000 /* FCode escape, 0xfc           */
-#define SYSIO_UPPID_RESV1	0x00fffff800000000 /* Reserved                     */
-#define SYSIO_UPPID_ENV		0x0000000400000000 /* Cannot generate ECC          */
-#define SYSIO_UPPID_ORD		0x0000000200000000 /* One Outstanding Read         */
-#define SYSIO_UPPID_RESV2	0x0000000180000000 /* Reserved                     */
-#define SYSIO_UPPID_PDQ		0x000000007e000000 /* Data Queue size              */
-#define SYSIO_UPPID_PRQ		0x0000000001e00000 /* Request Queue size           */
-#define SYSIO_UPPID_UCAP	0x00000000001f0000 /* UPA Capabilities             */
-#define SYSIO_UPPID_JEDEC	0x000000000000ffff /* JEDEC ID for SYSIO           */
-
-/* SYSIO UPA Configuration Register */
-#define SYSIO_UPCFG_RESV	0xffffffffffffff00 /* Reserved                     */
-#define SYSIO_UPCFG_SCIQ1	0x00000000000000f0 /* Unused, always zero          */
-#define SYSIO_UPCFG_SCIQ2	0x000000000000000f /* Requests Queue size (0x2)    */
-
-/* SYSIO Control Register */
-#define SYSIO_CONTROL_IMPL	0xf000000000000000 /* Implementation of this SYSIO */
-#define SYSIO_CONTROL_VER	0x0f00000000000000 /* Version of this SYSIO        */
-#define SYSIO_CONTROL_MID	0x00f8000000000000 /* UPA Module ID of SYSIO       */
-#define SYSIO_CONTROL_IGN	0x0007c00000000000 /* Interrupt Group Number       */
-#define SYSIO_CONTROL_RESV      0x00003ffffffffff0 /* Reserved                     */
-#define SYSIO_CONTROL_APCKEN	0x0000000000000008 /* Address Parity Check Enable  */
-#define SYSIO_CONTROL_APERR	0x0000000000000004 /* Incoming System Addr Parerr  */
-#define SYSIO_CONTROL_IAP	0x0000000000000002 /* Invert UPA Parity            */
-#define SYSIO_CONTROL_MODE	0x0000000000000001 /* SYSIO clock mode             */
-
-/* SYSIO ECC Control Register */
-#define SYSIO_ECNTRL_ECCEN	0x8000000000000000 /* Enable ECC Checking          */
-#define SYSIO_ECNTRL_UEEN	0x4000000000000000 /* Enable UE Interrupts         */
-#define SYSIO_ECNTRL_CEEN	0x2000000000000000 /* Enable CE Interrupts         */
-
-/* Uncorrectable Error AFSR, AFAR holds low 40bits of faulting physical address. */
-#define SYSIO_UEAFSR_PPIO	0x8000000000000000 /* Primary PIO is cause         */
-#define SYSIO_UEAFSR_PDRD	0x4000000000000000 /* Primary DVMA read is cause   */
-#define SYSIO_UEAFSR_PDWR	0x2000000000000000 /* Primary DVMA write is cause  */
-#define SYSIO_UEAFSR_SPIO	0x1000000000000000 /* Secondary PIO is cause       */
-#define SYSIO_UEAFSR_SDRD	0x0800000000000000 /* Secondary DVMA read is cause */
-#define SYSIO_UEAFSR_SDWR	0x0400000000000000 /* Secondary DVMA write is cause*/
-#define SYSIO_UEAFSR_RESV1	0x03ff000000000000 /* Reserved                     */
-#define SYSIO_UEAFSR_DOFF	0x0000e00000000000 /* Doubleword Offset            */
-#define SYSIO_UEAFSR_SIZE	0x00001c0000000000 /* Bad transfer size is 2**SIZE */
-#define SYSIO_UEAFSR_MID	0x000003e000000000 /* UPA MID causing the fault    */
-#define SYSIO_UEAFSR_RESV2	0x0000001fffffffff /* Reserved                     */
-
-/* Correctable Error AFSR, AFAR holds low 40bits of faulting physical address. */
-#define SYSIO_CEAFSR_PPIO	0x8000000000000000 /* Primary PIO is cause         */
-#define SYSIO_CEAFSR_PDRD	0x4000000000000000 /* Primary DVMA read is cause   */
-#define SYSIO_CEAFSR_PDWR	0x2000000000000000 /* Primary DVMA write is cause  */
-#define SYSIO_CEAFSR_SPIO	0x1000000000000000 /* Secondary PIO is cause       */
-#define SYSIO_CEAFSR_SDRD	0x0800000000000000 /* Secondary DVMA read is cause */
-#define SYSIO_CEAFSR_SDWR	0x0400000000000000 /* Secondary DVMA write is cause*/
-#define SYSIO_CEAFSR_RESV1	0x0300000000000000 /* Reserved                     */
-#define SYSIO_CEAFSR_ESYND	0x00ff000000000000 /* Syndrome Bits                */
-#define SYSIO_CEAFSR_DOFF	0x0000e00000000000 /* Double Offset                */
-#define SYSIO_CEAFSR_SIZE	0x00001c0000000000 /* Bad transfer size is 2**SIZE */
-#define SYSIO_CEAFSR_MID	0x000003e000000000 /* UPA MID causing the fault    */
-#define SYSIO_CEAFSR_RESV2	0x0000001fffffffff /* Reserved                     */
-
-/* DMA Scoreboard Diagnostic Register(s) */
-#define SYSIO_DSCORE_VALID	0x0040000000000000 /* Entry is valid               */
-#define SYSIO_DSCORE_C		0x0020000000000000 /* Transaction cacheable        */
-#define SYSIO_DSCORE_READ	0x0010000000000000 /* Transaction was a read       */
-#define SYSIO_DSCORE_TAG	0x000f000000000000 /* Transaction ID               */
-#define SYSIO_DSCORE_ADDR	0x0000ffffffffff80 /* Transaction PADDR            */
-#define SYSIO_DSCORE_SIZE	0x0000000000000030 /* Transaction size             */
-#define SYSIO_DSCORE_SRC	0x000000000000000f /* Transaction source           */
-
-/* SYSIO SBUS Control Register */
-#define SYSIO_SBCNTRL_IMPL	0xf000000000000000 /* Implementation               */
-#define SYSIO_SBCNTRL_REV	0x0f00000000000000 /* Revision                     */
-#define SYSIO_SBCNTRL_RESV1	0x00c0000000000000 /* Reserved                     */
-#define SYSIO_SBCNTRL_DPERR	0x003f000000000000 /* DMA Write Parity Error       */
-#define SYSIO_SBCNTRL_RESV2	0x0000800000000000 /* Reserved                     */
-#define SYSIO_SBCNTRL_PPERR	0x00007f0000000000 /* PIO Load Parity Error        */
-#define SYSIO_SBCNTRL_RESV	0x000000fffffff800 /* Reserved                     */
-#define SYSIO_SBCNTRL_FAST	0x0000000000000400 /* Enable Fast-SBUS mode.	   */
-#define SYSIO_SBCNTRL_WEN	0x0000000000000200 /* Power Mgmt Wake Enable       */
-#define SYSIO_SBCNTRL_EEN	0x0000000000000100 /* SBUS Error Interrupt Enable  */
-#define SYSIO_SBCNTRL_RESV3	0x00000000000000c0 /* Reserved                     */
-#define SYSIO_SBCNTRL_AEN	0x000000000000003f /* SBUS DVMA Arbitration Enable */
-
-/* SYSIO SBUS AFSR, AFAR holds low 40 bits of physical address causing the fault. */
-#define SYSIO_SBAFSR_PLE	0x8000000000000000 /* Primary Late PIO Error       */
-#define SYSIO_SBAFSR_PTO	0x4000000000000000 /* Primary SBUS Timeout         */
-#define SYSIO_SBAFSR_PBERR	0x2000000000000000 /* Primary SBUS Error ACK       */
-#define SYSIO_SBAFSR_SLE	0x1000000000000000 /* Secondary Late PIO Error     */
-#define SYSIO_SBAFSR_STO	0x0800000000000000 /* Secondary SBUS Timeout       */
-#define SYSIO_SBAFSR_SBERR	0x0400000000000000 /* Secondary SBUS Error ACK     */
-#define SYSIO_SBAFSR_RESV1	0x03ff000000000000 /* Reserved                     */
-#define SYSIO_SBAFSR_RD		0x0000800000000000 /* Primary was late PIO read    */
-#define SYSIO_SBAFSR_RESV2	0x0000600000000000 /* Reserved                     */
-#define SYSIO_SBAFSR_SIZE	0x00001c0000000000 /* Size of transfer             */
-#define SYSIO_SBAFSR_MID	0x000003e000000000 /* MID causing the error        */
-#define SYSIO_SBAFSR_RESV3	0x0000001fffffffff /* Reserved                     */
-
-/* SYSIO SBUS Slot Configuration Register(s) */
-#define SYSIO_SBSCFG_RESV1	0xfffffffff8000000 /* Reserved                     */
-#define SYSIO_SBSCFG_SADDR	0x0000000007ff0000 /* Segment Address (PA[40:30])  */
-#define SYSIO_SBSCFG_CP		0x0000000000008000 /* Bypasses are cacheable       */
-#define SYSIO_SBSCFG_ETM	0x0000000000004000 /* Ext Transfer Mode supported  */
-#define SYSIO_SBSCFG_PE		0x0000000000002000 /* SBUS Parity Checking Enable  */
-#define SYSIO_SBSCFG_RESV2	0x0000000000001fe0 /* Reserved                     */
-#define SYSIO_SBSCFG_BA64	0x0000000000000010 /* 64-byte bursts supported     */
-#define SYSIO_SBSCFG_BA32	0x0000000000000008 /* 32-byte bursts supported     */
-#define SYSIO_SBSCFG_BA16	0x0000000000000004 /* 16-byte bursts supported     */
-#define SYSIO_SBSCFG_BA8	0x0000000000000002 /* 8-byte bursts supported      */
-#define SYSIO_SBSCFG_BY		0x0000000000000001 /* IOMMU Bypass Enable          */
-
-/* IOMMU things defined fully in asm-sparc64/iommu.h */
-
-/* Streaming Buffer Control Register */
-#define SYSIO_SBUFCTRL_IMPL	0xf000000000000000 /* Implementation               */
-#define SYSIO_SBUFCTRL_REV	0x0f00000000000000 /* Revision                     */
-#define SYSIO_SBUFCTRL_DE	0x0000000000000002 /* Diag Mode Enable             */
-#define SYSIO_SBUFCTRL_SB_EN	0x0000000000000001 /* Streaming Buffer Enable      */
-
-/* Streaming Buffer Page Invalidate/Flush Register */
-#define SYSIO_SBUFFLUSH_ADDR	0x00000000ffffe000 /* DVMA Page to be flushed      */
-#define SYSIO_SBUFFLUSH_RESV    0x0000000000001fff /* Ignored bits                 */
-
-/* Streaming Buffer Flush Synchronization Register */
-#define SYSIO_SBUFSYNC_ADDR	0x000001fffffffffc /* Physical address to update   */
-#define SYSIO_SBUFSYNC_RESV	0x0000000000000003 /* Ignored bits                 */
-
-/* SYSIO Interrupt mapping register(s). */
-#define SYSIO_IMAP_VALID	0x80000000	/* This enables delivery.	   */
-#define SYSIO_IMAP_TID		0x7c000000	/* Target ID (MID to send it to)   */
-#define SYSIO_IMAP_RESV		0x03fff800	/* Reserved.			   */
-#define SYSIO_IMAP_IGN		0x000007c0	/* Interrupt Group Number.	   */
-#define SYSIO_IMAP_INO		0x0000003f	/* Interrupt Number Offset.	   */
-#define SYSIO_IMAP_INR		0x000007ff	/* Interrupt # (Gfx/UPA_slave only)*/
-
-/* SYSIO Interrupt clear pseudo register(s). */
-#define SYSIO_ICLR_IDLE		0x00000000	/* Transition to idle state.	   */
-#define SYSIO_ICLR_TRANSMIT	0x00000001	/* Transition to transmit state.   */
-#define SYSIO_ICLR_RESV		0x00000002	/* Reserved.			   */
-#define SYSIO_ICLR_PENDING	0x00000003	/* Transition to pending state.	   */
-
-/* SYSIO Interrupt Retry Timer register. */
-#define SYSIO_IRETRY_LIMIT	0x000000ff	/* The retry interval.		   */
-
-/* SYSIO Interrupt State registers. */
-#define SYSIO_ISTATE_IDLE	0x0 /* No interrupt received or pending */
-#define SYSIO_ISTATE_TRANSMIT	0x1 /* Received, but IRQ not dispatched */
-#define SYSIO_ISTATE_ILLEGAL	0x2 /* Impossible state                 */
-#define SYSIO_ISTATE_PENDING	0x3 /* Received and dispatched          */
-
-/* Two ways to get at the right bits, your choice... note that level
- * zero is illegal.  For slots 0 --> 3 the formula for the bit range
- * in the register is:
- *
- *	LSB	((SBUS_SLOT X 16) + (SBUS_LEVEL X 2))
- *	MSB	((SBUS_SLOT X 16) + (SBUS_LEVEL X 2)) + 1
- *
- * Thus the following macro.
- */
-#define SYSIO_SBUS_ISTATE(regval, slot, level)	\
-	(((regval) >> (((slot) * 16) + ((level) * 2))) & 0x3)
-
-#define SYSIO_SBUS_ISTATE_S0L1	0x000000000000000c /* Slot 0, level 1 */
-#define SYSIO_SBUS_ISTATE_S0L2	0x0000000000000030 /* Slot 0, level 2 */
-#define SYSIO_SBUS_ISTATE_S0L3	0x00000000000000c0 /* Slot 0, level 3 */
-#define SYSIO_SBUS_ISTATE_S0L4	0x0000000000000300 /* Slot 0, level 4 */
-#define SYSIO_SBUS_ISTATE_S0L5	0x0000000000000c00 /* Slot 0, level 5 */
-#define SYSIO_SBUS_ISTATE_S0L6	0x0000000000003000 /* Slot 0, level 6 */
-#define SYSIO_SBUS_ISTATE_S0L7	0x000000000000c000 /* Slot 0, level 7 */
-#define SYSIO_SBUS_ISTATE_S1L1	0x00000000000c0000 /* Slot 1, level 1 */
-#define SYSIO_SBUS_ISTATE_S1L2	0x0000000000300000 /* Slot 1, level 2 */
-#define SYSIO_SBUS_ISTATE_S1L3	0x0000000000c00000 /* Slot 1, level 3 */
-#define SYSIO_SBUS_ISTATE_S1L4	0x0000000003000000 /* Slot 1, level 4 */
-#define SYSIO_SBUS_ISTATE_S1L5	0x000000000c000000 /* Slot 1, level 5 */
-#define SYSIO_SBUS_ISTATE_S1L6	0x0000000030000000 /* Slot 1, level 6 */
-#define SYSIO_SBUS_ISTATE_S1L7	0x00000000c0000000 /* Slot 1, level 7 */
-#define SYSIO_SBUS_ISTATE_S2L1	0x0000000c00000000 /* Slot 2, level 1 */
-#define SYSIO_SBUS_ISTATE_S2L2	0x0000003000000000 /* Slot 2, level 2 */
-#define SYSIO_SBUS_ISTATE_S2L3	0x000000c000000000 /* Slot 2, level 3 */
-#define SYSIO_SBUS_ISTATE_S2L4	0x0000030000000000 /* Slot 2, level 4 */
-#define SYSIO_SBUS_ISTATE_S2L5	0x00000c0000000000 /* Slot 2, level 5 */
-#define SYSIO_SBUS_ISTATE_S2L6	0x0000300000000000 /* Slot 2, level 6 */
-#define SYSIO_SBUS_ISTATE_S2L7	0x0000c00000000000 /* Slot 2, level 7 */
-#define SYSIO_SBUS_ISTATE_S3L1	0x000c000000000000 /* Slot 3, level 1 */
-#define SYSIO_SBUS_ISTATE_S3L2	0x0030000000000000 /* Slot 3, level 2 */
-#define SYSIO_SBUS_ISTATE_S3L3	0x00c0000000000000 /* Slot 3, level 3 */
-#define SYSIO_SBUS_ISTATE_S3L4	0x0300000000000000 /* Slot 3, level 4 */
-#define SYSIO_SBUS_ISTATE_S3L5	0x0c00000000000000 /* Slot 3, level 5 */
-#define SYSIO_SBUS_ISTATE_S3L6	0x3000000000000000 /* Slot 3, level 6 */
-#define SYSIO_SBUS_ISTATE_S3L7	0xc000000000000000 /* Slot 3, level 7 */
-
-/* For OBIO devices things are a bit different, you just have to know what
- * you are looking for.
- */
-#define SYSIO_OBIO_ISTATE_SCSI	0x0000000000000003 /* Scsi		*/
-#define SYSIO_OBIO_ISTATE_ETH	0x000000000000000c /* Ethernet		*/
-#define SYSIO_OBIO_ISTATE_PP	0x0000000000000030 /* Parallel Port	*/
-#define SYSIO_OBIO_ISTATE_AUDIO	0x00000000000000c0 /* Sun Audio		*/
-#define SYSIO_OBIO_ISTATE_PFAIL	0x0000000000000300 /* Power Fail	*/
-#define SYSIO_OBIO_ISTATE_KBMS	0x0000000000000c00 /* kbd/mouse/serial	*/
-#define SYSIO_OBIO_ISTATE_FLPY	0x0000000000003000 /* Floppy Controller	*/
-#define SYSIO_OBIO_ISTATE_SPHW	0x000000000000c000 /* Spare HW		*/
-#define SYSIO_OBIO_ISTATE_KBD	0x0000000000030000 /* Keyboard		*/
-#define SYSIO_OBIO_ISTATE_MS	0x00000000000c0000 /* Mouse		*/
-#define SYSIO_OBIO_ISTATE_SER	0x0000000000300000 /* Serial		*/
-#define SYSIO_OBIO_ISTATE_TIM0	0x0000000000c00000 /* Timer 0		*/
-#define SYSIO_OBIO_ISTATE_TIM1	0x0000000003000000 /* Timer 1		*/
-#define SYSIO_OBIO_ISTATE_UE	0x000000000c000000 /* Uncorrectable Err	*/
-#define SYSIO_OBIO_ISTATE_CE	0x0000000030000000 /* Correctable Err	*/
-#define SYSIO_OBIO_ISTATE_SERR	0x00000000c0000000 /* SBUS Err		*/
-#define SYSIO_OBIO_ISTATE_PMGMT	0x0000000300000000 /* Power Management	*/
-#define SYSIO_OBIO_ISTATE_RSVI	0x0000000400000000 /* Reserved Int	*/
-#define SYSIO_OBIO_ISTATE_EUPA	0x0000000800000000 /* Expansion UPA (creator) */
-#define SYSIO_OBIO_ISTATE_RESV	0xfffffff000000000 /* Reserved...	*/
-
-/* SYSIO Counter and Limit registers are documented in timer.h as these
- * are generic SUN4U things.
- */
-
-/* SYSIO Performance Monitor Control register. */
-#define SYSIO_PCNTRL_CLR1	0x0000000000008000 /* Clear SEL1 counter              */
-#define SYSIO_PCNTRL_SEL1_SDR	0x0000000000000000 /* SEL1: Streaming DVMA reads      */
-#define SYSIO_PCNTRL_SEL1_SDW	0x0000000000000100 /* SEL1: Streaming DVMA writes     */
-#define SYSIO_PCNTRL_SEL1_CDR	0x0000000000000200 /* SEL1: Consistent DVMA reads     */
-#define SYSIO_PCNTRL_SEL1_CDW	0x0000000000000300 /* SEL1: Consistent DVMA writes    */
-#define SYSIO_PCNTRL_SEL1_TMISS	0x0000000000000400 /* SEL1: IOMMU TLB misses          */
-#define SYSIO_PCNTRL_SEL1_SMISS	0x0000000000000500 /* SEL1: Streaming Buffer misses   */
-#define SYSIO_PCNTRL_SEL1_SDC	0x0000000000000600 /* SEL1: SBUS dvma cycles          */
-#define SYSIO_PCNTRL_SEL1_DB	0x0000000000000700 /* SEL1: DVMA bytes transferred    */
-#define SYSIO_PCNTRL_SEL1_IRQ	0x0000000000000800 /* SEL1: Interrupts                */
-#define SYSIO_PCNTRL_SEL1_UIN	0x0000000000000900 /* SEL1: UPA IRQ NACK's            */
-#define SYSIO_PCNTRL_SEL1_PRD	0x0000000000000a00 /* SEL1: PIO reads                 */
-#define SYSIO_PCNTRL_SEL1_PWR	0x0000000000000b00 /* SEL1: PIO writes                */
-#define SYSIO_PCNTRL_SEL1_SRR	0x0000000000000c00 /* SEL1: SBUS reruns               */
-#define SYSIO_PCNTRL_SEL1_SPIO	0x0000000000000d00 /* SEL1: SYSIO PIO cycles          */
-#define SYSIO_PCNTRL_CLR0	0x0000000000000080 /* Clear SEL0 counter              */
-#define SYSIO_PCNTRL_SEL0_SDR	0x0000000000000000 /* SEL0: Streaming DVMA reads      */
-#define SYSIO_PCNTRL_SEL0_SDW	0x0000000000000001 /* SEL0: Streaming DVMA writes     */
-#define SYSIO_PCNTRL_SEL0_CDR	0x0000000000000002 /* SEL0: Consistent DVMA reads     */
-#define SYSIO_PCNTRL_SEL0_CDW	0x0000000000000003 /* SEL0: Consistent DVMA writes    */
-#define SYSIO_PCNTRL_SEL0_TMISS	0x0000000000000004 /* SEL0: IOMMU TLB misses          */
-#define SYSIO_PCNTRL_SEL0_SMISS	0x0000000000000005 /* SEL0: Streaming Buffer misses   */
-#define SYSIO_PCNTRL_SEL0_SDC	0x0000000000000006 /* SEL0: SBUS dvma cycles          */
-#define SYSIO_PCNTRL_SEL0_DB	0x0000000000000007 /* SEL0: DVMA bytes transferred    */
-#define SYSIO_PCNTRL_SEL0_IRQ	0x0000000000000008 /* SEL0: Interrupts                */
-#define SYSIO_PCNTRL_SEL0_UIN	0x0000000000000009 /* SEL0: UPA IRQ NACK's            */
-#define SYSIO_PCNTRL_SEL0_PRD	0x000000000000000a /* SEL0: PIO reads                 */
-#define SYSIO_PCNTRL_SEL0_PWR	0x000000000000000b /* SEL0: PIO writes                */
-#define SYSIO_PCNTRL_SEL0_SRR	0x000000000000000c /* SEL0: SBUS reruns               */
-#define SYSIO_PCNTRL_SEL0_SPIO	0x000000000000000d /* SEL0: SYSIO PIO cycles          */
-
-/* SYSIO Performance Monitor Counter register. */
-#define SYSIO_PCOUNT_CNT0	0xffffffff00000000 /* Counter zero  */
-#define SYSIO_PCOUNT_CNT1	0x00000000ffffffff /* Counter one  */
-
-#endif /* !(__SPARC64_SYSIO_H) */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/termios.h linux/include/asm-sparc64/termios.h
--- v2.3.34/linux/include/asm-sparc64/termios.h	Mon Nov  1 13:56:27 1999
+++ linux/include/asm-sparc64/termios.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: termios.h,v 1.8 1999/03/25 09:11:26 davem Exp $ */
+/* $Id: termios.h,v 1.9 1999/12/02 09:57:53 davem Exp $ */
 #ifndef _SPARC64_TERMIOS_H
 #define _SPARC64_TERMIOS_H
 
@@ -69,7 +69,7 @@
 #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 */
-#define N_SYNC_PPP	14
+#define N_SYNC_PPP	14	/* synchronous PPP */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/ttable.h linux/include/asm-sparc64/ttable.h
--- v2.3.34/linux/include/asm-sparc64/ttable.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-sparc64/ttable.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: ttable.h,v 1.13 1999/08/31 19:25:50 davem Exp $ */
+/* $Id: ttable.h,v 1.14 1999/10/13 11:48:58 jj Exp $ */
 #ifndef _SPARC64_TTABLE_H
 #define _SPARC64_TTABLE_H
 
@@ -107,7 +107,11 @@
 	ba,pt	%xcc, utrap_ill;					\
 	 mov	lvl, %o1;
 
+#ifdef CONFIG_SUNOS_EMUL
 #define SUNOS_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sunos_sys_table)
+#else
+#define SUNOS_SYSCALL_TRAP TRAP(sunos_syscall)
+#endif
 #define	LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sys_call_table32)
 #define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64)
 #define GETCC_TRAP TRAP(getcc)
@@ -159,6 +163,20 @@
 	        
 /* Before touching these macros, you owe it to yourself to go and
  * see how arch/sparc64/kernel/winfixup.S works... -DaveM
+ *
+ * For the user cases we used to use the %asi register, but
+ * it turns out that the "wr xxx, %asi" costs ~5 cycles, so
+ * now we use immediate ASI loads and stores instead.  Kudos
+ * to Greg Onufer for pointing out this performance anomaly.
+ *
+ * Further note that we cannot use the g2, g4, g5, and g7 alternate
+ * globals in the spill routines, check out the save instruction in
+ * arch/sparc64/kernel/etrap.S to see what I mean about g2, and
+ * g4/g5 are the globals which are preserved by etrap processing
+ * for the caller of it.  The g7 register is the return pc for
+ * etrap.  Finally, g6 is the current thread register so we cannot
+ * us it in the spill handlers either.  Most of these rules do not
+ * apply to fill processing, only g6 is not usable.
  */
 
 /* Normal kernel spill */
@@ -183,52 +201,67 @@
 	nop; nop; nop; nop; nop; nop; nop; nop;
 
 /* Normal 64bit spill */
-#define SPILL_1_GENERIC(xxx)				\
-	wr	%g0, xxx, %asi;				\
-	stxa	%l0, [%sp + STACK_BIAS + 0x00] %asi;	\
-	stxa	%l1, [%sp + STACK_BIAS + 0x08] %asi;	\
-	stxa	%l2, [%sp + STACK_BIAS + 0x10] %asi;	\
-	stxa	%l3, [%sp + STACK_BIAS + 0x18] %asi;	\
-	stxa	%l4, [%sp + STACK_BIAS + 0x20] %asi;	\
-	stxa	%l5, [%sp + STACK_BIAS + 0x28] %asi;	\
-	stxa	%l6, [%sp + STACK_BIAS + 0x30] %asi;	\
-	stxa	%l7, [%sp + STACK_BIAS + 0x38] %asi;	\
-	stxa	%i0, [%sp + STACK_BIAS + 0x40] %asi;	\
-	stxa	%i1, [%sp + STACK_BIAS + 0x48] %asi;	\
-	stxa	%i2, [%sp + STACK_BIAS + 0x50] %asi;	\
-	stxa	%i3, [%sp + STACK_BIAS + 0x58] %asi;	\
-	stxa	%i4, [%sp + STACK_BIAS + 0x60] %asi;	\
-	stxa	%i5, [%sp + STACK_BIAS + 0x68] %asi;	\
-	stxa	%i6, [%sp + STACK_BIAS + 0x70] %asi;	\
-	stxa	%i7, [%sp + STACK_BIAS + 0x78] %asi;	\
-	saved; retry; nop; nop; nop; nop; nop; nop;	\
-	nop; nop; nop; nop;				\
+#define SPILL_1_GENERIC(ASI)				\
+	add	%sp, STACK_BIAS + 0x00, %g1;		\
+	stxa	%l0, [%g1 + %g0] ASI;			\
+	mov	0x08, %g3;				\
+	stxa	%l1, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%l2, [%g1 + %g0] ASI;			\
+	stxa	%l3, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%l4, [%g1 + %g0] ASI;			\
+	stxa	%l5, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%l6, [%g1 + %g0] ASI;			\
+	stxa	%l7, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%i0, [%g1 + %g0] ASI;			\
+	stxa	%i1, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%i2, [%g1 + %g0] ASI;			\
+	stxa	%i3, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%i4, [%g1 + %g0] ASI;			\
+	stxa	%i5, [%g1 + %g3] ASI;			\
+	add	%g1, 0x10, %g1;				\
+	stxa	%i6, [%g1 + %g0] ASI;			\
+	stxa	%i7, [%g1 + %g3] ASI;			\
+	saved;						\
+	retry; nop; nop;				\
 	b,a,pt	%xcc, spill_fixup_dax;			\
 	b,a,pt	%xcc, spill_fixup_mna;			\
 	b,a,pt	%xcc, spill_fixup;
 
 /* Normal 32bit spill */
-#define SPILL_2_GENERIC(xxx)				\
-	wr	%g0, xxx, %asi;				\
+#define SPILL_2_GENERIC(ASI)				\
 	srl	%sp, 0, %sp;				\
-	stwa	%l0, [%sp + 0x00] %asi;			\
-	stwa	%l1, [%sp + 0x04] %asi;			\
-	stwa	%l2, [%sp + 0x08] %asi;			\
-	stwa	%l3, [%sp + 0x0c] %asi;			\
-	stwa	%l4, [%sp + 0x10] %asi;			\
-	stwa	%l5, [%sp + 0x14] %asi;			\
-	stwa	%l6, [%sp + 0x18] %asi;			\
-	stwa	%l7, [%sp + 0x1c] %asi;			\
-	stwa	%i0, [%sp + 0x20] %asi;			\
-	stwa	%i1, [%sp + 0x24] %asi;			\
-	stwa	%i2, [%sp + 0x28] %asi;			\
-	stwa	%i3, [%sp + 0x2c] %asi;			\
-	stwa	%i4, [%sp + 0x30] %asi;			\
-	stwa	%i5, [%sp + 0x34] %asi;			\
-	stwa	%i6, [%sp + 0x38] %asi;			\
-	stwa	%i7, [%sp + 0x3c] %asi;			\
-	saved; retry; nop; nop; nop; nop;		\
-	nop; nop; nop; nop; nop;			\
+	stwa	%l0, [%sp + %g0] ASI;			\
+	mov	0x04, %g3;				\
+	stwa	%l1, [%sp + %g3] ASI;			\
+	add	%sp, 0x08, %g1;				\
+	stwa	%l2, [%g1 + %g0] ASI;			\
+	stwa	%l3, [%g1 + %g3] ASI;			\
+	add	%g1, 0x08, %g1;				\
+	stwa	%l4, [%g1 + %g0] ASI;			\
+	stwa	%l5, [%g1 + %g3] ASI;			\
+	add	%g1, 0x08, %g1;				\
+	stwa	%l6, [%g1 + %g0] ASI;			\
+	stwa	%l7, [%g1 + %g3] ASI;			\
+	add	%g1, 0x08, %g1;				\
+	stwa	%i0, [%g1 + %g0] ASI;			\
+	stwa	%i1, [%g1 + %g3] ASI;			\
+	add	%g1, 0x08, %g1;				\
+	stwa	%i2, [%g1 + %g0] ASI;			\
+	stwa	%i3, [%g1 + %g3] ASI;			\
+	add	%g1, 0x08, %g1;				\
+	stwa	%i4, [%g1 + %g0] ASI;			\
+	stwa	%i5, [%g1 + %g3] ASI;			\
+	add	%g1, 0x08, %g1;				\
+	stwa	%i6, [%g1 + %g0] ASI;			\
+	stwa	%i7, [%g1 + %g3] ASI;			\
+	saved;						\
+        retry; nop; nop;				\
 	b,a,pt	%xcc, spill_fixup_dax;			\
 	b,a,pt	%xcc, spill_fixup_mna;			\
 	b,a,pt	%xcc, spill_fixup;
@@ -272,52 +305,63 @@
 	nop; nop; nop; nop; nop; nop; nop; nop;
 
 /* Normal 64bit fill */
-#define FILL_1_GENERIC(xxx)				\
-	wr	%g0, xxx, %asi;				\
-	ldxa	[%sp + STACK_BIAS + 0x00] %asi, %l0;	\
-	ldxa	[%sp + STACK_BIAS + 0x08] %asi, %l1;	\
-	ldxa	[%sp + STACK_BIAS + 0x10] %asi, %l2;	\
-	ldxa	[%sp + STACK_BIAS + 0x18] %asi, %l3;	\
-	ldxa	[%sp + STACK_BIAS + 0x20] %asi, %l4;	\
-	ldxa	[%sp + STACK_BIAS + 0x28] %asi, %l5;	\
-	ldxa	[%sp + STACK_BIAS + 0x30] %asi, %l6;	\
-	ldxa	[%sp + STACK_BIAS + 0x38] %asi, %l7;	\
-	ldxa	[%sp + STACK_BIAS + 0x40] %asi, %i0;	\
-	ldxa	[%sp + STACK_BIAS + 0x48] %asi, %i1;	\
-	ldxa	[%sp + STACK_BIAS + 0x50] %asi, %i2;	\
-	ldxa	[%sp + STACK_BIAS + 0x58] %asi, %i3;	\
-	ldxa	[%sp + STACK_BIAS + 0x60] %asi, %i4;	\
-	ldxa	[%sp + STACK_BIAS + 0x68] %asi, %i5;	\
-	ldxa	[%sp + STACK_BIAS + 0x70] %asi, %i6;	\
-	ldxa	[%sp + STACK_BIAS + 0x78] %asi, %i7;	\
-	restored; retry; nop; nop; nop; nop; nop; nop;	\
-	nop; nop; nop; nop;				\
+#define FILL_1_GENERIC(ASI)				\
+	add	%sp, STACK_BIAS + 0x00, %g1;		\
+	ldxa	[%g1 + %g0] ASI, %l0;			\
+	mov	0x08, %g2;				\
+	mov	0x10, %g3;				\
+	ldxa	[%g1 + %g2] ASI, %l1;			\
+	mov	0x18, %g5;				\
+	ldxa	[%g1 + %g3] ASI, %l2;			\
+	ldxa	[%g1 + %g5] ASI, %l3;			\
+	add	%g1, 0x20, %g1;				\
+	ldxa	[%g1 + %g0] ASI, %l4;			\
+	ldxa	[%g1 + %g2] ASI, %l5;			\
+	ldxa	[%g1 + %g3] ASI, %l6;			\
+	ldxa	[%g1 + %g5] ASI, %l7;			\
+	add	%g1, 0x20, %g1;				\
+	ldxa	[%g1 + %g0] ASI, %i0;			\
+	ldxa	[%g1 + %g2] ASI, %i1;			\
+	ldxa	[%g1 + %g3] ASI, %i2;			\
+	ldxa	[%g1 + %g5] ASI, %i3;			\
+	add	%g1, 0x20, %g1;				\
+	ldxa	[%g1 + %g0] ASI, %i4;			\
+	ldxa	[%g1 + %g2] ASI, %i5;			\
+	ldxa	[%g1 + %g3] ASI, %i6;			\
+	ldxa	[%g1 + %g5] ASI, %i7;			\
+	restored;					\
+	retry; nop; nop; nop; nop;			\
 	b,a,pt	%xcc, fill_fixup_dax;			\
 	b,a,pt	%xcc, fill_fixup_mna;			\
 	b,a,pt	%xcc, fill_fixup;
 
 /* Normal 32bit fill */
-#define FILL_2_GENERIC(xxx)				\
-	wr	%g0, xxx, %asi;				\
+#define FILL_2_GENERIC(ASI)				\
 	srl	%sp, 0, %sp;				\
-	lduwa	[%sp + 0x00] %asi, %l0;			\
-	lduwa	[%sp + 0x04] %asi, %l1;			\
-	lduwa	[%sp + 0x08] %asi, %l2;			\
-	lduwa	[%sp + 0x0c] %asi, %l3;			\
-	lduwa	[%sp + 0x10] %asi, %l4;			\
-	lduwa	[%sp + 0x14] %asi, %l5;			\
-	lduwa	[%sp + 0x18] %asi, %l6;			\
-	lduwa	[%sp + 0x1c] %asi, %l7;			\
-	lduwa	[%sp + 0x20] %asi, %i0;			\
-	lduwa	[%sp + 0x24] %asi, %i1;			\
-	lduwa	[%sp + 0x28] %asi, %i2;			\
-	lduwa	[%sp + 0x2c] %asi, %i3;			\
-	lduwa	[%sp + 0x30] %asi, %i4;			\
-	lduwa	[%sp + 0x34] %asi, %i5;			\
-	lduwa	[%sp + 0x38] %asi, %i6;			\
-	lduwa	[%sp + 0x3c] %asi, %i7;			\
-	restored; retry; nop; nop; nop; nop;		\
-	nop; nop; nop; nop; nop;			\
+	lduwa	[%sp + %g0] ASI, %l0;			\
+	mov	0x04, %g2;				\
+	mov	0x08, %g3;				\
+	lduwa	[%sp + %g2] ASI, %l1;			\
+	mov	0x0c, %g5;				\
+	lduwa	[%sp + %g3] ASI, %l2;			\
+	lduwa	[%sp + %g5] ASI, %l3;			\
+	add	%sp, 0x10, %g1;				\
+	lduwa	[%g1 + %g0] ASI, %l4;			\
+	lduwa	[%g1 + %g2] ASI, %l5;			\
+	lduwa	[%g1 + %g3] ASI, %l6;			\
+	lduwa	[%g1 + %g5] ASI, %l7;			\
+	add	%g1, 0x10, %g1;				\
+	lduwa	[%g1 + %g0] ASI, %i0;			\
+	lduwa	[%g1 + %g2] ASI, %i1;			\
+	lduwa	[%g1 + %g3] ASI, %i2;			\
+	lduwa	[%g1 + %g5] ASI, %i3;			\
+	add	%g1, 0x10, %g1;				\
+	lduwa	[%g1 + %g0] ASI, %i4;			\
+	lduwa	[%g1 + %g2] ASI, %i5;			\
+	lduwa	[%g1 + %g3] ASI, %i6;			\
+	lduwa	[%g1 + %g5] ASI, %i7;			\
+	restored;					\
+	retry; nop; nop; nop; nop;			\
 	b,a,pt	%xcc, fill_fixup_dax;			\
 	b,a,pt	%xcc, fill_fixup_mna;			\
 	b,a,pt	%xcc, fill_fixup;
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/uaccess.h linux/include/asm-sparc64/uaccess.h
--- v2.3.34/linux/include/asm-sparc64/uaccess.h	Mon Aug  2 22:07:16 1999
+++ linux/include/asm-sparc64/uaccess.h	Mon Dec 20 22:05:52 1999
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.31 1999/07/30 09:31:24 davem Exp $ */
+/* $Id: uaccess.h,v 1.32 1999/11/23 08:56:48 davem Exp $ */
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
 
@@ -347,8 +347,10 @@
 	__strncpy_from_user((unsigned long)(dest), (unsigned long)(src), (int)(count))
 
 extern int __strlen_user(const char *);
+extern int __strnlen_user(const char *, long len);
 
 #define strlen_user __strlen_user
+#define strnlen_user __strnlen_user
 
 #endif  /* __ASSEMBLY__ */
 
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h
--- v2.3.34/linux/include/asm-sparc64/unistd.h	Wed Aug  4 15:39:46 1999
+++ linux/include/asm-sparc64/unistd.h	Tue Dec 21 21:56:42 1999
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.31 1999/08/04 03:20:06 davem Exp $ */
+/* $Id: unistd.h,v 1.36 1999/12/21 14:09:51 jj Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
@@ -71,14 +71,14 @@
 /* #define __NR_mctl             53    SunOS specific                              */
 #define __NR_ioctl               54 /* Common                                      */
 #define __NR_reboot              55 /* Common                                      */
-/* #define __NR_ni_syscall       56    ENOSYS under SunOS                          */
+/* #define __NR_mmap2		 56    Linux sparc32 Specific                      */
 #define __NR_symlink             57 /* Common                                      */
 #define __NR_readlink            58 /* Common                                      */
 #define __NR_execve              59 /* Common                                      */
 #define __NR_umask               60 /* Common                                      */
 #define __NR_chroot              61 /* Common                                      */
 #define __NR_fstat               62 /* Common                                      */
-/* #define __NR_ni_syscall       63    ENOSYS under SunOS                          */
+/* #define __NR_fstat64          63    Linux sparc32 Specific                      */
 #define __NR_getpagesize         64 /* Common                                      */
 #define __NR_msync               65 /* Common in newer 1.3.x revs...               */
 #define __NR_vfork               66 /* Common                                      */
@@ -92,14 +92,14 @@
 #define __NR_mprotect            74 /* Common                                      */
 /* #define __NR_madvise          75    SunOS Specific                              */
 #define __NR_vhangup             76 /* Common                                      */
-/* #define __NR_ni_syscall       77    ENOSYS under SunOS                          */
+/* #define __NR_truncate64       77    Linux sparc32 Specific			   */
 /* #define __NR_mincore          78    SunOS Specific                              */
 #define __NR_getgroups           79 /* Common                                      */
 #define __NR_setgroups           80 /* Common                                      */
 #define __NR_getpgrp             81 /* Common                                      */
 /* #define __NR_setpgrp          82    setpgid, same difference...                 */
 #define __NR_setitimer           83 /* Common                                      */
-/* #define __NR_ni_syscall       84    ENOSYS under SunOS                          */
+/* #define __NR_ftruncate64      84    Linux sparc32 Specific			   */
 #define __NR_swapon              85 /* Common                                      */
 #define __NR_getitimer           86 /* Common                                      */
 /* #define __NR_gethostname      87    SunOS Specific                              */
@@ -147,19 +147,19 @@
 #define __NR_truncate           129 /* Common                                      */
 #define __NR_ftruncate          130 /* Common                                      */
 #define __NR_flock              131 /* Common                                      */
-/* #define __NR_ni_syscall      132    ENOSYS under SunOS                          */
+/* #define __NR_lstat64		132    Linux sparc32 Specific                      */
 #define __NR_sendto             133 /* Common                                      */
 #define __NR_shutdown           134 /* Common                                      */
 #define __NR_socketpair         135 /* Common                                      */
 #define __NR_mkdir              136 /* Common                                      */
 #define __NR_rmdir              137 /* Common                                      */
 #define __NR_utimes             138 /* SunOS Specific                              */
-/* #define __NR_ni_syscall      139    ENOSYS under SunOS                          */
+/* #define __NR_stat64		139    Linux sparc32 Specific			   */
 /* #define __NR_adjtime         140    SunOS Specific                              */
 #define __NR_getpeername        141 /* Common                                      */
 /* #define __NR_gethostid       142    SunOS Specific                              */
 /* #define __NR_ni_syscall      143    ENOSYS under SunOS                          */
-#define __NR_getrlimit          144 /* Common                                      */
+#define __NR_getrlimit		144 /* Common                                      */
 #define __NR_setrlimit          145 /* Common                                      */
 /* #define __NR_killpg          146    SunOS Specific                              */
 #define __NR_prctl		147 /* ENOSYS under SunOS                          */
diff -u --recursive --new-file v2.3.34/linux/include/asm-sparc64/upa.h linux/include/asm-sparc64/upa.h
--- v2.3.34/linux/include/asm-sparc64/upa.h	Mon Apr 14 16:28:24 1997
+++ linux/include/asm-sparc64/upa.h	Mon Dec 20 22:05:52 1999
@@ -1,7 +1,9 @@
-/* $Id: upa.h,v 1.2 1997/04/04 00:50:30 davem Exp $ */
+/* $Id: upa.h,v 1.3 1999/09/21 14:39:47 davem Exp $ */
 #ifndef _SPARC64_UPA_H
 #define _SPARC64_UPA_H
 
+#include <asm/asi.h>
+
 /* UPA level registers and defines. */
 
 /* UPA Config Register */
@@ -20,5 +22,89 @@
 #define UPA_PORTID_PREQRD       0x0000000001e00000 /* # incoming P_REQ's supported */
 #define UPA_PORTID_UPACAP       0x00000000001f0000 /* UPA capabilities of mod      */
 #define UPA_PORTID_ID           0x000000000000ffff /* Module Indentification bits  */
+
+/* UPA I/O space accessors */
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+extern __inline__ unsigned char _upa_readb(unsigned long addr)
+{
+	unsigned char ret;
+
+	__asm__ __volatile__("lduba\t[%1] %2, %0\t/* upa_readb */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+extern __inline__ unsigned short _upa_readw(unsigned long addr)
+{
+	unsigned short ret;
+
+	__asm__ __volatile__("lduha\t[%1] %2, %0\t/* upa_readw */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+extern __inline__ unsigned int _upa_readl(unsigned long addr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduwa\t[%1] %2, %0\t/* upa_readl */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+extern __inline__ unsigned long _upa_readq(unsigned long addr)
+{
+	unsigned long ret;
+
+	__asm__ __volatile__("ldxa\t[%1] %2, %0\t/* upa_readq */"
+			     : "=r" (ret)
+			     : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
+	return ret;
+}
+
+extern __inline__ void _upa_writeb(unsigned char b, unsigned long addr)
+{
+	__asm__ __volatile__("stba\t%0, [%1] %2\t/* upa_writeb */"
+			     : /* no outputs */
+			     : "r" (b), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+extern __inline__ void _upa_writew(unsigned short w, unsigned long addr)
+{
+	__asm__ __volatile__("stha\t%0, [%1] %2\t/* upa_writew */"
+			     : /* no outputs */
+			     : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+extern __inline__ void _upa_writel(unsigned int l, unsigned long addr)
+{
+	__asm__ __volatile__("stwa\t%0, [%1] %2\t/* upa_writel */"
+			     : /* no outputs */
+			     : "r" (l), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+extern __inline__ void _upa_writeq(unsigned long q, unsigned long addr)
+{
+	__asm__ __volatile__("stxa\t%0, [%1] %2\t/* upa_writeq */"
+			     : /* no outputs */
+			     : "r" (q), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+}
+
+#define upa_readb(__addr)		(_upa_readb((unsigned long)(__addr)))
+#define upa_readw(__addr)		(_upa_readw((unsigned long)(__addr)))
+#define upa_readl(__addr)		(_upa_readl((unsigned long)(__addr)))
+#define upa_readq(__addr)		(_upa_readq((unsigned long)(__addr)))
+#define upa_writeb(__b, __addr)		(_upa_writeb((__b), (unsigned long)(__addr)))
+#define upa_writew(__w, __addr)		(_upa_writew((__w), (unsigned long)(__addr)))
+#define upa_writel(__l, __addr)		(_upa_writel((__l), (unsigned long)(__addr)))
+#define upa_writeq(__q, __addr)		(_upa_writeq((__q), (unsigned long)(__addr)))
+#endif /* __KERNEL__ && !__ASSEMBLY__ */
 
 #endif /* !(_SPARC64_UPA_H) */
diff -u --recursive --new-file v2.3.34/linux/include/linux/acpi.h linux/include/linux/acpi.h
--- v2.3.34/linux/include/linux/acpi.h	Tue Dec  7 09:32:51 1999
+++ linux/include/linux/acpi.h	Tue Dec 28 17:44:06 1999
@@ -236,12 +236,6 @@
 #define ACPI_TMR_TICKS_TO_uS(ticks) \
   (((ticks) * 100) / (ACPI_TMR_HZ / 10000))
 
-/* CPU cycles -> PM timer cycles, looks somewhat heuristic but
-   (ticks = 3/11 * CPU_MHz + 2) comes pretty close for my systems
- */
-#define ACPI_CPU_TO_TMR_TICKS(cycles) \
-  ((cycles) / (3 * (loops_per_sec + 2500) / 500000 / 11 + 2))
-
 /* PM2_CNT flags */
 #define ACPI_ARB_DIS 0x01
 
diff -u --recursive --new-file v2.3.34/linux/include/linux/i2c-old.h linux/include/linux/i2c-old.h
--- v2.3.34/linux/include/linux/i2c-old.h	Mon Dec 20 18:48:22 1999
+++ linux/include/linux/i2c-old.h	Fri Dec 24 10:37:09 1999
@@ -42,6 +42,7 @@
 #define I2C_BUSID_PARPORT	2	/* Bit banging on a parallel port */
 #define I2C_BUSID_BUZ		3
 #define I2C_BUSID_ZORAN		4
+#define I2C_BUSID_CYBER2000	5
 
 /*
  * struct for a driver for a i2c chip (tuner, soundprocessor,
diff -u --recursive --new-file v2.3.34/linux/include/linux/interrupt.h linux/include/linux/interrupt.h
--- v2.3.34/linux/include/linux/interrupt.h	Wed Aug 18 16:43:32 1999
+++ linux/include/linux/interrupt.h	Tue Dec 28 17:42:53 1999
@@ -80,5 +80,6 @@
  */
 extern unsigned long probe_irq_on(void);	/* returns 0 on failure */
 extern int probe_irq_off(unsigned long);	/* returns 0 or negative on failure */
+extern unsigned int probe_irq_mask(unsigned long);	/* returns mask of ISA interrupts */
 
 #endif
diff -u --recursive --new-file v2.3.34/linux/include/linux/irda.h linux/include/linux/irda.h
--- v2.3.34/linux/include/linux/irda.h	Wed Oct 27 16:34:12 1999
+++ linux/include/linux/irda.h	Tue Dec 21 10:17:31 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Mar  8 14:06:12 1999
- * Modified at:   Sun Oct 10 23:00:59 1999
+ * Modified at:   Sun Dec 12 12:23:11 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -20,6 +20,9 @@
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
+ *     You probably need to include <sys/types.h> before this one if your
+ *     including this file from user-space 
+ *
  ********************************************************************/
 
 #ifndef KERNEL_IRDA_H
@@ -58,26 +61,35 @@
 
 /* These are the currently known dongles */
 typedef enum {
-	IRDA_TEKRAM_DONGLE,
-	IRDA_ESI_DONGLE,
-	IRDA_ACTISYS_DONGLE,
-	IRDA_ACTISYS_PLUS_DONGLE,
-	IRDA_GIRBIL_DONGLE,
-	IRDA_LITELINK_DONGLE,
-	IRDA_AIRPORT_DONGLE,
+	IRDA_TEKRAM_DONGLE       = 0,
+	IRDA_ESI_DONGLE          = 1,
+	IRDA_ACTISYS_DONGLE      = 2,
+	IRDA_ACTISYS_PLUS_DONGLE = 3,
+	IRDA_GIRBIL_DONGLE       = 4,
+	IRDA_LITELINK_DONGLE     = 5,
+	IRDA_AIRPORT_DONGLE      = 6,
+	IRDA_OLD_BELKIN_DONGLE   = 7,
 } IRDA_DONGLE;
 
+/* Protocol types to be used for SOCK_DGRAM */
+enum {
+	IRDAPROTO_UNITDATA = 0,
+	IRDAPROTO_ULTRA    = 1,
+	IRDAPROTO_MAX
+};
+
 #define SOL_IRLMP      266 /* Same as SOL_IRDA for now */
 #define SOL_IRTTP      266 /* Same as SOL_IRDA for now */
 
 #define IRLMP_ENUMDEVICES        1
 #define IRLMP_IAS_SET            2
-#define IRLMP_IAS_QUERY          3
-#define IRLMP_DISCOVERY_MASK_SET 4
-
-#define IRTTP_QOS_SET            5
-#define IRTTP_QOS_GET            6
-#define IRTTP_MAX_SDU_SIZE       7
+#define IRLMP_IAS_GET            3
+#define IRLMP_IAS_QUERY          4
+#define IRLMP_HINTS_SET          5
+
+#define IRTTP_QOS_SET            6
+#define IRTTP_QOS_GET            7
+#define IRTTP_MAX_SDU_SIZE       8
 
 #define IAS_MAX_STRING         256
 #define IAS_MAX_OCTET_STRING  1024
@@ -88,21 +100,21 @@
 
 struct sockaddr_irda {
 	sa_family_t   sir_family;   /* AF_IRDA */
-	unsigned char sir_lsap_sel; /* LSAP/TSAP selector */
-	unsigned int  sir_addr;     /* Device address */
+	u_int8_t      sir_lsap_sel; /* LSAP selector */
+	u_int32_t     sir_addr;     /* Device address */
 	char          sir_name[25]; /* Usually <service>:IrDA:TinyTP */
 };
 
 struct irda_device_info {
-	unsigned int  saddr;        /* Address of remote device */
-	unsigned int  daddr;        /* Link where it was discovered */
-	char          info[22];     /* Description */
-	unsigned char charset;      /* Charset used for description */
-	unsigned char hints[2];     /* Hint bits */
+	u_int32_t     saddr;    /* Address of local interface */
+	u_int32_t     daddr;    /* Address of remote device */
+	char          info[22]; /* Description */
+	u_int8_t      charset;  /* Charset used for description */
+	u_int8_t      hints[2]; /* Hint bits */
 };
 
 struct irda_device_list {
-       unsigned int len;
+       u_int32_t len;
        struct irda_device_info dev[1];
 };
 
@@ -131,9 +143,10 @@
 #define SIOCSMEDIABUSY (SIOCDEVPRIVATE + 3)
 #define SIOCGMEDIABUSY (SIOCDEVPRIVATE + 4)
 #define SIOCGRECEIVING (SIOCDEVPRIVATE + 5)
-#define SIOCSRAWMODE   (SIOCDEVPRIVATE + 6)
-#define SIOCSDTRRTS    (SIOCDEVPRIVATE + 7)
-#define SIOCGQOS       (SIOCDEVPRIVATE + 8)
+#define SIOCSMODE      (SIOCDEVPRIVATE + 6)
+#define SIOCGMODE      (SIOCDEVPRIVATE + 7)
+#define SIOCSDTRRTS    (SIOCDEVPRIVATE + 8)
+#define SIOCGQOS       (SIOCDEVPRIVATE + 9)
 
 /* No reason to include <linux/if.h> just because of this one ;-) */
 #define IRNAMSIZ 16 
@@ -167,7 +180,7 @@
 		struct if_irda_qos  ifru_qos;
 		unsigned short      ifru_flags;
 		unsigned int        ifru_receiving;
-		unsigned int        ifru_raw_mode;
+		unsigned int        ifru_mode;
 		unsigned int        ifru_dongle;
 	} ifr_ifru;
 };
@@ -175,7 +188,7 @@
 #define ifr_baudrate  ifr_ifru.ifru_qos.baudrate
 #define ifr_receiving ifr_ifru.ifru_receiving 
 #define ifr_dongle    ifr_ifru.ifru_dongle
-#define ifr_raw_mode  ifr_ifru.ifru_raw_mode
+#define ifr_mode      ifr_ifru.ifru_mode
 #define ifr_dtr       ifr_ifru.ifru_line.dtr
 #define ifr_rts       ifr_ifru.ifru_line.rts
 
diff -u --recursive --new-file v2.3.34/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v2.3.34/linux/include/linux/netdevice.h	Tue Nov 23 22:42:21 1999
+++ linux/include/linux/netdevice.h	Tue Dec 28 17:44:20 1999
@@ -293,6 +293,9 @@
 	/* Called after last user reference disappears. */
 	void			(*destructor)(struct net_device *dev);
 
+	/* Bridge stuff */
+	int			bridge_port_id;		
+	
 	/* Pointers to interface service routines.	*/
 	int			(*open)(struct net_device *dev);
 	int			(*stop)(struct net_device *dev);
diff -u --recursive --new-file v2.3.34/linux/include/linux/openprom_fs.h linux/include/linux/openprom_fs.h
--- v2.3.34/linux/include/linux/openprom_fs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/openprom_fs.h	Mon Dec 20 22:05:10 1999
@@ -0,0 +1,10 @@
+#ifndef _LINUX_OPENPROM_FS_H
+#define _LINUX_OPENPROM_FS_H
+
+/*
+ * The openprom filesystem constants/structures
+ */
+
+#define OPENPROM_SUPER_MAGIC 0x9fa1
+
+#endif /* _LINUX_OPENPROM_FS_H */
diff -u --recursive --new-file v2.3.34/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.3.34/linux/include/linux/pci.h	Wed Dec  8 14:11:28 1999
+++ linux/include/linux/pci.h	Tue Dec 28 17:42:53 1999
@@ -299,6 +299,7 @@
 	int ro;				/* Read/Only */
 
 	struct pci_bus	*bus;		/* bus this device is on */
+	struct pci_bus	*subordinate;	/* bus this device bridges to */
 	struct pci_dev	*sibling;	/* next device on this bus */
 	struct pci_dev	*next;		/* chain of all devices */
 
@@ -359,6 +360,7 @@
 
 	struct pci_dev	*self;		/* bridge device as seen by parent */
 	struct pci_dev	*devices;	/* devices behind this bridge */
+	struct pci_dev	**last_dev_p;	/* where should next device be linked to */
 	struct resource	*resource[4];	/* address space routed to this bus */
 
 	void		*sysdata;	/* hook for sys-specific extension */
@@ -413,14 +415,15 @@
 
 void pcibios_init(void);
 void pcibios_fixup_bus(struct pci_bus *);
-void pcibios_fixup_pbus_ranges(struct pci_bus *, struct pbus_set_ranges_data *);
 int pcibios_enable_device(struct pci_dev *);
 char *pcibios_setup (char *str);
 
+/* Used only when drivers/pci/setup.c is used */
 void pcibios_align_resource(void *, struct resource *, unsigned long);
 void pcibios_update_resource(struct pci_dev *, struct resource *,
 			     struct resource *, int);
 void pcibios_update_irq(struct pci_dev *, int irq);
+void pcibios_fixup_pbus_ranges(struct pci_bus *, struct pbus_set_ranges_data *);
 
 /* Backward compatibility, don't use in new code! */
 
@@ -443,10 +446,12 @@
 			 unsigned short index, unsigned char *bus,
 			 unsigned char *dev_fn);
 
-/* Generic PCI interface functions */
+/* Generic PCI functions used internally */
 
 void pci_init(void);
 struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
+struct pci_bus *pci_alloc_primary_bus(int bus);
+struct pci_dev *pci_scan_slot(struct pci_dev *temp);
 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);
@@ -454,6 +459,8 @@
 void pci_read_bridge_bases(struct pci_bus *child);
 struct resource *pci_find_parent_resource(struct pci_dev *dev, struct resource *res);
 
+/* Generic PCI functions exported to card drivers */
+
 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,
 				 unsigned int ss_vendor, unsigned int ss_device,
@@ -470,9 +477,11 @@
 int pci_write_config_byte(struct pci_dev *dev, int where, u8 val);
 int pci_write_config_word(struct pci_dev *dev, int where, u16 val);
 int pci_write_config_dword(struct pci_dev *dev, int where, u32 val);
+
 int pci_enable_device(struct pci_dev *dev);
 void pci_set_master(struct pci_dev *dev);
 int pci_set_power_state(struct pci_dev *dev, int state);
+int pci_assign_resource(struct pci_dev *dev, int i);
 
 /* Helper functions for low-level code (drivers/pci/setup.c) */
 
diff -u --recursive --new-file v2.3.34/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- v2.3.34/linux/include/linux/pci_ids.h	Mon Dec 20 18:48:22 1999
+++ linux/include/linux/pci_ids.h	Tue Dec 21 23:05:33 1999
@@ -363,11 +363,20 @@
 #define PCI_VENDOR_ID_TI		0x104c
 #define PCI_DEVICE_ID_TI_TVP4010	0x3d04
 #define PCI_DEVICE_ID_TI_TVP4020	0x3d07
-#define PCI_DEVICE_ID_TI_PCI1130	0xac12
-#define PCI_DEVICE_ID_TI_PCI1031	0xac13
-#define PCI_DEVICE_ID_TI_PCI1131	0xac15
-#define PCI_DEVICE_ID_TI_PCI1250	0xac16
-#define PCI_DEVICE_ID_TI_PCI1220	0xac17
+#define PCI_DEVICE_ID_TI_1130		0xac12
+#define PCI_DEVICE_ID_TI_1031		0xac13
+#define PCI_DEVICE_ID_TI_1131		0xac15
+#define PCI_DEVICE_ID_TI_1250		0xac16
+#define PCI_DEVICE_ID_TI_1220		0xac17
+#define PCI_DEVICE_ID_TI_1221		0xac19
+#define PCI_DEVICE_ID_TI_1210		0xac1a
+#define PCI_DEVICE_ID_TI_1450		0xac1b
+#define PCI_DEVICE_ID_TI_1225		0xac1c
+#define PCI_DEVICE_ID_TI_1251A		0xac1d
+#define PCI_DEVICE_ID_TI_1211		0xac1e
+#define PCI_DEVICE_ID_TI_1251B		0xac1f
+#define PCI_DEVICE_ID_TI_1420		0xac51
+
 
 #define PCI_VENDOR_ID_OAK		0x104e
 #define PCI_DEVICE_ID_OAK_OTI107	0x0107
diff -u --recursive --new-file v2.3.34/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.3.34/linux/include/linux/proc_fs.h	Tue Nov 23 22:42:21 1999
+++ linux/include/linux/proc_fs.h	Tue Dec 28 17:43:05 1999
@@ -26,11 +26,6 @@
 
 #define PROC_DYNAMIC_FIRST 4096
 #define PROC_NDYNAMIC      4096
-#define PROC_OPENPROM_FIRST (PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
-#define PROC_OPENPROM	   PROC_OPENPROM_FIRST
-#define PROC_NOPENPROM	   4096
-#define PROC_OPENPROMD_FIRST (PROC_OPENPROM_FIRST+PROC_NOPENPROM)
-#define PROC_NOPENPROMD	   4096
 
 #define PROC_SUPER_MAGIC 0x9fa0
 
@@ -117,17 +112,6 @@
 extern int proc_readdir(struct file *, void *, filldir_t);
 extern struct dentry *proc_lookup(struct inode *, struct dentry *);
 
-struct openpromfs_dev {
- 	struct openpromfs_dev *next;
- 	u32 node;
- 	ino_t inode;
- 	kdev_t rdev;
- 	mode_t mode;
- 	char name[32];
-};
-extern int proc_openprom_regdev(struct openpromfs_dev *);
-extern int proc_openprom_unregdev(struct openpromfs_dev *);
-  
 extern struct inode_operations proc_sys_inode_operations;
 extern struct inode_operations proc_kcore_inode_operations;
 extern struct inode_operations proc_kmsg_inode_operations;
diff -u --recursive --new-file v2.3.34/linux/include/linux/qnx4_fs.h linux/include/linux/qnx4_fs.h
--- v2.3.34/linux/include/linux/qnx4_fs.h	Fri Apr 23 21:20:38 1999
+++ linux/include/linux/qnx4_fs.h	Thu Dec 23 15:21:41 1999
@@ -2,8 +2,8 @@
  *  Name                         : qnx4_fs.h
  *  Author                       : Richard Frowijn
  *  Function                     : qnx4 global filesystem definitions
- *  Version                      : 1.0
- *  Last modified                : 23-03-1998
+ *  Version                      : 1.0.1
+ *  Last modified                : 1999-12-13
  *
  *  History                      : 23-03-1998 created
  */
@@ -14,7 +14,7 @@
 
 #define QNX4_ROOT_INO 1
 
-#define _MAX_XTNTS_PER_XBLK	60
+#define QNX4_MAX_XTNTS_PER_XBLK	60
 /* for di_status */
 #define QNX4_FILE_USED          0x01
 #define QNX4_FILE_MODIFIED      0x02
@@ -34,48 +34,48 @@
 #define QNX4_INODES_PER_BLOCK   0x08	/* 512 / 64 */
 
 /* for filenames */
-#define _SHORT_NAME_MAX        16
-#define QNX4_NAME_MAX          48
+#define QNX4_SHORT_NAME_MAX	16
+#define QNX4_NAME_MAX		48
 
 /*
  * This is the original qnx4 inode layout on disk.
  */
 struct qnx4_inode_entry {
-	char di_fname[16];
-	off_t di_size;
-	_xtnt_t di_first_xtnt;
-	long di_xblk;
+	char di_fname[QNX4_SHORT_NAME_MAX];
+	qnx4_off_t di_size;
+	qnx4_xtnt_t di_first_xtnt;
+	unsigned long di_xblk;
 	time_t di_ftime;
 	time_t di_mtime;
 	time_t di_atime;
 	time_t di_ctime;
-	_nxtnt_t di_num_xtnts;
+	qnx4_nxtnt_t di_num_xtnts;
 	mode_t di_mode;
-	muid_t di_uid;
-	mgid_t di_gid;
-	nlink_t di_nlink;
+	qnx4_muid_t di_uid;
+	qnx4_mgid_t di_gid;
+	qnx4_nlink_t di_nlink;
 	char di_zero[4];
-	_ftype_t di_type;
+	qnx4_ftype_t di_type;
 	unsigned char di_status;
 };
 
 struct qnx4_link_info {
 	char dl_fname[QNX4_NAME_MAX];
-	long dl_inode_blk;
+	unsigned long dl_inode_blk;
 	unsigned char dl_inode_ndx;
 	unsigned char dl_spare[10];
 	unsigned char dl_status;
 };
 
 struct qnx4_xblk {
-	long xblk_next_xblk;
-	long xblk_prev_xblk;
+	unsigned long xblk_next_xblk;
+	unsigned long xblk_prev_xblk;
 	unsigned char xblk_num_xtnts;
 	char xblk_spare[3];
 	long xblk_num_blocks;
-	_xtnt_t xblk_xnts[_MAX_XTNTS_PER_XBLK];
+	qnx4_xtnt_t xblk_xtnts[QNX4_MAX_XTNTS_PER_XBLK];
 	char xblk_signature[8];
-	_xtnt_t xblk_first_xtnt;
+	qnx4_xtnt_t xblk_first_xtnt;
 };
 
 struct qnx4_super_block {
@@ -98,6 +98,7 @@
 extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry);
 extern unsigned long qnx4_count_free_inodes(struct super_block *sb);
 extern unsigned long qnx4_count_free_blocks(struct super_block *sb);
+extern unsigned long qnx4_block_map(struct inode *inode, long iblock);
 
 extern struct buffer_head *qnx4_getblk(struct inode *, int, int);
 extern struct buffer_head *qnx4_bread(struct inode *, int, int);
@@ -107,8 +108,8 @@
 extern struct inode_operations qnx4_file_inode_operations;
 extern struct inode_operations qnx4_dir_inode_operations;
 extern struct inode_operations qnx4_symlink_inode_operations;
-extern int qnx4_is_free(struct super_block *sb, int block);
-extern int qnx4_set_bitmap(struct super_block *sb, int block, int busy);
+extern int qnx4_is_free(struct super_block *sb, long block);
+extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy);
 extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode);
 extern void qnx4_truncate(struct inode *inode);
 extern void qnx4_free_inode(struct inode *inode);
@@ -116,7 +117,7 @@
 extern int qnx4_rmdir(struct inode *dir, struct dentry *dentry);
 extern int qnx4_sync_file(struct file *file, struct dentry *dentry);
 extern int qnx4_sync_inode(struct inode *inode);
-extern int qnx4_bmap(struct inode *inode, int block);
+extern int qnx4_get_block(struct inode *inode, long iblock, struct buffer_head *bh, int create);
 
 #endif				/* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.34/linux/include/linux/qnx4_fs_i.h linux/include/linux/qnx4_fs_i.h
--- v2.3.34/linux/include/linux/qnx4_fs_i.h	Mon Aug 31 13:01:35 1998
+++ linux/include/linux/qnx4_fs_i.h	Thu Dec 23 00:08:44 1999
@@ -18,20 +18,20 @@
  */
 struct qnx4_inode_info {
 	char i_reserved[16];	/* 16 */
-	off_t i_size;		/*  4 */
-	_xtnt_t i_first_xtnt;	/*  8 */
+	qnx4_off_t i_size;		/*  4 */
+	qnx4_xtnt_t i_first_xtnt;	/*  8 */
 	long i_xblk;		/*  4 */
 	time_t i_ftime;		/*  4 */
 	time_t i_mtime;		/*  4 */
 	time_t i_atime;		/*  4 */
 	time_t i_ctime;		/*  4 */
-	_nxtnt_t i_num_xtnts;	/*  2 */
+	qnx4_nxtnt_t i_num_xtnts;	/*  2 */
 	mode_t i_mode;		/*  2 */
-	muid_t i_uid;		/*  2 */
-	mgid_t i_gid;		/*  2 */
-	nlink_t i_nlink;	/*  2 */
+	qnx4_muid_t i_uid;		/*  2 */
+	qnx4_mgid_t i_gid;		/*  2 */
+	qnx4_nlink_t i_nlink;	/*  2 */
 	char i_zero[4];		/*  4 */
-	_ftype_t i_type;	/*  1 */
+	qnx4_ftype_t i_type;	/*  1 */
 	unsigned char i_status;	/*  1 */
 };
 
diff -u --recursive --new-file v2.3.34/linux/include/linux/qnx4_fs_sb.h linux/include/linux/qnx4_fs_sb.h
--- v2.3.34/linux/include/linux/qnx4_fs_sb.h	Mon Aug 31 13:01:35 1998
+++ linux/include/linux/qnx4_fs_sb.h	Thu Dec 23 15:21:41 1999
@@ -11,7 +11,7 @@
 #ifndef _QNX4_FS_SB
 #define _QNX4_FS_SB
 
-#include <linux/qnxtypes.h>
+#include <linux/qnx4_fs.h>
 
 /*
  * qnx4 super-block data in memory
diff -u --recursive --new-file v2.3.34/linux/include/linux/qnxtypes.h linux/include/linux/qnxtypes.h
--- v2.3.34/linux/include/linux/qnxtypes.h	Mon Aug 31 13:01:35 1998
+++ linux/include/linux/qnxtypes.h	Thu Dec 23 00:08:44 1999
@@ -12,17 +12,17 @@
 #ifndef _QNX4TYPES_H
 #define _QNX4TYPES_H
 
-typedef unsigned short _nxtnt_t;
-typedef unsigned char _ftype_t;
+typedef unsigned short qnx4_nxtnt_t;
+typedef unsigned char qnx4_ftype_t;
 
 typedef struct {
 	long xtnt_blk;
 	long xtnt_size;
-} _xtnt_t;
+} qnx4_xtnt_t;
 
-typedef unsigned short muid_t;
-typedef unsigned short mgid_t;
-typedef unsigned long qnx_off_t;
-typedef unsigned short qnx_nlink_t;
+typedef unsigned short qnx4_muid_t;
+typedef unsigned short qnx4_mgid_t;
+typedef unsigned long qnx4_off_t;
+typedef unsigned short qnx4_nlink_t;
 
 #endif
diff -u --recursive --new-file v2.3.34/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v2.3.34/linux/include/linux/skbuff.h	Fri Sep 10 23:57:37 1999
+++ linux/include/linux/skbuff.h	Tue Dec 28 17:44:03 1999
@@ -168,19 +168,25 @@
 extern struct sk_buff *		dev_alloc_skb(unsigned int size);
 extern void			kfree_skbmem(struct sk_buff *skb);
 extern struct sk_buff *		skb_clone(struct sk_buff *skb, int priority);
-extern struct sk_buff *		skb_copy(struct sk_buff *skb, int priority);
-extern struct sk_buff *		skb_realloc_headroom(struct sk_buff *skb, int newheadroom);
+extern struct sk_buff *		skb_copy(const struct sk_buff *skb, int priority);
+extern struct sk_buff *		skb_copy_expand(const struct sk_buff *skb, 
+						int newheadroom,
+						int newtailroom,
+						int priority);
 #define dev_kfree_skb(a)	kfree_skb(a)
 extern unsigned char *		skb_put(struct sk_buff *skb, unsigned int len);
 extern unsigned char *		skb_push(struct sk_buff *skb, unsigned int len);
 extern unsigned char *		skb_pull(struct sk_buff *skb, unsigned int len);
-extern int			skb_headroom(struct sk_buff *skb);
-extern int			skb_tailroom(struct sk_buff *skb);
+extern int			skb_headroom(const struct sk_buff *skb);
+extern int			skb_tailroom(const struct sk_buff *skb);
 extern void			skb_reserve(struct sk_buff *skb, unsigned int len);
 extern void 			skb_trim(struct sk_buff *skb, unsigned int len);
 extern void	skb_over_panic(struct sk_buff *skb, int len, void *here);
 extern void	skb_under_panic(struct sk_buff *skb, int len, void *here);
 
+/* Backwards compatibility */
+#define skb_realloc_headroom(skb, nhr) skb_copy_expand(skb, nhr, skb_tailroom(skb), GFP_ATOMIC)
+
 /* Internal */
 extern __inline__ atomic_t *skb_datarefp(struct sk_buff *skb)
 {
@@ -534,12 +540,12 @@
 	return __skb_pull(skb,len);
 }
 
-extern __inline__ int skb_headroom(struct sk_buff *skb)
+extern __inline__ int skb_headroom(const struct sk_buff *skb)
 {
 	return skb->data-skb->head;
 }
 
-extern __inline__ int skb_tailroom(struct sk_buff *skb)
+extern __inline__ int skb_tailroom(const struct sk_buff *skb)
 {
 	return skb->end-skb->tail;
 }
diff -u --recursive --new-file v2.3.34/linux/include/math-emu/op-1.h linux/include/math-emu/op-1.h
--- v2.3.34/linux/include/math-emu/op-1.h	Tue Aug 31 17:29:15 1999
+++ linux/include/math-emu/op-1.h	Mon Dec 20 22:05:52 1999
@@ -199,25 +199,25 @@
 
 #define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y)				\
   do {									\
-    _FP_W_TYPE _nh, _nl, _q, _r;					\
+    _FP_W_TYPE _nh, _nl, _q, _r, _y;					\
 									\
     /* Normalize Y -- i.e. make the most significant bit set.  */	\
-    Y##_f <<= _FP_WFRACXBITS_##fs - 1;					\
+    _y = Y##_f << _FP_WFRACXBITS_##fs;					\
 									\
     /* Shift X op correspondingly high, that is, up one full word.  */	\
-    if (X##_f <= Y##_f)							\
+    if (X##_f < Y##_f)							\
       {									\
+	R##_e--;							\
 	_nl = 0;							\
 	_nh = X##_f;							\
       }									\
     else								\
       {									\
-	R##_e++;							\
-	_nl = X##_f << (_FP_W_TYPE_SIZE-1);				\
+	_nl = X##_f << (_FP_W_TYPE_SIZE - 1);				\
 	_nh = X##_f >> 1;						\
       }									\
     									\
-    udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);				\
+    udiv_qrnnd(_q, _r, _nh, _nl, _y);					\
     R##_f = _q | (_r != 0);						\
   } while (0)
 
diff -u --recursive --new-file v2.3.34/linux/include/net/br.h linux/include/net/br.h
--- v2.3.34/linux/include/net/br.h	Tue Nov 23 22:42:21 1999
+++ linux/include/net/br.h	Tue Dec 21 10:17:31 1999
@@ -19,7 +19,16 @@
 #define Forwarding	3			  /* (4 4 4)	 */
 #define Blocking	4			  /* (4.4.1)	 */
 
-#define No_of_ports 8
+
+/* MAG Yich! Easiest way of giving a configurable number of ports
+ * If you want more than 32, change BR_MAX_PORTS and recompile brcfg!
+ */
+#define BR_MAX_PORTS (32)
+#if CONFIG_BRIDGE_NUM_PORTS > BR_MAX_PORTS
+#undef CONFIG_BRIDGE_NUM_PORTS
+#define CONFIG_BRIDGE_NUM_PORTS BR_MAX_PORTS
+#endif
+#define No_of_ports CONFIG_BRIDGE_NUM_PORTS
 /* arbitrary choice, to allow the code below to compile */
 
 #define All_ports (No_of_ports + 1)
@@ -147,6 +156,7 @@
 	unsigned int     top_change;		  /* (4.5.3.12)	 */
 	unsigned short   topology_change_time;	  /* (4.5.3.13)	 */
 	unsigned short   hold_time;		  /* (4.5.3.14)	 */
+	unsigned int	 instance;
 } Bridge_data;
 
 /** Port Parameters (4.5.5) **/
@@ -160,7 +170,9 @@
 	unsigned short   designated_port;	  /* (4.5.5.7)	 */
 	unsigned int     top_change_ack;	  /* (4.5.5.8)	 */
 	unsigned int     config_pending;	  /* (4.5.5.9)	 */
-	struct net_device *dev;	
+        bridge_id_t      ifmac; 
+        char             ifname[IFNAMSIZ]; /* Make life easier for brcfg */
+        struct net_device *dev;	
 	struct fdb *fdb;	/* head of per port fdb chain */
 } Port_data;
 
@@ -245,13 +257,14 @@
 struct br_stat {
 	unsigned int flags;
 	Bridge_data bridge_data;
-	Port_data port_data[No_of_ports];
 	unsigned int policy;
 	unsigned int exempt_protocols;
 	unsigned short protocols[BR_MAX_PROTOCOLS];
 	unsigned short prot_id[BR_MAX_PROT_STATS];	/* Protocol encountered */
 	unsigned int prot_counter[BR_MAX_PROT_STATS];	/* How many packets ? */
 	br_stats_counter packet_cnts;
+	unsigned int	num_ports;
+	Port_data port_data[BR_MAX_PORTS + 1];
 };
 
 /* defined flags for br_stat.flags */
@@ -274,7 +287,7 @@
 #define	BRCMD_SET_BRIDGE_PRIORITY	5	/* arg1 = priority */
 #define	BRCMD_SET_PORT_PRIORITY	6	/* arg1 = port, arg2 = priority */
 #define	BRCMD_SET_PATH_COST	7	/* arg1 = port, arg2 = cost */
-#define	BRCMD_DISPLAY_FDB	8	/* arg1 = port */
+#define	BRCMD_DISPLAY_FDB	8
 #define	BRCMD_ENABLE_DEBUG	9
 #define	BRCMD_DISABLE_DEBUG	10
 #define BRCMD_SET_POLICY	11	/* arg1 = default policy (1==bridge all) */
@@ -283,22 +296,34 @@
 #define BRCMD_DISABLE_PROT_STATS 14
 #define BRCMD_ZERO_PROT_STATS	15
 #define BRCMD_TOGGLE_STP	16
+#define BRCMD_IF_ENABLE		17	/* arg1 = if_index */
+#define BRCMD_IF_DISABLE	18	/* arg1 = if_index */
+#define BRCMD_SET_IF_PRIORITY	19	/* arg1 = if_index, arg2 = priority */
+#define	BRCMD_SET_IF_PATH_COST	20	/* arg1 = if_index, arg2 = cost */
 
 /* prototypes of exported bridging functions... */
 
+#ifdef __KERNEL__
 void br_init(void);
 int br_receive_frame(struct sk_buff *skb);	/* 3.5 */
 int br_tx_frame(struct sk_buff *skb);
+int brg_init(void);
 int br_ioctl(unsigned int cmd, void *arg);
-int br_protocol_ok(unsigned short protocol);
 void requeue_fdb(struct fdb *node, int new_port);
 
 struct fdb *br_avl_find_addr(unsigned char addr[6]);
 struct fdb *br_avl_insert (struct fdb * new_node);
 void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,int* len, off_t offset, int length);
 void br_avl_delete_by_port(int port);
+int br_call_bridge(struct sk_buff *skb, unsigned short type);
+void br_spacedevice_register(void);
+
 /* externs */
 
 extern struct br_stat br_stats;
 extern Port_data port_info[];
 
+#endif
+
+
+ 
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/ircomm_core.h linux/include/net/irda/ircomm_core.h
--- v2.3.34/linux/include/net/irda/ircomm_core.h	Wed Oct 27 16:34:12 1999
+++ linux/include/net/irda/ircomm_core.h	Tue Dec 21 10:17:31 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Jun  9 08:58:43 1999
- * Modified at:   Tue Oct  5 09:13:50 1999
+ * Modified at:   Mon Dec 13 11:52:29 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -102,9 +102,6 @@
 				  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;
-}
+#define ircomm_is_connected(self) (self->state == IRCOMM_CONN)
 
 #endif
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/ircomm_tty.h linux/include/net/irda/ircomm_tty.h
--- v2.3.34/linux/include/net/irda/ircomm_tty.h	Sun Nov  7 16:37:34 1999
+++ linux/include/net/irda/ircomm_tty.h	Tue Dec 21 10:17:31 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Jun  6 23:24:22 1999
- * Modified at:   Sun Oct 31 19:50:35 1999
+ * Modified at:   Sun Dec 12 15:57:38 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -48,21 +48,23 @@
  * IrCOMM TTY driver state
  */
 struct ircomm_tty_cb {
-	queue_t queue;
+	queue_t queue;            /* Must be first */
 	magic_t magic;
 
-	int state;
+	int state;                /* Connect state */
 
 	struct tty_struct *tty;
-	struct ircomm_cb *ircomm;
+	struct ircomm_cb *ircomm; /* IrCOMM layer instance */
 
-	struct sk_buff *tx_skb;
-	struct sk_buff *ctrl_skb;
+	struct sk_buff *tx_skb;   /* Transmit buffer */
+	struct sk_buff *ctrl_skb; /* Control data buffer */
 
 	/* Parameters */
-	struct ircomm_params session;
+	struct ircomm_params settings;
 
-	__u8 service_type;
+	__u8 service_type;        /* The service that we support */
+	int client;               /* True if we are a client */
+	LOCAL_FLOW flow;          /* IrTTP flow status */
 
 	int line;
 	__u32 flags;
@@ -73,11 +75,10 @@
 	__u32 saddr;
 	__u32 daddr;
 
-	__u32 max_data_size;
-	__u32 max_header_size;
-
-	struct iriap_cb *iriap;
+	__u32 max_data_size;   /* Max data we can transmit in one packet */
+	__u32 max_header_size; /* The amount of header space we must reserve */
 
+	struct iriap_cb *iriap; /* Instance used for querying remote IAS */
 	struct ias_object* obj;
 	int skey;
 	int ckey;
@@ -93,6 +94,7 @@
         unsigned short    close_delay;
         unsigned short    closing_wait; /* time to wait before closing */
 
+	long session;           /* Session of opening process */
 	long pgrp;		/* pgrp of opening process */
 	int  open_count;
 	int  blocked_open;	/* # of blocked opens */
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/ircomm_tty_attach.h linux/include/net/irda/ircomm_tty_attach.h
--- v2.3.34/linux/include/net/irda/ircomm_tty_attach.h	Mon Oct  4 15:49:30 1999
+++ linux/include/net/irda/ircomm_tty_attach.h	Tue Dec 21 10:17:31 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Jun  9 15:55:18 1999
- * Modified at:   Thu Sep  2 10:29:30 1999
+ * Modified at:   Fri Dec 10 21:04:55 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -90,4 +90,7 @@
 				   __u32 max_sdu_size,
 				   __u8 max_header_size, 
 				   struct sk_buff *skb);
-#endif
+int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self);
+void ircomm_tty_link_established(struct ircomm_tty_cb *self);
+
+#endif /* IRCOMM_TTY_ATTACH_H */
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/irda.h linux/include/net/irda/irda.h
--- v2.3.34/linux/include/net/irda/irda.h	Sun Nov  7 16:37:34 1999
+++ linux/include/net/irda/irda.h	Tue Dec 28 17:44:23 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irda.h
- * Version:       
+ * Version:       1.0
  * Description:   IrDA common include file for kernel internal use
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Sun Oct 31 14:45:20 1999
+ * Modified at:   Tue Dec 14 19:01:26 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -116,6 +116,9 @@
 	__u32 saddr;          /* my local address */
 	__u32 daddr;          /* peer address */
 
+	struct lsap_cb *lsap; /* LSAP used by Ultra */
+	__u8  pid;            /* Protocol IP (PID) used by Ultra */
+
 	struct tsap_cb *tsap; /* TSAP used by this connection */
 	__u8 dtsap_sel;       /* remote TSAP address */
 	__u8 stsap_sel;       /* local TSAP address */
@@ -132,12 +135,13 @@
 	__u32 ckey;           /* IrLMP client handle */
 	__u32 skey;           /* IrLMP service handle */
 
-	struct ias_object *ias_obj;
-	struct iriap_cb *iriap;
+	struct ias_object *ias_obj;   /* Our service name + lsap in IAS */
+	struct iriap_cb *iriap;	      /* Used to query remote IAS */
+	struct ias_value *ias_result; /* Used by getsockopt(IRLMP_IAS_QUERY) */
 
 	int nslots;           /* Number of slots to use for discovery */
 
-	int errno;
+	int errno;            /* status of the IAS query */
 
 	struct sock *sk;
 	wait_queue_head_t ias_wait;       /* Wait for LM-IAS answer */
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h
--- v2.3.34/linux/include/net/irda/irda_device.h	Tue Nov 23 22:42:21 1999
+++ linux/include/net/irda/irda_device.h	Mon Dec 27 15:52:23 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:   Tue Nov 16 12:54:01 1999
+ * Modified at:   Mon Dec 13 12:05:31 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -86,7 +86,6 @@
 	TASK_CALLBACK function;
 	TASK_CALLBACK finished;
 
-	/* struct net_device *dev; */
 	struct irda_task *parent;
 	struct timer_list timer;
 
@@ -97,11 +96,11 @@
 /* Dongle info */
 struct dongle_reg;
 typedef struct {
-	struct dongle_reg *issue; /* Registration info */
-	struct net_device *dev;   /* Device we are attached to */
-	__u32 speed;              /* Current speed */
-	
-	int busy;
+	struct dongle_reg *issue;     /* Registration info */
+	struct net_device *dev;           /* Device we are attached to */
+	struct irda_task *speed_task; /* Task handling speed change */
+	struct irda_task *reset_task; /* Task handling reset */
+	__u32 speed;                  /* Current speed */
 
 	/* Callbacks to the IrDA device driver */
 	int (*set_mode)(struct net_device *, int mode);
@@ -112,7 +111,7 @@
 
 /* Dongle registration info */
 struct dongle_reg {
-	queue_t q;        /* Must be first */
+	queue_t q;         /* Must be first */
 	IRDA_DONGLE type;
 
 	void (*open)(dongle_t *dongle, struct qos_info *qos);
@@ -175,10 +174,11 @@
 
 void setup_dma(int channel, char *buffer, int count, int mode);
 
+void irda_task_delete(struct irda_task *task);
 int  irda_task_kick(struct irda_task *task);
-int  irda_task_execute(void *instance, TASK_CALLBACK function, 
-		       TASK_CALLBACK finished, struct irda_task *parent, 
-		       void *param);
+struct irda_task *irda_task_execute(void *instance, TASK_CALLBACK function, 
+				    TASK_CALLBACK finished, 
+				    struct irda_task *parent, void *param);
 void irda_task_next_state(struct irda_task *task, TASK_STATE state);
 
 extern const char *infrared_mode[];
@@ -189,6 +189,14 @@
  *    Utility function for getting the minimum turnaround time out of 
  *    the skb, where it has been hidden in the cb field.
  */
+#define irda_get_mtt(skb) (                                                 \
+        IRDA_MIN(10000,                                                     \
+                  (((struct irda_skb_cb *) skb->cb)->magic == LAP_MAGIC) ?  \
+                          ((struct irda_skb_cb *)(skb->cb))->mtt : 10000    \
+                 )							    \
+)
+
+#if 0
 extern inline __u16 irda_get_mtt(struct sk_buff *skb)
 {
 	__u16 mtt;
@@ -202,6 +210,7 @@
 	
 	return mtt;
 }
+#endif
 
 /*
  * Function irda_get_speed (skb)
@@ -209,6 +218,12 @@
  *    Extact the speed this frame should be sent out with from the skb
  *
  */
+#define irda_get_speed(skb) (	                                        \
+	(((struct irda_skb_cb*) skb->cb)->magic == LAP_MAGIC) ? 	\
+                  ((struct irda_skb_cb *)(skb->cb))->speed : 9600 	\
+)
+
+#if 0
 extern inline __u32 irda_get_speed(struct sk_buff *skb)
 {
 	__u32 speed;
@@ -220,7 +235,8 @@
 
 	return speed;
 }
-
 #endif
+
+#endif /* IRDA_DEVICE_H */
 
 
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/iriap.h linux/include/net/irda/iriap.h
--- v2.3.34/linux/include/net/irda/iriap.h	Sun Nov  7 16:37:34 1999
+++ linux/include/net/irda/iriap.h	Tue Dec 21 10:17:31 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 Oct 31 15:51:32 1999
+ * Modified at:   Tue Dec 14 21:55:18 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -83,6 +83,7 @@
 	void *priv;                /* Used to identify client */
 
 	__u8 max_header_size;
+	__u32 max_data_size;
 	
 	struct timer_list watchdog_timer;
 };
@@ -90,7 +91,7 @@
 int  iriap_init(void);
 void iriap_cleanup(void);
 
-struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
+struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv, 
 			    CONFIRM_CALLBACK callback);
 void iriap_close(struct iriap_cb *self);
 
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/irias_object.h linux/include/net/irda/irias_object.h
--- v2.3.34/linux/include/net/irda/irias_object.h	Wed Oct 27 16:34:12 1999
+++ linux/include/net/irda/irias_object.h	Tue Dec 21 10:17:31 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct  1 22:49:50 1998
- * Modified at:   Tue Oct  5 10:45:21 1999
+ * Modified at:   Wed Dec 15 11:20:57 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -92,6 +92,7 @@
 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);
+struct ias_value *irias_new_missing_value(void);
 void irias_delete_value(struct ias_value *value);
 
 extern struct ias_value missing;
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/irlap.h linux/include/net/irda/irlap.h
--- v2.3.34/linux/include/net/irda/irlap.h	Tue Nov 23 22:42:21 1999
+++ linux/include/net/irda/irlap.h	Mon Dec 27 15:52:23 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:   Tue Nov 16 10:00:36 1999
+ * Modified at:   Fri Dec 10 13:21:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -36,6 +36,8 @@
 
 #include <net/irda/irlap_event.h>
 
+#define CONFIG_IRDA_DYNAMIC_WINDOW 1
+
 #define LAP_RELIABLE   1
 #define LAP_UNRELIABLE 0
 
@@ -115,7 +117,8 @@
 	int final_timeout;
 	int wd_timeout;
 
-	struct sk_buff_head tx_list;  /* Frames to be transmitted */
+	struct sk_buff_head txq;  /* Frames to be transmitted */
+	struct sk_buff_head txq_ultra;
 
  	__u8    caddr;        /* Connection address */
 	__u32   saddr;        /* Source device address */
@@ -131,7 +134,7 @@
 #ifdef CONFIG_IRDA_FAST_RR
 	int     fast_RR_timeout;
 	int     fast_RR;      
-#endif
+#endif /* CONFIG_IRDA_FAST_RR */
 	
 	int N1; /* N1 * F-timer = Negitiated link disconnect warning threshold */
 	int N2; /* N2 * F-timer = Negitiated link disconnect time */
@@ -141,13 +144,16 @@
 	int     remote_busy;
 	int     xmitflag;
 
-	__u8    vs;           /* Next frame to be sent */
-	__u8    vr;           /* Next frame to be received */
-	__u8    va;           /* Last frame acked */
- 	int     window;       /* Nr of I-frames allowed to send */
-	int     window_size;  /* Current negotiated window size */
-	__u32   window_bytes; /* Number of bytes allowed to send */
-	__u32   bytes_left;   /* Number of bytes allowed to transmit */
+	__u8    vs;            /* Next frame to be sent */
+	__u8    vr;            /* Next frame to be received */
+	__u8    va;            /* Last frame acked */
+ 	int     window;        /* Nr of I-frames allowed to send */
+	int     window_size;   /* Current negotiated window size */
+
+#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
+	__u32   line_capacity; /* Number of bytes allowed to send */
+	__u32   bytes_left;    /* Number of bytes still allowed to transmit */
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
 
 	struct sk_buff_head wx_list;
 
@@ -177,7 +183,7 @@
 #ifdef CONFIG_IRDA_COMPRESSION
 	struct irda_compressor compressor;
         struct irda_compressor decompressor;
-#endif
+#endif /* CONFIG_IRDA_COMPRESSION */
 };
 
 extern hashbin_t *irlap;
@@ -197,9 +203,13 @@
 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_data_indication(struct irlap_cb *, struct sk_buff *);
-void irlap_unit_data_indication(struct irlap_cb *, struct sk_buff *);
-void irlap_data_request(struct irlap_cb *, struct sk_buff *, int reliable);
+void irlap_data_indication(struct irlap_cb *, struct sk_buff *, int unreliable);
+void irlap_data_request(struct irlap_cb *, struct sk_buff *, int unreliable);
+
+#ifdef CONFIG_IRDA_ULTRA
+void irlap_unitdata_request(struct irlap_cb *, struct sk_buff *);
+void irlap_unitdata_indication(struct irlap_cb *, struct sk_buff *);
+#endif /* CONFIG_IRDA_ULTRA */
 
 void irlap_disconnect_request(struct irlap_cb *);
 void irlap_disconnect_indication(struct irlap_cb *, LAP_REASON reason);
@@ -227,10 +237,10 @@
 
 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_apply_connection_parameters(struct irlap_cb *self);
 void irlap_set_local_busy(struct irlap_cb *self, int status);
 
 #define IRLAP_GET_HEADER_SIZE(self) 2 /* Will be different when we get VFIR */
-#define IRLAP_GET_TX_QUEUE_LEN(self) skb_queue_len(&self->tx_list)
+#define IRLAP_GET_TX_QUEUE_LEN(self) skb_queue_len(&self->txq)
 
 #endif
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/irlap_event.h linux/include/net/irda/irlap_event.h
--- v2.3.34/linux/include/net/irda/irlap_event.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/irlap_event.h	Mon Dec 27 15:52:22 1999
@@ -7,7 +7,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Mon Aug 16 10:16:12 1999
+ * Modified at:   Wed Dec  8 10:49:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -70,6 +70,7 @@
 
 	/* Send events */
 	SEND_I_CMD,
+	SEND_UI_FRAME,
 
 	/* Receive events */
 	RECV_DISCOVERY_XID_CMD,
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/irlap_frame.h linux/include/net/irda/irlap_frame.h
--- v2.3.34/linux/include/net/irda/irlap_frame.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/irlap_frame.h	Mon Dec 27 15:52:23 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Mon Aug 23 09:38:46 1999
+ * Modified at:   Thu Dec  9 15:50:09 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997-1999 Dag Brattli <dagb@cs.uit.no>,
@@ -116,8 +116,6 @@
 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);
@@ -129,7 +127,8 @@
 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_ui_frame(struct irlap_cb *self, struct sk_buff *skb,
+			 __u8 caddr, int command);
 
 extern int irlap_insert_qos_negotiation_params(struct irlap_cb *self, 
 					       struct sk_buff *skb);
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/irlmp.h linux/include/net/irda/irlmp.h
--- v2.3.34/linux/include/net/irda/irlmp.h	Wed Oct 27 16:34:12 1999
+++ linux/include/net/irda/irlmp.h	Tue Dec 21 10:17:31 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Tue Oct  5 15:20:56 1999
+ * Modified at:   Fri Dec 10 13:23:01 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -42,17 +42,14 @@
 #define LSAP_MASK     0x7f
 #define LSAP_IAS      0x00
 #define LSAP_ANY      0xff
+#define LSAP_MAX      0x6f /* 0x70-0x7f are reserved */
+#define LSAP_CONNLESS 0x70 /* Connectionless LSAP, mostly used for Ultra */
 
 #define DEV_ADDR_ANY  0xffffffff
 
-/* Predefined LSAPs used by the various servers */
-#define TSAP_IRLAN    0x05
-#define LSAP_IRLPT    0x06
-#define TSAP_IROBEX   0x07
-#define TSAP_IRCOMM   0x08
-
 #define LMP_HEADER          2    /* Dest LSAP + Source LSAP */
 #define LMP_CONTROL_HEADER  4
+#define LMP_PID_HEADER      1    /* Used by Ultra */
 #define LMP_MAX_HEADER      (LMP_CONTROL_HEADER+LAP_MAX_HEADER)
 
 #define LM_MAX_CONNECTIONS  10
@@ -101,18 +98,20 @@
 	queue_t queue;      /* Must be first */
 	magic_t magic;
 
-	int   connected;
-	int   persistent;
-
-	__u8  slsap_sel;   /* Source (this) LSAP address */
-	__u8  dlsap_sel;   /* Destination LSAP address (if connected) */
+	int  connected;
+	int  persistent;
 
-	struct sk_buff *tmp_skb; /* Store skb here while connecting */
+	__u8 slsap_sel;   /* Source (this) LSAP address */
+	__u8 dlsap_sel;   /* Destination LSAP address (if connected) */
+#ifdef CONFIG_IRDA_ULTRA
+	__u8 pid;         /* Used by connectionless LSAP */
+#endif /* CONFIG_IRDA_ULTRA */
+	struct sk_buff *conn_skb; /* Store skb here while connecting */
 
 	struct timer_list watchdog_timer;
 
 	IRLMP_STATE     lsap_state;  /* Connection state */
-	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 */
@@ -122,15 +121,16 @@
  *  Information about each registred IrLAP layer
  */
 struct lap_cb {
-	queue_t queue;      /* Must be first */
+	queue_t queue; /* Must be first */
 	magic_t magic;
 
 	int reason;    /* LAP disconnect reason */
 
 	IRLMP_STATE lap_state;
 
-	struct irlap_cb *irlap;    /* Instance of IrLAP layer */
+	struct irlap_cb *irlap;   /* Instance of IrLAP layer */
 	hashbin_t *lsaps;         /* LSAP associated with this link */
+	int refcount;
 
 	__u8  caddr;  /* Connection address */
  	__u32 saddr;  /* Source device address */
@@ -185,7 +185,7 @@
 /* Prototype declarations */
 int  irlmp_init(void);
 void irlmp_cleanup(void);
-struct lsap_cb *irlmp_open_lsap( __u8 slsap, notify_t *notify);
+struct lsap_cb *irlmp_open_lsap(__u8 slsap, notify_t *notify, __u8 pid);
 void irlmp_close_lsap( struct lsap_cb *self);
 
 __u16 irlmp_service_to_hint(int service);
@@ -217,10 +217,16 @@
 void irlmp_do_discovery(int nslots);
 discovery_t *irlmp_get_discovery_response(void);
 
-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 *);
+int  irlmp_data_request(struct lsap_cb *, struct sk_buff *);
+void irlmp_data_indication(struct lsap_cb *, struct sk_buff *);
+
+int  irlmp_udata_request(struct lsap_cb *, struct sk_buff *);
+void irlmp_udata_indication(struct lsap_cb *, struct sk_buff *);
+
+#ifdef CONFIG_IRDA_ULTRA
+int  irlmp_connless_data_request(struct lsap_cb *, struct sk_buff *);
+void irlmp_connless_data_indication(struct lsap_cb *, struct sk_buff *);
+#endif /* CONFIG_IRDA_ULTRA */
 
 void irlmp_status_request(void);
 void irlmp_status_indication(LINK_STATUS link, LOCK_STATUS lock);
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/irlmp_frame.h linux/include/net/irda/irlmp_frame.h
--- v2.3.34/linux/include/net/irda/irlmp_frame.h	Thu Apr 15 05:42:41 1999
+++ linux/include/net/irda/irlmp_frame.h	Tue Dec 21 10:17:31 1999
@@ -6,10 +6,11 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Tue Apr  6 17:12:57 1999
+ * Modified at:   Fri Dec 10 13:21:53 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 
@@ -42,8 +43,12 @@
 				int expedited, struct sk_buff *skb);
 void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap, 
 			__u8 opcode, struct sk_buff *skb);
-void irlmp_link_data_indication(struct lap_cb *, int reliable, 
-				struct sk_buff *);
+void irlmp_link_data_indication(struct lap_cb *, struct sk_buff *, 
+				int unreliable);
+#ifdef CONFIG_IRDA_ULTRA
+void irlmp_link_unitdata_indication(struct lap_cb *, struct sk_buff *);
+#endif /* CONFIG_IRDA_ULTRA */
+
 void irlmp_link_connect_indication(struct lap_cb *, __u32 saddr, __u32 daddr,
 				   struct qos_info *qos, struct sk_buff *skb);
 void irlmp_link_connect_request(__u32 daddr);
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/irport.h linux/include/net/irda/irport.h
--- v2.3.34/linux/include/net/irda/irport.h	Tue Nov 23 22:42:21 1999
+++ linux/include/net/irda/irport.h	Tue Dec 21 10:17:31 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:   Sat Nov 13 23:48:55 1999
+ * Modified at:   Sat Dec 11 14:34:18 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -54,7 +54,7 @@
 	struct net_device *netdev; /* Yes! we are some kind of netdevice */
 	struct net_device_stats stats;
 
-	struct irlap_cb    *irlap; /* The link layer we are binded to */
+	struct irlap_cb *irlap;    /* The link layer we are attached to */
 
 	struct chipio_t io;        /* IrDA controller information */
 	struct iobuff_t tx_buff;   /* Transmit buffer */
@@ -65,19 +65,24 @@
 
  	__u32 flags;               /* Interface flags */
 	__u32 new_speed;
+	int mode;
 
 	spinlock_t lock;           /* For serializing operations */
 
-	int mode;
+	/* For piggyback drivers */
+	void *priv;                
+	void (*change_speed)(void *priv, __u32 speed);
+	void (*interrupt)(int irq, void *dev_id, struct pt_regs *regs);
 };
 
-void irport_start(struct irport_cb *self, int iobase);
-void irport_stop(struct irport_cb *self, int iobase);
-int  irport_probe(int iobase);
-
-int irport_change_speed(struct irda_task *task);
-void __irport_change_speed(struct irport_cb *self, __u32 speed);
+struct irport_cb *irport_open(int i, unsigned int iobase, unsigned int irq);
+int  irport_close(struct irport_cb *self);
+void irport_start(struct irport_cb *self);
+void irport_stop(struct irport_cb *self);
+void irport_change_speed(void *priv, __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);
+int  irport_net_open(struct net_device *dev);
+int  irport_net_close(struct net_device *dev);
 
-#endif
+#endif /* IRPORT_H */
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/irttp.h linux/include/net/irda/irttp.h
--- v2.3.34/linux/include/net/irda/irttp.h	Wed Oct 27 16:34:12 1999
+++ linux/include/net/irda/irttp.h	Tue Dec 21 10:17:31 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:   Tue Oct  5 15:17:14 1999
+ * Modified at:   Sun Dec 12 13:09:07 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -44,16 +44,16 @@
 
 #define DEFAULT_INITIAL_CREDIT 14
 
-#define LOW_THRESHOLD           4
-#define HIGH_THRESHOLD         10
+#define TTP_LOW_THRESHOLD       4
+#define TTP_HIGH_THRESHOLD     10
 #define TTP_MAX_QUEUE          14
 
 /* Some priorities for disconnect requests */
 #define P_NORMAL    0
 #define P_HIGH      1
 
-#define SAR_DISABLE 0
-#define SAR_UNBOUND 0xffffffff
+#define TTP_SAR_DISABLE 0
+#define TTP_SAR_UNBOUND 0xffffffff
 
 /* Parameters */
 #define TTP_MAX_SDU_SIZE 0x01
@@ -141,7 +141,7 @@
 	return irlmp_get_daddr(self->lsap);
 }
 
-static __inline __u32 irttp_get_max_seq_size(struct tsap_cb *self)
+static __inline __u32 irttp_get_max_seg_size(struct tsap_cb *self)
 {
 	return self->max_seg_size;
 }
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/irtty.h linux/include/net/irda/irtty.h
--- v2.3.34/linux/include/net/irda/irtty.h	Tue Nov 23 22:42:21 1999
+++ linux/include/net/irda/irtty.h	Tue Dec 21 10:17:31 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:   Fri Nov  5 10:46:51 1999
+ * Modified at:   Sun Nov 21 21:19:35 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *  
  *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
@@ -49,6 +49,7 @@
 	magic_t magic;
 
 	struct net_device *netdev; /* Yes! we are some kind of netdevice */
+	struct irda_task *task;
 	struct net_device_stats stats;
 
 	struct tty_struct  *tty;
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/parameters.h linux/include/net/irda/parameters.h
--- v2.3.34/linux/include/net/irda/parameters.h	Tue Aug 31 17:29:15 1999
+++ linux/include/net/irda/parameters.h	Tue Dec 21 10:17:31 1999
@@ -6,7 +6,7 @@
  * 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 at:   Mon Dec 13 11:51:59 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -99,10 +99,7 @@
 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);
-}
+#define irda_param_insert_byte(buf,pi,pv) irda_param_pack(buf,"bbb",pi,1,pv)
 
 #endif /* IRDA_PARAMS_H */
 
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/qos.h linux/include/net/irda/qos.h
--- v2.3.34/linux/include/net/irda/qos.h	Wed Oct 27 16:34:12 1999
+++ linux/include/net/irda/qos.h	Tue Dec 28 17:44:21 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Sep 19 23:21:09 1997
- * Modified at:   Tue Oct  5 11:51:37 1999
+ * Modified at:   Thu Dec  2 13:51:54 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -87,17 +87,21 @@
 };
 
 extern __u32 baud_rates[];
-extern __u32 data_size[];
-extern __u32 min_turn_time[];
+extern __u32 data_sizes[];
+extern __u32 min_turn_times[];
 extern __u32 add_bofs[];
-extern __u32 compression[];
+extern __u32 compressions[];
 
 void irda_init_max_qos_capabilies(struct qos_info *qos);
 void irda_qos_compute_intersection(struct qos_info *, struct qos_info *);
 
+__u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time);
+__u32 irlap_requested_line_capacity(struct qos_info *qos);
+__u32 irlap_min_turn_time_in_bytes(__u32 speed, __u32 min_turn_time);
+
 int msb_index(__u16 byte);
-__u32 byte_value(__u8 byte, __u32 *array);
 int value_index(__u32 value, __u32 *array);
+__u32 byte_value(__u8 byte, __u32 *array);
 __u32 index_value(int index, __u32 *array);
 
 void irda_qos_bits_to_value(struct qos_info *qos);
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/smc-ircc.h linux/include/net/irda/smc-ircc.h
--- v2.3.34/linux/include/net/irda/smc-ircc.h	Sun Nov  7 16:37:34 1999
+++ linux/include/net/irda/smc-ircc.h	Tue Dec 21 10:17:31 1999
@@ -83,28 +83,28 @@
 #define UART_SCE_CFGB	0x01
 #define UART_FIFO_THRESHOLD	0x02
 
-#define UART_CFGA_AUX_IR		0x01<<7
+#define UART_CFGA_AUX_IR	0x01<<7
 #define UART_CFGA_HALF_DUPLEX	0x01<<2
 #define UART_CFGA_TX_POLARITY	0x01<<1
 #define UART_CFGA_RX_POLARITY	0x01
 
 #define UART_CFGA_COM		0x00<<3
 #define UART_CFGA_IRDA_SIR_A	0x01<<3
-#define UART_CFGA_ASK_SIR		0x02<<3
+#define UART_CFGA_ASK_SIR	0x02<<3
 #define UART_CFGA_IRDA_SIR_B	0x03<<3
 #define UART_CFGA_IRDA_HDLC 	0x04<<3
 #define UART_CFGA_IRDA_4PPM 	0x05<<3
-#define UART_CFGA_CONSUMER		0x06<<3
-#define UART_CFGA_RAW_IR		0x07<<3
+#define UART_CFGA_CONSUMER	0x06<<3
+#define UART_CFGA_RAW_IR	0x07<<3
 #define UART_CFGA_OTHER		0x08<<3
 
 #define UART_IR_HDLC			0x04
 #define UART_IR_4PPM			0x01
 #define UART_IR_CONSUMER		0x02
 
-#define UART_CFGB_LOOPBACK		0x01<<5
+#define UART_CFGB_LOOPBACK      0x01<<5
 #define UART_CFGB_LPBCK_TX_CRC	0x01<<4
-#define UART_CFGB_NOWAIT		0x01<<3
+#define UART_CFGB_NOWAIT	0x01<<3
 #define UART_CFGB_STRING_MOVE	0x01<<2
 #define UART_CFGB_DMA_BURST 	0x01<<1
 #define UART_CFGB_DMA_ENABLE	0x01
@@ -112,7 +112,7 @@
 #define UART_CFGB_COM		0x00<<6
 #define UART_CFGB_IR		0x01<<6
 #define UART_CFGB_AUX		0x02<<6
-#define UART_CFGB_INACTIVE		0x03<<6
+#define UART_CFGB_INACTIVE	0x03<<6
 
 /* Register block 2 - Consumer IR - not used */
 
@@ -125,13 +125,13 @@
 #define UART_INTERFACE	0x04   /* low 4 = DMA, high 4 = IRQ */
 
 /* Register block 4 - IrDA */
-#define UART_CONTROL        0x00
-#define UART_BOF_COUNT_LO      0x01
-#define UART_BRICKWALL_CNT_LO 0x02
-#define UART_BRICKWALL_TX_CNT_HI   0x03
-#define UART_TX_SIZE_LO   0x04
-#define UART_RX_SIZE_HI   0x05
-#define UART_RX_SIZE_LO   0x06
+#define UART_CONTROL             0x00
+#define UART_BOF_COUNT_LO        0x01
+#define UART_BRICKWALL_CNT_LO    0x02
+#define UART_BRICKWALL_TX_CNT_HI 0x03
+#define UART_TX_SIZE_LO          0x04
+#define UART_RX_SIZE_HI          0x05
+#define UART_RX_SIZE_LO          0x06
 
 #define UART_1152     0x01<<7
 #define UART_CRC      0x01<<6
@@ -152,8 +152,6 @@
 /* Private data for each instance */
 struct ircc_cb {
 	struct net_device *netdev; /* Yes! we are some kind of netdevice */
-	struct net_device_stats stats;
-	
 	struct irlap_cb    *irlap; /* The link layer we are binded to */
 	
 	struct chipio_t io;        /* IrDA controller information */
@@ -161,16 +159,15 @@
 	struct iobuff_t rx_buff;   /* Receive buffer */
 	struct qos_info qos;       /* QoS capabilities for this device */
 
-	struct irport_cb irport;
+	struct irport_cb *irport;
 	
+	__u32 new_speed;
 	__u32 flags;               /* Interface flags */
 
 	struct st_fifo st_fifo;
 
 	int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
 	int tx_len;              /* Number of frames in tx_buff */
-
-
 };
 
 #endif
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/w83977af.h linux/include/net/irda/w83977af.h
--- v2.3.34/linux/include/net/irda/w83977af.h	Thu Dec 17 09:01:03 1998
+++ linux/include/net/irda/w83977af.h	Tue Dec 21 10:17:31 1999
@@ -1,54 +1,53 @@
 #ifndef W83977AF_H
 #define W83977AF_H
 
-#define W977_EFER 0x370
-#define W977_EFIR 0x370
-#define W977_EFDR 0x371
+#define W977_EFIO_BASE 0x370
+#define W977_EFIO2_BASE 0x3f0
 #define W977_DEVICE_IR 0x06
 
 
 /*
  * Enter extended function mode
  */
-static inline void w977_efm_enter(void)
+static inline void w977_efm_enter(unsigned int efio)
 {
-        outb(0x87, W977_EFER);
-        outb(0x87, W977_EFER);
+        outb(0x87, efio);
+        outb(0x87, efio);
 }
 
 /*
  * Select a device to configure 
  */
 
-static inline void w977_select_device(__u8 devnum)
+static inline void w977_select_device(__u8 devnum, unsigned int efio)
 {
-	outb(0x07, W977_EFIR);
-	outb(devnum, W977_EFDR);
+	outb(0x07, efio);
+	outb(devnum, efio+1);
 } 
 
 /* 
  * Write a byte to a register
  */
-static inline void w977_write_reg(__u8 reg, __u8 value)
+static inline void w977_write_reg(__u8 reg, __u8 value, unsigned int efio)
 {
-	outb(reg, W977_EFIR);
-	outb(value, W977_EFDR);
+	outb(reg, efio);
+	outb(value, efio+1);
 }
 
 /*
  * read a byte from a register
  */
-static inline __u8 w977_read_reg(__u8 reg)
+static inline __u8 w977_read_reg(__u8 reg, unsigned int efio)
 {
-	outb(reg, W977_EFIR);
-	return inb(W977_EFDR);
+	outb(reg, efio);
+	return inb(efio+1);
 }
 
 /*
  * Exit extended function mode
  */
-static inline void w977_efm_exit(void)
+static inline void w977_efm_exit(unsigned int efio)
 {
-	outb(0xAA, W977_EFER);
+	outb(0xAA, efio);
 }
 #endif
diff -u --recursive --new-file v2.3.34/linux/include/net/irda/wrapper.h linux/include/net/irda/wrapper.h
--- v2.3.34/linux/include/net/irda/wrapper.h	Sun Nov  7 16:37:34 1999
+++ linux/include/net/irda/wrapper.h	Tue Dec 21 10:17:31 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:   Sat Oct 30 16:29:01 1999
+ * Modified at:   Thu Nov  4 14:25:54 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.34/linux/include/pcmcia/cs.h linux/include/pcmcia/cs.h
--- v2.3.34/linux/include/pcmcia/cs.h	Mon Dec 20 18:48:22 1999
+++ linux/include/pcmcia/cs.h	Tue Dec 21 10:53:27 1999
@@ -402,14 +402,6 @@
 #ifdef __KERNEL__
 
 /*
- *  Calls to set up low-level "Socket Services" drivers
- */
-
-typedef int (*ss_entry_t)(u_int sock, u_int cmd, void *arg);
-extern int register_ss_entry(int nsock, ss_entry_t entry);
-extern void unregister_ss_entry(ss_entry_t entry);
-
-/*
  *  The main Card Services entry point
  */
 
diff -u --recursive --new-file v2.3.34/linux/include/pcmcia/ss.h linux/include/pcmcia/ss.h
--- v2.3.34/linux/include/pcmcia/ss.h	Thu Nov 11 20:11:54 1999
+++ linux/include/pcmcia/ss.h	Tue Dec 21 20:22:14 1999
@@ -30,12 +30,6 @@
 #ifndef _LINUX_SS_H
 #define _LINUX_SS_H
 
-/* For RegisterCallback */
-typedef struct ss_callback_t {
-    void	(*handler)(void *info, u_int events);
-    void	*info;
-} ss_callback_t;
-
 /* Definitions for card status flags for GetStatus */
 #define SS_WRPROT	0x0001
 #define SS_CARDLOCK	0x0002
@@ -120,11 +114,28 @@
     u_int	start, stop;
 } cb_bridge_map;
 
-enum ss_service {
-    SS_RegisterCallback, SS_InquireSocket,
-    SS_GetStatus, SS_GetSocket, SS_SetSocket,
-    SS_GetIOMap, SS_SetIOMap, SS_GetMemMap, SS_SetMemMap,
-    SS_GetBridge, SS_SetBridge, SS_ProcSetup
+/*
+ * Socket operations.
+ */
+struct pccard_operations {
+	int (*register_callback)(unsigned int sock, void (*handler)(void *, unsigned int), void * info);
+	int (*inquire_socket)(unsigned int sock, socket_cap_t *cap);
+	int (*get_status)(unsigned int sock, u_int *value);
+	int (*get_socket)(unsigned int sock, socket_state_t *state);
+	int (*set_socket)(unsigned int sock, socket_state_t *state);
+	int (*get_io_map)(unsigned int sock, struct pccard_io_map *io);
+	int (*set_io_map)(unsigned int sock, struct pccard_io_map *io);
+	int (*get_mem_map)(unsigned int sock, struct pccard_mem_map *mem);
+	int (*set_mem_map)(unsigned int sock, struct pccard_mem_map *mem);
+	int (*get_bridge)(unsigned int sock, struct cb_bridge_map *m);
+	int (*set_bridge)(unsigned int sock, struct cb_bridge_map *m);
+	void (*proc_setup)(unsigned int sock, struct proc_dir_entry *base);
 };
+
+/*
+ *  Calls to set up low-level "Socket Services" drivers
+ */
+extern int register_ss_entry(int nsock, struct pccard_operations *ops);
+extern void unregister_ss_entry(struct pccard_operations *ops);
 
 #endif /* _LINUX_SS_H */
diff -u --recursive --new-file v2.3.34/linux/include/video/sbusfb.h linux/include/video/sbusfb.h
--- v2.3.34/linux/include/video/sbusfb.h	Tue Aug 31 17:29:15 1999
+++ linux/include/video/sbusfb.h	Mon Dec 20 22:06:42 1999
@@ -90,7 +90,8 @@
 	struct display disp;
 	struct display_switch dispsw;
 	struct fbtype type;
-	struct linux_sbus_device *sbdp;
+	struct sbus_dev *sbdp;
+	spinlock_t lock;
 	int prom_node, prom_parent;
 	union {
 		struct fb_info_creator ffb;
diff -u --recursive --new-file v2.3.34/linux/init/main.c linux/init/main.c
--- v2.3.34/linux/init/main.c	Tue Nov 23 22:42:21 1999
+++ linux/init/main.c	Fri Dec 24 13:06:05 1999
@@ -484,6 +484,7 @@
 	kmem_cache_init();
 	sti();
 	calibrate_delay();
+#if 0000
 #ifdef CONFIG_BLK_DEV_INITRD
 	// FIXME, use the bootmem.h interface.
 	if (initrd_start && !initrd_below_start_ok && initrd_start < memory_start) {
@@ -492,6 +493,7 @@
 		initrd_start = 0;
 	}
 #endif
+#endif /* 0000 */
 	mem_init();
 	kmem_cache_sizes_init();
 #ifdef CONFIG_PROC_FS
diff -u --recursive --new-file v2.3.34/linux/kernel/panic.c linux/kernel/panic.c
--- v2.3.34/linux/kernel/panic.c	Wed Dec 15 10:43:17 1999
+++ linux/kernel/panic.c	Mon Dec 20 22:05:10 1999
@@ -72,7 +72,12 @@
 		machine_restart(NULL);
 	}
 #ifdef __sparc__
-	printk("Press L1-A to return to the boot prom\n");
+	{
+		extern int stop_a_enabled;
+		/* Make sure the user can actually press L1-A */
+		stop_a_enabled = 1;
+		printk("Press L1-A to return to the boot prom\n");
+	}
 #endif
 	sti();
 	for(;;) {
diff -u --recursive --new-file v2.3.34/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.3.34/linux/kernel/sysctl.c	Tue Dec  7 09:32:52 1999
+++ linux/kernel/sysctl.c	Mon Dec 20 22:05:10 1999
@@ -60,6 +60,7 @@
 
 #ifdef __sparc__
 extern char reboot_command [];
+extern int stop_a_enabled;
 #endif
 #ifdef __powerpc__
 extern unsigned long htab_reclaim_on, zero_paged_on, powersave_nap;
@@ -185,6 +186,8 @@
 #ifdef __sparc__
 	{KERN_SPARC_REBOOT, "reboot-cmd", reboot_command,
 	 256, 0644, NULL, &proc_dostring, &sysctl_string },
+	{KERN_SPARC_STOP_A, "stop-a", &stop_a_enabled, sizeof (int),
+	 0644, NULL, &proc_dointvec},
 #endif
 #ifdef __powerpc__
 	{KERN_PPC_HTABRECLAIM, "htab-reclaim", &htab_reclaim_on, sizeof(int),
diff -u --recursive --new-file v2.3.34/linux/mm/bootmem.c linux/mm/bootmem.c
--- v2.3.34/linux/mm/bootmem.c	Tue Dec 14 01:27:24 1999
+++ linux/mm/bootmem.c	Mon Dec 20 21:59:45 1999
@@ -45,6 +45,7 @@
 {
 	unsigned long mapsize = ((end - start)+7)/8;
 
+	mapsize = (mapsize + (sizeof(long) - 1UL)) & ~(sizeof(long) - 1UL);
 	bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
 	bdata->node_boot_start = (start << PAGE_SHIFT);
 	bdata->node_low_pfn = end;
diff -u --recursive --new-file v2.3.34/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.3.34/linux/mm/vmscan.c	Tue Dec  7 09:32:52 1999
+++ linux/mm/vmscan.c	Mon Dec 20 21:59:45 1999
@@ -97,6 +97,7 @@
 	 * some real work in the future in "shrink_mmap()".
 	 */
 	if (!pte_dirty(pte)) {
+		flush_cache_page(vma, address);
 		pte_clear(page_table);
 		goto drop_pte;
 	}
diff -u --recursive --new-file v2.3.34/linux/net/Config.in linux/net/Config.in
--- v2.3.34/linux/net/Config.in	Fri Oct 15 15:25:14 1999
+++ linux/net/Config.in	Tue Dec 21 10:17:31 1999
@@ -62,7 +62,10 @@
    tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25
    tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB
    bool 'Bridging (EXPERIMENTAL)' CONFIG_BRIDGE
-   bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC
+   if [ "$CONFIG_BRIDGE" != "n" ]; then
+       int '  Maximum number of bridged interfaces' CONFIG_BRIDGE_NUM_PORTS 8
+   fi
+bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC
 #   if [ "$CONFIG_LLC" = "y" ]; then
 #      bool '  Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI
 #   fi
diff -u --recursive --new-file v2.3.34/linux/net/bridge/br.c linux/net/bridge/br.c
--- v2.3.34/linux/net/bridge/br.c	Tue Nov 23 22:42:21 1999
+++ linux/net/bridge/br.c	Tue Dec 21 10:17:31 1999
@@ -40,10 +40,19 @@
  *			so blame me first if its broken ;)
  *
  *	Robert Pintarelli:	fixed bug in bpdu time values
+ *
+ *      Matthew Grant:  start ports disabled.  
+ *                      auto-promiscuous mode on port enable/disable
+ *                      fleshed out interface event handling, interfaces 
+ *                        now register with bridge on module load as well as ifup
+ *                      port control ioctls with ifindex support
+ *                      brg0 logical ethernet interface
+ *                      reworked brcfg to take interface arguments
+ *                      added support for changing the hardware address
+ *                      generally made bridge a lot more usable.
  *	
  *	Todo:
- *		Don't bring up devices automatically. Start ports disabled
- *	and use a netlink notifier so a daemon can maintain the bridge
+ *	Use a netlink notifier so a daemon can maintain the bridge
  *	port group (could we also do multiple groups ????).
  *		A nice /proc file interface.
  *		Put the path costs in the port info and devices.
@@ -52,6 +61,7 @@
  *	
  */
  
+#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -60,10 +70,13 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
+#include <linux/malloc.h>
 #include <linux/string.h>
 #include <linux/net.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/ip.h>
@@ -71,6 +84,7 @@
 #include <linux/init.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
+#include <linux/rtnetlink.h>
 #include <net/br.h>
 #include <linux/proc_fs.h>
 
@@ -144,11 +158,20 @@
 static int br_flood(struct sk_buff *skb, int port);
 static int br_drop(struct sk_buff *skb);
 static int br_learn(struct sk_buff *skb, int port);	/* 3.8 */
+static int br_protocol_ok(unsigned short protocol);
+static int br_find_port(int ifindex);
+static void br_get_ifnames(void);
+static int brg_rx(struct sk_buff *skb, int port);
 
 static unsigned char bridge_ula[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
 static Bridge_data     bridge_info;			  /* (4.5.3)	 */
 Port_data       port_info[All_ports];		  /* (4.5.5)	 */
 
+/* MAG: Maximum port registered - used to speed up flooding and to make
+ * have a large ports array more efficient
+ */
+static int max_port_used = 0; 
+
 /* JRP: fdb cache 1/port save kmalloc/kfree on every frame */
 struct fdb	*newfdb[All_ports];
 int allocated_fdb_cnt = 0;
@@ -189,6 +212,30 @@
 	0
 };
 
+
+/* 
+ * the following data is for the bridge network device
+ */
+struct brg_if {
+  struct net_device dev;
+  char name[IFNAMSIZ];
+};
+static struct brg_if brg_if;
+
+/* 
+ * Here to save linkage? problems
+ */
+
+static inline int find_port(struct net_device *dev)
+{
+	int i;
+
+	for (i = One; i <= No_of_ports; i++)
+		if (port_info[i].dev == dev)
+			return(i);
+	return(0);
+}
+
 /*
  * Implementation of Protocol specific bridging
  *
@@ -201,7 +248,7 @@
 
 /* Checks if that protocol type is to be bridged */
 
-int br_protocol_ok(unsigned short protocol)
+static int inline br_protocol_ok(unsigned short protocol)
 {
 	unsigned x;
 	
@@ -830,12 +877,19 @@
 
 	return len;
 }
+
 void __init br_init(void)
 {						  /* (4.8.1)	 */
 	int port_no;
 
-	printk(KERN_INFO "NET4: Ethernet Bridge 005 for NET4.0\n");
+	printk(KERN_INFO "NET4: Ethernet Bridge 006 for NET4.0\n");
 
+	/* Set up brg device information */
+	bridge_info.instance = 0;
+	brg_init();
+
+	max_port_used = 0;
+	
 	/*
 	 * Form initial topology change time.
 	 * The topology change timer is only used if this is the root bridge.
@@ -865,8 +919,8 @@
 	stop_topology_change_timer();
 	memset(newfdb, 0, sizeof(newfdb));
 	for (port_no = One; port_no <= No_of_ports; port_no++) {	/* (4.8.1.4) */
-		/* initial state = Enable */
-		user_port_state[port_no] = ~Disabled;
+		/* initial state = Disable */
+		user_port_state[port_no] = Disabled;
 		port_priority[port_no] = 128;
 		br_init_port(port_no);
 		disable_port(port_no);
@@ -1194,7 +1248,7 @@
   	memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
  
   	if (br_stats.flags & BR_DEBUG)
- 		printk("send_%s_bpdu: port %i src %02x:%02x:%02x:%02x:%02x:%02x\n",
+ 		printk(KERN_DEBUG "send_%s_bpdu: port %i src %02x:%02x:%02x:%02x:%02x:%02x\n",
  			pdu_name,
   			port_no,
   			eth->h_source[0],
@@ -1295,6 +1349,9 @@
 	if (dev->flags & IFF_LOOPBACK)
 		return(NOTIFY_DONE);
 
+	if (dev == &brg_if.dev)
+	  return(NOTIFY_DONE);	/* Don't attach the brg device to a port! */
+	
 	switch (event) 
 	{
 		case NETDEV_DOWN:
@@ -1324,6 +1381,9 @@
 				{
 					port_info[i].dev = dev;
 					port_info[i].port_id = i;
+					dev->bridge_port_id = i;
+					if( i > max_port_used ) 
+						max_port_used = i;
 					/* set bridge addr from 1st device addr */
 					if (((htonl(bridge_info.bridge_id.BRIDGE_ID[0])&0xffff) == 0) &&
 						(bridge_info.bridge_id.BRIDGE_ID[1] == 0)) 
@@ -1333,7 +1393,10 @@
 							bridge_info.bridge_id.BRIDGE_PRIORITY = htons(32768);
 						set_bridge_priority(&bridge_info.bridge_id);
 					}
+					/* Add local MAC address */
 					br_add_local_mac(dev->dev_addr);
+					/* Save MAC address for latter change address events */
+					memcpy(port_info[i].ifmac.BRIDGE_ID_ULA, dev->dev_addr, 6);
 					if((br_stats.flags & BR_UP) &&
 				   		(user_port_state[i] != Disabled)) 
 				   	{
@@ -1351,19 +1414,116 @@
 				}
 			}
 			break;
+	        case NETDEV_REGISTER:
+		        if (br_stats.flags & BR_DEBUG) 
+				printk(KERN_DEBUG "br_device_event: NETDEV_REGISTER...\n");
+			/* printk(KERN_ERR "br_device_event: NETDEV_REGISTER...\n"); */
+			/* printk(KERN_ERR "br_device_event: dev->type: 0x%X\n", dev->type); */
+			/* Only handle ethernet ports */
+			if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_LOOPBACK)
+				return NOTIFY_DONE;
+			/* printk(KERN_ERR "br_device_event: Looking for port...\n"); */
+			for (i = One; i <= No_of_ports; i++) 
+			{
+				if (port_info[i].dev == NULL || port_info[i].dev == dev) 
+				{
+				        /* printk(KERN_ERR "br_device_event: Found port %d\n", i); */
+					port_info[i].dev = dev;
+					port_info[i].port_id = i;
+					dev->bridge_port_id = i;
+					if( i > max_port_used )
+						max_port_used = i;
+					/* handle local MAC address minuplations */
+					br_add_local_mac(dev->dev_addr);
+					memcpy(port_info[i].ifmac.BRIDGE_ID_ULA, dev->dev_addr, 6);
+					return NOTIFY_DONE;
+					break;
+				}
+			}
+			break;
 		case NETDEV_UNREGISTER:
 			if (br_stats.flags & BR_DEBUG)
 				printk(KERN_DEBUG "br_device_event: NETDEV_UNREGISTER...\n");
                         i = find_port(dev);
                         if (i > 0) {
 				br_avl_delete_by_port(i);
+				memset(port_info[i].ifmac.BRIDGE_ID_ULA, 0, 6);
 				port_info[i].dev = NULL;
 			}
 			break;
+		case NETDEV_CHANGEADDR:
+			if (br_stats.flags & BR_DEBUG)
+				printk(KERN_DEBUG "br_device_event: NETDEV_CHANGEADDR...\n");
+                        i = find_port(dev);
+                        if (i <= 0)  
+			  break;
+			if (memcmp(port_info[i].ifmac.BRIDGE_ID_ULA, dev->dev_addr, 6) != 0)
+			  break; /* Don't worry about a change of hardware broadcast address! */
+			if (dev->start) {
+			  printk(KERN_CRIT "br_device_event: NETDEV_CHANGEADDR on busy device %s - FIX DRIVER!\n", 
+				 dev->name);
+			/*  return NOTIFY_BAD;  It SHOULD be this, but I want to be friendly... */
+			  return NOTIFY_DONE;
+			}
+			br_avl_delete_by_port(i);
+			memset(port_info[i].ifmac.BRIDGE_ID_ULA, 0, 6);
+			break;
 	}
 	return NOTIFY_DONE;
 }
 
+/* Routine to loop over device list and register 
+ * interfaces to bridge.  Called from last part of net_dev_init just before
+ * bootp/rarp interface setup
+ */
+void br_spacedevice_register(void) 
+{
+	struct net_device *dev;
+	for( dev = dev_base; dev != NULL; dev = dev->next)
+	{
+		br_device_event(NULL, NETDEV_REGISTER, dev);
+	}
+}	
+
+
+/* This is for SPEED in the kernel in net_bh.c */
+
+int br_call_bridge(struct sk_buff *skb, unsigned short type)
+{
+	int port;
+	struct net_device *dev;
+  
+#if 0  /* Checked first in handle_bridge to save expense of function call */ 
+	if(!(br_stats.flags & BR_UP))
+		return 0;
+#endif
+  
+	dev = skb->dev;
+	port = dev->bridge_port_id;
+
+	if(!port)
+		return 0;
+
+	/* Sanity - make sure we are not leaping off into fairy space! */
+	if ( port < 0 || port > max_port_used || port_info[port].dev != dev) {
+		if (net_ratelimit())
+			printk(KERN_CRIT "br_call_bridge: device %s has invalid port ID %d!\n",
+				dev->name,
+				dev->bridge_port_id);
+		return 0;
+	}
+
+	if(user_port_state[port] == Disabled)
+		return 0;
+  
+	if (!br_protocol_ok(ntohs(type)))
+		return 0;
+
+	return 1;
+
+}
+
+
 /*
  * following routine is called when a frame is received
  * from an interface, it returns 1 when it consumes the
@@ -1375,6 +1535,7 @@
 	int port;
 	Port_data  *p;
 	struct ethhdr *eth;
+	struct net_device *dev;
 	
 	/* sanity */
 	if (!skb) {
@@ -1382,17 +1543,27 @@
 		return(1);
 	}
 
+	dev = skb->dev;
+
 	skb->pkt_bridged = IS_BRIDGED;
 
 	/* check for loopback */
-	if (skb->dev->flags & IFF_LOOPBACK)
+	if (dev->flags & IFF_LOOPBACK)
 		return 0 ;
 
-	port = find_port(skb->dev);
+#if 0
+	port = find_port(dev);
+#else
+	port = dev->bridge_port_id;
+#endif
 	
 	if(!port)
 		return 0;
 	
+	/* Hand off to brg_rx BEFORE we screw up the skb */
+	if(brg_rx(skb, port))
+	  return(1);
+
 	skb->nh.raw = skb->mac.raw;
 	eth = skb->mac.ethernet;
 	p = &port_info[port];
@@ -1501,7 +1672,7 @@
 	eth = skb->mac.ethernet;
 	port = 0;	/* an impossible port (locally generated) */	
 	if (br_stats.flags & BR_DEBUG)
-		printk("br_tx_fr : port %i src %02x:%02x:%02x:%02x:%02x:%02x"
+		printk(KERN_DEBUG "br_tx_fr : port %i src %02x:%02x:%02x:%02x:%02x:%02x"
 	  		" dest %02x:%02x:%02x:%02x:%02x:%02x\n", 
 			port,
 			eth->h_source[0],
@@ -1739,7 +1910,7 @@
 				/* timer expired, invalidate entry */
 				f->flags &= ~FDB_ENT_VALID;
 				if (br_stats.flags & BR_DEBUG)
-					printk("fdb entry expired...\n");
+					printk(KERN_DEBUG "fdb entry expired...\n");
 				/*
 				 *	Send flood and drop original
 				 */
@@ -1781,7 +1952,7 @@
 				/* timer expired, invalidate entry */
 				f->flags &= ~FDB_ENT_VALID;
 				if (br_stats.flags & BR_DEBUG)
-					printk("fdb entry expired...\n");
+					printk(KERN_DEBUG "fdb entry expired...\n");
 				++br_stats_cnt.drop_same_port_aged;
 			}
 			else ++br_stats_cnt.drop_same_port;
@@ -1808,6 +1979,9 @@
 	{
 		if (i == port)	/* don't send back where we got it */
 			continue;
+		if (i > max_port_used)
+			/* Don't go scanning empty port entries */
+			break;
 		if (port_info[i].state == Forwarding) 
 		{
 			nskb = skb_clone(skb, GFP_ATOMIC);
@@ -1820,7 +1994,7 @@
 			/* To get here we must have done ARP already,
 			   or have a received valid MAC header */
 			
-/*			printk("Flood to port %d\n",i);*/
+/*			printk(KERN_DEBUG "Flood to port %d\n",i);*/
 			nskb->nh.raw = nskb->data + ETH_HLEN;
 			nskb->priority = 1;
 			dev_queue_xmit(nskb);
@@ -1829,16 +2003,6 @@
 	return(0);
 }
 
-static int find_port(struct net_device *dev)
-{
-	int i;
-
-	for (i = One; i <= No_of_ports; i++)
-		if (port_info[i].dev == dev)
-			return(i);
-	return(0);
-}
-
 /*
  *	FIXME: This needs to come from the device structs, eg for
  *	10,100,1Gbit ethernet.
@@ -1945,17 +2109,58 @@
 	return fdbis;
 }
 
+
+/* Fill in interface names in port_info structure
+ */
+static void br_get_ifnames(void) {
+  int i;
+
+  for(i=One;i<=No_of_ports; i++) {
+    /* memset IS needed.  Kernel strncpy does NOT NULL terminate strings when limit
+       reached */
+    memset(port_info[i].ifname, 0, IFNAMSIZ); 
+    if( port_info[i].dev == 0 )
+      continue;
+    strncpy(port_info[i].ifname, port_info[i].dev->name, IFNAMSIZ-1);
+    /* Being paranoid */
+    port_info[i].ifname[IFNAMSIZ-1] = '\0';
+  }
+}
+
+/* Given an interface index, loop over port array to see if configured.  If
+   so, return port number, otherwise error */ 
+static int br_find_port(int ifindex) 
+{
+  int i;
+  
+  for(i=1; i <= No_of_ports; i++) {
+    if (port_info[i].dev == 0)
+      continue;
+    if (port_info[i].dev->ifindex == ifindex)
+      return(i);
+  }
+  
+  return -EUNATCH;  /* Tell me if this is incorrect error code for this case */
+} 
+
+
 int br_ioctl(unsigned int cmd, void *arg)
 {
-	int err, i;
+	int err, i, ifflags;
 	struct br_cf bcf;
 	bridge_id_t new_id;
-
+	struct net_device *dev;
+	
 	switch(cmd)
 	{
 		case SIOCGIFBR:	/* get bridging control blocks */
 			memcpy(&br_stats.bridge_data, &bridge_info, sizeof(Bridge_data));
-			memcpy(&br_stats.port_data, &port_info, sizeof(Port_data)*No_of_ports);
+
+			/* Fill in interface names in port_info*/
+			br_get_ifnames();
+			
+			br_stats.num_ports = No_of_ports;
+			memcpy(&br_stats.port_data, &port_info, sizeof(Port_data)*All_ports);
 
 			err = copy_to_user(arg, &br_stats, sizeof(struct br_stat));
 			if (err)
@@ -2021,16 +2226,28 @@
 					}
 					br_stats.flags ^= BR_STP_DISABLED;
 					break;
+			        case BRCMD_IF_ENABLE:
+				        bcf.arg1 = br_find_port(bcf.arg1);
+					if (bcf.arg1 < 0)
+						return(bcf.arg1);
 				case BRCMD_PORT_ENABLE:
 					if (port_info[bcf.arg1].dev == 0)
 						return(-EINVAL);
 					if (user_port_state[bcf.arg1] != Disabled)
 						return(-EALREADY);
 					printk(KERN_DEBUG "br: enabling port %i\n",bcf.arg1);
+					dev = port_info[bcf.arg1].dev;
+					ifflags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI))
+					  |(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI)); 
+					dev_change_flags(dev, ifflags|IFF_PROMISC);
 					user_port_state[bcf.arg1] = ~Disabled;
 					if(br_stats.flags & BR_UP)
 						enable_port(bcf.arg1);
 					break;
+			        case BRCMD_IF_DISABLE:
+				        bcf.arg1 = br_find_port(bcf.arg1);
+					if (bcf.arg1 < 0)
+						return(bcf.arg1);
 				case BRCMD_PORT_DISABLE:
 					if (port_info[bcf.arg1].dev == 0)
 						return(-EINVAL);
@@ -2040,12 +2257,20 @@
 					user_port_state[bcf.arg1] = Disabled;
 					if(br_stats.flags & BR_UP)
 						disable_port(bcf.arg1);
+					dev = port_info[bcf.arg1].dev;
+					ifflags = (dev->flags&~(IFF_PROMISC|IFF_ALLMULTI))
+					  |(dev->gflags&(IFF_PROMISC|IFF_ALLMULTI)); 
+					dev_change_flags(port_info[bcf.arg1].dev, ifflags & ~IFF_PROMISC);
 					break;
 				case BRCMD_SET_BRIDGE_PRIORITY:
 					new_id = bridge_info.bridge_id;
 					new_id.BRIDGE_PRIORITY = htons(bcf.arg1);
 					set_bridge_priority(&new_id);
 					break;
+			        case BRCMD_SET_IF_PRIORITY:
+				        bcf.arg1 = br_find_port(bcf.arg1);
+					if (bcf.arg1 < 0)
+						return(bcf.arg1);
 				case BRCMD_SET_PORT_PRIORITY:
 					if((port_info[bcf.arg1].dev == 0)
 					    || (bcf.arg2 & ~0xff))
@@ -2053,6 +2278,10 @@
 					port_priority[bcf.arg1] = bcf.arg2;
 					set_port_priority(bcf.arg1);
 					break;
+			        case BRCMD_SET_IF_PATH_COST:
+				        bcf.arg1 = br_find_port(bcf.arg1);
+					if (bcf.arg1 < 0)
+						return(bcf.arg1);
 				case BRCMD_SET_PATH_COST:
 					if (port_info[bcf.arg1].dev == 0)
 						return(-EINVAL);
@@ -2134,3 +2363,377 @@
 	}
 	return(0);
 }
+
+
+
+
+/* --------------------------------------------------------------------------------
+ *
+ *
+ *  Bridge network device here for future modularization - device structures
+ *  must be 'static' inside bridge instance
+ *  Modelled after sch_teql.c
+ * 
+ */
+
+
+
+/*
+ *	Index to functions.
+ */
+
+int	    brg_probe(struct net_device *dev);
+static int  brg_open(struct net_device *dev);
+static int  brg_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int  brg_close(struct net_device *dev);
+static struct net_device_stats *brg_get_stats(struct net_device *dev);
+static void brg_set_multicast_list(struct net_device *dev);
+
+/*
+ *	Board-specific info in dev->priv.
+ */
+
+struct net_local
+{
+	__u32		groups;
+	struct net_device_stats stats;
+};
+
+
+
+
+/*
+ *	To call this a probe is a bit misleading, however for real
+ *	hardware it would have to check what was present.
+ */
+ 
+int __init brg_probe(struct net_device *dev)
+{
+  unsigned int bogomips;
+  struct timeval utime;
+
+  printk(KERN_INFO "%s: network interface for Ethernet Bridge 006/NET4.0\n", dev->name);
+
+  /*
+   *	Initialize the device structure.
+   */
+  
+  dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+  if (dev->priv == NULL)
+    return -ENOMEM;
+  memset(dev->priv, 0, sizeof(struct net_local));
+
+  /* Set up MAC address based on BogoMIPs figure for first CPU and time
+   */ 
+  bogomips = (boot_cpu_data.loops_per_sec+2500)/500000 ;
+  get_fast_time(&utime);
+
+  /* Ummmm....  YES! */
+  dev->dev_addr[0] = '\xFE';
+  dev->dev_addr[1] = '\xFD';
+  dev->dev_addr[2] = (bridge_info.instance & 0x0F) << 4;
+  dev->dev_addr[2] |= ((utime.tv_sec & 0x000F0000) >> 16);
+  dev->dev_addr[3] = bogomips & 0xFF;
+  dev->dev_addr[4] = (utime.tv_sec & 0x0000FF00) >> 8;
+  dev->dev_addr[5] = (utime.tv_sec & 0x000000FF);
+  
+  printk(KERN_INFO "%s: generated MAC address %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n", 
+	 dev->name,
+	 dev->dev_addr[0],
+	 dev->dev_addr[1],
+	 dev->dev_addr[2],
+	 dev->dev_addr[3],
+	 dev->dev_addr[4],
+	 dev->dev_addr[5]);
+
+  
+  printk(KERN_INFO "%s: attached to bridge instance %lu\n", dev->name, dev->base_addr);
+
+  /*
+   *	The brg specific entries in the device structure.
+   */
+
+  dev->open = brg_open;
+  dev->hard_start_xmit = brg_start_xmit;
+  dev->stop = brg_close;
+  dev->get_stats = brg_get_stats;
+  dev->set_multicast_list = brg_set_multicast_list;
+
+  /*
+   *	Setup the generic properties
+   */
+
+  ether_setup(dev);
+
+  dev->tx_queue_len = 0;
+
+  return 0;
+}
+
+/*
+ *	Open/initialize the board.
+ */
+
+static int brg_open(struct net_device *dev)
+{
+        if (br_stats.flags & BR_DEBUG)
+		printk(KERN_DEBUG "%s: Doing brg_open()...", dev->name);
+
+	if (memcmp(dev->dev_addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0)
+	  return -EFAULT;
+
+	dev->start = 1;
+	dev->tbusy = 0;
+	return 0;
+}
+
+static unsigned brg_mc_hash(__u8 *dest)
+{
+	unsigned idx = 0;
+	idx ^= dest[0];
+	idx ^= dest[1];
+	idx ^= dest[2];
+	idx ^= dest[3];
+	idx ^= dest[4];
+	idx ^= dest[5];
+	return 1U << (idx&0x1F);
+}
+
+static void brg_set_multicast_list(struct net_device *dev)
+{
+	unsigned groups = ~0;
+	struct net_local *lp = (struct net_local *)dev->priv;
+
+	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
+		struct dev_mc_list *dmi;
+
+		groups = brg_mc_hash(dev->broadcast);
+
+		for (dmi=dev->mc_list; dmi; dmi=dmi->next) {
+			if (dmi->dmi_addrlen != 6)
+				continue;
+			groups |= brg_mc_hash(dmi->dmi_addr);
+		}
+	}
+	lp->groups = groups;
+}
+
+/*
+ *	We transmit by throwing the packet at the bridge.
+ */
+ 
+static int brg_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct net_local *lp = (struct net_local *)dev->priv;
+	struct ethhdr *eth = (struct ethhdr*)skb->data;
+	int port;
+
+	/* Deal with the bridge being disabled */
+	if(!(br_stats.flags & BR_UP)) {
+		/* Either this */
+		/* lp->stats.tx_errors++; */ /* this condition is NOT an error */
+		/* or this  (implied by RFC 2233) */
+		lp->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	lp->stats.tx_bytes+=skb->len;
+	lp->stats.tx_packets++;
+
+#if 0
+	++br_stats_cnt.port_not_disable;
+#endif
+	skb->mac.raw = skb->nh.raw = skb->data;
+	eth = skb->mac.ethernet;
+	port = 0;	/* an impossible port (locally generated) */	
+
+	 if (br_stats.flags & BR_DEBUG)
+		printk(KERN_DEBUG "%s: brg_start_xmit - src %02x:%02x:%02x:%02x:%02x:%02x"
+	  		" dest %02x:%02x:%02x:%02x:%02x:%02x\n", 
+		       dev->name,
+		       eth->h_source[0],
+		       eth->h_source[1],
+		       eth->h_source[2],
+		       eth->h_source[3],
+		       eth->h_source[4],
+		       eth->h_source[5],
+		       eth->h_dest[0],
+		       eth->h_dest[1],
+		       eth->h_dest[2],
+		       eth->h_dest[3],
+		       eth->h_dest[4],
+		       eth->h_dest[5]);
+	
+	/* Forward the packet ! */
+	if(br_forward(skb, port))
+	  return(0);
+    
+	/* Throw packet initially */
+	dev_kfree_skb(skb);
+	return 0;
+}
+
+
+/*
+ *	The typical workload of the driver:
+ *	Handle the ether interface interrupts.
+ *
+ *	(In this case handle the packets posted from the bridge)
+ */
+
+static int brg_rx(struct sk_buff *skb, int port)
+{
+        struct net_device *dev = &brg_if.dev;
+	struct net_local *lp = (struct net_local *)dev->priv;
+	struct ethhdr *eth = (struct ethhdr*)(skb->data);
+	int len = skb->len;
+	int clone = 0;
+
+	if (br_stats.flags & BR_DEBUG)
+		printk(KERN_DEBUG "%s: brg_rx()\n", dev->name);
+
+	/* Get out of here if the bridge interface is not up
+	 */
+	if(!(dev->flags & IFF_UP))
+	  return(0);
+	
+	/* Check that the port that this thing came off is in the forwarding state 
+	 * We sould only listen to the same address scope we will transmit to.
+	 */
+	if(port_info[port].state != Forwarding)
+	  return(0);
+
+	/* Is this for us? - broadcast/mulitcast/promiscuous packets need cloning,
+         * with uni-cast we eat the packet
+	 */
+	clone = 0;
+	if (dev->flags & IFF_PROMISC) {
+	  clone = 1;
+	}
+	else if (eth->h_dest[0]&1) {
+	  if (!(dev->flags&(IFF_ALLMULTI))
+	      && !(brg_mc_hash(eth->h_dest)&lp->groups))
+	    return(0);
+	  clone = 1;
+	}
+	else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN) != 0) {
+	  return(0);
+	}
+
+	/* Clone things here - we want to be transparent before we check packet data 
+	 * integrity
+	 */
+	if(clone) {
+	  struct sk_buff *skb2 = skb;
+	  skb = skb_clone(skb2, GFP_ATOMIC);
+	  if (skb == NULL) {
+	    return(0);
+	  }
+	  
+	}
+
+	/* Check packet length 
+	 */
+	if (len < 16) {
+		printk(KERN_DEBUG "%s : rx len = %d\n", dev->name, len);
+		kfree_skb(skb);
+		return(!clone);
+	}
+
+	if (br_stats.flags & BR_DEBUG)
+	  printk(KERN_DEBUG "%s: brg_rx - src %02x:%02x:%02x:%02x:%02x:%02x"
+		 " dest %02x:%02x:%02x:%02x:%02x:%02x\n", 
+		 dev->name,
+		 eth->h_source[0],
+		 eth->h_source[1],
+		 eth->h_source[2],
+		 eth->h_source[3],
+		 eth->h_source[4],
+		 eth->h_source[5],
+		 eth->h_dest[0],
+		 eth->h_dest[1],
+		 eth->h_dest[2],
+		 eth->h_dest[3],
+		 eth->h_dest[4],
+		 eth->h_dest[5]);
+
+	/* Do it */
+	skb->pkt_type = PACKET_HOST;
+	skb->dev = dev;
+	skb->protocol=eth_type_trans(skb,dev);
+	memset(skb->cb, 0, sizeof(skb->cb));
+	lp->stats.rx_packets++;
+	lp->stats.rx_bytes+=len;
+	netif_rx(skb);
+	return(!clone);
+}
+
+static int brg_close(struct net_device *dev)
+{
+	if (br_stats.flags & BR_DEBUG)
+		printk(KERN_DEBUG "%s: Shutting down.\n", dev->name);
+
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	return 0;
+}
+
+static struct net_device_stats *brg_get_stats(struct net_device *dev)
+{
+	struct net_local *lp = (struct net_local *)dev->priv;
+	return &lp->stats;
+}
+
+/* 
+ *      
+ */
+
+int __init brg_init(void)
+{
+        int err;
+
+	memset(&brg_if, 0, sizeof(brg_if));
+
+        rtnl_lock();
+
+	brg_if.dev.base_addr = bridge_info.instance;
+	sprintf (brg_if.name, "brg%d", bridge_info.instance);
+	brg_if.dev.name = (void*)&brg_if.name;
+        if(dev_get(brg_if.name)) {
+               printk(KERN_INFO "%s already loaded.\n", brg_if.name);
+	       return -EBUSY;
+	}
+        brg_if.dev.init = brg_probe;
+
+        err = register_netdevice(&brg_if.dev);
+        rtnl_unlock();
+        return err;
+}
+
+
+#if 0				/* Its here if we ever need it... */
+#ifdef MODULE
+
+void cleanup_module(void)
+{
+
+  /* 
+   * Unregister the device
+   */
+  rtnl_lock();
+  unregister_netdevice(&the_master.dev);
+  rtnl_unlock();
+
+  /*
+   *	Free up the private structure.
+   */
+  
+  kfree(brg_if.dev.priv);
+  brg_if.dev.priv = NULL;	/* gets re-allocated by brg_probe */
+}
+
+#endif /* MODULE */
+
+#endif
diff -u --recursive --new-file v2.3.34/linux/net/bridge/br_tree.c linux/net/bridge/br_tree.c
--- v2.3.34/linux/net/bridge/br_tree.c	Sun Mar  7 15:25:23 1999
+++ linux/net/bridge/br_tree.c	Tue Dec 21 10:17:31 1999
@@ -492,7 +492,8 @@
         port_info[port].fdb = NULL;
 
         /* remove the local mac too */
-        next = br_avl_find_addr(port_info[port].dev->dev_addr);
+/*        next = br_avl_find_addr(port_info[port].dev->dev_addr); */
+        next = br_avl_find_addr(port_info[port].ifmac.BRIDGE_ID_ULA);
         if (next != NULL)
                 br_avl_remove(next);
 
diff -u --recursive --new-file v2.3.34/linux/net/core/dev.c linux/net/core/dev.c
--- v2.3.34/linux/net/core/dev.c	Mon Dec 20 18:48:22 1999
+++ linux/net/core/dev.c	Thu Dec 23 00:08:44 1999
@@ -55,7 +55,7 @@
  *		Adam Sulmicki   :	Bug Fix : Network Device Unload
  *					A network device unload needs to purge
  *					the backlog queue.
- *	Paul Rusty Russel	:	SIOCSIFNAME
+ *	Paul Rusty Russell	:	SIOCSIFNAME
  */
 
 #include <asm/uaccess.h>
@@ -860,7 +860,11 @@
 #ifdef CONFIG_BRIDGE
 static inline void handle_bridge(struct sk_buff *skb, unsigned short type)
 {
-	if (br_stats.flags & BR_UP && br_protocol_ok(ntohs(type)))
+	/* 
+	 * The br_stats.flags is checked here to save the expense of a 
+	 * function call.
+	 */
+	if ((br_stats.flags & BR_UP) && br_call_bridge(skb, type))
 	{
 		/*
 		 *	We pass the bridge a complete frame. This means
@@ -884,7 +888,6 @@
 }
 #endif
 
-
 /*
  *	When we are called the queue is ready to grab, the interrupts are
  *	on and hardware can interrupt and queue to the receive queue as we
@@ -2094,6 +2097,13 @@
 
 	dst_init();
 	dev_mcast_init();
+
+#ifdef CONFIG_BRIDGE
+	/*
+	 * Register any statically linked ethernet devices with the bridge
+	 */
+	br_spacedevice_register();
+#endif
 
 	/*
 	 *	Initialise network devices
diff -u --recursive --new-file v2.3.34/linux/net/core/skbuff.c linux/net/core/skbuff.c
--- v2.3.34/linux/net/core/skbuff.c	Fri Oct 22 13:21:55 1999
+++ linux/net/core/skbuff.c	Wed Dec 22 19:55:38 1999
@@ -4,7 +4,7 @@
  *	Authors:	Alan Cox <iiitac@pyr.swan.ac.uk>
  *			Florian La Roche <rzsfl@rz.uni-sb.de>
  *
- *	Version:	$Id: skbuff.c,v 1.60 1999/08/23 07:02:01 davem Exp $
+ *	Version:	$Id: skbuff.c,v 1.62 1999/12/23 02:13:42 davem Exp $
  *
  *	Fixes:	
  *		Alan Cox	:	Fixed the worst of the load balancer bugs.
@@ -275,14 +275,48 @@
 	return n;
 }
 
+static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
+{
+	/*
+	 *	Shift between the two data areas in bytes
+	 */
+	unsigned long offset = new->data - old->data;
+
+	new->list=NULL;
+	new->sk=NULL;
+	new->dev=old->dev;
+	new->rx_dev=NULL;
+	new->priority=old->priority;
+	new->protocol=old->protocol;
+	new->dst=dst_clone(old->dst);
+	new->h.raw=old->h.raw+offset;
+	new->nh.raw=old->nh.raw+offset;
+	new->mac.raw=old->mac.raw+offset;
+	memcpy(new->cb, old->cb, sizeof(old->cb));
+	new->used=old->used;
+	new->is_clone=0;
+	atomic_set(&new->users, 1);
+	new->pkt_type=old->pkt_type;
+	new->stamp=old->stamp;
+	new->destructor = NULL;
+	new->security=old->security;
+#ifdef CONFIG_NETFILTER
+	new->nfmark=old->nfmark;
+	new->nfreason=old->nfreason;
+	new->nfcache=old->nfcache;
+#ifdef CONFIG_NETFILTER_DEBUG
+	new->nf_debug=old->nf_debug;
+#endif
+#endif
+}
+
 /*
  *	This is slower, and copies the whole data area 
  */
  
-struct sk_buff *skb_copy(struct sk_buff *skb, int gfp_mask)
+struct sk_buff *skb_copy(const struct sk_buff *skb, int gfp_mask)
 {
 	struct sk_buff *n;
-	unsigned long offset;
 
 	/*
 	 *	Allocate the copy buffer
@@ -292,12 +326,6 @@
 	if(n==NULL)
 		return NULL;
 
-	/*
-	 *	Shift between the two data areas in bytes
-	 */
-	 
-	offset=n->head-skb->head;
-
 	/* Set the data pointer */
 	skb_reserve(n,skb->data-skb->head);
 	/* Set the tail pointer and length */
@@ -305,86 +333,35 @@
 	/* Copy the bytes */
 	memcpy(n->head,skb->head,skb->end-skb->head);
 	n->csum = skb->csum;
-	n->list=NULL;
-	n->sk=NULL;
-	n->dev=skb->dev;
-	n->rx_dev=NULL;
-	n->priority=skb->priority;
-	n->protocol=skb->protocol;
-	n->dst=dst_clone(skb->dst);
-	n->h.raw=skb->h.raw+offset;
-	n->nh.raw=skb->nh.raw+offset;
-	n->mac.raw=skb->mac.raw+offset;
-	memcpy(n->cb, skb->cb, sizeof(skb->cb));
-	n->used=skb->used;
-	n->is_clone=0;
-	atomic_set(&n->users, 1);
-	n->pkt_type=skb->pkt_type;
-	n->stamp=skb->stamp;
-	n->destructor = NULL;
-	n->security=skb->security;
-#ifdef CONFIG_NETFILTER
-	n->nfmark=skb->nfmark;
-	n->nfreason=skb->nfreason;
-	n->nfcache=skb->nfcache;
-#ifdef CONFIG_NETFILTER_DEBUG
-	n->nf_debug=skb->nf_debug;
-#endif
-#endif
+	copy_skb_header(n, skb);
+
 	return n;
 }
 
-struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, int newheadroom)
+struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
+				int newheadroom,
+				int newtailroom,
+				int gfp_mask)
 {
 	struct sk_buff *n;
-	unsigned long offset;
 
 	/*
 	 *	Allocate the copy buffer
 	 */
  	 
-	n=alloc_skb((skb->end-skb->data)+newheadroom, GFP_ATOMIC);
+	n=alloc_skb(newheadroom + (skb->tail - skb->data) + newtailroom,
+		    gfp_mask);
 	if(n==NULL)
 		return NULL;
 
 	skb_reserve(n,newheadroom);
 
-	/*
-	 *	Shift between the two data areas in bytes
-	 */
-	 
-	offset=n->data-skb->data;
-
 	/* Set the tail pointer and length */
 	skb_put(n,skb->len);
-	/* Copy the bytes */
-	memcpy(n->data,skb->data,skb->len);
-	n->list=NULL;
-	n->sk=NULL;
-	n->priority=skb->priority;
-	n->protocol=skb->protocol;
-	n->dev=skb->dev;
-	n->rx_dev=NULL;
-	n->dst=dst_clone(skb->dst);
-	n->h.raw=skb->h.raw+offset;
-	n->nh.raw=skb->nh.raw+offset;
-	n->mac.raw=skb->mac.raw+offset;
-	memcpy(n->cb, skb->cb, sizeof(skb->cb));
-	n->used=skb->used;
-	n->is_clone=0;
-	atomic_set(&n->users, 1);
-	n->pkt_type=skb->pkt_type;
-	n->stamp=skb->stamp;
-	n->destructor = NULL;
-	n->security=skb->security;
-#ifdef CONFIG_NETFILTER
-	n->nfmark=skb->nfmark;
-	n->nfreason=skb->nfreason;
-	n->nfcache=skb->nfcache;
-#ifdef CONFIG_NETFILTER_DEBUG
-	n->nf_debug=skb->nf_debug;
-#endif
-#endif
+	/* Copy the bytes: data pointers must point to same data. */
+	memcpy(n->data - skb_headroom(skb), skb->head, skb->end-skb->head);
+
+	copy_skb_header(n, skb);
 	return n;
 }
 
diff -u --recursive --new-file v2.3.34/linux/net/core/sock.c linux/net/core/sock.c
--- v2.3.34/linux/net/core/sock.c	Mon Oct 11 15:38:15 1999
+++ linux/net/core/sock.c	Wed Dec 22 19:55:38 1999
@@ -7,7 +7,7 @@
  *		handler for protocols to use and generic option handler.
  *
  *
- * Version:	$Id: sock.c,v 1.86 1999/09/01 08:11:49 davem Exp $
+ * Version:	$Id: sock.c,v 1.87 1999/11/23 08:56:59 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.34/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.3.34/linux/net/ipv4/af_inet.c	Mon Dec 20 18:48:22 1999
+++ linux/net/ipv4/af_inet.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *
  *		PF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.97 1999/09/08 03:46:46 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.100 1999/12/21 04:05:02 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.34/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.3.34/linux/net/ipv4/arp.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv4/arp.c	Wed Dec 22 19:55:38 1999
@@ -1,6 +1,6 @@
 /* linux/net/inet/arp.c
  *
- * Version:	$Id: arp.c,v 1.81 1999/08/30 10:17:05 davem Exp $
+ * Version:	$Id: arp.c,v 1.83 1999/12/15 22:39:03 davem Exp $
  *
  * Copyright (C) 1994 by Florian  La Roche
  *
diff -u --recursive --new-file v2.3.34/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v2.3.34/linux/net/ipv4/fib_frontend.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv4/fib_frontend.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *
  *		IPv4 Forwarding Information Base: FIB frontend.
  *
- * Version:	$Id: fib_frontend.c,v 1.19 1999/08/31 07:03:23 davem Exp $
+ * Version:	$Id: fib_frontend.c,v 1.21 1999/12/15 22:39:07 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
diff -u --recursive --new-file v2.3.34/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.3.34/linux/net/ipv4/icmp.c	Tue Aug 31 17:29:15 1999
+++ linux/net/ipv4/icmp.c	Wed Dec 22 19:55:38 1999
@@ -3,7 +3,7 @@
  *	
  *		Alan Cox, <alan@redhat.com>
  *
- *	Version: $Id: icmp.c,v 1.61 1999/08/31 07:03:33 davem Exp $
+ *	Version: $Id: icmp.c,v 1.62 1999/12/23 01:43:37 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -483,7 +483,7 @@
 	unsigned long csum;
 
 	if (offset) {
-		icmp_param->csum=csum_partial_copy(icmp_param->data_ptr+offset-sizeof(struct icmphdr), 
+		icmp_param->csum=csum_partial_copy_nocheck(icmp_param->data_ptr+offset-sizeof(struct icmphdr), 
 				to, fraglen,icmp_param->csum);
 		return 0;
 	}
@@ -493,10 +493,10 @@
 	 *	the other fragments first, so that we get the checksum
 	 *	for the whole packet here.
 	 */
-	csum = csum_partial_copy((void *)&icmp_param->icmph,
+	csum = csum_partial_copy_nocheck((void *)&icmp_param->icmph,
 		to, sizeof(struct icmphdr), 
 		icmp_param->csum);
-	csum = csum_partial_copy(icmp_param->data_ptr,
+	csum = csum_partial_copy_nocheck(icmp_param->data_ptr,
 		to+sizeof(struct icmphdr),
 		fraglen-sizeof(struct icmphdr), csum);
 	icmph=(struct icmphdr *)to;
diff -u --recursive --new-file v2.3.34/linux/net/ipv4/igmp.c linux/net/ipv4/igmp.c
--- v2.3.34/linux/net/ipv4/igmp.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv4/igmp.c	Wed Dec 22 19:55:38 1999
@@ -8,7 +8,7 @@
  *	the older version didn't come out right using gcc 2.5.8, the newer one
  *	seems to fall out with gcc 2.6.2.
  *
- *	Version: $Id: igmp.c,v 1.34 1999/08/20 11:05:12 davem Exp $
+ *	Version: $Id: igmp.c,v 1.35 1999/12/15 22:39:10 davem Exp $
  *
  *	Authors:
  *		Alan Cox <Alan.Cox@linux.org>
diff -u --recursive --new-file v2.3.34/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- v2.3.34/linux/net/ipv4/ip_output.c	Mon Dec 20 18:48:22 1999
+++ linux/net/ipv4/ip_output.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *
  *		The Internet Protocol (IP) output module.
  *
- * Version:	$Id: ip_output.c,v 1.72 1999/09/07 02:31:15 davem Exp $
+ * Version:	$Id: ip_output.c,v 1.75 1999/12/21 04:05:04 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.34/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v2.3.34/linux/net/ipv4/ipmr.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv4/ipmr.c	Wed Dec 22 19:55:38 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.46 1999/08/31 07:03:44 davem Exp $
+ *	Version: $Id: ipmr.c,v 1.48 1999/12/15 22:39:16 davem Exp $
  *
  *	Fixes:
  *	Michael Chastain	:	Incorrect size of copying.
diff -u --recursive --new-file v2.3.34/linux/net/ipv4/proc.c linux/net/ipv4/proc.c
--- v2.3.34/linux/net/ipv4/proc.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv4/proc.c	Wed Dec 22 19:55:38 1999
@@ -7,7 +7,7 @@
  *		PROC file system.  It is mainly used for debugging and
  *		statistics.
  *
- * Version:	$Id: proc.c,v 1.36 1999/07/02 11:26:34 davem Exp $
+ * Version:	$Id: proc.c,v 1.37 1999/12/15 22:39:19 davem Exp $
  *
  * Authors:	Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
diff -u --recursive --new-file v2.3.34/linux/net/ipv4/raw.c linux/net/ipv4/raw.c
--- v2.3.34/linux/net/ipv4/raw.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv4/raw.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *
  *		RAW - implementation of IP "raw" sockets.
  *
- * Version:	$Id: raw.c,v 1.43 1999/08/20 11:05:57 davem Exp $
+ * Version:	$Id: raw.c,v 1.44 1999/12/15 22:39:21 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.34/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.3.34/linux/net/ipv4/route.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv4/route.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *
  *		ROUTE - implementation of the IP router.
  *
- * Version:	$Id: route.c,v 1.72 1999/08/30 10:17:12 davem Exp $
+ * Version:	$Id: route.c,v 1.75 1999/12/23 01:41:44 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -736,7 +736,7 @@
 					goto do_next;
 				}
 
-				rt_del(hash, rt);
+				rt_del(hash, rth);
 				if (!rt_intern_hash(hash, rt, &rt))
 					ip_rt_put(rt);
 				goto do_next;
diff -u --recursive --new-file v2.3.34/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.3.34/linux/net/ipv4/tcp.c	Mon Oct 11 15:38:15 1999
+++ linux/net/ipv4/tcp.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.151 1999/09/07 02:31:21 davem Exp $
+ * Version:	$Id: tcp.c,v 1.152 1999/11/23 08:57:03 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.34/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.3.34/linux/net/ipv4/tcp_input.c	Tue Dec 14 01:27:24 1999
+++ linux/net/ipv4/tcp_input.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.173 1999/09/07 02:31:27 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.176 1999/12/20 05:19:46 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.34/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.3.34/linux/net/ipv4/tcp_ipv4.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv4/tcp_ipv4.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.189 1999/09/07 02:31:33 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.192 1999/12/23 02:04:50 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -528,7 +528,10 @@
 	read_lock(&tcp_lhash_lock);
 	sk = tcp_listening_hash[tcp_lhashfn(hnum)];
 	if (sk) {
-		if (sk->num == hnum && sk->next == NULL)
+		if (sk->num == hnum &&
+		    sk->next == NULL &&
+		    (!sk->rcv_saddr || sk->rcv_saddr == daddr) &&
+		    !sk->bound_dev_if)
 			goto sherry_cache;
 		sk = __tcp_v4_lookup_listener(sk, daddr, hnum, dif);
 	}
diff -u --recursive --new-file v2.3.34/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.3.34/linux/net/ipv4/udp.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv4/udp.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *
  *		The User Datagram Protocol (UDP).
  *
- * Version:	$Id: udp.c,v 1.74 1999/08/20 11:06:12 davem Exp $
+ * Version:	$Id: udp.c,v 1.75 1999/12/15 22:39:34 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.34/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- v2.3.34/linux/net/ipv6/addrconf.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv6/addrconf.c	Wed Dec 22 19:55:38 1999
@@ -6,7 +6,7 @@
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
- *	$Id: addrconf.c,v 1.53 1999/08/31 07:03:54 davem Exp $
+ *	$Id: addrconf.c,v 1.55 1999/12/15 22:39:40 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
diff -u --recursive --new-file v2.3.34/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c
--- v2.3.34/linux/net/ipv6/af_inet6.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv6/af_inet6.c	Wed Dec 22 19:55:38 1999
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/af_inet.c
  *
- *	$Id: af_inet6.c,v 1.47 1999/08/31 07:03:58 davem Exp $
+ *	$Id: af_inet6.c,v 1.49 1999/12/15 22:39:43 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
diff -u --recursive --new-file v2.3.34/linux/net/ipv6/mcast.c linux/net/ipv6/mcast.c
--- v2.3.34/linux/net/ipv6/mcast.c	Mon Nov  1 13:56:27 1999
+++ linux/net/ipv6/mcast.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: mcast.c,v 1.26 1999/08/31 07:04:08 davem Exp $
+ *	$Id: mcast.c,v 1.27 1999/12/09 00:52:49 davem Exp $
  *
  *	Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c 
  *
diff -u --recursive --new-file v2.3.34/linux/net/ipv6/proc.c linux/net/ipv6/proc.c
--- v2.3.34/linux/net/ipv6/proc.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv6/proc.c	Wed Dec 22 19:55:38 1999
@@ -7,7 +7,7 @@
  *		PROC file system.  This is very similar to the IPv4 version,
  *		except it reports the sockets in the INET6 address family.
  *
- * Version:	$Id: proc.c,v 1.11 1999/07/02 11:26:45 davem Exp $
+ * Version:	$Id: proc.c,v 1.12 1999/12/15 22:39:48 davem Exp $
  *
  * Authors:	David S. Miller (davem@caip.rutgers.edu)
  *
diff -u --recursive --new-file v2.3.34/linux/net/ipv6/raw.c linux/net/ipv6/raw.c
--- v2.3.34/linux/net/ipv6/raw.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv6/raw.c	Wed Dec 22 19:55:38 1999
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/raw.c
  *
- *	$Id: raw.c,v 1.29 1999/08/20 11:06:26 davem Exp $
+ *	$Id: raw.c,v 1.30 1999/12/15 22:39:51 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
diff -u --recursive --new-file v2.3.34/linux/net/ipv6/route.c linux/net/ipv6/route.c
--- v2.3.34/linux/net/ipv6/route.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv6/route.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: route.c,v 1.40 1999/08/31 07:04:13 davem Exp $
+ *	$Id: route.c,v 1.42 1999/12/15 22:39:53 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
diff -u --recursive --new-file v2.3.34/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.3.34/linux/net/ipv6/tcp_ipv6.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv6/tcp_ipv6.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.112 1999/08/31 07:04:19 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.113 1999/12/15 22:39:58 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
diff -u --recursive --new-file v2.3.34/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
--- v2.3.34/linux/net/ipv6/udp.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ipv6/udp.c	Wed Dec 22 19:55:38 1999
@@ -7,7 +7,7 @@
  *
  *	Based on linux/ipv4/udp.c
  *
- *	$Id: udp.c,v 1.45 1999/08/20 11:06:32 davem Exp $
+ *	$Id: udp.c,v 1.46 1999/12/15 22:40: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
diff -u --recursive --new-file v2.3.34/linux/net/irda/Config.in linux/net/irda/Config.in
--- v2.3.34/linux/net/irda/Config.in	Mon Oct  4 15:49:30 1999
+++ linux/net/irda/Config.in	Tue Dec 21 10:17:58 1999
@@ -12,7 +12,7 @@
       comment 'IrDA protocols'
       source net/irda/irlan/Config.in
       source net/irda/ircomm/Config.in
-
+      bool '  Ultra (connectionless) protocol' CONFIG_IRDA_ULTRA
       bool '  IrDA protocol options' CONFIG_IRDA_OPTIONS
       if [ "$CONFIG_IRDA_OPTIONS" != "n" ]; then
 	 comment '  IrDA options'
diff -u --recursive --new-file v2.3.34/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.3.34/linux/net/irda/af_irda.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/af_irda.c	Tue Dec 21 10:17:58 1999
@@ -1,25 +1,44 @@
 /*********************************************************************
  *                
  * Filename:      af_irda.c
- * Version:       0.7
+ * Version:       0.9
  * Description:   IrDA sockets implementation
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 31 10:12:43 1998
- * Modified at:   Sun Oct 31 19:32:37 1999
+ * Modified at:   Fri Dec 17 22:37:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
  * 
- *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
- *      
+ *     Copyright (c) 1999 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1999 Jean Tourrilhes <jeant@rockfort.hpl.hp.com>
+ *     All Rights Reserved.
+ *
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
  *     published by the Free Software Foundation; either version 2 of 
  *     the License, or (at your option) any later version.
- *  
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
+ * 
+ *     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
+ *
+ *     Linux-IrDA now supports four different types of IrDA sockets:
+ *
+ *     o SOCK_STREAM:    TinyTP connections with SAR disabled. The
+ *                       max SDU size is 0 for conn. of this type
+ *     o SOCK_SEQPACKET: TinyTP connections with SAR enabled. TTP may 
+ *                       fragment the messages, but will preserve
+ *                       the message boundaries
+ *     o SOCK_DGRAM:     IRDAPROTO_UNITDATA: TinyTP connections with Unitdata 
+ *                       (unreliable) transfers
+ *                       IRDAPROTO_ULTRA: Connectionless and unreliable data
  *     
  ********************************************************************/
 
@@ -39,6 +58,7 @@
 #include <net/irda/irda.h>
 #include <net/irda/iriap.h>
 #include <net/irda/irias_object.h>
+#include <net/irda/irlmp.h>
 #include <net/irda/irttp.h>
 #include <net/irda/discovery.h>
 
@@ -50,7 +70,14 @@
 static int irda_create(struct socket *sock, int protocol);
 
 static struct proto_ops irda_stream_ops;
+static struct proto_ops irda_seqpacket_ops;
 static struct proto_ops irda_dgram_ops;
+
+#ifdef CONFIG_IRDA_ULTRA
+static struct proto_ops irda_ultra_ops;
+#define ULTRA_MAX_DATA 382
+#endif /* CONFIG_IRDA_ULTRA */
+
 static hashbin_t *cachelog = NULL;
 static DECLARE_WAIT_QUEUE_HEAD(discovery_wait); /* Wait for discovery */
 
@@ -133,6 +160,10 @@
 
 	self = (struct irda_sock *) instance;
 
+	sk = self->sk;
+	if (sk == NULL)
+		return;
+
 	/* How much header space do we need to reserve */
 	self->max_header_size = max_header_size;
 
@@ -140,19 +171,30 @@
 	self->max_sdu_size_tx = max_sdu_size;
 
 	/* Find out what the largest chunk of data that we can transmit is */
-	if (max_sdu_size == SAR_DISABLE)
-		self->max_data_size = irttp_get_max_seq_size(self->tsap);
-	else
+	switch (sk->type) {
+	case SOCK_STREAM:
+		if (max_sdu_size != 0) {
+			ERROR(__FUNCTION__ "(), max_sdu_size must be 0\n");
+			return;
+		}
+		self->max_data_size = irttp_get_max_seg_size(self->tsap);
+		break;
+	case SOCK_SEQPACKET:
+		if (max_sdu_size == 0) {
+			ERROR(__FUNCTION__ "(), max_sdu_size cannot be 0\n");
+			return;
+		}
 		self->max_data_size = max_sdu_size;
+		break;
+	default:
+		self->max_data_size = irttp_get_max_seg_size(self->tsap);
+	};
 
-	IRDA_DEBUG(1, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), max_data_size=%d\n", 
+		   self->max_data_size);
 
 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
 
-	sk = self->sk;
-	if (sk == NULL)
-		return;
-
 	skb_queue_tail(&sk->receive_queue, skb);
 
 	/* We are now connected! */
@@ -175,7 +217,11 @@
 
 	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	self = (struct irda_sock *) instance;
+ 	self = (struct irda_sock *) instance;
+
+	sk = self->sk;
+	if (sk == NULL)
+		return;
 
 	/* How much header space do we need to reserve */
 	self->max_header_size = max_header_size;
@@ -184,21 +230,31 @@
 	self->max_sdu_size_tx = max_sdu_size;	
 
 	/* Find out what the largest chunk of data that we can transmit is */
-	if (max_sdu_size == SAR_DISABLE)
-		self->max_data_size = irttp_get_max_seq_size(self->tsap);
-	else
+	switch (sk->type) {
+	case SOCK_STREAM:
+		if (max_sdu_size != 0) {
+			ERROR(__FUNCTION__ "(), max_sdu_size must be 0\n");
+			return;
+		}
+		self->max_data_size = irttp_get_max_seg_size(self->tsap);
+		break;
+	case SOCK_SEQPACKET:
+		if (max_sdu_size == 0) {
+			ERROR(__FUNCTION__ "(), max_sdu_size cannot be 0\n");
+			return;
+		}
 		self->max_data_size = max_sdu_size;
+		break;
+	default:
+		self->max_data_size = irttp_get_max_seg_size(self->tsap);
+	};
 
-	IRDA_DEBUG(1, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), max_data_size=%d\n", 
+		   self->max_data_size);
 
 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
-
-	sk = self->sk;
-	if (sk == NULL)
-		return;
 	
 	skb_queue_tail(&sk->receive_queue, skb);
-
 	sk->state_change(sk);
 }
 
@@ -212,7 +268,7 @@
 {
 	struct sk_buff *skb;
 
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 
@@ -239,7 +295,7 @@
 	struct irda_sock *self;
 	struct sock *sk;
 
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 	
 	self = (struct irda_sock *) instance;
 	ASSERT(self != NULL, return;);
@@ -254,11 +310,15 @@
 		break;
 	case FLOW_START:
 		self->tx_flow = flow;
-		IRDA_DEBUG(1, __FUNCTION__ "(), IrTTP wants us to start again\n");
+		IRDA_DEBUG(1, __FUNCTION__ 
+			   "(), IrTTP wants us to start again\n");
 		wake_up_interruptible(sk->sleep);
 		break;
 	default:
 		IRDA_DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+		/* Unknown flow command, better stop */
+		self->tx_flow = flow;
+		break;
 	}
 }
 
@@ -273,7 +333,7 @@
 {
 	struct irda_sock *self;
 	
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(priv != NULL, return;);
 	self = (struct irda_sock *) priv;
@@ -312,6 +372,8 @@
 		IRDA_DEBUG(0, __FUNCTION__ "(), bad type!\n");
 		break;
 	}
+	irias_delete_value(value);
+
 	/* Wake up any processes waiting for result */
 	wake_up_interruptible(&self->ias_wait);
 }
@@ -324,7 +386,7 @@
  */
 static void irda_discovery_indication(hashbin_t *log)
 {
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	cachelog = log;
 
@@ -353,6 +415,7 @@
 	notify.connect_indication    = irda_connect_indication;
 	notify.disconnect_indication = irda_disconnect_indication;
 	notify.data_indication       = irda_data_indication;
+	notify.udata_indication	     = irda_data_indication;
 	notify.flow_indication       = irda_flow_indication;
 	notify.instance = self;
 	strncpy(notify.name, name, NOTIFY_MAX_NAME);
@@ -370,6 +433,38 @@
 }
 
 /*
+ * Function irda_open_lsap (self)
+ *
+ *    Open local Link Service Access Point (LSAP). Used for opening Ultra
+ *    sockets
+ */
+#ifdef CONFIG_IRDA_ULTRA
+static int irda_open_lsap(struct irda_sock *self, int pid)
+{
+	notify_t notify;
+
+	if (self->lsap) {
+		WARNING(__FUNCTION__ "(), busy!\n");
+		return -EBUSY;
+	}
+	
+	/* Initialize callbacks to be used by the IrDA stack */
+	irda_notify_init(&notify);
+	notify.udata_indication	= irda_data_indication;
+	notify.instance = self;
+	strncpy(notify.name, "Ultra", NOTIFY_MAX_NAME);
+
+	self->lsap = irlmp_open_lsap(LSAP_CONNLESS, &notify, pid);	
+	if (self->lsap == NULL) {
+		IRDA_DEBUG( 0, __FUNCTION__ "(), Unable to allocate LSAP!\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_IRDA_ULTRA */
+
+/*
  * Function irda_find_lsap_sel (self, name)
  *
  *    Try to lookup LSAP selector in remote LM-IAS
@@ -377,7 +472,7 @@
  */
 static int irda_find_lsap_sel(struct irda_sock *self, char *name)
 {
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "(), name=%s\n", name);
 
 	ASSERT(self != NULL, return -1;);
 
@@ -401,6 +496,104 @@
 	return -ENETUNREACH; /* May not be true */
 }
 
+ /*
+ * Function irda_discover_daddr_and_lsap_sel (self, name)
+ *
+ *    This try to find a device with the requested service.
+ *
+ * It basically look into the discovery log. For each address in the list,
+ * it queries the LM-IAS of the device to find if this device offer
+ * the requested service.
+ * If there is more than one node supporting the service, we complain
+ * to the user (it should move devices around).
+ * The, we set both the destination address and the lsap selector to point
+ * on the service on the unique device we have found.
+ *
+ * Note : this function fails if there is more than one device in range,
+ * because IrLMP doesn't disconnect the LAP when the last LSAP is closed.
+ * Moreover, we would need to wait the LAP disconnection...
+ */
+static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
+{
+	discovery_t *discovery;
+	int err = -ENETUNREACH;
+	__u32	daddr = 0x0;		/* Address we found the service on */
+	__u8	dtsap_sel = 0x0;	/* TSAP associated with it */
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), name=%s\n", name);
+
+	ASSERT(self != NULL, return -1;);
+
+	/* 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);
+		
+	/* Check if the we got some results */
+	if (!cachelog)
+		/* Wait for answer */
+		/*interruptible_sleep_on(&self->discovery_wait);*/
+		return -EAGAIN;
+
+	/* 
+	 * Now, check all discovered devices (if any), and connect
+	 * client only about the services that the client is
+	 * interested in...
+	 */
+	discovery = (discovery_t *) hashbin_get_first(cachelog);
+	while (discovery != NULL) {
+		/* Mask out the ones we don't want */
+		if (discovery->hints.word & self->mask) {
+			/* Try this address */
+			self->daddr = discovery->daddr;
+			self->saddr = 0x0;
+			IRDA_DEBUG(1, __FUNCTION__ "(), trying daddr = %08x\n",
+				   self->daddr);
+
+			/* Query remote LM-IAS for this service */
+			err = irda_find_lsap_sel(self, name);
+			if (err == 0) {
+				/* We found the requested service */
+				if(daddr != 0x0) {
+					IRDA_DEBUG(0, __FUNCTION__
+						   "(), discovered service ''%s'' in two different devices !!!\n",
+						   name);
+					return(-ENOTUNIQ);
+				}
+				/* First time we foun that one, save it ! */
+				daddr = self->daddr;
+				dtsap_sel = self->dtsap_sel;
+			}
+		}
+
+		/* Next node, maybe we will be more lucky...  */
+		discovery = (discovery_t *) hashbin_get_next(cachelog);
+	}
+	cachelog = NULL;
+
+	/* Check out what we found */
+	if(daddr == 0x0) {
+		IRDA_DEBUG(0, __FUNCTION__
+			   "(), cannot discover service ''%s'' in any device !!!\n",
+			   name);
+		self->daddr = 0;	/* Guessing */
+		return(-ENETUNREACH);
+	}
+
+	/* Revert back to discovered device & service */
+	self->daddr = daddr;
+	self->saddr = 0x0;
+	self->dtsap_sel = dtsap_sel;
+
+	IRDA_DEBUG(0, __FUNCTION__ 
+		   "(), discovered requested service ''%s'' at address %08x\n",
+		   name, self->daddr);
+
+	return 0;
+}
+
 /*
  * Function irda_getname (sock, uaddr, uaddr_len, peer)
  *
@@ -446,12 +639,16 @@
 {
 	struct sock *sk = sock->sk;
 
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	if (sk->type == SOCK_STREAM && sk->state != TCP_LISTEN) {
+	if ((sk->type != SOCK_STREAM) && (sk->type != SOCK_SEQPACKET) &&
+	    (sk->type != SOCK_DGRAM))
+		return -EOPNOTSUPP;
+
+	if (sk->state != TCP_LISTEN) {
 		sk->max_ack_backlog = backlog;
 		sk->state           = TCP_LISTEN;
-
+		
 		return 0;
 	}
 	
@@ -472,15 +669,38 @@
 	__u16 hints = 0;
 	int err;
 
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
 
-	if ((addr_len < sizeof(struct sockaddr_irda)) || 
-	    (addr_len > sizeof(struct sockaddr_irda)))
+	if (addr_len != sizeof(struct sockaddr_irda))
 		return -EINVAL;
 
+#ifdef CONFIG_IRDA_ULTRA
+	/* Special care for Ultra sockets */
+	if ((sk->type == SOCK_DGRAM) && (sk->protocol == IRDAPROTO_ULTRA)) {
+		self->pid = addr->sir_lsap_sel;
+		if (self->pid & 0x80) {
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "(), extension in PID not supp!\n");
+			return -EOPNOTSUPP;
+		}
+		err = irda_open_lsap(self, self->pid);
+		if (err < 0)
+			return err;
+		
+		self->max_data_size = ULTRA_MAX_DATA - LMP_PID_HEADER;
+		self->max_header_size = IRDA_MAX_HEADER + LMP_PID_HEADER;
+
+		/* Pretend we are connected */
+		sock->state = SS_CONNECTED;
+		sk->state   = TCP_ESTABLISHED;
+
+		return 0;
+	}
+#endif /* CONFIG_IRDA_ULTRA */
+
 	err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name);
 	if (err < 0)
 		return err;
@@ -490,6 +710,8 @@
 	irias_add_integer_attrib(self->ias_obj, "IrDA:TinyTP:LsapSel", 
 				 self->stsap_sel);
 	irias_insert_object(self->ias_obj);
+	
+#if 1 /* Will be removed in near future */
 
 	/* Fill in some default hint bits values */
 	if (strncmp(addr->sir_name, "OBEX", 4) == 0)
@@ -497,7 +719,7 @@
 	
 	if (hints)
 		self->skey = irlmp_register_service(hints);
-
+#endif
 	return 0;
 }
 
@@ -515,7 +737,7 @@
 	struct sk_buff *skb;
 	int err;
 
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
@@ -530,10 +752,11 @@
 	if ((sk = sock->sk) == NULL)
 		return -EINVAL;
 
-	if (sk->type != SOCK_STREAM)
+	if ((sk->type != SOCK_STREAM) && (sk->type != SOCK_SEQPACKET) &&
+	    (sk->type != SOCK_DGRAM))
 		return -EOPNOTSUPP;
 
-	if (sk->state != TCP_LISTEN)
+	if (sk->state != TCP_LISTEN) 
 		return -EINVAL;
 
 	/*
@@ -606,9 +829,13 @@
 	struct irda_sock *self;
 	int err;
 
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	self = sk->protinfo.irda;
+	
+	/* Don't allow connect for Ultra sockets */
+	if ((sk->type == SOCK_DGRAM) && (sk->protocol == IRDAPROTO_ULTRA))
+		return -ESOCKTNOSUPPORT;
 
 	if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
 		sock->state = SS_CONNECTED;
@@ -629,18 +856,26 @@
 	if (addr_len != sizeof(struct sockaddr_irda))
 		return -EINVAL;
 
-	/* Check if user supplied the required destination device address */
-	if (!addr->sir_addr)
-		return -EINVAL;
-
-	self->daddr = addr->sir_addr;
-	IRDA_DEBUG(1, __FUNCTION__ "(), daddr = %08x\n", self->daddr);
-
-	/* Query remote LM-IAS */
-	err = irda_find_lsap_sel(self, addr->sir_name);
-	if (err) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
-		return err;
+	/* Check if user supplied any destination device address */
+	if (!addr->sir_addr) {
+		/* Try to find one suitable */
+		err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name);
+		if (err) {
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "(), auto-connect failed!\n");
+			return -EINVAL;
+		}
+	} else {
+		/* Use the one provided by the user */
+		self->daddr = addr->sir_addr;
+		IRDA_DEBUG(1, __FUNCTION__ "(), daddr = %08x\n", self->daddr);
+		
+		/* Query remote LM-IAS */
+		err = irda_find_lsap_sel(self, addr->sir_name);
+		if (err) {
+			IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+			return err;
+		}
 	}
 
 	/* Check if we have opened a local TSAP */
@@ -704,8 +939,9 @@
 	
 	/* Check for valid socket type */
 	switch (sock->type) {
-	case SOCK_STREAM:   /* FALLTHROUGH */
-	case SOCK_SEQPACKET:
+	case SOCK_STREAM:     /* For TTP connections with SAR disabled */
+	case SOCK_SEQPACKET:  /* For TTP connections with SAR enabled */
+	case SOCK_DGRAM:      /* For TTP Unitdata or LMP Ultra transfers */
 		break;
 	default:
 		return -ESOCKTNOSUPPORT;
@@ -726,10 +962,35 @@
 	sk->protinfo.irda = self;
 	sock_init_data(sock, sk);
 
-	if (sock->type == SOCK_STREAM)
+	switch (sock->type) {
+	case SOCK_STREAM:
 		sock->ops = &irda_stream_ops;
-	else
-		sock->ops = &irda_dgram_ops;
+		self->max_sdu_size_rx = TTP_SAR_DISABLE;
+		break;
+	case SOCK_SEQPACKET:
+		sock->ops = &irda_seqpacket_ops;
+		self->max_sdu_size_rx = TTP_SAR_UNBOUND;
+		break;
+	case SOCK_DGRAM:
+		switch (protocol) {
+#ifdef CONFIG_IRDA_ULTRA
+		case IRDAPROTO_ULTRA:
+			sock->ops = &irda_ultra_ops;
+			break;
+#endif /* CONFIG_IRDA_ULTRA */
+		case IRDAPROTO_UNITDATA:
+			sock->ops = &irda_dgram_ops;
+			/* We let Unitdata conn. be like seqpack conn. */
+			self->max_sdu_size_rx = TTP_SAR_UNBOUND;
+			break;
+		default:
+			ERROR(__FUNCTION__ "(), protocol not supported!\n");
+			return -ESOCKTNOSUPPORT;
+		}
+		break;
+	default:
+		return -ESOCKTNOSUPPORT;
+	}		
 
 	sk->protocol = protocol;
 
@@ -737,8 +998,8 @@
 	self->ckey = irlmp_register_client(0, NULL, NULL);
 	self->mask = 0xffff;
 	self->rx_flow = self->tx_flow = FLOW_START;
-	self->max_sdu_size_rx = SAR_DISABLE; /* Default value */
 	self->nslots = DISCOVERY_DEFAULT_SLOTS;
+	self->daddr = DEV_ADDR_ANY;
 
 	/* Notify that we are using the irda module, so nobody removes it */
 	irda_mod_inc_use_count();
@@ -774,7 +1035,12 @@
 		irttp_close_tsap(self->tsap);
 		self->tsap = NULL;
 	}
-
+#ifdef CONFIG_IRDA_ULTRA
+	if (self->lsap) {
+		irlmp_close_lsap(self->lsap);
+		self->lsap = NULL;
+	}
+#endif /* CONFIG_IRDA_ULTRA */
 	kfree(self);
 
 	/* Notify that we are not using the irda module anymore */
@@ -784,7 +1050,7 @@
 }
 
 /*
- * Function irda_release (sock, peer)
+ * Function irda_release (sock)
  *
  *    
  *
@@ -793,7 +1059,7 @@
 {
 	struct sock *sk = sock->sk;
 	
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
         if (sk == NULL) 
 		return 0;
@@ -814,14 +1080,14 @@
 /*
  * Function irda_sendmsg (sock, msg, len, scm)
  *
- *    Send message down to TinyTP
- *
+ *    Send message down to TinyTP. This function is used for both STREAM and
+ *    SEQPACK services. This is possible since it forces the client to 
+ *    fragment the message if necessary
  */
 static int irda_sendmsg(struct socket *sock, struct msghdr *msg, int len, 
 			struct scm_cookie *scm)
 {
 	struct sock *sk = sock->sk;
-/* 	struct sockaddr_irda *addr = (struct sockaddr_irda *) msg->msg_name; */
 	struct irda_sock *self;
 	struct sk_buff *skb;
 	unsigned char *asmptr;
@@ -855,9 +1121,9 @@
 
 	/* Check that we don't send out to big frames */
 	if (len > self->max_data_size) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), Warning to much data! "
-		      "Chopping frame from %d to %d bytes!\n", len, 
-		      self->max_data_size);
+		IRDA_DEBUG(2, __FUNCTION__ 
+			   "(), Chopping frame from %d to %d bytes!\n", len, 
+			   self->max_data_size);
 		len = self->max_data_size;
 	}
 
@@ -868,7 +1134,6 @@
 
 	skb_reserve(skb, self->max_header_size);
 	
-	IRDA_DEBUG(4, __FUNCTION__ "(), appending user data\n");
 	asmptr = skb->h.raw = skb_put(skb, len);
 	memcpy_fromiovec(asmptr, msg->msg_iov, len);
 
@@ -881,14 +1146,15 @@
 		IRDA_DEBUG(0, __FUNCTION__ "(), err=%d\n", err);
 		return err;
 	}
+	/* Tell client how much data we actually sent */
 	return len;
 }
 
 /*
- * Function irda_recvmsg (sock, msg, size, flags, scm)
- *
- *    Try to receive message and copy it to user
+ * Function irda_recvmsg_dgram (sock, msg, size, flags, scm)
  *
+ *    Try to receive message and copy it to user. The frame is discarded
+ *    after being read, regardless of how much the user actually read
  */
 static int irda_recvmsg_dgram(struct socket *sock, struct msghdr *msg, 
 			      int size, int flags, struct scm_cookie *scm)
@@ -912,6 +1178,9 @@
 	copied     = skb->len;
 	
 	if (copied > size) {
+		IRDA_DEBUG(2, __FUNCTION__ 
+			   "(), Received truncated frame (%d < %d)!\n",
+			   copied, size);
 		copied = size;
 		msg->msg_flags |= MSG_TRUNC;
 	}
@@ -980,7 +1249,6 @@
 	if (flags & MSG_WAITALL)
 		target = size;
 		
-		
 	msg->msg_namelen = 0;
 
 	do {
@@ -1060,6 +1328,132 @@
 }
 
 /*
+ * Function irda_sendmsg_dgram (sock, msg, len, scm)
+ *
+ *    Send message down to TinyTP for the unreliable sequenced
+ *    packet service...
+ *
+ */
+static int irda_sendmsg_dgram(struct socket *sock, struct msghdr *msg,
+			      int len, struct scm_cookie *scm)
+{
+	struct sock *sk = sock->sk;
+	struct irda_sock *self;
+	struct sk_buff *skb;
+	unsigned char *asmptr;
+	int err;
+	
+	IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
+	
+	if (msg->msg_flags & ~MSG_DONTWAIT)
+		return -EINVAL;
+
+	if (sk->shutdown & SEND_SHUTDOWN) {
+		send_sig(SIGPIPE, current, 0);
+		return -EPIPE;
+	}
+
+	if (sk->state != TCP_ESTABLISHED)
+		return -ENOTCONN;
+
+	self = sk->protinfo.irda;
+	ASSERT(self != NULL, return -1;);
+
+	/*  
+	 * Check that we don't send out to big frames. This is an unreliable 
+	 * service, so we have no fragmentation and no coalescence 
+	 */
+	if (len > self->max_data_size) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), Warning to much data! "
+			   "Chopping frame from %d to %d bytes!\n", len, 
+			   self->max_data_size);
+		len = self->max_data_size;
+	}
+
+	skb = sock_alloc_send_skb(sk, len + self->max_header_size, 0, 
+				  msg->msg_flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return -ENOBUFS;
+
+	skb_reserve(skb, self->max_header_size);
+	
+	IRDA_DEBUG(4, __FUNCTION__ "(), appending user data\n");
+	asmptr = skb->h.raw = skb_put(skb, len);
+	memcpy_fromiovec(asmptr, msg->msg_iov, len);
+
+	/* 
+	 * Just send the message to TinyTP, and let it deal with possible 
+	 * errors. No need to duplicate all that here
+	 */
+	err = irttp_udata_request(self->tsap, skb);
+	if (err) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), err=%d\n", err);
+		return err;
+	}
+	return len;
+}
+
+/*
+ * Function irda_sendmsg_ultra (sock, msg, len, scm)
+ *
+ *    Send message down to IrLMP for the unreliable Ultra
+ *    packet service...
+ */
+#ifdef CONFIG_IRDA_ULTRA
+static int irda_sendmsg_ultra(struct socket *sock, struct msghdr *msg,
+			      int len, struct scm_cookie *scm)
+{
+	struct sock *sk = sock->sk;
+	struct irda_sock *self;
+	struct sk_buff *skb;
+	unsigned char *asmptr;
+	int err;
+	
+	IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
+	
+	if (msg->msg_flags & ~MSG_DONTWAIT)
+		return -EINVAL;
+
+	if (sk->shutdown & SEND_SHUTDOWN) {
+		send_sig(SIGPIPE, current, 0);
+		return -EPIPE;
+	}
+
+	self = sk->protinfo.irda;
+	ASSERT(self != NULL, return -1;);
+
+	/*  
+	 * Check that we don't send out to big frames. This is an unreliable 
+	 * service, so we have no fragmentation and no coalescence 
+	 */
+	if (len > self->max_data_size) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), Warning to much data! "
+			   "Chopping frame from %d to %d bytes!\n", len, 
+			   self->max_data_size);
+		len = self->max_data_size;
+	}
+
+	skb = sock_alloc_send_skb(sk, len + self->max_header_size, 0, 
+				  msg->msg_flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return -ENOBUFS;
+
+	skb_reserve(skb, self->max_header_size);
+	
+	IRDA_DEBUG(4, __FUNCTION__ "(), appending user data\n");
+	asmptr = skb->h.raw = skb_put(skb, len);
+	memcpy_fromiovec(asmptr, msg->msg_iov, len);
+
+	err = irlmp_connless_data_request(self->lsap, skb);
+	if (err) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), err=%d\n", err);
+		return err;
+	}
+	return len;
+}
+#endif /* CONFIG_IRDA_ULTRA */
+
+/*
  * Function irda_shutdown (sk, how)
  *
  *    
@@ -1070,7 +1464,7 @@
 	struct irda_sock *self;
 	struct sock *sk = sock->sk;
 
-	IRDA_DEBUG( 0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	self = sk->protinfo.irda;
 	ASSERT(self != NULL, return -1;);
@@ -1103,7 +1497,7 @@
 	struct sock *sk = sock->sk;
 	unsigned int mask;
 
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	poll_wait(file, sk->sleep, wait);
 	mask = 0;
@@ -1115,9 +1509,10 @@
 		mask |= POLLHUP;
 
 	/* readable? */
-	if (!skb_queue_empty(&sk->receive_queue))
+	if (!skb_queue_empty(&sk->receive_queue)) {
+		IRDA_DEBUG(4, "Socket is readable\n");
 		mask |= POLLIN | POLLRDNORM;
-
+	}
 	/* Connection-based need to check for termination and startup */
 	if (sk->type == SOCK_STREAM && sk->state==TCP_CLOSE)
 		mask |= POLLHUP;
@@ -1208,6 +1603,8 @@
 {
  	struct sock *sk = sock->sk;
 	struct irda_sock *self;
+	struct irda_ias_set	ias_opt;
+	struct ias_object *	ias_obj;
 	int opt;
 	
 	self = sk->protinfo.irda;
@@ -1215,20 +1612,101 @@
 
 	if (level != SOL_IRLMP)
 		return -ENOPROTOOPT;
-	
-	if (optlen < sizeof(int))
-		return -EINVAL;
-	
-	if (get_user(opt, (int *)optval))
-		return -EFAULT;
-	
+		
 	switch (optname) {
 	case IRLMP_IAS_SET:
+		if (optlen != sizeof(struct irda_ias_set))
+			return -EINVAL;
+	
+		/* Copy query to the driver. */
+		if (copy_from_user(&ias_opt, (char *)optval, optlen))
+		  	return -EFAULT;
+
+		/* Find the object we target */
+		ias_obj = irias_find_object(ias_opt.irda_class_name);
+		if(ias_obj == (struct ias_object *) NULL) {
+			/* Create a new object */
+			ias_obj = irias_new_object(ias_opt.irda_class_name,
+						   jiffies);
+		}
+
+		/* Do we have it already ? */
+		if(irias_find_attrib(ias_obj, ias_opt.irda_attrib_name))
+			return -EINVAL;
+
+		/* Look at the type */
+		switch(ias_opt.irda_attrib_type) {
+		case IAS_INTEGER:
+			/* Add an integer attribute */
+			irias_add_integer_attrib(ias_obj,
+						 ias_opt.irda_attrib_name, 
+					 ias_opt.attribute.irda_attrib_int);
+			break;
+		case IAS_OCT_SEQ:
+			/* Check length */
+			if(ias_opt.attribute.irda_attrib_octet_seq.len >
+			   IAS_MAX_OCTET_STRING)
+				return -EINVAL;
+			/* Add an octet sequence attribute */
+			irias_add_octseq_attrib(
+			      ias_obj,
+			      ias_opt.irda_attrib_name, 
+			      ias_opt.attribute.irda_attrib_octet_seq.OctetSeq,
+			      ias_opt.attribute.irda_attrib_octet_seq.len);
+			break;
+		case IAS_STRING:
+			/* Should check charset & co */
+			/* Check length */
+			if(ias_opt.attribute.irda_attrib_string.len >
+			   IAS_MAX_STRING)
+				return -EINVAL;
+			/* NULL terminate the string (avoid troubles) */
+			ias_opt.attribute.irda_attrib_string.string[ias_opt.attribute.irda_attrib_string.len] = '\0';
+			/* Add a string attribute */
+			irias_add_string_attrib(
+				ias_obj,
+				ias_opt.irda_attrib_name, 
+				ias_opt.attribute.irda_attrib_string.string);
+			break;
+		default :
+			return -EINVAL;
+		}
+		irias_insert_object(ias_obj);
+		break;
+
 		IRDA_DEBUG(0, __FUNCTION__ "(), sorry not impl. yet!\n");
 		return -ENOPROTOOPT;
 	case IRTTP_MAX_SDU_SIZE:
-		IRDA_DEBUG(2, __FUNCTION__ "(), setting max_sdu_size = %d\n", opt);
-		self->max_sdu_size_rx = opt;
+		if (optlen < sizeof(int))
+			return -EINVAL;
+	
+		if (get_user(opt, (int *)optval))
+			return -EFAULT;
+		
+		/* Only possible for a seqpacket service (TTP with SAR) */
+		if (sk->type != SOCK_SEQPACKET) {
+			IRDA_DEBUG(2, __FUNCTION__ 
+				   "(), setting max_sdu_size = %d\n", opt);
+			self->max_sdu_size_rx = opt;
+		} else {
+			WARNING(__FUNCTION__ 
+				"(), not allowed to set MAXSDUSIZE for this "
+				"socket type!\n");
+			return -ENOPROTOOPT;
+		}
+		break;
+	case IRLMP_HINTS_SET:
+		if (optlen < sizeof(int))
+			return -EINVAL;
+	
+		if (get_user(opt, (int *)optval))
+			return -EFAULT;
+
+		/* Unregister any old registration */
+		if (self->skey)
+			irlmp_unregister_service(self->skey);
+
+		self->skey = irlmp_register_service((__u16) opt);
 		break;
 	default:
 		return -ENOPROTOOPT;
@@ -1236,6 +1714,101 @@
 	return 0;
 }
 
+ /*
+ * Function irda_simple_get_value_confirm (obj_id, value, priv)
+ *
+ *    Got answer from remote LM-IAS, just copy object to requester...
+ *
+ * Note : duplicate from above, but we need our own version that
+ * doesn't touch the dtsap_sel and save the full value structure...
+ */
+static void irda_simple_get_value_confirm(int result, __u16 obj_id, 
+					  struct ias_value *value, void *priv)
+{
+	struct irda_sock *self;
+	
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	ASSERT(priv != NULL, return;);
+	self = (struct irda_sock *) priv;
+	
+	if (!self) {
+		WARNING(__FUNCTION__ "(), lost myself!\n");
+		return;
+	}
+
+	/* We probably don't need to make any more queries */
+	iriap_close(self->iriap);
+	self->iriap = NULL;
+
+	/* Check if request succeeded */
+	if (result != IAS_SUCCESS) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), IAS query failed!\n");
+
+		self->errno = result;
+
+		/* Wake up any processes waiting for result */
+		wake_up_interruptible(&self->ias_wait);
+
+		return;
+	}
+
+	/* Clone the object (so the requester can free it) */
+	self->ias_result = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+	memcpy(self->ias_result, value, sizeof(struct ias_value));
+
+	/* Wake up any processes waiting for result */
+	wake_up_interruptible(&self->ias_wait);
+}
+
+/*
+ * Function irda_extract_ias_value(ias_opt, ias_value)
+ *
+ *    Translate internal IAS value structure to the user space representation
+ *
+ * The external representation of IAS values, as we exchange them with
+ * user space program is quite different from the internal representation,
+ * as stored in the IAS database (because we need a flat structure for
+ * crossing kernel boundary).
+ * This function transform the former in the latter. We also check
+ * that the value type is valid.
+ */
+static int irda_extract_ias_value(struct irda_ias_set *ias_opt,
+				  struct ias_value *ias_value)
+{
+	/* Look at the type */
+	switch(ias_value->type) {
+	case IAS_INTEGER:
+		/* Copy the integer */
+		ias_opt->attribute.irda_attrib_int = ias_value->t.integer;
+		break;
+	case IAS_OCT_SEQ:
+		/* Set length */
+		ias_opt->attribute.irda_attrib_octet_seq.len = ias_value->len;
+		/* Copy over */
+		memcpy(ias_opt->attribute.irda_attrib_octet_seq.OctetSeq,
+		       ias_value->t.oct_seq, ias_value->len);
+		break;
+	case IAS_STRING:
+		/* Set length */
+		ias_opt->attribute.irda_attrib_string.len = ias_value->len;
+		ias_opt->attribute.irda_attrib_string.charset = ias_value->charset;
+		/* Copy over */
+		memcpy(ias_opt->attribute.irda_attrib_string.string,
+		       ias_value->t.string, ias_value->len);
+		/* NULL terminate the string (avoid troubles) */
+		ias_opt->attribute.irda_attrib_string.string[ias_value->len] = '\0';
+		break;
+	default :
+		return -EINVAL;
+	}
+
+	/* Copy type over */
+	ias_opt->irda_attrib_type = ias_value->type;
+
+	return 0;
+}
+
 /*
  * Function irda_getsockopt (sock, level, optname, optval, optlen)
  *
@@ -1250,8 +1823,13 @@
 	struct irda_device_list list;
 	struct irda_device_info *info;
 	discovery_t *discovery;
+	struct irda_ias_set	ias_opt;	/* IAS get/query params */
+	struct ias_object *	ias_obj;	/* Object in IAS */
+	struct ias_attrib *	ias_attr;	/* Attribute in IAS object */
+	int daddr = 0;		/* Destination address for IAS queries */
 	int val = 0;
 	int len = 0;
+	int err;
 	int offset, total;
 
 	self = sk->protinfo.irda;
@@ -1293,9 +1871,8 @@
 		while (discovery != NULL) {
 			/* Mask out the ones we don't want */
 			if (discovery->hints.word & self->mask) {
-				
 				/* Check if room for this device entry */
-				if (len - total < sizeof(struct irda_device_info))
+				if (len-total<sizeof(struct irda_device_info))
 					break;
 
 				/* Copy discovery information */
@@ -1307,7 +1884,7 @@
 				strncpy(info->info, discovery->nickname,
 					NICKNAME_MAX_LEN);
 
-				if (copy_to_user(optval+offset, info, 
+				if (copy_to_user(optval+total, info, 
 						 sizeof(struct irda_device_info)))
 					return -EFAULT;
 				list.len++;
@@ -1336,6 +1913,103 @@
 		if (copy_to_user(optval, &val, len))
 			return -EFAULT;
 		break;
+	case IRLMP_IAS_GET:
+		/* The user want an object from our local IAS database.
+		 * We just need to query the IAS and return the value
+		 * that we found */
+
+		/* Check that the user has allocated the right space for us */
+		if (len != sizeof(ias_opt))
+			return -EINVAL;
+
+		/* Copy query to the driver. */
+		if (copy_from_user((char *) &ias_opt, (char *)optval, len))
+		  	return -EFAULT;
+
+		/* Find the object we target */
+		ias_obj = irias_find_object(ias_opt.irda_class_name);
+		if(ias_obj == (struct ias_object *) NULL)
+			return -EINVAL;
+
+		/* Find the attribute (in the object) we target */
+		ias_attr = irias_find_attrib(ias_obj,
+					     ias_opt.irda_attrib_name); 
+		if(ias_attr == (struct ias_attrib *) NULL)
+			return -EINVAL;
+
+		/* Translate from internal to user structure */
+		err = irda_extract_ias_value(&ias_opt, ias_attr->value);
+		if(err)
+			return err;
+
+		/* Copy reply to the user */
+		if (copy_to_user((char *)optval, (char *) &ias_opt,
+				 sizeof(ias_opt)))
+		  	return -EFAULT;
+		/* Note : don't need to put optlen, we checked it */
+		break;
+	case IRLMP_IAS_QUERY:
+		/* The user want an object from a remote IAS database.
+		 * We need to use IAP to query the remote database and
+		 * then wait for the answer to come back. */
+
+		/* Check that the user has allocated the right space for us */
+		if (len != sizeof(ias_opt))
+			return -EINVAL;
+
+		/* Copy query to the driver. */
+		if (copy_from_user((char *) &ias_opt, (char *)optval, len))
+		  	return -EFAULT;
+
+		/* Check the destination address requested */
+		daddr = ias_opt.attribute.irda_attrib_int;
+		if(self->daddr != DEV_ADDR_ANY) {
+			/* If we are connected, we must use the correct
+			 * destination address (or leave it unspecified) */
+			if((daddr != DEV_ADDR_ANY) || (daddr != self->daddr))
+				return -EINVAL;
+			daddr = self->daddr;
+		} else {
+			/* If we are not connected, we must specify a valid
+			 * destination address */
+			if(daddr == DEV_ADDR_ANY)
+				return -EINVAL;
+		}
+
+		/* Check that we can proceed with IAP */
+		if (self->iriap) {
+			WARNING(__FUNCTION__
+				"(), busy with a previous query\n");
+			return -EBUSY;
+		}
+
+		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
+					 irda_simple_get_value_confirm);
+
+		/* Query remote LM-IAS */
+		self->errno = 0;
+		iriap_getvaluebyclass_request(self->iriap, self->saddr,
+					      daddr,
+					      ias_opt.irda_class_name,
+					      ias_opt.irda_attrib_name);
+		/* Wait for answer */
+		interruptible_sleep_on(&self->ias_wait);
+		/* Check what happened */
+		if(self->errno)
+			return(self->errno);
+
+		/* Translate from internal to user structure */
+		err = irda_extract_ias_value(&ias_opt, self->ias_result);
+		kfree(self->ias_result); /* Cleanup (need to be *here*) */
+		if(err)
+			return err;
+
+		/* Copy reply to the user */
+		if (copy_to_user((char *)optval, (char *) &ias_opt,
+				 sizeof(ias_opt)))
+		  	return -EFAULT;
+		/* Note : don't need to put optlen, we checked it */
+		break;
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -1370,7 +2044,7 @@
 	sock_no_mmap
 };
 
-static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
+static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
 	PF_IRDA,
 	
 	irda_release,
@@ -1388,12 +2062,57 @@
 	sock_no_fcntl,
 	irda_sendmsg,
 	irda_recvmsg_dgram,
-	sock_no_mmap
+	sock_no_mmap,
+};
+
+static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
+	PF_IRDA,
+       
+	irda_release,
+	irda_bind,
+	irda_connect,
+	sock_no_socketpair,
+	irda_accept,
+	irda_getname,
+	datagram_poll,
+	irda_ioctl,
+	irda_listen,
+	irda_shutdown,
+	irda_setsockopt,
+	irda_getsockopt,
+	sock_no_fcntl,
+	irda_sendmsg_dgram,
+	irda_recvmsg_dgram,
+	sock_no_mmap,
 };
 
+#ifdef CONFIG_IRDA_ULTRA
+static struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
+	PF_IRDA,
+       
+	irda_release,
+	irda_bind,
+	sock_no_connect,
+	sock_no_socketpair,
+	sock_no_accept,
+	irda_getname,
+	datagram_poll,
+	irda_ioctl,
+	sock_no_listen,
+	irda_shutdown,
+	irda_setsockopt,
+	irda_getsockopt,
+	sock_no_fcntl,
+	irda_sendmsg_ultra,
+	irda_recvmsg_dgram,
+	sock_no_mmap,
+};
+#endif /* CONFIG_IRDA_ULTRA */
+
 #include <linux/smp_lock.h>
-SOCKOPS_WRAP(irda_dgram, PF_IRDA);
 SOCKOPS_WRAP(irda_stream, PF_IRDA);
+SOCKOPS_WRAP(irda_seqpacket, PF_IRDA);
+SOCKOPS_WRAP(irda_dgram, PF_IRDA);
 
 /*
  * Function irda_device_event (this, event, ptr)
diff -u --recursive --new-file v2.3.34/linux/net/irda/discovery.c linux/net/irda/discovery.c
--- v2.3.34/linux/net/irda/discovery.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/discovery.c	Tue Dec 21 10:17:58 1999
@@ -209,7 +209,8 @@
  *    Print discovery information in /proc file system
  *
  */
-int discovery_proc_read(char *buf, char **start, off_t offset, int len)
+int discovery_proc_read(char *buf, char **start, off_t offset, int len, 
+			int unused)
 {
 	discovery_t *discovery;
 	unsigned long flags;
diff -u --recursive --new-file v2.3.34/linux/net/irda/ircomm/ircomm_core.c linux/net/irda/ircomm/ircomm_core.c
--- v2.3.34/linux/net/irda/ircomm/ircomm_core.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/ircomm/ircomm_core.c	Tue Dec 21 10:17:58 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Jun  6 20:37:34 1999
- * Modified at:   Sat Oct 30 12:48:14 1999
+ * Modified at:   Thu Dec 16 21:15:26 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -144,9 +144,6 @@
 {
 	IRDA_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);
 
@@ -177,6 +174,11 @@
 {
 	struct ircomm_cb *entry;
 
+	ASSERT(self != NULL, return -EIO;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return -EIO;);
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
 	entry = hashbin_remove(ircomm, self->line, NULL);
 
 	ASSERT(entry == self, return -1;);
@@ -236,14 +238,14 @@
 	 * 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);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
+		dev_kfree_skb(skb);
+	}
 }
 
 /*
@@ -282,6 +284,10 @@
 					     self, info->qos, 
 					     info->max_data_size,
 					     info->max_header_size, skb);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
+		dev_kfree_skb(skb);
+	}
 }
 
 /*
@@ -319,6 +325,10 @@
 
 	if (self->notify.data_indication)
 		self->notify.data_indication(self->notify.instance, self, skb);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
+		dev_kfree_skb(skb);
+	}
 }
 
 /*
@@ -349,7 +359,8 @@
 	if (skb->len)
 		ircomm_data_indication(self, skb);		
 	else {
-		IRDA_DEBUG(4, __FUNCTION__ "(), data was control info only!\n");
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), data was control info only!\n");
 		dev_kfree_skb(skb);
 	}
 }
@@ -399,6 +410,10 @@
 	if (self->notify.udata_indication)
 		self->notify.udata_indication(self->notify.instance, self, 
 					      ctrl_skb);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
+		dev_kfree_skb(skb);
+	}
 }
 
 /*
@@ -438,6 +453,9 @@
 	if (self->notify.disconnect_indication) {
 		self->notify.disconnect_indication(self->notify.instance, self,
 						   info->reason, skb);
+	} else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
+		dev_kfree_skb(skb);
 	}
 }
 
@@ -462,7 +480,7 @@
 
 #ifdef CONFIG_PROC_FS
 /*
- * Function ircomm_proc_read (buf, start, offset, len)
+ * Function ircomm_proc_read (buf, start, offset, len, unused)
  *
  *    
  *
diff -u --recursive --new-file v2.3.34/linux/net/irda/ircomm/ircomm_event.c linux/net/irda/ircomm/ircomm_event.c
--- v2.3.34/linux/net/irda/ircomm/ircomm_event.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/ircomm/ircomm_event.c	Tue Dec 21 10:17:58 1999
@@ -3,10 +3,10 @@
  * Filename:      ircomm_event.c
  * Version:       1.0
  * Description:   IrCOMM layer state machine
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Jun  6 20:33:11 1999
- * Modified at:   Sat Oct 30 13:05:23 1999
+ * Modified at:   Sun Dec 12 13:44:32 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -109,6 +109,8 @@
 	default:
 		IRDA_DEBUG(4, __FUNCTION__"(), unknown event: %s\n",
 			   ircomm_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
 		return -EINVAL;
 	}
 	return ret;
@@ -139,6 +141,8 @@
 	default:
 		IRDA_DEBUG(0, __FUNCTION__"(), unknown event: %s\n",
 			   ircomm_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
 		ret = -EINVAL;
 	}
 	return ret;
@@ -172,6 +176,8 @@
 	default:
 		IRDA_DEBUG(0, __FUNCTION__ "(), unknown event = %s\n",
 			   ircomm_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
 		ret = -EINVAL;
 	}
 	return ret;
@@ -214,6 +220,8 @@
 	default:
 		IRDA_DEBUG(0, __FUNCTION__ "(), unknown event = %s\n",
 			   ircomm_event[event]);
+		if (skb)
+			dev_kfree_skb(skb);
 		ret = -EINVAL;
 	}
 	return ret;
diff -u --recursive --new-file v2.3.34/linux/net/irda/ircomm/ircomm_lmp.c linux/net/irda/ircomm/ircomm_lmp.c
--- v2.3.34/linux/net/irda/ircomm/ircomm_lmp.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/ircomm/ircomm_lmp.c	Tue Dec 21 10:17:58 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      ircomm_lmp.c
- * Version:       
+ * Version:       1.0
  * Description:   Interface between IrCOMM and IrLMP
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Jun  6 20:48:27 1999
- * Modified at:   Sat Oct 30 12:55:24 1999
+ * Modified at:   Sun Dec 12 13:44:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       Previous IrLPT work by Thomas Davis
  * 
@@ -60,7 +60,7 @@
 	notify.instance = self;
 	strncpy(notify.name, "IrCOMM", NOTIFY_MAX_NAME);
 
-	self->lsap = irlmp_open_lsap(LSAP_ANY, &notify);
+	self->lsap = irlmp_open_lsap(LSAP_ANY, &notify, 0);
 	if (!self->lsap) {
 		IRDA_DEBUG(0,__FUNCTION__"failed to allocate tsap\n");
 		return -1;
@@ -128,11 +128,8 @@
 		if (!skb)
 			return -ENOMEM;
 		
-		/* 
-		 *  Reserve space for MUX and LAP header 
-		 */
-		skb_reserve(skb, LMP_MAX_HEADER);
-		
+		/*  Reserve space for MUX and LAP header */
+		skb_reserve(skb, LMP_MAX_HEADER);		
 		userdata = skb;
 	}
 	ret = irlmp_disconnect_request(self->lsap, userdata);
@@ -323,5 +320,3 @@
 
 	ircomm_do_event(self, IRCOMM_LMP_DISCONNECT_INDICATION, skb, &info);
 }
-
-
diff -u --recursive --new-file v2.3.34/linux/net/irda/ircomm/ircomm_param.c linux/net/irda/ircomm/ircomm_param.c
--- v2.3.34/linux/net/irda/ircomm/ircomm_param.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/ircomm/ircomm_param.c	Tue Dec 21 10:17:58 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Jun  7 10:25:11 1999
- * Modified at:   Sat Oct 30 13:05:42 1999
+ * Modified at:   Tue Dec 14 15:26:30 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -28,6 +28,9 @@
  *     
  ********************************************************************/
 
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
 #include <net/irda/irda.h>
 #include <net/irda/parameters.h>
 
@@ -67,7 +70,7 @@
 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 },
+	{ ircomm_param_poll,         PV_NO_VALUE },
 };
 
 static pi_major_info_t pi_major_call_table[] = {
@@ -102,6 +105,7 @@
  */
 int ircomm_param_request(struct ircomm_tty_cb *self, __u8 pi, int flush)
 {
+	struct tty_struct *tty;
 	unsigned long flags;
 	struct sk_buff *skb;
 	int count;
@@ -111,10 +115,9 @@
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
-	if (self->state != IRCOMM_TTY_READY) {
-		IRDA_DEBUG(2, __FUNCTION__ "(), not ready yet!\n");
+	tty = self->tty;
+	if (!tty)
 		return 0;
-	}
 
 	/* Make sure we don't send parameters for raw mode */
 	if (self->service_type == IRCOMM_3_WIRE_RAW)
@@ -132,8 +135,7 @@
 		}
 		
 		skb_reserve(skb, self->max_header_size);
-
-		self->ctrl_skb = skb;		
+		self->ctrl_skb = skb;
 	}
 	/* 
 	 * Inserting is a little bit tricky since we don't know how much
@@ -142,17 +144,22 @@
 	count = irda_param_insert(self, pi, skb->tail, skb_tailroom(skb),
 				  &ircomm_param_info);
 	if (count < 0) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), no room for parameter!\n");
+		WARNING(__FUNCTION__ "(), no room for parameter!\n");
 		restore_flags(flags);
 		return -1;
 	}
 	skb_put(skb, count);
+
 	restore_flags(flags);
 
+	IRDA_DEBUG(2, __FUNCTION__ "(), skb->len=%d\n", skb->len);
+
 	if (flush) {
-		ircomm_control_request(self->ircomm, skb);
-		self->ctrl_skb = NULL;		
+		/* ircomm_tty_do_softint will take care of the rest */
+		queue_task(&self->tqueue, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);
 	}
+
 	return count;
 }
 
@@ -172,38 +179,45 @@
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
 	if (get) {
-		param->pv.b = self->session.service_type;
+		param->pv.b = self->settings.service_type;
 		return 0;
 	}
 
+	/* Find all common service types */
+	service_type &= self->service_type;
+	if (!service_type) {
+		IRDA_DEBUG(2, __FUNCTION__
+			   "(), No common service type to use!\n");
+		return -1;
+	}
+	IRDA_DEBUG(0, __FUNCTION__ "(), services in common=%02x\n",
+		   service_type);
+
 	/*
 	 * Now choose a preferred service type of those available
 	 */
-	if (service_type & IRCOMM_3_WIRE_RAW) {
-		IRDA_DEBUG(2, __FUNCTION__ "(), peer supports 3 wire raw\n");
-		self->session.service_type |= IRCOMM_3_WIRE_RAW;
-	}
-	if (service_type & IRCOMM_3_WIRE) {
-		IRDA_DEBUG(2, __FUNCTION__ "(), peer supports 3 wire\n");
-		self->session.service_type |= IRCOMM_3_WIRE;
-	}
-	if (service_type & IRCOMM_9_WIRE) {
-		IRDA_DEBUG(2, __FUNCTION__ "(), peer supports 9 wire\n");
-		self->session.service_type |= IRCOMM_9_WIRE;
-	}
-	if (service_type & IRCOMM_CENTRONICS) {
-		IRDA_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) {
-		IRDA_DEBUG(2, __FUNCTION__"(), No common service type to use!\n");
-		return -1;
+	if (service_type & IRCOMM_CENTRONICS)
+		self->settings.service_type = IRCOMM_CENTRONICS;
+	else if (service_type & IRCOMM_9_WIRE)
+		self->settings.service_type = IRCOMM_9_WIRE;
+	else if (service_type & IRCOMM_3_WIRE)
+		self->settings.service_type = IRCOMM_3_WIRE;
+	else if (service_type & IRCOMM_3_WIRE_RAW)
+		self->settings.service_type = IRCOMM_3_WIRE_RAW;
+
+	IRDA_DEBUG(0, __FUNCTION__ "(), resulting service type=0x%02x\n", 
+		   self->settings.service_type);
+
+	/* 
+	 * Now the line is ready for some communication. Check if we are a
+         * server, and send over some initial parameters 
+	 */
+	if (!self->client && (self->settings.service_type != IRCOMM_3_WIRE_RAW))
+	{
+		/* Init connection */
+		ircomm_tty_send_initial_parameters(self);
+		ircomm_tty_link_established(self);
 	}
-	
-	IRDA_DEBUG(2, __FUNCTION__ "(), resulting service type=0x%02x\n", 
-		   self->session.service_type);
 
 	return 0;
 }
@@ -225,10 +239,10 @@
 	if (get)
 		param->pv.b = IRCOMM_SERIAL;
 	else {
-		self->session.port_type = param->pv.b;
+		self->settings.port_type = param->pv.b;
 
 		IRDA_DEBUG(0, __FUNCTION__ "(), port type=%d\n", 
-			   self->session.port_type);
+			   self->settings.port_type);
 	}
 	return 0;
 }
@@ -250,7 +264,7 @@
 		IRDA_DEBUG(0, __FUNCTION__ "(), not imp!\n");
 	} else {
 		IRDA_DEBUG(0, __FUNCTION__ "(), port-name=%s\n", param->pv.c);
-		strncpy(self->session.port_name, param->pv.c, 32);
+		strncpy(self->settings.port_name, param->pv.c, 32);
 	}
 
 	return 0;
@@ -259,7 +273,7 @@
 /*
  * Function ircomm_param_data_rate (self, param)
  *
- *    Exchange data rate to be used in this session
+ *    Exchange data rate to be used in this settings
  *
  */
 static int ircomm_param_data_rate(void *instance, param_t *param, int get)
@@ -270,9 +284,9 @@
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
 	if (get)
-		param->pv.i = self->session.data_rate;
+		param->pv.i = self->settings.data_rate;
 	else
-		self->session.data_rate = param->pv.i;
+		self->settings.data_rate = param->pv.i;
 	
 	IRDA_DEBUG(2, __FUNCTION__ "(), data rate = %d\n", param->pv.i);
 
@@ -282,7 +296,7 @@
 /*
  * Function ircomm_param_data_format (self, param)
  *
- *    Exchange data format to be used in this session
+ *    Exchange data format to be used in this settings
  *
  */
 static int ircomm_param_data_format(void *instance, param_t *param, int get)
@@ -293,9 +307,9 @@
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
 	if (get)
-		param->pv.b = self->session.data_format;
+		param->pv.b = self->settings.data_format;
 	else
-		self->session.data_format = param->pv.b;
+		self->settings.data_format = param->pv.b;
 	
 	return 0;
 }
@@ -303,7 +317,7 @@
 /*
  * Function ircomm_param_flow_control (self, param)
  *
- *    Exchange flow control settings to be used in this session
+ *    Exchange flow control settings to be used in this settings
  *
  */
 static int ircomm_param_flow_control(void *instance, param_t *param, int get)
@@ -314,9 +328,9 @@
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 	
 	if (get)
-		param->pv.b = self->session.flow_control;
+		param->pv.b = self->settings.flow_control;
 	else
-		self->session.flow_control = param->pv.b;
+		self->settings.flow_control = param->pv.b;
 
 	IRDA_DEBUG(1, __FUNCTION__ "(), flow control = 0x%02x\n", param->pv.b);
 
@@ -337,14 +351,14 @@
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 	
 	if (get) {
-		param->pv.s = self->session.xonxoff[0];
-		param->pv.s |= self->session.xonxoff[1] << 8;
+		param->pv.s = self->settings.xonxoff[0];
+		param->pv.s |= self->settings.xonxoff[1] << 8;
 	} else {
-		self->session.xonxoff[0] = param->pv.s & 0xff;
-		self->session.xonxoff[1] = param->pv.s >> 8;
+		self->settings.xonxoff[0] = param->pv.s & 0xff;
+		self->settings.xonxoff[1] = param->pv.s >> 8;
 	}
 
-	IRDA_DEBUG(0, __FUNCTION__ "(), XON/XOFF = 0x%02x\n,0x%02x", 
+	IRDA_DEBUG(0, __FUNCTION__ "(), XON/XOFF = 0x%02x,0x%02x\n", 
 		   param->pv.s & 0xff, param->pv.s >> 8);
 
 	return 0;
@@ -364,11 +378,11 @@
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 	
 	if (get) {
-		param->pv.s = self->session.enqack[0];
-		param->pv.s |= self->session.enqack[1] << 8;
+		param->pv.s = self->settings.enqack[0];
+		param->pv.s |= self->settings.enqack[1] << 8;
 	} else {
-		self->session.enqack[0] = param->pv.s & 0xff;
-		self->session.enqack[1] = param->pv.s >> 8;
+		self->settings.enqack[0] = param->pv.s & 0xff;
+		self->settings.enqack[1] = param->pv.s >> 8;
 	}
 
 	IRDA_DEBUG(0, __FUNCTION__ "(), ENQ/ACK = 0x%02x,0x%02x\n",
@@ -405,29 +419,29 @@
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
 	if (get)
-		param->pv.b = self->session.dte;
+		param->pv.b = self->settings.dte;
 	else {
 		dte = param->pv.b;
 		
 		if (dte & IRCOMM_DELTA_DTR)
-			self->session.dce |= (IRCOMM_DELTA_DSR|
+			self->settings.dce |= (IRCOMM_DELTA_DSR|
 					      IRCOMM_DELTA_RI |
 					      IRCOMM_DELTA_CD);
 		if (dte & IRCOMM_DTR)
-			self->session.dce |= (IRCOMM_DSR|
+			self->settings.dce |= (IRCOMM_DSR|
 					      IRCOMM_RI |
 					      IRCOMM_CD);
 		
 		if (dte & IRCOMM_DELTA_RTS)
-			self->session.dce |= IRCOMM_DELTA_CTS;
+			self->settings.dce |= IRCOMM_DELTA_CTS;
 		if (dte & IRCOMM_RTS)
-			self->session.dce |= IRCOMM_CTS;
+			self->settings.dce |= IRCOMM_CTS;
 
 		/* Take appropriate actions */
 		ircomm_tty_check_modem_status(self);
 
 		/* Null modem cable emulator */
-		self->session.null_modem = TRUE;
+		self->settings.null_modem = TRUE;
 	}
 
 	return 0;
@@ -451,7 +465,7 @@
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
-	self->session.dce = dce;
+	self->settings.dce = dce;
 
 	/* Check if any of the settings have changed */
 	if (dce & 0x0f) {
@@ -483,7 +497,6 @@
 		/* Respond with DTE line settings */
 		ircomm_param_request(self, IRCOMM_DTE, TRUE);
 	}
-
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.34/linux/net/irda/ircomm/ircomm_ttp.c linux/net/irda/ircomm/ircomm_ttp.c
--- v2.3.34/linux/net/irda/ircomm/ircomm_ttp.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/ircomm/ircomm_ttp.c	Tue Dec 21 10:17:58 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      ircomm_ttp.c
- * Version:       
+ * Version:       1.0
  * Description:   Interface between IrCOMM and IrTTP
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Jun  6 20:48:27 1999
- * Modified at:   Sat Oct 30 12:55:36 1999
+ * Modified at:   Mon Dec 13 11:35:13 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -64,7 +64,7 @@
 	self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
 				     &notify);
 	if (!self->tsap) {
-		IRDA_DEBUG(0,__FUNCTION__"failed to allocate tsap\n");
+		IRDA_DEBUG(0, __FUNCTION__"failed to allocate tsap\n");
 		return -1;
 	}
 	self->slsap_sel = self->tsap->stsap_sel;
@@ -95,8 +95,8 @@
 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ret = irttp_connect_request(self->tsap, info->dlsap_sel,
-				    info->saddr, info->daddr, 
-				    NULL, SAR_DISABLE, userdata); 
+				    info->saddr, info->daddr, NULL, 
+				    TTP_SAR_DISABLE, userdata); 
 	return ret;
 }	
 
@@ -112,7 +112,7 @@
 
 	IRDA_DEBUG(4, __FUNCTION__"()\n");
 	
-	ret = irttp_connect_response(self->tsap, SAR_DISABLE, skb);
+	ret = irttp_connect_response(self->tsap, TTP_SAR_DISABLE, skb);
 
 	return ret;
 }
@@ -139,7 +139,7 @@
 	 * 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;);
+	ASSERT(skb_headroom(skb) >= IRCOMM_HEADER_SIZE, return -1;);
 	skb_push(skb, IRCOMM_HEADER_SIZE);
 
 	skb->data[0] = clen;
@@ -191,12 +191,13 @@
 	ASSERT(skb != NULL, return;);
 	ASSERT(qos != NULL, return;);
 
-	if (max_sdu_size != SAR_DISABLE) {
+	if (max_sdu_size != TTP_SAR_DISABLE) {
 		ERROR(__FUNCTION__ "(), SAR not allowed for IrCOMM!\n");
+		dev_kfree_skb(skb);
 		return;
 	}
 
-	info.max_data_size = irttp_get_max_seq_size(self->tsap)
+	info.max_data_size = irttp_get_max_seg_size(self->tsap)
 		- IRCOMM_HEADER_SIZE;
 	info.max_header_size = max_header_size + IRCOMM_HEADER_SIZE;
 	info.qos = qos;
@@ -227,12 +228,13 @@
 	ASSERT(skb != NULL, return;);
 	ASSERT(qos != NULL, return;);
 
-	if (max_sdu_size != SAR_DISABLE) {
+	if (max_sdu_size != TTP_SAR_DISABLE) {
 		ERROR(__FUNCTION__ "(), SAR not allowed for IrCOMM!\n");
+		dev_kfree_skb(skb);
 		return;
 	}
 
-	info.max_data_size = irttp_get_max_seq_size(self->tsap)
+	info.max_data_size = irttp_get_max_seg_size(self->tsap)
 		- IRCOMM_HEADER_SIZE;
 	info.max_header_size = max_header_size + IRCOMM_HEADER_SIZE;
 	info.qos = qos;
@@ -270,7 +272,7 @@
 	struct ircomm_cb *self = (struct ircomm_cb *) instance;
 	struct ircomm_info info;
 
-	IRDA_DEBUG(4, __FUNCTION__"()\n");
+	IRDA_DEBUG(2, __FUNCTION__"()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_MAGIC, return;);
diff -u --recursive --new-file v2.3.34/linux/net/irda/ircomm/ircomm_tty.c linux/net/irda/ircomm/ircomm_tty.c
--- v2.3.34/linux/net/irda/ircomm/ircomm_tty.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/ircomm/ircomm_tty.c	Tue Dec 21 10:17:58 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Jun  6 21:00:56 1999
- * Modified at:   Sat Oct 30 12:49:26 1999
+ * Modified at:   Thu Dec 16 22:07:37 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       serial.c and previous IrCOMM work by Takahide Higuchi
  * 
@@ -61,6 +61,7 @@
 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_do_softint(void *private_);
+static void ircomm_tty_shutdown(struct ircomm_tty_cb *self);
 
 static int ircomm_tty_data_indication(void *instance, void *sap,
 				      struct sk_buff *skb);
@@ -134,6 +135,20 @@
 	return 0;
 }
 
+#ifdef MODULE
+static void __ircomm_tty_cleanup(struct ircomm_tty_cb *self)
+{
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	ircomm_tty_shutdown(self);
+
+	self->magic = 0;
+	kfree(self);
+}
+
 /*
  * Function ircomm_tty_cleanup ()
  *
@@ -144,7 +159,7 @@
 {
 	int ret;
 
-	IRDA_DEBUG(4, __FUNCTION__"()\n");
+	IRDA_DEBUG(4, __FUNCTION__"()\n");	
 
 	ret = tty_unregister_driver(&driver);
         if (ret) {
@@ -152,8 +167,9 @@
 		return;
 	}
 
-	hashbin_delete(ircomm_tty, (FREE_FUNC) kfree);
+	hashbin_delete(ircomm_tty, (FREE_FUNC) __ircomm_tty_cleanup);
 }
+#endif /* MODULE */
 
 /*
  * Function ircomm_startup (self)
@@ -166,6 +182,8 @@
 	notify_t notify;
 	int ret;
 
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
@@ -189,9 +207,10 @@
 	strncpy(notify.name, "ircomm_tty", NOTIFY_MAX_NAME);
 	notify.instance = self;
 
-	if (!self->ircomm)
+	if (!self->ircomm) {
 		self->ircomm = ircomm_open(&notify, self->service_type, 
 					   self->line);
+	}
 	if (!self->ircomm)
 		return -ENODEV;
 
@@ -224,25 +243,23 @@
 	unsigned long	flags;
 	struct tty_struct *tty;
 	
-	tty = self->tty;
-
 	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
+	tty = self->tty;
+
 	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
+			return -EBUSY;
 		if ((self->flags & ASYNC_CALLOUT_ACTIVE) &&
 		    (self->flags & ASYNC_PGRP_LOCKOUT) &&
 		    (self->pgrp != current->pgrp))
-		    return -EBUSY;
+			return -EBUSY;
 		self->flags |= ASYNC_CALLOUT_ACTIVE;
 		return 0;
 	}
@@ -297,13 +314,13 @@
 		if (!(self->flags & ASYNC_CALLOUT_ACTIVE) &&
  		    (tty->termios->c_cflag & CBAUD)) {
 			save_flags(flags); cli();
-			self->session.dte |= IRCOMM_RTS + IRCOMM_DTR;
+			self->settings.dte |= IRCOMM_RTS + IRCOMM_DTR;
 		 	
 			ircomm_param_request(self, IRCOMM_DTE, TRUE);
 			restore_flags(flags);
 		}
 		
-		set_current_state(TASK_INTERRUPTIBLE);
+		current->state = TASK_INTERRUPTIBLE;
 		
 		if (tty_hung_up_p(filp) || !(self->flags & ASYNC_INITIALIZED)){
 			retval = (self->flags & ASYNC_HUP_NOTIFY) ?
@@ -318,7 +335,7 @@
 		 */
  		if (!(self->flags & ASYNC_CALLOUT_ACTIVE) &&
  		    !(self->flags & ASYNC_CLOSING) &&
- 		    (do_clocal || (self->session.dce & IRCOMM_CD)) &&
+ 		    (do_clocal || (self->settings.dce & IRCOMM_CD)) &&
 		    self->state == IRCOMM_TTY_READY)
 		{
  			break;
@@ -386,6 +403,8 @@
 		memset(self, 0, sizeof(struct ircomm_tty_cb));
 		
 		self->magic = IRCOMM_TTY_MAGIC;
+		self->flow = FLOW_STOP;
+
 		self->line = line;
 		self->tqueue.routine = ircomm_tty_do_softint;
 		self->tqueue.data = self;
@@ -397,7 +416,7 @@
 		/* Init some important stuff */
 		init_timer(&self->watchdog_timer);
 		init_waitqueue_head(&self->open_wait);
-		init_waitqueue_head(&self->close_wait);
+ 		init_waitqueue_head(&self->close_wait);
 
 		/* 
 		 * Force TTY into raw mode by default which is usually what
@@ -453,15 +472,14 @@
 	ret = ircomm_tty_block_til_ready(self, filp);
 	if (ret) {
 		/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
-		IRDA_DEBUG(0, __FUNCTION__ 
+		IRDA_DEBUG(2, __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;
@@ -478,14 +496,11 @@
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 	unsigned long flags;
 
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	if (!tty)
 		return;
 
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
-
 	save_flags(flags); 
 	cli();
 
@@ -493,10 +508,27 @@
 		MOD_DEC_USE_COUNT;
 		restore_flags(flags);
 
-		IRDA_DEBUG(2, __FUNCTION__ "(), returning 1\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), returning 1\n");
 		return;
 	}
 
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	if ((tty->count == 1) && (self->open_count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  state->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		IRDA_DEBUG(0, __FUNCTION__ "(), bad serial port count; "
+			   "tty->count is 1, state->count is %d\n", 
+			   self->open_count);
+		self->open_count = 1;
+	}
+
 	if (--self->open_count < 0) {
 		ERROR(__FUNCTION__ 
 		      "(), bad serial port count for ttys%d: %d\n",
@@ -507,7 +539,7 @@
 		MOD_DEC_USE_COUNT;
 		restore_flags(flags);
 
-		IRDA_DEBUG(2, __FUNCTION__ "(), open count > 0\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), open count > 0\n");
 		return;
 	}
 	self->flags |= ASYNC_CLOSING;
@@ -520,7 +552,7 @@
 	if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 		tty_wait_until_sent(tty, self->closing_wait);
 
-	self->flags &= ~ASYNC_INITIALIZED;
+	ircomm_tty_shutdown(self);
 
 	if (tty->driver.flush_buffer)
 		tty->driver.flush_buffer(tty);
@@ -543,34 +575,7 @@
 	wake_up_interruptible(&self->close_wait);
 
 	MOD_DEC_USE_COUNT;
-
-	del_timer(&self->watchdog_timer);
-	
-	/* Free parameter buffer */
-	if (self->ctrl_skb) {
-		dev_kfree_skb(self->ctrl_skb);
-		self->ctrl_skb = NULL;
-	}
-
-	/* Free transmit buffer */
-	if (self->tx_skb) {
-		dev_kfree_skb(self->tx_skb);
-		self->tx_skb = NULL;
-	}
-
 	restore_flags(flags);
-
-	ircomm_tty_detach_cable(self);
-	ircomm_close(self->ircomm);
-	self->ircomm = NULL;
-
-#if IRCOMM_TTY_CLOSE_WILL_DEALLOC
-	self->magic = 0;
-
-	hashbin_remove(ircomm_tty, self->line, NULL);
-
-	kfree(self);
-#endif
 }
 
 /*
@@ -606,7 +611,9 @@
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) private_;
 	struct tty_struct *tty;
 	unsigned long flags;
-	struct sk_buff *skb;
+	struct sk_buff *skb, *ctrl_skb;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	if (!self || self->magic != IRCOMM_TTY_MAGIC)
 		return;
@@ -615,6 +622,19 @@
 	if (!tty)
 		return;
 
+	/* Unlink control buffer */
+	save_flags(flags);
+	cli();
+
+	ctrl_skb = self->ctrl_skb;
+	self->ctrl_skb = NULL;
+
+	restore_flags(flags);
+
+	/* Flush control buffer if any */
+	if (ctrl_skb && self->flow == FLOW_START)
+		ircomm_control_request(self->ircomm, ctrl_skb);
+
 	if (tty->hw_stopped)
 		return;
 
@@ -625,7 +645,7 @@
 	skb = self->tx_skb;
 	self->tx_skb = NULL;
 
-	restore_flags(flags);
+	restore_flags(flags);	
 
 	/* Flush transmit buffer if any */
 	if (skb)
@@ -658,7 +678,7 @@
 	int len = 0;
 	int size;
 
-	IRDA_DEBUG(3, __FUNCTION__ "(), count=%d, hw_stopped=%d\n", count,
+	IRDA_DEBUG(2, __FUNCTION__ "(), count=%d, hw_stopped=%d\n", count,
 		   tty->hw_stopped);
 
 	ASSERT(self != NULL, return -1;);
@@ -788,7 +808,7 @@
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 	unsigned long orig_jiffies, poll_time;
 	
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
@@ -831,8 +851,8 @@
 	
 	/* Hardware flow control? */
 	if (tty->termios->c_cflag & CRTSCTS) {
-		self->session.dte &= ~IRCOMM_RTS;
-		self->session.dte |= IRCOMM_DELTA_RTS;
+		self->settings.dte &= ~IRCOMM_RTS;
+		self->settings.dte |= IRCOMM_DELTA_RTS;
 	
 		ircomm_param_request(self, IRCOMM_DTE, TRUE);
 	}
@@ -863,7 +883,7 @@
 
 	/* Using hardware flow control? */
 	if (tty->termios->c_cflag & CRTSCTS) {
-		self->session.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS);
+		self->settings.dte |= (IRCOMM_RTS|IRCOMM_DELTA_RTS);
 
 		ircomm_param_request(self, IRCOMM_DTE, TRUE);
 		IRDA_DEBUG(1, __FUNCTION__"(), FLOW_START\n");
@@ -897,6 +917,46 @@
 	return len;
 }
 
+static void ircomm_tty_shutdown(struct ircomm_tty_cb *self)
+{
+	unsigned long flags;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	
+	if (!(self->flags & ASYNC_INITIALIZED))
+		return;
+
+	save_flags(flags);
+	cli();
+
+	del_timer(&self->watchdog_timer);
+	
+	/* Free parameter buffer */
+	if (self->ctrl_skb) {
+		dev_kfree_skb(self->ctrl_skb);
+		self->ctrl_skb = NULL;
+	}
+
+	/* Free transmit buffer */
+	if (self->tx_skb) {
+		dev_kfree_skb(self->tx_skb);
+		self->tx_skb = NULL;
+	}
+
+	ircomm_tty_detach_cable(self);
+
+	if (self->ircomm) {
+		ircomm_close(self->ircomm);
+		self->ircomm = NULL;
+	}
+	self->flags &= ~ASYNC_INITIALIZED;
+
+	restore_flags(flags);
+}
+
 /*
  * Function ircomm_tty_hangup (tty)
  *
@@ -908,7 +968,7 @@
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 
-	IRDA_DEBUG(2, __FUNCTION__"()\n");
+	IRDA_DEBUG(0, __FUNCTION__"()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
@@ -917,17 +977,11 @@
 		return;
 
 	/* ircomm_tty_flush_buffer(tty); */
-	ircomm_tty_detach_cable(self);
-	ircomm_close(self->ircomm);
+	ircomm_tty_shutdown(self);
 
-	self->ircomm = NULL;
-
-	self->flags &= ~ASYNC_INITIALIZED;
-
-	self->open_count = 0;
 	self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
 	self->tty = 0;
-
+	self->open_count = 0;
 	wake_up_interruptible(&self->open_wait);
 }
 
@@ -983,19 +1037,21 @@
 	struct tty_struct *tty;
 	int status;
 
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 
 	tty = self->tty;
 
-	status = self->session.dce;
+	status = self->settings.dce;
 
 	if (status & IRCOMM_DCE_DELTA_ANY) {
 		/*wake_up_interruptible(&self->delta_msr_wait);*/
 	}
 	if ((self->flags & ASYNC_CHECK_CD) && (status & IRCOMM_DELTA_CD)) {
 		IRDA_DEBUG(2, __FUNCTION__ 
-			   "(), ttys%d CD now %s...\n", self->line,
+			   "(), ircomm%d CD now %s...\n", self->line,
 			   (status & IRCOMM_CD) ? "on" : "off");
 
 		if (status & IRCOMM_CD) {
@@ -1003,27 +1059,30 @@
 		} else if (!((self->flags & ASYNC_CALLOUT_ACTIVE) &&
 			   (self->flags & ASYNC_CALLOUT_NOHUP))) 
 		{
-			IRDA_DEBUG(2, __FUNCTION__ "(), Doing serial hangup..\n");
-			
+			IRDA_DEBUG(2, __FUNCTION__ 
+				   "(), Doing serial hangup..\n");
 			if (tty)
 				tty_hangup(tty);
+
+			/* Hangup will remote the tty, so better break out */
+			return;
 		}
 	}
 	if (self->flags & ASYNC_CTS_FLOW) {
 		if (tty->hw_stopped) {
 			if (status & IRCOMM_CTS) {
-				IRDA_DEBUG(2, __FUNCTION__ "(), CTS tx start...\n");
-				
+				IRDA_DEBUG(2, __FUNCTION__ 
+					   "(), CTS tx start...\n");
 				tty->hw_stopped = 0;
-
+				
 				queue_task(&self->tqueue, &tq_immediate);
 				mark_bh(IMMEDIATE_BH);
 				return;
 			}
 		} else {
 			if (!(status & IRCOMM_CTS)) {
-				IRDA_DEBUG(2, __FUNCTION__ "(), CTS tx stop...\n");
-
+				IRDA_DEBUG(2, __FUNCTION__ 
+					   "(), CTS tx stop...\n");
 				tty->hw_stopped = 1;
 			}
 		}
@@ -1047,8 +1106,20 @@
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 	ASSERT(skb != NULL, return -1;);
 
-	if (!self->tty)
+	if (!self->tty) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), no tty!\n");
+		dev_kfree_skb(skb);
 		return 0;
+	}
+
+	/* 
+	 * If we receive data when hardware is stopped then something is wrong.
+	 * We try to poll the peers line settings to check if we are up todate.
+	 */
+	if (self->tty->hw_stopped && (self->flow == FLOW_START)) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), polling for line settings!\n");
+		ircomm_param_request(self, IRCOMM_POLL, TRUE);
+	}
 
 	/* 
 	 * Just give it over to the line discipline. There is no need to
@@ -1113,15 +1184,15 @@
 
 		/* ircomm_tty_do_softint will take care of the rest */
 		queue_task(&self->tqueue, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);		
+		mark_bh(IMMEDIATE_BH);
 		break;
-	default:
-		/* If we get here, something is very wrong, better stop */
+	default:  /* If we get here, something is very wrong, better stop */
 	case FLOW_STOP:
 		IRDA_DEBUG(2, __FUNCTION__ "(), hw stopped!\n");
 		tty->hw_stopped = 1;
 		break;
 	}
+	self->flow = cmd;
 }
 
 static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf)
@@ -1141,57 +1212,57 @@
 		ret += sprintf(buf+ret, "No common service type!\n");
         ret += sprintf(buf+ret, "\n");
 
-	ret += sprintf(buf+ret, "Port name: %s\n", self->session.port_name);
+	ret += sprintf(buf+ret, "Port name: %s\n", self->settings.port_name);
 
 	ret += sprintf(buf+ret, "DTE status: ");	
-        if (self->session.dte & IRCOMM_RTS)
+        if (self->settings.dte & IRCOMM_RTS)
                 ret += sprintf(buf+ret, "RTS|");
-        if (self->session.dte & IRCOMM_DTR)
+        if (self->settings.dte & IRCOMM_DTR)
                 ret += sprintf(buf+ret, "DTR|");
-	if (self->session.dte)
+	if (self->settings.dte)
 		ret--; /* remove the last | */
         ret += sprintf(buf+ret, "\n");
 
 	ret += sprintf(buf+ret, "DCE status: ");
-        if (self->session.dce & IRCOMM_CTS)
+        if (self->settings.dce & IRCOMM_CTS)
                 ret += sprintf(buf+ret, "CTS|");
-        if (self->session.dce & IRCOMM_DSR)
+        if (self->settings.dce & IRCOMM_DSR)
                 ret += sprintf(buf+ret, "DSR|");
-        if (self->session.dce & IRCOMM_CD)
+        if (self->settings.dce & IRCOMM_CD)
                 ret += sprintf(buf+ret, "CD|");
-        if (self->session.dce & IRCOMM_RI) 
+        if (self->settings.dce & IRCOMM_RI) 
                 ret += sprintf(buf+ret, "RI|");
-	if (self->session.dce)
+	if (self->settings.dce)
 		ret--; /* remove the last | */
         ret += sprintf(buf+ret, "\n");
 
 	ret += sprintf(buf+ret, "Configuration: ");
-	if (!self->session.null_modem)
+	if (!self->settings.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, "Data rate: %d\n", self->settings.data_rate);
 
 	ret += sprintf(buf+ret, "Flow control: ");
-	if (self->session.flow_control & IRCOMM_XON_XOFF_IN)
+	if (self->settings.flow_control & IRCOMM_XON_XOFF_IN)
 		ret += sprintf(buf+ret, "XON_XOFF_IN|");
-	if (self->session.flow_control & IRCOMM_XON_XOFF_OUT)
+	if (self->settings.flow_control & IRCOMM_XON_XOFF_OUT)
 		ret += sprintf(buf+ret, "XON_XOFF_OUT|");
-	if (self->session.flow_control & IRCOMM_RTS_CTS_IN)
+	if (self->settings.flow_control & IRCOMM_RTS_CTS_IN)
 		ret += sprintf(buf+ret, "RTS_CTS_IN|");
-	if (self->session.flow_control & IRCOMM_RTS_CTS_OUT)
+	if (self->settings.flow_control & IRCOMM_RTS_CTS_OUT)
 		ret += sprintf(buf+ret, "RTS_CTS_OUT|");
-	if (self->session.flow_control & IRCOMM_DSR_DTR_IN)
+	if (self->settings.flow_control & IRCOMM_DSR_DTR_IN)
 		ret += sprintf(buf+ret, "DSR_DTR_IN|");
-	if (self->session.flow_control & IRCOMM_DSR_DTR_OUT)
+	if (self->settings.flow_control & IRCOMM_DSR_DTR_OUT)
 		ret += sprintf(buf+ret, "DSR_DTR_OUT|");
-	if (self->session.flow_control & IRCOMM_ENQ_ACK_IN)
+	if (self->settings.flow_control & IRCOMM_ENQ_ACK_IN)
 		ret += sprintf(buf+ret, "ENQ_ACK_IN|");
-	if (self->session.flow_control & IRCOMM_ENQ_ACK_OUT)
+	if (self->settings.flow_control & IRCOMM_ENQ_ACK_OUT)
 		ret += sprintf(buf+ret, "ENQ_ACK_OUT|");
-	if (self->session.flow_control)
+	if (self->settings.flow_control)
 		ret--; /* remove the last | */
         ret += sprintf(buf+ret, "\n");
 
@@ -1214,7 +1285,12 @@
 		ret--; /* remove the last | */
 	ret += sprintf(buf+ret, "\n");
 
+	ret += sprintf(buf+ret, "Role: %s\n", self->client ? 
+		       "client" : "server");
 	ret += sprintf(buf+ret, "Open count: %d\n", self->open_count);
+	ret += sprintf(buf+ret, "Max data size: %d\n", self->max_data_size);
+	ret += sprintf(buf+ret, "Max header size: %d\n", self->max_header_size);
+		
 	if (self->tty)
 		ret += sprintf(buf+ret, "Hardware: %s\n", 
 			       self->tty->hw_stopped ? "Stopped" : "Running");
diff -u --recursive --new-file v2.3.34/linux/net/irda/ircomm/ircomm_tty_attach.c linux/net/irda/ircomm/ircomm_tty_attach.c
--- v2.3.34/linux/net/irda/ircomm/ircomm_tty_attach.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/ircomm/ircomm_tty_attach.c	Tue Dec 21 10:17:58 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Jun  5 17:42:00 1999
- * Modified at:   Sun Oct 31 22:19:37 1999
+ * Modified at:   Wed Dec 15 23:32:08 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -124,7 +124,7 @@
  */
 int ircomm_tty_attach_cable(struct ircomm_tty_cb *self)
 {
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
@@ -159,17 +159,21 @@
  */
 void ircomm_tty_detach_cable(struct ircomm_tty_cb *self)
 {
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 
+	del_timer(&self->watchdog_timer);
+
 	/* Remove IrCOMM hint bits */
 	irlmp_unregister_client(self->ckey);
 	irlmp_unregister_service(self->skey);
 
-	if (self->iriap) 
+	if (self->iriap) { 
 		iriap_close(self->iriap);
+		self->iriap = NULL;
+	}
 
 	/* Remove LM-IAS object */
 	if (self->obj) {
@@ -183,7 +187,7 @@
 	self->daddr = self->saddr = 0;
 	self->dlsap_sel = self->slsap_sel = 0;
 
-	memset(&self->session, 0, sizeof(struct ircomm_params));
+	memset(&self->settings, 0, sizeof(struct ircomm_params));
 }
 
 /*
@@ -197,6 +201,8 @@
 	__u8 oct_seq[6];
 	__u16 hints;
 
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 	
@@ -237,7 +243,7 @@
  *    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)
+int ircomm_tty_send_initial_parameters(struct ircomm_tty_cb *self)
 {
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
@@ -250,27 +256,29 @@
 	 * haven't set them already
 	 */
 	IRDA_DEBUG(2, __FUNCTION__ "(), data-rate = %d\n", 
-		   self->session.data_rate);
-	if (!self->session.data_rate)
-		self->session.data_rate = 9600;
+		   self->settings.data_rate);
+	if (!self->settings.data_rate)
+		self->settings.data_rate = 9600;
 	IRDA_DEBUG(2, __FUNCTION__ "(), data-format = %d\n", 
-		   self->session.data_format);
-	if (!self->session.data_format)
-		self->session.data_format = IRCOMM_WSIZE_8;  /* 8N1 */
+		   self->settings.data_format);
+	if (!self->settings.data_format)
+		self->settings.data_format = IRCOMM_WSIZE_8;  /* 8N1 */
 
 	IRDA_DEBUG(2, __FUNCTION__ "(), flow-control = %d\n", 
-		   self->session.flow_control);
-	/*self->session.flow_control = IRCOMM_RTS_CTS_IN|IRCOMM_RTS_CTS_OUT;*/
+		   self->settings.flow_control);
+	/*self->settings.flow_control = IRCOMM_RTS_CTS_IN|IRCOMM_RTS_CTS_OUT;*/
 
 	/* Do not set delta values for the initial parameters */
-	self->session.dte = IRCOMM_DTR | IRCOMM_RTS;
+	self->settings.dte = IRCOMM_DTR | IRCOMM_RTS;
 
-	ircomm_param_request(self, IRCOMM_SERVICE_TYPE, FALSE);
+	/* Only send service type parameter when we are the client */
+	if (self->client)
+		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) {
+	if (self->settings.service_type == IRCOMM_3_WIRE) {
 		ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE);
 		return 0;
 	}
@@ -335,6 +343,12 @@
 	if (!self->tty)
 		return;
 
+	/* This will stop control data transfers */
+	self->flow = FLOW_STOP;
+
+	/* Stop data transfers */
+	self->tty->hw_stopped = 1;
+
 	ircomm_tty_do_event(self, IRCOMM_TTY_DISCONNECT_INDICATION, NULL, 
 			    NULL);
 }
@@ -395,6 +409,7 @@
 		IRDA_DEBUG(0, __FUNCTION__"(), got unknown type!\n");
 		break;
 	}
+	irias_delete_value(value);
 }
 
 /*
@@ -416,10 +431,14 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 
+	self->client = TRUE;
 	self->max_data_size = max_data_size;
 	self->max_header_size = max_header_size;
+	self->flow = FLOW_START;
 
 	ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_CONFIRM, NULL, NULL);
+
+	dev_kfree_skb(skb);
 }
 
 /*
@@ -443,8 +462,10 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 
+	self->client = FALSE;
 	self->max_data_size = max_data_size;
 	self->max_header_size = max_header_size;
+	self->flow = FLOW_START;
 
 	clen = skb->data[0];
 	if (clen)
@@ -453,6 +474,8 @@
 				       &ircomm_param_info);
 
 	ircomm_tty_do_event(self, IRCOMM_TTY_CONNECT_INDICATION, NULL, NULL);
+
+	dev_kfree_skb(skb);
 }
 
 /*
@@ -465,26 +488,31 @@
 {
 	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
+	if (!self->tty)
+		return;
+	
 	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. Otherwise
-	 * the client will have to wait for the CD to be set.
+	 * the client will have to wait for the CTS to be set.
 	 */
-	if (!(self->flags & ASYNC_CTS_FLOW)) {
+	if (self->flags & ASYNC_CTS_FLOW) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), waiting for CTS ...\n");
+		return;
+	} else {
 		IRDA_DEBUG(2, __FUNCTION__ "(), starting hardware!\n");
-		if (!self->tty)
-			return;
+
 		self->tty->hw_stopped = 0;
+	
+		/* Wake up processes blocked on open */
+		wake_up_interruptible(&self->open_wait);
 	}
-	/* 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);
 }
@@ -498,6 +526,9 @@
  */
 void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self, int timeout)
 {
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
 	irda_start_timer(&self->watchdog_timer, timeout, (void *) self,
 			 ircomm_tty_watchdog_timer_expired);
 }
@@ -512,7 +543,7 @@
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) data;
 	
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
@@ -535,13 +566,12 @@
 
 	IRDA_DEBUG(2, __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:
@@ -570,10 +600,6 @@
 		/* Accept connection */
 		ircomm_connect_response(self->ircomm, NULL);
 		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
-
-		/* Init connection */
-		ircomm_tty_send_initial_parameters(self);
-		ircomm_tty_link_established(self);
 		break;
 	case IRCOMM_TTY_WD_TIMER_EXPIRED:
 		/* Just stay idle */
@@ -640,15 +666,15 @@
 		/* Accept connection */
 		ircomm_connect_response(self->ircomm, NULL);
 		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
-
-		/* Init connection */
-		ircomm_tty_send_initial_parameters(self);
-		ircomm_tty_link_established(self);
 		break;
 	case IRCOMM_TTY_WD_TIMER_EXPIRED:
+#if 1
+		/* Give up */
+#else
 		/* Try to discover any remote devices */		
 		ircomm_tty_start_watchdog_timer(self, 3*HZ);
 		irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
+#endif
 		break;
 	case IRCOMM_TTY_DETACH_CABLE:
 		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
@@ -706,10 +732,6 @@
 		/* Accept connection */
 		ircomm_connect_response(self->ircomm, NULL);
 		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
-
-		/* Init connection */
-		ircomm_tty_send_initial_parameters(self);
-		ircomm_tty_link_established(self);
 		break;
 	case IRCOMM_TTY_DETACH_CABLE:
 		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
@@ -758,10 +780,6 @@
 		/* Accept connection */
 		ircomm_connect_response(self->ircomm, NULL);
 		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
-
-		/* Init connection */
-		ircomm_tty_send_initial_parameters(self);
-		ircomm_tty_link_established(self);
 		break;
 	case IRCOMM_TTY_DETACH_CABLE:
 		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
@@ -808,10 +826,6 @@
 		/* Accept connection */
 		ircomm_connect_response(self->ircomm, NULL);
 		ircomm_tty_next_state(self, IRCOMM_TTY_READY);
-
-		/* Init connection */
-		ircomm_tty_send_initial_parameters(self);
-		ircomm_tty_link_established(self);
 		break;
 	case IRCOMM_TTY_WD_TIMER_EXPIRED:
 		/* Go back to search mode */
@@ -819,7 +833,7 @@
 		ircomm_tty_start_watchdog_timer(self, 3*HZ);
 		break;
 	case IRCOMM_TTY_DETACH_CABLE:
-		ircomm_disconnect_request(self->ircomm, NULL);
+		/* ircomm_disconnect_request(self->ircomm, NULL); */
 		ircomm_tty_next_state(self, IRCOMM_TTY_IDLE);
 		break;
 	default:
@@ -855,9 +869,15 @@
 		ircomm_tty_next_state(self, IRCOMM_TTY_SEARCH);
 		ircomm_tty_start_watchdog_timer(self, 3*HZ);
 
-		/* Drop carrier */
-		self->session.dce = IRCOMM_DELTA_CD;
-		ircomm_tty_check_modem_status(self);
+		if (self->flags & ASYNC_CHECK_CD) {
+			/* Drop carrier */
+			self->settings.dce = IRCOMM_DELTA_CD;
+			ircomm_tty_check_modem_status(self);
+		} else {
+			IRDA_DEBUG(0, __FUNCTION__ "(), hanging up!\n");
+			if (self->tty)
+				tty_hangup(self->tty);
+		}
 		break;
 	default:
 		IRDA_DEBUG(2, __FUNCTION__"(), unknown event: %s\n",
@@ -876,9 +896,12 @@
 int ircomm_tty_do_event(struct ircomm_tty_cb *self, IRCOMM_TTY_EVENT event,
 			struct sk_buff *skb, struct ircomm_tty_info *info) 
 {
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
 	IRDA_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);
 }
 
@@ -890,6 +913,9 @@
  */
 void ircomm_tty_next_state(struct ircomm_tty_cb *self, IRCOMM_TTY_STATE state)
 {
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+
 	self->state = state;
 	
 	IRDA_DEBUG(2, __FUNCTION__": next state=%s, service type=%d\n", 
diff -u --recursive --new-file v2.3.34/linux/net/irda/ircomm/ircomm_tty_ioctl.c linux/net/irda/ircomm/ircomm_tty_ioctl.c
--- v2.3.34/linux/net/irda/ircomm/ircomm_tty_ioctl.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/ircomm/ircomm_tty_ioctl.c	Tue Dec 21 10:17:58 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Jun 10 14:39:09 1999
- * Modified at:   Sat Oct 30 12:50:41 1999
+ * Modified at:   Tue Dec 14 18:08:09 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -59,6 +59,8 @@
 	unsigned cflag, cval;
 	int baud;
 
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
 	if (!self->tty || !self->tty->termios || !self->ircomm)
 		return;
 
@@ -85,13 +87,13 @@
 	if (!baud)
 		baud = 9600;	/* B0 transition handled in rs_set_termios */
 
-	self->session.data_rate = baud;
+	self->settings.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;
+		/* self->settings.flow_control |= IRCOMM_RTS_CTS_IN; */
 	} else
 		self->flags &= ~ASYNC_CTS_FLOW;
 	
@@ -126,7 +128,7 @@
 			self->ignore_status_mask |= LSR_OE;
 	}
 #endif
-	self->session.data_format = cval;
+	self->settings.data_format = cval;
 
 	ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE);
  	ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE);
@@ -146,6 +148,8 @@
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 	unsigned int cflag = tty->termios->c_cflag;
 
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
 	if ((cflag == old_termios->c_cflag) && 
 	    (RELEVANT_IFLAG(tty->termios->c_iflag) == 
 	     RELEVANT_IFLAG(old_termios->c_iflag)))
@@ -158,17 +162,17 @@
 	/* Handle transition to B0 status */
 	if ((old_termios->c_cflag & CBAUD) &&
 	    !(cflag & CBAUD)) {
-		self->session.dte &= ~(IRCOMM_DTR|IRCOMM_RTS);
+		self->settings.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;
+		self->settings.dte |= IRCOMM_DTR;
 		if (!(tty->termios->c_cflag & CRTSCTS) || 
 		    !test_bit(TTY_THROTTLED, &tty->flags)) {
-			self->session.dte |= IRCOMM_RTS;
+			self->settings.dte |= IRCOMM_RTS;
 		}
 		ircomm_param_request(self, IRCOMM_DTE, TRUE);
 	}
@@ -193,14 +197,14 @@
 {
 	unsigned int result;
 
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	result =  ((self->session.dte & IRCOMM_RTS) ? TIOCM_RTS : 0)
-		| ((self->session.dte & IRCOMM_DTR) ? TIOCM_DTR : 0)
-		| ((self->session.dce & IRCOMM_CD)  ? TIOCM_CAR : 0)
-		| ((self->session.dce & IRCOMM_RI)  ? TIOCM_RNG : 0)
-		| ((self->session.dce & IRCOMM_DSR) ? TIOCM_DSR : 0)
-		| ((self->session.dce & IRCOMM_CTS) ? TIOCM_CTS : 0);
+	result =  ((self->settings.dte & IRCOMM_RTS) ? TIOCM_RTS : 0)
+		| ((self->settings.dte & IRCOMM_DTR) ? TIOCM_DTR : 0)
+		| ((self->settings.dce & IRCOMM_CD)  ? TIOCM_CAR : 0)
+		| ((self->settings.dce & IRCOMM_RI)  ? TIOCM_RNG : 0)
+		| ((self->settings.dce & IRCOMM_DSR) ? TIOCM_DSR : 0)
+		| ((self->settings.dce & IRCOMM_CTS) ? TIOCM_CTS : 0);
 
 	return put_user(result, value);
 }
@@ -227,27 +231,27 @@
 	if (error)
 		return error;
 
-	old_rts = self->session.dte & IRCOMM_RTS;
-	old_dtr = self->session.dte & IRCOMM_DTR;
+	old_rts = self->settings.dte & IRCOMM_RTS;
+	old_dtr = self->settings.dte & IRCOMM_DTR;
 
 	switch (cmd) {
 	case TIOCMBIS: 
 		if (arg & TIOCM_RTS) 
-			self->session.dte |= IRCOMM_RTS;
+			self->settings.dte |= IRCOMM_RTS;
 		if (arg & TIOCM_DTR)
-			self->session.dte |= IRCOMM_DTR;
+			self->settings.dte |= IRCOMM_DTR;
 		break;
 		
 	case TIOCMBIC:
 		if (arg & TIOCM_RTS)
-			self->session.dte &= ~IRCOMM_RTS;
+			self->settings.dte &= ~IRCOMM_RTS;
 		if (arg & TIOCM_DTR)
- 			self->session.dte &= ~IRCOMM_DTR;
+ 			self->settings.dte &= ~IRCOMM_DTR;
  		break;
 		
 	case TIOCMSET:
- 		self->session.dte = 
-			((self->session.dte & ~(IRCOMM_RTS | IRCOMM_DTR))
+ 		self->settings.dte = 
+			((self->settings.dte & ~(IRCOMM_RTS | IRCOMM_DTR))
 			 | ((arg & TIOCM_RTS) ? IRCOMM_RTS : 0)
 			 | ((arg & TIOCM_DTR) ? IRCOMM_DTR : 0));
 		break;
@@ -256,11 +260,11 @@
 		return -EINVAL;
 	}
 	
-	if ((self->session.dte & IRCOMM_RTS) != old_rts)
-		self->session.dte |= IRCOMM_DELTA_RTS;
+	if ((self->settings.dte & IRCOMM_RTS) != old_rts)
+		self->settings.dte |= IRCOMM_DELTA_RTS;
 
-	if ((self->session.dte & IRCOMM_DTR) != old_dtr)
-		self->session.dte |= IRCOMM_DELTA_DTR;
+	if ((self->settings.dte & IRCOMM_DTR) != old_dtr)
+		self->settings.dte |= IRCOMM_DELTA_DTR;
 
 	ircomm_param_request(self, IRCOMM_DTE, TRUE);
 	
@@ -281,12 +285,12 @@
 	if (!retinfo)
 		return -EFAULT;
 
-	IRDA_DEBUG(1, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	memset(&info, 0, sizeof(info));
 	info.line = self->line;
 	info.flags = self->flags;
-	info.baud_base = self->session.data_rate;
+	info.baud_base = self->settings.data_rate;
 	info.close_delay = self->close_delay;
 	info.closing_wait = self->closing_wait;
 
@@ -310,29 +314,33 @@
  *    
  *
  */
-static int ircomm_tty_set_serial_info(struct ircomm_tty_cb *tty,
+static int ircomm_tty_set_serial_info(struct ircomm_tty_cb *self,
 				      struct serial_struct *new_info)
 {
 #if 0
 	struct serial_struct new_serial;
-	struct ircomm_tty_cb old_driver;
+	struct ircomm_tty_cb old_state, *state;
 
-	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
 		return -EFAULT;
 
-	old_driver = *driver;
+
+	state = self
+	old_state = *self;
   
 	if (!capable(CAP_SYS_ADMIN)) {
-		if ((new_serial.baud_base != driver->comm->data_rate) ||
-		    (new_serial.close_delay != driver->close_delay) ||
+		if ((new_serial.baud_base != state->settings.data_rate) ||
+		    (new_serial.close_delay != state->close_delay) ||
 		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
-		     (driver->flags & ~ASYNC_USR_MASK)))
+		     (self->flags & ~ASYNC_USR_MASK)))
 			return -EPERM;
-		driver->flags = ((driver->flags & ~ASYNC_USR_MASK) |
+		state->flags = ((state->flags & ~ASYNC_USR_MASK) |
 				 (new_serial.flags & ASYNC_USR_MASK));
-		driver->custom_divisor = new_serial.custom_divisor;
+		self->flags = ((self->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+		/* self->custom_divisor = new_serial.custom_divisor; */
 		goto check_and_exit;
 	}
 
@@ -341,15 +349,14 @@
 	 * 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);
+	if (self->settings.data_rate != new_serial.baud_base) {
+		self->settings.data_rate = new_serial.baud_base;
+		ircomm_param_request(self, IRCOMM_DATA_RATE, TRUE);
 	}
 
-	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->close_delay = new_serial.close_delay * HZ/100;
+	self->closing_wait = new_serial.closing_wait * HZ/100;
+	/* self->custom_divisor = new_serial.custom_divisor; */
 
 	self->flags = ((self->flags & ~ASYNC_FLAGS) |
 		       (new_serial.flags & ASYNC_FLAGS));
@@ -358,7 +365,7 @@
  check_and_exit:
 
 	if (self->flags & ASYNC_INITIALIZED) {
-		if (((old_driver.flags & ASYNC_SPD_MASK) !=
+		if (((old_state.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)
@@ -387,6 +394,8 @@
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 	int ret = 0;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
 	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
diff -u --recursive --new-file v2.3.34/linux/net/irda/irda_device.c linux/net/irda/irda_device.c
--- v2.3.34/linux/net/irda/irda_device.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/irda_device.c	Tue Dec 21 10:17:58 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Oct  9 09:22:27 1999
- * Modified at:   Tue Nov 16 12:54:13 1999
+ * Modified at:   Sun Dec 12 12:24:32 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -62,6 +62,8 @@
 extern int actisys_init(void);
 extern int girbil_init(void);
 
+static void __irda_task_delete(struct irda_task *task);
+
 static hashbin_t *dongles = NULL;
 static hashbin_t *tasks = NULL;
 
@@ -94,14 +96,14 @@
 
 int __init irda_device_init( void)
 {
-	dongles = hashbin_new(HB_LOCAL);
+	dongles = hashbin_new(HB_GLOBAL);
 	if (dongles == NULL) {
 		printk(KERN_WARNING 
 		       "IrDA: Can't allocate dongles hashbin!\n");
 		return -ENOMEM;
 	}
 
-	tasks = hashbin_new(HB_LOCAL);
+	tasks = hashbin_new(HB_GLOBAL);
 	if (tasks == NULL) {
 		printk(KERN_WARNING 
 		       "IrDA: Can't allocate tasks hashbin!\n");
@@ -145,6 +147,9 @@
 #ifdef CONFIG_AIRPORT_DONGLE
  	airport_init();
 #endif
+#ifdef CONFIG_OLD_BELKIN
+ 	old_belkin_init();
+#endif
 	return 0;
 }
 
@@ -152,7 +157,7 @@
 {
 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	hashbin_delete(tasks, NULL);
+	hashbin_delete(tasks, (FREE_FUNC) __irda_task_delete);
 	hashbin_delete(dongles, NULL);
 }
 
@@ -188,7 +193,7 @@
 	struct if_irda_req req;
 	int ret;
 
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	if (!dev->do_ioctl) {
 		ERROR(__FUNCTION__ "(), do_ioctl not impl. by "
@@ -209,7 +214,7 @@
 	struct if_irda_req req;
 	int ret;
 
-	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	if (!dev->do_ioctl) {
 		ERROR(__FUNCTION__ "(), do_ioctl not impl. by "
@@ -257,6 +262,21 @@
 	task->state = state;
 }
 
+static void __irda_task_delete(struct irda_task *task)
+{
+	del_timer(&task->timer);
+	
+	kfree(task);
+}
+
+void irda_task_delete(struct irda_task *task)
+{
+	/* Unregister task */
+	hashbin_remove(tasks, (int) task, NULL);
+
+	__irda_task_delete(task);
+}
+
 /*
  * Function irda_task_kick (task)
  *
@@ -267,9 +287,9 @@
  */
 int irda_task_kick(struct irda_task *task)
 {
-	int timeout;
-	int ret = 0;
+	int finished = TRUE;
 	int count = 0;
+	int timeout;
 
 	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
@@ -281,13 +301,15 @@
 		timeout = task->function(task);
 		if (count++ > 100) {
 			ERROR(__FUNCTION__ "(), error in task handler!\n");
-			return -1;
+			irda_task_delete(task);
+			return TRUE;
 		}			
 	} while ((timeout == 0) && (task->state != IRDA_TASK_DONE));
 
 	if (timeout < 0) {
 		ERROR(__FUNCTION__ "(), Error executing task!\n");
-		return -1;
+		irda_task_delete(task);
+		return TRUE;
 	}
 
 	/* Check if we are finished */
@@ -311,20 +333,18 @@
 				irda_task_kick(task->parent);
 			}
 		}		
-		/* Unregister task */
-		hashbin_remove(tasks, (int) task, NULL);
-
-		kfree(task);
+		irda_task_delete(task);
 	} else if (timeout > 0) {
 		irda_start_timer(&task->timer, timeout, (void *) task, 
 				 irda_task_timer_expired);
-		ret = 1;
+		finished = FALSE;
 	} else {
-		IRDA_DEBUG(0, __FUNCTION__ "(), not finished, and no timeout!\n");
-		ret = 1;
+		IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), not finished, and no timeout!\n");
+		finished = FALSE;
 	}
 
-	return ret;
+	return finished;
 }
 
 /*
@@ -335,25 +355,26 @@
  *    called from interrupt context, so it's not possible to use
  *    schedule_timeout() 
  */
-int irda_task_execute(void *instance, TASK_CALLBACK function, 
-		      TASK_CALLBACK finished, struct irda_task *parent, 
-		      void *param)
+struct irda_task *irda_task_execute(void *instance, TASK_CALLBACK function, 
+				    TASK_CALLBACK finished, 
+				    struct irda_task *parent, void *param)
 {
 	struct irda_task *task;
+	int ret;
 
 	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	task = kmalloc(sizeof(struct irda_task), GFP_ATOMIC);
 	if (!task)
-		return -ENOMEM;
+		return NULL;
 
-	task->state = IRDA_TASK_INIT;
+	task->state    = IRDA_TASK_INIT;
 	task->instance = instance;
 	task->function = function;
 	task->finished = finished;
-	task->parent = parent;
-	task->param = param;	
-	task->magic = IRDA_TASK_MAGIC;
+	task->parent   = parent;
+	task->param    = param;	
+	task->magic    = IRDA_TASK_MAGIC;
 
 	init_timer(&task->timer);
 
@@ -361,7 +382,11 @@
 	hashbin_insert(tasks, (queue_t *) task, (int) task, NULL);
 
 	/* No time to waste, so lets get going! */
-	return irda_task_kick(task);
+	ret = irda_task_kick(task);
+	if (ret)
+		return NULL;
+	else
+		return task;
 }
 
 /*
@@ -394,7 +419,7 @@
         dev->hard_header_len = 0;
         dev->addr_len        = 0;
 
-	dev->new_style       = 1;
+	/* dev->new_style       = 1; */
 	/* dev->destructor      = irda_device_destructor; */
 
         dev->type            = ARPHRD_IRDA;
@@ -456,6 +481,8 @@
 	if (!dongle)
 		return NULL;
 
+	memset(dongle, 0, sizeof(dongle_t));
+
 	/* Bind the registration info to this particular instance */
 	dongle->issue = reg;
 	dongle->dev = dev;
@@ -518,12 +545,13 @@
 }
 
 /*
- * Function irda_device_set_raw_mode (self, mode)
- *
- *    
+ * Function irda_device_set_mode (self, mode)
  *
+ *    Set the Infrared device driver into mode where it sends and receives
+ *    data without using IrLAP framing. Check out the particular device
+ *    driver to find out which modes it support.
  */
-int irda_device_set_raw_mode(struct net_device* dev, int mode)
+int irda_device_set_mode(struct net_device* dev, int mode)
 {	
 	struct if_irda_req req;
 	int ret;
@@ -536,9 +564,9 @@
 		return -1;
 	}
 	
-	req.ifr_raw_mode = mode;
+	req.ifr_mode = mode;
 
-	ret = dev->do_ioctl(dev, (struct ifreq *) &req, SIOCSRAWMODE);
+	ret = dev->do_ioctl(dev, (struct ifreq *) &req, SIOCSMODE);
 	
 	return ret;
 }
@@ -546,7 +574,7 @@
 /*
  * Function setup_dma (idev, buffer, count, mode)
  *
- *    Setup the DMA channel
+ *    Setup the DMA channel. Commonly used by ISA FIR drivers
  *
  */
 void setup_dma(int channel, char *buffer, int count, int mode)
diff -u --recursive --new-file v2.3.34/linux/net/irda/iriap.c linux/net/irda/iriap.c
--- v2.3.34/linux/net/irda/iriap.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/iriap.c	Tue Dec 21 10:17:58 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:   Fri Nov  5 20:25:42 1999
+ * Modified at:   Fri Dec 17 15:58:16 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -61,6 +61,7 @@
 extern char *lmp_reasons[];
 
 static void __iriap_close(struct iriap_cb *self);
+static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode);
 static void iriap_disconnect_indication(void *instance, void *sap, 
 					LM_REASON reason, struct sk_buff *skb);
 static void iriap_connect_indication(void *instance, void *sap, 
@@ -82,8 +83,9 @@
  */
 int __init iriap_init(void)
 {
-	__u16 hints;
 	struct ias_object *obj;
+	struct iriap_cb *server;
+	__u16 hints;
 
 	/* Allocate master array */
 	iriap = hashbin_new(HB_LOCAL);
@@ -114,8 +116,13 @@
 	 *  Register server support with IrLMP so we can accept incoming 
 	 *  connections 
 	 */
-	iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
-	
+	server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
+	if (!server) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to open server\n");
+		return -1;
+	}
+	iriap_register_lsap(server, LSAP_IAS, IAS_SERVER);
+
 	return 0;
 }
 
@@ -142,10 +149,8 @@
 			    CONFIRM_CALLBACK callback)
 {
 	struct iriap_cb *self;
-	struct lsap_cb *lsap;
-	notify_t notify;
 
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	self = kmalloc(sizeof(struct iriap_cb), GFP_ATOMIC);
 	if (!self) {
@@ -157,36 +162,18 @@
 	 *  Initialize instance
 	 */
 	memset(self, 0, sizeof(struct iriap_cb));
-
-	irda_notify_init(&notify);
-	notify.connect_confirm       = iriap_connect_confirm;
-	notify.connect_indication    = iriap_connect_indication;
-	notify.disconnect_indication = iriap_disconnect_indication;
-	notify.data_indication       = iriap_data_indication;
-	notify.instance = self;
-	if (mode == IAS_CLIENT)
-		strcpy(notify.name, "IrIAS cli");
-	else
-		strcpy(notify.name, "IrIAS srv");
-
-	lsap = irlmp_open_lsap(slsap_sel, &notify);
-	if (lsap == NULL) {
-		ERROR(__FUNCTION__ "(), Unable to allocated LSAP!\n");
-		return NULL;
-	}
-	slsap_sel = lsap->slsap_sel;
 	
 	self->magic = IAS_MAGIC;
-	self->lsap = lsap;
-	self->slsap_sel = slsap_sel;
 	self->mode = mode;
+	if (mode == IAS_CLIENT)
+		iriap_register_lsap(self, slsap_sel, mode);
 
 	self->confirm = callback;
 	self->priv = priv;
 
 	init_timer(&self->watchdog_timer);
 
-	hashbin_insert(iriap, (queue_t *) self, slsap_sel, NULL);
+	hashbin_insert(iriap, (queue_t *) self, (int) self, NULL);
 	
 	/* Initialize state machines */
 	iriap_next_client_state(self, S_DISCONNECT);
@@ -226,6 +213,8 @@
 {
 	struct iriap_cb *entry;
 
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
 
@@ -234,13 +223,39 @@
 		self->lsap = NULL;
 	}
 
-	entry = (struct iriap_cb *) hashbin_remove(iriap, self->slsap_sel, 
-						   NULL);
+	entry = (struct iriap_cb *) hashbin_remove(iriap, (int) self, NULL);
 	ASSERT(entry == self, return;);
 
 	__iriap_close(self);
 }
 
+static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
+{
+	notify_t notify;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+	irda_notify_init(&notify);
+	notify.connect_confirm       = iriap_connect_confirm;
+	notify.connect_indication    = iriap_connect_indication;
+	notify.disconnect_indication = iriap_disconnect_indication;
+	notify.data_indication       = iriap_data_indication;
+	notify.instance = self;
+	if (mode == IAS_CLIENT)
+		strcpy(notify.name, "IrIAS cli");
+	else
+		strcpy(notify.name, "IrIAS srv");
+
+	self->lsap = irlmp_open_lsap(slsap_sel, &notify, 0);
+	if (self->lsap == NULL) {
+		ERROR(__FUNCTION__ "(), Unable to allocated LSAP!\n");
+		return -1;
+	}
+	self->slsap_sel = self->lsap->slsap_sel;
+
+	return 0;
+}
+
 /*
  * Function iriap_disconnect_indication (handle, reason)
  *
@@ -465,6 +480,10 @@
 			IRDA_DEBUG(0, __FUNCTION__
 				   "(), charset %s, not supported\n",
 				   ias_charset_types[charset]);
+
+			/* Aborting, close connection! */
+			iriap_disconnect_request(self);
+			dev_kfree_skb(skb);
 			return;
 			/* break; */
 		}
@@ -487,7 +506,7 @@
 		value = irias_new_octseq_value(fp+n, value_len);
 		break;
 	default:
-		value = &missing;
+		value = irias_new_missing_value();
 		break;
 	}
 	
@@ -499,6 +518,11 @@
 	 */
 	if (self->confirm)
 		self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler!\n");
+		irias_delete_value(value);
+	}
+	dev_kfree_skb(skb);
 }
 
 /*
@@ -527,10 +551,10 @@
 
 	/* 
 	 *  We must adjust the size of the response after the length of the 
-	 *  value. We add 9 bytes because of the 6 bytes for the frame and
-	 *  max 3 bytes for the value coding.
+	 *  value. We add 32 bytes because of the 6 bytes for the frame and
+	 *  max 5 bytes for the value coding.
 	 */
-	skb = dev_alloc_skb(value->len + self->max_header_size + 9);
+	skb = dev_alloc_skb(value->len + self->max_header_size + 32);
 	if (!skb)
 		return;
 
@@ -577,7 +601,7 @@
 		break;
 	case IAS_MISSING:
 		IRDA_DEBUG( 3, __FUNCTION__ ": sending IAS_MISSING\n");
-		skb_put( skb, 1);
+		skb_put(skb, 1);
 		fp[n++] = value->type;
 		break;
 	default:
@@ -585,6 +609,8 @@
 		break;
 	}
 	iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, skb);
+
+	iriap_close(self);
 }
 
 /*
@@ -631,7 +657,7 @@
 	obj = irias_find_object(name);
 	
 	if (obj == NULL) {
-		IRDA_DEBUG(0, "LM-IAS: Object not found\n");
+		IRDA_DEBUG(2, "LM-IAS: Object not found\n");
 		iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
 					       &missing);
 		return;
@@ -668,7 +694,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 
-	IRDA_DEBUG(6, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
@@ -683,7 +709,9 @@
 	frame = skb->data;
 
 	/* Build frame */
-	frame[0] = IAP_LST | self->operation;
+	frame[0] = IAP_LST | IAP_ACK | self->operation;
+
+	irlmp_data_request(self->lsap, skb);
 }
 
 /*
@@ -693,8 +721,8 @@
  *
  */
 static void iriap_connect_confirm(void *instance, void *sap, 
-				  struct qos_info *qos, 
-				  __u32 max_sdu_size, __u8 header_size, 
+				  struct qos_info *qos, __u32 max_seg_size, 
+				  __u8 max_header_size, 
 				  struct sk_buff *userdata)
 {
 	struct iriap_cb *self;
@@ -705,11 +733,14 @@
 	ASSERT(self->magic == IAS_MAGIC, return;);
 	ASSERT(userdata != NULL, return;);
 	
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	self->max_data_size = max_seg_size;
+	self->max_header_size = max_header_size;
 	
 	del_timer(&self->watchdog_timer);
 
-	iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata);
+	iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, NULL);
+
+	dev_kfree_skb(userdata);
 }
 
 /*
@@ -719,18 +750,43 @@
  *
  */
 static void iriap_connect_indication(void *instance, void *sap, 
-				     struct qos_info *qos, __u32 max_sdu_size,
-				     __u8 header_size, 
+				     struct qos_info *qos, __u32 max_seg_size,
+				     __u8 max_header_size, 
 				     struct sk_buff *userdata)
 {
-	struct iriap_cb *self;
+	struct iriap_cb *self, *new;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	self = (struct iriap_cb *) instance;
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
+	
+	/* Start new server */
+	new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL); 
+	if (!new) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), open failed\n");
+		dev_kfree_skb(userdata);
+		return;
+	}
+	
+	/* Now attach up the new "socket" */
+	new->lsap = irlmp_dup(self->lsap, new);
+	if (!new->lsap) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), dup failed!\n");
+		return;
+	}
+		
+	new->max_data_size = max_seg_size;
+	new->max_header_size = max_header_size;
 
-	iriap_do_server_event(self, IAP_LM_CONNECT_INDICATION, userdata);
+	/* Clean up the original one to keep it in listen state */
+	self->lsap->dlsap_sel = LSAP_ANY;
+	self->lsap->lsap_state = LSAP_DISCONNECTED;
+	/* FIXME: refcount in irlmp might get wrong */
+	
+	iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, userdata);
 }
  
 /*
@@ -746,7 +802,7 @@
 	__u8  *frame;
 	__u8  opcode;
 	
-	IRDA_DEBUG( 4, __FUNCTION__ "()\n"); 
+	IRDA_DEBUG(3, __FUNCTION__ "()\n"); 
 	
 	self = (struct iriap_cb *) instance;
 
@@ -768,12 +824,14 @@
 	if (~opcode & IAP_LST) {
 		WARNING(__FUNCTION__ "(), IrIAS multiframe commands or "
 			"results is not implemented yet!\n");
+		dev_kfree_skb(skb);
 		return 0;
 	}
 	
 	/* Check for ack frames since they don't contain any data */
 	if (opcode & IAP_ACK) {
 		IRDA_DEBUG(0, __FUNCTION__ "() Got ack frame!\n");
+		dev_kfree_skb(skb);
 	 	return 0;
 	}
 
@@ -782,9 +840,10 @@
 	switch (opcode) {
 	case GET_INFO_BASE:
 		IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
+		dev_kfree_skb(skb);
 		break;
 	case GET_VALUE_BY_CLASS:
-		iriap_do_call_event(self, IAP_RECV_F_LST, skb);
+		iriap_do_call_event(self, IAP_RECV_F_LST, NULL);
 			
 		switch (frame[1]) {
 		case IAS_SUCCESS:
@@ -802,6 +861,7 @@
 			if (self->confirm)
 				self->confirm(IAS_CLASS_UNKNOWN, 0, NULL, 
 					      self->priv);
+			dev_kfree_skb(skb);
 			break;
 		case IAS_ATTRIB_UNKNOWN:
 			WARNING(__FUNCTION__ "(), No such attribute!\n");
@@ -815,12 +875,14 @@
 			if (self->confirm)
 				self->confirm(IAS_CLASS_UNKNOWN, 0, NULL, 
 					      self->priv);
+			dev_kfree_skb(skb);
 			break;
 		}		
 		break;
 	default:
 		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n", 
 			   opcode);
+		dev_kfree_skb(skb);
 		break;
 	}
 	return 0;
diff -u --recursive --new-file v2.3.34/linux/net/irda/iriap_event.c linux/net/irda/iriap_event.c
--- v2.3.34/linux/net/irda/iriap_event.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/iriap_event.c	Tue Dec 21 10:17:58 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 Oct 31 22:13:00 1999
+ * Modified at:   Fri Dec 17 15:59:13 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -42,29 +42,29 @@
 static void state_s_outstanding  (struct iriap_cb *self, IRIAP_EVENT event, 
 				  struct sk_buff *skb);
 static void state_s_replying     (struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
+				  struct sk_buff *skb);
 static void state_s_wait_for_call(struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
+				  struct sk_buff *skb);
 static void state_s_wait_active  (struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
+				  struct sk_buff *skb);
 
 static void state_r_disconnect   (struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
+				  struct sk_buff *skb);
 static void state_r_call         (struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
+				  struct sk_buff *skb);
 static void state_r_waiting      (struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
+				  struct sk_buff *skb);
 static void state_r_wait_active  (struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
+				  struct sk_buff *skb);
 static void state_r_receiving    (struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
+				  struct sk_buff *skb);
 static void state_r_execute      (struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
+				  struct sk_buff *skb);
 static void state_r_returning    (struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb);
+				  struct sk_buff *skb);
 
 static void (*iriap_state[])(struct iriap_cb *self, IRIAP_EVENT event, 
-			      struct sk_buff *skb) = { 
+			     struct sk_buff *skb) = { 
 	/* Client FSM */
 	state_s_disconnect,
 	state_s_connecting,
@@ -141,7 +141,7 @@
 }
 
 void iriap_do_server_event(struct iriap_cb *self, IRIAP_EVENT event, 
-			    struct sk_buff *skb) 
+			   struct sk_buff *skb) 
 {
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
@@ -178,8 +178,8 @@
 		iriap_next_client_state(self, S_CONNECTING);
 		self->skb = skb;
 		ret = irlmp_connect_request(self->lsap, LSAP_IAS, 
-					     self->saddr, self->daddr, 
-					     NULL, NULL);
+					    self->saddr, self->daddr, 
+					    NULL, NULL);
 		break;
 	case IAP_LM_DISCONNECT_INDICATION:
 		break;
@@ -206,7 +206,7 @@
 		/*
 		 *  Jump to S-Call FSM
 		 */
-		iriap_do_call_event(self, IAP_CALL_REQUEST, skb);
+		iriap_do_call_event(self, IAP_CALL_REQUEST, NULL);
 		/* iriap_call_request(self, 0,0,0); */
 		iriap_next_client_state(self, S_CALL);
 		break;
@@ -258,15 +258,16 @@
 
 	switch (event) {
 	case IAP_CALL_REQUEST:
-		irlmp_data_request(self->lsap, self->skb);
+		skb = self->skb;
+		self->skb = NULL;
+
+		irlmp_data_request(self->lsap, skb);
 		iriap_next_call_state(self, S_OUTSTANDING);
 		break;
 	default:
 		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %d\n", event);
 		break;
 	}
-	if (skb)
-		dev_kfree_skb(skb);
 }
 
 /*
@@ -297,7 +298,6 @@
 		iriap_send_ack(self);
 		/*LM_Idle_request(idle); */
 
-		dev_kfree_skb(skb);
 		iriap_next_call_state(self, S_WAIT_FOR_CALL);
 		break;
 	default:
@@ -324,7 +324,7 @@
  *
  */
 static void state_s_wait_for_call(struct iriap_cb *self, IRIAP_EVENT event, 
-				   struct sk_buff *skb) 
+				  struct sk_buff *skb) 
 {
 	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented\n");
 }
@@ -400,14 +400,13 @@
 static void state_r_call(struct iriap_cb *self, IRIAP_EVENT event, 
 			 struct sk_buff *skb) 
 {
-	IRDA_DEBUG(4, "state_r_call()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	switch (event) {
 	case IAP_LM_DISCONNECT_INDICATION:
 		/* Abort call */
 		iriap_next_server_state(self, R_DISCONNECT);
-		iriap_next_r_connect_state(self, R_WAITING);
-		
+		iriap_next_r_connect_state(self, R_WAITING);		
 		break;
 	default:
 		IRDA_DEBUG(0, __FUNCTION__ "(), unknown event!\n");
@@ -431,8 +430,8 @@
 	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented\n");
 }
 
-static void state_r_wait_active(struct iriap_cb *self, 
-				 IRIAP_EVENT event, struct sk_buff *skb) 
+static void state_r_wait_active(struct iriap_cb *self, IRIAP_EVENT event, 
+				struct sk_buff *skb) 
 {
 	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented\n");
 }
diff -u --recursive --new-file v2.3.34/linux/net/irda/irias_object.c linux/net/irda/irias_object.c
--- v2.3.34/linux/net/irda/irias_object.c	Wed Oct 27 16:34:12 1999
+++ linux/net/irda/irias_object.c	Tue Dec 21 10:17:58 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct  1 22:50:04 1998
- * Modified at:   Sat Oct  9 17:11:16 1999
+ * Modified at:   Wed Dec 15 11:23:16 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -34,7 +34,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)
@@ -72,8 +72,8 @@
 	
 	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
-	obj = (struct ias_object *) kmalloc( sizeof( struct ias_object), 
-					     GFP_ATOMIC);
+	obj = (struct ias_object *) kmalloc(sizeof(struct ias_object), 
+					    GFP_ATOMIC);
 	if (obj == NULL) {
 		IRDA_DEBUG(0, __FUNCTION__ "(), Unable to allocate object!\n");
 		return NULL;
@@ -364,7 +364,7 @@
 {
 	struct ias_value *value;
 
-	value = kmalloc(sizeof( struct ias_value), GFP_ATOMIC);
+	value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
 	if (value == NULL) {
 		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
@@ -419,7 +419,7 @@
 		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
-	memset(value, 0, sizeof( struct ias_value));
+	memset(value, 0, sizeof(struct ias_value));
 
 	value->type = IAS_OCT_SEQ;
 	value->len = len;
@@ -430,6 +430,23 @@
 		return NULL;
 	}
 	memcpy(value->t.oct_seq, octseq , len);
+	return value;
+}
+
+struct ias_value *irias_new_missing_value(void)
+{
+	struct ias_value *value;
+
+	value = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
+	if (value == NULL) {
+		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
+		return NULL;
+	}
+	memset(value, 0, sizeof(struct ias_value));
+
+	value->type = IAS_MISSING;
+	value->len = 0;
+
 	return value;
 }
 
diff -u --recursive --new-file v2.3.34/linux/net/irda/irlan/irlan_client.c linux/net/irda/irlan/irlan_client.c
--- v2.3.34/linux/net/irda/irlan/irlan_client.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/irlan/irlan_client.c	Tue Dec 21 10:17:58 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 Oct 31 19:44:41 1999
+ * Modified at:   Tue Dec 14 15:47:02 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>
@@ -584,16 +584,7 @@
 					      NULL);
 			return;
 		}
-		break;
-	case IAS_STRING:
-		IRDA_DEBUG(2, __FUNCTION__ "(), got string %s\n", 
-			   value->t.string);
-		break;
-	case IAS_OCT_SEQ:
-		IRDA_DEBUG(2, __FUNCTION__ "(), OCT_SEQ not implemented\n");
-		break;
-	case IAS_MISSING:
-		IRDA_DEBUG(2, __FUNCTION__ "(), MISSING not implemented\n");
+		irias_delete_value(value);
 		break;
 	default:
 		IRDA_DEBUG(2, __FUNCTION__ "(), unknown type!\n");
diff -u --recursive --new-file v2.3.34/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
--- v2.3.34/linux/net/irda/irlan/irlan_common.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/irlan/irlan_common.c	Tue Dec 21 10:17:58 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 Oct 31 19:43:50 1999
+ * Modified at:   Thu Dec 16 21:16:14 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
diff -u --recursive --new-file v2.3.34/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c
--- v2.3.34/linux/net/irda/irlan/irlan_eth.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/irlan/irlan_eth.c	Tue Dec 21 10:17:58 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:   Sat Oct 30 12:58:30 1999
+ * Modified at:   Thu Dec 16 21:21:53 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>
@@ -348,6 +348,7 @@
 		return;
 	read_lock(&in_dev->lock);
 	if (in_dev->ifa_list)
+		
 	arp_send(ARPOP_REQUEST, ETH_P_ARP, 
 		 in_dev->ifa_list->ifa_address,
 		 dev, 
diff -u --recursive --new-file v2.3.34/linux/net/irda/irlap.c linux/net/irda/irlap.c
--- v2.3.34/linux/net/irda/irlap.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/irlap.c	Tue Dec 21 10:17:58 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:   Tue Nov 16 10:01:06 1999
+ * Modified at:   Thu Dec 16 22:59:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -131,22 +131,14 @@
 	irlap_next_state(self, LAP_OFFLINE);
 
 	/* Initialize transmit queue */
-	skb_queue_head_init(&self->tx_list);
+	skb_queue_head_init(&self->txq);
+	skb_queue_head_init(&self->txq_ultra);
 	skb_queue_head_init(&self->wx_list);
 
 	/* My unique IrLAP device address! */
 	get_random_bytes(&self->saddr, sizeof(self->saddr));
 	memcpy(dev->dev_addr, &self->saddr, 4);
 
-	/* 
-	 * Generate random connection address for this session, which must
-	 * be 7 bits wide and different from 0x00 and 0xfe 
-	 */
-	while ((self->caddr == 0x00) || (self->caddr == 0xfe)) {
-		get_random_bytes(&self->caddr, sizeof(self->caddr));
-		self->caddr &= 0xfe;
-	}
-
 	init_timer(&self->slot_timer);
 	init_timer(&self->query_timer);
 	init_timer(&self->discovery_timer);
@@ -157,6 +149,8 @@
 	init_timer(&self->media_busy_timer);	
 
 	irlap_apply_default_connection_parameters(self);
+
+	self->N3 = 3; /* # connections attemts to try before giving up */
 	
 	irlap_next_state(self, LAP_NDM);
 
@@ -308,7 +302,8 @@
  *    IrLMP for further processing
  *
  */
-inline void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb) 
+void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb,
+			   int unreliable) 
 {
 	/* Hide LAP header from IrLMP layer */
 	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
@@ -322,38 +317,9 @@
 		}
 	}
 #endif
-	irlmp_link_data_indication(self->notify.instance, LAP_RELIABLE, skb);
+	irlmp_link_data_indication(self->notify.instance, skb, unreliable);
 }
 
-/*
- * Function irlap_unit_data_indication (self, skb)
- *
- *    Received some data that was sent unreliable
- *
- */
-void irlap_unit_data_indication(struct irlap_cb *self, struct sk_buff *skb)
-{
-	IRDA_DEBUG(1, __FUNCTION__ "()\n"); 
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == LAP_MAGIC, return;);
-	ASSERT(skb != NULL, return;);
-
-	/* Hide LAP header from IrLMP layer */
-	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
-
-#ifdef CONFIG_IRDA_COMPRESSION
-	if (self->qos_tx.compression.value) {
-		
-		skb = irlap_decompress_frame(self, skb);
-		if (!skb) {
-			IRDA_DEBUG(1, __FUNCTION__ "(), Decompress error!\n");
-			return;
-		}
-	}
-#endif
-	irlmp_link_data_indication(self->notify.instance, LAP_UNRELIABLE, skb);
-}
 
 /*
  * Function irlap_data_request (self, skb)
@@ -361,12 +327,14 @@
  *    Queue data for transmission, must wait until XMIT state
  *
  */
-inline void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb,
-			       int reliable)
+void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb, 
+			int unreliable)
 {
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
+
 #ifdef CONFIG_IRDA_COMPRESSION
 	if (self->qos_tx.compression.value) {
 		skb = irlap_compress_frame(self, skb);
@@ -376,7 +344,6 @@
 		}
 	}
 #endif
-	
 	ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 
 	       return;);
 	skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
@@ -385,12 +352,10 @@
 	 *  Must set frame format now so that the rest of the code knows 
 	 *  if its dealing with an I or an UI frame
 	 */
-	if (reliable)
-		skb->data[1] = I_FRAME;
-	else {
-		IRDA_DEBUG(4, __FUNCTION__ "(), queueing unreliable frame\n");
+	if (unreliable)
 		skb->data[1] = UI_FRAME;
-	}
+	else
+		skb->data[1] = I_FRAME;
 
 	/* 
 	 *  Send event if this frame only if we are in the right state 
@@ -401,18 +366,67 @@
 		 *  Check if the transmit queue contains some unsent frames,
 		 *  and if so, make sure they are sent first
 		 */
-		if (!skb_queue_empty(&self->tx_list)) {
-			skb_queue_tail(&self->tx_list, skb);
-			skb = skb_dequeue(&self->tx_list);
+		if (!skb_queue_empty(&self->txq)) {
+			skb_queue_tail(&self->txq, skb);
+			skb = skb_dequeue(&self->txq);
 			
 			ASSERT(skb != NULL, return;);
 		}
 		irlap_do_event(self, SEND_I_CMD, skb, NULL);
 	} else
-		skb_queue_tail(&self->tx_list, skb);
+		skb_queue_tail(&self->txq, skb);
 }
 
 /*
+ * Function irlap_unitdata_request (self, skb)
+ *
+ *    Send Ultra data. This is data that must be sent outside any connection
+ *
+ */
+#ifdef CONFIG_IRDA_ULTRA
+void irlap_unitdata_request(struct irlap_cb *self, struct sk_buff *skb)
+{
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+
+	IRDA_DEBUG(3, __FUNCTION__ "()\n");
+
+	ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 
+	       return;);
+	skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+
+	skb->data[0] = CBROADCAST;
+	skb->data[1] = UI_FRAME;
+
+	skb_queue_tail(&self->txq_ultra, skb);
+
+	irlap_do_event(self, SEND_UI_FRAME, NULL, NULL);
+}
+#endif /*CONFIG_IRDA_ULTRA */
+
+/*
+ * Function irlap_udata_indication (self, skb)
+ *
+ *    Receive Ultra data. This is data that is received outside any connection
+ *
+ */
+#ifdef CONFIG_IRDA_ULTRA
+void irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb)
+{
+	IRDA_DEBUG(1, __FUNCTION__ "()\n"); 
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+
+	/* Hide LAP header from IrLMP layer */
+	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+
+	irlmp_link_unitdata_indication(self->notify.instance, skb);
+}
+#endif /* CONFIG_IRDA_ULTRA */
+
+/*
  * Function irlap_disconnect_request (void)
  *
  *    Request to disconnect connection by service user
@@ -425,7 +439,7 @@
 	ASSERT(self->magic == LAP_MAGIC, return;);
 	
 	/* Don't disconnect until all data frames are successfully sent */
-	if (skb_queue_len(&self->tx_list) > 0) {
+	if (skb_queue_len(&self->txq) > 0) {
 		self->disconnect_pending = TRUE;
 		
 		return;
@@ -466,7 +480,7 @@
 	/* Flush queues */
 	irlap_flush_all_queues(self);
 	
-	switch(reason) {
+	switch (reason) {
 	case LAP_RESET_INDICATION:
 		IRDA_DEBUG(1, __FUNCTION__ "(), Sending reset request!\n");
 		irlap_do_event(self, RESET_REQUEST, NULL, NULL);
@@ -479,8 +493,7 @@
 						 reason, NULL);
 		break;
 	default:
-		IRDA_DEBUG(1, __FUNCTION__ "(), Reason %d not implemented!\n", 
-		       reason);
+		ERROR(__FUNCTION__ "(), Unknown reason %d\n", reason);
 	}
 }
 
@@ -504,48 +517,47 @@
 	       (discovery->nslots == 8) || (discovery->nslots == 16), 
 	       return;);
 	
+  	/* Discovery is only possible in NDM mode */
+	if (self->state != LAP_NDM) {
+		IRDA_DEBUG(4, __FUNCTION__ 
+			   "(), discovery only possible in NDM mode\n");
+		irlap_discovery_confirm(self, NULL);
+		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) {
-		self->discovery_log= hashbin_new(HB_LOCAL);
-		
-		info.S = discovery->nslots; /* Number of slots */
-		info.s = 0; /* Current slot */
-		
-		self->discovery_cmd = discovery;
-		info.discovery = discovery;
-		
-		/* Check if the slot timeout is within limits */
-		if (sysctl_slot_timeout < 20) {
-			ERROR(__FUNCTION__ 
-			      "(), to low value for slot timeout!\n");
-			sysctl_slot_timeout = 20;
-		}
-		/* 
-		 * Highest value is actually 8, but we allow higher since
-		 * some devices seems to require it.
-		 */
-		if (sysctl_slot_timeout > 160) {
-			ERROR(__FUNCTION__ 
-			      "(), to high value for slot timeout!\n");
-			sysctl_slot_timeout = 160;
-		}
-
-		self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
-		
-		irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
-	} else { 
- 		IRDA_DEBUG(4, __FUNCTION__ 
-		       "(), discovery only possible in NDM mode\n");
-		irlap_discovery_confirm(self, NULL);
- 	} 
+	
+	self->discovery_log= hashbin_new(HB_LOCAL);
+	
+	info.S = discovery->nslots; /* Number of slots */
+	info.s = 0; /* Current slot */
+	
+	self->discovery_cmd = discovery;
+	info.discovery = discovery;
+	
+	/* Check if the slot timeout is within limits */
+	if (sysctl_slot_timeout < 20) {
+		ERROR(__FUNCTION__ 
+		      "(), to low value for slot timeout!\n");
+		sysctl_slot_timeout = 20;
+	}
+	/* 
+	 * Highest value is actually 8, but we allow higher since
+	 * some devices seems to require it.
+	 */
+	if (sysctl_slot_timeout > 160) {
+		ERROR(__FUNCTION__ 
+		      "(), to high value for slot timeout!\n");
+		sysctl_slot_timeout = 160;
+	}
+	
+	self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
+	
+	irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
 }
 
 /*
@@ -790,17 +802,16 @@
  */
 void irlap_wait_min_turn_around(struct irlap_cb *self, struct qos_info *qos) 
 {
+	__u32 min_turn_time;
 	__u32 speed;
-	__u32 usecs;
-	__u32 bytes ;
 	
 	/* Get QoS values.  */
 	speed = qos->baud_rate.value;
-	usecs = qos->min_turn_time.value;
+	min_turn_time = qos->min_turn_time.value;
 
 	/* No need to calculate XBOFs for speeds over 115200 bps */
 	if (speed > 115200) {
-		self->mtt_required = usecs;
+		self->mtt_required = min_turn_time;
 		return;
 	}
 	
@@ -809,9 +820,7 @@
 	 *  min turn time, so now we must calculate how many chars (XBOF's) we 
 	 *  must send for the requested time period (min turn time)
 	 */
-	bytes = speed * usecs / 10000000;
-
-	self->xbofs_delay = bytes;
+	self->xbofs_delay = irlap_min_turn_time_in_bytes(speed, min_turn_time);
 }
 
 /*
@@ -828,9 +837,12 @@
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
 	/* Free transmission queue */
-	while ((skb = skb_dequeue(&self->tx_list)) != NULL)
+	while ((skb = skb_dequeue(&self->txq)) != NULL)
 		dev_kfree_skb(skb);
 	
+	while ((skb = skb_dequeue(&self->txq_ultra)) != NULL)
+		dev_kfree_skb(skb);
+
 	/* Free sliding window buffered packets */
 	while ((skb = skb_dequeue(&self->wx_list)) != NULL)
 		dev_kfree_skb(skb);
@@ -872,7 +884,7 @@
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
-
+	
 	/* 
 	 *  Find out which compressors we support. We do this be checking that
 	 *  the corresponding compressor for each bit set in the QoS bits has 
@@ -888,17 +900,17 @@
 			IRDA_DEBUG(4, __FUNCTION__ 
 				   "(), bit %d is set by defalt\n", 8-i);
 			comp = hashbin_find(irlap_compressors, 
-					    compression[msb_index(mask)], 
+					    compressions[msb_index(mask)], 
 					    NULL);
 			if (!comp) {
 				/* Protocol not supported, so clear the bit */
 				IRDA_DEBUG(4, __FUNCTION__ "(), Compression "
-				       "protocol %d has not been loaded!\n", 
-				       compression[msb_index(mask)]);
+					   "protocol %d has not been loaded!\n", 
+					   compressions[msb_index(mask)]);
 				self->qos_rx.compression.bits &= ~mask;
 				IRDA_DEBUG(4, __FUNCTION__ 
-				       "(), comp bits 0x%02x\n", 
-				       self->qos_rx.compression.bits); 
+					   "(), comp bits 0x%02x\n", 
+					   self->qos_rx.compression.bits); 
 			}
 		}
 		/* Try the next bit */
@@ -955,17 +967,11 @@
 #endif
 	}
 
-	/* 
-	 *  Make the intersection between IrLAP and drivers QoS
-	 *  capabilities 
-	 */
-
 	/* Use 500ms in IrLAP for now */
-	self->qos_rx.max_turn_time.bits &= 0x03;
 	self->qos_rx.max_turn_time.bits &= 0x01;
 
 	/* Set data size */
-	/* self->qos_rx.data_size.bits &= 0x03; */
+	/*self->qos_rx.data_size.bits &= 0x03;*/
 
 	/* Set disconnect time */
 	self->qos_rx.link_disc_time.bits &= 0x07;
@@ -988,21 +994,47 @@
 
 	irlap_change_speed(self, 9600, TRUE);
 
+	/* Set mbusy when going to NDM state */
+	irda_device_set_media_busy(self->netdev, TRUE);
+
 	/* Default value in NDM */
 	self->bofs_count = 11;
 
-	/* Use these until connection has been made */
+	/* 
+	 * Generate random connection address for this session, which must
+	 * be 7 bits wide and different from 0x00 and 0xfe 
+	 */
+	while ((self->caddr == 0x00) || (self->caddr == 0xfe)) {
+		get_random_bytes(&self->caddr, sizeof(self->caddr));
+		self->caddr &= 0xfe;
+	}
+
+	/* Use default values until connection has been negitiated */
 	self->slot_timeout = sysctl_slot_timeout;
 	self->final_timeout = FINAL_TIMEOUT;
 	self->poll_timeout = POLL_TIMEOUT;
 	self->wd_timeout = WD_TIMEOUT;
 
+	/* Set some default values */
+	self->qos_tx.baud_rate.value = 9600;
+	self->qos_rx.baud_rate.value = 9600;
+	self->qos_tx.max_turn_time.value = 0;
+	self->qos_rx.max_turn_time.value = 0;
+	self->qos_tx.min_turn_time.value = 0;
+	self->qos_rx.min_turn_time.value = 0;
 	self->qos_tx.data_size.value = 64;
+	self->qos_rx.data_size.value = 64;
+	self->qos_tx.window_size.value = 1;
+	self->qos_rx.window_size.value = 1;
 	self->qos_tx.additional_bofs.value = 11;
+	self->qos_rx.additional_bofs.value = 11;
+	self->qos_tx.link_disc_time.value = 0;
+	self->qos_rx.link_disc_time.value = 0;
 
 	irlap_flush_all_queues(self);
 
 	self->disconnect_pending = FALSE;
+	self->connect_pending = FALSE;
 }
 
 /*
@@ -1011,56 +1043,62 @@
  *    Initialize IrLAP with the negotiated QoS values
  *
  */
-void irlap_apply_connection_parameters(struct irlap_cb *self, 
-				       struct qos_info *qos) 
+void irlap_apply_connection_parameters(struct irlap_cb *self) 
 {
 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	irlap_change_speed(self, qos->baud_rate.value, FALSE);
+	irlap_change_speed(self, self->qos_tx.baud_rate.value, FALSE);
 
-	self->window_size = qos->window_size.value;
-	self->window      = qos->window_size.value;
-	self->bofs_count  = qos->additional_bofs.value;
+	self->window_size = self->qos_tx.window_size.value;
+	self->window      = self->qos_tx.window_size.value;
+	self->bofs_count  = self->qos_tx.additional_bofs.value;
 
 	/*
 	 *  Calculate how many bytes it is possible to transmit before the
-	 *  link must be turned around wb = baud * mtt/1000 * 1/2
+	 *  link must be turned around
 	 */
-	self->window_bytes = qos->baud_rate.value 
-		* qos->max_turn_time.value / 10000;
-	IRDA_DEBUG(4, "Setting window_bytes = %d\n", self->window_bytes);
-
+	self->line_capacity = 
+		irlap_max_line_capacity(self->qos_tx.baud_rate.value,
+					self->qos_tx.max_turn_time.value);
 	/*
 	 *  Set N1 to 0 if Link Disconnect/Threshold Time = 3 and set it to 
 	 *  3 seconds otherwise. See page 71 in IrLAP for more details.
 	 *  TODO: these values should be calculated from the final timer
          *  as well
 	 */
-	if (qos->link_disc_time.value == 3)
+	ASSERT(self->qos_tx.max_turn_time.value != 0, return;);
+	if (self->qos_tx.link_disc_time.value == 3)
 		self->N1 = 0;
 	else
-		self->N1 = 3000 / qos->max_turn_time.value;
+		self->N1 = 3000 / self->qos_tx.max_turn_time.value;
 	
 	IRDA_DEBUG(4, "Setting N1 = %d\n", self->N1);
 	
-	self->N2 = qos->link_disc_time.value * 1000 / qos->max_turn_time.value;
+	
+	self->N2 = self->qos_tx.link_disc_time.value * 1000 / 
+		self->qos_tx.max_turn_time.value;
 	IRDA_DEBUG(4, "Setting N2 = %d\n", self->N2);
 
 	/* 
 	 *  Initialize timeout values, some of the rules are listed on 
 	 *  page 92 in IrLAP.
 	 */
-	self->poll_timeout = qos->max_turn_time.value * HZ / 1000;
-	self->final_timeout = qos->max_turn_time.value * HZ / 1000;
+	self->poll_timeout = self->qos_tx.max_turn_time.value * HZ / 1000;
 	self->wd_timeout = self->poll_timeout * 2;
 
+	/* 
+	 * Be careful to keep our promises to the peer device about how long
+	 * time it can keep the pf bit. So here we must use the rx_qos value
+	 */
+	self->final_timeout = self->qos_rx.max_turn_time.value * HZ / 1000;
+
 #ifdef CONFIG_IRDA_COMPRESSION
-	if (qos->compression.value) {
+	if (self->qos_tx.compression.value) {
 		IRDA_DEBUG(1, __FUNCTION__ "(), Initializing compression\n");
-		irda_set_compression(self, qos->compression.value);
+		irda_set_compression(self, self->qos_tx.compression.value);
 
 		irlap_compressor_init(self, 0);
 	}
@@ -1087,7 +1125,7 @@
 
 #ifdef CONFIG_PROC_FS
 /*
- * Function irlap_proc_read (buf, start, offset, len)
+ * Function irlap_proc_read (buf, start, offset, len, unused)
  *
  *    Give some info to the /proc file system
  *
@@ -1110,24 +1148,28 @@
 
 		len += sprintf(buf+len, "irlap%d ", i++);
 		len += sprintf(buf+len, "state: %s\n", 
-				irlap_state[ self->state]);
+			       irlap_state[self->state]);
 		
 		len += sprintf(buf+len, "  caddr: %#02x, ", self->caddr);
 		len += sprintf(buf+len, "saddr: %#08x, ", self->saddr);
 		len += sprintf(buf+len, "daddr: %#08x\n", self->daddr);
 		
 		len += sprintf(buf+len, "  win size: %d, ", 
-				self->window_size);
+			       self->window_size);
 		len += sprintf(buf+len, "win: %d, ", self->window);
-		len += sprintf(buf+len, "win bytes: %d, ", self->window_bytes);
+#if CONFIG_IRDA_DYNAMIC_WINDOW
+		len += sprintf(buf+len, "line capacity: %d, ", 
+			       self->line_capacity);
 		len += sprintf(buf+len, "bytes left: %d\n", self->bytes_left);
-
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
 		len += sprintf(buf+len, "  tx queue len: %d ", 
-				skb_queue_len(&self->tx_list));
+			       skb_queue_len(&self->txq));
 		len += sprintf(buf+len, "win queue len: %d ", 
-				skb_queue_len(&self->wx_list));
-		len += sprintf(buf+len, "rbusy: %s\n", self->remote_busy ? 
-				"TRUE" : "FALSE");
+			       skb_queue_len(&self->wx_list));
+		len += sprintf(buf+len, "rbusy: %s", self->remote_busy ?
+			       "TRUE" : "FALSE");
+		len += sprintf(buf+len, " mbusy: %s\n", self->media_busy ?
+			       "TRUE" : "FALSE");
 		
 		len += sprintf(buf+len, "  retrans: %d ", self->retry_count);
 		len += sprintf(buf+len, "vs: %d ", self->vs);
@@ -1137,42 +1179,42 @@
 		len += sprintf(buf+len, "  qos\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\tcomp\n");
 		
 		len += sprintf(buf+len, "  tx\t%d\t", 
-				self->qos_tx.baud_rate.value);
+			       self->qos_tx.baud_rate.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_tx.max_turn_time.value);
+			       self->qos_tx.max_turn_time.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_tx.data_size.value);
+			       self->qos_tx.data_size.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_tx.window_size.value);
+			       self->qos_tx.window_size.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_tx.additional_bofs.value);
+			       self->qos_tx.additional_bofs.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_tx.min_turn_time.value);
+			       self->qos_tx.min_turn_time.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_tx.link_disc_time.value);
+			       self->qos_tx.link_disc_time.value);
 #ifdef CONFIG_IRDA_COMPRESSION
 		len += sprintf(buf+len, "%d",
-				self->qos_tx.compression.value);
+			       self->qos_tx.compression.value);
 #endif
 		len += sprintf(buf+len, "\n");
 
 		len += sprintf(buf+len, "  rx\t%d\t", 
-				self->qos_rx.baud_rate.value);
+			       self->qos_rx.baud_rate.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_rx.max_turn_time.value);
+			       self->qos_rx.max_turn_time.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_rx.data_size.value);
+			       self->qos_rx.data_size.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_rx.window_size.value);
+			       self->qos_rx.window_size.value);
 		len += sprintf(buf+len, "%d\t",
-				self->qos_rx.additional_bofs.value);
+			       self->qos_rx.additional_bofs.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_rx.min_turn_time.value);
+			       self->qos_rx.min_turn_time.value);
 		len += sprintf(buf+len, "%d\t", 
-				self->qos_rx.link_disc_time.value);
+			       self->qos_rx.link_disc_time.value);
 #ifdef CONFIG_IRDA_COMPRESSION
 		len += sprintf(buf+len, "%d",
-				self->qos_rx.compression.value);
+			       self->qos_rx.compression.value);
 #endif
 		len += sprintf(buf+len, "\n");
 		
diff -u --recursive --new-file v2.3.34/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.3.34/linux/net/irda/irlap_event.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/irlap_event.c	Tue Dec 21 10:17:58 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:   Tue Nov 16 12:33:41 1999
+ * Modified at:   Tue Dec 14 18:58:28 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
@@ -85,6 +85,7 @@
 	"RESET_REQUEST",
 	"RESET_RESPONSE",
 	"SEND_I_CMD",
+	"SEND_UI_FRAME",
 	"RECV_DISCOVERY_XID_CMD",
 	"RECV_DISCOVERY_XID_RSP",
 	"RECV_SNRM_CMD",
@@ -173,7 +174,7 @@
 	 * 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 ((skb_queue_len(&self->txq) == 0) || (self->remote_busy)) {
 		if (self->fast_RR == TRUE) {
 			/*
 			 *  Assert that the fast poll timer has not reached the
@@ -200,8 +201,9 @@
 	} else
 		self->fast_RR = FALSE;
 
-	IRDA_DEBUG(4, __FUNCTION__ "(), Timeout=%d\n", timeout);
-#endif
+	IRDA_DEBUG(3, __FUNCTION__ "(), timeout=%d (%ld)\n", timeout, jiffies);
+#endif /* CONFIG_IRDA_FAST_RR */
+
 	if (timeout == 0)
 		irlap_do_event(self, POLL_TIMER_EXPIRED, NULL, NULL);
 	else
@@ -223,11 +225,11 @@
 	if (!self || self->magic != LAP_MAGIC)
 		return;
 	
-  	IRDA_DEBUG(4, __FUNCTION__ "(), event = %s, state = %s\n", 
-	      irlap_event[event], irlap_state[self->state]); 
+  	IRDA_DEBUG(3, __FUNCTION__ "(), event = %s, state = %s\n", 
+		   irlap_event[event], irlap_state[self->state]); 
 	
 	ret = (*state[self->state])(self, event, skb, info);
-	
+
 	/* 
 	 *  Check if there are any pending events that needs to be executed
 	 */
@@ -239,9 +241,9 @@
 		 * try to disconnect link if we send any data frames, since
 		 * that will change the state away form XMIT
 		 */
-		if (skb_queue_len(&self->tx_list)) {
+		if (skb_queue_len(&self->txq)) {
 			/* Try to send away all queued data frames */
-			while ((skb = skb_dequeue(&self->tx_list)) != NULL) {
+			while ((skb = skb_dequeue(&self->txq)) != NULL) {
 				ret = (*state[self->state])(self, SEND_I_CMD,
 							    skb, NULL);
 				if (ret == -EPROTO)
@@ -282,10 +284,11 @@
 	if (!self || self->magic != LAP_MAGIC)
 		return;
 	
-	IRDA_DEBUG(4, "next LAP state = %s\n", irlap_state[ state]);
+	IRDA_DEBUG(4, "next LAP state = %s\n", irlap_state[state]);
 
 	self->state = state;
 
+#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
 	/*
 	 *  If we are swithing away from a XMIT state then we are allowed to 
 	 *  transmit a maximum number of bytes again when we enter the XMIT 
@@ -293,7 +296,8 @@
 	 *  we cannot do this when swithing into the XMIT state :-)
 	 */
 	if ((state != LAP_XMIT_P) && (state != LAP_XMIT_S))
-		self->bytes_left = self->window_bytes;
+		self->bytes_left = self->line_capacity;
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
 }
 
 /*
@@ -307,7 +311,8 @@
 {
 	discovery_t *discovery_rsp;
 	int ret = 0;
-	
+	int i;
+
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == LAP_MAGIC, return -1;);
 
@@ -317,7 +322,7 @@
 
 		if (self->media_busy) {
 			IRDA_DEBUG(0, __FUNCTION__
-			      "(), CONNECT_REQUEST: media busy!\n");
+				   "(), CONNECT_REQUEST: media busy!\n");
 			
 			/* Always switch state before calling upper layers */
 			irlap_next_state(self, LAP_NDM);
@@ -355,10 +360,7 @@
 	 	if (self->media_busy) {
  			IRDA_DEBUG(0, __FUNCTION__ "(), media busy!\n"); 
 			/* irlap->log.condition = MEDIA_BUSY; */
-			
-			/* Always switch state before calling upper layers */
-			irlap_next_state(self, LAP_NDM); 
-			
+						
 			/* This will make IrLMP try again */
  			irlap_discovery_confirm(self, NULL);
 			return 0;
@@ -405,6 +407,32 @@
 		}
 		dev_kfree_skb(skb);
 		break;
+#ifdef CONFIG_IRDA_ULTRA
+	case SEND_UI_FRAME:
+		/* Only allowed to repeat an operation twice */
+		for (i=0; ((i<2) && (self->media_busy == FALSE)); i++) {
+			skb = skb_dequeue(&self->txq_ultra);
+			if (skb)			
+				irlap_send_ui_frame(self, skb, CBROADCAST, 
+						    CMD_FRAME);
+			else
+				break;
+		}
+		if (i == 2) {
+			/* Force us to listen 500 ms again */
+			irda_device_set_media_busy(self->netdev, TRUE);
+		}
+		break;
+	case RECV_UI_FRAME:
+		/* Only accept broadcast frames in NDM mode */
+		if (info->caddr != CBROADCAST) {
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "(), not a broadcast frame!\n");
+			dev_kfree_skb(skb);
+		} else
+			irlap_unitdata_indication(self, skb);
+		break;
+#endif /* CONFIG_IRDA_ULTRA */
 	case RECV_TEST_CMD:
 		/* Remove test frame header */
 		skb_pull(skb, sizeof(struct test_frame));
@@ -422,8 +450,8 @@
 		break;
 	default:
 		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[event]);
-
+			   irlap_event[event]);
+		
 		if (skb)
 			dev_kfree_skb(skb);
 
@@ -447,28 +475,29 @@
 	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;);
 
 		IRDA_DEBUG(4, __FUNCTION__ "(), daddr=%08x\n", 
-		      info->discovery->daddr);
+			   info->discovery->daddr);
 
 		if (!self->discovery_log) {
 			WARNING(__FUNCTION__ "(), discovery log is gone! "
 				"maybe the discovery timeout has been set to "
 				"short?\n");
+			dev_kfree_skb(skb);
 			break;
 		}
 		hashbin_insert(self->discovery_log, 
 			       (queue_t *) info->discovery,
 			       info->discovery->daddr, NULL);
 
-		dev_kfree_skb(skb);
-
 		/* Keep state */
-		irlap_next_state(self, LAP_QUERY); 
+		/* irlap_next_state(self, LAP_QUERY);  */
+
+		dev_kfree_skb(skb);
 		break;
 	case SLOT_TIMER_EXPIRED:
 		if (self->s < self->S) {
@@ -500,8 +529,8 @@
 		}
 		break;
 	default:
-		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
-		      irlap_event[event]);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlap_event[event]);
 
 		if (skb)
 			dev_kfree_skb(skb);
@@ -565,10 +594,10 @@
 		break;
 	default:
 		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
-		      irlap_event[event]);
+			   irlap_event[event]);
 
-		if ( skb)
-			dev_kfree_skb( skb);
+		if (skb)
+			dev_kfree_skb(skb);
 		
 		ret = -1;
 		break;
@@ -595,7 +624,6 @@
 
 	switch (event) {
 	case CONNECT_RESPONSE:
-		/* skb_pull(skb, 11); */
 		skb_pull(skb, sizeof(struct snrm_frame));
 
 		ASSERT(self->netdev != NULL, return -1;);
@@ -616,7 +644,7 @@
 		 * Applying the parameters now will make sure we change speed
 		 * after we have sent the next frame
 		 */
-		irlap_apply_connection_parameters(self, &self->qos_tx);
+		irlap_apply_connection_parameters(self);
 
 		/* 
 		 * Sending this frame will force a speed change after it has
@@ -631,10 +659,15 @@
 		 */
 		irlap_start_wd_timer(self, self->wd_timeout);
 		irlap_next_state(self, LAP_NRM_S);
+
+		dev_kfree_skb(skb);
 		break;
 	case RECV_DISCOVERY_XID_CMD:
-		IRDA_DEBUG(3, __FUNCTION__ "(), event RECV_DISCOVER_XID_CMD!\n");
+		IRDA_DEBUG(3, __FUNCTION__ 
+			   "(), event RECV_DISCOVER_XID_CMD!\n");
 		irlap_next_state(self, LAP_NDM);
+
+		dev_kfree_skb(skb);
 		break;		
 	case DISCONNECT_REQUEST:
 		irlap_send_dm_frame(self);
@@ -671,7 +704,7 @@
 	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) {
 /* 
@@ -694,7 +727,6 @@
 		irlap_start_final_timer(self, self->final_timeout);
 		self->retry_count++;
 		break;
-
 	case RECV_SNRM_CMD:
 		IRDA_DEBUG(4, __FUNCTION__ "(), SNRM battle!\n");
 
@@ -716,7 +748,9 @@
 			irlap_qos_negotiate(self, skb);
 			
 			irlap_send_ua_response_frame(self, &self->qos_rx);
-			irlap_apply_connection_parameters(self, &self->qos_tx);
+			irlap_apply_connection_parameters(self);
+
+			irlap_next_state(self, LAP_NRM_S);
 			irlap_connect_confirm(self, skb);
 			
 			/* 
@@ -725,8 +759,6 @@
 			 *  to use twice the value (note 3 IrLAP p. 60).  
 			 */
 			irlap_start_wd_timer(self, self->wd_timeout);
-			
-			irlap_next_state(self, LAP_NRM_S);
 		} else {
 			/* We just ignore the other device! */
 			dev_kfree_skb(skb);
@@ -749,7 +781,7 @@
 
 		irlap_qos_negotiate(self, skb);
 
-		irlap_apply_connection_parameters(self, &self->qos_tx); 
+		irlap_apply_connection_parameters(self);
 		self->retry_count = 0;
 		
 		/* This frame will actually force the speed change */
@@ -760,22 +792,20 @@
 
 		irlap_connect_confirm(self, skb);
 		break;
-
 	case RECV_DISC_FRAME:
 		del_timer(&self->final_timer);
 		irlap_next_state(self, LAP_NDM);
 
 		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
+		dev_kfree_skb(skb);
 		break;
-
 	/* DM handled in irlap_frame.c, irlap_driver_rcv() */		
 	default:
-		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
-		      irlap_event[event]);
-		
+		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
+			   irlap_event[event]);		
 		if (skb)
 			dev_kfree_skb(skb);
-
+		
 		ret = -1;
 		break;
 	}	
@@ -815,16 +845,17 @@
 		 *  Only send frame if send-window > 0.
 		 */ 
 		if ((self->window > 0) && (!self->remote_busy)) {
-
+#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
 			/*
 			 *  Test if we have transmitted more bytes over the 
 			 *  link than its possible to do with the current 
 			 *  speed and turn-around-time.
 			 */
-			if ((skb->len+self->bofs_count) > self->bytes_left) {
-				IRDA_DEBUG(4, __FUNCTION__ "(), Not allowed to "
-				      "transmit more bytes!\n");
-				skb_queue_head(&self->tx_list, skb);
+			if (skb->len > self->bytes_left) {
+				IRDA_DEBUG(4, __FUNCTION__ 
+					   "(), Not allowed to transmit more "
+					   "bytes!\n");
+				skb_queue_head(&self->txq, skb);
 
 				/*
 				 *  We should switch state to LAP_NRM_P, but
@@ -836,14 +867,14 @@
 				 */
 				return -EPROTO;
 			}
-			self->bytes_left -= (skb->len + self->bofs_count);
-
+			self->bytes_left -= skb->len;
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
 			/*
 			 *  Send data with poll bit cleared only if window > 1
 			 *  and there is more frames after this one to be sent
 			 */
 			if ((self->window > 1) && 
-			    skb_queue_len( &self->tx_list) > 0) 
+			    skb_queue_len( &self->txq) > 0) 
 			{   
 				irlap_send_data_primary(self, skb);
 				irlap_next_state(self, LAP_XMIT_P);
@@ -860,11 +891,11 @@
 #ifdef CONFIG_IRDA_FAST_RR
 			/* Peer may want to reply immediately */
 			self->fast_RR = FALSE;
-#endif
+#endif /* CONFIG_IRDA_FAST_RR */
 		} else {
 			IRDA_DEBUG(4, __FUNCTION__ 
-			      "(), Unable to send! remote busy?\n");
-			skb_queue_head(&self->tx_list, skb);
+				   "(), Unable to send! remote busy?\n");
+			skb_queue_head(&self->txq, skb);
 
 			/*
 			 *  The next ret is important, because it tells 
@@ -874,6 +905,8 @@
 		}
 		break;
 	case POLL_TIMER_EXPIRED:
+		IRDA_DEBUG(3, __FUNCTION__ "(), POLL_TIMER_EXPIRED (%ld)\n",
+			   jiffies);
 		irlap_send_rr_frame(self, CMD_FRAME);
 		irlap_start_final_timer(self, self->final_timeout);
 		irlap_next_state(self, LAP_NRM_P);
@@ -889,7 +922,7 @@
 		break;
 	default:
 		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[event]);
+			   irlap_event[event]);
 
 		if (skb)
 			dev_kfree_skb(skb);
@@ -923,9 +956,9 @@
 
 		/* Always switch state before calling upper layers */
 		irlap_next_state(self, LAP_NDM);
-
+		
 		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
-
+		dev_kfree_skb(skb);
 		break;
 	case FINAL_TIMER_EXPIRED:
 		if (self->retry_count < self->N3) {
@@ -983,7 +1016,7 @@
 		 *  to transmitt
 		 */
 		self->fast_RR = FALSE;
-#endif
+#endif /* CONFIG_IRDA_FAST_RR */
 		ASSERT( info != NULL, return -1;);
 
 		ns_status = irlap_validate_ns_received(self, info->ns);
@@ -993,9 +1026,7 @@
 		 *  Check for expected I(nformation) frame
 		 */
 		if ((ns_status == NS_EXPECTED) && (nr_status == NR_EXPECTED)) {
-			/* 
-			 *  poll bit cleared?
-			 */
+			/*  poll bit cleared?  */
 			if (!info->pf) {
 				self->vr = (self->vr + 1) % 8;
 			
@@ -1007,7 +1038,7 @@
 				/* Keep state, do not move this line */
 				irlap_next_state(self, LAP_NRM_P);
 				
-				irlap_data_indication(self, skb);
+				irlap_data_indication(self, skb, FALSE);
 			} else {
 				del_timer(&self->final_timer);
 
@@ -1031,7 +1062,7 @@
 				 */
 				irlap_next_state(self, LAP_XMIT_P);
 			
-				irlap_data_indication(self, skb);
+				irlap_data_indication(self, skb, FALSE);
 
 				/* This is the last frame */
 				irlap_start_poll_timer(self, self->poll_timeout);
@@ -1039,9 +1070,7 @@
 			break;
 			
 		}
-		/*
-		 *  Unexpected next to send (Ns)
-		 */
+		/* Unexpected next to send (Ns) */
 		if ((ns_status == NS_UNEXPECTED) && (nr_status == NR_EXPECTED))
 		{
 			if (!info->pf) {
@@ -1055,7 +1084,7 @@
 				/* Keep state */
 				irlap_next_state(self, LAP_NRM_P);
 			} else {
-				IRDA_DEBUG( 4, __FUNCTION__
+				IRDA_DEBUG(4, __FUNCTION__
 				       "(), missing or duplicate frame!\n");
 				
 				/* Update Nr received */
@@ -1092,7 +1121,7 @@
 				/* Keep state, do not move this line */
 				irlap_next_state(self, LAP_NRM_P);
 				
-				irlap_data_indication(self, skb);
+				irlap_data_indication(self, skb, FALSE);
 			} else {
 				/* 
 				 *  Do not resend frames until the last
@@ -1110,7 +1139,7 @@
 				/* Keep state, do not move this line!*/
 				irlap_next_state(self, LAP_NRM_P); 
 				
-				irlap_data_indication(self, skb);
+				irlap_data_indication(self, skb, FALSE);
 			}
 			break;
 		}
@@ -1121,7 +1150,8 @@
 		if ((ns_status == NS_UNEXPECTED) && 
 		    (nr_status == NR_UNEXPECTED)) 
 		{
-			IRDA_DEBUG( 4, "IrLAP: unexpected nr and ns!\n");
+			IRDA_DEBUG(4, __FUNCTION__ 
+				   "(), unexpected nr and ns!\n");
 			if (info->pf) {
 				/* Resend rejected frames */
 				irlap_resend_rejected_frames(self, CMD_FRAME);
@@ -1137,6 +1167,7 @@
 				
 				self->ack_required = FALSE;
 			}
+			dev_kfree_skb(skb);
 			break;
 		}
 
@@ -1148,7 +1179,7 @@
 				del_timer(&self->final_timer);
 				
 				irlap_next_state(self, LAP_RESET_WAIT);
-
+				
 				irlap_disconnect_indication(self, LAP_RESET_INDICATION);
 				self->xmitflag = TRUE;
 			} else {
@@ -1158,6 +1189,7 @@
 				
 				self->xmitflag = FALSE;
 			}
+			dev_kfree_skb(skb);
 			break;
 		}
 		IRDA_DEBUG(1, __FUNCTION__ "(), Not implemented!\n");
@@ -1166,13 +1198,13 @@
 		      irlap_event[ event], ns_status, nr_status);
 		break;
 	case RECV_UI_FRAME:
-		/*  poll bit cleared?  */
+		/* Poll bit cleared? */
 		if (!info->pf) {
-			irlap_unit_data_indication(self, skb);
+			irlap_data_indication(self, skb, TRUE);
 			irlap_next_state(self, LAP_NRM_P);
 		} else {
 			del_timer(&self->final_timer);
-			irlap_unit_data_indication(self, skb);
+			irlap_data_indication(self, skb, TRUE);
 			irlap_start_poll_timer(self, self->poll_timeout);
 		}
 		break;
@@ -1226,7 +1258,7 @@
 			irlap_next_state(self, LAP_NRM_P);
 		} else if (ret == NR_INVALID) {
 			IRDA_DEBUG(1, __FUNCTION__ "(), Received RR with "
-			      "invalid nr !\n");
+				   "invalid nr !\n");
 			del_timer(&self->final_timer);
 
 			irlap_next_state(self, LAP_RESET_WAIT);
@@ -1234,14 +1266,13 @@
 			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:
 		IRDA_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);
+			   "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;);
 
@@ -1251,21 +1282,18 @@
 
 		/* Update Nr received */
 		irlap_update_nr_received(self, info->nr);
-
 		irlap_next_state(self, LAP_XMIT_P);
 			
 		/* Start poll timer */
 		irlap_start_poll_timer(self, self->poll_timeout);
-		if (skb)
-			dev_kfree_skb(skb);
+		dev_kfree_skb(skb);
 		break;
 	case RECV_FRMR_RSP:
 		del_timer(&self->final_timer);
 		self->xmitflag = TRUE;
 		irlap_next_state(self, LAP_RESET_WAIT);
 		irlap_reset_indication(self);
-		if (skb)
-			dev_kfree_skb(skb);
+		dev_kfree_skb(skb);
 		break;
 	case FINAL_TIMER_EXPIRED:
 		/* 
@@ -1275,7 +1303,7 @@
 		 *  we only do this once for each frame.
 		 */
 		if (irda_device_is_receiving(self->netdev) && !self->add_wait) {
-			IRDA_DEBUG(4, "FINAL_TIMER_EXPIRED when receiving a "
+			IRDA_DEBUG(1, "FINAL_TIMER_EXPIRED when receiving a "
 			      "frame! Waiting a little bit more!\n");
 			irlap_start_final_timer(self, MSECS_TO_JIFFIES(300));
 
@@ -1299,7 +1327,7 @@
 		 	self->retry_count++;
 
 			IRDA_DEBUG(4, "irlap_state_nrm_p: FINAL_TIMER_EXPIRED:"
-			      " retry_count=%d\n", self->retry_count);
+				   " retry_count=%d\n", self->retry_count);
 			/* Keep state */
 		} else if (self->retry_count == self->N1) {
 			irlap_status_indication(STATUS_NO_ACTIVITY);
@@ -1310,7 +1338,7 @@
 			self->retry_count++;
 
 			IRDA_DEBUG(4, "retry count = N1; retry_count=%d\n", 
-			      self->retry_count);
+				   self->retry_count);
 			/* Keep state */
 		} else if (self->retry_count >= self->N2) {
 			irlap_apply_default_connection_parameters(self);
@@ -1336,13 +1364,11 @@
 		irlap_apply_default_connection_parameters(self);
 
 		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
-		if (skb)
-			dev_kfree_skb(skb);
-		
+		dev_kfree_skb(skb);		
 		break;
 	default:
 		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[event]);
+			   irlap_event[event]);
 
 		if (skb)
 			dev_kfree_skb(skb);
@@ -1392,7 +1418,7 @@
 		break;
 	default:
 		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[event]);
+			   irlap_event[event]);
 		if (skb)
 			dev_kfree_skb(skb);
 
@@ -1429,6 +1455,8 @@
 		irlap_next_state(self, LAP_NDM);
 
 		irlap_disconnect_indication(self, LAP_NO_RESPONSE);
+
+		dev_kfree_skb(skb);
 		break;
 	case RECV_UA_RSP:
 		del_timer(&self->final_timer);
@@ -1443,6 +1471,8 @@
 		irlap_next_state(self, LAP_XMIT_P);
 
 		irlap_start_poll_timer(self, self->poll_timeout);
+
+		dev_kfree_skb(skb);
 		break;
 	case FINAL_TIMER_EXPIRED:
 		if (self->retry_count < 3) {
@@ -1478,15 +1508,15 @@
 			irlap_start_wd_timer(self, self->wd_timeout);
 			irlap_next_state(self, LAP_NDM);
 		} else {
-			IRDA_DEBUG(0, __FUNCTION__ "(), SNRM frame contained an I "
-			      "field!\n");
-			dev_kfree_skb(skb);
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "(), SNRM frame contained an I field!\n");
+			
 		}
+		dev_kfree_skb(skb);
 		break;
 	default:
 		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[event]);
-
+			   irlap_event[event]);	
 		if (skb)
 			dev_kfree_skb(skb);
 
@@ -1508,7 +1538,7 @@
 {
 	int ret = 0;
 	
-	IRDA_DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
+	IRDA_DEBUG(4, __FUNCTION__ "(), event=%s\n", irlap_event[event]); 
 
 	ASSERT(self != NULL, return -ENODEV;);
 	ASSERT(self->magic == LAP_MAGIC, return -EBADR;);
@@ -1519,13 +1549,14 @@
 		 *  Send frame only if send window > 1
 		 */ 
 		if ((self->window > 0) && (!self->remote_busy)) {
+#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
 			/*
 			 *  Test if we have transmitted more bytes over the 
 			 *  link than its possible to do with the current 
 			 *  speed and turn-around-time.
 			 */
-			if ((skb->len+self->bofs_count) > self->bytes_left) {
-				skb_queue_head(&self->tx_list, skb);
+			if (skb->len > self->bytes_left) {
+				skb_queue_head(&self->txq, skb);
 				/*
 				 *  Switch to NRM_S, this is only possible
 				 *  when we are in secondary mode, since we 
@@ -1536,14 +1567,14 @@
 
 				return -EPROTO; /* Try again later */
 			}
-			self->bytes_left -= (skb->len + self->bofs_count);
-
+			self->bytes_left -= skb->len;
+#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */
 			/*
 			 *  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) 
+			    skb_queue_len(&self->txq) > 0) 
 			{   
 				irlap_send_data_secondary(self, skb);
 				irlap_next_state(self, LAP_XMIT_S);
@@ -1558,14 +1589,14 @@
 				ret = -EPROTO;
 			}
 		} else {
-			IRDA_DEBUG(1, __FUNCTION__ "(), Unable to send!\n");
-			skb_queue_head( &self->tx_list, skb);
+			IRDA_DEBUG(2, __FUNCTION__ "(), Unable to send!\n");
+			skb_queue_head(&self->txq, skb);
 			ret = -EPROTO;
 		}
 		break;
 	default:
-		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
-		      irlap_event[event]);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlap_event[event]);
 		if (skb)
 			dev_kfree_skb(skb);
 
@@ -1598,8 +1629,8 @@
 	case RECV_I_CMD: /* Optimize for the common case */
 		/* FIXME: must check for remote_busy below */
 		IRDA_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);
+			   "vr=%d, pf=%d\n", irlap_event[event], info->nr, 
+			   self->vs, info->ns, self->vr, info->pf);
 
 		self->retry_count = 0;
 
@@ -1629,13 +1660,13 @@
 				/* Keep state, do not move this line */
 				irlap_next_state(self, LAP_NRM_S);
 				
-				irlap_data_indication( self, skb);
+				irlap_data_indication(self, skb, FALSE);
 				break;
 			} else {
 				self->vr = (self->vr + 1) % 8;
 				
 				/* Update Nr received */
-				irlap_update_nr_received( self, info->nr);
+				irlap_update_nr_received(self, info->nr);
 				
 				/* 
 				 *  We should wait before sending RR, and
@@ -1650,10 +1681,10 @@
 				 * we decide if we should send a RR frame
 				 * or not
 				 */
-				irlap_data_indication(self, skb);
+				irlap_data_indication(self, skb, FALSE);
 
 				/* Any pending data requests?  */
-				if ((skb_queue_len(&self->tx_list) > 0) && 
+				if ((skb_queue_len(&self->txq) > 0) && 
 				    (self->window > 0)) 
 				{
 					self->ack_required = TRUE;
@@ -1714,7 +1745,7 @@
 				/* Keep state, do not move this line */
 				irlap_next_state(self, LAP_NRM_S);
 
-				irlap_data_indication(self, skb);
+				irlap_data_indication(self, skb, FALSE);
 				irlap_start_wd_timer(self, self->wd_timeout);
 				break;
 			}
@@ -1731,16 +1762,19 @@
 				/* Keep state, do not move this line */
 				irlap_next_state(self, LAP_NRM_S);
 				
-				irlap_data_indication(self, skb);
+				irlap_data_indication(self, skb, FALSE);
 				irlap_start_wd_timer(self, self->wd_timeout);
 			}
+			break;
 		}
 		
 		if (ret == NR_INVALID) {
 			IRDA_DEBUG(0, "NRM_S, NR_INVALID not implemented!\n");
+			dev_kfree_skb(skb);
 		}
 		if (ret == NS_INVALID) {
 			IRDA_DEBUG(0, "NRM_S, NS_INVALID not implemented!\n");
+			dev_kfree_skb(skb);
 		}
 		break;
 	case RECV_UI_FRAME:
@@ -1748,22 +1782,22 @@
 		 *  poll bit cleared?
 		 */
 		if (!info->pf) {
-			irlap_unit_data_indication(self, skb);
+			irlap_data_indication(self, skb, TRUE);
 			irlap_next_state(self, LAP_NRM_S); /* Keep state */
 		} else {
 			/*
 			 *  Any pending data requests?
 			 */
-			if ((skb_queue_len(&self->tx_list) > 0) && 
+			if ((skb_queue_len(&self->txq) > 0) && 
 			    (self->window > 0) && !self->remote_busy) 
 			{
-				irlap_unit_data_indication(self, skb);
+				irlap_data_indication(self, skb, TRUE);
 				
 				del_timer(&self->wd_timer);
 
 				irlap_next_state(self, LAP_XMIT_S);
 			} else {
-				irlap_unit_data_indication(self, skb);
+				irlap_data_indication(self, skb, TRUE);
 
 				irlap_wait_min_turn_around(self, &self->qos_tx);
 
@@ -1785,7 +1819,7 @@
 		 */
 		nr_status = irlap_validate_nr_received(self, info->nr);
 		if (nr_status == NR_EXPECTED) {
-			if ((skb_queue_len( &self->tx_list) > 0) && 
+			if ((skb_queue_len( &self->txq) > 0) && 
 			    (self->window > 0)) {
 				self->remote_busy = FALSE;
 				
@@ -1809,18 +1843,17 @@
 		} else if (nr_status == NR_UNEXPECTED) {
 			self->remote_busy = FALSE;
 			irlap_update_nr_received(self, info->nr);
-			irlap_resend_rejected_frames( self, RSP_FRAME);
+			irlap_resend_rejected_frames(self, RSP_FRAME);
 
 			irlap_start_wd_timer(self, self->wd_timeout);
 
 			/* Keep state */
 			irlap_next_state(self, LAP_NRM_S); 
 		} else {
-			IRDA_DEBUG(1, __FUNCTION__ "(), invalid nr not implemented!\n");
+			IRDA_DEBUG(1, __FUNCTION__ 
+				   "(), invalid nr not implemented!\n");
 		} 
-		if (skb)
-			dev_kfree_skb(skb);
-
+		dev_kfree_skb(skb);
 		break;
 	case RECV_SNRM_CMD:
 		/* SNRM frame is not allowed to contain an I-field */
@@ -1831,10 +1864,11 @@
 			
 			irlap_reset_indication(self);
 		} else {
-			IRDA_DEBUG(0, __FUNCTION__ "(), SNRM frame contained an "
-			      "I-field!\n");
-			dev_kfree_skb(skb);	       
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "(), SNRM frame contained an I-field!\n");
+			
 		}
+		dev_kfree_skb(skb);
 		break;
 	case WD_TIMER_EXPIRED:
 		/*
@@ -1842,7 +1876,7 @@
 		 *  disconnect time (note 2 in IrLAP p. 82)
 		 */
 		IRDA_DEBUG(1, __FUNCTION__ "(), retry_count = %d\n", 
-		      self->retry_count);
+			   self->retry_count);
 
 		if ((self->retry_count < (self->N2/2))  && 
 		    (self->retry_count != self->N1/2)) {
@@ -1873,9 +1907,7 @@
 		irlap_apply_default_connection_parameters(self);
 
 		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
-		if (skb)
-			dev_kfree_skb(skb);
-		
+		dev_kfree_skb(skb);		
 		break;
 	case RECV_DISCOVERY_XID_CMD:
 		irlap_wait_min_turn_around(self, &self->qos_tx);
@@ -1883,6 +1915,8 @@
 		self->ack_required = TRUE;
 		irlap_start_wd_timer(self, self->wd_timeout);
 		irlap_next_state(self, LAP_NRM_S);
+
+		dev_kfree_skb(skb);
 		break;
 	case RECV_TEST_CMD:
 		/* Remove test frame header */
@@ -1897,8 +1931,12 @@
 		break;
 	default:
 		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
-		      event, irlap_event[event]);
-		ret = -1;
+			   event, irlap_event[event]);
+
+		if (skb)
+			dev_kfree_skb(skb);
+
+		ret = -EINVAL;
 		break;
 	}
 	return ret;
@@ -1910,10 +1948,13 @@
  *    
  *
  */
-static int irlap_state_sclose( struct irlap_cb *self, IRLAP_EVENT event, 
-			       struct sk_buff *skb, struct irlap_info *info) 
+static int irlap_state_sclose(struct irlap_cb *self, IRLAP_EVENT event, 
+			      struct sk_buff *skb, struct irlap_info *info) 
 {
-	IRDA_DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
+
+	if (skb)
+		dev_kfree_skb(skb);
 
 	return -1;
 }
@@ -1924,19 +1965,19 @@
 {
 	int ret = 0;
 
-	IRDA_DEBUG(1, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
+	IRDA_DEBUG(1, __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 RESET_RESPONSE:
-		irlap_send_ua_response_frame( self, &self->qos_rx);
-		irlap_initiate_connection_state( self);
-		irlap_start_wd_timer( self, WD_TIMEOUT);
-		irlap_flush_all_queues( self);
+		irlap_send_ua_response_frame(self, &self->qos_rx);
+		irlap_initiate_connection_state(self);
+		irlap_start_wd_timer(self, WD_TIMEOUT);
+		irlap_flush_all_queues(self);
 		
-		irlap_next_state( self, LAP_NRM_S);
+		irlap_next_state(self, LAP_NRM_S);
 		break;
 	case DISCONNECT_REQUEST:
 		irlap_wait_min_turn_around( self, &self->qos_tx);
@@ -1946,9 +1987,12 @@
 	default:
 		IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
 		      event, irlap_event[event]);
-		ret = -1;
+
+		if (skb)
+			dev_kfree_skb(skb);
+
+		ret = -EINVAL;
 		break;
 	}
-
 	return ret;
 }
diff -u --recursive --new-file v2.3.34/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.3.34/linux/net/irda/irlap_frame.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/irlap_frame.c	Tue Dec 21 10:17:58 1999
@@ -1,16 +1,16 @@
 /*********************************************************************
  *                
  * Filename:      irlap_frame.c
- * Version:       0.9
+ * Version:       1.0
  * Description:   Build and transmit IrLAP frames
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Fri Nov  5 09:45:58 1999
+ * Modified at:   Tue Dec 14 09:45:25 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
- *     All Rights Resrved.
+ *     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 
@@ -46,8 +46,8 @@
  * Function irlap_insert_info (self, skb)
  *
  *    Insert minimum turnaround time and speed information into the skb. We 
- *    need to do this since it's per packet relevant information.
- *
+ *    need to do this since it's per packet relevant information. Safe to
+ *    have this function inlined since it's only called from one place
  */
 static inline void irlap_insert_info(struct irlap_cb *self, 
 				     struct sk_buff *skb)
@@ -83,13 +83,6 @@
  */
 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;
@@ -120,8 +113,7 @@
 	if (!skb)
 		return;
 
-	skb_put(skb, 2); 
-	frame = (struct snrm_frame *) skb->data;
+	frame = (struct snrm_frame *) skb_put(skb, 2); 
 
 	/* Insert connection address field */
 	if (qos)
@@ -216,8 +208,7 @@
 	if (!skb)
 		return;
 
-	skb_put(skb, 10);
-	frame = (struct ua_frame *) skb->data;
+	frame = (struct ua_frame *) skb_put(skb, 10);
 	
 	/* Build UA response */
 	frame->caddr = self->caddr;
@@ -257,8 +248,7 @@
 	if (!skb)
 		return;
 
-	skb_put( skb, 2);
-	frame = skb->data;
+	frame = skb_put( skb, 2);
 	
 	if (self->state == LAP_NDM)
 		frame[0] = CBROADCAST;
@@ -286,12 +276,11 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	skb = dev_alloc_skb(32);
+	skb = dev_alloc_skb(16);
 	if (!skb)
 		return;
 
-	skb_put(skb, 2);
-	frame = skb->data;
+	frame = skb_put(skb, 2);
 	
 	frame[0] = self->caddr | CMD_FRAME;
 	frame[1] = DISC_CMD | PF_BIT;
@@ -313,7 +302,8 @@
 	__u32 bcast = BROADCAST;
 	__u8 *info;
 
- 	IRDA_DEBUG(4, __FUNCTION__ "(), s=%d, S=%d, command=%d\n", s, S, command);
+ 	IRDA_DEBUG(4, __FUNCTION__ "(), s=%d, S=%d, command=%d\n", s, S, 
+		   command);
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
@@ -369,24 +359,23 @@
 	 *  EXTENSION bit is set in the first byte.
 	 */
 	if (!command || (frame->slotnr == 0xff)) {
-		int i;
+		int len;
 
-		if (discovery->hints.byte[0] & HINT_EXTENSION)
-			info = skb_put(skb, 3+discovery->name_len);
-		else
-			info = skb_put(skb, 2+discovery->name_len);
-		
-		i = 0;
-		info[i++] = discovery->hints.byte[0];
-		if (discovery->hints.byte[0] & HINT_EXTENSION)
-			info[i++] = discovery->hints.byte[1];
-		
-		info[i++] = discovery->charset;
-		
-		memcpy(&info[i++], discovery->nickname, discovery->name_len);
-	} 
-	ASSERT(self->netdev != NULL, return;);
+		if (discovery->hints.byte[0] & HINT_EXTENSION) {
+			info = skb_put(skb, 2);		
+			info[0] = discovery->hints.byte[0];
+			info[1] = discovery->hints.byte[1];
+		} else {
+			info = skb_put(skb, 1);
+			info[0] = discovery->hints.byte[0];
+		}
+		info = skb_put(skb, 1);
+		info[0] = discovery->charset;
 
+		len = IRDA_MIN(discovery->name_len, skb_tailroom(skb));
+		info = skb_put(skb, len);
+		memcpy(info, discovery->nickname, len);
+	} 
 	irlap_queue_xmit(self, skb);
 }
 
@@ -417,13 +406,15 @@
 
 	/* Make sure frame is addressed to us */
 	if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
+		IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), frame is not addressed to us!\n");
 		dev_kfree_skb(skb);
-		IRDA_DEBUG(0, __FUNCTION__ "(), frame is not addressed to us!\n");
 		return;
 	}
 
 	if ((discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC)) == NULL) {
 		WARNING(__FUNCTION__ "(), kmalloc failed!\n");
+		dev_kfree_skb(skb);
 		return;
 	}
 	memset(discovery, 0, sizeof(discovery_t));
@@ -483,7 +474,8 @@
 
 	/* Make sure frame is addressed to us */
 	if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
-		IRDA_DEBUG(0, __FUNCTION__ "(), frame is not addressed to us!\n");
+		IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), frame is not addressed to us!\n");
 		dev_kfree_skb(skb);
 		return;
 	}
@@ -503,6 +495,7 @@
 		break;
 	default:
 		/* Error!! */
+		dev_kfree_skb(skb);
 		return;
 	}
 	info->s = xid->slotnr;
@@ -519,6 +512,7 @@
 		discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC);
 		if (!discovery) {
 			WARNING(__FUNCTION__ "(), unable to malloc!\n");
+			dev_kfree_skb(skb);
 			return;
 		}
 	      
@@ -562,7 +556,7 @@
 	struct sk_buff *skb;
 	__u8 *frame;
 
-	skb = dev_alloc_skb(32);
+	skb = dev_alloc_skb(16);
 	if (!skb)
 		return;
 	
@@ -608,8 +602,7 @@
 	if (!skb)
 		return;
 
-	skb_put( skb, 2);
-	frame = skb->data;
+	frame = skb_put( skb, 2);
 	
 	frame[0] = self->caddr;
 	frame[0] |= (command) ? CMD_FRAME : 0;
@@ -620,7 +613,7 @@
 
 	frame[2] = 0;
 
-   	IRDA_DEBUG( 4, __FUNCTION__ "(), vr=%d, %ld\n",self->vr, jiffies); 
+   	IRDA_DEBUG(4, __FUNCTION__ "(), vr=%d, %ld\n",self->vr, jiffies); 
 
 	irlap_queue_xmit(self, skb);
 }
@@ -631,20 +624,17 @@
  *    Received RNR (Receive Not Ready) frame from peer station
  *
  */
-static void irlap_recv_rnr_frame( struct irlap_cb *self, struct sk_buff *skb, 
-				  struct irlap_info *info) 
+static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb, 
+				 struct irlap_info *info) 
 {
-	__u8 *frame;
-
-	ASSERT( skb != NULL, return;);
-	ASSERT( info != NULL, return;);
+	ASSERT(skb != NULL, return;);
+	ASSERT(info != NULL, return;);
 
-	frame = skb->data;
-	info->nr = frame[1] >> 5;
+	info->nr = skb->data[1] >> 5;
 
-	IRDA_DEBUG( 4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
+	IRDA_DEBUG(4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
 
-	irlap_do_event( self, RECV_RNR_FRAME, skb, info);
+	irlap_do_event(self, RECV_RNR_FRAME, skb, info);
 }
 
 /*
@@ -702,7 +692,7 @@
 		irlap_send_i_frame( self, tx_skb, CMD_FRAME);
 	} else {
 		IRDA_DEBUG( 4, __FUNCTION__ "(), sending unreliable frame\n");
-		irlap_send_ui_frame(self, skb, CMD_FRAME);
+		irlap_send_ui_frame(self, skb, self->caddr, CMD_FRAME);
 		self->window -= 1;
 	}
 }
@@ -765,12 +755,12 @@
 		del_timer(&self->poll_timer);
 
 		if (self->ack_required) {
-			irlap_send_ui_frame(self, skb, CMD_FRAME);
+			irlap_send_ui_frame(self, skb, self->caddr, CMD_FRAME);
 			irlap_send_rr_frame(self, CMD_FRAME);
 			self->ack_required = FALSE;
 		} else {
 			skb->data[1] |= PF_BIT;
-			irlap_send_ui_frame(self, skb, CMD_FRAME);
+			irlap_send_ui_frame(self, skb, self->caddr, CMD_FRAME);
 		}
 		self->window = self->window_size;
 		irlap_start_final_timer(self, self->final_timeout);
@@ -824,12 +814,12 @@
 		irlap_send_i_frame(self, tx_skb, RSP_FRAME); 
 	} else {
 		if (self->ack_required) {
-			irlap_send_ui_frame(self, skb, RSP_FRAME);
+			irlap_send_ui_frame(self, skb, self->caddr, RSP_FRAME);
 			irlap_send_rr_frame(self, RSP_FRAME);
 			self->ack_required = FALSE;
 		} else {
 			skb->data[1] |= PF_BIT;
-			irlap_send_ui_frame(self, skb, RSP_FRAME);
+			irlap_send_ui_frame(self, skb, self->caddr, RSP_FRAME);
 		}
 		self->window = self->window_size;
 
@@ -874,7 +864,7 @@
 
 		irlap_send_i_frame(self, tx_skb, RSP_FRAME); 
 	} else {
-		irlap_send_ui_frame(self, skb, RSP_FRAME);
+		irlap_send_ui_frame(self, skb, self->caddr, RSP_FRAME);
 		self->window -= 1;
 	}
 }
@@ -958,12 +948,12 @@
 	 */
 	return; /* Skip this for now, DB */
 
-	while (skb_queue_len( &self->tx_list) > 0) {
+	while (skb_queue_len( &self->txq) > 0) {
 		
 		IRDA_DEBUG(0, __FUNCTION__ "(), sending additional frames!\n");
-		if ((skb_queue_len( &self->tx_list) > 0) && 
+		if ((skb_queue_len( &self->txq) > 0) && 
 		    (self->window > 0)) {
-			skb = skb_dequeue( &self->tx_list); 
+			skb = skb_dequeue( &self->txq); 
 			ASSERT(skb != NULL, return;);
 
 			/*
@@ -971,7 +961,7 @@
 			 *  bit cleared
 			 */ 
 			if ((self->window > 1) && 
-			    skb_queue_len(&self->tx_list) > 0) 
+			    skb_queue_len(&self->txq) > 0) 
 			{
 				irlap_send_data_primary(self, skb);
 			} else {
@@ -988,21 +978,16 @@
  *
  */
 void irlap_send_ui_frame(struct irlap_cb *self, struct sk_buff *skb, 
-			 int command) 
+			 __u8 caddr, int command)
 {
-	__u8  *frame;
-
 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 	ASSERT(skb != NULL, return;);
 	
-	frame = skb->data;
-	
 	/* Insert connection address */
-	frame[0] = self->caddr;
-	frame[0] |= (command) ? CMD_FRAME : 0;
+	skb->data[0] = caddr | ((command) ? CMD_FRAME : 0);
 
 	irlap_queue_xmit(self, skb);
 }
@@ -1055,13 +1040,9 @@
 static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb, 
 				struct irlap_info *info)
 {
-	__u8 *frame;
-
 	IRDA_DEBUG( 4, __FUNCTION__ "()\n");
 
-	frame = skb->data;
-
-	info->pf = frame[1] & PF_BIT;      /* Final bit */
+	info->pf = skb->data[1] & PF_BIT;      /* Final bit */
 
 	irlap_do_event(self, RECV_UI_FRAME, skb, info);
 }
@@ -1173,6 +1154,7 @@
 	
 	if (skb->len < sizeof(struct test_frame)) {
 		IRDA_DEBUG(0, __FUNCTION__ "() test frame to short!\n");
+		dev_kfree_skb(skb);
 		return;
 	}
 
@@ -1265,14 +1247,17 @@
 			break;
 		case REJ:
 			IRDA_DEBUG( 0, "*** REJ frame received! ***\n");
+			dev_kfree_skb(skb);
 			break;
 		case SREJ:
 			IRDA_DEBUG( 0, "*** SREJ frame received! ***\n");
+			dev_kfree_skb(skb);
 			break;
 		default:
 			WARNING(__FUNCTION__ 
 				"() Unknown S-frame %02x received!\n",
 				info.control);
+			dev_kfree_skb(skb);
 			break;
 		}
 		return 0;
@@ -1293,6 +1278,7 @@
 	case DM_RSP:
 		IRDA_DEBUG( 0, "DM rsp frame received!\n");
 		irlap_next_state(self, LAP_NDM);
+		dev_kfree_skb(skb);
 		break;
 	case DISC_CMD:
 		irlap_do_event(self, RECV_DISC_FRAME, skb, &info);
@@ -1312,7 +1298,7 @@
 	default:
 		WARNING(__FUNCTION__ "(), Unknown frame %02x received!\n", 
 			info.control);
-		dev_kfree_skb( skb); 
+		dev_kfree_skb(skb); 
 		break;
 	}
 	return 0;
diff -u --recursive --new-file v2.3.34/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.3.34/linux/net/irda/irlmp.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/irlmp.c	Tue Dec 21 10:17:58 1999
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlmp.c
- * Version:       0.9
+ * Version:       1.0
  * Description:   IrDA Link Management Protocol (LMP) layer                 
  * Status:        Stable.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Sat Oct  9 17:00:49 1999
+ * Modified at:   Thu Dec 16 22:59:40 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -90,7 +90,7 @@
 	irlmp->unconnected_lsaps = hashbin_new(HB_GLOBAL);
 	irlmp->cachelog = hashbin_new(HB_GLOBAL);
 	
-	irlmp->free_lsap_sel = 0x10; /* Servers use 0x00-0x0f */
+	irlmp->free_lsap_sel = 0x10; /* Reserved 0x00-0x0f */
 #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
 	irlmp->cache.valid = FALSE;
 #endif
@@ -134,7 +134,7 @@
  *   Register with IrLMP and create a local LSAP,
  *   returns handle to LSAP.
  */
-struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify)
+struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify, __u8 pid)
 {
 	struct lsap_cb *self;
 
@@ -142,40 +142,33 @@
 	ASSERT(irlmp != NULL, return NULL;);
 	ASSERT(irlmp->magic == LMP_MAGIC, return NULL;);
 
-	/* 
-	 *  Does the client care which Source LSAP selector it gets? 
-	 */
+	/*  Does the client care which Source LSAP selector it gets?  */
 	if (slsap_sel == LSAP_ANY) {
-		/*
-		 *  Find unused LSAP
-		 */
 		slsap_sel = irlmp_find_free_slsap();
-		if ( slsap_sel == 0)
-			return NULL;
-	} else {
-		/*
-		 *  Client wants specific LSAP, so check if it's already
-		 *  in use
-		 */
-		if (irlmp_slsap_inuse(slsap_sel)) {
+		if (!slsap_sel)
 			return NULL;
-		}
-	}
+	} else if (irlmp_slsap_inuse(slsap_sel))
+		return NULL;
 
-	/*
-	 *  Allocate new instance of a LSAP connection
-	 */
+	/* Allocate new instance of a LSAP connection */
 	self = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
 	if (self == NULL) {
-		printk( KERN_ERR "IrLMP: Can't allocate memory for "
-			"LSAP control block!\n");
+		ERROR(__FUNCTION__ "(), can't allocate memory");
 		return NULL;
 	}
 	memset(self, 0, sizeof(struct lsap_cb));
 	
 	self->magic = LMP_LSAP_MAGIC;
 	self->slsap_sel = slsap_sel;
-	self->dlsap_sel = LSAP_ANY;
+
+	/* Fix connectionless LSAP's */
+	if (slsap_sel == LSAP_CONNLESS) {
+#ifdef CONFIG_IRDA_ULTRA
+		self->dlsap_sel = LSAP_CONNLESS;
+		self->pid = pid;
+#endif /* CONFIG_IRDA_ULTRA */
+	} else
+		self->dlsap_sel = LSAP_ANY;
 	self->connected = FALSE;
 
 	init_timer(&self->watchdog_timer);
@@ -185,9 +178,7 @@
 
 	irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
 	
-	/*
-	 *  Insert into queue of unconnected LSAPs
-	 */
+	/* Insert into queue of unconnected LSAPs */
 	hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) self, (int) self, 
 		       NULL);
 	
@@ -209,9 +200,12 @@
 	/*
 	 *  Set some of the variables to preset values
 	 */
-	self->magic = ~LMP_LSAP_MAGIC;
+	self->magic = 0;
 	del_timer(&self->watchdog_timer); /* Important! */
 
+	if (self->conn_skb)
+		dev_kfree_skb(self->conn_skb);
+
 #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
 	ASSERT(irlmp != NULL, return;);
 	irlmp->cache.valid = FALSE;
@@ -249,7 +243,7 @@
 	}
 	if (!lsap) {
 		IRDA_DEBUG(0, __FUNCTION__ 
-		       "(), Looks like somebody has removed me already!\n");
+		     "(), Looks like somebody has removed me already!\n");
 		return;
 	}
 	__irlmp_close_lsap(self);
@@ -373,7 +367,6 @@
 	skb_push(skb, LMP_CONTROL_HEADER);
 
 	self->dlsap_sel = dlsap_sel;
-	self->tmp_skb = skb;
 	
 	/*  
 	 * Find the link to where we should try to connect since there may
@@ -447,22 +440,17 @@
 	ASSERT(self->lap != NULL, return;);
 
 	IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
-	      self->slsap_sel, self->dlsap_sel);
-
+		   self->slsap_sel, self->dlsap_sel);
+	
 	self->qos = *self->lap->qos;
 
 	max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
-	IRDA_DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
-	
 	lap_header_size = IRLAP_GET_HEADER_SIZE(self->lap->irlap);
-
 	max_header_size = LMP_HEADER + lap_header_size;
 
-	IRDA_DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
-
 	/* Hide LMP_CONTROL_HEADER header from layer above */
 	skb_pull(skb, LMP_CONTROL_HEADER);
-
+	
 	if (self->notify.connect_indication)
 		self->notify.connect_indication(self->notify.instance, self, 
 						&self->qos, max_seg_size, 
@@ -484,9 +472,9 @@
 	self->connected = TRUE;
 
 	IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
-	      self->slsap_sel, self->dlsap_sel);
+		   self->slsap_sel, self->dlsap_sel);
 
-	/* Make room for MUX control header ( 3 bytes) */
+	/* Make room for MUX control header (3 bytes) */
 	ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return -1;);
 	skb_push(userdata, LMP_CONTROL_HEADER);
 	
@@ -519,7 +507,8 @@
 	lap_header_size = IRLAP_GET_HEADER_SIZE(self->lap->irlap);	
 	max_header_size = LMP_HEADER + lap_header_size;
 
-	IRDA_DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", 
+		   max_header_size);
 
 	/* Hide LMP_CONTROL_HEADER header from layer above */
 	skb_pull(skb, LMP_CONTROL_HEADER);
@@ -637,13 +626,12 @@
 	struct lsap_cb *lsap;
 
 	IRDA_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;); 
 
 	IRDA_DEBUG(3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
-	      self->slsap_sel, self->dlsap_sel);
+		   self->slsap_sel, self->dlsap_sel);
 
 	self->connected = FALSE;
 	self->dlsap_sel = LSAP_ANY;
@@ -670,9 +658,12 @@
 	/*
 	 *  Inform service user
 	 */
-	if (self->notify.disconnect_indication) {
+	if (self->notify.disconnect_indication)
 		self->notify.disconnect_indication(self->notify.instance, 
 						   self, reason, userdata);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), no handler\n");
+		dev_kfree_skb(userdata);
 	}
 }
 
@@ -687,9 +678,7 @@
 	struct lap_cb *lap;
 
 	/* Make sure the value is sane */
-	if ((nslots != 1) && (nslots != 6) && 
-	    (nslots != 8) && (nslots != 16)) 
-	{
+	if ((nslots != 1) && (nslots != 6) && (nslots != 8) && (nslots != 16)){
 		WARNING(__FUNCTION__ 
 		       "(), invalid value for number of slots!\n");
 		nslots = sysctl_discovery_slots = 8;
@@ -918,13 +907,15 @@
  *    Got data from LAP layer so pass it up to upper layer
  *
  */
-inline void irlmp_data_indication(struct lsap_cb *self, struct sk_buff *skb) 
+void irlmp_data_indication(struct lsap_cb *self, struct sk_buff *skb) 
 {
 	/* Hide LMP header from layer above */
 	skb_pull(skb, LMP_HEADER);
 
 	if (self->notify.data_indication)
 		self->notify.data_indication(self->notify.instance, self, skb);
+	else
+		dev_kfree_skb(skb);
 }
 
 /*
@@ -933,17 +924,17 @@
  *    
  *
  */
-inline void irlmp_udata_request(struct lsap_cb *self, struct sk_buff *skb) 
+int irlmp_udata_request(struct lsap_cb *self, struct sk_buff *skb) 
 {
  	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
 
-	ASSERT(skb != NULL, return;);
+	ASSERT(skb != NULL, 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_UDATA_REQUEST, skb);
+	return irlmp_do_lsap_event(self, LM_UDATA_REQUEST, skb);
 }
 
 /*
@@ -964,30 +955,83 @@
 	skb_pull(skb, LMP_HEADER);
 
 	if (self->notify.udata_indication)
-		self->notify.udata_indication(self->notify.instance, self, skb);
+		self->notify.udata_indication(self->notify.instance, self, 
+					      skb);
+	else
+		dev_kfree_skb(skb);
 }
 
 /*
- * Function irlmp_connection_less_data_request (skb)
+ * Function irlmp_connless_data_request (self, skb)
  *
- *    Send out of connection UI frames
+ *    
  *
  */
-void irlmp_connectionless_data_request( struct sk_buff *skb)
+#ifdef CONFIG_IRDA_ULTRA
+int irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *skb) 
 {
-	IRDA_DEBUG( 1, __FUNCTION__ "(), Sorry not implemented\n"); 
+	struct sk_buff *clone_skb;
+	struct lap_cb *lap;
+
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
+
+	ASSERT(skb != NULL, return -1;);
+	
+	/* Make room for MUX and PID header */
+	ASSERT(skb_headroom(skb) >= LMP_HEADER+LMP_PID_HEADER, return -1;);
+	
+	/* Insert protocol identifier */
+	skb_push(skb, LMP_PID_HEADER);
+	skb->data[0] = self->pid;
+
+	/* Connectionless sockets must use 0x70 */
+	skb_push(skb, LMP_HEADER);
+	skb->data[0] = skb->data[1] = LSAP_CONNLESS;
+
+	/* Try to send Connectionless  packets out on all links */
+	lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
+	while (lap != NULL) {
+		ASSERT(lap->magic == LMP_LAP_MAGIC, return -1;);
+
+		clone_skb = skb_clone(skb, GFP_ATOMIC);
+		if (!clone_skb)
+			return -ENOMEM;
+
+		irlap_unitdata_request(lap->irlap, clone_skb);
+		
+		lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
+	}
+	dev_kfree_skb(skb);
+
+	return 0;
 }
+#endif /* CONFIG_IRDA_ULTRA */
 
 /*
- * Function irlmp_connection_less_data_indication (skb)
+ * Function irlmp_connless_data_indication (self, skb)
  *
- *    
+ *    Receive unreliable data outside any connection. Mostly used by Ultra
  *
  */
-void irlmp_connectionless_data_indication(struct sk_buff *skb)
+#ifdef CONFIG_IRDA_ULTRA
+void irlmp_connless_data_indication(struct lsap_cb *self, struct sk_buff *skb) 
 {
-	IRDA_DEBUG( 1, __FUNCTION__ "()\n"); 
+ 	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
+
+	/* Hide LMP and PID header from layer above */
+	skb_pull(skb, LMP_HEADER+LMP_PID_HEADER);
+
+	if (self->notify.udata_indication)
+		self->notify.udata_indication(self->notify.instance, self,
+					      skb);
+	else
+		dev_kfree_skb(skb);
 }
+#endif /* CONFIG_IRDA_ULTRA */
 
 void irlmp_status_request(void) 
 {
@@ -1310,8 +1354,14 @@
 
 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
+#ifdef CONFIG_IRDA_ULTRA
+	/* Accept all bindings to the connectionless LSAP */
+	if (slsap_sel == LSAP_CONNLESS)
+		return FALSE;
+#endif /* CONFIG_IRDA_ULTRA */
+
 	/* Valid values are between 0 and 127 */
-	if (slsap_sel > 127)
+	if (slsap_sel > LSAP_MAX)
 		return TRUE;
 
 	/*
@@ -1359,8 +1409,8 @@
 	while (irlmp_slsap_inuse(irlmp->free_lsap_sel)) {
 		irlmp->free_lsap_sel++;
 
-		/* Check if we need to wraparound */
-		if (irlmp->free_lsap_sel > 127) {
+		/* Check if we need to wraparound (0x70-0x7f are reserved) */
+		if (irlmp->free_lsap_sel > LSAP_MAX) {
 			irlmp->free_lsap_sel = 10;
 
 			/* Make sure we terminate the loop */
@@ -1431,7 +1481,7 @@
 
 #ifdef CONFIG_PROC_FS
 /*
- * Function irlmp_proc_read (buf, start, offset, len)
+ * Function irlmp_proc_read (buf, start, offset, len, unused)
  *
  *    Give some info to the /proc file system
  *
@@ -1474,6 +1524,7 @@
 
 		len += sprintf(buf+len, "saddr: %#08x, daddr: %#08x, ",
 			       lap->saddr, lap->daddr); 
+		len += sprintf(buf+len, "refcount: %d", lap->refcount);
 		len += sprintf(buf+len, "\n");
 
 		len += sprintf(buf+len, "\nConnected LSAPs:\n");
@@ -1495,7 +1546,6 @@
 
 		lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
  	} 
-
 	restore_flags(flags);
 	
 	return len;
diff -u --recursive --new-file v2.3.34/linux/net/irda/irlmp_event.c linux/net/irda/irlmp_event.c
--- v2.3.34/linux/net/irda/irlmp_event.c	Wed Oct 27 16:34:13 1999
+++ linux/net/irda/irlmp_event.c	Tue Dec 21 10:17:58 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:   Tue Oct  5 13:47:53 1999
+ * Modified at:   Tue Dec 14 23:04:16 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -121,7 +121,7 @@
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
 	IRDA_DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
-	      irlmp_event[ event], irlmp_state[ self->lsap_state]);
+		   irlmp_event[event], irlmp_state[ self->lsap_state]);
 
 	return (*lsap_state[self->lsap_state]) (self, event, skb);
 }
@@ -139,8 +139,8 @@
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 	
 	IRDA_DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
-	      irlmp_event[event], 
-	      irlmp_state[self->lap_state]);
+		   irlmp_event[event], 
+		   irlmp_state[self->lap_state]);
 
 	(*lap_state[self->lap_state]) (self, event, skb);
 }
@@ -221,19 +221,23 @@
 	case LM_LAP_CONNECT_REQUEST:
 		IRDA_DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
 
+		irlmp_next_lap_state(self, LAP_U_CONNECT);
+		self->refcount++;
+
 		/* FIXME: need to set users requested QoS */
 		irlap_connect_request(self->irlap, self->daddr, NULL, 0);
-
-		irlmp_next_lap_state(self, LAP_U_CONNECT);
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
 		IRDA_DEBUG(4, __FUNCTION__ 
-		      "(), Error LM_LAP_DISCONNECT_INDICATION\n");
+			   "(), Error LM_LAP_DISCONNECT_INDICATION\n");
 		
-		irlmp_next_lap_state( self, LAP_STANDBY);
+		irlmp_next_lap_state(self, LAP_STANDBY);
 		break;
 	default:
-		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;
 	}
 }
@@ -245,8 +249,8 @@
  *    since the IrLAP connection does not exist, we must first start an
  *    IrLAP connection. We are now waiting response from IrLAP.
  * */
-static void irlmp_state_u_connect( struct lap_cb *self, IRLMP_EVENT event, 
-				   struct sk_buff *skb)
+static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event, 
+				  struct sk_buff *skb)
 {
 	struct lsap_cb *lsap;
 	struct lsap_cb *lsap_current;
@@ -254,23 +258,41 @@
 	IRDA_DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[event]);
 
 	switch (event) {
+	case LM_LAP_CONNECT_INDICATION:
+		/*  It's important to switch state first, to avoid IrLMP to 
+		 *  think that the link is free since IrLMP may then start
+		 *  discovery before the connection is properly set up. DB.
+		 */
+		irlmp_next_lap_state(self, LAP_ACTIVE);
+
+		/* Just accept connection TODO, this should be fixed */
+		irlap_connect_response(self->irlap, skb);
+
+		lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
+		while (lsap != NULL) {
+			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
+			lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
+		}
+		break;
+	case LM_LAP_CONNECT_REQUEST:
+		/* Already trying to connect */
+		self->refcount++;
+		break;
 	case LM_LAP_CONNECT_CONFIRM:
 		/* For all lsap_ce E Associated do LS_Connect_confirm */
 		irlmp_next_lap_state(self, LAP_ACTIVE);
 
 		lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
 		while (lsap != NULL) {
-			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, skb);
+			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
 			lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
-		}		
+		}
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
-		IRDA_DEBUG(2, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
-	
 		irlmp_next_lap_state(self, LAP_STANDBY);
+		self->refcount = 0;
 
 		/* Send disconnect event to all LSAPs using this link */
-		
 		lsap = (struct lsap_cb *) hashbin_get_first( self->lsaps);
 		while (lsap != NULL ) {
 			ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
@@ -278,7 +300,7 @@
 			lsap_current = lsap;
 
 			/* Be sure to stay one item ahead */
-			lsap = (struct lsap_cb *) hashbin_get_next( self->lsaps);
+			lsap = (struct lsap_cb *) hashbin_get_next(self->lsaps);
 			irlmp_do_lsap_event(lsap_current, 
 					    LM_LAP_DISCONNECT_INDICATION,
 					    NULL);
@@ -287,13 +309,15 @@
 	case LM_LAP_DISCONNECT_REQUEST:
 		IRDA_DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
 
-		irlmp_next_lap_state(self, LAP_STANDBY);
-
-		/* FIXME */
-/* 		irlap_disconnect_request( self->irlap); */
+		self->refcount--;
+		if (self->refcount == 0)
+			irlmp_next_lap_state(self, LAP_STANDBY);
 		break;
 	default:
-		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;
 	}	
 }
@@ -310,11 +334,12 @@
 	struct lsap_cb *lsap;
 	struct lsap_cb *lsap_current;
 
-	IRDA_DEBUG( 4, __FUNCTION__ "()\n"); 
+	IRDA_DEBUG(4, __FUNCTION__ "()\n"); 
 
- 	switch( event) {
+ 	switch (event) {
 	case LM_LAP_CONNECT_REQUEST:
-		IRDA_DEBUG( 4, __FUNCTION__ "(), LS_CONNECT_REQUEST\n");
+		IRDA_DEBUG(4, __FUNCTION__ "(), LS_CONNECT_REQUEST\n");
+		self->refcount++;
 
 		/*
 		 *  LAP connection allready active, just bounce back! Since we 
@@ -324,7 +349,7 @@
 		 */
 		lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
 		while (lsap != NULL) {
-			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, skb);
+			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
  			lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
 		}
 		
@@ -336,11 +361,13 @@
 			/* Be sure to stay one item ahead */
  			lsap = (struct lsap_cb*) hashbin_get_next(irlmp->unconnected_lsaps);
 			irlmp_do_lsap_event(lsap_current, 
-					    LM_LAP_CONNECT_CONFIRM, skb);
+					    LM_LAP_CONNECT_CONFIRM, NULL);
 		}
 		/* Keep state */
 		break;
 	case LM_LAP_DISCONNECT_REQUEST:
+		self->refcount--;
+
 		/*
 		 *  Need to find out if we should close IrLAP or not. If there
 		 *  is only one LSAP connection left on this link, that LSAP 
@@ -363,6 +390,7 @@
 		break;
 	case LM_LAP_DISCONNECT_INDICATION:
 		irlmp_next_lap_state(self, LAP_STANDBY);		
+		self->refcount = 0;
 		
 		/* 
 		 *  Inform all connected LSAP's using this link
@@ -381,7 +409,9 @@
 		}
 		break;
 	default:
-		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %d\n", event);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;
 	}	
 }
@@ -409,8 +439,21 @@
 	ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
 
 	switch (event) {
+#ifdef CONFIG_IRDA_ULTRA
+	case LM_UDATA_INDICATION:
+		irlmp_connless_data_indication(self, skb); 
+		break;
+#endif /* CONFIG_IRDA_ULTRA */
 	case LM_CONNECT_REQUEST:
 		IRDA_DEBUG(4, __FUNCTION__ "(), LM_CONNECT_REQUEST\n");
+
+		if (self->conn_skb) {
+			WARNING(__FUNCTION__ 
+				"(), busy with another request!\n");
+			return -EBUSY;
+		}
+		self->conn_skb = skb;
+
 		irlmp_next_lsap_state(self, LSAP_SETUP_PEND);
 
 		irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
@@ -421,10 +464,20 @@
 	case LM_CONNECT_INDICATION:
 		irlmp_next_lsap_state(self, LSAP_CONNECT_PEND);
 
-		irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, skb);
+		if (self->conn_skb) {
+			WARNING(__FUNCTION__ 
+				"(), busy with another request!\n");
+			return -EBUSY;
+		}
+		self->conn_skb = skb;
+
+		irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
 		break;
 	default:
-		IRDA_DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlmp_event[event]);
+		if (skb)
+  			dev_kfree_skb(skb);
 		break;
 	}
 	return ret;
@@ -471,7 +524,10 @@
 		irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
 		break;
 	default:
-		IRDA_DEBUG( 4, __FUNCTION__ "(), Unknown event\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;
 	}
 	return ret;
@@ -499,21 +555,28 @@
 		break;
 	case LM_CONNECT_RESPONSE:
 		IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, "
-		      "no indication issued yet\n");
+			   "no indication issued yet\n");
 		/* Keep state */
 		break;
 	case LM_DISCONNECT_REQUEST:
 		IRDA_DEBUG(0, __FUNCTION__ "(), LM_DISCONNECT_REQUEST, "
-		      "not yet bound to IrLAP connection\n");
+			   "not yet bound to IrLAP connection\n");
 		/* Keep state */
 		break;
 	case LM_LAP_CONNECT_CONFIRM:
 		IRDA_DEBUG(4, __FUNCTION__ "(), LS_CONNECT_CONFIRM\n");
 		irlmp_next_lsap_state(self, LSAP_CONNECT);
+
+		skb = self->conn_skb;
+		self->conn_skb = NULL;
+
 		irlmp_connect_indication(self, skb);
 		break;
 	default:
-		IRDA_DEBUG( 4, __FUNCTION__ "Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "Unknown event %s\n", 
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;	
 	}
 	return ret;
@@ -541,11 +604,9 @@
 	case LM_DATA_REQUEST: /* Optimize for the common case */
 		irlmp_send_data_pdu(self->lap, self->dlsap_sel, 
 				    self->slsap_sel, FALSE, skb);
-		/* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/
 		break;
 	case LM_DATA_INDICATION: /* Optimize for the common case */
 		irlmp_data_indication(self, skb); 
-		/* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/
 		break;
 	case LM_UDATA_REQUEST:
 		ASSERT(skb != NULL, return -1;);
@@ -554,21 +615,20 @@
 		break;
 	case LM_UDATA_INDICATION:
 		irlmp_udata_indication(self, skb); 
-		/* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/
 		break;
 	case LM_CONNECT_REQUEST:
 		IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_REQUEST, "
-		      "error, LSAP already connected\n");
+			   "error, LSAP already connected\n");
 		/* Keep state */
 		break;
 	case LM_CONNECT_RESPONSE:
 		IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, " 
-		      "error, LSAP allready connected\n");
+			   "error, LSAP allready connected\n");
 		/* Keep state */
 		break;
 	case LM_DISCONNECT_REQUEST:
-		irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, 
-				   self->slsap_sel, DISCONNECT, skb);
+		irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel,
+				   DISCONNECT, skb);
 		irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
 		
 		/* Try to close the LAP connection if its still there */
@@ -603,7 +663,10 @@
 		irlmp_disconnect_indication(self, reason, skb);
 		break;
 	default:
-		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;	
 	}
 	return ret;
@@ -673,7 +736,10 @@
 		irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
 		break;
 	default:
-		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;	
 	}
 	return ret;
@@ -700,9 +766,14 @@
 
 	switch (event) {
 	case LM_LAP_CONNECT_CONFIRM:
+		ASSERT(self->conn_skb != NULL, return -1;);
+
+		skb = self->conn_skb;
+		self->conn_skb = NULL;
+
 		irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, 
-				   self->slsap_sel, CONNECT_CMD, 
-				   self->tmp_skb);
+				   self->slsap_sel, CONNECT_CMD, skb);
+
 		irlmp_next_lsap_state(self, LSAP_SETUP);
 		break;
 	case LM_WATCHDOG_TIMEOUT:
@@ -710,21 +781,24 @@
 
 		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_next_lsap_state(self, LSAP_DISCONNECTED);
 
-		irlmp_disconnect_indication( self, LM_CONNECT_FAILURE, NULL);
+		irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
 		break;
 	case LM_LAP_DISCONNECT_INDICATION: /* LS_Disconnect.indication */
 		del_timer( &self->watchdog_timer);
 
-		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+		irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
 		
-		reason = irlmp_convert_lap_reason( self->lap->reason);
+		reason = irlmp_convert_lap_reason(self->lap->reason);
 		
 		irlmp_disconnect_indication(self, reason, NULL);
 		break;
 	default:
-		IRDA_DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
+			   irlmp_event[event]);
+		if (skb)
+ 			dev_kfree_skb(skb);
 		break;	
 	}
 	return ret;
diff -u --recursive --new-file v2.3.34/linux/net/irda/irlmp_frame.c linux/net/irda/irlmp_frame.c
--- v2.3.34/linux/net/irda/irlmp_frame.c	Wed Oct 27 16:34:13 1999
+++ linux/net/irda/irlmp_frame.c	Tue Dec 21 10:17:58 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:   Thu Jul  8 12:12:02 1999
+ * Modified at:   Mon Dec 13 13:41:12 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -45,9 +45,9 @@
 
 	if (expedited) {
 		IRDA_DEBUG(4, __FUNCTION__ "(), sending expedited data\n");
-		irlap_data_request(self->irlap, skb, FALSE);
-	} else
 		irlap_data_request(self->irlap, skb, TRUE);
+	} else
+		irlap_data_request(self->irlap, skb, FALSE);
 }
 
 /*
@@ -60,8 +60,8 @@
 {
 	__u8 *frame;
 	
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
-	
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 	ASSERT(skb != NULL, return;);
@@ -78,8 +78,7 @@
 	else
 		frame[3] = 0x00; /* rsvd */
 
-	ASSERT(self->irlap != NULL, return;);
-	irlap_data_request(self->irlap, skb, TRUE);
+	irlap_data_request(self->irlap, skb, FALSE);
 }
 
 /*
@@ -88,14 +87,16 @@
  *    Used by IrLAP to pass received data frames to IrLMP layer
  *
  */
-void irlmp_link_data_indication(struct lap_cb *self, int reliable, 
-			        struct sk_buff *skb)
+void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb, 
+				int unreliable)
 {
 	struct lsap_cb *lsap;
 	__u8   slsap_sel;   /* Source (this) LSAP address */
 	__u8   dlsap_sel;   /* Destination LSAP address */
 	__u8   *fp;
 	
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 	ASSERT(skb->len > 2, return;);
@@ -107,15 +108,16 @@
 	 *  destination LSAP of received frame is source LSAP in our view
 	 */
 	slsap_sel = fp[0] & LSAP_MASK; 
-	dlsap_sel = fp[1];
+	dlsap_sel = fp[1];	
 
 	/*
 	 *  Check if this is an incoming connection, since we must deal with
 	 *  it in a different way than other established connections.
 	 */
 	if ((fp[0] & CONTROL_BIT) && (fp[2] == CONNECT_CMD)) {
-		IRDA_DEBUG(3,"Incoming connection, source LSAP=%d, dest LSAP=%d\n",
-		      slsap_sel, dlsap_sel);
+		IRDA_DEBUG(3, __FUNCTION__ "(), incoming connection, "
+			   "source LSAP=%d, dest LSAP=%d\n",
+			   slsap_sel, dlsap_sel);
 		
 		/* Try to find LSAP among the unconnected LSAPs */
 		lsap = irlmp_find_lsap(self, dlsap_sel, slsap_sel, CONNECT_CMD,
@@ -148,7 +150,7 @@
 	 *  Check if we received a control frame? 
 	 */
 	if (fp[0] & CONTROL_BIT) {
-		switch(fp[2]) {
+		switch (fp[2]) {
 		case CONNECT_CMD:
 			lsap->lap = self;
 			irlmp_do_lsap_event(lsap, LM_CONNECT_INDICATION, skb);
@@ -157,35 +159,107 @@
 			irlmp_do_lsap_event(lsap, LM_CONNECT_CONFIRM, skb);
 			break;
 		case DISCONNECT:
-			IRDA_DEBUG( 4, __FUNCTION__ "(), Disconnect indication!\n");
+			IRDA_DEBUG(4, __FUNCTION__ 
+				   "(), Disconnect indication!\n");
 			irlmp_do_lsap_event(lsap, LM_DISCONNECT_INDICATION, 
 					    skb);
 			break;
 		case ACCESSMODE_CMD:
-			IRDA_DEBUG( 0, "Access mode cmd not implemented!\n");
+			IRDA_DEBUG(0, "Access mode cmd not implemented!\n");
+			dev_kfree_skb(skb);
 			break;
 		case ACCESSMODE_CNF:
-			IRDA_DEBUG( 0, "Access mode cnf not implemented!\n");
+			IRDA_DEBUG(0, "Access mode cnf not implemented!\n");
+			dev_kfree_skb(skb);
 			break;
 		default:
-			IRDA_DEBUG( 0, __FUNCTION__ 
-			       "(), Unknown control frame %02x\n", fp[2]);
+			IRDA_DEBUG(0, __FUNCTION__ 
+				   "(), Unknown control frame %02x\n", fp[2]);
+			dev_kfree_skb(skb);
 			break;
 		}
-	} else if (reliable == LAP_RELIABLE) {
+	} else if (unreliable) {
 		/* Optimize and bypass the state machine if possible */
 		if (lsap->lsap_state == LSAP_DATA_TRANSFER_READY)
-			irlmp_data_indication(lsap, skb);
+			irlmp_udata_indication(lsap, skb);
 		else
-			irlmp_do_lsap_event(lsap, LM_DATA_INDICATION, skb);
-	} else if (reliable == LAP_UNRELIABLE) {
+			irlmp_do_lsap_event(lsap, LM_UDATA_INDICATION, skb);
+	} else {	
 		/* Optimize and bypass the state machine if possible */
 		if (lsap->lsap_state == LSAP_DATA_TRANSFER_READY)
 			irlmp_data_indication(lsap, skb);
 		else
-			irlmp_do_lsap_event(lsap, LM_UDATA_INDICATION, skb);
+			irlmp_do_lsap_event(lsap, LM_DATA_INDICATION, skb);
+	}
+}
+
+/*
+ * Function irlmp_link_unitdata_indication (self, skb)
+ *
+ *    
+ *
+ */
+#ifdef CONFIG_IRDA_ULTRA
+void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
+{
+	struct lsap_cb *lsap;
+	__u8   slsap_sel;   /* Source (this) LSAP address */
+	__u8   dlsap_sel;   /* Destination LSAP address */
+	__u8   pid;         /* Protocol identifier */
+	__u8   *fp;
+	
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+	ASSERT(skb->len > 2, return;);
+
+	fp = skb->data;
+
+	/*
+	 *  The next statements may be confusing, but we do this so that 
+	 *  destination LSAP of received frame is source LSAP in our view
+	 */
+	slsap_sel = fp[0] & LSAP_MASK; 
+	dlsap_sel = fp[1];
+	pid       = fp[2];
+	
+	if (pid & 0x80) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), extension in PID not supp!\n");
+		dev_kfree_skb(skb);
+
+		return;
+	}
+
+	/* Check if frame is addressed to the connectionless LSAP */
+	if ((slsap_sel != LSAP_CONNLESS) || (dlsap_sel != LSAP_CONNLESS)) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), dropping frame!\n");
+		dev_kfree_skb(skb);
+		
+		return;
+	}
+	
+	lsap = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps);
+	while (lsap != NULL) {
+		/*
+		 *  Check if source LSAP and dest LSAP selectors and PID match.
+		 */
+		if ((lsap->slsap_sel == slsap_sel) && 
+		    (lsap->dlsap_sel == dlsap_sel) && 
+		    (lsap->pid == pid)) 
+		{			
+			break;
+		}
+		lsap = (struct lsap_cb *) hashbin_get_next(irlmp->unconnected_lsaps);
+	}
+	if (lsap)
+		irlmp_connless_data_indication(lsap, skb);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), found no matching LSAP!\n");
+		dev_kfree_skb(skb);
 	}
 }
+#endif /* CONFIG_IRDA_ULTRA */
 
 /*
  * Function irlmp_link_disconnect_indication (reason, userdata)
@@ -207,7 +281,9 @@
 	lap->daddr = DEV_ADDR_ANY;
 
         /* FIXME: must do something with the userdata if any */
-
+	if (userdata)
+		dev_kfree_skb(userdata);
+	
 	/*
 	 *  Inform station state machine
 	 */
@@ -251,6 +327,10 @@
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 	ASSERT(qos != NULL, return;);
 
+	/* Don't need use the userdata for now */
+	if (userdata)
+		dev_kfree_skb(userdata);
+
 	/* Copy QoS settings for this session */
 	self->qos = qos;
 
@@ -270,9 +350,10 @@
 	ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 
 	irlmp_add_discovery(irlmp->cachelog, discovery);
+	
+#if 0   /* This will just cause a lot of connection collisions */
 
 	/* Just handle it the same way as a discovery confirm */
-#if 0
 	irlmp_do_lap_event(self, LM_LAP_DISCOVERY_CONFIRM, NULL);
 #endif
 }
@@ -369,5 +450,3 @@
 	/* Sorry not found! */
 	return NULL;
 }
-
-
diff -u --recursive --new-file v2.3.34/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.3.34/linux/net/irda/irmod.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/irmod.c	Tue Dec 21 10:17:58 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:   Sun Nov 14 08:57:52 1999
+ * Modified at:   Thu Dec 16 21:46:38 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
@@ -140,6 +140,7 @@
 EXPORT_SYMBOL(irias_insert_object);
 EXPORT_SYMBOL(irias_new_object);
 EXPORT_SYMBOL(irias_delete_object);
+EXPORT_SYMBOL(irias_delete_value);
 EXPORT_SYMBOL(irias_find_object);
 EXPORT_SYMBOL(irias_find_attrib);
 EXPORT_SYMBOL(irias_new_integer_value);
@@ -194,6 +195,7 @@
 EXPORT_SYMBOL(irda_task_execute);
 EXPORT_SYMBOL(irda_task_kick);
 EXPORT_SYMBOL(irda_task_next_state);
+EXPORT_SYMBOL(irda_task_delete);
 
 EXPORT_SYMBOL(async_wrap_skb);
 EXPORT_SYMBOL(async_unwrap_char);
@@ -210,7 +212,7 @@
 
 int __init irda_init(void)
 {
-	MESSAGE("IrDA (tm) Protocols for Linux-2.3 (Dag Brattli)\n");
+	MESSAGE("IrDA (tm) Protocols for Linux-2.2 (Dag Brattli)\n");
 	
  	irlmp_init();
 	irlap_init();
@@ -523,6 +525,24 @@
 #ifdef MODULE
 	MOD_DEC_USE_COUNT;
 #endif
+}
+
+/*
+ * Function irda_proc_modcount (inode, fill)
+ *
+ *    Use by the proc file system functions to prevent the irda module
+ *    being removed while the use is standing in the net/irda directory
+ */
+void irda_proc_modcount(struct inode *inode, int fill)
+{
+#ifdef MODULE
+#ifdef CONFIG_PROC_FS
+	if (fill)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
+#endif /* CONFIG_PROC_FS */
+#endif /* MODULE */
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.3.34/linux/net/irda/irqueue.c linux/net/irda/irqueue.c
--- v2.3.34/linux/net/irda/irqueue.c	Wed Oct 27 16:34:13 1999
+++ linux/net/irda/irqueue.c	Tue Dec 21 10:17:58 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jun  9 13:29:31 1998
- * Modified at:   Tue Oct  5 09:02:15 1999
+ * Modified at:   Sun Dec 12 13:48:22 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (C) 1998-1999, Aage Kvalnes <aage@cs.uit.no>
@@ -88,13 +88,13 @@
 	/*
 	 * Free the entries in the hashbin
 	 */
-	for ( i = 0; i < HASHBIN_SIZE; i ++ ) {
-		queue = dequeue_first( (queue_t**) &hashbin->hb_queue[ i]);
-		while( queue ) {
-			if ( free_func)
-				(*free_func)( queue );
+	for (i = 0; i < HASHBIN_SIZE; i ++ ) {
+		queue = dequeue_first( (queue_t**) &hashbin->hb_queue[i]);
+		while (queue) {
+			if (free_func)
+				(*free_func)(queue);
 			queue = dequeue_first( 
-				(queue_t**) &hashbin->hb_queue[ i]);
+				(queue_t**) &hashbin->hb_queue[i]);
 		}
 	}
 	hashbin->hb_size = 0;
@@ -210,7 +210,7 @@
  *    Insert an entry into the hashbin
  *
  */
-void hashbin_insert( hashbin_t* hashbin, queue_t* entry, __u32 hashv, char* name)
+void hashbin_insert(hashbin_t* hashbin, queue_t* entry, __u32 hashv, char* name)
 {
 	unsigned long flags = 0;
 	int bin;
diff -u --recursive --new-file v2.3.34/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.3.34/linux/net/irda/irttp.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/irttp.c	Tue Dec 21 10:17:58 1999
@@ -3,10 +3,10 @@
  * Filename:      irttp.c
  * Version:       1.2
  * Description:   Tiny Transport Protocol (TTP) implementation
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Tue Oct 19 21:40:00 1999
+ * Modified at:   Thu Dec 16 23:00:03 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -166,7 +166,7 @@
 	/*
 	 *  Create LSAP at IrLMP layer
 	 */
-	lsap = irlmp_open_lsap(stsap_sel, &ttp_notify);
+	lsap = irlmp_open_lsap(stsap_sel, &ttp_notify, 0);
 	if (lsap == NULL) {
 		WARNING(__FUNCTION__ "(), unable to allocate LSAP!!\n");
 		return NULL;
@@ -326,7 +326,7 @@
 	 *  TxMaxSduSize 
 	 */
 	if ((self->tx_max_sdu_size != 0) && 
-	    (self->tx_max_sdu_size != SAR_UNBOUND) && 
+	    (self->tx_max_sdu_size != TTP_SAR_UNBOUND) && 
 	    (skb->len > self->tx_max_sdu_size))
 	{
 		ERROR(__FUNCTION__ "(), SAR enabled, "
@@ -365,7 +365,7 @@
 
 	/* Check if we can accept more data from client */
 	if ((!self->tx_sdu_busy) && 
-	    (skb_queue_len(&self->tx_queue) > HIGH_THRESHOLD)) {
+	    (skb_queue_len(&self->tx_queue) > TTP_HIGH_THRESHOLD)) {
 		
 		/* Tx queue filling up, so stop client */
 		self->tx_sdu_busy = TRUE;
@@ -446,7 +446,7 @@
 
 		/* Check if we can accept more frames from client */
 		if ((self->tx_sdu_busy) && 
-		    (skb_queue_len(&self->tx_queue) < LOW_THRESHOLD)) 
+		    (skb_queue_len(&self->tx_queue) < TTP_LOW_THRESHOLD)) 
 		{
 			self->tx_sdu_busy = FALSE;
 			
@@ -477,7 +477,7 @@
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);	
 
 	IRDA_DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
-	       self->send_credit, self->avail_credit, self->remote_credit);
+		   self->send_credit, self->avail_credit, self->remote_credit);
 	
 	/* Give credit to peer */
 	tx_skb = dev_alloc_skb(64);
@@ -533,9 +533,11 @@
 	ASSERT(skb != NULL, return -1;);
 
 	/* Just pass data to layer above */
-	if (self->notify.udata_indication) {
-		self->notify.udata_indication(self->notify.instance, self, skb);
-	}
+	if (self->notify.udata_indication)
+		self->notify.udata_indication(self->notify.instance, self,skb);
+	else
+		dev_kfree_skb(skb);
+
 	self->stats.rx_packets++;
 
 	return 0;
@@ -573,8 +575,10 @@
 		 *  more bit, so the defragment routing knows what to do
 		 */
 		skb_queue_tail(&self->rx_queue, skb);
-	} else
+	} else {
 		self->send_credit += n;	/* Dataless flowdata TTP-PDU */
+		dev_kfree_skb(skb);
+	}
 
 	irttp_run_rx_queue(self);
 
@@ -582,7 +586,7 @@
 	 *  Give avay some credits to peer? 
 	 */
 	if ((skb_queue_empty(&self->tx_queue)) && 
-	    (self->remote_credit < LOW_THRESHOLD) && 
+	    (self->remote_credit < TTP_LOW_THRESHOLD) && 
 	    (self->avail_credit > 0)) 
 	{
 		/* Schedule to start immediately after this thread */
@@ -830,7 +834,7 @@
 
 	lsap = (struct lsap_cb *) sap;
 
-	self->max_seg_size = max_seg_size;
+	self->max_seg_size = max_seg_size - TTP_HEADER;;
 	self->max_header_size = max_header_size+TTP_HEADER;
 
 	IRDA_DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
@@ -873,7 +877,8 @@
 		self->notify.connect_indication(self->notify.instance, self, 
 						qos, self->tx_max_sdu_size, 
 						self->max_header_size, skb);
-	}
+	} else
+		dev_kfree_skb(skb);
 }
 
 /*
@@ -895,7 +900,7 @@
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
 
 	IRDA_DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n", 
-	      self->stsap_sel);
+		   self->stsap_sel);
 	
 	/* Any userdata supplied? */
 	if (userdata == NULL) {
@@ -1093,7 +1098,7 @@
  *
  */
 void irttp_disconnect_indication(void *instance, void *sap, LM_REASON reason, 
-				 struct sk_buff *userdata) 
+				 struct sk_buff *skb) 
 {
 	struct tsap_cb *self;
 
@@ -1106,11 +1111,13 @@
 	
 	self->connected = FALSE;
 	
-	if (!self->notify.disconnect_indication)
-		return;
-
-	self->notify.disconnect_indication(self->notify.instance, self, reason,
-					   userdata);
+	if (self->notify.disconnect_indication)
+		self->notify.disconnect_indication(self->notify.instance, 
+						   self, reason, skb);
+	else {
+		if (skb)
+			dev_kfree_skb(skb);
+	}
 }
 
 /*
@@ -1157,8 +1164,8 @@
 	struct sk_buff *skb;
 	int more = 0;
 
-	IRDA_DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
-	       self->send_credit, self->avail_credit, self->remote_credit);
+	IRDA_DEBUG(2, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
+		   self->send_credit, self->avail_credit, self->remote_credit);
 
 	if (irda_lock(&self->rx_queue_lock) == FALSE)
 		return;
@@ -1183,7 +1190,7 @@
 		 * immediately. This can be requested by clients that
 		 * implements byte streams without any message boundaries
 		 */
-		if (self->rx_max_sdu_size == SAR_DISABLE) {
+		if (self->rx_max_sdu_size == TTP_SAR_DISABLE) {
 			irttp_do_data_indication(self, skb);
 			self->rx_sdu_size = 0;
 
@@ -1209,7 +1216,7 @@
 		 *  This is the last fragment, so time to reassemble!
 		 */
 		if ((self->rx_sdu_size <= self->rx_max_sdu_size) ||
-		    (self->rx_max_sdu_size == SAR_UNBOUND)) 
+		    (self->rx_max_sdu_size == TTP_SAR_UNBOUND)) 
 		{
 			/* 
 			 * A little optimizing. Only queue the fragment if
@@ -1285,10 +1292,10 @@
       	ASSERT(self != NULL, return NULL;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
 
-	IRDA_DEBUG(4, __FUNCTION__ "(), self->rx_sdu_size=%d\n", 
-	      self->rx_sdu_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), self->rx_sdu_size=%d\n", 
+		   self->rx_sdu_size);
 
-	skb = dev_alloc_skb(self->rx_sdu_size);
+	skb = dev_alloc_skb(TTP_HEADER + self->rx_sdu_size);
 	if (!skb)
 		return NULL;
 
@@ -1308,11 +1315,12 @@
 		
 		dev_kfree_skb(frag);
 	}
-	IRDA_DEBUG(4, __FUNCTION__ "(), frame len=%d\n", n);
-	/* Set the new length */
+	IRDA_DEBUG(2, __FUNCTION__ "(), frame len=%d\n", n);
 
-	IRDA_DEBUG(4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
+	IRDA_DEBUG(2, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
 	ASSERT(n <= self->rx_sdu_size, return NULL;);
+
+	/* Set the new length */
 	skb_trim(skb, n);
 
 	self->rx_sdu_size = 0;
@@ -1331,7 +1339,7 @@
 	struct sk_buff *frag;
 	__u8 *frame;
 
-	IRDA_DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
@@ -1340,22 +1348,9 @@
 	/*
 	 *  Split frame into a number of segments
 	 */
-	while (skb->len > 0) {
-		/*
-		 *  Instead of making the last segment, we just
-		 *  queue what is left of the original skb
-		 */
-		if (skb->len < self->max_seg_size) {
-			IRDA_DEBUG(4, __FUNCTION__ 
-			       "(), queuing last segment\n");
-
-			frame = skb_push(skb, TTP_HEADER);
-			frame[0] = 0x00; /* Clear more bit */
-			skb_queue_tail(&self->tx_queue, skb);
-			
-			return;
-		}
-		
+	while (skb->len > self->max_seg_size) {
+		IRDA_DEBUG(2, __FUNCTION__  "(), fragmenting ...\n");
+
 		/* Make new segment */
 		frag = dev_alloc_skb(self->max_seg_size+self->max_header_size);
 		if (!frag)
@@ -1363,19 +1358,28 @@
 
 		skb_reserve(frag, self->max_header_size);
 
-		/*
-		 *  Copy data from the original skb into this fragment. We
-		 *  first insert the TTP header with the more bit set
-		 */
-		frame = skb_put(frag, self->max_seg_size+TTP_HEADER);
+		/* Copy data from the original skb into this fragment. */
+		memcpy(skb_put(frag, self->max_seg_size), skb->data, 
+		       self->max_seg_size);
+
+		/* Insert TTP header, with the more bit set */
+		frame = skb_push(frag, TTP_HEADER);
 		frame[0] = TTP_MORE;
-		memcpy(frag->data+1, skb->data, self->max_seg_size);
 		
 		/* Hide the copied data from the original skb */
 		skb_pull(skb, self->max_seg_size);
-		
+
+		/* Queue fragment */
 		skb_queue_tail(&self->tx_queue, frag);
 	}
+	/* Queue what is left of the original skb */
+	IRDA_DEBUG(2, __FUNCTION__  "(), queuing last segment\n");
+	
+	frame = skb_push(skb, TTP_HEADER);
+	frame[0] = 0x00; /* Clear more bit */
+
+	/* Queue fragment */
+	skb_queue_tail(&self->tx_queue, skb);
 }
 
 /*
@@ -1422,7 +1426,7 @@
 	irttp_run_tx_queue(self);
 		
 	/*  Give avay some credits to peer?  */
-	if ((self->remote_credit < LOW_THRESHOLD) && 
+	if ((self->remote_credit < TTP_LOW_THRESHOLD) && 
 	    (self->avail_credit > 0) && (skb_queue_empty(&self->tx_queue)))
 	{
 		irttp_give_credit(self);
@@ -1477,7 +1481,7 @@
 
 #ifdef CONFIG_PROC_FS
 /*
- * Function irttp_proc_read (buf, start, offset, len)
+ * Function irttp_proc_read (buf, start, offset, len, unused)
  *
  *    Give some info to the /proc file system
  */
diff -u --recursive --new-file v2.3.34/linux/net/irda/parameters.c linux/net/irda/parameters.c
--- v2.3.34/linux/net/irda/parameters.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/parameters.c	Tue Dec 21 10:17:58 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Jun  7 10:25:11 1999
- * Modified at:   Fri Nov  5 08:20:38 1999
+ * Modified at:   Tue Dec 14 16:03:57 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -88,7 +88,7 @@
 	ret = (*func)(self, &p, PV_GET);
 
 	/* Extract values anyway, since handler may need them */
-	irda_param_pack(buf, "bb", p.pi, &p.pl);
+	irda_param_pack(buf, "bb", p.pi, p.pl);
 
 	if (ret < 0)
 		return ret;
diff -u --recursive --new-file v2.3.34/linux/net/irda/qos.c linux/net/irda/qos.c
--- v2.3.34/linux/net/irda/qos.c	Tue Nov 23 22:42:21 1999
+++ linux/net/irda/qos.c	Tue Dec 21 10:17:58 1999
@@ -1,13 +1,12 @@
 /*********************************************************************
- *                
- *                
+ *                                
  * Filename:      qos.c
  * Version:       1.0
  * Description:   IrLAP QoS parameter negotiation
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Sep  9 00:00:26 1997
- * Modified at:   Tue Nov 16 09:50:19 1999
+ * Modified at:   Sun Dec 12 13:47:09 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -52,18 +51,32 @@
 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 */
+__u32 min_turn_times[]  = { 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_sizes[]      = { 64, 128, 256, 512, 1024, 2048 };        /* bytes */
+__u32 add_bofs[]        = { 48, 24, 12, 5, 3, 2, 1, 0 };            /* bytes */
+__u32 max_turn_times[]  = { 500, 250, 100, 50 };                    /* ms */
+__u32 link_disc_times[] = { 3, 8, 12, 16, 20, 25, 30, 40 };         /* secs */
 
 #ifdef CONFIG_IRDA_COMPRESSION
-__u32 compression[] = { CI_BZIP2, CI_DEFLATE, CI_DEFLATE_DRAFT };
+__u32 compressions[] = { CI_BZIP2, CI_DEFLATE, CI_DEFLATE_DRAFT };
 #endif
 
+__u32 max_line_capacities[10][4] = {
+       /* 500 ms     250 ms  100 ms  50 ms (max turn time) */
+	{    100,      0,      0,     0 }, /*     2400 bps */
+	{    400,      0,      0,     0 }, /*     9600 bps */
+	{    800,      0,      0,     0 }, /*    19200 bps */
+	{   1600,      0,      0,     0 }, /*    38400 bps */
+	{   2360,      0,      0,     0 }, /*    57600 bps */
+	{   4800,   2400,    960,   480 }, /*   115200 bps */
+	{  28800,  11520,   5760,  2880 }, /*   576000 bps */
+	{  57600,  28800,  11520,  5760 }, /*  1152000 bps */
+	{ 200000, 100000,  40000, 20000 }, /*  4000000 bps */
+	{ 800000, 400000, 160000, 80000 }, /* 16000000 bps */
+};
+
 static pi_minor_info_t pi_minor_call_table_type_0[] = {
 	{ NULL, 0 },
 /* 01 */{ irlap_param_baud_rate,       PV_INTEGER | PV_LITTLE_ENDIAN },
@@ -150,6 +163,69 @@
 }
 
 /*
+ * Function irlap_adjust_qos_settings (qos)
+ *
+ *     Adjust QoS settings in case some values are not possible to use because
+ *     of other settings
+ */
+void irlap_adjust_qos_settings(struct qos_info *qos)
+{
+	__u32 line_capacity;
+	int index;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	/* 
+	 * Not allowed to use a max turn time less than 500 ms if the baudrate
+	 * is less than 115200
+	 */
+	if ((qos->baud_rate.value < 115200) && 
+	    (qos->max_turn_time.value < 500))
+	{
+		IRDA_DEBUG(0, __FUNCTION__ 
+			   "(), adjusting max turn time from %d to 500 ms\n",
+			   qos->max_turn_time.value);
+		qos->max_turn_time.value = 500;
+	}
+	
+	/*
+	 * The data size must be adjusted according to the baud rate and max 
+	 * turn time
+	 */
+	index = value_index(qos->data_size.value, data_sizes);
+	line_capacity = irlap_max_line_capacity(qos->baud_rate.value, 
+						qos->max_turn_time.value);
+
+#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
+	while ((qos->data_size.value > line_capacity) && (index > 0)) {
+		qos->data_size.value = data_sizes[index--];
+		IRDA_DEBUG(2, __FUNCTION__ 
+			   "(), redusing data size to %d\n",
+			   qos->data_size.value);
+	}
+#else /* Use method descibed in section 6.6.11 of IrLAP */
+	while (irlap_requested_line_capacity(qos) > line_capacity) {
+		ASSERT(index != 0, return;);
+
+		/* Must be able to send at least one frame */
+		if (qos->window_size.value > 1) {
+			qos->window_size.value--;
+			IRDA_DEBUG(2, __FUNCTION__ 
+				   "(), redusing window size to %d\n",
+				   qos->window_size.value);
+		} else if (index > 1) {
+			qos->data_size.value = data_sizes[index--];
+			IRDA_DEBUG(2, __FUNCTION__ 
+				   "(), redusing data size to %d\n",
+				   qos->data_size.value);
+		} else {
+			WARNING(__FUNCTION__ "(), nothing more we can do!\n");
+		}
+	}
+#endif CONFIG_IRDA_DYNAMIC_WINDOW
+}
+
+/*
  * Function irlap_negotiate (qos_device, qos_session, skb)
  *
  *    Negotiate QoS values, not really that much negotiation :-)
@@ -176,24 +252,26 @@
 	/* Convert the negotiated bits to values */
 	irda_qos_bits_to_value(&self->qos_tx);
 	irda_qos_bits_to_value(&self->qos_rx);
-		
+
+	irlap_adjust_qos_settings(&self->qos_tx);
+
 	IRDA_DEBUG(2, "Setting BAUD_RATE to %d bps.\n", 
-	      self->qos_tx.baud_rate.value);
+		   self->qos_tx.baud_rate.value);
 	IRDA_DEBUG(2, "Setting DATA_SIZE to %d bytes\n",
-	      self->qos_tx.data_size.value);
+		   self->qos_tx.data_size.value);
 	IRDA_DEBUG(2, "Setting WINDOW_SIZE to %d\n", 
-	      self->qos_tx.window_size.value);
+		   self->qos_tx.window_size.value);
 	IRDA_DEBUG(2, "Setting XBOFS to %d\n", 
-	      self->qos_tx.additional_bofs.value);
+		   self->qos_tx.additional_bofs.value);
 	IRDA_DEBUG(2, "Setting MAX_TURN_TIME to %d ms.\n",
-	      self->qos_tx.max_turn_time.value);
+		   self->qos_tx.max_turn_time.value);
 	IRDA_DEBUG(2, "Setting MIN_TURN_TIME to %d usecs.\n",
-	      self->qos_tx.min_turn_time.value);
+		   self->qos_tx.min_turn_time.value);
 	IRDA_DEBUG(2, "Setting LINK_DISC to %d secs.\n", 
-	      self->qos_tx.link_disc_time.value);
+		   self->qos_tx.link_disc_time.value);
 #ifdef CONFIG_IRDA_COMPRESSION
 	IRDA_DEBUG(2, "Setting COMPRESSION to %d\n", 
-	      self->qos_tx.compression.value);
+		   self->qos_tx.compression.value);
 #endif	
 	return ret;
 }
@@ -278,7 +356,8 @@
 
 	if (get) {
 		param->pv.i = self->qos_rx.baud_rate.bits;
-		IRDA_DEBUG(2, __FUNCTION__ "(), baud rate = 0x%02x\n", param->pv.i);		
+		IRDA_DEBUG(2, __FUNCTION__ "(), baud rate = 0x%02x\n", 
+			   param->pv.i);		
 	} else {
 		/* 
 		 *  Stations must agree on baud rate, so calculate
@@ -435,6 +514,57 @@
 	return 0;
 }
 
+/*
+ * Function irlap_max_line_capacity (speed, max_turn_time, min_turn_time)
+ *
+ *    Calculate the maximum line capacity
+ *
+ */
+__u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time)
+{
+	__u32 line_capacity;
+	int i,j;
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d, max_turn_time=%d\n",
+		   speed, max_turn_time);
+
+	i = value_index(speed, baud_rates);
+	j = value_index(max_turn_time, max_turn_times);
+
+	ASSERT(((i >=0) && (i <=10)), return 0;);
+	ASSERT(((j >=0) && (j <=4)), return 0;);
+
+	line_capacity = max_line_capacities[i][j];
+
+	IRDA_DEBUG(2, __FUNCTION__ "(), line capacity=%d bytes\n", 
+		   line_capacity);
+	
+	return line_capacity;
+}
+
+__u32 irlap_requested_line_capacity(struct qos_info *qos)
+{	__u32 line_capacity;
+	
+	line_capacity = qos->window_size.value * 
+		(qos->data_size.value + 6 + qos->additional_bofs.value) +
+		irlap_min_turn_time_in_bytes(qos->baud_rate.value, 
+					     qos->min_turn_time.value);
+	
+	IRDA_DEBUG(2, __FUNCTION__ "(), requested line capacity=%d\n",
+		   line_capacity);
+	
+	return line_capacity;			       		  
+}
+
+__u32 irlap_min_turn_time_in_bytes(__u32 speed, __u32 min_turn_time)
+{
+	__u32 bytes;
+	
+	bytes = speed * min_turn_time / 10000000;
+	
+	return bytes;
+}
+
 __u32 byte_value(__u8 byte, __u32 *array) 
 {
 	int index;
@@ -503,19 +633,19 @@
 	qos->baud_rate.value = baud_rates[index];
 
 	index = msb_index(qos->data_size.bits);
-	qos->data_size.value = data_size[index];
+	qos->data_size.value = data_sizes[index];
 
 	index = msb_index(qos->window_size.bits);
 	qos->window_size.value = index+1;
 
 	index = msb_index(qos->min_turn_time.bits);
-	qos->min_turn_time.value = min_turn_time[index];
+	qos->min_turn_time.value = min_turn_times[index];
 	
 	index = msb_index(qos->max_turn_time.bits);
-	qos->max_turn_time.value = max_turn_time[index];
+	qos->max_turn_time.value = max_turn_times[index];
 
 	index = msb_index(qos->link_disc_time.bits);
-	qos->link_disc_time.value = link_disc_time[index];
+	qos->link_disc_time.value = link_disc_times[index];
 	
 	index = msb_index(qos->additional_bofs.bits);
 	qos->additional_bofs.value = add_bofs[index];
@@ -523,7 +653,7 @@
 #ifdef CONFIG_IRDA_COMPRESSION
 	index = msb_index(qos->compression.bits);
 	if (index >= 0)
-		qos->compression.value = compression[index];
+		qos->compression.value = compressions[index];
 	else 
 		qos->compression.value = 0;
 #endif
diff -u --recursive --new-file v2.3.34/linux/net/irda/timer.c linux/net/irda/timer.c
--- v2.3.34/linux/net/irda/timer.c	Wed Oct 27 16:34:13 1999
+++ linux/net/irda/timer.c	Tue Dec 21 10:17:58 1999
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Thu Oct  7 12:30:19 1999
+ * Modified at:   Wed Dec  8 12:50:34 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -210,4 +210,8 @@
 	ASSERT(self != NULL, return;);
 
 	irda_device_set_media_busy(self->netdev, FALSE);
+
+	/* Send any pending Ultra frames if any */
+	if (!skb_queue_empty(&self->txq_ultra))
+		irlap_do_event(self, SEND_UI_FRAME, NULL, NULL);
 }
diff -u --recursive --new-file v2.3.34/linux/net/irda/wrapper.c linux/net/irda/wrapper.c
--- v2.3.34/linux/net/irda/wrapper.c	Sun Nov  7 16:37:34 1999
+++ linux/net/irda/wrapper.c	Tue Dec 21 10:17:58 1999
@@ -3,10 +3,10 @@
  * Filename:      wrapper.c
  * Version:       1.2
  * Description:   IrDA SIR async wrapper layer
- * Status:        Experimental.
+ * Status:        Stable
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Oct 30 17:24:25 1999
+ * Modified at:   Sun Dec 12 13:46: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>
@@ -86,11 +86,24 @@
 	 *  additional XBOFS
 	 */
 	if (((struct irda_skb_cb *)(skb->cb))->magic != LAP_MAGIC) {
+		/* 
+		 * This will happen for all frames sent from user-space.
+		 * Nothing to worry about, but we set the default number of 
+		 * BOF's
+		 */
 		IRDA_DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n");
 		xbofs = 10;
 	} else
 		xbofs = ((struct irda_skb_cb *)(skb->cb))->xbofs;
 
+	IRDA_DEBUG(4, __FUNCTION__ "(), xbofs=%d\n", xbofs);
+
+	/* Check that we never use more than 115 + 48 xbofs */
+	if (xbofs > 163) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), too many xbofs (%d)\n", xbofs);
+		xbofs = 163;
+	}
+
 	memset(tx_buff+n, XBOF, xbofs);
 	n += xbofs;
 
@@ -200,7 +213,7 @@
 /*
  * Function state_outside_frame (dev, rx_buff, byte)
  *
- *    
+ *    Not receiving any frame (or just bogus data)
  *
  */
 static void state_outside_frame(struct net_device *dev, 
@@ -219,6 +232,7 @@
 		irda_device_set_media_busy(dev, TRUE);
 		break;
 	default:
+		irda_device_set_media_busy(dev, TRUE);
 		break;
 	}
 }
@@ -249,13 +263,12 @@
 	case EOF:
 		/* Abort frame */
 		rx_buff->state = OUTSIDE_FRAME;
-
+		IRDA_DEBUG(1, __FUNCTION__ "(), abort frame\n");
 		stats->rx_errors++;
 		stats->rx_frame_errors++;
 		break;
 	default:
 		rx_buff->data[rx_buff->len++] = byte;
-		
 		rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
 		rx_buff->state = INSIDE_FRAME;
 		break;
@@ -265,7 +278,7 @@
 /*
  * Function state_link_escape (idev, byte)
  *
- *    
+ *    Found link escape character
  *
  */
 static void state_link_escape(struct net_device *dev, 
@@ -278,7 +291,7 @@
 		irda_device_set_media_busy(dev, TRUE);
 		break;
 	case CE:
-		IRDA_DEBUG(4, "WARNING: State not defined\n");
+		WARNING(__FUNCTION__ "(), state not defined\n");
 		break;
 	case EOF: /* Abort frame */
 		rx_buff->state = OUTSIDE_FRAME;
@@ -294,8 +307,7 @@
 			rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
 			rx_buff->state = INSIDE_FRAME;
 		} else {
-			IRDA_DEBUG(1, __FUNCTION__ 
-			      "(), Rx buffer overflow, aborting\n");
+			IRDA_DEBUG(1, __FUNCTION__ "(), rx buffer overflow\n");
 			rx_buff->state = OUTSIDE_FRAME;
 		}
 		break;
@@ -336,6 +348,7 @@
 			/* Wrong CRC, discard frame!  */
 			irda_device_set_media_busy(dev, TRUE); 
 
+			IRDA_DEBUG(1, __FUNCTION__ "(), crc error\n");
 			stats->rx_errors++;
 			stats->rx_crc_errors++;
 		}			
diff -u --recursive --new-file v2.3.34/linux/net/netsyms.c linux/net/netsyms.c
--- v2.3.34/linux/net/netsyms.c	Mon Dec 20 18:48:22 1999
+++ linux/net/netsyms.c	Wed Dec 22 19:55:38 1999
@@ -150,7 +150,7 @@
 EXPORT_SYMBOL(skb_free_datagram);
 EXPORT_SYMBOL(skb_copy_datagram);
 EXPORT_SYMBOL(skb_copy_datagram_iovec);
-EXPORT_SYMBOL(skb_realloc_headroom);
+EXPORT_SYMBOL(skb_copy_expand);
 EXPORT_SYMBOL(datagram_poll);
 EXPORT_SYMBOL(put_cmsg);
 EXPORT_SYMBOL(sock_kmalloc);
diff -u --recursive --new-file v2.3.34/linux/net/packet/af_packet.c linux/net/packet/af_packet.c
--- v2.3.34/linux/net/packet/af_packet.c	Tue Dec 14 01:27:24 1999
+++ linux/net/packet/af_packet.c	Wed Dec 22 19:55:38 1999
@@ -5,7 +5,7 @@
  *
  *		PACKET - implements raw packet sockets.
  *
- * Version:	$Id: af_packet.c,v 1.24 1999/08/30 12:14:52 davem Exp $
+ * Version:	$Id: af_packet.c,v 1.26 1999/12/20 05:20:02 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.34/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.3.34/linux/net/unix/af_unix.c	Mon Nov  1 13:56:27 1999
+++ linux/net/unix/af_unix.c	Wed Dec 22 19:55:38 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.84 1999/09/08 03:47:18 davem Exp $
+ * Version:	$Id: af_unix.c,v 1.87 1999/12/09 00:54:25 davem Exp $
  *
  * Fixes:
  *		Linus Torvalds	:	Assorted bug cures.
diff -u --recursive --new-file v2.3.34/linux/scripts/cramfs/mkcramfs.c linux/scripts/cramfs/mkcramfs.c
--- v2.3.34/linux/scripts/cramfs/mkcramfs.c	Wed Dec 31 16:00:00 1969
+++ linux/scripts/cramfs/mkcramfs.c	Tue Nov 23 17:53:38 1999
@@ -0,0 +1,349 @@
+#include <sys/types.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/fcntl.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* zlib required.. */
+#include <zlib.h>
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+#include "cramfs.h"
+
+#define PAGE_CACHE_SIZE (4096)
+
+static const char *progname = "mkcramfs";
+
+void usage(void)
+{
+	fprintf(stderr, "Usage: '%s dirname outfile'\n"
+		" where <dirname> is the root of the\n"
+		" filesystem to be compressed.\n", progname);
+	exit(1);
+}
+
+struct entry {
+	/* stats */
+	char *name;
+	unsigned int mode, size, uid, gid;
+
+	/* FS data */
+	void *uncompressed;
+	unsigned int dir_offset;	/* Where in the archive is the directory entry? */
+	unsigned int data_offset;	/* Where in the archive is the start of the data? */
+
+	/* organization */
+	struct entry *child;
+	struct entry *next;
+};
+
+/*
+ * We should mind about memory leaks and
+ * checking for out-of-memory.
+ *
+ * We don't.
+ */
+static unsigned int parse_directory(const char *name, struct entry **prev)
+{
+	DIR *dir;
+	int count = 0, totalsize = 0;
+	struct dirent *dirent;
+	char *path, *endpath;
+	int len = strlen(name);
+
+	dir = opendir(name);
+	if (!dir) {
+		perror(name);
+		exit(2);
+	}
+	/* Set up the path.. */
+	path = malloc(4096);
+	memcpy(path, name, len);
+	endpath = path + len;
+	*endpath = '/';
+	endpath++;
+
+	while ((dirent = readdir(dir)) != NULL) {
+		struct entry *entry;
+		struct stat st;
+		int fd, size;
+
+		/* Ignore "." and ".." - we won't be adding them to the archive */
+		if (dirent->d_name[0] == '.') {
+			if (dirent->d_name[1] == '\0')
+				continue;
+			if (dirent->d_name[1] == '.') {
+				if (dirent->d_name[2] == '\0')
+					continue;
+			}
+		}
+		strcpy(endpath, dirent->d_name);
+
+		if (lstat(path, &st) < 0) {
+			perror(endpath);
+			continue;
+		}
+		entry = calloc(1, sizeof(struct entry));
+		entry->name = strdup(dirent->d_name);
+		entry->mode = st.st_mode;
+		entry->size = st.st_size;
+		entry->uid = st.st_uid;
+		entry->gid = st.st_gid;
+		size = sizeof(struct cramfs_inode) + (~3 & (strlen(entry->name) + 3));
+		if (S_ISDIR(st.st_mode)) {
+			entry->size = parse_directory(path, &entry->child);
+		} else if (S_ISREG(st.st_mode)) {
+			int fd = open(path, O_RDONLY);
+			if (fd < 0) {
+				perror(path);
+				continue;
+			}
+			if (entry->size)
+				entry->uncompressed = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+			if (-1 == (int) (long) entry->uncompressed) {
+				perror("mmap");
+				exit(5);
+			}
+			close(fd);
+		} else if (S_ISLNK(st.st_mode)) {
+			entry->uncompressed = malloc(st.st_size);
+			if (readlink(path, entry->uncompressed, st.st_size) < 0) {
+				perror(path);
+				continue;
+			}
+		} else {
+			entry->size = st.st_rdev;
+		}
+
+		/* Link it into the list */
+		*prev = entry;
+		prev = &entry->next;
+		count++;
+		totalsize += size;
+	}
+	closedir(dir);
+	free(path);
+	return totalsize;
+}
+
+static void set_random(void *area, int size)
+{
+	int fd = open("/dev/random", O_RDONLY);
+
+	if (fd >= 0) {
+		if (read(fd, area, size) == size)
+			return;
+	}
+	memset(area, 0x00, size);
+}
+
+static unsigned int write_superblock(struct entry *root, char *base)
+{
+	struct cramfs_super *super = (struct cramfs_super *) base;
+	unsigned int offset = sizeof(struct cramfs_super);
+
+	super->magic = CRAMFS_MAGIC;
+	super->flags = 0;
+	super->size = 0x10000;
+	memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature));
+	set_random(super->fsid, sizeof(super->fsid));
+	strncpy(super->name, "Compressed", sizeof(super->name));
+
+	super->root.mode = root->mode;
+	super->root.uid = root->uid;
+	super->root.gid = root->gid;
+	super->root.size = root->size;
+	super->root.offset = offset >> 2;
+
+	return offset;
+}
+
+static void set_data_offset(struct entry *entry, char *base, unsigned long offset)
+{
+	struct cramfs_inode *inode = (struct cramfs_inode *) (base + entry->dir_offset);
+	inode->offset = (offset >> 2);
+}
+
+
+/*
+ * We do a width-first printout of the directory
+ * entries, using a stack to remember the directories
+ * we've seen.
+ */
+#define MAXENTRIES (100)
+static int stack_entries = 0;
+static struct entry *entry_stack[MAXENTRIES];
+
+static unsigned int write_directory_structure(struct entry *entry, char *base, unsigned int offset)
+{
+	for (;;) {
+		while (entry) {
+			struct cramfs_inode *inode = (struct cramfs_inode *) (base + offset);
+			int len = strlen(entry->name);
+
+			entry->dir_offset = offset;
+			offset += sizeof(struct cramfs_inode);
+
+			inode->mode = entry->mode;
+			inode->uid = entry->uid;
+			inode->gid = entry->gid;
+			inode->size = entry->size;
+			inode->offset = 0;	/* Fill in later */
+
+			memcpy(base + offset, entry->name, len);
+			/* Pad up the name to a 4-byte boundary */
+			while (len & 3) {
+				*(base + offset + len) = '\0';
+				len++;
+			}
+			inode->namelen = len >> 2;
+			offset += len;
+
+			printf("  %s\n", entry->name);
+
+			if (entry->child) {
+				entry_stack[stack_entries] = entry;
+				stack_entries++;
+			}
+			entry = entry->next;
+		}
+		if (!stack_entries)
+			break;
+		stack_entries--;
+		entry = entry_stack[stack_entries];
+
+		set_data_offset(entry, base, offset);
+		printf("'%s':\n", entry->name);
+		entry = entry->child;
+	}
+	return offset;
+}
+
+/*
+ * One 4-byte pointer per block and then the actual blocked
+ * output. The first block does not need an offset pointer,
+ * as it will start immediately after the pointer block.
+ *
+ * Note that size > 0, as a zero-sized file wouldn't ever
+ * have gotten here in the first place.
+ */
+static unsigned int do_compress(char *base, unsigned int offset, char *uncompressed, unsigned int size)
+{
+	unsigned long original_size = size;
+	unsigned long original_offset = offset;
+	unsigned long new_size;
+	unsigned long blocks = (size - 1) / PAGE_CACHE_SIZE + 1;
+	unsigned long curr = offset + 4 * blocks;
+	int change;
+
+	do {
+		unsigned int input = size;
+		unsigned long len = 8192;
+		if (input > PAGE_CACHE_SIZE)
+			input = PAGE_CACHE_SIZE;
+		compress(base + curr, &len, uncompressed, input);
+		uncompressed += input;
+		size -= input;
+		curr += len;
+
+		if (len > PAGE_CACHE_SIZE*2) {
+			printf("AIEEE: block expanded to > 2*blocklength (%d)\n", len);
+			exit(1);
+		}
+
+		*(u32 *) (base + offset) = curr;
+		offset += 4;
+	} while (size);
+
+	new_size = curr - original_offset;
+	change = new_size - original_size;
+	printf("%4.2f %% (%d bytes)\n", (change * 100) / (double) original_size, change);
+
+	return (curr + 3) & ~3;
+}
+
+static unsigned int write_data(struct entry *entry, char *base, unsigned int offset)
+{
+	do {
+		if (entry->uncompressed) {
+			set_data_offset(entry, base, offset);
+			offset = do_compress(base, offset, entry->uncompressed, entry->size);
+		}
+		if (entry->child)
+			offset = write_data(entry->child, base, offset);
+		entry = entry->next;
+	} while (entry);
+	return offset;
+}
+
+/* This is the maximum rom-image you can create */
+#define MAXROM (64*1024*1024)
+
+/*
+ * Usage:
+ *
+ *      mkcramfs directory-name
+ *
+ * where "directory-name" is simply the root of the directory
+ * tree that we want to generate a compressed filesystem out
+ * of..
+ */
+int main(int argc, char **argv)
+{
+	struct stat st;
+	struct entry *root_entry;
+	char *rom_image;
+	unsigned int offset, written;
+	int fd;
+
+	if (argc)
+		progname = argv[0];
+	if (argc != 3)
+		usage();
+
+	if (stat(argv[1], &st) < 0) {
+		perror(argv[1]);
+		exit(1);
+	}
+	fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
+
+	root_entry = calloc(1, sizeof(struct entry));
+	root_entry->mode = st.st_mode;
+	root_entry->uid = st.st_uid;
+	root_entry->gid = st.st_gid;
+	root_entry->name = "";
+
+	root_entry->size = parse_directory(argv[1], &root_entry->child);
+
+	rom_image = mmap(NULL, MAXROM, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	if (-1 == (int) (long) rom_image) {
+		perror("ROM image map");
+		exit(1);
+	}
+	offset = write_superblock(root_entry, rom_image);
+	printf("Super block: %d bytes\n", offset);
+
+	offset = write_directory_structure(root_entry->child, rom_image, offset);
+	printf("Directory data: %d bytes\n", offset);
+
+	offset = write_data(root_entry, rom_image, offset);
+	printf("Everything: %d bytes\n", offset);
+
+	written = write(fd, rom_image, offset);
+	if (written < 0) {
+		perror("rom image");
+		exit(1);
+	}
+	if (offset != written) {
+		fprintf(stderr, "ROM image write failed (%d %d)\n", written, offset);
+		exit(1);
+	}
+	return 0;
+}
